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)dbvmLoadRectangleConstant - 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 ~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,
00424 osStack,
00425 osDynamic,
00426 osPage,
00427 osFree
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