00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __CURSOR_H__
00012 #define __CURSOR_H__
00013
00014 #include "btree.h"
00015 #include "rtree.h"
00016
00017 BEGIN_GIGABASE_NAMESPACE
00018
00019 #include "selection.h"
00020
00021 enum dbCursorType {
00022 dbCursorViewOnly,
00023 dbCursorForUpdate,
00027 dbCursorIncremental,
00036 dbCursorDetached
00037 };
00038
00042 class dbTableIterator : public dbAbstractIterator {
00043 dbAnyCursor* cursor;
00044 dbExprNode* filter;
00045 oid_t curr;
00046
00047 public:
00048 void init(dbAnyCursor* cursor, dbExprNode* filter) {
00049 this->cursor = cursor;
00050 this->filter = filter;
00051 curr = 0;
00052 }
00053
00054 virtual oid_t next();
00055 virtual oid_t prev();
00056 virtual oid_t first();
00057 virtual oid_t last();
00058 };
00059
00060
00061
00065 class GIGABASE_DLL_ENTRY dbAnyCursor : public dbL2List {
00066 friend class dbDatabase;
00067 friend class dbHashTable;
00068 friend class dbRtreePage;
00069 friend class dbBtreePage;
00070 friend class dbRtreeIterator;
00071 friend class dbBtreeIterator;
00072 friend class dbTableIterator;
00073 friend class dbThickBtreePage;
00074 friend class dbSubSql;
00075 friend class dbStatement;
00076 friend class dbServer;
00077 friend class dbAnyContainer;
00078 friend class dbCLI;
00079 friend class JniResultSet;
00080 public:
00085 int getNumberOfRecords() const { return (int)selection.nRows; }
00086
00090 void remove();
00091
00096 bool isEmpty() const {
00097 return currId == 0;
00098 }
00099
00104 bool isUpdateCursor() const {
00105 return type == dbCursorForUpdate;
00106 }
00107
00112 bool isLimitReached() const {
00113 return selection.nRows >= limit || selection.nRows >= stmtLimitLen;
00114 }
00115
00126 int select(dbQuery& query, dbCursorType aType, void* paramStruct = NULL);
00127
00135 oid_t* toArrayOfOid(oid_t* arr) const;
00136
00143 int select(dbQuery& query, void* paramStruct = NULL) {
00144 return select(query, defaultType, paramStruct);
00145 }
00146
00154 int select(char_t const* condition, dbCursorType aType, void* paramStruct = NULL) {
00155 dbQuery query(condition);
00156 return select(query, aType, paramStruct);
00157 }
00158
00165 int select(char_t const* condition, void* paramStruct = NULL) {
00166 return select(condition, defaultType, paramStruct);
00167 }
00168
00174 int select(dbCursorType aType) {
00175 type = aType;
00176 reset();
00177 db->select(this);
00178 if (gotoFirst() && prefetch) {
00179 fetch();
00180 }
00181 return (int)selection.nRows;
00182 }
00183
00188 int select() {
00189 return select(defaultType);
00190 }
00191
00198 int selectByKey(char_t const* key, void const* value);
00199
00208 int selectByKeyRange(char_t const* key, void const* minValue, void const* maxValue, bool ascent = true);
00209
00215 bool update() {
00216 assert(type == dbCursorForUpdate && currId != 0);
00217 return db->update(currId, table, record);
00218 }
00219
00223 void removeAll() {
00224 assert(db != NULL);
00225 reset();
00226 db->deleteTable(table);
00227 }
00228
00232 void removeAllSelected();
00233
00237 void setSelectionLimit(size_t lim) { limit = lim; }
00238
00242 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00243
00250 void setPrefetchMode(bool mode) { prefetch = mode; }
00251
00262 bool isIncremental() {
00263 return iterator != NULL;
00264 }
00265
00270 bool hasIncrementalHint() {
00271 return type == dbCursorIncremental;
00272 }
00273
00278 void enableCheckForDuplicates(bool enabled) {
00279 checkForDuplicatedIsEnabled = enabled;
00280 }
00281
00285 void reset();
00286
00291 bool isLast() const;
00292
00297 bool isFirst() const;
00298
00304 void freeze();
00305
00309 void unfreeze();
00310
00318 bool skip(int n);
00319
00325 int seek(oid_t oid);
00326
00331 dbTableDescriptor* getTable() { return table; }
00332
00333
00338 bool isInSelection(oid_t oid);
00339
00344 void fetch() {
00345 dbRecord* row = (type == dbCursorDetached) ? db->fetchRow(tie, currId) : db->getRow(tie, currId);
00346 table->columns->fetchRecordFields(record, (byte*)row);
00347 }
00348
00352 bool hasNext() const;
00353
00357 bool hasCurrent() const {
00358 return currId != 0;
00359 }
00360
00361
00362 protected:
00363 dbDatabase* db;
00364 dbTableDescriptor* table;
00365 dbCursorType type;
00366 dbCursorType defaultType;
00367 dbSelection selection;
00368 bool allRecords;
00369 oid_t firstId;
00370 oid_t lastId;
00371 oid_t currId;
00372 byte* record;
00373 size_t limit;
00374 dbGetTie tie;
00375 void* paramBase;
00376
00377 int4* bitmap;
00378 size_t bitmapSize;
00379 bool eliminateDuplicates;
00380 bool checkForDuplicatedIsEnabled;
00381 bool prefetch;
00382 bool removed;
00383 bool lastRecordWasDeleted;
00384
00385 size_t stmtLimitStart;
00386 size_t stmtLimitLen;
00387 size_t nSkipped;
00388
00389 dbAbstractIterator*iterator;
00390 dbBtreeIterator btreeIterator;
00391 dbRtreeIterator rtreeIterator;
00392 dbTableIterator tableIterator;
00393
00394 void allocateBitmap();
00395 void deallocateBitmap();
00396
00397 void checkForDuplicates() {
00398 if (!eliminateDuplicates && checkForDuplicatedIsEnabled && limit > 1) {
00399 allocateBitmap();
00400 }
00401 }
00402
00403 bool isMarked(oid_t oid) {
00404 return bitmap != NULL && (bitmap[(size_t)(oid >> 5)] & (1 << ((int)oid & 31))) != 0;
00405 }
00406
00407 void mark(oid_t oid) {
00408 if (bitmap != NULL) {
00409 bitmap[(size_t)(oid >> 5)] |= 1 << ((int)oid & 31);
00410 }
00411 }
00412
00413 void setStatementLimit(dbQuery const& q) {
00414 stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00415 stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00416 }
00417
00418 void truncateSelection() {
00419 selection.truncate(stmtLimitStart, stmtLimitLen);
00420 }
00421
00422 bool add(oid_t oid) {
00423 if (selection.nRows < limit && selection.nRows < stmtLimitLen) {
00424 if (nSkipped < stmtLimitStart) {
00425 nSkipped += 1;
00426 return true;
00427 }
00428 if (eliminateDuplicates) {
00429 if (bitmap[(size_t)(oid >> 5)] & (1 << ((int)oid & 31))) {
00430 return true;
00431 }
00432 bitmap[oid >> 5] |= 1 << (oid & 31);
00433 }
00434 selection.add(oid);
00435 return selection.nRows < limit;
00436 }
00437 return false;
00438 }
00439
00440 byte* fetchNext();
00441 byte* fetchPrev();
00442 byte* fetchFirst();
00443 byte* fetchLast();
00444
00445 bool gotoNext();
00446 bool gotoPrev();
00447 bool gotoFirst();
00448 bool gotoLast();
00449
00450 bool moveNext();
00451 bool movePrev();
00452
00453 void setCurrent(dbAnyReference const& ref);
00454
00455 void setTable(dbTableDescriptor* aTable) {
00456 table = aTable;
00457 db = aTable->db;
00458 }
00459
00460 void setRecord(void* rec) {
00461 record = (byte*)rec;
00462 }
00463
00464 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec);
00465
00466 public:
00467 dbAnyCursor();
00468 ~dbAnyCursor();
00469 };
00470
00474 template<class T>
00475 class dbCursor : public dbAnyCursor {
00476 private:
00477
00478 dbCursor<T> operator = (dbCursor<T> const& src) {
00479 return *this;
00480 }
00481
00482 protected:
00483 T record;
00484
00485 public:
00490 dbCursor(dbCursorType type = dbCursorViewOnly)
00491 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00492
00499 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00500 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00501 {
00502 db = aDb;
00503 dbTableDescriptor* theTable = db->lookupTable(table);
00504 if (theTable != NULL) {
00505 table = theTable;
00506 }
00507 }
00508
00513 T* get() {
00514 return currId == 0 ? (T*)NULL : &record;
00515 }
00516
00521 T* next() {
00522 return (T*)fetchNext();
00523 }
00524
00529 T* prev() {
00530 return (T*)fetchPrev();
00531 }
00532
00537 T* first() {
00538 return (T*)fetchFirst();
00539 }
00540
00545 T* last() {
00546 return (T*)fetchLast();
00547 }
00548
00554 int seek(dbReference<T> const& ref) {
00555 return dbAnyCursor::seek(ref.getOid());
00556 }
00557
00562 T* operator ->() {
00563 assert(currId != 0);
00564 return &record;
00565 }
00566
00572 T* at(dbReference<T> const& ref) {
00573 setCurrent(ref);
00574 return &record;
00575 }
00576
00581 dbReference<T> currentId() const {
00582 return dbReference<T>(currId);
00583 }
00584
00589 void toArray(dbArray< dbReference<T> >& arr) const {
00590 arr.resize(selection.nRows);
00591 toArrayOfOid((oid_t*)arr.base());
00592 }
00593
00594 T* prevAvailable() {
00595 if (!removed) {
00596 return prev();
00597 } else {
00598 removed = false;
00599 return lastRecordWasDeleted ? get() : prev();
00600 }
00601 }
00602
00607 bool isInSelection(dbReference<T>& ref) {
00608 return dbAnyCursor::isInSelection(ref.getOid());
00609 }
00610 };
00611
00612 class dbParallelQueryContext {
00613 public:
00614 dbDatabase* const db;
00615 dbCompiledQuery* const query;
00616 dbAnyCursor* cursor;
00617 oid_t firstRow;
00618 dbTableDescriptor* table;
00619 dbSelection selection[dbMaxParallelSearchThreads];
00620
00621 void search(int i);
00622
00623 dbParallelQueryContext(dbDatabase* aDb, dbTableDescriptor* desc,
00624 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00625 : db(aDb), query(aQuery), cursor(aCursor), firstRow(desc->firstRow), table(desc) {}
00626 };
00627
00628 END_GIGABASE_NAMESPACE
00629
00630 #endif