|
|
| version 1.60, 2002/02/08 07:27:48 | version 1.68, 2002/12/09 12:19:16 |
|---|---|
| Line 2 | Line 2 |
| Parser: sql driver manager implementation. | Parser: sql driver manager implementation. |
| Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | |
| */ | */ |
| static const char* IDENT_SQL_DRIVER_MANAGER_C="$Date$"; | |
| #include "pa_sql_driver_manager.h" | #include "pa_sql_driver_manager.h" |
| #include "ltdl.h" | #include "ltdl.h" |
| #include "pa_sql_connection.h" | #include "pa_sql_connection.h" |
| Line 50 public: | Line 50 public: |
| virtual void *calloc(size_t size) { return Pooled::calloc(size); } | virtual void *calloc(size_t size) { return Pooled::calloc(size); } |
| /** | /** |
| normally we can't 'throw' from dynamic library, so | |
| the idea is to #1 jump to C++ some function to main body, where | the idea is to #1 jump to C++ some function to main body, where |
| every function stack frame has exception unwind information | every function stack frame has exception unwind information |
| and from there... #2 propagate_exception() | and from there... #2 propagate_exception() |
| but when parser configured --with-sjlj-exceptions | |
| one can simply 'throw' from dynamic library. | |
| [sad story: one can not longjump/throw due to some bug in gcc as of 3.2.1 version] | |
| */ | */ |
| virtual void _throw(const char *comment) { | virtual void _throw(const SQL_Error& aexception) { |
| // converting SQL_exception to parser Exception | |
| // hiding passwords and addresses from accidental show [imagine user forgot @exception] | // hiding passwords and addresses from accidental show [imagine user forgot @exception] |
| e=Exception(0, 0, | #ifdef PA_WITH_SJLJ_EXCEPTIONS |
| &url_without_login(pool(), furl), | throw |
| comment); | #else |
| fexception= | |
| #endif | |
| Exception(aexception.type(), | |
| aexception.problem_source()?static_cast<const String*>(aexception.problem_source()) | |
| :&url_without_login(pool(), furl), | |
| aexception.comment()); | |
| #ifndef PA_WITH_SJLJ_EXCEPTIONS | |
| longjmp(mark, 1); | longjmp(mark, 1); |
| #endif | |
| } | } |
| virtual void propagate_exception() { | virtual void propagate_exception() { |
| throw e; | #ifndef PA_WITH_SJLJ_EXCEPTIONS |
| throw fexception; | |
| #endif | |
| } | } |
| private: | private: |
| const String& furl; | const String& furl; |
| Exception e; | Exception fexception; |
| }; | }; |
| // helpers | // helpers |
| Line 107 SQL_Connection_ptr SQL_Driver_manager::g | Line 123 SQL_Connection_ptr SQL_Driver_manager::g |
| // we have table for locating protocol's library | // we have table for locating protocol's library |
| if(!protocol2driver_and_client) | if(!protocol2driver_and_client) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &request_url, | &request_url, |
| "$"MAIN_SQL_NAME":"MAIN_SQL_DRIVERS_NAME" table must be defined"); | "$"MAIN_SQL_NAME":"MAIN_SQL_DRIVERS_NAME" table must be defined"); |
| Line 130 SQL_Connection_ptr SQL_Driver_manager::g | Line 146 SQL_Connection_ptr SQL_Driver_manager::g |
| else { // no cached connection or it were unpingabe: connect/reconnect | else { // no cached connection or it were unpingabe: connect/reconnect |
| int pos=request_url.pos("://", 3); | int pos=request_url.pos("://", 3); |
| if(pos<0) | if(pos<0) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| request_url.size()?&request_url:&request_origin, | request_url.size()?&request_url:&request_origin, |
| "connection string must start with protocol://"); // NOTE: not THROW, but PTHROW | "connection string must start with protocol://"); |
| // make global_url C-string on global pool | // make global_url C-string on global pool |
| request_url_cstr=request_url.cstr(); | request_url_cstr=request_url.cstr(); |
| Line 160 SQL_Connection_ptr SQL_Driver_manager::g | Line 176 SQL_Connection_ptr SQL_Driver_manager::g |
| const String *dlopen_file_spec=0; | const String *dlopen_file_spec=0; |
| if(protocol2driver_and_client->locate(0, global_protocol)) { | if(protocol2driver_and_client->locate(0, global_protocol)) { |
| if(!(library=protocol2driver_and_client->item(1)) || library->size()==0) | if(!(library=protocol2driver_and_client->item(1)) || library->size()==0) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| protocol2driver_and_client->origin_string(), | protocol2driver_and_client->origin_string(), |
| "driver library column for protocol '%s' is empty", | "driver library column for protocol '%s' is empty", |
| request_protocol_cstr); | request_protocol_cstr); |
| dlopen_file_spec=protocol2driver_and_client->item(2); | dlopen_file_spec=protocol2driver_and_client->item(2); |
| } else | } else |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &request_url, | &request_url, |
| "undefined protocol '%s'", | "undefined protocol '%s'", |
| request_protocol_cstr); | request_protocol_cstr); |
| if(lt_dlinit()) | if(lt_dlinit()) |
| throw Exception(0, 0, | throw Exception(0, |
| library, | library, |
| "prepare to dynamic loading failed, %s", lt_dlerror()); | "prepare to dynamic loading failed, %s", lt_dlerror()); |
| const char *filename=library->cstr(String::UL_FILE_SPEC); | const char *filename=library->cstr(String::UL_FILE_SPEC); |
| lt_dlhandle handle=lt_dlopen(filename); | lt_dlhandle handle=lt_dlopen(filename); |
| if (!handle) | if (!handle) |
| throw Exception(0, 0, | throw Exception(0, |
| library, | library, |
| "can not open the module, %s", lt_dlerror()); | "can not open the module, %s", lt_dlerror()); |
| SQL_Driver_create_func create=(SQL_Driver_create_func)lt_dlsym(handle, | SQL_Driver_create_func create=(SQL_Driver_create_func)lt_dlsym(handle, |
| SQL_DRIVER_CREATE_NAME); | SQL_DRIVER_CREATE_NAME); |
| if(!create) | if(!create) |
| throw Exception(0, 0, | throw Exception(0, |
| library, | library, |
| "function '"SQL_DRIVER_CREATE_NAME"' was not found"); | "function '"SQL_DRIVER_CREATE_NAME"' was not found"); |
| Line 196 SQL_Connection_ptr SQL_Driver_manager::g | Line 212 SQL_Connection_ptr SQL_Driver_manager::g |
| // validate driver api version | // validate driver api version |
| int driver_api_version=driver->api_version(); | int driver_api_version=driver->api_version(); |
| if(driver_api_version!=SQL_DRIVER_API_VERSION) | if(driver_api_version!=SQL_DRIVER_API_VERSION) |
| throw Exception(0, 0, | throw Exception(0, |
| library, | library, |
| "driver implements API version 0x%04X not equal to 0x%04X", | "driver implements API version 0x%04X not equal to 0x%04X", |
| driver_api_version, SQL_DRIVER_API_VERSION); | driver_api_version, SQL_DRIVER_API_VERSION); |
| Line 207 SQL_Connection_ptr SQL_Driver_manager::g | Line 223 SQL_Connection_ptr SQL_Driver_manager::g |
| dlopen_file_spec->cstr(String::UL_AS_IS):0; | dlopen_file_spec->cstr(String::UL_AS_IS):0; |
| if(const char *error=driver->initialize( | if(const char *error=driver->initialize( |
| dlopen_file_spec_cstr)) | dlopen_file_spec_cstr)) |
| throw Exception(0, 0, | throw Exception(0, |
| library, | library, |
| "driver failed to initialize client library '%s', %s", | "driver failed to initialize client library '%s', %s", |
| dlopen_file_spec_cstr?dlopen_file_spec_cstr:"unspecifed", | dlopen_file_spec_cstr?dlopen_file_spec_cstr:"unspecifed", |