00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __LOCALCLI_H__
00012 #define __LOCALCLI_H__
00013
00014 #include "gigabase.h"
00015 #include "compiler.h"
00016 #include "cli.h"
00017 #include "cliproto.h"
00018 #include "array.h"
00019
00020 BEGIN_GIGABASE_NAMESPACE
00021
00022 inline int map_type(dbFieldDescriptor* fd) {
00023 return (fd->type < dbField::tpArray)
00024 ? gb2cli_type_mapping[fd->type]
00025 : (fd->type == dbField::tpArray && fd->components->type < dbField::tpArray)
00026 ? cli_array_of_oid + gb2cli_type_mapping[fd->components->type]
00027 : (fd->type == dbField::tpRectangle)
00028 ? cli_rectangle
00029 : cli_unknown;
00030 }
00031
00032
00033 struct parameter_binding {
00034 parameter_binding* next;
00035 char_t* name;
00036 int var_type;
00037 int var_len;
00038 void* var_ptr;
00039 };
00040
00041 struct column_binding {
00042 column_binding* next;
00043 dbFieldDescriptor* field;
00044 char_t* name;
00045 int var_type;
00046 int* var_len;
00047 void* var_ptr;
00048 cli_column_get_ex get_fnc;
00049 cli_column_set_ex set_fnc;
00050 };
00051
00052 struct session_desc;
00053
00054 struct statement_desc {
00055 int id;
00056 statement_desc* next;
00057 dbQuery query;
00058 dbAnyCursor cursor;
00059 dbTableDescriptor* table;
00060 column_binding* columns;
00061 parameter_binding* params;
00062 session_desc* session;
00063 bool first_fetch;
00064 bool for_update;
00065 bool prepared;
00066 bool updated;
00067 cli_oid_t oid;
00068 int n_params;
00069 int n_columns;
00070 int n_autoincremented_columns;
00071 int param_size;
00072 void* record_struct;
00073 dbSmallBuffer<char_t> sql;
00074
00075 statement_desc(int id, statement_desc* next)
00076 {
00077 this->id = id;
00078 this->next = next;
00079 }
00080 statement_desc() {}
00081 };
00082
00083
00084 class sql_scanner {
00085 private:
00086 char_t* p;
00087 char_t* ident;
00088
00089 public:
00090 int get();
00091
00092 char_t* current_position() {
00093 return p;
00094 }
00095
00096 char_t* identifier() {
00097 return ident;
00098 }
00099
00100 sql_scanner(char_t* sql) {
00101 p = sql;
00102 }
00103 };
00104
00105 struct session_desc {
00106 int id;
00107 char_t* name;
00108 session_desc* next;
00109 statement_desc* stmts;
00110 dbDatabase* db;
00111 dbMutex mutex;
00112 dbTableDescriptor* dropped_tables;
00113 dbTableDescriptor* existed_tables;
00114
00115 session_desc(int id, session_desc* next) {
00116 this->id = id;
00117 this->next = next;
00118 }
00119 session_desc() {}
00120 };
00121
00122 template<class T>
00123 class fixed_size_object_allocator {
00124 protected:
00125 T* free_chain;
00126 dbMutex mutex;
00127 int n_objects;
00128
00129 public:
00130 bool is_empty() {
00131 return n_objects == 0;
00132 }
00133
00134 T* allocate() {
00135 dbCriticalSection cs(mutex);
00136 T* obj = free_chain;
00137 if (obj == NULL) {
00138 obj = new T();
00139 } else {
00140 free_chain = obj->next;
00141 }
00142 n_objects += 1;
00143 return obj;
00144 }
00145
00146 void free(T* desc) {
00147 dbCriticalSection cs(mutex);
00148 desc->next = free_chain;
00149 free_chain = desc;
00150 n_objects -= 1;
00151 }
00152
00153 fixed_size_object_allocator() {
00154 free_chain = NULL;
00155 }
00156
00157 ~fixed_size_object_allocator() {
00158 T *obj, *next;
00159 for (obj = free_chain; obj != NULL; obj = next) {
00160 next = obj->next;
00161 delete obj;
00162 }
00163 }
00164 };
00165
00166 template<class T>
00167 class descriptor_table : public fixed_size_object_allocator<T> {
00168 protected:
00169 T** table;
00170 int descriptor_table_size;
00171
00172 public:
00173 descriptor_table() {
00174 int i;
00175 descriptor_table_size = 16;
00176 table = new T*[descriptor_table_size];
00177 T* next = NULL;
00178 for (i = 0; i < descriptor_table_size; i++) {
00179 table[i] = next = new T(i, next);
00180 }
00181 free_chain = next;
00182 }
00183
00184 ~descriptor_table() {
00185 delete[] table;
00186 }
00187
00188 T* get(int desc) {
00189 dbCriticalSection cs(mutex);
00190 return (desc >= descriptor_table_size) ? (T*)0 : table[desc];
00191 }
00192
00193 T* allocate() {
00194 dbCriticalSection cs(mutex);
00195 if (free_chain == NULL) {
00196 int i, n;
00197 T** desc = new T*[descriptor_table_size * 2];
00198 memcpy(desc, table, descriptor_table_size*sizeof(T*));
00199 delete[] table;
00200 table = desc;
00201 T* next = NULL;
00202 for (i = descriptor_table_size, n = i*2; i < n; i++) {
00203 table[i] = next = new T(i, next);
00204 }
00205 free_chain = next;
00206 descriptor_table_size = n;
00207 }
00208 T* desc = free_chain;
00209 free_chain = desc->next;
00210 return desc;
00211 }
00212 };
00213
00214 class GIGABASE_DLL_ENTRY dbCLI {
00215 private:
00216 fixed_size_object_allocator<column_binding> column_allocator;
00217 fixed_size_object_allocator<parameter_binding> parameter_allocator;
00218
00219 descriptor_table<session_desc> sessions;
00220 descriptor_table<statement_desc> statements;
00221
00222 session_desc* active_session_list;
00223
00224 dbMutex sessionMutex;
00225
00226 static int calculate_varying_length(char_t const* tableName, int& nFields, cli_field_descriptor* columns);
00227 static dbTableDescriptor* create_table_descriptor(dbDatabase* db,
00228 dbTable* table, char_t const* tableName,
00229 int nFields, int nColumns,
00230 cli_field_descriptor* columns);
00231
00232 public:
00233 static dbCLI instance;
00234
00235 dbCLI() {
00236 active_session_list = NULL;
00237 }
00238
00239 int create_session(char_t const* databasePath,
00240 time_t transactionCommitDelay,
00241 int openAttr,
00242 size_t poolSize);
00243
00244 int create_statement(int session, char_t const* sql);
00245 int bind_parameter(int statement,
00246 char_t const* param_name,
00247 int var_type,
00248 void* var_ptr);
00249 int bind_column(int statement,
00250 char_t const* column_name,
00251 int var_type,
00252 int* var_len,
00253 void* var_ptr);
00254
00255 int bind_array_column(int statement,
00256 char_t const* column_name,
00257 int var_type,
00258 void* var_ptr,
00259 cli_column_set_ex set,
00260 cli_column_get_ex get);
00261
00262 int fetch(int statement, int for_update);
00263
00264 int fetch_columns(statement_desc* stmt);
00265 int store_columns(char* buf, statement_desc* stmt);
00266
00267 int insert(int statement, cli_oid_t* oid);
00268 int update(int statement);
00269
00270 int freeze(int statement);
00271 int unfreeze(int statement);
00272
00273 int get_first(int statement);
00274 int get_last(int statement);
00275 int get_next(int statement);
00276 int get_prev(int statement);
00277
00278 int skip(int statement, int n);
00279 int seek(int statement, cli_oid_t oid);
00280
00281 cli_oid_t get_current_oid(int statement);
00282 int free_statement(int statement);
00283 int free_statement(statement_desc* stmt);
00284
00285 int commit(int statement);
00286 int precommit(int statement);
00287 int abort(int statement);
00288 int remove(int statement);
00289
00290 int describe(int session, char_t const* table, cli_field_descriptor** fields);
00291 int show_tables(int session, cli_table_descriptor** tables);
00292
00293 int match_columns(char_t const* table_name, statement_desc* stmt);
00294
00295
00296
00297 int create_table(int session, char_t const* tableName, int nColumns,
00298 cli_field_descriptor* columns);
00299
00300 int alter_table(int session, char_t const* tableName, int nColumns,
00301 cli_field_descriptor* columns);
00302
00303 int drop_table(int session, char_t const* tableName);
00304
00305 int alter_index(int session, char_t const* tableName, char_t const* fieldName, int newFlags);
00306
00307 cli_error_handler set_error_handler(int session, cli_error_handler new_handler);
00308
00309 int attach(int session);
00310 int detach(int session, int detach_mode);
00311
00312 int close(int session);
00313
00314 int prepare_query(int session, char_t const* query);
00315 int execute_query(int statement, int for_update, void* record_struct, va_list params);
00316 int insert_struct(int session, char_t const* table_name, void* record_struct, cli_oid_t* oid);
00317
00318 static int create_table(dbDatabase* db, char_t const* tableName, int nColumns,
00319 cli_field_descriptor* columns);
00320
00321 static int alter_table(dbDatabase* db, char_t const* tableName, int nColumns,
00322 cli_field_descriptor* columns);
00323
00324 static int alter_index(dbDatabase* db, char_t const* tableName, char_t const* fieldName, int newFlags);
00325
00326 };
00327
00328 END_GIGABASE_NAMESPACE
00329
00330 #endif