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