Bug Description
The ODBC backend never populates its statement cache, so every query executes through SQLExecDirect.
Depending on the driver used the user impact is ::
statement_cache_capacity (default 100) and Execute::persistent() are silently no-ops on ODBC.
SQLBindParameter followed by SQLExecDirect is valid ODBC, but a driver that only collects bindings on the SQLPrepare/SQLExecute path will send the statement with no parameter values at all.
Minimal Reproduction
(1) I used PostgreSQL as it doesn't have the param pass through issue.
Cargo.toml:
[package]
name = "repro"
version = "0.0.0"
edition = "2021"
[workspace]
[dependencies]
sqlx = { package = "sqlx-oldapi", version = "0.6.56", default-features = false, features = ["runtime-tokio-rustls", "odbc"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
src/main.rs:
use sqlx::Connection;
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let url = std::env::var("DATABASE_URL").expect("DATABASE_URL");
let mut conn = sqlx::OdbcConnection::connect(&url).await?;
for _ in 0..10 {
let row: (i32,) = sqlx::query_as("SELECT CAST(? AS INTEGER)")
.bind(42)
.fetch_one(&mut conn)
.await?;
assert_eq!(row.0, 42);
}
println!("cached_statements_size = {}", conn.cached_statements_size());
Ok(())
}
SOP
$ docker run --rm -d --name pg -e POSTGRES_PASSWORD='Password123!' -e POSTGRES_USER=root -e POSTGRES_DB=test -p 5432:5432 postgres:16
# ODBC backend
$ DATABASE_URL='Driver=/nix/store/1fyjnz2b5h28pdcy9wakcvcq8ywz166g-psqlodbc-18.00.0002/lib/psqlodbcw.so;Server=127.0.0.1;Port=5432;Database=test;UID=root;PWD=Password123!' cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
Running `target/debug/repro`
cached_statements_size = 0 # expected :: 1
(2) Is reproducible in SQLPage with SQLPage#1474.
In "index.sql": The following error occurred while executing an SQL statement:
error returned from database: ODBC emitted an error calling 'SQLExecDirect':
State: HY000, Native error: 100, Message: [GizmoData][GizmoSQL] (100) An execution error has occurred: Invalid Input Error: Values were not provided for the following prepared statement parameters: 1, 2. gRPC client debug context: UNKNOWN:Error received from peer ipv6:%5B::1%5D:31337 {grpc_message:"An execution error has occurred: Invalid Input Error: Values were not provided for the following prepared statement parameters: 1, 2", grpc_status:2, created_time:"2026-09-21T16:29:56.6640056+00:00"}. Client context: OK
Info
- SQLx version: 0.6.56 (
sqlx-oldapi, main at f8b378d1)
- SQLx features enabled:
runtime-tokio-rustls, odbc, postgres, any
- Database server and version: PostgreSQL 16 via psqlODBC 18.00.0002 (also reproduced against GizmoSQL 1.39.0 via gizmosql-odbc 1.1.2, and DuckDB via duckdb-odbc 1.5.5), unixODBC 2.3.14
- Operating system: NixOS 26.11, Linux 6.18.52 x86_64
rustc --version: rustc 1.98.1 (48a229cea 2026-09-01)
Bug Description
The ODBC backend never populates its statement cache, so every query executes through
SQLExecDirect.Depending on the driver used the user impact is ::
statement_cache_capacity(default 100) andExecute::persistent()are silently no-ops on ODBC.SQLBindParameterfollowed bySQLExecDirectis valid ODBC, but a driver that only collects bindings on theSQLPrepare/SQLExecutepath will send the statement with no parameter values at all.Minimal Reproduction
(1) I used PostgreSQL as it doesn't have the param pass through issue.
Cargo.toml:src/main.rs:SOP
(2) Is reproducible in SQLPage with SQLPage#1474.
Info
sqlx-oldapi,mainatf8b378d1)runtime-tokio-rustls,odbc,postgres,anyrustc --version: rustc 1.98.1 (48a229cea 2026-09-01)