00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __BTREE_H__
00012 #define __BTREE_H__
00013
00014
00015 BEGIN_GIGABASE_NAMESPACE
00016
00017 class dbAnyCursor;
00018
00019 #define MAX_BTREE_HEIGHT 8
00020
00021 class dbBtreePage {
00022 public:
00023 nat4 nItems;
00024 nat4 size;
00025
00026 struct str {
00027 oid_t oid;
00028 nat2 size;
00029 nat2 offs;
00030 };
00031
00032 enum { dbMaxKeyLen = (dbPageSize - sizeof(str)*2) / sizeof(char_t) / 2 };
00033
00034 struct item {
00035 oid_t oid;
00036 int keyLen;
00037 union {
00038 int1 keyInt1;
00039 int2 keyInt2;
00040 int4 keyInt4;
00041 db_int8 keyInt8;
00042 oid_t keyOid;
00043 real4 keyReal4;
00044 real8 keyReal8;
00045 char_t keyChar[dbMaxKeyLen];
00046 };
00047 };
00048 enum {
00049 maxItems = (dbPageSize - 8) / sizeof(oid_t)
00050 };
00051
00052
00053 union {
00054 oid_t record[maxItems];
00055 int1 keyInt1[(dbPageSize-8) / sizeof(int1)];
00056 int2 keyInt2[(dbPageSize-8) / sizeof(int2)];
00057 int4 keyInt4[(dbPageSize-8) / sizeof(int4)];
00058 db_int8 keyInt8[(dbPageSize-8) / sizeof(db_int8)];
00059 oid_t keyOid[(dbPageSize-8) / sizeof(oid_t)];
00060 real4 keyReal4[(dbPageSize-8) / sizeof(real4)];
00061 real8 keyReal8[(dbPageSize-8) / sizeof(real8)];
00062 char keyChar[dbPageSize-8];
00063 str keyStr[1];
00064 };
00065
00066 static oid_t allocate(dbDatabase* db, oid_t root, int type, int sizeofType, item& ins);
00067
00068 static int insert(dbDatabase* db, oid_t pageId,
00069 int type, int sizeofType, dbUDTComparator comparator, item& ins, int height);
00070 static int remove(dbDatabase* db, oid_t pageId,
00071 int type, int sizeofType, dbUDTComparator comparator, item& rem, int height);
00072
00073 static void purge(dbDatabase* db, oid_t pageId, int type, int height);
00074
00075 int insertStrKey(dbDatabase* db, int r, item& ins, int height);
00076 int replaceStrKey(dbDatabase* db, int r, item& ins, int height);
00077 int removeStrKey(int r);
00078 void compactify(dbDatabase* db, int m);
00079
00080 int handlePageUnderflow(dbDatabase* db, int r, int type, int sizeofType, item& rem,
00081 int height);
00082
00083 bool find(dbDatabase* db, dbSearchContext& sc, int type, int sizeofType,
00084 dbUDTComparator comparator, int height);
00085
00086 bool traverseForward(dbDatabase* db, dbAnyCursor* cursor,
00087 dbExprNode* condition, int type, int height);
00088 bool traverseBackward(dbDatabase* db, dbAnyCursor* cursor,
00089 dbExprNode* condition, int type, int height);
00090 };
00091
00092
00093 class GIGABASE_DLL_ENTRY dbBtree : public dbRecord {
00094 friend class dbBtreeIterator;
00095 protected:
00096 oid_t root;
00097 int4 height;
00098 int4 type;
00099 int4 sizeofType;
00100
00101 public:
00102 enum {
00103 FLAGS_CASE_INSENSITIVE = 1,
00104 FLAGS_THICK = 2
00105 };
00106 int1 flags;
00107
00108 bool isCaseInsensitive() {
00109 return (flags & FLAGS_CASE_INSENSITIVE) != 0;
00110 }
00111
00112 bool isThick() {
00113 return (flags & FLAGS_THICK) != 0;
00114 }
00115
00116 enum OperationEffect {
00117 done,
00118 overflow,
00119 underflow,
00120 not_found
00121 };
00122
00123 static oid_t allocate(dbDatabase* db, int type, int sizeofType, int flags = 0);
00124 static void find(dbDatabase* db, oid_t treeId, dbSearchContext& sc, dbUDTComparator comparator);
00125 static void insert(dbDatabase* db, oid_t treeId, oid_t recordId, int offs, dbUDTComparator comparator);
00126 static void insert(dbDatabase* db, oid_t treeId, dbBtreePage::item& ins, dbUDTComparator comparator);
00127 static void remove(dbDatabase* db, oid_t treeId, oid_t recordId, int offs, dbUDTComparator comparator);
00128 static void drop(dbDatabase* db, oid_t treeId);
00129 static void purge(dbDatabase* db, oid_t treeId);
00130
00131 static void traverseForward(dbDatabase* db, oid_t treeId,
00132 dbAnyCursor* cursor, dbExprNode* condition);
00133 static void traverseBackward(dbDatabase* db, oid_t treeId,
00134 dbAnyCursor* cursor, dbExprNode* condition);
00135 static void traverseForward(dbDatabase* db, oid_t treeId,
00136 dbAnyCursor* cursor)
00137 {
00138 traverseForward(db, treeId, cursor, NULL);
00139 }
00140 static void traverseBackward(dbDatabase* db, oid_t treeId,
00141 dbAnyCursor* cursor)
00142 {
00143 traverseBackward(db, treeId, cursor, NULL);
00144 }
00145 };
00146
00147 class GIGABASE_DLL_ENTRY dbBtreeIterator : public dbAbstractIterator {
00148 public:
00149 void init(dbDatabase* db, oid_t treeId, dbSearchContext& sc, dbUDTComparator comparator);
00150
00151 oid_t next();
00152 oid_t prev();
00153 oid_t first();
00154 oid_t last();
00155
00156 private:
00157 oid_t reset(bool ascent);
00158 oid_t gotoNextItem(byte* pg, int pos, bool forward);
00159
00160 oid_t getStringBtreePageOid(byte* pg, int i);
00161 oid_t getScalarBtreePageOid(byte* pg, int i);
00162 oid_t getStringThickBtreePageOid(byte* pg, int i);
00163 oid_t getScalarThickBtreePageOid(byte* pg, int i);
00164 void* getStringBtreePageKey(byte* pg, int i);
00165 void* getScalarBtreePageKey(byte* pg, int i);
00166 void* getStringThickBtreePageKey(byte* pg, int i);
00167 void* getScalarThickBtreePageKey(byte* pg, int i);
00168
00169 oid_t (dbBtreeIterator::*getOid)(byte* pg, int i);
00170 void* (dbBtreeIterator::*getKey)(byte* pg, int i);
00171
00172 int nItems(byte* pg) {
00173 return ((dbBtreePage*)pg)->nItems;
00174 }
00175
00176 dbUDTComparator comparator;
00177 dbDatabase* db;
00178 dbSearchContext sc;
00179 int sizeofType;
00180 int type;
00181 int height;
00182 oid_t treeId;
00183 oid_t pageStack[MAX_BTREE_HEIGHT];
00184 int posStack[MAX_BTREE_HEIGHT];
00185 };
00186
00187 class dbThickBtreePage {
00188 public:
00189 nat4 nItems;
00190 nat4 size;
00191
00192 struct reference {
00193 oid_t oid;
00194 oid_t recId;
00195 };
00196
00197 struct str : reference {
00198 nat2 size;
00199 nat2 offs;
00200 };
00201
00202 enum { dbMaxKeyLen = (dbPageSize - sizeof(str)*2) / sizeof(char_t) / 2 };
00203
00204 struct item : reference {
00205 int keyLen;
00206 union {
00207 int1 keyInt1;
00208 int2 keyInt2;
00209 int4 keyInt4;
00210 db_int8 keyInt8;
00211 oid_t keyOid;
00212 real4 keyReal4;
00213 real8 keyReal8;
00214 char_t keyChar[dbMaxKeyLen];
00215 };
00216 };
00217 enum {
00218 maxItems = (dbPageSize - 8) / sizeof(reference)
00219 };
00220
00221
00222 union {
00223 reference ref[maxItems];
00224 int1 keyInt1[(dbPageSize-8) / sizeof(int1)];
00225 int2 keyInt2[(dbPageSize-8) / sizeof(int2)];
00226 int4 keyInt4[(dbPageSize-8) / sizeof(int4)];
00227 db_int8 keyInt8[(dbPageSize-8) / sizeof(db_int8)];
00228 oid_t keyOid[(dbPageSize-8) / sizeof(oid_t)];
00229 real4 keyReal4[(dbPageSize-8) / sizeof(real4)];
00230 real8 keyReal8[(dbPageSize-8) / sizeof(real8)];
00231 char keyChar[dbPageSize-8];
00232 str keyStr[1];
00233 };
00234
00235 static oid_t allocate(dbDatabase* db, oid_t root, int type, int sizeofType, item& ins);
00236
00237 static int insert(dbDatabase* db, oid_t pageId,
00238 int type, int sizeofType, dbUDTComparator comparator, item& ins, int height);
00239 static int remove(dbDatabase* db, oid_t pageId,
00240 int type, int sizeofType, dbUDTComparator comparator, item& rem, int height);
00241
00242 static void purge(dbDatabase* db, oid_t pageId, int type, int height);
00243
00244 int insertStrKey(dbDatabase* db, int r, item& ins, int height);
00245 int replaceStrKey(dbDatabase* db, int r, item& ins, int height);
00246 int removeStrKey(int r);
00247 void compactify(dbDatabase* db, int m);
00248
00249 int handlePageUnderflow(dbDatabase* db, int r, int type, int sizeofType, item& rem,
00250 int height);
00251
00252 bool find(dbDatabase* db, dbSearchContext& sc, int type, int sizeofType,
00253 dbUDTComparator comparator, int height);
00254
00255 bool traverseForward(dbDatabase* db, dbAnyCursor* cursor,
00256 dbExprNode* condition, int type, int height);
00257 bool traverseBackward(dbDatabase* db, dbAnyCursor* cursor,
00258 dbExprNode* condition, int type, int height);
00259 };
00260
00261 END_GIGABASE_NAMESPACE
00262
00263 #endif