You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@datafusion.apache.org by "drewrip (via GitHub)" <gi...@apache.org> on 2026/06/23 21:43:34 UTC
[I] Unparser doesn't resolve column names in outer query correctly [datafusion]
drewrip opened a new issue, #23138:
URL: https://github.com/apache/datafusion/issues/23138
### Describe the bug
This is a follow to #22961 where I described bugs in the `Unparser` that is creating invalid SQL. In general, I'm still seeing a lot of errors in generated SQL due to column references not being appropriately qualified. This usually is showing up where we have an unnamed subquery.
### To Reproduce
This is a simple reproducer that uses DuckDB because DataFusion seems to accept the SQL. It targets datafusion `main` so that we can @goutamadwant 's changes from #23002 .
The Rust project:
```toml
datafusion = { git = "https://github.com/apache/datafusion.git" }
duckdb = { version = "1.10503.1", features = ["bundled"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
```
```rust
use std::sync::Arc;
use datafusion::arrow::datatypes::{DataType, Field, Schema};
use datafusion::catalog::{
CatalogProvider, MemoryCatalogProvider, MemorySchemaProvider, SchemaProvider,
};
use datafusion::datasource::empty::EmptyTable;
use datafusion::prelude::*;
use datafusion::sql::unparser::Unparser;
use datafusion::sql::unparser::dialect::DuckDBDialect;
use duckdb::Connection;
const QUERY: &str = r#"
SELECT * FROM
(
SELECT
order_id
FROM
"warehouse"."main"."order_items"
) oi
JOIN (
SELECT
order_id,
coalesce(discount_pct, 0) AS discount_pct_2
FROM
"warehouse"."main"."orders"
) o USING (order_id)
"#;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let order_items_schema = Arc::new(Schema::new(vec![Field::new(
"order_id",
DataType::Int32,
true,
)]));
let orders_schema = Arc::new(Schema::new(vec![
Field::new("order_id", DataType::Int32, false),
Field::new("customer_id", DataType::Int32, true),
Field::new("discount_pct", DataType::Decimal128(5, 2), true),
]));
let ctx = SessionContext::new();
let schema_provider = Arc::new(MemorySchemaProvider::new());
schema_provider.register_table(
"order_items".to_string(),
Arc::new(EmptyTable::new(order_items_schema)),
)?;
schema_provider.register_table(
"orders".to_string(),
Arc::new(EmptyTable::new(orders_schema)),
)?;
let catalog = Arc::new(MemoryCatalogProvider::new());
catalog.register_schema("main", schema_provider)?;
ctx.register_catalog("warehouse", catalog);
let dialect = DuckDBDialect::new();
let unparser = Unparser::new(&dialect);
let conn = Connection::open("warehouse.duckdb")?;
{
let unopt_plan = ctx.sql(QUERY).await?.into_unoptimized_plan();
let sql = unparser.plan_to_sql(&unopt_plan)?;
let mut stmt = conn.prepare(&sql.to_string())?;
match stmt.query([]) {
Ok(_) => {
println!("original query is valid");
}
Err(e) => {
println!("original query is not valid: {e}");
}
}
}
let plan = ctx.sql(QUERY).await?.into_optimized_plan()?;
let sql = unparser.plan_to_sql(&plan)?;
match conn.execute(&sql.to_string(), []) {
Ok(_) => {
println!("success");
}
Err(e) => {
println!("failed: {e}");
println!("Optimized sql =\n{sql}");
println!("Optimized plan =\n{}", plan.display_indent());
}
}
Ok(())
}
```
This yields the following error:
```
original query is valid
failed: Binder Error: Referenced table "o" not found!
Candidate tables: "oi"
LINE 1: ... "warehouse"."main"."order_items" AS "oi" INNER JOIN (SELECT "o"."order_id", CASE WHEN "__common_expr_1" IS NOT NULL...
^
Optimized sql =
SELECT "o"."order_id", "o"."discount_pct_2" FROM "warehouse"."main"."order_items" AS "oi" INNER JOIN (SELECT "o"."order_id", CASE WHEN "__common_expr_1" IS NOT NULL THEN "__common_expr_1" ELSE 0.00 END AS "discount_pct_2" FROM (SELECT CAST("o"."discount_pct" AS DECIMAL(22,2)) AS "__common_expr_1", "o"."order_id" FROM "warehouse"."main"."orders" AS "o")) AS "o" ON "oi"."order_id" = "o"."order_id"
Optimized plan =
Projection: o.order_id, o.discount_pct_2
Inner Join: oi.order_id = o.order_id
SubqueryAlias: oi
TableScan: warehouse.main.order_items projection=[order_id]
SubqueryAlias: o
Projection: warehouse.main.orders.order_id, CASE WHEN __common_expr_1 IS NOT NULL THEN __common_expr_1 ELSE Decimal128(0.00,22,2) END AS discount_pct_2
Projection: CAST(warehouse.main.orders.discount_pct AS Decimal128(22, 2)) AS __common_expr_1, warehouse.main.orders.order_id
TableScan: warehouse.main.orders projection=[order_id, discount_pct]
```
### Expected behavior
The `Unparser` should generate valid SQL. Specifically, we shouldn't be referencing "o" outside of the unnamed subquery.
```
SELECT
"o"."order_id",
"o"."discount_pct_2"
FROM
"warehouse"."main"."order_items" AS "oi"
INNER JOIN (
SELECT
"o"."order_id", <------ "o" doesn't exist here
CASE
WHEN "__common_expr_1" IS NOT NULL THEN "__common_expr_1"
ELSE 0.00
END AS "discount_pct_2"
FROM
(
SELECT
CAST("o"."discount_pct" AS DECIMAL(22, 2)) AS "__common_expr_1",
"o"."order_id"
FROM
"warehouse"."main"."orders" AS "o"
)
) AS "o" ON "oi"."order_id" = "o"."order_id"
```
### Additional context
The `LogicalPlan` that triggers this invalid SQL in this case is a direct result of the CSE pass. However, it does not seem to be doing anything wrong, we just can't accurately unparse the resulting `LogicalPlan`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [I] Unparser doesn't resolve column names in outer query correctly [datafusion]
Posted by "Phoenix500526 (via GitHub)" <gi...@apache.org>.
Phoenix500526 commented on issue #23138:
URL: https://github.com/apache/datafusion/issues/23138#issuecomment-4786773127
take
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org