Main Page   Class Hierarchy   Compound List   File List   Compound Members  

cursor.h

00001 //-< CURSOR.H >------------------------------------------------------*--------*
00002 // FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *
00003 // (Main Memory 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_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 
00265     void reset();
00266 
00271     bool isLast() const; 
00272 
00277     bool isFirst() const; 
00278 
00284     void freeze();
00285 
00289     void unfreeze();
00290 
00298     bool skip(int n);
00299 
00300 
00306     int seek(oid_t oid);
00307 
00311     dbTableDescriptor* getTable() { return table; }
00312 
00313 
00318     void setTable(dbTableDescriptor* aTable) { 
00319         table = aTable;
00320         db = aTable->db;
00321     }
00322 
00327     void setRecord(void* rec) { 
00328         record = (byte*)rec;
00329     }
00330 
00335     void* getRecord() { 
00336         return record;
00337     }
00338 
00343     bool isInSelection(oid_t oid);
00344 
00345 
00350     void fetch() { 
00351         assert(!(db->currIndex[currId] 
00352                  & (dbInternalObjectMarker|dbFreeHandleMarker)));
00353         table->columns->fetchRecordFields(record, 
00354                                           (byte*)db->getRow(currId));
00355     }
00356 
00360     bool hasNext() const;
00361     
00362   protected: 
00363     dbDatabase*        db;
00364     dbTableDescriptor* table;
00365     dbCursorType       type;
00366     dbCursorType       defaultType;
00367     dbSelection        selection;
00368     bool               allRecords;
00369     oid_t              firstId;
00370     oid_t              lastId;
00371     oid_t              currId;
00372     byte*              record;
00373     size_t             limit;
00374 
00375     int4*              bitmap; // bitmap to avoid duplicates
00376     size_t             bitmapSize;
00377     bool               eliminateDuplicates;
00378     bool               prefetch;
00379     bool               removed; // current record was removed
00380     bool               lastRecordWasDeleted; //last record was deleted
00381 
00382     size_t             stmtLimitStart;
00383     size_t             stmtLimitLen;
00384     size_t             nSkipped;
00385 
00386     void*              paramBase;
00387     
00388     void checkForDuplicates();
00389     void deallocateBitmap();
00390 
00391     bool isMarked(oid_t oid) { 
00392         return bitmap != NULL && (bitmap[oid >> 5] & (1 << (oid & 31))) != 0;
00393     }
00394 
00395     void setStatementLimit(dbQuery const& q) { 
00396         stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
00397         stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
00398     }
00399 
00400     void truncateSelection() { 
00401         selection.truncate(stmtLimitStart, stmtLimitLen);
00402     }
00403 
00404     void mark(oid_t oid) { 
00405         if (bitmap != NULL) { 
00406             bitmap[oid >> 5] |= 1 << (oid & 31);
00407         }
00408     }    
00409 
00410     bool add(oid_t oid) { 
00411         if (selection.nRows < limit && selection.nRows < stmtLimitLen) { 
00412             if (nSkipped < stmtLimitStart) { 
00413                 nSkipped += 1;
00414                 return true;
00415             }
00416             if (eliminateDuplicates) { 
00417                 if (bitmap[oid >> 5] & (1 << (oid & 31))) { 
00418                     return true;
00419                 }
00420                 bitmap[oid >> 5] |= 1 << (oid & 31);
00421             } 
00422             selection.add(oid);
00423             return selection.nRows < limit;
00424         } 
00425         return false;
00426     }
00427 
00428     bool gotoNext();
00429     bool gotoPrev(); 
00430     bool gotoFirst();
00431     bool gotoLast();
00432     
00433     bool moveNext();
00434     bool movePrev();
00435 
00436     void setCurrent(dbAnyReference const& ref);
00437 
00438     void adjustReferences(size_t base, size_t size, long shift) { 
00439         if (currId != 0 && record != NULL) { 
00440             table->columns->adjustReferences(record, base, size, shift);
00441         }
00442     }
00443 
00444     dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec)
00445     : table(&aTable),type(aType),defaultType(aType),
00446       allRecords(false),currId(0),record(rec)
00447     {
00448         db = aTable.db;
00449         limit = dbDefaultSelectionLimit;
00450         prefetch = rec != NULL;
00451         removed = false;
00452         bitmap = NULL; 
00453         bitmapSize = 0;
00454         eliminateDuplicates = false;
00455         paramBase = NULL;
00456         stmtLimitLen = dbDefaultSelectionLimit;
00457         stmtLimitStart = 0;
00458         nSkipped = 0;
00459     }
00460   public:
00461     dbAnyCursor() 
00462     : table(NULL),type(dbCursorViewOnly),defaultType(dbCursorViewOnly),
00463           allRecords(false),currId(0),record(NULL)
00464     {
00465         limit = dbDefaultSelectionLimit;
00466         prefetch = false;
00467         removed = false;
00468         bitmap = NULL;
00469         bitmapSize = 0;
00470         eliminateDuplicates = false;
00471         db = NULL;
00472         paramBase = NULL;
00473         stmtLimitLen = dbDefaultSelectionLimit;
00474         stmtLimitStart = 0;
00475         nSkipped = 0;
00476     }
00477     ~dbAnyCursor();
00478 };
00479 
00480 
00484 template<class T>
00485 class dbCursor : public dbAnyCursor { 
00486   private:
00487     // Itis not possible to copy cursors
00488     dbCursor<T> operator = (dbCursor<T> const& src) { 
00489         return *this;
00490     } 
00491 
00492   protected:
00493     T record;
00494     
00495   public:
00500     dbCursor(dbCursorType type = dbCursorViewOnly) 
00501         : dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
00502 
00509     dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
00510         : dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
00511     {
00512         db = aDb;
00513         dbTableDescriptor* theTable = db->lookupTable(table);
00514         if (theTable != NULL) { 
00515             table = theTable;
00516         }
00517     }
00518 
00523     T* get() { 
00524         return currId == 0 ? (T*)NULL : &record; 
00525     }
00526     
00531     T* next() { 
00532         if (gotoNext()) { 
00533             fetch();
00534             return &record;
00535         }
00536         return NULL;
00537     }
00538 
00543     T* prev() { 
00544         if (gotoPrev()) { 
00545             fetch();
00546             return &record;
00547         }
00548         return NULL;
00549     }
00550 
00555     T* first() { 
00556         if (gotoFirst()) {
00557             fetch();
00558             return &record;
00559         }
00560         return NULL;
00561     }
00562 
00567     T* last() { 
00568         if (gotoLast()) {
00569             fetch();
00570             return &record;
00571         }
00572         return NULL;
00573     }    
00574     
00580     int seek(dbReference<T> const& ref) { 
00581         return dbAnyCursor::seek(ref.getOid());
00582     }
00583 
00588     T* operator ->() { 
00589         assert(currId != 0);
00590         return &record;
00591     }
00592 
00598     T* at(dbReference<T> const& ref) { 
00599         setCurrent(ref);
00600         return &record;
00601     }
00602     
00607     void toArray(dbArray< dbReference<T> >& arr) const { 
00608         arr.resize(selection.nRows);
00609         toArrayOfOid((oid_t*)arr.base());
00610     }
00611 
00616     dbReference<T> currentId() const { 
00617         return dbReference<T>(currId);
00618     }
00619 
00636     T* nextAvailable() { 
00637         if (!removed) { 
00638             return next(); 
00639         } else {
00640             removed = false;
00641             return lastRecordWasDeleted ? NULL : get();
00642         }
00643     }
00644 
00662     T* prevAvailable() { 
00663         if (!removed) { 
00664             return prev(); 
00665         } else {
00666             removed = false;
00667             return lastRecordWasDeleted ? get() : prev();
00668         }
00669     }
00670 
00675     bool isInSelection(dbReference<T>& ref) {
00676         return dbAnyCursor::isInSelection(ref.getOid());
00677     }
00678 };
00679 
00680 class dbParallelQueryContext { 
00681   public:
00682     dbDatabase* const      db;
00683     dbCompiledQuery* const query;
00684     oid_t                  firstRow;
00685     dbTable*               table;
00686     dbAnyCursor*           cursor;
00687     dbSelection            selection[dbMaxParallelSearchThreads];
00688 
00689     void search(int i); 
00690 
00691     dbParallelQueryContext(dbDatabase* aDb, dbTable* aTable, 
00692                            dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
00693       : db(aDb), query(aQuery), firstRow(aTable->firstRow), table(aTable), cursor(aCursor) {}
00694 };
00695 
00696 
00697 extern char* strupper(char* s);
00698 
00699 extern char* strlower(char* s);
00700 
00701 END_FASTDB_NAMESPACE
00702 
00703 #endif

Generated on Mon Oct 23 13:23:58 2006 for FastDB by doxygen1.2.18