Skip to content

core: a field reference into a nullable struct, list or map derives a required type #1338

Description

@nielspardon

FieldReference.dereferenceStruct, dereferenceList and dereferenceMap type the result as the member's declared type and ignore the container's own nullability, so reading a field of a struct that may be null is typed as though it can never be null.

FieldReference.newRootStructReference(0, N.struct(R.I32, N.FP64)).dereferenceStruct(0).getType();
// I32{nullable=false}
FieldReference.newRootStructReference(0, N.list(R.I32)).dereferenceList(0).getType();
// I32{nullable=false}
FieldReference.newRootStructReference(0, N.map(R.STRING, R.I32))
    .dereferenceMap(ExpressionCreator.string(false, "k")).getType();
// I32{nullable=false}

Measured on main at 4bb02974. The derivation is StructFieldFinder, ListIndexFinder and MapKeyFinder.getReferencedType in FieldReference.java.

The spec does not settle it. site/docs/expressions/field_references.md (v0.102.0) gives a struct field reference's type as "Type of field referenced" and states no nullability rule for any kind of reference. The type is never serialized (StructField carries only field and child), so every consumer derives it itself. substrait-go (StructFieldRef.GetType) and substrait-python (type_inference.py) also return the declared member type unchanged.

This matters more since #1317: a nullable struct now keeps its required fields through Calcite instead of having them widened to nullable, so this derivation now decides the type of any reference into one. The open question is whether :core should make the derived type nullable when the container is, and if so, whether the spec should say so first.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions