📄 subsql.cpp
字号:
//-< SUBSQL.CPP >----------------------------------------------------*--------*// FastDB Version 1.0 (c) 1999 GARRET * ? *// (Main Memory Database Management System) * /\| *// * / \ *// Created: 20-Nov-98 K.A. Knizhnik * / [] \ *// Last update: 10-Dec-98 K.A. Knizhnik * GARRET *//-------------------------------------------------------------------*--------*// Interactive data manipulation language (subset of SQL)//-------------------------------------------------------------------*--------*#include <stdio.h>#include <ctype.h>#include "fastdb.h"#include "compiler.h"#include "wwwapi.h"#include "subsql.h"#include "symtab.h"#include "hashtab.h"#include "ttree.h"#include "rtree.h"#if THREADS_SUPPORTED#include "server.h"#endifBEGIN_FASTDB_NAMESPACEstatic char* typeMnem[] = { "Boolean", "Int1", "Int2", "Int4", "Int8", "Real4", "Real8", "String", "Reference", "Array", "MethodBool", "MethodInt1", "MethodInt2", "MethodInt4", "MethodInt8", "MethodReal4", "MethodReal8", "MethodString", "MethodReference", "Structure", "RawBinary", "StdString", "Rectangle", "Unknown" };char* dbSubSql::prompt = ">> ";dbSubSql::dbSubSql(dbAccessType accessType): dbDatabase(accessType){ static struct { char* name; int tag; } keywords[] = { {"alter", tkn_alter}, {"array", tkn_array}, {"autocommit", tkn_autocommit}, {"autoincrement",tkn_autoincrement}, {"backup", tkn_backup}, {"bool", tkn_bool}, {"commit", tkn_commit}, {"compactify",tkn_compactify}, {"count", tkn_count}, {"create", tkn_create}, {"delete", tkn_delete}, {"describe",tkn_describe}, {"drop", tkn_drop}, {"exit", tkn_exit}, {"export", tkn_export}, {"hash", tkn_hash}, {"help", tkn_help}, {"http", tkn_http}, {"import", tkn_import}, {"index", tkn_index}, {"int1", tkn_int1}, {"int2", tkn_int2}, {"int4", tkn_int4}, {"int8", tkn_int8}, {"inverse", tkn_inverse}, {"of", tkn_of}, {"off", tkn_off}, {"on", tkn_on}, {"open", tkn_open}, {"profile", tkn_profile}, {"reference",tkn_reference}, {"real4", tkn_real4}, {"real8", tkn_real8}, {"rectangle", tkn_rectangle}, {"rollback",tkn_rollback}, {"server", tkn_server}, {"set", tkn_set}, {"stop", tkn_stop}, {"show", tkn_show}, {"to", tkn_to}, {"update", tkn_update}, {"values", tkn_values}, {"version", tkn_version} }; for (unsigned i = 0; i < itemsof(keywords); i++) { dbSymbolTable::add(keywords[i].name, keywords[i].tag, FASTDB_CLONE_ANY_IDENTIFIER); } droppedTables = NULL; existedTables = NULL; opened = false; buflen = 1024; buf = new char[buflen]; httpServerRunning = false; databaseName = NULL; historyUsed = historyCurr = 0; ungetToken = -1; dotIsPartOfIdentifier = false; autocommit = false; dateFormat = getenv("SUBSQL_DATE_FORMAT");}dbSubSql::~dbSubSql() { delete[] buf; }//// Find one string within another, ignoring case//inline char* stristr(const char* haystack, const char* needle){ nat4 i, hayLen, ndlLen; ndlLen = strlen(needle); hayLen = strlen(haystack); if (ndlLen > hayLen) { return NULL; } for (i = 0; i <= (hayLen - ndlLen); i++) { if (strincmp(&haystack[i], needle, ndlLen) == 0) { return (char*)&haystack[i]; } } return NULL;}bool contains(dbUserFunctionArgument& arg1, dbUserFunctionArgument& arg2) { assert(arg1.type == dbUserFunctionArgument::atString && arg2.type == dbUserFunctionArgument::atString); return stristr(arg1.u.strValue, arg2.u.strValue) != NULL;}USER_FUNC(contains);char* cmpOidAndStr(dbUserFunctionArgument& arg1, dbUserFunctionArgument& arg2) { assert(arg1.type == dbUserFunctionArgument::atReference && arg2.type == dbUserFunctionArgument::atString); printf("arg1.u.oidValue=%x, arg1.u.strValue=%s\n", arg1.u.oidValue, arg2.u.strValue); char* ptr = new char[16]; sprintf(ptr, "%x", arg1.u.oidValue); return ptr;}USER_FUNC(cmpOidAndStr);int dbSubSql::get() { int ch = getc(in); if (ch == '\n') { pos = 0; line += 1; } else if (ch == '\t') { pos = DOALIGN(pos + 1, 8); } else { pos += 1; } return ch;}void dbSubSql::unget(int ch) { if (ch != EOF) { if (ch != '\n') { pos -= 1; } else { line -= 1; } ungetc(ch, in); }}void dbSubSql::warning(char const* msg){ fprintf(stderr, "%s at line %d position %d\n", msg, line, tknPos > 0 ? tknPos - 1 : 0);}void dbSubSql::error(char const* msg){#ifdef THROW_EXCEPTION_ON_ERROR dbDatabaseThreadContext* ctx = threadContext.get(); if (ctx != NULL) { ctx->interactive = true; } try { handleError(QueryError, msg, tknPos > 0 ? tknPos - 1 : 0); } catch(dbException) {}#else dbDatabaseThreadContext* ctx = threadContext.get(); if (ctx != NULL) { ctx->interactive = true; ctx->catched = true; if (setjmp(ctx->unwind) == 0) { handleError(QueryError, msg, tknPos > 0 ? tknPos - 1 : 0); } ctx->catched = false; } else { handleError(QueryError, msg, tknPos > 0 ? tknPos - 1 : 0); }#endif}int dbSubSql::scan() { int i, ch, digits; if (ungetToken >= 0) { int tkn = ungetToken; ungetToken = -1; return tkn; } bool dotIsIdentifierChar = dotIsPartOfIdentifier; dotIsPartOfIdentifier = false; nextToken: do { if ((ch = get()) == EOF) { return tkn_eof; } } while (isspace(ch)); tknPos = pos; switch (ch) { case '*': return tkn_all; case '(': return tkn_lpar; case ')': return tkn_rpar; case ',': return tkn_comma; case '.': return tkn_dot; case ';': return tkn_semi; case '=': return tkn_eq; case '\'': i = 0; while (true) { ch = get(); if (ch == '\'') { if ((ch = get()) != '\'') { unget(ch); break; } } else if (ch == '\n' || ch == EOF) { unget(ch); error("New line within character constant"); return tkn_error; } if (i+1 == buflen) { char* newbuf = new char[buflen*2]; memcpy(newbuf, buf, buflen); delete[] buf; buf = newbuf; buflen *= 2; } buf[i++] = ch; } buf[i] = '\0'; return tkn_sconst; case '-': if ((ch = get()) == '-') { // ANSI comments while ((ch = get()) != EOF && ch != '\n'); goto nextToken; } unget(ch); ch = '-'; // no break case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': i = 0; do { buf[i++] = ch; if (i == buflen) { error("Numeric constant too long"); return tkn_error; } ch = get(); } while (ch != EOF && (isdigit(ch) || ch == '+' || ch == '-' || ch == 'e' || ch == 'E' || ch == '.')); unget(ch); buf[i] = '\0'; if (sscanf(buf, INT8_FORMAT "%n", &ival, &digits) != 1) { error("Bad integer constant"); return tkn_error; } if (digits != i) { if (sscanf(buf, "%lf%n", &fval, &digits) != 1 || digits != i) { error("Bad float constant"); return tkn_error; } return tkn_fconst; } return tkn_iconst; case '#': ival = 0; while (true) { ch = get(); if (ch >= '0' && ch <= '9') { ival += (ival << 4) + ch-'0'; } else if (ch >= 'a' && ch <= 'f') { ival += (ival << 4) + ch-'a'+10; } else if (ch >= 'A' && ch <= 'F') { ival += (ival << 4) + ch-'A'+10; } else { unget(ch); return tkn_iconst; } } default: if (isalpha(ch) || ch == '$' || ch == '_') { i = 0; do { buf[i++] = ch; if (i == buflen) { error("Identifier too long"); return tkn_error; } ch = get(); } while (ch != EOF && (isalnum(ch) || ch == '$' || ch == '_' || (ch == '.' && dotIsIdentifierChar))); unget(ch); buf[i] = '\0'; name = buf; return dbSymbolTable::add(name, tkn_ident); } else { error("Invalid symbol"); return tkn_error; } }}bool dbSubSql::expect(char* expected, int token){ int tkn = scan(); if (tkn != token) { if (tkn != tkn_error) { char buf[256]; sprintf(buf, "Token '%s' expected", expected); error(buf); } return false; } return true;} bool dbSubSql::updateTable(bool create){ int tkn; dotIsPartOfIdentifier = true; if (!expect("table name", tkn_ident) || !expect("(", tkn_lpar)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -