Skip to content

Conversation

@kosiew
Copy link
Contributor

@kosiew kosiew commented Jan 23, 2026

Which issue does this PR close?

Rationale for this change

Struct-to-struct casting previously fell back to positional mapping when there was no field-name overlap and the number of fields matched. That behavior is ambiguous and can silently produce incorrect results when source/target schemas have different field naming conventions or ordering.

This PR makes struct casting strictly name-based: when there is no overlap in field names between the source and target structs, the cast is rejected with a clear planning error. This prevents accidental, hard-to-detect data corruption and forces callers to provide explicit field names (or align schemas) when casting.

What changes are included in this PR?

  • Removed the positional fallback logic for struct casting in cast_struct_column; child fields are now resolved only by name.
  • Updated validate_struct_compatibility to error out when there is no field name overlap, instead of allowing positional compatibility checks.
  • Updated unit tests to reflect the new behavior (no-overlap casts now fail with an appropriate error).
  • Updated SQLLogicTest files to construct structs using explicit field names (e.g. {id: 1} / {a: 1, b: 'x'} or struct(… AS field)), avoiding reliance on positional behavior.
  • Improved error messaging to explicitly mention the lack of field name overlap.

Are these changes tested?

Yes.

  • Updated existing Rust unit tests in nested_struct.rs to assert the new failure mode and error message.
  • Updated SQLLogicTest coverage (struct.slt, joins.slt) to use named struct literals so tests continue to validate struct behavior without positional casting.

Are there any user-facing changes?

Yes — behavioral change / potential breaking change.

  • Casting between two STRUCTs with no overlapping field names now fails (previously it could succeed via positional mapping if field counts matched).
  • Users must provide explicit field names (e.g. {a: 1, b: 'x'} or struct(expr AS a, expr AS b)) or ensure schemas share field names.
  • Error messages are more explicit: casts are rejected when there is “no field name overlap”.

LLM-generated code disclosure

This PR includes LLM-generated code and comments. All LLM-generated content has been manually reviewed and tested.

Remove positional struct field mapping, enforcing name overlap
for struct casts and document new behavior in casting logic
and validation errors. Update struct-cast tests to assert
new no-overlap error conditions, including equal/unequal
field counts and cast-time rejection scenarios.
@github-actions github-actions bot added sqllogictest SQL Logic Tests (.slt) common Related to common crate labels Jan 23, 2026
@github-actions github-actions bot added the optimizer Optimizer rules label Jan 23, 2026
@github-actions github-actions bot added the substrait Changes to the substrait crate label Jan 23, 2026
@adriangb
Copy link
Contributor

I think we'll need an entry in upgrading.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common Related to common crate optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt) substrait Changes to the substrait crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

# Eliminate positional fallback in struct casting

2 participants