1 //-< COMPILE.CPP >---------------------------------------------------*--------*
2 // FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *
3 // (Main Memory Database Management System)                          *   /\|  *
4 //                                                                   *  /  \  *
5 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
6 //                          Last update: 15-Jan-99    K.A. Knizhnik  * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Conditional expresion compiler
9 //-------------------------------------------------------------------*--------*
10 
11 #define INSIDE_FASTDB
12 
13 #include "database.h"
14 #include "array.h"
15 #include "query.h"
16 #include "cursor.h"
17 #include "compiler.h"
18 #include "symtab.h"
19 
20 #include <ctype.h>
21 
22 BEGIN_FASTDB_NAMESPACE
23 
24 nat1 const dbExprNode::nodeTypes[] = {
25 #define DBVM(cop, type, n_opernads, commutative) type,
26 // in the RAID - we cannot use source file with a '.d' suffix - this clashes
27 // with the CFW build system (specific to StoreAge build system)).
28 #ifdef VXWORKS
29 #include "compiler.dd"
30 #else
31 #include "compiler.d"
32 #endif // VXWORKS
33 0};
34 
35 nat1 const dbExprNode::nodeOperands[] = {
36 #define DBVM(cop, type, n_operands, commutative) n_operands,
37 // in the RAID - we cannot use source file with a '.d' suffix - this clashes
38 // with the CFW build system (specific to StoreAge build system).
39 #ifdef VXWORKS
40 #include "compiler.dd"
41 #else
42 #include "compiler.d"
43 #endif // VXWORKS
44 0};
45 
46 nat1 const dbExprNode::commutativeOperator[] = {
47 #define DBVM(cop, type, n_operands, commutative) commutative,
48 // in the RAID - we cannot use source file with a '.d' suffix - this clashes
49 // with the CFW build system (specific to StoreAge build system).
50 #ifdef VXWORKS
51 #include "compiler.dd"
52 #else
53 #include "compiler.d"
54 #endif // VXWORKS
55 0};
56 
57 
58 bool        dbCompiler::initialized;
59 
60 dbExprNodeAllocator dbExprNodeAllocator::instance;
61 
~dbExprNodeAllocator()62 dbExprNodeAllocator::~dbExprNodeAllocator() {
63     dbExprNodeSegment* segm = segmentList;
64     while (segm != NULL) {
65         dbExprNodeSegment* next = segm->next;
66         delete segm;
67         segm = next;
68     }
69 }
70 
allocate()71 inline dbExprNode* dbExprNodeAllocator::allocate()
72 {
73     dbCriticalSection cs(mutex);
74     dbExprNode* node = freeNodeList;
75     if (node == NULL) {
76         dbExprNodeSegment* seg = new dbExprNodeSegment;
77         seg->next = segmentList;
78         segmentList = seg;
79         node = (dbExprNode*)seg->buf;
80         dbExprNode* free = NULL;
81         for (int i = dbExprNodeSegment::allocationQuantum; --i != 0;) {
82             node->next = free;
83             free = node++;
84         }
85         freeNodeList = free;
86     } else {
87         freeNodeList = node->next;
88     }
89     return node;
90 }
91 
deallocate(dbExprNode * node)92 void dbExprNodeAllocator::deallocate(dbExprNode* node)
93 {
94     if (node != NULL) {
95         node->next = freeNodeList;
96         freeNodeList = node;
97     }
98 }
99 
reset()100 void dbExprNodeAllocator::reset()
101 {
102     dbExprNode* free = NULL;
103     for (dbExprNodeSegment* seg = segmentList; seg != NULL; seg = seg->next)
104     {
105         dbExprNode* node = (dbExprNode*)seg->buf;
106         for (int i = dbExprNodeSegment::allocationQuantum; --i >= 0;) {
107             node->next = free;
108             free = node++;
109          }
110     }
111     freeNodeList = free;
112 }
113 
dbExprNode(dbExprNode * node)114 dbExprNode::dbExprNode(dbExprNode* node)
115 {
116     memcpy(this, node, sizeof(*this));
117 
118     for (int i = nodeOperands[cop]; --i >= 0;) {
119         operand[i] = new dbExprNode(operand[i]);
120     }
121     if (cop == dbvmLoadStringConstant) {
122         char* s = new char[strlen(svalue.str)+1];
123         strcpy(s, svalue.str);
124         svalue.str = s;
125     }
126 }
127 
~dbExprNode()128 dbExprNode::~dbExprNode()
129 {
130     if (cop == dbvmLoadStringConstant) {
131         delete[] svalue.str;
132     } else if (cop == dbvmLoadWStringConstant) {
133         delete[] wsvalue.str;
134 #ifdef USE_REGEX
135     } else if (cop == dbvmMatchString) {
136         delete regex.opd;
137         regfree(&regex.re);
138 #endif
139     } else {
140         for (int i = nodeOperands[cop]; --i >= 0; ) {
141             delete operand[i];
142         }
143     }
144 }
145 
scan()146 int dbCompiler::scan()
147 {
148     char ch;
149     char *p, *q;
150     int  i, n, value;
151     char buf[maxSymbolLen+1];
152 
153     if (hasToken) {
154         hasToken = false;
155         return lex;
156     }
157    nextElement:
158     if (queryElement == NULL) {
159         return tkn_eof;
160     }
161     if (queryElement->type != dbQueryElement::qExpression) {
162         varType = queryElement->type;
163         varPtr = queryElement->ptr;
164         varRefTable = queryElement->ref;
165         if (varRefTable != NULL) {
166             varRefTable = table->db->lookupTable(varRefTable);
167         }
168         queryElement = queryElement->next;
169         return tkn_var;
170     }
171     p = q = (char*)queryElement->ptr + currPos;
172 
173     do {
174         ch = *p++;
175         if (ch == '\n') {
176             offsetWithinStatement = (int)((char*)queryElement->ptr - p);
177             firstPos = 0;
178         }
179     } while (isspace(byte(ch)));
180     currPos += (int)(p - q);
181 
182     switch (ch) {
183       case '\0':
184         if ((queryElement = queryElement->next) == NULL) {
185             return tkn_eof;
186         }
187         currPos = 0;
188         goto nextElement;
189       case '+':
190         return tkn_add;
191       case '-':
192         if (*p == '-') {
193             // ANSI comments
194             q = p;
195             do {
196                 p += 1;
197             } while (*p != '\n' && *p != '\0');
198             currPos +=(int)(p - q);
199             goto nextElement;
200         }
201         return tkn_sub;
202       case '*':
203         return tkn_mul;
204       case '/':
205         return tkn_div;
206       case '.':
207         return tkn_dot;
208       case ',':
209         return tkn_comma;
210       case '(':
211         return tkn_lpar;
212       case ')':
213         return tkn_rpar;
214       case '[':
215         return tkn_lbr;
216       case ']':
217         return tkn_rbr;
218       case ':':
219         return tkn_col;
220       case '^':
221         return tkn_power;
222       case '<':
223         if (*p == '=') {
224             currPos += 1;
225             return tkn_le;
226         } else if (*p == '>') {
227             currPos += 1;
228             return tkn_ne;
229         }
230         return tkn_lt;
231       case '>':
232         if (*p == '=') {
233             currPos += 1;
234             return tkn_ge;
235         }
236         return tkn_gt;
237       case '=':
238         return tkn_eq;
239       case '!':
240         if (*p != '=') {
241             error("Invalid token '!'");
242         }
243         currPos += 1;
244         return tkn_ne;
245       case '|':
246         if (*p != '|') {
247             error("Invalid token '|'");
248         }
249         currPos += 1;
250         return tkn_add;
251       case '\'':
252       {
253           char* strbuf = buf;
254           int bufSize = maxSymbolLen;
255           q = p;
256           i = 0;
257           while (true) {
258               if (*p == '\'') {
259                   if (*++p != '\'') {
260                       break;
261                   }
262               } else if (*p == '\0') {
263                   error("Unterminated character constant");
264               }
265               if (i+1 == bufSize) {
266                   char* newbuf = new char[(bufSize *= 2) + 1];
267                   memcpy(newbuf, strbuf, i);
268                   if (strbuf != buf) {
269                       delete[] strbuf;
270                   }
271                   strbuf = newbuf;
272               }
273               strbuf[i++] = *p++;
274           }
275           strbuf[i++] = '\0';
276           currPos += (int)(p - q);
277           svalue.str = new char[i];
278           memcpy(svalue.str, strbuf, i);
279           svalue.len = i;
280           if (strbuf != buf) {
281               delete[] strbuf;
282           }
283           return tkn_sconst;
284       }
285       case '#':
286         ivalue = 0;
287         q = p;
288         while (true) {
289             ch = *p++;
290             if (ch >= '0' && ch <= '9') {
291                 ivalue = (ivalue << 4) + ch-'0';
292             } else if (ch >= 'a' && ch <= 'f') {
293                 ivalue = (ivalue << 4) + ch-'a'+10;
294             } else if (ch >= 'A' && ch <= 'F') {
295                 ivalue = (ivalue << 4) + ch-'A'+10;
296             } else {
297                 currPos += (int)(p - q - 1);
298                 return tkn_iconst;
299             }
300         }
301       case '0': case '1': case '2': case '3': case '4':
302       case '5': case '6': case '7': case '8': case '9':
303         value = ch - '0';
304         for (q = p; isdigit(*(byte*)p); p++) {
305             value = value*10 + *p - '0';
306         }
307         if (*p == '.' || *p == 'e' || *p == 'E') {
308             if (sscanf(q-1, "%lf%n", &fvalue, &n) != 1) {
309                 error("Bad floating point constant");
310             }
311             currPos += n - 1;
312             return tkn_fconst;
313         } else if (p - q >= 9) {
314             if (sscanf(q-1, INT8_FORMAT "%n", &ivalue, &n) != 1) {
315                 error("Bad integer constant");
316             }
317             currPos += n - 1;
318             return tkn_iconst;
319         } else {
320             currPos += (int)(p - q);
321             ivalue = value;
322             return tkn_iconst;
323         }
324       default:
325         if (isalpha(ch) || ch == '$' || ch == '_') {
326             i = 0;
327             do {
328                 if (i == maxSymbolLen) {
329                     error("Name too long");
330                 }
331                 buf[i++] = ch;
332                 ch = *p++;
333             } while (isalnum(ch) || ch == '$' || ch == '_');
334             buf[i] = '\0';
335             name = buf;
336             currPos += i - 1;
337         } else {
338             error("Invalid symbol");
339         }
340         return dbSymbolTable::add(name, tkn_ident);
341    }
342 }
343 
disjunction()344 dbExprNode* dbCompiler::disjunction()
345 {
346     dbExprNode* left = conjunction();
347     if (lex == tkn_or) {
348         int pos = currPos;
349         dbExprNode* right = disjunction();
350         if (left->type == tpInteger && right->type == tpInteger) {
351             left = new dbExprNode(dbvmOrInt, left, right);
352         } else if (left->type == tpBoolean && right->type == tpBoolean) {
353             left = new dbExprNode(dbvmOrBool, left, right);
354         } else {
355             error("Bad operands for OR operator", pos);
356         }
357     }
358     return left;
359 }
360 
conjunction()361 dbExprNode* dbCompiler::conjunction()
362 {
363     dbExprNode* left = comparison();
364     if (lex == tkn_and) {
365         int pos = currPos;
366         dbExprNode* right = conjunction();
367         if (left->type == tpInteger && right->type == tpInteger) {
368             left = new dbExprNode(dbvmAndInt, left, right);
369         } else if (left->type == tpBoolean && right->type == tpBoolean) {
370             left = new dbExprNode(dbvmAndBool, left, right);
371         } else {
372             error("Bad operands for AND operator", pos);
373         }
374     }
375     return left;
376 }
377 
int2real(dbExprNode * expr)378 inline dbExprNode* int2real(dbExprNode* expr)
379 {
380     if (expr->cop == dbvmLoadIntConstant) {
381         expr->fvalue = (real8)expr->ivalue;
382         expr->cop = dbvmLoadRealConstant;
383         expr->type = tpReal;
384     } else {
385         expr = new dbExprNode(dbvmIntToReal, expr);
386     }
387     return expr;
388 }
389 
mbs2wcs(dbExprNode * expr)390 inline dbExprNode* mbs2wcs(dbExprNode* expr)
391 {
392     if (expr->cop == dbvmLoadStringConstant) {
393         size_t len = mbstowcs(NULL, expr->svalue.str, 0);
394         wchar_t* wstr = new wchar_t[len+1];
395         mbstowcs(wstr, expr->svalue.str, len);
396         delete[] expr->svalue.str;
397         expr->wsvalue.str = wstr;
398         expr->wsvalue.len = (int)len+1;
399         wstr[len] = 0;
400         expr->cop = dbvmLoadWStringConstant;
401         expr->type = tpWString;
402     } else if (expr->type == tpString) {
403         expr = new dbExprNode(dbvmMbsToWcs, expr);
404     } else if (expr->type != tpWString) {
405         return NULL;
406     }
407     return expr;
408 }
409 
compare(dbExprNode * expr,dbExprNode * list)410 void dbCompiler::compare(dbExprNode* expr, dbExprNode* list)
411 {
412     dbExprNode* selector = expr;
413     for (int n = 1; list != NULL; n++) {
414         dbExprNode* elem = list->operand[0];
415         dbExprNode* tail = list->operand[1];
416         int cop = dbvmVoid;
417         int rawBinarySize = 0;
418         void* rawBinaryComparator = NULL;
419         if (expr->type == tpInteger) {
420             if (elem->type == tpReal) {
421                 expr = int2real(expr);
422                 cop = dbvmEqReal;
423             } else if (elem->type == tpReference) {
424                 expr = new dbExprNode(dbvmIntToReference, expr);
425                 cop = dbvmEqReference;
426             } else if (elem->type == tpInteger) {
427                 cop = dbvmEqInt;
428             }
429         } else if (expr->type == tpReal) {
430             if (elem->type == tpReal) {
431                 cop = dbvmEqReal;
432             } else if (elem->type == tpInteger) {
433                 cop = dbvmEqReal;
434                 elem = int2real(elem);
435             }
436         } else if (expr->type == tpWString) {
437             if (elem->type == tpWString) {
438                 cop = dbvmEqWString;
439             } else if (elem->type == tpString) {
440                 cop = dbvmEqWString;
441                 elem = mbs2wcs(elem);
442             }
443         } else if (elem->type == tpWString) {
444             if (expr->type == tpString) {
445                 cop = dbvmEqWString;
446                 expr = mbs2wcs(expr);
447             }
448         } else if (expr->type == tpString && elem->type == tpString) {
449             cop = dbvmEqString;
450         } else if (expr->type == tpReference && (elem->type == tpReference || elem->type == tpInteger)) {
451             if (elem->type == tpInteger) {
452                 elem = new dbExprNode(dbvmIntToReference, elem);
453             }
454             cop = dbvmEqReference;
455         } else if (expr->type == tpBoolean && elem->type == tpBoolean) {
456             cop = dbvmEqBool;
457         } else if (expr->type == tpRawBinary && elem->type == tpRawBinary) {
458             cop = dbvmEqBinary;
459             if ((expr->cop == dbvmLoadSelfRawBinary || expr->cop == dbvmLoadRawBinary)
460                 && expr->ref.field != NULL)
461             {
462                 rawBinarySize = (int)expr->ref.field->dbsSize;
463                 rawBinaryComparator = (void*)expr->ref.field->_comparator;
464             } else if ((elem->cop == dbvmLoadSelfRawBinary || elem->cop == dbvmLoadRawBinary)
465                        && elem->ref.field != NULL)
466             {
467                 rawBinarySize = (int)elem->ref.field->dbsSize;
468                 rawBinaryComparator = (void*)elem->ref.field->_comparator;
469             } else {
470                 error("Operations with raw binary types should include at least one record field");
471             }
472         }
473         if (cop == dbvmVoid) {
474             char buf[256];
475             sprintf(buf, "Expression %d in right part of IN operator have "
476                     "incompatible type", n);
477             error(buf);
478         } else {
479             list->type = tpBoolean;
480             if (tail != NULL) {
481                 expr = new dbExprNode(cop, expr, elem, rawBinarySize);
482                 expr->func.fptr = rawBinaryComparator;
483                 list->operand[0] = expr;
484                 list->cop = dbvmOrBool;
485                 expr = new dbExprNode(selector);
486             } else {
487                 list->operand[1] = elem;
488                 list->operand[0] = expr;
489                 list->cop = cop;
490                 list->offs = rawBinarySize;
491                 list->func.fptr = rawBinaryComparator;
492             }
493         }
494         list = tail;
495     }
496 }
497 
rectangleConstant(dbExprNode * head)498 dbExprNode* dbCompiler::rectangleConstant(dbExprNode* head)
499 {
500     rectangle r;
501     for (int i = 0; i < RECTANGLE_DIMENSION*2; i++) {
502         if (head == NULL || head->operand[0] == NULL) {
503             error("Bad rectangle constant");
504         }
505         dbExprNode* elem = head->operand[0];
506         dbExprNode* tail = head->operand[1];
507         if (elem->type == tpReal) {
508             r.boundary[i] = (coord_t)elem->fvalue;
509         } else if (elem->type == tpInteger) {
510             r.boundary[i] = (coord_t)elem->ivalue;
511         } else {
512             error("Bad rectangle constant");
513         }
514         head = tail;
515     }
516     if (head != NULL) {
517         error("Bad rectangle constant");
518     }
519     return new dbExprNode(dbvmLoadRectangleConstant, r);
520 }
521 
522 
comparison()523 dbExprNode* dbCompiler::comparison()
524 {
525     int leftPos = currPos;
526     dbExprNode *left, *right;
527     left = addition();
528     int cop = lex;
529     if (cop == tkn_eq || cop == tkn_ne || cop == tkn_gt || cop == tkn_ge
530         || cop == tkn_le || cop == tkn_lt || cop == tkn_between || cop == tkn_overlaps
531         || cop == tkn_like || cop == tkn_match || cop == tkn_not || cop == tkn_is || cop == tkn_in)
532     {
533         int rightPos = currPos;
534         bool notOp = false;
535         if (cop == tkn_not) {
536             notOp = true;
537             cop = scan();
538             if (cop != tkn_like && cop != tkn_match && cop != tkn_between && cop != tkn_in) {
539                 error("LIKE, MATCH, BETWEEN or IN expected", rightPos);
540             }
541             rightPos = currPos;
542         } else if (cop == tkn_is) {
543             if (left->type != tpReference) {
544                 error("IS [NOT] NULL predicate can be applied only to "
545                       "references", rightPos);
546             }
547             rightPos = currPos;
548             if ((cop = scan()) == tkn_null) {
549                 left = new dbExprNode(dbvmIsNull, left);
550             } else if (cop == tkn_not) {
551                 rightPos = currPos;
552                 if (scan() == tkn_null) {
553                     left = new dbExprNode(dbvmNotBool,
554                                           new dbExprNode(dbvmIsNull, left));
555                 } else {
556                     error("NULL expected", rightPos);
557                 }
558             } else {
559                 error("[NOT] NULL expected", rightPos);
560             }
561             lex = scan();
562             return left;
563         }
564         right = addition();
565         if (cop == tkn_in) {
566             int type;
567             switch (right->type) {
568               case tpArray:
569                 switch (right->cop) {
570                   case dbvmLoadVarArrayOfOid:
571                   case dbvmLoadVarArrayOfOidPtr:
572                     type = dbField::tpReference;
573                     break;
574                   case dbvmLoadVarArrayOfInt4:
575                   case dbvmLoadVarArrayOfInt4Ptr:
576                     type = dbField::tpInt4;
577                     break;
578                   case dbvmLoadVarArrayOfInt8:
579                   case dbvmLoadVarArrayOfInt8Ptr:
580                     type = dbField::tpInt8;
581                     break;
582                   default:
583                     type = right->ref.field->components->type;
584                 }
585                 if ((left->type == tpBoolean && type == dbField::tpBool)
586                     || (left->type == tpInteger
587                         && (type == dbField::tpInt1
588                             || type == dbField::tpInt2
589                             || type == dbField::tpInt4
590                             || type == dbField::tpInt8))
591                     || (left->type == tpReal
592                         && (type == dbField::tpReal4
593                             || type == dbField::tpReal8))
594                     || ((left->type == tpString || left->type == tpWString)
595                         && (type == dbField::tpString || type == dbField::tpWString))
596                     || ((left->type == tpRectangle || left->type == tpList) && type == dbField::tpRectangle)
597                     || ((left->type == tpReference || left->type == tpInteger)
598                         && type == dbField::tpReference))
599                 {
600                     if (left->type == tpInteger && type == dbField::tpReference) {
601                         left = new dbExprNode(dbvmIntToReference, left);
602                     }
603                     if (type == dbField::tpRectangle) {
604                         if (left->type == tpList) {
605                             left = rectangleConstant(left);
606                         }
607                         left = new dbExprNode(dbvmInArrayRectangle, left, right);
608                     } else if (left->type == tpWString || type == dbField::tpWString) {
609                         left = new dbExprNode(dbvmInArrayWString, mbs2wcs(left), mbs2wcs(right));
610                     } else {
611                         left = new dbExprNode(dbvmInArrayBool + type, left, right);
612                     }
613                 } else {
614                     error("Type of selective expression of IN operator doesn't"
615                           " match type of the array");
616                 }
617                 break;
618               case tpWString:
619                 if (left->type == tpWString) {
620                     left = new dbExprNode(dbvmInWString, left, right);
621                 } else if (left->type == tpString) {
622                     left = new dbExprNode(dbvmInWString, mbs2wcs(left), right);
623                 } else {
624                     error("Left operand of IN expression hasn't string type");
625                 }
626                 break;
627               case tpString:
628                 if (left->type == tpString) {
629                     left = new dbExprNode(dbvmInString, left, right);
630                 } else if (left->type == tpWString) {
631                     left = new dbExprNode(dbvmInWString, left, mbs2wcs(right));
632                 } else {
633                     error("Left operand of IN expression hasn't string type");
634                 }
635                 break;
636               case tpRectangle:
637                 if (left->type == tpRectangle) {
638                     if (IS_CONSTANT(left->cop)) {
639                         left = new dbExprNode(dbvmGeRectangle, right, left);
640                     } else {
641                         left = new dbExprNode(dbvmLeRectangle, left, right);
642                     }
643                 } else if (left->type == tpList) {
644                     left = new dbExprNode(dbvmGeRectangle, right, rectangleConstant(left));
645                 } else {
646                     error("Left operand of IN expression hasn't rectangle type");
647                 }
648                 break;
649               case tpList:
650                 if (left->type == tpRectangle) {
651                     left = new dbExprNode(dbvmLeRectangle, left, rectangleConstant(right));
652                 } else {
653                     if (right->operand[0] == NULL) { // emtry list
654                         left = new dbExprNode(dbvmLoadFalse);
655                     } else {
656                         compare(left, right);
657                         left = right;
658                     }
659                 }
660                 break;
661               default:
662                 error("List of expressions or array expected", rightPos);
663             }
664         } else if (cop == tkn_between) {
665             int andPos = currPos;
666             if (lex != tkn_and) {
667                 error("AND expected");
668             }
669             dbExprNode* right2 = addition();
670             if (left->type == tpReal
671                 || right->type == tpReal || right2->type == tpReal)
672             {
673                 if (left->type == tpInteger) {
674                     left = int2real(left);
675                 } else if (left->type != tpReal) {
676                     error("operand of BETWEEN operator should be of "
677                           "integer, real or string type", leftPos);
678                 }
679                 if (right->type == tpInteger) {
680                     right = int2real(right);
681                 } else if (right->type != tpReal) {
682                     error("operand of BETWEEN operator should be of "
683                           "integer, real or string type", rightPos);
684                 }
685                 if (right2->type == tpInteger) {
686                     right2 = int2real(right2);
687                 } else if (right2->type != tpReal) {
688                     error("operand of BETWEEN operator should be of "
689                           "integer, real or string type", andPos);
690                 }
691                 left = new dbExprNode(dbvmBetweenReal, left, right, right2);
692             }
693             else if (left->type == tpInteger && right->type == tpInteger
694                      && right2->type == tpInteger)
695             {
696                 left = new dbExprNode(dbvmBetweenInt, left, right, right2);
697             }
698             else if (left->type == tpArray && right->type == tpArray
699                      && right2->type == tpArray)
700             {
701                 void* arrayComparator = NULL;
702                 if ((left->cop == dbvmLoadSelfArray || left->cop == dbvmLoadArray)
703                     && left->ref.field != NULL)
704                 {
705                     arrayComparator = (void*)left->ref.field->_comparator;
706                 } else {
707                     error("Operations with array should include at least one record field");
708                 }
709                 left = new dbExprNode(dbvmBetweenArray, left, right, right2);
710                 left->func.fptr = arrayComparator;
711             }
712             else if (left->type == tpWString || right->type == tpWString
713                      || right2->type == tpWString)
714             {
715                 left = mbs2wcs(left);
716                 right = mbs2wcs(right);
717                 right2 = mbs2wcs(right2);
718                 if (left == NULL || right == NULL || right2 == NULL) {
719                    error("operand of BETWEEN operator should be of integer, real or string type", andPos);
720                 }
721                 left = new dbExprNode(dbvmBetweenWString, left, right, right2);
722             }
723             else if (left->type == tpString && right->type == tpString
724                      && right2->type == tpString)
725             {
726                 left = new dbExprNode(dbvmBetweenString, left, right, right2);
727             }
728             else if (left->type == tpRawBinary && right->type == tpRawBinary
729                      && right2->type == tpRawBinary)
730             {
731                 int rawBinarySize = 0;
732                 void* rawBinaryComparator = NULL;
733                 if ((left->cop == dbvmLoadSelfRawBinary || left->cop == dbvmLoadRawBinary)
734                     && left->ref.field != NULL)
735                 {
736                     rawBinarySize = (int)left->ref.field->dbsSize;
737                     rawBinaryComparator = (void*)left->ref.field->_comparator;
738                 } else {
739                     error("Operations with raw binary types should include at least one record field");
740                 }
741                 left = new dbExprNode(dbvmBetweenBinary, left, right, right2);
742                 left->offs = rawBinarySize;
743                 left->func.fptr = rawBinaryComparator;
744             }
745             else {
746                 error("operands of BETWEEN operator should be of "
747                       "integer, real or string type", rightPos);
748             }
749 #ifdef USE_REGEX
750         } else if (cop == tkn_match) {
751             if (left->type != tpString) {
752                 error("left operands of MATCH operator should be of string type", leftPos);
753             }
754             if (right->cop != dbvmLoadStringConstant) {
755                 error("right operand of MATCH operator should be string constant", rightPos);
756             }
757             dbExprNode* expr = new dbExprNode(dbvmMatchString);
758             expr->regex.opd = left;
759             left = expr;
760             if (regcomp(&left->regex.re, (char*)right->svalue.str, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) {
761                 error("invalid regular expression", rightPos);
762             }
763 #endif
764         } else if (cop == tkn_like) {
765             if ((left->type != tpString && left->type != tpWString) || (right->type != tpString && right->type != tpWString)) {
766                 error("operands of LIKE operator should be of "
767                       "string type", rightPos);
768             }
769             if (lex == tkn_escape) {
770                 rightPos = currPos;
771                 if (scan() != tkn_sconst) {
772                     error("String literal espected after ESCAPE", rightPos);
773                 }
774                 lex = scan();
775                 if (left->type == tpWString || right->type == tpWString) {
776                     left = new dbExprNode(dbvmLikeEscapeWString, mbs2wcs(left), mbs2wcs(right),
777                                           mbs2wcs(new dbExprNode(dbvmLoadStringConstant, svalue)));
778                 } else {
779                     left = new dbExprNode(dbvmLikeEscapeString, left, right,
780                                           new dbExprNode(dbvmLoadStringConstant, svalue));
781                 }
782             } else {
783                 if (right->cop == dbvmLoadStringConstant) {
784                     char* str = right->svalue.str;
785                     char* w = findWildcard(str);
786                     if (w == NULL) {
787                         if (left->type == tpWString) {
788                             left = new dbExprNode(dbvmEqWString, left, mbs2wcs(right));
789                         } else {
790                             left = new dbExprNode(dbvmEqString, left, right);
791                         }
792                     } else if (w == str && *w == '%'
793                                && (w = findWildcard(str+1)) != NULL && *w == '%' && *(w+1) == '\0')
794                     {
795                         memcpy(str, str+1, w-str-1);
796                         str[w-str-1] = '\0';
797                         right->svalue.len -= 2;
798                         if (left->type == tpWString) {
799                             left = new dbExprNode(dbvmInWString, mbs2wcs(right), left);
800                         } else {
801                             left = new dbExprNode(dbvmInString, right, left);
802                         }
803                     } else {
804                         if (left->type == tpWString) {
805                             left = new dbExprNode(dbvmLikeWString, left, mbs2wcs(right));
806                         } else {
807                             left = new dbExprNode(dbvmLikeString, left, right);
808                         }
809                     }
810                 } else if (right->cop == dbvmLoadWStringConstant) {
811                     wchar_t* str = right->wsvalue.str;
812                     wchar_t* w = findWildcard(str);
813                     if (w == NULL) {
814                         left = new dbExprNode(dbvmEqWString, mbs2wcs(left), right);
815                     } else if (w == str && *w == '%'
816                                && (w = findWildcard(str+1)) != NULL && *w == '%' && *(w+1) == '\0')
817                     {
818                         memcpy(str, str+1, (w-str-1)*sizeof(wchar_t));
819                         str[w-str-1] = '\0';
820                         right->wsvalue.len -= 2;
821                         left = new dbExprNode(dbvmInWString, right, mbs2wcs(left));
822                     } else {
823                         left = new dbExprNode(dbvmLikeWString, mbs2wcs(left), right);
824                     }
825                 } else if (left->type == tpWString || right->type == tpWString) {
826                     left = new dbExprNode(dbvmLikeWString, mbs2wcs(left), mbs2wcs(right));
827                 } else {
828                     left = new dbExprNode(dbvmLikeString, left, right);
829                 }
830             }
831         } else if (cop == tkn_overlaps) {
832             if (left->type == tpRectangle && right->type == tpRectangle) {
833                 if (IS_CONSTANT(left->cop)) {
834                     left = new dbExprNode(dbvmOverlapsRectangle, right, left);
835                 } else {
836                     left = new dbExprNode(dbvmOverlapsRectangle, left, right);
837                 }
838             } else if (left->type == tpList && right->type == tpRectangle) {
839                 left = new dbExprNode(dbvmOverlapsRectangle, right, rectangleConstant(left));
840             } else if (left->type == tpRectangle && right->type == tpList) {
841                 left = new dbExprNode(dbvmOverlapsRectangle, left, rectangleConstant(right));
842             } else {
843                 error("operands of OVERLAPS operator should be of rectangle type", leftPos);
844             }
845         } else {
846             if (left->type == tpReal || right->type == tpReal) {
847                 if (left->type == tpInteger) {
848                     left = int2real(left);
849                 } else if (left->type != tpReal) {
850                     error("operands of relation operator should be of "
851                           "intger, real or string type", leftPos);
852                 }
853                 if (right->type == tpInteger) {
854                     right = int2real(right);
855                 } else if (right->type != tpReal) {
856                     error("operands of relation operator should be of "
857                           "intger, real or string type", rightPos);
858                 }
859                 left = new dbExprNode(dbvmEqReal + cop - tkn_eq, left, right);
860             } else if (left->type == tpInteger && right->type == tpInteger) {
861                 left = new dbExprNode(dbvmEqInt + cop - tkn_eq, left, right);
862             } else if (left->type == tpWString || right->type == tpWString) {
863                 left = mbs2wcs(left);
864                 right = mbs2wcs(right);
865                 if (left == NULL || right == NULL) {
866                     error("operands of relation operator should be of intger, real or string type", rightPos);
867                 }
868                 left = new dbExprNode(dbvmEqWString + cop-tkn_eq, left, right);
869             } else if (left->type == tpString && right->type == tpString) {
870                 left = new dbExprNode(dbvmEqString + cop-tkn_eq, left, right);
871             } else if (left->type == tpRectangle && right->type == tpRectangle) {
872                 left = new dbExprNode(dbvmEqRectangle + cop-tkn_eq, left, right);
873             } else if (left->type == tpList && right->type == tpRectangle) {
874                 left = new dbExprNode(dbvmEqRectangle + cop-tkn_eq, rectangleConstant(left), right);
875             } else if (left->type == tpRectangle && right->type == tpList) {
876                 left = new dbExprNode(dbvmEqRectangle + cop-tkn_eq, left, rectangleConstant(right));
877             } else if (left->type == tpArray && right->type == tpArray) {
878                 void* arrayComparator = NULL;
879                 if ((left->cop == dbvmLoadSelfArray || left->cop == dbvmLoadArray)
880                     && left->ref.field != NULL)
881                 {
882                     arrayComparator = (void*)left->ref.field->_comparator;
883                 } else if ((right->cop == dbvmLoadSelfArray || right->cop == dbvmLoadArray)
884                     && right->ref.field != NULL)
885                 {
886                     arrayComparator = (void*)right->ref.field->_comparator;
887                 } else {
888                     error("Operations with array should include at least one record field");
889                 }
890                 left = new dbExprNode(dbvmEqArray + cop-tkn_eq, left, right);
891                 left->func.fptr = arrayComparator;
892             } else if ((left->type == tpReference || left->type == tpInteger)
893                        && (right->type == tpReference || right->type == tpInteger))
894             {
895                 if (cop != tkn_eq && cop != tkn_ne) {
896                     error("References can be checked only for equality",
897                           rightPos);
898                 }
899                 if (left->type == tpInteger) {
900                     left = new dbExprNode(dbvmIntToReference, left);
901                 } else if (right->type == tpInteger) {
902                     right = new dbExprNode(dbvmIntToReference, right);
903                 }
904                 left = new dbExprNode(dbvmEqReference+cop-tkn_eq, left, right);
905             } else if (left->type == tpBoolean && right->type == tpBoolean) {
906                 if (cop != tkn_eq && cop != tkn_ne) {
907                     error("Boolean variables can be checked only for equality",
908                           rightPos);
909                 }
910                 left = new dbExprNode(dbvmEqBool + cop - tkn_eq, left, right);
911             } else if (left->type == tpRawBinary && right->type == tpRawBinary) {
912                 int rawBinarySize = 0;
913                 void* rawBinaryComparator = NULL;
914                 if ((left->cop == dbvmLoadSelfRawBinary || left->cop == dbvmLoadRawBinary)
915                     && left->ref.field != NULL)
916                 {
917                     rawBinarySize = (int)left->ref.field->dbsSize;
918                     rawBinaryComparator = (void*)left->ref.field->_comparator;
919                 } else if ((right->cop == dbvmLoadSelfRawBinary || right->cop == dbvmLoadRawBinary)
920                            && right->ref.field != NULL)
921                 {
922                     rawBinarySize = (int)right->ref.field->dbsSize;
923                     rawBinaryComparator = (void*)right->ref.field->_comparator;
924                 } else {
925                     error("Operations with raw binary types should include at least one record field");
926                 }
927                 left = new dbExprNode(dbvmEqBinary + cop - tkn_eq, left, right, rawBinarySize);
928                 left->func.fptr = rawBinaryComparator;
929             } else {
930                 error("operands of relation operator should be of "
931                       "integer, real or string type", rightPos);
932             }
933             //
934             // Optimization for applying indices: if operation is
935             // commuatative and left operand is constant then swap operands
936             //
937             if (IS_CONSTANT(left->operand[0]->cop)) {
938                 right = left->operand[1];
939                 left->operand[1] = left->operand[0];
940                 left->operand[0] = right;
941                 left->cop = dbExprNode::commutativeOperator[left->cop];
942             }
943         }
944         if (notOp) {
945             left = new dbExprNode(dbvmNotBool, left);
946         }
947     }
948     return left;
949 }
950 
addition()951 dbExprNode* dbCompiler::addition()
952 {
953     int leftPos = currPos;
954     dbExprNode* left = multiplication();
955     while (lex == tkn_add || lex == tkn_sub) {
956         int cop = lex;
957         int rightPos = currPos;
958         dbExprNode* right = multiplication();
959         if (left->type == tpReal || right->type == tpReal) {
960             if (left->type == tpInteger) {
961                 left = int2real(left);
962             } else if (left->type != tpReal) {
963                 error("operands of arithmetic operators should be of "
964                       "integer or real type", leftPos);
965             }
966             if (right->type == tpInteger) {
967                 right = int2real(right);
968             } else if (right->type != tpReal) {
969                 error("operands of arithmetic operator should be of "
970                       "integer or real type", rightPos);
971             }
972             left = new dbExprNode(cop==tkn_add ? dbvmAddReal : dbvmSubReal,
973                                   left, right);
974         } else if (left->type == tpInteger && right->type == tpInteger) {
975             left = new dbExprNode(cop==tkn_add ? dbvmAddInt : dbvmSubInt,
976                                   left, right);
977         } else if (left->type == tpRectangle || right->type == tpRectangle) {
978             if (cop == tkn_add) {
979                 if (left->type == tpRectangle || right->type == tpRectangle) {
980                     left = new dbExprNode(dbvmAddRectangle, left, right);
981                 } else if (left->type == tpRectangle || right->type == tpList) {
982                     left = new dbExprNode(dbvmAddRectangle, left, rectangleConstant(right));
983                 } else if (right->type == tpRectangle || left->type == tpList) {
984                     left = new dbExprNode(dbvmAddRectangle, rectangleConstant(left), right);
985                 } else {
986                     error("Rectangle can be added only with rectangle", rightPos);
987                 }
988             } else {
989                 error("Operation - is not defined for rectangles", rightPos);
990             }
991         } else if (left->type == tpWString || right->type == tpWString) {
992             if (cop == tkn_add) {
993                 left = mbs2wcs(left);
994                 right = mbs2wcs(right);
995                 if (left == NULL || right == NULL) {
996                      error("Operands if concatenation operator should have string type", rightPos);
997                 }
998                 left = new dbExprNode(dbvmWStringConcat, left, right);
999             } else {
1000                 error("Operation - is not defined for strings", rightPos);
1001             }
1002         } else if (left->type == tpString && right->type == tpString) {
1003             if (cop == tkn_add) {
1004                 left = new dbExprNode(dbvmStringConcat, left, right);
1005             } else {
1006                 error("Operation - is not defined for strings", rightPos);
1007             }
1008         } else {
1009             error("operands of arithmentic operator should be of "
1010                   "integer or real type", rightPos);
1011         }
1012         leftPos = rightPos;
1013     }
1014     return left;
1015 }
1016 
1017 
multiplication()1018 dbExprNode* dbCompiler::multiplication()
1019 {
1020     int leftPos = currPos;
1021     dbExprNode* left = power();
1022     while (lex == tkn_mul || lex == tkn_div) {
1023         int cop = lex;
1024         int rightPos = currPos;
1025         dbExprNode* right = power();
1026         if (left->type == tpReal || right->type == tpReal) {
1027             if (left->type == tpInteger) {
1028                 left = int2real(left);
1029             } else if (left->type != tpReal) {
1030                 error("operands of arithmetic operators should be of "
1031                       "integer or real type", leftPos);
1032             }
1033             if (right->type == tpInteger) {
1034                 right = int2real(right);
1035             } else if (right->type != tpReal) {
1036                     error("operands of arithmetic operator should be of "
1037                           "integer or real type", rightPos);
1038             }
1039             left = new dbExprNode(cop==tkn_mul ? dbvmMulReal : dbvmDivReal,
1040                                   left, right);
1041         } else if (left->type == tpInteger && right->type == tpInteger) {
1042             left = new dbExprNode(cop==tkn_mul ? dbvmMulInt : dbvmDivInt,
1043                                   left, right);
1044         } else {
1045             error("operands of arithmentic operator should be of "
1046                   "integer or real type", rightPos);
1047         }
1048         leftPos = rightPos;
1049     }
1050     return left;
1051 }
1052 
power()1053 dbExprNode* dbCompiler::power()
1054 {
1055     int leftPos = currPos;
1056     dbExprNode* left = userDefinedOperator();
1057     if (lex == tkn_power) {
1058         int rightPos = currPos;
1059         dbExprNode* right = power();
1060         if (left->type == tpReal || right->type == tpReal) {
1061             int cop = dbvmPowerReal;
1062             if (left->type == tpInteger) {
1063                 left = int2real(left);
1064             } else if (left->type != tpReal) {
1065                 error("operands of arithmetic operators should be of "
1066                       "integer or real type", leftPos);
1067             }
1068             if (right->type == tpInteger) {
1069                 cop = dbvmPowerRealInt;
1070             } else if (right->type != tpReal) {
1071                     error("operands of arithmetic operator should be of "
1072                           "integer or real type", rightPos);
1073             }
1074             left = new dbExprNode(cop, left, right);
1075         } else if (left->type == tpInteger && right->type == tpInteger) {
1076             left = new dbExprNode(dbvmPowerInt, left, right);
1077         } else {
1078             error("operands of arithmentic operator should be of "
1079                   "integer or real type", rightPos);
1080         }
1081     }
1082     return left;
1083 }
1084 
1085 
userDefinedOperator()1086 dbExprNode* dbCompiler::userDefinedOperator()
1087 {
1088     dbExprNode* left = term();
1089     while (lex == tkn_ident) {
1090         dbUserFunction* func = dbUserFunction::find(name);
1091         if (func != NULL) {
1092             int nParams =  func->getNumberOfParameters();
1093             if (nParams != 2) {
1094                 error("Only function with two arguments can be used as operator", currPos);
1095             }
1096             int rightPos = currPos;
1097             dbExprNode* right = term();
1098             if ((left->type != tpInteger && left->type != tpReal && left->type != tpString && left->type != tpWString
1099                  && left->type != tpReference && left->type != tpRawBinary && left->type != tpBoolean)
1100                 || (right->type != tpInteger && right->type != tpReal && right->type != tpString && right->type != tpWString
1101                     && right->type != tpReference && right->type != tpRawBinary && right->type != tpBoolean))
1102             {
1103 
1104                 error("User function should receive parameter of boolean, integer, real, string, reference or user defined type", rightPos);
1105             }
1106             left = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, left, right);
1107         } else {
1108             break;
1109         }
1110     }
1111     return left;
1112 }
1113 
field(dbExprNode * expr,dbTableDescriptor * refTable,dbFieldDescriptor * fd)1114 dbExprNode* dbCompiler::field(dbExprNode* expr, dbTableDescriptor* refTable,
1115                               dbFieldDescriptor* fd)
1116 {
1117     int pos;
1118 
1119     while (true) {
1120         switch (lex) {
1121           case tkn_dot:
1122             pos = currPos;
1123             if (scan() != tkn_ident) {
1124                 error("identifier expected", pos);
1125             }
1126             if (fd != NULL && fd->type == dbField::tpStructure) {
1127                 if ((fd = fd->findSymbol(name)) == NULL) {
1128                     error("Field not found");
1129                 }
1130             } else {
1131                 assert(expr != NULL);
1132                 if (expr->type != tpReference) {
1133                     error("Left operand of '.' should be "
1134                           "structure or reference", pos);
1135                 }
1136                 if (refTable == NULL && fd != NULL) {
1137                     refTable = fd->refTable;
1138                 }
1139                 if (refTable == NULL || (fd = refTable->findSymbol(name)) == NULL) {
1140                     error("Field not found");
1141                 }
1142                 refTable = NULL;
1143                 expr = new dbExprNode(dbvmDeref, expr);
1144             }
1145             break;
1146           case tkn_lbr:
1147             if (expr == NULL ||
1148                 (expr->type != tpArray && expr->type != tpString && expr->type != tpWString && expr->type != tpRectangle))
1149             {
1150                 error("Index can be applied only to arrays");
1151             } else {
1152                 dbExprNode* index = disjunction();
1153                 if (lex != tkn_rbr) {
1154                     error("']' expected");
1155                 }
1156                 if (index->type != tpInteger && index->type != tpFreeVar) {
1157                     error("Index should have integer type");
1158                 }
1159 
1160                 if (expr->type == tpString) {
1161                     lex = scan();
1162                     return new dbExprNode(dbvmCharAt, expr, index);
1163                 } else if (expr->type == tpWString) {
1164                     lex = scan();
1165                     return new dbExprNode(dbvmWCharAt, expr, index);
1166                 } if (expr->type == tpRectangle) {
1167                     lex = scan();
1168                     return new dbExprNode(dbvmRectangleCoord, expr, index);
1169                 }
1170                 if (fd == NULL) {
1171                     // variable of array of reference type
1172                     expr = new dbExprNode(dbvmGetAt,expr,index,sizeof(oid_t));
1173                 } else {
1174                     if (refTable == NULL) {
1175                         refTable = fd->refTable;
1176                     }
1177                     fd = fd->components;
1178                     expr = new dbExprNode(dbvmGetAt, expr, index, (int)fd->dbsSize);
1179                 }
1180             }
1181             break;
1182           default:
1183             if (expr == NULL) {
1184                 error("'.' expected");
1185             }
1186             return expr;
1187         }
1188         if (fd == NULL) {
1189             expr = new dbExprNode(dbvmLoadReference, expr, 0);
1190         } else if (fd->type == dbField::tpRawBinary) {
1191             expr = new dbExprNode(expr != NULL ? dbvmLoadRawBinary : dbvmLoadSelfRawBinary,
1192                                   fd, expr);
1193         } else if (fd->type == dbField::tpRectangle) {
1194             expr = new dbExprNode(expr != NULL ? dbvmLoadRectangle: dbvmLoadSelfRectangle,
1195                                   fd, expr);
1196         } else if (fd->type == dbField::tpWString) {
1197             expr = new dbExprNode(expr != NULL ? dbvmLoadWString : dbvmLoadSelfWString,
1198                                   fd, expr);
1199         } else if (fd->type == dbField::tpMethodWString) {
1200             expr = new dbExprNode(expr != NULL ? dbvmInvokeMethodWString : dbvmInvokeSelfMethodWString,  fd, expr);
1201         } else if ((unsigned)fd->type - dbField::tpMethodBool <= dbField::tpMethodReference - dbField::tpMethodBool) {
1202             expr = new dbExprNode((expr != NULL ? dbvmInvokeMethodBool : dbvmInvokeSelfMethodBool) + fd->type - dbField::tpMethodBool,
1203                                   fd, expr);
1204         } else if (fd->type != dbField::tpStructure) {
1205             expr = new dbExprNode((expr != NULL
1206                                    ? dbvmLoadBool : dbvmLoadSelfBool)
1207                                   + fd->type, fd, expr);
1208         }
1209         lex = scan();
1210     }
1211 }
1212 
1213 
1214 
buildList()1215 dbExprNode* dbCompiler::buildList() {
1216     dbExprNode* expr = disjunction();
1217     return new dbExprNode(dbvmList, expr, lex == tkn_comma ? buildList() : NULL);
1218 }
1219 
term()1220 dbExprNode* dbCompiler::term()
1221 {
1222     dbFieldDescriptor* fd;
1223     dbTableDescriptor* refTable;
1224     int cop;
1225     int pos = currPos;
1226     int prevLex = lex;
1227     dbBinding* bp;
1228     dbExprNode* expr = NULL;
1229     dbUserFunction* func;
1230 
1231     if ((cop = scan()) == tkn_where) {
1232         if (firstPos == 0) {
1233             firstPos = currPos;
1234         }
1235         cop = scan(); // just ignore 'where' keyword
1236     }
1237     lex = cop;
1238 
1239     switch (cop) {
1240       case tkn_eof:
1241       case tkn_order:
1242       case tkn_start:
1243       case tkn_limit:
1244         return new dbExprNode(dbvmVoid);
1245       case tkn_current:
1246         lex = scan();
1247         return field(new dbExprNode(dbvmCurrent), table, NULL);
1248       case tkn_ident:
1249         for (bp = bindings; bp != NULL; bp = bp->next) {
1250             if (name == bp->name) {
1251                 bp->used = true;
1252                 lex = scan();
1253                 return new dbExprNode(dbvmVariable, (dbExprNode*)0, bp->index);
1254             }
1255         }
1256         if ((fd = table->findSymbol(name)) == NULL) {
1257             if ((func = dbUserFunction::find(name)) != NULL) {
1258                 pos = currPos;
1259                 expr = term();
1260                 int argType = func->getParameterType();
1261                 int nParams =  func->getNumberOfParameters();
1262                 if (nParams > 1) {
1263                     if (expr->type != tpList || expr->operand[0] == NULL) {
1264                         error("Too few paramters for user defined function");
1265                     }
1266                     dbExprNode* params[3];
1267                     int n = 0;
1268                     do {
1269                         if (n == nParams) {
1270                             error("Too many parameters for user defined function");
1271                         }
1272                         dbExprNode* param = expr->operand[0];
1273                         if (param->type != tpInteger && param->type != tpReal && param->type != tpString && param->type != tpWString
1274                             && param->type != tpReference && param->type != tpRawBinary && param->type != tpBoolean)
1275                         {
1276                             error("User function should receive parameters of boolean, integer, real, string, reference or user defined type", pos);
1277                         }
1278                         params[n++] = param;
1279                         expr = expr->operand[1];
1280                     } while (expr != NULL);
1281 
1282                     if (n != nParams) {
1283                         error("Too few parameters for user defined function");
1284                     }
1285                     expr = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, params[0], params[1], params[2]);
1286                 } else {
1287                     if (argType == tpReal && expr->type == tpInteger) {
1288                         expr = int2real(expr);
1289                     } else if (argType == tpList) {
1290                         if (expr->type != tpInteger && expr->type != tpReal && expr->type != tpString && expr->type != tpWString
1291                             && expr->type != tpReference && expr->type != tpRawBinary && expr->type != tpBoolean)
1292                         {
1293                             error("User function should receive parameter of boolean, integer, real, string, reference or user defined type", pos);
1294                         }
1295                     } else if (argType != expr->type) {
1296                         error("Incompatible function argument", pos);
1297                     }
1298                     expr = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, expr);
1299                 }
1300                 return field(expr, NULL, NULL);
1301             }
1302             error("Field not found", pos);
1303         }
1304         if (fd->type == dbField::tpRawBinary) {
1305             expr = new dbExprNode(dbvmLoadSelfRawBinary, fd);
1306         } else if (fd->type == dbField::tpRectangle) {
1307             expr = new dbExprNode(dbvmLoadSelfRectangle, fd);
1308         } else if (fd->type == dbField::tpWString) {
1309             expr = new dbExprNode(dbvmLoadSelfWString, fd);
1310         } else if (fd->type != dbField::tpStructure) {
1311             expr = new dbExprNode(dbvmLoadSelfBool + fd->type, fd);
1312         }
1313         lex = scan();
1314         return field(expr, NULL, fd);
1315       case tkn_exists:
1316         if (scan() == tkn_ident) {
1317             dbBinding var;
1318             var.next = bindings;
1319             var.name = name;
1320             var.used = false;
1321             var.index = nFreeVars;
1322             bindings = &var;
1323             if (nFreeVars >= maxFreeVars) {
1324                 error("Too many nested EXISTS clauses\n");
1325             }
1326             nFreeVars += 1;
1327             pos = currPos;
1328             if (scan() != tkn_col) {
1329                 error("':' expected", pos);
1330             }
1331             expr = term();
1332             if (expr->type != tpBoolean) {
1333                 error("Expresion in EXISTS clause should be of boolean type");
1334             }
1335             if (var.used) {
1336                 expr = new dbExprNode(dbvmExists, expr, nFreeVars-1);
1337             }
1338             nFreeVars -= 1;
1339             assert(bindings == &var);
1340             bindings = var.next;
1341             return expr;
1342         } else {
1343             error("Free variable name expected");
1344         }
1345         break;
1346       case tkn_first:
1347         lex = scan();
1348         return field(new dbExprNode(dbvmFirst), table, NULL);
1349       case tkn_last:
1350         lex = scan();
1351         return field(new dbExprNode(dbvmLast), table, NULL);
1352       case tkn_false:
1353         expr = new dbExprNode(dbvmLoadFalse);
1354         break;
1355       case tkn_true:
1356         expr = new dbExprNode(dbvmLoadTrue);
1357         break;
1358       case tkn_null:
1359         expr = new dbExprNode(dbvmLoadNull);
1360         break;
1361       case tkn_iconst:
1362         expr = new dbExprNode(dbvmLoadIntConstant, ivalue);
1363         break;
1364       case tkn_fconst:
1365         expr = new dbExprNode(dbvmLoadRealConstant, fvalue);
1366         break;
1367       case tkn_sconst:
1368         expr = new dbExprNode(dbvmLoadStringConstant, svalue);
1369         lex = scan();
1370         return field(expr, NULL, NULL);
1371       case tkn_var:
1372         expr = new dbExprNode(dbvmLoadVarBool + varType -
1373                               dbQueryElement::qVarBool, varPtr);
1374         refTable = varRefTable;
1375         lex = scan();
1376         return field(expr, refTable, NULL);
1377       case tkn_abs:
1378       case tkn_area:
1379       case tkn_length:
1380       case tkn_lower:
1381       case tkn_upper:
1382       case tkn_integer:
1383       case tkn_real:
1384       case tkn_string:
1385       case tkn_wstring:
1386         pos = currPos;
1387         expr = term();
1388         switch (cop) {
1389           case tkn_abs:
1390             if (expr->type == tpInteger) {
1391                 cop = dbvmAbsInt;
1392             } else if (expr->type == tpReal) {
1393                 cop = dbvmAbsReal;
1394             } else {
1395                 error("ABS function can be applied only "
1396                       "to integer or real expression", pos);
1397             }
1398             break;
1399           case tkn_area:
1400             if (expr->type == tpRectangle) {
1401                 cop = dbvmRectangleArea;
1402             } else if (expr->type == tpList) {
1403                 expr = rectangleConstant(expr);
1404                 cop = dbvmRectangleArea;
1405             } else {
1406                 error("AREA function can be applied only to rectangles", pos);
1407             }
1408             break;
1409           case tkn_length:
1410             if (expr->type == tpArray) {
1411                 cop = dbvmLength;
1412             } else if (expr->type == tpString) {
1413                 cop = dbvmStringLength;
1414             } else if (expr->type == tpWString) {
1415                 cop = dbvmWStringLength;
1416             } else {
1417                 error("LENGTH function is defined only for arrays and strings",
1418                       pos);
1419             }
1420             break;
1421           case tkn_integer:
1422             if (expr->type == tpReal) {
1423                 cop = dbvmRealToInt;
1424             } else {
1425                 error("INTEGER function can be applied only to "
1426                       "expression of real type", pos);
1427             }
1428             break;
1429           case tkn_real:
1430             if (expr->type == tpInteger) {
1431                 cop = dbvmIntToReal;
1432             } else {
1433                 error("REAL function can be applied only to "
1434                       "expression of integer type", pos);
1435             }
1436             break;
1437           case tkn_wstring:
1438             if (expr->type == tpString) {
1439                 cop = dbvmMbsToWcs;
1440             } else {
1441                 error("WSTRING function can be applied only "
1442                       "to string expression", pos);
1443             }
1444            case tkn_string:
1445             if (expr->type == tpInteger) {
1446                 cop = dbvmIntToString;
1447             } else if (expr->type == tpReal) {
1448                 cop = dbvmRealToString;
1449             } else if (expr->type == tpWString) {
1450                 cop = dbvmWcsToMbs;
1451             } else {
1452                 error("STRING function can be applied only "
1453                       "to integer or real expression", pos);
1454             }
1455             break;
1456           case tkn_lower:
1457             if (expr->type == tpString) {
1458                 cop = dbvmLowerString;
1459             } else if (expr->type == tpWString) {
1460                 cop = dbvmLowerWString;
1461             } else {
1462                 error("LOWER function can be applied only to string argument", pos);
1463             }
1464             break;
1465           case tkn_upper:
1466             if (expr->type == tpString) {
1467                 cop = dbvmUpperString;
1468             } else if (expr->type == tpWString) {
1469                 cop = dbvmUpperWString;
1470             } else {
1471                 error("UPPER function can be applied only to string argument", pos);
1472             }
1473             break;
1474           default:
1475             assert(false);
1476         }
1477         return field(new dbExprNode(cop, expr), NULL, NULL);
1478       case tkn_lpar:
1479         {
1480             int tkn = scan();
1481             if (tkn == tkn_rpar) {
1482                 expr = new dbExprNode(dbvmList, (dbExprNode*)NULL);
1483             } else {
1484                 ungetToken(tkn);
1485                 expr = disjunction();
1486                 if (lex == tkn_comma) {
1487                     expr = new dbExprNode(dbvmList, expr, buildList());
1488                 } else if (prevLex == tkn_in) {
1489                     expr = new dbExprNode(dbvmList, expr);
1490                 }
1491                 if (lex != tkn_rpar) {
1492                     error("')' expected");
1493                 }
1494             }
1495         }
1496         break;
1497       case tkn_not:
1498         pos = currPos;
1499         expr = comparison();
1500         if (expr->type == tpInteger) {
1501             if (expr->cop == dbvmLoadIntConstant) {
1502                 expr->ivalue = ~expr->ivalue;
1503             } else {
1504                 expr = new dbExprNode(dbvmNotInt, expr);
1505             }
1506             return expr;
1507         } else if (expr->type == tpBoolean) {
1508             return new dbExprNode(dbvmNotBool, expr);
1509         } else {
1510             error("NOT operator can be applied only to "
1511                   "integer or boolean expressions", pos);
1512         }
1513         break;
1514       case tkn_add:
1515         error("Using of unary plus operator has no sence");
1516         break;
1517       case tkn_sub:
1518         pos = currPos;
1519         expr = term();
1520         if (expr->type == tpInteger) {
1521             if (expr->cop == dbvmLoadIntConstant) {
1522                 expr->ivalue = -expr->ivalue;
1523             } else {
1524                 expr = new dbExprNode(dbvmNegInt, expr);
1525             }
1526             return expr;
1527         } else if (expr->type == tpReal) {
1528             if (expr->cop == dbvmLoadRealConstant) {
1529                 expr->fvalue = -expr->fvalue;
1530             } else {
1531                 expr = new dbExprNode(dbvmNegReal, expr);
1532             }
1533             return expr;
1534         } else {
1535             error("Unary minus can be applied only to "
1536                   "integer or real expressions", pos);
1537         }
1538       default:
1539         error("operand expected");
1540     }
1541     lex = scan();
1542     return expr;
1543 }
1544 
error(const char * msg,int pos)1545 void dbCompiler::error(const char* msg, int pos)
1546 {
1547     if (pos < 0) {
1548         if ((pos = currPos-1) < 0) {
1549             pos = 0;
1550         }
1551     } else if (pos < firstPos) {
1552         pos = firstPos;
1553     }
1554     if (pos + offsetWithinStatement >= 0) {
1555         pos += offsetWithinStatement;
1556     }
1557     table->db->handleError(dbDatabase::QueryError, msg, pos);
1558     longjmp(abortCompilation, dbDatabase::QueryError);
1559 }
1560 
compileStartFollowPart(dbQuery & query)1561 void dbCompiler::compileStartFollowPart(dbQuery& query)
1562 {
1563     if (lex != tkn_start) {
1564         return;
1565     }
1566     int pos = currPos;
1567     if (scan() != tkn_from) {
1568         error("FROM expected after START", pos);
1569     }
1570     pos = currPos;
1571     switch (scan()) {
1572       case tkn_first:
1573         query.startFrom = dbCompiledQuery::StartFromFirst;
1574         break;
1575       case tkn_last:
1576         query.startFrom = dbCompiledQuery::StartFromLast;
1577         break;
1578       case tkn_var:
1579         if (varType == dbQueryElement::qVarReference) {
1580             if (varRefTable != table) {
1581                 error("Incompatiable type of reference variable");
1582             }
1583             query.startFrom = dbCompiledQuery::StartFromRef;
1584         } else if (varType == dbQueryElement::qVarArrayOfRef) {
1585             if (varRefTable != table) {
1586                 error("Incompatiable type of array of reference variable");
1587             }
1588             query.startFrom = dbCompiledQuery::StartFromArray;
1589         } else if (varType == dbQueryElement::qVarArrayOfRefPtr) {
1590             if (varRefTable != table) {
1591                 error("Incompatiable type of array of reference variable");
1592             }
1593             query.startFrom = dbCompiledQuery::StartFromArrayPtr;
1594         } else {
1595             error("Reference or array of reference variable expected");
1596         }
1597         query.root = varPtr;
1598         break;
1599       default:
1600         error("FIRST, LAST or reference varaible expected", pos);
1601     }
1602     if ((lex = scan()) == tkn_follow) {
1603         pos = currPos;
1604         if (scan() != tkn_by) {
1605             error("BY expected after FOLLOW", pos);
1606         }
1607         do {
1608             pos = currPos;
1609             if (scan() != tkn_ident) {
1610                 error("Field name expected", pos);
1611             }
1612             dbFieldDescriptor* fd;
1613             if ((fd = table->findSymbol(name)) == NULL) {
1614                 error("Field not found");
1615             }
1616             while (fd->type == dbField::tpStructure) {
1617                 pos = currPos;
1618                 if (scan() != tkn_dot) {
1619                     error("'.' expected", pos);
1620                 }
1621                 pos = currPos;
1622                 if (scan() != tkn_ident) {
1623                     error("Field name expected", pos);
1624                 }
1625                 if ((fd = fd->findSymbol(name)) == NULL) {
1626                     error("Field not found");
1627                 }
1628             }
1629             if (!(fd->type == dbField::tpReference
1630                   && fd->refTable == table) &&
1631                 !(fd->type == dbField::tpArray
1632                   && fd->components->type == dbField::tpReference
1633                   && fd->components->refTable == table))
1634             {
1635                 error("Follow field should be of compatibale reference "
1636                       "or array of reference type");
1637             }
1638             dbFollowByNode* node = new dbFollowByNode;
1639             node->field = fd;
1640             node->next = query.follow; // list should be inverted
1641             query.follow = node;
1642         } while ((lex = scan()) == tkn_comma);
1643     }
1644 }
1645 
deleteNode(dbExprNode * node)1646 void dbCompiler::deleteNode(dbExprNode* node) {
1647     dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
1648     dbCriticalSection cs(mutex);
1649     delete node;
1650 }
1651 
compileLimitPart(dbQuery & query)1652 void dbCompiler::compileLimitPart(dbQuery& query)
1653 {
1654     if (lex == tkn_limit) {
1655         int pos = currPos;
1656         cardinality_t l1 = 0;
1657         cardinality_t* lp1 = NULL;
1658         switch (scan()) {
1659           case tkn_iconst:
1660             l1 = (cardinality_t)ivalue;
1661             break;
1662           case tkn_var:
1663             if (sizeof(cardinality_t) == 4) {
1664                 if (varType != dbQueryElement::qVarInt4) {
1665                     error("LIMIT parameter should have int4 type", pos);
1666                 }
1667             } else {
1668                 if (varType != dbQueryElement::qVarInt8) {
1669                     error("LIMIT parameter should have int8 type", pos);
1670                 }
1671             }
1672             lp1 = (cardinality_t*)varPtr;
1673             break;
1674           default:
1675             error("Parameter or integer constant expected", pos);
1676         }
1677         if ((lex = scan()) == tkn_comma) {
1678             pos = currPos;
1679             cardinality_t l2 = 0;
1680             cardinality_t* lp2 = NULL;
1681             switch (scan()) {
1682               case tkn_iconst:
1683                 l2 = (cardinality_t)ivalue;
1684                 break;
1685               case tkn_var:
1686                 if (sizeof(cardinality_t) == 4) {
1687                     if (varType != dbQueryElement::qVarInt4) {
1688                         error("LIMIT parameter should have int4 type", pos);
1689                     }
1690                 } else {
1691                     if (varType != dbQueryElement::qVarInt8) {
1692                         error("LIMIT parameter should have int8 type", pos);
1693                     }
1694                 }
1695                 lp2 = (cardinality_t*)varPtr;
1696                 break;
1697               default:
1698                 error("Parameter or integer constant expected", pos);
1699             }
1700             query.stmtLimitStart = l1;
1701             query.stmtLimitStartPtr = lp1;
1702             query.stmtLimitLen = l2;
1703             query.stmtLimitLenPtr = lp2;
1704             lex = scan();
1705         } else {
1706             query.stmtLimitStart = 0;
1707             query.stmtLimitStartPtr = NULL;
1708             query.stmtLimitLen = l1;
1709             query.stmtLimitLenPtr = lp1;
1710         }
1711         query.limitSpecified = true;
1712     }
1713 }
1714 
compileOrderByPart(dbQuery & query)1715 void dbCompiler::compileOrderByPart(dbQuery& query)
1716 {
1717     if (lex == tkn_order) {
1718         dbOrderByNode** opp = &query.order;
1719         int pos = currPos;
1720         if (scan() != tkn_by) {
1721             error("BY expected after ORDER", pos);
1722         }
1723         int parentheses = 0;
1724         do {
1725             pos = currPos;
1726             int tkn = scan();
1727             if (tkn == tkn_lpar) {
1728                 parentheses += 1;
1729             } else {
1730                 ungetToken(tkn);
1731             }
1732             dbExprNode* expr = disjunction();
1733             dbOrderByNode* node = new dbOrderByNode;
1734             switch (expr->cop) {
1735               case dbvmLoadSelfBool:
1736               case dbvmLoadSelfInt1:
1737               case dbvmLoadSelfInt2:
1738               case dbvmLoadSelfInt4:
1739               case dbvmLoadSelfInt8:
1740               case dbvmLoadSelfReal4:
1741               case dbvmLoadSelfReal8:
1742               case dbvmLoadSelfString:
1743               case dbvmLoadSelfWString:
1744               case dbvmLoadSelfArray:
1745               case dbvmLoadSelfReference:
1746               case dbvmLoadSelfRawBinary:
1747                 assert(expr->ref.field != NULL);
1748                 node->field = expr->ref.field;
1749                 node->expr = NULL;
1750                 deleteNode(expr);
1751                 break;
1752               case dbvmLength:
1753                 if (expr->operand[0]->cop == dbvmLoadSelfArray) {
1754                     node->field = expr->operand[0]->ref.field;
1755                     node->expr = NULL;
1756                     deleteNode(expr);
1757                     break;
1758                 }
1759                 // no break
1760               default:
1761                 if (expr->type > tpReference) {
1762                     error("Expressions in ORDER BY part should have scalar type", pos);
1763                 }
1764                 node->field = NULL;
1765                 node->expr = expr;
1766             }
1767             node->table = table;
1768             node->ascent = true;
1769             *opp = node;
1770             opp = &node->next;
1771             *opp = NULL;
1772             if (lex == tkn_desc) {
1773                 node->ascent = false;
1774                 lex = scan();
1775             } else if (lex == tkn_asc) {
1776                 lex = scan();
1777             }
1778             if (lex == tkn_rpar) {
1779                 if (--parentheses < 0) {
1780                     error("Unbalanced parentheses ");
1781                 }
1782                 lex = scan();
1783             }
1784         } while (lex == tkn_comma);
1785     }
1786 }
1787 
1788 
compileExpression(dbTableDescriptor * table,char const * expr,int startPos)1789 dbExprNode* dbCompiler::compileExpression(dbTableDescriptor* table, char const* expr, int startPos)
1790 {
1791     TRACE_MSG(("Compile expression for table %s\n", table->name));
1792     if (setjmp(abortCompilation) == 0) {
1793         this->table = table;
1794         bindings = NULL;
1795         nFreeVars = 0;
1796         dbQueryElement elem(dbQueryElement::qExpression, expr, NULL);
1797         queryElement = &elem;
1798         hasToken  = false;
1799         currPos = firstPos = 0;
1800         offsetWithinStatement = startPos;
1801         return disjunction();
1802     } else {
1803         return NULL;
1804     }
1805 }
1806 
compile(dbTableDescriptor * table,dbQuery & query)1807 bool dbCompiler::compile(dbTableDescriptor* table, dbQuery& query)
1808 {
1809     TRACE_MSG(("Compile query for table %s\n", table->name));
1810     query.destroy();
1811     if (setjmp(abortCompilation) == 0) {
1812         this->table = table;
1813         bindings = NULL;
1814         nFreeVars = 0;
1815         queryElement = query.elements;
1816         currPos = firstPos = 0;
1817         hasToken  = false;
1818         offsetWithinStatement = query.pos;
1819         lex = tkn_eof;
1820         dbExprNode* expr = disjunction();
1821         if (expr->type != tpBoolean && expr->type != tpVoid) {
1822             error("Conditional expression should have boolean type\n");
1823         }
1824         compileStartFollowPart(query);
1825         compileOrderByPart(query);
1826         compileLimitPart(query);
1827         if (lex != tkn_eof) {
1828             error("START, ORDER BY or LIMIT expected");
1829         }
1830         query.tree = expr;
1831         query.table = table;
1832         return true;
1833     } else {
1834         dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
1835         dbCriticalSection cs(mutex);
1836         for (dbOrderByNode *op = query.order, *nop; op != NULL; op = nop) {
1837             nop = op->next;
1838             delete op;
1839         }
1840         for (dbFollowByNode *fp = query.follow, *nfp; fp != NULL; fp = nfp) {
1841             nfp = fp->next;
1842             delete fp;
1843         }
1844         return false;
1845     }
1846 }
1847 
dbCompiler()1848 dbCompiler::dbCompiler() {
1849     static struct {
1850         char* name;
1851         int   tag;
1852     } keywords[] = {
1853         {"all",     tkn_all},
1854         {"abs",     tkn_abs},
1855         {"and",     tkn_and},
1856 #ifndef AREA_IS_IDENTIFIER
1857         {"area",    tkn_area},
1858 #endif
1859         {"asc",     tkn_asc},
1860         {"between", tkn_between},
1861         {"by",      tkn_by},
1862         {"current", tkn_current},
1863         {"desc",    tkn_desc},
1864         {"escape",  tkn_escape},
1865         {"exists",  tkn_exists},
1866         {"first",   tkn_first},
1867         {"false",   tkn_false},
1868         {"follow",  tkn_follow},
1869         {"from",    tkn_from},
1870         {"in",      tkn_in},
1871         {"is",      tkn_is},
1872         {"integer", tkn_integer},
1873         {"insert",  tkn_insert},
1874         {"into",    tkn_into},
1875         {"last",    tkn_last},
1876         {"length",  tkn_length},
1877         {"like",    tkn_like},
1878         {"limit",   tkn_limit},
1879         {"lower",   tkn_lower},
1880 #ifdef USE_REGEX
1881         {"match",   tkn_match},
1882 #endif
1883         {"not",     tkn_not},
1884         {"null",    tkn_null},
1885         {"or",      tkn_or},
1886         {"order",   tkn_order},
1887         {"overlaps",tkn_overlaps},
1888         {"real",    tkn_real},
1889         {"select",  tkn_select},
1890         {"start",   tkn_start},
1891         {"string",  tkn_string},
1892         {"table",   tkn_table},
1893         {"true",    tkn_true},
1894         {"upper",   tkn_upper},
1895         {"where",   tkn_where},
1896         {"wstring", tkn_wstring}
1897     };
1898     if (!initialized) {
1899         for (unsigned i = 0; i < itemsof(keywords); i++) {
1900             dbSymbolTable::add(keywords[i].name, keywords[i].tag, FASTDB_CLONE_ANY_IDENTIFIER);
1901         }
1902         initialized = true;
1903     }
1904 }
1905 
removeTemporaries()1906 void dbInheritedAttribute::removeTemporaries()
1907 {
1908     for (dbStringValue *next, *s = tempStrings; s != NULL; s = next) {
1909         next = s->next;
1910         delete s;
1911     }
1912 }
1913 
1914 END_FASTDB_NAMESPACE
1915