Main Page   Class Hierarchy   Compound List   File List   Compound Members  

compiler.h

00001 //-<  COMPILE.H >----------------------------------------------------*--------*
00002 // GigaBASE                  Version 1.0         (c) 1999  GARRET    *     ?  *
00003 // (Post Relational Database Management System)                      *   /\|  *
00004 //                                                                   *  /  \  *
00005 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
00006 //                          Last update: 17-Jan-99    K.A. Knizhnik  * GARRET *
00007 //-------------------------------------------------------------------*--------*
00008 // Conditional expresion compiler
00009 //-------------------------------------------------------------------*--------*
00010 
00011 #ifndef __COMPILER_H__
00012 #define __COMPILER_H__
00013 
00014 #include <setjmp.h>
00015 #ifdef USE_REGEX
00016 extern "C" { 
00017 #include <regex.h>
00018 };
00019 #endif
00020 
00021 BEGIN_GIGABASE_NAMESPACE
00022 
00023 #if defined(__osf__) || defined(__FreeBSD__)
00024 #define longjmp(b,s) _longjmp(b,s) // do not restore signal context
00025 #define setjmp(b)  _setjmp(b)
00026 #endif
00027 
00028 enum dbvmCodes {
00029 #define DBVM(cop, type, n_operands, commutative) cop,
00030 #include "compiler.d"
00031 dbvmLastCode
00032 };
00033 
00034 
00035 #define IS_CONSTANT(c) \
00036 (unsigned(c) - dbvmLoadVarBool <= (unsigned)dbvmLoadRectangleConstant - dbvmLoadVarBool)
00037 
00038 
00039 // 
00040 // Check if operation is equality comparision 
00041 //
00042 #define IS_EQUAL_CMP(c) dbExprNode::commutativeOperator[c] == c
00043 
00044 enum nodeType {
00045     tpInteger,
00046     tpBoolean,
00047     tpReal,
00048     tpString,
00049     tpReference,
00050     tpRectangle,
00051     tpArray,
00052     tpRawBinary, 
00053     tpFreeVar,  // index of EXISTS clause
00054     tpList,     // list of expressions
00055     tpVoid
00056 };
00057 
00058 enum tokens {
00059     tkn_ident,
00060     tkn_lpar,
00061     tkn_rpar,
00062     tkn_lbr,
00063     tkn_rbr,
00064     tkn_dot,
00065     tkn_comma,
00066     tkn_power,
00067     tkn_iconst,
00068     tkn_sconst,
00069     tkn_fconst,
00070     tkn_all,
00071     tkn_add,
00072     tkn_sub,
00073     tkn_mul,
00074     tkn_div,
00075     tkn_and,
00076     tkn_or,
00077     tkn_not,
00078     tkn_null,
00079     tkn_neg,
00080     tkn_eq,
00081     tkn_ne,
00082     tkn_gt,
00083     tkn_ge,
00084     tkn_lt,
00085     tkn_le,
00086     tkn_between,
00087     tkn_escape,
00088     tkn_exists,
00089     tkn_like,
00090     tkn_limit,
00091     tkn_in,
00092     tkn_length,
00093     tkn_lower,
00094     tkn_upper,
00095     tkn_abs,
00096     tkn_area,
00097     tkn_is,
00098     tkn_integer,
00099     tkn_real,
00100     tkn_string,
00101     tkn_first,
00102     tkn_last,
00103     tkn_current,
00104     tkn_var,
00105     tkn_col,
00106     tkn_true,
00107     tkn_false,
00108     tkn_where,
00109     tkn_follow,
00110     tkn_start,
00111     tkn_from,
00112     tkn_order,
00113     tkn_overlaps,
00114     tkn_by,
00115     tkn_asc,
00116     tkn_desc,
00117     tkn_eof,
00118     tkn_insert, 
00119     tkn_into, 
00120     tkn_select, 
00121     tkn_table,
00122     tkn_error,
00123     tkn_match,
00124     tkn_last_token
00125 };
00126 
00127 struct dbStrLiteral {
00128     char_t* str;
00129     int     len;
00130 };
00131 
00132 
00133 class dbUserFunction;
00134 class dbExprNodeSegment;
00135 
00136 class GIGABASE_DLL_ENTRY dbExprNodeAllocator { 
00137   private:
00138     friend class dbExprNodeSegment;
00139     dbExprNode*        freeNodeList;
00140     dbExprNodeSegment* segmentList;
00141     dbMutex            mutex;
00142     
00143   public:  
00144     dbMutex&    getMutex() {
00145         return mutex;
00146     }
00147     dbExprNode* allocate();
00148     void        deallocate(dbExprNode* node);
00149     void        reset();
00150 
00151     ~dbExprNodeAllocator();
00152     static dbExprNodeAllocator instance;
00153 };
00154 
00155 class GIGABASE_DLL_ENTRY dbExprNode {
00156   public:
00157     nat1 cop;
00158     nat1 type;
00159     nat2 offs;
00160 
00161     static const nat1  nodeTypes[];
00162     static const nat1  nodeOperands[];
00163     static const nat1  commutativeOperator[];
00164 
00165 
00166     union {
00167         dbExprNode*  operand[3];
00168         dbExprNode*  next;
00169         oid_t        oid;
00170         db_int8      ivalue;
00171         real8        fvalue;
00172         rectangle    rvalue;
00173         dbStrLiteral svalue;
00174         void const*  var;
00175 
00176         struct {
00177             dbExprNode*         base;  // the same as operand[0]
00178             dbFieldDescriptor*  field;
00179         } ref;
00180 
00181         struct {
00182             dbExprNode*         arg[3];   // the same as operand[0]
00183             void*               fptr;
00184         } func;
00185 
00186 #ifdef USE_REGEX
00187         struct { 
00188             dbExprNode*         opd;  
00189             regex_t             re;
00190         } regex;
00191 #endif
00192     };
00193 
00194     dbExprNode(dbExprNode* node);
00195 
00196     dbExprNode(int cop, dbExprNode* left = NULL, dbExprNode* right = NULL,
00197                dbExprNode* right2 = NULL)
00198     {
00199         this->cop = cop;
00200         type = nodeTypes[cop];
00201         operand[0] = left;
00202         operand[1] = right;
00203         operand[2] = right2;
00204     }
00205     dbExprNode(int cop, dbExprNode* expr1, dbExprNode* expr2, int offs) {
00206         this->cop = cop;
00207         this->offs = (nat2)offs;
00208         type = nodeTypes[cop];
00209         operand[0] = expr1;
00210         operand[1] = expr2;
00211     }
00212     dbExprNode(int cop, dbExprNode* expr, int offs) {
00213         this->cop = cop;
00214         this->offs = (nat2)offs;
00215         type = nodeTypes[cop];
00216         operand[0] = expr;
00217     }
00218     dbExprNode(int cop, dbFieldDescriptor* field, dbExprNode* base = NULL)
00219     {
00220         this->cop = cop;
00221         this->offs = (nat2)field->dbsOffs;
00222         type = nodeTypes[cop];
00223         ref.field = field;
00224         ref.base = base;
00225     }
00226     dbExprNode(int cop, db_int8 ivalue) {
00227         this->cop = cop;
00228         this->ivalue = ivalue;
00229         type = tpInteger;
00230     }
00231     dbExprNode(int cop, rectangle rvalue) {
00232         this->cop = cop;
00233         this->rvalue = rvalue;
00234         type = tpRectangle;
00235     }
00236     dbExprNode(int cop, real8 fvalue) {
00237         this->cop = cop;
00238         this->fvalue = fvalue;
00239         type = tpReal;
00240     }
00241     dbExprNode(int cop, dbStrLiteral& svalue) {
00242         this->cop = cop;
00243         this->svalue = svalue;
00244         type = tpString;
00245     }
00246     dbExprNode(int cop, void const* var) {
00247         this->cop = cop;
00248         this->var = var;
00249         type = nodeTypes[cop];
00250     }
00251     dbExprNode(int cop, void* fptr, dbExprNode* expr1, dbExprNode* expr2 = NULL, dbExprNode* expr3 = NULL) { 
00252         this->cop = cop;
00253         func.arg[0] = expr1;
00254         func.arg[1] = expr2;
00255         func.arg[2] = expr3;
00256         func.fptr = fptr;
00257         type = nodeTypes[cop];
00258     }
00259     ~dbExprNode();
00260 
00261     void* operator new(size_t size) { 
00262         return dbExprNodeAllocator::instance.allocate();
00263     }
00264 
00265     void operator delete(void* ptr) { 
00266         dbExprNodeAllocator::instance.deallocate((dbExprNode*)ptr);
00267     }
00268 };
00269 
00270 
00271 class dbExprNodeSegment {
00272   public:
00273     enum { allocationQuantum = 1024};
00274     char               buf[sizeof(dbExprNode)*allocationQuantum];
00275     dbExprNodeSegment* next;
00276 };
00277 
00278 
00279 class dbBinding {
00280   public:
00281     dbBinding*    next;
00282     char_t const* name;
00283     bool          used;
00284     int           index;
00285 };
00286 
00287 class dbOrderByNode {
00288   public:
00289     dbOrderByNode*     next;
00290     dbFieldDescriptor* field;
00291     dbTableDescriptor* table;
00292     dbExprNode*        expr;
00293     bool               ascent;  // true for ascent order, false for descent
00294     
00295     ~dbOrderByNode() { 
00296         delete expr;
00297     }
00298 };
00299 
00300 class dbFollowByNode {
00301   public:
00302     dbFollowByNode*    next;
00303     dbFieldDescriptor* field;
00304 };
00305 
00306 class GIGABASE_DLL_ENTRY dbCompiler {
00307     friend class dbQuery;
00308     friend class dbQueryElement;
00309   public:
00310     enum {
00311         maxStrLen    = 4096,
00312         maxFreeVars  = 4
00313     };
00314 
00315     dbTableDescriptor* table;
00316     dbQueryElement*    queryElement;
00317     int                currPos;
00318     int                firstPos;
00319     int                offsetWithinStatement;
00320     int                bvalue;
00321     db_int8            ivalue;
00322     real8              fvalue;
00323     dbStrLiteral       svalue;
00324     int                lex;
00325     bool               has_token;               
00326     char_t*            name;
00327     dbBinding*         bindings;
00328     int                nFreeVars;
00329     int                varType;
00330     void const*        varPtr;
00331     dbTableDescriptor* varRefTable;
00332 
00333     jmp_buf            abortCompilation;
00334     static bool        initialized;
00335 
00336     void        compare(dbExprNode* expr, dbExprNode* list);
00337 
00338     int         scan();
00339     void        unget_token(int tkn) {
00340         lex = tkn;
00341         has_token = true;
00342     }
00343 
00344     void        error(const char* msg, int pos = -1);
00345     dbExprNode* conjunction();
00346     dbExprNode* disjunction();
00347     dbExprNode* comparison();
00348     dbExprNode* addition();
00349     dbExprNode* multiplication();
00350     dbExprNode* power();
00351     dbExprNode* userDefinedOperator();
00352     dbExprNode* term();
00353     dbExprNode* buildList();
00354     dbExprNode* field(dbExprNode* expr, dbTableDescriptor* refTable,
00355                       dbFieldDescriptor* fd);
00356 
00357     bool        compile(dbTableDescriptor* table, dbQuery& query);
00358     dbExprNode* compileExpression(dbTableDescriptor* table,  char_t const* expr, int startPos);
00359     void        compileOrderByPart(dbQuery& query);
00360     void        compileLimitPart(dbQuery& query);
00361     void        compileStartFollowPart(dbQuery& query);
00362 
00363     void        deleteNode(dbExprNode* node);
00364     dbExprNode* rectangleConstant(dbExprNode* head);
00365 
00366     dbCompiler();
00367 };
00368 
00369 class GIGABASE_DLL_ENTRY dbDatabaseThreadContext : public dbL2List {
00370   public:
00371     dbLockType holdLock;
00372     dbEvent    event;
00373     
00374     int concurrentId;
00375     dbL2List cursors;
00376 
00377     dbCompiler compiler;
00378 
00379     bool       interactive;
00380     bool       catched;
00381     bool       commitDelayed;
00382     bool       removeContext;
00383 
00384     dbLockType pendingLock;
00385     dbDatabaseThreadContext* nextPending;
00386 
00387     jmp_buf  unwind;
00388 
00389     dbDatabaseThreadContext() {
00390         concurrentId = 0;
00391         holdLock = dbNoLock;
00392         pendingLock = dbNoLock;
00393         interactive = false;
00394         catched = false;
00395         commitDelayed = false;
00396         removeContext = false;
00397         event.open();
00398     }
00399     ~dbDatabaseThreadContext() {
00400         event.close();
00401     }
00402 };
00403 
00404 class dbSynthesizedAttribute {
00405   public:
00406     union {
00407         byte*     base;
00408         int       bvalue;
00409         db_int8   ivalue;
00410         rectangle rvalue;
00411         real8     fvalue;
00412         void*     raw;
00413         oid_t     oid;
00414 
00415         struct {
00416             char* base;
00417             int   size;
00418         } array;
00419     };
00420     enum ObjectStorageClass {
00421         osSelf,     // self object field
00422         osStack,    // object allocate on stack
00423         osDynamic,  // object allocated by operstor new
00424         osPage,     // reference to page in page pool
00425         osFree      // deallocated attribute
00426     };
00427     ObjectStorageClass osClass;
00428     union {
00429         size_t sp;
00430         struct {
00431             byte*                   addr;
00432             dbSynthesizedAttribute* next;
00433         } loc;
00434     } os;
00435 
00436     dbSynthesizedAttribute() : osClass(osSelf) {}
00437 };
00438 
00439 class dbInheritedAttribute {
00440   public:
00441     byte*              record;
00442     oid_t              oid;
00443     dbTableDescriptor* table;
00444     dbDatabase*        db;
00445     size_t             paramBase;
00446 
00447     enum {
00448 #ifdef _ARM
00449         internalStackSize = 4*1024
00450 #else
00451         internalStackSize = 64*1024
00452 #endif
00453     };
00454 
00455 
00456     dbSynthesizedAttribute* dynChain;
00457     size_t sp;
00458 
00459     struct IteratorContext {
00460         int     index;
00461         int     sp;
00462         dbSynthesizedAttribute* dynChain;
00463         jmp_buf unwind;
00464     } exists_iterator[dbCompiler::maxFreeVars];
00465 
00466     byte   stack[internalStackSize];
00467 
00468     void cleanup() {
00469         dbSynthesizedAttribute* attr;
00470         for (attr = dynChain; attr != NULL; attr = attr->os.loc.next) {
00471             free(*attr);
00472         }
00473     }
00474 
00475     void unwind(int i) {
00476         IteratorContext* ctx = &exists_iterator[i];
00477         sp = ctx->sp;
00478         while (dynChain != ctx->dynChain) {
00479             free(*dynChain);
00480         }
00481         longjmp(ctx->unwind, 1);
00482     }
00483 
00484     void makeDynamic(dbSynthesizedAttribute& attr, void* p) {
00485         attr.osClass = dbSynthesizedAttribute::osDynamic;
00486         attr.os.loc.addr = (byte*)p;
00487         attr.os.loc.next = dynChain;
00488         dynChain = &attr;
00489     }
00490     void allocateString(dbSynthesizedAttribute& attr, int len) {
00491         if (sp + len*sizeof(char_t) > sizeof(stack)) {
00492             attr.array.base = (char*)dbMalloc(len*sizeof(char_t));
00493             attr.array.size = len;
00494             makeDynamic(attr, attr.array.base);
00495         } else {
00496             attr.osClass = dbSynthesizedAttribute::osStack;
00497             attr.array.base = (char*)stack + sp;
00498             attr.array.size = len;
00499             attr.os.sp = sp;
00500             sp += len*sizeof(char_t);
00501         }
00502     }
00503     void allocateString(dbSynthesizedAttribute& attr, char_t* str, size_t len) {
00504         allocateString(attr, (int)len);
00505         memcpy(attr.array.base, str, len*sizeof(char_t));
00506     }
00507     void allocateString(dbSynthesizedAttribute& attr, char_t* str) {
00508         allocateString(attr, str, STRLEN(str) + 1);
00509     }
00510 
00511     void free(dbSynthesizedAttribute& attr) {
00512         switch (attr.osClass) {
00513           case dbSynthesizedAttribute::osStack:
00514             sp = attr.os.sp;
00515             return;
00516           case dbSynthesizedAttribute::osPage:
00517             db->pool.unfix(attr.os.loc.addr);
00518             break;
00519           case dbSynthesizedAttribute::osDynamic:
00520             dbFree(attr.os.loc.addr);
00521             break;
00522           default:
00523             return;
00524         }
00525         dbSynthesizedAttribute** sap;
00526         for (sap = &dynChain; *sap != &attr; sap = &(*sap)->os.loc.next);
00527         *sap = attr.os.loc.next;
00528         attr.osClass = dbSynthesizedAttribute::osFree;
00529     }
00530 
00531     void load(dbSynthesizedAttribute& sattr) {
00532         offs_t pos = db->getPos(sattr.oid) & ~dbFlagsMask;
00533         int offs = (int)pos & (dbPageSize-1);
00534         byte* page = db->pool.get(pos - offs);
00535         dbRecord* rec = (dbRecord*)(page + offs);
00536         size_t size = rec->size;
00537         if (offs + size > dbPageSize) {
00538             byte* dst;
00539             size_t start = DOALIGN(sp, 8);
00540             if (start + size > sizeof(stack)) {
00541                 dst = dbMalloc(size);
00542                 makeDynamic(sattr, dst);
00543             } else {
00544                 sattr.osClass = dbSynthesizedAttribute::osStack;
00545                 sattr.os.sp = sp;
00546                 dst = stack + start;
00547                 sp = start + size;
00548             }
00549             sattr.base = dst;
00550             memcpy(dst, rec, dbPageSize - offs);
00551             db->pool.unfix(page);
00552             size -= dbPageSize - offs;
00553             pos += dbPageSize - offs;
00554             dst += dbPageSize - offs;
00555             while (size > dbPageSize) {
00556                 page = db->pool.get(pos);
00557                 memcpy(dst, page, dbPageSize);
00558                 db->pool.unfix(page);
00559                 dst += dbPageSize;
00560                 size -= dbPageSize;
00561                 pos += dbPageSize;
00562             }
00563             page = db->pool.get(pos);
00564             memcpy(dst, page, size);
00565             db->pool.unfix(page);
00566         } else {
00567             sattr.base = (byte*)rec;
00568             sattr.osClass = dbSynthesizedAttribute::osPage;
00569             sattr.os.loc.addr = page;
00570             sattr.os.loc.next = dynChain;
00571             dynChain = &sattr;
00572         }
00573     }
00574 
00575     dbInheritedAttribute() {
00576         dynChain = NULL;
00577         sp = 0;
00578     }
00579 
00580     ~dbInheritedAttribute() {
00581         cleanup();
00582     }
00583 };
00584 
00585 inline char_t* findWildcard(char_t* pattern, char_t* escape = NULL)
00586 {
00587     if (escape == NULL) {
00588         while (*pattern != dbMatchAnyOneChar &&
00589                *pattern != dbMatchAnySubstring)
00590         {
00591             if (*pattern++ == '\0') {
00592                 return NULL;
00593             }
00594         }
00595     } else {
00596         char_t esc = *escape;
00597         while (*pattern != dbMatchAnyOneChar &&
00598                *pattern != dbMatchAnySubstring &&
00599                *pattern != esc)
00600         {
00601             if (*pattern++ == '\0') {
00602                 return NULL;
00603             }
00604         }
00605     }
00606     return pattern;
00607 }
00608 
00609 
00610 END_GIGABASE_NAMESPACE
00611 
00612 #endif
00613 
00614 
00615 

Generated on Thu Feb 14 21:46:03 2008 for GigaBASE by doxygen1.2.18