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 EXTRA_DEBUG_NEW_PARAMS);
00490 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
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 friend class dbSelection;
00540 protected:
00544 dbTableDescriptor* next;
00545 static dbTableDescriptor* chain;
00546
00550 dbTableDescriptor* nextDbTable;
00551
00555 char* name;
00556
00560 oid_t tableId;
00561
00565 dbFieldDescriptor* columns;
00566
00570 dbFieldDescriptor* hashedFields;
00571
00575 dbFieldDescriptor* indexedFields;
00576
00580 dbFieldDescriptor* inverseFields;
00581
00585 dbFieldDescriptor* firstField;
00586
00590 dbFieldDescriptor** nextFieldLink;
00591
00595 dbDatabase* db;
00596
00600 bool fixedDatabase;
00601
00605 bool isStatic;
00606
00610 size_t appSize;
00611
00615 size_t fixedSize;
00616
00620 size_t nFields;
00621
00625 size_t nColumns;
00626
00630 int4 autoincrementCount;
00631
00632
00638 dbTableDescriptor* cloneOf;
00639
00640
00644 typedef dbFieldDescriptor* (*describeFunc)();
00645 describeFunc describeComponentsFunc;
00646
00650 dbTableDescriptor* clone();
00651
00655 size_t totalNamesLength();
00656
00668 int calculateFieldsAttributes(dbFieldDescriptor* fieldsList,
00669 char const* prefix, int offs,
00670 int indexMask, int& attr);
00671
00680 dbFieldDescriptor* buildFieldsList(dbTable* table, char const* prefix, int prefixLen, int& attr);
00681
00682 public:
00686 static int initialAutoincrementCount;
00687
00691 dbTableDescriptor* getNextTable() {
00692 return nextDbTable;
00693 }
00694
00698 dbFieldDescriptor* findSymbol(char const* name);
00699
00700
00704 dbFieldDescriptor* find(char const* name);
00705
00706
00711 dbFieldDescriptor* getFirstField() {
00712 return columns;
00713 }
00714
00720 dbFieldDescriptor* getNextField(dbFieldDescriptor* field) {
00721 if (field != NULL) {
00722 field = field->next;
00723 if (field == columns) {
00724 return NULL;
00725 }
00726 }
00727 return field;
00728 }
00729
00733 char* getName() {
00734 return name;
00735 }
00736
00741 void setFlags();
00742
00749 bool equal(dbTable* table);
00750
00759 bool match(dbTable* table, bool confirmDeleteColumns);
00760
00766 void checkRelationship();
00767
00772 dbDatabase* getDatabase() {
00773 assert(db != DETACHED_TABLE);
00774 return db;
00775 }
00776
00781 void storeInDatabase(dbTable* table);
00782
00786 static void cleanup();
00787
00792 dbTableDescriptor(dbTable* table);
00793
00802 dbTableDescriptor(char* tableName, dbDatabase* db, size_t objSize,
00803 describeFunc func, dbTableDescriptor* original = NULL);
00804
00808 ~dbTableDescriptor();
00809 };
00810
00814 struct dbVarying {
00815 nat4 size;
00816 int4 offs;
00817 };
00818
00822 struct dbField {
00823 enum FieldTypes {
00824 tpBool,
00825 tpInt1,
00826 tpInt2,
00827 tpInt4,
00828 tpInt8,
00829 tpReal4,
00830 tpReal8,
00831 tpString,
00832 tpReference,
00833 tpArray,
00834 tpMethodBool,
00835 tpMethodInt1,
00836 tpMethodInt2,
00837 tpMethodInt4,
00838 tpMethodInt8,
00839 tpMethodReal4,
00840 tpMethodReal8,
00841 tpMethodString,
00842 tpMethodReference,
00843 tpStructure,
00844 tpRawBinary,
00845 tpStdString,
00846 tpUnknown
00847 };
00848
00852 dbVarying name;
00853
00857 dbVarying tableName;
00858
00862 dbVarying inverse;
00863
00867 int4 type;
00868
00872 int4 offset;
00873
00877 nat4 size;
00878
00882 oid_t hashTable;
00883
00887 oid_t tTree;
00888 };
00889
00890
00894 class dbRecord {
00895 public:
00899 nat4 size;
00900
00904 oid_t next;
00905
00909 oid_t prev;
00910 };
00911
00912
00916 class dbTable : public dbRecord {
00917 public:
00921 dbVarying name;
00922
00926 dbVarying fields;
00927
00931 nat4 fixedSize;
00932
00936 nat4 nRows;
00937
00941 nat4 nColumns;
00942
00946 oid_t firstRow;
00947
00951 oid_t lastRow;
00952 #ifdef AUTOINCREMENT_SUPPORT
00953
00956 nat4 count;
00957 #endif
00958 };
00959
00960 inline dbFieldDescriptor* dbDescribeRawField(dbFieldDescriptor* fd, dbUDTComparator comparator)
00961 {
00962 fd->type = fd->appType = dbField::tpRawBinary;
00963 fd->alignment = 1;
00964 fd->comparator = comparator;
00965 return fd;
00966 }
00967
00968
00969 template<class T>
00970 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, T& x)
00971 {
00972 fd->type = fd->appType = dbField::tpStructure;
00973 fd->components = x.dbDescribeComponents(fd);
00974 return fd;
00975 }
00976
00977 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int1&)
00978 {
00979 fd->type = fd->appType = dbField::tpInt1;
00980 return fd;
00981 }
00982 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int2&)
00983 {
00984 fd->type = fd->appType = dbField::tpInt2;
00985 return fd;
00986 }
00987 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int4&)
00988 {
00989 fd->type = fd->appType = dbField::tpInt4;
00990 return fd;
00991 }
00992 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, db_int8&)
00993 {
00994 fd->type = fd->appType = dbField::tpInt8;
00995 return fd;
00996 }
00997 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat1&)
00998 {
00999 fd->type = fd->appType = dbField::tpInt1;
01000 return fd;
01001 }
01002 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat2&)
01003 {
01004 fd->type = fd->appType = dbField::tpInt2;
01005 return fd;
01006 }
01007 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat4&)
01008 {
01009 fd->type = fd->appType = dbField::tpInt4;
01010 return fd;
01011 }
01012 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat8&)
01013 {
01014 fd->type = fd->appType = dbField::tpInt8;
01015 return fd;
01016 }
01017 #if SIZEOF_LONG != 8
01018 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, long&)
01019 {
01020 fd->type = fd->appType = dbField::tpInt4;
01021 return fd;
01022 }
01023 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, unsigned long&)
01024 {
01025 fd->type = fd->appType = dbField::tpInt4;
01026 return fd;
01027 }
01028 #endif
01029 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, bool&)
01030 {
01031 fd->type = fd->appType = dbField::tpBool;
01032 return fd;
01033 }
01034 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real4&)
01035 {
01036 fd->type = fd->appType = dbField::tpReal4;
01037 return fd;
01038 }
01039 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real8&)
01040 {
01041 fd->type = fd->appType = dbField::tpReal8;
01042 return fd;
01043 }
01044 #ifdef USE_STD_STRING
01045 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, std::string&)
01046 {
01047 fd->type = dbField::tpString;
01048 fd->appType = dbField::tpStdString;
01049 fd->dbsSize = sizeof(dbVarying);
01050 fd->alignment = 4;
01051 fd->components = new dbFieldDescriptor("[]");
01052 fd->components->type = fd->components->appType = dbField::tpInt1;
01053 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = 1;
01054 return fd;
01055 }
01056 #endif
01057 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char const*&)
01058 {
01059 fd->type = fd->appType = dbField::tpString;
01060 fd->dbsSize = sizeof(dbVarying);
01061 fd->alignment = 4;
01062 fd->components = new dbFieldDescriptor("[]");
01063 fd->components->type = fd->components->appType = dbField::tpInt1;
01064 fd->components->dbsSize = fd->components->appSize = 1;
01065 fd->components->alignment = 1;
01066 return fd;
01067 }
01068 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char*&)
01069 {
01070 fd->type = fd->appType = dbField::tpString;
01071 fd->dbsSize = sizeof(dbVarying);
01072 fd->alignment = 4;
01073 fd->components = new dbFieldDescriptor("[]");
01074 fd->components->type = fd->components->appType = dbField::tpInt1;
01075 fd->components->dbsSize = fd->components->appSize = 1;
01076 fd->components->alignment = 1;
01077 return fd;
01078 }
01079
01080
01084 class FASTDB_DLL_ENTRY dbAnyMethodTrampoline {
01085 public:
01086 dbFieldDescriptor* cls;
01087
01093 virtual void invoke(byte* data, void* result) = 0;
01094
01101 virtual dbAnyMethodTrampoline* optimize() = 0;
01102
01107 dbAnyMethodTrampoline(dbFieldDescriptor* fd) { cls = fd; }
01108
01109 void* operator new(size_t size EXTRA_DEBUG_NEW_PARAMS);
01110 void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
01111
01115 virtual~dbAnyMethodTrampoline();
01116 };
01117
01118
01119 #if defined(__APPLE__) || defined(__VACPP_MULTI__) || defined(__IBMCPP__) || \
01120 (__SUNPRO_CC >= 0x520 && __SUNPRO_CC_COMPAT == 5)
01121
01124 template<class T, class R>
01125 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01126 public:
01127 typedef R (T::*mfunc)();
01128
01129 mfunc method;
01130 dbFieldDescriptor* cls;
01131 bool optimized;
01132
01133 void invoke(byte* data, void* result) {
01134 if (optimized) {
01135 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01136 } else {
01137 T rec;
01138 cls->components->fetchRecordFields((byte*)&rec, data);
01139 *(R*)result = (rec.*method)();
01140 }
01141 }
01142 dbAnyMethodTrampoline* optimize() {
01143 optimized = true;
01144 return this;
01145 }
01146
01147 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01148 : dbAnyMethodTrampoline(fd), method(f), cls(fd), optimized(false) {}
01149 };
01150
01151 #else
01152
01156 template<class T, class R>
01157 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01158 public:
01159 typedef R (T::*mfunc)();
01160 mfunc method;
01161
01162 void invoke(byte* data, void* result) {
01163 T rec;
01164 cls->components->fetchRecordFields((byte*)&rec, data);
01165 *(R*)result = (rec.*method)();
01166 }
01167 dbAnyMethodTrampoline* optimize();
01168
01169 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01170 : dbAnyMethodTrampoline(fd), method(f) {}
01171 };
01172
01173
01178 template<class T, class R>
01179 class dbMethodFastTrampoline : public dbMethodTrampoline<T,R> {
01180 public:
01181 void invoke(byte* data, void* result) {
01182 *(R*)result = (((T*)(data + cls->dbsOffs))->*method)();
01183 }
01184 dbMethodFastTrampoline(dbMethodTrampoline<T,R>* mt)
01185 : dbMethodTrampoline<T,R>(mt->cls, mt->method) {
01186 delete mt;
01187 }
01188 };
01189
01190 template<class T, class R>
01191 inline dbAnyMethodTrampoline* dbMethodTrampoline<T,R>::optimize() {
01192 return new dbMethodFastTrampoline<T,R>(this);
01193 }
01194
01195 #endif
01196
01197 template<class T, class R>
01198 inline dbFieldDescriptor* dbDescribeMethod(dbFieldDescriptor* fd, R (T::*p)())
01199 {
01200 R ret;
01201 dbDescribeField(fd, ret);
01202 assert(fd->type <= dbField::tpReference);
01203 fd->appType = fd->type += dbField::tpMethodBool;
01204 fd->method = new dbMethodTrampoline<T,R>(fd, p);
01205 return fd;
01206 }
01207
01208 #endif
01209
01210