00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __CURSOR_H__
00012 #define __CURSOR_H__
00013
00014 BEGIN_GIGABASE_NAMESPACE
00015
00016 #include "selection.h"
00017 #include "btree.h"
00018 #include "rtree.h"
00019
00020 enum dbCursorType {
00021 dbCursorViewOnly,
00022 dbCursorForUpdate
00023 };
00024
00028 class dbTableIterator : public dbAbstractIterator {
00029 dbAnyCursor* cursor;
00030 dbExprNode* filter;
00031 oid_t curr;
00032
00033 public:
00034 void init(dbAnyCursor* cursor, dbExprNode* filter) {
00035 this->cursor = cursor;
00036 this->filter = filter;
00037 curr = 0;
00038 }
00039
00040 virtual oid_t next();
00041 virtual oid_t prev();
00042 virtual oid_t first();
00043 virtual oid_t last();
00044 };
00045
00046
00047
00051 class GIGABASE_DLL_ENTRY dbAnyCursor : public dbL2List {
00052 friend class dbDatabase;
00053 friend class dbHashTable;
00054 friend class dbRtreePage;
00055 friend class dbBtreePage;
00056 friend class dbRtreeIterator;
00057 friend class dbBtreeIterator;
00058 friend class dbTableIterator;
00059 friend class dbThickBtreePage;
00060 friend class dbSubSql;
00061 friend class dbStatement;
00062 friend class dbServer;
00063 friend class dbAnyContainer;
00064 friend class dbCLI;
00065 friend class JniResultSet;
00066 public:
00071 int getNumberOfRecords() const { return (int)selection.nRows; }
00072
00076 void remove();
00077
00082 bool isEmpty() const {
00083 return currId == 0;
00084 }
00085
00090 bool isUpdateCursor() const {
00091 return type == dbCursorForUpdate;
00092 }
00093
00098 bool isLimitReached() const {
00099 return selection.nRows >= limit || selection.nRows >= stmtLimitLen;
00100 }
00101
00112 int select(dbQuery& query, dbCursorType aType, void* paramStruct = NULL) {
00113 paramBase = paramStruct;
00114 type = aType;
00115 reset();
00116 db->select(this, query);
00117 paramBase = NULL;
00118 if (gotoFirst() && prefetch) {
00119 fetch();
00120 }
00121 return (int)selection.nRows;
00122 }
00123
00131 oid_t* toArrayOfOid(oid_t* arr) const;
00132
00139 int select(dbQuery& query, void* paramStruct = NULL) {
00140 return select(query, defaultType, paramStruct);
00141 }
00142
00150 int select(char_t const* condition, dbCursorType aType, void* paramStruct = NULL) {
00151 dbQuery query(condition);
00152 return select(query, aType, paramStruct);
00153 }
00154
00161 int select(char_t const* condition, void* paramStruct = NULL) {
00162 return select(condition, defaultType, paramStruct);
00163 }
00164
00170 int select(dbCursorType aType) {
00171 type = aType;
00172 reset();
00173 db->select(this);
00174 if (gotoFirst() && prefetch) {
00175 fetch();
00176 }
00177 return (int)selection.nRows;
00178 }
00179
00184 int select() {
00185 return select(defaultType);
00186 }
00187
00194 int selectByKey(char_t const* key, void const* value);
00195
00204 int selectByKeyRange(char_t const* key, void const* minValue, void const* maxValue, bool ascent = true);
00205
00210 void update() {
00211 assert(type == dbCursorForUpdate && currId != 0);
00212 db->update(currId, table, record);
00213 }
00214
00218 void removeAll() {
00219 assert(db != NULL);
00220 reset();
00221 db->deleteTable(table);
00222 }
00223
00227 void removeAllSelected();
00228
00232 void setSelectionLimit(size_t lim) { limit = lim; }
00233
00237 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00238
00245 void setPrefetchMode(bool mode) { prefetch = mode; }
00246
00255 bool setIncrementalHint(bool inc) {
00256 bool prev = inc;
00257 assert(!inc || type != dbCursorForUpdate);
00258 incremental = inc;
00259 return prev;
00260 }
00261
00271 bool isIncremental() {
00272 return iterator != NULL;
00273 }
00274
00278 void reset();
00279
00284 bool isLast() const;
00285
00290 bool isFirst() const;
00291
00297 void freeze();
00298
00302 void unfreeze();
00303
00311 bool skip(int n);
00312
00318 int seek(oid_t oid);
00319
00324 dbTableDescriptor* getTable() { return table; }
00325
00326
00331 bool isInSelection(oid_t oid);
00332
00337 void fetch() {
00338 table->columns->fetchRecordFields(record,
00339 (byte*)db->getRow(tie, currId));
00340 }
00341
00345 bool hasNext() const;
00346
00350 bool hasCurrent() const {
00351 return currId != 0;
00352 }
00353
00354
00355 protected:
00356 dbDatabase* db;
00357 dbTableDescriptor* table;
00358 dbCursorType type;
00359 dbCursorType defaultType;
00360 dbSelection selection;
00361 bool allRecords;
00362 oid_t firstId;
00363 oid_t lastId;
00364 oid_t currId;
00365 byte* record;
00366 size_t limit;
00367 dbGetTie tie;
00368 void* paramBase;
00369
00370 int4* bitmap;
00371 size_t bitmapSize;
00372 bool eliminateDuplicates;
00373 bool prefetch;
00374 bool removed;
00375 bool incremental;
00376
00377 size_t stmtLimitStart;
00378 size_t stmtLimitLen;
00379 size_t nSkipped;
00380
00381 dbAbstractIterator*iterator;
00382 dbBtreeIterator btreeIterator;
00383 dbRtreeIterator rtreeIterator;
00384 dbTableIterator tableIterator;
00385
00386 void allocateBitmap();
00387
00388 void checkForDuplicates() {
00389 if (!eliminateDuplicates && limit > 1) {
00390 allocateBitmap();
00391 }
00392 }
00393
00394 bool isMarked(oid_t oid) {
00395 return bitmap != NULL && (bitmap[oid >> 5] & (1 << (oid & 31))) != 0;
00396 }
00397
00398 void mark(oid_t oid) {
00399 if (bitmap != NULL) {
00400 bitmap[oid >> 5] |= 1 << (oid & 31);
00401 }
00402 }
00403
00404 void setStatementLimit(dbQuery const& q) {
00405 stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00406 stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00407 }
00408
00409 void truncateSelection() {
00410 selection.truncate(stmtLimitStart, stmtLimitLen);
00411 }
00412
00413 bool add(oid_t oid) {
00414 if (selection.nRows < limit && selection.nRows < stmtLimitLen) {
00415 if (nSkipped < stmtLimitStart) {
00416 nSkipped += 1;
00417 return true;
00418 }
00419 if (eliminateDuplicates) {
00420 if (bitmap[oid >> 5] & (1 << (oid & 31))) {
00421 return true;
00422 }
00423 bitmap[oid >> 5] |= 1 << (oid & 31);
00424 }
00425 selection.add(oid);
00426 return selection.nRows < limit;
00427 }
00428 return false;
00429 }
00430
00431 bool gotoNext();
00432 bool gotoPrev();
00433 bool gotoFirst();
00434 bool gotoLast();
00435
00436 void setCurrent(dbAnyReference const& ref);
00437
00438 void setTable(dbTableDescriptor* aTable) {
00439 table = aTable;
00440 db = aTable->db;
00441 }
00442
00443 void setRecord(void* rec) {
00444 record = (byte*)rec;
00445 }
00446
00447 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec);
00448
00449 public:
00450 dbAnyCursor();
00451 ~dbAnyCursor();
00452 };
00453
00457 template<class T>
00458 class dbCursor : public dbAnyCursor {
00459 protected:
00460 T record;
00461
00462 public:
00467 dbCursor(dbCursorType type = dbCursorViewOnly)
00468 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00469
00476 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00477 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00478 {
00479 db = aDb;
00480 dbTableDescriptor* theTable = db->lookupTable(table);
00481 if (theTable != NULL) {
00482 table = theTable;
00483 }
00484 }
00485
00490 T* get() {
00491 return currId == 0 ? (T*)NULL : &record;
00492 }
00493
00498 T* next() {
00499 if (gotoNext()) {
00500 fetch();
00501 return &record;
00502 }
00503 return NULL;
00504 }
00505
00510 T* prev() {
00511 if (gotoPrev()) {
00512 fetch();
00513 return &record;
00514 }
00515 return NULL;
00516 }
00517
00522 T* first() {
00523 if (gotoFirst()) {
00524 fetch();
00525 return &record;
00526 }
00527 return NULL;
00528 }
00529
00534 T* last() {
00535 if (gotoLast()) {
00536 fetch();
00537 return &record;
00538 }
00539 return NULL;
00540 }
00541
00547 int seek(dbReference<T> const& ref) {
00548 return dbAnyCursor::seek(ref.getOid());
00549 }
00550
00555 T* operator ->() {
00556 assert(currId != 0);
00557 return &record;
00558 }
00559
00565 T* at(dbReference<T> const& ref) {
00566 setCurrent(ref);
00567 return &record;
00568 }
00569
00574 dbReference<T> currentId() const {
00575 return dbReference<T>(currId);
00576 }
00577
00582 void toArray(dbArray< dbReference<T> >& arr) const {
00583 arr.resize(selection.nRows);
00584 toArrayOfOid((oid_t*)arr.base());
00585 }
00586
00603 T* nextAvailable() {
00604 if (!removed) {
00605 return next();
00606 } else {
00607 removed = false;
00608 return get();
00609 }
00610 }
00611
00616 bool isInSelection(dbReference<T>& ref) {
00617 return dbAnyCursor::isInSelection(ref.getOid());
00618 }
00619 };
00620
00621 class dbParallelQueryContext {
00622 public:
00623 dbDatabase* const db;
00624 dbCompiledQuery* const query;
00625 dbAnyCursor* cursor;
00626 oid_t firstRow;
00627 dbTableDescriptor* table;
00628 dbSelection selection[dbMaxParallelSearchThreads];
00629
00630 void search(int i);
00631
00632 dbParallelQueryContext(dbDatabase* aDb, dbTableDescriptor* desc,
00633 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00634 : db(aDb), query(aQuery), cursor(aCursor), firstRow(desc->firstRow), table(desc) {}
00635 };
00636
00637 END_GIGABASE_NAMESPACE
00638
00639 #endif