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