00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __CURSOR_H__
00012 #define __CURSOR_H__
00013
00014 class dbOrderByNode;
00015
00016 class FASTDB_DLL_ENTRY dbSelection {
00017 public:
00018 enum { quantum = 1024 };
00019 class segment {
00020 public:
00021 segment* prev;
00022 segment* next;
00023 size_t nRows;
00024 oid_t rows[quantum];
00025
00026 segment(segment* after) {
00027 prev = after;
00028 next = NULL;
00029 nRows = 0;
00030 }
00031 };
00032 segment* first;
00033 segment* last;
00034 segment* curr;
00035 size_t nRows;
00036 size_t pos;
00037
00038 void add(oid_t oid) {
00039 if (last == NULL) {
00040 first = last = new segment(NULL);
00041 } else if (last->nRows == quantum) {
00042 last = last->next = new segment(last);
00043 }
00044 last->rows[last->nRows++] = oid;
00045 nRows += 1;
00046 }
00047
00048 void sort(dbDatabase* db, dbOrderByNode* order);
00049 static int compare(dbRecord* a, dbRecord* b, dbOrderByNode* order);
00050
00051 void toArray(oid_t* oids);
00052
00053 dbSelection() {
00054 nRows = 0;
00055 pos = 0;
00056 first = curr = last = NULL;
00057 }
00058 void reverse();
00059 void reset();
00060 };
00061
00062 enum dbCursorType {
00063 dbCursorViewOnly,
00064 dbCursorForUpdate
00065 };
00066
00070 class FASTDB_DLL_ENTRY dbAnyCursor : public dbL2List {
00071 friend class dbAnyContainer;
00072 friend class dbDatabase;
00073 friend class dbHashTable;
00074 friend class dbTtreeNode;
00075 friend class dbSubSql;
00076 friend class dbStatement;
00077 friend class dbServer;
00078 friend class dbCLI;
00079 public:
00084 int getNumberOfRecords() { return selection.nRows; }
00085
00089 void remove();
00090
00095 bool isEmpty() { return currId == 0; }
00096
00101 bool isLimitReached() { return selection.nRows >= limit; }
00102
00110 oid_t* toArrayOfOid(oid_t* arr);
00111
00122 int select(dbQuery& query, dbCursorType aType, void* paramStruct = NULL) {
00123 type = aType;
00124 reset();
00125 paramBase = paramStruct;
00126 db->select(this, query);
00127 paramBase = NULL;
00128 if (gotoFirst() && prefetch) {
00129 fetch();
00130 }
00131 return selection.nRows;
00132 }
00133
00140 int select(dbQuery& query, void* paramStruct = NULL) {
00141 return select(query, defaultType, paramStruct);
00142 }
00143
00151 int select(char const* condition, dbCursorType aType, void* paramStruct = NULL) {
00152 dbQuery query(condition);
00153 return select(query, aType, paramStruct);
00154 }
00155
00162 int select(char 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 selection.nRows;
00179 }
00180
00185 int select() {
00186 return select(defaultType);
00187 }
00188
00193 void update() {
00194 assert(type == dbCursorForUpdate && currId != 0);
00195 updateInProgress = true;
00196 db->update(currId, table, record);
00197 updateInProgress = false;
00198 }
00199
00203 void removeAll() {
00204 assert(db != NULL);
00205 db->deleteTable(table);
00206 reset();
00207 }
00208
00212 void removeAllSelected();
00213
00217 void setSelectionLimit(size_t lim) { limit = lim; }
00218
00222 void unsetSelectionLimit() { limit = dbDefaultSelectionLimit; }
00223
00230 void setPrefetchMode(bool mode) { prefetch = mode; }
00231
00235 void reset();
00236
00241 bool isLast();
00242
00247 bool isFirst();
00248
00254 void freeze();
00255
00259 void unfreeze();
00260
00264 dbTableDescriptor* getTable() { return table; }
00265
00266 protected:
00267 dbDatabase* db;
00268 dbTableDescriptor* table;
00269 dbCursorType type;
00270 dbCursorType defaultType;
00271 dbSelection selection;
00272 bool allRecords;
00273 oid_t firstId;
00274 oid_t lastId;
00275 oid_t currId;
00276 byte* record;
00277 size_t limit;
00278
00279 int4* bitmap;
00280 size_t bitmapSize;
00281 bool eliminateDuplicates;
00282 bool prefetch;
00283 bool removed;
00284 bool updateInProgress;
00285
00286 void* paramBase;
00287
00288 void checkForDuplicates() {
00289 if (!eliminateDuplicates && limit > 1) {
00290 eliminateDuplicates = true;
00291 size_t size = (db->currIndexSize + 31) / 32;
00292 if (size > bitmapSize) {
00293 delete[] bitmap;
00294 bitmap = new int4[size];
00295 bitmapSize = size;
00296 }
00297 memset(bitmap, 0, size*4);
00298 }
00299 }
00300
00301 bool isMarked(oid_t oid) {
00302 return bitmap != NULL && (bitmap[oid >> 5] & (1 << (oid & 31))) != 0;
00303 }
00304
00305 void mark(oid_t oid) {
00306 if (bitmap != NULL) {
00307 bitmap[oid >> 5] |= 1 << (oid & 31);
00308 }
00309 }
00310
00311 bool add(oid_t oid) {
00312 if (selection.nRows < limit) {
00313 if (eliminateDuplicates) {
00314 if (bitmap[oid >> 5] & (1 << (oid & 31))) {
00315 return true;
00316 }
00317 bitmap[oid >> 5] |= 1 << (oid & 31);
00318 }
00319 selection.add(oid);
00320 return selection.nRows < limit;
00321 }
00322 return false;
00323 }
00324
00325 bool gotoNext();
00326 bool gotoPrev();
00327 bool gotoFirst();
00328 bool gotoLast();
00329
00330 void setCurrent(dbAnyReference const& ref);
00331
00332 void fetch() {
00333 assert(!(db->currIndex[currId]
00334 & (dbInternalObjectMarker|dbFreeHandleMarker)));
00335 table->columns->fetchRecordFields(record,
00336 (byte*)db->getRow(currId));
00337 }
00338
00339 void adjustReferences(size_t base, size_t size, long shift) {
00340 if (currId != 0) {
00341 table->columns->adjustReferences(record, base, size, shift);
00342 }
00343 }
00344
00345 void setTable(dbTableDescriptor* aTable) {
00346 table = aTable;
00347 db = aTable->db;
00348 }
00349
00350 void setRecord(byte* rec) {
00351 record = rec;
00352 }
00353
00354 dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec)
00355 : table(&aTable),type(aType),defaultType(aType),
00356 allRecords(false),currId(0),record(rec)
00357 {
00358 db = aTable.db;
00359 limit = dbDefaultSelectionLimit;
00360 updateInProgress = false;
00361 prefetch = true;
00362 removed = false;
00363 bitmap = NULL;
00364 bitmapSize = 0;
00365 eliminateDuplicates = false;
00366 paramBase = NULL;
00367 }
00368 public:
00369 dbAnyCursor()
00370 : table(NULL),type(dbCursorViewOnly),defaultType(dbCursorViewOnly),
00371 allRecords(false),currId(0),record(NULL)
00372 {
00373 limit = dbDefaultSelectionLimit;
00374 updateInProgress = false;
00375 prefetch = false;
00376 removed = false;
00377 bitmap = NULL;
00378 bitmapSize = 0;
00379 eliminateDuplicates = false;
00380 db = NULL;
00381 paramBase = NULL;
00382 }
00383 ~dbAnyCursor();
00384 };
00385
00386
00390 template<class T>
00391 class dbCursor : public dbAnyCursor {
00392 protected:
00393 T record;
00394
00395 public:
00400 dbCursor(dbCursorType type = dbCursorViewOnly)
00401 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00402
00409 dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00410 : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00411 {
00412 db = aDb;
00413 dbTableDescriptor* theTable = db->lookupTable(table);
00414 if (theTable != NULL) {
00415 table = theTable;
00416 }
00417 }
00418
00423 T* get() {
00424 return currId == 0 ? (T*)NULL : &record;
00425 }
00426
00431 T* next() {
00432 if (gotoNext()) {
00433 fetch();
00434 return &record;
00435 }
00436 return NULL;
00437 }
00438
00443 T* prev() {
00444 if (gotoPrev()) {
00445 fetch();
00446 return &record;
00447 }
00448 return NULL;
00449 }
00450
00455 T* first() {
00456 if (gotoFirst()) {
00457 fetch();
00458 return &record;
00459 }
00460 return NULL;
00461 }
00462
00467 T* last() {
00468 if (gotoLast()) {
00469 fetch();
00470 return &record;
00471 }
00472 return NULL;
00473 }
00474
00479 T* operator ->() {
00480 assert(currId != 0);
00481 return &record;
00482 }
00483
00489 T* at(dbReference<T> const& ref) {
00490 setCurrent(ref);
00491 return &record;
00492 }
00493
00498 void toArray(dbArray< dbReference<T> >& arr) {
00499 arr.resize(selection.nRows);
00500 toArrayOfOid((oid_t*)arr.base());
00501 }
00502
00507 dbReference<T> currentId() {
00508 return dbReference<T>(currId);
00509 }
00510
00527 T* nextAvailable() {
00528 if (!removed) {
00529 return next();
00530 } else {
00531 removed = false;
00532 return get();
00533 }
00534 }
00535 };
00536
00537 class dbParallelQueryContext {
00538 public:
00539 dbDatabase* const db;
00540 dbCompiledQuery* const query;
00541 oid_t firstRow;
00542 dbTable* table;
00543 dbAnyCursor* cursor;
00544 dbSelection selection[dbMaxParallelSearchThreads];
00545
00546 void search(int i);
00547
00548 dbParallelQueryContext(dbDatabase* aDb, dbTable* aTable,
00549 dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00550 : db(aDb), query(aQuery), firstRow(aTable->firstRow), table(aTable), cursor(aCursor) {}
00551 };
00552
00553
00554 extern char* strupper(char* s);
00555
00556 extern char* strlower(char* s);
00557
00558 #endif