diff --git a/ibis-server/tests/routers/v3/connector/mssql/test_query.py b/ibis-server/tests/routers/v3/connector/mssql/test_query.py index 9d029f0ad..697dd2bfc 100644 --- a/ibis-server/tests/routers/v3/connector/mssql/test_query.py +++ b/ibis-server/tests/routers/v3/connector/mssql/test_query.py @@ -107,3 +107,20 @@ async def test_pagination(client, manifest_str, connection_info): }, ) assert response.status_code == 422 + + +async def test_trim_function(client, manifest_str, connection_info): + response = await client.post( + url=f"{base_url}/query", + json={ + "connectionInfo": connection_info, + "manifestStr": manifest_str, + "sql": "SELECT TRIM(' hello ')", + }, + headers={ + X_WREN_FALLBACK_DISABLE: "true", + }, + ) + assert response.status_code == 200 + result = response.json() + assert result["data"] == [["hello"]] diff --git a/wren-core/core/src/mdl/dialect/inner_dialect.rs b/wren-core/core/src/mdl/dialect/inner_dialect.rs index 5a9605380..f93558b84 100644 --- a/wren-core/core/src/mdl/dialect/inner_dialect.rs +++ b/wren-core/core/src/mdl/dialect/inner_dialect.rs @@ -382,6 +382,18 @@ fn non_uppercase(sql: &str) -> bool { pub struct MsSqlDialect {} impl InnerDialect for MsSqlDialect { + fn scalar_function_to_sql_overrides( + &self, + unparser: &Unparser, + function_name: &str, + args: &[Expr], + ) -> Result> { + match function_name { + "btrim" => scalar_function_to_sql_internal(unparser, None, "trim", args), + _ => Ok(None), + } + } + fn to_unicode_string_literal(&self, s: &str) -> Option { if !s.is_ascii() { Some(ast::Expr::value(ast::Value::NationalStringLiteral( diff --git a/wren-core/core/src/mdl/mod.rs b/wren-core/core/src/mdl/mod.rs index 87e21297d..7bd7c0602 100644 --- a/wren-core/core/src/mdl/mod.rs +++ b/wren-core/core/src/mdl/mod.rs @@ -3691,8 +3691,9 @@ mod test { Ok(()) } + // bigquery and mssql will transform trim to trim, others to btrim #[tokio::test] - async fn test_trim_function_bigquery() -> Result<()> { + async fn test_trim_function_bigquery_and_mssql() -> Result<()> { let ctx = create_wren_ctx(None, Some(&DataSource::BigQuery)); let manifest = ManifestBuilder::new() .catalog("wren") @@ -3718,6 +3719,57 @@ mod test { @"SELECT trim(customer.c_name) FROM (SELECT customer.c_name FROM (SELECT __source.c_name AS c_name FROM customer AS __source) AS customer) AS customer" ); + let ctx = create_wren_ctx(None, Some(&DataSource::MSSQL)); + let manifest = ManifestBuilder::new() + .catalog("wren") + .schema("test") + .model( + ModelBuilder::new("customer") + .table_reference("customer") + .column(ColumnBuilder::new("c_custkey", "int").build()) + .column(ColumnBuilder::new("c_name", "string").build()) + .build(), + ) + .data_source(DataSource::MSSQL) + .build(); + let analyzed_mdl = Arc::new(AnalyzedWrenMDL::analyze( + manifest, + Arc::new(HashMap::default()), + Mode::Unparse, + )?); + + let headers = Arc::new(HashMap::default()); + let sql = "SELECT trim(c_name) FROM customer"; + assert_snapshot!( + transform_sql_with_ctx(&ctx, Arc::clone(&analyzed_mdl), &[], Arc::clone(&headers), sql).await?, + @"SELECT trim(customer.c_name) FROM (SELECT customer.c_name FROM (SELECT __source.c_name AS c_name FROM customer AS __source) AS customer) AS customer" + ); + + let manifest = ManifestBuilder::new() + .catalog("wren") + .schema("test") + .model( + ModelBuilder::new("customer") + .table_reference("customer") + .column(ColumnBuilder::new("c_custkey", "int").build()) + .column(ColumnBuilder::new("c_name", "string").build()) + .build(), + ) + .data_source(DataSource::MSSQL) + .build(); + let analyzed_mdl = Arc::new(AnalyzedWrenMDL::analyze( + manifest, + Arc::new(HashMap::default()), + Mode::Unparse, + )?); + + let headers = Arc::new(HashMap::default()); + let sql = "SELECT trim(c_name) FROM customer"; + assert_snapshot!( + transform_sql_with_ctx(&ctx, Arc::clone(&analyzed_mdl), &[], Arc::clone(&headers), sql).await?, + @"SELECT trim(customer.c_name) FROM (SELECT customer.c_name FROM (SELECT __source.c_name AS c_name FROM customer AS __source) AS customer) AS customer" + ); + let ctx = create_wren_ctx(None, None); // normal data source will be transformed to btrim let manifest = ManifestBuilder::new()