• Main Page
  • Classes
  • Files
  • File List

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

Generated on Mon Aug 23 2010 00:04:01 for GigaBASE by  doxygen 1.7.1