Skip to content

Unparse SubqueryAlias with the pushdown TableScan fail #13272

@goldmedal

Description

@goldmedal

Describe the bug

I tried to unparse an optimized plan but encountered a 'field not found' issue. The unoptimized plan unparses correctly, suggesting a bug in the unparsing for TableScan with some pushdown. I've provided the reproduction program in the next section and the execution result below.

The executed result

## Input SQL: 
SELECT
  customer_view.c_custkey,
  customer_view.c_name,
  customer_view.custkey_plus
FROM
  (
    SELECT
      customer.c_custkey,
      customer.c_name,
      customer.custkey_plus
    FROM
      (
        SELECT
          customer.c_custkey,
          CAST(customer.c_custkey AS BIGINT) + 1 AS custkey_plus,
          customer.c_name
        FROM
          (
            SELECT
              customer.c_custkey AS c_custkey,
              customer.c_name AS c_name
            FROM
              customer
          ) AS customer
      ) AS customer
  ) AS customer_view
    
## Unoptimized Plan
Projection: customer_view.c_custkey, customer_view.c_name, customer_view.custkey_plus
  SubqueryAlias: customer_view
    Projection: customer.c_custkey, customer.c_name, customer.custkey_plus
      SubqueryAlias: customer
        Projection: customer.c_custkey, CAST(customer.c_custkey AS Int64) + Int64(1) AS custkey_plus, customer.c_name
          SubqueryAlias: customer
            Projection: customer.c_custkey, customer.c_name
              TableScan: customer

## Unparse unoptimized plan:
SELECT customer_view.c_custkey, customer_view.c_name, customer_view.custkey_plus FROM (SELECT customer.c_custkey, customer.c_name, customer.custkey_plus FROM (SELECT customer.c_custkey, (CAST(customer.c_custkey AS BIGINT) + 1) AS custkey_plus, customer.c_name FROM (SELECT customer.c_custkey, customer.c_name FROM customer) AS customer) AS customer) AS customer_view

## Optimized Plan
SubqueryAlias: customer_view
  Projection: customer.c_custkey, customer.c_name, customer.custkey_plus
    SubqueryAlias: customer
      Projection: customer.c_custkey, CAST(customer.c_custkey AS Int64) + Int64(1) AS custkey_plus, customer.c_name
        SubqueryAlias: customer
          TableScan: customer projection=[c_custkey, c_name]


Error: Schema error: No field named customer_view.c_custkey. Valid fields are customer.c_custkey, custkey_plus, customer.c_name.

To Reproduce

The executable main:

#[tokio::main]
pub async fn main() -> Result<()> {
    let ctx = SessionContext::new();
    let sql = r#"
SELECT
  customer_view.c_custkey,
  customer_view.c_name,
  customer_view.custkey_plus
FROM
  (
    SELECT
      customer.c_custkey,
      customer.c_name,
      customer.custkey_plus
    FROM
      (
        SELECT
          customer.c_custkey,
          CAST(customer.c_custkey AS BIGINT) + 1 AS custkey_plus,
          customer.c_name
        FROM
          (
            SELECT
              customer.c_custkey AS c_custkey,
              customer.c_name AS c_name
            FROM
              customer
          ) AS customer
      ) AS customer
  ) AS customer_view
    "#;
    ctx.register_batch("customer", customer())?;
    println!("Input SQL: {}", sql);
    let plan = ctx.sql(sql).await?.into_unoptimized_plan();
    println!("## Unoptimized Plan");
    println!("{}", plan);
    let result = plan_to_sql(&plan)?;
    println!("Unparse unoptimized plan: {}", result);

    let plan = ctx.sql(sql).await?.into_optimized_plan()?;
    println!("## Optimized Plan");
    println!("{}", plan);
    match plan_to_sql(&plan) {
        Ok(sql) => {
            println!("{}", sql);
        }
        Err(e) => {
            eprintln!("Error: {}", e);
        }
    }
    Ok(())
}


/// Return a RecordBatch with made up data about customer
fn customer() -> RecordBatch {
    let custkey: ArrayRef = Arc::new(Int64Array::from(vec![1, 2, 3]));
    let name: ArrayRef =
        Arc::new(StringArray::from_iter_values(["Gura", "Azki", "Ina"]));
    RecordBatch::try_from_iter(vec![("c_custkey", custkey), ("c_name", name)])
        .unwrap()
}

Expected behavior

The optimized plan should be unparsed well.

Additional context

The full backtrace:

backtrace:    0: std::backtrace_rs::backtrace::libunwind::trace
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/../../backtrace/src/backtrace/libunwind.rs:116:5
   1: std::backtrace_rs::backtrace::trace_unsynchronized
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2: std::backtrace::Backtrace::create
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/backtrace.rs:331:13
   3: std::backtrace::Backtrace::capture
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/backtrace.rs:296:9
   4: datafusion_common::error::DataFusionError::get_back_trace
             at ./datafusion/common/src/error.rs:398:30
   5: datafusion_common::error::field_not_found
             at ./datafusion/common/src/error.rs:603:27
   6: datafusion_common::dfschema::DFSchema::field_with_qualified_name::{{closure}}
             at ./datafusion/common/src/dfschema.rs:529:28
   7: core::option::Option<T>::ok_or_else
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/option.rs:1269:25
   8: datafusion_common::dfschema::DFSchema::field_with_qualified_name
             at ./datafusion/common/src/dfschema.rs:527:19
   9: datafusion_common::dfschema::DFSchema::field_from_column
             at ./datafusion/common/src/dfschema.rs:537:24
  10: <datafusion_common::dfschema::DFSchema as datafusion_common::dfschema::ExprSchema>::data_type_and_nullable
             at ./datafusion/common/src/dfschema.rs:961:21
  11: <P as datafusion_common::dfschema::ExprSchema>::data_type_and_nullable
             at ./datafusion/common/src/dfschema.rs:943:9
  12: <datafusion_expr::expr::Expr as datafusion_expr::expr_schema::ExprSchemable>::data_type_and_nullable
             at ./datafusion/expr/src/expr_schema.rs:379:32
  13: <datafusion_expr::expr::Expr as datafusion_expr::expr_schema::ExprSchemable>::to_field
             at ./datafusion/expr/src/expr_schema.rs:423:37
  14: datafusion_expr::utils::exprlist_to_fields::{{closure}}
             at ./datafusion/expr/src/utils.rs:757:26
...
  29: datafusion_expr::utils::exprlist_to_fields
             at ./datafusion/expr/src/utils.rs:703:18
  30: datafusion_expr::logical_plan::plan::projection_schema
             at ./datafusion/expr/src/logical_plan/plan.rs:2143:37
  31: datafusion_expr::logical_plan::plan::Projection::try_new
             at ./datafusion/expr/src/logical_plan/plan.rs:2093:33
  32: datafusion_expr::logical_plan::builder::project
             at ./datafusion/expr/src/logical_plan/builder.rs:1553:5
  33: datafusion_expr::logical_plan::builder::LogicalPlanBuilder::project
             at ./datafusion/expr/src/logical_plan/builder.rs:473:9
  34: datafusion_sql::unparser::plan::<impl datafusion_sql::unparser::Unparser>::unparse_table_scan_pushdown
             at ./datafusion/sql/src/unparser/plan.rs:820:25
  35: datafusion_sql::unparser::plan::<impl datafusion_sql::unparser::Unparser>::select_to_sql_recursively
             at ./datafusion/sql/src/unparser/plan.rs:567:43
  36: datafusion_sql::unparser::plan::<impl datafusion_sql::unparser::Unparser>::select_to_sql_expr
             at ./datafusion/sql/src/unparser/plan.rs:142:9
  37: datafusion_sql::unparser::plan::<impl datafusion_sql::unparser::Unparser>::select_to_sql_statement
             at ./datafusion/sql/src/unparser/plan.rs:127:20
  38: datafusion_sql::unparser::plan::<impl datafusion_sql::unparser::Unparser>::plan_to_sql
             at ./datafusion/sql/src/unparser/plan.rs:109:43
  39: datafusion_sql::unparser::plan::plan_to_sql
             at ./datafusion/sql/src/unparser/plan.rs:86:5

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions