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
00017 #ifdef USE_STD_STRING
00018 #include <string>
00019 #endif
00020
00021 #ifndef dbDatabaseOffsetBits
00022 #define dbDatabaseOffsetBits 32
00023 #endif
00024
00025 #ifndef dbDatabaseOidBits
00026 #define dbDatabaseOidBits 32
00027 #endif
00028
00032 #if dbDatabaseOidBits > 32
00033 typedef nat8 oid_t;
00034 #else
00035 typedef nat4 oid_t;
00036 #endif
00037
00041 #if dbDatabaseOffsetBits > 32
00042 typedef nat8 offs_t;
00043 #else
00044 typedef nat4 offs_t;
00045 #endif
00046
00050 enum dbIndexType {
00051 HASHED = 1,
00052 INDEXED = 2,
00053
00054 DB_FIELD_CASCADE_DELETE = 8,
00055
00056 AUTOINCREMENT = 16,
00057
00058 DB_FIELD_INHERITED_MASK = ~(HASHED|INDEXED)
00059 };
00060
00061
00065 #define KEY(x, index) \
00066 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00067 sizeof(x), index), x)
00068
00072 #define FIELD(x) KEY(x, 0)
00073
00077 typedef int (*dbUDTComparator)(void*, void*, size_t);
00078
00082 #define UDT(x, index, comparator) \
00083 *dbDescribeRawField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00084 sizeof(x), index), (dbUDTComparator)comparator)
00085
00089 #define RAWFIELD(x) UDT(x, 0, &memcmp)
00090
00094 #define RAWKEY(x, index) UDT(x, index, &memcmp)
00095
00101 #define RELATION(x,inverse) \
00102 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00103 sizeof(x), 0, #inverse), x)
00104
00110 #define OWNER(x,member) \
00111 *dbDescribeField(new dbFieldDescriptor(#x, (char*)&x-(char*)this, \
00112 sizeof(x), DB_FIELD_CASCADE_DELETE, \
00113 #member), x)
00114
00117 #define METHOD(x) \
00118 *dbDescribeMethod(new dbFieldDescriptor(#x), &self::x)
00119
00123 #define SUPERCLASS(x) \
00124 x::dbDescribeComponents(NULL)->adjustOffsets((char*)((x*)this)-(char*)this)
00125
00130 #define TYPE_DESCRIPTOR(fields) \
00131 dbFieldDescriptor* dbDescribeComponents(dbFieldDescriptor*) { \
00132 return &fields; \
00133 } \
00134 static dbTableDescriptor dbDescriptor
00135
00136
00142 #define CLASS_DESCRIPTOR(name, fields) \
00143 typedef name self; \
00144 dbFieldDescriptor* dbDescribeComponents(dbFieldDescriptor*) { \
00145 return &fields; \
00146 } \
00147 static dbTableDescriptor dbDescriptor
00148
00152 #define REGISTER_IN(table, database) \
00153 dbTableDescriptor* dbGetTableDescriptor(table*) \
00154 { return &table::dbDescriptor; } \
00155 static dbFieldDescriptor* dbDescribeComponentsOf##table() \
00156 { return ((table*)0)->dbDescribeComponents(NULL); } \
00157 dbTableDescriptor table::dbDescriptor(#table, database, sizeof(table), \
00158 &dbDescribeComponentsOf##table)
00159
00164 #define REGISTER(table) REGISTER_IN(table, NULL)
00165
00170 #define DETACHED_TABLE ((dbDatabase*)-1)
00171 #define REGISTER_UNASSIGNED(table) REGISTER_IN(table, DETACHED_TABLE)
00172
00173
00174 class dbDatabase;
00175 class dbAnyArray;
00176 class dbTableDescriptor;
00177 class dbAnyMethodTrampoline;
00178
00182 class FASTDB_DLL_ENTRY dbFieldDescriptor {
00183 public:
00187 dbFieldDescriptor* next;
00191 dbFieldDescriptor* prev;
00192
00196 dbFieldDescriptor* nextField;
00197
00201 dbFieldDescriptor* nextHashedField;
00202
00206 dbFieldDescriptor* nextIndexedField;
00207
00211 dbFieldDescriptor* nextInverseField;
00212
00216 int fieldNo;
00217
00221 char* name;
00222
00226 char* longName;
00227
00231 char* refTableName;
00232
00236 dbTableDescriptor* refTable;
00237
00241 dbTableDescriptor* defTable;
00242
00246 dbFieldDescriptor* inverseRef;
00247
00251 char* inverseRefName;
00252
00256 int type;
00257
00261 int appType;
00262
00266 int indexType;
00267
00271 int dbsOffs;
00272
00276 int appOffs;
00277
00281 dbFieldDescriptor* components;
00282
00286 oid_t hashTable;
00287
00291 oid_t tTree;
00292
00296 size_t dbsSize;
00297
00301 size_t appSize;
00302
00307 size_t alignment;
00308
00312 dbUDTComparator comparator;
00313
00317 enum FieldAttributes {
00318 ComponentOfArray = 0x01,
00319 HasArrayComponents = 0x02,
00320 OneToOneMapping = 0x04,
00321 Updated = 0x08
00322 };
00323 int attr;
00324
00328 int oldDbsType;
00332 int oldDbsOffs;
00336 int oldDbsSize;
00337
00341 dbAnyMethodTrampoline* method;
00342
00346 void (*arrayAllocator)(dbAnyArray* array, void* data, size_t length);
00347
00348
00359 size_t calculateRecordSize(byte* base, size_t offs);
00360
00370 size_t calculateNewRecordSize(byte* base, size_t offs);
00371
00381 size_t convertRecord(byte* dst, byte* src, size_t offs);
00382
00393 int sizeWithoutOneField(dbFieldDescriptor* field,
00394 byte* base, size_t& size);
00395
00405 size_t copyRecordExceptOneField(dbFieldDescriptor* field,
00406 byte* dst, byte* src, size_t offs);
00407
00418 size_t storeRecordFields(byte* dst, byte* src, size_t offs, bool insert);
00419
00427 void markUpdatedFields(byte* dst, byte* src);
00428
00436 void fetchRecordFields(byte* dst, byte* src);
00437
00446 void adjustReferences(byte* record, size_t base, size_t size, long shift);
00447
00453 dbFieldDescriptor* find(const char* name);
00454
00459 dbFieldDescriptor* getFirstComponent() {
00460 return components;
00461 }
00462
00467 dbFieldDescriptor* getNextComponent(dbFieldDescriptor* field) {
00468 if (field != NULL) {
00469 field = field->next;
00470 if (field == components) {
00471 return NULL;
00472 }
00473 }
00474 return field;
00475 }
00476
00480 dbFieldDescriptor& operator, (dbFieldDescriptor& field) {
00481 dbFieldDescriptor* tail = field.prev;
00482 tail->next = this;
00483 prev->next = &field;
00484 field.prev = prev;
00485 prev = tail;
00486 return *this;
00487 }
00488
00489 void* operator new(size_t size);
00490 void operator delete(void* p);
00491
00495 dbFieldDescriptor& adjustOffsets(long offs);
00496
00506 dbFieldDescriptor(char* name, int offs, int size, int indexType,
00507 char* inverse = NULL,
00508 dbFieldDescriptor* components = NULL);
00509
00514 dbFieldDescriptor(char* name);
00515
00519 ~dbFieldDescriptor();
00520 };
00521
00522
00526 class FASTDB_DLL_ENTRY dbTableDescriptor {
00527 friend class dbCompiler;
00528 friend class dbDatabase;
00529 friend class dbTable;
00530 friend class dbAnyCursor;
00531 friend class dbSubSql;
00532 friend class dbHashTable;
00533 friend class dbTtreeNode;
00534 friend class dbServer;
00535 friend class dbColumnBinding;
00536 friend class dbFieldDescriptor;
00537 friend class dbAnyContainer;
00538 friend class dbCLI;
00539 protected:
00543 dbTableDescriptor* next;
00544 static dbTableDescriptor* chain;
00545
00549 dbTableDescriptor* nextDbTable;
00550
00554 char* name;
00555
00559 oid_t tableId;
00560
00564 dbFieldDescriptor* columns;
00565
00569 dbFieldDescriptor* hashedFields;
00570
00574 dbFieldDescriptor* indexedFields;
00575
00579 dbFieldDescriptor* inverseFields;
00580
00584 dbFieldDescriptor* firstField;
00585
00589 dbFieldDescriptor** nextFieldLink;
00590
00594 dbDatabase* db;
00595
00599 bool fixedDatabase;
00600
00604 bool isStatic;
00605
00609 size_t appSize;
00610
00614 size_t fixedSize;
00615
00619 size_t nFields;
00620
00624 size_t nColumns;
00625
00629 int4 autoincrementCount;
00630
00631
00637 dbTableDescriptor* cloneOf;
00638
00639
00643 typedef dbFieldDescriptor* (*describeFunc)();
00644 describeFunc describeComponentsFunc;
00645
00649 dbTableDescriptor* clone();
00650
00654 size_t totalNamesLength();
00655
00667 int calculateFieldsAttributes(dbFieldDescriptor* fieldsList,
00668 char const* prefix, int offs,
00669 int indexMask, int& attr);
00670
00679 dbFieldDescriptor* buildFieldsList(dbTable* table, char const* prefix, int prefixLen, int& attr);
00680
00681 public:
00685 static int initialAutoincrementCount;
00686
00690 dbFieldDescriptor* findSymbol(char const* name);
00691
00692
00696 dbFieldDescriptor* find(char const* name);
00697
00698
00703 dbFieldDescriptor* getFirstField() {
00704 return columns;
00705 }
00706
00712 dbFieldDescriptor* getNextField(dbFieldDescriptor* field) {
00713 if (field != NULL) {
00714 field = field->next;
00715 if (field == columns) {
00716 return NULL;
00717 }
00718 }
00719 return field;
00720 }
00721
00725 char* getName() {
00726 return name;
00727 }
00728
00733 void setFlags();
00734
00741 bool equal(dbTable* table);
00742
00750 bool match(dbTable* table);
00751
00757 void checkRelationship();
00758
00763 dbDatabase* getDatabase() { return db; }
00764
00769 void storeInDatabase(dbTable* table);
00770
00774 static void cleanup();
00775
00780 dbTableDescriptor(dbTable* table);
00781
00790 dbTableDescriptor(char* tableName, dbDatabase* db, size_t objSize,
00791 describeFunc func, dbTableDescriptor* original = NULL);
00792
00796 ~dbTableDescriptor();
00797 };
00798
00802 struct dbVarying {
00803 nat4 size;
00804 int4 offs;
00805 };
00806
00810 struct dbField {
00811 enum FieldTypes {
00812 tpBool,
00813 tpInt1,
00814 tpInt2,
00815 tpInt4,
00816 tpInt8,
00817 tpReal4,
00818 tpReal8,
00819 tpString,
00820 tpReference,
00821 tpArray,
00822 tpMethodBool,
00823 tpMethodInt1,
00824 tpMethodInt2,
00825 tpMethodInt4,
00826 tpMethodInt8,
00827 tpMethodReal4,
00828 tpMethodReal8,
00829 tpMethodString,
00830 tpMethodReference,
00831 tpStructure,
00832 tpRawBinary,
00833 tpStdString,
00834 tpUnknown
00835 };
00836
00840 dbVarying name;
00841
00845 dbVarying tableName;
00846
00850 dbVarying inverse;
00851
00855 int4 type;
00856
00860 int4 offset;
00861
00865 nat4 size;
00866
00870 oid_t hashTable;
00871
00875 oid_t tTree;
00876 };
00877
00878
00882 class dbRecord {
00883 public:
00887 nat4 size;
00888
00892 oid_t next;
00893
00897 oid_t prev;
00898 };
00899
00900
00904 class dbTable : public dbRecord {
00905 public:
00909 dbVarying name;
00910
00914 dbVarying fields;
00915
00919 nat4 fixedSize;
00920
00924 nat4 nRows;
00925
00929 nat4 nColumns;
00930
00934 oid_t firstRow;
00935
00939 oid_t lastRow;
00940 #ifdef AUTOINCREMENT_SUPPORT
00941
00944 nat4 count;
00945 #endif
00946 };
00947
00948 inline dbFieldDescriptor* dbDescribeRawField(dbFieldDescriptor* fd, dbUDTComparator comparator)
00949 {
00950 fd->type = fd->appType = dbField::tpRawBinary;
00951 fd->alignment = 1;
00952 fd->comparator = comparator;
00953 return fd;
00954 }
00955
00956
00957 template<class T>
00958 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, T& x)
00959 {
00960 fd->type = fd->appType = dbField::tpStructure;
00961 fd->components = x.dbDescribeComponents(fd);
00962 return fd;
00963 }
00964
00965 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int1&)
00966 {
00967 fd->type = fd->appType = dbField::tpInt1;
00968 return fd;
00969 }
00970 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int2&)
00971 {
00972 fd->type = fd->appType = dbField::tpInt2;
00973 return fd;
00974 }
00975 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int4&)
00976 {
00977 fd->type = fd->appType = dbField::tpInt4;
00978 return fd;
00979 }
00980 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, db_int8&)
00981 {
00982 fd->type = fd->appType = dbField::tpInt8;
00983 return fd;
00984 }
00985 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat1&)
00986 {
00987 fd->type = fd->appType = dbField::tpInt1;
00988 return fd;
00989 }
00990 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat2&)
00991 {
00992 fd->type = fd->appType = dbField::tpInt2;
00993 return fd;
00994 }
00995 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat4&)
00996 {
00997 fd->type = fd->appType = dbField::tpInt4;
00998 return fd;
00999 }
01000 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat8&)
01001 {
01002 fd->type = fd->appType = dbField::tpInt8;
01003 return fd;
01004 }
01005 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, bool&)
01006 {
01007 fd->type = fd->appType = dbField::tpBool;
01008 return fd;
01009 }
01010 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real4&)
01011 {
01012 fd->type = fd->appType = dbField::tpReal4;
01013 return fd;
01014 }
01015 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real8&)
01016 {
01017 fd->type = fd->appType = dbField::tpReal8;
01018 return fd;
01019 }
01020 #ifdef USE_STD_STRING
01021 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, std::string&)
01022 {
01023 fd->type = dbField::tpString;
01024 fd->appType = dbField::tpStdString;
01025 fd->dbsSize = sizeof(dbVarying);
01026 fd->alignment = 4;
01027 fd->components = new dbFieldDescriptor("[]");
01028 fd->components->type = fd->components->appType = dbField::tpInt1;
01029 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = 1;
01030 return fd;
01031 }
01032 #endif
01033 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char const*&)
01034 {
01035 fd->type = fd->appType = dbField::tpString;
01036 fd->dbsSize = sizeof(dbVarying);
01037 fd->alignment = 4;
01038 fd->components = new dbFieldDescriptor("[]");
01039 fd->components->type = fd->components->appType = dbField::tpInt1;
01040 fd->components->dbsSize = fd->components->appSize = 1;
01041 fd->components->alignment = 1;
01042 return fd;
01043 }
01044 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char*&)
01045 {
01046 fd->type = fd->appType = dbField::tpString;
01047 fd->dbsSize = sizeof(dbVarying);
01048 fd->alignment = 4;
01049 fd->components = new dbFieldDescriptor("[]");
01050 fd->components->type = fd->components->appType = dbField::tpInt1;
01051 fd->components->dbsSize = fd->components->appSize = 1;
01052 fd->components->alignment = 1;
01053 return fd;
01054 }
01055
01056
01060 class FASTDB_DLL_ENTRY dbAnyMethodTrampoline {
01061 public:
01062 dbFieldDescriptor* cls;
01063
01069 virtual void invoke(byte* data, void* result) = 0;
01070
01077 virtual dbAnyMethodTrampoline* optimize() = 0;
01078
01083 dbAnyMethodTrampoline(dbFieldDescriptor* fd) { cls = fd; }
01084
01088 virtual~dbAnyMethodTrampoline();
01089 };
01090
01091
01092 #if defined(__APPLE__) || defined(__VACPP_MULTI__) || defined(__IBMCPP__) || \
01093 (__SUNPRO_CC >= 0x520 && __SUNPRO_CC_COMPAT == 5)
01094
01097 template<class T, class R>
01098 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01099 public:
01100 typedef R (T::*mfunc)();
01101
01102 mfunc method;
01103 dbFieldDescriptor* cls;
01104 bool optimized;
01105
01106 void invoke(byte* data, void* result) {
01107 if (optimized) {
01108 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01109 } else {
01110 T rec;
01111 cls->components->fetchRecordFields((byte*)&rec, data);
01112 *(R*)result = (rec.*method)();
01113 }
01114 }
01115 dbAnyMethodTrampoline* optimize() {
01116 optimized = true;
01117 return this;
01118 }
01119
01120 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01121 : dbAnyMethodTrampoline(fd), method(f), cls(fd), optimized(false) {}
01122 };
01123
01124 #else
01125
01129 template<class T, class R>
01130 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01131 public:
01132 typedef R (T::*mfunc)();
01133 mfunc method;
01134
01135 void invoke(byte* data, void* result) {
01136 T rec;
01137 cls->components->fetchRecordFields((byte*)&rec, data);
01138 *(R*)result = (rec.*method)();
01139 }
01140 dbAnyMethodTrampoline* optimize();
01141
01142 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01143 : dbAnyMethodTrampoline(fd), method(f) {}
01144 };
01145
01146
01151 template<class T, class R>
01152 class dbMethodFastTrampoline : public dbMethodTrampoline<T,R> {
01153 public:
01154 void invoke(byte* data, void* result) {
01155 *(R*)result = (((T*)(data + cls->dbsOffs))->*method)();
01156 }
01157 dbMethodFastTrampoline(dbMethodTrampoline<T,R>* mt)
01158 : dbMethodTrampoline<T,R>(mt->cls, mt->method) {
01159 delete mt;
01160 }
01161 };
01162
01163 template<class T, class R>
01164 inline dbAnyMethodTrampoline* dbMethodTrampoline<T,R>::optimize() {
01165 return new dbMethodFastTrampoline<T,R>(this);
01166 }
01167
01168 #endif
01169
01170 template<class T, class R>
01171 inline dbFieldDescriptor* dbDescribeMethod(dbFieldDescriptor* fd, R (T::*p)())
01172 {
01173 R ret;
01174 dbDescribeField(fd, ret);
01175 assert(fd->type <= dbField::tpReference);
01176 fd->appType = fd->type += dbField::tpMethodBool;
01177 fd->method = new dbMethodTrampoline<T,R>(fd, p);
01178 return fd;
01179 }
01180
01181 #endif
01182
01183