1 //-< COMPILE.H >-----------------------------------------------------*--------*
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: 17-Jan-99    K.A. Knizhnik  * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Conditional expresion compiler
9 //-------------------------------------------------------------------*--------*
10 
11 #ifndef __COMPILER_H__
12 #define __COMPILER_H__
13 
14 #include <setjmp.h>
15 #ifdef USE_REGEX
16 #include <regex.h>
17 #endif
18 
19 BEGIN_FASTDB_NAMESPACE
20 
21 #if defined(__osf__) || defined(__FreeBSD__)
22 #define longjmp(b,s) _longjmp(b,s) // do not restore signal context
23 #define setjmp(b)  _setjmp(b)
24 #endif
25 
26 enum dbvmCodes {
27 #define DBVM(cop, type, n_operands, commutative) cop,
28 #ifdef VXWORKS
29 #include "compiler.dd"
30 #else
31 #include "compiler.d"
32 #endif // VXWORKS
33 dbvmLastCode
34 };
35 
36 #define IS_CONSTANT(c) \
37     (unsigned(c) - dbvmLoadVarBool <= (unsigned)dbvmLoadRectangleConstant - dbvmLoadVarBool)
38 
39 enum nodeType {
40     tpInteger,
41     tpBoolean,
42     tpReal,
43     tpString,
44     tpWString,
45     tpReference,
46     tpRectangle,
47     tpArray,
48     tpRawBinary,
49     tpFreeVar,  // index of EXISTS clause
50     tpList,     // list of expressions
51     tpVoid
52 };
53 
54 enum tokens {
55     tkn_ident,
56     tkn_lpar,
57     tkn_rpar,
58     tkn_lbr,
59     tkn_rbr,
60     tkn_dot,
61     tkn_comma,
62     tkn_power,
63     tkn_iconst,
64     tkn_sconst,
65     tkn_fconst,
66     tkn_add,
67     tkn_sub,
68     tkn_mul,
69     tkn_div,
70     tkn_and,
71     tkn_or,
72     tkn_not,
73     tkn_null,
74     tkn_neg,
75     tkn_eq,
76     tkn_ne,
77     tkn_gt,
78     tkn_ge,
79     tkn_lt,
80     tkn_le,
81     tkn_between,
82     tkn_escape,
83     tkn_exists,
84     tkn_like,
85     tkn_limit,
86     tkn_in,
87     tkn_length,
88     tkn_lower,
89     tkn_upper,
90     tkn_abs,
91     tkn_area,
92     tkn_is,
93     tkn_integer,
94     tkn_real,
95     tkn_string,
96     tkn_wstring,
97     tkn_first,
98     tkn_last,
99     tkn_current,
100     tkn_var,
101     tkn_col,
102     tkn_true,
103     tkn_false,
104     tkn_where,
105     tkn_follow,
106     tkn_start,
107     tkn_from,
108     tkn_order,
109     tkn_overlaps,
110     tkn_by,
111     tkn_asc,
112     tkn_desc,
113     tkn_eof,
114     tkn_insert,
115     tkn_into,
116     tkn_select,
117     tkn_table,
118     tkn_error,
119     tkn_all,
120     tkn_match,
121     tkn_last_token
122 };
123 
124 struct dbStrLiteral {
125     char* str;
126     int   len;
127 };
128 
129 struct dbWStrLiteral {
130     wchar_t* str;
131     int      len;
132 };
133 
134 
135 class dbUserFunction;
136 class dbExprNodeSegment;
137 
138 class FASTDB_DLL_ENTRY dbExprNodeAllocator {
139   private:
140     friend class dbExprNodeSegment;
141     dbExprNode*        freeNodeList;
142     dbExprNodeSegment* segmentList;
143     dbMutex            mutex;
144 
145   public:
getMutex()146     dbMutex&    getMutex() {
147         return mutex;
148     }
149     dbExprNode* allocate();
150     void        deallocate(dbExprNode* node);
151     void        reset();
152 
153     ~dbExprNodeAllocator();
154     static dbExprNodeAllocator instance;
155 };
156 
157 class FASTDB_DLL_ENTRY dbExprNode {
158     friend class dbExprNodeSegment;
159   public:
160     nat1 cop;
161     nat1 type;
162     nat2 offs;
163 
164     static const nat1  nodeTypes[];
165     static const nat1  nodeOperands[];
166     static const nat1  commutativeOperator[];
167 
168     struct ref_operands {
169         dbExprNode*         base;  // the same as operand[0]
170         dbFieldDescriptor*  field;
171     };
172 
173     struct func_operands {
174         dbExprNode*         arg[3];
175         void*               fptr;
176     };
177 
178 #ifdef USE_REGEX
179     struct regex_operands {
180         dbExprNode*         opd;
181         regex_t             re;
182     };
183 #endif
184 
185     union {
186         dbExprNode*    operand[3];
187         dbExprNode*    next;
188         oid_t          oid;
189         db_int8        ivalue;
190         real8          fvalue;
191         rectangle      rvalue;
192         dbStrLiteral   svalue;
193         dbWStrLiteral  wsvalue;
194         void const*    var;
195         ref_operands   ref;
196         func_operands  func;
197 #ifdef USE_REGEX
198         regex_operands regex;
199 #endif
200     };
201 
202     dbExprNode(dbExprNode* node);
203 
204     dbExprNode(int cop, dbExprNode* left = NULL, dbExprNode* right = NULL,
205                dbExprNode* right2 = NULL)
206     {
207         this->cop = cop;
208         type = nodeTypes[cop];
209         operand[0] = left;
210         operand[1] = right;
211         operand[2] = right2;
212     }
dbExprNode(int cop,dbExprNode * expr1,dbExprNode * expr2,int offs)213     dbExprNode(int cop, dbExprNode* expr1, dbExprNode* expr2, int offs) {
214         this->cop = cop;
215         this->offs = (nat2)offs;
216         type = nodeTypes[cop];
217         operand[0] = expr1;
218         operand[1] = expr2;
219     }
dbExprNode(int cop,dbExprNode * expr,int offs)220     dbExprNode(int cop, dbExprNode* expr, int offs) {
221         this->cop = cop;
222         this->offs = (nat2)offs;
223         type = nodeTypes[cop];
224         operand[0] = expr;
225     }
226     dbExprNode(int cop, dbFieldDescriptor* field, dbExprNode* base = NULL)
227     {
228         this->cop = cop;
229         this->offs = (nat2)field->dbsOffs;
230         type = nodeTypes[cop];
231         ref.field = field;
232         ref.base = base;
233     }
dbExprNode(int cop,db_int8 ivalue)234     dbExprNode(int cop, db_int8 ivalue) {
235         this->cop = cop;
236         this->ivalue = ivalue;
237         type = tpInteger;
238     }
dbExprNode(int cop,real8 fvalue)239     dbExprNode(int cop, real8 fvalue) {
240         this->cop = cop;
241         this->fvalue = fvalue;
242         type = tpReal;
243     }
dbExprNode(int cop,rectangle rvalue)244     dbExprNode(int cop, rectangle rvalue) {
245         this->cop = cop;
246         this->rvalue = rvalue;
247         type = tpRectangle;
248     }
dbExprNode(int cop,dbStrLiteral & svalue)249     dbExprNode(int cop, dbStrLiteral& svalue) {
250         this->cop = cop;
251         this->svalue = svalue;
252         type = tpString;
253     }
dbExprNode(int cop,dbWStrLiteral & wsvalue)254     dbExprNode(int cop, dbWStrLiteral& wsvalue) {
255         this->cop = cop;
256         this->wsvalue = wsvalue;
257         type = tpWString;
258     }
dbExprNode(int cop,void const * var)259     dbExprNode(int cop, void const* var) {
260         this->cop = cop;
261         this->var = var;
262         type = nodeTypes[cop];
263     }
264     dbExprNode(int cop, void* fptr, dbExprNode* expr1, dbExprNode* expr2 = NULL, dbExprNode* expr3 = NULL) {
265         this->cop = cop;
266         func.arg[0] = expr1;
267         func.arg[1] = expr2;
268         func.arg[2] = expr3;
269         func.fptr = fptr;
270         type = nodeTypes[cop];
271     }
272     ~dbExprNode();
273 
new(size_t size EXTRA_DEBUG_NEW_PARAMS)274     void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS) {
275         return dbExprNodeAllocator::instance.allocate();
276     }
277 
delete(void * ptr EXTRA_DEBUG_NEW_PARAMS)278     void operator delete(void* ptr EXTRA_DEBUG_NEW_PARAMS) {
279         dbExprNodeAllocator::instance.deallocate((dbExprNode*)ptr);
280     }
281 };
282 
283 
284 class dbExprNodeSegment {
285   public:
286     enum { allocationQuantum = 1024};
287     char               buf[sizeof(dbExprNode)*allocationQuantum];
288     dbExprNodeSegment* next;
289 };
290 
291 
292 class dbBinding {
293   public:
294     dbBinding*  next;
295     char const* name;
296     bool        used;
297     int         index;
298 };
299 
300 class dbOrderByNode {
301   public:
302     dbOrderByNode*     next;
303     dbFieldDescriptor* field;
304     dbTableDescriptor* table;
305     dbExprNode*        expr;
306     bool               ascent;  // true for ascent order, false for descent
307 
getField()308     dbFieldDescriptor* getField() {
309         return (field != NULL) ? field
310             : ((unsigned)expr->cop - dbvmLoadBool <= dbvmLoadRawBinary - dbvmLoadBool)
311                ? expr->ref.field : NULL;
312     }
313 
~dbOrderByNode()314     ~dbOrderByNode() {
315         delete expr;
316     }
317 };
318 
319 class dbFollowByNode {
320   public:
321     dbFollowByNode*    next;
322     dbFieldDescriptor* field;
323 };
324 
325 class FASTDB_DLL_ENTRY dbCompiler {
326     friend class dbQuery;
327     friend class dbQueryElement;
328   public:
329     enum {
330         maxSymbolLen    = 4096,
331         maxFreeVars  = 4
332     };
333 
334     dbTableDescriptor* table;
335     dbQueryElement*    queryElement;
336     int                currPos;
337     int                firstPos;
338     int                offsetWithinStatement;
339     int                bvalue;
340     db_int8            ivalue;
341     real8              fvalue;
342     dbStrLiteral       svalue;
343     dbWStrLiteral      wsvalue;
344     bool               hasToken;
345     int                lex;
346     char*              name;
347     dbBinding*         bindings;
348     int                nFreeVars;
349     int                varType;
350     void const*        varPtr;
351     dbTableDescriptor* varRefTable;
352 
353     jmp_buf            abortCompilation;
354     static bool        initialized;
355 
356     void        compare(dbExprNode* expr, dbExprNode* list);
357 
358     int         scan();
ungetToken(int tkn)359     void        ungetToken(int tkn) {
360         lex = tkn;
361         hasToken = true;
362     }
363     void        error(const char* msg, int pos = -1);
364     dbExprNode* conjunction();
365     dbExprNode* disjunction();
366     dbExprNode* comparison();
367     dbExprNode* addition();
368     dbExprNode* multiplication();
369     dbExprNode* power();
370     dbExprNode* term();
371     dbExprNode* buildList();
372     dbExprNode* userDefinedOperator();
373     dbExprNode* field(dbExprNode* expr, dbTableDescriptor* refTable,
374                       dbFieldDescriptor* fd);
375 
376     bool        compile(dbTableDescriptor* table, dbQuery& query);
377     dbExprNode* compileExpression(dbTableDescriptor* table,  char const* expr, int startPos);
378     void        compileOrderByPart(dbQuery& query);
379     void        compileLimitPart(dbQuery& query);
380     void        compileStartFollowPart(dbQuery& query);
381 
382     void        deleteNode(dbExprNode* node);
383     dbExprNode* rectangleConstant(dbExprNode* head);
384 
385     dbCompiler();
386 };
387 
388 class dbDatabaseThreadContext : public dbL2List {
389   public:
390     int readAccess;
391     int writeAccess;
392     int concurrentId;
393     int mutatorCSLocked;
394     int isMutator;
395 
396     dbL2List cursors;
397 
398     dbCompiler compiler;
399 
400     dbProcessId currPid;
401 
402     bool     interactive;
403     bool     catched;
404     bool     commitDelayed;
405     bool     removeContext;
406     jmp_buf  unwind;
407 
dbDatabaseThreadContext()408     dbDatabaseThreadContext() {
409         concurrentId = 0;
410         readAccess = false;
411         writeAccess = false;
412         mutatorCSLocked = false;
413         isMutator = false;
414         interactive = false;
415         catched = false;
416         commitDelayed = false;
417         removeContext = false;
418         currPid = dbProcessId::getCurrent();
419     }
420 };
421 
422 union dbSynthesizedAttribute {
423     byte*     base;
424     int       bvalue;
425     db_int8   ivalue;
426     real8     fvalue;
427     rectangle rvalue;
428     void*     raw;
429     oid_t     oid;
430 
431     struct {
432         char* base;
433         int   size;
434         dbUDTComparator comparator;
435     } array;
436 };
437 
438 struct dbStringValue;
439 
440 struct FASTDB_DLL_ENTRY dbInheritedAttribute {
441     byte*          record;
442     oid_t          oid;
443     dbTable*       table;
444     dbDatabase*    db;
445     dbStringValue* tempStrings;
446     size_t         paramBase;
447     enum {
448         internalStrBufSize = 8*1024
449     };
450     size_t         strBufPos;
451     char           strBuf[internalStrBufSize];
452 
453     struct {
454         int     index;
455         jmp_buf unwind;
456     } exists_iterator[dbCompiler::maxFreeVars];
457 
458     void removeTemporaries();
459 
dbInheritedAttributedbInheritedAttribute460     dbInheritedAttribute() {
461         tempStrings = NULL;
462         strBufPos = 0;
463     }
464 
~dbInheritedAttributedbInheritedAttribute465     ~dbInheritedAttribute() {
466         removeTemporaries();
467     }
468 };
469 
470 struct dbStringValue {
471     dbStringValue* next;
472     char           str[1];
473 
createdbStringValue474     static char* create(size_t size, dbInheritedAttribute& attr) {
475         if (attr.strBufPos + size > sizeof(attr.strBuf)) {
476             dbStringValue* sv =
477                 (dbStringValue*)new char[offsetof(dbStringValue, str) + size];
478             sv->next = attr.tempStrings;
479             attr.tempStrings = sv;
480             return sv->str;
481         } else {
482             char* p = attr.strBuf + attr.strBufPos;
483             attr.strBufPos += size;
484             return p;
485         }
486     }
487 
createdbStringValue488     static char* create(char const* s, dbInheritedAttribute& attr) {
489         size_t len = strlen(s) + 1;
490         char*  buf;
491         if (attr.strBufPos + len > sizeof(attr.strBuf)) {
492             dbStringValue* sv =
493                 (dbStringValue*)new char[offsetof(dbStringValue,str)+len];
494             sv->next = attr.tempStrings;
495             attr.tempStrings = sv;
496             buf = sv->str;
497         } else {
498             buf = attr.strBuf + attr.strBufPos;
499             attr.strBufPos += len;
500         }
501         return strcpy(buf, s);
502     }
503 };
504 
505 inline char* findWildcard(char* pattern, char* escape = NULL)
506 {
507     if (escape == NULL) {
508         while (*pattern != dbMatchAnyOneChar &&
509                *pattern != dbMatchAnySubstring)
510         {
511             if (*pattern++ == '\0') {
512                 return NULL;
513             }
514         }
515     } else {
516         char esc = *escape;
517         while (*pattern != dbMatchAnyOneChar &&
518                *pattern != dbMatchAnySubstring &&
519                *pattern != esc)
520         {
521             if (*pattern++ == '\0') {
522                 return NULL;
523             }
524         }
525     }
526     return pattern;
527 }
528 
529 inline wchar_t* findWildcard(wchar_t* pattern, wchar_t* escape = NULL)
530 {
531     if (escape == NULL) {
532         while (*pattern != dbMatchAnyOneChar &&
533                *pattern != dbMatchAnySubstring)
534         {
535             if (*pattern++ == '\0') {
536                 return NULL;
537             }
538         }
539     } else {
540         wchar_t esc = *escape;
541         while (*pattern != dbMatchAnyOneChar &&
542                *pattern != dbMatchAnySubstring &&
543                *pattern != esc)
544         {
545             if (*pattern++ == '\0') {
546                 return NULL;
547             }
548         }
549     }
550     return pattern;
551 }
552 
553 END_FASTDB_NAMESPACE
554 
555 #endif
556