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