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 #include <regex.h>
00017 #endif
00018
00019 BEGIN_FASTDB_NAMESPACE
00020
00021 #if defined(__osf__) || defined(__FreeBSD__)
00022 #define longjmp(b,s) _longjmp(b,s) // do not restore signal context
00023 #define setjmp(b) _setjmp(b)
00024 #endif
00025
00026 enum dbvmCodes {
00027 #define DBVM(cop, type, n_operands, commutative) cop,
00028 #include "compiler.d"
00029 dbvmLastCode
00030 };
00031
00032 #define IS_CONSTANT(c) \
00033 (unsigned(c) - dbvmLoadVarBool <= (unsigned)dbvmLoadRectangleConstant - dbvmLoadVarBool)
00034
00035 enum nodeType {
00036 tpInteger,
00037 tpBoolean,
00038 tpReal,
00039 tpString,
00040 tpReference,
00041 tpRectangle,
00042 tpArray,
00043 tpRawBinary,
00044 tpFreeVar,
00045 tpList,
00046 tpVoid
00047 };
00048
00049 enum tokens {
00050 tkn_ident,
00051 tkn_lpar,
00052 tkn_rpar,
00053 tkn_lbr,
00054 tkn_rbr,
00055 tkn_dot,
00056 tkn_comma,
00057 tkn_power,
00058 tkn_iconst,
00059 tkn_sconst,
00060 tkn_fconst,
00061 tkn_add,
00062 tkn_sub,
00063 tkn_mul,
00064 tkn_div,
00065 tkn_and,
00066 tkn_or,
00067 tkn_not,
00068 tkn_null,
00069 tkn_neg,
00070 tkn_eq,
00071 tkn_ne,
00072 tkn_gt,
00073 tkn_ge,
00074 tkn_lt,
00075 tkn_le,
00076 tkn_between,
00077 tkn_escape,
00078 tkn_exists,
00079 tkn_like,
00080 tkn_limit,
00081 tkn_in,
00082 tkn_length,
00083 tkn_lower,
00084 tkn_upper,
00085 tkn_abs,
00086 tkn_area,
00087 tkn_is,
00088 tkn_integer,
00089 tkn_real,
00090 tkn_string,
00091 tkn_first,
00092 tkn_last,
00093 tkn_current,
00094 tkn_var,
00095 tkn_col,
00096 tkn_true,
00097 tkn_false,
00098 tkn_where,
00099 tkn_follow,
00100 tkn_start,
00101 tkn_from,
00102 tkn_order,
00103 tkn_overlaps,
00104 tkn_by,
00105 tkn_asc,
00106 tkn_desc,
00107 tkn_eof,
00108 tkn_insert,
00109 tkn_into,
00110 tkn_select,
00111 tkn_table,
00112 tkn_error,
00113 tkn_all,
00114 tkn_match,
00115 tkn_last_token
00116 };
00117
00118 struct dbStrLiteral {
00119 char* str;
00120 int len;
00121 };
00122
00123
00124 class dbUserFunction;
00125 class dbExprNodeSegment;
00126
00127 class FASTDB_DLL_ENTRY dbExprNodeAllocator {
00128 private:
00129 friend class dbExprNodeSegment;
00130 dbExprNode* freeNodeList;
00131 dbExprNodeSegment* segmentList;
00132 dbMutex mutex;
00133
00134 public:
00135 dbMutex& getMutex() {
00136 return mutex;
00137 }
00138 dbExprNode* allocate();
00139 void deallocate(dbExprNode* node);
00140 void reset();
00141
00142 ~dbExprNodeAllocator();
00143 static dbExprNodeAllocator instance;
00144 };
00145
00146 class FASTDB_DLL_ENTRY dbExprNode {
00147 friend class dbExprNodeSegment;
00148 public:
00149 nat1 cop;
00150 nat1 type;
00151 nat2 offs;
00152
00153 static const nat1 nodeTypes[];
00154 static const nat1 nodeOperands[];
00155 static const nat1 commutativeOperator[];
00156
00157 struct ref_operands {
00158 dbExprNode* base;
00159 dbFieldDescriptor* field;
00160 };
00161
00162 struct func_operands {
00163 dbExprNode* arg[3];
00164 void* fptr;
00165 };
00166
00167 #ifdef USE_REGEX
00168 struct regex_operands {
00169 dbExprNode* opd;
00170 regex_t re;
00171 };
00172 #endif
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 ref_operands ref;
00184 func_operands func;
00185 #ifdef USE_REGEX
00186 regex_operands regex;
00187 #endif
00188 };
00189
00190 dbExprNode(dbExprNode* node);
00191
00192 dbExprNode(int cop, dbExprNode* left = NULL, dbExprNode* right = NULL,
00193 dbExprNode* right2 = NULL)
00194 {
00195 this->cop = cop;
00196 type = nodeTypes[cop];
00197 operand[0] = left;
00198 operand[1] = right;
00199 operand[2] = right2;
00200 }
00201 dbExprNode(int cop, dbExprNode* expr1, dbExprNode* expr2, int offs) {
00202 this->cop = cop;
00203 this->offs = (nat2)offs;
00204 type = nodeTypes[cop];
00205 operand[0] = expr1;
00206 operand[1] = expr2;
00207 }
00208 dbExprNode(int cop, dbExprNode* expr, int offs) {
00209 this->cop = cop;
00210 this->offs = (nat2)offs;
00211 type = nodeTypes[cop];
00212 operand[0] = expr;
00213 }
00214 dbExprNode(int cop, dbFieldDescriptor* field, dbExprNode* base = NULL)
00215 {
00216 this->cop = cop;
00217 this->offs = (nat2)field->dbsOffs;
00218 type = nodeTypes[cop];
00219 ref.field = field;
00220 ref.base = base;
00221 }
00222 dbExprNode(int cop, db_int8 ivalue) {
00223 this->cop = cop;
00224 this->ivalue = ivalue;
00225 type = tpInteger;
00226 }
00227 dbExprNode(int cop, real8 fvalue) {
00228 this->cop = cop;
00229 this->fvalue = fvalue;
00230 type = tpReal;
00231 }
00232 dbExprNode(int cop, rectangle rvalue) {
00233 this->cop = cop;
00234 this->rvalue = rvalue;
00235 type = tpRectangle;
00236 }
00237 dbExprNode(int cop, dbStrLiteral& svalue) {
00238 this->cop = cop;
00239 this->svalue = svalue;
00240 type = tpString;
00241 }
00242 dbExprNode(int cop, void const* var) {
00243 this->cop = cop;
00244 this->var = var;
00245 type = nodeTypes[cop];
00246 }
00247 dbExprNode(int cop, void* fptr, dbExprNode* expr1, dbExprNode* expr2 = NULL, dbExprNode* expr3 = NULL) {
00248 this->cop = cop;
00249 func.arg[0] = expr1;
00250 func.arg[1] = expr2;
00251 func.arg[2] = expr3;
00252 func.fptr = fptr;
00253 type = nodeTypes[cop];
00254 }
00255 ~dbExprNode();
00256
00257 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS) {
00258 return dbExprNodeAllocator::instance.allocate();
00259 }
00260
00261 void operator delete(void* ptr EXTRA_DEBUG_NEW_PARAMS) {
00262 dbExprNodeAllocator::instance.deallocate((dbExprNode*)ptr);
00263 }
00264 };
00265
00266
00267 class dbExprNodeSegment {
00268 public:
00269 enum { allocationQuantum = 1024};
00270 char buf[sizeof(dbExprNode)*allocationQuantum];
00271 dbExprNodeSegment* next;
00272 };
00273
00274
00275 class dbBinding {
00276 public:
00277 dbBinding* next;
00278 char const* name;
00279 bool used;
00280 int index;
00281 };
00282
00283 class dbOrderByNode {
00284 public:
00285 dbOrderByNode* next;
00286 dbFieldDescriptor* field;
00287 dbTableDescriptor* table;
00288 dbExprNode* expr;
00289 bool ascent;
00290
00291 ~dbOrderByNode() {
00292 delete expr;
00293 }
00294 };
00295
00296 class dbFollowByNode {
00297 public:
00298 dbFollowByNode* next;
00299 dbFieldDescriptor* field;
00300 };
00301
00302 class FASTDB_DLL_ENTRY dbCompiler {
00303 friend class dbQuery;
00304 friend class dbQueryElement;
00305 public:
00306 enum {
00307 maxStrLen = 4096,
00308 maxFreeVars = 4
00309 };
00310
00311 dbTableDescriptor* table;
00312 dbQueryElement* queryElement;
00313 int currPos;
00314 int firstPos;
00315 int offsetWithinStatement;
00316 int bvalue;
00317 db_int8 ivalue;
00318 real8 fvalue;
00319 dbStrLiteral svalue;
00320 bool hasToken;
00321 int lex;
00322 char* name;
00323 dbBinding* bindings;
00324 int nFreeVars;
00325 int varType;
00326 void const* varPtr;
00327 dbTableDescriptor* varRefTable;
00328
00329 jmp_buf abortCompilation;
00330 static bool initialized;
00331
00332 void compare(dbExprNode* expr, dbExprNode* list);
00333
00334 int scan();
00335 void ungetToken(int tkn) {
00336 lex = tkn;
00337 hasToken = true;
00338 }
00339 void error(const char* msg, int pos = -1);
00340 dbExprNode* conjunction();
00341 dbExprNode* disjunction();
00342 dbExprNode* comparison();
00343 dbExprNode* addition();
00344 dbExprNode* multiplication();
00345 dbExprNode* power();
00346 dbExprNode* term();
00347 dbExprNode* buildList();
00348 dbExprNode* userDefinedOperator();
00349 dbExprNode* field(dbExprNode* expr, dbTableDescriptor* refTable,
00350 dbFieldDescriptor* fd);
00351
00352 bool compile(dbTableDescriptor* table, dbQuery& query);
00353 dbExprNode* compileExpression(dbTableDescriptor* table, char const* expr, int startPos);
00354 void compileOrderByPart(dbQuery& query);
00355 void compileLimitPart(dbQuery& query);
00356 void compileStartFollowPart(dbQuery& query);
00357
00358 void deleteNode(dbExprNode* node);
00359 dbExprNode* rectangleConstant(dbExprNode* head);
00360
00361 dbCompiler();
00362 };
00363
00364 class dbDatabaseThreadContext : public dbL2List {
00365 public:
00366 int readAccess;
00367 int writeAccess;
00368 int concurrentId;
00369 int mutatorCSLocked;
00370 int isMutator;
00371
00372 dbL2List cursors;
00373
00374 dbCompiler compiler;
00375
00376 dbProcessId currPid;
00377
00378 bool interactive;
00379 bool catched;
00380 bool commitDelayed;
00381 bool removeContext;
00382 jmp_buf unwind;
00383
00384 dbDatabaseThreadContext() {
00385 concurrentId = 0;
00386 readAccess = false;
00387 writeAccess = false;
00388 mutatorCSLocked = false;
00389 isMutator = false;
00390 interactive = false;
00391 catched = false;
00392 commitDelayed = false;
00393 removeContext = false;
00394 currPid = dbProcessId::getCurrent();
00395 }
00396 };
00397
00398 union dbSynthesizedAttribute {
00399 byte* base;
00400 int bvalue;
00401 db_int8 ivalue;
00402 real8 fvalue;
00403 rectangle rvalue;
00404 void* raw;
00405 oid_t oid;
00406
00407 struct {
00408 char* base;
00409 int size;
00410 } array;
00411 };
00412
00413 struct dbStringValue;
00414
00415 struct FASTDB_DLL_ENTRY dbInheritedAttribute {
00416 byte* record;
00417 oid_t oid;
00418 dbTable* table;
00419 dbDatabase* db;
00420 dbStringValue* tempStrings;
00421 size_t paramBase;
00422 enum {
00423 internalStrBufSize = 8*1024
00424 };
00425 size_t strBufPos;
00426 char strBuf[internalStrBufSize];
00427
00428 struct {
00429 int index;
00430 jmp_buf unwind;
00431 } exists_iterator[dbCompiler::maxFreeVars];
00432
00433 void removeTemporaries();
00434
00435 dbInheritedAttribute() {
00436 tempStrings = NULL;
00437 strBufPos = 0;
00438 }
00439
00440 ~dbInheritedAttribute() {
00441 removeTemporaries();
00442 }
00443 };
00444
00445 struct dbStringValue {
00446 dbStringValue* next;
00447 char str[1];
00448
00449 static char* create(size_t size, dbInheritedAttribute& attr) {
00450 if (attr.strBufPos + size > sizeof(attr.strBuf)) {
00451 dbStringValue* sv =
00452 (dbStringValue*)new char[offsetof(dbStringValue, str) + size];
00453 sv->next = attr.tempStrings;
00454 attr.tempStrings = sv;
00455 return sv->str;
00456 } else {
00457 char* p = attr.strBuf + attr.strBufPos;
00458 attr.strBufPos += size;
00459 return p;
00460 }
00461 }
00462
00463 static char* create(char const* s, dbInheritedAttribute& attr) {
00464 size_t len = strlen(s) + 1;
00465 char* buf;
00466 if (attr.strBufPos + len > sizeof(attr.strBuf)) {
00467 dbStringValue* sv =
00468 (dbStringValue*)new char[offsetof(dbStringValue,str)+len];
00469 sv->next = attr.tempStrings;
00470 attr.tempStrings = sv;
00471 buf = sv->str;
00472 } else {
00473 buf = attr.strBuf + attr.strBufPos;
00474 attr.strBufPos += len;
00475 }
00476 return strcpy(buf, s);
00477 }
00478 };
00479
00480 inline char* findWildcard(char* pattern, char* escape = NULL)
00481 {
00482 if (escape == NULL) {
00483 while (*pattern != dbMatchAnyOneChar &&
00484 *pattern != dbMatchAnySubstring)
00485 {
00486 if (*pattern++ == '\0') {
00487 return NULL;
00488 }
00489 }
00490 } else {
00491 char esc = *escape;
00492 while (*pattern != dbMatchAnyOneChar &&
00493 *pattern != dbMatchAnySubstring &&
00494 *pattern != esc)
00495 {
00496 if (*pattern++ == '\0') {
00497 return NULL;
00498 }
00499 }
00500 }
00501 return pattern;
00502 }
00503
00504 END_FASTDB_NAMESPACE
00505
00506 #endif