00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __SUBSQL_H__
00012 #define __SUBSQL_H__
00013
00014 #pragma warning(disable: 4786)
00015
00016 BEGIN_GIGABASE_NAMESPACE
00017
00018 enum SubSqlTokens {
00019 tkn_alter = tkn_last_token,
00020 tkn_array,
00021 tkn_autoincrement,
00022 tkn_autocommit,
00023 tkn_backup,
00024 tkn_bool,
00025 tkn_commit,
00026 tkn_compactify,
00027 tkn_count,
00028 tkn_create,
00029 tkn_delete,
00030 tkn_describe,
00031 tkn_drop,
00032 tkn_exit,
00033 tkn_export,
00034 tkn_hash,
00035 tkn_help,
00036 tkn_http,
00037 tkn_import,
00038 tkn_index,
00039 tkn_int1,
00040 tkn_int2,
00041 tkn_int4,
00042 tkn_int8,
00043 tkn_inverse,
00044 tkn_memory,
00045 tkn_of,
00046 tkn_off,
00047 tkn_on,
00048 tkn_open,
00049 tkn_profile,
00050 tkn_real4,
00051 tkn_real8,
00052 tkn_rectangle,
00053 tkn_reference,
00054 tkn_restore,
00055 tkn_rollback,
00056 tkn_server,
00057 tkn_set,
00058 tkn_stop,
00059 tkn_semi,
00060 tkn_show,
00061 tkn_to,
00062 tkn_update,
00063 tkn_values,
00064 tkn_version,
00065 tkn_include,
00066 tkn_exclude,
00067 };
00068
00069 struct tableField {
00070 char_t* name;
00071 char_t* refTableName;
00072 char_t* inverseRefName;
00073 int type;
00074
00075 tableField() { name = refTableName = inverseRefName = NULL; }
00076 ~tableField() { delete[] name; delete[] refTableName; delete[] inverseRefName; }
00077 };
00078
00079
00080 class dbList {
00081 public:
00082 enum NodeType {
00083 nInteger,
00084 nBool,
00085 nReal,
00086 nString,
00087 nTuple,
00088 nAutoinc
00089 };
00090
00091 dbList* next;
00092 int type;
00093 union {
00094 bool bval;
00095 db_int8 ival;
00096 real8 fval;
00097 char_t* sval;
00098 struct {
00099 int nComponents;
00100 dbList* components;
00101 } aggregate;
00102 };
00103
00104 ~dbList() {
00105 if (type == nTuple) {
00106 dbList* list = aggregate.components;
00107 while (list != NULL) {
00108 dbList* tail = list->next;
00109 delete list;
00110 list = tail;
00111 }
00112 } else if (type == nString) {
00113 delete[] sval;
00114 }
00115 }
00116
00117 dbList(int type) {
00118 this->type = type;
00119 next = NULL;
00120 }
00121 };
00122
00123 class dbUpdateElement {
00124 public:
00125 dbUpdateElement* next;
00126 dbFieldDescriptor* field;
00127 dbExprNode* value;
00128 char_t* strValue;
00129
00130 dbUpdateElement() {
00131 next = NULL;
00132 strValue = NULL;
00133 value = NULL;
00134 }
00135 ~dbUpdateElement() {
00136 delete[] strValue;
00137 delete value;
00138 }
00139 };
00140
00141
00142 #define MAX_HISTORY_SIZE 16
00143
00144 class dbXmlScanner {
00145 public:
00146 enum {
00147 MaxIdentSize = 256
00148 };
00149 enum token {
00150 xml_ident,
00151 xml_sconst,
00152 xml_iconst,
00153 xml_fconst,
00154 xml_lt,
00155 xml_gt,
00156 xml_lts,
00157 xml_gts,
00158 xml_eq,
00159 xml_eof,
00160 xml_error
00161 };
00162 dbXmlScanner(FILE* f) {
00163 in = f;
00164 sconst = new char_t[size = 1024];
00165 line = 1;
00166 pos = 0;
00167 }
00168 token scan();
00169
00170 char_t* getString() {
00171 return sconst;
00172 }
00173
00174 char_t* getIdentifier() {
00175 return ident;
00176 }
00177
00178 size_t getStringLength() {
00179 return slen;
00180 }
00181
00182 db_int8 getInt() {
00183 return iconst;
00184 }
00185
00186 double getReal() {
00187 return fconst;
00188 }
00189
00190 bool expect(int sourcePos, token expected) {
00191 return assure(scan(), sourcePos, expected);
00192 }
00193
00194 bool assure(token tkn, int sourcePos, token expected) {
00195 if (tkn != expected) {
00196 fprintf(stderr, "subsql.cpp:%d: line %d, column %d: Get token %d instead of expected token %d\n",
00197 sourcePos, line, pos, tkn, expected);
00198 return false;
00199 }
00200 return true;
00201 }
00202
00203 bool expect(int sourcePos, char_t* expected) {
00204 token tkn = scan();
00205 if (tkn != xml_ident) {
00206 fprintf(stderr, "subsql.cpp:%d: line %d, column %d: Get token %d instead of expected identifier\n",
00207 sourcePos, line, pos, tkn);
00208 return false;
00209 }
00210 if (STRCMP(ident, expected) != 0) {
00211 FPRINTF(stderr, STRLITERAL("subsql.cpp:%d: line %d, column %d: Get tag '%s' instead of expected '%s'\n"),
00212 sourcePos, line, pos, ident, expected);
00213 return false;
00214 }
00215 return true;
00216 }
00217
00218 private:
00219 int get();
00220 void unget(int ch);
00221
00222 int line;
00223 int pos;
00224 FILE* in;
00225 char_t* sconst;
00226 size_t size;
00227 size_t slen;
00228 db_int8 iconst;
00229 double fconst;
00230 char_t ident[MaxIdentSize];
00231 };
00232
00233 class dbTmpAllocator {
00234 enum {
00235 CHUNK_SIZE = 4096
00236 };
00237 struct Chunk {
00238 Chunk* next;
00239 Chunk* prev;
00240 };
00241 Chunk* curr;
00242 size_t used;
00243
00244 public:
00245 dbTmpAllocator() {
00246 curr = NULL;
00247 used = CHUNK_SIZE;
00248 }
00249
00250 ~dbTmpAllocator() {
00251 reset();
00252 }
00253
00254 void reset() {
00255 Chunk *c, *next;
00256 for (c = curr; c != NULL; c = next) {
00257 next = c->next;
00258 dbFree(c);
00259 }
00260 curr = NULL;
00261 used = CHUNK_SIZE;
00262 }
00263
00264
00265 void* alloc(size_t size) {
00266 size = DOALIGN(size, 8);
00267 if (size > CHUNK_SIZE/2) {
00268 Chunk* newChunk = (Chunk*)dbMalloc(size + sizeof(Chunk));
00269 if (curr != NULL) {
00270 newChunk->next = curr->next;
00271 curr->next = newChunk;
00272 } else {
00273 curr = newChunk;
00274 newChunk->next = NULL;
00275 used = CHUNK_SIZE;
00276 }
00277 return newChunk+1;
00278 } else if (size <= CHUNK_SIZE - used) {
00279 used += size;
00280 return (char*)curr + used - size;
00281 } else {
00282 Chunk* newChunk = (Chunk*)dbMalloc(CHUNK_SIZE);
00283 used = sizeof(Chunk) + size;
00284 newChunk->next = curr;
00285 curr = newChunk;
00286 return newChunk+1;
00287 }
00288 }
00289 };
00290
00298 class TextVector
00299 {
00300 public:
00301 TextVector();
00302 ~TextVector();
00303
00305 void clear();
00306
00308 void add(const char_t *text);
00309
00311 bool inVector(const char_t *text) const;
00312 protected:
00313 typedef char_t *CharPtr;
00314 CharPtr *m_items;
00315 int m_nrItems;
00316 int m_bufSize;
00317
00318 private:
00320 TextVector(const TextVector &other);
00321 TextVector &operator=(const TextVector &other);
00322 };
00323
00324 class dbSubSql : public dbDatabase {
00325 private:
00327 enum SelectionMethod {
00328 sel_all,
00329 sel_all_except,
00330 sel_named_only,
00331 };
00332
00333 int pos;
00334 int line;
00335 int tknPos;
00336 char_t* buf;
00337 int buflen;
00338 FILE* in;
00339 bool opened;
00340 db_int8 ival;
00341 real8 fval;
00342 char_t* name;
00343
00344 oid_t* oidMap;
00345 oid_t oidMapSize;
00346
00347 dbTmpAllocator tmpAlloc;
00348
00349 dbTableDescriptor* metatable;
00350 static char const* prompt;
00351
00352 dbTableDescriptor* droppedTables;
00353 dbTableDescriptor* existedTables;
00354
00355 dbQuery query;
00356 dbCompiler compiler;
00357
00358 int ungetToken;
00359 bool autocommit;
00360
00361 bool dotIsPartOfIdentifier;
00362
00363 char_t* dateFormat;
00364
00365 dbEvent daemonTerminationEvent;
00366 dbThread httpServerThread;
00367 HTTPapi* httpServer;
00368 bool httpServerRunning;
00369 char_t* databasePath;
00370 char* queryHistory[MAX_HISTORY_SIZE];
00371 unsigned historyUsed;
00372 unsigned historyCurr;
00373
00374 static void thread_proc httpServerThreadProc(void* arg);
00375
00376 void deleteColumns(dbFieldDescriptor* columns);
00377
00378 void httpServerLoop();
00379
00380 void startHttpServer(char_t const* address);
00381 void stopHttpServer(char_t const* address);
00382
00383 void handleError(dbErrorClass error, char const* msg = NULL, int arg = 0);
00384
00385 void warning(char const* msg);
00386 void error(char const* msg);
00387
00388 int get();
00389 void unget(int ch);
00390 int scan();
00391 bool parse();
00392
00393 bool expect(char const* expected, int token);
00394
00395 void recovery();
00396 void profile();
00397
00398 void exportDatabase(FILE* out, const TextVector &tables, SelectionMethod method);
00399 bool importDatabase(FILE* in);
00400
00401 oid_t mapId(long id);
00402 bool importField(char_t* terminator, dbFieldDescriptor* fd, byte* rec, dbXmlScanner& scanner);
00403 bool importRecord(char_t* terminator, dbFieldDescriptor* fieldList, byte* rec, dbXmlScanner& scanner);
00404 void insertRecord(dbTableDescriptor* desc, oid_t oid, void const* record);
00405
00406 bool isValidOid(oid_t oid);
00407
00408 void dumpRecord(byte* record, dbFieldDescriptor* first);
00409 static int calculateRecordSize(dbList* list, int offs,
00410 dbFieldDescriptor* first);
00411 int initializeRecordFields(dbList* node, byte* dst, int offs,
00412 dbFieldDescriptor* first);
00413 bool insertRecord(dbList* list, dbTableDescriptor* desc);
00414 bool readCondition();
00415 int readExpression();
00416 int readValues(dbList** chain);
00417 bool updateFields(dbAnyCursor* cursor, dbUpdateElement* elems);
00418 bool updateTable(bool create);
00419 int parseType(char_t*& reftableName, char_t*& inverseRefName);
00420 int updateRecords(dbTableDescriptor* desc, dbList *fields, dbList *values, dbAnyCursor &cursor, byte *buf);
00421
00422 dbFieldDescriptor* readFieldName();
00423
00425 bool parseExportTables(TextVector &tables, SelectionMethod &method);
00426 bool shouldExportTable(const char_t *name, const TextVector &tableNames, SelectionMethod method);
00427
00428 public:
00429 void run(int argc, char* argv[]);
00430 void selectionPage(WWWconnection& con);
00431 void queryPage(WWWconnection& con);
00432 void defaultPage(WWWconnection& con);
00433
00434 dbSubSql(dbAccessType type = dbAllAccess, size_t poolSize = 0);
00435 virtual~dbSubSql();
00436 };
00437
00438 END_GIGABASE_NAMESPACE
00439
00440
00441 #endif