Skip to content

expr: Convert record.rs to the sqlfunc macro - #39094

Closed
antiguru wants to merge 1 commit into
sqlfunc-convert-mapfrom
sqlfunc-convert-record
Closed

antiguru wants to merge 1 commit into
sqlfunc-convert-mapfrom
sqlfunc-convert-record

Conversation

@antiguru

@antiguru antiguru commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Converts CastRecordToString and RecordGet to #[sqlfunc]. CastRecordToString allocates its result, which the arena passed to EagerUnaryFunc::call now covers, and its NULL check moves into its ExcludeNull<Datum<'a>> input. RecordGet takes a DatumList<'a> and returns the selected field, with an output_type_expr that gives that field's column type. It keeps the could_error = true the old impl inherited, which #39814 drops.

func_registry_records_sqlfunc_sources used record_get as its example of a function with no recorded source, so it switches to extract_interval. The registry reports only sqlfunc_signature moving, on both records.

Based on #39093.

🤖 Generated with Claude Code

@antiguru
antiguru requested a review from a team as a code owner September 23, 2026 21:10
@antiguru
antiguru added this pull request to stack #38942 September 24, 2026 08:52
@antiguru
antiguru force-pushed the sqlfunc-convert-record branch from 8fb9b56 to ab71954 Compare September 24, 2026 10:14
@antiguru
antiguru requested a review from petrosagg September 24, 2026 11:18
@antiguru
antiguru force-pushed the sqlfunc-convert-record branch from ab71954 to 165fb4f Compare September 24, 2026 14:29
@antiguru
antiguru force-pushed the sqlfunc-convert-record branch from 165fb4f to 6eb1536 Compare September 25, 2026 16:00
@antiguru
antiguru removed the request for review from petrosagg October 13, 2026 15:56
@antiguru
antiguru force-pushed the sqlfunc-convert-map branch from 923e52e to b1f46ff Compare October 14, 2026 09:11
@antiguru
antiguru force-pushed the sqlfunc-convert-record branch from 6eb1536 to 5663ac0 Compare October 14, 2026 09:11
@antiguru
antiguru requested a review from mgree October 14, 2026 10:22
Both impls checked NULL in the body, which under the macro has to come from the
input type.

`CastRecordToString` was hand-written because it allocates its result, which the
eager trait now covers: a `String` output is pushed into the arena by
`OutputDatumType::into_result`. Its input is `ExcludeNull<Datum<'a>>`, because
`stringify_datum` takes a raw `Datum` and a bare `Datum` accepts NULL.
`ExcludeNull` reports `nullable() == false`, so the derived `propagates_nulls`
is true, matching the declaration, and its `try_from_result` turns
`Datum::Null` into `Err(Ok(Datum::Null))`, which the evaluation layer returns as
`Ok(Datum::Null)`. `introduces_nulls` derives false from the `String` inside the
`Result`. `output_sql_type` returned `String.nullable(input_type.nullable)`,
which the derived output plus the unary tail gives for a non-nullable input, so
no output modifier is needed. `preserves_uniqueness = true` carries over,
`could_error` derives true from the fallible output, and `inverse`,
`is_monotone` and `is_eliminable_cast` returned the trait defaults and are
dropped. The `TODO?` on `inverse` now sits on the function. `Display` wrote a
fixed string, so `sqlname` reproduces it.

`RecordGet` allocates nothing and returns a field borrowed from its input, so
its output is a bare `Datum<'a>` and it takes no arena. Its input is
`DatumList<'a>`, which is what the body unwrapped the record to; `DatumList`
reports `nullable() == false` on its own, so no `ExcludeNull` wrapper is needed
and the derived `propagates_nulls` is true.

`RecordGet`'s `output_sql_type` reads the input, so it becomes an
`output_type_expr` that returns the selected field's column type. The
hand-written version also ORed `input_type.nullable` onto that type, which the
unary tail now does, so the expression drops the term. `introduces_nulls`
derives true from the bare `Datum` output, which is what the impl declared. The
output is a bare `Datum`, from which `could_error` would derive false, so the
modifier pins the `true` the impl declared by inheriting `LazyUnaryFunc`'s
conservative default. `preserves_uniqueness`, `inverse`, `is_monotone` and
`is_eliminable_cast` returned the trait defaults and are dropped, and its
`Display` formats the field index, so it stays hand-written under `skip_display
= true`.

`func_registry_records_sqlfunc_sources` used `record_get` as its example of a
function with no recorded source. It now has one, so the assertion moves to
`extract_interval`.

The registry reports only `sqlfunc_signature` moving, on both records.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@antiguru
antiguru force-pushed the sqlfunc-convert-map branch from b1f46ff to e61cc4e Compare October 14, 2026 15:18
@antiguru
antiguru force-pushed the sqlfunc-convert-record branch from 5663ac0 to 3cfd255 Compare October 14, 2026 15:18
@antiguru
antiguru removed this pull request from stack #38942 October 14, 2026 15:45
@antiguru

Copy link
Copy Markdown
Member Author

Folded into #39062, which now carries all twenty file conversions as separate commits, per review feedback to land them as one PR.

Posted by Claude Code.

@antiguru antiguru closed this Oct 14, 2026
@antiguru
antiguru deleted the sqlfunc-convert-record branch October 14, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant