1 //-< QUERY.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: 10-Dec-98 K.A. Knizhnik * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Constructing and hashing database query statements
9 //-------------------------------------------------------------------*--------*
10
11 #ifndef __QUERY_H__
12 #define __QUERY_H__
13
14 BEGIN_FASTDB_NAMESPACE
15
16 /**
17 * Element of the query
18 */
19 class FASTDB_DLL_ENTRY dbQueryElement {
20 friend class dbQuery;
21 friend class dbCompiler;
22 friend class dbQueryExpression;
23 friend class dbQueryElementAllocator;
24 friend class dbCLI;
25 public:
26 enum ElementType {
27 qExpression, // part of SQL expression
28 qVarBool,
29 qVarInt1,
30 qVarInt2,
31 qVarInt4,
32 qVarInt8,
33 qVarReal4,
34 qVarReal8,
35 qVarString,
36 qVarStringPtr,
37 qVarWString,
38 qVarWStringPtr,
39 qVarReference,
40 qVarRectangle,
41 qVarRectanglePtr,
42 qVarArrayOfRef,
43 qVarArrayOfInt4,
44 qVarArrayOfInt8,
45 qVarArrayOfRefPtr,
46 qVarArrayOfInt4Ptr,
47 qVarArrayOfInt8Ptr,
48 qVarRawData,
49 qVarRawDataPtr,
50 #ifdef USE_STD_STRING
51 qVarStdString,
52 qVarStdWString,
53 #endif
54 qVarUnknown
55 };
56
getType()57 ElementType getType() const { return type; }
nextElement()58 dbQueryElement* nextElement() const { return next; }
59
60 void* operator new (size_t size EXTRA_DEBUG_NEW_PARAMS);
61 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
62
63 char* dump(char* buf);
64 char* dumpValues(char* buf);
65
66 dbQueryElement(ElementType t, void const* p,
67 dbTableDescriptor* table = NULL)
68 {
69 type = t;
70 ptr = p;
71 ref = table;
72 next = NULL;
73 }
74 private:
75 dbQueryElement* next;
76 void const* ptr;
77 ElementType type;
78 dbTableDescriptor* ref;
79 };
80
81
82 /**
83 * Allocator of query elements. This class links deallocated elements in the list of free elements,
84 * and reused them in future. So number of system memory allocator invocations is dramatically reduced.
85 * Cleanup of free elements lst is performed by <code>dbDatabase::cleanup()</code> method
86 */
87 class FASTDB_DLL_ENTRY dbQueryElementAllocator {
88 friend class dbDatabase;
89
90 dbMutex mutex;
91 dbQueryElement* freeChain;
92
93 public:
deallocate(dbQueryElement * first,dbQueryElement ** lastNext)94 void deallocate(dbQueryElement* first, dbQueryElement** lastNext) {
95 dbCriticalSection cs(mutex);
96 if (first != NULL) {
97 *lastNext = freeChain;
98 freeChain = first;
99 }
100 }
101
102 void* allocate(size_t size);
103
104 dbQueryElementAllocator();
105 ~dbQueryElementAllocator();
106
107 void reset();
108
109 static dbQueryElementAllocator instance;
110 };
111
112 /**
113 * This class represents component of the structure.
114 * It is mostly needed for implementation of application specific database types. For example, look at
115 * <code>dbDate</code> class. It contains <code>int4 jday</code> component which stores time in seconds sinse 1970.
116 * This class defines its own comparison methods:
117 * <PRE>
118 * dbQueryExpression operator == (char const* field) {
119 * dbQueryExpression expr;
120 * expr = dbComponent(field,"jday"),"=",jday;
121 * return expr;
122 * }
123 * </PRE>
124 * Making it possible to sepcify queries like this (assume that record has column "released" with type dbDate:
125 * <PRE>
126 * dbQuery q;
127 * dbDate date;
128 * q = date == "released";
129 * </PRE>
130 */
131 class FASTDB_DLL_ENTRY dbComponent {
132 public:
133 char const* structure;
134 char const* field;
135
structure(s)136 dbComponent(char const* s, char const* f=NULL) : structure(s), field(f) {}
137 };
138
139
140 /**
141 * Class representing SubSQL expression.
142 * It is mostly needed for implementation of application specific database types.
143 * Look at the example in dbComponent class.
144 * The effect of addeing dbExpression to the query is the same as if this expresion is enclosed in parenthesis.
145 */
146 class FASTDB_DLL_ENTRY dbQueryExpression {
147 friend class dbQuery;
148 dbQueryElement* first;
149 dbQueryElement** last;
150 bool operand;
151
152 public:
153 dbQueryExpression& add(dbQueryElement::ElementType type, void const* ptr, dbTableDescriptor* table = NULL) {
154 last = &(*last = new dbQueryElement(type, ptr, table))->next;
155 operand = (type == dbQueryElement::qExpression);
156 return *this;
157 }
158
159 dbQueryExpression& operator = (char const* ptr) {
160 first = NULL, last = &first;
161 return add(dbQueryElement::qExpression, ptr);
162 }
163 dbQueryExpression& operator = (dbComponent const& comp);
164
165 dbQueryExpression& operator = (dbQueryExpression const& expr);
166
167 dbQueryExpression& operator,(int1 const& ptr) {
168 return add(dbQueryElement::qVarInt1, &ptr);
169 }
170 dbQueryExpression& operator,(int2 const& ptr) {
171 return add(dbQueryElement::qVarInt2, &ptr);
172 }
173 dbQueryExpression& operator,(int4 const& ptr) {
174 return add(dbQueryElement::qVarInt4, &ptr);
175 }
176 dbQueryExpression& operator,(db_int8 const& ptr) {
177 return add(dbQueryElement::qVarInt8, &ptr);
178 }
179 dbQueryExpression& operator,(nat1 const& ptr) {
180 return add(dbQueryElement::qVarInt1, &ptr);
181 }
182 dbQueryExpression& operator,(nat2 const& ptr) {
183 return add(dbQueryElement::qVarInt2, &ptr);
184 }
185 dbQueryExpression& operator,(nat4 const& ptr) {
186 return add(dbQueryElement::qVarInt4, &ptr);
187 }
188 dbQueryExpression& operator,(db_nat8 const& ptr) {
189 return add(dbQueryElement::qVarInt8, &ptr);
190 }
191 #if SIZEOF_LONG != 8
192 dbQueryExpression& operator,(long const& ptr) {
193 return add(sizeof(long) == 4 ? dbQueryElement::qVarInt4 : dbQueryElement::qVarInt8, &ptr);
194 }
195 dbQueryExpression& operator,(unsigned long const& ptr) {
196 return add(sizeof(long) == 4 ? dbQueryElement::qVarInt4 : dbQueryElement::qVarInt8, &ptr);
197 }
198 #endif
199 dbQueryExpression& operator,(real4 const& ptr) {
200 return add(dbQueryElement::qVarReal4, &ptr);
201 }
202 dbQueryExpression& operator,(real8 const& ptr) {
203 return add(dbQueryElement::qVarReal8, &ptr);
204 }
205 dbQueryExpression& operator,(bool const& ptr) {
206 return add(dbQueryElement::qVarBool, &ptr);
207 }
208 dbQueryExpression& operator,(char const* ptr) {
209 return add(operand ? dbQueryElement::qVarString
210 : dbQueryElement::qExpression, ptr);
211 }
212 dbQueryExpression& operator,(char const** ptr) {
213 return add(dbQueryElement::qVarStringPtr, ptr);
214 }
215 dbQueryExpression& operator,(char** ptr) {
216 return add(dbQueryElement::qVarStringPtr, ptr);
217 }
218 dbQueryExpression& operator,(wchar_t const* ptr) {
219 return add(dbQueryElement::qVarWString, ptr);
220 }
221 dbQueryExpression& operator,(wchar_t const** ptr) {
222 return add(dbQueryElement::qVarWStringPtr, ptr);
223 }
224 dbQueryExpression& operator,(wchar_t** ptr) {
225 return add(dbQueryElement::qVarWStringPtr, ptr);
226 }
227 dbQueryExpression& operator,(void const* ptr) {
228 return add(dbQueryElement::qVarRawData, ptr);
229 }
230 dbQueryExpression& operator,(void** ptr) {
231 return add(dbQueryElement::qVarRawDataPtr, ptr);
232 }
233 dbQueryExpression& operator,(rectangle const& rect) {
234 return add(dbQueryElement::qVarRectangle, &rect);
235 }
236 dbQueryExpression& operator,(rectangle* rect) {
237 return add(dbQueryElement::qVarRectanglePtr, &rect);
238 }
239 #ifdef USE_STD_STRING
240 dbQueryExpression& operator,(std::string const& str) {
241 return add(dbQueryElement::qVarStdString, &str);
242 }
243 dbQueryExpression& operator,(std::wstring const& str) {
244 return add(dbQueryElement::qVarStdWString, &str);
245 }
246 #endif
247 dbQueryExpression& operator,(dbQueryExpression const& expr) {
248 *last = new dbQueryElement(dbQueryElement::qExpression, "(");
249 (*last)->next = expr.first;
250 last = expr.last;
251 *last = new dbQueryElement(dbQueryElement::qExpression, ")");
252 last = &(*last)->next;
253 operand = false;
254 return *this;
255 }
256 dbQueryExpression& operator,(dbComponent const& comp) {
257 add(dbQueryElement::qExpression, comp.structure);
258 if (comp.field != NULL) {
259 add(dbQueryElement::qExpression, ".");
260 add(dbQueryElement::qExpression, comp.field);
261 }
262 operand = false;
263 return *this;
264 }
265 dbQueryExpression& operator += (dbComponent const& comp) {
266 return *this,comp;
267 }
268 dbQueryExpression& operator += (char const* ptr) {
269 return add(dbQueryElement::qExpression, ptr);
270 }
271 #ifndef NO_MEMBER_TEMPLATES
272 template<class T>
273 dbQueryExpression& operator,(dbReference<T> const& value) {
274 return add(dbQueryElement::qVarReference, &value, &T::dbDescriptor);
275 }
276
277 template<class T>
278 inline dbQueryExpression& operator,(dbArray< dbReference<T> > const& value) {
279 return add(dbQueryElement::qVarArrayOfRef, &value, &T::dbDescriptor);
280 }
281
282 template<class T>
283 inline dbQueryExpression& operator,(dbArray< dbReference<T> >const* const& value) {
284 return add(dbQueryElement::qVarArrayOfRefPtr, &value, &T::dbDescriptor);
285 }
286 #endif
287 #if !defined(_MSC_VER) || _MSC_VER+0 >= 1300
288 inline dbQueryExpression& operator,(dbArray<db_int4> const& value) {
289 return add(dbQueryElement::qVarArrayOfInt4, &value);
290 }
291
292 inline dbQueryExpression& operator,(dbArray<db_int4>const* const& value) {
293 return add(dbQueryElement::qVarArrayOfInt4Ptr, &value);
294 }
295
296 inline dbQueryExpression& operator,(dbArray<db_int8> const& value) {
297 return add(dbQueryElement::qVarArrayOfInt8, &value);
298 }
299
300 inline dbQueryExpression& operator,(dbArray<db_int8>const* const& value) {
301 return add(dbQueryElement::qVarArrayOfInt8Ptr, &value);
302 }
303 #endif
304 };
305
306 class dbOrderByNode;
307 class dbFollowByNode;
308
309
310 /**
311 * Class used for precompiled queries
312 */
313 class FASTDB_DLL_ENTRY dbCompiledQuery {
314 public:
315 dbExprNode* tree;
316 dbOrderByNode* order;
317 dbFollowByNode* follow;
318 dbTableDescriptor* table;
319 int schemeVersion;
320
321 cardinality_t stmtLimitStart;
322 cardinality_t stmtLimitLen;
323 cardinality_t* stmtLimitStartPtr;
324 cardinality_t* stmtLimitLenPtr;
325 bool limitSpecified;
326
327 enum IteratorInit {
328 StartFromAny,
329 StartFromFirst,
330 StartFromLast,
331 StartFromRef,
332 StartFromArray,
333 StartFromArrayPtr
334 };
335 IteratorInit startFrom;
336 void const* root;
337
338 void destroy();
339
compiled()340 bool compiled() { return tree != NULL; }
341
compileError()342 bool compileError() { return !compiled(); }
343
dbCompiledQuery()344 dbCompiledQuery() {
345 tree = NULL;
346 order = NULL;
347 follow = NULL;
348 table = NULL;
349 startFrom = StartFromAny;
350 limitSpecified = false;
351 }
352 };
353
354 /**
355 * Query class. It is derived from <code>dbCompiledQuery</code> class because each query is compiled only once - when
356 * it is executed first time. All subsequent executions of query used precompiled tree.
357 */
358 class FASTDB_DLL_ENTRY dbQuery : public dbCompiledQuery {
359 friend class dbCompiler;
360 friend class dbDatabase;
361 friend class dbSubSql;
362 friend class dbCLI;
363 private:
364 dbMutex mutex;
365 dbQueryElement* elements;
366 dbQueryElement** nextElement;
367 bool operand;
368 bool mutexLocked;
369
370 //
371 // Prohibite query copying
372 //
dbQuery(dbQuery const &)373 dbQuery(dbQuery const&) : dbCompiledQuery() {}
374 dbQuery& operator =(dbQuery const&) { return *this; }
375
376 public:
377 int pos; // position of condition in statement
378
379
dump(char * buf)380 char* dump(char* buf) {
381 char* p = buf;
382 for (dbQueryElement* elem = elements; elem != NULL; elem = elem->next) {
383 p = elem->dump(p);
384 }
385 return buf;
386 }
387
dumpValues(char * buf)388 char* dumpValues(char* buf) {
389 char* p = buf;
390 for (dbQueryElement* elem = elements; elem != NULL; elem = elem->next) {
391 p = elem->dumpValues(p);
392 }
393 return buf;
394 }
395
396 dbQuery& append(dbQueryElement::ElementType type, void const* ptr,
397 dbTableDescriptor* table = NULL)
398 {
399 nextElement = &(*nextElement=new dbQueryElement(type,ptr,table))->next;
400 operand = (type == dbQueryElement::qExpression);
401 return *this;
402 }
403
404 dbQuery& reset();
405
406 //
407 // Redefined operator = and , make it possible to specify query in the
408 // following way:
409 // int x, y;
410 // dbDataTime dt;
411 // dbQuery q;
412 // dbCursor<record> cursor;
413 // q = "x=",x,"and y=",y,"and",dt == "date";
414 // for (x = 0; x < max_x; x++) {
415 // for (y = 0; y < max_y; y++) {
416 // cursor.select(q);
417 // ...
418 // }
419 // }
420
421 dbQuery& add(dbQueryExpression const& expr);
422
And(dbQueryExpression const & expr)423 dbQuery& And(dbQueryExpression const& expr) {
424 if (elements != NULL) {
425 append(dbQueryElement::qExpression, "and");
426 }
427 return add(expr);
428 }
429
Or(dbQueryExpression const & expr)430 dbQuery& Or(dbQueryExpression const& expr) {
431 if (elements != NULL) {
432 append(dbQueryElement::qExpression, "or");
433 }
434 return add(expr);
435 }
436
And(char const * str)437 dbQuery& And(char const* str) {
438 if (elements != NULL) {
439 append(dbQueryElement::qExpression, "and");
440 }
441 return append(dbQueryElement::qExpression, str);
442 }
443
Or(char const * str)444 dbQuery& Or(char const* str) {
445 if (elements != NULL) {
446 append(dbQueryElement::qExpression, "or");
447 }
448 return append(dbQueryElement::qExpression, str);
449 }
450
add(char const * str)451 dbQuery& add(char const* str) {
452 return append(operand ? dbQueryElement::qVarString
453 : dbQueryElement::qExpression, str);
454 }
add(char const ** str)455 dbQuery& add(char const** str) {
456 return append(dbQueryElement::qVarStringPtr, str);
457 }
add(wchar_t const * str)458 dbQuery& add(wchar_t const* str) {
459 return append(dbQueryElement::qVarWString, str);
460 }
add(wchar_t const ** str)461 dbQuery& add(wchar_t const** str) {
462 return append(dbQueryElement::qVarWStringPtr, str);
463 }
add(rectangle const & rect)464 dbQuery& add(rectangle const& rect) {
465 return append(dbQueryElement::qVarRectangle, &rect);
466 }
add(rectangle * rect)467 dbQuery& add(rectangle* rect) {
468 return append(dbQueryElement::qVarRectanglePtr, &rect);
469 }
470 #ifdef USE_STD_STRING
add(std::string const & str)471 dbQuery& add(std::string const& str) {
472 return append(dbQueryElement::qVarStdString, &str);
473 }
474 dbQuery& operator,(std::string const& str) { return add(str); }
add(std::wstring const & str)475 dbQuery& add(std::wstring const& str) {
476 return append(dbQueryElement::qVarStdWString, &str);
477 }
478 dbQuery& operator,(std::wstring const& str) { return add(str); }
479 #endif
add(char ** str)480 dbQuery& add(char** str) {
481 return append(dbQueryElement::qVarStringPtr, str);
482 }
add(wchar_t ** str)483 dbQuery& add(wchar_t** str) {
484 return append(dbQueryElement::qVarWStringPtr, str);
485 }
add(int1 const & value)486 dbQuery& add(int1 const& value) {
487 return append(dbQueryElement::qVarInt1, &value);
488 }
add(int2 const & value)489 dbQuery& add (int2 const& value) {
490 return append(dbQueryElement::qVarInt2, &value);
491 }
add(int4 const & value)492 dbQuery& add (int4 const& value) {
493 return append(dbQueryElement::qVarInt4, &value);
494 }
add(db_int8 const & value)495 dbQuery& add (db_int8 const& value) {
496 return append(dbQueryElement::qVarInt8, &value);
497 }
add(nat1 const & value)498 dbQuery& add(nat1 const& value) {
499 return append(dbQueryElement::qVarInt1, &value);
500 }
add(nat2 const & value)501 dbQuery& add (nat2 const& value) {
502 return append(dbQueryElement::qVarInt2, &value);
503 }
add(nat4 const & value)504 dbQuery& add (nat4 const& value) {
505 return append(dbQueryElement::qVarInt4, &value);
506 }
add(db_nat8 const & value)507 dbQuery& add (db_nat8 const& value) {
508 return append(dbQueryElement::qVarInt8, &value);
509 }
510 #if SIZEOF_LONG != 8
add(long const & value)511 dbQuery& add (long const& value) {
512 return append(sizeof(long) == 4 ? dbQueryElement::qVarInt4 : dbQueryElement::qVarInt8, &value);
513 }
add(unsigned long const & value)514 dbQuery& add (unsigned long const& value) {
515 return append(sizeof(long) == 4 ? dbQueryElement::qVarInt4 : dbQueryElement::qVarInt8, &value);
516 }
517 #endif
add(real4 const & value)518 dbQuery& add (real4 const& value) {
519 return append(dbQueryElement::qVarReal4, &value);
520 }
add(real8 const & value)521 dbQuery& add(real8 const& value) {
522 return append(dbQueryElement::qVarReal8, &value);
523 }
add(bool const & value)524 dbQuery& add(bool const& value) {
525 return append(dbQueryElement::qVarBool, &value);
526 }
add(void const * value)527 dbQuery& add(void const* value) {
528 return append(dbQueryElement::qVarRawData, value);
529 }
add(void ** value)530 dbQuery& add(void** value) {
531 return append(dbQueryElement::qVarRawDataPtr, value);
532 }
533
534 dbQuery& operator,(char const* value) { return add(value); }
535 dbQuery& operator,(char const** value) { return add(value); }
536 dbQuery& operator,(char** value) { return add(value); }
537 dbQuery& operator,(wchar_t const* value) { return add(value); }
538 dbQuery& operator,(wchar_t const** value) { return add(value); }
539 dbQuery& operator,(wchar_t** value) { return add(value); }
540 dbQuery& operator,(int1 const& value) { return add(value); }
541 dbQuery& operator,(int2 const& value) { return add(value); }
542 dbQuery& operator,(int4 const& value) { return add(value); }
543 dbQuery& operator,(db_int8 const& value) { return add(value); }
544 dbQuery& operator,(nat1 const& value) { return add(value); }
545 dbQuery& operator,(nat2 const& value) { return add(value); }
546 dbQuery& operator,(nat4 const& value) { return add(value); }
547 dbQuery& operator,(db_nat8 const& value) { return add(value); }
548 #if SIZEOF_LONG != 8
549 dbQuery& operator,(long const& value) { return add(value); }
550 dbQuery& operator,(unsigned long const& value) { return add(value); }
551 #endif
552 dbQuery& operator,(real4 const& value) { return add(value); }
553 dbQuery& operator,(real8 const& value) { return add(value); }
554 dbQuery& operator,(bool const& value) { return add(value); }
555 dbQuery& operator,(void const* value) { return add(value); }
556 dbQuery& operator,(dbQueryExpression const& expr) { return add(expr); }
557 dbQuery& operator,(rectangle const& rect) { return add(rect); }
558
559 dbQuery& operator = (const char* str) {
560 return reset().append(dbQueryElement::qExpression, str);
561 }
562
563 #if !defined(_MSC_VER) || _MSC_VER+0 >= 1300
564 inline dbQuery& operator,(dbArray<db_int4> const& value) {
565 return append(dbQueryElement::qVarArrayOfInt4, &value);
566 }
567
568 inline dbQuery& operator,(dbArray<db_int4>const* const& value) {
569 return append(dbQueryElement::qVarArrayOfInt4Ptr, &value);
570 }
571
572 inline dbQuery& operator,(dbArray<db_int8> const& value) {
573 return append(dbQueryElement::qVarArrayOfInt8, &value);
574 }
575
576 inline dbQuery& operator,(dbArray<db_int8>const* const& value) {
577 return append(dbQueryElement::qVarArrayOfInt8Ptr, &value);
578 }
579
add(dbArray<db_int4> const & value)580 inline dbQuery& add(dbArray<db_int4> const& value) {
581 return append(dbQueryElement::qVarArrayOfInt4, &value);
582 }
583
add(dbArray<db_int4> const * const & value)584 inline dbQuery& add(dbArray<db_int4>const* const& value) {
585 return append(dbQueryElement::qVarArrayOfInt4Ptr, &value);
586 }
587
add(dbArray<db_int8> const & value)588 inline dbQuery& add(dbArray<db_int8> const& value) {
589 return append(dbQueryElement::qVarArrayOfInt8, &value);
590 }
591
add(dbArray<db_int8> const * const & value)592 inline dbQuery& add(dbArray<db_int8>const* const& value) {
593 return append(dbQueryElement::qVarArrayOfInt8Ptr, &value);
594 }
595 #endif
596
597 #ifndef NO_MEMBER_TEMPLATES
598 template<class T>
599 dbQuery& operator,(dbReference<T> const& value) {
600 return append(dbQueryElement::qVarReference, &value, &T::dbDescriptor);
601 }
602
603 template<class T>
604 inline dbQuery& operator,(dbArray< dbReference<T> > const& value) {
605 return append(dbQueryElement::qVarArrayOfRef, &value, &T::dbDescriptor);
606 }
607
608 template<class T>
609 inline dbQuery& operator,(dbArray< dbReference<T> >const* const& value) {
610 return append(dbQueryElement::qVarArrayOfRefPtr, &value, &T::dbDescriptor);
611 }
612
613 template<class T>
add(dbReference<T> const & value)614 dbQuery& add(dbReference<T> const& value) {
615 return append(dbQueryElement::qVarReference, &value, &T::dbDescriptor);
616 }
617
618 template<class T>
add(dbArray<dbReference<T>> const & value)619 dbQuery& add(dbArray< dbReference<T> > const& value) {
620 return append(dbQueryElement::qVarArrayOfRef, &value, &T::dbDescriptor);
621 }
622 template<class T>
add(dbArray<dbReference<T>> const * const & value)623 dbQuery& add(dbArray< dbReference<T> >const* const& value) {
624 return append(dbQueryElement::qVarArrayOfRefPtr, &value, &T::dbDescriptor);
625 }
626
627 template<class T>
628 dbQuery& operator = (T const& value) {
629 return reset().add(value);
630 }
631 #else
632 dbQuery& operator = (dbQueryExpression const& expr) {
633 return reset().add(expr);
634 }
635 dbQuery& operator = (rectangle const& expr) {
636 return reset().add(expr);
637 }
638 #endif
639
640
getElements()641 dbQueryElement* getElements() const {
642 return elements;
643 }
644
isEmpty()645 bool isEmpty() {
646 return elements == NULL
647 || (elements->next == NULL && elements->type == dbQueryElement::qExpression && *(char*)elements->ptr == 0);
648 }
649
dbQuery()650 dbQuery() {
651 elements = NULL;
652 nextElement = &elements;
653 operand = false;
654 pos = 0;
655 }
dbQuery(char const * str)656 dbQuery(char const* str) {
657 elements = new dbQueryElement(dbQueryElement::qExpression, str);
658 nextElement = &elements->next;
659 operand = true;
660 pos = 0;
661 }
~dbQuery()662 ~dbQuery() {
663 reset();
664 }
665 };
666
667 #ifdef NO_MEMBER_TEMPLATES
668 template<class T>
669 inline dbQueryExpression& operator,(dbQueryExpression& expr, dbReference<T> const& value) {
670 return expr.add(dbQueryElement::qVarReference, &value, &T::dbDescriptor);
671 }
672 template<class T>
673 inline dbQueryExpression& operator,(dbQueryExpression& expr, dbArray< dbReference<T> > const& value) {
674 return expr.add(dbQueryElement::qVarArrayOfRef, &value,
675 &T::dbDescriptor);
676 }
677
678 template<class T>
679 inline dbQueryExpression& operator,(dbQueryExpression& expr, dbArray< dbReference<T> >const* const& value) {
680 return expr.add(dbQueryElement::qVarArrayOfRefPtr, &value, &T::dbDescriptor);
681 }
682
683 template<class T>
684 inline dbQuery& operator,(dbQuery& query, dbReference<T> const& value) {
685 return query.append(dbQueryElement::qVarReference, &value,
686 &T::dbDescriptor);
687 }
688
689 template<class T>
690 inline dbQuery& operator,(dbQuery& query,
691 dbArray< dbReference<T> > const& value)
692 {
693 return query.append(dbQueryElement::qVarArrayOfRef, &value,
694 &T::dbDescriptor);
695 }
696
697 template<class T>
698 inline dbQuery& operator,(dbQuery& query,
699 dbArray< dbReference<T> >const* const& value)
700 {
701 return query.append(dbQueryElement::qVarArrayOfRefPtr, &value,
702 &T::dbDescriptor);
703 }
704
705 template<class T>
add(dbQuery & query,dbReference<T> const & value)706 inline dbQuery& add(dbQuery& query, dbReference<T> const& value) {
707 return query.append(dbQueryElement::qVarReference, &value, &T::dbDescriptor);
708 }
709
710 template<class T>
add(dbQuery & query,dbArray<dbReference<T>> const & value)711 inline dbQuery& add(dbQuery& query, dbArray< dbReference<T> > const& value) {
712 return query.append(dbQueryElement::qVarArrayOfRef, &value,
713 &T::dbDescriptor);
714 }
715
716 template<class T>
add(dbQuery & query,dbArray<dbReference<T>> const * const & value)717 inline dbQuery& add(dbQuery& query, dbArray< dbReference<T> >const* const& value) {
718 return query.append(dbQueryElement::qVarArrayOfRefPtr, &value, &T::dbDescriptor);
719 }
720 #endif
721
722 #define USER_FUNC(f) static dbUserFunction f##_descriptor(&f, (char*)#f)
723
724 struct dbInheritedAttribute;
725 union dbSynthesizedAttribute;
726
727 /**
728 * This class represent argument of user defined funtion.
729 * @see dbUserFunction class.
730 */
731 class FASTDB_DLL_ENTRY dbUserFunctionArgument {
732 public:
733 enum dbArgumentType {
734 atInteger,
735 atBoolean,
736 atString,
737 atReal,
738 atReference,
739 atRawBinary,
740 atWString
741 };
742 dbArgumentType type;
743 union {
744 real8 realValue;
745 db_int8 intValue;
746 bool boolValue;
747 char const* strValue;
748 wchar_t const* wstrValue;
749 oid_t oidValue;
750 void* rawValue;
751 } u;
752
753 private:
754 friend class dbDatabase;
755 dbUserFunctionArgument(dbExprNode* expr,
756 dbInheritedAttribute& iattr,
757 dbSynthesizedAttribute& sattr,
758 int i);
759 };
760
761 /**
762 * dbUserFunction class is used to bind user defined functions to the database.
763 * This class contains list of all user functions declared by application and provides method
764 * for locating function by name and adding new user defined functions.
765 * User defined functions can have fro 0 till 3 parameters (of <code>dbUserFunctionArgument</code> type)
766 * and should return integer, boolean, real or string value. Type of the function is detected by overloaded
767 * constructors. User defined function descriptor is cerated by <code>USER_FUNC</code> macro.
768 */
769 class FASTDB_DLL_ENTRY dbUserFunction {
770 friend class dbDatabase;
771 friend class dbCompiler;
772
773 void* fptr;
774 char* fname;
775
776 dbUserFunction* next;
777 static dbUserFunction* list;
778
779 enum funcType {
780 fInt2Bool,
781 fReal2Bool,
782 fStr2Bool,
783 fWStr2Bool,
784 fInt2Int,
785 fReal2Int,
786 fStr2Int,
787 fWStr2Int,
788 fInt2Real,
789 fReal2Real,
790 fStr2Real,
791 fWStr2Real,
792 fInt2Str,
793 fReal2Str,
794 fStr2Str,
795 fWStr2Str,
796 fInt2WStr,
797 fReal2WStr,
798 fStr2WStr,
799 fWStr2WStr,
800 fArg2Bool,
801 fArg2Int,
802 fArg2Real,
803 fArg2Str,
804 fArg2WStr,
805 fArgArg2Bool,
806 fArgArg2Int,
807 fArgArg2Real,
808 fArgArg2Str,
809 fArgArg2WStr,
810 fArgArgArg2Bool,
811 fArgArgArg2Int,
812 fArgArgArg2Real,
813 fArgArgArg2Str,
814 fArgArgArg2WStr
815 };
816 int type;
817
818 void bind(char* name, void* f, funcType ftype);
819
820 public:
821
find(char const * name)822 static dbUserFunction* find(char const* name) {
823 for (dbUserFunction* func = list; func != NULL; func = func->next) {
824 if (name == func->fname) {
825 return func;
826 }
827 }
828 return NULL;
829 }
830
831 int getParameterType();
832
833 int getNumberOfParameters();
834
dbUserFunction(bool (* f)(db_int8),char * name)835 dbUserFunction(bool (*f)(db_int8), char* name) {
836 bind(name, (void*)f, fInt2Bool);
837 }
dbUserFunction(bool (* f)(real8),char * name)838 dbUserFunction(bool (*f)(real8), char* name) {
839 bind(name, (void*)f, fReal2Bool);
840 }
dbUserFunction(bool (* f)(char const *),char * name)841 dbUserFunction(bool (*f)(char const*), char* name) {
842 bind(name, (void*)f, fStr2Bool);
843 }
dbUserFunction(bool (* f)(wchar_t const *),char * name)844 dbUserFunction(bool (*f)(wchar_t const*), char* name) {
845 bind(name, (void*)f, fWStr2Bool);
846 }
dbUserFunction(db_int8 (* f)(db_int8),char * name)847 dbUserFunction(db_int8 (*f)(db_int8), char* name) {
848 bind(name, (void*)f, fInt2Int);
849 }
dbUserFunction(db_int8 (* f)(real8),char * name)850 dbUserFunction(db_int8 (*f)(real8), char* name) {
851 bind(name, (void*)f, fReal2Int);
852 }
dbUserFunction(db_int8 (* f)(char const *),char * name)853 dbUserFunction(db_int8 (*f)(char const*), char* name) {
854 bind(name, (void*)f, fStr2Int);
855 }
dbUserFunction(db_int8 (* f)(wchar_t const *),char * name)856 dbUserFunction(db_int8 (*f)(wchar_t const*), char* name) {
857 bind(name, (void*)f, fWStr2Int);
858 }
dbUserFunction(real8 (* f)(db_int8),char * name)859 dbUserFunction(real8 (*f)(db_int8), char* name) {
860 bind(name, (void*)f, fInt2Real);
861 }
dbUserFunction(real8 (* f)(real8),char * name)862 dbUserFunction(real8 (*f)(real8), char* name) {
863 bind(name, (void*)f, fReal2Real);
864 }
dbUserFunction(real8 (* f)(char const *),char * name)865 dbUserFunction(real8 (*f)(char const*), char* name) {
866 bind(name, (void*)f, fStr2Real);
867 }
dbUserFunction(real8 (* f)(wchar_t const *),char * name)868 dbUserFunction(real8 (*f)(wchar_t const*), char* name) {
869 bind(name, (void*)f, fWStr2Real);
870 }
dbUserFunction(char * (* f)(db_int8),char * name)871 dbUserFunction(char* (*f)(db_int8), char* name) {
872 bind(name, (void*)f, fInt2Str);
873 }
dbUserFunction(char * (* f)(real8),char * name)874 dbUserFunction(char* (*f)(real8), char* name) {
875 bind(name, (void*)f, fReal2Str);
876 }
dbUserFunction(char * (* f)(char const *),char * name)877 dbUserFunction(char* (*f)(char const*), char* name) {
878 bind(name, (void*)f, fStr2Str);
879 }
dbUserFunction(char * (* f)(wchar_t const *),char * name)880 dbUserFunction(char* (*f)(wchar_t const*), char* name) {
881 bind(name, (void*)f, fWStr2Str);
882 }
dbUserFunction(wchar_t * (* f)(db_int8),char * name)883 dbUserFunction(wchar_t* (*f)(db_int8), char* name) {
884 bind(name, (void*)f, fInt2WStr);
885 }
dbUserFunction(wchar_t * (* f)(real8),char * name)886 dbUserFunction(wchar_t* (*f)(real8), char* name) {
887 bind(name, (void*)f, fReal2WStr);
888 }
dbUserFunction(wchar_t * (* f)(char const *),char * name)889 dbUserFunction(wchar_t* (*f)(char const*), char* name) {
890 bind(name, (void*)f, fStr2WStr);
891 }
dbUserFunction(wchar_t * (* f)(wchar_t const *),char * name)892 dbUserFunction(wchar_t* (*f)(wchar_t const*), char* name) {
893 bind(name, (void*)f, fWStr2WStr);
894 }
895
896
dbUserFunction(bool (* f)(dbUserFunctionArgument &),char * name)897 dbUserFunction(bool (*f)(dbUserFunctionArgument&), char* name) {
898 bind(name, (void*)f, fArg2Bool);
899 }
dbUserFunction(char * (* f)(dbUserFunctionArgument &),char * name)900 dbUserFunction(char* (*f)(dbUserFunctionArgument&), char* name) {
901 bind(name, (void*)f, fArg2Str);
902 }
dbUserFunction(wchar_t * (* f)(dbUserFunctionArgument &),char * name)903 dbUserFunction(wchar_t* (*f)(dbUserFunctionArgument&), char* name) {
904 bind(name, (void*)f, fArg2WStr);
905 }
dbUserFunction(db_int8 (* f)(dbUserFunctionArgument &),char * name)906 dbUserFunction(db_int8 (*f)(dbUserFunctionArgument&), char* name) {
907 bind(name, (void*)f, fArg2Int);
908 }
dbUserFunction(real8 (* f)(dbUserFunctionArgument &),char * name)909 dbUserFunction(real8 (*f)(dbUserFunctionArgument&), char* name) {
910 bind(name, (void*)f, fArg2Real);
911 }
912
dbUserFunction(bool (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)913 dbUserFunction(bool (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
914 bind(name, (void*)f, fArgArg2Bool);
915 }
dbUserFunction(char * (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)916 dbUserFunction(char* (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
917 bind(name, (void*)f, fArgArg2Str);
918 }
dbUserFunction(wchar_t * (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)919 dbUserFunction(wchar_t* (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
920 bind(name, (void*)f, fArgArg2WStr);
921 }
dbUserFunction(db_int8 (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)922 dbUserFunction(db_int8 (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
923 bind(name, (void*)f, fArgArg2Int);
924 }
dbUserFunction(real8 (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)925 dbUserFunction(real8 (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
926 bind(name, (void*)f, fArgArg2Real);
927 }
928
929
dbUserFunction(bool (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)930 dbUserFunction(bool (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
931 bind(name, (void*)f, fArgArgArg2Bool);
932 }
dbUserFunction(char * (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)933 dbUserFunction(char* (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
934 bind(name, (void*)f, fArgArgArg2Str);
935 }
dbUserFunction(wchar_t * (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)936 dbUserFunction(wchar_t* (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
937 bind(name, (void*)f, fArgArgArg2WStr);
938 }
dbUserFunction(db_int8 (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)939 dbUserFunction(db_int8 (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
940 bind(name, (void*)f, fArgArgArg2Int);
941 }
dbUserFunction(real8 (* f)(dbUserFunctionArgument &,dbUserFunctionArgument &,dbUserFunctionArgument &),char * name)942 dbUserFunction(real8 (*f)(dbUserFunctionArgument&, dbUserFunctionArgument&, dbUserFunctionArgument&), char* name) {
943 bind(name, (void*)f, fArgArgArg2Real);
944 }
945
946 ~dbUserFunction();
947 };
948
949 END_FASTDB_NAMESPACE
950
951 #endif
952
953
954
955