=== modified file 'driver/catalog.c' --- driver/catalog.c 2010-04-08 09:03:07 +0000 +++ driver/catalog.c 2010-04-09 11:22:19 +0000 @@ -35,6 +35,18 @@ /* @type : internal + @purpose : checks if server supports I_S +*/ +my_bool server_has_i_s(DBC FAR *dbc) +{ + /* + According to the server ChangeLog INFORMATION_SCHEMA was introduced + in the 5.0.2 + */ + return is_minimum_version(dbc->mysql.server_version, "5.0.2", 5); +} +/* + @type : internal @purpose : returns the next token */ @@ -178,7 +190,165 @@ /** - 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 + @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_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 */ + char buff[255], *to; + my_bool clause_added= FALSE; + + 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, "SELECT TABLE_NAME, TABLE_COMMENT, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE "); + + if (catalog && *catalog) + { + to= strmov(to, "TABLE_SCHEMA LIKE '"); + to+= myodbc_escape_string(mysql, to, sizeof(buff) - (to - buff), + (char *)catalog, catalog_length, 1); + to= strmov(to, "' "); + clause_added= TRUE; + } + else + { + to= strmov(to, "TABLE_SCHEMA = DATABASE()"); + } + + 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_tables) + to= strmov(to, "OR "); + else + to= strmov(to, "AND "); + + to= strmov(to, "TABLE_TYPE='VIEW' "); + if (show_tables) + 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, "AND TABLE_NAME 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 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 @@ -195,50 +365,17 @@ SQLSMALLINT catalog_length, SQLCHAR *table, SQLSMALLINT table_length, - my_bool wildcard) + my_bool wildcard, + my_bool show_tables, + my_bool show_views) { - 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); + if (server_has_i_s(stmt->dbc) && !stmt->dbc->ds->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_show(stmt, catalog, catalog_length, + table, table_length, wildcard); } @@ -379,7 +516,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)) { @@ -437,13 +575,18 @@ 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); + int type_index= 2; + int comment_index= 1; + my_bool view; + if (stmt->dbc->ds->no_information_schema + || !server_has_i_s(stmt->dbc)) + type_index= comment_index= (stmt->result->field_count == 18) ? 17 : 15; + + view= (myodbc_casecmp(row[type_index], "VIEW", 4) == 0); if ((view && !views) || (!view && !user_tables)) { - row_count--; + --row_count; continue; } @@ -663,7 +806,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)) { @@ -1695,8 +1839,7 @@ CLEAR_STMT_ERROR(hstmt); my_SQLFreeStmt(hstmt,MYSQL_RESET); - /* For 5.0 and later, use INFORMATION_SCHEMA. */ - if (is_minimum_version(stmt->dbc->mysql.server_version, "5.0", 3)) + if (server_has_i_s(stmt->dbc)) { MYSQL *mysql= &stmt->dbc->mysql; char query[2048], *buff; /* This should be big enough. */ @@ -1832,10 +1975,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_show(stmt, + szFkCatalogName, cbFkCatalogName, + szFkTableName, cbFkTableName, + FALSE); + + if (!stmt->result) { if (mysql_errno(&stmt->dbc->mysql)) { @@ -2030,7 +2176,7 @@ my_SQLFreeStmt(hstmt,MYSQL_RESET); /* If earlier than 5.0, the server doesn't even support stored procs. */ - if (!is_minimum_version(stmt->dbc->mysql.server_version, "5.0", 3)) + if (!server_has_i_s(stmt->dbc)) { /* We use the server to generate a fake result with no rows, but === modified file 'driver/utility.c' --- driver/utility.c 2010-03-18 20:05:12 +0000 +++ driver/utility.c 2010-04-09 11:22:04 +0000 @@ -2736,7 +2736,7 @@ Returns new_value if operation was successful, -1 otherwise */ -SQLRETURN set_sql_select_limit(DBC *dbc, SQLULEN new_value) +SQLRETURN set_sql_select_limit(DBC FAR *dbc, SQLULEN new_value) { char query[44]; SQLRETURN rc; === modified file 'setupgui/windows/odbcdialogparams.cpp' --- setupgui/windows/odbcdialogparams.cpp 2010-03-01 22:45:48 +0000 +++ setupgui/windows/odbcdialogparams.cpp 2010-04-08 16:12:27 +0000 @@ -252,6 +252,8 @@ GET_BOOL(METADATA_TAB, ignore_N_in_name_table); GET_BOOL(METADATA_TAB, no_catalog); GET_BOOL(METADATA_TAB, limit_column_size); + GET_BOOL(METADATA_TAB, no_information_schema); + SET_BOOL(METADATA_TAB, no_information_schema); /* 3 - Cursors/Results */ GET_BOOL(CURSORS_TAB, return_matching_rows); @@ -266,11 +268,11 @@ GET_BOOL(DEBUG_TAB,save_queries); /* 5 - ssl related */ - getStrFieldData(¶ms.sslkey , SSL_TAB, IDC_EDIT_sslkey); - getStrFieldData(¶ms.sslcert , SSL_TAB, IDC_EDIT_sslcert); - getStrFieldData(¶ms.sslca , SSL_TAB, IDC_EDIT_sslca); - getStrFieldData(¶ms.sslcapath , SSL_TAB, IDC_EDIT_sslcapath); - getStrFieldData(¶ms.sslcipher , SSL_TAB, IDC_EDIT_sslcipher); + getStrFieldData(¶ms.sslkey , SSL_TAB, IDC_EDIT_sslkey); + getStrFieldData(¶ms.sslcert , SSL_TAB, IDC_EDIT_sslcert); + getStrFieldData(¶ms.sslca , SSL_TAB, IDC_EDIT_sslca); + getStrFieldData(¶ms.sslcapath, SSL_TAB, IDC_EDIT_sslcapath); + getStrFieldData(¶ms.sslcipher, SSL_TAB, IDC_EDIT_sslcipher); GET_BOOL(SSL_TAB,sslverify); /* 6 - Misc*/ @@ -788,4 +790,3 @@ BusyIndicator= false; return OkPressed; } - === modified file 'setupgui/windows/odbcdialogparams.rc' --- setupgui/windows/odbcdialogparams.rc 2010-03-01 22:45:48 +0000 +++ setupgui/windows/odbcdialogparams.rc 2010-04-08 17:18:44 +0000 @@ -126,6 +126,8 @@ CONTROL "Disable catalog support",IDC_CHECK_no_catalog,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,72,91,10 CONTROL "Limit column size to signed 32-bit range",IDC_CHECK_limit_column_size, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,87,141,10 + CONTROL "Don't use INFORMATION_SCHEMA for metadata",IDC_CHECK_no_information_schema, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,102,154,10 END @@ -271,4 +273,3 @@ ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED - === modified file 'setupgui/windows/resource.h' --- setupgui/windows/resource.h 2010-03-01 22:45:48 +0000 +++ setupgui/windows/resource.h 2010-04-08 15:48:33 +0000 @@ -114,6 +114,7 @@ #define IDC_CHECK_handle_binary_as_char 10036 #define IDC_CHECK_save_queries 10037 #define IDC_CHECK_clientinteractive 10040 +#define IDC_CHECK_no_information_schema 10041 #define IDC_BUTTON_TEST 11014 #define IDC_BUTTON_HELP 11015 #define IDC_STATIC -1 === modified file 'test/my_catalog.c' --- test/my_catalog.c 2010-04-08 09:03:07 +0000 +++ test/my_catalog.c 2010-04-09 15:02:18 +0000 @@ -570,7 +570,7 @@ ok_stmt(hstmt, SQLNumResultCols(hstmt, &ColumnCount)); is_num(ColumnCount, 5); - for (i= 1; i <= ColumnCount; i++) + for (i= 1; i <= ColumnCount; ++i) { ok_stmt(hstmt, SQLDescribeCol(hstmt, (SQLUSMALLINT)i, szColName, MAX_NAME_LEN, &pcbColName, &pfSqlType, @@ -753,6 +753,65 @@ } +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 istest__"); + ok_sql(hstmt, "DROP DATABASE IF EXISTS istest_1"); + ok_sql(hstmt, "DROP DATABASE IF EXISTS istest_2"); + + ok_sql(hstmt, "CREATE DATABASE istest__"); + ok_sql(hstmt, "CREATE DATABASE istest_1"); + ok_sql(hstmt, "CREATE DATABASE istest_2"); + + ok_sql(hstmt, "CREATE TABLE istest__.istab_(a INT,b INT,c INT, d INT)"); + ok_sql(hstmt, "CREATE TABLE istest_1.istab1(a INT,b INT,c INT, d INT)"); + ok_sql(hstmt, "CREATE TABLE istest_2.istab2(a INT,b INT,c INT, d INT)"); + + /* We need to have istest__ as the default DB */ + sprintf((char *)conn, "DSN=%s;UID=%s;PWD=%s;DATABASE=istest__;OPTION=0", 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, "istest__", SQL_NTS, "", 0, "istab%", 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, "istab%", 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 @@ -1432,6 +1491,7 @@ ok_sql(hstmt, "create table t_bug39957 (x int)"); ok_stmt(hstmt, SQLTables(hstmt, NULL, 0, NULL, 0, (SQLCHAR *)"t_bug39957", SQL_NTS, NULL, 0)); + ok_stmt(hstmt, SQLFetch(hstmt)); is_str(my_fetch_str(hstmt, buf, 3), "t_bug39957", 11); expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); @@ -1587,6 +1647,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.c' --- util/installer.c 2010-03-01 22:45:48 +0000 +++ util/installer.c 2010-04-08 17:15:27 +0000 @@ -1328,6 +1328,7 @@ ds->allow_multiple_statements= (options & FLAG_MULTI_STATEMENTS) > 0; ds->limit_column_size= (options & FLAG_COLUMN_SIZE_S32) > 0; ds->handle_binary_as_char= (options & FLAG_NO_BINARY_RESULT) > 0; + ds->no_information_schema= (options & FLAG_NO_INFORMATION_SCHEMA) > 0; ds->default_bigint_bind_str= (options & FLAG_DFLT_BIGINT_BIND_STR) > 0; } @@ -1377,6 +1378,8 @@ options|= FLAG_LOG_QUERY; if (ds->dont_cache_result) options|= FLAG_NO_CACHE; + if (ds->no_information_schema) + options|= FLAG_NO_INFORMATION_SCHEMA; if (ds->force_use_of_forward_only_cursors) options|= FLAG_FORWARD_CURSOR; if (ds->auto_reconnect) === modified file 'util/installer.h' --- util/installer.h 2010-03-01 22:45:48 +0000 +++ util/installer.h 2010-04-08 17:15:39 +0000 @@ -141,6 +141,7 @@ BOOL default_bigint_bind_str; /* debug */ BOOL save_queries; + BOOL no_information_schema; /* SSL */ unsigned int sslverify; } DataSource; @@ -197,12 +198,15 @@ #define FLAG_MULTI_STATEMENTS (1 << 26) /* Allow multiple statements in a query */ #define FLAG_COLUMN_SIZE_S32 (1 << 27) /* Limit column size to a signed 32-bit value (automatically set for ADO) */ #define FLAG_NO_BINARY_RESULT (1 << 28) /* Disables charset 63 for columns with empty org_table */ - /* When binding SQL_BIGINT as SQL_C_DEFAULT, treat it as a string (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) #ifdef __cplusplus