=== modified file 'ChangeLog' --- ChangeLog 2010-09-24 10:21:39 +0000 +++ ChangeLog 2010-10-01 21:24:52 +0000 @@ -12,6 +12,8 @@ (Bug #56717) * Errors would not be reported in bulk upload. (Bug #56804) * MSI installer does not set InstallLocation value in registry. (Bug #56978) + * SQLProcedureColumns doesn't work with certain data/parameters combinations. + (Bug #57182) ---- === modified file 'driver/catalog.c' --- driver/catalog.c 2010-08-19 15:37:55 +0000 +++ driver/catalog.c 2010-10-01 20:27:35 +0000 @@ -93,15 +93,22 @@ if (!(stmt->result && stmt->result_array)) { if (stmt->result) + { my_free((char *)stmt->result, MYF(0)); + } if (stmt->result_array) + { my_free((char *)stmt->result_array, MYF(0)); + } set_mem_error(&stmt->dbc->mysql); return handle_connection_error(stmt); } stmt->fake_result= 1; - stmt->result->row_count= rowcnt; + + set_rows_count(stmt, rowcnt); + mysql_link_fields(stmt, fields, fldcnt); + return SQL_SUCCESS; } === modified file 'driver/catalog_no_i_s.c' --- driver/catalog_no_i_s.c 2010-08-19 15:37:55 +0000 +++ driver/catalog_no_i_s.c 2010-10-01 20:27:35 +0000 @@ -1477,10 +1477,15 @@ if(!myodbc_strcasecmp(type_map->type_name, "set") || !myodbc_strcasecmp(type_map->type_name, "enum")) { - sprintf(param_dbtype, "%s", "char"); - } - - data[mypcTYPE_NAME]= my_strdup(myodbc_strlwr(param_dbtype, 0), MYF(0)); /* TYPE_NAME */ + data[mypcTYPE_NAME]= my_strdup("char", MYF(0)); + } + else + { + data[mypcTYPE_NAME]= my_strdup(type_map->type_name, MYF(0)); + } + + + /* TYPE_NAME */ proc_get_param_col_len(stmt, sql_type_index, param_size, dec, flags, param_size_buf); data[mypcCOLUMN_SIZE]= my_strdup(param_size_buf, MYF(0)); /* COLUMN_SIZE */ @@ -1555,6 +1560,8 @@ } } + return_params_num= total_params_num; + if (cbColumnName) { pthread_mutex_lock(&stmt->dbc->lock); @@ -1587,7 +1594,6 @@ params= params_r->next; } - return_params_num= total_params_num - 1; /* 1st element is always 1 */ for (i= 1; i < columns_res->field_count; ++i) { @@ -1596,6 +1602,11 @@ --return_params_num; } } + + if (return_params_num == 0) + { + goto empty_set; + } } stmt->result= proc_list_res; @@ -1605,12 +1616,14 @@ tempdata= stmt->result_array; if(params_r->next) + { params= params_r->next; + } /* copy data */ - for (i= 1; i < total_params_num; ++i) + for (i= 0; i < total_params_num; ++i) { - int skip_result= (columns_res ? strcmp(row[i], "1") : 0); + int skip_result= (columns_res ? strcmp(row[i+1], "1") : 0); if(params && params->data) { cur_params= params; @@ -1634,7 +1647,7 @@ } } - stmt->result->row_count= return_params_num; + set_rows_count(stmt, return_params_num); mysql_link_fields(stmt, SQLPROCEDURECOLUMNS_fields, SQLPROCEDURECOLUMNS_FIELDS); === modified file 'driver/myutil.h' --- driver/myutil.h 2010-08-19 15:37:55 +0000 +++ driver/myutil.h 2010-09-30 16:10:20 +0000 @@ -313,6 +313,7 @@ int proc_get_param_sql_type_index(SQLCHAR *ptype, int len); SQLTypeMap *proc_get_param_map_by_index(int index); char *proc_param_next_token(char *str, char *str_end); +void set_rows_count(STMT * stmt, my_ulonglong rows); #ifdef __WIN__ #define cmp_database(A,B) myodbc_strcasecmp((const char *)(A),(const char *)(B)) === modified file 'driver/utility.c' --- driver/utility.c 2010-08-19 15:37:55 +0000 +++ driver/utility.c 2010-10-01 21:28:44 +0000 @@ -3364,7 +3364,6 @@ quote_symbol= '\0'; } - ++str; --len; } @@ -3412,3 +3411,18 @@ return elem; } + + +/** + Sets row_count in STMT's MYSQL_RES and affected rows property MYSQL object. Primary use is to set + number of affected rows for constructed resulsets. Setting mysql.affected_rows + is required for SQLRowCount to return correct data for such resultsets. +*/ +void set_rows_count(STMT *stmt, my_ulonglong rows) +{ + if (stmt != NULL && stmt->result != NULL) + { + stmt->result->row_count= rows; + stmt->dbc->mysql.affected_rows= rows; + } +} === modified file 'test/my_catalog.c' --- test/my_catalog.c 2010-08-20 17:53:37 +0000 +++ test/my_catalog.c 2010-10-01 21:20:47 +0000 @@ -2039,15 +2039,15 @@ param_cat= (SQLCHAR*)my_fetch_str(hstmt, buff, 1); is_str(param_cat, data_to_check[iter].c01_procedure_cat, - strlen(data_to_check[iter].c01_procedure_cat)); + strlen(data_to_check[iter].c01_procedure_cat) + 1); is_str(my_fetch_str(hstmt, buff, 3), data_to_check[iter].c03_procedure_name, - strlen(data_to_check[iter].c03_procedure_name)); + strlen(data_to_check[iter].c03_procedure_name) + 1); param_name= (SQLCHAR*)my_fetch_str(hstmt, buff, 4); is_str(param_name, data_to_check[iter].c04_column_name, - strlen(data_to_check[iter].c04_column_name)); + strlen(data_to_check[iter].c04_column_name) + 1); is_num(my_fetch_int(hstmt, 5), data_to_check[iter].c05_column_type); @@ -2055,7 +2055,7 @@ is_str(my_fetch_str(hstmt, buff, 7), data_to_check[iter].c07_type_name, - strlen(data_to_check[iter].c07_type_name)); + strlen(data_to_check[iter].c07_type_name) + 1); col_size= my_fetch_uint(hstmt, 8); is_num(col_size, data_to_check[iter].c08_column_size); @@ -2078,13 +2078,13 @@ is_str(my_fetch_str(hstmt, buff, 19), data_to_check[iter].c19_is_nullable, - strlen(data_to_check[iter].c19_is_nullable)); + strlen(data_to_check[iter].c19_is_nullable + 1)); ++iter; } ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); - + ok_sql(hstmt, "drop procedure if exists procedure_columns_test1"); ok_sql(hstmt, "drop procedure if exists procedure_columns_test2"); ok_sql(hstmt, "drop procedure if exists procedure_columns_test2_noparam"); @@ -2092,13 +2092,83 @@ ok_sql(hstmt, "drop function if exists procedure_columns_test4_func"); ok_sql(hstmt, "drop function if exists procedure_columns_test4_func_noparam"); ok_sql(hstmt, "drop procedure if exists procedure_columns_test5"); - + + + return OK; +} + + +DECLARE_TEST(t_bug57182) +{ + SQLLEN nRowCount; + SQLCHAR buff[24]; + + ok_sql(hstmt, "drop procedure if exists bug57182"); + ok_sql(hstmt, "CREATE DEFINER=`adb`@`%` PROCEDURE `bug57182`(in id int, in name varchar(20)) " + "BEGIN" + " insert into simp values (id, name);" + "END"); + + ok_stmt(hstmt, SQLProcedureColumns(hstmt, "test", SQL_NTS, NULL, 0, + "bug57182", SQL_NTS, + NULL, 0)); + + ok_stmt(hstmt, SQLRowCount(hstmt, &nRowCount)); + is_num(2, nRowCount) + + ok_stmt(hstmt, SQLFetch(hstmt)); + + is_str(my_fetch_str(hstmt, buff, 3), "bug57182", 9); + is_str(my_fetch_str(hstmt, buff, 4), "id", 3); + is_str(my_fetch_str(hstmt, buff, 7), "int", 4); + + ok_stmt(hstmt, SQLFetch(hstmt)); + + is_str(my_fetch_str(hstmt, buff, 3), "bug57182", 9); + is_str(my_fetch_str(hstmt, buff, 4), "name", 5); + is_str(my_fetch_str(hstmt, buff, 7), "varchar", 8); + is_num(my_fetch_int(hstmt, 8), 20); + + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + /* Almost the same thing but with column specified */ + ok_stmt(hstmt, SQLProcedureColumns(hstmt, "test", SQL_NTS, NULL, 0, + "bug57182", SQL_NTS, + "id", SQL_NTS)); + + ok_stmt(hstmt, SQLRowCount(hstmt, &nRowCount)); + is_num(1, nRowCount) + + ok_stmt(hstmt, SQLFetch(hstmt)); + + is_str(my_fetch_str(hstmt, buff, 3), "bug57182", 9); + is_str(my_fetch_str(hstmt, buff, 4), "id", 3); + is_str(my_fetch_str(hstmt, buff, 7), "int", 4); + + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + /* And testing impossible column condition - expecting to get no rows */ + ok_stmt(hstmt, SQLProcedureColumns(hstmt, "test", SQL_NTS, NULL, 0, + "bug57182", SQL_NTS, + "non_existing_column%", SQL_NTS)); + + ok_stmt(hstmt, SQLRowCount(hstmt, &nRowCount)); + is_num(0, nRowCount); + + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA); + + ok_sql(hstmt, "drop procedure if exists bug57182"); + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); return OK; } BEGIN_TESTS - + ADD_TEST(my_columns_null) ADD_TEST(my_drop_table) ADD_TEST(my_table_dbs) @@ -2137,6 +2207,7 @@ ADD_TEST(t_bug53235) ADD_TEST(t_bug50195) ADD_TEST(t_sqlprocedurecolumns) + ADD_TEST(t_bug57182) END_TESTS