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
00018 enum dbCursorType {
00019 dbCursorViewOnly,
00020 dbCursorForUpdate
00021 };
00022
00026 class GIGABASE_DLL_ENTRY dbAnyCursor : public dbL2List {
00027 friend class dbDatabase;
00028 friend class dbHashTable;
00029 friend class dbRtreePage;
00030 friend class dbBtreePage;
00031 friend class dbThickBtreePage;
00032 friend class dbSubSql;
00033 friend class dbStatement;
00034 friend class dbServer;
00035 friend class dbAnyContainer;
00036 friend class dbCLI;
00037 public:
00042 int getNumberOfRecords() const { return selection.nRows; }
00043
00047 void remove();
00048
00053 bool isEmpty() const {
00054 return currId == 0;
00055 }
00056
00061 bool isUpdateCursor() const {
00062 return type == dbCursorForUpdate;
00063 }
00064
00069 bool isLimitReached() const {
00070 return selection.nRows >= limit || selection.nRows >= stmtLimitLen;
00071 }
00072
00083 int select(dbQuery& query, dbCursorType aType, void* paramStruct = NULL) {
00084 paramBase = paramStruct;
00085 type = aType;
00086 reset();
00087 db->select(this, query);
00088 paramBase = NULL;
00089 if (gotoFirst() && prefetch) {
00090 fetch();
00091 }
00092 return selection.nRows;
00093 }
00094
00102 oid_t* toArrayOfOid(oid_t* arr) const;
00103
00110 int select(dbQuery& query, void* paramStruct = NULL) {
00111 return select(query, defaultType, paramStruct);
00112 }
00113
00121 int select(char_t const* condition, dbCursorType aType, void* paramStruct = NULL) {
00122 dbQuery query(condition);
00123 return select(query, aType, paramStruct);
00124 }
00125
00132 int select(char_t const* condition, void* paramStruct = NULL) {
00133 return select(condition, defaultType, paramStruct);
00134 }
00135
00141 int select(dbCursorType aType) {
00142 type = aType;
00143 reset();
00144 db->select(this);
00145 if (gotoFirst() && prefetch) {
00146 fetch();
00147 }
00148 return selection.nRows;
00149 }
00150
00155 int select() {
00156 return select(defaultType);
00157 }
00158
00165 int selectByKey(char_t const* key, void const* value);
00166
00175 int selectByKeyRange(char_t const* key, void const* minValue, void const* maxValue, bool ascent = true);
00176
00181 void update() {
00182 assert(type == dbCursorForUpdate && currId != 0);
00183 updateInProgress = true;
00184 db->update(currId, table, record);
00185 updateInProgress = false;
00186 }
00187
00191 void removeAll() {
00192 assert(db != NULL);
00193 reset();
00194 db->deleteTable(table);
00195 }
00196
00200 void removeAllSelected();
00201
00205 void setSelectionLimit(size_t lim) { limit = lim; }
00206
00210 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00211
00218 void setPrefetchMode(bool mode) { prefetch = mode; }
00219
00223 void reset();
00224
00229 bool isLast() const;
00230
00235 bool isFirst() const;
00236
00242 void freeze();
00243
00247 void unfreeze();
00248
00256 bool skip(int n);
00257
00263 int seek(oid_t oid);
00264
00269 dbTableDescriptor* getTable() { return table; }
00270
00271
00276 bool isInSelection(oid_t oid);
00277
00282 void fetch() {
00283 table->columns->fetchRecordFields(record,
00284 (byte*)db->getRow(tie, currId));
00285 }
00286
00287 protected:
00288 dbDatabase* db;
00289 dbTableDescriptor* table;
00290 dbCursorType type;
00291 dbCursorType defaultType;
00292 dbSelection selection;
00293 bool allRecords;
00294 oid_t firstId;
00295 oid_t lastId;
00296 oid_t currId;
00297 byte* record;
00298 size_t limit;
00299 dbGetTie tie;
00300 void* paramBase;
00301
00302 int4* bitmap;
00303 size_t bitmapSize;
00304 bool eliminateDuplicates;
00305 bool prefetch;
00306 bool removed;
00307 bool updateInProgress;
00308
00309 size_t stmtLimitStart;
00310 size_t stmtLimitLen;
00311 size_t nSkipped;
00312
00313 void allocateBitmap();
00314
00315 void checkForDuplicates() {
00316 if (!eliminateDuplicates && limit > 1) {
00317 allocateBitmap();
00318 }
00319 }
00320
00321 bool isMarked(oid_t oid) {
00322 return bitmap != NULL && (bitmap[oid >> 5] & (1 << (oid & 31))) != 0;
00323 }
00324
00325 void mark(oid_t oid) {
00326 if (bitmap != NULL) {
00327 bitmap[oid >> 5] |= 1 << (oid & 31);
00328 }
00329 }
00330
00331 void setStatementLimit(dbQuery const& q) {
00332 stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00333 stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00334 }
00335
00336 void truncateSelection() {
00337 selection.truncate(stmtLimitStart, stmtLimitLen);
00338 }
00339
00340 bool add(oid_t oid) {
00341 if (selection.nRows < limit && selection.nRows < stmtLimitLen) {
00342 if (nSkipped < stmtLimitStart) {
00343 nSkipped += 1;
00344 return true;
00345 }
00346 if (eliminateDuplicates) {
00347 if (bitmap[oid >> 5] & (1 << (oid & 31))) {
00348 return true;
00349 }
00350 bitmap[oid >> 5] |= 1 << (oid & 31);
00351 }
00352 selection.add(oid);
00353 return selection.nRows < limit;
00354 }
00355 return false;
00356 }
00357
00358 bool gotoNext();
00359 bool gotoPrev();
00360 bool gotoFirst();
00361 bool gotoLast();
00362
00363 void setCurrent(dbAnyReference const& ref);
00364
00365 void setTable(dbTableDescriptor* aTable) {
00366 table = aTable;
00367 db = aTable->db;
00368 }
00369
00370 void setRecord(void* rec) {
00371 record = (byte*)rec;
00372 }
00373
00374 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec)
00375 : table(&aTable),type(aType),defaultType(aType),
00376 allRecords(false),currId(0),record(rec)
00377 {
00378 limit = dbDefaultSelectionLimit;
00379 updateInProgress = false;
00380 prefetch = true;
00381 removed = false;
00382 bitmap = NULL;
00383 bitmapSize = 0;
00384 eliminateDuplicates = false;
00385 db = aTable.db;
00386 paramBase = NULL;
00387 stmtLimitLen = dbDefaultSelectionLimit;
00388 stmtLimitStart = 0;
00389 nSkipped = 0;
00390 }
00391
00392 public:
00393 dbAnyCursor()
00394 : table(NULL),type(dbCursorViewOnly),defaultType(dbCursorViewOnly),
00395 allRecords(false),currId(0),record(NULL)
00396 {
00397 limit = dbDefaultSelectionLimit;
00398 updateInProgress = false;
00399 prefetch = false;
00400 removed = false;
00401 bitmap = NULL;
00402 bitmapSize = 0;
00403 eliminateDuplicates = false;
00404 db = NULL;
00405 paramBase = NULL;
00406 stmtLimitLen = dbDefaultSelectionLimit;
00407 stmtLimitStart = 0;
00408 nSkipped = 0;
00409 }
00410 ~dbAnyCursor();
00411 };
00412
00416 template<class T>
00417 class dbCursor : public dbAnyCursor {
00418 protected:
00419 T record;
00420
00421 public:
00426 dbCursor(dbCursorType type = dbCursorViewOnly)
00427 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00428
00435 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00436 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00437 {
00438 db = aDb;
00439 dbTableDescriptor* theTable = db->lookupTable(table);
00440 if (theTable != NULL) {
00441 table = theTable;
00442 }
00443 }
00444
00449 T* get() {
00450 return currId == 0 ? (T*)NULL : &record;
00451 }
00452
00457 T* next() {
00458 if (gotoNext()) {
00459 fetch();
00460 return &record;
00461 }
00462 return NULL;
00463 }
00464
00469 T* prev() {
00470 if (gotoPrev()) {
00471 fetch();
00472 return &record;
00473 }
00474 return NULL;
00475 }
00476
00481 T* first() {
00482 if (gotoFirst()) {
00483 fetch();
00484 return &record;
00485 }
00486 return NULL;
00487 }
00488
00493 T* last() {
00494 if (gotoLast()) {
00495 fetch();
00496 return &record;
00497 }
00498 return NULL;
00499 }
00500
00506 int seek(dbReference<T> const& ref) {
00507 return dbAnyCursor::seek(ref.getOid());
00508 }
00509
00514 T* operator ->() {
00515 assert(currId != 0);
00516 return &record;
00517 }
00518
00524 T* at(dbReference<T> const& ref) {
00525 setCurrent(ref);
00526 return &record;
00527 }
00528
00533 dbReference<T> currentId() const {
00534 return dbReference<T>(currId);
00535 }
00536
00541 void toArray(dbArray< dbReference<T> >& arr) const {
00542 arr.resize(selection.nRows);
00543 toArrayOfOid((oid_t*)arr.base());
00544 }
00545
00562 T* nextAvailable() {
00563 if (!removed) {
00564 return next();
00565 } else {
00566 removed = false;
00567 return get();
00568 }
00569 }
00570
00575 bool isInSelection(dbReference<T>& ref) const {
00576 return dbAnyCursor::isInSelection(ref.getOid());
00577 }
00578 };
00579
00580 class dbParallelQueryContext {
00581 public:
00582 dbDatabase* const db;
00583 dbCompiledQuery* const query;
00584 dbAnyCursor* cursor;
00585 oid_t firstRow;
00586 dbTableDescriptor* table;
00587 dbSelection selection[dbMaxParallelSearchThreads];
00588
00589 void search(int i);
00590
00591 dbParallelQueryContext(dbDatabase* aDb, dbTableDescriptor* desc,
00592 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00593 : db(aDb), query(aQuery), cursor(aCursor), firstRow(desc->firstRow), table(desc) {}
00594 };
00595
00596 END_GIGABASE_NAMESPACE
00597
00598 #endif