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
00024 };
00025
00029 class dbTableIterator : public dbAbstractIterator {
00030 dbAnyCursor* cursor;
00031 dbExprNode* filter;
00032 oid_t curr;
00033
00034 public:
00035 void init(dbAnyCursor* cursor, dbExprNode* filter) {
00036 this->cursor = cursor;
00037 this->filter = filter;
00038 curr = 0;
00039 }
00040
00041 virtual oid_t next();
00042 virtual oid_t prev();
00043 virtual oid_t first();
00044 virtual oid_t last();
00045 };
00046
00047
00048
00052 class GIGABASE_DLL_ENTRY dbAnyCursor : public dbL2List {
00053 friend class dbDatabase;
00054 friend class dbHashTable;
00055 friend class dbRtreePage;
00056 friend class dbBtreePage;
00057 friend class dbRtreeIterator;
00058 friend class dbBtreeIterator;
00059 friend class dbTableIterator;
00060 friend class dbThickBtreePage;
00061 friend class dbSubSql;
00062 friend class dbStatement;
00063 friend class dbServer;
00064 friend class dbAnyContainer;
00065 friend class dbCLI;
00066 friend class JniResultSet;
00067 public:
00072 int getNumberOfRecords() const { return (int)selection.nRows; }
00073
00077 void remove();
00078
00083 bool isEmpty() const {
00084 return currId == 0;
00085 }
00086
00091 bool isUpdateCursor() const {
00092 return type == dbCursorForUpdate;
00093 }
00094
00099 bool isLimitReached() const {
00100 return selection.nRows >= limit || selection.nRows >= stmtLimitLen;
00101 }
00102
00113 int select(dbQuery& query, dbCursorType aType, void* paramStruct = NULL) {
00114 paramBase = paramStruct;
00115 type = aType;
00116 reset();
00117 db->select(this, query);
00118 paramBase = NULL;
00119 if (gotoFirst() && prefetch) {
00120 fetch();
00121 }
00122 return (int)selection.nRows;
00123 }
00124
00132 oid_t* toArrayOfOid(oid_t* arr) const;
00133
00140 int select(dbQuery& query, void* paramStruct = NULL) {
00141 return select(query, defaultType, paramStruct);
00142 }
00143
00151 int select(char_t const* condition, dbCursorType aType, void* paramStruct = NULL) {
00152 dbQuery query(condition);
00153 return select(query, aType, paramStruct);
00154 }
00155
00162 int select(char_t const* condition, void* paramStruct = NULL) {
00163 return select(condition, defaultType, paramStruct);
00164 }
00165
00171 int select(dbCursorType aType) {
00172 type = aType;
00173 reset();
00174 db->select(this);
00175 if (gotoFirst() && prefetch) {
00176 fetch();
00177 }
00178 return (int)selection.nRows;
00179 }
00180
00185 int select() {
00186 return select(defaultType);
00187 }
00188
00195 int selectByKey(char_t const* key, void const* value);
00196
00205 int selectByKeyRange(char_t const* key, void const* minValue, void const* maxValue, bool ascent = true);
00206
00211 void update() {
00212 assert(type == dbCursorForUpdate && currId != 0);
00213 db->update(currId, table, record);
00214 }
00215
00219 void removeAll() {
00220 assert(db != NULL);
00221 reset();
00222 db->deleteTable(table);
00223 }
00224
00228 void removeAllSelected();
00229
00233 void setSelectionLimit(size_t lim) { limit = lim; }
00234
00238 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00239
00246 void setPrefetchMode(bool mode) { prefetch = mode; }
00247
00256 bool setIncrementalHint(bool inc) {
00257 bool prev = incremental;
00258 assert(!inc || type != dbCursorForUpdate);
00259 incremental = inc;
00260 return prev;
00261 }
00262
00272 bool isIncremental() {
00273 return iterator != NULL;
00274 }
00275
00279 void reset();
00280
00285 bool isLast() const;
00286
00291 bool isFirst() const;
00292
00298 void freeze();
00299
00303 void unfreeze();
00304
00312 bool skip(int n);
00313
00319 int seek(oid_t oid);
00320
00325 dbTableDescriptor* getTable() { return table; }
00326
00327
00332 bool isInSelection(oid_t oid);
00333
00338 void fetch() {
00339 table->columns->fetchRecordFields(record,
00340 (byte*)db->getRow(tie, currId));
00341 }
00342
00346 bool hasNext() const;
00347
00351 bool hasCurrent() const {
00352 return currId != 0;
00353 }
00354
00355
00356 protected:
00357 dbDatabase* db;
00358 dbTableDescriptor* table;
00359 dbCursorType type;
00360 dbCursorType defaultType;
00361 dbSelection selection;
00362 bool allRecords;
00363 oid_t firstId;
00364 oid_t lastId;
00365 oid_t currId;
00366 byte* record;
00367 size_t limit;
00368 dbGetTie tie;
00369 void* paramBase;
00370
00371 int4* bitmap;
00372 size_t bitmapSize;
00373 bool eliminateDuplicates;
00374 bool prefetch;
00375 bool removed;
00376 bool lastRecordWasDeleted;
00377 bool incremental;
00378
00379 size_t stmtLimitStart;
00380 size_t stmtLimitLen;
00381 size_t nSkipped;
00382
00383 dbAbstractIterator*iterator;
00384 dbBtreeIterator btreeIterator;
00385 dbRtreeIterator rtreeIterator;
00386 dbTableIterator tableIterator;
00387
00388 void allocateBitmap();
00389 void deallocateBitmap();
00390
00391 void checkForDuplicates() {
00392 if (!eliminateDuplicates && limit > 1) {
00393 allocateBitmap();
00394 }
00395 }
00396
00397 bool isMarked(oid_t oid) {
00398 return bitmap != NULL && (bitmap[(size_t)(oid >> 5)] & (1 << ((int)oid & 31))) != 0;
00399 }
00400
00401 void mark(oid_t oid) {
00402 if (bitmap != NULL) {
00403 bitmap[(size_t)(oid >> 5)] |= 1 << ((int)oid & 31);
00404 }
00405 }
00406
00407 void setStatementLimit(dbQuery const& q) {
00408 stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00409 stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00410 }
00411
00412 void truncateSelection() {
00413 selection.truncate(stmtLimitStart, stmtLimitLen);
00414 }
00415
00416 bool add(oid_t oid) {
00417 if (selection.nRows < limit && selection.nRows < stmtLimitLen) {
00418 if (nSkipped < stmtLimitStart) {
00419 nSkipped += 1;
00420 return true;
00421 }
00422 if (eliminateDuplicates) {
00423 if (bitmap[(size_t)(oid >> 5)] & (1 << ((int)oid & 31))) {
00424 return true;
00425 }
00426 bitmap[oid >> 5] |= 1 << (oid & 31);
00427 }
00428 selection.add(oid);
00429 return selection.nRows < limit;
00430 }
00431 return false;
00432 }
00433
00434 bool gotoNext();
00435 bool gotoPrev();
00436 bool gotoFirst();
00437 bool gotoLast();
00438
00439 bool moveNext();
00440 bool movePrev();
00441
00442 void setCurrent(dbAnyReference const& ref);
00443
00444 void setTable(dbTableDescriptor* aTable) {
00445 table = aTable;
00446 db = aTable->db;
00447 }
00448
00449 void setRecord(void* rec) {
00450 record = (byte*)rec;
00451 }
00452
00453 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec);
00454
00455 public:
00456 dbAnyCursor();
00457 ~dbAnyCursor();
00458 };
00459
00463 template<class T>
00464 class dbCursor : public dbAnyCursor {
00465 private:
00466
00467 dbCursor<T> operator = (dbCursor<T> const& src) {
00468 return *this;
00469 }
00470
00471 protected:
00472 T record;
00473
00474 public:
00479 dbCursor(dbCursorType type = dbCursorViewOnly)
00480 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00481
00488 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00489 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00490 {
00491 db = aDb;
00492 dbTableDescriptor* theTable = db->lookupTable(table);
00493 if (theTable != NULL) {
00494 table = theTable;
00495 }
00496 }
00497
00502 T* get() {
00503 return currId == 0 ? (T*)NULL : &record;
00504 }
00505
00510 T* next() {
00511 if (gotoNext()) {
00512 fetch();
00513 return &record;
00514 }
00515 return NULL;
00516 }
00517
00522 T* prev() {
00523 if (gotoPrev()) {
00524 fetch();
00525 return &record;
00526 }
00527 return NULL;
00528 }
00529
00534 T* first() {
00535 if (gotoFirst()) {
00536 fetch();
00537 return &record;
00538 }
00539 return NULL;
00540 }
00541
00546 T* last() {
00547 if (gotoLast()) {
00548 fetch();
00549 return &record;
00550 }
00551 return NULL;
00552 }
00553
00559 int seek(dbReference<T> const& ref) {
00560 return dbAnyCursor::seek(ref.getOid());
00561 }
00562
00567 T* operator ->() {
00568 assert(currId != 0);
00569 return &record;
00570 }
00571
00577 T* at(dbReference<T> const& ref) {
00578 setCurrent(ref);
00579 return &record;
00580 }
00581
00586 dbReference<T> currentId() const {
00587 return dbReference<T>(currId);
00588 }
00589
00594 void toArray(dbArray< dbReference<T> >& arr) const {
00595 arr.resize(selection.nRows);
00596 toArrayOfOid((oid_t*)arr.base());
00597 }
00598
00615 T* nextAvailable() {
00616 if (!removed) {
00617 return next();
00618 } else {
00619 removed = false;
00620 return lastRecordWasDeleted ? NULL : get();
00621 }
00622 }
00623
00641 T* prevAvailable() {
00642 if (!removed) {
00643 return prev();
00644 } else {
00645 removed = false;
00646 return lastRecordWasDeleted ? get() : prev();
00647 }
00648 }
00649
00654 bool isInSelection(dbReference<T>& ref) {
00655 return dbAnyCursor::isInSelection(ref.getOid());
00656 }
00657 };
00658
00659 class dbParallelQueryContext {
00660 public:
00661 dbDatabase* const db;
00662 dbCompiledQuery* const query;
00663 dbAnyCursor* cursor;
00664 oid_t firstRow;
00665 dbTableDescriptor* table;
00666 dbSelection selection[dbMaxParallelSearchThreads];
00667
00668 void search(int i);
00669
00670 dbParallelQueryContext(dbDatabase* aDb, dbTableDescriptor* desc,
00671 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00672 : db(aDb), query(aQuery), cursor(aCursor), firstRow(desc->firstRow), table(desc) {}
00673 };
00674
00675 END_GIGABASE_NAMESPACE
00676
00677 #endif