Index: driver/results.c =================================================================== --- driver/results.c (revision 610) +++ driver/results.c (working copy) @@ -528,6 +528,9 @@ return set_error(stmt,MYERR_S1002,"Invalid column number",0); type= unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,&display_size ); + + if ((stmt->dbc->flag & FLAG_COLUMN_SIZE_S32) && precision > INT_MAX32) + precision= INT_MAX32; /* printf( "[PAH][%s][%d][%s] type=%d\n", __FILE__, __LINE__, __FUNCTION__, type ); */ Index: driver/myodbc3.h =================================================================== --- driver/myodbc3.h (revision 611) +++ driver/myodbc3.h (working copy) @@ -165,6 +165,7 @@ #define FLAG_ZERO_DATE_TO_MIN (1 << 24) /* Convert XXXX-00-00 date to ODBC min date on results */ #define FLAG_MIN_DATE_TO_ZERO (1 << 25) /* Convert ODBC min date to 0000-00-00 on query */ #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) */ /* We don't make any assumption about what the default may be. */ #ifndef DEFAULT_TXN_ISOLATION Index: driver/connect.c =================================================================== --- driver/connect.c (revision 611) +++ driver/connect.c (working copy) @@ -111,6 +111,15 @@ options= strtoul(ds->pszOPTION, NULL, 10); port= (unsigned int)atoi(ds->pszPORT); +#ifdef WIN32 + /* + Detect if we are running with ADO present, and force on the + FLAG_COLUMN_SIZE_S32 option if we are. + */ + if (GetModuleHandle("msado15.dll") != NULL) + options|= FLAG_COLUMN_SIZE_S32; +#endif + mysql_init(mysql); flags= get_client_flags(options); Index: test/my_result.c =================================================================== --- test/my_result.c (revision 610) +++ test/my_result.c (working copy) @@ -1831,6 +1831,117 @@ } +/** + Bug #13776: Invalid string or buffer length error +*/ +DECLARE_TEST(t_bug13776) +{ + SQLHENV henv1; + SQLHDBC hdbc1; + SQLHSTMT hstmt1; + + SQLULEN pcColSz; + SQLCHAR szColName[MAX_NAME_LEN]; + SQLCHAR szData[MAX_ROW_DATA_LEN+1]; + SQLSMALLINT pfSqlType, pcbScale, pfNullable; + + SET_DSN_OPTION(1 << 27); + + /* Establish the new connection */ + alloc_basic_handles(&henv1, &hdbc1, &hstmt1); + + ok_sql(hstmt1, "DROP TABLE IF EXISTS t_bug13776"); + ok_sql(hstmt1, "CREATE TABLE t_bug13776(ltext LONGTEXT)"); + ok_sql(hstmt1, "INSERT INTO t_bug13776 VALUES ('long text test')"); + ok_sql(hstmt1, "SELECT * FROM t_bug13776"); + ok_stmt(hstmt1, SQLDescribeCol(hstmt1, 1, szColName, MAX_NAME_LEN+1, NULL, + &pfSqlType, &pcColSz, &pcbScale, &pfNullable)); + + /* Size of LONGTEXT should have been capped to 1 << 31. */ + is_num(pcColSz, 2147483647L); + + ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_CLOSE)); + + ok_sql(hstmt1, "DROP TABLE IF EXISTS t_bug13776"); + + free_basic_handles(&henv1, &hdbc1, &hstmt1); + + SET_DSN_OPTION(0); + + return OK; +} + + +/** + Test that FLAG_COLUMN_SIZE_S32 is automatically enabled when ADO library + is loaded. +*/ +DECLARE_TEST(t_bug13776_auto) +{ +#ifdef WIN32 + SQLHENV henv1; + SQLHDBC hdbc1; + SQLHSTMT hstmt1; + HMODULE ado_dll; + + SQLULEN pcColSz; + SQLCHAR szColName[MAX_NAME_LEN]; + SQLCHAR szData[MAX_ROW_DATA_LEN+1]; + SQLSMALLINT pfSqlType, pcbScale, pfNullable; + SQLCHAR *env_path= NULL; + SQLCHAR szFileToLoad[255]; + + /** @todo get the full path to the library using getenv */ + env_path= getenv("CommonProgramFiles(x86)"); + if (!env_path) + env_path= getenv("CommonProgramFiles"); + + if (!env_path) + { + printf("# No path for CommonProgramFiles in %s on line %d\n", + __FILE__, __LINE__); + return FAIL; + } + + sprintf(szFileToLoad, "%s\\System\\ado\\msado15.dll", env_path); + + ado_dll= LoadLibrary(szFileToLoad); + if (!ado_dll) + { + printf("# Could not load %s in %s on line %d\n", + szFileToLoad, __FILE__, __LINE__); + return FAIL; + } + + /* Establish the new connection */ + alloc_basic_handles(&henv1, &hdbc1, &hstmt1); + + ok_sql(hstmt1, "DROP TABLE IF EXISTS t_bug13776"); + ok_sql(hstmt1, "CREATE TABLE t_bug13776(ltext LONGTEXT)"); + ok_sql(hstmt1, "INSERT INTO t_bug13776 VALUES ('long text test')"); + ok_sql(hstmt1, "SELECT * FROM t_bug13776"); + ok_stmt(hstmt1, SQLDescribeCol(hstmt1, 1, szColName, MAX_NAME_LEN+1, NULL, + &pfSqlType, &pcColSz, &pcbScale, &pfNullable)); + + /* + IF adodb15.dll is loaded SQLDescribeCol should return the length of + LONGTEXT columns as 2G instead of 4G + */ + is_num(pcColSz, 2147483647L); + + ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_CLOSE)); + + ok_sql(hstmt1, "DROP TABLE IF EXISTS t_bug13776"); + + free_basic_handles(&henv1, &hdbc1, &hstmt1); + + FreeLibrary(ado_dll); +#endif + + return OK; +} + + BEGIN_TESTS ADD_TEST(my_resultset) ADD_TEST(t_convert_type) @@ -1852,6 +1963,8 @@ ADD_TEST(t_bug27544) ADD_TEST(t_bug16817) ADD_TEST(bug6157) + ADD_TEST(t_bug13776) + ADD_TEST(t_bug13776_auto) END_TESTS Index: ChangeLog =================================================================== --- ChangeLog (revision 612) +++ ChangeLog (working copy) @@ -1,6 +1,9 @@ 3.51.18 Functionality added or changed: + * Added FLAG_COLUMN_SIZE_S32 to limit the reported column size to a + signed 32-bit integer. This option is automatically enabled for ADO + applications, in order to work around a bug in ADO. (Bug #13776) * Added FLAG_MULTI_STATEMENTS to allow issuing queries that contain multiple statements. Also added to the setup GUI. (Bug #7445) * Removed support for the TRACE and TRACEFILE DSN options. The standard Index: setup/MYODBCSetupDataSourceTab3.cpp =================================================================== --- setup/MYODBCSetupDataSourceTab3.cpp (revision 611) +++ setup/MYODBCSetupDataSourceTab3.cpp (working copy) @@ -100,6 +100,8 @@ nFlags |= 1 << 23; if ( ptab3c->pcheckboxMultiStatements->isChecked() ) nFlags |= 1 << 26; + if ( ptab3c->pcheckboxCapColumnSize->isChecked() ) + nFlags |= 1 << 27; return nFlags; } Index: setup/MYODBCSetupDataSourceTab3c.h =================================================================== --- setup/MYODBCSetupDataSourceTab3c.h (revision 611) +++ setup/MYODBCSetupDataSourceTab3c.h (working copy) @@ -49,6 +49,7 @@ MYODBCSetupCheckBox *pcheckboxDisableTransactions; MYODBCSetupCheckBox *pcheckboxForceUseOfForwardOnlyCursors; MYODBCSetupCheckBox *pcheckboxMultiStatements; + MYODBCSetupCheckBox *pcheckboxCapColumnSize; }; #endif Index: setup/MYODBCSetupDataSourceTab3c.cpp =================================================================== --- setup/MYODBCSetupDataSourceTab3c.cpp (revision 611) +++ setup/MYODBCSetupDataSourceTab3c.cpp (working copy) @@ -31,6 +31,7 @@ QString stringDisableTransactions( tr("Disable transactions.") ); QString stringForceUseOfForwardOnlyCursors( tr("Force the use of Forward-only cursor type. In case of applications setting the default static/dynamic cursor type, and one wants driver to use non-cache result sets, then this option will ensure the forward-only cursor behavior.") ); QString stringMultiStatements( tr("Allow multiple statements in a single query.") ); + QString stringCapColumnSize( tr("Limit reported column size to signed 32-bit integer (possible workaround for some applications, automatically enabled for applications using ADO)") ); #if QT_VERSION >= 0x040000 QVBoxLayout *playoutFields = new QVBoxLayout; @@ -115,6 +116,15 @@ QToolTip::add( pcheckboxMultiStatements, stringMultiStatements ); #endif + pcheckboxCapColumnSize = new MYODBCSetupCheckBox( tr("Limit column size to signed 32-bit range"), this ); + pcheckboxCapColumnSize->setAssistText( stringCapColumnSize ); + playoutFields->addWidget( pcheckboxCapColumnSize ); +#if QT_VERSION >= 0x040000 + pcheckboxCapColumnSize->setToolTip( stringCapColumnSize ); +#else + QToolTip::add( pcheckboxCapColumnSize, stringCapColumnSize ); +#endif + playoutFields->addStretch( 10 ); }