Interface StructBuilder


@Experimental public interface StructBuilder

Sets the fields of one struct — a record being written, or a struct nested inside one.

A record is a struct, so RowWriter.writeRow(Consumer) hands the same builder a nested setStruct(String, Consumer) does. Fields are addressed by the name they carry in the schema, or by their position in it; the synthetic list / element and key_value groups a LIST or MAP introduces are never spelled by the caller.

rows.writeRow(row -> row
        .setLong("id", 1)
        .setString("name", "hardwood")
        .setStruct("address", address -> address.setString("city", "Berlin")));

Every setter has an index-taking mirror, and getFieldCount() and getFieldName(int) report the positions those indices address — the same pair FieldAccessor exposes on the read side.

A loop that walks a row's fields by index can therefore read back and write forward through the same positions, provided the write schema mirrors what was read. The reader's index is the position in projected schema order; this one is the position in the write schema's declaration order. They are the same position when the whole file is read into its own schema, and they diverge under a projection: reading three of ten columns and writing into the ten-column schema shifts every position, and where the columns that land on each other happen to share a type the values are written to the wrong fields rather than rejected. Comparing getFieldName(int) against the reader's for each index costs one string comparison per field and turns that into a failure.

A field that is never set is written as null if it is OPTIONAL, and fails the record if it is REQUIRED; setNull(String) states the same thing explicitly, and a null value handed to any of the object-typed setters does too. Setting the same field twice within one scope, naming a field the schema does not have, or using a setter that does not fit the field's declared type all throw at the call.

The builder is valid only inside the lambda it was passed to. Retaining one and using it afterwards throws IllegalStateException rather than writing into a later record.

This API is Experimental: the shape may change in future releases.