Struct union type coercion takes field nullability from the wrong field when field order differs
维护者通常 1 天内回复
@med9110 已经在做这个了。
开始于 2026年10月14日。
评估
调研方向
从 (DataType::Struct(lhs), DataType::Struct(rhs)) 分支开始,该分支位于 datafusion/expr-common/src/type_coercion/binary.rs 的 type_union_resolution_coercion 中。让 search_corresponding_coerced_type 同时返回按名称匹配的 rhs 字段,并将该字段传给 coerce_fields,而不是按位置 zip。运行该文件中现有的 struct union coercion 测试,并添加一个字段顺序互换的用例。当 Struct { a: Int32 NOT NULL, b: Int32 NOT NULL } 与 Struct { b: Int32 NULL, a: Int32 NOT NULL } 做 union 得到 Struct { a: Int32 NOT NULL, b: Int32 NULL } 时即完成。
由索引模型根据 Issue 内容生成。
描述
Describe the bug
In the (DataType::Struct(lhs), DataType::Struct(rhs)) arm of type_union_resolution_coercion (type_coercion/binary.rs#L835-L872), each field's coerced type is computed by matching fields by name (search_corresponding_coerced_type), but the field's nullability is computed by zipping lhs and rhs positionally:
let coerced_types = lhs
.iter()
.map(|lhs_field| search_corresponding_coerced_type(lhs_field, rhs))
.collect::<Option<Vec<_>>>()?;
// preserve the field name and nullability
let orig_fields = std::iter::zip(lhs.iter(), rhs.iter());
let fields: Vec<FieldRef> = coerced_types
.into_iter()
.zip(orig_fields)
.map(|(datatype, (lhs, rhs))| coerce_fields(datatype, lhs, rhs))
.collect();
coerce_fields sets nullable = lhs.is_nullable() || rhs.is_nullable(). When the two structs have the same field names in a different order, the nullability of each output field comes from an unrelated right-hand field.
To Reproduce
Resolve the union type of:
lhs = Struct { a: Int32 NOT NULL, b: Int32 NOT NULL }rhs = Struct { b: Int32 NULL, a: Int32 NOT NULL }
The result is Struct { a: Int32 NULL, b: Int32 NOT NULL }. Field b is reported as non-nullable even though the right-hand b can contain nulls (and a is needlessly marked nullable).
Expected behavior
Nullability is taken from the name-matched pair, giving Struct { a: Int32 NOT NULL, b: Int32 NULL }. For example, have search_corresponding_coerced_type return the matched rhs_field along with the coerced type, and pass that field to coerce_fields.
Additional context
The nearby try_type_union_resolution_with_struct (about L900-L970) walks data_types three times, each re-matching DataType::Struct with an internal_err! fallback the first loop already rules out. It may be worth simplifying in the same change.
Line references are pinned to commit 0d79252f61bd.
- 主要语言
- Rust
- 星标
- 9.5k
- 派生
- 2.5k
- 平均合并
- 4 天 19 小时
- 30 天内合并 PR
- 342
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
apache/datafusion 的其他 Issue
-
[Bug] atan2 does not normalize -0.0 the way Spark does可能已有人在做 @spicysharkco 于 1 天前认领。 未关闭bug spark
难度 2/5 1-3 小时 新手友好度 72/100
apache/datafusion#26333 ·
维护者通常 1 天内回复
-
bug help wanted unparser
难度 2/5 1-3 小时 新手友好度 72/100
apache/datafusion#26316 · 1 条评论 ·
维护者通常 1 天内回复
-
Deduplicate bucket computation in width_bucket_interval_mdn_exact可能已有人在做 @nightcityblade 于 2 天前认领。 未关闭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 于 2 天前认领。 未关闭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 于 2 天前认领。 未关闭bug functions good first issue help wanted tech debt
难度 1/5 1 小时以内 新手友好度 92/100
apache/datafusion#26297 · 1 条评论 ·
维护者通常 1 天内回复
查看 apache/datafusion 的全部 Issue
相似的 Issue
-
priority: medium
难度 2/5 1-3 小时 新手友好度 68/100
storytold/photocraft#6759 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 65/100
-
area:logging documentation good first issue
难度 2/5 1-3 小时 新手友好度 72/100
hugowis/open-fpv-sim#48 ·
-
难度 2/5 1-3 小时 新手友好度 68/100
IngvarConsulting/unica#1537 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 70/100