📄 localcli.cpp
字号:
//-< 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 "rtree.h"
#include "hashtab.h"
#include "symtab.h"
#include <ctype.h>
USE_FASTDB_NAMESPACE
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, INFINITE, transactionCommitDelay)) {
db->close();
delete db;
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()) {
db->close();
delete db;
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()) {
db->close();
delete db;
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;
}
dbCriticalSection cs2(s->mutex);
for (stmt = s->stmts; stmt != NULL; stmt = next) {
next = stmt->next;
release_statement(stmt);
}
if (--s->db->accessCount == 0) {
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.put(strlen(sql)+1);
strcpy(stmt->sql.base(), 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->record_struct = NULL;
stmt->n_autoincremented_columns = 0;
stmt->oid = 0;
stmt->updated = false;
stmt->table = NULL;
stmt->cursor.db = NULL;
{
dbCriticalSection cs(s->mutex);
stmt->next = s->stmts;
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 && var_type != cli_rectangle && var_type != cli_datetime) {
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -