=== modified file 'driver/catalog.c' --- driver/catalog.c 2008-10-09 18:52:04 +0000 +++ driver/catalog.c 2009-04-09 09:15:01 +0000 @@ -172,7 +172,7 @@ /** - Get the table status for a table or tables. + Get the table status for a table or tables using Information_Schema DB. @param[in] stmt Handle to statement @param[in] catalog Catalog (database) of table, @c NULL for current @@ -184,12 +184,14 @@ @return Result of SHOW TABLE STATUS, or NULL if there is an error or empty result (check mysql_errno(&stmt->dbc->mysql) != 0) */ -static MYSQL_RES *mysql_table_status(STMT *stmt, - SQLCHAR *catalog, - SQLSMALLINT catalog_length, - SQLCHAR *table, - SQLSMALLINT table_length, - my_bool wildcard) +static MYSQL_RES *mysql_table_status_i_s(STMT *stmt, + SQLCHAR *catalog, + SQLSMALLINT catalog_length, + SQLCHAR *table, + SQLSMALLINT table_length, + my_bool wildcard, + my_bool show_tables, + my_bool show_views) { MYSQL *mysql= &stmt->dbc->mysql; /** @todo determine real size for buffer */ @@ -200,13 +202,40 @@ if (catalog_length == SQL_NTS && catalog) catalog_length= strlen((char *)catalog); - to= strmov(buff, "SHOW TABLE STATUS "); + to= strmov(buff, "SELECT TABLE_NAME, TABLE_COMMENT, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA "); + if (catalog && *catalog) { - to= strmov(to, "FROM `"); + to= strmov(to, "LIKE '"); to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff), (char *)catalog, catalog_length, 1); - to= strmov(to, "` "); + } + else + { + to= strmov(to, "='"); + to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff), + (char *)stmt->dbc->database, strlen(stmt->dbc->database), 1); + } + to= strmov(to, "' "); + + if (show_tables) + { + to= strmov(to, "AND "); + if (show_views) + to= strmov(to, "( "); + to= strmov(to, "TABLE_TYPE='BASE TABLE' "); + } + + if (show_views) + { + if (show_views) + to= strmov(to, "OR "); + else + to= strmov(to, "AND "); + + to= strmov(to, "TABLE_TYPE='VIEW' "); + if (show_tables) + to= strmov(to, ") "); } /* @@ -219,7 +248,7 @@ if (table && *table) { - to= strmov(to, "LIKE '"); + to= strmov(to, "AND TABLE_NAME LIKE '"); if (wildcard) to+= mysql_real_escape_string(mysql, to, (char *)table, table_length); else @@ -235,6 +264,104 @@ return mysql_store_result(mysql); } +/** + Get the table status for a table or tables using SHOW TABLE STATUS. + + @param[in] stmt Handle to statement + @param[in] catalog Catalog (database) of table, @c NULL for current + @param[in] catalog_length Length of catalog name, or @c SQL_NTS + @param[in] table Name of table + @param[in] table_length Length of table name, or @c SQL_NTS + @param[in] wildcard Whether the table name is a wildcard + + @return Result of SHOW TABLE STATUS, or NULL if there is an error + or empty result (check mysql_errno(&stmt->dbc->mysql) != 0) +*/ +static MYSQL_RES *mysql_table_status_show(STMT *stmt, + SQLCHAR *catalog, + SQLSMALLINT catalog_length, + SQLCHAR *table, + SQLSMALLINT table_length, + my_bool wildcard) +{ + MYSQL *mysql= &stmt->dbc->mysql; + /** @todo determine real size for buffer */ + char buff[255], *to; + + if (table_length == SQL_NTS && table) + table_length= strlen((char *)table); + if (catalog_length == SQL_NTS && catalog) + catalog_length= strlen((char *)catalog); + + to= strmov(buff, "SHOW TABLE STATUS "); + if (catalog && *catalog) + { + to= strmov(to, "FROM `"); + to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff), + (char *)catalog, catalog_length, 1); + to= strmov(to, "` "); + } + + /* + As a pattern-value argument, an empty string needs to be treated + literally. (It's not the same as NULL, which is the same as '%'.) + But it will never match anything, so bail out now. + */ + if (table && wildcard && !*table) + return NULL; + + if (table && *table) + { + to= strmov(to, "LIKE '"); + if (wildcard) + to+= mysql_real_escape_string(mysql, to, (char *)table, table_length); + else + to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff), + (char *)table, table_length, 0); + to= strmov(to, "'"); + } + + MYLOG_QUERY(stmt, buff); + if (mysql_query(mysql,buff)) + return NULL; + + return mysql_store_result(mysql); +} + + +/** + Get the table status for a table or tables + + @param[in] stmt Handle to statement + @param[in] catalog Catalog (database) of table, @c NULL for current + @param[in] catalog_length Length of catalog name, or @c SQL_NTS + @param[in] table Name of table + @param[in] table_length Length of table name, or @c SQL_NTS + @param[in] wildcard Whether the table name is a wildcard + + @return Result of SHOW TABLE STATUS, or NULL if there is an error + or empty result (check mysql_errno(&stmt->dbc->mysql) != 0) +*/ +static MYSQL_RES *mysql_table_status(STMT *stmt, + SQLCHAR *catalog, + SQLSMALLINT catalog_length, + SQLCHAR *table, + SQLSMALLINT table_length, + my_bool wildcard, + my_bool show_tables, + my_bool show_views) +{ + if (is_minimum_version(stmt->dbc->mysql.server_version, "5.0", 3) && + !option_flag(stmt, FLAG_NO_INFORMATION_SCHEMA)) + return mysql_table_status_i_s(stmt, catalog, catalog_length, + table, table_length, wildcard, + show_tables, show_views); + else + return mysql_table_status_i_s(stmt, catalog, catalog_length, + table, table_length, wildcard, + show_tables, show_views); +} + /* **************************************************************************** @@ -370,7 +497,8 @@ { pthread_mutex_lock(&stmt->dbc->lock); stmt->result= mysql_table_status(stmt, catalog, catalog_len, - table, table_len, TRUE); + table, table_len, TRUE, + user_tables, views); if (!stmt->result && mysql_errno(&stmt->dbc->mysql)) { @@ -428,9 +556,7 @@ while ((row= mysql_fetch_row(stmt->result))) { - int comment_index= (stmt->result->field_count == 18) ? 17 : 15; - my_bool view= (!row[1] && - myodbc_casecmp(row[comment_index], "view", 4) == 0); + my_bool view= (myodbc_casecmp(row[2], "VIEW", 4) == 0); if ((view && !views) || (!view && !user_tables)) { @@ -442,7 +568,7 @@ data[1]= ""; data[2]= strdup_root(&stmt->result->field_alloc, row[0]); data[3]= view ? "VIEW" : "TABLE"; - data[4]= strdup_root(&stmt->result->field_alloc, row[comment_index]); + data[4]= strdup_root(&stmt->result->field_alloc, row[1]); data+= SQLTABLES_FIELDS; } @@ -654,7 +780,8 @@ /* Get the list of tables that match szCatalog and szTable */ pthread_mutex_lock(&stmt->dbc->lock); - res= mysql_table_status(stmt, szCatalog, cbCatalog, szTable, cbTable, TRUE); + res= mysql_table_status(stmt, szCatalog, cbCatalog, szTable, cbTable, TRUE, + TRUE, TRUE); if (!res && mysql_errno(&stmt->dbc->mysql)) { @@ -1824,10 +1951,13 @@ cbPkTableName= strlen((char *)szPkTableName); pthread_mutex_lock(&stmt->dbc->lock); - if (!(stmt->result= mysql_table_status(stmt, - szFkCatalogName, cbFkCatalogName, - szFkTableName, cbFkTableName, - FALSE))) + + stmt->result= mysql_table_status(stmt, + szFkCatalogName, cbFkCatalogName, + szFkTableName, cbFkTableName, + FALSE, TRUE, FALSE); + + if (!stmt->result) { if (mysql_errno(&stmt->dbc->mysql)) { === modified file 'driver/driver.h' --- driver/driver.h 2008-10-09 17:29:02 +0000 +++ driver/driver.h 2009-04-02 13:09:24 +0000 @@ -152,6 +152,10 @@ (automatically set for MS Access) see bug#24535 */ #define FLAG_DFLT_BIGINT_BIND_STR (1 << 29) +/* + Use SHOW TABLE STATUS instead Information_Schema DB for table metadata +*/ +#define FLAG_NO_INFORMATION_SCHEMA (1 << 30) /* We don't make any assumption about what the default may be. */ #ifndef DEFAULT_TXN_ISOLATION === modified file 'setupgui/utils.c' --- setupgui/utils.c 2008-08-04 13:39:09 +0000 +++ setupgui/utils.c 2009-04-08 08:24:40 +0000 @@ -59,6 +59,7 @@ params->enable_auto_reconnect= (nOptions & FLAG_AUTO_RECONNECT) > 0; params->enable_auto_increment_null_search= (nOptions & FLAG_AUTO_IS_NULL) > 0; params->handle_binary_as_char= (nOptions & FLAG_NO_BINARY_RESULT) > 0; + params->no_information_schema= (nOptions & FLAG_NO_INFORMATION_SCHEMA) > 0; } @@ -237,6 +238,8 @@ nFlags|= FLAG_LOG_QUERY; if (params->dont_cache_result) nFlags|= FLAG_NO_CACHE; + if (params->no_information_schema) + nFlags|= FLAG_NO_INFORMATION_SCHEMA; if (params->force_use_of_forward_only_cursors) nFlags|= FLAG_FORWARD_CURSOR; if (params->allow_multiple_statements) === modified file 'setupgui/windows/odbcdialogparams.cpp' --- setupgui/windows/odbcdialogparams.cpp 2008-08-04 13:39:09 +0000 +++ setupgui/windows/odbcdialogparams.cpp 2009-04-08 08:24:47 +0000 @@ -237,6 +237,7 @@ GET_BOOL(2,dont_use_set_locale); GET_BOOL(2,pad_char_to_full_length); GET_BOOL(2,dont_cache_result); + GET_BOOL(2,no_information_schema); /* flags 3 */ GET_BOOL(3,return_table_names_for_SqlDesribeCol); GET_BOOL(3,ignore_space_after_function_names); @@ -277,6 +278,7 @@ SET_BOOL(2,dont_use_set_locale); SET_BOOL(2,pad_char_to_full_length); SET_BOOL(2,dont_cache_result); + SET_BOOL(2,no_information_schema); /* flags 3 */ SET_BOOL(3,return_table_names_for_SqlDesribeCol); SET_BOOL(3,ignore_space_after_function_names); === modified file 'setupgui/windows/odbcdialogparams.rc' --- setupgui/windows/odbcdialogparams.rc 2008-08-04 13:39:09 +0000 +++ setupgui/windows/odbcdialogparams.rc 2009-04-08 08:15:10 +0000 @@ -97,6 +97,8 @@ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,87,127,10 CONTROL "Don't cache results of forward-only cursors",IDC_CHECK_dont_cache_result, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,102,154,10 + CONTROL "Ignore Information_Schema database",IDC_CHECK_no_information_schema, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,117,154,10 END IDD_TAB3 DIALOGEX 0, 0, 209, 151 === modified file 'setupgui/windows/resource.h' --- setupgui/windows/resource.h 2008-08-04 13:39:09 +0000 +++ setupgui/windows/resource.h 2009-04-08 08:15:16 +0000 @@ -83,6 +83,7 @@ #define IDC_EDIT_sslcipher 10035 #define IDC_CHECK_handle_binary_as_char 10036 #define IDC_CHECK_save_queries 10037 +#define IDC_CHECK_no_information_schema 10038 #define IDC_BUTTON_TEST 11014 #define IDC_BUTTON_HELP 11015 #define IDC_STATIC -1 === modified file 'test/my_catalog.c' --- test/my_catalog.c 2008-11-21 20:57:00 +0000 +++ test/my_catalog.c 2009-04-17 11:21:51 +0000 @@ -544,11 +544,11 @@ t_describe_col t_tables_bug_data[5] = { - {"TABLE_CAT", 9, SQL_WVARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, - {"TABLE_SCHEM",11, SQL_WVARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, - {"TABLE_NAME", 10, SQL_WVARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, - {"TABLE_TYPE", 10, SQL_WVARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, - {"REMARKS", 7, SQL_WVARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, + {"TABLE_CAT", 9, SQL_VARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, + {"TABLE_SCHEM",11, SQL_VARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, + {"TABLE_NAME", 10, SQL_VARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, + {"TABLE_TYPE", 10, SQL_VARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, + {"REMARKS", 7, SQL_VARCHAR, MYSQL_NAME_LEN, 0, SQL_NULLABLE}, }; @@ -747,6 +747,64 @@ } +DECLARE_TEST(my_information_schema) +{ + SQLCHAR conn[256], conn_out[256]; + HDBC hdbc1; + HSTMT hstmt1; + SQLSMALLINT conn_out_len; + SQLRETURN rc; + + ok_sql(hstmt, "DROP DATABASE IF EXISTS test__"); + ok_sql(hstmt, "DROP DATABASE IF EXISTS test_1"); + ok_sql(hstmt, "DROP DATABASE IF EXISTS test_2"); + + ok_sql(hstmt, "CREATE DATABASE test__"); + ok_sql(hstmt, "CREATE DATABASE test_1"); + ok_sql(hstmt, "CREATE DATABASE test_2"); + + ok_sql(hstmt, "CREATE TABLE test__.tab_(a INT,b INT,c INT, d INT)"); + ok_sql(hstmt, "CREATE TABLE test_1.tab1(a INT,b INT,c INT, d INT)"); + ok_sql(hstmt, "CREATE TABLE test_2.tab2(a INT,b INT,c INT, d INT)"); + + sprintf((char *)conn, "DSN=%s;UID=%s;PWD=%s;DATABASE=test__", mydsn, myuid, mypwd); + if (mysock != NULL) + { + strcat((char *)conn, ";SOCKET="); + strcat((char *)conn, (char *)mysock); + } + if (myport) + { + char pbuff[20]; + sprintf(pbuff, ";PORT=%d", myport); + strcat((char *)conn, pbuff); + } + + ok_env(henv, SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1)); + + ok_con(hdbc1, SQLDriverConnect(hdbc1, NULL, conn, sizeof(conn), conn_out, + sizeof(conn_out), &conn_out_len, + SQL_DRIVER_NOPROMPT)); + ok_con(hdbc1, SQLAllocStmt(hdbc1, &hstmt1)); + + rc = SQLTables(hstmt1, "test__", SQL_NTS, "", 0, "tab%", SQL_NTS, NULL, 0); + mystmt(hstmt1,rc); + + /* all tables from all databases should be displayed */ + is(3 == my_print_non_format_result(hstmt1)); + rc = SQLFreeStmt(hstmt1, SQL_CLOSE); + + rc = SQLTables(hstmt1, NULL, 0, NULL, 0, "tab%", SQL_NTS, NULL, 0); + mystmt(hstmt1,rc); + + is(1 == my_print_non_format_result(hstmt1)); + rc = SQLFreeStmt(hstmt1, SQL_CLOSE); + mystmt(hstmt1,rc); + + return OK; +} + + /** Bug #4518: SQLForeignKeys returns too many foreign key Bug #27723: SQLForeignKeys does not escape _ and % in the table name arguments @@ -1450,6 +1508,7 @@ ADD_TEST(t_current_catalog) ADD_TEST(tmysql_showkeys) ADD_TEST(t_sqltables) + ADD_TEST(my_information_schema) ADD_TEST(t_bug4518) ADD_TEST(empty_set) ADD_TEST(t_bug23031) === modified file 'util/installer.h' --- util/installer.h 2008-11-21 20:57:00 +0000 +++ util/installer.h 2009-04-08 08:20:10 +0000 @@ -133,6 +133,7 @@ BOOL limit_column_size; /* debug */ BOOL save_queries; + BOOL no_information_schema; /* SSL */ unsigned int sslverify; } DataSource;