1 //-< CURSOR.CPP >----------------------------------------------------*--------*
2 // GigaBASE                  Version 1.0         (c) 1999  GARRET    *     ?  *
3 // (Post Relational Database Management System)                      *   /\|  *
4 //                                                                   *  /  \  *
5 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
6 //                          Last update: 21-Dec-98    K.A. Knizhnik  * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Table cursor
9 //-------------------------------------------------------------------*--------*
10 
11 #define INSIDE_GIGABASE
12 
13 #include "gigabase.h"
14 #include "compiler.h"
15 #include "btree.h"
16 
17 BEGIN_GIGABASE_NAMESPACE
18 
19 size_t dbSelection::buildSelectionBitmapThreshold = 100;
20 
next()21 oid_t dbTableIterator::next()
22 {
23     if (curr != 0) {
24         dbRecord rec;
25         oid_t oid = curr;
26         while (true) {
27             cursor->db->getHeader(rec, oid);
28             oid = rec.next;
29             if (oid != 0) {
30                 if (filter == NULL
31                     || cursor->db->evaluateBoolean(filter, oid, cursor->table, cursor))
32                 {
33                     return curr = oid;
34                 }
35             } else {
36                 break;
37             }
38         }
39     }
40     return 0;
41 }
42 
prev()43 oid_t dbTableIterator::prev()
44 {
45     if (curr != 0) {
46         dbRecord rec;
47         oid_t oid = curr;
48         while (true) {
49             cursor->db->getHeader(rec, oid);
50             oid = rec.prev;
51             if (oid != 0) {
52                 if (filter == NULL
53                     || cursor->db->evaluateBoolean(filter, oid, cursor->table, cursor))
54                 {
55                     return curr = oid;
56                 }
57             } else {
58                 break;
59             }
60         }
61     }
62     return 0;
63 }
64 
first()65 oid_t dbTableIterator::first()
66 {
67     oid_t oid = cursor->table->firstRow;
68     while (oid != 0
69            && filter != NULL
70            && !cursor->db->evaluateBoolean(filter, oid, cursor->table, cursor))
71     {
72         dbRecord rec;
73         cursor->db->getHeader(rec, oid);
74         oid = rec.next;
75     }
76     return curr = oid;
77 }
78 
79 
last()80 oid_t dbTableIterator::last()
81 {
82     oid_t oid = cursor->table->lastRow;
83     while (oid != 0
84            && filter != NULL
85            && !cursor->db->evaluateBoolean(filter, oid, cursor->table, cursor))
86     {
87         dbRecord rec;
88         cursor->db->getHeader(rec, oid);
89         oid = rec.prev;
90     }
91     return curr = oid;
92 }
93 
94 
reset()95 void dbSelection::reset()
96 {
97     while (first.next != &first) {
98         delete first.next;
99     }
100     first.nRows = 0;
101     curr = &first;
102     nRows = 0;
103     pos = 0;
104 }
105 
reverse()106 void dbSelection::reverse()
107 {
108     segment* seg = &first;
109     do {
110         segment* next = seg->next;
111         seg->next = seg->prev;
112         seg->prev = next;
113         for (int l = 0, r = (int)seg->nRows-1; l < r; l++, r--) {
114             oid_t oid = seg->rows[l];
115             seg->rows[l] = seg->rows[r];
116             seg->rows[r] = oid;
117         }
118         seg = next;
119     } while (seg != &first);
120 }
121 
truncate(cardinality_t from,cardinality_t length)122 void dbSelection::truncate(cardinality_t from, cardinality_t length)
123 {
124     if (from == 0 && length >= nRows) {
125         // do nothing
126         return;
127     }
128     segment* src = &first;
129     bool empty = true;
130     if (from < nRows) {
131         do {
132             if (from < src->nRows) {
133                 empty = false;
134                 break;
135             }
136             from -= src->nRows;
137         } while ((src = src->next) != &first);
138     }
139     if (from + length > nRows) {
140         length = nRows - from;
141     }
142     nRows = 0;
143     segment* dst = &first;
144     size_t pos = 0;
145     if (!empty) {
146         while (length != 0) {
147             size_t n = src->nRows - from;
148             if (n > length) {
149                 n = length;
150             }
151             if (dst->nRows == pos) {
152                 dst = dst->next;
153                 pos = 0;
154             }
155             if (n > dst->nRows - pos) {
156                 n = dst->nRows - pos;
157             }
158             memcpy(dst->rows + pos, src->rows + from, n*sizeof(oid_t));
159             pos += n;
160             length -= n;
161             nRows += n;
162             if ((from += n) == src->nRows) {
163                 if ((src = src->next) == &first) {
164                     break;
165                 }
166                 from = 0;
167             }
168         }
169     }
170     dst->nRows = pos;
171     dst = dst->next;
172     while (dst != &first) {
173         segment* next = dst->next;
174         delete dst;
175         dst = next;
176     }
177 }
178 
compare(oid_t o1,dbRecord * a,oid_t o2,dbRecord * b,dbOrderByNode * order)179 int dbSelection::compare(oid_t o1, dbRecord* a, oid_t o2, dbRecord* b, dbOrderByNode* order)
180 {
181     byte* p = (byte*)a;
182     byte* q = (byte*)b;
183     int diff = 0;
184     do {
185         if (order->expr != NULL) {
186             dbDatabase* db = order->table->db;
187             dbInheritedAttribute   iattr1;
188             dbInheritedAttribute   iattr2;
189             dbSynthesizedAttribute sattr1;
190             dbSynthesizedAttribute sattr2;
191             iattr1.db = iattr2.db = db;
192             iattr1.table = iattr2.table = order->table;
193             iattr1.record = sattr1.base = p;
194             iattr1.oid = o1;
195             iattr2.record = sattr2.base = q;
196             iattr2.oid = o2;
197             db->execute(order->expr, iattr1, sattr1);
198             db->execute(order->expr, iattr2, sattr2);
199             switch (order->expr->type) {
200               case tpInteger:
201                 diff = sattr1.ivalue < sattr2.ivalue ? -1 : sattr1.ivalue == sattr2.ivalue ? 0 : 1;
202                 break;
203               case tpReal:
204                 diff = sattr1.fvalue < sattr2.fvalue ? -1 : sattr1.fvalue == sattr2.fvalue ? 0 : 1;
205                 break;
206               case tpBoolean:
207                 diff = sattr1.bvalue != 0 ? sattr2.bvalue != 0 ? 0 : 1 : sattr2.bvalue != 0 ? -1 : 0;
208                 break;
209               case tpString:
210 #ifdef USE_LOCALE_SETTINGS
211                 diff = STRCOLL((char_t*)sattr1.array.base, (char_t*)sattr2.array.base);
212 #else
213                 diff = STRCMP((char_t*)sattr1.array.base, (char_t*)sattr2.array.base);
214 #endif
215                 break;
216               case tpReference:
217                 diff = sattr1.oid < sattr2.oid ? -1 : sattr1.oid == sattr2.oid ? 0 : 1;
218                 break;
219               default:
220                 assert(false);
221             }
222             iattr1.free(sattr1);
223             iattr2.free(sattr2);
224         } else {
225             int offs = order->field->dbsOffs;
226             switch (order->field->type) {
227               case dbField::tpBool:
228                 diff = *(bool*)(p + offs) - *(bool*)(q + offs);
229                 break;
230               case dbField::tpInt1:
231                 diff = *(int1*)(p + offs) - *(int1*)(q + offs);
232                 break;
233               case dbField::tpInt2:
234                 diff = *(int2*)(p + offs) - *(int2*)(q + offs);
235                 break;
236               case dbField::tpInt4:
237               case dbField::tpArray: // compre arrays length
238                 diff = *(int4*)(p + offs) < *(int4*)(q + offs) ? -1 :
239                     *(int4*)(p + offs) == *(int4*)(q + offs) ? 0 : 1;
240                 break;
241               case dbField::tpInt8:
242                 diff = *(db_int8*)(p + offs) < *(db_int8*)(q + offs) ? -1 :
243                     *(db_int8*)(p + offs) == *(db_int8*)(q + offs) ? 0 : 1;
244                 break;
245               case dbField::tpReference:
246                 diff = *(oid_t*)(p + offs) < *(oid_t*)(q + offs) ? -1 :
247                     *(oid_t*)(p + offs) == *(oid_t*)(q + offs) ? 0 : 1;
248                 break;
249               case dbField::tpReal4:
250                 diff = *(real4*)(p + offs) < *(real4*)(q + offs) ? -1 :
251                     *(real4*)(p + offs) == *(real4*)(q + offs) ? 0 : 1;
252                 break;
253               case dbField::tpReal8:
254                 diff = *(real8*)(p + offs) < *(real8*)(q + offs) ? -1 :
255                     *(real8*)(p + offs) == *(real8*)(q + offs) ? 0 : 1;
256                 break;
257               case dbField::tpString:
258 #ifdef USE_LOCALE_SETTINGS
259                 diff = STRCOLL((char_t*)(p + ((dbVarying*)(p + offs))->offs),
260                                (char_t*)(q + ((dbVarying*)(q + offs))->offs));
261 #else
262                 diff = STRCMP((char_t*)(p + ((dbVarying*)(p + offs))->offs),
263                               (char_t*)(q + ((dbVarying*)(q + offs))->offs));
264 #endif
265                 break;
266               case dbField::tpRawBinary:
267                 diff = order->field->comparator(p + offs, q + offs, order->field->dbsSize);
268                 break;
269               default:
270                 assert(false);
271             }
272         }
273         if (!order->ascent) {
274             diff = -diff;
275         }
276     } while (diff == 0 && (order = order->next) != NULL);
277 
278     return diff;
279 }
280 
281 struct dbSortContext {
282     dbDatabase*    db;
283     dbOrderByNode* order;
284 };
285 
packStrKey(byte * p,bool caseInsensitive)286 inline db_int8 packStrKey(byte* p, bool caseInsensitive)
287 {
288     char_t cnvBuf[8/sizeof(char_t) + 1];
289     if (caseInsensitive) {
290         size_t i;
291         for (i = 0; i < 8/sizeof(char_t) && *((char_t*)p + i) != 0; i++) {
292             cnvBuf[i] = TOLOWER(*((char_t*)p + i));
293         }
294         cnvBuf[i] = 0;
295         p = (byte*)cnvBuf;
296     }
297 #ifdef USE_LOCALE_SETTINGS
298     char_t buf[8/sizeof(char_t)];
299     STRXFRM(buf, (char_t*)p, itemsof(buf));
300     p = (byte*)buf;
301 #endif
302     db_int8 pkey = 0;
303     for (size_t i = 0; i < 8/sizeof(char_t) && *((char_t*)p + i) != 0; i++) {
304         char_t ch = *((char_t*)p + i);
305         pkey |= ((db_int8)ch & ((1 << sizeof(char_t)*8)-1))
306             << ((8/sizeof(char_t)-1-i)*8*sizeof(char_t));
307     }
308     // As far as signed comparison is used for packed key,
309     // and strcmp compares characters as unsign, we should make this
310     // correction
311     return pkey - ((db_int8)-1 << 63);
312 }
313 
cmpStrKey(void const * a,void const * b)314 static int __cdecl cmpStrKey(void const* a, void const* b)
315 {
316 #ifdef USE_LOCALE_SETTINGS
317     return STRCOLL(((dbSortRecord*)a)->u.strKey, ((dbSortRecord*)b)->u.strKey);
318 #else
319     return STRCMP(((dbSortRecord*)a)->u.strKey, ((dbSortRecord*)b)->u.strKey);
320 #endif
321 }
322 
cmpIntKey(void const * a,void const * b)323 static int __cdecl cmpIntKey(void const* a, void const* b)
324 {
325     return ((dbSortRecord*)a)->u.intKey < ((dbSortRecord*)b)->u.intKey ? -1
326         : ((dbSortRecord*)a)->u.intKey == ((dbSortRecord*)b)->u.intKey ? 0 : 1;
327 }
328 
cmpLongKey(void const * a,void const * b)329 static int __cdecl cmpLongKey(void const* a, void const* b)
330 {
331     return ((dbSortRecord*)a)->u.longKey < ((dbSortRecord*)b)->u.longKey ? -1
332         : ((dbSortRecord*)a)->u.longKey == ((dbSortRecord*)b)->u.longKey ? 0 : 1;
333 }
334 
cmpRealKey(void const * a,void const * b)335 static int __cdecl cmpRealKey(void const* a, void const* b)
336 {
337     return ((dbSortRecord*)a)->u.realKey < ((dbSortRecord*)b)->u.realKey ? -1
338         : ((dbSortRecord*)a)->u.realKey == ((dbSortRecord*)b)->u.realKey ? 0 : 1;
339 }
340 
cmpStrKeyDesc(void const * a,void const * b)341 static int __cdecl cmpStrKeyDesc(void const* a, void const* b)
342 {
343 #ifdef USE_LOCALE_SETTINGS
344     return -STRCOLL(((dbSortRecord*)a)->u.strKey, ((dbSortRecord*)b)->u.strKey);
345 #else
346     return -STRCMP(((dbSortRecord*)a)->u.strKey, ((dbSortRecord*)b)->u.strKey);
347 #endif
348 }
349 
cmpIntKeyDesc(void const * a,void const * b)350 static int __cdecl cmpIntKeyDesc(void const* a, void const* b)
351 {
352     return ((dbSortRecord*)a)->u.intKey > ((dbSortRecord*)b)->u.intKey ? -1
353         : ((dbSortRecord*)a)->u.intKey == ((dbSortRecord*)b)->u.intKey ? 0 : 1;
354 }
355 
cmpLongKeyDesc(void const * a,void const * b)356 static int __cdecl cmpLongKeyDesc(void const* a, void const* b)
357 {
358     return ((dbSortRecord*)a)->u.longKey > ((dbSortRecord*)b)->u.longKey ? -1
359         : ((dbSortRecord*)a)->u.longKey == ((dbSortRecord*)b)->u.longKey ? 0 : 1;
360 }
361 
cmpRealKeyDesc(void const * a,void const * b)362 static int __cdecl cmpRealKeyDesc(void const* a, void const* b)
363 {
364     return ((dbSortRecord*)a)->u.realKey > ((dbSortRecord*)b)->u.realKey ? -1
365         : ((dbSortRecord*)a)->u.realKey == ((dbSortRecord*)b)->u.realKey ? 0 : 1;
366 }
367 
368 
369 static dbThreadContext<dbSortContext> sortThreadContext;
370 
371 
exactKeyCmp(void const * a,void const * b)372 int __cdecl dbSelection::exactKeyCmp(void const* a, void const* b)
373 {
374     dbGetTie ta, tb;
375     dbSortContext* ctx = sortThreadContext.get();
376     return compare(((dbSortRecord*)a)->oid, ctx->db->getRow(ta, ((dbSortRecord*)a)->oid),
377                    ((dbSortRecord*)b)->oid, ctx->db->getRow(tb, ((dbSortRecord*)b)->oid),
378                    ctx->order);
379 }
380 
udtComparator(void const * a,void const * b)381 int __cdecl dbSelection::udtComparator(void const* a, void const* b)
382 {
383     dbSortContext* ctx = sortThreadContext.get();
384     int rc = ctx->order->field->comparator(((dbSortRecord*)a)->u.rawKey, ((dbSortRecord*)b)->u.rawKey,
385                                            ctx->order->field->dbsSize);
386     return ctx->order->ascent ? rc : -rc;
387 }
388 
toArray(oid_t * oids) const389 void dbSelection::toArray(oid_t* oids) const
390 {
391     segment const* seg = &first;
392     do {
393         for (int i = 0, n = (int)seg->nRows; i < n; i++) {
394             *oids++ = seg->rows[i];
395         }
396     } while ((seg = seg->next) != &first);
397 }
398 
compareOids(void const * a,void const * b)399 static int __cdecl compareOids(void const* a, void const* b)
400 {
401     return *(oid_t*)a < *(oid_t*)b ? -1 : *(oid_t*)a == *(oid_t*)b ? 0 : 1;
402 }
403 
404 
allocateBitmap(dbDatabase * db)405 void dbSelection::allocateBitmap(dbDatabase* db)
406 {
407     size_t size = (size_t)((db->currIndexSize + 31) / 32);
408     if (size > bitmapSize) {
409         delete[] bitmap;
410         bitmap = new int4[size];
411         bitmapSize = size;
412     }
413     memset(bitmap, 0, size*4);
414 }
415 
deallocateBitmap()416 void dbSelection::deallocateBitmap()
417 {
418     if (bitmap != NULL) {
419         delete[] bitmap;
420         bitmap = NULL;
421         bitmapSize = 0;
422     }
423 }
424 
merge(dbDatabase * db,dbSelection & selection)425 void dbSelection::merge(dbDatabase* db, dbSelection& selection)
426 {
427     size_t n1 = nRows, n2 = selection.nRows;
428     TRACE_MSG((STRLITERAL("Performing indexed merge of %d and %d rows\n"), n1, n2));
429     segment* dst = &first;
430     size_t n = 0, j = 0;
431 
432     if (n1 > buildSelectionBitmapThreshold || n2 > buildSelectionBitmapThreshold) {
433         allocateBitmap(db);
434         int4* bm = bitmap;
435         segment const* seg = &selection.first;
436         do {
437             for (size_t i = 0, sn = seg->nRows; i < sn; i++) {
438                 oid_t o = seg->rows[i];
439                 bm[(size_t)o >> 5] |= 1 << ((int)o & 31);
440             }
441         } while ((seg = seg->next) != &selection.first);
442 
443         seg = &first;
444         do {
445             for (size_t i = 0, sn = seg->nRows; i < sn; i++) {
446                 oid_t o = seg->rows[i];
447                 if (bm[(size_t)o >> 5] & (1 << ((int)o & 31))) {
448                     if (j == dst->nRows) {
449                         dst = dst->next;
450                         j = 0;
451                     }
452                     dst->rows[j++] = o;
453                     n += 1;
454                 }
455             }
456         } while ((seg = seg->next) != &first);
457     } else {
458         dbSmallBuffer<oid_t> buf2(n2);
459         dbSmallBuffer<oid_t> buf1(n1);
460         oid_t* refs1 = buf1.base();
461         oid_t* refs2 = buf2.base();
462         toArray(refs1);
463         selection.toArray(refs2);
464         qsort(refs1, nRows, sizeof(oid_t), &compareOids);
465         qsort(refs2, selection.nRows, sizeof(oid_t), &compareOids);
466         size_t i1 = 0, i2 = 0;
467 
468         while (true) {
469             if (i1 == n1 || i2 == n2) {
470                 break;
471             }
472             if (refs1[i1] > refs2[i2]) {
473                 i2 += 1;
474             } else if (refs1[i1] < refs2[i2]) {
475                 i1 += 1;
476             } else {
477                 if (j == dst->nRows) {
478                     dst = dst->next;
479                     j = 0;
480                 }
481                 n += 1;
482                 dst->rows[j++] = refs1[i1];
483                 i1 += 1;
484                 i2 += 1;
485             }
486         }
487     }
488     dst->nRows = j;
489     nRows = n;
490     segment* next = dst->next;
491     first.prev = dst;
492     dst->next = &first;
493     while (next != &first) {
494         dst = next;
495         next = dst->next;
496         delete dst;
497     }
498 }
499 
500 
sort(dbDatabase * db,dbOrderByNode * order,bool caseInsensitive,dbSortResult * sortResult)501 void dbSelection::sort(dbDatabase* db, dbOrderByNode* order, bool caseInsensitive, dbSortResult* sortResult)
502 {
503     int i = 0, j, k, n = (int)nRows;
504     dbSortRecord* keys = new dbSortRecord[n];
505     char* rawKeys = NULL;
506     segment* seg = &first;
507     bool partialOrder = false;
508 
509     TRACE_MSG((STRLITERAL("Sort %d records\n"), n));
510 
511     if (order->expr != NULL) {
512         dbSynthesizedAttribute result;
513         switch (order->expr->type) {
514           case tpReal:
515             do {
516                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
517                     db->evaluate(order->expr, seg->rows[j], order->table, result);
518                     keys[i].u.realKey = result.fvalue;
519                     keys[i].oid = seg->rows[j];
520                 }
521             } while ((seg = seg->next) != &first);
522             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpRealKey : cmpRealKeyDesc);
523             break;
524           case tpInteger:
525             do {
526                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
527                     db->evaluate(order->expr, seg->rows[j], order->table, result);
528                     keys[i].u.longKey = result.ivalue;
529                     keys[i].oid = seg->rows[j];
530                 }
531             } while ((seg = seg->next) != &first);
532             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpIntKey : cmpIntKeyDesc);
533             break;
534           case tpBoolean:
535             do {
536                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
537                     db->evaluate(order->expr, seg->rows[j], order->table, result);
538                     keys[i].u.intKey = result.bvalue;
539                     keys[i].oid = seg->rows[j];
540                 }
541             } while ((seg = seg->next) != &first);
542             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpIntKey : cmpIntKeyDesc);
543             break;
544           case tpReference:
545             do {
546                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
547                     db->evaluate(order->expr, seg->rows[j], order->table, result);
548                     keys[i].u.longKey = result.oid;
549                     keys[i].oid = seg->rows[j];
550                 }
551             } while ((seg = seg->next) != &first);
552             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpLongKey : cmpLongKeyDesc);
553             break;
554           case tpString:
555             if (sortResult != NULL) {
556                 do {
557                     for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
558                         char_t buf[dbBtreePage::dbMaxKeyLen];
559                         int len = (int)db->evaluateString(order->expr, seg->rows[j], order->table, buf, itemsof(buf));
560                         assert(len <= dbBtreePage::dbMaxKeyLen);
561                         keys[i].u.strKey = sortResult->strBuf.put(buf, len);
562                         if (caseInsensitive) {
563                             strlower(keys[i].u.strKey, keys[i].u.strKey);
564                         }
565                         keys[i].oid = seg->rows[j];
566                     }
567                 } while ((seg = seg->next) != &first);
568                 qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpStrKey : cmpStrKeyDesc);
569             } else {
570                 do {
571                     for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
572                         char_t buf[8/sizeof(char_t)];
573                         db->evaluateString(order->expr, seg->rows[j], order->table, buf, itemsof(buf));
574                         keys[i].u.longKey = packStrKey((byte*)buf, caseInsensitive);
575                         keys[i].oid = seg->rows[j];
576                     }
577                 } while ((seg = seg->next) != &first);
578                 qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpLongKey : cmpLongKeyDesc);
579                 partialOrder = true;
580             }
581             break;
582           default:
583             assert(false);
584         }
585     } else {
586         int offs = order->field->dbsOffs;
587         dbGetTie tie;
588         byte* p;
589 
590         memset(keys, 0, n*sizeof(dbSortRecord));
591 
592         switch (order->field->type) {
593           case dbField::tpBool:
594           case dbField::tpInt1:
595             do {
596                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
597                     p = (byte*)db->getRow(tie, seg->rows[j]);
598                     keys[i].u.intKey = *(int1*)(p + offs);
599                     keys[i].oid = seg->rows[j];
600                 }
601             } while ((seg = seg->next) != &first);
602             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpIntKey : cmpIntKeyDesc);
603             break;
604           case dbField::tpInt2:
605             do {
606                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
607                     p = (byte*)db->getRow(tie, seg->rows[j]);
608                     keys[i].u.intKey = *(int2*)(p + offs);
609                     keys[i].oid = seg->rows[j];
610                 }
611             } while ((seg = seg->next) != &first);
612             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpIntKey : cmpIntKeyDesc);
613             break;
614           case dbField::tpReal4:
615             do {
616                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
617                     p = (byte*)db->getRow(tie, seg->rows[j]);
618                     keys[i].u.realKey = *(float*)(p + offs);
619                     keys[i].oid = seg->rows[j];
620                 }
621             } while ((seg = seg->next) != &first);
622             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpRealKey : cmpRealKeyDesc);
623             break;
624           case dbField::tpInt4:
625           case dbField::tpArray:
626             do {
627                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
628                     p = (byte*)db->getRow(tie, seg->rows[j]);
629                     keys[i].u.intKey = *(int4*)(p + offs);
630                     keys[i].oid = seg->rows[j];
631                 }
632             } while ((seg = seg->next) != &first);
633             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpIntKey : cmpIntKeyDesc);
634             break;
635           case dbField::tpInt8:
636             do {
637                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
638                     p = (byte*)db->getRow(tie, seg->rows[j]);
639                     keys[i].u.longKey = *(db_int8*)(p + offs);
640                     keys[i].oid = seg->rows[j];
641                 }
642             } while ((seg = seg->next) != &first);
643             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpLongKey : cmpLongKeyDesc);
644             break;
645           case dbField::tpReference:
646             do {
647                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
648                     p = (byte*)db->getRow(tie, seg->rows[j]);
649                     keys[i].u.longKey = *(oid_t*)(p + offs);
650                     keys[i].oid = seg->rows[j];
651                 }
652             } while ((seg = seg->next) != &first);
653             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpLongKey : cmpLongKeyDesc);
654             break;
655           case dbField::tpReal8:
656             do {
657                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
658                     p = (byte*)db->getRow(tie, seg->rows[j]);
659                     keys[i].u.realKey = *(real8*)(p + offs);
660                     keys[i].oid = seg->rows[j];
661                 }
662             } while ((seg = seg->next) != &first);
663             qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpRealKey : cmpRealKeyDesc);
664             break;
665           case dbField::tpString:
666             if (sortResult != NULL) {
667                 do {
668                     for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
669                         byte* p = (byte*)db->getRow(tie, seg->rows[j]);
670                         keys[i].u.strKey = sortResult->strBuf.put((char_t*)(p + ((dbVarying*)(p + offs))->offs),
671                                                                   ((dbVarying*)(p + offs))->size-1);
672                         if (caseInsensitive) {
673                             strlower(keys[i].u.strKey, keys[i].u.strKey);
674                         }
675                         keys[i].oid = seg->rows[j];
676                     }
677                 } while ((seg = seg->next) != &first);
678                 qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpStrKey : cmpStrKeyDesc);
679             } else {
680                 do {
681                     for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
682                         byte* p = (byte*)db->getRow(tie, seg->rows[j]);
683                         keys[i].u.longKey = packStrKey(p + ((dbVarying*)(p + offs))->offs, caseInsensitive);
684                         keys[i].oid = seg->rows[j];
685                     }
686                 } while ((seg = seg->next) != &first);
687                 qsort(keys, n, sizeof(dbSortRecord), order->ascent ? cmpLongKey : cmpLongKeyDesc);
688                 partialOrder = true;
689             }
690             break;
691           case dbField::tpRawBinary:
692           {
693             int rawSize = (int)order->field->dbsSize;
694             rawKeys = new char[n*rawSize];
695             dbSortContext ctx;
696             ctx.db = db;
697             ctx.order = order;
698             sortThreadContext.set(&ctx);
699             do {
700                 for (j = 0, k = (int)seg->nRows; j < k; j++, i++) {
701                     p = (byte*)db->getRow(tie, seg->rows[j]);
702                     keys[i].oid = seg->rows[j];
703                     keys[i].u.rawKey = rawKeys + i*rawSize;
704                     memcpy(keys[i].u.rawKey, p + offs, rawSize);
705                 }
706             } while ((seg = seg->next) != &first);
707             qsort(keys, n, sizeof(dbSortRecord), udtComparator);
708             break;
709           }
710         default:
711           assert(false);
712         }
713     }
714     if (order->next != NULL || partialOrder) {
715         dbSortContext ctx;
716         ctx.db = db;
717         ctx.order = partialOrder ? order : order->next;
718         sortThreadContext.set(&ctx);
719         if (rawKeys != NULL) {
720             for (i = 0, k = 0; i < n; i = j) {
721                 for (j = i+1; j < n && order->field->comparator(keys[j].u.rawKey,
722                                                                 keys[i].u.rawKey,
723                                                                 order->field->dbsSize) == 0; j++);
724                 if (j > i + 1) {
725                     qsort(keys + i, j - i, sizeof(dbSortRecord), exactKeyCmp);
726                 }
727             }
728         } else {
729             for (i = 0, k = 0; i < n; i = j) {
730                 for (j = i+1; j < n && keys[j].u.longKey == keys[i].u.longKey; j++);
731                 if (j > i + 1) {
732                     qsort(keys + i, j - i, sizeof(dbSortRecord), exactKeyCmp);
733                 }
734             }
735         }
736     }
737     if (sortResult != NULL) {
738         sortResult->keys = keys;
739         sortResult->rawKeys = rawKeys;
740     } else {
741         if (n != 0) {
742             for (i = 0, j = 0, seg = &first, k = (int)seg->nRows; i < n; i++, j++) {
743                 if (j == k) {
744                     seg = seg->next;
745                     k = (int)seg->nRows;
746                     j = 0;
747                 }
748                 seg->rows[j] = keys[i].oid;
749             }
750         }
751         delete[] keys;
752         delete[] rawKeys;
753     }
754 }
755 
dbAnyCursor(dbTableDescriptor & aTable,dbCursorType aType,byte * rec)756 dbAnyCursor::dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec)
757 : table(&aTable),type(aType),defaultType(aType),
758   allRecords(false),currId(0),record(rec)
759 {
760     limit = dbDefaultSelectionLimit;
761     prefetch = rec != NULL;
762     removed = false;
763     eliminateDuplicates = false;
764     checkForDuplicatedIsEnabled = true;
765     db = aTable.db;
766     paramBase = NULL;
767     stmtLimitLen = dbDefaultSelectionLimit;
768     stmtLimitStart = 0;
769     nSkipped = 0;
770     iterator = NULL;
771 }
772 
dbAnyCursor(dbCursorType aType)773 dbAnyCursor::dbAnyCursor(dbCursorType aType)
774 : table(NULL),type(aType),defaultType(aType),
775   allRecords(false),currId(0),record(NULL)
776 {
777     limit = dbDefaultSelectionLimit;
778     prefetch = false;
779     removed = false;
780     eliminateDuplicates = false;
781     checkForDuplicatedIsEnabled = true;
782     db = NULL;
783     paramBase = NULL;
784     stmtLimitLen = dbDefaultSelectionLimit;
785     stmtLimitStart = 0;
786     nSkipped = 0;
787     iterator = NULL;
788 }
789 
select(dbQuery & query,dbCursorType aType,void * paramStruct)790 cardinality_t dbAnyCursor::select(dbQuery& query, dbCursorType aType, void* paramStruct)
791 {
792     paramBase = paramStruct;
793     type = aType;
794     reset();
795     db->select(this, query);
796     paramBase = NULL;
797     if (gotoFirst() && prefetch) {
798         fetch();
799     }
800     if (aType == dbCursorDetached) {
801         unlink();
802         db->commit();
803     }
804     return selection.nRows;
805 }
806 
toArrayOfOid(oid_t * arr) const807 oid_t* dbAnyCursor::toArrayOfOid(oid_t* arr) const
808 {
809     assert(iterator == NULL); // do not use incremental cursor if you need to get array of OIDs
810     if (arr == NULL) {
811         arr = new oid_t[selection.nRows];
812     }
813     if (allRecords) {
814         dbRecord rec;
815         oid_t* oids = arr;
816         for (oid_t oid = firstId; oid != 0; oid = rec.next) {
817              db->getHeader(rec, oid);
818              *oids++ = oid;
819         }
820     } else {
821         selection.toArray(arr);
822     }
823     return arr;
824 }
setCurrent(dbAnyReference const & ref)825 void dbAnyCursor::setCurrent(dbAnyReference const& ref)
826 {
827     removed = false;
828     assert(ref.oid != 0);
829     reset();
830     db->beginTransaction(type == dbCursorForUpdate ? dbUpdateLock : dbSharedLock);
831     db->threadContext.get()->cursors.link(this);
832     currId = ref.oid;
833     selection.first.nRows = 1;
834     selection.first.rows[0] = currId;
835     selection.nRows = 1;
836     if (prefetch) {
837         fetch();
838     }
839 }
840 
selectByKey(char_t const * key,void const * value)841 cardinality_t dbAnyCursor::selectByKey(char_t const* key, void const* value)
842 {
843     dbFieldDescriptor* field = table->find(key);
844     assert(field != NULL);
845     return selectByKey(field, value);
846 }
847 
selectByKey(dbFieldDescriptor * field,void const * value)848 cardinality_t dbAnyCursor::selectByKey(dbFieldDescriptor* field, void const* value)
849 {
850     assert(field->hashTable != 0 || field->bTree != 0);
851     reset();
852     db->beginTransaction(type == dbCursorForUpdate ? dbUpdateLock : dbSharedLock);
853     db->threadContext.get()->cursors.link(this);
854     dbSearchContext sc;
855     sc.db = db;
856     sc.probes = 0;
857     sc.ascent = true;
858     sc.offs = field->dbsOffs;
859     sc.cursor = this;
860     sc.tmpKeys = false;
861     sc.condition = NULL;
862     sc.prefixLength = 0;
863     sc.spatialSearch = false;
864     sc.arraySearch = false;
865     sc.firstKey = sc.lastKey = (char_t*)value;
866     sc.firstKeyInclusion = sc.lastKeyInclusion = true;
867     if (type == dbCursorIncremental) {
868         btreeIterator.init(db, field->bTree, sc, field->comparator);
869         iterator = &btreeIterator;
870     } else {
871         dbBtree::find(db, field->bTree, sc, field->comparator);
872     }
873     if (gotoFirst() && prefetch) {
874         fetch();
875     }
876     return selection.nRows;
877 }
878 
seek(oid_t oid)879 int dbAnyCursor::seek(oid_t oid)
880 {
881     int pos = 0;
882     if (gotoFirst()) {
883         do {
884             if (currId == oid) {
885                 if (prefetch) {
886                     fetch();
887                 }
888                 return pos;
889             }
890             pos += 1;
891         } while (gotoNext());
892     }
893     return -1;
894 }
895 
skip(int n)896 bool dbAnyCursor::skip(int n) {
897     while (n > 0) {
898         if (!gotoNext()) {
899             return false;
900         }
901         n -= 1;
902     }
903     while (n < 0) {
904         if (!gotoPrev()) {
905             return false;
906         }
907         n += 1;
908     }
909     if (prefetch) {
910         fetch();
911     }
912     return true;
913 }
914 
selectByKeyRange(char_t const * key,void const * minValue,void const * maxValue,bool ascent)915 cardinality_t dbAnyCursor::selectByKeyRange(char_t const* key, void const* minValue,
916                                   void const* maxValue, bool ascent)
917 {
918     dbFieldDescriptor* field = table->find(key);
919     assert(field != NULL);
920     return selectByKeyRange(field, minValue, maxValue, ascent);
921 }
922 
selectByKeyRange(dbFieldDescriptor * field,void const * minValue,void const * maxValue,bool ascent)923 cardinality_t dbAnyCursor::selectByKeyRange(dbFieldDescriptor* field, void const* minValue,
924                                   void const* maxValue, bool ascent)
925 {
926     assert(field->bTree != 0);
927     reset();
928     db->beginTransaction(type == dbCursorForUpdate ? dbUpdateLock : dbSharedLock);
929     db->threadContext.get()->cursors.link(this);
930     dbSearchContext sc;
931     sc.db = db;
932     sc.probes = 0;
933     sc.offs = field->dbsOffs;
934     sc.cursor = this;
935     sc.tmpKeys = false;
936     sc.ascent = ascent;
937     sc.condition = NULL;
938     sc.prefixLength = 0;
939     sc.firstKey = (char_t*)minValue;
940     sc.lastKey = (char_t*)maxValue;
941     sc.firstKeyInclusion = sc.lastKeyInclusion = true;
942     sc.spatialSearch = false;
943     sc.arraySearch = false;
944     if (type == dbCursorIncremental) {
945         btreeIterator.init(db, field->bTree, sc, field->comparator);
946         iterator = &btreeIterator;
947     } else {
948         dbBtree::find(db, field->bTree, sc, field->comparator);
949     }
950     if (gotoFirst() && prefetch) {
951         fetch();
952     }
953     return selection.nRows;
954 }
955 
remove()956 void dbAnyCursor::remove()
957 {
958     oid_t removedId = currId;
959     lastRecordWasDeleted = false;
960     if (type != dbCursorForUpdate) {
961         db->handleError(dbDatabase::CursorError, "Readonly cursor");
962     }
963     if (removedId == 0) {
964         db->handleError(dbDatabase::CursorError, "No current record");
965     }
966     if (allRecords) {
967         dbRecord rec;
968         db->getHeader(rec, removedId);
969         if (rec.next != 0) {
970             if (removedId == firstId) {
971                 firstId = currId = rec.next;
972             } else {
973                 currId = rec.next;
974             }
975         } else {
976             lastRecordWasDeleted = true;
977             if (removedId == firstId) {
978                 firstId = lastId = currId = 0;
979             } else {
980                 lastId = currId = rec.prev;
981             }
982         }
983     } else {
984         if (selection.curr != NULL) {
985             if (--selection.curr->nRows == 0 || selection.pos == selection.curr->nRows) {
986                 dbSelection::segment* s = selection.curr, *next= s->next;;
987                 if (selection.curr->nRows == 0 && s != &selection.first) {
988                     delete s;
989                 }
990                 if (next != &selection.first) {
991                     selection.curr = next;
992                     selection.pos = 0;
993                 } else {
994                     lastRecordWasDeleted = true;
995                     selection.curr = next->prev;
996                     selection.pos = selection.curr->nRows-1;
997                 }
998                 if (selection.curr->nRows != 0) {
999                     currId = selection.curr->rows[selection.pos];
1000                 } else {
1001                     currId = 0;
1002                 }
1003             } else {
1004                 memcpy(selection.curr->rows + selection.pos,
1005                        selection.curr->rows + selection.pos + 1,
1006                        (selection.curr->nRows - selection.pos)
1007                        *sizeof(oid_t));
1008                 currId = selection.curr->rows[selection.pos];
1009             }
1010         } else {
1011             currId = 0;
1012         }
1013     }
1014     byte* saveRecord = record;
1015     record = NULL;
1016     db->remove(table, removedId);
1017     record = saveRecord;
1018     removed = true;
1019     if (currId != 0 && prefetch) {
1020         fetch();
1021     }
1022 }
1023 
1024 
removeAllSelected()1025 void dbAnyCursor::removeAllSelected()
1026 {
1027     if (type != dbCursorForUpdate) {
1028         db->handleError(dbDatabase::CursorError, "Readonly cursor");
1029     }
1030     byte* saveRecord = record;
1031     record = NULL;
1032     if (allRecords) {
1033         removeAll();
1034     } else if (selection.nRows != 0) {
1035         dbSelection::segment* curr = &selection.first;
1036         currId = 0;
1037         do {
1038             for (int i = 0, n = (int)curr->nRows; i < n; i++) {
1039                 db->remove(table, curr->rows[i]);
1040             }
1041         } while ((curr = curr->next) != &selection.first);
1042         reset();
1043     } else if (currId != 0) {
1044         db->remove(table, currId);
1045         currId = 0;
1046     }
1047     record = saveRecord;
1048 }
1049 
isLast() const1050 bool dbAnyCursor::isLast() const
1051 {
1052     if (iterator != NULL) {
1053         if (currId != 0) {
1054             if (!iterator->next()) {
1055                 return true;
1056             }
1057             iterator->prev();
1058         }
1059     } else if (allRecords) {
1060         if (currId != 0) {
1061             dbRecord rec;
1062             db->getHeader(rec, currId);
1063             return rec.next == 0;
1064         }
1065     } else if (selection.curr != NULL) {
1066         return selection.pos+1 == selection.curr->nRows
1067             && selection.curr->next == &selection.first;
1068     }
1069     return false;
1070 }
1071 
1072 
isFirst() const1073 bool dbAnyCursor::isFirst() const
1074 {
1075     if (iterator != NULL) {
1076         if (currId != 0) {
1077             if (!iterator->prev()) {
1078                 return true;
1079             }
1080             iterator->next();
1081         }
1082     } else if (allRecords) {
1083         if (currId != 0) {
1084             dbRecord rec;
1085             db->getHeader(rec, currId);
1086             return rec.prev == 0;
1087         }
1088     } else if (selection.curr != NULL) {
1089         return selection.pos == 0 && selection.curr == &selection.first;
1090     }
1091     return false;
1092 }
1093 
1094 
hasNext() const1095 bool dbAnyCursor::hasNext() const
1096 {
1097     if (iterator != NULL) {
1098         if (currId != 0 && iterator->next()) {
1099             iterator->prev();
1100             return true;
1101         }
1102     } else if (allRecords) {
1103         if (currId != 0) {
1104             dbRecord rec;
1105             db->getHeader(rec, currId);
1106             return rec.next != 0;
1107         }
1108     } else if (selection.curr != NULL
1109                && (selection.pos+1 < selection.curr->nRows || selection.curr->next != &selection.first))
1110     {
1111         return true;
1112     }
1113     return false;
1114 }
1115 
fetchNext()1116 byte* dbAnyCursor::fetchNext()
1117 {
1118     byte* result = NULL;
1119     if (type == dbCursorDetached) {
1120         db->beginTransaction(dbSharedLock);
1121         db->threadContext.get()->cursors.link(this);
1122         assert(!removed);
1123         while (gotoNext()) {
1124             if (db->isValidOid(currId)) {
1125                 fetch();
1126                 result = record;
1127                 break;
1128             }
1129         }
1130         unlink();
1131         db->commit();
1132     } else {
1133         if (!removed) {
1134             if (gotoNext()) {
1135                 fetch();
1136                 result = record;
1137             }
1138         } else {
1139             removed = false;
1140             if (currId != 0 && !lastRecordWasDeleted) {
1141                 if (!prefetch) {
1142                     fetch();
1143                 }
1144                 result = record;
1145             }
1146         }
1147     }
1148     return result;
1149 }
1150 
fetchPrev()1151 byte* dbAnyCursor::fetchPrev()
1152 {
1153     if (type == dbCursorDetached) {
1154         db->beginTransaction(dbSharedLock);
1155         db->threadContext.get()->cursors.link(this);
1156         assert(!removed);
1157         byte* result = NULL;
1158         while (gotoPrev()) {
1159             if (db->isValidOid(currId)) {
1160                 fetch();
1161                 result = record;
1162                 break;
1163             }
1164         }
1165         unlink();
1166         db->commit();
1167         return result;
1168     } else {
1169         if (removed) {
1170             removed = false;
1171             if (lastRecordWasDeleted) {
1172                 if (currId != 0) {
1173                     if (!prefetch) {
1174                         fetch();
1175                     }
1176                     return record;
1177                 }
1178                 return NULL;
1179             }
1180         }
1181         if (gotoPrev()) {
1182             fetch();
1183             return record;
1184         }
1185         return NULL;
1186     }
1187 }
1188 
fetchFirst()1189 byte* dbAnyCursor::fetchFirst()
1190 {
1191     byte* result = NULL;
1192 
1193     if (type == dbCursorDetached) {
1194         db->beginTransaction(dbSharedLock);
1195         db->threadContext.get()->cursors.link(this);
1196 
1197         if (gotoFirst()) {
1198             do {
1199                 if (db->isValidOid(currId)) {
1200                     fetch();
1201                     result = record;
1202                     break;
1203                 }
1204             } while (gotoNext());
1205         }
1206         unlink();
1207         db->commit();
1208     } else {
1209         if (gotoFirst()) {
1210             fetch();
1211             result = record;
1212         }
1213     }
1214     return result;
1215 }
1216 
fetchLast()1217 byte* dbAnyCursor::fetchLast()
1218 {
1219     byte* result = NULL;
1220 
1221     if (type == dbCursorDetached) {
1222         db->beginTransaction(dbSharedLock);
1223         db->threadContext.get()->cursors.link(this);
1224 
1225         if (gotoLast()) {
1226             do {
1227                 if (db->isValidOid(currId)) {
1228                     fetch();
1229                     result = record;
1230                     break;
1231                 }
1232             } while (gotoPrev());
1233         }
1234         unlink();
1235         db->commit();
1236     } else {
1237         if (gotoLast()) {
1238             fetch();
1239             result = record;
1240         }
1241     }
1242     return result;
1243 }
1244 
1245 
gotoNext()1246 bool dbAnyCursor::gotoNext()
1247 {
1248     if (iterator != NULL) {
1249         oid_t next = iterator->next();
1250         if (next != 0) {
1251             currId = next;
1252             return true;
1253         }
1254         return false;
1255     }
1256     removed = false;
1257     if (allRecords) {
1258         if (currId != 0) {
1259             dbRecord rec;
1260             db->getHeader(rec, currId);
1261             if (rec.next != 0) {
1262                 currId = rec.next;
1263                 return true;
1264             }
1265         }
1266     } else if (selection.curr != NULL) {
1267         if (++selection.pos == selection.curr->nRows) {
1268             if (selection.curr->next == &selection.first) {
1269                 selection.pos -= 1;
1270                 return false;
1271             }
1272             selection.pos = 0;
1273             selection.curr = selection.curr->next;
1274         }
1275         currId = selection.curr->rows[selection.pos];
1276         return true;
1277     }
1278     return false;
1279 }
1280 
gotoPrev()1281 bool dbAnyCursor::gotoPrev()
1282 {
1283     if (iterator != NULL) {
1284         oid_t prev = iterator->prev();
1285         if (prev != 0) {
1286             currId = prev;
1287             return true;
1288         }
1289         return false;
1290     }
1291     removed = false;
1292     if (allRecords) {
1293         if (currId != 0) {
1294             dbRecord rec;
1295             db->getHeader(rec, currId);
1296             if (rec.prev != 0) {
1297                 currId = rec.prev;
1298                 return true;
1299             }
1300         }
1301     } else if (selection.curr != NULL) {
1302         if (selection.pos == 0) {
1303             if (selection.curr == &selection.first || selection.curr->prev->nRows == 0) {
1304                 return false;
1305             }
1306             selection.curr = selection.curr->prev;
1307             selection.pos = selection.curr->nRows;
1308         }
1309         currId = selection.curr->rows[--selection.pos];
1310         return true;
1311     }
1312     return false;
1313 }
1314 
1315 
moveNext()1316 bool dbAnyCursor::moveNext()
1317 {
1318     if (!removed) {
1319         return gotoNext();
1320     } else {
1321         removed = false;
1322         return !lastRecordWasDeleted;
1323     }
1324 }
1325 
movePrev()1326 bool dbAnyCursor::movePrev()
1327 {
1328     if (!removed) {
1329         return gotoPrev();
1330     } else {
1331         removed = false;
1332         return lastRecordWasDeleted ? (currId != 0) : gotoPrev();
1333     }
1334 }
1335 
gotoFirst()1336 bool dbAnyCursor::gotoFirst()
1337 {
1338     if (iterator != NULL) {
1339         if ((currId = iterator->first()) != 0) {
1340             selection.nRows = 1;
1341             return true;
1342         }
1343         return false;
1344     }
1345     removed = false;
1346     if (allRecords) {
1347         currId = firstId;
1348         return (currId != 0);
1349     } else {
1350         selection.curr = selection.first.nRows == 0 ? selection.first.next : &selection.first;
1351         selection.pos = 0;
1352         if (selection.curr->nRows == 0) {
1353             return (currId != 0);
1354         } else {
1355             currId = selection.curr->rows[0];
1356             return true;
1357         }
1358     }
1359 }
1360 
gotoLast()1361 bool dbAnyCursor::gotoLast()
1362 {
1363     if (iterator != NULL) {
1364         return (currId = iterator->last()) != 0;
1365     }
1366     removed = false;
1367     if (allRecords) {
1368         currId = lastId;
1369         return (currId != 0);
1370     } else {
1371         selection.curr = selection.first.prev;
1372         if (selection.curr->nRows == 0) {
1373             return (currId != 0);
1374         } else {
1375             selection.pos = selection.curr->nRows-1;
1376             currId = selection.curr->rows[selection.pos];
1377             return true;
1378         }
1379     }
1380 }
1381 
isInSelection(oid_t oid)1382 bool dbAnyCursor::isInSelection(oid_t oid)
1383 {
1384     assert(iterator == NULL);
1385     if (eliminateDuplicates) {
1386         return isMarked(oid);
1387     } else if (selection.nRows > dbSelection::buildSelectionBitmapThreshold) {
1388         checkForDuplicates();
1389         dbSelection::segment* curr = &selection.first;
1390         do {
1391             for (int i = 0, n = (int)curr->nRows; i < n; i++) {
1392                 oid_t o = curr->rows[i];
1393                 selection.bitmap[(size_t)o >> 5] |= 1 << ((int)o & 31);
1394             }
1395         } while ((curr = curr->next) != &selection.first);
1396         return isMarked(oid);
1397     } else {
1398         dbSelection::segment* curr = &selection.first;
1399         do {
1400             for (int i = 0, n = (int)curr->nRows; i < n; i++) {
1401                 if (curr->rows[i] == oid) {
1402                     return true;
1403                 }
1404             }
1405         } while ((curr = curr->next) != &selection.first);
1406         return false;
1407     }
1408 }
1409 
reset()1410 void dbAnyCursor::reset()
1411 {
1412     if (db == NULL) {
1413         db = table->db;
1414         assert(((void)"cursor associated with online database table",
1415                 table->tableId != 0));
1416     } else if (table->db != db) {
1417         table = db->lookupTable(table);
1418     }
1419     unlink();
1420     selection.reset();
1421     eliminateDuplicates = false;
1422     allRecords = false;
1423     removed = false;
1424     currId = 0;
1425     tie.reset();
1426     stmtLimitLen = dbDefaultSelectionLimit;
1427     stmtLimitStart = 0;
1428     nSkipped = 0;
1429     iterator = NULL;
1430 }
1431 
freeze()1432 void dbAnyCursor::freeze()
1433 {
1434     assert(type != dbCursorIncremental && type != dbCursorDetached);
1435     unlink();
1436     tie.reset();
1437 }
1438 
unfreeze()1439 void dbAnyCursor::unfreeze()
1440 {
1441     db->beginTransaction(type == dbCursorForUpdate ? dbUpdateLock : dbSharedLock);
1442     db->threadContext.get()->cursors.link(this);
1443     if (currId != 0 && prefetch) {
1444         fetch();
1445     }
1446 }
1447 
~dbAnyCursor()1448 dbAnyCursor::~dbAnyCursor()
1449 {
1450     selection.reset();
1451 }
1452 
search(int i)1453 void dbParallelQueryContext::search(int i)
1454 {
1455     int nThreads = db->parThreads;
1456     oid_t oid = firstRow;
1457     dbRecord rec;
1458     int j;
1459     for (j = i; --j >= 0;) {
1460         db->getHeader(rec, oid);
1461         oid = rec.next;
1462     }
1463     while (oid != 0) {
1464         if (db->evaluateBoolean(query->tree, oid, table, cursor)) {
1465             selection[i].add(oid);
1466         }
1467         db->getHeader(rec, oid);
1468         oid = rec.next;
1469         for (j = nThreads; --j > 0 && oid != 0;) {
1470             db->getHeader(rec, oid);
1471             oid = rec.next;
1472         }
1473     }
1474     if (query->order != NULL) {
1475         selection[i].sort(db, query->order);
1476     }
1477 }
1478 
1479 END_GIGABASE_NAMESPACE
1480 
1481 
1482 
1483 
1484 
1485 
1486 
1487