1 //-< QUERY.CPP >-----------------------------------------------------*--------*
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: 10-Dec-98 K.A. Knizhnik * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Constructing and hashing database query statements
9 //-------------------------------------------------------------------*--------*
10
11 #define INSIDE_FASTDB
12
13 #include "fastdb.h"
14 #include "symtab.h"
15 #include "compiler.h"
16
17 BEGIN_FASTDB_NAMESPACE
18
19 dbQueryElementAllocator dbQueryElementAllocator::instance;
20
21
dump(char * buf)22 char* dbQueryElement::dump(char* buf)
23 {
24 switch (type) {
25 case qExpression:
26 buf += sprintf(buf, " %s ", (const char*)ptr);
27 break;
28 case qVarBool:
29 buf += sprintf(buf, "{boolean}");
30 break;
31 case qVarInt1:
32 buf += sprintf(buf, "{int1}");
33 break;
34 case qVarInt2:
35 buf += sprintf(buf, "{int2}");
36 break;
37 case qVarInt4:
38 buf += sprintf(buf, "{int4}");
39 break;
40 case qVarInt8:
41 buf += sprintf(buf, "{int8}");
42 break;
43 case qVarReal4:
44 buf += sprintf(buf, "{real4}");
45 break;
46 case qVarReal8:
47 buf += sprintf(buf, "{real8}");
48 break;
49 case qVarString:
50 buf += sprintf(buf, "{char*}");
51 break;
52 case qVarStringPtr:
53 buf += sprintf(buf, "{char**}");
54 break;
55 case qVarWString:
56 buf += sprintf(buf, "{wchar_t*}");
57 break;
58 case qVarWStringPtr:
59 buf += sprintf(buf, "{wchar_t**}");
60 break;
61 case qVarReference:
62 if (ref != NULL) {
63 buf += sprintf(buf, "{dbReference<%s>}", ref->getName());
64 } else {
65 buf += sprintf(buf, "{dbAnyReference}");
66 }
67 break;
68 case qVarArrayOfInt4:
69 buf += sprintf(buf, "{dbArray<int4>}");
70 break;
71 case qVarArrayOfInt4Ptr:
72 buf += sprintf(buf, "{dbArray<int4>*}");
73 break;
74 case qVarArrayOfInt8:
75 buf += sprintf(buf, "{dbArray<int8>}");
76 break;
77 case qVarArrayOfInt8Ptr:
78 buf += sprintf(buf, "{dbArray<int8>*}");
79 break;
80 case qVarArrayOfRef:
81 if (ref != NULL) {
82 buf += sprintf(buf, "{dbArray< dbReference<%s> >}", ref->getName());
83 } else {
84 buf += sprintf(buf, "{dbArray<dbAnyReference>}");
85 }
86 break;
87 case qVarArrayOfRefPtr:
88 if (ref != NULL) {
89 buf += sprintf(buf, "{dbArray< dbReference<%s> >*}", ref->getName());
90 } else {
91 buf += sprintf(buf, "{dbArray<dbAnyReference>*}");
92 }
93 break;
94 case qVarRawData:
95 case qVarRawDataPtr:
96 buf += sprintf(buf, "{raw binary}");
97 break;
98 case qVarRectangle:
99 case qVarRectanglePtr:
100 buf += sprintf(buf, "{rectangle}");
101 break;
102 #ifdef USE_STD_STRING
103 case qVarStdString:
104 buf += sprintf(buf, "{string}");
105 break;
106 case qVarStdWString:
107 buf += sprintf(buf, "{wstring}");
108 break;
109 #endif
110 default:
111 break;
112 }
113 return buf;
114 }
115
116
dumpValues(char * buf)117 char* dbQueryElement::dumpValues(char* buf)
118 {
119 switch (type) {
120 case qExpression:
121 buf += sprintf(buf, " %s ", (char*)ptr);
122 break;
123 case qVarBool:
124 buf += sprintf(buf, "%s", *(bool*)ptr ? "true" : "false");
125 break;
126 case qVarInt1:
127 buf += sprintf(buf, "%d", *(int1*)ptr);
128 break;
129 case qVarInt2:
130 buf += sprintf(buf, "%d", *(int2*)ptr);
131 break;
132 case qVarInt4:
133 buf += sprintf(buf, "%d", *(int4*)ptr);
134 break;
135 case qVarInt8:
136 buf += sprintf(buf, INT8_FORMAT, *(db_int8*)ptr);
137 break;
138 case qVarReal4:
139 buf += sprintf(buf, "%f", *(real4*)ptr);
140 break;
141 case qVarReal8:
142 buf += sprintf(buf, "%f", *(real8*)ptr);
143 break;
144 case qVarString:
145 buf += sprintf(buf, "'%s'", (char*)ptr);
146 break;
147 case qVarStringPtr:
148 buf += sprintf(buf, "'%s'", *(char**)ptr);
149 break;
150 case qVarWString:
151 buf += sprintf(buf, "'%ls'", (wchar_t*)ptr);
152 break;
153 case qVarWStringPtr:
154 buf += sprintf(buf, "'%ls'", *(wchar_t**)ptr);
155 break;
156 case qVarReference:
157 if (ref != NULL) {
158 buf += sprintf(buf, "@%s:%lx", ref->getName(), (unsigned long)*(oid_t*)ptr);
159 } else {
160 buf += sprintf(buf, "@%lx", (unsigned long)*(oid_t*)ptr);
161 }
162 break;
163 case qVarArrayOfInt4:
164 buf += sprintf(buf, "{dbArray<int4>}");
165 break;
166 case qVarArrayOfInt4Ptr:
167 buf += sprintf(buf, "{dbArray<int4>*}");
168 break;
169 case qVarArrayOfInt8:
170 buf += sprintf(buf, "{dbArray<int8>}");
171 break;
172 case qVarArrayOfInt8Ptr:
173 buf += sprintf(buf, "{dbArray<int8>*}");
174 break;
175 case qVarArrayOfRef:
176 if (ref != NULL) {
177 buf += sprintf(buf, "{dbArray< dbReference<%s> >}", ref->getName());
178 } else {
179 buf += sprintf(buf, "{dbArray<dbAnyReference>}");
180 }
181 break;
182 case qVarArrayOfRefPtr:
183 if (ref != NULL) {
184 buf += sprintf(buf, "{dbArray< dbReference<%s> >*}", ref->getName());
185 } else {
186 buf += sprintf(buf, "{dbArray<dbAnyReference>*}");
187 }
188 break;
189 case qVarRawData:
190 case qVarRawDataPtr:
191 buf += sprintf(buf, "{raw binary}");
192 break;
193 case qVarRectangle:
194 {
195 int i, sep = '(';
196 rectangle& r = *(rectangle*)ptr;
197 for (i = 0; i < rectangle::dim*2; i++) {
198 buf += sprintf(buf, "%c%f", sep, (double)r.boundary[i]);
199 sep = ',';
200 }
201 *buf++ = ')';
202 *buf = '\0';
203 }
204 break;
205 case qVarRectanglePtr:
206 {
207 int i, sep = '(';
208 rectangle& r = **(rectangle**)ptr;
209 for (i = 0; i < rectangle::dim*2; i++) {
210 buf += sprintf(buf, "%c%f", sep, (double)r.boundary[i]);
211 sep = ',';
212 }
213 *buf++ = ')';
214 *buf = '\0';
215 }
216 break;
217 #ifdef USE_STD_STRING
218 case qVarStdString:
219 buf += sprintf(buf, "'%s'", ((std::string*)ptr)->c_str());
220 break;
221 case qVarStdWString:
222 buf += sprintf(buf, "'%ls'", ((std::wstring*)ptr)->c_str());
223 break;
224 #endif
225 default:
226 break;
227 }
228 return buf;
229 }
230
dbQueryElementAllocator()231 dbQueryElementAllocator::dbQueryElementAllocator()
232 : freeChain(NULL)
233 {
234 }
235
allocate(size_t size)236 void* dbQueryElementAllocator::allocate(size_t size)
237 {
238 dbCriticalSection cs(mutex);
239 dbQueryElement* elem = freeChain;
240 if (elem != NULL) {
241 freeChain = elem->next;
242 return elem;
243 } else {
244 return dbMalloc(size);
245 }
246 }
247
operator new(size_t size EXTRA_DEBUG_NEW_PARAMS)248 void* dbQueryElement::operator new(size_t size EXTRA_DEBUG_NEW_PARAMS) {
249 return dbQueryElementAllocator::instance.allocate(size);
250 }
251
252
operator delete(void * p EXTRA_DEBUG_NEW_PARAMS)253 void dbQueryElement::operator delete(void* p EXTRA_DEBUG_NEW_PARAMS)
254 {
255 dbFree(p);
256 }
257
258
~dbQueryElementAllocator()259 dbQueryElementAllocator::~dbQueryElementAllocator()
260 {
261 reset();
262 }
263
reset()264 void dbQueryElementAllocator::reset()
265 {
266 dbCriticalSection cs(mutex);
267 dbQueryElement *elem, *next;
268 for (elem = freeChain; elem != NULL; elem = next) {
269 next = elem->next;
270 delete elem;
271 }
272 freeChain = NULL;
273 }
274
operator =(dbComponent const & comp)275 dbQueryExpression& dbQueryExpression::operator = (dbComponent const& comp)
276 {
277 first = NULL;
278 last = &first;
279 add(dbQueryElement::qExpression, comp.structure);
280 if (comp.field != NULL) {
281 add(dbQueryElement::qExpression, ".");
282 add(dbQueryElement::qExpression, comp.field);
283 }
284 operand = false;
285 return *this;
286 }
287
operator =(dbQueryExpression const & expr)288 dbQueryExpression& dbQueryExpression::operator=(dbQueryExpression const& expr)
289 {
290 first = new dbQueryElement(dbQueryElement::qExpression, "(");
291 first->next = expr.first;
292 last = expr.last;
293 *last = new dbQueryElement(dbQueryElement::qExpression, ")");
294 last = &(*last)->next;
295 operand = false;
296 return *this;
297 }
298
add(dbQueryExpression const & expr)299 dbQuery& dbQuery::add(dbQueryExpression const& expr)
300 {
301 append(dbQueryElement::qExpression, "(");
302 *nextElement = expr.first;
303 nextElement = expr.last;
304 append(dbQueryElement::qExpression, ")");
305 operand = false;
306 return *this;
307 }
308
309
310
reset()311 dbQuery& dbQuery::reset()
312 {
313 dbQueryElementAllocator::instance.deallocate(elements, nextElement);
314 elements = NULL;
315 nextElement = &elements;
316 operand = false;
317 mutexLocked = false;
318 dbCompiledQuery::destroy();
319 return *this;
320 }
321
destroy()322 void dbCompiledQuery::destroy()
323 {
324 if (tree != NULL) {
325 dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
326 dbCriticalSection cs(mutex);
327 if (mutex.isInitialized()) {
328 delete tree;
329 for (dbOrderByNode *op = order, *nop; op != NULL; op = nop) {
330 nop = op->next;
331 delete op;
332 }
333 for (dbFollowByNode *fp = follow, *nfp; fp != NULL; fp = nfp) {
334 nfp = fp->next;
335 delete fp;
336 }
337 }
338 tree = NULL;
339 }
340 startFrom = StartFromAny;
341 follow = NULL;
342 order = NULL;
343 table = NULL;
344 limitSpecified = false;
345 }
346
getParameterType()347 int dbUserFunction::getParameterType()
348 {
349 static byte argType[] = {
350 tpInteger,
351 tpReal,
352 tpString,
353 tpWString,
354 tpInteger,
355 tpReal,
356 tpString,
357 tpWString,
358 tpInteger,
359 tpReal,
360 tpString,
361 tpWString,
362 tpInteger,
363 tpReal,
364 tpString,
365 tpWString,
366 tpInteger,
367 tpReal,
368 tpString,
369 tpWString,
370 tpList,
371 tpList,
372 tpList,
373 tpList,
374 tpList,
375 tpList,
376 tpList,
377 tpList,
378 tpList,
379 tpList,
380 tpList,
381 tpList
382 };
383 return argType[type];
384 }
385
getNumberOfParameters()386 int dbUserFunction::getNumberOfParameters()
387 {
388 static byte nArgs[] = {
389 1,
390 1,
391 1,
392 1,
393 1,
394 1,
395 1,
396 1,
397 1,
398 1,
399 1,
400 1,
401 1,
402 1,
403 1,
404 1,
405 1,
406 1,
407 1,
408 1,
409 1,
410 1,
411 1,
412 1,
413 2,
414 2,
415 2,
416 2,
417 3,
418 3,
419 3,
420 3
421 };
422 return nArgs[type];
423 }
424
425 dbUserFunction* dbUserFunction::list;
426
427
bind(char * name,void * f,funcType ftype)428 void dbUserFunction::bind(char* name, void* f, funcType ftype)
429 {
430 fname = name;
431 dbSymbolTable::add(fname, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);
432 next = list;
433 list = this;
434 fptr = f;
435 type = ftype;
436 }
437
~dbUserFunction()438 dbUserFunction::~dbUserFunction()
439 {
440 dbUserFunction *fp, **fpp;
441 for (fpp = &list; (fp = *fpp) != this; fpp = &fp->next);
442 *fpp = next;
443 }
444
dbUserFunctionArgument(dbExprNode * expr,dbInheritedAttribute & iattr,dbSynthesizedAttribute & sattr,int i)445 dbUserFunctionArgument::dbUserFunctionArgument(dbExprNode* expr,
446 dbInheritedAttribute& iattr,
447 dbSynthesizedAttribute& sattr,
448 int i)
449 {
450 dbDatabase::execute(expr->func.arg[i], iattr, sattr);
451 switch (expr->func.arg[i]->type) {
452 case tpInteger:
453 u.intValue = sattr.ivalue;
454 type = atInteger;
455 break;
456 case tpReal:
457 u.realValue = sattr.fvalue;
458 type = atReal;
459 break;
460 case tpString:
461 u.strValue = sattr.array.base;
462 type = atString;
463 break;
464 case tpWString:
465 u.wstrValue = (wchar_t*)sattr.array.base;
466 type = atWString;
467 break;
468 case tpBoolean:
469 u.boolValue = sattr.bvalue;
470 type = atBoolean;
471 break;
472 case tpReference:
473 u.oidValue = sattr.oid;
474 type = atReference;
475 break;
476 case tpRawBinary:
477 u.rawValue = sattr.raw;
478 type = atRawBinary;
479 break;
480 default:
481 assert(false);
482 }
483 }
484
485 END_FASTDB_NAMESPACE
486