00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __CURSOR_H__
00012 #define __CURSOR_H__
00013
00014 BEGIN_FASTDB_NAMESPACE
00015
00016 class dbOrderByNode;
00017
00018 class FASTDB_DLL_ENTRY dbSelection {
00019 public:
00020 enum { quantum = 1024 };
00021 class segment {
00022 public:
00023 segment* prev;
00024 segment* next;
00025 size_t nRows;
00026 oid_t rows[quantum];
00027
00028 segment(segment* after) {
00029 prev = after;
00030 next = NULL;
00031 nRows = 0;
00032 }
00033 };
00034 segment* first;
00035 segment* last;
00036 segment* curr;
00037 size_t nRows;
00038 size_t pos;
00039
00040 segment* createNewSegment(segment* after);
00041
00042 void add(oid_t oid) {
00043 if (last == NULL) {
00044 first = last = createNewSegment(NULL);
00045 } else if (last->nRows == quantum) {
00046 last = last->next = createNewSegment(last);
00047 }
00048 last->rows[last->nRows++] = oid;
00049 nRows += 1;
00050 }
00051
00052 void sort(dbDatabase* db, dbOrderByNode* order);
00053 static int compare(oid_t a, oid_t b, dbOrderByNode* order);
00054
00055 void toArray(oid_t* oids) const;
00056 void truncate(size_t from, size_t length);
00057
00058 dbSelection() {
00059 nRows = 0;
00060 pos = 0;
00061 first = curr = last = NULL;
00062 }
00063 void reverse();
00064 void reset();
00065 };
00066
00067 enum dbCursorType {
00068 dbCursorViewOnly,
00069 dbCursorForUpdate
00070 };
00071
00075 class FASTDB_DLL_ENTRY dbAnyCursor : public dbL2List {
00076 friend class dbAnyContainer;
00077 friend class dbDatabase;
00078 friend class dbHashTable;
00079 friend class dbTtreeNode;
00080 friend class dbRtreePage;
00081 friend class dbSubSql;
00082 friend class dbStatement;
00083 friend class dbServer;
00084 friend class dbCLI;
00085 friend class JniResultSet;
00086 public:
00091 int getNumberOfRecords() const { return (int)selection.nRows; }
00092
00096 void remove();
00097
00102 bool isEmpty() const { return currId == 0; }
00103
00108 bool isUpdateCursor() const {
00109 return type == dbCursorForUpdate;
00110 }
00111
00116 bool isLimitReached() const { return selection.nRows >= limit || selection.nRows >= stmtLimitLen; }
00117
00125 oid_t* toArrayOfOid(oid_t* arr) const;
00126
00137 int select(dbQuery& query, dbCursorType aType, void* paramStruct = NULL) {
00138 type = aType;
00139 reset();
00140 paramBase = paramStruct;
00141 db->select(this, query);
00142 paramBase = NULL;
00143 if (gotoFirst() && prefetch) {
00144 fetch();
00145 }
00146 return (int)selection.nRows;
00147 }
00148
00155 int select(dbQuery& query, void* paramStruct = NULL) {
00156 return select(query, defaultType, paramStruct);
00157 }
00158
00166 int select(char const* condition, dbCursorType aType, void* paramStruct = NULL) {
00167 dbQuery query(condition);
00168 return select(query, aType, paramStruct);
00169 }
00170
00177 int select(char const* condition, void* paramStruct = NULL) {
00178 return select(condition, defaultType, paramStruct);
00179 }
00180
00186 int select(dbCursorType aType) {
00187 type = aType;
00188 reset();
00189 db->select(this);
00190 if (gotoFirst() && prefetch) {
00191 fetch();
00192 }
00193 return (int)selection.nRows;
00194 }
00195
00200 int select() {
00201 return select(defaultType);
00202 }
00203
00210 int selectByKey(char const* key, void const* value);
00211
00219 int selectByKeyRange(char const* key, void const* minValue, void const* maxValue);
00220
00225 void update() {
00226 assert(type == dbCursorForUpdate && currId != 0);
00227 db->update(currId, table, record);
00228 }
00229
00233 void removeAll() {
00234 assert(db != NULL);
00235 db->deleteTable(table);
00236 reset();
00237 }
00238
00242 void removeAllSelected();
00243
00247 void setSelectionLimit(size_t lim) { limit = lim; }
00248
00252 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00253
00260 void setPrefetchMode(bool mode) { prefetch = mode; }
00261
00262
00267 void enableCheckForDuplicates(bool enabled) {
00268 checkForDuplicatedIsEnabled = enabled;
00269 }
00270
00271
00275 void reset();
00276
00281 bool isLast() const;
00282
00287 bool isFirst() const;
00288
00294 void freeze();
00295
00299 void unfreeze();
00300
00308 bool skip(int n);
00309
00310
00316 int seek(oid_t oid);
00317
00321 dbTableDescriptor* getTable() { return table; }
00322
00323
00328 void setTable(dbTableDescriptor* aTable) {
00329 table = aTable;
00330 db = aTable->db;
00331 }
00332
00337 void setRecord(void* rec) {
00338 record = (byte*)rec;
00339 }
00340
00345 void* getRecord() {
00346 return record;
00347 }
00348
00353 bool isInSelection(oid_t oid);
00354
00355
00360 void fetch() {
00361 assert(!(db->currIndex[currId]
00362 & (dbInternalObjectMarker|dbFreeHandleMarker)));
00363 table->columns->fetchRecordFields(record,
00364 (byte*)db->getRow(currId));
00365 }
00366
00370 bool hasNext() const;
00371
00372 protected:
00373 dbDatabase* db;
00374 dbTableDescriptor* table;
00375 dbCursorType type;
00376 dbCursorType defaultType;
00377 dbSelection selection;
00378 bool allRecords;
00379 oid_t firstId;
00380 oid_t lastId;
00381 oid_t currId;
00382 byte* record;
00383 size_t limit;
00384
00385 int4* bitmap;
00386 size_t bitmapSize;
00387 bool eliminateDuplicates;
00388 bool checkForDuplicatedIsEnabled;
00389 bool prefetch;
00390 bool removed;
00391 bool lastRecordWasDeleted;
00392
00393 size_t stmtLimitStart;
00394 size_t stmtLimitLen;
00395 size_t nSkipped;
00396
00397 void* paramBase;
00398
00399 void checkForDuplicates();
00400 void deallocateBitmap();
00401
00402 bool isMarked(oid_t oid) {
00403 return bitmap != NULL && (bitmap[oid >> 5] & (1 << (oid & 31))) != 0;
00404 }
00405
00406 void setStatementLimit(dbQuery const& q) {
00407 stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00408 stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00409 }
00410
00411 void truncateSelection() {
00412 selection.truncate(stmtLimitStart, stmtLimitLen);
00413 }
00414
00415 void mark(oid_t oid) {
00416 if (bitmap != NULL) {
00417 bitmap[oid >> 5] |= 1 << (oid & 31);
00418 }
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[oid >> 5] & (1 << (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
00442 bool gotoNext();
00443 bool gotoPrev();
00444 bool gotoFirst();
00445 bool gotoLast();
00446
00447 bool moveNext();
00448 bool movePrev();
00449
00450 void setCurrent(dbAnyReference const& ref);
00451
00452 void adjustReferences(size_t base, size_t size, long shift) {
00453 if (currId != 0 && record != NULL) {
00454 table->columns->adjustReferences(record, base, size, shift);
00455 }
00456 }
00457
00458 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec)
00459 : table(&aTable),type(aType),defaultType(aType),
00460 allRecords(false),currId(0),record(rec)
00461 {
00462 db = aTable.db;
00463 limit = dbDefaultSelectionLimit;
00464 prefetch = rec != NULL;
00465 removed = false;
00466 bitmap = NULL;
00467 bitmapSize = 0;
00468 eliminateDuplicates = false;
00469 checkForDuplicatedIsEnabled = true;
00470 paramBase = NULL;
00471 stmtLimitLen = dbDefaultSelectionLimit;
00472 stmtLimitStart = 0;
00473 nSkipped = 0;
00474 }
00475 public:
00476 dbAnyCursor()
00477 : table(NULL),type(dbCursorViewOnly),defaultType(dbCursorViewOnly),
00478 allRecords(false),currId(0),record(NULL)
00479 {
00480 limit = dbDefaultSelectionLimit;
00481 prefetch = false;
00482 removed = false;
00483 bitmap = NULL;
00484 bitmapSize = 0;
00485 eliminateDuplicates = false;
00486 checkForDuplicatedIsEnabled = true;
00487 db = NULL;
00488 paramBase = NULL;
00489 stmtLimitLen = dbDefaultSelectionLimit;
00490 stmtLimitStart = 0;
00491 nSkipped = 0;
00492 }
00493 ~dbAnyCursor();
00494 };
00495
00496
00500 template<class T>
00501 class dbCursor : public dbAnyCursor {
00502 private:
00503
00504 dbCursor<T> operator = (dbCursor<T> const& src) {
00505 return *this;
00506 }
00507
00508 protected:
00509 T record;
00510
00511 public:
00516 dbCursor(dbCursorType type = dbCursorViewOnly)
00517 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00518
00525 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00526 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00527 {
00528 db = aDb;
00529 dbTableDescriptor* theTable = db->lookupTable(table);
00530 if (theTable != NULL) {
00531 table = theTable;
00532 }
00533 }
00534
00539 T* get() {
00540 return currId == 0 ? (T*)NULL : &record;
00541 }
00542
00547 T* next() {
00548 return (T*)fetchNext();
00549 }
00550
00555 T* prev() {
00556 return (T*)fetchPrev();
00557 }
00558
00563 T* first() {
00564 if (gotoFirst()) {
00565 fetch();
00566 return &record;
00567 }
00568 return NULL;
00569 }
00570
00575 T* last() {
00576 if (gotoLast()) {
00577 fetch();
00578 return &record;
00579 }
00580 return NULL;
00581 }
00582
00588 int seek(dbReference<T> const& ref) {
00589 return dbAnyCursor::seek(ref.getOid());
00590 }
00591
00596 T* operator ->() {
00597 assert(currId != 0);
00598 return &record;
00599 }
00600
00606 T* at(dbReference<T> const& ref) {
00607 setCurrent(ref);
00608 return &record;
00609 }
00610
00615 void toArray(dbArray< dbReference<T> >& arr) const {
00616 arr.resize(selection.nRows);
00617 toArrayOfOid((oid_t*)arr.base());
00618 }
00619
00624 dbReference<T> currentId() const {
00625 return dbReference<T>(currId);
00626 }
00627
00632 bool isInSelection(dbReference<T>& ref) {
00633 return dbAnyCursor::isInSelection(ref.getOid());
00634 }
00635 };
00636
00637 class dbParallelQueryContext {
00638 public:
00639 dbDatabase* const db;
00640 dbCompiledQuery* const query;
00641 oid_t firstRow;
00642 dbTable* table;
00643 dbAnyCursor* cursor;
00644 dbSelection selection[dbMaxParallelSearchThreads];
00645
00646 void search(int i);
00647
00648 dbParallelQueryContext(dbDatabase* aDb, dbTable* aTable,
00649 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00650 : db(aDb), query(aQuery), firstRow(aTable->firstRow), table(aTable), cursor(aCursor) {}
00651 };
00652
00653
00654 extern char* strupper(char* s);
00655
00656 extern char* strlower(char* s);
00657
00658 END_FASTDB_NAMESPACE
00659
00660 #endif