00001
00002
00003
00004
00005
00006
00007
00008
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
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,
00054 tpList,
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;
00178 dbFieldDescriptor* field;
00179 } ref;
00180
00181 struct {
00182 dbExprNode* arg[3];
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;
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,
00422 osStack,
00423 osDynamic,
00424 osPage,
00425 osFree
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