1 //-< COMPILE.H >-----------------------------------------------------*--------* 2 // FastDB Version 1.0 (c) 1999 GARRET * ? * 3 // (Main Memory Database Management System) * /\| * 4 // * / \ * 5 // Created: 20-Nov-98 K.A. Knizhnik * / [] \ * 6 // Last update: 17-Jan-99 K.A. Knizhnik * GARRET * 7 //-------------------------------------------------------------------*--------* 8 // Conditional expresion compiler 9 //-------------------------------------------------------------------*--------* 10 11 #ifndef __COMPILER_H__ 12 #define __COMPILER_H__ 13 14 #include <setjmp.h> 15 #ifdef USE_REGEX 16 #include <regex.h> 17 #endif 18 19 BEGIN_FASTDB_NAMESPACE 20 21 #if defined(__osf__) || defined(__FreeBSD__) 22 #define longjmp(b,s) _longjmp(b,s) // do not restore signal context 23 #define setjmp(b) _setjmp(b) 24 #endif 25 26 enum dbvmCodes { 27 #define DBVM(cop, type, n_operands, commutative) cop, 28 #ifdef VXWORKS 29 #include "compiler.dd" 30 #else 31 #include "compiler.d" 32 #endif // VXWORKS 33 dbvmLastCode 34 }; 35 36 #define IS_CONSTANT(c) \ 37 (unsigned(c) - dbvmLoadVarBool <= (unsigned)dbvmLoadRectangleConstant - dbvmLoadVarBool) 38 39 enum nodeType { 40 tpInteger, 41 tpBoolean, 42 tpReal, 43 tpString, 44 tpWString, 45 tpReference, 46 tpRectangle, 47 tpArray, 48 tpRawBinary, 49 tpFreeVar, // index of EXISTS clause 50 tpList, // list of expressions 51 tpVoid 52 }; 53 54 enum tokens { 55 tkn_ident, 56 tkn_lpar, 57 tkn_rpar, 58 tkn_lbr, 59 tkn_rbr, 60 tkn_dot, 61 tkn_comma, 62 tkn_power, 63 tkn_iconst, 64 tkn_sconst, 65 tkn_fconst, 66 tkn_add, 67 tkn_sub, 68 tkn_mul, 69 tkn_div, 70 tkn_and, 71 tkn_or, 72 tkn_not, 73 tkn_null, 74 tkn_neg, 75 tkn_eq, 76 tkn_ne, 77 tkn_gt, 78 tkn_ge, 79 tkn_lt, 80 tkn_le, 81 tkn_between, 82 tkn_escape, 83 tkn_exists, 84 tkn_like, 85 tkn_limit, 86 tkn_in, 87 tkn_length, 88 tkn_lower, 89 tkn_upper, 90 tkn_abs, 91 tkn_area, 92 tkn_is, 93 tkn_integer, 94 tkn_real, 95 tkn_string, 96 tkn_wstring, 97 tkn_first, 98 tkn_last, 99 tkn_current, 100 tkn_var, 101 tkn_col, 102 tkn_true, 103 tkn_false, 104 tkn_where, 105 tkn_follow, 106 tkn_start, 107 tkn_from, 108 tkn_order, 109 tkn_overlaps, 110 tkn_by, 111 tkn_asc, 112 tkn_desc, 113 tkn_eof, 114 tkn_insert, 115 tkn_into, 116 tkn_select, 117 tkn_table, 118 tkn_error, 119 tkn_all, 120 tkn_match, 121 tkn_last_token 122 }; 123 124 struct dbStrLiteral { 125 char* str; 126 int len; 127 }; 128 129 struct dbWStrLiteral { 130 wchar_t* str; 131 int len; 132 }; 133 134 135 class dbUserFunction; 136 class dbExprNodeSegment; 137 138 class FASTDB_DLL_ENTRY dbExprNodeAllocator { 139 private: 140 friend class dbExprNodeSegment; 141 dbExprNode* freeNodeList; 142 dbExprNodeSegment* segmentList; 143 dbMutex mutex; 144 145 public: getMutex()146 dbMutex& getMutex() { 147 return mutex; 148 } 149 dbExprNode* allocate(); 150 void deallocate(dbExprNode* node); 151 void reset(); 152 153 ~dbExprNodeAllocator(); 154 static dbExprNodeAllocator instance; 155 }; 156 157 class FASTDB_DLL_ENTRY dbExprNode { 158 friend class dbExprNodeSegment; 159 public: 160 nat1 cop; 161 nat1 type; 162 nat2 offs; 163 164 static const nat1 nodeTypes[]; 165 static const nat1 nodeOperands[]; 166 static const nat1 commutativeOperator[]; 167 168 struct ref_operands { 169 dbExprNode* base; // the same as operand[0] 170 dbFieldDescriptor* field; 171 }; 172 173 struct func_operands { 174 dbExprNode* arg[3]; 175 void* fptr; 176 }; 177 178 #ifdef USE_REGEX 179 struct regex_operands { 180 dbExprNode* opd; 181 regex_t re; 182 }; 183 #endif 184 185 union { 186 dbExprNode* operand[3]; 187 dbExprNode* next; 188 oid_t oid; 189 db_int8 ivalue; 190 real8 fvalue; 191 rectangle rvalue; 192 dbStrLiteral svalue; 193 dbWStrLiteral wsvalue; 194 void const* var; 195 ref_operands ref; 196 func_operands func; 197 #ifdef USE_REGEX 198 regex_operands regex; 199 #endif 200 }; 201 202 dbExprNode(dbExprNode* node); 203 204 dbExprNode(int cop, dbExprNode* left = NULL, dbExprNode* right = NULL, 205 dbExprNode* right2 = NULL) 206 { 207 this->cop = cop; 208 type = nodeTypes[cop]; 209 operand[0] = left; 210 operand[1] = right; 211 operand[2] = right2; 212 } dbExprNode(int cop,dbExprNode * expr1,dbExprNode * expr2,int offs)213 dbExprNode(int cop, dbExprNode* expr1, dbExprNode* expr2, int offs) { 214 this->cop = cop; 215 this->offs = (nat2)offs; 216 type = nodeTypes[cop]; 217 operand[0] = expr1; 218 operand[1] = expr2; 219 } dbExprNode(int cop,dbExprNode * expr,int offs)220 dbExprNode(int cop, dbExprNode* expr, int offs) { 221 this->cop = cop; 222 this->offs = (nat2)offs; 223 type = nodeTypes[cop]; 224 operand[0] = expr; 225 } 226 dbExprNode(int cop, dbFieldDescriptor* field, dbExprNode* base = NULL) 227 { 228 this->cop = cop; 229 this->offs = (nat2)field->dbsOffs; 230 type = nodeTypes[cop]; 231 ref.field = field; 232 ref.base = base; 233 } dbExprNode(int cop,db_int8 ivalue)234 dbExprNode(int cop, db_int8 ivalue) { 235 this->cop = cop; 236 this->ivalue = ivalue; 237 type = tpInteger; 238 } dbExprNode(int cop,real8 fvalue)239 dbExprNode(int cop, real8 fvalue) { 240 this->cop = cop; 241 this->fvalue = fvalue; 242 type = tpReal; 243 } dbExprNode(int cop,rectangle rvalue)244 dbExprNode(int cop, rectangle rvalue) { 245 this->cop = cop; 246 this->rvalue = rvalue; 247 type = tpRectangle; 248 } dbExprNode(int cop,dbStrLiteral & svalue)249 dbExprNode(int cop, dbStrLiteral& svalue) { 250 this->cop = cop; 251 this->svalue = svalue; 252 type = tpString; 253 } dbExprNode(int cop,dbWStrLiteral & wsvalue)254 dbExprNode(int cop, dbWStrLiteral& wsvalue) { 255 this->cop = cop; 256 this->wsvalue = wsvalue; 257 type = tpWString; 258 } dbExprNode(int cop,void const * var)259 dbExprNode(int cop, void const* var) { 260 this->cop = cop; 261 this->var = var; 262 type = nodeTypes[cop]; 263 } 264 dbExprNode(int cop, void* fptr, dbExprNode* expr1, dbExprNode* expr2 = NULL, dbExprNode* expr3 = NULL) { 265 this->cop = cop; 266 func.arg[0] = expr1; 267 func.arg[1] = expr2; 268 func.arg[2] = expr3; 269 func.fptr = fptr; 270 type = nodeTypes[cop]; 271 } 272 ~dbExprNode(); 273 new(size_t size EXTRA_DEBUG_NEW_PARAMS)274 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS) { 275 return dbExprNodeAllocator::instance.allocate(); 276 } 277 delete(void * ptr EXTRA_DEBUG_NEW_PARAMS)278 void operator delete(void* ptr EXTRA_DEBUG_NEW_PARAMS) { 279 dbExprNodeAllocator::instance.deallocate((dbExprNode*)ptr); 280 } 281 }; 282 283 284 class dbExprNodeSegment { 285 public: 286 enum { allocationQuantum = 1024}; 287 char buf[sizeof(dbExprNode)*allocationQuantum]; 288 dbExprNodeSegment* next; 289 }; 290 291 292 class dbBinding { 293 public: 294 dbBinding* next; 295 char const* name; 296 bool used; 297 int index; 298 }; 299 300 class dbOrderByNode { 301 public: 302 dbOrderByNode* next; 303 dbFieldDescriptor* field; 304 dbTableDescriptor* table; 305 dbExprNode* expr; 306 bool ascent; // true for ascent order, false for descent 307 getField()308 dbFieldDescriptor* getField() { 309 return (field != NULL) ? field 310 : ((unsigned)expr->cop - dbvmLoadBool <= dbvmLoadRawBinary - dbvmLoadBool) 311 ? expr->ref.field : NULL; 312 } 313 ~dbOrderByNode()314 ~dbOrderByNode() { 315 delete expr; 316 } 317 }; 318 319 class dbFollowByNode { 320 public: 321 dbFollowByNode* next; 322 dbFieldDescriptor* field; 323 }; 324 325 class FASTDB_DLL_ENTRY dbCompiler { 326 friend class dbQuery; 327 friend class dbQueryElement; 328 public: 329 enum { 330 maxSymbolLen = 4096, 331 maxFreeVars = 4 332 }; 333 334 dbTableDescriptor* table; 335 dbQueryElement* queryElement; 336 int currPos; 337 int firstPos; 338 int offsetWithinStatement; 339 int bvalue; 340 db_int8 ivalue; 341 real8 fvalue; 342 dbStrLiteral svalue; 343 dbWStrLiteral wsvalue; 344 bool hasToken; 345 int lex; 346 char* name; 347 dbBinding* bindings; 348 int nFreeVars; 349 int varType; 350 void const* varPtr; 351 dbTableDescriptor* varRefTable; 352 353 jmp_buf abortCompilation; 354 static bool initialized; 355 356 void compare(dbExprNode* expr, dbExprNode* list); 357 358 int scan(); ungetToken(int tkn)359 void ungetToken(int tkn) { 360 lex = tkn; 361 hasToken = true; 362 } 363 void error(const char* msg, int pos = -1); 364 dbExprNode* conjunction(); 365 dbExprNode* disjunction(); 366 dbExprNode* comparison(); 367 dbExprNode* addition(); 368 dbExprNode* multiplication(); 369 dbExprNode* power(); 370 dbExprNode* term(); 371 dbExprNode* buildList(); 372 dbExprNode* userDefinedOperator(); 373 dbExprNode* field(dbExprNode* expr, dbTableDescriptor* refTable, 374 dbFieldDescriptor* fd); 375 376 bool compile(dbTableDescriptor* table, dbQuery& query); 377 dbExprNode* compileExpression(dbTableDescriptor* table, char const* expr, int startPos); 378 void compileOrderByPart(dbQuery& query); 379 void compileLimitPart(dbQuery& query); 380 void compileStartFollowPart(dbQuery& query); 381 382 void deleteNode(dbExprNode* node); 383 dbExprNode* rectangleConstant(dbExprNode* head); 384 385 dbCompiler(); 386 }; 387 388 class dbDatabaseThreadContext : public dbL2List { 389 public: 390 int readAccess; 391 int writeAccess; 392 int concurrentId; 393 int mutatorCSLocked; 394 int isMutator; 395 396 dbL2List cursors; 397 398 dbCompiler compiler; 399 400 dbProcessId currPid; 401 402 bool interactive; 403 bool catched; 404 bool commitDelayed; 405 bool removeContext; 406 jmp_buf unwind; 407 dbDatabaseThreadContext()408 dbDatabaseThreadContext() { 409 concurrentId = 0; 410 readAccess = false; 411 writeAccess = false; 412 mutatorCSLocked = false; 413 isMutator = false; 414 interactive = false; 415 catched = false; 416 commitDelayed = false; 417 removeContext = false; 418 currPid = dbProcessId::getCurrent(); 419 } 420 }; 421 422 union dbSynthesizedAttribute { 423 byte* base; 424 int bvalue; 425 db_int8 ivalue; 426 real8 fvalue; 427 rectangle rvalue; 428 void* raw; 429 oid_t oid; 430 431 struct { 432 char* base; 433 int size; 434 dbUDTComparator comparator; 435 } array; 436 }; 437 438 struct dbStringValue; 439 440 struct FASTDB_DLL_ENTRY dbInheritedAttribute { 441 byte* record; 442 oid_t oid; 443 dbTable* table; 444 dbDatabase* db; 445 dbStringValue* tempStrings; 446 size_t paramBase; 447 enum { 448 internalStrBufSize = 8*1024 449 }; 450 size_t strBufPos; 451 char strBuf[internalStrBufSize]; 452 453 struct { 454 int index; 455 jmp_buf unwind; 456 } exists_iterator[dbCompiler::maxFreeVars]; 457 458 void removeTemporaries(); 459 dbInheritedAttributedbInheritedAttribute460 dbInheritedAttribute() { 461 tempStrings = NULL; 462 strBufPos = 0; 463 } 464 ~dbInheritedAttributedbInheritedAttribute465 ~dbInheritedAttribute() { 466 removeTemporaries(); 467 } 468 }; 469 470 struct dbStringValue { 471 dbStringValue* next; 472 char str[1]; 473 createdbStringValue474 static char* create(size_t size, dbInheritedAttribute& attr) { 475 if (attr.strBufPos + size > sizeof(attr.strBuf)) { 476 dbStringValue* sv = 477 (dbStringValue*)new char[offsetof(dbStringValue, str) + size]; 478 sv->next = attr.tempStrings; 479 attr.tempStrings = sv; 480 return sv->str; 481 } else { 482 char* p = attr.strBuf + attr.strBufPos; 483 attr.strBufPos += size; 484 return p; 485 } 486 } 487 createdbStringValue488 static char* create(char const* s, dbInheritedAttribute& attr) { 489 size_t len = strlen(s) + 1; 490 char* buf; 491 if (attr.strBufPos + len > sizeof(attr.strBuf)) { 492 dbStringValue* sv = 493 (dbStringValue*)new char[offsetof(dbStringValue,str)+len]; 494 sv->next = attr.tempStrings; 495 attr.tempStrings = sv; 496 buf = sv->str; 497 } else { 498 buf = attr.strBuf + attr.strBufPos; 499 attr.strBufPos += len; 500 } 501 return strcpy(buf, s); 502 } 503 }; 504 505 inline char* findWildcard(char* pattern, char* escape = NULL) 506 { 507 if (escape == NULL) { 508 while (*pattern != dbMatchAnyOneChar && 509 *pattern != dbMatchAnySubstring) 510 { 511 if (*pattern++ == '\0') { 512 return NULL; 513 } 514 } 515 } else { 516 char esc = *escape; 517 while (*pattern != dbMatchAnyOneChar && 518 *pattern != dbMatchAnySubstring && 519 *pattern != esc) 520 { 521 if (*pattern++ == '\0') { 522 return NULL; 523 } 524 } 525 } 526 return pattern; 527 } 528 529 inline wchar_t* findWildcard(wchar_t* pattern, wchar_t* escape = NULL) 530 { 531 if (escape == NULL) { 532 while (*pattern != dbMatchAnyOneChar && 533 *pattern != dbMatchAnySubstring) 534 { 535 if (*pattern++ == '\0') { 536 return NULL; 537 } 538 } 539 } else { 540 wchar_t esc = *escape; 541 while (*pattern != dbMatchAnyOneChar && 542 *pattern != dbMatchAnySubstring && 543 *pattern != esc) 544 { 545 if (*pattern++ == '\0') { 546 return NULL; 547 } 548 } 549 } 550 return pattern; 551 } 552 553 END_FASTDB_NAMESPACE 554 555 #endif 556