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 *FASTDB_NS::dbDescribeField(new FASTDB_NS::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 *FASTDB_NS::dbDescribeRawField(new FASTDB_NS::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 *FASTDB_NS::dbDescribeField(new FASTDB_NS::dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00108 sizeof(x), 0, #inverse), x)
00109
00115 #define INDEXED_RELATION(x,inverse) \
00116 *FASTDB_NS::dbDescribeField(new FASTDB_NS::dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00117 sizeof(x), FASTDB_NS::INDEXED, #inverse), x)
00118
00119
00125 #define OWNER(x,member) \
00126 *FASTDB_NS::dbDescribeField(new FASTDB_NS::dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00127 sizeof(x), FASTDB_NS::DB_FIELD_CASCADE_DELETE, \
00128 #member), x)
00129
00132 #define METHOD(x) \
00133 *FASTDB_NS::dbDescribeMethod(new FASTDB_NS::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 FASTDB_NS::dbFieldDescriptor* dbDescribeComponents(FASTDB_NS::dbFieldDescriptor*) { \
00147 return &fields; \
00148 } \
00149 static FASTDB_NS::dbTableDescriptor dbDescriptor
00150
00151
00157 #define CLASS_DESCRIPTOR(name, fields) \
00158 typedef name self; \
00159 FASTDB_NS::dbFieldDescriptor* dbDescribeComponents(FASTDB_NS::dbFieldDescriptor*) { \
00160 return &fields; \
00161 } \
00162 static FASTDB_NS::dbTableDescriptor dbDescriptor
00163
00167 #define REGISTER_IN(table, database) \
00168 FASTDB_NS::dbTableDescriptor* dbGetTableDescriptor(table*) \
00169 { return &table::dbDescriptor; } \
00170 static FASTDB_NS::dbFieldDescriptor* dbDescribeComponentsOf##table() \
00171 { return ((table*)0)->dbDescribeComponents(NULL); } \
00172 FASTDB_NS::dbTableDescriptor table::dbDescriptor(#table, database, sizeof(table), \
00173 &dbDescribeComponentsOf##table)
00174
00179 #define REGISTER(table) REGISTER_IN(table, NULL)
00180
00185 #define DETACHED_TABLE ((FASTDB_NS::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
00424 enum StoreMode {
00425 Insert,
00426 Update,
00427 Import
00428 };
00429
00440 size_t storeRecordFields(byte* dst, byte* src, size_t offs, StoreMode mode);
00441
00449 void markUpdatedFields(byte* dst, byte* src);
00450
00458 void fetchRecordFields(byte* dst, byte* src);
00459
00468 void adjustReferences(byte* record, size_t base, size_t size, long shift);
00469
00475 dbFieldDescriptor* find(const char* name);
00476
00481 dbFieldDescriptor* getFirstComponent() {
00482 return components;
00483 }
00484
00489 dbFieldDescriptor* getNextComponent(dbFieldDescriptor* field) {
00490 if (field != NULL) {
00491 field = field->next;
00492 if (field == components) {
00493 return NULL;
00494 }
00495 }
00496 return field;
00497 }
00498
00502 dbFieldDescriptor& operator, (dbFieldDescriptor& field) {
00503 dbFieldDescriptor* tail = field.prev;
00504 tail->next = this;
00505 prev->next = &field;
00506 field.prev = prev;
00507 prev = tail;
00508 return *this;
00509 }
00510
00511 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS);
00512 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
00513
00517 dbFieldDescriptor& adjustOffsets(long offs);
00518
00528 dbFieldDescriptor(char const* name, size_t offs, size_t size, int indexType,
00529 char const* inverse = NULL,
00530 dbFieldDescriptor* components = NULL);
00531
00536 dbFieldDescriptor(char const* name);
00537
00541 ~dbFieldDescriptor();
00542 };
00543
00544
00548 class FASTDB_DLL_ENTRY dbTableDescriptor {
00549 friend class dbCompiler;
00550 friend class dbDatabase;
00551 friend class dbReplicatedDatabase;
00552 friend class dbTable;
00553 friend class dbAnyCursor;
00554 friend class dbSubSql;
00555 friend class dbHashTable;
00556 friend class dbTtreeNode;
00557 friend class dbRtreePage;
00558 friend class dbServer;
00559 friend class dbColumnBinding;
00560 friend class dbFieldDescriptor;
00561 friend class dbAnyContainer;
00562 friend class dbCLI;
00563 friend class dbSelection;
00564 protected:
00568 dbTableDescriptor* next;
00569 static dbTableDescriptor* chain;
00570
00574 dbTableDescriptor* nextDbTable;
00575
00579 char* name;
00580
00584 oid_t tableId;
00585
00589 dbFieldDescriptor* columns;
00590
00594 dbFieldDescriptor* hashedFields;
00595
00599 dbFieldDescriptor* indexedFields;
00600
00604 dbFieldDescriptor* inverseFields;
00605
00609 dbFieldDescriptor* firstField;
00610
00614 dbFieldDescriptor** nextFieldLink;
00615
00619 dbDatabase* db;
00620
00624 bool fixedDatabase;
00625
00629 bool isStatic;
00630
00634 size_t appSize;
00635
00639 size_t fixedSize;
00640
00644 size_t nFields;
00645
00649 size_t nColumns;
00650
00654 int4 autoincrementCount;
00655
00656
00662 dbTableDescriptor* cloneOf;
00663
00664
00668 typedef dbFieldDescriptor* (*describeFunc)();
00669 describeFunc describeComponentsFunc;
00670
00674 dbTableDescriptor* collisionChain;
00675
00679 dbTableDescriptor* clone();
00680
00684 size_t totalNamesLength();
00685
00697 int calculateFieldsAttributes(dbFieldDescriptor* fieldsList,
00698 char const* prefix, int offs,
00699 int indexMask, int& attr);
00700
00709 dbFieldDescriptor* buildFieldsList(dbTable* table, char const* prefix, int prefixLen, int& attr);
00710
00711 public:
00716 static int initialAutoincrementCount;
00717
00721 dbTableDescriptor* getNextTable() {
00722 return nextDbTable;
00723 }
00724
00728 dbFieldDescriptor* findSymbol(char const* name);
00729
00730
00734 dbFieldDescriptor* find(char const* name);
00735
00736
00741 dbFieldDescriptor* getFirstField() {
00742 return columns;
00743 }
00744
00749 int getLastValueOfAutoincrementCount() const {
00750 return autoincrementCount;
00751 }
00752
00758 dbFieldDescriptor* getNextField(dbFieldDescriptor* field) {
00759 if (field != NULL) {
00760 field = field->next;
00761 if (field == columns) {
00762 return NULL;
00763 }
00764 }
00765 return field;
00766 }
00767
00771 char* getName() {
00772 return name;
00773 }
00774
00778 size_t size() {
00779 return appSize;
00780 }
00781
00786 void setFlags();
00787
00794 bool equal(dbTable* table);
00795
00804 bool match(dbTable* table, bool confirmDeleteColumns);
00805
00811 void checkRelationship();
00812
00817 dbDatabase* getDatabase() {
00818 assert(db != DETACHED_TABLE);
00819 return db;
00820 }
00821
00826 void storeInDatabase(dbTable* table);
00827
00831 static void cleanup();
00832
00837 dbTableDescriptor(dbTable* table);
00838
00847 dbTableDescriptor(char const* tableName, dbDatabase* db, size_t objSize,
00848 describeFunc func, dbTableDescriptor* original = NULL);
00849
00853 ~dbTableDescriptor();
00854 };
00855
00859 struct dbVarying {
00860 nat4 size;
00861 int4 offs;
00862 };
00863
00867 struct dbField {
00868 enum FieldTypes {
00869 tpBool,
00870 tpInt1,
00871 tpInt2,
00872 tpInt4,
00873 tpInt8,
00874 tpReal4,
00875 tpReal8,
00876 tpString,
00877 tpReference,
00878 tpArray,
00879 tpMethodBool,
00880 tpMethodInt1,
00881 tpMethodInt2,
00882 tpMethodInt4,
00883 tpMethodInt8,
00884 tpMethodReal4,
00885 tpMethodReal8,
00886 tpMethodString,
00887 tpMethodReference,
00888 tpStructure,
00889 tpRawBinary,
00890 tpStdString,
00891 tpRectangle,
00892 tpUnknown
00893 };
00894
00898 dbVarying name;
00899
00903 dbVarying tableName;
00904
00908 dbVarying inverse;
00909
00913 #ifdef OLD_FIELD_DESCRIPTOR_FORMAT
00914 int4 type;
00915 #else
00916 #if BYTE_ORDER == BIG_ENDIAN
00917 int4 flags : 24;
00918 int4 type : 8;
00919 #else
00920 int4 type : 8;
00921 int4 flags : 24;
00922 #endif
00923 #endif
00924
00928 int4 offset;
00929
00933 nat4 size;
00934
00938 oid_t hashTable;
00939
00943 oid_t tTree;
00944 };
00945
00946
00950 class dbRecord {
00951 public:
00955 nat4 size;
00956
00960 oid_t next;
00961
00965 oid_t prev;
00966 };
00967
00968
00972 class dbTable : public dbRecord {
00973 public:
00977 dbVarying name;
00978
00982 dbVarying fields;
00983
00987 nat4 fixedSize;
00988
00992 nat4 nRows;
00993
00997 nat4 nColumns;
00998
01002 oid_t firstRow;
01003
01007 oid_t lastRow;
01008 #ifdef AUTOINCREMENT_SUPPORT
01009
01012 nat4 count;
01013 #endif
01014 };
01015
01016 inline dbFieldDescriptor* dbDescribeRawField(dbFieldDescriptor* fd, dbUDTComparator comparator)
01017 {
01018 fd->type = fd->appType = dbField::tpRawBinary;
01019 fd->alignment = 1;
01020 fd->comparator = comparator;
01021 return fd;
01022 }
01023
01024
01025 template<class T>
01026 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, T& x)
01027 {
01028 fd->type = fd->appType = dbField::tpStructure;
01029 fd->components = x.dbDescribeComponents(fd);
01030 return fd;
01031 }
01032
01033 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int1&)
01034 {
01035 fd->type = fd->appType = dbField::tpInt1;
01036 return fd;
01037 }
01038 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int2&)
01039 {
01040 fd->type = fd->appType = dbField::tpInt2;
01041 return fd;
01042 }
01043 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int4&)
01044 {
01045 fd->type = fd->appType = dbField::tpInt4;
01046 return fd;
01047 }
01048 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, db_int8&)
01049 {
01050 fd->type = fd->appType = dbField::tpInt8;
01051 return fd;
01052 }
01053 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat1&)
01054 {
01055 fd->type = fd->appType = dbField::tpInt1;
01056 return fd;
01057 }
01058 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat2&)
01059 {
01060 fd->type = fd->appType = dbField::tpInt2;
01061 return fd;
01062 }
01063 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat4&)
01064 {
01065 fd->type = fd->appType = dbField::tpInt4;
01066 return fd;
01067 }
01068 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat8&)
01069 {
01070 fd->type = fd->appType = dbField::tpInt8;
01071 return fd;
01072 }
01073 #if SIZEOF_LONG != 8
01074 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, long&)
01075 {
01076 fd->type = fd->appType = dbField::tpInt4;
01077 return fd;
01078 }
01079 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, unsigned long&)
01080 {
01081 fd->type = fd->appType = dbField::tpInt4;
01082 return fd;
01083 }
01084 #endif
01085 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, bool&)
01086 {
01087 fd->type = fd->appType = dbField::tpBool;
01088 return fd;
01089 }
01090 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real4&)
01091 {
01092 fd->type = fd->appType = dbField::tpReal4;
01093 return fd;
01094 }
01095 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real8&)
01096 {
01097 fd->type = fd->appType = dbField::tpReal8;
01098 return fd;
01099 }
01100 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, rectangle&)
01101 {
01102 fd->type = fd->appType = dbField::tpRectangle;
01103 fd->alignment = sizeof(coord_t);
01104 return fd;
01105 }
01106 #ifdef USE_STD_STRING
01107 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, std::string&)
01108 {
01109 fd->type = dbField::tpString;
01110 fd->appType = dbField::tpStdString;
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 = fd->components->alignment = 1;
01116 return fd;
01117 }
01118 #endif
01119 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char const*&)
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 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char*&)
01131 {
01132 fd->type = fd->appType = dbField::tpString;
01133 fd->dbsSize = sizeof(dbVarying);
01134 fd->alignment = 4;
01135 fd->components = new dbFieldDescriptor("[]");
01136 fd->components->type = fd->components->appType = dbField::tpInt1;
01137 fd->components->dbsSize = fd->components->appSize = 1;
01138 fd->components->alignment = 1;
01139 return fd;
01140 }
01141
01142
01146 class FASTDB_DLL_ENTRY dbAnyMethodTrampoline {
01147 public:
01148 dbFieldDescriptor* cls;
01149
01155 virtual void invoke(byte* data, void* result) = 0;
01156
01163 virtual dbAnyMethodTrampoline* optimize() = 0;
01164
01169 dbAnyMethodTrampoline(dbFieldDescriptor* fd) { cls = fd; }
01170
01171 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS);
01172 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
01173
01177 virtual~dbAnyMethodTrampoline();
01178 };
01179
01180
01181 #if defined(__APPLE__) || defined(__VACPP_MULTI__) || defined(__IBMCPP__) || defined(__HP_aCC) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x510 && __SUNPRO_CC_COMPAT == 5)
01182
01185 template<class T, class R>
01186 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01187 public:
01188 typedef R (T::*mfunc)();
01189
01190 mfunc method;
01191 dbFieldDescriptor* cls;
01192 bool optimized;
01193
01194 void invoke(byte* data, void* result) {
01195 if (optimized) {
01196 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01197 } else {
01198 T rec;
01199 this->cls->components->fetchRecordFields((byte*)&rec, data);
01200 *(R*)result = (rec.*method)();
01201 }
01202 }
01203 dbAnyMethodTrampoline* optimize() {
01204 optimized = true;
01205 return this;
01206 }
01207
01208 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01209 : dbAnyMethodTrampoline(fd)
01210 {
01211 this->method = f;
01212 this->cls = fd;
01213 this->optimized = false;
01214 }
01215 };
01216
01217 #else
01218
01222 template<class T, class R>
01223 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01224 public:
01225 typedef R (T::*mfunc)();
01226 mfunc method;
01227 void invoke(byte* data, void* result) {
01228 T rec;
01229 this->cls->components->fetchRecordFields((byte*)&rec, data);
01230 *(R*)result = (rec.*method)();
01231 }
01232 dbAnyMethodTrampoline* optimize();
01233
01234 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01235 : dbAnyMethodTrampoline(fd), method(f) {}
01236 };
01237
01238
01243 template<class T, class R>
01244 class dbMethodFastTrampoline : public dbAnyMethodTrampoline {
01245 typedef R (T::*mfunc)();
01246 mfunc method;
01247 public:
01248 dbAnyMethodTrampoline* optimize() {
01249 return this;
01250 }
01251 void invoke(byte* data, void* result) {
01252 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01253 }
01254 dbMethodFastTrampoline(dbMethodTrampoline<T,R>* mt)
01255 : dbAnyMethodTrampoline(mt->cls), method(mt->method) {
01256 delete mt;
01257 }
01258 };
01259
01260 template<class T, class R>
01261 inline dbAnyMethodTrampoline* dbMethodTrampoline<T,R>::optimize() {
01262 return new dbMethodFastTrampoline<T,R>(this);
01263 }
01264
01265 #endif
01266
01267 template<class T, class R>
01268 inline dbFieldDescriptor* dbDescribeMethod(dbFieldDescriptor* fd, R (T::*p)())
01269 {
01270 R ret;
01271 dbDescribeField(fd, ret);
01272 assert(fd->type <= dbField::tpReference);
01273 fd->appType = fd->type += dbField::tpMethodBool;
01274 fd->method = new dbMethodTrampoline<T,R>(fd, p);
01275 return fd;
01276 }
01277
01278 END_FASTDB_NAMESPACE
01279
01280 #endif
01281
01282