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)dbvmLoadVarStdString - 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 
00298 class dbFollowByNode {
00299   public:
00300     dbFollowByNode*    next;
00301     dbFieldDescriptor* field;
00302 };
00303 
00304 class GIGABASE_DLL_ENTRY dbCompiler {
00305     friend class dbQuery;
00306     friend class dbQueryElement;
00307   public:
00308     enum {
00309         maxStrLen    = 4096,
00310         maxFreeVars  = 4
00311     };
00312 
00313     dbTableDescriptor* table;
00314     dbQueryElement*    queryElement;
00315     int                currPos;
00316     int                firstPos;
00317     int                offsetWithinStatement;
00318     int                bvalue;
00319     db_int8            ivalue;
00320     real8              fvalue;
00321     dbStrLiteral       svalue;
00322     int                lex;
00323     bool               has_token;               
00324     char_t*            name;
00325     dbBinding*         bindings;
00326     int                nFreeVars;
00327     int                varType;
00328     void const*        varPtr;
00329     dbTableDescriptor* varRefTable;
00330 
00331     jmp_buf            abortCompilation;
00332     static bool        initialized;
00333 
00334     int         compare(dbExprNode* expr, dbExprNode* list);
00335 
00336     int         scan();
00337     void        unget_token(int tkn) {
00338         lex = tkn;
00339         has_token = true;
00340     }
00341 
00342     void        error(const char* msg, int pos = -1);
00343     dbExprNode* conjunction();
00344     dbExprNode* disjunction();
00345     dbExprNode* comparison();
00346     dbExprNode* addition();
00347     dbExprNode* multiplication();
00348     dbExprNode* power();
00349     dbExprNode* userDefinedOperator();
00350     dbExprNode* term();
00351     dbExprNode* field(dbExprNode* expr, dbTableDescriptor* refTable,
00352                       dbFieldDescriptor* fd);
00353 
00354     bool        compile(dbTableDescriptor* table, dbQuery& query);
00355     dbExprNode* compileExpression(dbTableDescriptor* table,  char_t const* expr, int startPos);
00356     void        compileOrderByPart(dbQuery& query);
00357     void        compileLimitPart(dbQuery& query);
00358     void        compileStartFollowPart(dbQuery& query);
00359 
00360     dbCompiler();
00361 };
00362 
00363 class GIGABASE_DLL_ENTRY dbDatabaseThreadContext : public dbL2List {
00364   public:
00365     dbLockType holdLock;
00366     dbEvent    event;
00367     
00368     int concurrentId;
00369     dbL2List cursors;
00370 
00371     dbCompiler compiler;
00372 
00373     bool       interactive;
00374     bool       catched;
00375     bool       commitDelayed;
00376     bool       removeContext;
00377 
00378     dbLockType pendingLock;
00379     dbDatabaseThreadContext* nextPending;
00380 
00381     jmp_buf  unwind;
00382 
00383     dbDatabaseThreadContext() {
00384         concurrentId = 0;
00385         holdLock = dbNoLock;
00386         pendingLock = dbNoLock;
00387         interactive = false;
00388         catched = false;
00389         commitDelayed = false;
00390         removeContext = false;
00391         event.open();
00392     }
00393     ~dbDatabaseThreadContext() {
00394         event.close();
00395     }
00396 };
00397 
00398 class dbSynthesizedAttribute {
00399   public:
00400     union {
00401         byte*     base;
00402         int       bvalue;
00403         db_int8   ivalue;
00404         rectangle rvalue;
00405         real8     fvalue;
00406         void*     raw;
00407         oid_t     oid;
00408 
00409         struct {
00410             char* base;
00411             int   size;
00412         } array;
00413     };
00414     enum ObjectStorageClass {
00415         osSelf,     // self object field
00416         osStack,    // object allocate on stack
00417         osDynamic,  // object allocated by operstor new
00418         osPage      // reference to page in page pool
00419     };
00420     ObjectStorageClass osClass;
00421     union {
00422         int sp;
00423         struct {
00424             byte*                   addr;
00425             dbSynthesizedAttribute* next;
00426         } loc;
00427     } os;
00428 };
00429 
00430 class dbInheritedAttribute {
00431   public:
00432     byte*              record;
00433     oid_t              oid;
00434     dbTableDescriptor* table;
00435     dbDatabase*        db;
00436     size_t             paramBase;
00437 
00438     enum {
00439 #ifdef _ARM
00440         internalStackSize = 4*1024
00441 #else
00442         internalStackSize = 64*1024
00443 #endif
00444     };
00445 
00446 
00447     dbSynthesizedAttribute* dynChain;
00448     size_t sp;
00449 
00450     struct IteratorContext {
00451         int     index;
00452         int     sp;
00453         dbSynthesizedAttribute* dynChain;
00454         jmp_buf unwind;
00455     } exists_iterator[dbCompiler::maxFreeVars];
00456 
00457     byte   stack[internalStackSize];
00458 
00459     void cleanup() {
00460         dbSynthesizedAttribute* attr;
00461         for (attr = dynChain; attr != NULL; attr = attr->os.loc.next) {
00462             free(*attr);
00463         }
00464     }
00465 
00466     void unwind(int i) {
00467         IteratorContext* ctx = &exists_iterator[i];
00468         sp = ctx->sp;
00469         while (dynChain != ctx->dynChain) {
00470             free(*dynChain);
00471         }
00472         longjmp(ctx->unwind, 1);
00473     }
00474 
00475     void makeDynamic(dbSynthesizedAttribute& attr, void* p) {
00476         attr.osClass = dbSynthesizedAttribute::osDynamic;
00477         attr.os.loc.addr = (byte*)p;
00478         attr.os.loc.next = dynChain;
00479         dynChain = &attr;
00480     }
00481     void allocateString(dbSynthesizedAttribute& attr, int len) {
00482         if (sp + len*sizeof(char_t) > sizeof(stack)) {
00483             attr.array.base = (char*)dbMalloc(len*sizeof(char_t));
00484             attr.array.size = len;
00485             makeDynamic(attr, attr.array.base);
00486         } else {
00487             attr.osClass = dbSynthesizedAttribute::osStack;
00488             attr.array.base = (char*)stack + sp;
00489             attr.array.size = len;
00490             attr.os.sp = sp;
00491             sp += len*sizeof(char_t);
00492         }
00493     }
00494     void allocateString(dbSynthesizedAttribute& attr, char_t* str, size_t len) {
00495         allocateString(attr, len);
00496         memcpy(attr.array.base, str, len*sizeof(char_t));
00497     }
00498     void allocateString(dbSynthesizedAttribute& attr, char_t* str) {
00499         allocateString(attr, str, STRLEN(str) + 1);
00500     }
00501 
00502     void free(dbSynthesizedAttribute& attr) {
00503         switch (attr.osClass) {
00504           case dbSynthesizedAttribute::osStack:
00505             sp = attr.os.sp;
00506             return;
00507           case dbSynthesizedAttribute::osPage:
00508             db->pool.unfix(attr.os.loc.addr);
00509             break;
00510           case dbSynthesizedAttribute::osDynamic:
00511             dbFree(attr.os.loc.addr);
00512             break;
00513           default:
00514             return;
00515         }
00516         dbSynthesizedAttribute** sap;
00517         for (sap = &dynChain; *sap != &attr; sap = &(*sap)->os.loc.next);
00518         *sap = attr.os.loc.next;
00519     }
00520 
00521     void load(dbSynthesizedAttribute& sattr) {
00522         offs_t pos = db->getPos(sattr.oid) & ~dbFlagsMask;
00523         int offs = (int)pos & (dbPageSize-1);
00524         byte* page = db->pool.get(pos - offs);
00525         dbRecord* rec = (dbRecord*)(page + offs);
00526         size_t size = rec->size;
00527         if (offs + size > dbPageSize) {
00528             byte* dst;
00529             int start = DOALIGN(sp, 8);
00530             if (start + size > sizeof(stack)) {
00531                 dst = dbMalloc(size);
00532                 makeDynamic(sattr, dst);
00533             } else {
00534                 sattr.osClass = dbSynthesizedAttribute::osStack;
00535                 sattr.os.sp = sp;
00536                 dst = stack + start;
00537                 sp = start + size;
00538             }
00539             sattr.base = dst;
00540             memcpy(dst, rec, dbPageSize - offs);
00541             db->pool.unfix(page);
00542             size -= dbPageSize - offs;
00543             pos += dbPageSize - offs;
00544             dst += dbPageSize - offs;
00545             while (size > dbPageSize) {
00546                 page = db->pool.get(pos);
00547                 memcpy(dst, page, dbPageSize);
00548                 db->pool.unfix(page);
00549                 dst += dbPageSize;
00550                 size -= dbPageSize;
00551                 pos += dbPageSize;
00552             }
00553             page = db->pool.get(pos);
00554             memcpy(dst, page, size);
00555             db->pool.unfix(page);
00556         } else {
00557             sattr.base = (byte*)rec;
00558             sattr.osClass = dbSynthesizedAttribute::osPage;
00559             sattr.os.loc.addr = page;
00560             sattr.os.loc.next = dynChain;
00561             dynChain = &sattr;
00562         }
00563     }
00564 
00565     dbInheritedAttribute() {
00566         dynChain = NULL;
00567         sp = 0;
00568     }
00569 
00570     ~dbInheritedAttribute() {
00571         cleanup();
00572     }
00573 };
00574 
00575 END_GIGABASE_NAMESPACE
00576 
00577 #endif
00578 
00579 
00580 

Generated on Thu Feb 12 18:46:27 2004 for GigaBASE by doxygen 1.3.5