diff --git a/doc/developer/sqlfunc.md b/doc/developer/sqlfunc.md index d98d3e4e5c710..7ebce1785573b 100644 --- a/doc/developer/sqlfunc.md +++ b/doc/developer/sqlfunc.md @@ -1,10 +1,11 @@ # The `#[sqlfunc]` macro The `#[sqlfunc]` attribute macro generates boilerplate for SQL scalar functions. -It creates a unit struct, a trait implementation (`EagerUnaryFunc`, `EagerBinaryFunc`, or `EagerVariadicFunc`), and a `Display` impl from a plain Rust function. +From a plain Rust function it creates a trait implementation (`EagerUnaryFunc`, `EagerBinaryFunc`, or `EagerVariadicFunc`), a `FuncName` implementation, and, unless the function takes a `&self` receiver, the struct itself. +It also creates a `Display` implementation unless `skip_display` suppresses it. -The macro lives in `src/expr-derive-impl/src/sqlfunc.rs`. -The generated trait implementations live in `src/expr/src/scalar/func/{unary,binary,variadic}.rs`. +The macro lives in `src/expr-derive-impl/`, with its entry point in `sqlfunc.rs`. +The traits it implements are defined in `src/expr/src/scalar/func/{unary,binary,variadic}.rs`. ## Quick start @@ -28,12 +29,14 @@ This generates: The macro determines function arity from parameter count and types, after excluding `&self` receivers and trailing `&RowArena` parameters: -| Effective params | Dispatches to | Notes | -|---|---|---| -| 0 | Error | Nullary functions are not supported. | -| 1 | `EagerUnaryFunc` | Does not support `&RowArena`. | -| 2 | `EagerBinaryFunc` | Supports `&RowArena`. | -| 3+ | `EagerVariadicFunc` | Supports `&RowArena` and `&self`. | +| Effective params | Dispatches to | +|---|---| +| 0 | Error: nullary functions are not supported. | +| 1 | `EagerUnaryFunc` | +| 2 | `EagerBinaryFunc` | +| 3+ | `EagerVariadicFunc` | + +Every arity accepts a `&self` receiver and a trailing `&RowArena`. **Exception:** If any parameter uses `Variadic` or `OptionalArg`, the function is always treated as variadic, regardless of parameter count. @@ -56,14 +59,16 @@ The SQL-visible name of the function. * **Default:** the Rust function name (via `stringify!`) * **Applies to:** all arities +The generated `Display` impl is the only reader, so `skip_display = true` rejects `sqlname`. + ### `propagates_nulls` Whether a NULL input produces a NULL output, skipping the function body entirely. When true, the evaluation layer short-circuits on NULL inputs and returns NULL without calling the function. -This also affects `output_type`: if `propagates_nulls` is true and any input column is nullable, the output column is marked nullable. +This also affects the output column type: if `propagates_nulls` is true and any input column is nullable, the output column is marked nullable. * **Type:** boolean expression -* **Default:** inferred from input type — `!Input::nullable()`. +* **Default:** `!Input::nullable()`, inferred from the input type. If the input type accepts `Option` or `Datum` (which can represent NULL), it is nullable, so `propagates_nulls` defaults to `false`. If the input type is a non-nullable type like `&str` or `i32`, nulls are propagated (the function never sees them). * **Applies to:** binary, variadic @@ -75,11 +80,11 @@ Whether the function can produce NULL from non-NULL inputs. The optimizer uses this to reason about column nullability. * **Type:** boolean expression -* **Default:** inferred from output type — `Output::nullable()`. +* **Default:** `Output::nullable()`, inferred from the output type. A function returning `Option` or `Datum` introduces nulls. A function returning `String` or `i32` does not. * **Applies to:** all arities -* **Note:** required when using `output_type_expr` (because the output type is not statically known). +* **Note:** set it where the return type overstates it. A function returning `Datum` or `Option` that yields NULL only for NULL inputs declares `introduces_nulls = false`. ### `could_error` @@ -87,7 +92,7 @@ Whether the function can produce an error at runtime. The optimizer uses this to avoid certain rewrites that might change error behavior. * **Type:** boolean expression -* **Default:** inferred from output type — `Output::fallible()`. +* **Default:** `Output::fallible()`, inferred from the output type. A function returning `Result` is fallible. A function returning `T` directly is not. * **Applies to:** all arities @@ -122,16 +127,25 @@ Whether the function is injective: if `f(x) = f(y)` then `x = y`. The inverse function, if it exists. -* **Type:** expression evaluating to `Option` +* **Type:** expression convertible into `crate::UnaryFunc`, for example `inverse = NegFloat64` * **Default:** `None` * **Applies to:** unary only +### `is_eliminable_cast` + +Whether the function is a cast that does no work and only changes the tracked type. +Lowering drops such casts when `enable_cast_elimination` is on. + +* **Type:** boolean expression +* **Default:** `false` +* **Applies to:** unary only + ### `negate` The logical negation of a comparison function. For example, `<` negates to `>=`. -* **Type:** expression evaluating to `Option` +* **Type:** expression convertible into `crate::BinaryFunc`, for example `negate = NotEq` * **Default:** `None` * **Applies to:** binary only @@ -155,7 +169,7 @@ Whether the function is associative: `f(a, f(b, c)) = f(f(a, b), c)`. ### `output_type` An explicit type path for computing the output column type. -When set, the macro generates `output_type` and `introduces_nulls` based on this type instead of inferring from the return type. +When set, the output column type and the `introduces_nulls` default come from this type instead of the return type. * **Type:** type path (e.g., `i16`, `String`) * **Default:** inferred from return type via `Self::Output::as_column_type()` @@ -164,13 +178,14 @@ When set, the macro generates `output_type` and `introduces_nulls` based on this ### `output_type_expr` -An expression that computes the output column type at runtime. +An expression that computes the output column type when the expression is typed. +It can read `self` and the input column types, bound as `input_type` for unary functions and as `input_types` for binary and variadic ones. Use this for functions whose output type depends on input types or struct fields (e.g., `ArrayCreate` where the element type is stored on the struct). +The macro applies the nullability rules in [Null handling](#null-handling) on top of the expression's result. * **Type:** expression evaluating to `SqlColumnType` * **Default:** none * **Applies to:** all arities -* **Requires:** `introduces_nulls` (must be specified explicitly) * **Cannot be combined with:** `output_type` ### `test` @@ -181,32 +196,66 @@ Generate a snapshot test for the macro expansion. * **Default:** `false` * **Applies to:** all arities -Snapshot files are stored in `src/expr-derive-impl/src/snapshots/`. -Update them with `cargo insta accept` after running `cargo test -p mz-expr-derive-impl`. +The test is emitted next to the function, so its snapshot lands in the `snapshots/` directory beside the calling source file, for example `src/expr/src/scalar/func/snapshots/`. +Update it with `cargo insta accept` after running `cargo test -p mz-expr`. +The macro's own expansion tests live in `src/expr-derive-impl/src/test.rs`, with snapshots in `src/expr-derive-impl/src/snapshots/`. -Which modifiers apply to which arity is declared in -`src/expr-derive-impl/src/shape.rs`, one table per arity. A modifier absent from an -arity's table is rejected with an error naming both the modifier and the arity. +### `skip_display` -## Variadic functions +Suppresses the generated `Display` impl. +Use this when the displayed name depends on the struct's own state, so the call site keeps a hand-written `Display` impl. +`RangeCreate` is an example: it picks between `int4range`, `int8range`, `daterange`, `numrange`, `tsrange`, and `tstzrange` based on its `elem_type` field. +Setting it to `true` rejects `sqlname`, whose only reader is the suppressed impl, and requires a `&self` receiver, since a unit struct has no state to display. + +* **Type:** `bool` +* **Default:** `false` +* **Applies to:** all arities + +Which modifiers apply to which arity is declared in `src/expr-derive-impl/src/shape.rs`, one table per arity. +A modifier absent from an arity's table is rejected with an error naming both the modifier and the arity. + +## Generic type parameters + +A function can be generic over the element type of a container, for example `fn range_lower<'a, T>(a: Range) -> Option`. +The generated trait impl replaces each type parameter with `Datum<'a>`, because the parameters are not in scope there. +Without `output_type` or `output_type_expr`, the macro derives the output column type from where the first type parameter of the output appears among the inputs, through `mz_repr::SqlContainerType`: + +* Output `T` from an input container: the container's element type. +* Output `T` from an input `T`: that input's type. +* Output container from an input container: the input's element type, wrapped in the output container. + +Any other combination needs an explicit `output_type_expr`. +The derived type is nullable when the return type is an `Option`, which also sets the `introduces_nulls` default. +For binary and variadic functions, the derived expression soft-asserts that every input carrying the parameter agrees on its SQL type. + +## Generated items ### Struct name -For variadic functions, the struct name can be specified as the first positional argument. -This is required when a `&self` receiver is present (the struct is defined externally): +The struct name defaults to the camel-cased function name, and the first positional argument to the `sqlfunc` macro overrides it. +With a `&self` receiver the macro does not define the struct, so the name must match the one defined externally: ```rust -#[sqlfunc(ArrayFill, sqlname = "array_fill")] -fn array_fill_variadic<'a>(&self, fill: Datum<'a>, dims: Datum<'a>, temp_storage: &'a RowArena) -> Result, EvalError> { +#[sqlfunc( + ArrayFill, + output_type_expr = "SqlScalarType::Array(Box::new(self.elem_type.clone())).nullable(false)", + introduces_nulls = false +)] +fn array_fill<'a>( + &self, + fill: Datum<'a>, + dims: Option>, + lower_bounds: OptionalArg>>, + temp_storage: &'a RowArena, +) -> Result, EvalError> { // ... } ``` -Without a `&self` receiver, the struct name defaults to the camel-cased function name. -It can still be overridden with the first positional argument: +Without `&self`, the macro defines the struct under that name: ```rust -#[sqlfunc(Replace, sqlname = "replace")] +#[sqlfunc(Replace)] fn replace(text: &str, from: &str, to: &str) -> Result { // ... } @@ -217,11 +266,18 @@ fn replace(text: &str, from: &str, to: &str) -> Result { When a `&self` receiver is present, the macro assumes the struct is defined externally and generates: * A method `impl StructName { fn ... }` containing the function body. -* An `EagerVariadicFunc` trait implementation that delegates to the method. -* A `Display` implementation. +* The `Eager*Func` trait implementation for the function's arity, delegating to the method. +* A `Display` implementation, unless `skip_display` suppresses it. Without `&self`, the macro generates the struct itself (with standard derives) in addition to the trait and display implementations. +### `&RowArena` + +A trailing `&RowArena` parameter gives the function access to temporary storage for allocating return values that borrow from the arena. +It is excluded from arity detection and from the generated `Input` type. + +## Variadic functions + ### `Variadic` and `OptionalArg` These wrapper types affect both arity detection and null handling. @@ -249,14 +305,6 @@ fn pad_leading(string: &str, raw_len: i32, pad: OptionalArg<&str>) -> Result f32 { @@ -321,7 +372,7 @@ fn add_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result, EvalError> { ```rust #[sqlfunc(sqlname = "datediff")] fn date_diff_date(unit_str: &str, a: Date, b: Date) -> Result { - // Three fixed parameters → variadic with tuple input (&str, Date, Date) + // Three fixed parameters make it variadic, with tuple input (&str, Date, Date). } ``` @@ -330,7 +381,7 @@ fn date_diff_date(unit_str: &str, a: Date, b: Date) -> Result { ```rust #[sqlfunc(is_associative = true)] fn concat(strs: Variadic>) -> Result { - // Variadic detected → variadic dispatch regardless of parameter count + // A Variadic parameter makes it variadic regardless of parameter count. } ``` @@ -339,12 +390,28 @@ fn concat(strs: Variadic>) -> Result { ```rust #[sqlfunc( ArrayCreate, - sqlname = "array_create", - output_type_expr = "SqlScalarType::Array(Box::new(self.elem_type.clone())).nullable(false)", - introduces_nulls = false + output_type_expr = "SqlScalarType::Array(Box::new(self.elem_type.clone())).nullable(false)" )] fn array_create<'a>(&self, datums: Variadic>, temp_storage: &'a RowArena) -> Array<'a> { // &self: struct defined externally with an elem_type field // output_type_expr: output type depends on runtime struct fields } ``` + +## Shapes the macro does not cover + +Two shapes stay hand-written by design. + +* Functions generic over an `Eval` implementor, which hold sub-expressions in a `Box` + or a `Box<[E]>` and evaluate them per element. The macro would need to emit an + implementation generic over a struct type parameter with a trait bound, which is a + different mechanism from the type-parameter erasure it applies. The + `impl LazyUnaryFunc` blocks under `src/expr/src/scalar/func/impls/` are these. +* Functions that do not evaluate every operand. The macro emits `Eager*` + implementations, which evaluate all arguments before dispatch. `And`, `Or`, + `Coalesce`, `Greatest`, `Least`, `ErrorIfNull`, and `CaseLiteral` are these. + +Hand-written `LazyUnaryFunc` implementations under `src/expr/src/scalar/func/impls/` +outside both categories are convertible. One that allocates its output gets a +`RowArena` from `EagerUnaryFunc::call`, and `RecordGet`, which returns a field borrowed +from its input, needs only an `output_type_expr` reading `input_type`. diff --git a/src/catalog/tests/audit_log_details.rs b/src/catalog/tests/audit_log_details.rs index 2c172d8afe24b..90656850a64eb 100644 --- a/src/catalog/tests/audit_log_details.rs +++ b/src/catalog/tests/audit_log_details.rs @@ -26,6 +26,7 @@ use mz_audit_log::EventDetails; use mz_catalog::durable::objects::serialization::RustType; use mz_catalog_protos::objects::audit_log_event_v1; use mz_expr::func::{EagerUnaryFunc, ParseCatalogAuditLogDetails}; +use mz_repr::RowArena; use mz_repr::adt::jsonb::Jsonb; use proptest::prelude::*; @@ -42,8 +43,9 @@ proptest! { let proto_json = serde_json::to_value(&proto).expect("proto serializes"); let jsonb = Jsonb::from_serde_json(proto_json).expect("valid jsonb"); + let temp_storage = RowArena::new(); let got = ParseCatalogAuditLogDetails - .call(jsonb.as_ref()) + .call(jsonb.as_ref(), &temp_storage) .expect("helper succeeded"); let got_json = got.as_ref().to_serde_json(); diff --git a/src/catalog/tests/sql_parse_catalog.rs b/src/catalog/tests/sql_parse_catalog.rs index 9531021c3a929..e6e937efcf3f1 100644 --- a/src/catalog/tests/sql_parse_catalog.rs +++ b/src/catalog/tests/sql_parse_catalog.rs @@ -20,20 +20,25 @@ use mz_repr::adt::jsonb::Jsonb; use mz_repr::adt::mz_acl_item::{AclMode, MzAclItem}; use mz_repr::network_policy_id::NetworkPolicyId; use mz_repr::role_id::RoleId; -use mz_repr::{CatalogItemId, GlobalId}; +use mz_repr::{CatalogItemId, GlobalId, RowArena}; use mz_sql::names::{DatabaseId, SchemaId}; use proptest::prelude::*; fn serialize_and_parse_catalog_id(val: &impl serde::Serialize) -> String { let json = serde_json::to_value(val).unwrap(); let jsonb = Jsonb::from_serde_json(json).unwrap(); - ParseCatalogId.call(jsonb.as_ref()).unwrap() + let temp_storage = RowArena::new(); + ParseCatalogId.call(jsonb.as_ref(), &temp_storage).unwrap() } fn serialize_and_parse_catalog_privileges(val: &impl serde::Serialize) -> Vec { let json = serde_json::to_value(val).unwrap(); let jsonb = Jsonb::from_serde_json(json).unwrap(); - ParseCatalogPrivileges.call(jsonb.as_ref()).unwrap().0 + let temp_storage = RowArena::new(); + ParseCatalogPrivileges + .call(jsonb.as_ref(), &temp_storage) + .unwrap() + .0 } proptest! { diff --git a/src/compute-types/tests/snapshots/func_registry.json b/src/compute-types/tests/snapshots/func_registry.json index 40d22170943a0..1183451eb5914 100644 --- a/src/compute-types/tests/snapshots/func_registry.json +++ b/src/compute-types/tests/snapshots/func_registry.json @@ -619,7 +619,7 @@ "map_build": {"variant":"MapBuild","propagates_nulls":false,"introduces_nulls":false,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["String:NotNull","Int32:NotNull"],"output_type":"Map { value_type: Int32, custom_id: None }:NotNull","sqlfunc_signature":"fn(Variadic<(Option<&'a str>, Datum<'a>)>) -> Result, EvalError>"}, "or": {"variant":"Or","propagates_nulls":false,"introduces_nulls":false,"could_error":false,"is_monotone":true,"is_associative":true,"is_infix_op":true,"input_types":["Bool:NotNull","Bool:NotNull"],"output_type":"Bool:NotNull","sqlfunc_signature":null}, "pad_leading": {"variant":"PadLeading","propagates_nulls":true,"introduces_nulls":false,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["String:NotNull","Int32:NotNull","String:NotNull"],"output_type":"String:NotNull","sqlfunc_signature":"fn(&'a str, i32, OptionalArg<&'a str>) -> Result"}, - "range_create": {"variant":"RangeCreate","propagates_nulls":false,"introduces_nulls":false,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["Int32:NotNull","Int32:NotNull","String:NotNull"],"output_type":"Range { element_type: Int32 }:NotNull","sqlfunc_signature":null}, + "range_create": {"variant":"RangeCreate","propagates_nulls":false,"introduces_nulls":false,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["Int32:NotNull","Int32:NotNull","String:NotNull"],"output_type":"Range { element_type: Int32 }:NotNull","sqlfunc_signature":"fn(Datum<'a>, Datum<'a>, Datum<'a>) -> Result>, EvalError>"}, "record_create": {"variant":"RecordCreate","propagates_nulls":false,"introduces_nulls":false,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["Int32:NotNull"],"output_type":"Record { fields: [(ColumnName(\"a\"), SqlColumnType { scalar_type: Int32, nullable: false })], custom_id: None }:NotNull","sqlfunc_signature":"fn(Variadic>) -> Result, EvalError>"}, "regexp_match": {"variant":"RegexpMatch","propagates_nulls":true,"introduces_nulls":true,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["String:NotNull","String:NotNull","String:NotNull"],"output_type":"Array(String):Null","sqlfunc_signature":"fn(&'a str, &'a str, OptionalArg<&'a str>) -> Result, EvalError>"}, "regexp_replace": {"variant":"RegexpReplace","propagates_nulls":true,"introduces_nulls":false,"could_error":true,"is_monotone":false,"is_associative":false,"is_infix_op":false,"input_types":["String:NotNull","String:NotNull","String:NotNull","String:NotNull"],"output_type":"String:NotNull","sqlfunc_signature":"fn(&'a str, &'a str, &'a str, OptionalArg<&'a str>) -> Result, EvalError>"}, diff --git a/src/compute-types/tests/snapshots/func_registry_digests.json b/src/compute-types/tests/snapshots/func_registry_digests.json index 5f8d4a2116229..5b65a2e1f5c3e 100644 --- a/src/compute-types/tests/snapshots/func_registry_digests.json +++ b/src/compute-types/tests/snapshots/func_registry_digests.json @@ -1,3 +1,3 @@ { - "1": "sha256:6464d6eed984478e19c76a27b6cd2f5b86318b8fffabd73d0aa70d7f41a5db4b" + "1": "sha256:0c737bd1372e641b0c9f99554c078c77a33e225a2aa184eda1928a9a68a1a712" } diff --git a/src/compute-types/tests/snapshots/func_registry_source.json b/src/compute-types/tests/snapshots/func_registry_source.json index 413670921c869..e9c300fb36c5f 100644 --- a/src/compute-types/tests/snapshots/func_registry_source.json +++ b/src/compute-types/tests/snapshots/func_registry_source.json @@ -18,10 +18,10 @@ "age_timestamp": {"display":"age","sqlfunc_decl":"#[sqlfunc(sqlname = \"age\")] fn age_timestamp(a: CheckedTimestamp, b: CheckedTimestamp,) -> Result","body_fingerprint":"d5c8b6d58dc02ca0"}, "age_timestamp_tz": {"display":"age","sqlfunc_decl":"#[sqlfunc(sqlname = \"age\")] fn age_timestamp_tz(a: CheckedTimestamp>, b: CheckedTimestamp>,) -> Result","body_fingerprint":"d5c8b6d58dc02ca0"}, "array_array_concat": {"display":"||","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.without_modifiers().nullable(true)\", is_infix_op = true, sqlname = \"||\", propagates_nulls = false, introduces_nulls = false)] fn array_array_concat<'a>(a: Option>, b: Option>, temp_storage: &'a RowArena,) -> Result>, EvalError>","body_fingerprint":"9ff9a14b971a8019"}, - "array_contains": {"display":"array_contains","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"array_contains\", propagates_nulls = true, introduces_nulls = false)] fn array_contains<'a>(a: Datum<'a>, array: Array<'a>) -> bool","body_fingerprint":"258f7d3f3cd6573f"}, + "array_contains": {"display":"array_contains","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"array_contains\", propagates_nulls = true)] fn array_contains<'a>(a: Datum<'a>, array: Array<'a>) -> bool","body_fingerprint":"258f7d3f3cd6573f"}, "array_contains_array": {"display":"@>","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"@>\")] fn array_contains_array<'a>(a: Array<'a>, b: Array<'a>) -> bool","body_fingerprint":"f4c8b92bc69598c5"}, "array_contains_array_rev": {"display":"<@","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"<@\")] fn array_contains_array_rev<'a>(a: Array<'a>, b: Array<'a>) -> bool","body_fingerprint":"c3e1b66a36e33dea"}, - "array_length": {"display":"array_length","sqlfunc_decl":"#[sqlfunc(sqlname = \"array_length\", propagates_nulls = true, introduces_nulls = true)] fn array_length<'a>(a: Array<'a>, b: i64) -> Result, EvalError>","body_fingerprint":"511a574b8b3ab56a"}, + "array_length": {"display":"array_length","sqlfunc_decl":"#[sqlfunc(sqlname = \"array_length\", propagates_nulls = true)] fn array_length<'a>(a: Array<'a>, b: i64) -> Result, EvalError>","body_fingerprint":"511a574b8b3ab56a"}, "array_lower": {"display":"array_lower","sqlfunc_decl":"#[sqlfunc(is_infix_op = true)] fn array_lower<'a>(a: Array<'a>, i: i64) -> Result, EvalError>","body_fingerprint":"fa2b8d3be6005650"}, "array_remove": {"display":"array_remove","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.without_modifiers().nullable(true)\", sqlname = \"array_remove\", propagates_nulls = false, introduces_nulls = false)] fn array_remove<'a>(arr: Array<'a>, b: Datum<'a>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"f8e91dd54724c5e7"}, "array_upper": {"display":"array_upper","sqlfunc_decl":"#[sqlfunc(is_infix_op = true)] fn array_upper<'a>(a: Array<'a>, i: i64) -> Result, EvalError>","body_fingerprint":"8aac123bc3861c38"}, @@ -60,10 +60,10 @@ "convert_from": {"display":"convert_from","sqlfunc_decl":"#[sqlfunc(sqlname = \"convert_from\", propagates_nulls = true)] fn convert_from<'a>(a: &'a[u8], b: &str) -> Result<&'a str, EvalError>","body_fingerprint":"6854417075f37414"}, "date_bin_timestamp": {"display":"bin_unix_epoch_timestamp","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(false, true)\", sqlname = \"bin_unix_epoch_timestamp\")] fn date_bin_timestamp(stride: Interval, source: CheckedTimestamp,) -> Result, EvalError>","body_fingerprint":"810678cf4587a7d7"}, "date_bin_timestamp_tz": {"display":"bin_unix_epoch_timestamptz","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(false, true)\", sqlname = \"bin_unix_epoch_timestamptz\")] fn date_bin_timestamp_tz(stride: Interval, source: CheckedTimestamp>,) -> Result>, EvalError>","body_fingerprint":"de4ceb358cd8ed50"}, - "date_part_interval_f64": {"display":"date_partiv","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_partiv\", propagates_nulls = true, introduces_nulls = false)] fn date_part_interval_f64(units: &str, b: Interval) -> Result","body_fingerprint":"ee191a869c785c4d"}, - "date_part_interval_numeric": {"display":"extractiv","sqlfunc_decl":"#[sqlfunc(sqlname = \"extractiv\", propagates_nulls = true, introduces_nulls = false)] fn date_part_interval_numeric(units: &str, b: Interval) -> Result","body_fingerprint":"5a0c19540e3d27b2"}, - "date_part_time_f64": {"display":"date_partt","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_partt\", propagates_nulls = true, introduces_nulls = false)] fn date_part_time_f64(units: &str, b: chrono::NaiveTime) -> Result","body_fingerprint":"4f0e87bfd219ac4d"}, - "date_part_time_numeric": {"display":"extractt","sqlfunc_decl":"#[sqlfunc(sqlname = \"extractt\", propagates_nulls = true, introduces_nulls = false)] fn date_part_time_numeric(units: &str, b: chrono::NaiveTime) -> Result","body_fingerprint":"84ebc563755b77b2"}, + "date_part_interval_f64": {"display":"date_partiv","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_partiv\", propagates_nulls = true)] fn date_part_interval_f64(units: &str, b: Interval) -> Result","body_fingerprint":"ee191a869c785c4d"}, + "date_part_interval_numeric": {"display":"extractiv","sqlfunc_decl":"#[sqlfunc(sqlname = \"extractiv\", propagates_nulls = true)] fn date_part_interval_numeric(units: &str, b: Interval) -> Result","body_fingerprint":"5a0c19540e3d27b2"}, + "date_part_time_f64": {"display":"date_partt","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_partt\", propagates_nulls = true)] fn date_part_time_f64(units: &str, b: chrono::NaiveTime) -> Result","body_fingerprint":"4f0e87bfd219ac4d"}, + "date_part_time_numeric": {"display":"extractt","sqlfunc_decl":"#[sqlfunc(sqlname = \"extractt\", propagates_nulls = true)] fn date_part_time_numeric(units: &str, b: chrono::NaiveTime) -> Result","body_fingerprint":"84ebc563755b77b2"}, "date_part_timestamp_timestamp_f64": {"display":"date_partts","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_partts\", propagates_nulls = true)] fn date_part_timestamp_timestamp_f64(units: &str, ts: CheckedTimestamp,) -> Result","body_fingerprint":"64042d92ba3d53b5"}, "date_part_timestamp_timestamp_numeric": {"display":"extractts","sqlfunc_decl":"#[sqlfunc(sqlname = \"extractts\", propagates_nulls = true)] fn date_part_timestamp_timestamp_numeric(units: &str, ts: CheckedTimestamp,) -> Result","body_fingerprint":"6d7cba6f9bedfe2d"}, "date_part_timestamp_timestamp_tz_f64": {"display":"date_parttstz","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_parttstz\", propagates_nulls = true)] fn date_part_timestamp_timestamp_tz_f64(units: &str, ts: CheckedTimestamp>,) -> Result","body_fingerprint":"64042d92ba3d53b5"}, @@ -87,12 +87,12 @@ "element_list_concat": {"display":"||","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"||\", propagates_nulls = false)] fn element_list_concat<'a, T: FromDatum<'a>>(a: T, b: Option>, temp_storage: &'a RowArena,) -> DatumList<'a, T>","body_fingerprint":"74d5291ced5c8c85"}, "encode": {"display":"encode","sqlfunc_decl":"#[sqlfunc] fn encode(bytes: &[u8], format: &str) -> Result","body_fingerprint":"386a66d9b57c930f"}, "encoded_bytes_char_length": {"display":"length","sqlfunc_decl":"#[sqlfunc(sqlname = \"length\", propagates_nulls = true)] fn encoded_bytes_char_length(a: &[u8], b: &str) -> Result","body_fingerprint":"00dd505df65ef857"}, - "eq": {"display":"=","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"=\", negate = \"Some(NotEq.into())\")] fn eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"a0737efed3c5645e"}, + "eq": {"display":"=","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"=\", negate = NotEq)] fn eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"a0737efed3c5645e"}, "extract_date_units": {"display":"extractd","sqlfunc_decl":"#[sqlfunc(sqlname = \"extractd\", propagates_nulls = true)] fn extract_date_units(units: &str, b: Date) -> Result","body_fingerprint":"552752eb53e25f38"}, "get_bit": {"display":"get_bit","sqlfunc_decl":"#[sqlfunc(propagates_nulls = true)] fn get_bit(bytes: &[u8], index: i32) -> Result","body_fingerprint":"2c27c6d616894079"}, "get_byte": {"display":"get_byte","sqlfunc_decl":"#[sqlfunc(propagates_nulls = true)] fn get_byte(bytes: &[u8], index: i32) -> Result","body_fingerprint":"dc6519b277087f72"}, - "gt": {"display":">","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \">\", negate = \"Some(Lte.into())\")] fn gt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"440733ba035333f6"}, - "gte": {"display":">=","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \">=\", negate = \"Some(Lt.into())\")] fn gte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"88cc442a3f88c691"}, + "gt": {"display":">","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \">\", negate = Lte)] fn gt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"440733ba035333f6"}, + "gte": {"display":">=","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \">=\", negate = Lt)] fn gte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"88cc442a3f88c691"}, "is_like_match_case_insensitive": {"display":"ilike","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"ilike\")] fn is_like_match_case_insensitive(haystack: &str, pattern: &str) -> Result","body_fingerprint":"b81302ce9602899f"}, "is_like_match_case_sensitive": {"display":"like","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"like\")] fn is_like_match_case_sensitive(haystack: &str, pattern: &str) -> Result","body_fingerprint":"b0ccd689977c372e"}, "is_regexp_match_case_insensitive": {"display":"~*","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"~*\")] fn is_regexp_match_case_insensitive(haystack: &str, needle: &str) -> Result","body_fingerprint":"5882540ca41af87c"}, @@ -100,8 +100,8 @@ "jsonb_concat": {"display":"||","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"||\")] fn jsonb_concat<'a>(a: JsonbRef<'a>, b: JsonbRef<'a>, temp_storage: &'a RowArena,) -> Option>","body_fingerprint":"5c7d5752a10e5eb1"}, "jsonb_contains_jsonb": {"display":"@>","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"@>\")] fn jsonb_contains_jsonb<'a>(a: JsonbRef<'a>, b: JsonbRef<'a>) -> bool","body_fingerprint":"eb83b3a7d21cc242"}, "jsonb_contains_string": {"display":"?","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"?\")] fn jsonb_contains_string<'a>(a: JsonbRef<'a>, k: &str) -> bool","body_fingerprint":"4256b57e7bb85cda"}, - "jsonb_delete_int64": {"display":"-","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Jsonb.nullable(true)\", is_infix_op = true, sqlname = \"-\", propagates_nulls = true, introduces_nulls = true)] fn jsonb_delete_int64<'a>(a: Datum<'a>, i: i64, temp_storage: &'a RowArena) -> Datum<'a>","body_fingerprint":"e52af4297083a865"}, - "jsonb_delete_string": {"display":"-","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Jsonb.nullable(true)\", is_infix_op = true, sqlname = \"-\", propagates_nulls = true, introduces_nulls = true)] fn jsonb_delete_string<'a>(a: Datum<'a>, k: &str, temp_storage: &'a RowArena) -> Datum<'a>","body_fingerprint":"1db9bcb86d8fbd17"}, + "jsonb_delete_int64": {"display":"-","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Jsonb.nullable(true)\", is_infix_op = true, sqlname = \"-\", propagates_nulls = true)] fn jsonb_delete_int64<'a>(a: Datum<'a>, i: i64, temp_storage: &'a RowArena) -> Datum<'a>","body_fingerprint":"e52af4297083a865"}, + "jsonb_delete_string": {"display":"-","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Jsonb.nullable(true)\", is_infix_op = true, sqlname = \"-\", propagates_nulls = true)] fn jsonb_delete_string<'a>(a: Datum<'a>, k: &str, temp_storage: &'a RowArena) -> Datum<'a>","body_fingerprint":"1db9bcb86d8fbd17"}, "jsonb_get_int64": {"display":"->","sqlfunc_decl":"#[sqlfunc(sqlname = \"->\", is_infix_op = true)] fn jsonb_get_int64<'a>(a: JsonbRef<'a>, i: i64) -> Option>","body_fingerprint":"f12db52366cb6a1a"}, "jsonb_get_int64_stringify": {"display":"->>","sqlfunc_decl":"#[sqlfunc(sqlname = \"->>\", is_infix_op = true)] fn jsonb_get_int64_stringify<'a>(a: JsonbRef<'a>, i: i64, temp_storage: &'a RowArena,) -> Option<&'a str>","body_fingerprint":"4a3fe3f77f2f86f9"}, "jsonb_get_path": {"display":"#>","sqlfunc_decl":"#[sqlfunc(sqlname = \"#>\", is_infix_op = true)] fn jsonb_get_path<'a>(mut json: JsonbRef<'a>, b: Array<'a>) -> Option>","body_fingerprint":"d6e238bc2cb523f6"}, @@ -109,7 +109,7 @@ "jsonb_get_string": {"display":"->","sqlfunc_decl":"#[sqlfunc(sqlname = \"->\", is_infix_op = true)] fn jsonb_get_string<'a>(a: JsonbRef<'a>, k: &str) -> Option>","body_fingerprint":"2c6b71b287aac9c7"}, "jsonb_get_string_stringify": {"display":"->>","sqlfunc_decl":"#[sqlfunc(sqlname = \"->>\", is_infix_op = true)] fn jsonb_get_string_stringify<'a>(a: JsonbRef<'a>, k: &str, temp_storage: &'a RowArena,) -> Option<&'a str>","body_fingerprint":"7f27a524571dc983"}, "left": {"display":"left","sqlfunc_decl":"#[sqlfunc(propagates_nulls = true, is_monotone = (false, false))] fn left<'a>(string: &'a str, b: i32) -> Result<&'a str, EvalError>","body_fingerprint":"01be9696c362dfc9"}, - "like_escape": {"display":"like_escape","sqlfunc_decl":"#[sqlfunc(propagates_nulls = true, introduces_nulls = false)] fn like_escape<'a>(pattern: &str, b: &str, temp_storage: &'a RowArena,) -> Result<&'a str, EvalError>","body_fingerprint":"761f2691cbcaee5c"}, + "like_escape": {"display":"like_escape","sqlfunc_decl":"#[sqlfunc(propagates_nulls = true)] fn like_escape<'a>(pattern: &str, b: &str, temp_storage: &'a RowArena,) -> Result<&'a str, EvalError>","body_fingerprint":"761f2691cbcaee5c"}, "list_contains_list": {"display":"@>","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"@>\")] fn list_contains_list<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"9b911bace0fe1e31"}, "list_contains_list_rev": {"display":"<@","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"<@\")] fn list_contains_list_rev<'a>(a: ExcludeNull>, b: ExcludeNull>,) -> bool","body_fingerprint":"1317829caf34be82"}, "list_element_concat": {"display":"||","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"||\", propagates_nulls = false)] fn list_element_concat<'a, T: FromDatum<'a>>(a: Option>, b: T, temp_storage: &'a RowArena,) -> DatumList<'a, T>","body_fingerprint":"71fed4e933e22e71"}, @@ -117,8 +117,8 @@ "list_list_concat": {"display":"||","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"||\", propagates_nulls = false, introduces_nulls = false)] fn list_list_concat<'a, T: FromDatum<'a>>(a: Option>, b: Option>, temp_storage: &'a RowArena,) -> Option>","body_fingerprint":"8e64667161369169"}, "list_remove": {"display":"list_remove","sqlfunc_decl":"#[sqlfunc(sqlname = \"list_remove\")] fn list_remove<'a, T: FromDatum<'a>>(a: DatumList<'a, T>, b: T, temp_storage: &'a RowArena,) -> DatumList<'a, T>","body_fingerprint":"685cdd219b48e8fb"}, "log_base_numeric": {"display":"log","sqlfunc_decl":"#[sqlfunc(sqlname = \"log\", propagates_nulls = true)] fn log_base_numeric(mut a: Numeric, mut b: Numeric) -> Result","body_fingerprint":"34396d686148c173"}, - "lt": {"display":"<","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \"<\", negate = \"Some(Gte.into())\")] fn lt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"33e35c6214c55a46"}, - "lte": {"display":"<=","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \"<=\", negate = \"Some(Gt.into())\")] fn lte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"9662e0716e38349f"}, + "lt": {"display":"<","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \"<\", negate = Gte)] fn lt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"33e35c6214c55a46"}, + "lte": {"display":"<=","sqlfunc_decl":"#[sqlfunc(is_monotone = \"(true, true)\", is_infix_op = true, sqlname = \"<=\", negate = Gt)] fn lte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"9662e0716e38349f"}, "map_contains_all_keys": {"display":"?&","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"?&\")] fn map_contains_all_keys<'a>(map: DatumMap<'a>, keys: Array<'a>) -> bool","body_fingerprint":"098fa1816021b8c9"}, "map_contains_any_keys": {"display":"?|","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"?|\", propagates_nulls = true)] fn map_contains_any_keys<'a>(map: DatumMap<'a>, keys: Array<'a>) -> bool","body_fingerprint":"99dd5d1bde4e90ea"}, "map_contains_key": {"display":"?","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"?\", propagates_nulls = true)] fn map_contains_key<'a>(map: DatumMap<'a>, k: &str) -> bool","body_fingerprint":"a3c666058c532732"}, @@ -146,7 +146,7 @@ "mz_acl_item_contains_privilege": {"display":"mz_aclitem_contains_privilege","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_aclitem_contains_privilege\", output_type = \"bool\", propagates_nulls = true)] fn mz_acl_item_contains_privilege(mz_acl_item: MzAclItem, privileges: &str,) -> Result","body_fingerprint":"da42b543c89f25ee"}, "mz_render_typmod": {"display":"mz_render_typmod","sqlfunc_decl":"#[sqlfunc] fn mz_render_typmod(oid: u32, typmod: i32) -> String","body_fingerprint":"c59c5905a68081a1"}, "normalize": {"display":"normalize","sqlfunc_decl":"#[sqlfunc] fn normalize(text: &str, form_str: &str) -> Result","body_fingerprint":"5c7622700646707b"}, - "not_eq": {"display":"!=","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"!=\", negate = \"Some(Eq.into())\")] fn not_eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"3c0c1af3605d6148"}, + "not_eq": {"display":"!=","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"!=\", negate = Eq)] fn not_eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool","body_fingerprint":"3c0c1af3605d6148"}, "parse_ident": {"display":"parse_ident","sqlfunc_decl":"#[sqlfunc] fn parse_ident<'a>(ident: &'a str, strict: bool) -> Result>, EvalError>","body_fingerprint":"3c1a3ead179e37f1"}, "position": {"display":"position","sqlfunc_decl":"#[sqlfunc] fn position(substring: &str, string: &str) -> Result","body_fingerprint":"b795aa808765e4f6"}, "power": {"display":"power","sqlfunc_decl":"#[sqlfunc(propagates_nulls = true)] fn power(a: f64, b: f64) -> Result","body_fingerprint":"2456483c2b457bdb"}, @@ -169,7 +169,7 @@ "range_contains_timestamp_rev": {"display":"<@","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"<@\", propagates_nulls = true)] fn range_contains_timestamp_rev<'a>(a: Range>, elem: CheckedTimestamp,) -> bool","body_fingerprint":"753872bbc33a41f9"}, "range_contains_timestamp_tz": {"display":"@>","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"@>\", propagates_nulls = true)] fn range_contains_timestamp_tz<'a>(a: Range>, elem: CheckedTimestamp>,) -> bool","body_fingerprint":"753872bbc33a41f9"}, "range_contains_timestamp_tz_rev": {"display":"<@","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"<@\", propagates_nulls = true)] fn range_contains_timestamp_tz_rev<'a>(a: Range>, elem: CheckedTimestamp>,) -> bool","body_fingerprint":"753872bbc33a41f9"}, - "range_difference": {"display":"-","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.without_modifiers().nullable(true)\", is_infix_op = true, sqlname = \"-\", propagates_nulls = true, introduces_nulls = false)] fn range_difference<'a>(l: Range>, r: Range>,) -> Result>, EvalError>","body_fingerprint":"9e565b1aa199a975"}, + "range_difference": {"display":"-","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.without_modifiers().nullable(true)\", is_infix_op = true, sqlname = \"-\", propagates_nulls = true)] fn range_difference<'a>(l: Range>, r: Range>,) -> Result>, EvalError>","body_fingerprint":"9e565b1aa199a975"}, "range_intersection": {"display":"*","sqlfunc_decl":"#[sqlfunc(is_infix_op = true, sqlname = \"*\")] fn range_intersection(l: Range, r: Range) -> Range","body_fingerprint":"03b9790d658da21d"}, "range_overlaps": {"display":"&&","sqlfunc_decl":"#[sqlfunc(output_type = \"bool\", is_infix_op = true, sqlname = \"&&\", propagates_nulls = true)] fn range_overlaps<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>","body_fingerprint":"fa1814e86cee0aef"}, "range_overleft": {"display":"&<","sqlfunc_decl":"#[sqlfunc(output_type = \"bool\", is_infix_op = true, sqlname = \"&<\", propagates_nulls = true)] fn range_overleft<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>","body_fingerprint":"46a271100deeb160"}, @@ -238,91 +238,91 @@ "bit_count_bytes": {"display":"bit_count","sqlfunc_decl":"#[sqlfunc(sqlname = \"bit_count\")] fn bit_count_bytes<'a>(a: &'a[u8]) -> Result","body_fingerprint":"5f7403bf914230df"}, "bit_length_bytes": {"display":"bit_length","sqlfunc_decl":"#[sqlfunc(sqlname = \"bit_length\")] fn bit_length_bytes<'a>(a: &'a[u8]) -> Result","body_fingerprint":"52e45f0cc4320f34"}, "bit_length_string": {"display":"bit_length","sqlfunc_decl":"#[sqlfunc(sqlname = \"bit_length\")] fn bit_length_string<'a>(a: &'a str) -> Result","body_fingerprint":"2c1bd580cf4dff9a"}, - "bit_not_int16": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = to_unary!(BitNotInt16))] fn bit_not_int16(a: i16) -> i16","body_fingerprint":"de26b65a3695fb67"}, - "bit_not_int32": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = to_unary!(BitNotInt32))] fn bit_not_int32(a: i32) -> i32","body_fingerprint":"de26b65a3695fb67"}, - "bit_not_int64": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = to_unary!(BitNotInt64))] fn bit_not_int64(a: i64) -> i64","body_fingerprint":"de26b65a3695fb67"}, - "bit_not_uint16": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = to_unary!(super::BitNotUint16))] fn bit_not_uint16(a: u16) -> u16","body_fingerprint":"de26b65a3695fb67"}, - "bit_not_uint32": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = to_unary!(super::BitNotUint32))] fn bit_not_uint32(a: u32) -> u32","body_fingerprint":"de26b65a3695fb67"}, - "bit_not_uint64": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = to_unary!(super::BitNotUint64))] fn bit_not_uint64(a: u64) -> u64","body_fingerprint":"de26b65a3695fb67"}, + "bit_not_int16": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = BitNotInt16)] fn bit_not_int16(a: i16) -> i16","body_fingerprint":"de26b65a3695fb67"}, + "bit_not_int32": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = BitNotInt32)] fn bit_not_int32(a: i32) -> i32","body_fingerprint":"de26b65a3695fb67"}, + "bit_not_int64": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = BitNotInt64)] fn bit_not_int64(a: i64) -> i64","body_fingerprint":"de26b65a3695fb67"}, + "bit_not_uint16": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = super::BitNotUint16)] fn bit_not_uint16(a: u16) -> u16","body_fingerprint":"de26b65a3695fb67"}, + "bit_not_uint32": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = super::BitNotUint32)] fn bit_not_uint32(a: u32) -> u32","body_fingerprint":"de26b65a3695fb67"}, + "bit_not_uint64": {"display":"~","sqlfunc_decl":"#[sqlfunc(sqlname = \"~\", preserves_uniqueness = true, inverse = super::BitNotUint64)] fn bit_not_uint64(a: u64) -> u64","body_fingerprint":"de26b65a3695fb67"}, "byte_length_bytes": {"display":"octet_length","sqlfunc_decl":"#[sqlfunc(sqlname = \"octet_length\")] fn byte_length_bytes<'a>(a: &'a[u8]) -> Result","body_fingerprint":"792df15254a6dd62"}, "byte_length_string": {"display":"octet_length","sqlfunc_decl":"#[sqlfunc(sqlname = \"octet_length\")] fn byte_length_string<'a>(a: &'a str) -> Result","body_fingerprint":"b0e2845f0e625884"}, "cast_array_to_array": {"display":"arraytoarray","sqlfunc_decl":null,"body_fingerprint":null}, "cast_array_to_jsonb": {"display":"arraytojsonb","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_array_to_list_one_dim": {"display":"arraytolist","sqlfunc_decl":"#[sqlfunc(sqlname = \"arraytolist\", introduces_nulls = false)] fn cast_array_to_list_one_dim<'a, T>(a: Array<'a, T>) -> Result, EvalError>","body_fingerprint":"62ae04042cf94d79"}, + "cast_array_to_list_one_dim": {"display":"arraytolist","sqlfunc_decl":"#[sqlfunc(sqlname = \"arraytolist\")] fn cast_array_to_list_one_dim<'a, T>(a: Array<'a, T>) -> Result, EvalError>","body_fingerprint":"62ae04042cf94d79"}, "cast_array_to_string": {"display":"arraytostr","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_bool_to_int32": {"display":"boolean_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToBool), is_monotone = true)] fn cast_bool_to_int32(a: bool) -> i32","body_fingerprint":"593c44fb5565e5fd"}, - "cast_bool_to_int64": {"display":"boolean_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToBool), is_monotone = true)] fn cast_bool_to_int64(a: bool) -> i64","body_fingerprint":"593c44fb5565e5fd"}, - "cast_bool_to_string": {"display":"boolean_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToBool), is_monotone = true)] fn cast_bool_to_string<'a>(a: bool) -> &'a str","body_fingerprint":"c7aac8105dc5f1c7"}, - "cast_bool_to_string_nonstandard": {"display":"boolean_to_nonstandard_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_nonstandard_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToBool), is_monotone = true)] fn cast_bool_to_string_nonstandard<'a>(a: bool) -> &'a str","body_fingerprint":"d01277a32fb3a68d"}, - "cast_bytes_to_string": {"display":"bytea_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"bytea_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToBytes))] fn cast_bytes_to_string(a: &[u8]) -> String","body_fingerprint":"358eaa033dcd2a74"}, - "cast_char_to_string": {"display":"char_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"char_to_text\", preserves_uniqueness = true, is_eliminable_cast = true, inverse = to_unary!(super::CastStringToChar {length: None, fail_on_len: false,}))] fn cast_char_to_string<'a>(a: Char<&'a str>) -> &'a str","body_fingerprint":"ba6f1e61cfed1bde"}, + "cast_bool_to_int32": {"display":"boolean_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToBool, is_monotone = true)] fn cast_bool_to_int32(a: bool) -> i32","body_fingerprint":"593c44fb5565e5fd"}, + "cast_bool_to_int64": {"display":"boolean_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToBool, is_monotone = true)] fn cast_bool_to_int64(a: bool) -> i64","body_fingerprint":"593c44fb5565e5fd"}, + "cast_bool_to_string": {"display":"boolean_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_text\", preserves_uniqueness = true, inverse = super::CastStringToBool, is_monotone = true)] fn cast_bool_to_string<'a>(a: bool) -> &'a str","body_fingerprint":"c7aac8105dc5f1c7"}, + "cast_bool_to_string_nonstandard": {"display":"boolean_to_nonstandard_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"boolean_to_nonstandard_text\", preserves_uniqueness = true, inverse = super::CastStringToBool, is_monotone = true)] fn cast_bool_to_string_nonstandard<'a>(a: bool) -> &'a str","body_fingerprint":"d01277a32fb3a68d"}, + "cast_bytes_to_string": {"display":"bytea_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"bytea_to_text\", preserves_uniqueness = true, inverse = super::CastStringToBytes)] fn cast_bytes_to_string(a: &[u8]) -> String","body_fingerprint":"358eaa033dcd2a74"}, + "cast_char_to_string": {"display":"char_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"char_to_text\", preserves_uniqueness = true, is_eliminable_cast = true, inverse = super::CastStringToChar {length: None, fail_on_len: false,})] fn cast_char_to_string<'a>(a: Char<&'a str>) -> &'a str","body_fingerprint":"ba6f1e61cfed1bde"}, "cast_date_to_mz_timestamp": {"display":"date_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_to_mz_timestamp\", preserves_uniqueness = true, is_monotone = true)] fn cast_date_to_mz_timestamp(a: Date) -> Result","body_fingerprint":"a3e1799a8f942589"}, - "cast_date_to_string": {"display":"date_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToDate))] fn cast_date_to_string(a: Date) -> String","body_fingerprint":"cb0468f6ec8a742b"}, + "cast_date_to_string": {"display":"date_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"date_to_text\", preserves_uniqueness = true, inverse = super::CastStringToDate)] fn cast_date_to_string(a: Date) -> String","body_fingerprint":"cb0468f6ec8a742b"}, "cast_date_to_timestamp": {"display":"date_to_timestamp","sqlfunc_decl":null,"body_fingerprint":null}, "cast_date_to_timestamp[precision]": {"display":"date_to_timestamp","sqlfunc_decl":null,"body_fingerprint":null}, "cast_date_to_timestamp_tz": {"display":"date_to_timestamp_with_timezone","sqlfunc_decl":null,"body_fingerprint":null}, "cast_date_to_timestamp_tz[precision]": {"display":"date_to_timestamp_with_timezone","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_float32_to_float64": {"display":"real_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_double\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToFloat32), is_monotone = true)] fn cast_float32_to_float64(a: f32) -> f64","body_fingerprint":"bc3f020571556877"}, - "cast_float32_to_int16": {"display":"real_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_smallint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt16ToFloat32), is_monotone = true)] fn cast_float32_to_int16(a: f32) -> Result","body_fingerprint":"a61b0421f5cc5491"}, - "cast_float32_to_int32": {"display":"real_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_integer\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt32ToFloat32), is_monotone = true)] fn cast_float32_to_int32(a: f32) -> Result","body_fingerprint":"2c382a851af2f38d"}, - "cast_float32_to_int64": {"display":"real_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_bigint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt64ToFloat32), is_monotone = true)] fn cast_float32_to_int64(a: f32) -> Result","body_fingerprint":"80675472dd05ab57"}, + "cast_float32_to_float64": {"display":"real_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_double\", preserves_uniqueness = false, inverse = super::CastFloat64ToFloat32, is_monotone = true)] fn cast_float32_to_float64(a: f32) -> f64","body_fingerprint":"bc3f020571556877"}, + "cast_float32_to_int16": {"display":"real_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_smallint\", preserves_uniqueness = false, inverse = super::CastInt16ToFloat32, is_monotone = true)] fn cast_float32_to_int16(a: f32) -> Result","body_fingerprint":"a61b0421f5cc5491"}, + "cast_float32_to_int32": {"display":"real_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_integer\", preserves_uniqueness = false, inverse = super::CastInt32ToFloat32, is_monotone = true)] fn cast_float32_to_int32(a: f32) -> Result","body_fingerprint":"2c382a851af2f38d"}, + "cast_float32_to_int64": {"display":"real_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_bigint\", preserves_uniqueness = false, inverse = super::CastInt64ToFloat32, is_monotone = true)] fn cast_float32_to_int64(a: f32) -> Result","body_fingerprint":"80675472dd05ab57"}, "cast_float32_to_numeric": {"display":"real_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_float32_to_numeric[scale]": {"display":"real_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_float32_to_string": {"display":"real_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_text\", preserves_uniqueness = false, inverse = to_unary!(super::CastStringToFloat32))] fn cast_float32_to_string(a: f32) -> String","body_fingerprint":"afb99469117094e4"}, - "cast_float32_to_uint16": {"display":"real_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_uint2\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint16ToFloat32), is_monotone = true)] fn cast_float32_to_uint16(a: f32) -> Result","body_fingerprint":"f6e8bfea3622de5c"}, - "cast_float32_to_uint32": {"display":"real_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_uint4\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint32ToFloat32), is_monotone = true)] fn cast_float32_to_uint32(a: f32) -> Result","body_fingerprint":"69f3d9020edb4fb3"}, - "cast_float32_to_uint64": {"display":"real_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_uint8\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint64ToFloat32), is_monotone = true)] fn cast_float32_to_uint64(a: f32) -> Result","body_fingerprint":"adde45c7e5b5b59c"}, - "cast_float64_to_float32": {"display":"double_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToFloat64), is_monotone = true)] fn cast_float64_to_float32(a: f64) -> Result","body_fingerprint":"3f343e5a91c3f24a"}, - "cast_float64_to_int16": {"display":"double_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_smallint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt16ToFloat64), is_monotone = true)] fn cast_float64_to_int16(a: f64) -> Result","body_fingerprint":"7b6999b1278d8e02"}, - "cast_float64_to_int32": {"display":"double_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_integer\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt32ToFloat64), is_monotone = true)] fn cast_float64_to_int32(a: f64) -> Result","body_fingerprint":"3e35668ff852238a"}, - "cast_float64_to_int64": {"display":"f64toi64","sqlfunc_decl":"#[sqlfunc(sqlname = \"f64toi64\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt64ToFloat64), is_monotone = true)] fn cast_float64_to_int64(a: f64) -> Result","body_fingerprint":"eff404954eb17e94"}, + "cast_float32_to_string": {"display":"real_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_text\", preserves_uniqueness = false, inverse = super::CastStringToFloat32)] fn cast_float32_to_string(a: f32) -> String","body_fingerprint":"afb99469117094e4"}, + "cast_float32_to_uint16": {"display":"real_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_uint2\", preserves_uniqueness = false, inverse = super::CastUint16ToFloat32, is_monotone = true)] fn cast_float32_to_uint16(a: f32) -> Result","body_fingerprint":"f6e8bfea3622de5c"}, + "cast_float32_to_uint32": {"display":"real_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_uint4\", preserves_uniqueness = false, inverse = super::CastUint32ToFloat32, is_monotone = true)] fn cast_float32_to_uint32(a: f32) -> Result","body_fingerprint":"69f3d9020edb4fb3"}, + "cast_float32_to_uint64": {"display":"real_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"real_to_uint8\", preserves_uniqueness = false, inverse = super::CastUint64ToFloat32, is_monotone = true)] fn cast_float32_to_uint64(a: f32) -> Result","body_fingerprint":"adde45c7e5b5b59c"}, + "cast_float64_to_float32": {"display":"double_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToFloat64, is_monotone = true)] fn cast_float64_to_float32(a: f64) -> Result","body_fingerprint":"3f343e5a91c3f24a"}, + "cast_float64_to_int16": {"display":"double_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_smallint\", preserves_uniqueness = false, inverse = super::CastInt16ToFloat64, is_monotone = true)] fn cast_float64_to_int16(a: f64) -> Result","body_fingerprint":"7b6999b1278d8e02"}, + "cast_float64_to_int32": {"display":"double_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_integer\", preserves_uniqueness = false, inverse = super::CastInt32ToFloat64, is_monotone = true)] fn cast_float64_to_int32(a: f64) -> Result","body_fingerprint":"3e35668ff852238a"}, + "cast_float64_to_int64": {"display":"f64toi64","sqlfunc_decl":"#[sqlfunc(sqlname = \"f64toi64\", preserves_uniqueness = false, inverse = super::CastInt64ToFloat64, is_monotone = true)] fn cast_float64_to_int64(a: f64) -> Result","body_fingerprint":"eff404954eb17e94"}, "cast_float64_to_numeric": {"display":"double_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_float64_to_numeric[scale]": {"display":"double_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_float64_to_string": {"display":"double_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_text\", preserves_uniqueness = false, inverse = to_unary!(super::CastStringToFloat64))] fn cast_float64_to_string(a: f64) -> String","body_fingerprint":"ed1946d3de6a3555"}, - "cast_float64_to_uint16": {"display":"double_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_uint2\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint16ToFloat64), is_monotone = true)] fn cast_float64_to_uint16(a: f64) -> Result","body_fingerprint":"9cdb81df1272809a"}, - "cast_float64_to_uint32": {"display":"double_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_uint4\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint32ToFloat64), is_monotone = true)] fn cast_float64_to_uint32(a: f64) -> Result","body_fingerprint":"1fd96b053ec266ec"}, - "cast_float64_to_uint64": {"display":"double_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_uint8\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint64ToFloat64), is_monotone = true)] fn cast_float64_to_uint64(a: f64) -> Result","body_fingerprint":"98051c71e907f216"}, - "cast_int16_to_float32": {"display":"smallint_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_real\", preserves_uniqueness = true, inverse = to_unary!(super::CastFloat32ToInt16), is_monotone = true)] fn cast_int16_to_float32(a: i16) -> f32","body_fingerprint":"6ad73befb8ca2a34"}, - "cast_int16_to_float64": {"display":"smallint_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_double\", preserves_uniqueness = true, inverse = to_unary!(super::CastFloat64ToInt16), is_monotone = true)] fn cast_int16_to_float64(a: i16) -> f64","body_fingerprint":"8a67f84e8764d837"}, - "cast_int16_to_int32": {"display":"smallint_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToInt16), is_monotone = true)] fn cast_int16_to_int32(a: i16) -> i32","body_fingerprint":"bc65045bb6754831"}, - "cast_int16_to_int64": {"display":"smallint_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToInt16), is_monotone = true)] fn cast_int16_to_int64(a: i16) -> i64","body_fingerprint":"9c62c1a559decc6e"}, + "cast_float64_to_string": {"display":"double_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_text\", preserves_uniqueness = false, inverse = super::CastStringToFloat64)] fn cast_float64_to_string(a: f64) -> String","body_fingerprint":"ed1946d3de6a3555"}, + "cast_float64_to_uint16": {"display":"double_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_uint2\", preserves_uniqueness = false, inverse = super::CastUint16ToFloat64, is_monotone = true)] fn cast_float64_to_uint16(a: f64) -> Result","body_fingerprint":"9cdb81df1272809a"}, + "cast_float64_to_uint32": {"display":"double_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_uint4\", preserves_uniqueness = false, inverse = super::CastUint32ToFloat64, is_monotone = true)] fn cast_float64_to_uint32(a: f64) -> Result","body_fingerprint":"1fd96b053ec266ec"}, + "cast_float64_to_uint64": {"display":"double_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"double_to_uint8\", preserves_uniqueness = false, inverse = super::CastUint64ToFloat64, is_monotone = true)] fn cast_float64_to_uint64(a: f64) -> Result","body_fingerprint":"98051c71e907f216"}, + "cast_int16_to_float32": {"display":"smallint_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_real\", preserves_uniqueness = true, inverse = super::CastFloat32ToInt16, is_monotone = true)] fn cast_int16_to_float32(a: i16) -> f32","body_fingerprint":"6ad73befb8ca2a34"}, + "cast_int16_to_float64": {"display":"smallint_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_double\", preserves_uniqueness = true, inverse = super::CastFloat64ToInt16, is_monotone = true)] fn cast_int16_to_float64(a: i16) -> f64","body_fingerprint":"8a67f84e8764d837"}, + "cast_int16_to_int32": {"display":"smallint_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToInt16, is_monotone = true)] fn cast_int16_to_int32(a: i16) -> i32","body_fingerprint":"bc65045bb6754831"}, + "cast_int16_to_int64": {"display":"smallint_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToInt16, is_monotone = true)] fn cast_int16_to_int64(a: i16) -> i64","body_fingerprint":"9c62c1a559decc6e"}, "cast_int16_to_numeric": {"display":"smallint_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_int16_to_numeric[scale]": {"display":"smallint_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_int16_to_string": {"display":"smallint_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToInt16))] fn cast_int16_to_string(a: i16) -> String","body_fingerprint":"1317bc80b391426b"}, - "cast_int16_to_uint16": {"display":"smallint_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_uint2\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint16ToInt16), is_monotone = true)] fn cast_int16_to_uint16(a: i16) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, - "cast_int16_to_uint32": {"display":"smallint_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_uint4\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint32ToInt16), is_monotone = true)] fn cast_int16_to_uint32(a: i16) -> Result","body_fingerprint":"a030b0b7248d6b70"}, - "cast_int16_to_uint64": {"display":"smallint_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_uint8\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint64ToInt16), is_monotone = true)] fn cast_int16_to_uint64(a: i16) -> Result","body_fingerprint":"47756d82c581e442"}, - "cast_int2_vector_to_array": {"display":"int2vectortoarray","sqlfunc_decl":"#[sqlfunc(sqlname = \"int2vectortoarray\", is_monotone = true, introduces_nulls = false, output_type_expr = SqlScalarType::Array(Box::from(SqlScalarType::Int16)).nullable(input_type.nullable))] fn cast_int2_vector_to_array<'a>(a: Int2Vector<'a>) -> Array<'a>","body_fingerprint":"ba6f1e61cfed1bde"}, - "cast_int2_vector_to_string": {"display":"int2vectortostr","sqlfunc_decl":"#[sqlfunc(sqlname = \"int2vectortostr\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToInt2Vector))] fn cast_int2_vector_to_string<'a>(a: Int2Vector<'a>) -> Result","body_fingerprint":"aaf9f407dda56cb6"}, - "cast_int32_to_bool": {"display":"integer_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_boolean\", preserves_uniqueness = false, inverse = to_unary!(super::CastBoolToInt32))] fn cast_int32_to_bool(a: i32) -> bool","body_fingerprint":"3d151ef3613e7c96"}, - "cast_int32_to_float32": {"display":"integer_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToInt32), is_monotone = true)] fn cast_int32_to_float32(a: i32) -> f32","body_fingerprint":"5cbae9f61a68b6b7"}, - "cast_int32_to_float64": {"display":"integer_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_double\", preserves_uniqueness = true, inverse = to_unary!(super::CastFloat64ToInt32), is_monotone = true)] fn cast_int32_to_float64(a: i32) -> f64","body_fingerprint":"8a67f84e8764d837"}, - "cast_int32_to_int16": {"display":"integer_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_smallint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt16ToInt32), is_monotone = true)] fn cast_int32_to_int16(a: i32) -> Result","body_fingerprint":"106c56bf06c2a245"}, - "cast_int32_to_int64": {"display":"integer_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToInt32), is_monotone = true)] fn cast_int32_to_int64(a: i32) -> i64","body_fingerprint":"9c62c1a559decc6e"}, + "cast_int16_to_string": {"display":"smallint_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_text\", preserves_uniqueness = true, inverse = super::CastStringToInt16)] fn cast_int16_to_string(a: i16) -> String","body_fingerprint":"1317bc80b391426b"}, + "cast_int16_to_uint16": {"display":"smallint_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_uint2\", preserves_uniqueness = true, inverse = super::CastUint16ToInt16, is_monotone = true)] fn cast_int16_to_uint16(a: i16) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, + "cast_int16_to_uint32": {"display":"smallint_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_uint4\", preserves_uniqueness = true, inverse = super::CastUint32ToInt16, is_monotone = true)] fn cast_int16_to_uint32(a: i16) -> Result","body_fingerprint":"a030b0b7248d6b70"}, + "cast_int16_to_uint64": {"display":"smallint_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"smallint_to_uint8\", preserves_uniqueness = true, inverse = super::CastUint64ToInt16, is_monotone = true)] fn cast_int16_to_uint64(a: i16) -> Result","body_fingerprint":"47756d82c581e442"}, + "cast_int2_vector_to_array": {"display":"int2vectortoarray","sqlfunc_decl":"#[sqlfunc(sqlname = \"int2vectortoarray\", is_monotone = true, output_type_expr = SqlScalarType::Array(Box::from(SqlScalarType::Int16)).nullable(input_type.nullable))] fn cast_int2_vector_to_array<'a>(a: Int2Vector<'a>) -> Array<'a>","body_fingerprint":"ba6f1e61cfed1bde"}, + "cast_int2_vector_to_string": {"display":"int2vectortostr","sqlfunc_decl":"#[sqlfunc(sqlname = \"int2vectortostr\", preserves_uniqueness = true, inverse = super::CastStringToInt2Vector)] fn cast_int2_vector_to_string<'a>(a: Int2Vector<'a>) -> Result","body_fingerprint":"aaf9f407dda56cb6"}, + "cast_int32_to_bool": {"display":"integer_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_boolean\", preserves_uniqueness = false, inverse = super::CastBoolToInt32)] fn cast_int32_to_bool(a: i32) -> bool","body_fingerprint":"3d151ef3613e7c96"}, + "cast_int32_to_float32": {"display":"integer_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToInt32, is_monotone = true)] fn cast_int32_to_float32(a: i32) -> f32","body_fingerprint":"5cbae9f61a68b6b7"}, + "cast_int32_to_float64": {"display":"integer_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_double\", preserves_uniqueness = true, inverse = super::CastFloat64ToInt32, is_monotone = true)] fn cast_int32_to_float64(a: i32) -> f64","body_fingerprint":"8a67f84e8764d837"}, + "cast_int32_to_int16": {"display":"integer_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_smallint\", preserves_uniqueness = true, inverse = super::CastInt16ToInt32, is_monotone = true)] fn cast_int32_to_int16(a: i32) -> Result","body_fingerprint":"106c56bf06c2a245"}, + "cast_int32_to_int64": {"display":"integer_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToInt32, is_monotone = true)] fn cast_int32_to_int64(a: i32) -> i64","body_fingerprint":"9c62c1a559decc6e"}, "cast_int32_to_mz_timestamp": {"display":"integer_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_mz_timestamp\", preserves_uniqueness = true, is_monotone = true)] fn cast_int32_to_mz_timestamp(a: i32) -> Result","body_fingerprint":"fc5c2486a53be81d"}, "cast_int32_to_numeric": {"display":"integer_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_int32_to_numeric[scale]": {"display":"integer_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_int32_to_oid": {"display":"integer_to_oid","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_oid\", preserves_uniqueness = true, inverse = to_unary!(super::CastOidToInt32))] fn cast_int32_to_oid(a: i32) -> Oid","body_fingerprint":"d1031e0d6bd03d94"}, - "cast_int32_to_pg_legacy_char": {"display":"integer_to_\"char\"","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_\\\"char\\\"\", preserves_uniqueness = true, inverse = to_unary!(super::CastPgLegacyCharToInt32))] fn cast_int32_to_pg_legacy_char(a: i32) -> Result","body_fingerprint":"1e3bbcb1147be1fe"}, - "cast_int32_to_string": {"display":"integer_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToInt32))] fn cast_int32_to_string(a: i32) -> String","body_fingerprint":"05e6cfd50d0297f5"}, - "cast_int32_to_uint16": {"display":"integer_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_uint2\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint16ToInt32), is_monotone = true)] fn cast_int32_to_uint16(a: i32) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, - "cast_int32_to_uint32": {"display":"integer_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_uint4\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint32ToInt32), is_monotone = true)] fn cast_int32_to_uint32(a: i32) -> Result","body_fingerprint":"a030b0b7248d6b70"}, - "cast_int32_to_uint64": {"display":"integer_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_uint8\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint64ToInt32), is_monotone = true)] fn cast_int32_to_uint64(a: i32) -> Result","body_fingerprint":"47756d82c581e442"}, - "cast_int64_to_bool": {"display":"bigint_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_boolean\", preserves_uniqueness = false, inverse = to_unary!(super::CastBoolToInt64))] fn cast_int64_to_bool(a: i64) -> bool","body_fingerprint":"3d151ef3613e7c96"}, - "cast_int64_to_float32": {"display":"bigint_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToInt64), is_monotone = true)] fn cast_int64_to_float32(a: i64) -> f32","body_fingerprint":"9e9699b80ff60ed3"}, - "cast_int64_to_float64": {"display":"bigint_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_double\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToInt64), is_monotone = true)] fn cast_int64_to_float64(a: i64) -> f64","body_fingerprint":"c9df6ab828789d9a"}, - "cast_int64_to_int16": {"display":"bigint_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_smallint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt16ToInt64), is_monotone = true)] fn cast_int64_to_int16(a: i64) -> Result","body_fingerprint":"106c56bf06c2a245"}, - "cast_int64_to_int32": {"display":"bigint_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToInt64), is_monotone = true)] fn cast_int64_to_int32(a: i64) -> Result","body_fingerprint":"de1123491c3c9cf9"}, + "cast_int32_to_oid": {"display":"integer_to_oid","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_oid\", preserves_uniqueness = true, inverse = super::CastOidToInt32)] fn cast_int32_to_oid(a: i32) -> Oid","body_fingerprint":"d1031e0d6bd03d94"}, + "cast_int32_to_pg_legacy_char": {"display":"integer_to_\"char\"","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_\\\"char\\\"\", preserves_uniqueness = true, inverse = super::CastPgLegacyCharToInt32)] fn cast_int32_to_pg_legacy_char(a: i32) -> Result","body_fingerprint":"1e3bbcb1147be1fe"}, + "cast_int32_to_string": {"display":"integer_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_text\", preserves_uniqueness = true, inverse = super::CastStringToInt32)] fn cast_int32_to_string(a: i32) -> String","body_fingerprint":"05e6cfd50d0297f5"}, + "cast_int32_to_uint16": {"display":"integer_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_uint2\", preserves_uniqueness = true, inverse = super::CastUint16ToInt32, is_monotone = true)] fn cast_int32_to_uint16(a: i32) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, + "cast_int32_to_uint32": {"display":"integer_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_uint4\", preserves_uniqueness = true, inverse = super::CastUint32ToInt32, is_monotone = true)] fn cast_int32_to_uint32(a: i32) -> Result","body_fingerprint":"a030b0b7248d6b70"}, + "cast_int32_to_uint64": {"display":"integer_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"integer_to_uint8\", preserves_uniqueness = true, inverse = super::CastUint64ToInt32, is_monotone = true)] fn cast_int32_to_uint64(a: i32) -> Result","body_fingerprint":"47756d82c581e442"}, + "cast_int64_to_bool": {"display":"bigint_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_boolean\", preserves_uniqueness = false, inverse = super::CastBoolToInt64)] fn cast_int64_to_bool(a: i64) -> bool","body_fingerprint":"3d151ef3613e7c96"}, + "cast_int64_to_float32": {"display":"bigint_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToInt64, is_monotone = true)] fn cast_int64_to_float32(a: i64) -> f32","body_fingerprint":"9e9699b80ff60ed3"}, + "cast_int64_to_float64": {"display":"bigint_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_double\", preserves_uniqueness = false, inverse = super::CastFloat64ToInt64, is_monotone = true)] fn cast_int64_to_float64(a: i64) -> f64","body_fingerprint":"c9df6ab828789d9a"}, + "cast_int64_to_int16": {"display":"bigint_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_smallint\", preserves_uniqueness = true, inverse = super::CastInt16ToInt64, is_monotone = true)] fn cast_int64_to_int16(a: i64) -> Result","body_fingerprint":"106c56bf06c2a245"}, + "cast_int64_to_int32": {"display":"bigint_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToInt64, is_monotone = true)] fn cast_int64_to_int32(a: i64) -> Result","body_fingerprint":"de1123491c3c9cf9"}, "cast_int64_to_mz_timestamp": {"display":"bigint_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_mz_timestamp\", preserves_uniqueness = true, is_monotone = true)] fn cast_int64_to_mz_timestamp(a: i64) -> Result","body_fingerprint":"b76dcbb5b02bb973"}, "cast_int64_to_numeric": {"display":"bigint_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_int64_to_numeric[scale]": {"display":"bigint_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_int64_to_oid": {"display":"bigint_to_oid","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_oid\", preserves_uniqueness = true, inverse = to_unary!(super::CastOidToInt64))] fn cast_int64_to_oid(a: i64) -> Result","body_fingerprint":"bf43df4e3acd363e"}, - "cast_int64_to_string": {"display":"bigint_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToInt64))] fn cast_int64_to_string(a: i64) -> String","body_fingerprint":"87b2e153d32bdbe4"}, - "cast_int64_to_uint16": {"display":"bigint_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_uint2\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint16ToInt64), is_monotone = true)] fn cast_int64_to_uint16(a: i64) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, - "cast_int64_to_uint32": {"display":"bigint_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_uint4\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint32ToInt64), is_monotone = true)] fn cast_int64_to_uint32(a: i64) -> Result","body_fingerprint":"a030b0b7248d6b70"}, - "cast_int64_to_uint64": {"display":"bigint_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_uint8\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint64ToInt64), is_monotone = true)] fn cast_int64_to_uint64(a: i64) -> Result","body_fingerprint":"47756d82c581e442"}, - "cast_interval_to_string": {"display":"interval_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"interval_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToInterval))] fn cast_interval_to_string(a: Interval) -> String","body_fingerprint":"669273f352f36790"}, - "cast_interval_to_time": {"display":"interval_to_time","sqlfunc_decl":"#[sqlfunc(sqlname = \"interval_to_time\", preserves_uniqueness = false, inverse = to_unary!(super::CastTimeToInterval))] fn cast_interval_to_time(i: Interval) -> NaiveTime","body_fingerprint":"10491f8adbe1a0c8"}, + "cast_int64_to_oid": {"display":"bigint_to_oid","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_oid\", preserves_uniqueness = true, inverse = super::CastOidToInt64)] fn cast_int64_to_oid(a: i64) -> Result","body_fingerprint":"bf43df4e3acd363e"}, + "cast_int64_to_string": {"display":"bigint_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_text\", preserves_uniqueness = true, inverse = super::CastStringToInt64)] fn cast_int64_to_string(a: i64) -> String","body_fingerprint":"87b2e153d32bdbe4"}, + "cast_int64_to_uint16": {"display":"bigint_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_uint2\", preserves_uniqueness = true, inverse = super::CastUint16ToInt64, is_monotone = true)] fn cast_int64_to_uint16(a: i64) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, + "cast_int64_to_uint32": {"display":"bigint_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_uint4\", preserves_uniqueness = true, inverse = super::CastUint32ToInt64, is_monotone = true)] fn cast_int64_to_uint32(a: i64) -> Result","body_fingerprint":"a030b0b7248d6b70"}, + "cast_int64_to_uint64": {"display":"bigint_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"bigint_to_uint8\", preserves_uniqueness = true, inverse = super::CastUint64ToInt64, is_monotone = true)] fn cast_int64_to_uint64(a: i64) -> Result","body_fingerprint":"47756d82c581e442"}, + "cast_interval_to_string": {"display":"interval_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"interval_to_text\", preserves_uniqueness = true, inverse = super::CastStringToInterval)] fn cast_interval_to_string(a: Interval) -> String","body_fingerprint":"669273f352f36790"}, + "cast_interval_to_time": {"display":"interval_to_time","sqlfunc_decl":"#[sqlfunc(sqlname = \"interval_to_time\", preserves_uniqueness = false, inverse = super::CastTimeToInterval)] fn cast_interval_to_time(i: Interval) -> NaiveTime","body_fingerprint":"10491f8adbe1a0c8"}, "cast_jsonb_to_bool": {"display":"jsonb_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonb_to_boolean\", is_monotone = true)] fn cast_jsonb_to_bool<'a>(a: JsonbRef<'a>) -> Result","body_fingerprint":"54d24ddd4a4d16dd"}, "cast_jsonb_to_float32": {"display":"jsonb_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonb_to_real\", is_monotone = true)] fn cast_jsonb_to_float32<'a>(a: JsonbRef<'a>) -> Result","body_fingerprint":"a360187e1f3c2707"}, "cast_jsonb_to_float64": {"display":"jsonb_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonb_to_double\", is_monotone = true)] fn cast_jsonb_to_float64<'a>(a: JsonbRef<'a>) -> Result","body_fingerprint":"28f4795819c8834b"}, @@ -331,123 +331,123 @@ "cast_jsonb_to_int64": {"display":"jsonb_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonb_to_bigint\", is_monotone = true)] fn cast_jsonb_to_int64<'a>(a: JsonbRef<'a>) -> Result","body_fingerprint":"56297e8c84111140"}, "cast_jsonb_to_numeric": {"display":"jsonb_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_jsonb_to_numeric[scale]": {"display":"jsonb_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_jsonb_to_string": {"display":"jsonb_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonb_to_text\", preserves_uniqueness = false, inverse = to_unary!(super::CastStringToJsonb))] fn cast_jsonb_to_string<'a>(a: JsonbRef<'a>) -> String","body_fingerprint":"d2322a46ec145a41"}, + "cast_jsonb_to_string": {"display":"jsonb_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonb_to_text\", preserves_uniqueness = false, inverse = super::CastStringToJsonb)] fn cast_jsonb_to_string<'a>(a: JsonbRef<'a>) -> String","body_fingerprint":"d2322a46ec145a41"}, "cast_jsonbable_to_jsonb": {"display":"jsonbable_to_jsonb","sqlfunc_decl":"#[sqlfunc(sqlname = \"jsonbable_to_jsonb\")] fn cast_jsonbable_to_jsonb<'a>(a: JsonbRef<'a>) -> JsonbRef<'a>","body_fingerprint":"ae0d031ddd541adf"}, "cast_list1_to_list2": {"display":"list1tolist2","sqlfunc_decl":null,"body_fingerprint":null}, "cast_list_to_jsonb": {"display":"listtojsonb","sqlfunc_decl":null,"body_fingerprint":null}, "cast_list_to_string": {"display":"listtostr","sqlfunc_decl":null,"body_fingerprint":null}, "cast_map_to_string": {"display":"maptostr","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_mz_timestamp_to_string": {"display":"mz_timestamp_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_timestamp_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToMzTimestamp))] fn cast_mz_timestamp_to_string(a: Timestamp) -> String","body_fingerprint":"01add8290ea7f57b"}, - "cast_mz_timestamp_to_timestamp": {"display":"mz_timestamp_to_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_timestamp_to_timestamp\", preserves_uniqueness = true, inverse = to_unary!(super::CastTimestampToMzTimestamp))] fn cast_mz_timestamp_to_timestamp(a: Timestamp,) -> Result, EvalError>","body_fingerprint":"bdf56920d511c8d8"}, - "cast_mz_timestamp_to_timestamp_tz": {"display":"mz_timestamp_to_timestamp_tz","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_timestamp_to_timestamp_tz\", preserves_uniqueness = true, inverse = to_unary!(super::CastTimestampTzToMzTimestamp))] fn cast_mz_timestamp_to_timestamp_tz(a: Timestamp,) -> Result>, EvalError>","body_fingerprint":"caec6fa728d2239c"}, - "cast_numeric_to_float32": {"display":"numeric_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_float32(a: Numeric) -> Result","body_fingerprint":"6c06659074de0284"}, - "cast_numeric_to_float64": {"display":"numeric_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_double\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_float64(a: Numeric) -> Result","body_fingerprint":"871d8812540ac370"}, - "cast_numeric_to_int16": {"display":"numeric_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_smallint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt16ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_int16(mut a: Numeric) -> Result","body_fingerprint":"77481fedc95d9314"}, - "cast_numeric_to_int32": {"display":"numeric_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_integer\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt32ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_int32(mut a: Numeric) -> Result","body_fingerprint":"ed75fe1c956193df"}, - "cast_numeric_to_int64": {"display":"numeric_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_bigint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt64ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_int64(mut a: Numeric) -> Result","body_fingerprint":"cdde936dce05d663"}, + "cast_mz_timestamp_to_string": {"display":"mz_timestamp_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_timestamp_to_text\", preserves_uniqueness = true, inverse = super::CastStringToMzTimestamp)] fn cast_mz_timestamp_to_string(a: Timestamp) -> String","body_fingerprint":"01add8290ea7f57b"}, + "cast_mz_timestamp_to_timestamp": {"display":"mz_timestamp_to_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_timestamp_to_timestamp\", preserves_uniqueness = true, inverse = super::CastTimestampToMzTimestamp)] fn cast_mz_timestamp_to_timestamp(a: Timestamp,) -> Result, EvalError>","body_fingerprint":"bdf56920d511c8d8"}, + "cast_mz_timestamp_to_timestamp_tz": {"display":"mz_timestamp_to_timestamp_tz","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_timestamp_to_timestamp_tz\", preserves_uniqueness = true, inverse = super::CastTimestampTzToMzTimestamp)] fn cast_mz_timestamp_to_timestamp_tz(a: Timestamp,) -> Result>, EvalError>","body_fingerprint":"caec6fa728d2239c"}, + "cast_numeric_to_float32": {"display":"numeric_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToNumeric(None), is_monotone = true)] fn cast_numeric_to_float32(a: Numeric) -> Result","body_fingerprint":"6c06659074de0284"}, + "cast_numeric_to_float64": {"display":"numeric_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_double\", preserves_uniqueness = false, inverse = super::CastFloat64ToNumeric(None), is_monotone = true)] fn cast_numeric_to_float64(a: Numeric) -> Result","body_fingerprint":"871d8812540ac370"}, + "cast_numeric_to_int16": {"display":"numeric_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_smallint\", preserves_uniqueness = false, inverse = super::CastInt16ToNumeric(None), is_monotone = true)] fn cast_numeric_to_int16(mut a: Numeric) -> Result","body_fingerprint":"77481fedc95d9314"}, + "cast_numeric_to_int32": {"display":"numeric_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_integer\", preserves_uniqueness = false, inverse = super::CastInt32ToNumeric(None), is_monotone = true)] fn cast_numeric_to_int32(mut a: Numeric) -> Result","body_fingerprint":"ed75fe1c956193df"}, + "cast_numeric_to_int64": {"display":"numeric_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_bigint\", preserves_uniqueness = false, inverse = super::CastInt64ToNumeric(None), is_monotone = true)] fn cast_numeric_to_int64(mut a: Numeric) -> Result","body_fingerprint":"cdde936dce05d663"}, "cast_numeric_to_mz_timestamp": {"display":"numeric_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_mz_timestamp\", preserves_uniqueness = true, is_monotone = true)] fn cast_numeric_to_mz_timestamp(a: Numeric) -> Result","body_fingerprint":"b76dcbb5b02bb973"}, - "cast_numeric_to_string": {"display":"numeric_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_text\", preserves_uniqueness = false, inverse = to_unary!(super::CastStringToNumeric(None)))] fn cast_numeric_to_string(a: Numeric) -> String","body_fingerprint":"6d385094e70a788b"}, - "cast_numeric_to_uint16": {"display":"numeric_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_uint2\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint16ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_uint16(mut a: Numeric) -> Result","body_fingerprint":"760b6946b443d612"}, - "cast_numeric_to_uint32": {"display":"numeric_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_uint4\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint32ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_uint32(mut a: Numeric) -> Result","body_fingerprint":"8c42b9414d05f99a"}, - "cast_numeric_to_uint64": {"display":"numeric_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_uint8\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint64ToNumeric(None)), is_monotone = true)] fn cast_numeric_to_uint64(mut a: Numeric) -> Result","body_fingerprint":"02049691c2bf3324"}, - "cast_oid_to_int32": {"display":"oid_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"oid_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToOid))] fn cast_oid_to_int32(a: Oid) -> i32","body_fingerprint":"8640976e71e6dabf"}, - "cast_oid_to_int64": {"display":"oid_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"oid_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToOid))] fn cast_oid_to_int64(a: Oid) -> i64","body_fingerprint":"51f755d07bbeb47c"}, - "cast_oid_to_reg_class": {"display":"oidtoregclass","sqlfunc_decl":"#[sqlfunc(sqlname = \"oidtoregclass\", preserves_uniqueness = true, inverse = to_unary!(super::CastRegClassToOid))] fn cast_oid_to_reg_class(a: Oid) -> RegClass","body_fingerprint":"e7da11fedd409f5b"}, - "cast_oid_to_reg_proc": {"display":"oidtoregproc","sqlfunc_decl":"#[sqlfunc(sqlname = \"oidtoregproc\", preserves_uniqueness = true, inverse = to_unary!(super::CastRegProcToOid))] fn cast_oid_to_reg_proc(a: Oid) -> RegProc","body_fingerprint":"f32b107253804abb"}, - "cast_oid_to_reg_type": {"display":"oidtoregtype","sqlfunc_decl":"#[sqlfunc(sqlname = \"oidtoregtype\", preserves_uniqueness = true, inverse = to_unary!(super::CastRegTypeToOid))] fn cast_oid_to_reg_type(a: Oid) -> RegType","body_fingerprint":"c75d209f0f3ed94b"}, - "cast_oid_to_string": {"display":"oid_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"oid_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToOid))] fn cast_oid_to_string(a: Oid) -> String","body_fingerprint":"27da34f3f80e857a"}, - "cast_pg_legacy_char_to_char": {"display":"\"char\"_to_char","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_char\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToPgLegacyChar))] fn cast_pg_legacy_char_to_char(a: PgLegacyChar) -> Result, EvalError>","body_fingerprint":"a03aad3766040029"}, - "cast_pg_legacy_char_to_int32": {"display":"\"char\"_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToPgLegacyChar))] fn cast_pg_legacy_char_to_int32(a: PgLegacyChar) -> i32","body_fingerprint":"1976be6ad62975f3"}, - "cast_pg_legacy_char_to_string": {"display":"\"char\"_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToPgLegacyChar))] fn cast_pg_legacy_char_to_string(a: PgLegacyChar) -> Result","body_fingerprint":"a6ca26834f5d02bc"}, - "cast_pg_legacy_char_to_var_char": {"display":"\"char\"_to_varchar","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_varchar\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToVarChar {fail_on_len: false, length: Some(VarCharMaxLength::try_from(1).unwrap()),}))] fn cast_pg_legacy_char_to_var_char(a: PgLegacyChar) -> Result, EvalError>","body_fingerprint":"757b2f161f95b71c"}, + "cast_numeric_to_string": {"display":"numeric_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_text\", preserves_uniqueness = false, inverse = super::CastStringToNumeric(None))] fn cast_numeric_to_string(a: Numeric) -> String","body_fingerprint":"6d385094e70a788b"}, + "cast_numeric_to_uint16": {"display":"numeric_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_uint2\", preserves_uniqueness = false, inverse = super::CastUint16ToNumeric(None), is_monotone = true)] fn cast_numeric_to_uint16(mut a: Numeric) -> Result","body_fingerprint":"760b6946b443d612"}, + "cast_numeric_to_uint32": {"display":"numeric_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_uint4\", preserves_uniqueness = false, inverse = super::CastUint32ToNumeric(None), is_monotone = true)] fn cast_numeric_to_uint32(mut a: Numeric) -> Result","body_fingerprint":"8c42b9414d05f99a"}, + "cast_numeric_to_uint64": {"display":"numeric_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"numeric_to_uint8\", preserves_uniqueness = false, inverse = super::CastUint64ToNumeric(None), is_monotone = true)] fn cast_numeric_to_uint64(mut a: Numeric) -> Result","body_fingerprint":"02049691c2bf3324"}, + "cast_oid_to_int32": {"display":"oid_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"oid_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToOid)] fn cast_oid_to_int32(a: Oid) -> i32","body_fingerprint":"8640976e71e6dabf"}, + "cast_oid_to_int64": {"display":"oid_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"oid_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToOid)] fn cast_oid_to_int64(a: Oid) -> i64","body_fingerprint":"51f755d07bbeb47c"}, + "cast_oid_to_reg_class": {"display":"oidtoregclass","sqlfunc_decl":"#[sqlfunc(sqlname = \"oidtoregclass\", preserves_uniqueness = true, inverse = super::CastRegClassToOid)] fn cast_oid_to_reg_class(a: Oid) -> RegClass","body_fingerprint":"e7da11fedd409f5b"}, + "cast_oid_to_reg_proc": {"display":"oidtoregproc","sqlfunc_decl":"#[sqlfunc(sqlname = \"oidtoregproc\", preserves_uniqueness = true, inverse = super::CastRegProcToOid)] fn cast_oid_to_reg_proc(a: Oid) -> RegProc","body_fingerprint":"f32b107253804abb"}, + "cast_oid_to_reg_type": {"display":"oidtoregtype","sqlfunc_decl":"#[sqlfunc(sqlname = \"oidtoregtype\", preserves_uniqueness = true, inverse = super::CastRegTypeToOid)] fn cast_oid_to_reg_type(a: Oid) -> RegType","body_fingerprint":"c75d209f0f3ed94b"}, + "cast_oid_to_string": {"display":"oid_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"oid_to_text\", preserves_uniqueness = true, inverse = super::CastStringToOid)] fn cast_oid_to_string(a: Oid) -> String","body_fingerprint":"27da34f3f80e857a"}, + "cast_pg_legacy_char_to_char": {"display":"\"char\"_to_char","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_char\", preserves_uniqueness = true, inverse = super::CastStringToPgLegacyChar)] fn cast_pg_legacy_char_to_char(a: PgLegacyChar) -> Result, EvalError>","body_fingerprint":"a03aad3766040029"}, + "cast_pg_legacy_char_to_int32": {"display":"\"char\"_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToPgLegacyChar)] fn cast_pg_legacy_char_to_int32(a: PgLegacyChar) -> i32","body_fingerprint":"1976be6ad62975f3"}, + "cast_pg_legacy_char_to_string": {"display":"\"char\"_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_text\", preserves_uniqueness = true, inverse = super::CastStringToPgLegacyChar)] fn cast_pg_legacy_char_to_string(a: PgLegacyChar) -> Result","body_fingerprint":"a6ca26834f5d02bc"}, + "cast_pg_legacy_char_to_var_char": {"display":"\"char\"_to_varchar","sqlfunc_decl":"#[sqlfunc(sqlname = \"\\\"char\\\"_to_varchar\", preserves_uniqueness = true, inverse = super::CastStringToVarChar {fail_on_len: false, length: Some(VarCharMaxLength::try_from(1).unwrap()),})] fn cast_pg_legacy_char_to_var_char(a: PgLegacyChar) -> Result, EvalError>","body_fingerprint":"757b2f161f95b71c"}, "cast_range_to_string": {"display":"rangetostr","sqlfunc_decl":null,"body_fingerprint":null}, "cast_record1_to_record2": {"display":"record1torecord2","sqlfunc_decl":null,"body_fingerprint":null}, "cast_record_to_string": {"display":"recordtostr","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_reg_class_to_oid": {"display":"regclasstooid","sqlfunc_decl":"#[sqlfunc(sqlname = \"regclasstooid\", preserves_uniqueness = true, inverse = to_unary!(super::CastOidToRegClass))] fn cast_reg_class_to_oid(a: RegClass) -> Oid","body_fingerprint":"0c8b6d41527aa7c1"}, - "cast_reg_proc_to_oid": {"display":"regproctooid","sqlfunc_decl":"#[sqlfunc(sqlname = \"regproctooid\", preserves_uniqueness = true, inverse = to_unary!(super::CastOidToRegProc))] fn cast_reg_proc_to_oid(a: RegProc) -> Oid","body_fingerprint":"0c8b6d41527aa7c1"}, - "cast_reg_type_to_oid": {"display":"regtypetooid","sqlfunc_decl":"#[sqlfunc(sqlname = \"regtypetooid\", preserves_uniqueness = true, inverse = to_unary!(super::CastOidToRegType))] fn cast_reg_type_to_oid(a: RegType) -> Oid","body_fingerprint":"0c8b6d41527aa7c1"}, + "cast_reg_class_to_oid": {"display":"regclasstooid","sqlfunc_decl":"#[sqlfunc(sqlname = \"regclasstooid\", preserves_uniqueness = true, inverse = super::CastOidToRegClass)] fn cast_reg_class_to_oid(a: RegClass) -> Oid","body_fingerprint":"0c8b6d41527aa7c1"}, + "cast_reg_proc_to_oid": {"display":"regproctooid","sqlfunc_decl":"#[sqlfunc(sqlname = \"regproctooid\", preserves_uniqueness = true, inverse = super::CastOidToRegProc)] fn cast_reg_proc_to_oid(a: RegProc) -> Oid","body_fingerprint":"0c8b6d41527aa7c1"}, + "cast_reg_type_to_oid": {"display":"regtypetooid","sqlfunc_decl":"#[sqlfunc(sqlname = \"regtypetooid\", preserves_uniqueness = true, inverse = super::CastOidToRegType)] fn cast_reg_type_to_oid(a: RegType) -> Oid","body_fingerprint":"0c8b6d41527aa7c1"}, "cast_string_to_array": {"display":"strtoarray","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_bool": {"display":"text_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_boolean\", preserves_uniqueness = false, inverse = to_unary!(super::CastBoolToString))] fn cast_string_to_bool<'a>(a: &'a str) -> Result","body_fingerprint":"638f838369c262c5"}, - "cast_string_to_bytes": {"display":"text_to_bytea","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_bytea\", preserves_uniqueness = false, inverse = to_unary!(super::CastBytesToString))] fn cast_string_to_bytes<'a>(a: &'a str) -> Result, EvalError>","body_fingerprint":"65b8f3875b482dc6"}, + "cast_string_to_bool": {"display":"text_to_boolean","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_boolean\", preserves_uniqueness = false, inverse = super::CastBoolToString)] fn cast_string_to_bool<'a>(a: &'a str) -> Result","body_fingerprint":"638f838369c262c5"}, + "cast_string_to_bytes": {"display":"text_to_bytea","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_bytea\", preserves_uniqueness = false, inverse = super::CastBytesToString)] fn cast_string_to_bytes<'a>(a: &'a str) -> Result, EvalError>","body_fingerprint":"65b8f3875b482dc6"}, "cast_string_to_char": {"display":"text_to_char[len=5, fail_on_len=true]","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_char[unbounded]": {"display":"text_to_char[len=unbounded]","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_date": {"display":"text_to_date","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_date\", preserves_uniqueness = false, inverse = to_unary!(super::CastDateToString))] fn cast_string_to_date<'a>(a: &'a str) -> Result","body_fingerprint":"f3e731f76cc73135"}, - "cast_string_to_float32": {"display":"text_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToString))] fn cast_string_to_float32<'a>(a: &'a str) -> Result","body_fingerprint":"91409492a5e89f0a"}, - "cast_string_to_float64": {"display":"text_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_double\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToString))] fn cast_string_to_float64<'a>(a: &'a str) -> Result","body_fingerprint":"2bc75019f794547f"}, - "cast_string_to_int16": {"display":"text_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_smallint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt16ToString))] fn cast_string_to_int16<'a>(a: &'a str) -> Result","body_fingerprint":"e0d58271c1dabb79"}, + "cast_string_to_date": {"display":"text_to_date","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_date\", preserves_uniqueness = false, inverse = super::CastDateToString)] fn cast_string_to_date<'a>(a: &'a str) -> Result","body_fingerprint":"f3e731f76cc73135"}, + "cast_string_to_float32": {"display":"text_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToString)] fn cast_string_to_float32<'a>(a: &'a str) -> Result","body_fingerprint":"91409492a5e89f0a"}, + "cast_string_to_float64": {"display":"text_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_double\", preserves_uniqueness = false, inverse = super::CastFloat64ToString)] fn cast_string_to_float64<'a>(a: &'a str) -> Result","body_fingerprint":"2bc75019f794547f"}, + "cast_string_to_int16": {"display":"text_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_smallint\", preserves_uniqueness = false, inverse = super::CastInt16ToString)] fn cast_string_to_int16<'a>(a: &'a str) -> Result","body_fingerprint":"e0d58271c1dabb79"}, "cast_string_to_int2_vector": {"display":"strtoint2vector","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_int32": {"display":"text_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_integer\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt32ToString))] fn cast_string_to_int32<'a>(a: &'a str) -> Result","body_fingerprint":"20e90d93b93143b7"}, - "cast_string_to_int64": {"display":"text_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_bigint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt64ToString))] fn cast_string_to_int64<'a>(a: &'a str) -> Result","body_fingerprint":"e1660dcc9eb69d4e"}, - "cast_string_to_interval": {"display":"text_to_interval","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_interval\", preserves_uniqueness = false, inverse = to_unary!(super::CastIntervalToString))] fn cast_string_to_interval<'a>(a: &'a str) -> Result","body_fingerprint":"116b4b312967b8fa"}, - "cast_string_to_jsonb": {"display":"text_to_jsonb","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_jsonb\", preserves_uniqueness = false, inverse = to_unary!(super::CastJsonbToString))] fn cast_string_to_jsonb<'a>(a: &'a str) -> Result","body_fingerprint":"a1052efe1c240d42"}, + "cast_string_to_int32": {"display":"text_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_integer\", preserves_uniqueness = false, inverse = super::CastInt32ToString)] fn cast_string_to_int32<'a>(a: &'a str) -> Result","body_fingerprint":"20e90d93b93143b7"}, + "cast_string_to_int64": {"display":"text_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_bigint\", preserves_uniqueness = false, inverse = super::CastInt64ToString)] fn cast_string_to_int64<'a>(a: &'a str) -> Result","body_fingerprint":"e1660dcc9eb69d4e"}, + "cast_string_to_interval": {"display":"text_to_interval","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_interval\", preserves_uniqueness = false, inverse = super::CastIntervalToString)] fn cast_string_to_interval<'a>(a: &'a str) -> Result","body_fingerprint":"116b4b312967b8fa"}, + "cast_string_to_jsonb": {"display":"text_to_jsonb","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_jsonb\", preserves_uniqueness = false, inverse = super::CastJsonbToString)] fn cast_string_to_jsonb<'a>(a: &'a str) -> Result","body_fingerprint":"a1052efe1c240d42"}, "cast_string_to_list": {"display":"strtolist","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_map": {"display":"strtomap","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_mz_timestamp": {"display":"text_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_mz_timestamp\", preserves_uniqueness = false, inverse = to_unary!(super::CastMzTimestampToString))] fn cast_string_to_mz_timestamp(a: String) -> Result","body_fingerprint":"cb6d03fd3862d585"}, + "cast_string_to_mz_timestamp": {"display":"text_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_mz_timestamp\", preserves_uniqueness = false, inverse = super::CastMzTimestampToString)] fn cast_string_to_mz_timestamp(a: String) -> Result","body_fingerprint":"cb6d03fd3862d585"}, "cast_string_to_numeric": {"display":"text_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_numeric[scale]": {"display":"text_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_oid": {"display":"text_to_oid","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_oid\", preserves_uniqueness = false, inverse = to_unary!(super::CastOidToString))] fn cast_string_to_oid<'a>(a: &'a str) -> Result","body_fingerprint":"6abdb6ec1a51e421"}, - "cast_string_to_pg_legacy_char": {"display":"text_to_\"char\"","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_\\\"char\\\"\", preserves_uniqueness = false, inverse = to_unary!(super::CastPgLegacyCharToString))] fn cast_string_to_pg_legacy_char<'a>(a: &'a str) -> PgLegacyChar","body_fingerprint":"0bc2951a9224cbfe"}, + "cast_string_to_oid": {"display":"text_to_oid","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_oid\", preserves_uniqueness = false, inverse = super::CastOidToString)] fn cast_string_to_oid<'a>(a: &'a str) -> Result","body_fingerprint":"6abdb6ec1a51e421"}, + "cast_string_to_pg_legacy_char": {"display":"text_to_\"char\"","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_\\\"char\\\"\", preserves_uniqueness = false, inverse = super::CastPgLegacyCharToString)] fn cast_string_to_pg_legacy_char<'a>(a: &'a str) -> PgLegacyChar","body_fingerprint":"0bc2951a9224cbfe"}, "cast_string_to_pg_legacy_name": {"display":"text_to_name","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_name\", preserves_uniqueness = false)] fn cast_string_to_pg_legacy_name<'a>(a: &'a str) -> PgLegacyName","body_fingerprint":"5e8a8033c5923679"}, "cast_string_to_range": {"display":"strtorange","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_time": {"display":"text_to_time","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_time\", preserves_uniqueness = false, inverse = to_unary!(super::CastTimeToString))] fn cast_string_to_time<'a>(a: &'a str) -> Result","body_fingerprint":"a77b2ae1f754733a"}, + "cast_string_to_time": {"display":"text_to_time","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_time\", preserves_uniqueness = false, inverse = super::CastTimeToString)] fn cast_string_to_time<'a>(a: &'a str) -> Result","body_fingerprint":"a77b2ae1f754733a"}, "cast_string_to_timestamp": {"display":"text_to_timestamp","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_timestamp[precision]": {"display":"text_to_timestamp","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_timestamp_tz": {"display":"text_to_timestamp_with_time_zone","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_timestamp_tz[precision]": {"display":"text_to_timestamp_with_time_zone","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_string_to_uint16": {"display":"text_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uint2\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint16ToString))] fn cast_string_to_uint16(a: &str) -> Result","body_fingerprint":"24acd39037db6a64"}, - "cast_string_to_uint32": {"display":"text_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uint4\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint32ToString))] fn cast_string_to_uint32(a: &str) -> Result","body_fingerprint":"b2084e6a8db500de"}, - "cast_string_to_uint64": {"display":"text_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uint8\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint64ToString))] fn cast_string_to_uint64(a: &str) -> Result","body_fingerprint":"13e9c822b8db2fd3"}, - "cast_string_to_uuid": {"display":"text_to_uuid","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uuid\", preserves_uniqueness = false, inverse = to_unary!(super::CastUuidToString))] fn cast_string_to_uuid<'a>(a: &'a str) -> Result","body_fingerprint":"1b842d70222444b4"}, + "cast_string_to_uint16": {"display":"text_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uint2\", preserves_uniqueness = false, inverse = super::CastUint16ToString)] fn cast_string_to_uint16(a: &str) -> Result","body_fingerprint":"24acd39037db6a64"}, + "cast_string_to_uint32": {"display":"text_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uint4\", preserves_uniqueness = false, inverse = super::CastUint32ToString)] fn cast_string_to_uint32(a: &str) -> Result","body_fingerprint":"b2084e6a8db500de"}, + "cast_string_to_uint64": {"display":"text_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uint8\", preserves_uniqueness = false, inverse = super::CastUint64ToString)] fn cast_string_to_uint64(a: &str) -> Result","body_fingerprint":"13e9c822b8db2fd3"}, + "cast_string_to_uuid": {"display":"text_to_uuid","sqlfunc_decl":"#[sqlfunc(sqlname = \"text_to_uuid\", preserves_uniqueness = false, inverse = super::CastUuidToString)] fn cast_string_to_uuid<'a>(a: &'a str) -> Result","body_fingerprint":"1b842d70222444b4"}, "cast_string_to_var_char": {"display":"text_to_varchar[len=5, fail_on_len=true]","sqlfunc_decl":null,"body_fingerprint":null}, "cast_string_to_var_char[unbounded]": {"display":"text_to_varchar[len=unbounded]","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_time_to_interval": {"display":"time_to_interval","sqlfunc_decl":"#[sqlfunc(sqlname = \"time_to_interval\", preserves_uniqueness = true, inverse = to_unary!(super::CastIntervalToTime))] fn cast_time_to_interval(t: NaiveTime) -> Interval","body_fingerprint":"ccddb65c5498d02b"}, - "cast_time_to_string": {"display":"time_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"time_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToTime))] fn cast_time_to_string(a: NaiveTime) -> String","body_fingerprint":"202bf0607fb79334"}, - "cast_timestamp_to_date": {"display":"timestamp_to_date","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_to_date\", preserves_uniqueness = false, inverse = to_unary!(super::CastDateToTimestamp(None)), is_monotone = true)] fn cast_timestamp_to_date(a: CheckedTimestamp) -> Result","body_fingerprint":"a26913c563b50828"}, + "cast_time_to_interval": {"display":"time_to_interval","sqlfunc_decl":"#[sqlfunc(sqlname = \"time_to_interval\", preserves_uniqueness = true, inverse = super::CastIntervalToTime)] fn cast_time_to_interval(t: NaiveTime) -> Interval","body_fingerprint":"ccddb65c5498d02b"}, + "cast_time_to_string": {"display":"time_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"time_to_text\", preserves_uniqueness = true, inverse = super::CastStringToTime)] fn cast_time_to_string(a: NaiveTime) -> String","body_fingerprint":"202bf0607fb79334"}, + "cast_timestamp_to_date": {"display":"timestamp_to_date","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_to_date\", preserves_uniqueness = false, inverse = super::CastDateToTimestamp(None), is_monotone = true)] fn cast_timestamp_to_date(a: CheckedTimestamp) -> Result","body_fingerprint":"a26913c563b50828"}, "cast_timestamp_to_mz_timestamp": {"display":"timestamp_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_to_mz_timestamp\", is_monotone = true)] fn cast_timestamp_to_mz_timestamp(a: CheckedTimestamp,) -> Result","body_fingerprint":"9f93bf228455a7ac"}, - "cast_timestamp_to_string": {"display":"timestamp_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToTimestamp(None)))] fn cast_timestamp_to_string(a: CheckedTimestamp) -> String","body_fingerprint":"b46f9f4f8a380d77"}, + "cast_timestamp_to_string": {"display":"timestamp_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_to_text\", preserves_uniqueness = true, inverse = super::CastStringToTimestamp(None))] fn cast_timestamp_to_string(a: CheckedTimestamp) -> String","body_fingerprint":"b46f9f4f8a380d77"}, "cast_timestamp_to_time": {"display":"timestamp_to_time","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_to_time\", preserves_uniqueness = false)] fn cast_timestamp_to_time(a: CheckedTimestamp) -> NaiveTime","body_fingerprint":"53eb4feb26b05af6"}, "cast_timestamp_to_timestamp_tz": {"display":"timestamp_to_timestamp_with_time_zone","sqlfunc_decl":null,"body_fingerprint":null}, "cast_timestamp_to_timestamp_tz[widening]": {"display":"timestamp_to_timestamp_with_time_zone","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_timestamp_tz_to_date": {"display":"timestamp_with_time_zone_to_date","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_with_time_zone_to_date\", preserves_uniqueness = false, inverse = to_unary!(super::CastDateToTimestampTz(None)), is_monotone = true)] fn cast_timestamp_tz_to_date(a: CheckedTimestamp>) -> Result","body_fingerprint":"ccad20bb42ff4c4b"}, + "cast_timestamp_tz_to_date": {"display":"timestamp_with_time_zone_to_date","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_with_time_zone_to_date\", preserves_uniqueness = false, inverse = super::CastDateToTimestampTz(None), is_monotone = true)] fn cast_timestamp_tz_to_date(a: CheckedTimestamp>) -> Result","body_fingerprint":"ccad20bb42ff4c4b"}, "cast_timestamp_tz_to_mz_timestamp": {"display":"timestamp_tz_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_tz_to_mz_timestamp\", is_monotone = true)] fn cast_timestamp_tz_to_mz_timestamp(a: CheckedTimestamp>,) -> Result","body_fingerprint":"21967251d0e3e387"}, - "cast_timestamp_tz_to_string": {"display":"timestamp_with_time_zone_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_with_time_zone_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToTimestampTz(None)))] fn cast_timestamp_tz_to_string(a: CheckedTimestamp>) -> String","body_fingerprint":"89e85f6ed441bf9d"}, + "cast_timestamp_tz_to_string": {"display":"timestamp_with_time_zone_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_with_time_zone_to_text\", preserves_uniqueness = true, inverse = super::CastStringToTimestampTz(None))] fn cast_timestamp_tz_to_string(a: CheckedTimestamp>) -> String","body_fingerprint":"89e85f6ed441bf9d"}, "cast_timestamp_tz_to_time": {"display":"timestamp_with_time_zone_to_time","sqlfunc_decl":"#[sqlfunc(sqlname = \"timestamp_with_time_zone_to_time\", preserves_uniqueness = false)] fn cast_timestamp_tz_to_time(a: CheckedTimestamp>) -> NaiveTime","body_fingerprint":"37aa04a94ad6e09f"}, "cast_timestamp_tz_to_timestamp": {"display":"timestamp_with_time_zone_to_timestamp","sqlfunc_decl":null,"body_fingerprint":null}, "cast_timestamp_tz_to_timestamp[widening]": {"display":"timestamp_with_time_zone_to_timestamp","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_uint16_to_float32": {"display":"uint2_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_real\", preserves_uniqueness = true, inverse = to_unary!(super::CastFloat32ToUint16), is_monotone = true)] fn cast_uint16_to_float32(a: u16) -> f32","body_fingerprint":"6ad73befb8ca2a34"}, - "cast_uint16_to_float64": {"display":"uint2_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_double\", preserves_uniqueness = true, inverse = to_unary!(super::CastFloat64ToUint16), is_monotone = true)] fn cast_uint16_to_float64(a: u16) -> f64","body_fingerprint":"8a67f84e8764d837"}, - "cast_uint16_to_int16": {"display":"uint2_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_smallint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt16ToUint16), is_monotone = true)] fn cast_uint16_to_int16(a: u16) -> Result","body_fingerprint":"106c56bf06c2a245"}, - "cast_uint16_to_int32": {"display":"uint2_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToUint16), is_monotone = true)] fn cast_uint16_to_int32(a: u16) -> i32","body_fingerprint":"bc65045bb6754831"}, - "cast_uint16_to_int64": {"display":"uint2_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToUint16), is_monotone = true)] fn cast_uint16_to_int64(a: u16) -> i64","body_fingerprint":"9c62c1a559decc6e"}, + "cast_uint16_to_float32": {"display":"uint2_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_real\", preserves_uniqueness = true, inverse = super::CastFloat32ToUint16, is_monotone = true)] fn cast_uint16_to_float32(a: u16) -> f32","body_fingerprint":"6ad73befb8ca2a34"}, + "cast_uint16_to_float64": {"display":"uint2_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_double\", preserves_uniqueness = true, inverse = super::CastFloat64ToUint16, is_monotone = true)] fn cast_uint16_to_float64(a: u16) -> f64","body_fingerprint":"8a67f84e8764d837"}, + "cast_uint16_to_int16": {"display":"uint2_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_smallint\", preserves_uniqueness = true, inverse = super::CastInt16ToUint16, is_monotone = true)] fn cast_uint16_to_int16(a: u16) -> Result","body_fingerprint":"106c56bf06c2a245"}, + "cast_uint16_to_int32": {"display":"uint2_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToUint16, is_monotone = true)] fn cast_uint16_to_int32(a: u16) -> i32","body_fingerprint":"bc65045bb6754831"}, + "cast_uint16_to_int64": {"display":"uint2_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToUint16, is_monotone = true)] fn cast_uint16_to_int64(a: u16) -> i64","body_fingerprint":"9c62c1a559decc6e"}, "cast_uint16_to_numeric": {"display":"uint2_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_uint16_to_numeric[scale]": {"display":"uint2_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_uint16_to_string": {"display":"uint2_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToUint16))] fn cast_uint16_to_string(a: u16) -> String","body_fingerprint":"9bf1ab0aacc40d76"}, - "cast_uint16_to_uint32": {"display":"uint2_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_uint4\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint32ToUint16), is_monotone = true)] fn cast_uint16_to_uint32(a: u16) -> u32","body_fingerprint":"dea4c81a20b621c5"}, - "cast_uint16_to_uint64": {"display":"uint2_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_uint8\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint64ToUint16), is_monotone = true)] fn cast_uint16_to_uint64(a: u16) -> u64","body_fingerprint":"b2d1e1ed622bf362"}, - "cast_uint32_to_float32": {"display":"uint4_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToUint32), is_monotone = true)] fn cast_uint32_to_float32(a: u32) -> f32","body_fingerprint":"5cbae9f61a68b6b7"}, - "cast_uint32_to_float64": {"display":"uint4_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_double\", preserves_uniqueness = true, inverse = to_unary!(super::CastFloat64ToUint32), is_monotone = true)] fn cast_uint32_to_float64(a: u32) -> f64","body_fingerprint":"8a67f84e8764d837"}, - "cast_uint32_to_int16": {"display":"uint4_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_smallint\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt16ToUint32), is_monotone = true)] fn cast_uint32_to_int16(a: u32) -> Result","body_fingerprint":"106c56bf06c2a245"}, - "cast_uint32_to_int32": {"display":"uint4_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_integer\", preserves_uniqueness = false, inverse = to_unary!(super::CastInt32ToUint32), is_monotone = true)] fn cast_uint32_to_int32(a: u32) -> Result","body_fingerprint":"de1123491c3c9cf9"}, - "cast_uint32_to_int64": {"display":"uint4_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToUint32), is_monotone = true)] fn cast_uint32_to_int64(a: u32) -> i64","body_fingerprint":"9c62c1a559decc6e"}, + "cast_uint16_to_string": {"display":"uint2_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_text\", preserves_uniqueness = true, inverse = super::CastStringToUint16)] fn cast_uint16_to_string(a: u16) -> String","body_fingerprint":"9bf1ab0aacc40d76"}, + "cast_uint16_to_uint32": {"display":"uint2_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_uint4\", preserves_uniqueness = true, inverse = super::CastUint32ToUint16, is_monotone = true)] fn cast_uint16_to_uint32(a: u16) -> u32","body_fingerprint":"dea4c81a20b621c5"}, + "cast_uint16_to_uint64": {"display":"uint2_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint2_to_uint8\", preserves_uniqueness = true, inverse = super::CastUint64ToUint16, is_monotone = true)] fn cast_uint16_to_uint64(a: u16) -> u64","body_fingerprint":"b2d1e1ed622bf362"}, + "cast_uint32_to_float32": {"display":"uint4_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToUint32, is_monotone = true)] fn cast_uint32_to_float32(a: u32) -> f32","body_fingerprint":"5cbae9f61a68b6b7"}, + "cast_uint32_to_float64": {"display":"uint4_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_double\", preserves_uniqueness = true, inverse = super::CastFloat64ToUint32, is_monotone = true)] fn cast_uint32_to_float64(a: u32) -> f64","body_fingerprint":"8a67f84e8764d837"}, + "cast_uint32_to_int16": {"display":"uint4_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_smallint\", preserves_uniqueness = false, inverse = super::CastInt16ToUint32, is_monotone = true)] fn cast_uint32_to_int16(a: u32) -> Result","body_fingerprint":"106c56bf06c2a245"}, + "cast_uint32_to_int32": {"display":"uint4_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_integer\", preserves_uniqueness = false, inverse = super::CastInt32ToUint32, is_monotone = true)] fn cast_uint32_to_int32(a: u32) -> Result","body_fingerprint":"de1123491c3c9cf9"}, + "cast_uint32_to_int64": {"display":"uint4_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToUint32, is_monotone = true)] fn cast_uint32_to_int64(a: u32) -> i64","body_fingerprint":"9c62c1a559decc6e"}, "cast_uint32_to_mz_timestamp": {"display":"uint4_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_mz_timestamp\", preserves_uniqueness = true, is_monotone = true)] fn cast_uint32_to_mz_timestamp(a: u32) -> Timestamp","body_fingerprint":"b0767bc58896866d"}, "cast_uint32_to_numeric": {"display":"uint4_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_uint32_to_numeric[scale]": {"display":"uint4_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_uint32_to_string": {"display":"uint4_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToUint32))] fn cast_uint32_to_string(a: u32) -> String","body_fingerprint":"6eaa3daac575f51c"}, - "cast_uint32_to_uint16": {"display":"uint4_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_uint2\", preserves_uniqueness = false, inverse = to_unary!(super::CastUint16ToUint32), is_monotone = true)] fn cast_uint32_to_uint16(a: u32) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, - "cast_uint32_to_uint64": {"display":"uint4_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_uint8\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint64ToUint32), is_monotone = true)] fn cast_uint32_to_uint64(a: u32) -> u64","body_fingerprint":"b2d1e1ed622bf362"}, - "cast_uint64_to_float32": {"display":"uint8_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_real\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat32ToUint64), is_monotone = true)] fn cast_uint64_to_float32(a: u64) -> f32","body_fingerprint":"5cbae9f61a68b6b7"}, - "cast_uint64_to_float64": {"display":"uint8_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_double\", preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToUint64), is_monotone = true)] fn cast_uint64_to_float64(a: u64) -> f64","body_fingerprint":"08e345cc4df1813c"}, - "cast_uint64_to_int16": {"display":"uint8_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_smallint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt16ToUint64), is_monotone = true)] fn cast_uint64_to_int16(a: u64) -> Result","body_fingerprint":"106c56bf06c2a245"}, - "cast_uint64_to_int32": {"display":"uint8_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_integer\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt32ToUint64), is_monotone = true)] fn cast_uint64_to_int32(a: u64) -> Result","body_fingerprint":"de1123491c3c9cf9"}, - "cast_uint64_to_int64": {"display":"uint8_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_bigint\", preserves_uniqueness = true, inverse = to_unary!(super::CastInt64ToUint64), is_monotone = true)] fn cast_uint64_to_int64(a: u64) -> Result","body_fingerprint":"0ad4c02482cd3a4d"}, + "cast_uint32_to_string": {"display":"uint4_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_text\", preserves_uniqueness = true, inverse = super::CastStringToUint32)] fn cast_uint32_to_string(a: u32) -> String","body_fingerprint":"6eaa3daac575f51c"}, + "cast_uint32_to_uint16": {"display":"uint4_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_uint2\", preserves_uniqueness = false, inverse = super::CastUint16ToUint32, is_monotone = true)] fn cast_uint32_to_uint16(a: u32) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, + "cast_uint32_to_uint64": {"display":"uint4_to_uint8","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint4_to_uint8\", preserves_uniqueness = true, inverse = super::CastUint64ToUint32, is_monotone = true)] fn cast_uint32_to_uint64(a: u32) -> u64","body_fingerprint":"b2d1e1ed622bf362"}, + "cast_uint64_to_float32": {"display":"uint8_to_real","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_real\", preserves_uniqueness = false, inverse = super::CastFloat32ToUint64, is_monotone = true)] fn cast_uint64_to_float32(a: u64) -> f32","body_fingerprint":"5cbae9f61a68b6b7"}, + "cast_uint64_to_float64": {"display":"uint8_to_double","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_double\", preserves_uniqueness = false, inverse = super::CastFloat64ToUint64, is_monotone = true)] fn cast_uint64_to_float64(a: u64) -> f64","body_fingerprint":"08e345cc4df1813c"}, + "cast_uint64_to_int16": {"display":"uint8_to_smallint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_smallint\", preserves_uniqueness = true, inverse = super::CastInt16ToUint64, is_monotone = true)] fn cast_uint64_to_int16(a: u64) -> Result","body_fingerprint":"106c56bf06c2a245"}, + "cast_uint64_to_int32": {"display":"uint8_to_integer","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_integer\", preserves_uniqueness = true, inverse = super::CastInt32ToUint64, is_monotone = true)] fn cast_uint64_to_int32(a: u64) -> Result","body_fingerprint":"de1123491c3c9cf9"}, + "cast_uint64_to_int64": {"display":"uint8_to_bigint","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_bigint\", preserves_uniqueness = true, inverse = super::CastInt64ToUint64, is_monotone = true)] fn cast_uint64_to_int64(a: u64) -> Result","body_fingerprint":"0ad4c02482cd3a4d"}, "cast_uint64_to_mz_timestamp": {"display":"uint8_to_mz_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_mz_timestamp\", preserves_uniqueness = true, is_monotone = true)] fn cast_uint64_to_mz_timestamp(a: u64) -> Timestamp","body_fingerprint":"bc3f020571556877"}, "cast_uint64_to_numeric": {"display":"uint8_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, "cast_uint64_to_numeric[scale]": {"display":"uint8_to_numeric","sqlfunc_decl":null,"body_fingerprint":null}, - "cast_uint64_to_string": {"display":"uint8_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToUint64))] fn cast_uint64_to_string(a: u64) -> String","body_fingerprint":"d3ae11258ec41861"}, - "cast_uint64_to_uint16": {"display":"uint8_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_uint2\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint16ToUint64), is_monotone = true)] fn cast_uint64_to_uint16(a: u64) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, - "cast_uint64_to_uint32": {"display":"uint8_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_uint4\", preserves_uniqueness = true, inverse = to_unary!(super::CastUint32ToUint64), is_monotone = true)] fn cast_uint64_to_uint32(a: u64) -> Result","body_fingerprint":"a030b0b7248d6b70"}, - "cast_uuid_to_string": {"display":"uuid_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uuid_to_text\", preserves_uniqueness = true, inverse = to_unary!(super::CastStringToUuid))] fn cast_uuid_to_string(u: Uuid) -> String","body_fingerprint":"3c6c65885274db4a"}, - "cast_var_char_to_string": {"display":"varchar_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"varchar_to_text\", preserves_uniqueness = true, is_eliminable_cast = true, inverse = to_unary!(super::CastStringToVarChar {length: None, fail_on_len: false,}),)] fn cast_var_char_to_string<'a>(a: VarChar<&'a str>) -> &'a str","body_fingerprint":"ba6f1e61cfed1bde"}, + "cast_uint64_to_string": {"display":"uint8_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_text\", preserves_uniqueness = true, inverse = super::CastStringToUint64)] fn cast_uint64_to_string(a: u64) -> String","body_fingerprint":"d3ae11258ec41861"}, + "cast_uint64_to_uint16": {"display":"uint8_to_uint2","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_uint2\", preserves_uniqueness = true, inverse = super::CastUint16ToUint64, is_monotone = true)] fn cast_uint64_to_uint16(a: u64) -> Result","body_fingerprint":"6e1da3fc5a1ea1ec"}, + "cast_uint64_to_uint32": {"display":"uint8_to_uint4","sqlfunc_decl":"#[sqlfunc(sqlname = \"uint8_to_uint4\", preserves_uniqueness = true, inverse = super::CastUint32ToUint64, is_monotone = true)] fn cast_uint64_to_uint32(a: u64) -> Result","body_fingerprint":"a030b0b7248d6b70"}, + "cast_uuid_to_string": {"display":"uuid_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"uuid_to_text\", preserves_uniqueness = true, inverse = super::CastStringToUuid)] fn cast_uuid_to_string(u: Uuid) -> String","body_fingerprint":"3c6c65885274db4a"}, + "cast_var_char_to_string": {"display":"varchar_to_text","sqlfunc_decl":"#[sqlfunc(sqlname = \"varchar_to_text\", preserves_uniqueness = true, is_eliminable_cast = true, inverse = super::CastStringToVarChar {length: None, fail_on_len: false,},)] fn cast_var_char_to_string<'a>(a: VarChar<&'a str>) -> &'a str","body_fingerprint":"ba6f1e61cfed1bde"}, "cbrt_float64": {"display":"cbrtf64","sqlfunc_decl":"#[sqlfunc(sqlname = \"cbrtf64\")] fn cbrt_float64(a: f64) -> f64","body_fingerprint":"ab1bb0604756c134"}, "ceil_float32": {"display":"ceilf32","sqlfunc_decl":"#[sqlfunc(sqlname = \"ceilf32\")] fn ceil_float32(a: f32) -> f32","body_fingerprint":"e901321fe4b5135a"}, "ceil_float64": {"display":"ceilf64","sqlfunc_decl":"#[sqlfunc(sqlname = \"ceilf64\")] fn ceil_float64(a: f64) -> f64","body_fingerprint":"e901321fe4b5135a"}, @@ -516,14 +516,14 @@ "mz_type_name": {"display":"mz_type_name","sqlfunc_decl":"#[sqlfunc] fn mz_type_name(oid: Oid) -> Option","body_fingerprint":"783f0ac69e525f59"}, "mz_validate_privileges": {"display":"mz_validate_privileges","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_validate_privileges\")] fn mz_validate_privileges(privileges: String) -> Result","body_fingerprint":"24f14aa3d6084878"}, "mz_validate_role_privilege": {"display":"mz_validate_role_privilege","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_validate_role_privilege\")] fn mz_validate_role_privilege(privilege: String) -> Result","body_fingerprint":"dfa620601fa04e4a"}, - "neg_float32": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = false, inverse = to_unary!(NegFloat32), is_monotone = true)] fn neg_float32(a: f32) -> f32","body_fingerprint":"eed9462be0936615"}, - "neg_float64": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = false, inverse = to_unary!(NegFloat64), is_monotone = true)] fn neg_float64(a: f64) -> f64","body_fingerprint":"eed9462be0936615"}, - "neg_int16": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = to_unary!(NegInt16), is_monotone = true)] fn neg_int16(a: i16) -> Result","body_fingerprint":"c79dbf2b948ca575"}, - "neg_int32": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = to_unary!(NegInt32), is_monotone = true)] fn neg_int32(a: i32) -> Result","body_fingerprint":"9e8a3d8b774e9eb7"}, - "neg_int64": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = to_unary!(NegInt64), is_monotone = true)] fn neg_int64(a: i64) -> Result","body_fingerprint":"1fda6bdf25c3ba84"}, - "neg_interval": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = to_unary!(super::NegInterval))] fn neg_interval(i: Interval) -> Result","body_fingerprint":"8103afafe9ec2da2"}, - "neg_numeric": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = to_unary!(NegNumeric), is_monotone = true)] fn neg_numeric(mut a: Numeric) -> Numeric","body_fingerprint":"e8ea884374a674de"}, - "not": {"display":"NOT","sqlfunc_decl":"#[sqlfunc(sqlname = \"NOT\", preserves_uniqueness = true, inverse = to_unary!(Not), is_monotone = true)] fn not(a: bool) -> bool","body_fingerprint":"de26b65a3695fb67"}, + "neg_float32": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = false, inverse = NegFloat32, is_monotone = true)] fn neg_float32(a: f32) -> f32","body_fingerprint":"eed9462be0936615"}, + "neg_float64": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = false, inverse = NegFloat64, is_monotone = true)] fn neg_float64(a: f64) -> f64","body_fingerprint":"eed9462be0936615"}, + "neg_int16": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = NegInt16, is_monotone = true)] fn neg_int16(a: i16) -> Result","body_fingerprint":"c79dbf2b948ca575"}, + "neg_int32": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = NegInt32, is_monotone = true)] fn neg_int32(a: i32) -> Result","body_fingerprint":"9e8a3d8b774e9eb7"}, + "neg_int64": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = NegInt64, is_monotone = true)] fn neg_int64(a: i64) -> Result","body_fingerprint":"1fda6bdf25c3ba84"}, + "neg_interval": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = super::NegInterval)] fn neg_interval(i: Interval) -> Result","body_fingerprint":"8103afafe9ec2da2"}, + "neg_numeric": {"display":"-","sqlfunc_decl":"#[sqlfunc(sqlname = \"-\", preserves_uniqueness = true, inverse = NegNumeric, is_monotone = true)] fn neg_numeric(mut a: Numeric) -> Numeric","body_fingerprint":"e8ea884374a674de"}, + "not": {"display":"NOT","sqlfunc_decl":"#[sqlfunc(sqlname = \"NOT\", preserves_uniqueness = true, inverse = Not, is_monotone = true)] fn not(a: bool) -> bool","body_fingerprint":"de26b65a3695fb67"}, "pad_char": {"display":"padchar","sqlfunc_decl":null,"body_fingerprint":null}, "pad_char[unbounded]": {"display":"padchar","sqlfunc_decl":null,"body_fingerprint":null}, "panic": {"display":"mz_panic","sqlfunc_decl":"#[sqlfunc(sqlname = \"mz_panic\")] fn panic<'a>(a: &'a str) -> String","body_fingerprint":"95469a722cc261a6"}, @@ -552,7 +552,7 @@ "redact_sql": {"display":"redact_sql","sqlfunc_decl":"#[sqlfunc] fn redact_sql(sql: &str) -> Result","body_fingerprint":"e51c438a74bfae3f"}, "regexp_match": {"display":"regexp_match[\"a+\", case_insensitive=false]","sqlfunc_decl":null,"body_fingerprint":null}, "regexp_split_to_array": {"display":"regexp_split_to_array[\"a+\", case_insensitive=false]","sqlfunc_decl":null,"body_fingerprint":null}, - "reverse": {"display":"reverse","sqlfunc_decl":"#[sqlfunc(preserves_uniqueness = true, inverse = to_unary!(Reverse))] fn reverse<'a>(a: &'a str) -> String","body_fingerprint":"0c1c74222afa8291"}, + "reverse": {"display":"reverse","sqlfunc_decl":"#[sqlfunc(preserves_uniqueness = true, inverse = Reverse)] fn reverse<'a>(a: &'a str) -> String","body_fingerprint":"0c1c74222afa8291"}, "round_float32": {"display":"roundf32","sqlfunc_decl":"#[sqlfunc(sqlname = \"roundf32\")] fn round_float32(a: f32) -> f32","body_fingerprint":"726a414c9bcfc312"}, "round_float64": {"display":"roundf64","sqlfunc_decl":"#[sqlfunc(sqlname = \"roundf64\")] fn round_float64(a: f64) -> f64","body_fingerprint":"726a414c9bcfc312"}, "round_numeric": {"display":"roundnumeric","sqlfunc_decl":"#[sqlfunc(sqlname = \"roundnumeric\", is_monotone = true)] fn round_numeric(mut a: Numeric) -> Numeric","body_fingerprint":"9f85cf9238995ce1"}, @@ -590,7 +590,7 @@ "and": {"display":"AND","sqlfunc_decl":null,"body_fingerprint":null}, "array_create": {"display":"array_create","sqlfunc_decl":"#[sqlfunc(ArrayCreate, output_type_expr = \"match &self.elem_type { SqlScalarType::Array(_) => self.elem_type.clone().nullable(false), _ => SqlScalarType::Array(Box::new(self.elem_type.clone())).nullable(false) }\", introduces_nulls = false)] fn array_create<'a>(&self, datums: Variadic>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"37bebf040b665d37"}, "array_fill": {"display":"array_fill","sqlfunc_decl":"#[sqlfunc(ArrayFill, output_type_expr = \"SqlScalarType::Array(Box::new(self.elem_type.clone())).nullable(false)\", introduces_nulls = false)] fn array_fill<'a>(&self, fill: Datum<'a>, dims: Option>, lower_bounds: OptionalArg>>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"56cda42de9453873"}, - "array_index": {"display":"array_index","sqlfunc_decl":"#[sqlfunc(ArrayIndex, sqlname = \"array_index\", introduces_nulls = true)] fn array_index<'a, T: FromDatum<'a>>(&self, array: Array<'a, T>, indices: Variadic,) -> Option","body_fingerprint":"840ba88214eccddb"}, + "array_index": {"display":"array_index","sqlfunc_decl":"#[sqlfunc(ArrayIndex, sqlname = \"array_index\")] fn array_index<'a, T: FromDatum<'a>>(&self, array: Array<'a, T>, indices: Variadic,) -> Option","body_fingerprint":"840ba88214eccddb"}, "array_position": {"display":"array_position","sqlfunc_decl":"#[sqlfunc] fn array_position<'a>(array: Array<'a>, search: Datum<'a>, initial_pos: OptionalArg>,) -> Result, EvalError>","body_fingerprint":"f9edd12fe2a084fe"}, "array_to_string": {"display":"array_to_string","sqlfunc_decl":"#[sqlfunc] fn array_to_string<'a>(&self, array: Array<'a>, delimiter: &str, null_str_arg: OptionalArg>, temp_storage: &RowArena,) -> Result","body_fingerprint":"549bbda8f04d8a10"}, "case_literal": {"display":"case_literal[1 cases]","sqlfunc_decl":null,"body_fingerprint":null}, @@ -611,7 +611,7 @@ "jsonb_build_object": {"display":"jsonb_build_object","sqlfunc_decl":"#[sqlfunc] fn jsonb_build_object<'a>(mut kvs: Variadic<(Datum<'a>, Datum<'a>)>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"3cad7e59cbb01abb"}, "least": {"display":"least","sqlfunc_decl":null,"body_fingerprint":null}, "list_create": {"display":"list_create","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::List { element_type: Box::new(self.elem_type.clone()), custom_id: None }.nullable(false)\", introduces_nulls = false)] fn list_create<'a>(&self, datums: Variadic>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"33c53edba0b092fb"}, - "list_index": {"display":"list_index","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.unwrap_list_nth_layer_type(input_types.len() - 1).clone().nullable(true)\", introduces_nulls = true)] fn list_index<'a>(buf: DatumList<'a>, indices: Variadic) -> Datum<'a>","body_fingerprint":"57fb9087cef6d141"}, + "list_index": {"display":"list_index","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.unwrap_list_nth_layer_type(input_types.len() - 1).clone().nullable(true)\")] fn list_index<'a>(buf: DatumList<'a>, indices: Variadic) -> Datum<'a>","body_fingerprint":"57fb9087cef6d141"}, "list_slice_linear": {"display":"list_slice_linear","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"input_types[0].scalar_type.clone().nullable(false)\", introduces_nulls = false)] fn list_slice_linear<'a>(list: DatumList<'a>, first: (i64, i64), remainder: Variadic<(i64, i64)>, temp_storage: &'a RowArena,) -> Datum<'a>","body_fingerprint":"cf2a665e88d1643d"}, "make_acl_item": {"display":"makeaclitem","sqlfunc_decl":"#[sqlfunc(sqlname = \"makeaclitem\")] fn make_acl_item(grantee_oid: u32, grantor_oid: u32, privileges: &str, is_grantable: bool,) -> Result","body_fingerprint":"1c05a3379c7fda3b"}, "make_mz_acl_item": {"display":"make_mz_aclitem","sqlfunc_decl":"#[sqlfunc(sqlname = \"make_mz_aclitem\")] fn make_mz_acl_item(grantee_str: &str, grantor_str: &str, privileges: &str,) -> Result","body_fingerprint":"b641508330ebb598"}, @@ -619,9 +619,9 @@ "map_build": {"display":"map_build","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Map { value_type: Box::new(self.value_type.clone()), custom_id: None }.nullable(false)\", introduces_nulls = false)] fn map_build<'a>(&self, datums: Variadic<(Option<&str>, Datum<'a>)>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"3cf673accdd42c16"}, "or": {"display":"OR","sqlfunc_decl":null,"body_fingerprint":null}, "pad_leading": {"display":"lpad","sqlfunc_decl":"#[sqlfunc(sqlname = \"lpad\")] fn pad_leading(string: &str, raw_len: i32, pad: OptionalArg<&str>, temp_storage: &RowArena,) -> Result","body_fingerprint":"029efffef6e8305f"}, - "range_create": {"display":"int4range","sqlfunc_decl":null,"body_fingerprint":null}, + "range_create": {"display":"int4range","sqlfunc_decl":"#[sqlfunc(RangeCreate, skip_display = true, output_type_expr = \"SqlScalarType::Range { element_type: Box::new(self.elem_type.clone()) }.nullable(false)\")] fn range_create<'a>(&self, lower: Datum<'a>, upper: Datum<'a>, flags_datum: Datum<'a>,) -> Result>, EvalError>","body_fingerprint":"c21eff7867791358"}, "record_create": {"display":"record_create","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Record { fields: self.field_names.clone().into_iter().zip_eq(input_types.iter().cloned()).collect(), custom_id: None }.nullable(false)\", introduces_nulls = false)] fn record_create<'a>(&self, datums: Variadic>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"92fe79be327ac13b"}, - "regexp_match": {"display":"regexp_match","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true)\", introduces_nulls = true)] fn regexp_match<'a>(haystack: &'a str, needle: &str, flags: OptionalArg<&str>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"b4cc3a20cfd56b95"}, + "regexp_match": {"display":"regexp_match","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true)\")] fn regexp_match<'a>(haystack: &'a str, needle: &str, flags: OptionalArg<&str>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"b4cc3a20cfd56b95"}, "regexp_replace": {"display":"regexp_replace","sqlfunc_decl":"#[sqlfunc] fn regexp_replace<'a>(source: &'a str, pattern: &str, replacement: &str, flags_opt: OptionalArg<&str>, temp_storage: &RowArena,) -> Result, EvalError>","body_fingerprint":"b90fa61dbc761b25"}, "regexp_split_to_array": {"display":"regexp_split_to_array","sqlfunc_decl":"#[sqlfunc(output_type_expr = \"SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)\", introduces_nulls = false)] fn regexp_split_to_array<'a>(text: &str, regexp_str: &str, flags: OptionalArg<&str>, temp_storage: &'a RowArena,) -> Result, EvalError>","body_fingerprint":"ef10171f781288f9"}, "replace": {"display":"replace","sqlfunc_decl":"#[sqlfunc] fn replace(text: &str, from: &str, to: &str, temp_storage: &RowArena) -> Result","body_fingerprint":"bfaeb5ab9715cbb8"}, diff --git a/src/expr-derive-impl/src/generate.rs b/src/expr-derive-impl/src/generate.rs index 8203dca714909..cd51c76d523f5 100644 --- a/src/expr-derive-impl/src/generate.rs +++ b/src/expr-derive-impl/src/generate.rs @@ -11,7 +11,7 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; -use crate::modifiers::{Modifiers, reject_inapplicable}; +use crate::modifiers::Modifiers; use crate::shape::{Modifier, Shape}; use crate::signature; use crate::source::sqlfunc_source; @@ -28,7 +28,6 @@ fn override_methods( mods: &Modifiers, mut introduces_nulls_fn: Option, ) -> Vec { - let present: Vec<_> = mods.iter().collect(); shape .modifiers() .iter() @@ -36,15 +35,13 @@ fn override_methods( if *modifier == Modifier::IntroducesNulls { return introduces_nulls_fn.take(); } - let expr = present - .iter() - .find(|(candidate, _)| candidate == modifier) - .map(|(_, expr)| *expr)?; - let name = Ident::new(modifier.name(), proc_macro2::Span::call_site()); - let ret = ret.to_tokens(); + let expr = mods.get(*modifier)?; + let name = Ident::new(modifier.name(), Span::call_site()); + let body = ret.body(expr); + let ret = ret.tokens(); Some(quote! { fn #name(&self) -> #ret { - #expr + #body } }) }) @@ -61,11 +58,14 @@ struct Codegen { /// The registry's record of this function's source, generated as members of the /// `FuncName` impl. source: TokenStream, + /// Suppresses the generated `Display` impl, so a call site whose SQL name + /// depends on struct state can supply its own. + skip_display: bool, } /// Wraps an arity's trait impl with the parts every arity shares: the unit-struct -/// definition (unless `has_self`), the `Display` impl, the `FuncName` impl, and the -/// annotated function itself. +/// definition (unless `has_self`), the `Display` impl (unless `skip_display`), the +/// `FuncName` impl, and the annotated function itself. fn expand(e: &Codegen, func: &syn::ItemFn, trait_impl: TokenStream) -> TokenStream { let func_name = &func.sig.ident; let Codegen { @@ -73,12 +73,17 @@ fn expand(e: &Codegen, func: &syn::ItemFn, trait_impl: TokenStream) -> TokenStre has_self, sqlname, source, + skip_display, } = e; - let display_impl = quote! { - impl std::fmt::Display for #struct_name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str(#sqlname) + let display_impl = if *skip_display { + quote! {} + } else { + quote! { + impl std::fmt::Display for #struct_name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(#sqlname) + } } } }; @@ -118,122 +123,122 @@ fn expand(e: &Codegen, func: &syn::ItemFn, trait_impl: TokenStream) -> TokenStre } } -/// A variadic function's parameter names and their pre-erasure types, skipping the -/// receiver and the trailing `&RowArena`. -fn variadic_params( - func: &syn::ItemFn, - arena: bool, - has_self: bool, -) -> darling::Result<(Vec, Vec)> { - let start = usize::from(has_self); - let end = func.sig.inputs.len() - usize::from(arena); - if end == start { - return Err(darling::Error::custom( - "variadic function must have at least one input parameter", - )); - } - +/// The SQL arguments' pre-erasure types, and the names `call` binds them to. +/// +/// Unary and binary bind their inputs positionally as `a` and `b`, ignoring how the +/// function spells its parameters, while variadic forwards the real names. +fn sql_params(shape: Shape, func: &syn::ItemFn) -> darling::Result<(Vec, Vec)> { + // `crate::sqlfunc::determine_shape` gives unary one SQL argument and binary two. + const POSITIONAL: [&str; 2] = ["a", "b"]; let mut types = Vec::new(); let mut names = Vec::new(); - for param in func.sig.inputs.iter().skip(start).take(end - start) { - match param { - syn::FnArg::Typed(pat) => { + for (position, param) in signature::sql_args(func).into_iter().enumerate() { + let syn::FnArg::Typed(pat) = param else { + return Err(darling::Error::custom("unexpected self parameter").with_span(param)); + }; + let name = match shape { + Shape::Unary | Shape::Binary => Ident::new(POSITIONAL[position], Span::call_site()), + Shape::Variadic => { let syn::Pat::Ident(ident) = &*pat.pat else { return Err( darling::Error::custom("unsupported parameter pattern").with_span(&pat.pat) ); }; - names.push(ident.ident.clone()); - types.push(signature::patch_lifetimes(&pat.ty)); + ident.ident.clone() } - syn::FnArg::Receiver(_) => { - return Err(darling::Error::custom("unexpected self parameter")); + }; + types.push(signature::patch_lifetimes(&pat.ty)); + names.push(name); + } + Ok((types, names)) +} + +/// The column type expression the output-type method starts from, and the +/// `introduces_nulls` method if one is generated. +/// +/// `output_type`, `output_type_expr` and `introduces_nulls` decide both together. A +/// generic signature that sets neither output modifier derives them from where its +/// type parameters appear. +fn output_type_and_introduces_nulls( + shape: Shape, + mods: &Modifiers, + param_types_raw: &[syn::Type], + output_ty_raw: &syn::Type, + generic_params: &[Ident], +) -> darling::Result<(TokenStream, Option)> { + let output_type = mods.output_type(); + let mut output_type_expr = mods.output_type_expr().map(|expr| quote! { #expr }); + let mut introduces_nulls = mods + .get(Modifier::IntroducesNulls) + .map(|expr| quote! { #expr }); + + // Derive the output type from where the generic parameters land. This reads the + // pre-erasure types, because erasure is what removes those parameters. + if !generic_params.is_empty() && output_type.is_none() && output_type_expr.is_none() { + if let Some(derived) = signature::derive_output_type_for_generics( + param_types_raw, + output_ty_raw, + generic_params, + shape == Shape::Unary, + )? { + output_type_expr = Some(derived); + if introduces_nulls.is_none() { + let nullable = signature::is_option_wrapped(output_ty_raw); + introduces_nulls = Some(quote! { #nullable }); } } } - Ok((types, names)) + + let column_type = match (output_type, output_type_expr) { + (Some(output_type), _) => quote! { <#output_type>::as_column_type() }, + (None, Some(output_type_expr)) => output_type_expr, + (None, None) => quote! { Self::Output::as_column_type() }, + }; + // Without an `introduces_nulls` method the trait default reads `Self::Output`, + // which an explicit `output_type` replaces. + let introduces_nulls = introduces_nulls.or_else(|| { + output_type.map(|output_type| { + quote! { <#output_type as ::mz_repr::OutputDatumType<'_, ()>>::nullable() } + }) + }); + let introduces_nulls_fn = introduces_nulls.map(|introduces_nulls| { + quote! { + fn introduces_nulls(&self) -> bool { + #introduces_nulls + } + } + }); + Ok((column_type, introduces_nulls_fn)) } /// Generates the trait impl for one `#[sqlfunc]`-annotated function, together with the /// items [`expand`] wraps around it. /// -/// `struct_ty` names the generated struct when the call site spells one, which only -/// the variadic arity accepts. `has_self` says the annotated function takes a -/// receiver, so the trait's `call` dispatches through it. +/// `struct_ty` names the generated struct when the call site spells one. pub(crate) fn generate( shape: Shape, func: &syn::ItemFn, mods: Modifiers, struct_ty: Option, - has_self: bool, attr: &TokenStream, ) -> darling::Result { - reject_inapplicable(shape, &mods)?; - let fn_name = &func.sig.ident; let struct_name = struct_ty .as_ref() .and_then(|ty| ty.segments.last()) .map_or_else(|| signature::camel_case(fn_name), |seg| seg.ident.clone()); - // Whether the annotated function itself wants the arena, which is independent of - // whether the trait's `call` receives one. + // A receiver makes `call` dispatch through `self` to a method on a struct defined + // at the call site. + let has_self = signature::has_receiver(func); + mods.validate(shape, has_self)?; + // Whether the annotated function takes the arena. The trait's `call` always receives + // one. let arena = signature::last_is_arena(func); let output_ty_raw = signature::output_type(func)?; let generic_params = signature::find_generic_type_params(func); - // Unary and binary bind their inputs positionally, ignoring how the function - // spells its parameters, while variadic forwards the real names. - let (param_types_raw, param_names) = match shape { - Shape::Unary => ( - vec![signature::arg_type(func, 0)?], - vec![Ident::new("a", Span::call_site())], - ), - Shape::Binary => ( - vec![signature::arg_type(func, 0)?, signature::arg_type(func, 1)?], - vec![ - Ident::new("a", Span::call_site()), - Ident::new("b", Span::call_site()), - ], - ), - Shape::Variadic => variadic_params(func, arena, has_self)?, - }; - - let output_type = mods.output_type().cloned(); - let mut output_type_expr = mods.output_type_expr().cloned(); - let mut introduces_nulls = mods.introduces_nulls().cloned(); - - // Derive the output type from where the generic parameters land. This reads the - // pre-erasure types, because erasure is what removes those parameters. - if !generic_params.is_empty() && output_type.is_none() && output_type_expr.is_none() { - if let Some(derived) = signature::derive_output_type_for_generics( - ¶m_types_raw, - output_ty_raw, - &generic_params, - shape == Shape::Unary, - )? { - output_type_expr = Some(syn::parse2(derived)?); - if introduces_nulls.is_none() { - let nullable = signature::is_option_wrapped(output_ty_raw); - introduces_nulls = Some(syn::parse_quote!(#nullable)); - } - } - } - - // TODO: these two conflict checks construct their error with `unknown_field`, - // which renders as "Unknown field: ", while every other modifier - // legality error in the crate uses `Error::custom`. The message text is pinned - // by a snapshot, so changing the constructor requires updating that snapshot. - if output_type.is_some() && output_type_expr.is_some() { - return Err(darling::Error::unknown_field( - "output_type and output_type_expr cannot be used together", - )); - } - if output_type_expr.is_some() && introduces_nulls.is_none() { - return Err(darling::Error::unknown_field( - "output_type_expr requires introduces_nulls", - )); - } + let (param_types_raw, param_names) = sql_params(shape, func)?; // Replace generic type params with `Datum<'a>` for use in the trait impl's associated // types, where the function's parameters are not in scope. @@ -255,39 +260,15 @@ pub(crate) fn generate( quote! { (#(#param_names),*) } }; - let (mut output_type_code, mut introduces_nulls_fn) = if let Some(output_type) = output_type { - let introduces_nulls_fn = quote! { - fn introduces_nulls(&self) -> bool { - <#output_type as ::mz_repr::OutputDatumType<'_, ()>>::nullable() - } - }; - ( - quote! { <#output_type>::as_column_type() }, - Some(introduces_nulls_fn), - ) - } else { - (quote! { Self::Output::as_column_type() }, None) - }; - - if let Some(output_type_expr) = output_type_expr { - output_type_code = quote! { #output_type_expr }; - } - - if let Some(introduces_nulls) = introduces_nulls { - introduces_nulls_fn = Some(quote! { - fn introduces_nulls(&self) -> bool { - #introduces_nulls - } - }); - } - + let (output_type_code, introduces_nulls_fn) = output_type_and_introduces_nulls( + shape, + &mods, + ¶m_types_raw, + output_ty_raw, + &generic_params, + )?; let methods = override_methods(shape, &mods, introduces_nulls_fn); - let arena_param = if shape.takes_arena() { - quote! { , temp_storage: &'a mz_repr::RowArena } - } else { - quote! {} - }; let arena_arg = if arena { quote! { , temp_storage } } else { @@ -310,8 +291,8 @@ pub(crate) fn generate( fn call<'a>( &self, - #destructure: Self::Input<'a> - #arena_param + #destructure: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, ) -> Self::Output<'a> { #receiver #fn_name(#(#param_names),* #arena_arg) } @@ -339,6 +320,7 @@ pub(crate) fn generate( has_self, sqlname, source: sqlfunc_source(attr, func, ¶m_types_raw, output_ty_raw, ¶m_types), + skip_display: mods.skip_display(), }; Ok(expand(&codegen, func, trait_impl)) } diff --git a/src/expr-derive-impl/src/lib.rs b/src/expr-derive-impl/src/lib.rs index 6746e7e218f47..dc2f4018f061f 100644 --- a/src/expr-derive-impl/src/lib.rs +++ b/src/expr-derive-impl/src/lib.rs @@ -22,15 +22,8 @@ mod sqlfunc; pub use sqlfunc::sqlfunc; -/// Non-exported version of `sqlfunc` for testing purposes, accepting proc_macro2 token streams. -#[cfg(any(feature = "test", test))] -fn sqlfunc_for_test( - attr: proc_macro2::TokenStream, - item: proc_macro2::TokenStream, -) -> darling::Result { - sqlfunc(attr, item, false) -} - +/// Expands `#[sqlfunc(attr)]` on `item` and returns the formatted expansion, or the +/// formatted errors, along with the formatted input. #[cfg(any(feature = "test", test))] pub fn test_sqlfunc( attr: proc_macro2::TokenStream, @@ -43,356 +36,18 @@ pub fn test_sqlfunc( let input = rust_fmt(&format!("#[sqlfunc({attr})]\n{item}")); let output = rust_fmt( - &sqlfunc_for_test(attr, item) + &sqlfunc(attr, item, false) .unwrap_or_else(|err| err.write_errors()) .to_string(), ); (output, input) } +/// [`test_sqlfunc`] over source text, as the generated snapshot tests pass it. #[cfg(any(feature = "test", test))] pub fn test_sqlfunc_str(attr: &str, item: &str) -> (String, String) { test_sqlfunc(attr.parse().unwrap(), item.parse().unwrap()) } #[cfg(test)] -mod test { - use quote::quote; - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_add_int16() { - let attr = quote! { - is_monotone = (true, true), - output_type = i16, - is_infix_op = true, - sqlname = "+", - propagates_nulls = true, - test = true, - }; - let item = quote! { - fn add_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result, EvalError> { - a.unwrap_int16() - .checked_add(b.unwrap_int16()) - .ok_or(EvalError::NumericFieldOverflow) - .map(Datum::from) - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("add_int16", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_unary() { - let attr = quote! {test = true}; - let item = quote! { - fn unary_fn<'a>(a: Datum<'a>) -> bool { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("unary_fn", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_unary_arena() { - let attr = quote! {test = true}; - let item = quote! { - fn unary_fn<'a>(a: Datum<'a>, temp_storage: &RowArena) -> bool { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("unary_arena_fn", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_unary_ref() { - let attr = quote! {test = true}; - let item = quote! { - fn unary_fn<'a>(a: &i16) -> bool { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("unary_ref", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_complex_output_type() { - let attr = quote! { - is_monotone = (true, true), - output_type = "Option", - is_infix_op = true, - sqlname = "test", - propagates_nulls = true, - test = true, - }; - let item = quote! { - fn complex_output_type_fn<'a>( - a: Datum<'a>, - b: Datum<'a>, - ) -> Result, EvalError> { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("complex_type", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_binary_arena() { - let attr = quote! {test = true}; - let item = quote! { - fn unary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("binary_arena_fn", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_variadic_tuple() { - let attr = quote! { - Replace, - sqlname = "replace", - }; - let item = quote! { - fn replace(text: &str, from: &str, to: &str) -> Result { - Ok(text.replace(from, to)) - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("variadic_tuple", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_variadic_variadic_type() { - let attr = quote! { - Concat, - sqlname = "concat", - is_associative = true, - }; - let item = quote! { - fn concat(strs: Variadic>) -> Result { - Ok(strs.into_iter().flatten().collect()) - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("variadic_variadic_type", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_variadic_arena() { - let attr = quote! { - ArrayFill, - sqlname = "array_fill", - introduces_nulls = false, - }; - let item = quote! { - fn array_fill<'a>( - &self, - fill: Datum<'a>, - dims: Datum<'a>, - lb: OptionalArg>, - temp_storage: &RowArena, - ) -> Result, EvalError> { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("variadic_arena", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_variadic_modifiers() { - let attr = quote! { - Greatest, - sqlname = "greatest", - could_error = false, - is_monotone = true, - }; - let item = quote! { - fn greatest<'a>(datums: Variadic>) -> Datum<'a> { - datums.into_iter().max().unwrap_or(Datum::Null) - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("variadic_modifiers", output, &input); - } - - #[cfg_attr(miri, ignore)] - #[mz_ore::test] - fn insta_test_unary_generic_range() { - let attr = quote! { - sqlname = "rangelower", - is_monotone = true, - }; - let item = quote! { - fn range_lower<'a, T>(a: Range) -> Option { - a.inner.map(|inner| inner.lower.bound).flatten() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("unary_generic_range", output, &input); - } - - #[cfg_attr(miri, ignore)] - #[mz_ore::test] - fn insta_test_binary_generic_list() { - let attr = quote! { - is_infix_op = true, - sqlname = "||", - propagates_nulls = false, - introduces_nulls = false, - }; - let item = quote! { - fn list_list_concat<'a, T>( - a: Option>, - b: Option>, - temp_storage: &'a RowArena, - ) -> Option> { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("binary_generic_list", output, &input); - } - - #[cfg_attr(miri, ignore)] - #[mz_ore::test] - fn insta_test_binary_multi_generic() { - let attr = quote! { - sqlname = "multi_generic", - }; - let item = quote! { - fn multi_generic<'a, A, B>( - a: DatumList<'a, A>, - b: DatumList<'a, B>, - ) -> Option { - unimplemented!() - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("binary_multi_generic", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_unary_all_modifiers() { - let attr = quote! { - could_error = true, - output_type = i16, - inverse = None, - is_monotone = true, - preserves_uniqueness = true, - is_eliminable_cast = false, - sqlname = "unary_all_modifiers", - }; - let item = quote! { - fn unary_all_modifiers<'a>(a: Datum<'a>) -> Datum<'a> { - a - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("unary_all_modifiers", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_binary_all_modifiers() { - let attr = quote! { - could_error = true, - output_type = i16, - is_infix_op = true, - is_monotone = (true, true), - is_infinity_monotone = false, - negate = None, - propagates_nulls = true, - sqlname = "binary_all_modifiers", - }; - let item = quote! { - fn binary_all_modifiers<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> { - a - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("binary_all_modifiers", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn insta_test_variadic_all_modifiers() { - let attr = quote! { - could_error = true, - output_type = i16, - is_infix_op = true, - is_monotone = true, - is_associative = true, - propagates_nulls = true, - sqlname = "variadic_all_modifiers", - }; - let item = quote! { - fn variadic_all_modifiers<'a>(datums: Variadic>) -> Datum<'a> { - datums.into_iter().next().unwrap_or(Datum::Null) - } - }; - let (output, input) = super::test_sqlfunc(attr, item); - insta::assert_snapshot!("variadic_all_modifiers", output, &input); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn unknown_modifier_is_an_error() { - let (output, _input) = super::test_sqlfunc( - quote! { not_a_modifier = true }, - quote! { - fn some_unary<'a>(a: i32) -> i32 { a } - }, - ); - assert!( - output.contains("not_a_modifier"), - "expected an error naming the unknown modifier, got:\n{output}" - ); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn unary_rejects_negate_by_name() { - let (output, _input) = crate::test_sqlfunc( - quote! { negate = to_unary!(super::Foo) }, - quote! { - fn some_unary<'a>(a: i32) -> i32 { a } - }, - ); - assert!( - output.contains("`negate` is not supported for unary functions"), - "expected an error naming the modifier and the arity, got:\n{output}" - ); - } - - #[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri - #[mz_ore::test] - fn unary_rejects_is_infinity_monotone() { - let (output, _input) = crate::test_sqlfunc( - quote! { is_infinity_monotone = false }, - quote! { - fn some_unary<'a>(a: i32) -> i32 { a } - }, - ); - assert!( - output.contains("`is_infinity_monotone` is not supported for unary functions"), - "is_infinity_monotone must be rejected on unary rather than ignored, got:\n{output}" - ); - } -} +mod test; diff --git a/src/expr-derive-impl/src/modifiers.rs b/src/expr-derive-impl/src/modifiers.rs index 9b80017465d9e..7c99d7df6c23b 100644 --- a/src/expr-derive-impl/src/modifiers.rs +++ b/src/expr-derive-impl/src/modifiers.rs @@ -8,10 +8,10 @@ // by the Apache License, Version 2.0. //! The `#[sqlfunc]` attribute's key-value modifiers. //! -//! [`Modifiers`] is the parsed attribute and [`reject_inapplicable`] gates it against -//! the per-arity tables in [`crate::shape`]. Modifiers that feed `Display` or the -//! output-type body have their own accessors, and the ones that map onto a trait method -//! are reached through [`Modifiers::iter`]. +//! [`Modifiers`] is the parsed attribute. [`Modifiers::validate`] checks it before +//! anything is generated. Modifiers that feed `Display` or the output-type body have +//! their own accessors, and the ones that map onto a trait method are reached through +//! [`Modifiers::get`]. use proc_macro2::TokenStream; use quote::quote; @@ -20,9 +20,6 @@ use syn::{Expr, Lit}; use crate::shape::{Modifier, Shape}; /// Modifiers passed as key-value pairs to the `#[sqlfunc]` macro. -/// -/// Which arities accept which modifier is declared by the tables in [`crate::shape`], -/// not here. [`reject_inapplicable`] enforces it. #[derive(Debug, Default, darling::FromMeta)] pub(crate) struct Modifiers { /// Whether the function is monotone with respect to its arguments. Binary functions @@ -57,6 +54,9 @@ pub(crate) struct Modifiers { is_eliminable_cast: Option, /// Whether to generate a snapshot test for the function. Defaults to false. test: Option, + /// Suppresses the generated `fmt::Display`. Set this when the struct's name + /// depends on its state, so the call site keeps a hand-written impl. + skip_display: Option, } impl Modifiers { @@ -83,62 +83,73 @@ impl Modifiers { self.output_type_expr.as_ref() } - /// The call site's `introduces_nulls`, which `crate::generate::generate` combines - /// with the output type instead of emitting it on its own. - pub(crate) fn introduces_nulls(&self) -> Option<&Expr> { - self.introduces_nulls.as_ref() + /// Whether the call site asked to suppress the generated `Display` impl. + pub(crate) fn skip_display(&self) -> bool { + self.skip_display.unwrap_or(false) } - /// The method-producing modifiers that are present, in this method's own fixed - /// order, which does not match any of the three per-arity tables in - /// `crate::shape`. A caller that needs table order joins against - /// `Shape::modifiers()` by `Modifier` instead. - /// - /// Modifiers that do not produce a trait method are excluded, because - /// `crate::generate::generate` reads those through their accessors. - /// `introduces_nulls` is included so [`reject_inapplicable`] checks it, although - /// `crate::generate::generate` builds its method from the output type. - pub(crate) fn iter(&self) -> impl Iterator + '_ { - [ - (Modifier::CouldError, self.could_error.as_ref()), - (Modifier::IntroducesNulls, self.introduces_nulls.as_ref()), - (Modifier::IsMonotone, self.is_monotone.as_ref()), - (Modifier::IsInfixOp, self.is_infix_op.as_ref()), - (Modifier::PropagatesNulls, self.propagates_nulls.as_ref()), - (Modifier::Inverse, self.inverse.as_ref()), - ( - Modifier::PreservesUniqueness, - self.preserves_uniqueness.as_ref(), - ), - (Modifier::IsEliminableCast, self.is_eliminable_cast.as_ref()), - (Modifier::Negate, self.negate.as_ref()), - ( - Modifier::IsInfinityMonotone, - self.is_infinity_monotone.as_ref(), - ), - (Modifier::IsAssociative, self.is_associative.as_ref()), - ] - .into_iter() - .filter_map(|(modifier, expr)| expr.map(|expr| (modifier, expr))) + /// The expression the call site gave a method-producing modifier, if any. + pub(crate) fn get(&self, modifier: Modifier) -> Option<&Expr> { + match modifier { + Modifier::CouldError => self.could_error.as_ref(), + Modifier::IntroducesNulls => self.introduces_nulls.as_ref(), + Modifier::IsMonotone => self.is_monotone.as_ref(), + Modifier::IsInfixOp => self.is_infix_op.as_ref(), + Modifier::PropagatesNulls => self.propagates_nulls.as_ref(), + Modifier::Inverse => self.inverse.as_ref(), + Modifier::PreservesUniqueness => self.preserves_uniqueness.as_ref(), + Modifier::IsEliminableCast => self.is_eliminable_cast.as_ref(), + Modifier::Negate => self.negate.as_ref(), + Modifier::IsInfinityMonotone => self.is_infinity_monotone.as_ref(), + Modifier::IsAssociative => self.is_associative.as_ref(), + } } -} -/// Errors if `mods` carries a method-producing modifier `shape` does not accept. -pub(crate) fn reject_inapplicable(shape: Shape, mods: &Modifiers) -> darling::Result<()> { - for (modifier, _) in mods.iter() { - let accepted = shape - .modifiers() - .iter() - .any(|(candidate, _)| *candidate == modifier); - if !accepted { - return Err(darling::Error::custom(format!( - "`{}` is not supported for {} functions", - modifier.name(), - shape.label(), - ))); + /// Errors if a modifier does not apply to `shape`, or conflicts with another + /// modifier or with the function's receiver. Reports every problem, each at the + /// modifier it concerns. + pub(crate) fn validate(&self, shape: Shape, has_self: bool) -> darling::Result<()> { + let mut errors = darling::Error::accumulator(); + for modifier in Modifier::ALL { + let Some(expr) = self.get(modifier) else { + continue; + }; + if !shape.accepts(modifier) { + errors.push( + darling::Error::custom(format!( + "`{}` is not supported for {} functions", + modifier.name(), + shape.label(), + )) + .with_span(expr), + ); + } + } + if let (Some(_), Some(expr)) = (&self.output_type, &self.output_type_expr) { + errors.push( + darling::Error::custom("output_type and output_type_expr cannot be used together") + .with_span(expr), + ); + } + if self.skip_display() { + if let Some(sqlname) = &self.sqlname { + errors.push( + darling::Error::custom( + "sqlname has no effect with skip_display, which suppresses the only impl that reads it", + ) + .with_span(sqlname), + ); + } + // A hand-written `Display` is only needed when the name depends on struct + // state, and without `&self` the macro defines a unit struct that has none. + if !has_self { + errors.push(darling::Error::custom( + "skip_display requires a &self receiver, since a unit struct has no state for a hand-written Display to read", + )); + } } + errors.finish() } - Ok(()) } /// A name for the SQL function. It can be either a literal or a macro, thus we diff --git a/src/expr-derive-impl/src/shape.rs b/src/expr-derive-impl/src/shape.rs index 22de6fe8f70df..c05f4a5a08183 100644 --- a/src/expr-derive-impl/src/shape.rs +++ b/src/expr-derive-impl/src/shape.rs @@ -26,8 +26,8 @@ pub(crate) enum Shape { /// A modifier that maps directly onto one optional trait method. /// /// Modifiers that do not produce a trait method, such as `sqlname`, `output_type`, -/// `output_type_expr`, and `test`, are absent: `crate::generate::generate` handles -/// those explicitly because they feed `Display`, the output-type body, or the +/// `output_type_expr`, `test`, and `skip_display`, are absent: `crate::generate::generate` +/// handles those explicitly because they feed `Display`, the output-type body, or the /// expansion decision instead. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum Modifier { @@ -45,6 +45,21 @@ pub(crate) enum Modifier { } impl Modifier { + /// Every method-producing modifier. + pub(crate) const ALL: [Modifier; 11] = [ + Modifier::CouldError, + Modifier::IntroducesNulls, + Modifier::IsMonotone, + Modifier::IsInfixOp, + Modifier::PropagatesNulls, + Modifier::Inverse, + Modifier::PreservesUniqueness, + Modifier::IsEliminableCast, + Modifier::Negate, + Modifier::IsInfinityMonotone, + Modifier::IsAssociative, + ]; + /// The attribute key, which is also the generated method name. pub(crate) fn name(&self) -> &'static str { match self { @@ -73,7 +88,7 @@ pub(crate) enum ReturnTy { } impl ReturnTy { - pub(crate) fn to_tokens(&self) -> TokenStream { + pub(crate) fn tokens(&self) -> TokenStream { match self { ReturnTy::Bool => quote! { bool }, ReturnTy::BoolPair => quote! { (bool, bool) }, @@ -81,12 +96,20 @@ impl ReturnTy { ReturnTy::OptBinaryFunc => quote! { Option }, } } + + /// The method body for a modifier whose value is `expr`. A function-valued + /// modifier names the function, and the body converts it into the enum. + pub(crate) fn body(&self, expr: &syn::Expr) -> TokenStream { + match self { + ReturnTy::Bool | ReturnTy::BoolPair => quote! { #expr }, + ReturnTy::OptUnaryFunc => quote! { Some(crate::UnaryFunc::from(#expr)) }, + ReturnTy::OptBinaryFunc => quote! { Some(crate::BinaryFunc::from(#expr)) }, + } + } } -// `crate::generate::override_methods` walks these tables in order to generate each -// arity's override methods. The order here therefore determines the method order -// in the generated code, which the insta snapshots under `sqlfunc.rs` pin exactly, -// so it is load-bearing, not cosmetic. +// `crate::generate::override_methods` walks these tables in order, so they also fix +// the method order in the generated code, which the snapshots in `crate::test` pin. const UNARY_MODIFIERS: &[(Modifier, ReturnTy)] = &[ (Modifier::CouldError, ReturnTy::Bool), (Modifier::IntroducesNulls, ReturnTy::Bool), @@ -126,6 +149,13 @@ impl Shape { } } + /// Whether this arity's table lists `modifier`. + pub(crate) fn accepts(&self, modifier: Modifier) -> bool { + self.modifiers() + .iter() + .any(|(candidate, _)| *candidate == modifier) + } + pub(crate) fn label(&self) -> &'static str { match self { Shape::Unary => "unary", @@ -168,14 +198,6 @@ impl Shape { } } - /// Whether the trait's `call` receives a `&'a RowArena`. - pub(crate) fn takes_arena(&self) -> bool { - match self { - Shape::Unary => false, - Shape::Binary | Shape::Variadic => true, - } - } - /// The tail of the output-type method, which sets the nullability of the /// `output` column type the caller computed. /// @@ -190,10 +212,18 @@ impl Shape { /// some input is nullable, because the optimizer short-circuits an all-NULL call. pub(crate) fn nullability(&self, checks: &[TokenStream]) -> TokenStream { match self { + // NOTE: unary omits the non-nullable-position term the other two arities + // carry. That is sound only because `PropagatesNulls` is absent from + // `UNARY_MODIFIERS`, so a unary `propagates_nulls` is always + // `!Input::nullable()`, which is what the position check tests for every + // parameter type in the tree. + // Adding `PropagatesNulls` to the unary table without also adding the term + // here lets `propagates_nulls = false` report a non-nullable output for an + // input the evaluation layer short-circuits to NULL. Shape::Unary => quote! { output.nullable(nullable || (propagates_nulls && input_type.nullable)) }, - Shape::Binary => quote! { + Shape::Binary | Shape::Variadic => quote! { let non_nullable_input_is_nullable = false #(#checks)*; let inputs_nullable = input_types.iter().any(|it| it.nullable); let is_null = nullable @@ -201,15 +231,6 @@ impl Shape { || (propagates_nulls && inputs_nullable); output.nullable(is_null) }, - Shape::Variadic => quote! { - let non_nullable_input_is_nullable = false #(#checks)*; - let inputs_nullable = input_types.iter().any(|it| it.nullable); - output.nullable( - nullable - || non_nullable_input_is_nullable - || (propagates_nulls && inputs_nullable) - ) - }, } } } @@ -218,21 +239,18 @@ impl Shape { mod tests { use super::{Modifier, Shape}; - fn has(shape: Shape, m: Modifier) -> bool { - shape - .modifiers() - .iter() - .any(|(candidate, _)| *candidate == m) - } - #[mz_ore::test] fn unary_accepts_inverse_and_rejects_negate() { - assert!(has(Shape::Unary, Modifier::Inverse)); - assert!(has(Shape::Unary, Modifier::PreservesUniqueness)); - assert!(has(Shape::Unary, Modifier::IsEliminableCast)); - assert!(!has(Shape::Unary, Modifier::Negate)); - assert!(!has(Shape::Unary, Modifier::IsInfixOp)); - assert!(!has(Shape::Unary, Modifier::PropagatesNulls)); - assert!(!has(Shape::Unary, Modifier::IsAssociative)); + assert!(Shape::Unary.accepts(Modifier::Inverse)); + assert!(Shape::Unary.accepts(Modifier::PreservesUniqueness)); + assert!(Shape::Unary.accepts(Modifier::IsEliminableCast)); + assert!(!Shape::Unary.accepts(Modifier::Negate)); + assert!(!Shape::Unary.accepts(Modifier::IsInfixOp)); + assert!( + !Shape::Unary.accepts(Modifier::PropagatesNulls), + "Shape::nullability omits unary's non-nullable-position term on the strength of \ + this absence" + ); + assert!(!Shape::Unary.accepts(Modifier::IsAssociative)); } } diff --git a/src/expr-derive-impl/src/signature.rs b/src/expr-derive-impl/src/signature.rs index 649daf95c5fcb..12a4a0599139f 100644 --- a/src/expr-derive-impl/src/signature.rs +++ b/src/expr-derive-impl/src/signature.rs @@ -33,6 +33,23 @@ pub(crate) fn last_is_arena(func: &syn::ItemFn) -> bool { }) } +/// The parameters that carry SQL arguments, which excludes a `&self` receiver and a +/// trailing `&RowArena`. +pub(crate) fn sql_args(func: &syn::ItemFn) -> Vec<&syn::FnArg> { + let end = func.sig.inputs.len() - usize::from(last_is_arena(func)); + func.sig + .inputs + .iter() + .take(end) + .skip(usize::from(has_receiver(func))) + .collect() +} + +/// Checks if the function takes a `self` receiver. +pub(crate) fn has_receiver(func: &syn::ItemFn) -> bool { + matches!(func.sig.inputs.first(), Some(syn::FnArg::Receiver(_))) +} + /// Checks if a parameter type accepts NULL. /// /// `Option` always accepts NULL. `OptionalArg` delegates to `T`. @@ -59,6 +76,21 @@ fn is_nullable_type(ty: &syn::Type) -> bool { false } +/// Checks whether a parameter's type is `Variadic<...>` or `OptionalArg<...>`, which +/// makes the function variadic regardless of parameter count. +pub(crate) fn is_variadic_arg(arg: &syn::FnArg) -> bool { + let syn::FnArg::Typed(pat) = arg else { + return false; + }; + let syn::Type::Path(path) = &*pat.ty else { + return false; + }; + path.path + .segments + .last() + .is_some_and(|segment| segment.ident == "Variadic" || segment.ident == "OptionalArg") +} + /// Checks if a type is `Variadic`. fn is_variadic_type(ty: &syn::Type) -> bool { if let syn::Type::Path(type_path) = ty { @@ -306,17 +338,18 @@ pub(crate) fn derive_output_type_for_generics( is_unary: bool, ) -> darling::Result> { // Find the first generic param that appears in the output. - let generic_name = match generic_names - .iter() - .find(|gn| classify_generic_usage(output_ty, gn) != GenericUsage::Absent) - { - Some(gn) => gn, - None => return Ok(None), + let Some((generic_name, output_usage)) = generic_names.iter().find_map(|gn| { + let usage = classify_generic_usage(output_ty, gn); + (usage != GenericUsage::Absent).then_some((gn, usage)) + }) else { + return Ok(None); }; - derive_output_type_for_generic(input_types, output_ty, generic_name, is_unary) + derive_output_type_for_generic(input_types, output_ty, generic_name, output_usage, is_unary) + .map(Some) } -/// Derives an `output_type_expr` for a single generic parameter. +/// Derives an `output_type_expr` for a single generic parameter, which appears in the +/// output type as `output_usage`. /// /// Uses `SqlContainerType` trait calls instead of matching on specific container /// type names. The generated code calls `::unwrap_element_type()` @@ -325,13 +358,9 @@ fn derive_output_type_for_generic( input_types: &[syn::Type], output_ty: &syn::Type, generic_name: &Ident, + output_usage: GenericUsage, is_unary: bool, -) -> darling::Result> { - let output_usage = classify_generic_usage(output_ty, generic_name); - if output_usage == GenericUsage::Absent { - return Ok(None); - } - +) -> darling::Result { let nullable = is_option_wrapped(output_ty); // Find the first input parameter that has T in a container. @@ -355,9 +384,9 @@ fn derive_output_type_for_generic( } let (pos, source_usage) = container_input.ok_or_else(|| { - darling::Error::custom( - "generic parameter T appears in the output type but not in any input type", - ) + darling::Error::custom(format!( + "generic parameter {generic_name} appears in the output type but not in any input type", + )) })?; // Generate the base expression to access the input type. @@ -454,7 +483,7 @@ fn derive_output_type_for_generic( } }; - Ok(Some(expr)) + Ok(expr) } /// Generates a token stream that extracts the T-level SQL type from an input @@ -570,34 +599,6 @@ pub(crate) fn erase_all_generic_params(ty: &syn::Type, generic_names: &[Ident]) ty } -/// Determines the argument type of the nth argument of the function. -/// -/// Adds a lifetime `'a` to the argument type if it is a reference type. -/// -/// Panics if the function has fewer than `nth` arguments. Returns an error if -/// the parameter is a `self` receiver. -pub(crate) fn arg_type(arg: &syn::ItemFn, nth: usize) -> Result { - match &arg.sig.inputs[nth] { - syn::FnArg::Typed(pat) => { - // Patch lifetimes to be 'a if reference - if let syn::Type::Reference(r) = &*pat.ty { - if r.lifetime.is_none() { - let ty = syn::Type::Reference(syn::TypeReference { - lifetime: Some(Lifetime::new("'a", r.span())), - ..r.clone() - }); - return Ok(ty); - } - } - Ok((*pat.ty).clone()) - } - syn::FnArg::Receiver(_) => Err(syn::Error::new( - arg.sig.inputs[nth].span(), - "Unsupported argument type", - )), - } -} - /// Recursively patches lifetimes in a type, adding `'a` to references without a lifetime /// and recursing into generic arguments and tuples. pub(crate) fn patch_lifetimes(ty: &syn::Type) -> syn::Type { @@ -642,7 +643,7 @@ pub(crate) fn output_type(arg: &syn::ItemFn) -> Result<&syn::Type, syn::Error> { syn::ReturnType::Type(_, ty) => Ok(&*ty), syn::ReturnType::Default => Err(syn::Error::new( arg.sig.output.span(), - "Function needs to return a value", + "function needs to return a value", )), } } diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_all_modifiers.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_all_modifiers.snap index fed9d6ed84766..12f2c2cfa8696 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_all_modifiers.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_all_modifiers.snap @@ -1,6 +1,6 @@ --- source: src/expr-derive-impl/src/lib.rs -expression: "#[sqlfunc(\n could_error = true,\n output_type = i16,\n is_infix_op = true,\n is_monotone = (true, true),\n is_infinity_monotone = false,\n negate = None,\n propagates_nulls = true,\n sqlname = \"binary_all_modifiers\",\n)]\nfn binary_all_modifiers<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {\n a\n}\n" +expression: "#[sqlfunc(\n could_error = true,\n output_type = i16,\n is_infix_op = true,\n is_monotone = (true, true),\n is_infinity_monotone = false,\n negate = BinaryAllModifiers,\n propagates_nulls = true,\n sqlname = \"binary_all_modifiers\",\n)]\nfn binary_all_modifiers<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> {\n a\n}\n" --- #[derive( Ord, @@ -57,7 +57,7 @@ impl crate::func::binary::EagerBinaryFunc for BinaryAllModifiers { false } fn negate(&self) -> Option { - None + Some(crate::BinaryFunc::from(BinaryAllModifiers)) } fn propagates_nulls(&self) -> bool { true @@ -72,7 +72,7 @@ impl crate::func::FuncName for BinaryAllModifiers { const NAME: &'static str = stringify!(binary_all_modifiers); #[cfg(feature = "func-registry")] const SQLFUNC: Option = Some(crate::func::SqlFuncSource { - decl: "#[sqlfunc(could_error = true, output_type = i16, is_infix_op = true, is_monotone = (true, true), is_infinity_monotone = false, negate = None, propagates_nulls = true, sqlname = \"binary_all_modifiers\",)] fn binary_all_modifiers<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>", + decl: "#[sqlfunc(could_error = true, output_type = i16, is_infix_op = true, is_monotone = (true, true), is_infinity_monotone = false, negate = BinaryAllModifiers, propagates_nulls = true, sqlname = \"binary_all_modifiers\",)] fn binary_all_modifiers<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a>", signature: "fn(Datum<'a>, Datum<'a>) -> Datum<'a>", body_fingerprint: 14373755090808246356u64, }); diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_arena_fn.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_arena_fn.snap index 254844ae635cd..8aa5093ebd96d 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_arena_fn.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_arena_fn.snap @@ -1,6 +1,6 @@ --- -source: src/expr-derive-impl/src/lib.rs -expression: "#[sqlfunc(test = true)]\nfn unary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool {\n unimplemented!()\n}\n" +source: src/expr-derive-impl/src/test.rs +expression: "#[sqlfunc(test = true)]\nfn binary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool {\n unimplemented!()\n}\n" --- #[derive( Ord, @@ -14,8 +14,8 @@ expression: "#[sqlfunc(test = true)]\nfn unary_fn<'a>(a: Datum<'a>, b: u16, temp Hash, )] #[cfg_attr(any(test, feature = "proptest"), derive(proptest_derive::Arbitrary))] -pub struct UnaryFn; -impl crate::func::binary::EagerBinaryFunc for UnaryFn { +pub struct BinaryFn; +impl crate::func::binary::EagerBinaryFunc for BinaryFn { type Input<'a> = (Datum<'a>, u16); type Output<'a> = bool; fn call<'a>( @@ -23,7 +23,7 @@ impl crate::func::binary::EagerBinaryFunc for UnaryFn { (a, b): Self::Input<'a>, temp_storage: &'a mz_repr::RowArena, ) -> Self::Output<'a> { - unary_fn(a, b, temp_storage) + binary_fn(a, b, temp_storage) } fn output_sql_type( &self, @@ -43,16 +43,16 @@ impl crate::func::binary::EagerBinaryFunc for UnaryFn { output.nullable(is_null) } } -impl std::fmt::Display for UnaryFn { +impl std::fmt::Display for BinaryFn { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str(stringify!(unary_fn)) + f.write_str(stringify!(binary_fn)) } } -impl crate::func::FuncName for UnaryFn { - const NAME: &'static str = stringify!(unary_fn); +impl crate::func::FuncName for BinaryFn { + const NAME: &'static str = stringify!(binary_fn); #[cfg(feature = "func-registry")] const SQLFUNC: Option = Some(crate::func::SqlFuncSource { - decl: "#[sqlfunc(test = true)] fn unary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool", + decl: "#[sqlfunc(test = true)] fn binary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool", signature: "fn(Datum<'a>, u16) -> bool", body_fingerprint: 4726381389472009124u64, }); @@ -71,6 +71,6 @@ impl crate::func::FuncName for UnaryFn { .collect() } } -fn unary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool { +fn binary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool { unimplemented!() } diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_self.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_self.snap new file mode 100644 index 0000000000000..e2898a9be1901 --- /dev/null +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__binary_self.snap @@ -0,0 +1,67 @@ +--- +source: src/expr-derive-impl/src/lib.rs +expression: "#[sqlfunc(ClampAt, sqlname = \"clamp_at\", is_infix_op = false, test = true)]\nfn clamp_at<'a>(&self, a: i64, b: i64) -> i64 {\n a.clamp(self.lower, b)\n}\n" +--- +impl ClampAt { + fn clamp_at<'a>(&self, a: i64, b: i64) -> i64 { + a.clamp(self.lower, b) + } +} +impl crate::func::binary::EagerBinaryFunc for ClampAt { + type Input<'a> = (i64, i64); + type Output<'a> = i64; + fn call<'a>( + &self, + (a, b): Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { + self.clamp_at(a, b) + } + fn output_sql_type( + &self, + input_types: &[mz_repr::SqlColumnType], + ) -> mz_repr::SqlColumnType { + use mz_repr::AsColumnType; + let output = Self::Output::as_column_type(); + let propagates_nulls = crate::func::binary::EagerBinaryFunc::propagates_nulls( + self, + ); + let nullable = output.nullable; + let non_nullable_input_is_nullable = false + || input_types.get(0usize).map_or(false, |t| t.nullable) + || input_types.get(1usize).map_or(false, |t| t.nullable); + let inputs_nullable = input_types.iter().any(|it| it.nullable); + let is_null = nullable || non_nullable_input_is_nullable + || (propagates_nulls && inputs_nullable); + output.nullable(is_null) + } + fn is_infix_op(&self) -> bool { + false + } +} +impl std::fmt::Display for ClampAt { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("clamp_at") + } +} +impl crate::func::FuncName for ClampAt { + const NAME: &'static str = stringify!(clamp_at); + #[cfg(feature = "func-registry")] + const SQLFUNC: Option = Some(crate::func::SqlFuncSource { + decl: "#[sqlfunc(ClampAt, sqlname = \"clamp_at\", is_infix_op = false, test = true)] fn clamp_at<'a>(&self, a: i64, b: i64) -> i64", + signature: "fn(i64, i64) -> i64", + body_fingerprint: 6685180180282358271u64, + }); + #[cfg(feature = "func-registry")] + fn sqlfunc_input_types() -> Option> { + use crate::func::registry::{ProbeColumnType as _, ProbeColumnTypeFallback as _}; + [ + (&crate::func::registry::ColumnTypeProbe::(::std::marker::PhantomData)) + .column_type(), + (&crate::func::registry::ColumnTypeProbe::(::std::marker::PhantomData)) + .column_type(), + ] + .into_iter() + .collect() + } +} diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__skip_display.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__skip_display.snap new file mode 100644 index 0000000000000..d3100211a17a6 --- /dev/null +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__skip_display.snap @@ -0,0 +1,49 @@ +--- +source: src/expr-derive-impl/src/lib.rs +expression: "#[sqlfunc(ExtractThing, skip_display = true, test = true)]\nfn extract_thing<'a>(&self, a: i64) -> i64 {\n a + self.offset\n}\n" +--- +impl ExtractThing { + fn extract_thing<'a>(&self, a: i64) -> i64 { + a + self.offset + } +} +impl crate::func::EagerUnaryFunc for ExtractThing { + type Input<'a> = i64; + type Output<'a> = i64; + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { + self.extract_thing(a) + } + fn output_sql_type( + &self, + input_type: mz_repr::SqlColumnType, + ) -> mz_repr::SqlColumnType { + use mz_repr::AsColumnType; + let output = Self::Output::as_column_type(); + let propagates_nulls = crate::func::EagerUnaryFunc::propagates_nulls(self); + let nullable = output.nullable; + output.nullable(nullable || (propagates_nulls && input_type.nullable)) + } +} +impl crate::func::FuncName for ExtractThing { + const NAME: &'static str = stringify!(extract_thing); + #[cfg(feature = "func-registry")] + const SQLFUNC: Option = Some(crate::func::SqlFuncSource { + decl: "#[sqlfunc(ExtractThing, skip_display = true, test = true)] fn extract_thing<'a>(&self, a: i64) -> i64", + signature: "fn(i64) -> i64", + body_fingerprint: 12939012847358732198u64, + }); + #[cfg(feature = "func-registry")] + fn sqlfunc_input_types() -> Option> { + use crate::func::registry::{ProbeColumnType as _, ProbeColumnTypeFallback as _}; + [ + (&crate::func::registry::ColumnTypeProbe::(::std::marker::PhantomData)) + .column_type(), + ] + .into_iter() + .collect() + } +} diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_all_modifiers.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_all_modifiers.snap index 212a16c82a90a..0f50a3f5275b6 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_all_modifiers.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_all_modifiers.snap @@ -1,6 +1,6 @@ --- source: src/expr-derive-impl/src/lib.rs -expression: "#[sqlfunc(\n could_error = true,\n output_type = i16,\n inverse = None,\n is_monotone = true,\n preserves_uniqueness = true,\n is_eliminable_cast = false,\n sqlname = \"unary_all_modifiers\",\n)]\nfn unary_all_modifiers<'a>(a: Datum<'a>) -> Datum<'a> {\n a\n}\n" +expression: "#[sqlfunc(\n could_error = true,\n output_type = i16,\n inverse = UnaryAllModifiers,\n is_monotone = true,\n preserves_uniqueness = true,\n is_eliminable_cast = false,\n sqlname = \"unary_all_modifiers\",\n)]\nfn unary_all_modifiers<'a>(a: Datum<'a>) -> Datum<'a> {\n a\n}\n" --- #[derive( Ord, @@ -18,7 +18,11 @@ pub struct UnaryAllModifiers; impl crate::func::EagerUnaryFunc for UnaryAllModifiers { type Input<'a> = Datum<'a>; type Output<'a> = Datum<'a>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { unary_all_modifiers(a) } fn output_sql_type( @@ -38,7 +42,7 @@ impl crate::func::EagerUnaryFunc for UnaryAllModifiers { >::nullable() } fn inverse(&self) -> Option { - None + Some(crate::UnaryFunc::from(UnaryAllModifiers)) } fn is_monotone(&self) -> bool { true @@ -59,7 +63,7 @@ impl crate::func::FuncName for UnaryAllModifiers { const NAME: &'static str = stringify!(unary_all_modifiers); #[cfg(feature = "func-registry")] const SQLFUNC: Option = Some(crate::func::SqlFuncSource { - decl: "#[sqlfunc(could_error = true, output_type = i16, inverse = None, is_monotone = true, preserves_uniqueness = true, is_eliminable_cast = false, sqlname = \"unary_all_modifiers\",)] fn unary_all_modifiers<'a>(a: Datum<'a>) -> Datum<'a>", + decl: "#[sqlfunc(could_error = true, output_type = i16, inverse = UnaryAllModifiers, is_monotone = true, preserves_uniqueness = true, is_eliminable_cast = false, sqlname = \"unary_all_modifiers\",)] fn unary_all_modifiers<'a>(a: Datum<'a>) -> Datum<'a>", signature: "fn(Datum<'a>) -> Datum<'a>", body_fingerprint: 14373755090808246356u64, }); diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_fn.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_fn.snap index fdb1a9d0684b5..b5de6faac963a 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_fn.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_fn.snap @@ -2,6 +2,66 @@ source: src/expr-derive-impl/src/lib.rs expression: "#[sqlfunc(test = true)]\nfn unary_fn<'a>(a: Datum<'a>, temp_storage: &RowArena) -> bool {\n unimplemented!()\n}\n" --- -::core::compile_error! { - "Unary functions do not yet support RowArena." +#[derive( + Ord, + PartialOrd, + Clone, + Debug, + Eq, + PartialEq, + serde::Serialize, + serde::Deserialize, + Hash, +)] +#[cfg_attr(any(test, feature = "proptest"), derive(proptest_derive::Arbitrary))] +pub struct UnaryFn; +impl crate::func::EagerUnaryFunc for UnaryFn { + type Input<'a> = Datum<'a>; + type Output<'a> = bool; + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { + unary_fn(a, temp_storage) + } + fn output_sql_type( + &self, + input_type: mz_repr::SqlColumnType, + ) -> mz_repr::SqlColumnType { + use mz_repr::AsColumnType; + let output = Self::Output::as_column_type(); + let propagates_nulls = crate::func::EagerUnaryFunc::propagates_nulls(self); + let nullable = output.nullable; + output.nullable(nullable || (propagates_nulls && input_type.nullable)) + } +} +impl std::fmt::Display for UnaryFn { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(stringify!(unary_fn)) + } +} +impl crate::func::FuncName for UnaryFn { + const NAME: &'static str = stringify!(unary_fn); + #[cfg(feature = "func-registry")] + const SQLFUNC: Option = Some(crate::func::SqlFuncSource { + decl: "#[sqlfunc(test = true)] fn unary_fn<'a>(a: Datum<'a>, temp_storage: &RowArena) -> bool", + signature: "fn(Datum<'a>) -> bool", + body_fingerprint: 4726381389472009124u64, + }); + #[cfg(feature = "func-registry")] + fn sqlfunc_input_types() -> Option> { + use crate::func::registry::{ProbeColumnType as _, ProbeColumnTypeFallback as _}; + [ + (&crate::func::registry::ColumnTypeProbe::< + Datum<'static>, + >(::std::marker::PhantomData)) + .column_type(), + ] + .into_iter() + .collect() + } +} +fn unary_fn<'a>(a: Datum<'a>, temp_storage: &RowArena) -> bool { + unimplemented!() } diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_used.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_used.snap new file mode 100644 index 0000000000000..3b99d84a59791 --- /dev/null +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_arena_used.snap @@ -0,0 +1,65 @@ +--- +source: src/expr-derive-impl/src/lib.rs +expression: "#[sqlfunc(sqlname = \"to_arena_string\", test = true)]\nfn to_arena_string<'a>(a: i32, temp_storage: &'a RowArena) -> &'a str {\n temp_storage.push_string(a.to_string())\n}\n" +--- +#[derive( + Ord, + PartialOrd, + Clone, + Debug, + Eq, + PartialEq, + serde::Serialize, + serde::Deserialize, + Hash, +)] +#[cfg_attr(any(test, feature = "proptest"), derive(proptest_derive::Arbitrary))] +pub struct ToArenaString; +impl crate::func::EagerUnaryFunc for ToArenaString { + type Input<'a> = i32; + type Output<'a> = &'a str; + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { + to_arena_string(a, temp_storage) + } + fn output_sql_type( + &self, + input_type: mz_repr::SqlColumnType, + ) -> mz_repr::SqlColumnType { + use mz_repr::AsColumnType; + let output = Self::Output::as_column_type(); + let propagates_nulls = crate::func::EagerUnaryFunc::propagates_nulls(self); + let nullable = output.nullable; + output.nullable(nullable || (propagates_nulls && input_type.nullable)) + } +} +impl std::fmt::Display for ToArenaString { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("to_arena_string") + } +} +impl crate::func::FuncName for ToArenaString { + const NAME: &'static str = stringify!(to_arena_string); + #[cfg(feature = "func-registry")] + const SQLFUNC: Option = Some(crate::func::SqlFuncSource { + decl: "#[sqlfunc(sqlname = \"to_arena_string\", test = true)] fn to_arena_string<'a>(a: i32, temp_storage: &'a RowArena) -> &'a str", + signature: "fn(i32) -> &'a str", + body_fingerprint: 17915273539525400975u64, + }); + #[cfg(feature = "func-registry")] + fn sqlfunc_input_types() -> Option> { + use crate::func::registry::{ProbeColumnType as _, ProbeColumnTypeFallback as _}; + [ + (&crate::func::registry::ColumnTypeProbe::(::std::marker::PhantomData)) + .column_type(), + ] + .into_iter() + .collect() + } +} +fn to_arena_string<'a>(a: i32, temp_storage: &'a RowArena) -> &'a str { + temp_storage.push_string(a.to_string()) +} diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_fn.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_fn.snap index a747f717228a8..d599f6341bda7 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_fn.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_fn.snap @@ -18,7 +18,11 @@ pub struct UnaryFn; impl crate::func::EagerUnaryFunc for UnaryFn { type Input<'a> = Datum<'a>; type Output<'a> = bool; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { unary_fn(a) } fn output_sql_type( diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_generic_range.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_generic_range.snap index 00f49b11b93ba..b7c6b38a7cb12 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_generic_range.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_generic_range.snap @@ -18,7 +18,11 @@ pub struct RangeLower; impl crate::func::EagerUnaryFunc for RangeLower { type Input<'a> = Range>; type Output<'a> = Option>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { range_lower(a) } fn output_sql_type( diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_nested_ref.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_nested_ref.snap new file mode 100644 index 0000000000000..f322accd0d34a --- /dev/null +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_nested_ref.snap @@ -0,0 +1,67 @@ +--- +source: src/expr-derive-impl/src/test.rs +expression: "#[sqlfunc(test = true)]\nfn unary_fn<'a>(a: Option<&str>) -> bool {\n unimplemented!()\n}\n" +--- +#[derive( + Ord, + PartialOrd, + Clone, + Debug, + Eq, + PartialEq, + serde::Serialize, + serde::Deserialize, + Hash, +)] +#[cfg_attr(any(test, feature = "proptest"), derive(proptest_derive::Arbitrary))] +pub struct UnaryFn; +impl crate::func::EagerUnaryFunc for UnaryFn { + type Input<'a> = Option<&'a str>; + type Output<'a> = bool; + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { + unary_fn(a) + } + fn output_sql_type( + &self, + input_type: mz_repr::SqlColumnType, + ) -> mz_repr::SqlColumnType { + use mz_repr::AsColumnType; + let output = Self::Output::as_column_type(); + let propagates_nulls = crate::func::EagerUnaryFunc::propagates_nulls(self); + let nullable = output.nullable; + output.nullable(nullable || (propagates_nulls && input_type.nullable)) + } +} +impl std::fmt::Display for UnaryFn { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(stringify!(unary_fn)) + } +} +impl crate::func::FuncName for UnaryFn { + const NAME: &'static str = stringify!(unary_fn); + #[cfg(feature = "func-registry")] + const SQLFUNC: Option = Some(crate::func::SqlFuncSource { + decl: "#[sqlfunc(test = true)] fn unary_fn<'a>(a: Option<&str>) -> bool", + signature: "fn(Option<&'a str>) -> bool", + body_fingerprint: 4726381389472009124u64, + }); + #[cfg(feature = "func-registry")] + fn sqlfunc_input_types() -> Option> { + use crate::func::registry::{ProbeColumnType as _, ProbeColumnTypeFallback as _}; + [ + (&crate::func::registry::ColumnTypeProbe::< + Option<&'static str>, + >(::std::marker::PhantomData)) + .column_type(), + ] + .into_iter() + .collect() + } +} +fn unary_fn<'a>(a: Option<&str>) -> bool { + unimplemented!() +} diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_ref.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_ref.snap index 9b2deda1e20f5..3f3e50f3ed19f 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_ref.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_ref.snap @@ -18,7 +18,11 @@ pub struct UnaryFn; impl crate::func::EagerUnaryFunc for UnaryFn { type Input<'a> = &'a i16; type Output<'a> = bool; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { unary_fn(a) } fn output_sql_type( diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_self.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_self.snap new file mode 100644 index 0000000000000..1ce9e1444377e --- /dev/null +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__unary_self.snap @@ -0,0 +1,56 @@ +--- +source: src/expr-derive-impl/src/lib.rs +expression: "#[sqlfunc(PadTo, sqlname = \"pad_to\", test = true)]\nfn pad_to<'a>(&self, a: &'a str, temp_storage: &'a RowArena) -> &'a str {\n temp_storage.push_string(format!(\"{a:width$}\", width = self.width))\n}\n" +--- +impl PadTo { + fn pad_to<'a>(&self, a: &'a str, temp_storage: &'a RowArena) -> &'a str { + temp_storage.push_string(format!("{a:width$}", width = self.width)) + } +} +impl crate::func::EagerUnaryFunc for PadTo { + type Input<'a> = &'a str; + type Output<'a> = &'a str; + fn call<'a>( + &self, + a: Self::Input<'a>, + temp_storage: &'a mz_repr::RowArena, + ) -> Self::Output<'a> { + self.pad_to(a, temp_storage) + } + fn output_sql_type( + &self, + input_type: mz_repr::SqlColumnType, + ) -> mz_repr::SqlColumnType { + use mz_repr::AsColumnType; + let output = Self::Output::as_column_type(); + let propagates_nulls = crate::func::EagerUnaryFunc::propagates_nulls(self); + let nullable = output.nullable; + output.nullable(nullable || (propagates_nulls && input_type.nullable)) + } +} +impl std::fmt::Display for PadTo { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("pad_to") + } +} +impl crate::func::FuncName for PadTo { + const NAME: &'static str = stringify!(pad_to); + #[cfg(feature = "func-registry")] + const SQLFUNC: Option = Some(crate::func::SqlFuncSource { + decl: "#[sqlfunc(PadTo, sqlname = \"pad_to\", test = true)] fn pad_to<'a>(&self, a: &'a str, temp_storage: &'a RowArena) -> &'a str", + signature: "fn(&'a str) -> &'a str", + body_fingerprint: 9097626259777403017u64, + }); + #[cfg(feature = "func-registry")] + fn sqlfunc_input_types() -> Option> { + use crate::func::registry::{ProbeColumnType as _, ProbeColumnTypeFallback as _}; + [ + (&crate::func::registry::ColumnTypeProbe::< + &'static str, + >(::std::marker::PhantomData)) + .column_type(), + ] + .into_iter() + .collect() + } +} diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_all_modifiers.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_all_modifiers.snap index 484e94cef9e6e..a3c2dc25aa0a5 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_all_modifiers.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_all_modifiers.snap @@ -1,5 +1,5 @@ --- -source: src/expr-derive-impl/src/lib.rs +source: src/expr-derive-impl/src/test.rs expression: "#[sqlfunc(\n could_error = true,\n output_type = i16,\n is_infix_op = true,\n is_monotone = true,\n is_associative = true,\n propagates_nulls = true,\n sqlname = \"variadic_all_modifiers\",\n)]\nfn variadic_all_modifiers<'a>(datums: Variadic>) -> Datum<'a> {\n datums.into_iter().next().unwrap_or(Datum::Null)\n}\n" --- #[derive( @@ -37,11 +37,9 @@ impl crate::func::variadic::EagerVariadicFunc for VariadicAllModifiers { let nullable = output.nullable; let non_nullable_input_is_nullable = false; let inputs_nullable = input_types.iter().any(|it| it.nullable); - output - .nullable( - nullable || non_nullable_input_is_nullable - || (propagates_nulls && inputs_nullable), - ) + let is_null = nullable || non_nullable_input_is_nullable + || (propagates_nulls && inputs_nullable); + output.nullable(is_null) } fn could_error(&self) -> bool { true diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_arena.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_arena.snap index b9d67aad14f47..24e1f01d95e2a 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_arena.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_arena.snap @@ -1,5 +1,5 @@ --- -source: src/expr-derive-impl/src/lib.rs +source: src/expr-derive-impl/src/test.rs expression: "#[sqlfunc(ArrayFill, sqlname = \"array_fill\", introduces_nulls = false)]\nfn array_fill<'a>(\n &self,\n fill: Datum<'a>,\n dims: Datum<'a>,\n lb: OptionalArg>,\n temp_storage: &RowArena,\n) -> Result, EvalError> {\n unimplemented!()\n}\n" --- impl ArrayFill { @@ -35,11 +35,9 @@ impl crate::func::variadic::EagerVariadicFunc for ArrayFill { let nullable = output.nullable; let non_nullable_input_is_nullable = false; let inputs_nullable = input_types.iter().any(|it| it.nullable); - output - .nullable( - nullable || non_nullable_input_is_nullable - || (propagates_nulls && inputs_nullable), - ) + let is_null = nullable || non_nullable_input_is_nullable + || (propagates_nulls && inputs_nullable); + output.nullable(is_null) } fn introduces_nulls(&self) -> bool { false diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_modifiers.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_modifiers.snap index 2a3edfaa9c858..2ff40cc04d0c0 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_modifiers.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_modifiers.snap @@ -1,6 +1,6 @@ --- -source: src/expr-derive-impl/src/lib.rs -expression: "#[sqlfunc(Greatest, sqlname = \"greatest\", could_error = false, is_monotone = true)]\nfn greatest<'a>(datums: Variadic>) -> Datum<'a> {\n datums.into_iter().max().unwrap_or(Datum::Null)\n}\n" +source: src/expr-derive-impl/src/test.rs +expression: "#[sqlfunc(MaxDatum, could_error = false, is_monotone = true)]\nfn max_datum<'a>(datums: Variadic>) -> Datum<'a> {\n datums.into_iter().max().unwrap_or(Datum::Null)\n}\n" --- #[derive( Ord, @@ -14,8 +14,8 @@ expression: "#[sqlfunc(Greatest, sqlname = \"greatest\", could_error = false, is Hash, )] #[cfg_attr(any(test, feature = "proptest"), derive(proptest_derive::Arbitrary))] -pub struct Greatest; -impl crate::func::variadic::EagerVariadicFunc for Greatest { +pub struct MaxDatum; +impl crate::func::variadic::EagerVariadicFunc for MaxDatum { type Input<'a> = Variadic>; type Output<'a> = Datum<'a>; fn call<'a>( @@ -23,7 +23,7 @@ impl crate::func::variadic::EagerVariadicFunc for Greatest { datums: Self::Input<'a>, temp_storage: &'a mz_repr::RowArena, ) -> Self::Output<'a> { - greatest(datums) + max_datum(datums) } fn output_type( &self, @@ -37,11 +37,9 @@ impl crate::func::variadic::EagerVariadicFunc for Greatest { let nullable = output.nullable; let non_nullable_input_is_nullable = false; let inputs_nullable = input_types.iter().any(|it| it.nullable); - output - .nullable( - nullable || non_nullable_input_is_nullable - || (propagates_nulls && inputs_nullable), - ) + let is_null = nullable || non_nullable_input_is_nullable + || (propagates_nulls && inputs_nullable); + output.nullable(is_null) } fn could_error(&self) -> bool { false @@ -50,16 +48,16 @@ impl crate::func::variadic::EagerVariadicFunc for Greatest { true } } -impl std::fmt::Display for Greatest { +impl std::fmt::Display for MaxDatum { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str("greatest") + f.write_str(stringify!(max_datum)) } } -impl crate::func::FuncName for Greatest { - const NAME: &'static str = stringify!(greatest); +impl crate::func::FuncName for MaxDatum { + const NAME: &'static str = stringify!(max_datum); #[cfg(feature = "func-registry")] const SQLFUNC: Option = Some(crate::func::SqlFuncSource { - decl: "#[sqlfunc(Greatest, sqlname = \"greatest\", could_error = false, is_monotone = true,)] fn greatest<'a>(datums: Variadic>) -> Datum<'a>", + decl: "#[sqlfunc(MaxDatum, could_error = false, is_monotone = true,)] fn max_datum<'a>(datums: Variadic>) -> Datum<'a>", signature: "fn(Variadic>) -> Datum<'a>", body_fingerprint: 12432331865766881162u64, }); @@ -80,6 +78,6 @@ impl crate::func::FuncName for Greatest { .collect() } } -fn greatest<'a>(datums: Variadic>) -> Datum<'a> { +fn max_datum<'a>(datums: Variadic>) -> Datum<'a> { datums.into_iter().max().unwrap_or(Datum::Null) } diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_tuple.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_tuple.snap index 5c30e5f17ad3c..26d12b0a5b8af 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_tuple.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_tuple.snap @@ -1,5 +1,5 @@ --- -source: src/expr-derive-impl/src/lib.rs +source: src/expr-derive-impl/src/test.rs expression: "#[sqlfunc(Replace, sqlname = \"replace\")]\nfn replace(text: &str, from: &str, to: &str) -> Result {\n Ok(text.replace(from, to))\n}\n" --- #[derive( @@ -40,11 +40,9 @@ impl crate::func::variadic::EagerVariadicFunc for Replace { || input_types.get(1usize).map_or(false, |t| t.nullable) || input_types.get(2usize).map_or(false, |t| t.nullable); let inputs_nullable = input_types.iter().any(|it| it.nullable); - output - .nullable( - nullable || non_nullable_input_is_nullable - || (propagates_nulls && inputs_nullable), - ) + let is_null = nullable || non_nullable_input_is_nullable + || (propagates_nulls && inputs_nullable); + output.nullable(is_null) } } impl std::fmt::Display for Replace { diff --git a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_variadic_type.snap b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_variadic_type.snap index 634e29df91e15..3868209fe582b 100644 --- a/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_variadic_type.snap +++ b/src/expr-derive-impl/src/snapshots/mz_expr_derive_impl__test__variadic_variadic_type.snap @@ -1,5 +1,5 @@ --- -source: src/expr-derive-impl/src/lib.rs +source: src/expr-derive-impl/src/test.rs expression: "#[sqlfunc(Concat, sqlname = \"concat\", is_associative = true)]\nfn concat(strs: Variadic>) -> Result {\n Ok(strs.into_iter().flatten().collect())\n}\n" --- #[derive( @@ -37,11 +37,9 @@ impl crate::func::variadic::EagerVariadicFunc for Concat { let nullable = output.nullable; let non_nullable_input_is_nullable = false; let inputs_nullable = input_types.iter().any(|it| it.nullable); - output - .nullable( - nullable || non_nullable_input_is_nullable - || (propagates_nulls && inputs_nullable), - ) + let is_null = nullable || non_nullable_input_is_nullable + || (propagates_nulls && inputs_nullable); + output.nullable(is_null) } fn is_associative(&self) -> bool { true diff --git a/src/expr-derive-impl/src/source.rs b/src/expr-derive-impl/src/source.rs index 2fc811982830d..e7c4701230179 100644 --- a/src/expr-derive-impl/src/source.rs +++ b/src/expr-derive-impl/src/source.rs @@ -114,8 +114,8 @@ fn fnv1a64(bytes: &[u8]) -> u64 { /// implement. /// /// Text comes from the token trees via [`render_tokens`], so formatting and -/// comments do not affect it. `input_tys_raw` are the parameter types as -/// written, for the signature. `input_tys` are the erased types the trait +/// comments do not affect it. `input_tys_raw` are the parameter types +/// before generic erasure, with `'a` added to elided references, for the signature. `input_tys` are the erased types the trait /// impl uses, for the probes. pub(crate) fn sqlfunc_source( attr: &TokenStream, diff --git a/src/expr-derive-impl/src/sqlfunc.rs b/src/expr-derive-impl/src/sqlfunc.rs index 762aa77981148..2ff7c56c14b57 100644 --- a/src/expr-derive-impl/src/sqlfunc.rs +++ b/src/expr-derive-impl/src/sqlfunc.rs @@ -18,7 +18,7 @@ use quote::quote; use crate::generate::generate; use crate::modifiers::Modifiers; use crate::shape::Shape; -use crate::signature::last_is_arena; +use crate::signature; /// Implementation for the `#[sqlfunc]` macro. The first parameter is the attribute /// arguments, the second is the function body. The third parameter indicates @@ -32,7 +32,7 @@ pub fn sqlfunc( ) -> darling::Result { let mut attr_args = darling::ast::NestedMeta::parse_meta_list(attr.clone())?; - // Check if the first attribute arg is a bare Path (struct name for variadic). + // Check if the first attribute arg is a bare Path (struct name). let struct_ty = match attr_args.first() { Some(darling::ast::NestedMeta::Meta(syn::Meta::Path(_))) => { let darling::ast::NestedMeta::Meta(syn::Meta::Path(path)) = attr_args.remove(0) else { @@ -47,24 +47,12 @@ pub fn sqlfunc( let generate_tests = modifiers.generates_test(); let func = syn::parse2::(item.clone())?; - let tokens = match determine_arity(&func) { - Arity::Nullary => Err(darling::Error::custom("Nullary functions not supported")), - Arity::Unary { arena: false } => { - generate(Shape::Unary, &func, modifiers, None, false, &attr) - } - Arity::Unary { arena: true } => Err(darling::Error::custom( - "Unary functions do not yet support RowArena.", - )), - Arity::Binary => generate(Shape::Binary, &func, modifiers, None, false, &attr), - Arity::Variadic { has_self } => generate( - Shape::Variadic, - &func, - modifiers, - struct_ty, - has_self, - &attr, - ), - }?; + let Some(shape) = determine_shape(&func) else { + return Err(darling::Error::custom( + "nullary functions are not supported", + )); + }; + let tokens = generate(shape, &func, modifiers, struct_ty, &attr)?; let test = (generate_tests && include_test).then(|| generate_test(attr, item, &func.sig.ident)); @@ -97,75 +85,21 @@ fn generate_test(_attr: TokenStream, _item: TokenStream, _name: &Ident) -> Token quote! {} } -/// Arity classification for a function annotated with `#[sqlfunc]`. -enum Arity { - Nullary, - Unary { - /// Whether a trailing `&RowArena` parameter is present, which - /// `EagerUnaryFunc::call` has no place for. - arena: bool, - }, - Binary, - Variadic { - has_self: bool, - }, -} - -/// Checks whether a parameter's type is `Variadic<...>` or `OptionalArg<...>`, -/// which indicates the function should be treated as variadic regardless of -/// parameter count. -fn is_variadic_arg(arg: &syn::FnArg) -> bool { - if let syn::FnArg::Typed(pat) = arg { - if let syn::Type::Path(path) = &*pat.ty { - if let Some(segment) = path.path.segments.last() { - let ident = segment.ident.to_string(); - return ident == "Variadic" || ident == "OptionalArg"; - } - } - } - false -} - -/// Determines the arity of a function annotated with `#[sqlfunc]`. +/// The shape of a function annotated with `#[sqlfunc]`, or `None` for a function +/// without SQL arguments. /// -/// Accounts for `&self` receivers, trailing `&RowArena` parameters, and -/// parameter types like `Variadic` or `OptionalArg` that indicate -/// variadic dispatch. -fn determine_arity(func: &syn::ItemFn) -> Arity { - let arena = last_is_arena(func); - let has_self = matches!(func.sig.inputs.first(), Some(syn::FnArg::Receiver(_))); - - let mut effective_count = func.sig.inputs.len(); - if arena { - effective_count -= 1; +/// Only the SQL arguments count, so a `&self` receiver and a trailing `&RowArena` are +/// skipped. A `Variadic` or `OptionalArg` argument makes the function variadic +/// regardless of how many arguments it has. +fn determine_shape(func: &syn::ItemFn) -> Option { + let args = signature::sql_args(func); + if args.iter().any(|arg| signature::is_variadic_arg(arg)) { + return Some(Shape::Variadic); } - if has_self { - effective_count -= 1; - } - - // Check if any effective parameter uses a variadic-typed wrapper. - let start = if has_self { 1 } else { 0 }; - let end = if arena { - func.sig.inputs.len() - 1 - } else { - func.sig.inputs.len() - }; - let has_variadic_param = func - .sig - .inputs - .iter() - .skip(start) - .take(end - start) - .any(is_variadic_arg); - - if has_variadic_param || effective_count >= 3 { - Arity::Variadic { has_self } - } else { - match effective_count { - 0 => Arity::Nullary, - 1 => Arity::Unary { arena }, - 2 => Arity::Binary, - _ => unreachable!(), - } + match args.len() { + 0 => None, + 1 => Some(Shape::Unary), + 2 => Some(Shape::Binary), + _ => Some(Shape::Variadic), } } diff --git a/src/expr-derive-impl/src/test.rs b/src/expr-derive-impl/src/test.rs new file mode 100644 index 0000000000000..a20d0b4dc3b5b --- /dev/null +++ b/src/expr-derive-impl/src/test.rs @@ -0,0 +1,469 @@ +// Copyright Materialize, Inc. and contributors. All rights reserved. +// +// Use of this software is governed by the Business Source License +// included in the LICENSE file. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0. + +//! Snapshot and diagnostic tests for the `#[sqlfunc]` expansion. + +use quote::quote; + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_add_int16() { + let attr = quote! { + is_monotone = (true, true), + output_type = i16, + is_infix_op = true, + sqlname = "+", + propagates_nulls = true, + test = true, + }; + let item = quote! { + fn add_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result, EvalError> { + a.unwrap_int16() + .checked_add(b.unwrap_int16()) + .ok_or(EvalError::NumericFieldOverflow) + .map(Datum::from) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("add_int16", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary() { + let attr = quote! {test = true}; + let item = quote! { + fn unary_fn<'a>(a: Datum<'a>) -> bool { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_fn", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_arena() { + let attr = quote! {test = true}; + let item = quote! { + fn unary_fn<'a>(a: Datum<'a>, temp_storage: &RowArena) -> bool { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_arena_fn", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_arena_used() { + let attr = quote! { sqlname = "to_arena_string", test = true }; + let item = quote! { + fn to_arena_string<'a>(a: i32, temp_storage: &'a RowArena) -> &'a str { + temp_storage.push_string(a.to_string()) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_arena_used", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_ref() { + let attr = quote! {test = true}; + let item = quote! { + fn unary_fn<'a>(a: &i16) -> bool { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_ref", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_nested_ref() { + let attr = quote! {test = true}; + let item = quote! { + fn unary_fn<'a>(a: Option<&str>) -> bool { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + assert!( + output.contains("type Input<'a> = Option<&'a str>;"), + "a reference nested in a unary parameter must get the trait's lifetime, got:\n{output}" + ); + insta::assert_snapshot!("unary_nested_ref", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_complex_output_type() { + let attr = quote! { + is_monotone = (true, true), + output_type = "Option", + is_infix_op = true, + sqlname = "test", + propagates_nulls = true, + test = true, + }; + let item = quote! { + fn complex_output_type_fn<'a>( + a: Datum<'a>, + b: Datum<'a>, + ) -> Result, EvalError> { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("complex_type", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_binary_arena() { + let attr = quote! {test = true}; + let item = quote! { + fn binary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("binary_arena_fn", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_variadic_tuple() { + let attr = quote! { + Replace, + sqlname = "replace", + }; + let item = quote! { + fn replace(text: &str, from: &str, to: &str) -> Result { + Ok(text.replace(from, to)) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("variadic_tuple", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_variadic_variadic_type() { + let attr = quote! { + Concat, + sqlname = "concat", + is_associative = true, + }; + let item = quote! { + fn concat(strs: Variadic>) -> Result { + Ok(strs.into_iter().flatten().collect()) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("variadic_variadic_type", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_variadic_arena() { + let attr = quote! { + ArrayFill, + sqlname = "array_fill", + introduces_nulls = false, + }; + let item = quote! { + fn array_fill<'a>( + &self, + fill: Datum<'a>, + dims: Datum<'a>, + lb: OptionalArg>, + temp_storage: &RowArena, + ) -> Result, EvalError> { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("variadic_arena", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_variadic_modifiers() { + let attr = quote! { + MaxDatum, + could_error = false, + is_monotone = true, + }; + let item = quote! { + fn max_datum<'a>(datums: Variadic>) -> Datum<'a> { + datums.into_iter().max().unwrap_or(Datum::Null) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("variadic_modifiers", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_generic_range() { + let attr = quote! { + sqlname = "rangelower", + is_monotone = true, + }; + let item = quote! { + fn range_lower<'a, T>(a: Range) -> Option { + a.inner.map(|inner| inner.lower.bound).flatten() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_generic_range", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_binary_generic_list() { + let attr = quote! { + is_infix_op = true, + sqlname = "||", + propagates_nulls = false, + introduces_nulls = false, + }; + let item = quote! { + fn list_list_concat<'a, T>( + a: Option>, + b: Option>, + temp_storage: &'a RowArena, + ) -> Option> { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("binary_generic_list", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_binary_multi_generic() { + let attr = quote! { + sqlname = "multi_generic", + }; + let item = quote! { + fn multi_generic<'a, A, B>( + a: DatumList<'a, A>, + b: DatumList<'a, B>, + ) -> Option { + unimplemented!() + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("binary_multi_generic", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_all_modifiers() { + let attr = quote! { + could_error = true, + output_type = i16, + inverse = UnaryAllModifiers, + is_monotone = true, + preserves_uniqueness = true, + is_eliminable_cast = false, + sqlname = "unary_all_modifiers", + }; + let item = quote! { + fn unary_all_modifiers<'a>(a: Datum<'a>) -> Datum<'a> { + a + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_all_modifiers", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_binary_all_modifiers() { + let attr = quote! { + could_error = true, + output_type = i16, + is_infix_op = true, + is_monotone = (true, true), + is_infinity_monotone = false, + negate = BinaryAllModifiers, + propagates_nulls = true, + sqlname = "binary_all_modifiers", + }; + let item = quote! { + fn binary_all_modifiers<'a>(a: Datum<'a>, b: Datum<'a>) -> Datum<'a> { + a + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("binary_all_modifiers", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_variadic_all_modifiers() { + let attr = quote! { + could_error = true, + output_type = i16, + is_infix_op = true, + is_monotone = true, + is_associative = true, + propagates_nulls = true, + sqlname = "variadic_all_modifiers", + }; + let item = quote! { + fn variadic_all_modifiers<'a>(datums: Variadic>) -> Datum<'a> { + datums.into_iter().next().unwrap_or(Datum::Null) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("variadic_all_modifiers", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn unknown_modifier_is_an_error() { + let (output, _input) = super::test_sqlfunc( + quote! { not_a_modifier = true }, + quote! { + fn some_unary<'a>(a: i32) -> i32 { a } + }, + ); + assert!( + output.contains("not_a_modifier"), + "expected an error naming the unknown modifier, got:\n{output}" + ); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn unary_rejects_negate_by_name() { + let (output, _input) = super::test_sqlfunc( + quote! { negate = super::Foo }, + quote! { + fn some_unary<'a>(a: i32) -> i32 { a } + }, + ); + assert!( + output.contains("`negate` is not supported for unary functions"), + "expected an error naming the modifier and the arity, got:\n{output}" + ); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn unary_rejects_is_infinity_monotone() { + let (output, _input) = super::test_sqlfunc( + quote! { is_infinity_monotone = false }, + quote! { + fn some_unary<'a>(a: i32) -> i32 { a } + }, + ); + assert!( + output.contains("`is_infinity_monotone` is not supported for unary functions"), + "is_infinity_monotone must be rejected on unary rather than ignored, got:\n{output}" + ); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_unary_self() { + let attr = quote! { PadTo, sqlname = "pad_to", test = true }; + let item = quote! { + fn pad_to<'a>(&self, a: &'a str, temp_storage: &'a RowArena) -> &'a str { + temp_storage.push_string(format!("{a:width$}", width = self.width)) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("unary_self", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_binary_self() { + let attr = quote! { ClampAt, sqlname = "clamp_at", is_infix_op = false, test = true }; + let item = quote! { + fn clamp_at<'a>(&self, a: i64, b: i64) -> i64 { + a.clamp(self.lower, b) + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + insta::assert_snapshot!("binary_self", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn insta_test_skip_display() { + let attr = quote! { ExtractThing, skip_display = true, test = true }; + let item = quote! { + fn extract_thing<'a>(&self, a: i64) -> i64 { + a + self.offset + } + }; + let (output, input) = super::test_sqlfunc(attr, item); + assert!( + !output.contains("impl std::fmt::Display"), + "skip_display must suppress the Display impl, got:\n{output}" + ); + insta::assert_snapshot!("skip_display", output, &input); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn skip_display_rejects_sqlname() { + let (output, _input) = super::test_sqlfunc( + quote! { ExtractThing, skip_display = true, sqlname = "extract_thing" }, + quote! { + fn extract_thing<'a>(&self, a: i64) -> i64 { a + self.offset } + }, + ); + // A successful expansion also contains both modifier names, because the + // registry's `decl` field echoes the attribute text, so match the error itself. + assert!( + output.contains("sqlname has no effect with skip_display"), + "expected the conflict error, got:\n{output}" + ); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn skip_display_rejects_a_unit_struct() { + let (output, _input) = super::test_sqlfunc( + quote! { skip_display = true }, + quote! { + fn extract_thing(a: i64) -> i64 { a } + }, + ); + assert!( + output.contains("skip_display requires a &self receiver"), + "expected the receiver error, got:\n{output}" + ); +} + +#[cfg_attr(miri, ignore)] // unsupported operation: extern static `pidfd_spawnp` is not supported by Miri +#[mz_ore::test] +fn validation_reports_every_error() { + let (output, _input) = super::test_sqlfunc( + quote! { negate = super::Foo, skip_display = true }, + quote! { + fn some_unary<'a>(a: i32) -> i32 { a } + }, + ); + assert!( + output.contains("`negate` is not supported for unary functions") + && output.contains("skip_display requires a &self receiver"), + "expected both errors, got:\n{output}" + ); +} diff --git a/src/expr-derive/src/lib.rs b/src/expr-derive/src/lib.rs index af194b195e414..5f7fd5565d83a 100644 --- a/src/expr-derive/src/lib.rs +++ b/src/expr-derive/src/lib.rs @@ -15,40 +15,11 @@ /// and variadic functions. Depending on the kind of function, it will implement the /// appropriate traits: `EagerUnaryFunc`, `EagerBinaryFunc`, or `EagerVariadicFunc`. /// -/// The macro takes the following arguments: -/// * `is_monotone`: An expression indicating whether the function is monotone. For unary functions, -/// it should be an expression that evaluates to a boolean. For binary functions, it should be a -/// tuple of two expressions, each evaluating to a boolean. See `LazyBinaryFunc` for details. -/// * `sqlname`: The SQL name of the function. -/// * `preserves_uniqueness`: A boolean indicating whether the function preserves uniqueness. -/// Unary functions only. -/// * `inverse`: A function that is the inverse of the function. Applies to unary functions only. -/// * `negate`: A function that negates the function. Applies to binary functions only. For example, -/// the `!=` operator is the negation of the `=` operator, and we'd mark the `Eq` function with -/// `negate = Some(BinaryFunc::NotEq)`. -/// * `is_infix_op`: A boolean indicating whether the function is an infix operator. Applies to -/// binary functions only. -/// * `output_type`: The output type of the function. -/// * `output_type_expr`: An expression that evaluates to the output type. Applies to binary -/// and variadic functions. For binary functions, the expression has access to `input_type_a` -/// and `input_type_b`; for variadic functions, it has access to `input_types: &[SqlColumnType]`. -/// Should evaluate to a `SqlColumnType` value. This expression determines the *base* output -/// type; the macro separately computes nullability by combining `introduces_nulls`, -/// `propagates_nulls`, and input nullability. Requires `introduces_nulls`, and conflicts -/// with `output_type`. -/// * `could_error`: A boolean indicating whether the function could error. -/// * `propagates_nulls`: A boolean indicating whether the function propagates nulls. Applies to -/// binary and variadic functions. If not specified, use the default implementation from the -/// trait. The default is to return true if all input types are non-nullable. -/// * `introduces_nulls`: A boolean indicating whether the function introduces nulls. Applies to -/// all functions. If not specified, use the default implementation from the trait. -/// The default is to return the `nullable` property of the output type. -/// * `test`: A boolean indicating whether to generate a snapshot test for the function. -/// Defaults to `false`. +/// `doc/developer/sqlfunc.md` documents the modifiers, their defaults, and which arities +/// accept them. /// /// # Limitations /// * The input and output types can contain lifetime parameters, as long as they are `'a`. -/// * Unary functions cannot yet receive a `&RowArena` as an argument. /// /// # Examples /// ```ignore diff --git a/src/expr/src/scalar/func.rs b/src/expr/src/scalar/func.rs index 9c3ae37aa3212..ccc17749acf2d 100644 --- a/src/expr/src/scalar/func.rs +++ b/src/expr/src/scalar/func.rs @@ -187,7 +187,6 @@ func_name! { ListLengthMax => "list_length_max", MapBuildFromRecordList => "map_build_from_record_list", PadChar => "pad_char", - variadic::RangeCreate => "range_create", RecordGet => "record_get", RegexpMatch => "regexp_match", RegexpReplace => "regexp_replace", @@ -1810,8 +1809,7 @@ fn range_intersection(l: Range, r: Range) -> Range { output_type_expr = "input_types[0].scalar_type.without_modifiers().nullable(true)", is_infix_op = true, sqlname = "-", - propagates_nulls = true, - introduces_nulls = false + propagates_nulls = true )] fn range_difference<'a>( l: Range>, @@ -1820,7 +1818,7 @@ fn range_difference<'a>( Ok(l.difference(&r)?) } -#[sqlfunc(is_infix_op = true, sqlname = "=", negate = "Some(NotEq.into())")] +#[sqlfunc(is_infix_op = true, sqlname = "=", negate = NotEq)] fn eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { // SQL equality demands that if either input is null, then the result should be null. However, // we don't need to handle this case here; it is handled when `BinaryFunc::eval` checks @@ -1828,7 +1826,7 @@ fn eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { a == b } -#[sqlfunc(is_infix_op = true, sqlname = "!=", negate = "Some(Eq.into())")] +#[sqlfunc(is_infix_op = true, sqlname = "!=", negate = Eq)] fn not_eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { a != b } @@ -1837,7 +1835,7 @@ fn not_eq<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { is_monotone = "(true, true)", is_infix_op = true, sqlname = "<", - negate = "Some(Gte.into())" + negate = Gte )] fn lt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { a < b @@ -1847,7 +1845,7 @@ fn lt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { is_monotone = "(true, true)", is_infix_op = true, sqlname = "<=", - negate = "Some(Gt.into())" + negate = Gt )] fn lte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { a <= b @@ -1857,7 +1855,7 @@ fn lte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { is_monotone = "(true, true)", is_infix_op = true, sqlname = ">", - negate = "Some(Lte.into())" + negate = Lte )] fn gt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { a > b @@ -1867,7 +1865,7 @@ fn gt<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { is_monotone = "(true, true)", is_infix_op = true, sqlname = ">=", - negate = "Some(Lt.into())" + negate = Lt )] fn gte<'a>(a: ExcludeNull>, b: ExcludeNull>) -> bool { a >= b @@ -2113,8 +2111,7 @@ fn jsonb_concat<'a>( output_type_expr = "SqlScalarType::Jsonb.nullable(true)", is_infix_op = true, sqlname = "-", - propagates_nulls = true, - introduces_nulls = true + propagates_nulls = true )] fn jsonb_delete_int64<'a>(a: Datum<'a>, i: i64, temp_storage: &'a RowArena) -> Datum<'a> { match a { @@ -2141,8 +2138,7 @@ fn jsonb_delete_int64<'a>(a: Datum<'a>, i: i64, temp_storage: &'a RowArena) -> D output_type_expr = "SqlScalarType::Jsonb.nullable(true)", is_infix_op = true, sqlname = "-", - propagates_nulls = true, - introduces_nulls = true + propagates_nulls = true )] fn jsonb_delete_string<'a>(a: Datum<'a>, k: &str, temp_storage: &'a RowArena) -> Datum<'a> { match a { @@ -2158,11 +2154,7 @@ fn jsonb_delete_string<'a>(a: Datum<'a>, k: &str, temp_storage: &'a RowArena) -> } } -#[sqlfunc( - sqlname = "extractiv", - propagates_nulls = true, - introduces_nulls = false -)] +#[sqlfunc(sqlname = "extractiv", propagates_nulls = true)] fn date_part_interval_numeric(units: &str, b: Interval) -> Result { match units.parse() { Ok(units) => Ok(date_part_interval_inner::(units, b)?), @@ -2170,11 +2162,7 @@ fn date_part_interval_numeric(units: &str, b: Interval) -> Result Result { match units.parse() { Ok(units) => Ok(date_part_interval_inner::(units, b)?), @@ -2182,11 +2170,7 @@ fn date_part_interval_f64(units: &str, b: Interval) -> Result { } } -#[sqlfunc( - sqlname = "extractt", - propagates_nulls = true, - introduces_nulls = false -)] +#[sqlfunc(sqlname = "extractt", propagates_nulls = true)] fn date_part_time_numeric(units: &str, b: chrono::NaiveTime) -> Result { match units.parse() { Ok(units) => Ok(date_part_time_inner::(units, b)?), @@ -2194,11 +2178,7 @@ fn date_part_time_numeric(units: &str, b: chrono::NaiveTime) -> Result Result { match units.parse() { Ok(units) => Ok(date_part_time_inner::(units, b)?), @@ -2680,7 +2660,7 @@ fn text_concat_binary(a: &str, b: &str, temp_storage: &RowArena) -> Result( pattern: &str, b: &str, @@ -3005,11 +2985,7 @@ fn trim_trailing<'a>(a: &'a str, trim_chars: &str) -> &'a str { a.trim_end_matches(|c| trim_chars.contains(c)) } -#[sqlfunc( - sqlname = "array_length", - propagates_nulls = true, - introduces_nulls = true -)] +#[sqlfunc(sqlname = "array_length", propagates_nulls = true)] fn array_length<'a>(a: Array<'a>, b: i64) -> Result, EvalError> { let i = match usize::try_from(b) { Ok(0) | Err(_) => return Ok(None), @@ -3106,8 +3082,7 @@ fn array_upper<'a>(a: Array<'a>, i: i64) -> Result, EvalError> { #[sqlfunc( is_infix_op = true, sqlname = "array_contains", - propagates_nulls = true, - introduces_nulls = false + propagates_nulls = true )] fn array_contains<'a>(a: Datum<'a>, array: Array<'a>) -> bool { array.elements().iter().any(|e| e == a) diff --git a/src/expr/src/scalar/func/impls/array.rs b/src/expr/src/scalar/func/impls/array.rs index fc38c40f4f260..b475563a643bc 100644 --- a/src/expr/src/scalar/func/impls/array.rs +++ b/src/expr/src/scalar/func/impls/array.rs @@ -20,7 +20,7 @@ use crate::{Eval, EvalError, MirScalarExpr}; // NOTE: This cast does not preserve uniqueness: It returns only the array's elements and drops the // dimension metadata, so arrays that differ only in their lower bounds (e.g. `[1:1]={42}` and // `[2:2]={42}`) collapse to the same list. -#[sqlfunc(sqlname = "arraytolist", introduces_nulls = false)] +#[sqlfunc(sqlname = "arraytolist")] fn cast_array_to_list_one_dim<'a, T>(a: Array<'a, T>) -> Result, EvalError> { let ndims = a.dims().ndims(); if ndims > 1 { diff --git a/src/expr/src/scalar/func/impls/boolean.rs b/src/expr/src/scalar/func/impls/boolean.rs index 171ecddacac47..1dff09e549b98 100644 --- a/src/expr/src/scalar/func/impls/boolean.rs +++ b/src/expr/src/scalar/func/impls/boolean.rs @@ -13,7 +13,7 @@ use mz_repr::strconv; #[sqlfunc( sqlname = "NOT", preserves_uniqueness = true, - inverse = to_unary!(Not), + inverse = Not, is_monotone = true )] fn not(a: bool) -> bool { @@ -23,7 +23,7 @@ fn not(a: bool) -> bool { #[sqlfunc( sqlname = "boolean_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToBool), + inverse = super::CastStringToBool, is_monotone = true )] fn cast_bool_to_string<'a>(a: bool) -> &'a str { @@ -36,7 +36,7 @@ fn cast_bool_to_string<'a>(a: bool) -> &'a str { #[sqlfunc( sqlname = "boolean_to_nonstandard_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToBool), + inverse = super::CastStringToBool, is_monotone = true )] fn cast_bool_to_string_nonstandard<'a>(a: bool) -> &'a str { @@ -50,7 +50,7 @@ fn cast_bool_to_string_nonstandard<'a>(a: bool) -> &'a str { #[sqlfunc( sqlname = "boolean_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToBool), + inverse = super::CastInt32ToBool, is_monotone = true )] fn cast_bool_to_int32(a: bool) -> i32 { @@ -63,7 +63,7 @@ fn cast_bool_to_int32(a: bool) -> i32 { #[sqlfunc( sqlname = "boolean_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToBool), + inverse = super::CastInt64ToBool, is_monotone = true )] fn cast_bool_to_int64(a: bool) -> i64 { diff --git a/src/expr/src/scalar/func/impls/byte.rs b/src/expr/src/scalar/func/impls/byte.rs index 2dbeb4947aaa6..0971e7d5afa02 100644 --- a/src/expr/src/scalar/func/impls/byte.rs +++ b/src/expr/src/scalar/func/impls/byte.rs @@ -16,7 +16,7 @@ use crate::EvalError; #[sqlfunc( sqlname = "bytea_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToBytes) + inverse = super::CastStringToBytes )] fn cast_bytes_to_string(a: &[u8]) -> String { let mut buf = String::new(); diff --git a/src/expr/src/scalar/func/impls/char.rs b/src/expr/src/scalar/func/impls/char.rs index d7235ef27eec9..475e320fe024e 100644 --- a/src/expr/src/scalar/func/impls/char.rs +++ b/src/expr/src/scalar/func/impls/char.rs @@ -11,7 +11,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::char::{Char, CharLength, format_str_pad}; -use mz_repr::{SqlColumnType, SqlScalarType}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType}; use serde::{Deserialize, Serialize}; use crate::scalar::func::EagerUnaryFunc; @@ -38,7 +38,7 @@ impl EagerUnaryFunc for PadChar { type Input<'a> = &'a str; type Output<'a> = Char; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { Char(format_str_pad(a, self.length)) } @@ -62,10 +62,10 @@ impl fmt::Display for PadChar { sqlname = "char_to_text", preserves_uniqueness = true, is_eliminable_cast = true, - inverse = to_unary!(super::CastStringToChar{ + inverse = super::CastStringToChar{ length: None, fail_on_len: false, - }) + } )] fn cast_char_to_string<'a>(a: Char<&'a str>) -> &'a str { a.0 diff --git a/src/expr/src/scalar/func/impls/date.rs b/src/expr/src/scalar/func/impls/date.rs index bb4f5dd1ee548..689b8fb05489a 100644 --- a/src/expr/src/scalar/func/impls/date.rs +++ b/src/expr/src/scalar/func/impls/date.rs @@ -15,7 +15,7 @@ use mz_repr::adt::date::Date; use mz_repr::adt::datetime::DateTimeUnits; use mz_repr::adt::numeric::Numeric; use mz_repr::adt::timestamp::{CheckedTimestamp, DateLike, TimestampPrecision}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -25,7 +25,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "date_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToDate) + inverse = super::CastStringToDate )] fn cast_date_to_string(a: Date) -> String { let mut buf = String::new(); @@ -50,7 +50,7 @@ impl EagerUnaryFunc for CastDateToTimestamp { type Input<'a> = Date; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let out = CheckedTimestamp::from_timestamplike(NaiveDate::from(a).and_hms_opt(0, 0, 0).unwrap())?; let updated = out.round_to_precision(self.0)?; @@ -97,7 +97,7 @@ impl EagerUnaryFunc for CastDateToTimestampTz { type Input<'a> = Date; type Output<'a> = Result>, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let out = CheckedTimestamp::from_timestamplike(DateTime::::from_naive_utc_and_offset( NaiveDate::from(a).and_hms_opt(0, 0, 0).unwrap(), @@ -179,7 +179,7 @@ impl EagerUnaryFunc for ExtractDate { type Input<'a> = Date; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { extract_date_inner(self.0, a.into()) } diff --git a/src/expr/src/scalar/func/impls/float32.rs b/src/expr/src/scalar/func/impls/float32.rs index 3bd1e2b0368bc..d4930d171d7d4 100644 --- a/src/expr/src/scalar/func/impls/float32.rs +++ b/src/expr/src/scalar/func/impls/float32.rs @@ -11,7 +11,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -20,7 +20,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "-", preserves_uniqueness = false, - inverse = to_unary!(NegFloat32), + inverse = NegFloat32, is_monotone = true )] fn neg_float32(a: f32) -> f32 { @@ -55,7 +55,7 @@ fn floor_float32(a: f32) -> f32 { #[sqlfunc( sqlname = "real_to_smallint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt16ToFloat32), + inverse = super::CastInt16ToFloat32, is_monotone = true )] fn cast_float32_to_int16(a: f32) -> Result { @@ -72,7 +72,7 @@ fn cast_float32_to_int16(a: f32) -> Result { #[sqlfunc( sqlname = "real_to_integer", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt32ToFloat32), + inverse = super::CastInt32ToFloat32, is_monotone = true )] fn cast_float32_to_int32(a: f32) -> Result { @@ -93,7 +93,7 @@ fn cast_float32_to_int32(a: f32) -> Result { #[sqlfunc( sqlname = "real_to_bigint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt64ToFloat32), + inverse = super::CastInt64ToFloat32, is_monotone = true )] fn cast_float32_to_int64(a: f32) -> Result { @@ -114,7 +114,7 @@ fn cast_float32_to_int64(a: f32) -> Result { #[sqlfunc( sqlname = "real_to_double", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat64ToFloat32), + inverse = super::CastFloat64ToFloat32, is_monotone = true )] fn cast_float32_to_float64(a: f32) -> f64 { @@ -124,7 +124,7 @@ fn cast_float32_to_float64(a: f32) -> f64 { #[sqlfunc( sqlname = "real_to_text", preserves_uniqueness = false, - inverse = to_unary!(super::CastStringToFloat32) + inverse = super::CastStringToFloat32 )] fn cast_float32_to_string(a: f32) -> String { let mut s = String::new(); @@ -135,7 +135,7 @@ fn cast_float32_to_string(a: f32) -> String { #[sqlfunc( sqlname = "real_to_uint2", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint16ToFloat32), + inverse = super::CastUint16ToFloat32, is_monotone = true )] fn cast_float32_to_uint16(a: f32) -> Result { @@ -152,7 +152,7 @@ fn cast_float32_to_uint16(a: f32) -> Result { #[sqlfunc( sqlname = "real_to_uint4", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint32ToFloat32), + inverse = super::CastUint32ToFloat32, is_monotone = true )] fn cast_float32_to_uint32(a: f32) -> Result { @@ -172,7 +172,7 @@ fn cast_float32_to_uint32(a: f32) -> Result { #[sqlfunc( sqlname = "real_to_uint8", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint64ToFloat32), + inverse = super::CastUint64ToFloat32, is_monotone = true )] fn cast_float32_to_uint64(a: f32) -> Result { @@ -206,7 +206,7 @@ impl EagerUnaryFunc for CastFloat32ToNumeric { type Input<'a> = f32; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { if a.is_infinite() { return Err(EvalError::InfinityOutOfDomain( "casting real to numeric".into(), diff --git a/src/expr/src/scalar/func/impls/float64.rs b/src/expr/src/scalar/func/impls/float64.rs index de6096dfd1b52..d616898494f51 100644 --- a/src/expr/src/scalar/func/impls/float64.rs +++ b/src/expr/src/scalar/func/impls/float64.rs @@ -14,7 +14,7 @@ use mz_expr_derive::sqlfunc; use mz_ore::cast::TryCastFrom; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; use mz_repr::adt::timestamp::CheckedTimestamp; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -24,7 +24,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "-", preserves_uniqueness = false, - inverse = to_unary!(NegFloat64), + inverse = NegFloat64, is_monotone = true )] fn neg_float64(a: f64) -> f64 { @@ -59,7 +59,7 @@ fn floor_float64(a: f64) -> f64 { #[sqlfunc( sqlname = "double_to_smallint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt16ToFloat64), + inverse = super::CastInt16ToFloat64, is_monotone = true )] fn cast_float64_to_int16(a: f64) -> Result { @@ -76,7 +76,7 @@ fn cast_float64_to_int16(a: f64) -> Result { #[sqlfunc( sqlname = "double_to_integer", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt32ToFloat64), + inverse = super::CastInt32ToFloat64, is_monotone = true )] fn cast_float64_to_int32(a: f64) -> Result { @@ -97,7 +97,7 @@ fn cast_float64_to_int32(a: f64) -> Result { #[sqlfunc( sqlname = "f64toi64", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt64ToFloat64), + inverse = super::CastInt64ToFloat64, is_monotone = true )] fn cast_float64_to_int64(a: f64) -> Result { @@ -118,7 +118,7 @@ fn cast_float64_to_int64(a: f64) -> Result { #[sqlfunc( sqlname = "double_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToFloat64), + inverse = super::CastFloat32ToFloat64, is_monotone = true )] fn cast_float64_to_float32(a: f64) -> Result { @@ -137,7 +137,7 @@ fn cast_float64_to_float32(a: f64) -> Result { #[sqlfunc( sqlname = "double_to_text", preserves_uniqueness = false, - inverse = to_unary!(super::CastStringToFloat64) + inverse = super::CastStringToFloat64 )] fn cast_float64_to_string(a: f64) -> String { let mut s = String::new(); @@ -148,7 +148,7 @@ fn cast_float64_to_string(a: f64) -> String { #[sqlfunc( sqlname = "double_to_uint2", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint16ToFloat64), + inverse = super::CastUint16ToFloat64, is_monotone = true )] fn cast_float64_to_uint16(a: f64) -> Result { @@ -165,7 +165,7 @@ fn cast_float64_to_uint16(a: f64) -> Result { #[sqlfunc( sqlname = "double_to_uint4", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint32ToFloat64), + inverse = super::CastUint32ToFloat64, is_monotone = true )] fn cast_float64_to_uint32(a: f64) -> Result { @@ -182,7 +182,7 @@ fn cast_float64_to_uint32(a: f64) -> Result { #[sqlfunc( sqlname = "double_to_uint8", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint64ToFloat64), + inverse = super::CastUint64ToFloat64, is_monotone = true )] fn cast_float64_to_uint64(a: f64) -> Result { @@ -217,7 +217,7 @@ impl EagerUnaryFunc for CastFloat64ToNumeric { type Input<'a> = f64; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { if a.is_infinite() { return Err(EvalError::InfinityOutOfDomain( "casting double precision to numeric".into(), diff --git a/src/expr/src/scalar/func/impls/int16.rs b/src/expr/src/scalar/func/impls/int16.rs index 6a3c38d2b02e2..b7ae0cb476535 100644 --- a/src/expr/src/scalar/func/impls/int16.rs +++ b/src/expr/src/scalar/func/impls/int16.rs @@ -11,7 +11,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -20,7 +20,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "-", preserves_uniqueness = true, - inverse = to_unary!(NegInt16), + inverse = NegInt16, is_monotone = true )] fn neg_int16(a: i16) -> Result { @@ -31,7 +31,7 @@ fn neg_int16(a: i16) -> Result { #[sqlfunc( sqlname = "~", preserves_uniqueness = true, - inverse = to_unary!(BitNotInt16) + inverse = BitNotInt16 )] fn bit_not_int16(a: i16) -> i16 { !a @@ -46,7 +46,7 @@ fn abs_int16(a: i16) -> Result { #[sqlfunc( sqlname = "smallint_to_real", preserves_uniqueness = true, - inverse = to_unary!(super::CastFloat32ToInt16), + inverse = super::CastFloat32ToInt16, is_monotone = true )] fn cast_int16_to_float32(a: i16) -> f32 { @@ -56,7 +56,7 @@ fn cast_int16_to_float32(a: i16) -> f32 { #[sqlfunc( sqlname = "smallint_to_double", preserves_uniqueness = true, - inverse = to_unary!(super::CastFloat64ToInt16), + inverse = super::CastFloat64ToInt16, is_monotone = true )] fn cast_int16_to_float64(a: i16) -> f64 { @@ -66,7 +66,7 @@ fn cast_int16_to_float64(a: i16) -> f64 { #[sqlfunc( sqlname = "smallint_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToInt16), + inverse = super::CastInt32ToInt16, is_monotone = true )] fn cast_int16_to_int32(a: i16) -> i32 { @@ -76,7 +76,7 @@ fn cast_int16_to_int32(a: i16) -> i32 { #[sqlfunc( sqlname = "smallint_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToInt16), + inverse = super::CastInt64ToInt16, is_monotone = true )] fn cast_int16_to_int64(a: i16) -> i64 { @@ -86,7 +86,7 @@ fn cast_int16_to_int64(a: i16) -> i64 { #[sqlfunc( sqlname = "smallint_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToInt16) + inverse = super::CastStringToInt16 )] fn cast_int16_to_string(a: i16) -> String { let mut buf = String::new(); @@ -97,7 +97,7 @@ fn cast_int16_to_string(a: i16) -> String { #[sqlfunc( sqlname = "smallint_to_uint2", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint16ToInt16), + inverse = super::CastUint16ToInt16, is_monotone = true )] fn cast_int16_to_uint16(a: i16) -> Result { @@ -107,7 +107,7 @@ fn cast_int16_to_uint16(a: i16) -> Result { #[sqlfunc( sqlname = "smallint_to_uint4", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint32ToInt16), + inverse = super::CastUint32ToInt16, is_monotone = true )] fn cast_int16_to_uint32(a: i16) -> Result { @@ -117,7 +117,7 @@ fn cast_int16_to_uint32(a: i16) -> Result { #[sqlfunc( sqlname = "smallint_to_uint8", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint64ToInt16), + inverse = super::CastUint64ToInt16, is_monotone = true )] fn cast_int16_to_uint64(a: i16) -> Result { @@ -141,7 +141,7 @@ impl EagerUnaryFunc for CastInt16ToNumeric { type Input<'a> = i16; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut a = Numeric::from(i32::from(a)); if let Some(scale) = self.0 { if numeric::rescale(&mut a, scale.into_u8()).is_err() { diff --git a/src/expr/src/scalar/func/impls/int2vector.rs b/src/expr/src/scalar/func/impls/int2vector.rs index 1f16072232780..ea8d60becc89c 100644 --- a/src/expr/src/scalar/func/impls/int2vector.rs +++ b/src/expr/src/scalar/func/impls/int2vector.rs @@ -17,7 +17,6 @@ use crate::scalar::func::stringify_datum; #[sqlfunc( sqlname = "int2vectortoarray", is_monotone = true, - introduces_nulls = false, output_type_expr = SqlScalarType::Array(Box::from(SqlScalarType::Int16)) .nullable(input_type.nullable) )] @@ -28,7 +27,7 @@ fn cast_int2_vector_to_array<'a>(a: Int2Vector<'a>) -> Array<'a> { #[sqlfunc( sqlname = "int2vectortostr", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToInt2Vector) + inverse = super::CastStringToInt2Vector )] fn cast_int2_vector_to_string<'a>(a: Int2Vector<'a>) -> Result { let mut buf = String::new(); diff --git a/src/expr/src/scalar/func/impls/int32.rs b/src/expr/src/scalar/func/impls/int32.rs index e89dce9d726b7..a4a5f2746eee3 100644 --- a/src/expr/src/scalar/func/impls/int32.rs +++ b/src/expr/src/scalar/func/impls/int32.rs @@ -13,7 +13,7 @@ use mz_expr_derive::sqlfunc; use mz_ore::cast::ReinterpretCast; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; use mz_repr::adt::system::{Oid, PgLegacyChar}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -22,7 +22,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "-", preserves_uniqueness = true, - inverse = to_unary!(NegInt32), + inverse = NegInt32, is_monotone = true )] fn neg_int32(a: i32) -> Result { @@ -33,7 +33,7 @@ fn neg_int32(a: i32) -> Result { #[sqlfunc( sqlname = "~", preserves_uniqueness = true, - inverse = to_unary!(BitNotInt32) + inverse = BitNotInt32 )] fn bit_not_int32(a: i32) -> i32 { !a @@ -48,7 +48,7 @@ fn abs_int32(a: i32) -> Result { #[sqlfunc( sqlname = "integer_to_boolean", preserves_uniqueness = false, - inverse = to_unary!(super::CastBoolToInt32) + inverse = super::CastBoolToInt32 )] fn cast_int32_to_bool(a: i32) -> bool { a != 0 @@ -57,7 +57,7 @@ fn cast_int32_to_bool(a: i32) -> bool { #[sqlfunc( sqlname = "integer_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToInt32), + inverse = super::CastFloat32ToInt32, is_monotone = true )] fn cast_int32_to_float32(a: i32) -> f32 { @@ -71,7 +71,7 @@ fn cast_int32_to_float32(a: i32) -> f32 { #[sqlfunc( sqlname = "integer_to_double", preserves_uniqueness = true, - inverse = to_unary!(super::CastFloat64ToInt32), + inverse = super::CastFloat64ToInt32, is_monotone = true )] fn cast_int32_to_float64(a: i32) -> f64 { @@ -81,7 +81,7 @@ fn cast_int32_to_float64(a: i32) -> f64 { #[sqlfunc( sqlname = "integer_to_smallint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt16ToInt32), + inverse = super::CastInt16ToInt32, is_monotone = true )] fn cast_int32_to_int16(a: i32) -> Result { @@ -91,7 +91,7 @@ fn cast_int32_to_int16(a: i32) -> Result { #[sqlfunc( sqlname = "integer_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToInt32), + inverse = super::CastInt64ToInt32, is_monotone = true )] fn cast_int32_to_int64(a: i32) -> i64 { @@ -101,7 +101,7 @@ fn cast_int32_to_int64(a: i32) -> i64 { #[sqlfunc( sqlname = "integer_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToInt32) + inverse = super::CastStringToInt32 )] fn cast_int32_to_string(a: i32) -> String { let mut buf = String::new(); @@ -112,7 +112,7 @@ fn cast_int32_to_string(a: i32) -> String { #[sqlfunc( sqlname = "integer_to_uint2", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint16ToInt32), + inverse = super::CastUint16ToInt32, is_monotone = true )] fn cast_int32_to_uint16(a: i32) -> Result { @@ -122,7 +122,7 @@ fn cast_int32_to_uint16(a: i32) -> Result { #[sqlfunc( sqlname = "integer_to_uint4", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint32ToInt32), + inverse = super::CastUint32ToInt32, is_monotone = true )] fn cast_int32_to_uint32(a: i32) -> Result { @@ -132,7 +132,7 @@ fn cast_int32_to_uint32(a: i32) -> Result { #[sqlfunc( sqlname = "integer_to_uint8", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint64ToInt32), + inverse = super::CastUint64ToInt32, is_monotone = true )] fn cast_int32_to_uint64(a: i32) -> Result { @@ -156,7 +156,7 @@ impl EagerUnaryFunc for CastInt32ToNumeric { type Input<'a> = i32; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut a = Numeric::from(a); if let Some(scale) = self.0 { if numeric::rescale(&mut a, scale.into_u8()).is_err() { @@ -193,7 +193,7 @@ impl fmt::Display for CastInt32ToNumeric { #[sqlfunc( sqlname = "integer_to_oid", preserves_uniqueness = true, - inverse = to_unary!(super::CastOidToInt32) + inverse = super::CastOidToInt32 )] fn cast_int32_to_oid(a: i32) -> Oid { // For historical reasons in PostgreSQL, the bytes of the `i32` are @@ -209,7 +209,7 @@ fn cast_int32_to_oid(a: i32) -> Oid { #[sqlfunc( sqlname = "integer_to_\"char\"", preserves_uniqueness = true, - inverse = to_unary!(super::CastPgLegacyCharToInt32) + inverse = super::CastPgLegacyCharToInt32 )] fn cast_int32_to_pg_legacy_char(a: i32) -> Result { // Per PostgreSQL, casts to `PgLegacyChar` are performed as if diff --git a/src/expr/src/scalar/func/impls/int64.rs b/src/expr/src/scalar/func/impls/int64.rs index 763661faadab8..10cf7dc73b1e8 100644 --- a/src/expr/src/scalar/func/impls/int64.rs +++ b/src/expr/src/scalar/func/impls/int64.rs @@ -12,7 +12,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; use mz_repr::adt::system::Oid; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -21,7 +21,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "-", preserves_uniqueness = true, - inverse = to_unary!(NegInt64), + inverse = NegInt64, is_monotone = true )] fn neg_int64(a: i64) -> Result { @@ -32,7 +32,7 @@ fn neg_int64(a: i64) -> Result { #[sqlfunc( sqlname = "~", preserves_uniqueness = true, - inverse = to_unary!(BitNotInt64) + inverse = BitNotInt64 )] fn bit_not_int64(a: i64) -> i64 { !a @@ -47,7 +47,7 @@ fn abs_int64(a: i64) -> Result { #[sqlfunc( sqlname = "bigint_to_boolean", preserves_uniqueness = false, - inverse = to_unary!(super::CastBoolToInt64) + inverse = super::CastBoolToInt64 )] fn cast_int64_to_bool(a: i64) -> bool { a != 0 @@ -56,7 +56,7 @@ fn cast_int64_to_bool(a: i64) -> bool { #[sqlfunc( sqlname = "bigint_to_smallint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt16ToInt64), + inverse = super::CastInt16ToInt64, is_monotone = true )] fn cast_int64_to_int16(a: i64) -> Result { @@ -66,7 +66,7 @@ fn cast_int64_to_int16(a: i64) -> Result { #[sqlfunc( sqlname = "bigint_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToInt64), + inverse = super::CastInt32ToInt64, is_monotone = true )] fn cast_int64_to_int32(a: i64) -> Result { @@ -76,7 +76,7 @@ fn cast_int64_to_int32(a: i64) -> Result { #[sqlfunc( sqlname = "bigint_to_oid", preserves_uniqueness = true, - inverse = to_unary!(super::CastOidToInt64) + inverse = super::CastOidToInt64 )] fn cast_int64_to_oid(a: i64) -> Result { // Unlike casting a 16-bit or 32-bit integers to OID, casting a 64-bit @@ -89,7 +89,7 @@ fn cast_int64_to_oid(a: i64) -> Result { #[sqlfunc( sqlname = "bigint_to_uint2", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint16ToInt64), + inverse = super::CastUint16ToInt64, is_monotone = true )] fn cast_int64_to_uint16(a: i64) -> Result { @@ -99,7 +99,7 @@ fn cast_int64_to_uint16(a: i64) -> Result { #[sqlfunc( sqlname = "bigint_to_uint4", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint32ToInt64), + inverse = super::CastUint32ToInt64, is_monotone = true )] fn cast_int64_to_uint32(a: i64) -> Result { @@ -109,7 +109,7 @@ fn cast_int64_to_uint32(a: i64) -> Result { #[sqlfunc( sqlname = "bigint_to_uint8", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint64ToInt64), + inverse = super::CastUint64ToInt64, is_monotone = true )] fn cast_int64_to_uint64(a: i64) -> Result { @@ -133,7 +133,7 @@ impl EagerUnaryFunc for CastInt64ToNumeric { type Input<'a> = i64; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut a = Numeric::from(a); if let Some(scale) = self.0 { if numeric::rescale(&mut a, scale.into_u8()).is_err() { @@ -170,7 +170,7 @@ impl fmt::Display for CastInt64ToNumeric { #[sqlfunc( sqlname = "bigint_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToInt64), + inverse = super::CastFloat32ToInt64, is_monotone = true )] // TODO(benesch): remove potentially dangerous usage of `as`. @@ -182,7 +182,7 @@ fn cast_int64_to_float32(a: i64) -> f32 { #[sqlfunc( sqlname = "bigint_to_double", preserves_uniqueness = false, // Witness: (1111111111111111111, 1111111111111111112). - inverse = to_unary!(super::CastFloat64ToInt64), + inverse = super::CastFloat64ToInt64, is_monotone = true )] // TODO(benesch): remove potentially dangerous usage of `as`. @@ -194,7 +194,7 @@ fn cast_int64_to_float64(a: i64) -> f64 { #[sqlfunc( sqlname = "bigint_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToInt64) + inverse = super::CastStringToInt64 )] fn cast_int64_to_string(a: i64) -> String { let mut buf = String::new(); diff --git a/src/expr/src/scalar/func/impls/interval.rs b/src/expr/src/scalar/func/impls/interval.rs index a45d6f664b0a7..e8bad917bb776 100644 --- a/src/expr/src/scalar/func/impls/interval.rs +++ b/src/expr/src/scalar/func/impls/interval.rs @@ -19,7 +19,7 @@ use crate::EvalError; #[sqlfunc( sqlname = "interval_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToInterval) + inverse = super::CastStringToInterval )] fn cast_interval_to_string(a: Interval) -> String { let mut buf = String::new(); @@ -30,7 +30,7 @@ fn cast_interval_to_string(a: Interval) -> String { #[sqlfunc( sqlname = "interval_to_time", preserves_uniqueness = false, - inverse = to_unary!(super::CastTimeToInterval) + inverse = super::CastTimeToInterval )] fn cast_interval_to_time(i: Interval) -> NaiveTime { // Modeled after the PostgreSQL implementation: @@ -64,7 +64,7 @@ fn cast_interval_to_time(i: Interval) -> NaiveTime { #[sqlfunc( sqlname = "-", preserves_uniqueness = true, - inverse = to_unary!(super::NegInterval) + inverse = super::NegInterval )] fn neg_interval(i: Interval) -> Result { i.checked_neg() diff --git a/src/expr/src/scalar/func/impls/jsonb.rs b/src/expr/src/scalar/func/impls/jsonb.rs index 92fadbe54f8bd..947b492cae618 100644 --- a/src/expr/src/scalar/func/impls/jsonb.rs +++ b/src/expr/src/scalar/func/impls/jsonb.rs @@ -12,7 +12,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::jsonb::{Jsonb, JsonbRef}; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{Datum, Row, RowPacker, SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{Datum, Row, RowArena, RowPacker, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -22,7 +22,7 @@ use crate::scalar::func::impls::numeric::*; #[sqlfunc( sqlname = "jsonb_to_text", preserves_uniqueness = false, - inverse = to_unary!(super::CastStringToJsonb) + inverse = super::CastStringToJsonb )] pub fn cast_jsonb_to_string<'a>(a: JsonbRef<'a>) -> String { let mut buf = String::new(); @@ -102,7 +102,7 @@ impl EagerUnaryFunc for CastJsonbToNumeric { type Input<'a> = JsonbRef<'a>; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { match a.into_datum() { Datum::Numeric(mut num) => match self.0 { None => Ok(num.into_inner()), diff --git a/src/expr/src/scalar/func/impls/list.rs b/src/expr/src/scalar/func/impls/list.rs index 7b7e1f2f8db18..544c93e190719 100644 --- a/src/expr/src/scalar/func/impls/list.rs +++ b/src/expr/src/scalar/func/impls/list.rs @@ -293,7 +293,7 @@ fn list_length<'a>(a: DatumList<'a>) -> Result { /// The `list_length_max` implementation. /// -/// We're not deriving `sqlfunc` here because we need to pass in the `max_layer` parameter. +/// TODO: convertible to `#[sqlfunc]`, which accepts a `&self` receiver. #[derive( Ord, PartialOrd, diff --git a/src/expr/src/scalar/func/impls/mz_timestamp.rs b/src/expr/src/scalar/func/impls/mz_timestamp.rs index 6f2d637752232..7eb37d079da1e 100644 --- a/src/expr/src/scalar/func/impls/mz_timestamp.rs +++ b/src/expr/src/scalar/func/impls/mz_timestamp.rs @@ -25,7 +25,7 @@ use crate::EvalError; #[sqlfunc( sqlname = "mz_timestamp_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToMzTimestamp) + inverse = super::CastStringToMzTimestamp )] fn cast_mz_timestamp_to_string(a: Timestamp) -> String { let mut buf = String::new(); @@ -36,7 +36,7 @@ fn cast_mz_timestamp_to_string(a: Timestamp) -> String { #[sqlfunc( sqlname = "text_to_mz_timestamp", preserves_uniqueness = false, - inverse = to_unary!(super::CastMzTimestampToString) + inverse = super::CastMzTimestampToString )] fn cast_string_to_mz_timestamp(a: String) -> Result { strconv::parse_mz_timestamp(&a).err_into() @@ -127,7 +127,7 @@ fn cast_date_to_mz_timestamp(a: Date) -> Result { #[sqlfunc( sqlname = "mz_timestamp_to_timestamp", preserves_uniqueness = true, - inverse = to_unary!(super::CastTimestampToMzTimestamp) + inverse = super::CastTimestampToMzTimestamp )] fn cast_mz_timestamp_to_timestamp( a: Timestamp, @@ -143,7 +143,7 @@ fn cast_mz_timestamp_to_timestamp( #[sqlfunc( sqlname = "mz_timestamp_to_timestamp_tz", preserves_uniqueness = true, - inverse = to_unary!(super::CastTimestampTzToMzTimestamp) + inverse = super::CastTimestampTzToMzTimestamp )] fn cast_mz_timestamp_to_timestamp_tz( a: Timestamp, diff --git a/src/expr/src/scalar/func/impls/numeric.rs b/src/expr/src/scalar/func/impls/numeric.rs index 79c0d8369a286..a9e8788fcb3e2 100644 --- a/src/expr/src/scalar/func/impls/numeric.rs +++ b/src/expr/src/scalar/func/impls/numeric.rs @@ -12,7 +12,7 @@ use std::fmt; use dec::{OrderedDecimal, Rounding}; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -21,7 +21,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "-", preserves_uniqueness = true, - inverse = to_unary!(NegNumeric), + inverse = NegNumeric, is_monotone = true )] fn neg_numeric(mut a: Numeric) -> Numeric { @@ -154,7 +154,7 @@ fn sqrt_numeric(mut a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_smallint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt16ToNumeric(None)), + inverse = super::CastInt16ToNumeric(None), is_monotone = true )] pub fn cast_numeric_to_int16(mut a: Numeric) -> Result { @@ -170,7 +170,7 @@ pub fn cast_numeric_to_int16(mut a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_integer", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt32ToNumeric(None)), + inverse = super::CastInt32ToNumeric(None), is_monotone = true )] pub fn cast_numeric_to_int32(mut a: Numeric) -> Result { @@ -184,7 +184,7 @@ pub fn cast_numeric_to_int32(mut a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_bigint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt64ToNumeric(None)), + inverse = super::CastInt64ToNumeric(None), is_monotone = true )] pub fn cast_numeric_to_int64(mut a: Numeric) -> Result { @@ -198,7 +198,7 @@ pub fn cast_numeric_to_int64(mut a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToNumeric(None)), + inverse = super::CastFloat32ToNumeric(None), is_monotone = true )] pub fn cast_numeric_to_float32(a: Numeric) -> Result { @@ -213,7 +213,7 @@ pub fn cast_numeric_to_float32(a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_double", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat64ToNumeric(None)), + inverse = super::CastFloat64ToNumeric(None), is_monotone = true )] pub fn cast_numeric_to_float64(a: Numeric) -> Result { @@ -228,7 +228,7 @@ pub fn cast_numeric_to_float64(a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_text", preserves_uniqueness = false, - inverse = to_unary!(super::CastStringToNumeric(None)) + inverse = super::CastStringToNumeric(None) )] fn cast_numeric_to_string(a: Numeric) -> String { let mut buf = String::new(); @@ -239,7 +239,7 @@ fn cast_numeric_to_string(a: Numeric) -> String { #[sqlfunc( sqlname = "numeric_to_uint2", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint16ToNumeric(None)), + inverse = super::CastUint16ToNumeric(None), is_monotone = true )] fn cast_numeric_to_uint16(mut a: Numeric) -> Result { @@ -255,7 +255,7 @@ fn cast_numeric_to_uint16(mut a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_uint4", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint32ToNumeric(None)), + inverse = super::CastUint32ToNumeric(None), is_monotone = true )] fn cast_numeric_to_uint32(mut a: Numeric) -> Result { @@ -269,7 +269,7 @@ fn cast_numeric_to_uint32(mut a: Numeric) -> Result { #[sqlfunc( sqlname = "numeric_to_uint8", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint64ToNumeric(None)), + inverse = super::CastUint64ToNumeric(None), is_monotone = true )] fn cast_numeric_to_uint64(mut a: Numeric) -> Result { @@ -325,7 +325,7 @@ impl EagerUnaryFunc for AdjustNumericScale { type Input<'a> = Numeric; type Output<'a> = Result; - fn call<'a>(&self, mut d: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, mut d: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { if numeric::rescale(&mut d, self.0.into_u8()).is_err() { return Err(EvalError::NumericFieldOverflow); }; diff --git a/src/expr/src/scalar/func/impls/oid.rs b/src/expr/src/scalar/func/impls/oid.rs index 8dc2459c20b61..1ac1698d48a38 100644 --- a/src/expr/src/scalar/func/impls/oid.rs +++ b/src/expr/src/scalar/func/impls/oid.rs @@ -16,7 +16,7 @@ use mz_repr::strconv; #[sqlfunc( sqlname = "oid_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToOid) + inverse = super::CastStringToOid )] fn cast_oid_to_string(a: Oid) -> String { let mut buf = String::new(); @@ -27,7 +27,7 @@ fn cast_oid_to_string(a: Oid) -> String { #[sqlfunc( sqlname = "oid_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToOid) + inverse = super::CastInt32ToOid )] fn cast_oid_to_int32(a: Oid) -> i32 { // For historical reasons in PostgreSQL, the bytes of the `u32` are @@ -42,7 +42,7 @@ fn cast_oid_to_int32(a: Oid) -> i32 { #[sqlfunc( sqlname = "oid_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToOid) + inverse = super::CastInt64ToOid )] fn cast_oid_to_int64(a: Oid) -> i64 { i64::from(a.0) @@ -51,7 +51,7 @@ fn cast_oid_to_int64(a: Oid) -> i64 { #[sqlfunc( sqlname = "oidtoregclass", preserves_uniqueness = true, - inverse = to_unary!(super::CastRegClassToOid) + inverse = super::CastRegClassToOid )] fn cast_oid_to_reg_class(a: Oid) -> RegClass { RegClass(a.0) @@ -60,7 +60,7 @@ fn cast_oid_to_reg_class(a: Oid) -> RegClass { #[sqlfunc( sqlname = "oidtoregproc", preserves_uniqueness = true, - inverse = to_unary!(super::CastRegProcToOid) + inverse = super::CastRegProcToOid )] fn cast_oid_to_reg_proc(a: Oid) -> RegProc { RegProc(a.0) @@ -69,7 +69,7 @@ fn cast_oid_to_reg_proc(a: Oid) -> RegProc { #[sqlfunc( sqlname = "oidtoregtype", preserves_uniqueness = true, - inverse = to_unary!(super::CastRegTypeToOid) + inverse = super::CastRegTypeToOid )] fn cast_oid_to_reg_type(a: Oid) -> RegType { RegType(a.0) diff --git a/src/expr/src/scalar/func/impls/pg_legacy_char.rs b/src/expr/src/scalar/func/impls/pg_legacy_char.rs index fd24b6fa14110..91136e777dbf4 100644 --- a/src/expr/src/scalar/func/impls/pg_legacy_char.rs +++ b/src/expr/src/scalar/func/impls/pg_legacy_char.rs @@ -38,7 +38,7 @@ where #[sqlfunc( sqlname = "\"char\"_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToPgLegacyChar) + inverse = super::CastStringToPgLegacyChar )] fn cast_pg_legacy_char_to_string(a: PgLegacyChar) -> Result { let mut buf = String::new(); @@ -49,7 +49,7 @@ fn cast_pg_legacy_char_to_string(a: PgLegacyChar) -> Result { #[sqlfunc( sqlname = "\"char\"_to_char", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToPgLegacyChar) + inverse = super::CastStringToPgLegacyChar )] fn cast_pg_legacy_char_to_char(a: PgLegacyChar) -> Result, EvalError> { let mut buf = String::new(); @@ -60,10 +60,10 @@ fn cast_pg_legacy_char_to_char(a: PgLegacyChar) -> Result, EvalErro #[sqlfunc( sqlname = "\"char\"_to_varchar", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToVarChar{ + inverse = super::CastStringToVarChar{ fail_on_len: false, length: Some(VarCharMaxLength::try_from(1).unwrap()), - }) + } )] fn cast_pg_legacy_char_to_var_char(a: PgLegacyChar) -> Result, EvalError> { let mut buf = String::new(); @@ -74,7 +74,7 @@ fn cast_pg_legacy_char_to_var_char(a: PgLegacyChar) -> Result, E #[sqlfunc( sqlname = "\"char\"_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToPgLegacyChar) + inverse = super::CastInt32ToPgLegacyChar )] fn cast_pg_legacy_char_to_int32(a: PgLegacyChar) -> i32 { // Per PostgreSQL, casts to `i32` are performed as if `PgLegacyChar` is diff --git a/src/expr/src/scalar/func/impls/regproc.rs b/src/expr/src/scalar/func/impls/regproc.rs index f2f50269b0385..af2c33b3d96af 100644 --- a/src/expr/src/scalar/func/impls/regproc.rs +++ b/src/expr/src/scalar/func/impls/regproc.rs @@ -13,7 +13,7 @@ use mz_repr::adt::system::{Oid, RegClass, RegProc, RegType}; #[sqlfunc( sqlname = "regclasstooid", preserves_uniqueness = true, - inverse = to_unary!(super::CastOidToRegClass) + inverse = super::CastOidToRegClass )] fn cast_reg_class_to_oid(a: RegClass) -> Oid { Oid(a.0) @@ -22,7 +22,7 @@ fn cast_reg_class_to_oid(a: RegClass) -> Oid { #[sqlfunc( sqlname = "regproctooid", preserves_uniqueness = true, - inverse = to_unary!(super::CastOidToRegProc) + inverse = super::CastOidToRegProc )] fn cast_reg_proc_to_oid(a: RegProc) -> Oid { Oid(a.0) @@ -31,7 +31,7 @@ fn cast_reg_proc_to_oid(a: RegProc) -> Oid { #[sqlfunc( sqlname = "regtypetooid", preserves_uniqueness = true, - inverse = to_unary!(super::CastOidToRegType) + inverse = super::CastOidToRegType )] fn cast_reg_type_to_oid(a: RegType) -> Oid { Oid(a.0) diff --git a/src/expr/src/scalar/func/impls/string.rs b/src/expr/src/scalar/func/impls/string.rs index 28de6c8a32734..35fecbcccca74 100644 --- a/src/expr/src/scalar/func/impls/string.rs +++ b/src/expr/src/scalar/func/impls/string.rs @@ -39,7 +39,7 @@ use crate::{Eval, EvalError, MirScalarExpr, UnaryFunc, like_pattern}; #[sqlfunc( sqlname = "text_to_boolean", preserves_uniqueness = false, - inverse = to_unary!(super::CastBoolToString) + inverse = super::CastBoolToString )] fn cast_string_to_bool<'a>(a: &'a str) -> Result { strconv::parse_bool(a).err_into() @@ -51,7 +51,7 @@ fn cast_string_to_bool<'a>(a: &'a str) -> Result { // collapse to 'a'::"char"), so inverse-cast canonicalization of // `c::text = lit` would silently change results. preserves_uniqueness = false, - inverse = to_unary!(super::CastPgLegacyCharToString) + inverse = super::CastPgLegacyCharToString )] fn cast_string_to_pg_legacy_char<'a>(a: &'a str) -> PgLegacyChar { PgLegacyChar(a.as_bytes().get(0).copied().unwrap_or(0)) @@ -70,7 +70,7 @@ fn cast_string_to_pg_legacy_name<'a>(a: &'a str) -> PgLegacyName { // `b::text = lit` would otherwise rewrite to a comparison that ignores // the actual textual form. preserves_uniqueness = false, - inverse = to_unary!(super::CastBytesToString) + inverse = super::CastBytesToString )] fn cast_string_to_bytes<'a>(a: &'a str) -> Result, EvalError> { strconv::parse_bytes(a).err_into() @@ -79,7 +79,7 @@ fn cast_string_to_bytes<'a>(a: &'a str) -> Result, EvalError> { #[sqlfunc( sqlname = "text_to_smallint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt16ToString) + inverse = super::CastInt16ToString )] fn cast_string_to_int16<'a>(a: &'a str) -> Result { strconv::parse_int16(a).err_into() @@ -88,7 +88,7 @@ fn cast_string_to_int16<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_integer", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt32ToString) + inverse = super::CastInt32ToString )] fn cast_string_to_int32<'a>(a: &'a str) -> Result { strconv::parse_int32(a).err_into() @@ -97,7 +97,7 @@ fn cast_string_to_int32<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_bigint", preserves_uniqueness = false, - inverse = to_unary!(super::CastInt64ToString) + inverse = super::CastInt64ToString )] fn cast_string_to_int64<'a>(a: &'a str) -> Result { strconv::parse_int64(a).err_into() @@ -106,7 +106,7 @@ fn cast_string_to_int64<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToString) + inverse = super::CastFloat32ToString )] fn cast_string_to_float32<'a>(a: &'a str) -> Result { strconv::parse_float32(a).err_into() @@ -115,7 +115,7 @@ fn cast_string_to_float32<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_double", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat64ToString) + inverse = super::CastFloat64ToString )] fn cast_string_to_float64<'a>(a: &'a str) -> Result { strconv::parse_float64(a).err_into() @@ -124,7 +124,7 @@ fn cast_string_to_float64<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_oid", preserves_uniqueness = false, - inverse = to_unary!(super::CastOidToString) + inverse = super::CastOidToString )] fn cast_string_to_oid<'a>(a: &'a str) -> Result { Ok(Oid(strconv::parse_oid(a)?)) @@ -133,7 +133,7 @@ fn cast_string_to_oid<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_uint2", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint16ToString) + inverse = super::CastUint16ToString )] fn cast_string_to_uint16(a: &str) -> Result { strconv::parse_uint16(a).err_into() @@ -142,7 +142,7 @@ fn cast_string_to_uint16(a: &str) -> Result { #[sqlfunc( sqlname = "text_to_uint4", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint32ToString) + inverse = super::CastUint32ToString )] fn cast_string_to_uint32(a: &str) -> Result { strconv::parse_uint32(a).err_into() @@ -151,13 +151,13 @@ fn cast_string_to_uint32(a: &str) -> Result { #[sqlfunc( sqlname = "text_to_uint8", preserves_uniqueness = false, - inverse = to_unary!(super::CastUint64ToString) + inverse = super::CastUint64ToString )] fn cast_string_to_uint64(a: &str) -> Result { strconv::parse_uint64(a).err_into() } -#[sqlfunc(preserves_uniqueness = true, inverse = to_unary!(Reverse))] +#[sqlfunc(preserves_uniqueness = true, inverse = Reverse)] fn reverse<'a>(a: &'a str) -> String { a.chars().rev().collect() } @@ -179,7 +179,7 @@ impl EagerUnaryFunc for CastStringToNumeric { type Input<'a> = &'a str; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut d = strconv::parse_numeric(a)?; if let Some(scale) = self.0 { if numeric::rescale(&mut d.0, scale.into_u8()).is_err() { @@ -207,7 +207,7 @@ impl fmt::Display for CastStringToNumeric { #[sqlfunc( sqlname = "text_to_date", preserves_uniqueness = false, - inverse = to_unary!(super::CastDateToString) + inverse = super::CastDateToString )] fn cast_string_to_date<'a>(a: &'a str) -> Result { strconv::parse_date(a).err_into() @@ -216,7 +216,7 @@ fn cast_string_to_date<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_time", preserves_uniqueness = false, - inverse = to_unary!(super::CastTimeToString) + inverse = super::CastTimeToString )] fn cast_string_to_time<'a>(a: &'a str) -> Result { strconv::parse_time(a).err_into() @@ -239,7 +239,7 @@ impl EagerUnaryFunc for CastStringToTimestamp { type Input<'a> = &'a str; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let out = strconv::parse_timestamp(a)?; let updated = out.round_to_precision(self.0)?; Ok(updated) @@ -292,7 +292,7 @@ impl EagerUnaryFunc for CastStringToTimestampTz { type Input<'a> = &'a str; type Output<'a> = Result>, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let out = strconv::parse_timestamptz(a)?; let updated = out.round_to_precision(self.0)?; Ok(updated) @@ -316,7 +316,7 @@ impl fmt::Display for CastStringToTimestampTz { #[sqlfunc( sqlname = "text_to_interval", preserves_uniqueness = false, - inverse = to_unary!(super::CastIntervalToString) + inverse = super::CastIntervalToString )] fn cast_string_to_interval<'a>(a: &'a str) -> Result { strconv::parse_interval(a).err_into() @@ -325,7 +325,7 @@ fn cast_string_to_interval<'a>(a: &'a str) -> Result { #[sqlfunc( sqlname = "text_to_uuid", preserves_uniqueness = false, - inverse = to_unary!(super::CastUuidToString) + inverse = super::CastUuidToString )] fn cast_string_to_uuid<'a>(a: &'a str) -> Result { strconv::parse_uuid(a).err_into() @@ -696,7 +696,7 @@ impl EagerUnaryFunc for CastStringToChar { type Input<'a> = &'a str; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let s = format_str_trim(a, self.length, self.fail_on_len).map_err(|_| { assert!(self.fail_on_len); EvalError::StringValueTooLong { @@ -878,7 +878,7 @@ impl EagerUnaryFunc for CastStringToVarChar { type Input<'a> = &'a str; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let s = mz_repr::adt::varchar::format_str(a, self.length, self.fail_on_len).map_err(|_| { assert!(self.fail_on_len); @@ -1015,7 +1015,7 @@ impl fmt::Display for CastStringToInt2Vector { #[sqlfunc( sqlname = "text_to_jsonb", preserves_uniqueness = false, - inverse = to_unary!(super::CastJsonbToString) + inverse = super::CastJsonbToString )] // TODO(jamii): it would be much more efficient to skip the intermediate repr::jsonb::Jsonb. fn cast_string_to_jsonb<'a>(a: &'a str) -> Result { @@ -1120,7 +1120,7 @@ impl EagerUnaryFunc for IsLikeMatch { type Input<'a> = &'a str; type Output<'a> = bool; - fn call<'a>(&self, haystack: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, haystack: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { self.0.is_match(haystack) } @@ -1157,7 +1157,7 @@ impl EagerUnaryFunc for IsRegexpMatch { type Input<'a> = &'a str; type Output<'a> = bool; - fn call<'a>(&self, haystack: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, haystack: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { self.0.is_match(haystack) } diff --git a/src/expr/src/scalar/func/impls/time.rs b/src/expr/src/scalar/func/impls/time.rs index a3a2e11e8ec36..849d43dbe9f05 100644 --- a/src/expr/src/scalar/func/impls/time.rs +++ b/src/expr/src/scalar/func/impls/time.rs @@ -16,7 +16,7 @@ use mz_repr::adt::datetime::{DateTimeField, DateTimeUnits}; use mz_repr::adt::interval::Interval; use mz_repr::adt::numeric::{DecimalLike, Numeric}; use mz_repr::adt::timestamp::TimeLike; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -25,7 +25,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "time_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToTime) + inverse = super::CastStringToTime )] fn cast_time_to_string(a: NaiveTime) -> String { let mut buf = String::new(); @@ -36,7 +36,7 @@ fn cast_time_to_string(a: NaiveTime) -> String { #[sqlfunc( sqlname = "time_to_interval", preserves_uniqueness = true, - inverse = to_unary!(super::CastIntervalToTime) + inverse = super::CastIntervalToTime )] fn cast_time_to_interval(t: NaiveTime) -> Interval { // wont overflow because value can't exceed 24 hrs + 1_000_000 ns = 86_400 seconds + 1_000_000 ns = 86_400_001_000 us @@ -103,7 +103,7 @@ impl EagerUnaryFunc for ExtractTime { type Input<'a> = NaiveTime; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_time_inner(self.0, a) } @@ -135,7 +135,7 @@ impl EagerUnaryFunc for DatePartTime { type Input<'a> = NaiveTime; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_time_inner(self.0, a) } @@ -180,7 +180,7 @@ impl EagerUnaryFunc for TimezoneTime { type Input<'a> = NaiveTime; type Output<'a> = NaiveTime; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { timezone_time(self.tz, a, &self.wall_time) } diff --git a/src/expr/src/scalar/func/impls/timestamp.rs b/src/expr/src/scalar/func/impls/timestamp.rs index 67101b913c809..7ecda69066a6d 100644 --- a/src/expr/src/scalar/func/impls/timestamp.rs +++ b/src/expr/src/scalar/func/impls/timestamp.rs @@ -21,7 +21,7 @@ use mz_repr::adt::timestamp::{ CheckedTimestamp, MAX_PRECISION, TimestampPrecision, checked_add_with_leapsecond, checked_sub_with_leapsecond, }; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -32,7 +32,7 @@ use crate::scalar::func::{EagerUnaryFunc, TimestampLike}; #[sqlfunc( sqlname = "timestamp_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToTimestamp(None)) + inverse = super::CastStringToTimestamp(None) )] fn cast_timestamp_to_string(a: CheckedTimestamp) -> String { let mut buf = String::new(); @@ -43,7 +43,7 @@ fn cast_timestamp_to_string(a: CheckedTimestamp) -> String { #[sqlfunc( sqlname = "timestamp_with_time_zone_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToTimestampTz(None)) + inverse = super::CastStringToTimestampTz(None) )] fn cast_timestamp_tz_to_string(a: CheckedTimestamp>) -> String { let mut buf = String::new(); @@ -54,7 +54,7 @@ fn cast_timestamp_tz_to_string(a: CheckedTimestamp>) -> String { #[sqlfunc( sqlname = "timestamp_to_date", preserves_uniqueness = false, - inverse = to_unary!(super::CastDateToTimestamp(None)), + inverse = super::CastDateToTimestamp(None), is_monotone = true )] fn cast_timestamp_to_date(a: CheckedTimestamp) -> Result { @@ -64,7 +64,7 @@ fn cast_timestamp_to_date(a: CheckedTimestamp) -> Result>) -> Result { @@ -91,7 +91,7 @@ impl EagerUnaryFunc for CastTimestampToTimestampTz { type Input<'a> = CheckedTimestamp; type Output<'a> = Result>, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let out = CheckedTimestamp::try_from(DateTime::::from_naive_utc_and_offset(a.into(), Utc))?; let updated = out.round_to_precision(self.to)?; @@ -147,7 +147,7 @@ impl EagerUnaryFunc for AdjustTimestampPrecision { type Input<'a> = CheckedTimestamp; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { // This should never have been called if precisions are same. // Adding a soft-assert to flag if there are such instances. mz_ore::soft_assert_no_log!(self.to != self.from); @@ -202,7 +202,7 @@ impl EagerUnaryFunc for CastTimestampTzToTimestamp { type Input<'a> = CheckedTimestamp>; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let out = CheckedTimestamp::try_from(a.naive_utc())?; let updated = out.round_to_precision(self.to)?; Ok(updated) @@ -257,7 +257,7 @@ impl EagerUnaryFunc for AdjustTimestampTzPrecision { type Input<'a> = CheckedTimestamp>; type Output<'a> = Result>, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { // This should never have been called if precisions are same. // Adding a soft-assert to flag if there are such instances. mz_ore::soft_assert_no_log!(self.to != self.from); @@ -354,7 +354,7 @@ impl EagerUnaryFunc for ExtractInterval { type Input<'a> = Interval; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_interval_inner(self.0, a) } @@ -386,7 +386,7 @@ impl EagerUnaryFunc for DatePartInterval { type Input<'a> = Interval; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_interval_inner(self.0, a) } @@ -464,7 +464,7 @@ impl EagerUnaryFunc for ExtractTimestamp { type Input<'a> = CheckedTimestamp; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_timestamp_inner(self.0, &*a) } @@ -500,7 +500,7 @@ impl EagerUnaryFunc for ExtractTimestampTz { type Input<'a> = CheckedTimestamp>; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_timestamp_inner(self.0, &*a) } @@ -539,7 +539,7 @@ impl EagerUnaryFunc for DatePartTimestamp { type Input<'a> = CheckedTimestamp; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_timestamp_inner(self.0, &*a) } @@ -571,7 +571,7 @@ impl EagerUnaryFunc for DatePartTimestampTz { type Input<'a> = CheckedTimestamp>; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_part_timestamp_inner(self.0, &*a) } @@ -632,7 +632,7 @@ impl EagerUnaryFunc for DateTruncTimestamp { type Input<'a> = CheckedTimestamp; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_trunc_inner(self.0, &*a)?.try_into().err_into() } @@ -668,7 +668,7 @@ impl EagerUnaryFunc for DateTruncTimestampTz { type Input<'a> = CheckedTimestamp>; type Output<'a> = Result>, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { date_trunc_inner(self.0, &*a)?.try_into().err_into() } @@ -748,7 +748,7 @@ impl EagerUnaryFunc for TimezoneTimestamp { type Input<'a> = CheckedTimestamp; type Output<'a> = Result>, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { timezone_timestamp(self.0, a.to_naive()) } @@ -780,7 +780,7 @@ impl EagerUnaryFunc for TimezoneTimestampTz { type Input<'a> = CheckedTimestamp>; type Output<'a> = Result, EvalError>; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { timezone_timestamptz(self.0, a.into())? .try_into() .err_into() @@ -817,7 +817,7 @@ impl EagerUnaryFunc for ToCharTimestamp { type Input<'a> = CheckedTimestamp; type Output<'a> = String; - fn call<'a>(&self, input: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, input: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { self.format.render(&*input) } @@ -852,7 +852,7 @@ impl EagerUnaryFunc for ToCharTimestampTz { type Input<'a> = CheckedTimestamp>; type Output<'a> = String; - fn call<'a>(&self, input: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, input: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { self.format.render(&*input) } diff --git a/src/expr/src/scalar/func/impls/uint16.rs b/src/expr/src/scalar/func/impls/uint16.rs index afa6f6d0d9c94..3dfebd9a791d2 100644 --- a/src/expr/src/scalar/func/impls/uint16.rs +++ b/src/expr/src/scalar/func/impls/uint16.rs @@ -11,7 +11,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -20,7 +20,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "~", preserves_uniqueness = true, - inverse = to_unary!(super::BitNotUint16) + inverse = super::BitNotUint16 )] fn bit_not_uint16(a: u16) -> u16 { !a @@ -29,7 +29,7 @@ fn bit_not_uint16(a: u16) -> u16 { #[sqlfunc( sqlname = "uint2_to_real", preserves_uniqueness = true, - inverse = to_unary!(super::CastFloat32ToUint16), + inverse = super::CastFloat32ToUint16, is_monotone = true )] fn cast_uint16_to_float32(a: u16) -> f32 { @@ -39,7 +39,7 @@ fn cast_uint16_to_float32(a: u16) -> f32 { #[sqlfunc( sqlname = "uint2_to_double", preserves_uniqueness = true, - inverse = to_unary!(super::CastFloat64ToUint16), + inverse = super::CastFloat64ToUint16, is_monotone = true )] fn cast_uint16_to_float64(a: u16) -> f64 { @@ -49,7 +49,7 @@ fn cast_uint16_to_float64(a: u16) -> f64 { #[sqlfunc( sqlname = "uint2_to_uint4", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint32ToUint16), + inverse = super::CastUint32ToUint16, is_monotone = true )] fn cast_uint16_to_uint32(a: u16) -> u32 { @@ -59,7 +59,7 @@ fn cast_uint16_to_uint32(a: u16) -> u32 { #[sqlfunc( sqlname = "uint2_to_uint8", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint64ToUint16), + inverse = super::CastUint64ToUint16, is_monotone = true )] fn cast_uint16_to_uint64(a: u16) -> u64 { @@ -69,7 +69,7 @@ fn cast_uint16_to_uint64(a: u16) -> u64 { #[sqlfunc( sqlname = "uint2_to_smallint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt16ToUint16), + inverse = super::CastInt16ToUint16, is_monotone = true )] fn cast_uint16_to_int16(a: u16) -> Result { @@ -79,7 +79,7 @@ fn cast_uint16_to_int16(a: u16) -> Result { #[sqlfunc( sqlname = "uint2_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToUint16), + inverse = super::CastInt32ToUint16, is_monotone = true )] fn cast_uint16_to_int32(a: u16) -> i32 { @@ -88,7 +88,7 @@ fn cast_uint16_to_int32(a: u16) -> i32 { #[sqlfunc( sqlname = "uint2_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToUint16), + inverse = super::CastInt64ToUint16, is_monotone = true )] fn cast_uint16_to_int64(a: u16) -> i64 { @@ -98,7 +98,7 @@ fn cast_uint16_to_int64(a: u16) -> i64 { #[sqlfunc( sqlname = "uint2_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToUint16) + inverse = super::CastStringToUint16 )] fn cast_uint16_to_string(a: u16) -> String { let mut buf = String::new(); @@ -123,7 +123,7 @@ impl EagerUnaryFunc for CastUint16ToNumeric { type Input<'a> = u16; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut a = Numeric::from(i32::from(a)); if let Some(scale) = self.0 { if numeric::rescale(&mut a, scale.into_u8()).is_err() { diff --git a/src/expr/src/scalar/func/impls/uint32.rs b/src/expr/src/scalar/func/impls/uint32.rs index 24d4d456136e1..fa6c43f1375a5 100644 --- a/src/expr/src/scalar/func/impls/uint32.rs +++ b/src/expr/src/scalar/func/impls/uint32.rs @@ -11,7 +11,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -20,7 +20,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "~", preserves_uniqueness = true, - inverse = to_unary!(super::BitNotUint32) + inverse = super::BitNotUint32 )] fn bit_not_uint32(a: u32) -> u32 { !a @@ -29,7 +29,7 @@ fn bit_not_uint32(a: u32) -> u32 { #[sqlfunc( sqlname = "uint4_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToUint32), + inverse = super::CastFloat32ToUint32, is_monotone = true )] fn cast_uint32_to_float32(a: u32) -> f32 { @@ -43,7 +43,7 @@ fn cast_uint32_to_float32(a: u32) -> f32 { #[sqlfunc( sqlname = "uint4_to_double", preserves_uniqueness = true, - inverse = to_unary!(super::CastFloat64ToUint32), + inverse = super::CastFloat64ToUint32, is_monotone = true )] fn cast_uint32_to_float64(a: u32) -> f64 { @@ -57,7 +57,7 @@ fn cast_uint32_to_float64(a: u32) -> f64 { // into an index lookup on `col`, skipping the cast and dropping its // out-of-range error. preserves_uniqueness = false, - inverse = to_unary!(super::CastUint16ToUint32), + inverse = super::CastUint16ToUint32, is_monotone = true )] fn cast_uint32_to_uint16(a: u32) -> Result { @@ -67,7 +67,7 @@ fn cast_uint32_to_uint16(a: u32) -> Result { #[sqlfunc( sqlname = "uint4_to_uint8", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint64ToUint32), + inverse = super::CastUint64ToUint32, is_monotone = true )] fn cast_uint32_to_uint64(a: u32) -> u64 { @@ -78,7 +78,7 @@ fn cast_uint32_to_uint64(a: u32) -> u64 { sqlname = "uint4_to_smallint", // Partial: errors for `u32` values above `i16::MAX`. See `uint4_to_uint2`. preserves_uniqueness = false, - inverse = to_unary!(super::CastInt16ToUint32), + inverse = super::CastInt16ToUint32, is_monotone = true )] fn cast_uint32_to_int16(a: u32) -> Result { @@ -89,7 +89,7 @@ fn cast_uint32_to_int16(a: u32) -> Result { sqlname = "uint4_to_integer", // Partial: errors for `u32` values above `i32::MAX`. See `uint4_to_uint2`. preserves_uniqueness = false, - inverse = to_unary!(super::CastInt32ToUint32), + inverse = super::CastInt32ToUint32, is_monotone = true )] fn cast_uint32_to_int32(a: u32) -> Result { @@ -99,7 +99,7 @@ fn cast_uint32_to_int32(a: u32) -> Result { #[sqlfunc( sqlname = "uint4_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToUint32), + inverse = super::CastInt64ToUint32, is_monotone = true )] fn cast_uint32_to_int64(a: u32) -> i64 { @@ -109,7 +109,7 @@ fn cast_uint32_to_int64(a: u32) -> i64 { #[sqlfunc( sqlname = "uint4_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToUint32) + inverse = super::CastStringToUint32 )] fn cast_uint32_to_string(a: u32) -> String { let mut buf = String::new(); @@ -134,7 +134,7 @@ impl EagerUnaryFunc for CastUint32ToNumeric { type Input<'a> = u32; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut a = Numeric::from(a); if let Some(scale) = self.0 { if numeric::rescale(&mut a, scale.into_u8()).is_err() { diff --git a/src/expr/src/scalar/func/impls/uint64.rs b/src/expr/src/scalar/func/impls/uint64.rs index 86ad5cee67da3..9e42d38d91bf4 100644 --- a/src/expr/src/scalar/func/impls/uint64.rs +++ b/src/expr/src/scalar/func/impls/uint64.rs @@ -11,7 +11,7 @@ use std::fmt; use mz_expr_derive::sqlfunc; use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale}; -use mz_repr::{SqlColumnType, SqlScalarType, strconv}; +use mz_repr::{RowArena, SqlColumnType, SqlScalarType, strconv}; use serde::{Deserialize, Serialize}; use crate::EvalError; @@ -20,7 +20,7 @@ use crate::scalar::func::EagerUnaryFunc; #[sqlfunc( sqlname = "~", preserves_uniqueness = true, - inverse = to_unary!(super::BitNotUint64) + inverse = super::BitNotUint64 )] fn bit_not_uint64(a: u64) -> u64 { !a @@ -29,7 +29,7 @@ fn bit_not_uint64(a: u64) -> u64 { #[sqlfunc( sqlname = "uint8_to_real", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat32ToUint64), + inverse = super::CastFloat32ToUint64, is_monotone = true )] fn cast_uint64_to_float32(a: u64) -> f32 { @@ -43,7 +43,7 @@ fn cast_uint64_to_float32(a: u64) -> f32 { #[sqlfunc( sqlname = "uint8_to_double", preserves_uniqueness = false, - inverse = to_unary!(super::CastFloat64ToUint64), + inverse = super::CastFloat64ToUint64, is_monotone = true )] fn cast_uint64_to_float64(a: u64) -> f64 { @@ -57,7 +57,7 @@ fn cast_uint64_to_float64(a: u64) -> f64 { #[sqlfunc( sqlname = "uint8_to_uint2", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint16ToUint64), + inverse = super::CastUint16ToUint64, is_monotone = true )] fn cast_uint64_to_uint16(a: u64) -> Result { @@ -67,7 +67,7 @@ fn cast_uint64_to_uint16(a: u64) -> Result { #[sqlfunc( sqlname = "uint8_to_uint4", preserves_uniqueness = true, - inverse = to_unary!(super::CastUint32ToUint64), + inverse = super::CastUint32ToUint64, is_monotone = true )] fn cast_uint64_to_uint32(a: u64) -> Result { @@ -77,7 +77,7 @@ fn cast_uint64_to_uint32(a: u64) -> Result { #[sqlfunc( sqlname = "uint8_to_smallint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt16ToUint64), + inverse = super::CastInt16ToUint64, is_monotone = true )] fn cast_uint64_to_int16(a: u64) -> Result { @@ -87,7 +87,7 @@ fn cast_uint64_to_int16(a: u64) -> Result { #[sqlfunc( sqlname = "uint8_to_integer", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt32ToUint64), + inverse = super::CastInt32ToUint64, is_monotone = true )] fn cast_uint64_to_int32(a: u64) -> Result { @@ -97,7 +97,7 @@ fn cast_uint64_to_int32(a: u64) -> Result { #[sqlfunc( sqlname = "uint8_to_bigint", preserves_uniqueness = true, - inverse = to_unary!(super::CastInt64ToUint64), + inverse = super::CastInt64ToUint64, is_monotone = true )] fn cast_uint64_to_int64(a: u64) -> Result { @@ -107,7 +107,7 @@ fn cast_uint64_to_int64(a: u64) -> Result { #[sqlfunc( sqlname = "uint8_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToUint64) + inverse = super::CastStringToUint64 )] fn cast_uint64_to_string(a: u64) -> String { let mut buf = String::new(); @@ -132,7 +132,7 @@ impl EagerUnaryFunc for CastUint64ToNumeric { type Input<'a> = u64; type Output<'a> = Result; - fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> { + fn call<'a>(&self, a: Self::Input<'a>, _temp_storage: &'a RowArena) -> Self::Output<'a> { let mut a = Numeric::from(a); if let Some(scale) = self.0 { if numeric::rescale(&mut a, scale.into_u8()).is_err() { diff --git a/src/expr/src/scalar/func/impls/uuid.rs b/src/expr/src/scalar/func/impls/uuid.rs index 95b6064544f47..cc02680a3642e 100644 --- a/src/expr/src/scalar/func/impls/uuid.rs +++ b/src/expr/src/scalar/func/impls/uuid.rs @@ -14,7 +14,7 @@ use uuid::Uuid; #[sqlfunc( sqlname = "uuid_to_text", preserves_uniqueness = true, - inverse = to_unary!(super::CastStringToUuid) + inverse = super::CastStringToUuid )] fn cast_uuid_to_string(u: Uuid) -> String { let mut buf = String::with_capacity(36); diff --git a/src/expr/src/scalar/func/impls/varchar.rs b/src/expr/src/scalar/func/impls/varchar.rs index 76aeec77477eb..ffd270357a525 100644 --- a/src/expr/src/scalar/func/impls/varchar.rs +++ b/src/expr/src/scalar/func/impls/varchar.rs @@ -15,10 +15,10 @@ use mz_repr::adt::varchar::VarChar; sqlname = "varchar_to_text", preserves_uniqueness = true, is_eliminable_cast = true, - inverse = to_unary!(super::CastStringToVarChar { + inverse = super::CastStringToVarChar { length: None, fail_on_len: false, - }), + }, )] fn cast_var_char_to_string<'a>(a: VarChar<&'a str>) -> &'a str { a.0 diff --git a/src/expr/src/scalar/func/macros.rs b/src/expr/src/scalar/func/macros.rs index a6522d54a549b..10f90e439003a 100644 --- a/src/expr/src/scalar/func/macros.rs +++ b/src/expr/src/scalar/func/macros.rs @@ -136,6 +136,42 @@ mod test { SqlScalarType::Float32.nullable(true) ); } + + // Separate from the tests above, which call the lazy traits' methods and would + // find them ambiguous with the eager traits in scope. + mod stateful { + use mz_expr_derive::sqlfunc; + use mz_repr::RowArena; + + use crate::EvalError; + use crate::scalar::func::EagerUnaryFunc; + use crate::scalar::func::binary::EagerBinaryFunc; + + pub struct AddOffset(i64); + + #[sqlfunc(sqlname = "add_offset")] + fn add_offset(&self, a: i64) -> i64 { + a + self.0 + } + + pub struct ScaleSum(i64); + + #[sqlfunc(sqlname = "scale_sum")] + fn scale_sum(&self, a: i64, b: i64) -> Result { + (a + b) + .checked_mul(self.0) + .ok_or(EvalError::NumericFieldOverflow) + } + + #[mz_ore::test] + fn stateful_unary_and_binary_read_their_state() { + let arena = RowArena::new(); + assert_eq!(EagerUnaryFunc::call(&AddOffset(3), 4, &arena), 7); + assert_eq!(EagerBinaryFunc::call(&ScaleSum(2), (3, 4), &arena), Ok(14)); + assert_eq!(format!("{}", AddOffset(3)), "add_offset"); + assert_eq!(format!("{}", ScaleSum(2)), "scale_sum"); + } + } } /// Temporary macro that generates the equivalent of what enum_dispatch will do in the future. We diff --git a/src/expr/src/scalar/func/unary.rs b/src/expr/src/scalar/func/unary.rs index 60c7eb268da11..7783b6be946c9 100644 --- a/src/expr/src/scalar/func/unary.rs +++ b/src/expr/src/scalar/func/unary.rs @@ -111,7 +111,7 @@ pub trait EagerUnaryFunc { type Input<'a>: InputDatumType<'a, EvalError>; type Output<'a>: OutputDatumType<'a, EvalError>; - fn call<'a>(&self, input: Self::Input<'a>) -> Self::Output<'a>; + fn call<'a>(&self, input: Self::Input<'a>, temp_storage: &'a RowArena) -> Self::Output<'a>; /// The output SqlColumnType of this function fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType; @@ -165,7 +165,7 @@ impl LazyUnaryFunc for T { ) -> Result, EvalError> { match T::Input::<'_>::try_from_result(a.eval(datums, temp_storage)) { // If we can convert to the input type then we call the function - Ok(input) => self.call(input).into_result(temp_storage), + Ok(input) => self.call(input, temp_storage).into_result(temp_storage), // If we can't and we got a non-null datum something went wrong in the planner Err(Ok(datum)) if !datum.is_null() => { Err(EvalError::Internal("invalid input type".into())) diff --git a/src/expr/src/scalar/func/variadic.rs b/src/expr/src/scalar/func/variadic.rs index 3248a896eddb7..c284acbf9d387 100644 --- a/src/expr/src/scalar/func/variadic.rs +++ b/src/expr/src/scalar/func/variadic.rs @@ -373,7 +373,7 @@ fn array_fill<'a>( pub struct ArrayIndex { pub offset: i64, } -#[sqlfunc(ArrayIndex, sqlname = "array_index", introduces_nulls = true)] +#[sqlfunc(ArrayIndex, sqlname = "array_index")] fn array_index<'a, T: FromDatum<'a>>( &self, array: Array<'a, T>, @@ -598,48 +598,36 @@ impl fmt::Display for RangeCreate { } } -impl EagerVariadicFunc for RangeCreate { - type Input<'a> = (Datum<'a>, Datum<'a>, Datum<'a>); - type Output<'a> = Result, EvalError>; - - fn call<'a>( - &self, - (lower, upper, flags_datum): Self::Input<'a>, - temp_storage: &'a RowArena, - ) -> Self::Output<'a> { - let flags = match flags_datum { - Datum::Null => { - return Err(EvalError::InvalidRange( - InvalidRangeError::NullRangeBoundFlags, - )); - } - o => o.unwrap_str(), - }; - - let (lower_inclusive, upper_inclusive) = parse_range_bound_flags(flags)?; - - let mut range = Range::new(Some(( - RangeBound::new(lower, lower_inclusive), - RangeBound::new(upper, upper_inclusive), - ))); +#[sqlfunc( + RangeCreate, + skip_display = true, + output_type_expr = "SqlScalarType::Range { element_type: Box::new(self.elem_type.clone()) }.nullable(false)" +)] +fn range_create<'a>( + &self, + lower: Datum<'a>, + upper: Datum<'a>, + flags_datum: Datum<'a>, +) -> Result>, EvalError> { + let flags = match flags_datum { + Datum::Null => { + return Err(EvalError::InvalidRange( + InvalidRangeError::NullRangeBoundFlags, + )); + } + o => o.unwrap_str(), + }; - range.canonicalize()?; + let (lower_inclusive, upper_inclusive) = parse_range_bound_flags(flags)?; - Ok(temp_storage.make_datum(|row| { - row.push_range(range).expect("errors already handled"); - })) - } + let mut range = Range::new(Some(( + RangeBound::new(lower, lower_inclusive), + RangeBound::new(upper, upper_inclusive), + ))); - fn output_type(&self, _input_types: &[SqlColumnType]) -> SqlColumnType { - SqlScalarType::Range { - element_type: Box::new(self.elem_type.clone()), - } - .nullable(false) - } + range.canonicalize()?; - fn introduces_nulls(&self) -> bool { - false - } + Ok(range) } #[sqlfunc(sqlname = "datediff")] @@ -1013,8 +1001,7 @@ fn record_create<'a>( } #[sqlfunc( - output_type_expr = "input_types[0].scalar_type.unwrap_list_nth_layer_type(input_types.len() - 1).clone().nullable(true)", - introduces_nulls = true + output_type_expr = "input_types[0].scalar_type.unwrap_list_nth_layer_type(input_types.len() - 1).clone().nullable(true)" )] // TODO(benesch): remove potentially dangerous usage of `as`. #[allow(clippy::as_conversions)] @@ -1304,8 +1291,7 @@ fn pad_leading( } #[sqlfunc( - output_type_expr = "SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true)", - introduces_nulls = true + output_type_expr = "SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true)" )] fn regexp_match<'a>( haystack: &'a str,