00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __SELECTION_H__
00012 #define __SELECTION_H__
00013
00014 class dbOrderByNode;
00015 class dbDatabase;
00016 class dbRecord;
00017
00018 class GIGABASE_DLL_ENTRY dbL2List {
00019 public:
00020 dbL2List* next;
00021 dbL2List* prev;
00022
00023 void link(dbL2List* elem) {
00024 elem->prev = this;
00025 elem->next = next;
00026 next = next->prev = elem;
00027 }
00028 void unlink() {
00029 #ifdef __INSURE__
00030 if (((void*) next == (void*) prev) &&
00031 ((void*) next == (void*) this)) return;
00032 #endif
00033 next->prev = prev;
00034 prev->next = next;
00035 next = prev = this;
00036 }
00037 bool isEmpty() {
00038 return next == this;
00039 }
00040 void reset() {
00041 next = prev = this;
00042 }
00043 dbL2List() {
00044 next = prev = this;
00045 }
00046 ~dbL2List() {
00047 unlink();
00048 }
00049 };
00050
00051
00052
00053 struct GIGABASE_DLL_ENTRY dbSortRecord {
00054 oid_t oid;
00055 union {
00056 db_int8 longKey;
00057 real8 realKey;
00058 int4 intKey;
00059 void* rawKey;
00060 char_t* strKey;
00061 } u;
00062 };
00063
00064 class GIGABASE_DLL_ENTRY dbStrBuffer {
00065 protected:
00066 struct dbStrSegment {
00067 enum {
00068 dbSegmentSize = 256*1024
00069 };
00070 dbStrSegment* next;
00071 char_t data[dbSegmentSize];
00072 };
00073 dbStrSegment* chain;
00074 int used;
00075 public:
00076 char_t* put(char_t const* str, size_t len) {
00077 assert(len < dbStrSegment::dbSegmentSize);
00078 if (used + len >= dbStrSegment::dbSegmentSize) {
00079 dbStrSegment* seg = new dbStrSegment();
00080 seg->next = chain;
00081 chain = seg;
00082 used = 0;
00083 }
00084 char_t* p = chain->data + used;
00085 memcpy(p, str, sizeof(char_t)*(len + 1));
00086 used += len + 1;
00087 return p;
00088 }
00089 dbStrBuffer() {
00090 chain = NULL;
00091 used = dbStrSegment::dbSegmentSize;
00092 }
00093 ~dbStrBuffer() {
00094 while (chain != NULL) {
00095 dbStrSegment* next = chain->next;
00096 delete chain;
00097 chain = next;
00098 }
00099 }
00100 };
00101
00102 class GIGABASE_DLL_ENTRY dbSortResult {
00103 public:
00104 dbStrBuffer strBuf;
00105 dbSortRecord* keys;
00106 char* rawKeys;
00107
00108 ~dbSortResult() {
00109 delete[] keys;
00110 delete[] rawKeys;
00111 }
00112 };
00113
00114
00115 class GIGABASE_DLL_ENTRY dbSelection {
00116 public:
00117 enum { FIRST_SEGMENT_SIZE = 16 };
00118 class segment {
00119 public:
00120 segment* prev;
00121 segment* next;
00122 size_t nRows;
00123 size_t maxRows;
00124 oid_t rows[FIRST_SEGMENT_SIZE];
00125
00126 static segment* allocate(size_t nRows, segment* after) {
00127 segment* s = (segment*)dbMalloc(sizeof(segment) + sizeof(oid_t)*(nRows-FIRST_SEGMENT_SIZE));
00128 s->next = after->next;
00129 s->prev = after;
00130 after->next = after->next->prev = s;
00131 s->nRows = 0;
00132 s->maxRows = nRows;
00133 return s;
00134 }
00135
00136 void operator delete(void* p) {
00137 dbFree(p);
00138 }
00139
00140 segment() {
00141 maxRows = FIRST_SEGMENT_SIZE;
00142 next = prev = this;
00143 nRows = 0;
00144 }
00145
00146 void prune() {
00147 next = prev = this;
00148 }
00149
00150 ~segment() {
00151 prev->next = next;
00152 next->prev = prev;
00153 }
00154 };
00155 segment first;
00156 segment* curr;
00157 size_t nRows;
00158 size_t pos;
00159
00160 void add(oid_t oid) {
00161 segment* s = first.prev;
00162 if (s->nRows == s->maxRows) {
00163 s = segment::allocate(s->maxRows*2, s);
00164 }
00165 s->rows[s->nRows++] = oid;
00166 nRows += 1;
00167 }
00168
00169 void truncate(size_t from, size_t length);
00170 void toArray(oid_t* oids) const;
00171 void merge(dbSelection& selection);
00172
00173 void sort(dbDatabase* db, dbOrderByNode* order, bool caseInsensitive = false, dbSortResult* sortResult = NULL);
00174 static int compare(dbRecord* a, dbRecord* b, dbOrderByNode* order);
00175
00176 static int __cdecl exactKeyCmp(void const* a, void const* b);
00177 static int __cdecl udtComparator(void const* a, void const* b);
00178
00179 dbSelection() {
00180 nRows = 0;
00181 pos = 0;
00182 curr = &first;
00183 }
00184 void reverse();
00185 void reset();
00186 };
00187
00188 #endif