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