From 0c62340657e3d11069266d01bf4bbc3dd3dfd659 Mon Sep 17 00:00:00 2001 From: HARRISON Date: Tue, 13 Oct 2026 15:06:09 +0800 Subject: [PATCH] fix(sundb): stop quoting simple identifiers in generated SQL --- crates/dbx-sql-data/src/data_grid_sql.rs | 23 +++++++++++++++++++ .../src/sql_dialect/identifiers.rs | 7 ++++++ .../dbx-sql-dialect/src/sql_dialect/tests.rs | 6 +++++ 3 files changed, 36 insertions(+) diff --git a/crates/dbx-sql-data/src/data_grid_sql.rs b/crates/dbx-sql-data/src/data_grid_sql.rs index 1a6ada288c..562a13de5a 100644 --- a/crates/dbx-sql-data/src/data_grid_sql.rs +++ b/crates/dbx-sql-data/src/data_grid_sql.rs @@ -4504,6 +4504,29 @@ mod tests { } } + fn sundb_people_save_options() -> DataGridSaveStatementOptions { + let mut options = mysql_people_save_options(1); + options.database_type = Some(DatabaseType::Sundb); + // SUNDB resolves unquoted names case-insensitively (folding to uppercase), so the + // grid must not quote them: a quoted `"rs_salest_budget"` preserved the case and + // matched nothing (#11986). + options.table_meta.table_name = "rs_salest_budget".to_string(); + options.table_meta.schema = None; + options.dirty_rows = vec![(0, vec![(1, json!("blocked"))])]; + options + } + + #[test] + fn sundb_grid_save_leaves_simple_identifiers_unquoted() { + let statements = + build_data_grid_save_statements(&sundb_people_save_options(), None, &mut Vec::new(), &mut Vec::new()); + + assert_eq!(statements.len(), 1); + assert!(statements[0].starts_with("UPDATE rs_salest_budget SET "), "{}", statements[0]); + assert!(statements[0].contains("WHERE id = 1"), "{}", statements[0]); + assert!(!statements[0].contains("\"rs_salest_budget\""), "{}", statements[0]); + } + fn mysql_people_save_options(row_count: usize) -> DataGridSaveStatementOptions { DataGridSaveStatementOptions { database_type: Some(DatabaseType::Mysql), diff --git a/crates/dbx-sql-dialect/src/sql_dialect/identifiers.rs b/crates/dbx-sql-dialect/src/sql_dialect/identifiers.rs index 9b290327c1..8a6f6f7172 100644 --- a/crates/dbx-sql-dialect/src/sql_dialect/identifiers.rs +++ b/crates/dbx-sql-dialect/src/sql_dialect/identifiers.rs @@ -169,6 +169,13 @@ pub fn quote_table_identifier(database_type: Option, name: &str) - format!("`{}`", name.replace('`', "``")) } Some(DatabaseType::Informix) if is_simple_informix_identifier(name) => name.to_string(), + // SUNDB folds unquoted identifiers to uppercase (its JDBC driver reports + // storesUpperCaseIdentifiers=true / supportsMixedCaseIdentifiers=false), so + // `select * from rs_salest_budget` resolves to RS_SALEST_BUDGET. Quoting the + // name preserves its case instead, and the generated UPDATE then finds no such + // table (#11986). Emit simple names unquoted, as Informix does; a name that + // needs quoting keeps the generic double-quote form. + Some(DatabaseType::Sundb) if is_simple_informix_identifier(name) => name.to_string(), Some(DatabaseType::Neo4j) => format!("`{}`", name.replace('`', "``")), Some(DatabaseType::Nebula) => format!("`{}`", name.replace('\\', "\\\\").replace('`', "\\`")), Some(DatabaseType::SqlServer) => format!("[{}]", name.replace(']', "]]")), diff --git a/crates/dbx-sql-dialect/src/sql_dialect/tests.rs b/crates/dbx-sql-dialect/src/sql_dialect/tests.rs index dcf3131966..26e7a7be81 100644 --- a/crates/dbx-sql-dialect/src/sql_dialect/tests.rs +++ b/crates/dbx-sql-dialect/src/sql_dialect/tests.rs @@ -33,6 +33,12 @@ fn quotes_identifiers_by_database_type() { assert_eq!(quote_table_identifier(Some(DatabaseType::Gaussdb), "\"MixedCase\""), "\"MixedCase\""); assert_eq!(quote_table_identifier(Some(DatabaseType::OpenGauss), "\"MixedCase\""), "\"MixedCase\""); assert_eq!(quote_table_identifier(Some(DatabaseType::Informix), "users_1"), "users_1"); + // SUNDB folds unquoted names to uppercase, so a simple lowercase name must stay + // unquoted; quoting it preserved the case and the statement found no such table (#11986). + assert_eq!(quote_table_identifier(Some(DatabaseType::Sundb), "rs_salest_budget"), "rs_salest_budget"); + assert_eq!(quote_table_identifier(Some(DatabaseType::Sundb), "YEAR"), "YEAR"); + assert_eq!(quote_table_identifier(Some(DatabaseType::Sundb), "user name"), "\"user name\""); + assert_eq!(quote_table_identifier(Some(DatabaseType::Sundb), "user\"name"), "\"user\"\"name\""); assert_eq!(quote_table_identifier(Some(DatabaseType::Jdbc), "users_1"), "users_1"); assert_eq!(quote_table_identifier(Some(DatabaseType::Jdbc), "user name"), "user name"); assert_eq!(quote_table_identifier(Some(DatabaseType::Iotdb), "root.test.device2"), "root.test.device2");