Unparser turns NULL list literals into `[]` and fails on NULL struct/map literals
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 72/100
調査の方向性
Unparser::scalar_to_sql から始めてください(datafusion/sql/src/unparser/expr.rs)。List のアーム(1450〜1454行目付近)は、子の値を null のチェックなしに描画します。Struct、Map、Union のアーム(1579〜1581行目付近)は、null の場合でも not_impl_err! を返します。issue の2つの CASE クエリで再現し、その後 Int32(None) のような型付き null がすでに NULL に unparse されるかを確認してください。ネストした型の NULL リテラルが NULL に unparse され、datafusion-sql の既存の unparser テストがすべて通れば完了です。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
The SQL unparser mishandles NULL literals of nested types:
- A NULL list literal unparses as
[], so the generated SQL returns an empty array where the plan returns NULL, with no error. - A NULL struct, map, or union literal fails with
NotImplemented("Unsupported scalar: ...").
Optimized plans contain these literals whenever type coercion casts a NULL to a nested type and constant folding turns the cast into a literal, e.g. CASE WHEN ... THEN NULL ELSE list_col END or ... UNION ALL SELECT NULL.
The cause is in Unparser::scalar_to_sql. The list arms render the scalar's child values without checking whether the list itself is null (unparser/expr.rs#L1450-L1454), and the Struct/Map/Union arms return not_impl_err! even for nulls (unparser/expr.rs#L1579-L1581). Every other typed null, such as Int32(None) or DurationSecond(None), unparses as NULL.
To Reproduce
use datafusion::error::Result;
use datafusion::prelude::*;
use datafusion::sql::unparser::plan_to_sql;
#[tokio::main]
async fn main() -> Result<()> {
let ctx = SessionContext::new();
ctx.sql("CREATE TABLE t AS SELECT 1 AS a, [1, 2] AS l, named_struct('x', 1) AS s")
.await?;
for sql in [
"SELECT CASE WHEN a > 0 THEN NULL ELSE l END AS c FROM t",
"SELECT CASE WHEN a > 0 THEN NULL ELSE s END AS c FROM t",
] {
let plan = ctx.sql(sql).await?.into_optimized_plan()?;
println!("{:?}", plan_to_sql(&plan).map(|s| s.to_string()));
}
Ok(())
}
Output:
Ok("SELECT CASE WHEN (t.a > 0) THEN [] ELSE t.l END AS c FROM t")
Err(NotImplemented("Unsupported scalar: Struct({x:})"))
Running the first unparsed query returns [] where the original returns NULL. SELECT l FROM t UNION ALL SELECT NULL FROM t similarly unparses to ... UNION ALL SELECT [] AS l FROM t. Map columns fail the same way as struct columns.
Expected behavior
NULL nested-type literals unparse as NULL, like other typed nulls, e.g. CASE WHEN (t.a > 0) THEN NULL ELSE t.l END.
A guard arm at the top of scalar_to_sql is enough:
ScalarValue::List(_)
| ScalarValue::LargeList(_)
| ScalarValue::FixedSizeList(_)
| ScalarValue::ListView(_)
| ScalarValue::LargeListView(_)
| ScalarValue::Struct(_)
| ScalarValue::Map(_)
| ScalarValue::Union(..)
if v.is_null() =>
{
Ok(ast::Expr::value(ast::Value::Null))
}
With this arm, the queries above, the UNION ALL case, and the map case all unparse to SQL that returns the same results as the original query, and the existing datafusion-sql tests still pass.
Additional context
- Non-null struct and map literals, such as a constant-folded
named_struct('x', 1), also fail withUnsupported scalar. Rendering those needs dialect-specific syntax, so they are out of scope here. - Once #26311 merges,
CASE WHEN a > 0 THEN s ELSE NULL ENDfails the same way. Until then the unparser drops the failing ELSE, which happens to give the same result forELSE NULL. - Line references are pinned to commit 0d79252f61bd.
- 主要言語
- Rust
- スター
- 9.4k
- フォーク
- 2.5k
- 平均マージ
- 4日 13時間
- マージ済み PR(30日)
- 353
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
apache/datafusion のほかの issue
-
Deduplicate bucket computation in width_bucket_interval_mdn_exact対応中かも @nightcityblade が 1 日前に担当しました。 オープンenhancement good first issue help wanted spark tech debt
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
apache/datafusion#26307 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
Use the shared aggr_test_schema in CSV scan tests instead of a local copy対応中かも @med9110 が 1 日前に担当しました。 オープンcore enhancement good first issue help wanted tech debt
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
apache/datafusion#26306 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
gcd benchmarks pass number_rows: 0 for 100k-row inputs対応中かも @med9110 が 1 日前に担当しました。 オープンbug functions good first issue help wanted tech debt
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
apache/datafusion#26297 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Struct union type coercion takes field nullability from the wrong field when field order differs対応中かも @med9110 が 1 日前に担当しました。 オープンbug help wanted logical-expr tech debt
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
apache/datafusion#26296 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
MIN/MAX don't unwrap nested encodings inside Dictionary columns対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
apache/datafusion#26290 ·
メンテナーはふだん 1 日以内に返信
apache/datafusion の issue をすべて見る
似ている issue
-
Four problem loader browser tests fail on Windows対応中かも @Patriciaath999 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
starkware-libs/sequencer#15229 ·
メンテナーはふだん 1 日以内に返信
-
`fnox set` ignores piped stdin when `--description` is given, saving the secret without a valueオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
ActivityWatch/aw-notify-rs#47 · コメント 1 件 ·