localcli.cpp

来自「一个功能强大的内存数据库源代码,c++编写,有详细的注释」· C++ 代码 · 共 1,971 行 · 第 1/4 页

CPP
1,971
字号
//-< LOCALCLI.CPP >--------------------------------------------------*--------*// FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *// (Main Memory Database Management System)                          *   /\|  *//                                                                   *  /  \  *//                          Created:     20-Jun-2002  K.A. Knizhnik  * / [] \ *//                          Last update: 20-Jun-2002  K.A. Knizhnik  * GARRET *//-------------------------------------------------------------------*--------*// Implementation of local C interface to database//-------------------------------------------------------------------*--------*#define INSIDE_FASTDB#include "localcli.h"#include "ttree.h"#include "hashtab.h"#include "symtab.h"#include <ctype.h>dbCLI dbCLI::instance;int cli_open(char const* server_url,	     int         max_connect_attempts,	     int         reconnect_timeout_sec){    return cli_bad_address;}int cli_create(char const* databaseName,	       char const* filePath,	       unsigned    transactionCommitDelay, 	       int         openAttr, 	       size_t      initDatabaseSize,               size_t      extensionQuantum,               size_t      initIndexSize,               size_t      fileSizeLimit){    return dbCLI::instance.create_session(databaseName, filePath, transactionCommitDelay, openAttr,                                           initDatabaseSize, extensionQuantum, initIndexSize, fileSizeLimit);}int dbCLI::create_session(char const* databaseName, 			  char const* filePath,			  unsigned    transactionCommitDelay, 			  int         openAttr, 			  size_t      initDatabaseSize,                          size_t      extensionQuantum,                          size_t      initIndexSize,                          size_t      fileSizeLimit){    dbCriticalSection cs(sessionMutex);    dbDatabase* db = NULL;     session_desc* s;    for (s = active_session_list; s != NULL; s = s->next) { 	if (strcmp(s->name, databaseName) == 0) { 	    db = s->db;	    db->accessCount += 1;	    break;	}    }    if (db == NULL) { 	db = new dbDatabase((openAttr & cli_open_readonly) 			    ? (openAttr & cli_open_concurrent)                               ? dbDatabase::dbConcurrentRead : dbDatabase::dbReadOnly                             : (openAttr & cli_open_concurrent)                               ? dbDatabase::dbConcurrentUpdate : dbDatabase::dbAllAccess,			    initDatabaseSize,                             extensionQuantum,                             initIndexSize);	 	if (!db->open(databaseName, filePath, 0, transactionCommitDelay)) { 	    return cli_database_not_found;	}        db->setFileSizeLimit(fileSizeLimit);	dbTable* table = (dbTable*)db->getRow(dbMetaTableId);	dbTableDescriptor* metatable = new dbTableDescriptor(table);	db->linkTable(metatable, dbMetaTableId);	oid_t tableId = table->firstRow;	while (tableId != 0) {	    table = (dbTable*)db->getRow(tableId);	    dbTableDescriptor* desc;	    for (desc = db->tables; desc != NULL && desc->tableId != tableId; desc = desc->nextDbTable);	    if (desc == NULL) { 		desc = new dbTableDescriptor(table);		db->linkTable(desc, tableId);		desc->setFlags();	    }	    tableId = table->next;	}	if (!db->completeDescriptorsInitialization()) {	    return cli_table_not_found;	}	db->accessCount = 1;    }    s = sessions.allocate();    s->name = new char[strlen(databaseName) + 1];    strcpy(s->name, databaseName);    s->db = db;    s->stmts = NULL;    s->next = active_session_list;    s->existed_tables = db->tables;    s->dropped_tables = NULL;    active_session_list = s;    return s->id;}int cli_create_replication_node(int         nodeId,                                int         nServers,                                char*       nodeNames[],                                char const* databaseName,                                 char const* filePath,                                 int         openAttr,                                 size_t      initDatabaseSize,                                size_t      extensionQuantum,                                size_t      initIndexSize,                                size_t      fileSizeLimit){    return dbCLI::instance.create_replication_node(nodeId,                                                   nServers,                                                   nodeNames,                                                   databaseName,                                                    filePath,                                                    openAttr,                                                    initDatabaseSize,                                                   extensionQuantum,                                                   initIndexSize,                                                   fileSizeLimit);}int dbCLI::create_replication_node(int         nodeId,                                   int         nServers,                                   char*       nodeNames[],                                   char const* databaseName,                                    char const* filePath,                                    int         openAttr,                                    size_t      initDatabaseSize,                                   size_t      extensionQuantum,                                   size_t      initIndexSize,                                   size_t      fileSizeLimit){#ifdef REPLICATION_SUPPORT    dbCriticalSection cs(sessionMutex);    dbDatabase* db = NULL;     session_desc* s;    for (s = active_session_list; s != NULL; s = s->next) { 	if (strcmp(s->name, databaseName) == 0) { 	    db = s->db;	    db->accessCount += 1;	    break;	}    }    if (db == NULL) { 	db = new dbReplicatedDatabase((openAttr & cli_open_readonly)                                       ? (openAttr & cli_open_concurrent)                                       ? dbDatabase::dbConcurrentRead : dbDatabase::dbReadOnly                                       : (openAttr & cli_open_concurrent)                                       ? dbDatabase::dbConcurrentUpdate : dbDatabase::dbAllAccess,                                      initDatabaseSize,                                       extensionQuantum,                                       initIndexSize);	         	if (!((dbReplicatedDatabase*)db)->open(databaseName, filePath, nodeId, nodeNames, nServers)) {	    return cli_database_not_found;	}        db->setFileSizeLimit(fileSizeLimit);	dbTable* table = (dbTable*)db->getRow(dbMetaTableId);	dbTableDescriptor* metatable = new dbTableDescriptor(table);	db->linkTable(metatable, dbMetaTableId);	oid_t tableId = table->firstRow;	while (tableId != 0) {	    table = (dbTable*)db->getRow(tableId);	    dbTableDescriptor* desc;	    for (desc = db->tables; desc != NULL && desc->tableId != tableId; desc = desc->nextDbTable);	    if (desc == NULL) { 		desc = new dbTableDescriptor(table);		db->linkTable(desc, tableId);		desc->setFlags();	    }	    tableId = table->next;	}	if (!db->completeDescriptorsInitialization()) {	    return cli_table_not_found;	}	db->accessCount = 1;    }    s = sessions.allocate();    s->name = new char[strlen(databaseName) + 1];    strcpy(s->name, databaseName);    s->db = db;    s->stmts = NULL;    s->next = active_session_list;    s->existed_tables = db->tables;    s->dropped_tables = NULL;    active_session_list = s;    return s->id;#else     return cli_not_implemented;#endif}int cli_close(int session){    return dbCLI::instance.close(session);}int dbCLI::close(int session){    dbCriticalSection cs(sessionMutex);    statement_desc *stmt, *next;    session_desc* s = sessions.get(session);    if (s == NULL) {	return cli_bad_descriptor;    }        for (stmt = s->stmts; stmt != NULL; stmt = next) {	next = stmt->next;	free_statement(stmt);    }    if (--s->db->accessCount == 0) { 	dbTableDescriptor *desc, *next_desc;	for (desc = s->db->tables; desc != NULL; desc = next_desc) {	    next_desc = desc->nextDbTable;	    if (!desc->isStatic) { 		delete desc;	    }	}	s->db->tables = NULL;	s->db->close();	delete s->db;    }    while (s->dropped_tables != NULL) {	dbTableDescriptor* next = s->dropped_tables->nextDbTable;	delete s->dropped_tables;	s->dropped_tables = next;    }    session_desc** spp;    for (spp = &active_session_list; *spp != s; spp = &(*spp)->next);    *spp = s->next;    delete[] s->name;    sessions.free(s);    return cli_ok;}int cli_statement(int session, char const* sql){    return dbCLI::instance.create_statement(session, sql);}int dbCLI::create_statement(int session, char const* sql){    session_desc* s = sessions.get(session);    if (s == NULL) {	return cli_bad_descriptor;    }    statement_desc* stmt = statements.allocate();    stmt->sql = new char[strlen(sql)+1];    strcpy(stmt->sql, sql);    stmt->columns = NULL;    stmt->params = NULL;    stmt->session = s;    stmt->for_update = 0;    stmt->first_fetch = true;    stmt->prepared = false;    stmt->n_params = 0;    stmt->n_columns = 0;    stmt->n_autoincremented_columns = 0;    stmt->oid = 0;    stmt->next = s->stmts;    stmt->updated = false;    stmt->table = NULL;    s->stmts = stmt;    char const* p = sql;    parameter_binding** last = &stmt->params;    while (*p != '\0') {	if (*p == '\'') {	    do {		do {		    p += 1;		} while (*p != '\0' && *p != '\'');		if (*p == '\0') {		    *last = NULL;		    free_statement(stmt);		    return cli_bad_statement;		}	    } while (*++p == '\'');	} else if (*p == '%') {	    stmt->n_params += 1;	    char const* q = p++;	    while (isalnum((unsigned char)*p) || *p == '_') p += 1;	    if (*p == '%') {		*last = NULL;		free_statement(stmt);		return cli_bad_statement;	    }	    parameter_binding* pb = parameter_allocator.allocate();	    int len = p - q;	    pb->name = new char[len+1];	    memcpy(pb->name, q, len);	    pb->name[len] = '\0';	    *last = pb;	    last = &pb->next;	    pb->var_ptr = NULL;	} else {	    p += 1;	}    }    *last = NULL;    return stmt->id;}int cli_parameter(int           statement,		  char const* param_name,		  int           var_type,		  void*         var_ptr){    return dbCLI::instance.bind_parameter(statement, param_name, var_type, var_ptr);}int dbCLI::bind_parameter(int           statement,			  char const* param_name,			  int           var_type,			  void*         var_ptr){    if ((unsigned)var_type >= cli_array_of_oid) {	return cli_unsupported_type;    }    statement_desc* s = statements.get(statement);    if (s == NULL) {	return cli_bad_descriptor;    }    s->prepared = false;    for (parameter_binding* pb = s->params; pb != NULL; pb = pb->next) {	if (strcmp(pb->name, param_name) == 0) {	    pb->var_ptr  = var_ptr;	    pb->var_type = var_type;	    return cli_ok;	}    }    return cli_parameter_not_found;}int cli_column(int           statement,	       char const* column_name,	       int           var_type,	       int*          var_len,	       void*         var_ptr){    return dbCLI::instance.bind_column(statement, column_name, var_type, var_len, var_ptr);}int dbCLI::bind_column(int           statement,		       char const* column_name,		       int           var_type,		       int*          var_len,		       void*         var_ptr){    statement_desc* s = statements.get(statement);    if (s == NULL) {	return cli_bad_descriptor;    }    if ((unsigned)var_type >= cli_unknown) { 	return cli_unsupported_type;    }    s->prepared = false;    if (var_type == cli_autoincrement) {	s->n_autoincremented_columns += 1;    }    column_binding* cb = column_allocator.allocate();    cb->name = new char[strlen(column_name) + 1];    cb->next = s->columns;    s->columns = cb;    s->n_columns += 1;    strcpy(cb->name, column_name);    cb->var_type = var_type;    cb->var_len = var_len;    cb->var_ptr = var_ptr;    cb->set_fnc = NULL;    cb->get_fnc = NULL;    return cli_ok;}int cli_array_column(int            statement,		     char const*  column_name,		     int            var_type,		     void*          var_ptr,		     cli_column_set set,		     cli_column_get get){    return cli_array_column_ex(statement, column_name, var_type, var_ptr, 			       (cli_column_set_ex)set, (cli_column_get_ex)get);}int cli_array_column_ex(int               statement,			char const*     column_name,			int               var_type,			void*             var_ptr,			cli_column_set_ex set,			cli_column_get_ex get){    return dbCLI::instance.bind_array_column(statement, column_name, var_type, var_ptr, set, get);}int dbCLI::bind_array_column(int               statement,			     char const*     column_name,			     int               var_type,			     void*             var_ptr,			     cli_column_set_ex set,			     cli_column_get_ex get){    statement_desc* s = statements.get(statement);    if (s == NULL) {	return cli_bad_descriptor;    }    if (var_type < cli_asciiz || var_type > cli_array_of_string) {	return cli_unsupported_type;    }    s->prepared = false;    column_binding* cb = new column_binding;    cb->name = new char[strlen(column_name) + 1];    cb->next = s->columns;    s->columns = cb;    s->n_columns += 1;    strcpy(cb->name, column_name);    cb->var_type = var_type;    cb->var_len = NULL;    cb->var_ptr = var_ptr;    cb->set_fnc = set;    cb->get_fnc = get;    return cli_ok;}int dbCLI::match_columns(char const* table_name, statement_desc* stmt){        stmt->table = stmt->session->db->findTable(table_name);    if (stmt->table == NULL) {	return cli_table_not_found;    }    for (column_binding* cb = stmt->columns; cb != NULL; cb = cb->next) { 	cb->field = stmt->table->find(cb->name);	if (cb->field == NULL) { 	    return cli_column_not_found;	}    }    return cli_ok;}int cli_fetch(int statement, int for_update){    return dbCLI::instance.fetch(statement, for_update);}int dbCLI::fetch(int statement, int for_update){    statement_desc* stmt = statements.get(statement);        if (stmt == NULL) {	return cli_bad_descriptor;    }    stmt->for_update = for_update;    stmt->oid = 0;    if (!stmt->prepared) {	int tkn;	sql_scanner scanner(stmt->sql);	if (scanner.get() != tkn_select) {	    return cli_bad_statement;	}	if ((tkn = scanner.get()) == tkn_all) {	    tkn = scanner.get();	}	if (tkn == tkn_from && scanner.get() == tkn_ident) {	    int rc = match_columns(scanner.identifier(), stmt);	    if (rc != cli_ok) { 		return rc;	    }	} else { 	    return cli_bad_statement;	}	char* p = scanner.current_position(), *q = p;	parameter_binding* pb = stmt->params;	stmt->query.reset();	while (*p != '\0') {	    if (*p == '\'') {		do {		    do {			p += 1;		    } while (*p != '\0' && *p != '\'');		    if (*p == '\0') {			return cli_bad_statement;		    }		} while (*++p == '\'');	    } else if (*p == '%') {		if (p != q) { 		    *p = '\0';		    stmt->query.append(dbQueryElement::qExpression, q);		    

⌨️ 快捷键说明

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