Repository navigation
expr: Correct over-conservative properties of record_get and map_build_from_record_list - #39814
Conversation
| } | ||
| )] | ||
| fn record_get<'a>(&self, a: DatumList<'a>) -> Datum<'a> { | ||
| a.iter().nth(self.0).unwrap() |
There was a problem hiding this comment.
Claude, please file a linear issue for avoiding panics in function implementations to enforce invariants.
f74d198 to
bf94aba
Compare
bf94aba to
e94c12d
Compare
mgree
left a comment
There was a problem hiding this comment.
LGTM. For posterity, https://linear.app/materializeinc/issue/CPU-308/avoid-panics-in-scalar-function-implementations-to-enforce-invariants documents the tension between panics and internal errors.
`record_get` returns a field of its input record and never produces an `EvalError`, yet it declared `could_error = true`. The flag came over from the hand-written implementation, whose `LazyUnaryFunc::could_error` defaulted to true. Dropping it lets the macro infer `false` from the non-`Result` output. Registry: `record_get` changes `could_error` from true to false. The current `LIR_VERSION` hasn't shipped, so the snapshots were regenerated in place. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`map_build_from_record_list` skips NULL records and NULL keys and always returns a map, so it never returns NULL for a non-NULL input and never produces an `EvalError`. It declared `introduces_nulls` and `could_error` true and a nullable output anyway, because the hand-written impl did, and its conversion to the sqlfunc macro kept those declarations. Dropping the pins lets the macro derive both flags as false from the `DatumMap` output, and the `output_type_expr` reports `nullable(false)`, leaving nullability to the unary tail. The registry reports `map_build_from_record_list` moving `introduces_nulls` and `could_error` from true to false and its output type from nullable to non-nullable. The current `LIR_VERSION` hasn't shipped, so the snapshots are regenerated in place. The sqllogictest shards passed on an earlier version of the stack that carried this change inside the `map.rs` conversion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e94c12d to
0d5fecd
Compare
…ro (#39062) Converts the remaining hand-written scalar functions to `#[sqlfunc]`, one commit per source file or function: the `Cast*ToNumeric` casts (`int16`, `int32`, `int64`, `uint16`, `uint32`, `uint64`, `float32`, `float64`, `jsonb`), `PadChar`, `AdjustNumericScale`, `CastArrayToString`, `CastRangeToString`, and all of `date.rs`, `time.rs`, `map.rs`, `record.rs`, `list.rs`, `timestamp.rs` and `string.rs`. Each commit message accounts for every method the deleted impl overrode. No declared property changes. The registry reports only the macro provenance fields moving. Where a hand-written impl declared a property more conservatively than the body needs, the conversion pins the declared value: `could_error` on `record_get`, and `introduces_nulls`, `could_error` and a nullable output on `map_build_from_record_list`. #39814 corrects both. Supersedes #39079 to #39097, which held one conversion each. Based on #39061. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
QA LLM Review (Post Merge)@antiguru — an automated review of commit 1. HIGH -- Narrowing
|
because the body always returns a map. The output type becomes the column type of every materialized view that calls `map_build`, and existing views pick up the narrowed type when the catalog re-derives their description on upgrade. A Kafka sink with Avro on such a view then regenerates its schema without the `null` branch, and a schema registry under its default BACKWARD compatibility rejects it, so the sink stalls. Iceberg sinks compare nullability exactly and fail the same way. This restores the nullable output and `introduces_nulls = true` and keeps `could_error = false`, which changes no column type. The registry reports `map_build_from_record_list` moving `introduces_nulls` back to true and its output type back to nullable, the declarations before MaterializeInc#39814. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#39814 narrowed `map_build`'s output type to NOT NULL. Existing materialized views that call `map_build` pick up the narrowed column type on upgrade, and a Kafka Avro sink on such a view then registers a schema the registry rejects as incompatible, which stalls the sink. The post-merge QA review on #39814 reproduced this against Redpanda's schema registry. This restores the nullable output and `introduces_nulls = true`, and keeps `could_error = false`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Two functions declared properties more conservatively than their bodies need, inherited from hand-written impls and kept by their conversion to
#[sqlfunc]in #39062. This drops the pins and lets the macro derive the properties from the output type.record_getreturns a field of its input record and never produces anEvalError, but it declaredcould_error = true, theLazyUnaryFuncdefault. It now derivesfalsefrom the non-Resultoutput.map_build_from_record_listskips NULL records and keys and always returns a map, but it declaredintroduces_nullsandcould_errortrue and a nullable output. Both flags now derivefalsefrom theDatumMapoutput, and the output type is non-nullable.The registry reports exactly these moves. The current
LIR_VERSIONhasn't shipped, so the snapshots are regenerated in place. The sqllogictest files that mentionrecord_getshow no plan changes, and the sqllogictest shards passed on an earlier version of the stack that carried themap_build_from_record_listchange.Based on #39105.
🤖 Generated with Claude Code