From d93abea495f2b0f1492efc13127133b33982e2bc Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Tue, 18 Aug 2026 03:38:47 +0000 Subject: [PATCH] fix(jdbc): qualify TDengine table preview queries Closes #6509 --- .../dbx-core/src/sql_dialect/table_select.rs | 10 +++- crates/dbx-core/src/sql_dialect/tests.rs | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/crates/dbx-core/src/sql_dialect/table_select.rs b/crates/dbx-core/src/sql_dialect/table_select.rs index e0ad0085ab..28fb78686f 100644 --- a/crates/dbx-core/src/sql_dialect/table_select.rs +++ b/crates/dbx-core/src/sql_dialect/table_select.rs @@ -191,8 +191,16 @@ pub fn build_table_data_select_sql(options: TableDataSelectSqlOptions) -> String return format!("{}[1h]", victoriametrics_metric_selector(&options.table_name)); } + // TDengine's JDBC connection context setters do not affect WebSocket statements, + // so table reads must carry the selected database in the SQL itself. + let jdbc_tdengine_database = (database_type == Some(DatabaseType::Jdbc) + && options.driver_profile.as_deref().is_some_and(|profile| profile.trim().eq_ignore_ascii_case("tdengine"))) + .then(|| options.database.as_deref().map(str::trim).filter(|database| !database.is_empty()).or(schema)) + .flatten(); + let table = if let Some(database) = jdbc_tdengine_database { + qualified_table_name(Some(DatabaseType::Tdengine), Some(database), &options.table_name) // Doris / StarRocks multi-catalog: prefix the catalog for external-catalog tables. - let table = if uses_connection_identifier_quote(database_type, options.identifier_quote.as_deref()) { + } else if uses_connection_identifier_quote(database_type, options.identifier_quote.as_deref()) { table_data_qualified_table_name(database_type, schema, &options.table_name, options.identifier_quote.as_deref()) } else { qualified_table_name_with_catalog( diff --git a/crates/dbx-core/src/sql_dialect/tests.rs b/crates/dbx-core/src/sql_dialect/tests.rs index 35e570ec7c..f98e40a9a6 100644 --- a/crates/dbx-core/src/sql_dialect/tests.rs +++ b/crates/dbx-core/src/sql_dialect/tests.rs @@ -293,6 +293,53 @@ fn builds_select_sql_with_limit_syntax_for_database_type() { ); } +#[test] +fn jdbc_tdengine_table_preview_qualifies_selected_database() { + assert_eq!( + build_table_data_select_sql(TableDataSelectSqlOptions { + database_type: Some(DatabaseType::Jdbc), + driver_profile: Some(" TDENGINE ".to_string()), + schema: None, + database: Some("bopu_light".to_string()), + table_name: "mppd_pwr_862288087612675".to_string(), + limit: Some(100), + ..Default::default() + }), + "SELECT * FROM `bopu_light`.`mppd_pwr_862288087612675`;" + ); + + assert_eq!( + build_table_data_select_sql(TableDataSelectSqlOptions { + database_type: Some(DatabaseType::Jdbc), + driver_profile: Some("tdengine".to_string()), + schema: Some("fallback_db".to_string()), + database: Some(" ".to_string()), + table_name: "meter`readings".to_string(), + limit: Some(100), + ..Default::default() + }), + "SELECT * FROM `fallback_db`.`meter``readings`;" + ); +} + +#[test] +fn jdbc_non_tdengine_and_unscoped_tdengine_previews_remain_unqualified() { + for (driver_profile, database) in [(Some("postgres"), Some("analytics")), (Some("tdengine"), None)] { + assert_eq!( + build_table_data_select_sql(TableDataSelectSqlOptions { + database_type: Some(DatabaseType::Jdbc), + driver_profile: driver_profile.map(str::to_string), + schema: None, + database: database.map(str::to_string), + table_name: "readings".to_string(), + limit: Some(100), + ..Default::default() + }), + "SELECT * FROM readings;" + ); + } +} + #[test] fn builds_table_data_where_and_schema_queries() { assert_eq!(