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(®ex.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