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