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 BEGIN_GIGABASE_NAMESPACE
00019
00020 #ifndef dbDatabaseOffsetBits
00021 #ifdef LARGE_DATABASE_SUPPORT
00022 #define dbDatabaseOffsetBits 40 // up to 1 terabyte
00023 #else
00024 #define dbDatabaseOffsetBits 32 // 37 - 128Gb, 40 - up to 1 terabyte
00025 #endif
00026 #endif
00027
00028 #ifndef dbDatabaseOidBits
00029 #define dbDatabaseOidBits 32
00030 #endif
00031
00035 #if dbDatabaseOidBits > 32
00036 typedef nat8 oid_t;
00037 #else
00038 typedef nat4 oid_t;
00039 #endif
00040
00044 #if dbDatabaseOffsetBits > 32
00045 typedef nat8 offs_t;
00046 #else
00047 typedef nat4 offs_t;
00048 #endif
00049
00050 #include "selection.h"
00051
00055 enum dbIndexType {
00056 HASHED = 1,
00057 INDEXED = 2,
00058 CASE_INSENSITIVE = 4,
00059
00060 DB_FIELD_CASCADE_DELETE = 8,
00061 UNIQUE = 16,
00062
00063 AUTOINCREMENT = 32,
00064 OPTIMIZE_DUPLICATES = 64,
00065 DB_BLOB_CASCADE_DELETE = 128,
00066
00067 DB_TIMESTAMP = 256,
00068
00069 DB_FIELD_INHERITED_MASK = ~(HASHED|INDEXED)
00070 };
00071
00075 #define KEY(x, index) \
00076 *GB_NS::dbDescribeField(new GB_NS::dbFieldDescriptor(STRLITERAL(#x), (char*)&x-(char*)this, \
00077 sizeof(x), index), x)
00078
00082 #define FIELD(x) KEY(x, 0)
00083
00087 typedef int (*dbUDTComparator)(void*, void*, size_t);
00088
00092 #define UDT(x, index, comparator) \
00093 *GB_NS::dbDescribeRawField(new GB_NS::dbFieldDescriptor(STRLITERAL(#x), (char*)&x-(char*)this, \
00094 sizeof(x), index), (GB_NS::dbUDTComparator)comparator)
00095
00099 #define RAWFIELD(x) UDT(x, 0, &memcmp)
00100
00104 #define RAWKEY(x, index) UDT(x, index, &memcmp)
00105
00106
00112 #define RELATION(x,inverse) \
00113 *GB_NS::dbDescribeField(new GB_NS::dbFieldDescriptor(STRLITERAL(#x), (char*)&x-(char*)this, \
00114 sizeof(x), 0, STRLITERAL(#inverse)), x)
00115
00121 #define INDEXED_RELATION(x,inverse) \
00122 *GB_NS::dbDescribeField(new GB_NS::dbFieldDescriptor(STRLITERAL(#x), (char*)&x-(char*)this, \
00123 sizeof(x), GB_NS::INDEXED, STRLITERAL(#inverse)), x)
00124
00130 #define OWNER(x,member) \
00131 *GB_NS::dbDescribeField(new GB_NS::dbFieldDescriptor(STRLITERAL(#x), (char*)&x-(char*)this, \
00132 sizeof(x), GB_NS::DB_FIELD_CASCADE_DELETE, \
00133 STRLITERAL(#member)), x)
00134
00138 #define METHOD(x) \
00139 *GB_NS::dbDescribeMethod(new GB_NS::dbFieldDescriptor(STRLITERAL(#x)), &self::x)
00140
00147 #define BLOB(x) \
00148 *GB_NS::dbDescribeField(new GB_NS::dbFieldDescriptor(STRLITERAL(#x), (char*)&x-(char*)this, \
00149 sizeof(x), GB_NS::DB_BLOB_CASCADE_DELETE), x)
00150
00153 #define SUPERCLASS(x) \
00154 x::dbDescribeComponents(NULL)->adjustOffsets((char*)((x*)this)-(char*)this)
00155
00160 #define TYPE_DESCRIPTOR(fields) \
00161 GB_NS::dbFieldDescriptor* dbDescribeComponents(GB_NS::dbFieldDescriptor*) { \
00162 return &fields; \
00163 } \
00164 static GB_NS::dbTableDescriptor dbDescriptor
00165
00171 #define CLASS_DESCRIPTOR(name, fields) \
00172 typedef name self; \
00173 GB_NS::dbFieldDescriptor* dbDescribeComponents(GB_NS::dbFieldDescriptor*) { \
00174 return &fields; \
00175 } \
00176 static GB_NS::dbTableDescriptor dbDescriptor
00177
00178 #if (defined(_MSC_VER) && _MSC_VER+0 < 1200) || defined(__MWERKS__)
00179
00182 #if defined(_MSC_VER)
00183 #define TEMPLATE_SPEC
00184 #else
00185 #define TEMPLATE_SPEC template <>
00186 #endif
00187 #define REGISTER_IN(table, database) \
00188 TEMPLATE_SPEC GB_NS::dbTableDescriptor* dbGetTableDescriptor<table>(table*) \
00189 { return &table::dbDescriptor; } \
00190 static GB_NS::dbFieldDescriptor* dbDescribeComponentsOf##table() \
00191 { return ((table*)0)->dbDescribeComponents(NULL); } \
00192 GB_NS::dbTableDescriptor table::dbDescriptor(_T(#table), database, sizeof(table), \
00193 &dbDescribeComponentsOf##table)
00194
00195 #define REGISTER_TEMPLATE_IN(table, database) \
00196 TEMPLATE_SPEC GB_NS::dbTableDescriptor* dbGetTableDescriptor<table>(table*) \
00197 { return &table::dbDescriptor; } \
00198 static GB_NS::dbFieldDescriptor* dbDescribeComponentsOf##table() \
00199 { return ((table*)0)->dbDescribeComponents(NULL); } \
00200 template<> GB_NS::dbTableDescriptor table::dbDescriptor(_T(#table), database, sizeof(table), \
00201 &dbDescribeComponentsOf##table)
00202 #else
00203
00206 #define REGISTER_IN(table, database) \
00207 GB_NS::dbTableDescriptor* dbGetTableDescriptor(table*) \
00208 { return &table::dbDescriptor; } \
00209 static GB_NS::dbFieldDescriptor* dbDescribeComponentsOf##table() \
00210 { return ((table*)0)->dbDescribeComponents(NULL); } \
00211 GB_NS::dbTableDescriptor table::dbDescriptor(_T(#table), database, sizeof(table), \
00212 &dbDescribeComponentsOf##table)
00213 #define REGISTER_TEMPLATE_IN(table, database) \
00214 GB_NS::dbTableDescriptor* dbGetTableDescriptor(table*) \
00215 { return &table::dbDescriptor; } \
00216 static GB_NS::dbFieldDescriptor* dbDescribeComponentsOf##table() \
00217 { return ((table*)0)->dbDescribeComponents(NULL); } \
00218 template<> GB_NS::dbTableDescriptor table::dbDescriptor(_T(#table), database, sizeof(table), \
00219 &dbDescribeComponentsOf##table)
00220 #endif
00221
00226 #define REGISTER(table) REGISTER_IN(table, NULL)
00227 #define REGISTER_TEMPLATE(table) REGISTER_TEMPLATE_IN(table, NULL)
00228
00233 #define DETACHED_TABLE ((GB_NS::dbDatabase*)-1)
00234 #define REGISTER_UNASSIGNED(table) REGISTER_IN(table, DETACHED_TABLE)
00235 #define REGISTER_TEMPLATE_UNASSIGNED(table) REGISTER_TEMPLATE_IN(table, DETACHED_TABLE)
00236
00237
00238 class dbDatabase;
00239 class dbAnyArray;
00240 class dbTableDescriptor;
00241 class dbAnyMethodTrampoline;
00242 class dbTable;
00243
00247 class GIGABASE_DLL_ENTRY dbFieldDescriptor {
00248 public:
00252 dbFieldDescriptor* next;
00253
00257 dbFieldDescriptor* prev;
00258
00262 dbFieldDescriptor* nextField;
00263
00267 dbFieldDescriptor* nextHashedField;
00268
00272 dbFieldDescriptor* nextIndexedField;
00273
00277 dbFieldDescriptor* nextInverseField;
00278
00282 int fieldNo;
00283
00287 char_t* name;
00288
00292 char_t* longName;
00293
00297 char_t* refTableName;
00298
00302 dbTableDescriptor* refTable;
00303
00307 dbTableDescriptor* defTable;
00308
00312 dbFieldDescriptor* inverseRef;
00313
00317 char_t* inverseRefName;
00318
00322 int type;
00323
00327 int appType;
00328
00332 int indexType;
00333
00337 int dbsOffs;
00338
00342 int appOffs;
00343
00347 dbFieldDescriptor* components;
00348
00352 oid_t hashTable;
00353
00357 oid_t bTree;
00358
00362 size_t dbsSize;
00363
00367 size_t appSize;
00368
00373 size_t alignment;
00374
00378 dbUDTComparator comparator;
00379
00383 enum FieldAttributes {
00384 ComponentOfArray = 0x01,
00385 HasArrayComponents = 0x02,
00386 OneToOneMapping = 0x04,
00387 Updated = 0x08
00388 };
00389 int attr;
00390
00394 int oldDbsType;
00398 int oldDbsOffs;
00402 int oldDbsSize;
00403
00404
00408 dbAnyMethodTrampoline* method;
00409
00413 void (*arrayAllocator)(dbAnyArray* array, void* data, size_t length);
00414
00425 size_t calculateRecordSize(byte* base, size_t offs);
00426
00436 size_t calculateNewRecordSize(byte* base, size_t offs);
00437
00447 size_t convertRecord(byte* dst, byte* src, size_t offs);
00448
00459 int sizeWithoutOneField(dbFieldDescriptor* field,
00460 byte* base, size_t& size);
00461
00471 size_t copyRecordExceptOneField(dbFieldDescriptor* field,
00472 byte* dst, byte* src, size_t offs);
00473
00474
00475 enum StoreMode {
00476 Insert,
00477 Update,
00478 Import
00479 };
00480
00491 size_t storeRecordFields(byte* dst, byte* src, size_t offs, StoreMode mode);
00492
00500 void markUpdatedFields(byte* dst, byte* src);
00501
00509 void fetchRecordFields(byte* dst, byte* src);
00510
00516 dbFieldDescriptor* find(const char_t* name);
00517
00522 dbFieldDescriptor* getFirstComponent() {
00523 return components;
00524 }
00525
00530 dbFieldDescriptor* getNextComponent(dbFieldDescriptor* field) {
00531 if (field != NULL) {
00532 field = field->next;
00533 if (field == components) {
00534 return NULL;
00535 }
00536 }
00537 return field;
00538 }
00539
00543 dbFieldDescriptor& operator, (dbFieldDescriptor& field) {
00544 dbFieldDescriptor* tail = field.prev;
00545 tail->next = this;
00546 prev->next = &field;
00547 field.prev = prev;
00548 prev = tail;
00549 return *this;
00550 }
00551
00552 void* operator new(size_t size);
00553 void operator delete(void* p);
00554
00558 dbFieldDescriptor& adjustOffsets(long offs);
00559
00569 dbFieldDescriptor(char_t const* name, size_t offs, size_t size, int indexType,
00570 char_t const* inverse = NULL,
00571 dbFieldDescriptor* components = NULL);
00572
00577 dbFieldDescriptor(char_t const* name);
00578
00582 ~dbFieldDescriptor();
00583 };
00584
00585
00589 class GIGABASE_DLL_ENTRY dbTableDescriptor {
00590 friend class dbCompiler;
00591 friend class dbDatabase;
00592 friend class dbReplicatedDatabase;
00593 friend class dbTable;
00594 friend class dbAnyCursor;
00595 friend class dbSubSql;
00596 friend class dbParallelQueryContext;
00597 friend class dbServer;
00598 friend class dbAnyContainer;
00599 friend class dbColumnBinding;
00600 friend class dbFieldDescriptor;
00601 friend class dbSelection;
00602 friend class dbTableIterator;
00603 friend class dbCLI;
00604 protected:
00608 dbTableDescriptor* next;
00609 static dbTableDescriptor* chain;
00610
00614 dbTableDescriptor* nextDbTable;
00615
00619 char_t* name;
00620
00624 oid_t tableId;
00625
00629 dbFieldDescriptor* columns;
00630
00634 dbFieldDescriptor* hashedFields;
00635
00639 dbFieldDescriptor* indexedFields;
00640
00644 dbFieldDescriptor* inverseFields;
00645
00649 dbFieldDescriptor* firstField;
00650
00654 dbFieldDescriptor** nextFieldLink;
00655
00659 dbDatabase* db;
00660
00664 bool fixedDatabase;
00665
00669 bool isStatic;
00670
00676 dbTableDescriptor* cloneOf;
00677
00681 size_t appSize;
00682
00686 size_t fixedSize;
00687
00691 size_t nFields;
00692
00696 size_t nColumns;
00697
00701 oid_t firstRow;
00702
00706 oid_t lastRow;
00707
00711 size_t nRows;
00712
00716 int4 autoincrementCount;
00717
00721 dbTableDescriptor* nextBatch;
00722
00726 bool isInBatch;
00727
00731 dbSelection batch;
00732
00736 int transactionId;
00737
00741 typedef dbFieldDescriptor* (*describeFunc)();
00742 describeFunc describeComponentsFunc;
00743
00747 dbTableDescriptor* collisionChain;
00748
00752 size_t totalNamesLength();
00753
00765 int calculateFieldsAttributes(dbFieldDescriptor* fieldsList,
00766 char_t const* prefix, int offs,
00767 int indexMask, int& attr);
00768
00777 dbFieldDescriptor* buildFieldsList(dbTable* table, char_t const* prefix,
00778 int prefixLen, int& attr);
00782 dbTableDescriptor* clone();
00783
00784 public:
00788 static int initialAutoincrementCount;
00789
00790
00794 dbTableDescriptor* getNextTable() {
00795 return nextDbTable;
00796 }
00797
00801 dbFieldDescriptor* findSymbol(char_t const* name);
00802
00806 dbFieldDescriptor* find(char_t const* name);
00807
00812 dbFieldDescriptor* getFirstField() {
00813 return columns;
00814 }
00815
00820 int getLastValueOfAutoincrementCount() const {
00821 return autoincrementCount;
00822 }
00823
00829 dbFieldDescriptor* getNextField(dbFieldDescriptor* field) {
00830 if (field != NULL) {
00831 field = field->next;
00832 if (field == columns) {
00833 return NULL;
00834 }
00835 }
00836 return field;
00837 }
00838
00842 char_t* getName() {
00843 return name;
00844 }
00845
00849 size_t size() {
00850 return appSize;
00851 }
00852
00859 bool equal(dbTable* table);
00860
00869 bool match(dbTable* table, bool confirmDeleteColumns);
00870
00876 void checkRelationship();
00877
00882 dbDatabase* getDatabase() { return db; }
00883
00888 void storeInDatabase(dbTable* table);
00889
00894 void setFlags();
00895
00896
00900 static void cleanup();
00901
00902
00907 dbTableDescriptor(dbTable* table);
00908
00917 dbTableDescriptor(char_t const* tableName,
00918 dbDatabase* db,
00919 size_t objSize,
00920 describeFunc func,
00921 dbTableDescriptor* original = NULL);
00922
00926 ~dbTableDescriptor();
00927 };
00928
00932 struct dbVarying {
00933 nat4 size;
00934 int4 offs;
00935 };
00936
00940 struct dbField {
00941 enum FieldTypes {
00942 tpBool,
00943 tpInt1,
00944 tpInt2,
00945 tpInt4,
00946 tpInt8,
00947 tpReal4,
00948 tpReal8,
00949 tpString,
00950 tpReference,
00951 tpArray,
00952 tpMethodBool,
00953 tpMethodInt1,
00954 tpMethodInt2,
00955 tpMethodInt4,
00956 tpMethodInt8,
00957 tpMethodReal4,
00958 tpMethodReal8,
00959 tpMethodString,
00960 tpMethodReference,
00961 tpStructure,
00962 tpRawBinary,
00963 tpStdString,
00964 tpMfcString,
00965 tpRectangle,
00966 tpUnknown
00967 };
00968
00972 dbVarying name;
00973
00977 dbVarying tableName;
00978
00982 dbVarying inverse;
00983
00987 #ifdef OLD_FIELD_DESCRIPTOR_FORMAT
00988 int4 type;
00989 #else
00990 #if BYTE_ORDER == BIG_ENDIAN
00991 int4 flags : 24;
00992 int4 type : 8;
00993 #else
00994 int4 type : 8;
00995 int4 flags : 24;
00996 #endif
00997 #endif
00998
01002 int4 offset;
01003
01007 nat4 size;
01008
01012 oid_t hashTable;
01013
01017 oid_t bTree;
01018 };
01019
01020
01024 class dbRecord {
01025 public:
01029 nat4 size;
01030
01034 oid_t next;
01035
01039 oid_t prev;
01040 };
01041
01042
01046 class dbTable : public dbRecord {
01047 public:
01051 dbVarying name;
01052
01056 dbVarying fields;
01057
01061 nat4 fixedSize;
01062
01066 nat4 nRows;
01067
01071 nat4 nColumns;
01072
01076 oid_t firstRow;
01077
01081 oid_t lastRow;
01082 #ifdef AUTOINCREMENT_SUPPORT
01083
01086 nat4 count;
01087 #endif
01088 };
01089
01090 inline dbFieldDescriptor* dbDescribeRawField(dbFieldDescriptor* fd, dbUDTComparator comparator)
01091 {
01092 fd->type = fd->appType = dbField::tpRawBinary;
01093 fd->alignment = 1;
01094 fd->comparator = comparator;
01095 return fd;
01096 }
01097
01098 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int1&)
01099 {
01100 fd->type = fd->appType = dbField::tpInt1;
01101 return fd;
01102 }
01103 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int2&)
01104 {
01105 fd->type = fd->appType = dbField::tpInt2;
01106 return fd;
01107 }
01108 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, int4&)
01109 {
01110 fd->type = fd->appType = dbField::tpInt4;
01111 return fd;
01112 }
01113 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, db_int8&)
01114 {
01115 fd->type = fd->appType = dbField::tpInt8;
01116 return fd;
01117 }
01118 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat1&)
01119 {
01120 fd->type = fd->appType = dbField::tpInt1;
01121 return fd;
01122 }
01123 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat2&)
01124 {
01125 fd->type = fd->appType = dbField::tpInt2;
01126 return fd;
01127 }
01128 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat4&)
01129 {
01130 fd->type = fd->appType = dbField::tpInt4;
01131 return fd;
01132 }
01133 #if SIZEOF_LONG != 8
01134 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, long&)
01135 {
01136 fd->type = fd->appType = dbField::tpInt4;
01137 return fd;
01138 }
01139 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, unsigned long&)
01140 {
01141 fd->type = fd->appType = dbField::tpInt4;
01142 return fd;
01143 }
01144 #endif
01145 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, nat8&)
01146 {
01147 fd->type = fd->appType = dbField::tpInt8;
01148 return fd;
01149 }
01150 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, bool&)
01151 {
01152 fd->type = fd->appType = dbField::tpBool;
01153 return fd;
01154 }
01155 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real4&)
01156 {
01157 fd->type = fd->appType = dbField::tpReal4;
01158 return fd;
01159 }
01160 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, real8&)
01161 {
01162 fd->type = fd->appType = dbField::tpReal8;
01163 return fd;
01164 }
01165 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, rectangle&)
01166 {
01167 fd->type = fd->appType = dbField::tpRectangle;
01168 fd->alignment = sizeof(coord_t);
01169 return fd;
01170 }
01171
01172 #ifdef USE_STD_STRING
01173 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, STD_STRING&)
01174 {
01175 fd->type = dbField::tpString;
01176 fd->appType = dbField::tpStdString;
01177 fd->dbsSize = sizeof(dbVarying);
01178 fd->alignment = 4;
01179 fd->components = new dbFieldDescriptor(STRLITERAL("[]"));
01180 fd->components->type = fd->components->appType = dbField::tpInt1 + (sizeof(char_t) - 1);
01181 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = sizeof(char_t);
01182 return fd;
01183 }
01184 #endif
01185 #ifdef USE_MFC_STRING
01186 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, MFC_STRING&)
01187 {
01188 fd->type = dbField::tpString;
01189 fd->appType = dbField::tpMfcString;
01190 fd->dbsSize = sizeof(dbVarying);
01191 fd->alignment = 4;
01192 fd->components = new dbFieldDescriptor(STRLITERAL("[]"));
01193 fd->components->type = fd->components->appType = dbField::tpInt1 + (sizeof(char_t) - 1);
01194 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = sizeof(char_t);
01195 return fd;
01196 }
01197 #endif
01198
01199 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char_t const*&)
01200 {
01201 fd->type = fd->appType = dbField::tpString;
01202 fd->dbsSize = sizeof(dbVarying);
01203 fd->alignment = 4;
01204 fd->components = new dbFieldDescriptor(STRLITERAL("[]"));
01205 fd->components->type = fd->components->appType = dbField::tpInt1 + (sizeof(char_t) - 1);
01206 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = sizeof(char_t);
01207 return fd;
01208 }
01209 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, char_t*&)
01210 {
01211 fd->type = fd->appType = dbField::tpString;
01212 fd->dbsSize = sizeof(dbVarying);
01213 fd->alignment = 4;
01214 fd->components = new dbFieldDescriptor(STRLITERAL("[]"));
01215 fd->components->type = fd->components->appType = dbField::tpInt1 + (sizeof(char_t) - 1);
01216 fd->components->dbsSize = fd->components->appSize = fd->components->alignment = sizeof(char_t);
01217 return fd;
01218 }
01219
01220
01221 template<class T>
01222 inline dbFieldDescriptor* dbDescribeField(dbFieldDescriptor* fd, T& x)
01223 {
01224 fd->type = fd->appType = dbField::tpStructure;
01225 fd->components = x.dbDescribeComponents(fd);
01226 return fd;
01227 }
01228
01229
01233 class GIGABASE_DLL_ENTRY dbAnyMethodTrampoline {
01234 public:
01235 dbFieldDescriptor* cls;
01236
01242 virtual void invoke(byte* data, void* result) = 0;
01243
01250 virtual dbAnyMethodTrampoline* optimize() = 0;
01251
01256 dbAnyMethodTrampoline(dbFieldDescriptor* fd) { cls = fd; }
01257
01261 virtual~dbAnyMethodTrampoline();
01262
01263 void* operator new(size_t size);
01264 void operator delete(void* p);
01265 };
01266
01267 #if defined(__APPLE__) || defined(__VACPP_MULTI__) || defined(__IBMCPP__) || defined(__HP_aCC) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x510 && __SUNPRO_CC_COMPAT == 5)
01268
01271 template<class T, class R>
01272 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01273 public:
01274 typedef R (T::*mfunc)();
01275
01276 mfunc method;
01277 dbFieldDescriptor* cls;
01278 bool optimized;
01279
01280 void invoke(byte* data, void* result) {
01281 if (optimized) {
01282 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01283 } else {
01284 T rec;
01285 this->cls->components->fetchRecordFields((byte*)&rec, data);
01286 *(R*)result = (rec.*method)();
01287 }
01288 }
01289 dbAnyMethodTrampoline* optimize() {
01290 optimized = true;
01291 return this;
01292 }
01293
01294 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01295 : dbAnyMethodTrampoline(fd)
01296 {
01297 this->method = f;
01298 this->cls = fd;
01299 this->optimized = false;
01300 }
01301 };
01302
01303 #else
01304
01308 template<class T, class R>
01309 class dbMethodTrampoline : public dbAnyMethodTrampoline {
01310 public:
01311 typedef R (T::*mfunc)();
01312 mfunc method;
01313
01314 void invoke(byte* data, void* result) {
01315 T rec;
01316 this->cls->components->fetchRecordFields((byte*)&rec, data);
01317 *(R*)result = (rec.*method)();
01318 }
01319 dbAnyMethodTrampoline* optimize();
01320
01321 dbMethodTrampoline(dbFieldDescriptor* fd, mfunc f)
01322 : dbAnyMethodTrampoline(fd), method(f) {}
01323 };
01324
01325 template<class T, class R>
01326 class dbMethodFastTrampoline : public dbAnyMethodTrampoline {
01327 typedef R (T::*mfunc)();
01328 mfunc method;
01329 public:
01330 dbAnyMethodTrampoline* optimize() {
01331 return this;
01332 }
01333 void invoke(byte* data, void* result) {
01334 *(R*)result = (((T*)(data + this->cls->dbsOffs))->*method)();
01335 }
01336 dbMethodFastTrampoline(dbMethodTrampoline<T,R>* mt)
01337 : dbAnyMethodTrampoline(mt->cls), method(mt->method) {
01338 delete mt;
01339 }
01340 };
01341
01342 template<class T, class R>
01343 inline dbAnyMethodTrampoline* dbMethodTrampoline<T,R>::optimize() {
01344 return new dbMethodFastTrampoline<T,R>(this);
01345 }
01346
01347 #endif
01348 template<class T, class R>
01349 inline dbFieldDescriptor* dbDescribeMethod(dbFieldDescriptor* fd, R (T::*p)())
01350 {
01351 R ret;
01352 dbDescribeField(fd, ret);
01353 assert(fd->type <= dbField::tpReference);
01354 fd->appType = fd->type += dbField::tpMethodBool;
01355 fd->method = new dbMethodTrampoline<T,R>(fd, p);
01356 return fd;
01357 }
01358
01359 END_GIGABASE_NAMESPACE
01360
01361 #endif
01362
01363