Main Page | Class Hierarchy | Class List | File List | Class Members

cursor.h

00001 //-< CURSOR.H >------------------------------------------------------*--------*
00002 // GigaBASE                  Version 1.0         (c) 1999  GARRET    *     ?  *
00003 // (Post Relational Database Management System)                      *   /\|  *
00004 //                                                                   *  /  \  *
00005 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
00006 //                          Last update: 10-Dec-98    K.A. Knizhnik  * GARRET *
00007 //-------------------------------------------------------------------*--------*
00008 // Table cursor
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; // bitmap to avoid duplicates
00303     size_t             bitmapSize;
00304     bool               eliminateDuplicates;
00305     bool               prefetch;
00306     bool               removed; // current record was 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

Generated on Thu Feb 12 18:46:27 2004 for GigaBASE by doxygen 1.3.5