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