--- sql/mysql/parser3mysql.C 2019/09/03 20:16:55 1.55 +++ sql/mysql/parser3mysql.C 2020/01/18 20:59:24 1.63 @@ -1,7 +1,7 @@ /** @file Parser MySQL driver. - Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2019 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) @@ -15,7 +15,7 @@ #include "pa_sql_driver.h" -volatile const char * IDENT_PARSER3MYSQL_C="$Id: parser3mysql.C,v 1.55 2019/09/03 20:16:55 moko Exp $" IDENT_PA_SQL_DRIVER_H; +volatile const char * IDENT_PARSER3MYSQL_C="$Id: parser3mysql.C,v 1.63 2020/01/18 20:59:24 moko Exp $" IDENT_PA_SQL_DRIVER_H; #define NO_CLIENT_LONG_LONG #include "mysql.h" @@ -24,7 +24,7 @@ volatile const char * IDENT_PARSER3MYSQL #define MAX_STRING 0x400 #define MAX_NUMBER 20 -#if _MSC_VER +#ifdef _MSC_VER # define snprintf _snprintf # define strcasecmp _stricmp #endif @@ -334,7 +334,7 @@ public: MYSQL_RES *res=NULL; if(placeholders_count>0) - services._throw("bind variables not supported (yet)"); + services._throw("bind variables not supported yet"); bool transcode_needed=_transcode_required(connection); @@ -343,10 +343,7 @@ public: if(transcode_needed) { statement_size=strlen(astatement); // transcode query from $request:charset to ?ClientCharset - services.transcode(astatement, statement_size, - astatement, statement_size, - services.request_charset(), - connection.client_charset); + services.transcode(astatement, statement_size, astatement, statement_size, services.request_charset(), connection.client_charset); } const char *statement; @@ -368,90 +365,97 @@ public: if(mysql_query(connection.handle, statement)) _throw(connection, mysql_error(connection.handle)); - if(!(res=mysql_store_result(connection.handle)) && mysql_field_count(connection.handle)) - _throw(connection, mysql_error(connection.handle)); - if(!res) // empty result: insert|delete|update|... - return; - size_t column_count=mysql_num_fields(res); - if(!column_count) // old client - column_count=mysql_field_count(connection.handle); - - if(!column_count){ - mysql_free_result(res); - services._throw("result contains no columns"); - } - - bool failed=false; - SQL_Error sql_error; - -#define CHECK(afailed) \ - if(afailed) { \ - failed=true; \ - goto cleanup; \ - } - -#define DO_FETCH_FIELDS(transcode_column_name) { \ - for(size_t i=0; iname_length; \ - const char* str=strdup(services, field->name, length); \ - transcode_column_name \ - CHECK(handlers.add_column(sql_error, str, length)); \ - } else { \ - /* seen broken client, that reported "44" column count for "select 2+2" */ \ - column_count=i; \ - break; \ - } \ - } \ - } - -#define DO_FETCH_ROWS(transcode_cell_value) { \ - while(MYSQL_ROW mysql_row=mysql_fetch_row(res)) { \ - CHECK(handlers.add_row(sql_error)); \ - unsigned long *lengths=mysql_fetch_lengths(res); \ - for(size_t i=0; itype); - // transcode column's name from ?ClientCharset to $request:charset - services.transcode(str, length, - str, length, - connection.client_charset, - services.request_charset()); - ) - CHECK(handlers.before_rows(sql_error)); - DO_FETCH_ROWS( - if(transcode_column[i]) - // transcode cell's value from ?ClientCharset to $request:charset - services.transcode(str, length, - str, length, - connection.client_charset, - services.request_charset()); - ) - } else { - // without transcoding - DO_FETCH_FIELDS() - CHECK(handlers.before_rows(sql_error)); - DO_FETCH_ROWS() - } -cleanup: - mysql_free_result(res); - if(failed) - services._throw(sql_error); + if(res=mysql_store_result(connection.handle)){ + + size_t column_count=mysql_num_fields(res); + if(!column_count) // old client + column_count=mysql_field_count(connection.handle); + + if(!column_count){ + mysql_free_result(res); + services._throw("result contains no columns"); + } + + SQL_Error sql_error; + +#define CHECK(afailed) \ + if(afailed) { \ + mysql_free_result(res); \ + services._throw(sql_error); \ + } + +#define DO_FETCH_FIELDS(transcode_column_name) \ + for(size_t i=0; iname_length; \ + const char* str=strdup(services, field->name, length); \ + transcode_column_name \ + CHECK(handlers.add_column(sql_error, str, length)); \ + } else { \ + /* seen broken client, that reported "44" column count for "select 2+2" */ \ + column_count=i; \ + break; \ + } \ + } + +#define DO_FETCH_ROWS(transcode_cell_value) \ + while(MYSQL_ROW mysql_row=mysql_fetch_row(res)) { \ + CHECK(handlers.add_row(sql_error)); \ + unsigned long *lengths=mysql_fetch_lengths(res); \ + for(size_t i=0; itype); + // transcode column's name from ?ClientCharset to $request:charset + services.transcode(str, length, str, length, connection.client_charset, services.request_charset()); + ) + CHECK(handlers.before_rows(sql_error)); + DO_FETCH_ROWS( + // transcode cell's value from ?ClientCharset to $request:charset + if(transcode_column[i]) + services.transcode(str, length, str, length, connection.client_charset, services.request_charset()); + ) +#ifdef _MSC_VER + services.realloc(transcode_column,0); +#endif + } else { + // without transcoding + DO_FETCH_FIELDS({}) + CHECK(handlers.before_rows(sql_error)); + DO_FETCH_ROWS({}) + } + + mysql_free_result(res); + + } else { + if(mysql_field_count(connection.handle)) + _throw(connection, mysql_error(connection.handle)); + // empty result: insert|delete|update|... + } + + next_result = mysql_next_result(connection.handle); + if (next_result > 0) + _throw(connection, mysql_error(connection.handle)); + } while (next_result == 0); } private: @@ -464,10 +468,7 @@ private: void _throw(Connection& connection, const char* aerr_msg) { size_t length=strlen(aerr_msg); if(length && _transcode_required(connection)) { - connection.services->transcode(aerr_msg, length, - aerr_msg, length, - connection.client_charset, - connection.services->request_charset()); + connection.services->transcode(aerr_msg, length, aerr_msg, length, connection.client_charset, connection.services->request_charset()); } connection.services->_throw(aerr_msg); } @@ -508,9 +509,11 @@ private: // mysql client library funcs typedef unsigned int (STDCALL *t_mysql_num_fields)(MYSQL_RES *); t_mysql_num_fields mysql_num_fields; typedef unsigned int (STDCALL *t_mysql_field_count)(MYSQL *); t_mysql_field_count mysql_field_count; + typedef unsigned int (STDCALL *t_mysql_next_result)(MYSQL *); t_mysql_next_result mysql_next_result; static unsigned int STDCALL subst_mysql_num_fields(MYSQL_RES *res) { return res->field_count; } static unsigned int STDCALL subst_mysql_field_count(MYSQL *mysql) { return mysql->field_count; } + static unsigned int STDCALL subst_mysql_next_result(MYSQL *mysql) { return -1; } private: // mysql client library funcs linking @@ -556,6 +559,7 @@ private: // mysql client library funcs l DLINK(mysql_fetch_field); SLINK(mysql_num_fields); SLINK(mysql_field_count); + SLINK(mysql_next_result); return 0; }