00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __DATABASE_H__
00012 #define __DATABASE_H__
00013
00014 #include "class.h"
00015 #include "reference.h"
00016 #include "file.h"
00017 #include "pagepool.h"
00018
00019 BEGIN_GIGABASE_NAMESPACE
00020
00021 #if defined(_WINCE) || defined(__SYMBIAN32__)
00022
00025 const size_t dbDefaultInitIndexSize = 10*1024;
00026
00030 const size_t dbDefaultExtensionQuantum = 1*512*1024;
00031
00032 const size_t dbAllocationQuantumBits = 5;
00033 const size_t dbPageBits = 12;
00034 #else
00035
00038 const size_t dbDefaultInitIndexSize = 512*1024;
00039
00043 const size_t dbDefaultExtensionQuantum = 4*1024*1024;
00044 const size_t dbAllocationQuantumBits = 6;
00045 const size_t dbPageBits = 13;
00046 #endif
00047
00051 const unsigned dbMaxParallelSearchThreads = 64;
00052
00056 enum dbHandleFlags {
00057 dbPageObjectFlag = 0x1,
00058 dbModifiedFlag = 0x2,
00059 dbFreeHandleFlag = 0x4,
00060 dbFlagsMask = 0x7,
00061 dbFlagsBits = 3
00062 };
00063
00064 const size_t dbAllocationQuantum = 1 << dbAllocationQuantumBits;
00065 const size_t dbPageSize = 1 << dbPageBits;
00066 const size_t dbIdsPerPage = dbPageSize / sizeof(oid_t);
00067 const size_t dbHandlesPerPage = dbPageSize / sizeof(offs_t);
00068 const size_t dbHandleBits = 1 + sizeof(offs_t)/4;
00069 const size_t dbBitmapSegmentBits = dbPageBits + 3 + dbAllocationQuantumBits;
00070 const size_t dbBitmapSegmentSize = 1 << dbBitmapSegmentBits;
00071 const size_t dbBitmapPages = 1 << (dbDatabaseOffsetBits-dbBitmapSegmentBits);
00072 const size_t dbDirtyPageBitmapSize = 1 << (dbDatabaseOidBits-dbPageBits+dbHandleBits-3);
00073 const size_t dbDefaultSelectionLimit = 2000000000;
00078 const int dbBMsearchThreshold = 512;
00082 const size_t dbIndexedMergeThreshold = 100;
00083
00084
00085 const char_t dbMatchAnyOneChar = '_';
00086 const char_t dbMatchAnySubstring = '%';
00087
00088 const int dbMaxFileSegments = 64;
00089 const int dbTableHashSize = 1009;
00090
00094 enum dbPredefinedIds {
00095 dbInvalidId,
00096 dbMetaTableId,
00097 dbBitmapId,
00098 dbFirstUserId = dbBitmapId + dbBitmapPages
00099 };
00100
00104 enum dbLockType {
00105 dbNoLock,
00106 dbSharedLock,
00107 dbUpdateLock,
00108 dbExclusiveLock
00109 };
00110
00114 class dbHeader {
00115 public:
00116 int4 curr;
00117 int4 dirty;
00118 int4 initialized;
00119 #if dbDatabaseOffsetBits > 32 && defined(ALIGN_HEADER)
00120 int4 pad1;
00121 #endif
00122 struct {
00123 offs_t size;
00124 offs_t index;
00125 offs_t shadowIndex;
00126 #if dbDatabaseOffsetBits > 32 && dbDatabaseOidBits <= 32 && defined(ALIGN_HEADER)
00127 oid_t pad2;
00128 #endif
00129 oid_t indexSize;
00130 oid_t shadowIndexSize;
00131 oid_t indexUsed;
00132 oid_t freeList;
00133 oid_t bitmapEnd;
00134 #ifdef DO_NOT_REUSE_OID_WITHIN_SESSION
00135 struct {
00136 oid_t head;
00137 oid_t tail;
00138 } sessionFreeList;
00139 #endif
00140 } root[2];
00141
00142 int4 versionMajor;
00143 int4 versionMinor;
00144 int4 transactionId;
00145 int4 mode;
00146
00147 enum {
00148 MODE_ALIGN_HEADER = 0x01,
00149 MODE_OID_64 = 0x02,
00150 MODE_OFFS_64 = 0x04,
00151 MODE_UNICODE = 0x08,
00152 MODE_AUTOINCREMENT = 0x10,
00153 MODE_RECTANGLE_DIM = 0x20,
00154 MODE_DO_NOT_REUSE_OID = 0x40
00155 };
00156
00157 int getVersion() {
00158 return versionMajor*100 + versionMinor;
00159 }
00160
00161 bool isCompatible();
00162 static int getCurrentMode();
00163
00164 bool isInitialized() {
00165 return initialized == 1
00166 && (dirty == 1 || dirty == 0)
00167 && (curr == 1 || curr == 0)
00168 && root[curr].size > root[curr].index
00169 && root[curr].size > root[curr].shadowIndex
00170 && root[curr].size > root[curr].indexSize*sizeof(offs_t)
00171 + root[curr].shadowIndexSize*sizeof(offs_t)
00172 && root[curr].indexSize >= root[curr].indexUsed
00173 && root[curr].indexUsed >= dbFirstUserId
00174 && root[curr].bitmapEnd > dbBitmapId;
00175 }
00176 };
00177
00178 class dbSynthesizedAttribute;
00179 class dbInheritedAttribute;
00180 class dbDatabaseThreadContext;
00181 class dbSession;
00182
00183 struct dbMemoryStatistic {
00184 offs_t used;
00185 offs_t free;
00186 offs_t nHoles;
00187 offs_t minHoleSize;
00188 offs_t maxHoleSize;
00189 size_t nHolesOfSize[dbDatabaseOffsetBits];
00190 };
00191
00192 class dbMonitor {
00193 public:
00194 dbLockType accLock;
00195
00196 dbDatabaseThreadContext* firstPending;
00197 dbDatabaseThreadContext* lastPending;
00198
00199 int nLockUpgrades;
00200
00201 int nReaders;
00202 int nWriters;
00203 int backupInProgress;
00204
00205 void wait(dbLockType type, dbMutex& mutex, dbDatabaseThreadContext* ctx);
00206
00207 dbMonitor() {
00208 firstPending = lastPending = NULL;
00209 accLock = dbNoLock;
00210 backupInProgress = 0;
00211 nReaders = nWriters = 0;
00212 nLockUpgrades = 0;
00213 }
00214 };
00215
00216
00217
00218 class dbAnyCursor;
00219 class dbQuery;
00220 class dbExprNode;
00221 class dbSearchContext;
00222 class dbXmlContext;
00223 class dbXmlScanner;
00224
00225
00226 class dbVisitedObject {
00227 public:
00228 dbVisitedObject* next;
00229 oid_t oid;
00230
00231 dbVisitedObject(oid_t oid, dbVisitedObject* chain) {
00232 this->oid = oid;
00233 next = chain;
00234 }
00235 };
00236
00240 class dbTransactionLogger
00241 {
00242 public:
00251 virtual bool insert(dbTableDescriptor* table, oid_t oid, dbRecord const* dbsObj, void const* appObj) = 0;
00252
00261 virtual bool update(dbTableDescriptor* table, oid_t oid, dbRecord const* dbsObj, void const* appObj) = 0;
00262
00269 virtual bool remove(dbTableDescriptor* table, oid_t oid) = 0;
00270
00275 virtual bool commitPhase1() = 0;
00276
00280 virtual void commitPhase2() = 0;
00281
00285 virtual void rollback() = 0;
00286 };
00287
00291 class dbFileTransactionLogger : public dbTransactionLogger
00292 {
00293 dbOSFile log;
00294 char* buf;
00295 size_t used;
00296 size_t allocated;
00297 bool crc;
00298
00302 enum OperationKind {
00303 opInsert,
00304 opUpdate,
00305 opRemove
00306 };
00307 void append(OperationKind kind, dbTableDescriptor* table, oid_t oid, dbRecord const* body);
00308 char* extend(size_t size);
00309
00310 public:
00311 virtual bool insert(dbTableDescriptor* table, oid_t oid, dbRecord const* dbsObj, void const* appObj);
00312 virtual bool update(dbTableDescriptor* table, oid_t oid, dbRecord const* dbsObj, void const* appObj);
00313 virtual bool remove(dbTableDescriptor* table, oid_t oid);
00314
00315 virtual bool commitPhase1();
00316 virtual void commitPhase2();
00317 virtual void rollback();
00318
00319 dbFileTransactionLogger();
00320 virtual~dbFileTransactionLogger();
00321
00322
00329 bool open(char_t const* path, int flags = dbFile::no_sync, bool crc = true);
00330
00334 void close();
00335
00336 enum RestoreStatus
00337 {
00338 rsOK,
00339 rsCRCMismatch,
00340 rsReadFailed,
00341 rsTableNotFound,
00342 rsOIDMismatch
00343 };
00344
00351 RestoreStatus restore(dbDatabase& db, size_t& nTrans);
00352 };
00353
00357 class GIGABASE_DLL_ENTRY dbDatabase
00358 {
00359 friend class dbSession;
00360 friend class dbSelection;
00361 friend class dbAnyCursor;
00362 friend class dbHashTable;
00363 friend class dbQuery;
00364 friend class dbRtree;
00365 friend class dbRtreePage;
00366 friend class dbBtree;
00367 friend class dbBtreePage;
00368 friend class dbThickBtreePage;
00369 friend class dbInheritedAttribute;
00370 friend class dbParallelQueryContext;
00371 friend class dbServer;
00372 friend class dbPagePool;
00373
00374 friend class dbBlob;
00375 friend class dbBlobIterator;
00376 friend class dbBlobReadIterator;
00377 friend class dbBlobWriteIterator;
00378 friend class dbAnyContainer;
00379
00380 friend class dbGetTie;
00381 friend class dbPutTie;
00382
00383 friend class dbFileTransactionLogger;
00384
00385 friend class dbUserFunctionArgument;
00386
00387 friend class dbCLI;
00388 friend class GiSTdb;
00389
00390 friend class dbBtreeIterator;
00391 friend class dbRtreeIterator;
00392 friend class dbTableIterator;
00393 public:
00401 bool open(char_t const* databaseName, time_t transactionCommitDelay = 0, int openAttr = 0);
00402
00410 bool open(dbFile* file, time_t transactionCommitDelay = 0, bool deleteFileOnClose = false);
00411
00412 enum dbAccessType {
00413 dbReadOnly,
00414 dbAllAccess,
00415 dbMulticlientReadOnly,
00416 dbMulticlientReadWrite
00417 };
00418
00422 struct OpenParameters {
00426 char_t const* databaseName;
00427
00431 int openAttr;
00432
00436 dbFile* file;
00437
00441 time_t transactionCommitDelay;
00442
00446 bool deleteFileOnClose;
00447
00457 bool doNotReuseOidAfterClose;
00458
00464 bool preserveExistedIndices;
00465
00469 dbAccessType accessType;
00470
00477 size_t poolSize;
00478
00482 size_t extensionQuantum;
00483
00487 size_t initIndexSize;
00488
00492 int nThreads;
00493
00494
00499 offs_t freeSpaceReuseThreshold;
00500
00501 OpenParameters() {
00502 databaseName = NULL;
00503 openAttr = 0;
00504 file = NULL;
00505 transactionCommitDelay = 0;
00506 deleteFileOnClose = false;
00507 accessType = dbAllAccess;
00508 poolSize = 0;
00509 extensionQuantum = dbDefaultExtensionQuantum;
00510 initIndexSize = dbDefaultInitIndexSize;
00511 nThreads = 1;
00512 freeSpaceReuseThreshold = dbDefaultExtensionQuantum;
00513 doNotReuseOidAfterClose = false;
00514 preserveExistedIndices = false;
00515 }
00516 };
00517
00518
00524 bool open(OpenParameters& params);
00525
00526
00530 virtual void close();
00531
00535 void commit();
00536
00540 void executeBatch();
00541
00546 void precommit();
00547
00551 void rollback();
00552
00557 void attach();
00558
00564 void attach(dbDatabaseThreadContext* ctx);
00565
00566 enum DetachFlags {
00567 COMMIT = 1,
00568 DESTROY_CONTEXT = 2
00569 };
00574 void detach(int flags = COMMIT|DESTROY_CONTEXT);
00575
00580 void lock(dbLockType type = dbExclusiveLock) { beginTransaction(type); }
00581
00582 enum BackupFlags
00583 {
00584 BCK_COMPACTIFY = 1,
00585 BCK_INCREMENTAL = 2,
00586 BCK_HOLD_LOCK = 4
00587 };
00588
00595 bool backup(char_t const* backupFileName, int flags = 0);
00596
00604 bool backup(dbOSFile* file, int flags = 0);
00605
00612 bool restore(char_t const* backupFileName, char_t const* databaseFileName);
00613
00617 int getVersion();
00618
00623 void assign(dbTableDescriptor& desc) {
00624 assert(((void)"Table is not yet assigned to the database",
00625 desc.tableId == 0));
00626 desc.db = this;
00627 desc.fixedDatabase = true;
00628 }
00629
00636 dbTableDescriptor* lookupTable(dbTableDescriptor* desc);
00637
00642 void getMemoryStatistic(dbMemoryStatistic& stat);
00643
00651 void setConcurrency(unsigned nThreads);
00652
00657 soffs_t getAllocatedSize() { return allocatedSize; }
00658
00666 void allowColumnsDeletion(bool enabled = true) {
00667 confirmDeleteColumns = enabled;
00668 }
00669
00674 void enableInverseReferencesUpdate(bool enabled = true) {
00675 inverseReferencesUpdate = enabled;
00676 }
00677
00681 void disableOidReuseOnClose(bool disabled = true) {
00682 doNotReuseOidAfterClose = disabled;
00683 }
00684
00685
00693 bool prepareQuery(dbAnyCursor* cursor, dbQuery& query);
00694
00698 enum dbErrorClass {
00699 NoError,
00700 QueryError,
00701 ArithmeticError,
00702 IndexOutOfRangeError,
00703 DatabaseOpenError,
00704 FileError,
00705 OutOfMemoryError,
00706 Deadlock,
00707 NullReferenceError,
00708 FileLimitExeeded,
00709 DatabaseReadOnly,
00710 UniqueConstraintViolation,
00711 InconsistentInverseReference,
00712 OperationNotSupported,
00713 SocketError,
00714 CursorError,
00715 AccessToDeletedObject,
00716 IncompatibleSchemaChange,
00717 RejectedByTransactionLogger
00718 };
00719 static char const* const errorMessage[];
00720 typedef void (*dbErrorHandler)(int error, char const* msg, int msgarg, void* context);
00721
00728 dbErrorHandler setErrorHandler(dbErrorHandler newHandler, void* errorHandlerContext = NULL);
00729
00735 void setTransactionLogger(dbTransactionLogger* logger);
00736
00743 virtual void scheduleBackup(char_t const* fileName, time_t periodSec);
00744
00745
00753 virtual void handleError(dbErrorClass error, char const* msg = NULL,
00754 int arg = 0);
00755
00756 dbAccessType accessType;
00757 size_t extensionQuantum;
00758 size_t initIndexSize;
00759 offs_t freeSpaceReuseThreshold;
00760
00761 static unsigned dbParallelScanThreshold;
00762 dbTableDescriptor* tableHash[dbTableHashSize];
00763
00774 bool insertRecord(dbTableDescriptor* table, dbAnyReference* ref,
00775 void const* record, bool batch);
00780 offs_t used();
00781
00785 bool isOpen() const { return opened; }
00786
00793 offs_t getDatabaseSize() {
00794 return header->root[1-curr].size;
00795 }
00796
00803 void setFileExtensionQuantum(offs_t quantum) {
00804 dbFileExtensionQuantum = quantum;
00805 }
00806
00811 void setFileSizeLimit(offs_t limit) {
00812 dbFileSizeLimit = limit;
00813 }
00814
00826 void createCluster(offs_t size);
00827
00828
00829 #ifndef NO_MEMBER_TEMPLATES
00830
00836 template<class T>
00837 dbReference<T> insert(T const& record) {
00838 dbReference<T> ref;
00839 insertRecord(lookupTable(&T::dbDescriptor), &ref, &record, false);
00840 return ref;
00841 }
00848 template<class T>
00849 dbReference<T> batchInsert(T const& record) {
00850 dbReference<T> ref;
00851 insertRecord(lookupTable(&T::dbDescriptor), &ref, &record, true);
00852 return ref;
00853 }
00854 #endif
00855
00861 bool isValidOid(oid_t oid) {
00862 if (oid < dbFirstUserId || oid >= currIndexSize) {
00863 return false;
00864 }
00865 offs_t pos = getPos(oid);
00866 return !(pos & (dbFreeHandleFlag|dbPageObjectFlag));
00867 }
00868
00870 enum SelectionMethod {
00871 sel_all,
00872 sel_all_except,
00873 sel_named_only
00874 };
00875
00883 void exportDatabaseToXml(FILE* out, char_t const* const* tables, size_t nTables, SelectionMethod method);
00884
00894 void exportDatabaseToXml(FILE* out, char_t const* const* tables, size_t nTables, SelectionMethod method, char_t const* encoding);
00895
00901 bool importDatabaseFromXml(FILE* in);
00902
00903 #ifdef PROFILE
00904
00908 static void profile(char const* file);
00909
00914 static void profile(FILE* file);
00915 #endif
00916
00929 dbDatabase(dbAccessType type = dbAllAccess,
00930 size_t poolSize = 0,
00931 size_t dbExtensionQuantum = dbDefaultExtensionQuantum,
00932 size_t dbInitIndexSize = dbDefaultInitIndexSize,
00933 int nThreads = 1
00934
00935
00936
00937
00938 #ifdef NO_PTHREADS
00939 , bool usePthreads = false
00940 #endif
00941 );
00942
00946 virtual ~dbDatabase();
00947
00954 dbTableDescriptor* findTableByName(char_t const* name);
00955
00961 dbTableDescriptor* findTableByID(oid_t id);
00962
00967 dbTableDescriptor* getTables() {
00968 return tables;
00969 }
00970
00971 protected:
00972 dbThreadContext<dbDatabaseThreadContext> threadContext;
00973
00974 dbThreadPool threadPool;
00975
00976 dbHeader* header;
00977 int4* dirtyPagesMap;
00978 unsigned parThreads;
00979 bool modified;
00980
00981 int curr;
00982
00983
00984 int transactionId;
00985
00986 bool uncommittedChanges;
00987
00988 offs_t dbFileExtensionQuantum;
00989 offs_t dbFileSizeLimit;
00990
00991
00992 volatile int commitInProgress;
00993 volatile int concurrentTransId;
00994
00995 oid_t currRBitmapPage;
00996 size_t currRBitmapOffs;
00997
00998 oid_t currPBitmapPage;
00999 size_t currPBitmapOffs;
01000
01001
01002 struct dbLocation {
01003 offs_t pos;
01004 offs_t size;
01005 dbLocation* next;
01006 };
01007 dbLocation* reservedChain;
01008
01009 oid_t committedIndexSize;
01010 oid_t currIndexSize;
01011
01012 oid_t updatedRecordId;
01013
01014 dbFile* file;
01015 dbMutex mutex;
01016 dbSemaphore writeSem;
01017 dbSemaphore readSem;
01018 dbSemaphore upgradeSem;
01019 dbEvent backupCompletedEvent;
01020 dbMonitor monitor;
01021 dbPagePool pool;
01022 dbTableDescriptor* tables;
01023
01024 int* bitmapPageAvailableSpace;
01025 bool opened;
01026
01027 soffs_t allocatedSize;
01028 offs_t deallocatedSize;
01029
01030 int forceCommitCount;
01031 time_t commitDelay;
01032 time_t commitTimeout;
01033 time_t commitTimerStarted;
01034
01035 dbMutex commitThreadSyncMutex;
01036 dbMutex delayedCommitStartTimerMutex;
01037 dbMutex delayedCommitStopTimerMutex;
01038 dbEvent commitThreadSyncEvent;
01039
01040 dbEvent delayedCommitStartTimerEvent;
01041
01042 dbEvent delayedCommitStopTimerEvent;
01043 dbDatabaseThreadContext* delayedCommitContext;
01044
01045 dbMutex backupMutex;
01046 dbEvent backupInitEvent;
01047 char_t* backupFileName;
01048 time_t backupPeriod;
01049
01050 dbThread backupThread;
01051 dbThread commitThread;
01052
01053 dbTableDescriptor* batchList;
01054
01055 int accessCount;
01056
01057 dbL2List threadContextList;
01058 dbMutex threadContextListMutex;
01059
01060 dbErrorHandler errorHandler;
01061 void* errorHandlerContext;
01062
01063 dbTransactionLogger* logger;
01064
01065 bool confirmDeleteColumns;
01066 bool inverseReferencesUpdate;
01067
01068 int schemeVersion;
01069 dbVisitedObject* visitedChain;
01070
01071 int* btreeBuf;
01072 bool deleteFile;
01073 bool doNotReuseOidAfterClose;
01074 bool preserveExistedIndices;
01075 dbXmlContext* xmlContext;
01076
01077 int* dirtyPageBitmap;
01078 size_t dirtyPageBitmapSize;
01079
01080 oid_t mapId(long id);
01081 bool importField(char_t* terminator, dbFieldDescriptor* fd, byte* rec, dbXmlScanner& scanner);
01082 bool importRecord(char_t* terminator, dbFieldDescriptor* fieldList, byte* rec, dbXmlScanner& scanner);
01083 bool insertRecord(dbTableDescriptor* desc, oid_t oid, void const* record);
01084
01085
01091 dbTableDescriptor* loadMetaTable();
01092
01093 void releaseFile();
01094
01098 virtual void replicatePage(offs_t pageOffs, void* pageData);
01099
01103 void delayedCommit();
01104
01108 void backupScheduler();
01109
01110 static void thread_proc delayedCommitProc(void* arg) {
01111 ((dbDatabase*)arg)->delayedCommit();
01112 }
01113
01114 static void thread_proc backupSchedulerProc(void* arg) {
01115 ((dbDatabase*)arg)->backupScheduler();
01116 }
01117
01122 void commit(dbDatabaseThreadContext* ctx);
01123
01129 offs_t getPos(oid_t oid) {
01130 byte* p = pool.get(header->root[1-curr].index
01131 + (offs_t)(oid / dbHandlesPerPage) * dbPageSize);
01132 offs_t pos = *((offs_t*)p + oid % dbHandlesPerPage);
01133 pool.unfix(p);
01134 return pos;
01135 }
01136
01142 void setPos(oid_t oid, offs_t pos) {
01143 byte* p = pool.put(header->root[1-curr].index
01144 + (offs_t)(oid / dbHandlesPerPage) * dbPageSize);
01145 *((offs_t*)p + oid % dbHandlesPerPage) = pos;
01146 pool.unfix(p);
01147 }
01148
01155 dbRecord* getRow(dbGetTie& tie, oid_t oid) {
01156 offs_t pos = getPos(oid);
01157 if (pos & (dbFreeHandleFlag|dbPageObjectFlag)) {
01158 handleError(dbDatabase::AccessToDeletedObject);
01159 }
01160 tie.set(pool, pos & ~dbFlagsMask);
01161 return (dbRecord*)tie.get();
01162 }
01163
01171 dbRecord* getRow(dbGetTie& tie, oid_t oid, size_t size) {
01172 offs_t pos = getPos(oid);
01173 if (pos & (dbFreeHandleFlag|dbPageObjectFlag)) {
01174 handleError(dbDatabase::AccessToDeletedObject);
01175 }
01176 tie.set(pool, pos & ~dbFlagsMask, size);
01177 return (dbRecord*)tie.get();
01178 }
01179
01186 dbRecord* fetchRow(dbGetTie& tie, oid_t oid) {
01187 offs_t pos = getPos(oid);
01188 if (pos & (dbFreeHandleFlag|dbPageObjectFlag)) {
01189 handleError(dbDatabase::AccessToDeletedObject);
01190 }
01191 tie.fetch(pool, pos & ~dbFlagsMask);
01192 return (dbRecord*)tie.get();
01193 }
01194
01200 void getHeader(dbRecord& rec, oid_t oid) {
01201 offs_t pos = getPos(oid);
01202 int offs = (int)pos & (dbPageSize-1);
01203 byte* p = pool.get(pos - offs);
01204 rec = *(dbRecord*)(p + (offs & ~dbFlagsMask));
01205 pool.unfix(p);
01206 }
01207
01213 byte* put(oid_t oid) {
01214 offs_t pos = getPos(oid);
01215 int offs = (int)pos & (dbPageSize-1);
01216 return pool.put(pos-offs) + (offs & ~dbFlagsMask);
01217 }
01218
01224 byte* get(oid_t oid) {
01225 offs_t pos = getPos(oid);
01226 int offs = (int)pos & (dbPageSize-1);
01227 return pool.get(pos-offs) + (offs & ~dbFlagsMask);
01228 }
01229
01237 dbRecord* putRow(dbPutTie& tie, oid_t oid, size_t newSize);
01238
01245 dbRecord* putRow(dbPutTie& tie, oid_t oid);
01246
01253 byte* put(dbPutTie& tie, oid_t oid);
01254
01259 void restoreTablesConsistency();
01260
01266 void applyIndex(dbFieldDescriptor* field, dbSearchContext& sc);
01267
01275 bool isIndicesApplicable(dbAnyCursor* cursor, dbExprNode* expr, bool& unique);
01276
01292 bool applyIndices(dbAnyCursor* cursor, dbExprNode* expr, dbExprNode* topExpr, dbExprNode* filter,
01293 dbQuery& query, dbFieldDescriptor* &indexedField, bool& truncate, bool ascent);
01294
01302 bool isIndexApplicableToExpr(dbSearchContext& sc, dbExprNode* expr);
01303
01307 bool followInverseReference(dbExprNode* expr, dbExprNode* andExpr,
01308 dbAnyCursor* cursor, oid_t iref);
01309
01317 bool existsInverseReference(dbExprNode* expr, int nExistsClauses);
01318
01324 bool existsIndexedReference(dbExprNode* expr);
01325
01332 static void _fastcall execute(dbExprNode* expr,
01333 dbInheritedAttribute& iattr,
01334 dbSynthesizedAttribute& sattr);
01343 bool evaluateBoolean(dbExprNode* expr, oid_t oid, dbTableDescriptor* table, dbAnyCursor* cursor);
01344
01354 size_t evaluateString(dbExprNode* expr, oid_t oid, dbTableDescriptor* table, char_t* buf, size_t bufSize);
01355
01363 void evaluate(dbExprNode* expr, oid_t oid, dbTableDescriptor* table, dbSynthesizedAttribute& result);
01364
01369 void select(dbAnyCursor* cursor);
01370
01376 void select(dbAnyCursor* cursor, dbQuery& query);
01377
01383 void traverse(dbAnyCursor* cursor, dbQuery& query);
01384
01393 bool update(oid_t oid, dbTableDescriptor* table, void const* record);
01394
01400 void remove(dbTableDescriptor* table, oid_t oid);
01401
01409 offs_t allocate(offs_t size, oid_t oid = 0);
01410
01416 void free(offs_t pos, offs_t size);
01417
01422 void extend(offs_t size);
01423
01430 void cloneBitmap(offs_t pos, offs_t size);
01431
01436 oid_t allocateId();
01437
01442 void freeId(oid_t oid);
01443
01450 void updateCursors(oid_t oid, bool removed = false);
01451
01456 oid_t allocatePage() {
01457 oid_t oid = allocateId();
01458 setPos(oid, allocate(dbPageSize) | dbPageObjectFlag | dbModifiedFlag);
01459 return oid;
01460 }
01461
01466 void freePage(oid_t oid);
01467
01475 oid_t allocateRow(oid_t tableId, size_t size,
01476 dbTableDescriptor* desc = NULL)
01477 {
01478 oid_t oid = allocateId();
01479 allocateRow(tableId, oid, size, desc);
01480 return oid;
01481 }
01482
01491 void allocateRow(oid_t tableId, oid_t oid, size_t size, dbTableDescriptor* desc);
01492
01499 void freeRow(oid_t tableId, oid_t oid, dbTableDescriptor* desc = NULL);
01500
01505 static void deleteCompiledQuery(dbExprNode* tree);
01506
01511 void beginTransaction(dbLockType type);
01516 void endTransaction(dbDatabaseThreadContext* ctx);
01517
01521 void initializeMetaTable();
01522
01529 bool loadScheme();
01530
01536 bool completeDescriptorsInitialization();
01537
01543 void reformatTable(oid_t tableId, dbTableDescriptor* desc);
01544
01550 void addIndices(dbTableDescriptor* desc);
01551
01557 oid_t addNewTable(dbTableDescriptor* desc);
01558
01565 void updateTableDescriptor(dbTableDescriptor* desc,
01566 oid_t tableId, dbTable* table);
01567
01568
01574 void removeInverseReferences(dbTableDescriptor* desc, oid_t oid);
01575
01576
01585 void insertInverseReference(dbFieldDescriptor* desc, oid_t reverseId,
01586 oid_t targetId);
01587
01596 void removeInverseReference(dbFieldDescriptor* desc,
01597 oid_t reverseId, oid_t targetId);
01598
01603 void deleteTable(dbTableDescriptor* desc);
01604
01609 void dropTable(dbTableDescriptor* desc);
01610
01615 void createIndex(dbFieldDescriptor* fd);
01616
01621 void createHashTable(dbFieldDescriptor* fd);
01622
01627 void dropIndex(dbFieldDescriptor* fd);
01628
01633 void dropHashTable(dbFieldDescriptor* fd);
01634
01640 void linkTable(dbTableDescriptor* table, oid_t tableId);
01641
01646 void unlinkTable(dbTableDescriptor* table);
01647
01648
01655 bool wasReserved(offs_t pos, offs_t size);
01656
01665 void reserveLocation(dbLocation& location, offs_t pos, offs_t size);
01666
01671 void commitLocation();
01672
01678 dbTableDescriptor* findTable(char_t const* name);
01679
01680
01685 void cleanupOnOpenError();
01686
01690 void setDirty();
01691
01695 void refreshTable(dbTableDescriptor* desc);
01696 };
01697
01698 template<class T>
01699 dbReference<T> insert(T const& record) {
01700 dbReference<T> ref;
01701 T::dbDescriptor.getDatabase()->insertRecord(&T::dbDescriptor, &ref, &record, false);
01702 return ref;
01703 }
01704
01705 template<class T>
01706 dbReference<T> batchInsert(T const& record) {
01707 dbReference<T> ref;
01708 T::dbDescriptor.getDatabase()->insertRecord(&T::dbDescriptor, &ref, &record, true);
01709 return ref;
01710 }
01711
01712 #ifdef NO_MEMBER_TEMPLATES
01713 template<class T>
01714 dbReference<T> insert(dbDatabase& db, T const& record) {
01715 dbReference<T> ref;
01716 db.insertRecord(db.lookupTable(&T::dbDescriptor), &ref, &record, false);
01717 return ref;
01718 }
01719 template<class T>
01720 dbReference<T> batchInsert(dbDatabase& db, T const& record) {
01721 dbReference<T> ref;
01722 db.insertRecord(db.lookupTable(&T::dbDescriptor), &ref, &record, true);
01723 return ref;
01724 }
01725 #endif
01726
01727 class dbSearchContext {
01728 public:
01729 dbDatabase* db;
01730 dbExprNode* condition;
01731 dbAnyCursor* cursor;
01732 char_t* firstKey;
01733 int firstKeyInclusion;
01734 char_t* lastKey;
01735 int lastKeyInclusion;
01736 int prefixLength;
01737 int offs;
01738 int probes;
01739 bool ascent;
01740 bool tmpKeys;
01741 bool spatialSearch;
01742 bool arraySearch;
01743
01744 void operator = (dbSearchContext const& sc);
01745
01746 union {
01747 bool b;
01748 int1 i1;
01749 int2 i2;
01750 int4 i4;
01751 db_int8 i8;
01752 real4 f4;
01753 real8 f8;
01754 oid_t oid;
01755 void* raw;
01756 rectangle* rect;
01757 char_t* s;
01758 dbAnyArray* a;
01759 } literal[2];
01760 };
01761
01762 END_GIGABASE_NAMESPACE
01763
01764 #endif
01765