diff --git a/common/database/database_connection.cpp b/common/database/database_connection.cpp index c826c22373..531b05e4a5 100644 --- a/common/database/database_connection.cpp +++ b/common/database/database_connection.cpp @@ -400,7 +400,6 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable, try { statement.prepare( *m_conn, query ); - statement.bind( 0, aWhere.second.c_str() ); } catch( std::exception& e ) { @@ -414,6 +413,24 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable, return false; } + // Pre-describe parameter as VARCHAR to avoid SQLDescribeParam call. Some ODBC drivers + // (Microsoft Access, Excel, CSV) don't implement SQLDescribeParam. + try + { + statement.describe_parameters( { 0 }, { SQL_VARCHAR }, { 255 }, { 0 } ); + statement.bind( 0, aWhere.second.c_str() ); + } + catch( std::exception& e ) + { + m_lastError = e.what(); + wxLogTrace( traceDatabase, wxT( "Exception while binding parameter for SelectOne: %s" ), + m_lastError ); + + Disconnect(); + + return false; + } + wxLogTrace( traceDatabase, wxT( "SelectOne: `%s` with parameter `%s`" ), toUTF8( query ), aWhere.second ); diff --git a/thirdparty/nanodbc/README.txt b/thirdparty/nanodbc/README.txt index 2eb1bb681c..61298e3b27 100644 --- a/thirdparty/nanodbc/README.txt +++ b/thirdparty/nanodbc/README.txt @@ -10,9 +10,3 @@ including Werror is a bad idea. Note: The cpp and header file have been modified to remove the #ifdef _clang_ from the includes. This was needed when nanodbc changed the standard library, but now with GCC 13, this is needed when building with the GCC standard library and clang. - -Note: The cpp file has been modified to add fallback handling for SQLDescribeParam failures. -Microsoft non-SQL ODBC drivers (Access, Excel, CSV) do not implement SQLDescribeParam, -causing parameter binding to fail. The fix falls back to SQL_VARCHAR with size 255 when -SQLDescribeParam fails, matching the approach used by the r-dbi/odbc project. -See https://gitlab.com/kicad/code/kicad/-/issues/15880 diff --git a/thirdparty/nanodbc/nanodbc/nanodbc.cpp b/thirdparty/nanodbc/nanodbc/nanodbc.cpp index cf52e0a39f..04f86025e4 100644 --- a/thirdparty/nanodbc/nanodbc/nanodbc.cpp +++ b/thirdparty/nanodbc/nanodbc/nanodbc.cpp @@ -1932,11 +1932,7 @@ public: 0, &nullable); if (!success(rc)) - { - // Fallback for ODBC drivers that don't implement SQLDescribeParam - return 255; - } - + NANODBC_THROW_DATABASE_ERROR(stmt_, SQL_HANDLE_STMT); NANODBC_ASSERT( parameter_size < static_cast(std::numeric_limits::max())); return static_cast(parameter_size); @@ -1991,14 +1987,7 @@ public: ¶m.scale_, &nullable); if (!success(rc)) - { - // Fallback to binding as VARCHAR if SQLDescribeParam fails. - // This is necessary to support ODBC drivers that don't implement SQLDescribeParam, - // such as Microsoft Access, Excel, and CSV drivers. - param.type_ = SQL_VARCHAR; - param.size_ = 255; - param.scale_ = 0; - } + NANODBC_THROW_DATABASE_ERROR(stmt_, SQL_HANDLE_STMT); } else {