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
00214 void update() {
00215 assert(type == dbCursorForUpdate && currId != 0);
00216 db->update(currId, table, record);
00217 }
00218
00222 void removeAll() {
00223 assert(db != NULL);
00224 reset();
00225 db->deleteTable(table);
00226 }
00227
00231 void removeAllSelected();
00232
00236 void setSelectionLimit(size_t lim) { limit = lim; }
00237
00241 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00242
00249 void setPrefetchMode(bool mode) { prefetch = mode; }
00250
00261 bool isIncremental() {
00262 return iterator != NULL;
00263 }
00264
00269 bool hasIncrementalHint() {
00270 return type == dbCursorIncremental;
00271 }
00272
00277 void enableCheckForDuplicates(bool enabled) {
00278 checkForDuplicatedIsEnabled = enabled;
00279 }
00280
00284 void reset();
00285
00290 bool isLast() const;
00291
00296 bool isFirst() const;
00297
00303 void freeze();
00304
00308 void unfreeze();
00309
00317 bool skip(int n);
00318
00324 int seek(oid_t oid);
00325
00330 dbTableDescriptor* getTable() { return table; }
00331
00332
00337 bool isInSelection(oid_t oid);
00338
00343 void fetch() {
00344 dbRecord* row = (type == dbCursorDetached) ? db->fetchRow(tie, currId) : db->getRow(tie, currId);
00345 table->columns->fetchRecordFields(record, (byte*)row);
00346 }
00347
00351 bool hasNext() const;
00352
00356 bool hasCurrent() const {
00357 return currId != 0;
00358 }
00359
00360
00361 protected:
00362 dbDatabase* db;
00363 dbTableDescriptor* table;
00364 dbCursorType type;
00365 dbCursorType defaultType;
00366 dbSelection selection;
00367 bool allRecords;
00368 oid_t firstId;
00369 oid_t lastId;
00370 oid_t currId;
00371 byte* record;
00372 size_t limit;
00373 dbGetTie tie;
00374 void* paramBase;
00375
00376 int4* bitmap;
00377 size_t bitmapSize;
00378 bool eliminateDuplicates;
00379 bool checkForDuplicatedIsEnabled;
00380 bool prefetch;
00381 bool removed;
00382 bool lastRecordWasDeleted;
00383
00384 size_t stmtLimitStart;
00385 size_t stmtLimitLen;
00386 size_t nSkipped;
00387
00388 dbAbstractIterator*iterator;
00389 dbBtreeIterator btreeIterator;
00390 dbRtreeIterator rtreeIterator;
00391 dbTableIterator tableIterator;
00392
00393 void allocateBitmap();
00394 void deallocateBitmap();
00395
00396 void checkForDuplicates() {
00397 if (!eliminateDuplicates && checkForDuplicatedIsEnabled && limit > 1) {
00398 allocateBitmap();
00399 }
00400 }
00401
00402 bool isMarked(oid_t oid) {
00403 return bitmap != NULL && (bitmap[(size_t)(oid >> 5)] & (1 << ((int)oid & 31))) != 0;
00404 }
00405
00406 void mark(oid_t oid) {
00407 if (bitmap != NULL) {
00408 bitmap[(size_t)(oid >> 5)] |= 1 << ((int)oid & 31);
00409 }
00410 }
00411
00412 void setStatementLimit(dbQuery const& q) {
00413 stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00414 stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00415 }
00416
00417 void truncateSelection() {
00418 selection.truncate(stmtLimitStart, stmtLimitLen);
00419 }
00420
00421 bool add(oid_t oid) {
00422 if (selection.nRows < limit && selection.nRows < stmtLimitLen) {
00423 if (nSkipped < stmtLimitStart) {
00424 nSkipped += 1;
00425 return true;
00426 }
00427 if (eliminateDuplicates) {
00428 if (bitmap[(size_t)(oid >> 5)] & (1 << ((int)oid & 31))) {
00429 return true;
00430 }
00431 bitmap[oid >> 5] |= 1 << (oid & 31);
00432 }
00433 selection.add(oid);
00434 return selection.nRows < limit;
00435 }
00436 return false;
00437 }
00438
00439 byte* fetchNext();
00440 byte* fetchPrev();
00441 byte* fetchFirst();
00442 byte* fetchLast();
00443
00444 bool gotoNext();
00445 bool gotoPrev();
00446 bool gotoFirst();
00447 bool gotoLast();
00448
00449 bool moveNext();
00450 bool movePrev();
00451
00452 void setCurrent(dbAnyReference const& ref);
00453
00454 void setTable(dbTableDescriptor* aTable) {
00455 table = aTable;
00456 db = aTable->db;
00457 }
00458
00459 void setRecord(void* rec) {
00460 record = (byte*)rec;
00461 }
00462
00463 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec);
00464
00465 public:
00466 dbAnyCursor();
00467 ~dbAnyCursor();
00468 };
00469
00473 template<class T>
00474 class dbCursor : public dbAnyCursor {
00475 private:
00476
00477 dbCursor<T> operator = (dbCursor<T> const& src) {
00478 return *this;
00479 }
00480
00481 protected:
00482 T record;
00483
00484 public:
00489 dbCursor(dbCursorType type = dbCursorViewOnly)
00490 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00491
00498 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00499 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00500 {
00501 db = aDb;
00502 dbTableDescriptor* theTable = db->lookupTable(table);
00503 if (theTable != NULL) {
00504 table = theTable;
00505 }
00506 }
00507
00512 T* get() {
00513 return currId == 0 ? (T*)NULL : &record;
00514 }
00515
00520 T* next() {
00521 return (T*)fetchNext();
00522 }
00523
00528 T* prev() {
00529 return (T*)fetchPrev();
00530 }
00531
00536 T* first() {
00537 return (T*)fetchFirst();
00538 }
00539
00544 T* last() {
00545 return (T*)fetchLast();
00546 }
00547
00553 int seek(dbReference<T> const& ref) {
00554 return dbAnyCursor::seek(ref.getOid());
00555 }
00556
00561 T* operator ->() {
00562 assert(currId != 0);
00563 return &record;
00564 }
00565
00571 T* at(dbReference<T> const& ref) {
00572 setCurrent(ref);
00573 return &record;
00574 }
00575
00580 dbReference<T> currentId() const {
00581 return dbReference<T>(currId);
00582 }
00583
00588 void toArray(dbArray< dbReference<T> >& arr) const {
00589 arr.resize(selection.nRows);
00590 toArrayOfOid((oid_t*)arr.base());
00591 }
00592
00593 T* prevAvailable() {
00594 if (!removed) {
00595 return prev();
00596 } else {
00597 removed = false;
00598 return lastRecordWasDeleted ? get() : prev();
00599 }
00600 }
00601
00606 bool isInSelection(dbReference<T>& ref) {
00607 return dbAnyCursor::isInSelection(ref.getOid());
00608 }
00609 };
00610
00611 class dbParallelQueryContext {
00612 public:
00613 dbDatabase* const db;
00614 dbCompiledQuery* const query;
00615 dbAnyCursor* cursor;
00616 oid_t firstRow;
00617 dbTableDescriptor* table;
00618 dbSelection selection[dbMaxParallelSearchThreads];
00619
00620 void search(int i);
00621
00622 dbParallelQueryContext(dbDatabase* aDb, dbTableDescriptor* desc,
00623 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00624 : db(aDb), query(aQuery), cursor(aCursor), firstRow(desc->firstRow), table(desc) {}
00625 };
00626
00627 END_GIGABASE_NAMESPACE
00628
00629 #endif