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