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