00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __CLASS_H__
00012 #define __CLASS_H__
00013
00014 #include "stdtp.h"
00015 #include "sync.h"
00016 #include "rectangle.h"
00017
00018 #ifdef USE_STD_STRING
00019 #include <string>
00020 #endif
00021
00022 BEGIN_FASTDB_NAMESPACE
00023
00024 #ifndef dbDatabaseOffsetBits
00025 #define dbDatabaseOffsetBits 32
00026 #endif
00027
00028 #ifndef dbDatabaseOidBits
00029 #define dbDatabaseOidBits 32
00030 #endif
00031
00035 #if dbDatabaseOidBits > 32
00036 typedef size_t oid_t;
00037 #else
00038 typedef nat4 oid_t;
00039 #endif
00040
00044 #if dbDatabaseOffsetBits > 32
00045 typedef size_t offs_t;
00046 #else
00047 typedef nat4 offs_t;
00048 #endif
00049
00053 enum dbIndexType {
00054 HASHED = 1,
00055 INDEXED = 2,
00056
00057 DB_FIELD_CASCADE_DELETE = 8,
00058
00059 AUTOINCREMENT = 16,
00060
00061 DB_TIMESTAMP = 256,
00062
00063 DB_FIELD_INHERITED_MASK = ~(HASHED|INDEXED)
00064 };
00065
00066
00070 #define KEY(x, index) \
00071 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00072 sizeof(x), index), x)
00073
00077 #define FIELD(x) KEY(x, 0)
00078
00082 typedef int (*dbUDTComparator)(void*, void*, size_t);
00083
00087 #define UDT(x, index, comparator) \
00088 *dbDescribeRawField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00089 sizeof(x), index), (dbUDTComparator)comparator)
00090
00094 #define RAWFIELD(x) UDT(x, 0, &memcmp)
00095
00099 #define RAWKEY(x, index) UDT(x, index, &memcmp)
00100
00106 #define RELATION(x,inverse) \
00107 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00108 sizeof(x), 0, #inverse), x)
00109
00115 #define INDEXED_RELATION(x,inverse) \
00116 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00117 sizeof(x), INDEXED, #inverse), x)
00118
00119
00125 #define OWNER(x,member) \
00126 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00127 sizeof(x), DB_FIELD_CASCADE_DELETE, \
00128 #member), x)
00129
00132 #define METHOD(x) \
00133 *dbDescribeMethod(new dbFieldDescriptor(#x), &self::x)
00134
00138 #define SUPERCLASS(x) \
00139 x::dbDescribeComponents(NULL)->adjustOffsets((char*)((x*)this)-(char*)this)
00140
00145 #define TYPE_DESCRIPTOR(fields) \
00146 dbFieldDescriptor* dbDescribeComponents(dbFieldDescriptor*) { \
00147 return &fields; \
00148 } \
00149 static dbTableDescriptor dbDescriptor
00150
00151
00157 #define CLASS_DESCRIPTOR(name, fields) \
00158 typedef name self; \
00159 dbFieldDescriptor* dbDescribeComponents(dbFieldDescriptor*) { \
00160 return &fields; \
00161 } \
00162 static dbTableDescriptor dbDescriptor
00163
00167 #define REGISTER_IN(table, database) \
00168 dbTableDescriptor* dbGetTableDescriptor(table*) \
00169 { return &table::dbDescriptor; } \
00170 static dbFieldDescriptor* dbDescribeComponentsOf##table() \
00171 { return ((table*)0)->dbDescribeComponents(NULL); } \
00172 dbTableDescriptor table::dbDescriptor(#table, database, sizeof(table), \
00173 &dbDescribeComponentsOf##table)
00174
00179 #define REGISTER(table) REGISTER_IN(table, NULL)
00180
00185 #define DETACHED_TABLE ((dbDatabase*)-1)
00186 #define REGISTER_UNASSIGNED(table) REGISTER_IN(table, DETACHED_TABLE)
00187
00188
00189 class dbTable;
00190 class dbDatabase;
00191 class dbAnyArray;
00192 class dbTableDescriptor;
00193 class dbAnyMethodTrampoline;
00194
00198 class FASTDB_DLL_ENTRY dbFieldDescriptor {
00199 public:
00203 dbFieldDescriptor* next;
00207 dbFieldDescriptor* prev;
00208
00212 dbFieldDescriptor* nextField;
00213
00217 dbFieldDescriptor* nextHashedField;
00218
00222 dbFieldDescriptor* nextIndexedField;
00223
00227 dbFieldDescriptor* nextInverseField;
00228
00232 int fieldNo;
00233
00237 char* name;
00238
00242 char* longName;
00243
00247 char* refTableName;
00248
00252 dbTableDescriptor* refTable;
00253
00257 dbTableDescriptor* defTable;
00258
00262 dbFieldDescriptor* inverseRef;
00263
00267 char* inverseRefName;
00268
00272 int type;
00273
00277 int appType;
00278
00282 int indexType;
00283
00287 int dbsOffs;
00288
00292 int appOffs;
00293
00297 dbFieldDescriptor* components;
00298
00302 oid_t hashTable;
00303
00307 oid_t tTree;
00308
00312 size_t dbsSize;
00313
00317 size_t appSize;
00318
00323 size_t alignment;
00324
00328 dbUDTComparator comparator;
00329
00333 enum FieldAttributes {
00334 ComponentOfArray = 0x01,
00335 HasArrayComponents = 0x02,
00336 OneToOneMapping = 0x04,
00337 Updated = 0x08
00338 };
00339 int attr;
00340
00344 int oldDbsType;
00348 int oldDbsOffs;
00352 int oldDbsSize;
00353
00357 dbAnyMethodTrampoline* method;
00358
00362 void (*arrayAllocator)(dbAnyArray* array, void* data, size_t length);
00363
00364
00375 size_t calculateRecordSize(byte* base, size_t offs);
00376
00386 size_t calculateNewRecordSize(byte* base, size_t offs);
00387
00397 size_t convertRecord(byte* dst, byte* src, size_t offs);
00398
00409 int sizeWithoutOneField(dbFieldDescriptor* field,
00410 byte* base, size_t& size);
00411
00421 size_t copyRecordExceptOneField(dbFieldDescriptor* field,
00422 byte* dst, byte* src, size_t offs);
00423
00434 size_t storeRecordFields(byte* dst, byte* src, size_t offs, bool insert);
00435
00443 void markUpdatedFields(byte* dst, byte* src);
00444
00452 void fetchRecordFields(byte* dst, byte* src);
00453
00462 void adjustReferences(byte* record, size_t base, size_t size, long shift);
00463
00469 dbFieldDescriptor* find(const char* name);
00470
00475 dbFieldDescriptor* getFirstComponent() {
00476 return components;
00477 }
00478
00483 dbFieldDescriptor* getNextComponent(dbFieldDescriptor* field) {
00484 if (field != NULL) {
00485 field = field->next;
00486 if (field == components) {
00487 return NULL;
00488 }
00489 }
00490 return field;
00491 }
00492
00496 dbFieldDescriptor& operator, (dbFieldDescriptor& field) {
00497 dbFieldDescriptor* tail = field.prev;
00498 tail->next = this;
00499 prev->next = &field;
00500 field.prev = prev;
00501 prev = tail;
00502 return *this;
00503 }
00504
00505 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS);
00506 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
00507
00511 dbFieldDescriptor& adjustOffsets(long offs);
00512
00522 dbFieldDescriptor(char const* name, size_t offs, size_t size, int indexType,
00523 char const* inverse = NULL,
00524 dbFieldDescriptor* components = NULL);
00525
00530 dbFieldDescriptor(char const* name);
00531
00535 ~dbFieldDescriptor();
00536 };
00537
00538
00542 class FASTDB_DLL_ENTRY dbTableDescriptor {
00543 friend class dbCompiler;
00544 friend class dbDatabase;
00545 friend class dbReplicatedDatabase;
00546 friend class dbTable;
00547 friend class dbAnyCursor;
00548 friend class dbSubSql;
00549 friend class dbHashTable;
00550 friend class dbTtreeNode;
00551 friend class dbRtreePage;
00552 friend class dbServer;
00553 friend class dbColumnBinding;
00554 friend class dbFieldDescriptor;
00555 friend class dbAnyContainer;
00556 friend class dbCLI;
00557 friend class dbSelection;
00558 protected:
00562 dbTableDescriptor* next;
00563 static dbTableDescriptor* chain;
00564
00568 dbTableDescriptor* nextDbTable;
00569
00573 char* name;
00574
00578 oid_t tableId;
00579
00583 dbFieldDescriptor* columns;
00584
00588 dbFieldDescriptor* hashedFields;
00589
00593 dbFieldDescriptor* indexedFields;
00594
00598 dbFieldDescriptor* inverseFields;
00599
00603 dbFieldDescriptor* firstField;
00604
00608 dbFieldDescriptor** nextFieldLink;
00609
00613 dbDatabase* db;
00614
00618 bool fixedDatabase;
00619
00623 bool isStatic;
00624
00628 size_t appSize;
00629
00633 size_t fixedSize;
00634
00638 size_t nFields;
00639
00643 size_t nColumns;
00644
00648 int4 autoincrementCount;
00649
00650
00656 dbTableDescriptor* cloneOf;
00657
00658
00662 typedef dbFieldDescriptor* (*describeFunc)();
00663 describeFunc describeComponentsFunc;
00664
00668 dbTableDescriptor* clone();
00669
00673 size_t totalNamesLength();
00674
00686 int calculateFieldsAttributes(dbFieldDescriptor* fieldsList,
00687 char const* prefix, int offs,
00688 int indexMask, int& attr);
00689
00698 dbFieldDescriptor* buildFieldsList(dbTable* table, char const* prefix, int prefixLen, int& attr);
00699
00700 public:
00705 static int initialAutoincrementCount;
00706
00710 dbTableDescriptor* getNextTable() {
00711 return nextDbTable;
00712 }
00713
00717 dbFieldDescriptor* findSymbol(char const* name);
00718
00719
00723 dbFieldDescriptor* find(char const* name);
00724
00725
00730 dbFieldDescriptor* getFirstField() {
00731 return columns;
00732 }
00733
00738 int getLastValueOfAutoincrementCount() const {
00739 return autoincrementCount;
00740 }
00741
00747 dbFieldDescriptor* getNextField(dbFieldDescriptor* field) {
00748 if (field != NULL) {
00749 field = field->next;
00750 if (field == columns) {
00751 return NULL;
00752 }
00753 }
00754 return field;
00755 }
00756
00760 char* getName() {
00761 return name;
00762 }
00763
00767 size_t size() {
00768 return appSize;
00769 }
00770
00775 void setFlags();
00776
00783 bool equal(dbTable* table);
00784
00793 bool match(dbTable* table, bool confirmDeleteColumns);
00794
00800 void checkRelationship();
00801
00806 dbDatabase* getDatabase() {
00807 assert(db != DETACHED_TABLE);
00808 return db;
00809 }
00810
00815 void storeInDatabase(dbTable* table);
00816
00820 static void cleanup();
00821
00826 dbTableDescriptor(dbTable* table);
00827
00836 dbTableDescriptor(char const* tableName, dbDatabase* db, size_t objSize,
00837 describeFunc func, dbTableDescriptor* original = NULL);
00838
00842 ~dbTableDescriptor();
00843 };
00844
00848 struct dbVarying {
00849 nat4 size;
00850 int4 offs;
00851 };
00852
00856 struct dbField {
00857 enum FieldTypes {
00858 tpBool,
00859 tpInt1,
00860 tpInt2,
00861 tpInt4,
00862 tpInt8,
00863 tpReal4,
00864 tpReal8,
00865 tpString,
00866 tpReference,
00867 tpArray,
00868 tpMethodBool,
00869 tpMethodInt1,
00870 tpMethodInt2,
00871 tpMethodInt4,
00872 tpMethodInt8,
00873 tpMethodReal4,
00874 tpMethodReal8,
00875 tpMethodString,
00876 tpMethodReference,
00877 tpStructure,
00878 tpRawBinary,
00879 tpStdString,
00880 tpRectangle,
00881 tpUnknown
00882 };
00883
00887 dbVarying name;
00888
00892 dbVarying tableName;
00893
00897 dbVarying inverse;
00898
00902 #ifdef OLD_FIELD_DESCRIPTOR_FORMAT
00903 int4 type;
00904 #else
00905 #if BYTE_ORDER == BIG_ENDIAN
00906 int4 flags : 24;
00907 int4 type : 8;
00908 #else
00909 int4 type : 8;
00910 int4 flags : 24;
00911 #endif
00912 #endif
00913
00917 int4 offset;
00918
00922 nat4 size;
00923
00927 oid_t hashTable;
00928
00932 oid_t tTree;
00933 };
00934
00935
00939 class dbRecord {
00940 public:
00944 nat4 size;
00945
00949 oid_t next;
00950
00954 oid_t prev;
00955 };
00956
00957
00961 class dbTable : public dbRecord {
00962 public:
00966 dbVarying name;
00967
00971 dbVarying fields;
00972
00976 nat4 fixedSize;
00977
00981 nat4 nRows;
00982
00986 nat4 nColumns;
00987
00991 oid_t firstRow;
00992
00996 oid_t lastRow;
00997 #ifdef AUTOINCREMENT_SUPPORT
00998
01001 nat4 count;
01002 #endif
01003 };
01004
01005 inline dbFieldDescriptor* dbDescribeRawField(dbFieldDescriptor* fd, dbUDTComparator comparator)
01006 {
01007 fd->type = fd->appType = dbField::tpRawBinary;
01008 fd->alignment = 1;
01009 fd->comparator = comparator;
01010 return fd;
01011 }
01012
01013
01014 template<class T>
01015 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, T& x)
01016 {
01017 fd->type = fd->appType = dbField::tpStructure;
01018 fd->components = x.dbDescribeComponents(fd);
01019 return fd;
01020 }
01021
01022 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int1&)
01023 {
01024 fd->type = fd->appType = dbField::tpInt1;
01025 return fd;
01026 }
01027 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int2&)
01028 {
01029 fd->type = fd->appType = dbField::tpInt2;
01030 return fd;
01031 }
01032 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int4&)
01033 {
01034 fd->type = fd->appType = dbField::tpInt4;
01035 return fd;
01036 }
01037 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, db_int8&)
01038 {
01039 fd->type = fd->appType = dbField::tpInt8;
01040 return fd;
01041 }
01042 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat1&)
01043 {
01044 fd->type = fd->appType = dbField::tpInt1;
01045 return fd;
01046 }
01047 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat2&)
01048 {
01049 fd->type = fd->appType = dbField::tpInt2;
01050 return fd;
01051 }
01052 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat4&)
01053 {
01054 fd->type = fd->appType = dbField::tpInt4;
01055 return fd;
01056 }
01057 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat8&)
01058 {
01059 fd->type = fd->appType = dbField::tpInt8;
01060 return fd;
01061 }
01062 #if SIZEOF_LONG != 8
01063 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, long&)
01064 {
01065 fd->type = fd->appType = dbField::tpInt4;
01066 return fd;
01067 }
01068 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, unsigned long&)
01069 {
01070 fd->type = fd->appType = dbField::tpInt4;
01071 return fd;
01072 }
01073 #endif
01074 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, bool&)
01075 {
01076 fd->type = fd->appType = dbField::tpBool;
01077 return fd;
01078 }
01079 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real4&)
01080 {
01081 fd->type = fd->appType = dbField::tpReal4;
01082 return fd;
01083 }
01084 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real8&)
01085 {
01086 fd->type = fd->appType = dbField::tpReal8;
01087 return fd;
01088 }
01089 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, rectangle&)
01090 {
01091 fd->type = fd->appType = dbField::tpRectangle;
01092 fd->alignment = sizeof(coord_t);
01093 return fd;
01094 }
01095 #ifdef USE_STD_STRING
01096 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, std::string&)
01097 {
01098 fd->type = dbField::tpString;
01099 fd->appType = dbField::tpStdString;
01100 fd->dbsSize = sizeof(dbVarying);
01101 fd->alignment = 4;
01102 fd->components = new dbFieldDescriptor("[]");
01103 fd->components->type = fd->components->appType = dbField::tpInt1;
01104 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = 1;
01105 return fd;
01106 }
01107 #endif
01108 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char const*&)
01109 {
01110 fd->type = fd->appType = dbField::tpString;
01111 fd->dbsSize = sizeof(dbVarying);
01112 fd->alignment = 4;
01113 fd->components = new dbFieldDescriptor("[]");
01114 fd->components->type = fd->components->appType = dbField::tpInt1;
01115 fd->components->dbsSize = fd->components->appSize = 1;
01116 fd->components->alignment = 1;
01117 return fd;
01118 }
01119 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char*&)
01120 {
01121 fd->type = fd->appType = dbField::tpString;
01122 fd->dbsSize = sizeof(dbVarying);
01123 fd->alignment = 4;
01124 fd->components = new dbFieldDescriptor("[]");
01125 fd->components->type = fd->components->appType = dbField::tpInt1;
01126 fd->components->dbsSize = fd->components->appSize = 1;
01127 fd->components->alignment = 1;
01128 return fd;
01129 }
01130
01131
01135 class FASTDB_DLL_ENTRY dbAnyMethodTrampoline {
01136 public:
01137 dbFieldDescriptor* cls;
01138
01144 virtual void invoke(byte* data, void* result) = 0;
01145
01152 virtual dbAnyMethodTrampoline* optimize() = 0;
01153
01158 dbAnyMethodTrampoline(dbFieldDescriptor* fd) { cls = fd; }
01159
01160 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS);
01161 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
01162
01166 virtual~dbAnyMethodTrampoline();
01167 };
01168
01169
01170 #if defined(__APPLE__) || defined(__VACPP_MULTI__) || defined(__IBMCPP__) || defined(__HP_aCC) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x510 && __SUNPRO_CC_COMPAT == 5)
01171
01174 template<class T, class R>
01175 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01176 public:
01177 typedef R (T::*mfunc)();
01178
01179 mfunc method;
01180 dbFieldDescriptor* cls;
01181 bool optimized;
01182
01183 void invoke(byte* data, void* result) {
01184 if (optimized) {
01185 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01186 } else {
01187 T rec;
01188 this->cls->components->fetchRecordFields((byte*)&rec, data);
01189 *(R*)result = (rec.*method)();
01190 }
01191 }
01192 dbAnyMethodTrampoline* optimize() {
01193 optimized = true;
01194 return this;
01195 }
01196
01197 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01198 : dbAnyMethodTrampoline(fd)
01199 {
01200 this->method = f;
01201 this->cls = fd;
01202 this->optimized = false;
01203 }
01204 };
01205
01206 #else
01207
01211 template<class T, class R>
01212 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01213 public:
01214 typedef R (T::*mfunc)();
01215 mfunc method;
01216 void invoke(byte* data, void* result) {
01217 T rec;
01218 this->cls->components->fetchRecordFields((byte*)&rec, data);
01219 *(R*)result = (rec.*method)();
01220 }
01221 dbAnyMethodTrampoline* optimize();
01222
01223 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01224 : dbAnyMethodTrampoline(fd), method(f) {}
01225 };
01226
01227
01232 template<class T, class R>
01233 class dbMethodFastTrampoline : public dbAnyMethodTrampoline {
01234 typedef R (T::*mfunc)();
01235 mfunc method;
01236 public:
01237 dbAnyMethodTrampoline* optimize() {
01238 return this;
01239 }
01240 void invoke(byte* data, void* result) {
01241 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01242 }
01243 dbMethodFastTrampoline(dbMethodTrampoline<T,R>* mt)
01244 : dbAnyMethodTrampoline(mt->cls), method(mt->method) {
01245 delete mt;
01246 }
01247 };
01248
01249 template<class T, class R>
01250 inline dbAnyMethodTrampoline* dbMethodTrampoline<T,R>::optimize() {
01251 return new dbMethodFastTrampoline<T,R>(this);
01252 }
01253
01254 #endif
01255
01256 template<class T, class R>
01257 inline dbFieldDescriptor* dbDescribeMethod(dbFieldDescriptor* fd, R (T::*p)())
01258 {
01259 R ret;
01260 dbDescribeField(fd, ret);
01261 assert(fd->type <= dbField::tpReference);
01262 fd->appType = fd->type += dbField::tpMethodBool;
01263 fd->method = new dbMethodTrampoline<T,R>(fd, p);
01264 return fd;
01265 }
01266
01267 END_FASTDB_NAMESPACE
01268
01269 #endif
01270
01271