From ce3d2507977eba5b782669d96f599afd28b00f46 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 29 Sep 2025 17:49:19 +0000 Subject: [PATCH 1/3] feat: Remove ODBC max column size limit and warn on password Co-authored-by: contact --- src/webserver/database/connect.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/webserver/database/connect.rs b/src/webserver/database/connect.rs index bdf9ccca..a51c08b8 100644 --- a/src/webserver/database/connect.rs +++ b/src/webserver/database/connect.rs @@ -208,6 +208,10 @@ fn set_custom_connect_options(options: &mut AnyConnectOptions, config: &AppConfi if let Some(sqlite_options) = options.as_sqlite_mut() { set_custom_connect_options_sqlite(sqlite_options, config); } + // Allow fetching very large text fields when using ODBC by removing the max column size limit + if let Some(odbc_options) = options.as_odbc_mut() { + *odbc_options = std::mem::take(odbc_options).max_column_size(None); + } } fn set_custom_connect_options_sqlite( @@ -242,6 +246,10 @@ fn set_database_password(options: &mut AnyConnectOptions, password: &str) { *opts = take(opts).password(password); } else if let Some(opts) = options.as_mssql_mut() { *opts = take(opts).password(password); + } else if let Some(_opts) = options.as_odbc_mut() { + log::warn!( + "Setting a password for an ODBC connection is not supported via separate config; include credentials in the DSN or connection string" + ); } else if let Some(_opts) = options.as_sqlite_mut() { log::warn!("Setting a password for a SQLite database is not supported"); } else { From 5f8cbdebcb3a7693cebeb95e61d9bfa2717a4ecf Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 29 Sep 2025 19:31:57 +0000 Subject: [PATCH 2/3] Refactor: Extract ODBC connection options to a separate function Co-authored-by: contact --- src/webserver/database/connect.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/webserver/database/connect.rs b/src/webserver/database/connect.rs index a51c08b8..b5c85de8 100644 --- a/src/webserver/database/connect.rs +++ b/src/webserver/database/connect.rs @@ -10,6 +10,7 @@ use anyhow::Context; use futures_util::future::BoxFuture; use sqlx::{ any::{Any, AnyConnectOptions, AnyKind}, + odbc::OdbcConnectOptions, pool::PoolOptions, sqlite::{Function, SqliteConnectOptions, SqliteFunctionCtx}, ConnectOptions, Connection, Executor, @@ -208,10 +209,9 @@ fn set_custom_connect_options(options: &mut AnyConnectOptions, config: &AppConfi if let Some(sqlite_options) = options.as_sqlite_mut() { set_custom_connect_options_sqlite(sqlite_options, config); } - // Allow fetching very large text fields when using ODBC by removing the max column size limit - if let Some(odbc_options) = options.as_odbc_mut() { - *odbc_options = std::mem::take(odbc_options).max_column_size(None); - } + if let Some(odbc_options) = options.as_odbc_mut() { + set_custom_connect_options_odbc(odbc_options, config); + } } fn set_custom_connect_options_sqlite( @@ -239,6 +239,11 @@ fn make_sqlite_fun(name: &str, f: fn(&str) -> String) -> Function { }) } +fn set_custom_connect_options_odbc(odbc_options: &mut OdbcConnectOptions, _config: &AppConfig) { + // Allow fetching very large text fields when using ODBC by removing the max column size limit + *odbc_options = std::mem::take(odbc_options).max_column_size(None); +} + fn set_database_password(options: &mut AnyConnectOptions, password: &str) { if let Some(opts) = options.as_postgres_mut() { *opts = take(opts).password(password); @@ -246,8 +251,8 @@ fn set_database_password(options: &mut AnyConnectOptions, password: &str) { *opts = take(opts).password(password); } else if let Some(opts) = options.as_mssql_mut() { *opts = take(opts).password(password); - } else if let Some(_opts) = options.as_odbc_mut() { - log::warn!( + } else if let Some(_opts) = options.as_odbc_mut() { + log::warn!( "Setting a password for an ODBC connection is not supported via separate config; include credentials in the DSN or connection string" ); } else if let Some(_opts) = options.as_sqlite_mut() { From 3959e0b421e14c31d858fa27bedaff6503c89057 Mon Sep 17 00:00:00 2001 From: lovasoa Date: Mon, 29 Sep 2025 22:01:00 +0200 Subject: [PATCH 3/3] feat: Enhance ODBC connection options by adding batch size configuration and logging --- src/webserver/database/connect.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/webserver/database/connect.rs b/src/webserver/database/connect.rs index b5c85de8..b67dd431 100644 --- a/src/webserver/database/connect.rs +++ b/src/webserver/database/connect.rs @@ -239,9 +239,13 @@ fn make_sqlite_fun(name: &str, f: fn(&str) -> String) -> Function { }) } -fn set_custom_connect_options_odbc(odbc_options: &mut OdbcConnectOptions, _config: &AppConfig) { +fn set_custom_connect_options_odbc(odbc_options: &mut OdbcConnectOptions, config: &AppConfig) { // Allow fetching very large text fields when using ODBC by removing the max column size limit - *odbc_options = std::mem::take(odbc_options).max_column_size(None); + let batch_size = config.max_pending_rows.clamp(1, 1024); + odbc_options.batch_size(batch_size); + log::trace!("ODBC batch size set to {batch_size}"); + // Disables ODBC batching, but avoids truncation of large text fields + odbc_options.max_column_size(None); } fn set_database_password(options: &mut AnyConnectOptions, password: &str) {