Index: driver/myodbc3.h =================================================================== --- driver/myodbc3.h (revision 422) +++ driver/myodbc3.h (working copy) @@ -325,6 +325,7 @@ { DBC FAR *dbc; MYSQL_RES *result; + my_bool fake_result; MYSQL_ROW array,result_array,current_values; MYSQL_ROW (*fix_fields)(struct tagSTMT FAR* stmt,MYSQL_ROW row); MYSQL_FIELD *fields; Index: driver/catalog.c =================================================================== --- driver/catalog.c (revision 422) +++ driver/catalog.c (working copy) @@ -334,6 +334,7 @@ /* Return set of allowed Table owners */ MYODBCDbgInfo( "%s", "Return set of table owners / Schema names" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLTABLES_owner_values, sizeof(SQLTABLES_owner_values), MYF(0)); @@ -351,6 +352,7 @@ /* Return set of TableType qualifiers */ MYODBCDbgInfo( "%s", "Return set of table types" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLTABLES_type_values, sizeof(SQLTABLES_type_values), MYF(0)); @@ -533,6 +535,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLTABLES_values, sizeof(SQLTABLES_values), @@ -861,6 +864,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLCOLUMNS_values, sizeof(SQLCOLUMNS_values), @@ -1039,6 +1043,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLSTAT_values, sizeof(SQLSTAT_values), @@ -1231,6 +1236,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLTABLES_priv_values, sizeof(SQLTABLES_priv_values), @@ -1405,6 +1411,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLCOLUMNS_priv_values, sizeof(SQLCOLUMNS_priv_values), @@ -1632,6 +1639,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLSPECIALCOLUMNS_values, sizeof(SQLSPECIALCOLUMNS_values), @@ -1753,6 +1761,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLPRIM_KEYS_values, sizeof(SQLPRIM_KEYS_values), @@ -2085,6 +2094,7 @@ else /* NO FOREIGN KEY support from SERVER */ { stmt->result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->eof=1; } stmt->result->row_count= row_count; @@ -2095,6 +2105,7 @@ empty_set: MYODBCDbgInfo( "%s", "Can't match anything; Returning empty set" ); stmt->result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result->row_count= 0; stmt->result_array= (MYSQL_ROW) my_memdup((gptr) SQLFORE_KEYS_values, sizeof(SQLFORE_KEYS_values), Index: driver/info.c =================================================================== --- driver/info.c (revision 422) +++ driver/info.c (working copy) @@ -1067,6 +1067,7 @@ /* Set up result Data dictionary. */ stmt->result= (MYSQL_RES *)my_malloc(sizeof(MYSQL_RES), MYF(MY_ZEROFILL)); + stmt->fake_result= 1; stmt->result_array= (char **)my_malloc(sizeof(SQL_GET_TYPE_INFO_values), MYF(MY_FAE | MY_ZEROFILL)); Index: driver/handle.c =================================================================== --- driver/handle.c (revision 422) +++ driver/handle.c (working copy) @@ -423,12 +423,16 @@ if (fOption == SQL_RESET_PARAMS) MYODBCDbgReturnReturn( SQL_SUCCESS ); - mysql_free_result(stmt->result); + if (!stmt->fake_result) + mysql_free_result(stmt->result); + else + x_free((gptr)stmt->result); x_free((gptr) stmt->fields); x_free((gptr) stmt->array); x_free((gptr) stmt->result_array); x_free((gptr) stmt->odbc_types); stmt->result= 0; + stmt->fake_result= 0; stmt->result_lengths= 0; stmt->fields= 0; stmt->array= 0; Index: test/my_catalog.c =================================================================== --- test/my_catalog.c (revision 422) +++ test/my_catalog.c (working copy) @@ -1172,6 +1172,51 @@ } +/** + Tests the non-error code paths in catalog.c that return an empty set to + make sure the resulting empty result sets at least indicate the right + number of columns. +*/ +DECLARE_TEST(empty_set) +{ + SQLSMALLINT columns; + + /* SQLTables(): no known table types. */ + ok_stmt(hstmt, SQLTables(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS, + (SQLCHAR *)"UNKNOWN", SQL_NTS)); + ok_stmt(hstmt, SQLNumResultCols(hstmt, &columns)); + is_num(columns, 5); + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + /* SQLTables(): no tables found. */ + ok_stmt(hstmt, SQLTables(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, + (SQLCHAR *)"no_such_table", SQL_NTS, NULL, SQL_NTS)); + ok_stmt(hstmt, SQLNumResultCols(hstmt, &columns)); + is_num(columns, 5); + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + /* SQLColumns(): no table specified. */ + ok_stmt(hstmt, SQLColumns(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, + NULL, SQL_NTS, NULL, SQL_NTS)); + ok_stmt(hstmt, SQLNumResultCols(hstmt, &columns)); + is_num(columns, 18); + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + /* SQLStatistics(): no table specified. */ + ok_stmt(hstmt, SQLStatistics(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, + NULL, SQL_NTS, 0, 0)); + ok_stmt(hstmt, SQLNumResultCols(hstmt, &columns)); + is_num(columns, 13); + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + return OK; +} + + BEGIN_TESTS ADD_TEST(my_columns_null) ADD_TEST(my_drop_table) @@ -1189,6 +1234,7 @@ ADD_TEST(tmysql_showkeys) ADD_TEST(t_sqltables) ADD_TEST(t_bug4518) + ADD_TEST(empty_set) END_TESTS Index: test/my_use_result.c =================================================================== --- test/my_use_result.c (revision 422) +++ test/my_use_result.c (working copy) @@ -70,8 +70,42 @@ } +/** + Bug #4657: "Don't Cache Results" crashes when using catalog functions +*/ +DECLARE_TEST(t_bug4657) +{ + SQLCHAR name[10]; + SQLSMALLINT column_count; + SQLLEN name_length; + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug4657"); + ok_sql(hstmt, "CREATE TABLE t_bug4657 (a INT)"); + + ok_stmt(hstmt, SQLTables(hstmt, (SQLCHAR *)"", SQL_NTS, + (SQLCHAR *)"", SQL_NTS, + (SQLCHAR *)"", SQL_NTS, + (SQLCHAR *)"TABLE,VIEW", SQL_NTS)); + + ok_stmt(hstmt, SQLNumResultCols(hstmt, &column_count)); + is_num(column_count, 5); + + ok_stmt(hstmt, SQLBindCol(hstmt, 3, SQL_C_CHAR, name, sizeof(name), + &name_length)); + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_UNBIND)); + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug4657"); + + return OK; +} + + BEGIN_TESTS ADD_TEST(t_use_result) + ADD_TEST(t_bug4657) END_TESTS