00001
00002
00003
00004
00005
00006
00007
00008
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
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,
00064 tpList,
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;
00187 dbFieldDescriptor* field;
00188 } ref;
00189
00190 struct {
00191 dbExprNode* arg[3];
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;
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,
00416 osStack,
00417 osDynamic,
00418 osPage
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