⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subsql.cpp

📁 用于嵌入式环境的数据库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//-< 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"

#if THREADS_SUPPORTED
#include "server.h"
#endif

static char* typeMnem[] = {
        "Boolean",
        "Int1",
        "Int2",
        "Int4",
        "Int8",
        "Real4",
        "Real8",
        "String",
        "Reference",
        "Array",
        "MethodBool",
        "MethodInt1",
        "MethodInt2",
        "MethodInt4",
        "MethodInt8",
        "MethodReal4",
        "MethodReal8",
        "MethodString",
        "MethodReference",
        "Structure",
        "RawBinary",
        "StdString",
        "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},
        {"reference",tkn_reference},
        {"real4",   tkn_real4},
        {"real8",   tkn_real8},
        {"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;
    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);

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;
    }
  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 == '_'));
            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;
    if (!expect("table name", tkn_ident) || !expect("(", tkn_lpar)) { 
        return false;
    }
    char* name = this->name;
    int varyingLength = strlen(name)+1;

    static const struct { 
        int size;
        int alignment;
    } typeDesc[] = { 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -