--- sql/mysql/parser3mysql.C 2004/12/23 16:54:52 1.26 +++ sql/mysql/parser3mysql.C 2008/06/24 17:21:10 1.32 @@ -10,7 +10,7 @@ 2001.11.06 numrows on "HP-UX istok1 B.11.00 A 9000/869 448594332 two-user license" 3.23.42 & 4.0.0.alfa never worked, both subst & .sl version returned 0 */ -static const char *RCSId="$Id: parser3mysql.C,v 1.26 2004/12/23 16:54:52 paf Exp $"; +static const char *RCSId="$Id: parser3mysql.C,v 1.32 2008/06/24 17:21:10 misha Exp $"; #include "config_includes.h" @@ -29,32 +29,32 @@ static const char *RCSId="$Id: parser3my #endif static char *lsplit(char *string, char delim) { - if(string) { + if(string) { char *v=strchr(string, delim); if(v) { *v=0; return v+1; } - } - return 0; + } + return 0; } static char *lsplit(char **string_ref, char delim) { - char *result=*string_ref; + char *result=*string_ref; char *next=lsplit(*string_ref, delim); - *string_ref=next; - return result; + *string_ref=next; + return result; } static char* rsplit(char* string, char delim) { - if(string) { + if(string) { char* v=strrchr(string, delim); if(v) { *v=0; return v+1; } - } - return NULL; + } + return NULL; } static void toupper_str(char *out, const char *in, size_t size) { @@ -68,15 +68,21 @@ struct Connection { MYSQL* handle; const char* cstrClientCharset; bool autocommit; + bool multi_statements; }; + /** MySQL server driver */ class MySQL_Driver : public SQL_Driver { public: - MySQL_Driver() : SQL_Driver() { + MySQL_Driver() : SQL_Driver() {} + + ~MySQL_Driver() { + if(mysql_server_end) + mysql_server_end(); } /// get api version @@ -89,13 +95,17 @@ public: /** connect @param url format: @b user:pass@host[:port]|[/unix/socket]/database? - charset=cp1251_koi8& + ClientCharset=charset& // transcode by parser + charset=cp1251_koi8& // transcode by server with 'set CHARACTER SET xyz' timeout=3& - compress=1& - named_pipe=1 + compress=0& + named_pipe=1& + autocommit=1 3.23.22b - Currently the only option for @b character_set_name is cp1251_koi8. - WARNING: must be used only to connect, for buffer doesn't live long + Currently the only option for @b character_set_name is cp1251_koi8. + WARNING: must be used only to connect, for buffer doesn't live long + 4.1+ accept not only 'cp1251_koi8' but 'cp1251', 'utf8' and much more + it can be usable for transcoding using sql server */ void connect( char *url, @@ -123,36 +133,39 @@ public: Connection& connection=*(Connection *)services.malloc(sizeof(Connection)); connection.services=&services; - connection.handle=mysql_init(NULL); + connection.handle=mysql_init(NULL); connection.cstrClientCharset=0; connection.autocommit=true; + connection.multi_statements=false; *connection_ref=&connection; - while(options) { - if(char *key=lsplit(&options, '&')) { - if(*key) { - if(char *value=lsplit(key, '=')) { - if(strcmp(key, "ClientCharset" ) == 0) { + while(options){ + if(char *key=lsplit(&options, '&')){ + if(*key){ + if(char *value=lsplit(key, '=')){ + if(strcmp(key, "ClientCharset" )==0){ // transcoding with parser toupper_str(value, value, strlen(value)); connection.cstrClientCharset=value; - } else if(strcasecmp(key, "charset")==0) { // left for backward compatibility, consider using ClientCharset + } else if(strcasecmp(key, "charset")==0){ // transcoding with server cstrBackwardCompAskServerToTranscode=value; - } else if(strcasecmp(key, "timeout")==0) { + } else if(strcasecmp(key, "timeout")==0){ unsigned int timeout=(unsigned int)atoi(value); if(mysql_options(connection.handle, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout)!=0) services._throw(mysql_error(connection.handle)); - } else if(strcasecmp(key, "compress")==0) { + } else if(strcasecmp(key, "compress")==0){ if(atoi(value)) if(mysql_options(connection.handle, MYSQL_OPT_COMPRESS, 0)!=0) services._throw(mysql_error(connection.handle)); - } else if(strcasecmp(key, "named_pipe")==0) { + } else if(strcasecmp(key, "named_pipe")==0){ if(atoi(value)) if(mysql_options(connection.handle, MYSQL_OPT_NAMED_PIPE , 0)!=0) services._throw(mysql_error(connection.handle)); - } else if(strcasecmp(key, "autocommit")==0) { - if(atoi(value)==0) { + } else if(strcasecmp(key, "multi_statements")==0) { + if(atoi(value)!=0) + connection.multi_statements=true; + } else if(strcasecmp(key, "autocommit")==0){ + if(atoi(value)==0) connection.autocommit=false; - } } else services._throw("unknown connect option" /*key*/); } else @@ -161,24 +174,20 @@ public: } } - if(connection.cstrClientCharset && cstrBackwardCompAskServerToTranscode) - services._throw("use 'ClientCharset' option only, " - "'charset' option is obsolete and should not be used with new 'ClientCharset' option"); - if(!mysql_real_connect(connection.handle, - host, user, pwd, db, port?port:MYSQL_PORT, unix_socket, 0)) + host, user, pwd, db, port?port:MYSQL_PORT, unix_socket, (connection.multi_statements) ? CLIENT_MULTI_STATEMENTS : CLIENT_MULTI_RESULTS)) services._throw(mysql_error(connection.handle)); if(cstrBackwardCompAskServerToTranscode) { // set charset - char statement[MAX_STRING]="set CHARACTER SET "; // cp1251_koi8 + char statement[MAX_STRING]="SET CHARACTER SET "; strncat(statement, cstrBackwardCompAskServerToTranscode, MAX_STRING); exec(connection, statement); } if(!connection.autocommit) - exec(connection, "set autocommit=0"); + exec(connection, "SET AUTOCOMMIT=0"); } void exec(Connection& connection, const char* statement) { @@ -193,18 +202,20 @@ public: mysql_close(connection.handle); connection.handle=0; } + void commit(void *aconnection) { //_asm int 3; Connection& connection=*static_cast(aconnection); if(!connection.autocommit) - exec(connection, "commit"); + exec(connection, "COMMIT"); } + void rollback(void *aconnection) { Connection& connection=*static_cast(aconnection); if(!connection.autocommit) - exec(connection, "rollback"); + exec(connection, "ROLLBACK"); } bool ping(void *aconnection) { @@ -304,10 +315,10 @@ public: CHECK(handlers.add_column(sql_error, str, length)); } else { - // seen some broken client, - // which reported "44" for column count of response to "select 2+2" - column_count=i; - break; + // seen some broken client, + // which reported "44" for column count of response to "select 2+2" + column_count=i; + break; } } @@ -331,11 +342,11 @@ public: str, length, cstrClientCharset, services.request_charset()); - } else - str=0; - CHECK(handlers.add_row_cell(sql_error, str, length)); - } - } + } else + str=0; + CHECK(handlers.add_row_cell(sql_error, str, length)); + } + } cleanup: mysql_free_result(res); if(failed) @@ -346,6 +357,8 @@ private: // mysql client library funcs typedef MYSQL* (STDCALL *t_mysql_init)(MYSQL *); t_mysql_init mysql_init; + typedef void (STDCALL *t_mysql_server_end)(); t_mysql_server_end mysql_server_end; + typedef int (STDCALL *t_mysql_options)(MYSQL *mysql, enum mysql_option option, const char *arg); t_mysql_options mysql_options; typedef MYSQL_RES* (STDCALL *t_mysql_store_result)(MYSQL *); t_mysql_store_result mysql_store_result; @@ -397,8 +410,11 @@ private: // mysql client library funcs l return "can not open the dynamic link module"; } + #define GLINK(name) \ + name=(t_##name)lt_dlsym(handle, #name); + #define DSLINK(name, action) \ - name=(t_##name)lt_dlsym(handle, #name); \ + GLINK(name) \ if(!name) \ action; @@ -406,6 +422,7 @@ private: // mysql client library funcs l #define SLINK(name) DSLINK(name, name=subst_##name) DLINK(mysql_init); + GLINK(mysql_server_end); DLINK(mysql_options); DLINK(mysql_store_result); DLINK(mysql_query); @@ -426,5 +443,6 @@ private: // mysql client library funcs l }; extern "C" SQL_Driver *SQL_DRIVER_CREATE() { - return new MySQL_Driver(); + static MySQL_Driver Driver; + return &Driver; }