SubstraitRelNodeConverter.visit(NamedUpdate) builds its update column list by indexing the schema's flattened name list with a top-level column ordinal:
https://github.com/substrait-io/substrait-java/blob/main/isthmus/src/main/java/io/substrait/isthmus/SubstraitRelNodeConverter.java#L721
NamedStruct.names() is one name per struct field at every level, in depth-first order, while TransformExpression.getColumnTarget() is an index among the top-level columns. The two agree only for a flat schema.
For a table whose schema is struct(struct(i32, i32), i32) the names are ["s", "x", "y", "n"], so an update targeting column 1 — the top-level column n — resolves to x, a nested field. The resulting LogicalTableModify names a column that does not exist at the top level, or silently the wrong one when a nested name collides with a real column.
This is the same flat-vs-depth-first confusion as #1152, which #1153 fixed for VirtualTableScan; the sibling method in the same file was left as it was. A struct-literal transformation targeting a struct column also carries Calcite's placeholder field names rather than the schema's, which is the other half of what #1153 fixed.
SubstraitRelNodeConverter.visit(NamedUpdate)builds its update column list by indexing the schema's flattened name list with a top-level column ordinal:https://github.com/substrait-io/substrait-java/blob/main/isthmus/src/main/java/io/substrait/isthmus/SubstraitRelNodeConverter.java#L721
NamedStruct.names()is one name per struct field at every level, in depth-first order, whileTransformExpression.getColumnTarget()is an index among the top-level columns. The two agree only for a flat schema.For a table whose schema is
struct(struct(i32, i32), i32)the names are["s", "x", "y", "n"], so an update targeting column 1 — the top-level columnn— resolves tox, a nested field. The resultingLogicalTableModifynames a column that does not exist at the top level, or silently the wrong one when a nested name collides with a real column.This is the same flat-vs-depth-first confusion as #1152, which #1153 fixed for
VirtualTableScan; the sibling method in the same file was left as it was. A struct-literal transformation targeting a struct column also carries Calcite's placeholder field names rather than the schema's, which is the other half of what #1153 fixed.