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

Generated on Thu Nov 24 23:14:29 2005 for GigaBASE by doxygen 1.3.5