diff --git a/Cargo.lock b/Cargo.lock
index 223889581470d..b7473fdd9243f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6232,7 +6232,6 @@ dependencies = [
"openssl",
"opentelemetry",
"prometheus",
- "proptest",
"prost",
"qcell",
"rand 0.10.3",
diff --git a/doc/user/content/sql/functions/cast.md b/doc/user/content/sql/functions/cast.md
index 67bf61a6ad6ad..d92a29ceb4d63 100644
--- a/doc/user/content/sql/functions/cast.md
+++ b/doc/user/content/sql/functions/cast.md
@@ -1,14 +1,12 @@
---
-title: "CAST and TRY_CAST"
+title: "CAST function and operator"
description: "Returns the value converted to the specified type"
menu:
main:
parent: 'sql-functions'
---
-The `cast` function and operator return a value converted to the specified
-[type](../../types/). The `try_cast` function does the same, but returns `NULL`
-instead of an error when the value cannot be converted.
+The `cast` function and operator return a value converted to the specified [type](../../types/).
## Signatures
@@ -20,16 +18,10 @@ The following special syntax is permitted if _val_ is a string literal:
{{% include-syntax file="examples/sql_functions/cast" example="syntax-literal" %}}
-{{% include-syntax file="examples/sql_functions/cast" example="syntax-try-cast" %}}
-
### Return value
`cast` returns the value with the type specified by the _type_ parameter.
-`try_cast` returns the value with the type specified by the _type_ parameter,
-or `NULL` if the conversion fails. Its result is nullable whenever the
-conversion can fail, even when the value being converted is not.
-
## Details
### Valid casts
@@ -177,67 +169,6 @@ Source type | Return type
2 Casting a [`float`](../../types/float/) to a [`numeric`](../../types/numeric/) can yield an imprecise result due to the floating point arithmetic involved in the conversion.
-### `TRY_CAST`
-
-{{< public-preview />}}
-
-`TRY_CAST` accepts the same explicit casts as `CAST`, and returns `NULL` where
-`CAST` would return an error: for example, text that does not parse as the
-target type, a number that does not fit in the target type, or a JSON value of
-the wrong kind. When the conversion succeeds, `TRY_CAST` and `CAST` return the
-same value.
-
-`TRY_CAST` only suppresses errors from the conversion itself. Errors raised
-while computing the value being converted still propagate:
-
-```mzsql
-SELECT TRY_CAST(1 / 0 AS text);
-```
-```nofmt
-ERROR: division by zero
-```
-
-A parameter whose type is inferred from `TRY_CAST` is decoded as the target
-type when the statement is bound, so a bound value that does not convert is a
-bind error rather than `NULL`. To get `NULL` instead, give the parameter an
-explicit type:
-
-```mzsql
-SELECT TRY_CAST($1::text AS int);
-```
-
-Converting a value of a composite type ([`array`](../../types/array/),
-[`list`](../../types/list/), or [`record`](../../types/record/)) converts each
-element. If any element fails to convert, `TRY_CAST` returns `NULL` for the
-whole value rather than a value with `NULL` elements.
-
-`TRY_CAST` accepts every explicit cast that `CAST` does, with these
-differences, each of which is reported when the statement is planned:
-
-- `TRY_CAST` does not support the casts that look up objects in the catalog:
- casts to or from `regclass`, `regproc`, `regtype`, `aclitem`, and
- [`mz_aclitem`](../../types/mz_aclitem/), other than those between the `oid`
- alias types and the integer types.
-
-- An `ARRAY`, `LIST`, or `ROW` constructor written directly inside `TRY_CAST`
- is typed on its own before the conversion, where `CAST` would type it from
- the target. Its elements must therefore already agree on a type, and an
- empty constructor needs an explicit type:
-
- ```mzsql
- -- With a text column s, CAST(ARRAY[s, 2] AS int[]) plans, but this does not:
- -- "ARRAY types text and integer cannot be matched".
- SELECT TRY_CAST(ARRAY[s, 2] AS int[]) FROM t;
- -- Give the elements a common type instead.
- SELECT TRY_CAST(ARRAY[s, 2::text] AS int[]) FROM t;
- SELECT TRY_CAST(ARRAY[]::text[] AS int[]);
- ```
-
-- A `MAP` constructor written directly inside `TRY_CAST` is rejected. It would
- be typed on its own like the other constructors, and there is no cast
- between two [`map`](../../types/map/) types to convert it afterward. Convert
- it with `CAST` or `::` instead.
-
## Examples
```mzsql
@@ -271,29 +202,5 @@ SELECT 100.21::numeric(10, 2)::float AS dec_to_float;
100.21
```
-
-
-```mzsql
-SELECT TRY_CAST('42' AS int) AS ok, TRY_CAST('forty-two' AS int) AS bad;
-```
-```nofmt
- ok | bad
-----+-----
- 42 |
-```
-
-
-
-Routing rows whose values do not convert, instead of failing the whole view:
-
-```mzsql
-CREATE VIEW parsed AS
- SELECT raw, TRY_CAST(raw AS timestamp) AS ts
- FROM events;
-
-CREATE VIEW unparseable AS
- SELECT raw FROM parsed WHERE ts IS NULL AND raw IS NOT NULL;
-```
-
## Related topics
* [Data Types](../../types/)
diff --git a/doc/user/data/examples/sql_functions/cast.yml b/doc/user/data/examples/sql_functions/cast.yml
index d73537fd51770..edaad0b222a60 100644
--- a/doc/user/data/examples/sql_functions/cast.yml
+++ b/doc/user/data/examples/sql_functions/cast.yml
@@ -20,17 +20,6 @@
description: |
The return value's [type](/sql/types/).
-- name: "syntax-try-cast"
- code: |
- TRY_CAST ( AS )
- syntax_elements:
- - name: "``"
- description: |
- Any value you want to convert.
- - name: "**AS** ``"
- description: |
- The return value's [type](/sql/types/).
-
- name: "syntax-literal"
code: |
''
diff --git a/doc/user/data/sql_funcs.yml b/doc/user/data/sql_funcs.yml
index dd35ce712ed5b..3882e88901889 100644
--- a/doc/user/data/sql_funcs.yml
+++ b/doc/user/data/sql_funcs.yml
@@ -5,11 +5,6 @@
description: Value as type `T`
url: /sql/functions/cast
- - signature: TRY_CAST (cast_expr) -> T?
- description: Value as type `T`, or _NULL_ if the conversion fails.
- url: /sql/functions/cast#try_cast
- version-added: v26.45
-
- signature: 'coalesce(x: T...) -> T?'
description: First non-_NULL_ arg, or _NULL_ if all are _NULL_.
diff --git a/misc/python/materialize/mzcompose/__init__.py b/misc/python/materialize/mzcompose/__init__.py
index 014a9a0af967e..ac33a4161dc18 100644
--- a/misc/python/materialize/mzcompose/__init__.py
+++ b/misc/python/materialize/mzcompose/__init__.py
@@ -134,7 +134,6 @@ def get_minimal_system_parameters(
),
"enable_s3_tables_region_check": "false",
"enable_statement_lifecycle_logging": "true",
- "enable_try_cast": "true",
# Introspection goldens depend on the replica topology, so tests need
# one consistent value rather than a varying one.
"enable_unified_cluster": (
diff --git a/src/adapter/Cargo.toml b/src/adapter/Cargo.toml
index c296b52d51ef6..2ecb728a48c27 100644
--- a/src/adapter/Cargo.toml
+++ b/src/adapter/Cargo.toml
@@ -107,8 +107,6 @@ datadriven.workspace = true
mz-alloc-default = { path = "../alloc-default" }
mz-persist = { path = "../persist", features = ["turmoil"] }
mz-persist-client = { path = "../persist-client", features = ["turmoil"] }
-mz-repr = { path = "../repr", features = ["proptest"] }
-proptest.workspace = true
turmoil.workspace = true
[[bench]]
diff --git a/src/adapter/src/catalog.rs b/src/adapter/src/catalog.rs
index c776e39f0c51f..402855e4565d3 100644
--- a/src/adapter/src/catalog.rs
+++ b/src/adapter/src/catalog.rs
@@ -3713,376 +3713,6 @@ mod tests {
}
}
- /// `TRY_CAST` must plan as the strict cast with every unary stage wrapped
- /// in `TryCast`, for every pair of types the strict cast supports, except
- /// the SQL-implemented casts, which it must refuse with a dedicated error.
- #[mz_ore::test(tokio::test)]
- #[cfg_attr(miri, ignore)] // unsupported operation: can't call foreign function `TLS_client_method` on OS `linux`
- async fn test_try_cast_wraps_every_stage_of_every_cast() {
- use mz_expr::UnaryFunc;
- use mz_expr::func::TryCast;
- use mz_expr::visit::{Visit, VisitChildren};
- use mz_ore::collections::CollectionExt;
- use mz_repr::SqlScalarBaseType as B;
- use mz_repr::explain::ExprHumanizer;
- use mz_sql::plan::{HirRelationExpr, Params, Plan, PlanError, valid_cast_base_type_pairs};
-
- /// Calls `f` on every scalar expression node in `rel`, including those
- /// inside subqueries.
- fn for_each_scalar(rel: &HirRelationExpr, f: &mut impl FnMut(&HirScalarExpr)) {
- rel.visit_pre(&mut |rel: &HirRelationExpr| {
- rel.visit_children(|scalar: &HirScalarExpr| scalar.visit_pre(&mut *f));
- });
- }
-
- fn unary_calls(rel: &HirRelationExpr) -> Vec {
- let mut funcs = vec![];
- for_each_scalar(rel, &mut |e| {
- if let HirScalarExpr::CallUnary { func, .. } = e {
- funcs.push(func.clone());
- }
- });
- funcs
- }
-
- fn has_subquery(rel: &HirRelationExpr) -> bool {
- let mut found = false;
- for_each_scalar(rel, &mut |e| {
- found |= matches!(e, HirScalarExpr::Exists(..) | HirScalarExpr::Select(..));
- });
- found
- }
-
- Catalog::with_debug(|mut catalog| async move {
- catalog
- .system_config_mut()
- .set("enable_try_cast", VarInput::Flat("on"))
- .expect("valid setting");
- // A record type can only be named in SQL through a user-defined
- // type, so create one to reach the record-to-record cast.
- let (id, gid) = catalog
- .allocate_user_id_for_test()
- .await
- .expect("allocate id");
- let item = catalog
- .state()
- .deserialize_item(
- gid,
- "CREATE TYPE materialize.public.rec AS (a pg_catalog.int8, b pg_catalog.text)",
- &BTreeMap::new(),
- &mut LocalExpressionCache::Closed,
- None,
- )
- .expect("valid type");
- let commit_ts = catalog.current_upper().await;
- catalog
- .transact(
- None,
- commit_ts,
- None,
- vec![Op::CreateItem {
- item,
- name: QualifiedItemName {
- qualifiers: ItemQualifiers {
- database_spec: ResolvedDatabaseSpecifier::Id(DatabaseId::User(1)),
- schema_spec: SchemaSpecifier::Id(SchemaId::User(3)),
- },
- item: "rec".to_string(),
- },
- id,
- owner_id: MZ_SYSTEM_ROLE_ID,
- }],
- )
- .await
- .expect("create type");
- let conn_catalog = catalog.for_system_session();
- let pcx = PlanContext::zero();
- let plan_select = |expr: std::string::String| -> Result {
- let sql = format!("SELECT {expr}");
- let stmt = mz_sql_parser::parser::parse_statements(&sql)
- .expect("parses")
- .into_element()
- .ast;
- let (stmt, resolved_ids) = mz_sql::names::resolve(&conn_catalog, stmt)?;
- let params = Params::empty();
- let (plan, _) =
- mz_sql::plan::plan(Some(&pcx), &conn_catalog, stmt, ¶ms, &resolved_ids)?;
- match plan {
- Plan::Select(plan) => Ok(plan.source),
- other => panic!("expected a SELECT plan, got {other:?}"),
- }
- };
-
- // `SqlScalarType::enumerate` has no instance of the parameterized
- // type families, nor of `name` and `aclitem`, so those come as
- // hand-written SQL. A source is an expression of the type; a target
- // is a type name. The anonymous record source has a field of a
- // different type than `rec`, so casting it there converts a field.
- let mut sources: Vec<(std::string::String, B)> = SqlScalarType::enumerate()
- .iter()
- .map(|ty| {
- let name = conn_catalog.humanize_sql_scalar_type(ty, false);
- (format!("NULL::{name}"), ty.into())
- })
- .collect();
- let mut targets: Vec<(std::string::String, B)> = SqlScalarType::enumerate()
- .iter()
- .map(|ty| (conn_catalog.humanize_sql_scalar_type(ty, false), ty.into()))
- .collect();
- let extra_types = [
- ("name", B::PgLegacyName),
- ("aclitem", B::AclItem),
- ("int4 list", B::List),
- ("int8 list", B::List),
- ("int2[]", B::Array),
- ("int4[]", B::Array),
- ("int8[]", B::Array),
- ("map[text=>int4]", B::Map),
- ("int4range", B::Range),
- ("materialize.public.rec", B::Record),
- ];
- for (name, base) in extra_types {
- sources.push((format!("NULL::{name}"), base));
- targets.push((name.to_string(), base));
- }
- sources.push(("ROW(1, 'a')".to_string(), B::Record));
-
- let mut exercised = BTreeSet::new();
- let mut unsupported = BTreeSet::new();
- let mut unplannable = BTreeSet::new();
- for (source, from) in &sources {
- for (to_name, to) in &targets {
- let strict = plan_select(format!("CAST({source} AS {to_name})"));
- let lenient = plan_select(format!("TRY_CAST({source} AS {to_name})"));
- let strict = match strict {
- Ok(strict) => strict,
- Err(PlanError::InvalidCast { .. }) => {
- assert!(
- matches!(lenient, Err(PlanError::InvalidCast { .. })),
- "{source} to {to_name}: CAST is invalid, so TRY_CAST must be too, got {lenient:?}"
- );
- continue;
- }
- Err(_) => {
- unplannable.insert((source.clone(), to_name.clone()));
- continue;
- }
- };
- let strict_funcs = unary_calls(&strict);
- assert!(
- !strict_funcs.iter().any(|f| matches!(f, UnaryFunc::TryCast(_))),
- "{source} to {to_name}: CAST must not produce TryCast, got {strict_funcs:?}"
- );
- exercised.insert((*from, *to));
- match lenient {
- Ok(lenient) => {
- // Spelled out rather than built with
- // `UnaryFunc::try_cast`, which the planner itself
- // uses: an oracle built from the code under test
- // would pass an always-wrap mutant.
- let wrapped: Vec = strict_funcs
- .iter()
- .map(|f| {
- if f.could_error() {
- UnaryFunc::TryCast(TryCast {
- inner: Box::new(f.clone()),
- })
- } else {
- f.clone()
- }
- })
- .collect();
- assert_eq!(
- unary_calls(&lenient),
- wrapped,
- "{source} to {to_name}: TRY_CAST must wrap every fallible stage of CAST"
- );
- }
- Err(PlanError::TryCastUnsupported { .. }) => {
- assert!(
- has_subquery(&strict),
- "{source} to {to_name}: TRY_CAST refused a cast that is not SQL-implemented"
- );
- unsupported.insert((*from, *to));
- }
- Err(err) => panic!("{source} to {to_name}: unexpected error {err}"),
- }
- }
- }
- assert!(unplannable.is_empty(), "casts that did not plan: {unplannable:?}");
-
- let table: BTreeSet<(B, B)> = valid_cast_base_type_pairs().collect();
- let unexercised: Vec<_> = table.difference(&exercised).collect();
- assert!(
- unexercised.is_empty(),
- "cast table entries the type lists above do not reach: {unexercised:?}"
- );
-
- // The string category routes through `text`, so each catalog-lookup
- // cast is refused for every string-like type.
- let string_like = [B::String, B::Char, B::VarChar, B::PgLegacyChar, B::PgLegacyName];
- let mut expected = BTreeSet::new();
- for s in string_like {
- for reg in [B::RegClass, B::RegProc, B::RegType] {
- expected.insert((s, reg));
- expected.insert((reg, s));
- }
- for acl in [B::AclItem, B::MzAclItem] {
- expected.insert((acl, s));
- }
- }
- expected.insert((B::AclItem, B::MzAclItem));
- expected.insert((B::MzAclItem, B::AclItem));
- assert_eq!(unsupported, expected);
- })
- .await;
- }
-
- /// For every type pair `TRY_CAST` supports and many values of the source
- /// type, `TRY_CAST` agrees with `CAST` where `CAST` succeeds and is NULL
- /// where `CAST` errors. It never errors itself.
- #[mz_ore::test(tokio::test)]
- #[cfg_attr(miri, ignore)] // unsupported operation: can't call foreign function `TLS_client_method` on OS `linux`
- async fn proptest_try_cast_agrees_with_cast() {
- use std::cell::Cell;
-
- use mz_expr::CastFailureMode;
- use mz_repr::{ColumnName, arb_datum_for_scalar};
- use mz_sql::plan::{CastContext, plan_hypothetical_cast_with_failure_mode};
- use proptest::test_runner::{Config, TestRunner};
-
- fn record(fields: &[(&str, SqlScalarType)]) -> SqlScalarType {
- SqlScalarType::Record {
- fields: fields
- .iter()
- .map(|(name, ty)| (ColumnName::from(*name), ty.clone().nullable(true)))
- .collect(),
- custom_id: None,
- }
- }
-
- Catalog::with_debug(|catalog| async move {
- let conn_catalog = catalog.for_system_session();
- let pcx = PlanContext::zero();
- let scx = StatementContext::new(Some(&pcx), &conn_catalog);
- let qcx = QueryContext::root(&scx, QueryLifetime::OneShot);
- let ecx = ExprContext {
- qcx: &qcx,
- name: "proptest_try_cast",
- scope: &Scope::empty(),
- relation_type: &SqlRelationType::empty(),
- allow_aggregates: false,
- allow_subqueries: true,
- allow_parameters: false,
- allow_windows: false,
- };
- let plan = |mode, from: &SqlScalarType, to: &SqlScalarType| {
- let ccx = CastContext::Explicit;
- plan_hypothetical_cast_with_failure_mode(&ecx, ccx, mode, from, to)
- };
-
- // `SqlScalarType::enumerate` has no instance of the parameterized
- // type families, nor of `name` and `aclitem`. Two widths of each
- // container so that the element casts are exercised.
- let mut types = SqlScalarType::enumerate().to_vec();
- types.extend([
- SqlScalarType::PgLegacyName,
- SqlScalarType::AclItem,
- SqlScalarType::List {
- element_type: Box::new(SqlScalarType::Int32),
- custom_id: None,
- },
- SqlScalarType::List {
- element_type: Box::new(SqlScalarType::Int64),
- custom_id: None,
- },
- SqlScalarType::Array(Box::new(SqlScalarType::Int32)),
- SqlScalarType::Array(Box::new(SqlScalarType::Int64)),
- SqlScalarType::Map {
- value_type: Box::new(SqlScalarType::Int32),
- custom_id: None,
- },
- SqlScalarType::Range {
- element_type: Box::new(SqlScalarType::Int32),
- },
- record(&[("a", SqlScalarType::Int32), ("b", SqlScalarType::String)]),
- record(&[("a", SqlScalarType::Int64), ("b", SqlScalarType::String)]),
- ]);
-
- let mut pairs = 0usize;
- // Counted from inside `check`, which the proptest runner requires
- // to be `Fn`, hence the `Cell`.
- let values = Cell::new(0usize);
- for from in &types {
- for to in &types {
- let Some(strict) = plan(CastFailureMode::Error, from, to) else {
- continue;
- };
- let Some(lenient) = plan(CastFailureMode::NullFallback, from, to) else {
- // The SQL-implemented casts, refused by the planner.
- continue;
- };
- pairs += 1;
- let arena = RowArena::new();
- let check = |datum: Datum| {
- values.set(values.get() + 1);
- let row = [datum];
- let strict_result = strict.eval(&row, &arena);
- let lenient_result = lenient.eval(&row, &arena);
- match (&strict_result, &lenient_result) {
- (Ok(s), Ok(l)) => assert_eq!(
- s, l,
- "{from:?} to {to:?} on {datum}: TRY_CAST differs from CAST"
- ),
- (Err(_), Ok(Datum::Null)) => {}
- (Err(err), Ok(l)) => panic!(
- "{from:?} to {to:?} on {datum}: CAST errors ({err}) but TRY_CAST gives {l}"
- ),
- (_, Err(err)) => {
- panic!("{from:?} to {to:?} on {datum}: TRY_CAST errored: {err}")
- }
- }
- };
-
- // Edge values, then NULL, then random values of the source
- // type.
- for datum in from.interesting_datums() {
- check(datum);
- }
- check(Datum::Null);
- let mut runner = TestRunner::new(Config {
- cases: 64,
- ..Config::default()
- });
- runner
- .run(&arb_datum_for_scalar(from.clone()), |pd| {
- check(Datum::from(&pd));
- Ok(())
- })
- .expect("oracle holds");
-
- // A random string almost never parses as the target type,
- // so for string sources also feed the rendering of random
- // target values, which exercises the success branch.
- let render = plan(CastFailureMode::Error, to, &SqlScalarType::String);
- if from.base_eq(&SqlScalarType::String) && let Some(render) = render {
- runner
- .run(&arb_datum_for_scalar(to.clone()), |pd| {
- if let Ok(s) = render.eval(&[Datum::from(&pd)], &arena) {
- check(s);
- }
- Ok(())
- })
- .expect("oracle holds");
- }
- }
- }
- assert!(pairs > 200, "only {pairs} pairs exercised");
- assert!(values.get() > 10_000, "only {} values checked", values.get());
- })
- .await;
- }
-
fn smoketest_fn(
name: &&str,
call_name: String,
diff --git a/src/compute-types/tests/snapshots/func_registry.json b/src/compute-types/tests/snapshots/func_registry.json
index 40d22170943a0..3011949cfcf27 100644
--- a/src/compute-types/tests/snapshots/func_registry.json
+++ b/src/compute-types/tests/snapshots/func_registry.json
@@ -578,11 +578,6 @@
"trunc_float32": {"variant":"TruncFloat32","propagates_nulls":true,"introduces_nulls":false,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["Float32:NotNull"],"output_type":"Float32:NotNull","sqlfunc_signature":"fn(f32) -> f32"},
"trunc_float64": {"variant":"TruncFloat64","propagates_nulls":true,"introduces_nulls":false,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["Float64:NotNull"],"output_type":"Float64:NotNull","sqlfunc_signature":"fn(f64) -> f64"},
"trunc_numeric": {"variant":"TruncNumeric","propagates_nulls":true,"introduces_nulls":false,"could_error":false,"preserves_uniqueness":false,"is_monotone":true,"is_eliminable_cast":false,"inverse":null,"input_types":["Numeric { max_scale: None }:NotNull"],"output_type":"Numeric { max_scale: None }:NotNull","sqlfunc_signature":"fn(Numeric) -> Numeric"},
- "try_cast": {"variant":"TryCast","propagates_nulls":true,"introduces_nulls":true,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["String:NotNull"],"output_type":"Int32:Null","sqlfunc_signature":null},
- "try_cast[infallible]": {"variant":"TryCast","propagates_nulls":true,"introduces_nulls":false,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["Int32:NotNull"],"output_type":"Int64:Null","sqlfunc_signature":null},
- "try_cast[jsonb]": {"variant":"TryCast","propagates_nulls":true,"introduces_nulls":true,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["Jsonb:NotNull"],"output_type":"Numeric { max_scale: None }:Null","sqlfunc_signature":null},
- "try_cast[list]": {"variant":"TryCast","propagates_nulls":true,"introduces_nulls":true,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["List { element_type: Int64, custom_id: None }:NotNull"],"output_type":"List { element_type: Int32, custom_id: None }:Null","sqlfunc_signature":null},
- "try_cast[narrowing]": {"variant":"TryCast","propagates_nulls":true,"introduces_nulls":true,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["Int64:NotNull"],"output_type":"Int32:Null","sqlfunc_signature":null},
"try_parse_monotonic_iso8601_timestamp": {"variant":"TryParseMonotonicIso8601Timestamp","propagates_nulls":true,"introduces_nulls":true,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["String:NotNull"],"output_type":"Timestamp { precision: None }:Null","sqlfunc_signature":"fn(&'a str) -> Option>"},
"upper": {"variant":"Upper","propagates_nulls":true,"introduces_nulls":false,"could_error":false,"preserves_uniqueness":false,"is_monotone":false,"is_eliminable_cast":false,"inverse":null,"input_types":["String:NotNull"],"output_type":"String:NotNull","sqlfunc_signature":"fn(&'a str) -> String"}
},
diff --git a/src/compute-types/tests/snapshots/func_registry_digests.json b/src/compute-types/tests/snapshots/func_registry_digests.json
index 5f8d4a2116229..83abe62f0005d 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:628fcb08bde495ddd92d1f1d004c4abfa5b69b6456b4ccac1580a43aed8a601c"
}
diff --git a/src/compute-types/tests/snapshots/func_registry_source.json b/src/compute-types/tests/snapshots/func_registry_source.json
index 413670921c869..f5aaf0b008968 100644
--- a/src/compute-types/tests/snapshots/func_registry_source.json
+++ b/src/compute-types/tests/snapshots/func_registry_source.json
@@ -578,11 +578,6 @@
"trunc_float32": {"display":"truncf32","sqlfunc_decl":"#[sqlfunc(sqlname = \"truncf32\")] fn trunc_float32(a: f32) -> f32","body_fingerprint":"b9a309bede7a3d9d"},
"trunc_float64": {"display":"truncf64","sqlfunc_decl":"#[sqlfunc(sqlname = \"truncf64\")] fn trunc_float64(a: f64) -> f64","body_fingerprint":"b9a309bede7a3d9d"},
"trunc_numeric": {"display":"truncnumeric","sqlfunc_decl":"#[sqlfunc(sqlname = \"truncnumeric\", is_monotone = true)] fn trunc_numeric(mut a: Numeric) -> Numeric","body_fingerprint":"325db9fb2ac6dff2"},
- "try_cast": {"display":"try_cast[text_to_integer]","sqlfunc_decl":null,"body_fingerprint":null},
- "try_cast[infallible]": {"display":"try_cast[integer_to_bigint]","sqlfunc_decl":null,"body_fingerprint":null},
- "try_cast[jsonb]": {"display":"try_cast[jsonb_to_numeric]","sqlfunc_decl":null,"body_fingerprint":null},
- "try_cast[list]": {"display":"try_cast[list1tolist2]","sqlfunc_decl":null,"body_fingerprint":null},
- "try_cast[narrowing]": {"display":"try_cast[bigint_to_integer]","sqlfunc_decl":null,"body_fingerprint":null},
"try_parse_monotonic_iso8601_timestamp": {"display":"try_parse_monotonic_iso8601_timestamp","sqlfunc_decl":"#[sqlfunc(sqlname = \"try_parse_monotonic_iso8601_timestamp\")] fn try_parse_monotonic_iso8601_timestamp<'a>(a: &'a str,) -> Option>","body_fingerprint":"248be614321cc3e0"},
"upper": {"display":"upper","sqlfunc_decl":"#[sqlfunc] fn upper<'a>(a: &'a str) -> String","body_fingerprint":"b2fbf9e0812208ab"}
},
diff --git a/src/compute-types/tests/snapshots/lir_v1.json b/src/compute-types/tests/snapshots/lir_v1.json
index 8abbd8dc80994..f303aa43faf80 100644
--- a/src/compute-types/tests/snapshots/lir_v1.json
+++ b/src/compute-types/tests/snapshots/lir_v1.json
@@ -3654,13 +3654,6 @@
"TruncFloat32": "UNITSTRUCT",
"TruncFloat64": "UNITSTRUCT",
"TruncNumeric": "UNITSTRUCT",
- "TryCast": {
- "STRUCT": {
- "inner": {
- "TYPENAME": "UnaryFunc"
- }
- }
- },
"TryParseMonotonicIso8601Timestamp": "UNITSTRUCT",
"UnaryFunc": {
"ENUM": {
@@ -5334,11 +5327,6 @@
"TYPENAME": "TruncNumeric"
}
},
- "TryCast": {
- "NEWTYPE": {
- "TYPENAME": "TryCast"
- }
- },
"TryParseMonotonicIso8601Timestamp": {
"NEWTYPE": {
"TYPENAME": "TryParseMonotonicIso8601Timestamp"
diff --git a/src/expr-parser/src/parser.rs b/src/expr-parser/src/parser.rs
index d25449ae5622e..d446a382903ea 100644
--- a/src/expr-parser/src/parser.rs
+++ b/src/expr-parser/src/parser.rs
@@ -1380,22 +1380,6 @@ mod scalar {
exprs,
))
}
- // `try_cast[]()` wraps the named cast so
- // that its errors become NULL.
- "try_cast" => {
- let name = params.parse::()?;
- let Some(cast) = UnaryFunc::from_variant_name(&name.to_string()) else {
- return Err(Error::new(name.span(), "unsupported function name"));
- };
- let expr = Box::new(parse_expr(&inner)?);
- Ok(MirScalarExpr::CallUnary {
- func: func::TryCast {
- inner: Box::new(cast),
- }
- .into(),
- expr,
- })
- }
_ => Err(Error::new(
ident.span(),
"unsupported parameterized function",
diff --git a/src/expr/fuzz/fuzz_targets/mfp_optimize.rs b/src/expr/fuzz/fuzz_targets/mfp_optimize.rs
index 58fd0c959e566..8ae846c935ac8 100644
--- a/src/expr/fuzz/fuzz_targets/mfp_optimize.rs
+++ b/src/expr/fuzz/fuzz_targets/mfp_optimize.rs
@@ -71,7 +71,7 @@ use std::collections::{BTreeMap, BTreeSet};
use libfuzzer_sys::arbitrary::{self, Arbitrary, Unstructured};
use libfuzzer_sys::fuzz_target;
use mz_expr::{
- Eval, EvalError, MapFilterProject, MirScalarExpr, SafeMfpPlan, UnaryFunc, UnmaterializableFunc,
+ Eval, EvalError, MapFilterProject, MirScalarExpr, SafeMfpPlan, UnmaterializableFunc,
VariadicFunc, func,
};
use mz_repr::{Datum, Diff, ReprScalarType, Row, RowArena, Timestamp};
@@ -165,22 +165,6 @@ fn gen_leaf(u: &mut Unstructured, want: Ty, cols: &[Ty]) -> arbitrary::Result,
-) -> arbitrary::Result {
- let cast = cast.into();
- Ok(if bool::arbitrary(u)? {
- UnaryFunc::try_cast(cast)
- } else {
- cast
- })
-}
-
fn gen_scalar(
u: &mut Unstructured,
want: Ty,
@@ -208,8 +192,7 @@ fn gen_scalar(
4 => Ok(gen_scalar(u, Ty::Int, cols, d)?
.call_binary(gen_scalar(u, Ty::Int, cols, d)?, func::ModInt32)),
// int8 -> int4 (fallible: out-of-range overflows).
- _ => Ok(gen_scalar(u, Ty::Long, cols, d)?
- .call_unary(maybe_try_cast(u, func::CastInt64ToInt32)?)),
+ _ => Ok(gen_scalar(u, Ty::Long, cols, d)?.call_unary(func::CastInt64ToInt32)),
},
Ty::Long => match u.int_in_range(0u8..=4)? {
0 => {
@@ -225,8 +208,7 @@ fn gen_scalar(
3 => Ok(gen_scalar(u, Ty::Long, cols, d)?
.call_binary(gen_scalar(u, Ty::Long, cols, d)?, func::MulInt64)),
// int4 -> int8 (infallible widening).
- _ => Ok(gen_scalar(u, Ty::Int, cols, d)?
- .call_unary(maybe_try_cast(u, func::CastInt32ToInt64)?)),
+ _ => Ok(gen_scalar(u, Ty::Int, cols, d)?.call_unary(func::CastInt32ToInt64)),
},
Ty::Bool => match u.int_in_range(0u8..=5)? {
0 => {
diff --git a/src/expr/fuzz/fuzz_targets/mir_scalar_reduce.rs b/src/expr/fuzz/fuzz_targets/mir_scalar_reduce.rs
index 8d0c073bd204e..975bd23ab40e6 100644
--- a/src/expr/fuzz/fuzz_targets/mir_scalar_reduce.rs
+++ b/src/expr/fuzz/fuzz_targets/mir_scalar_reduce.rs
@@ -66,7 +66,7 @@
use libfuzzer_sys::arbitrary::{self, Arbitrary, Unstructured};
use libfuzzer_sys::fuzz_target;
use mz_expr::func::variadic::{And, Or};
-use mz_expr::{Eval, EvalError, MirScalarExpr, UnaryFunc, VariadicFunc, func};
+use mz_expr::{Eval, EvalError, MirScalarExpr, VariadicFunc, func};
use mz_repr::{Datum, ReprColumnType, ReprScalarType, Row, RowArena};
// Column layout: a contiguous block per type. Columns are nullable.
@@ -273,22 +273,6 @@ fn gen_wide_and_or(u: &mut Unstructured, depth: u32) -> arbitrary::Result,
-) -> arbitrary::Result {
- let cast = cast.into();
- Ok(if bool::arbitrary(u)? {
- UnaryFunc::try_cast(cast)
- } else {
- cast
- })
-}
-
fn gen_expr(u: &mut Unstructured, ty: Ty, depth: u32) -> arbitrary::Result {
if depth == 0 || u.ratio(2u8, 5u8)? {
return gen_leaf(u, ty);
@@ -313,10 +297,8 @@ fn gen_expr(u: &mut Unstructured, ty: Ty, depth: u32) -> arbitrary::Result Ok(gen_expr(u, Ty::Int, d)?.call_unary(func::AbsInt32)),
// Casts that produce an int4.
_ => match u.int_in_range(0u8..=2)? {
- 0 => Ok(gen_expr(u, Ty::Long, d)?
- .call_unary(maybe_try_cast(u, func::CastInt64ToInt32)?)),
- 1 => Ok(gen_expr(u, Ty::Str, d)?
- .call_unary(maybe_try_cast(u, func::CastStringToInt32)?)),
+ 0 => Ok(gen_expr(u, Ty::Long, d)?.call_unary(func::CastInt64ToInt32)),
+ 1 => Ok(gen_expr(u, Ty::Str, d)?.call_unary(func::CastStringToInt32)),
_ => Ok(gen_expr(u, Ty::Str, d)?.call_unary(func::ByteLengthString)),
},
},
@@ -342,10 +324,8 @@ fn gen_expr(u: &mut Unstructured, ty: Ty, depth: u32) -> arbitrary::Result Ok(gen_expr(u, Ty::Long, d)?.call_unary(func::AbsInt64)),
// Casts that produce an int8.
_ => match u.int_in_range(0u8..=1)? {
- 0 => Ok(gen_expr(u, Ty::Int, d)?
- .call_unary(maybe_try_cast(u, func::CastInt32ToInt64)?)),
- _ => Ok(gen_expr(u, Ty::Str, d)?
- .call_unary(maybe_try_cast(u, func::CastStringToInt64)?)),
+ 0 => Ok(gen_expr(u, Ty::Int, d)?.call_unary(func::CastInt32ToInt64)),
+ _ => Ok(gen_expr(u, Ty::Str, d)?.call_unary(func::CastStringToInt64)),
},
}
}
@@ -381,24 +361,20 @@ fn gen_expr(u: &mut Unstructured, ty: Ty, depth: u32) -> arbitrary::Result bool cast.
- _ => Ok(gen_expr(u, Ty::Int, d)?.call_unary(maybe_try_cast(u, func::CastInt32ToBool)?)),
+ _ => Ok(gen_expr(u, Ty::Int, d)?.call_unary(func::CastInt32ToBool)),
},
- Ty::Str => {
- match u.int_in_range(0u8..=3)? {
- 0 => {
- let cond = gen_expr(u, Ty::Bool, d)?;
- let then = gen_expr(u, Ty::Str, d)?;
- let els = gen_expr(u, Ty::Str, d)?;
- Ok(cond.if_then_else(then, els))
- }
- 1 => Ok(gen_expr(u, Ty::Str, d)?
- .call_binary(gen_expr(u, Ty::Str, d)?, func::TextConcatBinary)),
- 2 => Ok(gen_expr(u, Ty::Int, d)?
- .call_unary(maybe_try_cast(u, func::CastInt32ToString)?)),
- _ => Ok(gen_expr(u, Ty::Bool, d)?
- .call_unary(maybe_try_cast(u, func::CastBoolToString)?)),
+ Ty::Str => match u.int_in_range(0u8..=3)? {
+ 0 => {
+ let cond = gen_expr(u, Ty::Bool, d)?;
+ let then = gen_expr(u, Ty::Str, d)?;
+ let els = gen_expr(u, Ty::Str, d)?;
+ Ok(cond.if_then_else(then, els))
}
- }
+ 1 => Ok(gen_expr(u, Ty::Str, d)?
+ .call_binary(gen_expr(u, Ty::Str, d)?, func::TextConcatBinary)),
+ 2 => Ok(gen_expr(u, Ty::Int, d)?.call_unary(func::CastInt32ToString)),
+ _ => Ok(gen_expr(u, Ty::Bool, d)?.call_unary(func::CastBoolToString)),
+ },
}
}
diff --git a/src/expr/src/interpret.rs b/src/expr/src/interpret.rs
index 6900762409af3..5bba046327695 100644
--- a/src/expr/src/interpret.rs
+++ b/src/expr/src/interpret.rs
@@ -1688,42 +1688,10 @@ mod tests {
Not(_) => arg.scalar_type == ReprScalarType::Bool,
IsNull(_) => true,
TryParseMonotonicIso8601Timestamp(_) => arg.scalar_type == ReprScalarType::String,
- TryCast(f) => unary_typecheck(&f.inner, arg),
_ => false,
}
}
- /// Fallible casts to wrap in `TryCast`, as the planner does for `TRY_CAST`:
- /// narrowing integer casts, float to integer, numeric to integer, and the
- /// jsonb casts that reject the wrong kind of value.
- const TRY_CAST_INNER_FUNCS: &[UnaryFunc] = &[
- UnaryFunc::CastInt64ToInt32(CastInt64ToInt32),
- UnaryFunc::CastInt32ToInt16(CastInt32ToInt16),
- UnaryFunc::CastInt64ToUint64(CastInt64ToUint64),
- UnaryFunc::CastFloat64ToInt64(CastFloat64ToInt64),
- UnaryFunc::CastFloat64ToFloat32(CastFloat64ToFloat32),
- UnaryFunc::CastNumericToInt32(CastNumericToInt32),
- UnaryFunc::CastNumericToMzTimestamp(CastNumericToMzTimestamp),
- UnaryFunc::CastJsonbToNumeric(CastJsonbToNumeric(None)),
- UnaryFunc::CastJsonbToBool(CastJsonbToBool),
- UnaryFunc::CastTimestampToMzTimestamp(CastTimestampToMzTimestamp),
- ];
-
- /// The declared unary functions, plus `TryCast` around each fallible cast
- /// in `TRY_CAST_INNER_FUNCS`, so the interpreter's properties are checked
- /// over the null-fallback wrapper as well.
- fn interesting_unary_funcs() -> Vec {
- let mut funcs = INTERESTING_UNARY_FUNCS.to_vec();
- funcs.extend(TRY_CAST_INNER_FUNCS.iter().map(|cast| {
- assert!(
- cast.could_error(),
- "{cast} never errors, so wrapping it is pointless"
- );
- UnaryFunc::try_cast(cast.clone())
- }));
- funcs
- }
-
fn interesting_binary_funcs() -> Vec {
vec![
AddTimestampInterval.into(),
@@ -1997,7 +1965,7 @@ mod tests {
column_gen
.prop_union(literal_gen)
.prop_recursive(4, 64, 8, |self_gen| {
- let unary_gen = (select(interesting_unary_funcs()), self_gen.clone())
+ let unary_gen = (select(INTERESTING_UNARY_FUNCS), self_gen.clone())
.prop_filter_map("unary func", |(func, (expr_in, type_in))| {
if !unary_typecheck(&func, &type_in) {
return None;
diff --git a/src/expr/src/lib.rs b/src/expr/src/lib.rs
index ec3b4298d6bd5..75dd1eceb030a 100644
--- a/src/expr/src/lib.rs
+++ b/src/expr/src/lib.rs
@@ -46,9 +46,7 @@ pub use relation::{
RowSetFinishing, RowSetFinishingIncremental, WindowFrame, WindowFrameBound, WindowFrameUnits,
canonicalize, compare_columns, non_nullable_columns,
};
-pub use scalar::func::{
- self, BinaryFunc, CastFailureMode, UnaryFunc, UnmaterializableFunc, VariadicFunc,
-};
+pub use scalar::func::{self, BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc};
pub use scalar::{
Columns, DomainLimit, Eval, EvalError, FilterCharacteristics, MirScalarExpr, OptimizableExpr,
ProtoDomainLimit, ProtoEvalError, StableEvalError, StableEvalErrorRef, like_pattern,
diff --git a/src/expr/src/scalar/func.rs b/src/expr/src/scalar/func.rs
index 9c3ae37aa3212..9c438a4ba0400 100644
--- a/src/expr/src/scalar/func.rs
+++ b/src/expr/src/scalar/func.rs
@@ -197,7 +197,6 @@ func_name! {
TimezoneTimestampTz => "timezone_timestamp_tz",
ToCharTimestamp => "to_char_timestamp",
ToCharTimestampTz => "to_char_timestamp_tz",
- TryCast => "try_cast",
variadic::And => "and",
variadic::Coalesce => "coalesce",
variadic::Greatest => "greatest",
diff --git a/src/expr/src/scalar/func/impls.rs b/src/expr/src/scalar/func/impls.rs
index 3566471da08ba..ae00788120800 100644
--- a/src/expr/src/scalar/func/impls.rs
+++ b/src/expr/src/scalar/func/impls.rs
@@ -36,7 +36,6 @@ mod regproc;
mod string;
mod time;
mod timestamp;
-mod try_cast;
mod uint16;
mod uint32;
mod uint64;
@@ -72,7 +71,6 @@ pub use crate::scalar::func::impls::regproc::*;
pub use crate::scalar::func::impls::string::*;
pub use crate::scalar::func::impls::time::*;
pub use crate::scalar::func::impls::timestamp::*;
-pub use crate::scalar::func::impls::try_cast::*;
pub use crate::scalar::func::impls::uint16::*;
pub use crate::scalar::func::impls::uint32::*;
pub use crate::scalar::func::impls::uint64::*;
diff --git a/src/expr/src/scalar/func/impls/try_cast.rs b/src/expr/src/scalar/func/impls/try_cast.rs
deleted file mode 100644
index f16ea671f517b..0000000000000
--- a/src/expr/src/scalar/func/impls/try_cast.rs
+++ /dev/null
@@ -1,285 +0,0 @@
-// 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.
-
-use std::fmt;
-
-use mz_repr::{Datum, RowArena, SqlColumnType};
-use serde::{Deserialize, Serialize};
-
-use crate::scalar::func::{LazyUnaryFunc, UnaryFunc};
-use crate::{Eval, EvalError, MirScalarExpr};
-
-/// What a cast does when the value cannot be converted to the target type.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub enum CastFailureMode {
- /// The cast raises an error.
- Error,
- /// The cast evaluates to `NULL`. Each cast function is wrapped in
- /// [`TryCast`], so errors raised while evaluating the cast's argument
- /// still propagate.
- NullFallback,
-}
-
-/// Wraps a cast function so that its errors become `NULL`.
-///
-/// The argument is evaluated first, and its errors propagate. Only errors
-/// raised by `inner` itself are swallowed. Because the wrapper is strict in its
-/// argument and never errors, it is safe for the optimizer to treat it like
-/// any other infallible unary function.
-#[derive(
- Ord,
- PartialOrd,
- Clone,
- Debug,
- Eq,
- PartialEq,
- Serialize,
- Deserialize,
- Hash
-)]
-pub struct TryCast {
- pub inner: Box>,
-}
-
-/// Evaluates to the first column of the row it is given.
-///
-/// `TryCast::eval` needs to hand an already evaluated datum to `inner`, but
-/// `LazyUnaryFunc::eval` takes the argument as an `&'a impl Eval` and returns
-/// a `Datum<'a>`, so a value constructed inside `eval` cannot serve as the
-/// argument. Instead the datum becomes a one-column row and this `'static`
-/// reader stands in for the argument, mirroring how the element casts of
-/// `CastList1ToList2` evaluate against a one-column row.
-struct FirstColumn;
-
-static FIRST_COLUMN: FirstColumn = FirstColumn;
-
-impl Eval for FirstColumn {
- fn eval<'a>(
- &'a self,
- datums: &[Datum<'a>],
- _temp_storage: &'a RowArena,
- ) -> Result, EvalError> {
- Ok(datums[0])
- }
-
- fn could_error(&self) -> bool {
- false
- }
-}
-
-impl LazyUnaryFunc for TryCast {
- fn eval<'a>(
- &'a self,
- datums: &[Datum<'a>],
- temp_storage: &'a RowArena,
- a: &'a impl Eval,
- ) -> Result, EvalError> {
- let a = a.eval(datums, temp_storage)?;
- match self.inner.eval(&[a], temp_storage, &FIRST_COLUMN) {
- Ok(datum) => Ok(datum),
- // An internal error means the planner handed `inner` a datum of
- // the wrong kind. No cast reports it for bad user data, so it is
- // a planner bug, and swallowing it would hide that from CI. Soft
- // assertions are off in production, where the row becomes NULL
- // like any other failure and nothing is logged.
- Err(EvalError::Internal(message)) => {
- mz_ore::soft_panic_no_log!(
- "TRY_CAST swallowed an internal error from {}: {message}",
- self.inner
- );
- Ok(Datum::Null)
- }
- Err(_) => Ok(Datum::Null),
- }
- }
-
- fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
- self.inner.output_sql_type(input_type).nullable(true)
- }
-
- fn propagates_nulls(&self) -> bool {
- self.inner.propagates_nulls()
- }
-
- fn introduces_nulls(&self) -> bool {
- self.inner.could_error() || self.inner.introduces_nulls()
- }
-
- fn could_error(&self) -> bool {
- false
- }
-
- fn preserves_uniqueness(&self) -> bool {
- // Every failing input maps to the same NULL.
- //
- // If there was somehow a _unique_ failing input
- // and no other value produce NULL, this could be true.
- // It's not clear that situation ever arises.
- false
- }
-
- fn inverse(&self) -> Option {
- None
- }
-
- fn is_monotone(&self) -> bool {
- // The failing inputs, which may sit anywhere in the domain, map to
- // NULL, so the wrapper is not monotone even when `inner` is.
- //
- // If the domain of failures was somehow monotonic with respect to NULL,
- // this could be true.
- false
- }
-
- fn is_eliminable_cast(&self) -> bool {
- false
- }
-}
-
-impl UnaryFunc {
- /// Wraps `inner` in [`TryCast`] if it could error, so that its errors
- /// become NULL. A function that cannot error has nothing to fall back
- /// from and is returned as is, keeping its nullability.
- pub fn try_cast(inner: UnaryFunc) -> UnaryFunc {
- if inner.could_error() {
- UnaryFunc::TryCast(TryCast {
- inner: Box::new(inner),
- })
- } else {
- inner
- }
- }
-}
-
-impl TryCast {
- /// Rebuilds this function with any expressions stored in `inner` converted
- /// to `E2`.
- pub fn try_map_expr<'a, E2: TryFrom<&'a E>>(&'a self) -> Result, E2::Error> {
- Ok(TryCast {
- inner: Box::new(self.inner.try_map_expr()?),
- })
- }
-
- /// Rebuilds this function with any expressions stored in `inner` converted
- /// to `E2`.
- pub fn map_expr<'a, E2: From<&'a E>>(&'a self) -> TryCast {
- TryCast {
- inner: Box::new(self.inner.map_expr()),
- }
- }
-}
-
-impl fmt::Display for TryCast {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // The brackets attach the guard to the function rather than to its
- // argument: `try_cast[f](x)` catches errors from `f`, not from `x`.
- write!(f, "try_cast[{}]", self.inner)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use mz_repr::{Datum, ReprScalarType, RowArena};
-
- use crate::scalar::func::{CastInt64ToInt32, CastStringToInt32, CastStringToInt64, TryCast};
- use crate::{Eval, EvalError, MirScalarExpr, UnaryFunc};
-
- fn try_cast(inner: impl Into) -> UnaryFunc {
- TryCast {
- inner: Box::new(inner.into()),
- }
- .into()
- }
-
- fn eval(expr: &MirScalarExpr) -> Result, EvalError> {
- // The expressions under test are closed, so an empty row suffices.
- let arena = Box::leak(Box::new(RowArena::new()));
- expr.eval(&[], arena)
- }
-
- fn text(s: &str) -> MirScalarExpr {
- MirScalarExpr::literal_ok(Datum::String(s), ReprScalarType::String)
- }
-
- #[mz_ore::test]
- fn cast_error_becomes_null() {
- let expr = text("abc").call_unary(try_cast(CastStringToInt32));
- assert_eq!(eval(&expr), Ok(Datum::Null));
- }
-
- #[mz_ore::test]
- fn success_agrees_with_strict_cast() {
- let lenient = text("42").call_unary(try_cast(CastStringToInt32));
- let strict = text("42").call_unary(CastStringToInt32);
- assert_eq!(eval(&lenient), Ok(Datum::Int32(42)));
- assert_eq!(eval(&lenient), eval(&strict));
- }
-
- #[mz_ore::test]
- fn null_argument_stays_null() {
- let expr = MirScalarExpr::literal_null(ReprScalarType::String)
- .call_unary(try_cast(CastStringToInt32));
- assert_eq!(eval(&expr), Ok(Datum::Null));
- }
-
- #[mz_ore::test]
- fn argument_error_propagates() {
- let expr = MirScalarExpr::literal(Err(EvalError::DivisionByZero), ReprScalarType::String)
- .call_unary(try_cast(CastStringToInt32));
- assert_eq!(eval(&expr), Err(EvalError::DivisionByZero));
- }
-
- /// A two-stage chain, text to int8 to int4, wrapped per stage as the
- /// planner does. A failure at either stage yields NULL because the later
- /// stage propagates the NULL the earlier one produced.
- #[mz_ore::test]
- fn chain_nulls_at_either_stage() {
- let chain = |s: &str| {
- text(s)
- .call_unary(try_cast(CastStringToInt64))
- .call_unary(try_cast(CastInt64ToInt32))
- };
- assert_eq!(eval(&chain("abc")), Ok(Datum::Null), "fails at stage one");
- assert_eq!(
- eval(&chain("3000000000")),
- Ok(Datum::Null),
- "fails at stage two"
- );
- assert_eq!(eval(&chain("5")), Ok(Datum::Int32(5)));
- }
-
- /// A datum of the wrong kind reaches the inner cast only through a
- /// planner bug, which the wrapper reports under soft assertions and hides
- /// as NULL otherwise.
- #[mz_ore::test]
- fn internal_error_is_a_soft_panic() {
- let expr = MirScalarExpr::literal_ok(Datum::Int64(7), ReprScalarType::Int64)
- .call_unary(try_cast(CastStringToInt32));
- let outcome = mz_ore::panic::catch_unwind(|| eval(&expr));
- if mz_ore::assert::soft_assertions_enabled() {
- assert!(outcome.is_err(), "soft assertion should have fired");
- } else {
- assert_eq!(outcome.expect("no panic"), Ok(Datum::Null));
- }
- }
-
- #[mz_ore::test]
- fn metadata() {
- let func = try_cast(CastStringToInt32);
- assert!(!func.could_error());
- assert!(func.introduces_nulls());
- assert!(func.propagates_nulls());
- assert!(!func.is_monotone());
- assert!(!func.preserves_uniqueness());
- assert_eq!(func.inverse(), None);
- let input = mz_repr::SqlScalarType::String.nullable(false);
- assert!(func.output_sql_type(input).nullable);
- assert_eq!(func.to_string(), "try_cast[text_to_integer]");
- }
-}
diff --git a/src/expr/src/scalar/func/registry.rs b/src/expr/src/scalar/func/registry.rs
index 9b1a02ea21aba..09a46269a711a 100644
--- a/src/expr/src/scalar/func/registry.rs
+++ b/src/expr/src/scalar/func/registry.rs
@@ -579,53 +579,6 @@ fn unary_samples() -> Vec> {
record_type(),
),
unary(RecordGet(1), record_type()),
- // The null-fallback wrapper around a cast. Its properties derive from
- // the wrapped function, so the samples cover the branches that differ:
- // a fallible parse, a narrowing cast with an inverse (which the wrapper
- // must not inherit), a nullable output the wrapper only forces nullable,
- // a container cast whose element cast lives inside the wrapper, and a
- // wrapper around a function that cannot error, which the planner never
- // emits but the type allows.
- unary(
- TryCast {
- inner: Box::new(CastStringToInt32.into()),
- },
- SqlScalarType::String,
- ),
- unary(
- TryCast {
- inner: Box::new(CastInt64ToInt32.into()),
- },
- SqlScalarType::Int64,
- )
- .labeled("narrowing"),
- unary(
- TryCast {
- inner: Box::new(CastJsonbToNumeric(None).into()),
- },
- SqlScalarType::Jsonb,
- )
- .labeled("jsonb"),
- unary(
- TryCast {
- inner: Box::new(
- CastList1ToList2 {
- return_ty: list_type(SqlScalarType::Int32),
- cast_expr: column(0),
- }
- .into(),
- ),
- },
- list_type(SqlScalarType::Int64),
- )
- .labeled("list"),
- unary(
- TryCast {
- inner: Box::new(CastInt32ToInt64.into()),
- },
- SqlScalarType::Int32,
- )
- .labeled("infallible"),
unary(
CastStringToArray {
return_ty: array_type(SqlScalarType::Int32),
diff --git a/src/expr/src/scalar/func/unary.rs b/src/expr/src/scalar/func/unary.rs
index 60c7eb268da11..c53f9d8ec60ef 100644
--- a/src/expr/src/scalar/func/unary.rs
+++ b/src/expr/src/scalar/func/unary.rs
@@ -422,7 +422,6 @@ derive_unary!(
CastMapToString,
CastInt2VectorToString,
CastRangeToString,
- TryCast(E),
CeilFloat32,
CeilFloat64,
CeilNumeric,
@@ -573,14 +572,11 @@ mod test {
#[mz_ore::test]
fn test_could_error() {
- let funcs: [UnaryFunc; 5] = [
+ let funcs: [UnaryFunc; 4] = [
UnaryFunc::IsNull(IsNull),
UnaryFunc::CastVarCharToString(CastVarCharToString),
UnaryFunc::Not(Not),
UnaryFunc::IsLikeMatch(IsLikeMatch(like_pattern::compile("%hi%", false).unwrap())),
- UnaryFunc::TryCast(TryCast {
- inner: Box::new(UnaryFunc::CastStringToInt32(CastStringToInt32)),
- }),
];
for func in funcs {
assert!(!func.could_error())
diff --git a/src/expr/tests/spec/interpret.spec b/src/expr/tests/spec/interpret.spec
index defdbd0f14ae9..8f0d632d5c4af 100644
--- a/src/expr/tests/spec/interpret.spec
+++ b/src/expr/tests/spec/interpret.spec
@@ -159,22 +159,3 @@ expr (#0 = #1)
test (true, false, null::boolean, 13)
----
may contain: [false null]
-
-# TryCast never errors and may yield NULL for any input, so the output spec
-# admits NULL even though the input values all convert.
-interpret
-types (text?)
-values ("12", "13")
-expr try_cast[cast_string_to_int32](#0)
-test (12, 13, 14, null::integer)
-----
-may contain: [12 13 14 null]
-
-# The argument's error still propagates through the wrapper.
-interpret
-types (bigint?)
-values (1::bigint, 2::bigint)
-expr try_cast[cast_int64_to_int32](div_int64(#0, 0))
-test (1, null::integer)
-----
-may contain: [1 null ]
diff --git a/src/expr/tests/spec/reduce.spec b/src/expr/tests/spec/reduce.spec
index 08c857d4c0d4d..08d20b0250741 100644
--- a/src/expr/tests/spec/reduce.spec
+++ b/src/expr/tests/spec/reduce.spec
@@ -703,44 +703,3 @@ types (integer?, integer?, integer?)
(#0 = #1)
((#0 + 1) < 2147483647)
((#0 + 1) < #2)
-
-## TryCast wraps a cast function so that its errors become NULL. Errors
-## from the argument still propagate.
-
-reduce
-types (text?)
-try_cast[cast_string_to_int32]("42")
-----
-42
-
-reduce
-types (text?)
-try_cast[cast_string_to_int32]("abc")
-----
-null
-
-reduce
-types (text?)
-try_cast[cast_string_to_int32](null::text)
-----
-null
-
-reduce
-types (bigint?)
-try_cast[cast_int64_to_int32](div_int64(1, 0))
-----
-error("division by zero")
-
-# The wrapper introduces NULLs, so IS NULL must not be pushed through it the
-# way it is for a plain cast.
-reduce
-types (text?)
-((try_cast[cast_string_to_int32](#0)) IS NULL)
-----
-(try_cast[text_to_integer](#0)) IS NULL
-
-reduce
-types (text?)
-((cast_string_to_int32(#0)) IS NULL)
-----
-(#0) IS NULL
diff --git a/src/repr/src/scalar.rs b/src/repr/src/scalar.rs
index 284d60e525426..8d095a632cd06 100644
--- a/src/repr/src/scalar.rs
+++ b/src/repr/src/scalar.rs
@@ -3592,28 +3592,6 @@ impl SqlScalarType {
}
}
- /// Reports whether `predicate` holds for this type or for any type nested
- /// within it: the element type of a list, array, map, or range, or a field
- /// type of a record, at any depth.
- pub fn contains(&self, predicate: &impl Fn(&SqlScalarType) -> bool) -> bool {
- if predicate(self) {
- return true;
- }
- match self {
- SqlScalarType::List { element_type, .. }
- | SqlScalarType::Array(element_type)
- | SqlScalarType::Map {
- value_type: element_type,
- ..
- }
- | SqlScalarType::Range { element_type } => element_type.contains(predicate),
- SqlScalarType::Record { fields, .. } => fields
- .iter()
- .any(|(_, field)| field.scalar_type.contains(predicate)),
- _ => false,
- }
- }
-
/// Returns the [`SqlScalarType`] of elements in a [`SqlScalarType::Array`],
/// [`SqlScalarType::Int2Vector`], or [`SqlScalarType::List`].
///
@@ -6226,31 +6204,4 @@ mod tests {
}
}
}
-
- #[mz_ore::test]
- fn scalar_type_contains_walks_nested_types() {
- let is_legacy_char = |ty: &SqlScalarType| *ty == SqlScalarType::PgLegacyChar;
- let nested = SqlScalarType::Record {
- fields: [
- ("a".into(), SqlScalarType::Int32.nullable(true)),
- (
- "b".into(),
- SqlScalarType::List {
- element_type: Box::new(SqlScalarType::Map {
- value_type: Box::new(SqlScalarType::PgLegacyChar),
- custom_id: None,
- }),
- custom_id: None,
- }
- .nullable(true),
- ),
- ]
- .into(),
- custom_id: None,
- };
- assert!(nested.contains(&is_legacy_char));
- assert!(SqlScalarType::PgLegacyChar.contains(&is_legacy_char));
- assert!(!SqlScalarType::Array(Box::new(SqlScalarType::String)).contains(&is_legacy_char));
- assert!(!SqlScalarType::Int32.contains(&is_legacy_char));
- }
}
diff --git a/src/sql-lexer/build.rs b/src/sql-lexer/build.rs
index 5c7d90b7eeb7f..223fe3ff64e48 100644
--- a/src/sql-lexer/build.rs
+++ b/src/sql-lexer/build.rs
@@ -44,9 +44,6 @@ fn main() -> Result<()> {
let mut buf = CodegenBuf::new();
- // Multi-word keywords like `TRY_CAST` keep their underscore in the
- // variant name so that `as_str` can uppercase it verbatim.
- buf.writeln("#[allow(non_camel_case_types)]");
buf.writeln("#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]");
buf.write_block("pub enum Keyword", |buf| {
for kw in &keywords {
diff --git a/src/sql-lexer/src/keywords.txt b/src/sql-lexer/src/keywords.txt
index 1e3d34cc8b060..18763dd47871e 100644
--- a/src/sql-lexer/src/keywords.txt
+++ b/src/sql-lexer/src/keywords.txt
@@ -509,7 +509,6 @@ Transactional
Transform
Trim
True
-Try_Cast
Tunnel
Type
Types
diff --git a/src/sql-parser/src/ast/defs/expr.rs b/src/sql-parser/src/ast/defs/expr.rs
index 4a8c682a96b48..ecdb3b7c46fa7 100644
--- a/src/sql-parser/src/ast/defs/expr.rs
+++ b/src/sql-parser/src/ast/defs/expr.rs
@@ -106,12 +106,10 @@ pub enum Expr {
expr1: Box>,
expr2: Option>>,
},
- /// CAST an expression to a different data type, e.g. `CAST(foo AS VARCHAR(123))`
- /// or `TRY_CAST(foo AS int4)`.
+ /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
Cast {
expr: Box>,
data_type: T::DataType,
- failure_mode: CastFailureMode,
},
/// `expr COLLATE collation`
Collate {
@@ -367,11 +365,7 @@ impl AstDisplay for Expr {
}
}
}
- Expr::Cast {
- expr,
- data_type,
- failure_mode: CastFailureMode::Error,
- } => {
+ Expr::Cast { expr, data_type } => {
// `::` binds very tightly, so a non-self-delimiting operand must
// be parenthesized or the cast re-associates into its spine.
// `CAST(-0 AS int4)` (i.e. `Cast(- 0)`) would otherwise print as
@@ -389,17 +383,6 @@ impl AstDisplay for Expr {
f.write_str("::");
f.write_node(data_type);
}
- Expr::Cast {
- expr,
- data_type,
- failure_mode: CastFailureMode::NullFallback,
- } => {
- f.write_str("TRY_CAST(");
- f.write_node(&expr);
- f.write_str(" AS ");
- f.write_node(data_type);
- f.write_str(")");
- }
Expr::Collate { expr, collation } => {
// `COLLATE` binds very tightly (`PostfixCollateAt`), so a
// low-precedence operand must be parenthesized or the collation
@@ -869,11 +852,7 @@ fn prints_self_delimiting(expr: &Expr) -> bool {
| Expr::Map(_)
| Expr::MapSubquery(_)
| Expr::Case { .. }
- | Expr::Row { .. }
- | Expr::Cast {
- failure_mode: CastFailureMode::NullFallback,
- ..
- } => true,
+ | Expr::Row { .. } => true,
// The postfix `::` / `COLLATE` / `[…]` forms print as ``,
// so they are safe only when their inner operand is.
Expr::Cast { expr, .. } | Expr::Collate { expr, .. } | Expr::Subscript { expr, .. } => {
@@ -913,12 +892,7 @@ fn bare_prefix_operand_needs_parens(operand: &Expr) -> bool {
let mut saw_postfix = false;
loop {
match e {
- Expr::Cast {
- expr,
- failure_mode: CastFailureMode::Error,
- ..
- }
- | Expr::Subscript { expr, .. } => {
+ Expr::Cast { expr, .. } | Expr::Subscript { expr, .. } => {
saw_postfix = true;
e = expr.as_ref();
}
@@ -974,12 +948,8 @@ fn write_subscript_receiver(f: &mut AstFormatter,
| Expr::MapSubquery(_)
| Expr::FieldAccess { .. }
| Expr::WildcardAccess(_)
- | Expr::Collate { .. }
- | Expr::Cast {
- failure_mode: CastFailureMode::NullFallback,
- ..
- } => false,
- // `::` `Cast`: the type parser swallows a following `[…]` as an array suffix
+ | Expr::Collate { .. } => false,
+ // `Cast`: the type parser swallows a following `[…]` as an array suffix
// (`a::int4[1]` is `a` cast to `int4[]`, not a subscript of `a::int4`).
// `Subscript`: consecutive `[…]` flatten into one node (`a[1][2]` is a
// single subscript), so a nested subscript receiver must be parenthesized
@@ -1080,7 +1050,6 @@ impl Expr {
Expr::Cast {
expr: Box::new(self),
data_type,
- failure_mode: CastFailureMode::Error,
}
}
@@ -1146,16 +1115,6 @@ impl Op {
}
}
-/// What a cast does when the value cannot be converted to the target type.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub enum CastFailureMode {
- /// The cast raises an error, as `CAST(expr AS type)` and `expr::type` do.
- Error,
- /// The cast evaluates to `NULL`, as `TRY_CAST(expr AS type)` does. Errors
- /// raised while evaluating `expr` itself still propagate.
- NullFallback,
-}
-
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum HomogenizingFunction {
Coalesce,
diff --git a/src/sql-parser/src/lib.rs b/src/sql-parser/src/lib.rs
index 7e50da55f7b4b..9181737211a5a 100644
--- a/src/sql-parser/src/lib.rs
+++ b/src/sql-parser/src/lib.rs
@@ -43,7 +43,7 @@ mod ident;
#[cfg(feature = "test")]
pub fn datadriven_testcase(tc: &datadriven::TestCase) -> String {
use crate::ast::display::AstDisplay;
- use crate::ast::{CastFailureMode, Expr, Statement};
+ use crate::ast::{Expr, Statement};
use datadriven::TestCase;
use mz_ore::collections::CollectionExt;
use mz_ore::fmt::FormatBuffer;
@@ -125,20 +125,13 @@ pub fn datadriven_testcase(tc: &datadriven::TestCase) -> String {
match parser::parse_expr(&printed) {
Ok(parsed) => {
// TODO: We always coerce the double colon operator into a Cast expr instead
- // of keeping it as an Op (see parse_pg_cast). An erroring Expr::Cast
- // always prints itself as double colon. We're thus unable to perfectly
- // roundtrip `CAST(..)`. We could fix this by keeping "::" as a binary
- // operator and teaching func.rs how to handle it, similar to how that
- // file handles "~~" (without the parser converting that operator
- // directly into an Expr::Like). `TRY_CAST(..)` has no operator form
- // and so does roundtrip.
- if !matches!(
- parsed,
- Expr::Cast {
- failure_mode: CastFailureMode::Error,
- ..
- }
- ) {
+ // of keeping it as an Op (see parse_pg_cast). Expr::Cast always prints
+ // itself as double colon. We're thus unable to perfectly roundtrip
+ // `CAST(..)`. We could fix this by keeping "::" as a binary operator and
+ // teaching func.rs how to handle it, similar to how that file handles "~~"
+ // (without the parser converting that operator directly into an
+ // Expr::Like).
+ if !matches!(parsed, Expr::Cast { .. }) {
if parsed != s {
panic!(
"reparse comparison failed: {input} != {s}\n{:?}\n!=\n{:?}\n{printed}\n",
diff --git a/src/sql-parser/src/parser.rs b/src/sql-parser/src/parser.rs
index 5df0bf2c091dd..e0f679ba16260 100644
--- a/src/sql-parser/src/parser.rs
+++ b/src/sql-parser/src/parser.rs
@@ -656,7 +656,6 @@ impl<'a> Parser<'a> {
Ok(Expr::Cast {
expr: Box::new(Expr::Value(Value::String(parser.parse_literal_string()?))),
data_type,
- failure_mode: CastFailureMode::Error,
})
}
}));
@@ -680,10 +679,7 @@ impl<'a> Parser<'a> {
}
(Token::Keyword(MAP), Some(Token::LBracket) | Some(Token::LParen)) => self.parse_map(),
(Token::Keyword(CASE), _) => self.parse_case_expr(),
- (Token::Keyword(CAST), _) => self.parse_cast_expr(CastFailureMode::Error),
- (Token::Keyword(TRY_CAST), Some(Token::LParen)) => {
- self.parse_cast_expr(CastFailureMode::NullFallback)
- }
+ (Token::Keyword(CAST), _) => self.parse_cast_expr(),
(Token::Keyword(COALESCE), Some(Token::LParen)) => {
self.parse_homogenizing_function(HomogenizingFunction::Coalesce)
}
@@ -1008,9 +1004,8 @@ impl<'a> Parser<'a> {
})
}
- /// Parses the argument list of `CAST(...)` or `TRY_CAST(...)`, the keyword
- /// having already been consumed.
- fn parse_cast_expr(&mut self, failure_mode: CastFailureMode) -> Result, ParserError> {
+ /// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)`
+ fn parse_cast_expr(&mut self) -> Result, ParserError> {
// Whether `expr` is safe to print directly to the left of a Postgres-style
// `::` cast without wrapping it in parentheses. `Expr::Cast` /
// `Expr::Collate` print as the postfix forms `::` /
@@ -1028,11 +1023,7 @@ impl<'a> Parser<'a> {
| Expr::HomogenizingFunction { .. }
| Expr::NullIf { .. }
| Expr::Subquery { .. }
- | Expr::Parameter(..)
- | Expr::Cast {
- failure_mode: CastFailureMode::NullFallback,
- ..
- } => true,
+ | Expr::Parameter(..) => true,
Expr::Cast { expr, .. } | Expr::Collate { expr, .. } => safe_before_pg_cast(expr),
_ => false,
}
@@ -1047,23 +1038,24 @@ impl<'a> Parser<'a> {
// CAST( OP AS )
// to
// OP ::
- // (because we print an erroring Expr::Cast always as a Postgres-style
- // cast, i.e. `::`) which could incorrectly change the meaning of the
- // expression as the `::` binds tightly. To be safe, we wrap the inner
+ // (because we print Expr::Cast always as a Postgres-style cast, i.e. `::`)
+ // which could incorrectly change the meaning of the expression
+ // as the `::` binds tightly. To be safe, we wrap the inner
// expression in parentheses
// ( OP )::
// unless the inner expression is of a kind that we know is
- // safe to follow with a `::` without wrapping. `TRY_CAST(...)` prints
- // in its function-like form, which delimits its operand itself.
- let expr = match failure_mode {
- CastFailureMode::Error if !safe_before_pg_cast(&expr) => Expr::Nested(Box::new(expr)),
- CastFailureMode::Error | CastFailureMode::NullFallback => expr,
- };
- Ok(Expr::Cast {
- expr: Box::new(expr),
- data_type,
- failure_mode,
- })
+ // safe to follow with a `::` without wrapping.
+ if safe_before_pg_cast(&expr) {
+ Ok(Expr::Cast {
+ expr: Box::new(expr),
+ data_type,
+ })
+ } else {
+ Ok(Expr::Cast {
+ expr: Box::new(Expr::Nested(Box::new(expr))),
+ data_type,
+ })
+ }
}
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
@@ -1512,15 +1504,9 @@ impl<'a> Parser<'a> {
// If the expression that is being cast can end with a type name, then let's parenthesize
// it. Otherwise, the `[...]` would melt into the type name (making it an array type).
- // Specifically, the only expressions whose printing can end with a type name are `::`
- // casts, so check for that.
- if matches!(
- expr,
- Expr::Cast {
- failure_mode: CastFailureMode::Error,
- ..
- }
- ) {
+ // Specifically, the only expressions whose printing can end with a type name are casts, so
+ // check for that.
+ if matches!(expr, Expr::Cast { .. }) {
Ok(Expr::Subscript {
expr: Box::new(Expr::Nested(Box::new(expr))),
positions,
@@ -1724,7 +1710,6 @@ impl<'a> Parser<'a> {
Ok(Expr::Cast {
expr: Box::new(expr),
data_type: self.parse_data_type()?,
- failure_mode: CastFailureMode::Error,
})
}
diff --git a/src/sql-parser/tests/testdata/literal b/src/sql-parser/tests/testdata/literal
index edbef52cf6773..6859333e7f41e 100644
--- a/src/sql-parser/tests/testdata/literal
+++ b/src/sql-parser/tests/testdata/literal
@@ -113,122 +113,122 @@ Value(HexString("deadBEEF"))
parse-scalar
DATE '1999-01-01'
----
-Cast { expr: Value(String("1999-01-01")), data_type: Other { name: Name(UnresolvedItemName([Ident("date")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01")), data_type: Other { name: Name(UnresolvedItemName([Ident("date")])), typ_mod: [] } }
parse-scalar
DATE 'invalid date'
----
-Cast { expr: Value(String("invalid date")), data_type: Other { name: Name(UnresolvedItemName([Ident("date")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("invalid date")), data_type: Other { name: Name(UnresolvedItemName([Ident("date")])), typ_mod: [] } }
parse-scalar
TIME '01:23:34'
----
-Cast { expr: Value(String("01:23:34")), data_type: Other { name: Name(UnresolvedItemName([Ident("time")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("01:23:34")), data_type: Other { name: Name(UnresolvedItemName([Ident("time")])), typ_mod: [] } }
parse-scalar
TIME 'invalid time'
----
-Cast { expr: Value(String("invalid time")), data_type: Other { name: Name(UnresolvedItemName([Ident("time")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("invalid time")), data_type: Other { name: Name(UnresolvedItemName([Ident("time")])), typ_mod: [] } }
parse-scalar
TIMESTAMP '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] } }
parse-scalar
TIMESTAMPTZ '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] } }
parse-scalar
TIMESTAMP WITH TIME ZONE '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] } }
parse-scalar
TIMESTAMP WITHOUT TIME ZONE '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] } }
parse-scalar
TIMESTAMP 'invalid timestamptx'
----
-Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] } }
parse-scalar
TIMESTAMPTZ 'invalid timestamptx'
----
-Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] } }
parse-scalar
TIMESTAMP WITH TIME ZONE 'invalid timestamptx'
----
-Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [] } }
parse-scalar
TIMESTAMP WITHOUT TIME ZONE 'invalid timestamptx'
----
-Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] }, failure_mode: Error }
+Cast { expr: Value(String("invalid timestamptx")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [] } }
parse-scalar
TIMESTAMP(-1) '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [-1] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [-1] } }
parse-scalar
TIMESTAMPTZ(-1) '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [-1] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [-1] } }
parse-scalar
TIMESTAMP(-1) WITH TIME ZONE '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [-1] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [-1] } }
parse-scalar
TIMESTAMP(-1) WITHOUT TIME ZONE '1999-01-01 01:23:34.555'
----
-Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [-1] }, failure_mode: Error }
+Cast { expr: Value(String("1999-01-01 01:23:34.555")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [-1] } }
parse-scalar
TIMESTAMP(3) '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [3] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [3] } }
parse-scalar
TIMESTAMPTZ(3) '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [3] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [3] } }
parse-scalar
TIMESTAMP(3) WITH TIME ZONE '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [3] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [3] } }
parse-scalar
TIMESTAMP(3) WITHOUT TIME ZONE '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [3] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [3] } }
parse-scalar
TIMESTAMP(7) '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [7] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [7] } }
parse-scalar
TIMESTAMPTZ(7) '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [7] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [7] } }
parse-scalar
TIMESTAMP(7) WITH TIME ZONE '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [7] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamptz")])), typ_mod: [7] } }
parse-scalar
TIMESTAMP(7) WITHOUT TIME ZONE '1970-01-01T00:00:00.666666666'
----
-Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [7] }, failure_mode: Error }
+Cast { expr: Value(String("1970-01-01T00:00:00.666666666")), data_type: Other { name: Name(UnresolvedItemName([Ident("timestamp")])), typ_mod: [7] } }
parse-scalar
TIMESTAMP(9223372036854775808) '1970-01-01T00:00:00.666666666'
diff --git a/src/sql-parser/tests/testdata/scalar b/src/sql-parser/tests/testdata/scalar
index 752a2c22788e4..73cb36de081f6 100644
--- a/src/sql-parser/tests/testdata/scalar
+++ b/src/sql-parser/tests/testdata/scalar
@@ -185,7 +185,7 @@ Op { op: Op { namespace: None, op: "!~*" }, expr1: Identifier([Ident("a")]), exp
parse-scalar
a !x 'foo'
----
-Op { op: Op { namespace: None, op: "!" }, expr1: Identifier([Ident("a")]), expr2: Some(Cast { expr: Value(String("foo")), data_type: Other { name: Name(UnresolvedItemName([Ident("x")])), typ_mod: [] }, failure_mode: Error }) }
+Op { op: Op { namespace: None, op: "!" }, expr1: Identifier([Ident("a")]), expr2: Some(Cast { expr: Value(String("foo")), data_type: Other { name: Name(UnresolvedItemName([Ident("x")])), typ_mod: [] } }) }
parse-scalar
a !x
@@ -209,66 +209,6 @@ CAST(id AS BIGINT)
----
id::int8
-# TRY_CAST has no operator spelling, so it prints in its function-like form and
-# never needs the parenthesization that `::` casts need around their operand.
-parse-scalar roundtrip
-TRY_CAST(id AS BIGINT)
-----
-TRY_CAST(id AS int8)
-
-parse-scalar roundtrip
-try_cast(a + b AS int4)
-----
-TRY_CAST(a + b AS int4)
-
-parse-scalar roundtrip
--TRY_CAST(2 AS int4)
-----
-- TRY_CAST(2 AS int4)
-
-parse-scalar roundtrip
-TRY_CAST(x AS int4)::text
-----
-TRY_CAST(x AS int4)::text
-
-parse-scalar roundtrip
-TRY_CAST(x::int2 AS int4)
-----
-TRY_CAST(x::int2 AS int4)
-
-parse-scalar roundtrip
-TRY_CAST(CAST(x AS smallint) AS int)
-----
-TRY_CAST(x::int2 AS int4)
-
-parse-scalar roundtrip
-TRY_CAST(x AS int4 list)[1]
-----
-TRY_CAST(x AS int4 list)[1]
-
-parse-scalar roundtrip
-CAST(TRY_CAST(x AS int4 list) AS text)
-----
-TRY_CAST(x AS int4 list)::text
-
-parse-scalar
-TRY_CAST(id AS int4)
-----
-Cast { expr: Identifier([Ident("id")]), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: NullFallback }
-
-parse-scalar
-TRY_CAST(id, int4)
-----
-error: Expected AS, found comma
-TRY_CAST(id, int4)
- ^
-
-# TRY_CAST is not reserved, so it remains usable as a bare identifier.
-parse-scalar roundtrip
-try_cast + 1
-----
-try_cast + 1
-
parse-scalar roundtrip
id::double precision
----
@@ -901,17 +841,17 @@ address[1:list_length(address) - 1]
parse-scalar
ARRAY[]::int[]
----
-Cast { expr: Array([]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }), failure_mode: Error }
+Cast { expr: Array([]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }) }
parse-scalar
ARRAY[]::int[][][][]
----
-Cast { expr: Array([]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }), failure_mode: Error }
+Cast { expr: Array([]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }) }
parse-scalar
ARRAY[]::int[2][2]
----
-Cast { expr: Array([]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }), failure_mode: Error }
+Cast { expr: Array([]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }) }
parse-scalar roundtrip
ARRAY[1, 2, 3][-1]
diff --git a/src/sql-parser/tests/testdata/select b/src/sql-parser/tests/testdata/select
index 14ef9fe5450c6..57a834a31760d 100644
--- a/src/sql-parser/tests/testdata/select
+++ b/src/sql-parser/tests/testdata/select
@@ -1617,7 +1617,7 @@ SELECT foo::uuid list[2] FROM fake_table;
----
SELECT foo::uuid list[] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Identifier([Ident("foo")]), data_type: Array(List(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] })), failure_mode: Error }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Identifier([Ident("foo")]), data_type: Array(List(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] })) }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# Subscripting after a cast. The danger here is that if the cast is to list or array, then the subscript could melt into
# the type as if it were creating an array type if the parser and/or AST printer is not careful.
@@ -1627,26 +1627,14 @@ SELECT CAST(my_json AS uuid list)[my_index] FROM fake_table;
----
SELECT (my_json::uuid list)[my_index] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: List(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }), failure_mode: Error }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
-
-parse-statement
-SELECT TRY_CAST(my_json AS uuid[])[my_index] FROM fake_table;
-----
-SELECT TRY_CAST(my_json AS uuid[])[my_index] FROM fake_table
-=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Cast { expr: Identifier([Ident("my_json")]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }), failure_mode: NullFallback }, positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
-
-parse-statement roundtrip
-SELECT try_cast, try_cast.x FROM try_cast
-----
-SELECT try_cast, try_cast.x FROM try_cast
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: List(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }) }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
SELECT CAST(my_json AS uuid[])[my_index] FROM fake_table;
----
SELECT (my_json::uuid[])[my_index] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }), failure_mode: Error }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }) }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# This would not plan, because we are subscripting into a uuid, but it's still nice if it roundtrips through the parser.
parse-statement
@@ -1654,7 +1642,7 @@ SELECT CAST(my_json AS uuid)[my_index] FROM fake_table;
----
SELECT (my_json::uuid)[my_index] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }, failure_mode: Error }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] } }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# Same as above, but with Postgres-style casts.
@@ -1663,14 +1651,14 @@ SELECT (my_json::uuid list)[my_index] FROM fake_table;
----
SELECT (my_json::uuid list)[my_index] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: List(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }), failure_mode: Error }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: List(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }) }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
SELECT (my_json::uuid[])[my_index] FROM fake_table;
----
SELECT (my_json::uuid[])[my_index] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }), failure_mode: Error }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Array(Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }) }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# This would not plan, because we are subscripting into a uuid, but it's still nice if it roundtrips through the parser.
parse-statement
@@ -1678,7 +1666,7 @@ SELECT (my_json::uuid)[my_index] FROM fake_table;
----
SELECT (my_json::uuid)[my_index] FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] }, failure_mode: Error }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Subscript { expr: Nested(Cast { expr: Identifier([Ident("my_json")]), data_type: Other { name: Name(UnresolvedItemName([Ident("uuid")])), typ_mod: [] } }), positions: [SubscriptPosition { start: Some(Identifier([Ident("my_index")])), end: None, explicit_slice: false }] }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# Casts are always printed as Postgres-style casts, that is, with `::`. When going from `CAST` to `::`, we have to avoid
# the daner of `::` binding to just part of the expression that was originally being cast. E.g. rewriting
@@ -1691,7 +1679,7 @@ SELECT CAST(a + b AS integer) FROM fake_table;
----
SELECT (a + b)::int4 FROM fake_table
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Op { op: Op { namespace: None, op: "+" }, expr1: Identifier([Ident("a")]), expr2: Some(Identifier([Ident("b")])) }), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Op { op: Op { namespace: None, op: "+" }, expr1: Identifier([Ident("a")]), expr2: Some(Identifier([Ident("b")])) }), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }, alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("fake_table")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# We should avoid inserting superfluous parenthesis, or it won't roundtrip after printing the cast in the Postgres
# style, because some parser code paths eat superfluous parenthesis, including the code path that handles
@@ -1701,7 +1689,7 @@ SELECT round(1.5678, CAST((SELECT n FROM nums) AS integer));
----
SELECT round(1.5678, (SELECT n FROM nums)::int4)
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Function(Function { name: Name(UnresolvedItemName([Ident("round")])), args: Args { args: [Value(Number("1.5678")), Cast { expr: Subquery(Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Identifier([Ident("n")]), alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("nums")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }], order_by: [] }, filter: None, over: None, distinct: false }), alias: None }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Function(Function { name: Name(UnresolvedItemName([Ident("round")])), args: Args { args: [Value(Number("1.5678")), Cast { expr: Subquery(Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Identifier([Ident("n")]), alias: None }], from: [TableWithJoins { relation: Table { name: Name(UnresolvedItemName([Ident("nums")])), alias: None }, joins: [] }], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }], order_by: [] }, filter: None, over: None, distinct: false }), alias: None }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# Prepared statement parameter handling in casts. (Note: some extra wrapping parens here are currently not removed.)
parse-statement
@@ -1709,49 +1697,49 @@ select $2::int as col
----
SELECT $2::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Parameter(2), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Parameter(2), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
select CAST($2 AS int) as col
----
SELECT $2::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Parameter(2), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Parameter(2), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
select $1 + ($2)::int as col
----
SELECT $1 + ($2)::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Cast { expr: Nested(Parameter(2)), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }) }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Cast { expr: Nested(Parameter(2)), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }) }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
select $1 + $2::int as col
----
SELECT $1 + $2::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Cast { expr: Parameter(2), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }) }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Cast { expr: Parameter(2), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }) }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
select ($1 + $2)::int as col
----
SELECT ($1 + $2)::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Parameter(2)) }), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Parameter(2)) }), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
select ((($1)))::int as col
----
SELECT ((($1)))::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Nested(Nested(Parameter(1)))), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Nested(Nested(Parameter(1)))), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
parse-statement
select ((($1 + $2)))::int as col
----
SELECT ((($1 + $2)))::int4 AS col
=>
-Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Nested(Nested(Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Parameter(2)) }))), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] }, failure_mode: Error }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
+Select(SelectStatement { query: Query { ctes: Simple([]), body: Select(Select { distinct: None, projection: [Expr { expr: Cast { expr: Nested(Nested(Nested(Op { op: Op { namespace: None, op: "+" }, expr1: Parameter(1), expr2: Some(Parameter(2)) }))), data_type: Other { name: Name(UnresolvedItemName([Ident("int4")])), typ_mod: [] } }, alias: Some(Ident("col")) }], from: [], selection: None, group_by: [], having: None, qualify: None, options: [] }), order_by: [], limit: None, offset: None }, as_of: None })
# Map subqueries
parse-statement
diff --git a/src/sql-pretty/src/doc.rs b/src/sql-pretty/src/doc.rs
index ecc57a4b1b65a..a0f6b9553382a 100644
--- a/src/sql-pretty/src/doc.rs
+++ b/src/sql-pretty/src/doc.rs
@@ -1254,26 +1254,13 @@ impl Pretty {
let doc = intersperse_line_nest(docs);
bracket_doc(RcDoc::text("CASE"), doc, RcDoc::text("END"), RcDoc::line())
}
- Expr::Cast {
- expr,
- data_type,
- failure_mode: CastFailureMode::Error,
- } => {
+ Expr::Cast { expr, data_type } => {
let doc = self.doc_expr(expr);
RcDoc::concat([
doc,
RcDoc::text(format!("::{}", data_type.to_ast_string_simple())),
])
}
- Expr::Cast {
- expr,
- data_type,
- failure_mode: CastFailureMode::NullFallback,
- } => bracket(
- "TRY_CAST(",
- self.doc_expr(expr),
- format!(" AS {})", data_type.to_ast_string_simple()),
- ),
Expr::Nested(ast) => bracket("(", self.doc_expr(ast), ")"),
Expr::Function(fun) => self.doc_function(fun),
Expr::Subquery(ast) => bracket("(", self.doc_query(ast), ")"),
diff --git a/src/sql/src/plan.rs b/src/sql/src/plan.rs
index c23aace7f9814..66fcdd93c367e 100644
--- a/src/sql/src/plan.rs
+++ b/src/sql/src/plan.rs
@@ -99,9 +99,6 @@ pub(crate) mod statement;
pub(crate) mod transform_ast;
pub(crate) mod transform_hir;
pub(crate) mod typeconv;
-pub use typeconv::{
- CastContext, plan_hypothetical_cast_with_failure_mode, valid_cast_base_type_pairs,
-};
pub(crate) mod with_options;
use crate::plan;
diff --git a/src/sql/src/plan/error.rs b/src/sql/src/plan/error.rs
index 07867033a1a15..ec848436bf9dc 100644
--- a/src/sql/src/plan/error.rs
+++ b/src/sql/src/plan/error.rs
@@ -153,11 +153,6 @@ pub enum PlanError {
UnsupportedRangeElementType {
element_type_name: String,
},
- /// The cast exists, but `TRY_CAST` cannot turn its failures into NULL.
- TryCastUnsupported {
- from: String,
- to: String,
- },
InvalidTable {
name: String,
},
@@ -665,12 +660,6 @@ impl fmt::Display for PlanError {
Self::InvalidTemporarySchema => {
write!(f, "cannot create temporary item in non-temporary schema")
}
- Self::TryCastUnsupported { from, to } => {
- write!(
- f,
- "TRY_CAST cannot fall back to NULL for the cast from {from} to {to}; use CAST instead"
- )
- }
Self::InvalidCast { name, ccx, from, to } =>{
write!(
f,
diff --git a/src/sql/src/plan/query.rs b/src/sql/src/plan/query.rs
index d2a296a0983eb..07c8749d41ba6 100644
--- a/src/sql/src/plan/query.rs
+++ b/src/sql/src/plan/query.rs
@@ -75,7 +75,7 @@ use mz_sql_parser::ast::display::AstDisplay;
use mz_sql_parser::ast::visit::Visit;
use mz_sql_parser::ast::visit_mut::{self, VisitMut};
use mz_sql_parser::ast::{
- AsOf, Assignment, AstInfo, CastFailureMode, CreateWebhookSourceBody, CreateWebhookSourceCheck,
+ AsOf, Assignment, AstInfo, CreateWebhookSourceBody, CreateWebhookSourceCheck,
CreateWebhookSourceHeader, CreateWebhookSourceSecret, CteBlock, DeleteStatement, Distinct,
Expr, Function, FunctionArgs, HomogenizingFunction, Ident, InsertSource, IsExprConstruct, Join,
JoinConstraint, JoinOperator, Limit, MapEntry, MutRecBlock, MutRecBlockOption,
@@ -3691,9 +3691,7 @@ fn invent_column_name(
Expr::Array { .. } => Some(("array".into(), NameQuality::High)),
Expr::List { .. } => Some(("list".into(), NameQuality::High)),
Expr::Map { .. } | Expr::MapSubquery(_) => Some(("map".into(), NameQuality::High)),
- Expr::Cast {
- expr, data_type, ..
- } => match invent(ecx, expr, table_func_names)? {
+ Expr::Cast { expr, data_type } => match invent(ecx, expr, table_func_names)? {
Some((name, NameQuality::High)) => Some((name, NameQuality::High)),
_ => Some((data_type.unqualified_item_name().into(), NameQuality::Low)),
},
@@ -4192,11 +4190,7 @@ fn plan_expr_inner<'a>(
Expr::Op { op, expr1, expr2 } => {
Ok(plan_op(ecx, normalize::op(op)?, expr1, expr2.as_deref())?.into())
}
- Expr::Cast {
- expr,
- data_type,
- failure_mode,
- } => plan_cast(ecx, expr, data_type, *failure_mode),
+ Expr::Cast { expr, data_type } => plan_cast(ecx, expr, data_type),
Expr::Function(func) => Ok(plan_function(ecx, func)?.into()),
// Special functions and operators.
@@ -4304,23 +4298,13 @@ fn plan_row(ecx: &ExprContext, exprs: &[Expr]) -> Result,
data_type: &ResolvedDataType,
- failure_mode: CastFailureMode,
) -> Result {
- let (name, failure_mode) = match failure_mode {
- CastFailureMode::Error => ("CAST", mz_expr::CastFailureMode::Error),
- CastFailureMode::NullFallback => {
- ecx.qcx.scx.require_feature_flag(&vars::ENABLE_TRY_CAST)?;
- ("TRY_CAST", mz_expr::CastFailureMode::NullFallback)
- }
- };
let to_scalar_type = scalar_type_from_sql(ecx.qcx.scx, data_type)?;
- let expr = match (expr, failure_mode) {
+ let expr = match expr {
// Special case a direct cast of an ARRAY, LIST, or MAP expression so
// we can pass in the target type as a type hint. This is
// a limited form of the coercion that we do for string literals
@@ -4329,40 +4313,14 @@ fn plan_cast(
// PostgreSQL compatibility trouble.
//
// See: https://github.com/postgres/postgres/blob/31f403e95/src/backend/parser/parse_expr.c#L2762-L2768
- //
- // The hint makes the element casts part of the literal, where a
- // failure mode cannot reach them. Under `NullFallback` an ARRAY or
- // LIST literal is planned on its own instead, so the cast that gets
- // wrapped is the whole-value one, and a bad element yields NULL for
- // the whole value just as it does for a non-literal source. A MAP
- // literal has no whole-value cast to fall back on, since there is no
- // cast between map types, so under `NullFallback` it is rejected
- // rather than converted with the hint's element-level strictness.
- (Expr::Array(exprs), mz_expr::CastFailureMode::Error) => {
- plan_array(ecx, exprs, Some(&to_scalar_type))?
- }
- (Expr::List(exprs), mz_expr::CastFailureMode::Error) => {
- plan_list(ecx, exprs, Some(&to_scalar_type))?
- }
- (Expr::Map(exprs), mz_expr::CastFailureMode::Error) => {
- plan_map(ecx, exprs, Some(&to_scalar_type))?
- }
- (Expr::Map(_), mz_expr::CastFailureMode::NullFallback) => {
- bail_unsupported!("MAP constructor as the argument of TRY_CAST")
- }
- (expr, _) => plan_expr(ecx, expr)?,
+ Expr::Array(exprs) => plan_array(ecx, exprs, Some(&to_scalar_type))?,
+ Expr::List(exprs) => plan_list(ecx, exprs, Some(&to_scalar_type))?,
+ Expr::Map(exprs) => plan_map(ecx, exprs, Some(&to_scalar_type))?,
+ _ => plan_expr(ecx, expr)?,
};
- let ecx = &ecx.with_name(name);
- // A string literal reaches its cast through coercion, so the failure mode
- // has to apply there too, or `TRY_CAST('abc' AS int4)` would still error.
- let expr = typeconv::plan_coerce_with_failure_mode(ecx, expr, &to_scalar_type, failure_mode)?;
- let expr = typeconv::plan_cast_with_failure_mode(
- ecx,
- CastContext::Explicit,
- failure_mode,
- expr,
- &to_scalar_type,
- )?;
+ let ecx = &ecx.with_name("CAST");
+ let expr = typeconv::plan_coerce(ecx, expr, &to_scalar_type)?;
+ let expr = typeconv::plan_cast(ecx, CastContext::Explicit, expr, &to_scalar_type)?;
Ok(expr.into())
}
diff --git a/src/sql/src/plan/typeconv.rs b/src/sql/src/plan/typeconv.rs
index 6de8dbfc56d32..fce74bc72fc3f 100644
--- a/src/sql/src/plan/typeconv.rs
+++ b/src/sql/src/plan/typeconv.rs
@@ -16,19 +16,17 @@ use std::sync::LazyLock;
use dynfmt::{Format, SimpleCurlyFormat};
use itertools::Itertools;
+use mz_expr::func;
use mz_expr::func::variadic::{JsonbBuildObject, RecordCreate};
use mz_expr::func::{CastArrayToJsonb, CastListToJsonb};
-use mz_expr::{CastFailureMode, func};
-use mz_ore::soft_panic_or_log;
use mz_repr::{
- ColumnName, Datum, Row, SqlColumnType, SqlRelationType, SqlScalarBaseType, SqlScalarType,
+ ColumnName, Datum, SqlColumnType, SqlRelationType, SqlScalarBaseType, SqlScalarType,
};
use crate::catalog::TypeCategory;
use crate::plan::error::PlanError;
use crate::plan::hir::{
- AbstractColumnType, CoercibleScalarExpr, CoercibleScalarType, HirScalarExpr, NameMetadata,
- UnaryFunc,
+ AbstractColumnType, CoercibleScalarExpr, CoercibleScalarType, HirScalarExpr, UnaryFunc,
};
use crate::plan::query::{ExprContext, QueryContext};
use crate::plan::scope::Scope;
@@ -36,7 +34,7 @@ use crate::plan::scope::Scope;
/// Like func::sql_impl_func, but for casts.
fn sql_impl_cast(expr: &'static str) -> CastTemplate {
let invoke = crate::func::sql_impl(expr);
- CastTemplate::strict_only(move |ecx, _ccx, from_type, _to_type| {
+ CastTemplate::new(move |ecx, _ccx, from_type, _to_type| {
// Oddly, this needs to be able to gracefully fail so we can detect unmet dependencies.
let mut out = invoke(ecx, vec![from_type.clone()]).ok()?;
Some(move |e| {
@@ -51,7 +49,7 @@ fn sql_impl_cast_per_context(casts: &[(CastContext, &'static str)]) -> CastTempl
.iter()
.map(|(ccx, expr)| (ccx.clone(), crate::func::sql_impl(expr)))
.collect();
- CastTemplate::strict_only(move |ecx, ccx, from_type, _to_type| {
+ CastTemplate::new(move |ecx, ccx, from_type, _to_type| {
let invoke = &casts[&ccx];
let r = invoke(ecx, vec![from_type.clone()]);
let mut out = r.ok()?;
@@ -66,9 +64,8 @@ fn sql_impl_cast_per_context(casts: &[(CastContext, &'static str)]) -> CastTempl
type Cast = Box HirScalarExpr>;
/// A cast template is a function that produces a `Cast` given a concrete input
-/// and output type and a failure mode. A template can return `None` to
-/// indicate that it is incapable of producing a cast for the specified types,
-/// or for the specified failure mode.
+/// and output type. A template can return `None` to indicate that it is
+/// incapable of producing a cast for the specified types.
///
/// Cast templates are used to share code for similar casts, where the input or
/// output type is of one "category" of type. For example, a single cast
@@ -77,29 +74,13 @@ type Cast = Box HirScalarExpr>;
/// which is impractical.
struct CastTemplate(
Box<
- dyn Fn(
- &ExprContext,
- CastContext,
- CastFailureMode,
- &SqlScalarType,
- &SqlScalarType,
- ) -> Option
+ dyn Fn(&ExprContext, CastContext, &SqlScalarType, &SqlScalarType) -> Option
+ Send
+ Sync,
>,
);
impl CastTemplate {
- /// Builds a template from a builder of the erroring cast.
- ///
- /// Under [`CastFailureMode::NullFallback`] the template emits the same
- /// stages with each one that could error wrapped in `TryCast`, so a
- /// failure at any stage yields NULL. A stage that cannot error is emitted as
- /// is, so a cast that cannot fail plans exactly as `CAST` does and keeps its
- /// nullability. That requires the builder to apply only unary functions to its
- /// input, which [`extract_unary_stages_for_try_cast`] verifies; a builder of any other shape
- /// yields `None` under `NullFallback` and must use
- /// [`CastTemplate::strict_only`] instead.
fn new(t: T) -> CastTemplate
where
T: Fn(&ExprContext, CastContext, &SqlScalarType, &SqlScalarType) -> Option
@@ -108,85 +89,12 @@ impl CastTemplate {
+ 'static,
C: FnOnce(HirScalarExpr) -> HirScalarExpr + 'static,
{
- CastTemplate(Box::new(move |ecx, ccx, mode, from_ty, to_ty| {
- let cast = t(ecx, ccx, from_ty, to_ty)?;
- match mode {
- CastFailureMode::Error => Some(Box::new(cast)),
- CastFailureMode::NullFallback => {
- let stages = extract_unary_stages_for_try_cast(from_ty, cast)?;
- Some(Box::new(move |mut expr: HirScalarExpr| {
- for stage in stages {
- expr = expr.call_unary(UnaryFunc::try_cast(stage));
- }
- expr
- }))
- }
- }
- }))
- }
-
- /// Builds a template that supports only [`CastFailureMode::Error`].
- ///
- /// For casts implemented in SQL: their failures come from `mz_error_if_null`
- /// calls and from subquery cardinality, neither of which a scalar-level
- /// wrapper can turn into NULL.
- fn strict_only(t: T) -> CastTemplate
- where
- T: Fn(&ExprContext, CastContext, &SqlScalarType, &SqlScalarType) -> Option
- + Send
- + Sync
- + 'static,
- C: FnOnce(HirScalarExpr) -> HirScalarExpr + 'static,
- {
- CastTemplate(Box::new(move |ecx, ccx, mode, from_ty, to_ty| match mode {
- CastFailureMode::Error => Some(Box::new(t(ecx, ccx, from_ty, to_ty)?)),
- CastFailureMode::NullFallback => None,
+ CastTemplate(Box::new(move |ecx, ccx, from_ty, to_ty| {
+ Some(Box::new(t(ecx, ccx, from_ty, to_ty)?))
}))
}
}
-/// Extracts a sequence of `UnaryFunc`s from a cast, returning `None` if the cast
-/// is not a sequence of `UnaryFunc`s.
-///
-/// These stages must propagate nulls: f(g(e)) == try[f](try[g](e)) only when
-/// f and g return null on a null input. (As of 2026-09-15, this is true of all
-/// casts that are sequences of `UnaryFunc` stages.)
-fn extract_unary_stages_for_try_cast(
- from: &SqlScalarType,
- cast: impl FnOnce(HirScalarExpr) -> HirScalarExpr,
-) -> Option> {
- // dummy argument (built manually to avoid an assert)
- let sentinel = HirScalarExpr::Literal(
- Row::pack([Datum::Dummy]),
- from.clone().nullable(false),
- NameMetadata::default(),
- );
- let mut expr = cast(sentinel.clone());
- let mut stages = vec![];
- loop {
- match expr {
- HirScalarExpr::CallUnary {
- func, expr: inner, ..
- } => {
- stages.push(func);
- expr = *inner;
- }
- other if other == sentinel => break,
- _ => return None,
- }
- }
- stages.reverse();
- if let Some(stage) = stages
- .iter()
- .skip(1)
- .find(|stage| !stage.propagates_nulls())
- {
- soft_panic_or_log!("cast stage {stage} does not propagate NULLs; TRY_CAST cannot wrap it");
- return None;
- }
- Some(stages)
-}
-
impl From for CastTemplate {
fn from(u: UnaryFunc) -> CastTemplate {
CastTemplate::new(move |_ecx, _ccx, _from, _to| {
@@ -1191,8 +1099,6 @@ pub enum CastError {
},
/// Cast would apply but is disallowed (e.g. range over an unsupported element type).
UnsupportedRangeElementType { element_type_name: String },
- /// The cast exists but has no null-fallback form, so `TRY_CAST` cannot use it.
- NullFallbackUnsupported { from: String, to: String },
}
impl CastError {
@@ -1208,9 +1114,6 @@ impl CastError {
CastError::UnsupportedRangeElementType { element_type_name } => {
PlanError::UnsupportedRangeElementType { element_type_name }
}
- CastError::NullFallbackUnsupported { from, to } => {
- PlanError::TryCastUnsupported { from, to }
- }
}
}
}
@@ -1224,13 +1127,11 @@ impl CastError {
fn get_cast(
ecx: &ExprContext,
ccx: CastContext,
- mode: CastFailureMode,
from: &SqlScalarType,
to: &SqlScalarType,
) -> Result {
use CastContext::*;
- // The identity cast cannot fail, so it is the same in every failure mode.
if from == to || (ccx == Implicit && from.base_eq(to)) {
return Ok(Box::new(|expr| expr));
}
@@ -1255,20 +1156,8 @@ fn get_cast(
} else {
None
};
- let build = |mode| template.and_then(|template| (template.0)(ecx, ccx, mode, from, to));
- match build(mode) {
+ match template.and_then(|template| (template.0)(ecx, ccx, from, to)) {
Some(cast) => Ok(cast),
- // A template declines a failure mode by returning `None`, the same way
- // it declines a type pair. Tell the two apart so that the error names
- // the actual problem.
- None if mode == CastFailureMode::NullFallback
- && build(CastFailureMode::Error).is_some() =>
- {
- Err(CastError::NullFallbackUnsupported {
- from: ecx.humanize_sql_scalar_type(from, false),
- to: ecx.humanize_sql_scalar_type(to, false),
- })
- }
None => Err(CastError::InvalidCast {
ccx,
from: ecx.humanize_sql_scalar_type(from, false),
@@ -1277,13 +1166,6 @@ fn get_cast(
}
}
-/// The base type pairs that have an entry in the cast table, for tests that
-/// want to prove they exercised every one.
-pub fn valid_cast_base_type_pairs() -> impl Iterator-
-{
- VALID_CASTS.keys().copied()
-}
-
/// Converts an expression to `SqlScalarType::String`.
///
/// Most types have an explicit cast to string, but a few do not: `mz_aclitem`
@@ -1516,18 +1398,6 @@ pub fn plan_coerce<'a>(
ecx: &'a ExprContext,
e: CoercibleScalarExpr,
coerce_to: &SqlScalarType,
-) -> Result {
- plan_coerce_with_failure_mode(ecx, e, coerce_to, CastFailureMode::Error)
-}
-
-/// Like [`plan_coerce`], but the casts that coerce a literal to `coerce_to`
-/// use the given failure mode. `TRY_CAST('abc' AS int4)` reaches its cast
-/// through this coercion, so the mode has to apply here too.
-pub fn plan_coerce_with_failure_mode<'a>(
- ecx: &'a ExprContext,
- e: CoercibleScalarExpr,
- coerce_to: &SqlScalarType,
- mode: CastFailureMode,
) -> Result {
use CoercibleScalarExpr::*;
@@ -1543,32 +1413,22 @@ pub fn plan_coerce_with_failure_mode<'a>(
// (with either implicit or explicit semantics) via a separate call
// to `plan_cast`.
let coerce_to_base = &coerce_to.without_modifiers();
- plan_cast_with_failure_mode(ecx, CastContext::Coerced, mode, lit, coerce_to_base)?
+ plan_cast(ecx, CastContext::Coerced, lit, coerce_to_base)?
}
LiteralRecord(exprs) => {
let arity = exprs.len();
- // Under `NullFallback` the target field types are not pushed into
- // the literal. Fields are typed on their own, so every field
- // conversion happens inside the record cast that follows, where
- // the `TryCast` wrapper covers it, and a bad field yields NULL for
- // the whole record rather than a record with a NULL field. This
- // mirrors how `plan_cast` treats collection constructors.
- let coercions = match (coerce_to, mode) {
- (SqlScalarType::Record { fields, .. }, CastFailureMode::Error)
- if fields.len() == arity =>
- {
- fields
- .iter()
- .map(|(_name, ty)| &ty.scalar_type)
- .cloned()
- .collect()
- }
+ let coercions = match coerce_to {
+ SqlScalarType::Record { fields, .. } if fields.len() == arity => fields
+ .iter()
+ .map(|(_name, ty)| &ty.scalar_type)
+ .cloned()
+ .collect(),
_ => vec![SqlScalarType::String; exprs.len()],
};
let mut out = vec![];
for (e, coerce_to) in exprs.into_iter().zip_eq(coercions) {
- out.push(plan_coerce_with_failure_mode(ecx, e, &coerce_to, mode)?);
+ out.push(plan_coerce(ecx, e, &coerce_to)?);
}
HirScalarExpr::call_variadic(
RecordCreate {
@@ -1635,17 +1495,6 @@ pub fn plan_hypothetical_cast(
ccx: CastContext,
from: &SqlScalarType,
to: &SqlScalarType,
-) -> Option {
- plan_hypothetical_cast_with_failure_mode(ecx, ccx, CastFailureMode::Error, from, to)
-}
-
-/// Similar to `plan_hypothetical_cast`, but with a `CastFailureMode` to specify behavior.
-pub fn plan_hypothetical_cast_with_failure_mode(
- ecx: &ExprContext,
- ccx: CastContext,
- mode: CastFailureMode,
- from: &SqlScalarType,
- to: &SqlScalarType,
) -> Option {
// Reconstruct an expression context where the expression is evaluated on
// the "first column" of some imaginary row.
@@ -1674,13 +1523,7 @@ pub fn plan_hypothetical_cast_with_failure_mode(
// Determine the `ScalarExpr` required to cast our column to the target
// component type.
- //
- // NOTE: the templates plan element casts through `plan_hypothetical_cast`,
- // which is always strict, whatever the enclosing cast's failure mode. Under
- // `TRY_CAST` the enclosing function is what gets wrapped, so a bad element
- // makes the whole value NULL rather than producing a value with NULL holes
- // in it.
- plan_cast_with_failure_mode(&ecx, ccx, mode, col_expr, to)
+ plan_cast(&ecx, ccx, col_expr, to)
.ok()?
// TODO(jkosh44) Support casts that have correlated implementations.
.lower_uncorrelated(ecx.catalog().system_vars())
@@ -1701,27 +1544,13 @@ pub fn plan_cast(
ccx: CastContext,
expr: HirScalarExpr,
to: &SqlScalarType,
-) -> Result {
- plan_cast_with_failure_mode(ecx, ccx, CastFailureMode::Error, expr, to)
-}
-
-/// Like [`plan_cast`], but with the given failure mode. Under
-/// [`CastFailureMode::NullFallback`] every stage of the cast, including the
-/// intermediate string cast that string-like types route through, is wrapped so
-/// that a failure anywhere yields NULL.
-pub fn plan_cast_with_failure_mode(
- ecx: &ExprContext,
- ccx: CastContext,
- mode: CastFailureMode,
- expr: HirScalarExpr,
- to: &SqlScalarType,
) -> Result {
let from = ecx.scalar_type(&expr);
- // Close over `ccx`, `mode`, `from`, and `to` to simplify error messages in
- // the face of intermediate expressions.
+ // Close over `ccx`, `from`, and `to` to simplify error messages in the
+ // face of intermediate expressions.
let cast_inner = |from, to, expr| {
- get_cast(ecx, ccx, mode, from, to)
+ get_cast(ecx, ccx, from, to)
.map(|cast| cast(expr))
.map_err(|e| e.into_plan_error(ecx.name.into()))
};
@@ -1740,7 +1569,7 @@ pub fn plan_cast_with_failure_mode(
// registered cast when one exists (`int4`, by byte value) and
// otherwise render it to text first.
let expr = match from {
- SqlScalarType::PgLegacyChar => match get_cast(ecx, ccx, mode, &from, to) {
+ SqlScalarType::PgLegacyChar => match get_cast(ecx, ccx, &from, to) {
Ok(cast) => return Ok(cast(expr)),
Err(_) => cast_inner(&from, &SqlScalarType::String, expr)?,
},
@@ -1765,70 +1594,5 @@ pub fn can_cast(
cast_from: &SqlScalarType,
cast_to: &SqlScalarType,
) -> bool {
- get_cast(ecx, ccx, CastFailureMode::Error, cast_from, cast_to).is_ok()
-}
-
-#[cfg(test)]
-mod tests {
- use mz_expr::func::{CastInt64ToInt32, CastStringToInt64, Eq as EqFunc, IsNull};
- use mz_repr::SqlScalarType;
-
- use super::extract_unary_stages_for_try_cast;
- use crate::plan::hir::HirScalarExpr;
-
- #[mz_ore::test]
- fn cast_stages_of_chain_are_innermost_first() {
- let stages =
- extract_unary_stages_for_try_cast(&SqlScalarType::String, |e: HirScalarExpr| {
- e.call_unary(CastStringToInt64.into())
- .call_unary(CastInt64ToInt32.into())
- });
- assert_eq!(
- stages,
- Some(vec![CastStringToInt64.into(), CastInt64ToInt32.into()])
- );
- }
-
- #[mz_ore::test]
- fn cast_stages_of_identity_is_empty() {
- assert_eq!(
- extract_unary_stages_for_try_cast(&SqlScalarType::Int32, |e: HirScalarExpr| e),
- Some(vec![])
- );
- }
-
- #[mz_ore::test]
- fn cast_stages_rejects_non_unary_shapes() {
- let compares = |e: HirScalarExpr| {
- let zero = HirScalarExpr::literal_null(SqlScalarType::Int32);
- e.call_binary(zero, EqFunc)
- };
- assert_eq!(
- extract_unary_stages_for_try_cast(&SqlScalarType::Int32, compares),
- None
- );
- let ignores_input = |_: HirScalarExpr| HirScalarExpr::literal_null(SqlScalarType::Int32);
- assert_eq!(
- extract_unary_stages_for_try_cast(&SqlScalarType::Int32, ignores_input),
- None
- );
- }
-
- /// A stage after the first that does not propagate NULLs would turn the
- /// NULL of an earlier failure into a value, so wrapping must refuse it.
- #[mz_ore::test]
- fn cast_stages_rejects_non_null_propagating_later_stage() {
- let chain = |e: HirScalarExpr| {
- e.call_unary(CastInt64ToInt32.into())
- .call_unary(IsNull.into())
- };
- let outcome = mz_ore::panic::catch_unwind(|| {
- extract_unary_stages_for_try_cast(&SqlScalarType::Int64, chain)
- });
- if mz_ore::assert::soft_assertions_enabled() {
- assert!(outcome.is_err(), "soft assertion should have fired");
- } else {
- assert_eq!(outcome.expect("no panic"), None);
- }
- }
+ get_cast(ecx, ccx, cast_from, cast_to).is_ok()
}
diff --git a/src/sql/src/pure.rs b/src/sql/src/pure.rs
index c64437da0051f..842132e00e6c1 100644
--- a/src/sql/src/pure.rs
+++ b/src/sql/src/pure.rs
@@ -38,18 +38,18 @@ use mz_sql_parser::ast::visit::{Visit, visit_function};
use mz_sql_parser::ast::visit_mut::{VisitMut, visit_expr_mut};
use mz_sql_parser::ast::{
AlterSourceAction, AlterSourceAddSubsourceOptionName, AlterSourceStatement, AvroDocOn,
- CastFailureMode, ColumnName, CreateMaterializedViewStatement, CreateSinkConnection,
- CreateSinkOptionName, CreateSinkStatement, CreateSourceOptionName, CreateSubsourceOption,
- CreateSubsourceOptionName, CreateTableFromSourceStatement, CsrConfigOption,
- CsrConfigOptionName, CsrConnection, CsrSeedAvro, CsrSeedProtobuf, CsrSeedProtobufSchema,
- DeferredItemName, DocOnIdentifier, DocOnSchema, Expr, Function, FunctionArgs, GlueAvroOption,
- GlueAvroSeed, Ident, KafkaSourceConfigOption, KafkaSourceConfigOptionName, LoadGenerator,
- LoadGeneratorOption, LoadGeneratorOptionName, MaterializedViewOption,
- MaterializedViewOptionName, MySqlConfigOption, MySqlConfigOptionName, PgConfigOption,
- PgConfigOptionName, RawItemName, ReaderSchemaSelectionStrategy, RefreshAtOptionValue,
- RefreshEveryOptionValue, RefreshOptionValue, SourceEnvelope, SqlServerConfigOption,
- SqlServerConfigOptionName, Statement, TableFromSourceColumns, TableFromSourceOption,
- TableFromSourceOptionName, UnresolvedItemName,
+ ColumnName, CreateMaterializedViewStatement, CreateSinkConnection, CreateSinkOptionName,
+ CreateSinkStatement, CreateSourceOptionName, CreateSubsourceOption, CreateSubsourceOptionName,
+ CreateTableFromSourceStatement, CsrConfigOption, CsrConfigOptionName, CsrConnection,
+ CsrSeedAvro, CsrSeedProtobuf, CsrSeedProtobufSchema, DeferredItemName, DocOnIdentifier,
+ DocOnSchema, Expr, Function, FunctionArgs, GlueAvroOption, GlueAvroSeed, Ident,
+ KafkaSourceConfigOption, KafkaSourceConfigOptionName, LoadGenerator, LoadGeneratorOption,
+ LoadGeneratorOptionName, MaterializedViewOption, MaterializedViewOptionName, MySqlConfigOption,
+ MySqlConfigOptionName, PgConfigOption, PgConfigOptionName, RawItemName,
+ ReaderSchemaSelectionStrategy, RefreshAtOptionValue, RefreshEveryOptionValue,
+ RefreshOptionValue, SourceEnvelope, SqlServerConfigOption, SqlServerConfigOptionName,
+ Statement, TableFromSourceColumns, TableFromSourceOption, TableFromSourceOptionName,
+ UnresolvedItemName,
};
use mz_sql_server_util::desc::SqlServerTableDesc;
use mz_storage_types::configuration::StorageConfiguration;
@@ -3174,7 +3174,6 @@ impl VisitMut<'_, Aug> for MzNowPurifierVisitor {
*expr = Expr::Cast {
expr: Box::new(Expr::Value(Value::Number(mz_now.to_string()))),
data_type: self.mz_timestamp_type.clone(),
- failure_mode: CastFailureMode::Error,
};
self.introduced_mz_timestamp = true;
}
diff --git a/src/sql/src/session/vars/definitions.rs b/src/sql/src/session/vars/definitions.rs
index fabe52224b73b..87c976a1ff7f1 100644
--- a/src/sql/src/session/vars/definitions.rs
+++ b/src/sql/src/session/vars/definitions.rs
@@ -2152,12 +2152,6 @@ feature_flags!(
default: true,
enable_for_item_parsing: true,
},
- {
- name: enable_try_cast,
- desc: "TRY_CAST( AS ) syntax",
- default: true,
- enable_for_item_parsing: true,
- },
{
name: enable_mz_notices,
desc: "Populate the contents of `mz_internal.mz_notices`",
diff --git a/src/transform/fuzz/src/lib.rs b/src/transform/fuzz/src/lib.rs
index ddfa9df08c1d4..cb09a96ee3d3e 100644
--- a/src/transform/fuzz/src/lib.rs
+++ b/src/transform/fuzz/src/lib.rs
@@ -30,8 +30,7 @@ use std::collections::BTreeMap;
use libfuzzer_sys::arbitrary::{self, Arbitrary, Unstructured};
use mz_expr::{
- AggregateExpr, AggregateFunc, ColumnOrder, EvalError, MirRelationExpr, MirScalarExpr,
- UnaryFunc, func,
+ AggregateExpr, AggregateFunc, ColumnOrder, EvalError, MirRelationExpr, MirScalarExpr, func,
};
use mz_repr::optimize::OptimizerFeatures;
use mz_repr::{Datum, Diff, GlobalId, ReprColumnType, ReprRelationType, ReprScalarType, Row};
@@ -97,23 +96,6 @@ fn cols_of(schema: &[Ty], ty: Ty) -> Vec {
/// exercise error-propagation paths). Includes `Add`/`Sub`/`Mul`/`Mod` per
/// integer width, the boolean connectives, `Eq` across a random type, `If`, and
/// the `int4`<->`int8`/`int4`<->`bool` casts so neither integer width is a leaf.
-
-/// A cast as the planner emits it: strict, or, half the time, as `TRY_CAST`
-/// would emit it, wrapped in `TryCast` when it could error. The wrapper is
-/// strict in its argument and never errors, so it needs no special handling in
-/// the oracle; generating it checks that `reduce` treats it that way.
-fn maybe_try_cast(
- u: &mut Unstructured,
- cast: impl Into,
-) -> arbitrary::Result {
- let cast = cast.into();
- Ok(if bool::arbitrary(u)? {
- UnaryFunc::try_cast(cast)
- } else {
- cast
- })
-}
-
pub fn gen_scalar(
u: &mut Unstructured,
ty: Ty,
@@ -152,8 +134,7 @@ pub fn gen_scalar(
3 => gen_scalar(u, Ty::Int32, schema, d)?
.call_binary(gen_scalar(u, Ty::Int32, schema, d)?, func::ModInt32),
// Narrowing cast from int8 (may error on overflow, folds to an error).
- 4 => gen_scalar(u, Ty::Int64, schema, d)?
- .call_unary(maybe_try_cast(u, func::CastInt64ToInt32)?),
+ 4 => gen_scalar(u, Ty::Int64, schema, d)?.call_unary(func::CastInt64ToInt32),
_ => gen_if(u)?,
},
Ty::Int64 => match u.int_in_range(0u8..=5)? {
@@ -166,8 +147,7 @@ pub fn gen_scalar(
3 => gen_scalar(u, Ty::Int64, schema, d)?
.call_binary(gen_scalar(u, Ty::Int64, schema, d)?, func::ModInt64),
// Widening cast from int4.
- 4 => gen_scalar(u, Ty::Int32, schema, d)?
- .call_unary(maybe_try_cast(u, func::CastInt32ToInt64)?),
+ 4 => gen_scalar(u, Ty::Int32, schema, d)?.call_unary(func::CastInt32ToInt64),
_ => gen_if(u)?,
},
Ty::Bool => match u.int_in_range(0u8..=5)? {
@@ -181,8 +161,7 @@ pub fn gen_scalar(
a.call_binary(b, func::Eq)
}
// Cast int4 -> bool (nonzero is true).
- 4 => gen_scalar(u, Ty::Int32, schema, d)?
- .call_unary(maybe_try_cast(u, func::CastInt32ToBool)?),
+ 4 => gen_scalar(u, Ty::Int32, schema, d)?.call_unary(func::CastInt32ToBool),
_ => gen_if(u)?,
},
})
diff --git a/test/sqllogictest/mzcompose.py b/test/sqllogictest/mzcompose.py
index 78b172f87e35a..f9e143e3467e2 100644
--- a/test/sqllogictest/mzcompose.py
+++ b/test/sqllogictest/mzcompose.py
@@ -588,9 +588,6 @@ def compileFastSltConfig() -> SltRunConfig:
"test/sqllogictest/cast.slt",
"test/sqllogictest/char.slt",
"test/sqllogictest/chbench.slt",
- # A constant-folded numeric(5,2) literal loses its scale in a view;
- # see the file's header.
- "test/sqllogictest/try_cast_noindex.slt",
"test/sqllogictest/chr.slt",
"test/sqllogictest/cluster.slt",
"test/sqllogictest/coercion.slt",
@@ -1094,9 +1091,6 @@ def compileSlowSltConfig() -> SltRunConfig:
# pg_typeof contains public schema name in views
"test/sqllogictest/cast.slt",
"test/sqllogictest/map.slt",
- # A constant-folded numeric(5,2) literal loses its scale in a view;
- # see the file's header.
- "test/sqllogictest/try_cast_noindex.slt",
# pg_typeof contains public schema name in views
"test/sqllogictest/typeof.slt",
# https://github.com/MaterializeInc/database-issues/issues/9513#issuecomment-3128051157
diff --git a/test/sqllogictest/try_cast.slt b/test/sqllogictest/try_cast.slt
deleted file mode 100644
index f0bc51fa17913..0000000000000
--- a/test/sqllogictest/try_cast.slt
+++ /dev/null
@@ -1,4471 +0,0 @@
-# Copyright Materialize, Inc. and contributors. All rights reserved.
-#
-# Use of this software is governed by the Business Source License
-# included in the LICENSE file at the root of this repository.
-#
-# 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.
-
-# TRY_CAST(expr AS type) is CAST(expr AS type) that yields NULL where the cast
-# would error. Errors raised by `expr` itself still propagate.
-#
-# The matrix below has one block per entry of the planner's cast table. For
-# each source value that converts, the block shows the TRY_CAST result and
-# checks that it agrees with CAST (the second column, always true, comparing
-# the text renderings so that every type is comparable; the third
-# column checks that a NULL source yields NULL). For each source value that
-# does not convert, the block checks that CAST errors and TRY_CAST is NULL.
-# The values were chosen so that every cast with a failure mode has at least
-# one failing value; a block with no failing value is a cast that cannot fail.
-#
-# The numeric(5,2) target's blocks are in try_cast_noindex.slt, see there.
-
-mode cockroach
-
-# The feature flag gates the syntax.
-simple conn=mz_system,user=mz_system
-ALTER SYSTEM SET enable_try_cast = false
-----
-COMPLETE 0
-
-statement error enable_try_cast
-SELECT TRY_CAST('1' AS int4)
-
-simple conn=mz_system,user=mz_system
-ALTER SYSTEM SET enable_try_cast = true
-----
-COMPLETE 0
-
-# Record types can only be named through user-defined types.
-statement ok
-CREATE TYPE rec8 AS (a int8, b text)
-
-statement ok
-CREATE TYPE rec2 AS (a int2, b text)
-
-# Basics.
-query ITT
-SELECT TRY_CAST('42' AS int4), TRY_CAST('abc' AS int4)::text, TRY_CAST(NULL AS int4)::text
-----
-42 NULL NULL
-
-query T
-SELECT pg_typeof(TRY_CAST(1 AS int8))
-----
-bigint
-
-# The argument is evaluated first, and its errors propagate.
-statement error division by zero
-SELECT TRY_CAST(1 / 0 AS text)
-
-statement error number too large to fit in target type
-SELECT TRY_CAST(CAST('99999' AS smallint) AS integer)
-
-statement error division by zero
-SELECT TRY_CAST(TRY_CAST(1 / 0 AS int8) AS int4)
-
-# Every stage of a multi-stage cast is protected.
-query TT
-SELECT TRY_CAST((-1)::int8 AS regclass)::text, TRY_CAST(5::int8 AS regclass)::text
-----
-NULL 5
-
-# String-like targets route through text, and an explicit cast to char(n)
-# truncates rather than failing, as CAST does.
-query T
-SELECT TRY_CAST(12345 AS char(3))
-----
-123
-
-# A bad element yields NULL for the whole value, never a value with NULL
-# holes in it. Collection literals are typed on their own, so the same holds
-# for them.
-query TTTT
-SELECT TRY_CAST('{1,2,x}' AS int4 list)::text, TRY_CAST('{1,2,3}' AS int4 list)::text, TRY_CAST(ARRAY['1', 'x'] AS int4[])::text, TRY_CAST(LIST[100000] AS int2 list)::text
-----
-NULL {1,2,3} NULL NULL
-
-query TT
-SELECT TRY_CAST(ROW(100000, 'a') AS rec2)::text, TRY_CAST(ROW(1, 'a') AS rec8)::text
-----
-NULL (1,a)
-
-# The same holds when the fields are untyped literals, which are typed on
-# their own rather than coerced to the record's field types.
-query TT
-SELECT TRY_CAST(ROW('100000', 'a') AS rec2)::text, TRY_CAST(ROW('1', 'a') AS rec8)::text
-----
-NULL (1,a)
-
-# Because the literal is typed on its own, its elements must agree on a type
-# (CAST would coerce them all to the target's element type), and an empty
-# literal needs its own type annotation.
-statement error ARRAY types text and integer cannot be matched
-SELECT TRY_CAST(ARRAY[s, 2] AS int4[]) FROM (VALUES ('1')) AS v(s)
-
-query T
-SELECT TRY_CAST(ARRAY[s, 2::text] AS int4[])::text FROM (VALUES ('1')) AS v(s)
-----
-{1,2}
-
-statement error cannot determine type of empty array
-SELECT TRY_CAST(ARRAY[] AS int4[])
-
-# There is no cast between map types, so a MAP constructor has no whole-value
-# cast to fall back on and is rejected rather than converted element by element.
-statement error MAP constructor as the argument of TRY_CAST not yet supported
-SELECT TRY_CAST(MAP['k' => '1'] AS map[text=>int4])
-
-query T
-SELECT TRY_CAST(MAP['k' => '1']::map[text=>int4] AS map[text=>int4])::text
-----
-{k=>1}
-
-query T
-SELECT TRY_CAST(ARRAY[]::int4[] AS int8[])::text
-----
-{}
-
-# Pairs CAST rejects are rejected the same way.
-statement error CAST does not support casting from integer to jsonb
-SELECT TRY_CAST(1 AS jsonb)
-
-# The catalog-lookup casts are implemented in SQL and have no null-fallback
-# form. String-like types route through text, so all of them are refused.
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regclass
-SELECT TRY_CAST(NULL::text AS regclass)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regclass to text
-SELECT TRY_CAST(NULL::regclass AS text)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regproc
-SELECT TRY_CAST(NULL::text AS regproc)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regproc to text
-SELECT TRY_CAST(NULL::regproc AS text)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regtype
-SELECT TRY_CAST(NULL::text AS regtype)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regtype to text
-SELECT TRY_CAST(NULL::regtype AS text)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regclass
-SELECT TRY_CAST(NULL::char(3) AS regclass)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regclass to text
-SELECT TRY_CAST(NULL::regclass AS char(3))
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regproc
-SELECT TRY_CAST(NULL::char(3) AS regproc)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regproc to text
-SELECT TRY_CAST(NULL::regproc AS char(3))
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regtype
-SELECT TRY_CAST(NULL::char(3) AS regtype)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regtype to text
-SELECT TRY_CAST(NULL::regtype AS char(3))
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regclass
-SELECT TRY_CAST(NULL::varchar(3) AS regclass)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regclass to text
-SELECT TRY_CAST(NULL::regclass AS varchar(3))
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regproc
-SELECT TRY_CAST(NULL::varchar(3) AS regproc)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regproc to text
-SELECT TRY_CAST(NULL::regproc AS varchar(3))
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regtype
-SELECT TRY_CAST(NULL::varchar(3) AS regtype)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regtype to text
-SELECT TRY_CAST(NULL::regtype AS varchar(3))
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regclass
-SELECT TRY_CAST(NULL::name AS regclass)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regclass to text
-SELECT TRY_CAST(NULL::regclass AS name)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regproc
-SELECT TRY_CAST(NULL::name AS regproc)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regproc to text
-SELECT TRY_CAST(NULL::regproc AS name)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from text to regtype
-SELECT TRY_CAST(NULL::name AS regtype)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from regtype to text
-SELECT TRY_CAST(NULL::regtype AS name)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from aclitem to text
-SELECT TRY_CAST(NULL::aclitem AS text)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from mz_aclitem to text
-SELECT TRY_CAST(NULL::mz_aclitem AS text)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from aclitem to mz_aclitem
-SELECT TRY_CAST(NULL::aclitem AS mz_aclitem)
-
-statement error TRY_CAST cannot fall back to NULL for the cast from mz_aclitem to aclitem
-SELECT TRY_CAST(NULL::mz_aclitem AS aclitem)
-
-# TRY_CAST over a NOT NULL column is nullable, and NULL fallbacks flow through
-# dataflows without error. A TRY_CAST that cannot fail, here bool to int4 over
-# a NOT NULL column, is planned as the plain cast and stays NOT NULL.
-statement ok
-CREATE TABLE t (s text NOT NULL)
-
-statement ok
-INSERT INTO t VALUES ('1'), ('2'), ('x'), ('3000000000'), ('2020-01-01')
-
-statement ok
-CREATE MATERIALIZED VIEW mv AS SELECT s, TRY_CAST(s AS int4) AS i, TRY_CAST(s AS date) AS d, TRY_CAST(s AS int4 list) AS l, TRY_CAST(s = '' AS int4) AS b FROM t
-
-statement ok
-CREATE INDEX mv_i ON mv (i)
-
-query TTTTI rowsort
-SELECT s, i::text, d::text, l::text, b FROM mv
-----
-1 1 NULL NULL 0
-2 2 NULL NULL 0
-2020-01-01 NULL 2020-01-01 NULL 0
-3000000000 NULL NULL NULL 0
-x NULL NULL NULL 0
-
-query TT rowsort
-SELECT name, nullable::text FROM mz_columns WHERE id = (SELECT id FROM mz_materialized_views WHERE name = 'mv') AND name IN ('s', 'i', 'b')
-----
-b false
-i true
-s false
-
-# A view definition plans as a TryCast.
-statement ok
-CREATE VIEW v AS SELECT TRY_CAST(s AS int4) AS i FROM t
-
-query T multiline
-EXPLAIN RAW PLAN FOR VIEW v
-----
-Project (#1)
- Map (try_cast[text_to_integer](#0{s}))
- Get materialize.public.t
-
-EOF
-
-query T multiline
-EXPLAIN RAW PLAN FOR SELECT TRY_CAST(s AS int4) FROM t
-----
-Project (#1)
- Map (try_cast[text_to_integer](#0{s}))
- Get materialize.public.t
-
-Target cluster: quickstart
-
-EOF
-
-query T multiline
-EXPLAIN OPTIMIZED PLAN AS VERBOSE TEXT FOR SELECT TRY_CAST('x' AS int4), TRY_CAST('7' AS int4)
-----
-Explained Query (fast path):
- Constant
- - (null, 7)
-
-Target cluster: quickstart
-
-EOF
-
-# The matrix.
-
-## boolean sources
-
-# boolean -> int4
-query TBB
-SELECT TRY_CAST(true AS int4)::text, TRY_CAST(true AS int4)::text IS NOT DISTINCT FROM CAST(true AS int4)::text, TRY_CAST(NULL::bool AS int4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(false AS int4)::text, TRY_CAST(false AS int4)::text IS NOT DISTINCT FROM CAST(false AS int4)::text, TRY_CAST(NULL::bool AS int4) IS NULL
-----
-0 true true
-
-# boolean -> int8
-query TBB
-SELECT TRY_CAST(true AS int8)::text, TRY_CAST(true AS int8)::text IS NOT DISTINCT FROM CAST(true AS int8)::text, TRY_CAST(NULL::bool AS int8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(false AS int8)::text, TRY_CAST(false AS int8)::text IS NOT DISTINCT FROM CAST(false AS int8)::text, TRY_CAST(NULL::bool AS int8) IS NULL
-----
-0 true true
-
-# boolean -> text
-query TBB
-SELECT TRY_CAST(true AS text)::text, TRY_CAST(true AS text)::text IS NOT DISTINCT FROM CAST(true AS text)::text, TRY_CAST(NULL::bool AS text) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST(false AS text)::text, TRY_CAST(false AS text)::text IS NOT DISTINCT FROM CAST(false AS text)::text, TRY_CAST(NULL::bool AS text) IS NULL
-----
-false true true
-
-## smallint sources
-
-# smallint -> int4
-query TBB
-SELECT TRY_CAST(1::int2 AS int4)::text, TRY_CAST(1::int2 AS int4)::text IS NOT DISTINCT FROM CAST(1::int2 AS int4)::text, TRY_CAST(NULL::int2 AS int4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS int4)::text, TRY_CAST(32767::int2 AS int4)::text IS NOT DISTINCT FROM CAST(32767::int2 AS int4)::text, TRY_CAST(NULL::int2 AS int4) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS int4)::text, TRY_CAST((-1)::int2 AS int4)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS int4)::text, TRY_CAST(NULL::int2 AS int4) IS NULL
-----
--1 true true
-
-# smallint -> int8
-query TBB
-SELECT TRY_CAST(1::int2 AS int8)::text, TRY_CAST(1::int2 AS int8)::text IS NOT DISTINCT FROM CAST(1::int2 AS int8)::text, TRY_CAST(NULL::int2 AS int8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS int8)::text, TRY_CAST(32767::int2 AS int8)::text IS NOT DISTINCT FROM CAST(32767::int2 AS int8)::text, TRY_CAST(NULL::int2 AS int8) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS int8)::text, TRY_CAST((-1)::int2 AS int8)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS int8)::text, TRY_CAST(NULL::int2 AS int8) IS NULL
-----
--1 true true
-
-# smallint -> uint2
-query TBB
-SELECT TRY_CAST(1::int2 AS uint2)::text, TRY_CAST(1::int2 AS uint2)::text IS NOT DISTINCT FROM CAST(1::int2 AS uint2)::text, TRY_CAST(NULL::int2 AS uint2) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS uint2)::text, TRY_CAST(32767::int2 AS uint2)::text IS NOT DISTINCT FROM CAST(32767::int2 AS uint2)::text, TRY_CAST(NULL::int2 AS uint2) IS NULL
-----
-32767 true true
-
-statement error
-SELECT CAST((-1)::int2 AS uint2)
-
-query T
-SELECT TRY_CAST((-1)::int2 AS uint2)::text
-----
-NULL
-
-# smallint -> uint4
-query TBB
-SELECT TRY_CAST(1::int2 AS uint4)::text, TRY_CAST(1::int2 AS uint4)::text IS NOT DISTINCT FROM CAST(1::int2 AS uint4)::text, TRY_CAST(NULL::int2 AS uint4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS uint4)::text, TRY_CAST(32767::int2 AS uint4)::text IS NOT DISTINCT FROM CAST(32767::int2 AS uint4)::text, TRY_CAST(NULL::int2 AS uint4) IS NULL
-----
-32767 true true
-
-statement error
-SELECT CAST((-1)::int2 AS uint4)
-
-query T
-SELECT TRY_CAST((-1)::int2 AS uint4)::text
-----
-NULL
-
-# smallint -> uint8
-query TBB
-SELECT TRY_CAST(1::int2 AS uint8)::text, TRY_CAST(1::int2 AS uint8)::text IS NOT DISTINCT FROM CAST(1::int2 AS uint8)::text, TRY_CAST(NULL::int2 AS uint8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS uint8)::text, TRY_CAST(32767::int2 AS uint8)::text IS NOT DISTINCT FROM CAST(32767::int2 AS uint8)::text, TRY_CAST(NULL::int2 AS uint8) IS NULL
-----
-32767 true true
-
-statement error
-SELECT CAST((-1)::int2 AS uint8)
-
-query T
-SELECT TRY_CAST((-1)::int2 AS uint8)::text
-----
-NULL
-
-# smallint -> float4
-query TBB
-SELECT TRY_CAST(1::int2 AS float4)::text, TRY_CAST(1::int2 AS float4)::text IS NOT DISTINCT FROM CAST(1::int2 AS float4)::text, TRY_CAST(NULL::int2 AS float4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS float4)::text, TRY_CAST(32767::int2 AS float4)::text IS NOT DISTINCT FROM CAST(32767::int2 AS float4)::text, TRY_CAST(NULL::int2 AS float4) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS float4)::text, TRY_CAST((-1)::int2 AS float4)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS float4)::text, TRY_CAST(NULL::int2 AS float4) IS NULL
-----
--1 true true
-
-# smallint -> float8
-query TBB
-SELECT TRY_CAST(1::int2 AS float8)::text, TRY_CAST(1::int2 AS float8)::text IS NOT DISTINCT FROM CAST(1::int2 AS float8)::text, TRY_CAST(NULL::int2 AS float8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS float8)::text, TRY_CAST(32767::int2 AS float8)::text IS NOT DISTINCT FROM CAST(32767::int2 AS float8)::text, TRY_CAST(NULL::int2 AS float8) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS float8)::text, TRY_CAST((-1)::int2 AS float8)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS float8)::text, TRY_CAST(NULL::int2 AS float8) IS NULL
-----
--1 true true
-
-# smallint -> numeric
-query TBB
-SELECT TRY_CAST(1::int2 AS numeric)::text, TRY_CAST(1::int2 AS numeric)::text IS NOT DISTINCT FROM CAST(1::int2 AS numeric)::text, TRY_CAST(NULL::int2 AS numeric) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS numeric)::text, TRY_CAST(32767::int2 AS numeric)::text IS NOT DISTINCT FROM CAST(32767::int2 AS numeric)::text, TRY_CAST(NULL::int2 AS numeric) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS numeric)::text, TRY_CAST((-1)::int2 AS numeric)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS numeric)::text, TRY_CAST(NULL::int2 AS numeric) IS NULL
-----
--1 true true
-
-# smallint -> oid
-query TBB
-SELECT TRY_CAST(1::int2 AS oid)::text, TRY_CAST(1::int2 AS oid)::text IS NOT DISTINCT FROM CAST(1::int2 AS oid)::text, TRY_CAST(NULL::int2 AS oid) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS oid)::text, TRY_CAST(32767::int2 AS oid)::text IS NOT DISTINCT FROM CAST(32767::int2 AS oid)::text, TRY_CAST(NULL::int2 AS oid) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS oid)::text, TRY_CAST((-1)::int2 AS oid)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS oid)::text, TRY_CAST(NULL::int2 AS oid) IS NULL
-----
-4294967295 true true
-
-# smallint -> regclass
-query TBB
-SELECT TRY_CAST(1::int2 AS regclass)::text, TRY_CAST(1::int2 AS regclass)::text IS NOT DISTINCT FROM CAST(1::int2 AS regclass)::text, TRY_CAST(NULL::int2 AS regclass) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS regclass)::text, TRY_CAST(32767::int2 AS regclass)::text IS NOT DISTINCT FROM CAST(32767::int2 AS regclass)::text, TRY_CAST(NULL::int2 AS regclass) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS regclass)::text, TRY_CAST((-1)::int2 AS regclass)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS regclass)::text, TRY_CAST(NULL::int2 AS regclass) IS NULL
-----
-4294967295 true true
-
-# smallint -> regproc
-query TBB
-SELECT TRY_CAST(1::int2 AS regproc)::text, TRY_CAST(1::int2 AS regproc)::text IS NOT DISTINCT FROM CAST(1::int2 AS regproc)::text, TRY_CAST(NULL::int2 AS regproc) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS regproc)::text, TRY_CAST(32767::int2 AS regproc)::text IS NOT DISTINCT FROM CAST(32767::int2 AS regproc)::text, TRY_CAST(NULL::int2 AS regproc) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS regproc)::text, TRY_CAST((-1)::int2 AS regproc)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS regproc)::text, TRY_CAST(NULL::int2 AS regproc) IS NULL
-----
-4294967295 true true
-
-# smallint -> regtype
-query TBB
-SELECT TRY_CAST(1::int2 AS regtype)::text, TRY_CAST(1::int2 AS regtype)::text IS NOT DISTINCT FROM CAST(1::int2 AS regtype)::text, TRY_CAST(NULL::int2 AS regtype) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS regtype)::text, TRY_CAST(32767::int2 AS regtype)::text IS NOT DISTINCT FROM CAST(32767::int2 AS regtype)::text, TRY_CAST(NULL::int2 AS regtype) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS regtype)::text, TRY_CAST((-1)::int2 AS regtype)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS regtype)::text, TRY_CAST(NULL::int2 AS regtype) IS NULL
-----
-4294967295 true true
-
-# smallint -> text
-query TBB
-SELECT TRY_CAST(1::int2 AS text)::text, TRY_CAST(1::int2 AS text)::text IS NOT DISTINCT FROM CAST(1::int2 AS text)::text, TRY_CAST(NULL::int2 AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS text)::text, TRY_CAST(32767::int2 AS text)::text IS NOT DISTINCT FROM CAST(32767::int2 AS text)::text, TRY_CAST(NULL::int2 AS text) IS NULL
-----
-32767 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS text)::text, TRY_CAST((-1)::int2 AS text)::text IS NOT DISTINCT FROM CAST((-1)::int2 AS text)::text, TRY_CAST(NULL::int2 AS text) IS NULL
-----
--1 true true
-
-## integer sources
-
-# integer -> bool
-query TBB
-SELECT TRY_CAST(1 AS bool)::text, TRY_CAST(1 AS bool)::text IS NOT DISTINCT FROM CAST(1 AS bool)::text, TRY_CAST(NULL::int4 AS bool) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS bool)::text, TRY_CAST(2147483647 AS bool)::text IS NOT DISTINCT FROM CAST(2147483647 AS bool)::text, TRY_CAST(NULL::int4 AS bool) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST(-1 AS bool)::text, TRY_CAST(-1 AS bool)::text IS NOT DISTINCT FROM CAST(-1 AS bool)::text, TRY_CAST(NULL::int4 AS bool) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST(100000 AS bool)::text, TRY_CAST(100000 AS bool)::text IS NOT DISTINCT FROM CAST(100000 AS bool)::text, TRY_CAST(NULL::int4 AS bool) IS NULL
-----
-true true true
-
-# integer -> oid
-query TBB
-SELECT TRY_CAST(1 AS oid)::text, TRY_CAST(1 AS oid)::text IS NOT DISTINCT FROM CAST(1 AS oid)::text, TRY_CAST(NULL::int4 AS oid) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS oid)::text, TRY_CAST(2147483647 AS oid)::text IS NOT DISTINCT FROM CAST(2147483647 AS oid)::text, TRY_CAST(NULL::int4 AS oid) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS oid)::text, TRY_CAST(-1 AS oid)::text IS NOT DISTINCT FROM CAST(-1 AS oid)::text, TRY_CAST(NULL::int4 AS oid) IS NULL
-----
-4294967295 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS oid)::text, TRY_CAST(100000 AS oid)::text IS NOT DISTINCT FROM CAST(100000 AS oid)::text, TRY_CAST(NULL::int4 AS oid) IS NULL
-----
-100000 true true
-
-# integer -> regclass
-query TBB
-SELECT TRY_CAST(1 AS regclass)::text, TRY_CAST(1 AS regclass)::text IS NOT DISTINCT FROM CAST(1 AS regclass)::text, TRY_CAST(NULL::int4 AS regclass) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS regclass)::text, TRY_CAST(2147483647 AS regclass)::text IS NOT DISTINCT FROM CAST(2147483647 AS regclass)::text, TRY_CAST(NULL::int4 AS regclass) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS regclass)::text, TRY_CAST(-1 AS regclass)::text IS NOT DISTINCT FROM CAST(-1 AS regclass)::text, TRY_CAST(NULL::int4 AS regclass) IS NULL
-----
-4294967295 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS regclass)::text, TRY_CAST(100000 AS regclass)::text IS NOT DISTINCT FROM CAST(100000 AS regclass)::text, TRY_CAST(NULL::int4 AS regclass) IS NULL
-----
-100000 true true
-
-# integer -> regproc
-query TBB
-SELECT TRY_CAST(1 AS regproc)::text, TRY_CAST(1 AS regproc)::text IS NOT DISTINCT FROM CAST(1 AS regproc)::text, TRY_CAST(NULL::int4 AS regproc) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS regproc)::text, TRY_CAST(2147483647 AS regproc)::text IS NOT DISTINCT FROM CAST(2147483647 AS regproc)::text, TRY_CAST(NULL::int4 AS regproc) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS regproc)::text, TRY_CAST(-1 AS regproc)::text IS NOT DISTINCT FROM CAST(-1 AS regproc)::text, TRY_CAST(NULL::int4 AS regproc) IS NULL
-----
-4294967295 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS regproc)::text, TRY_CAST(100000 AS regproc)::text IS NOT DISTINCT FROM CAST(100000 AS regproc)::text, TRY_CAST(NULL::int4 AS regproc) IS NULL
-----
-100000 true true
-
-# integer -> regtype
-query TBB
-SELECT TRY_CAST(1 AS regtype)::text, TRY_CAST(1 AS regtype)::text IS NOT DISTINCT FROM CAST(1 AS regtype)::text, TRY_CAST(NULL::int4 AS regtype) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS regtype)::text, TRY_CAST(2147483647 AS regtype)::text IS NOT DISTINCT FROM CAST(2147483647 AS regtype)::text, TRY_CAST(NULL::int4 AS regtype) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS regtype)::text, TRY_CAST(-1 AS regtype)::text IS NOT DISTINCT FROM CAST(-1 AS regtype)::text, TRY_CAST(NULL::int4 AS regtype) IS NULL
-----
-4294967295 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS regtype)::text, TRY_CAST(100000 AS regtype)::text IS NOT DISTINCT FROM CAST(100000 AS regtype)::text, TRY_CAST(NULL::int4 AS regtype) IS NULL
-----
-100000 true true
-
-# integer -> "char"
-query TBB
-SELECT TRY_CAST(1 AS "char")::text, TRY_CAST(1 AS "char")::text IS NOT DISTINCT FROM CAST(1 AS "char")::text, TRY_CAST(NULL::int4 AS "char") IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS "char")::text, TRY_CAST(2147483647 AS "char")::text IS NOT DISTINCT FROM CAST(2147483647 AS "char")::text, TRY_CAST(NULL::int4 AS "char") IS NULL
-----
-2 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS "char")::text, TRY_CAST(-1 AS "char")::text IS NOT DISTINCT FROM CAST(-1 AS "char")::text, TRY_CAST(NULL::int4 AS "char") IS NULL
-----
-- true true
-
-query TBB
-SELECT TRY_CAST(100000 AS "char")::text, TRY_CAST(100000 AS "char")::text IS NOT DISTINCT FROM CAST(100000 AS "char")::text, TRY_CAST(NULL::int4 AS "char") IS NULL
-----
-1 true true
-
-# integer -> int2
-query TBB
-SELECT TRY_CAST(1 AS int2)::text, TRY_CAST(1 AS int2)::text IS NOT DISTINCT FROM CAST(1 AS int2)::text, TRY_CAST(NULL::int4 AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(2147483647 AS int2)
-
-query T
-SELECT TRY_CAST(2147483647 AS int2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(-1 AS int2)::text, TRY_CAST(-1 AS int2)::text IS NOT DISTINCT FROM CAST(-1 AS int2)::text, TRY_CAST(NULL::int4 AS int2) IS NULL
-----
--1 true true
-
-statement error
-SELECT CAST(100000 AS int2)
-
-query T
-SELECT TRY_CAST(100000 AS int2)::text
-----
-NULL
-
-# integer -> int8
-query TBB
-SELECT TRY_CAST(1 AS int8)::text, TRY_CAST(1 AS int8)::text IS NOT DISTINCT FROM CAST(1 AS int8)::text, TRY_CAST(NULL::int4 AS int8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS int8)::text, TRY_CAST(2147483647 AS int8)::text IS NOT DISTINCT FROM CAST(2147483647 AS int8)::text, TRY_CAST(NULL::int4 AS int8) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS int8)::text, TRY_CAST(-1 AS int8)::text IS NOT DISTINCT FROM CAST(-1 AS int8)::text, TRY_CAST(NULL::int4 AS int8) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS int8)::text, TRY_CAST(100000 AS int8)::text IS NOT DISTINCT FROM CAST(100000 AS int8)::text, TRY_CAST(NULL::int4 AS int8) IS NULL
-----
-100000 true true
-
-# integer -> uint2
-query TBB
-SELECT TRY_CAST(1 AS uint2)::text, TRY_CAST(1 AS uint2)::text IS NOT DISTINCT FROM CAST(1 AS uint2)::text, TRY_CAST(NULL::int4 AS uint2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(2147483647 AS uint2)
-
-query T
-SELECT TRY_CAST(2147483647 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST(-1 AS uint2)
-
-query T
-SELECT TRY_CAST(-1 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST(100000 AS uint2)
-
-query T
-SELECT TRY_CAST(100000 AS uint2)::text
-----
-NULL
-
-# integer -> uint4
-query TBB
-SELECT TRY_CAST(1 AS uint4)::text, TRY_CAST(1 AS uint4)::text IS NOT DISTINCT FROM CAST(1 AS uint4)::text, TRY_CAST(NULL::int4 AS uint4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS uint4)::text, TRY_CAST(2147483647 AS uint4)::text IS NOT DISTINCT FROM CAST(2147483647 AS uint4)::text, TRY_CAST(NULL::int4 AS uint4) IS NULL
-----
-2147483647 true true
-
-statement error
-SELECT CAST(-1 AS uint4)
-
-query T
-SELECT TRY_CAST(-1 AS uint4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(100000 AS uint4)::text, TRY_CAST(100000 AS uint4)::text IS NOT DISTINCT FROM CAST(100000 AS uint4)::text, TRY_CAST(NULL::int4 AS uint4) IS NULL
-----
-100000 true true
-
-# integer -> uint8
-query TBB
-SELECT TRY_CAST(1 AS uint8)::text, TRY_CAST(1 AS uint8)::text IS NOT DISTINCT FROM CAST(1 AS uint8)::text, TRY_CAST(NULL::int4 AS uint8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS uint8)::text, TRY_CAST(2147483647 AS uint8)::text IS NOT DISTINCT FROM CAST(2147483647 AS uint8)::text, TRY_CAST(NULL::int4 AS uint8) IS NULL
-----
-2147483647 true true
-
-statement error
-SELECT CAST(-1 AS uint8)
-
-query T
-SELECT TRY_CAST(-1 AS uint8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(100000 AS uint8)::text, TRY_CAST(100000 AS uint8)::text IS NOT DISTINCT FROM CAST(100000 AS uint8)::text, TRY_CAST(NULL::int4 AS uint8) IS NULL
-----
-100000 true true
-
-# integer -> float4
-query TBB
-SELECT TRY_CAST(1 AS float4)::text, TRY_CAST(1 AS float4)::text IS NOT DISTINCT FROM CAST(1 AS float4)::text, TRY_CAST(NULL::int4 AS float4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS float4)::text, TRY_CAST(2147483647 AS float4)::text IS NOT DISTINCT FROM CAST(2147483647 AS float4)::text, TRY_CAST(NULL::int4 AS float4) IS NULL
-----
-2147483600 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS float4)::text, TRY_CAST(-1 AS float4)::text IS NOT DISTINCT FROM CAST(-1 AS float4)::text, TRY_CAST(NULL::int4 AS float4) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS float4)::text, TRY_CAST(100000 AS float4)::text IS NOT DISTINCT FROM CAST(100000 AS float4)::text, TRY_CAST(NULL::int4 AS float4) IS NULL
-----
-100000 true true
-
-# integer -> float8
-query TBB
-SELECT TRY_CAST(1 AS float8)::text, TRY_CAST(1 AS float8)::text IS NOT DISTINCT FROM CAST(1 AS float8)::text, TRY_CAST(NULL::int4 AS float8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS float8)::text, TRY_CAST(2147483647 AS float8)::text IS NOT DISTINCT FROM CAST(2147483647 AS float8)::text, TRY_CAST(NULL::int4 AS float8) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS float8)::text, TRY_CAST(-1 AS float8)::text IS NOT DISTINCT FROM CAST(-1 AS float8)::text, TRY_CAST(NULL::int4 AS float8) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS float8)::text, TRY_CAST(100000 AS float8)::text IS NOT DISTINCT FROM CAST(100000 AS float8)::text, TRY_CAST(NULL::int4 AS float8) IS NULL
-----
-100000 true true
-
-# integer -> numeric
-query TBB
-SELECT TRY_CAST(1 AS numeric)::text, TRY_CAST(1 AS numeric)::text IS NOT DISTINCT FROM CAST(1 AS numeric)::text, TRY_CAST(NULL::int4 AS numeric) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS numeric)::text, TRY_CAST(2147483647 AS numeric)::text IS NOT DISTINCT FROM CAST(2147483647 AS numeric)::text, TRY_CAST(NULL::int4 AS numeric) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS numeric)::text, TRY_CAST(-1 AS numeric)::text IS NOT DISTINCT FROM CAST(-1 AS numeric)::text, TRY_CAST(NULL::int4 AS numeric) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS numeric)::text, TRY_CAST(100000 AS numeric)::text IS NOT DISTINCT FROM CAST(100000 AS numeric)::text, TRY_CAST(NULL::int4 AS numeric) IS NULL
-----
-100000 true true
-
-# integer -> text
-query TBB
-SELECT TRY_CAST(1 AS text)::text, TRY_CAST(1 AS text)::text IS NOT DISTINCT FROM CAST(1 AS text)::text, TRY_CAST(NULL::int4 AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS text)::text, TRY_CAST(2147483647 AS text)::text IS NOT DISTINCT FROM CAST(2147483647 AS text)::text, TRY_CAST(NULL::int4 AS text) IS NULL
-----
-2147483647 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS text)::text, TRY_CAST(-1 AS text)::text IS NOT DISTINCT FROM CAST(-1 AS text)::text, TRY_CAST(NULL::int4 AS text) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS text)::text, TRY_CAST(100000 AS text)::text IS NOT DISTINCT FROM CAST(100000 AS text)::text, TRY_CAST(NULL::int4 AS text) IS NULL
-----
-100000 true true
-
-# integer -> mz_timestamp
-query TBB
-SELECT TRY_CAST(1 AS mz_timestamp)::text, TRY_CAST(1 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(1 AS mz_timestamp)::text, TRY_CAST(NULL::int4 AS mz_timestamp) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS mz_timestamp)::text, TRY_CAST(2147483647 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(2147483647 AS mz_timestamp)::text, TRY_CAST(NULL::int4 AS mz_timestamp) IS NULL
-----
-2147483647 true true
-
-statement error
-SELECT CAST(-1 AS mz_timestamp)
-
-query T
-SELECT TRY_CAST(-1 AS mz_timestamp)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(100000 AS mz_timestamp)::text, TRY_CAST(100000 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(100000 AS mz_timestamp)::text, TRY_CAST(NULL::int4 AS mz_timestamp) IS NULL
-----
-100000 true true
-
-## bigint sources
-
-# bigint -> bool
-query TBB
-SELECT TRY_CAST(1::int8 AS bool)::text, TRY_CAST(1::int8 AS bool)::text IS NOT DISTINCT FROM CAST(1::int8 AS bool)::text, TRY_CAST(NULL::int8 AS bool) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS bool)::text, TRY_CAST(9223372036854775807::int8 AS bool)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS bool)::text, TRY_CAST(NULL::int8 AS bool) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS bool)::text, TRY_CAST((-1)::int8 AS bool)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS bool)::text, TRY_CAST(NULL::int8 AS bool) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS bool)::text, TRY_CAST(3000000000::int8 AS bool)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS bool)::text, TRY_CAST(NULL::int8 AS bool) IS NULL
-----
-true true true
-
-# bigint -> int2
-query TBB
-SELECT TRY_CAST(1::int8 AS int2)::text, TRY_CAST(1::int8 AS int2)::text IS NOT DISTINCT FROM CAST(1::int8 AS int2)::text, TRY_CAST(NULL::int8 AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS int2)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS int2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS int2)::text, TRY_CAST((-1)::int8 AS int2)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS int2)::text, TRY_CAST(NULL::int8 AS int2) IS NULL
-----
--1 true true
-
-statement error
-SELECT CAST(3000000000::int8 AS int2)
-
-query T
-SELECT TRY_CAST(3000000000::int8 AS int2)::text
-----
-NULL
-
-# bigint -> int4
-query TBB
-SELECT TRY_CAST(1::int8 AS int4)::text, TRY_CAST(1::int8 AS int4)::text IS NOT DISTINCT FROM CAST(1::int8 AS int4)::text, TRY_CAST(NULL::int8 AS int4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS int4)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS int4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS int4)::text, TRY_CAST((-1)::int8 AS int4)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS int4)::text, TRY_CAST(NULL::int8 AS int4) IS NULL
-----
--1 true true
-
-statement error
-SELECT CAST(3000000000::int8 AS int4)
-
-query T
-SELECT TRY_CAST(3000000000::int8 AS int4)::text
-----
-NULL
-
-# bigint -> uint2
-query TBB
-SELECT TRY_CAST(1::int8 AS uint2)::text, TRY_CAST(1::int8 AS uint2)::text IS NOT DISTINCT FROM CAST(1::int8 AS uint2)::text, TRY_CAST(NULL::int8 AS uint2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS uint2)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1)::int8 AS uint2)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST(3000000000::int8 AS uint2)
-
-query T
-SELECT TRY_CAST(3000000000::int8 AS uint2)::text
-----
-NULL
-
-# bigint -> uint4
-query TBB
-SELECT TRY_CAST(1::int8 AS uint4)::text, TRY_CAST(1::int8 AS uint4)::text IS NOT DISTINCT FROM CAST(1::int8 AS uint4)::text, TRY_CAST(NULL::int8 AS uint4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS uint4)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1)::int8 AS uint4)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS uint4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS uint4)::text, TRY_CAST(3000000000::int8 AS uint4)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS uint4)::text, TRY_CAST(NULL::int8 AS uint4) IS NULL
-----
-3000000000 true true
-
-# bigint -> uint8
-query TBB
-SELECT TRY_CAST(1::int8 AS uint8)::text, TRY_CAST(1::int8 AS uint8)::text IS NOT DISTINCT FROM CAST(1::int8 AS uint8)::text, TRY_CAST(NULL::int8 AS uint8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS uint8)::text, TRY_CAST(9223372036854775807::int8 AS uint8)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS uint8)::text, TRY_CAST(NULL::int8 AS uint8) IS NULL
-----
-9223372036854775807 true true
-
-statement error
-SELECT CAST((-1)::int8 AS uint8)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS uint8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS uint8)::text, TRY_CAST(3000000000::int8 AS uint8)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS uint8)::text, TRY_CAST(NULL::int8 AS uint8) IS NULL
-----
-3000000000 true true
-
-# bigint -> numeric
-query TBB
-SELECT TRY_CAST(1::int8 AS numeric)::text, TRY_CAST(1::int8 AS numeric)::text IS NOT DISTINCT FROM CAST(1::int8 AS numeric)::text, TRY_CAST(NULL::int8 AS numeric) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS numeric)::text, TRY_CAST(9223372036854775807::int8 AS numeric)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS numeric)::text, TRY_CAST(NULL::int8 AS numeric) IS NULL
-----
-9223372036854775807 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS numeric)::text, TRY_CAST((-1)::int8 AS numeric)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS numeric)::text, TRY_CAST(NULL::int8 AS numeric) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS numeric)::text, TRY_CAST(3000000000::int8 AS numeric)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS numeric)::text, TRY_CAST(NULL::int8 AS numeric) IS NULL
-----
-3000000000 true true
-
-# bigint -> float4
-query TBB
-SELECT TRY_CAST(1::int8 AS float4)::text, TRY_CAST(1::int8 AS float4)::text IS NOT DISTINCT FROM CAST(1::int8 AS float4)::text, TRY_CAST(NULL::int8 AS float4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS float4)::text, TRY_CAST(9223372036854775807::int8 AS float4)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS float4)::text, TRY_CAST(NULL::int8 AS float4) IS NULL
-----
-9.223372e+18 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS float4)::text, TRY_CAST((-1)::int8 AS float4)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS float4)::text, TRY_CAST(NULL::int8 AS float4) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS float4)::text, TRY_CAST(3000000000::int8 AS float4)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS float4)::text, TRY_CAST(NULL::int8 AS float4) IS NULL
-----
-3000000000 true true
-
-# bigint -> float8
-query TBB
-SELECT TRY_CAST(1::int8 AS float8)::text, TRY_CAST(1::int8 AS float8)::text IS NOT DISTINCT FROM CAST(1::int8 AS float8)::text, TRY_CAST(NULL::int8 AS float8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS float8)::text, TRY_CAST(9223372036854775807::int8 AS float8)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS float8)::text, TRY_CAST(NULL::int8 AS float8) IS NULL
-----
-9.223372036854776e+18 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS float8)::text, TRY_CAST((-1)::int8 AS float8)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS float8)::text, TRY_CAST(NULL::int8 AS float8) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS float8)::text, TRY_CAST(3000000000::int8 AS float8)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS float8)::text, TRY_CAST(NULL::int8 AS float8) IS NULL
-----
-3000000000 true true
-
-# bigint -> oid
-query TBB
-SELECT TRY_CAST(1::int8 AS oid)::text, TRY_CAST(1::int8 AS oid)::text IS NOT DISTINCT FROM CAST(1::int8 AS oid)::text, TRY_CAST(NULL::int8 AS oid) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS oid)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS oid)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1)::int8 AS oid)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS oid)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS oid)::text, TRY_CAST(3000000000::int8 AS oid)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS oid)::text, TRY_CAST(NULL::int8 AS oid) IS NULL
-----
-3000000000 true true
-
-# bigint -> regclass
-query TBB
-SELECT TRY_CAST(1::int8 AS regclass)::text, TRY_CAST(1::int8 AS regclass)::text IS NOT DISTINCT FROM CAST(1::int8 AS regclass)::text, TRY_CAST(NULL::int8 AS regclass) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS regclass)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS regclass)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1)::int8 AS regclass)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS regclass)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS regclass)::text, TRY_CAST(3000000000::int8 AS regclass)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS regclass)::text, TRY_CAST(NULL::int8 AS regclass) IS NULL
-----
-3000000000 true true
-
-# bigint -> regproc
-query TBB
-SELECT TRY_CAST(1::int8 AS regproc)::text, TRY_CAST(1::int8 AS regproc)::text IS NOT DISTINCT FROM CAST(1::int8 AS regproc)::text, TRY_CAST(NULL::int8 AS regproc) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS regproc)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS regproc)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1)::int8 AS regproc)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS regproc)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS regproc)::text, TRY_CAST(3000000000::int8 AS regproc)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS regproc)::text, TRY_CAST(NULL::int8 AS regproc) IS NULL
-----
-3000000000 true true
-
-# bigint -> regtype
-query TBB
-SELECT TRY_CAST(1::int8 AS regtype)::text, TRY_CAST(1::int8 AS regtype)::text IS NOT DISTINCT FROM CAST(1::int8 AS regtype)::text, TRY_CAST(NULL::int8 AS regtype) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(9223372036854775807::int8 AS regtype)
-
-query T
-SELECT TRY_CAST(9223372036854775807::int8 AS regtype)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1)::int8 AS regtype)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS regtype)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS regtype)::text, TRY_CAST(3000000000::int8 AS regtype)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS regtype)::text, TRY_CAST(NULL::int8 AS regtype) IS NULL
-----
-3000000000 true true
-
-# bigint -> text
-query TBB
-SELECT TRY_CAST(1::int8 AS text)::text, TRY_CAST(1::int8 AS text)::text IS NOT DISTINCT FROM CAST(1::int8 AS text)::text, TRY_CAST(NULL::int8 AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS text)::text, TRY_CAST(9223372036854775807::int8 AS text)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS text)::text, TRY_CAST(NULL::int8 AS text) IS NULL
-----
-9223372036854775807 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS text)::text, TRY_CAST((-1)::int8 AS text)::text IS NOT DISTINCT FROM CAST((-1)::int8 AS text)::text, TRY_CAST(NULL::int8 AS text) IS NULL
-----
--1 true true
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS text)::text, TRY_CAST(3000000000::int8 AS text)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS text)::text, TRY_CAST(NULL::int8 AS text) IS NULL
-----
-3000000000 true true
-
-# bigint -> mz_timestamp
-query TBB
-SELECT TRY_CAST(1::int8 AS mz_timestamp)::text, TRY_CAST(1::int8 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(1::int8 AS mz_timestamp)::text, TRY_CAST(NULL::int8 AS mz_timestamp) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS mz_timestamp)::text, TRY_CAST(9223372036854775807::int8 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS mz_timestamp)::text, TRY_CAST(NULL::int8 AS mz_timestamp) IS NULL
-----
-9223372036854775807 true true
-
-statement error
-SELECT CAST((-1)::int8 AS mz_timestamp)
-
-query T
-SELECT TRY_CAST((-1)::int8 AS mz_timestamp)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS mz_timestamp)::text, TRY_CAST(3000000000::int8 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS mz_timestamp)::text, TRY_CAST(NULL::int8 AS mz_timestamp) IS NULL
-----
-3000000000 true true
-
-## uint2 sources
-
-# uint2 -> uint4
-query TBB
-SELECT TRY_CAST(1::uint2 AS uint4)::text, TRY_CAST(1::uint2 AS uint4)::text IS NOT DISTINCT FROM CAST(1::uint2 AS uint4)::text, TRY_CAST(NULL::uint2 AS uint4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS uint4)::text, TRY_CAST(65535::uint2 AS uint4)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS uint4)::text, TRY_CAST(NULL::uint2 AS uint4) IS NULL
-----
-65535 true true
-
-# uint2 -> uint8
-query TBB
-SELECT TRY_CAST(1::uint2 AS uint8)::text, TRY_CAST(1::uint2 AS uint8)::text IS NOT DISTINCT FROM CAST(1::uint2 AS uint8)::text, TRY_CAST(NULL::uint2 AS uint8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS uint8)::text, TRY_CAST(65535::uint2 AS uint8)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS uint8)::text, TRY_CAST(NULL::uint2 AS uint8) IS NULL
-----
-65535 true true
-
-# uint2 -> int2
-query TBB
-SELECT TRY_CAST(1::uint2 AS int2)::text, TRY_CAST(1::uint2 AS int2)::text IS NOT DISTINCT FROM CAST(1::uint2 AS int2)::text, TRY_CAST(NULL::uint2 AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(65535::uint2 AS int2)
-
-query T
-SELECT TRY_CAST(65535::uint2 AS int2)::text
-----
-NULL
-
-# uint2 -> int4
-query TBB
-SELECT TRY_CAST(1::uint2 AS int4)::text, TRY_CAST(1::uint2 AS int4)::text IS NOT DISTINCT FROM CAST(1::uint2 AS int4)::text, TRY_CAST(NULL::uint2 AS int4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS int4)::text, TRY_CAST(65535::uint2 AS int4)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS int4)::text, TRY_CAST(NULL::uint2 AS int4) IS NULL
-----
-65535 true true
-
-# uint2 -> int8
-query TBB
-SELECT TRY_CAST(1::uint2 AS int8)::text, TRY_CAST(1::uint2 AS int8)::text IS NOT DISTINCT FROM CAST(1::uint2 AS int8)::text, TRY_CAST(NULL::uint2 AS int8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS int8)::text, TRY_CAST(65535::uint2 AS int8)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS int8)::text, TRY_CAST(NULL::uint2 AS int8) IS NULL
-----
-65535 true true
-
-# uint2 -> numeric
-query TBB
-SELECT TRY_CAST(1::uint2 AS numeric)::text, TRY_CAST(1::uint2 AS numeric)::text IS NOT DISTINCT FROM CAST(1::uint2 AS numeric)::text, TRY_CAST(NULL::uint2 AS numeric) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS numeric)::text, TRY_CAST(65535::uint2 AS numeric)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS numeric)::text, TRY_CAST(NULL::uint2 AS numeric) IS NULL
-----
-65535 true true
-
-# uint2 -> float4
-query TBB
-SELECT TRY_CAST(1::uint2 AS float4)::text, TRY_CAST(1::uint2 AS float4)::text IS NOT DISTINCT FROM CAST(1::uint2 AS float4)::text, TRY_CAST(NULL::uint2 AS float4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS float4)::text, TRY_CAST(65535::uint2 AS float4)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS float4)::text, TRY_CAST(NULL::uint2 AS float4) IS NULL
-----
-65535 true true
-
-# uint2 -> float8
-query TBB
-SELECT TRY_CAST(1::uint2 AS float8)::text, TRY_CAST(1::uint2 AS float8)::text IS NOT DISTINCT FROM CAST(1::uint2 AS float8)::text, TRY_CAST(NULL::uint2 AS float8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS float8)::text, TRY_CAST(65535::uint2 AS float8)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS float8)::text, TRY_CAST(NULL::uint2 AS float8) IS NULL
-----
-65535 true true
-
-# uint2 -> text
-query TBB
-SELECT TRY_CAST(1::uint2 AS text)::text, TRY_CAST(1::uint2 AS text)::text IS NOT DISTINCT FROM CAST(1::uint2 AS text)::text, TRY_CAST(NULL::uint2 AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS text)::text, TRY_CAST(65535::uint2 AS text)::text IS NOT DISTINCT FROM CAST(65535::uint2 AS text)::text, TRY_CAST(NULL::uint2 AS text) IS NULL
-----
-65535 true true
-
-## uint4 sources
-
-# uint4 -> uint2
-query TBB
-SELECT TRY_CAST(1::uint4 AS uint2)::text, TRY_CAST(1::uint4 AS uint2)::text IS NOT DISTINCT FROM CAST(1::uint4 AS uint2)::text, TRY_CAST(NULL::uint4 AS uint2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(4294967295::uint4 AS uint2)
-
-query T
-SELECT TRY_CAST(4294967295::uint4 AS uint2)::text
-----
-NULL
-
-# uint4 -> uint8
-query TBB
-SELECT TRY_CAST(1::uint4 AS uint8)::text, TRY_CAST(1::uint4 AS uint8)::text IS NOT DISTINCT FROM CAST(1::uint4 AS uint8)::text, TRY_CAST(NULL::uint4 AS uint8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS uint8)::text, TRY_CAST(4294967295::uint4 AS uint8)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS uint8)::text, TRY_CAST(NULL::uint4 AS uint8) IS NULL
-----
-4294967295 true true
-
-# uint4 -> int2
-query TBB
-SELECT TRY_CAST(1::uint4 AS int2)::text, TRY_CAST(1::uint4 AS int2)::text IS NOT DISTINCT FROM CAST(1::uint4 AS int2)::text, TRY_CAST(NULL::uint4 AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(4294967295::uint4 AS int2)
-
-query T
-SELECT TRY_CAST(4294967295::uint4 AS int2)::text
-----
-NULL
-
-# uint4 -> int4
-query TBB
-SELECT TRY_CAST(1::uint4 AS int4)::text, TRY_CAST(1::uint4 AS int4)::text IS NOT DISTINCT FROM CAST(1::uint4 AS int4)::text, TRY_CAST(NULL::uint4 AS int4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(4294967295::uint4 AS int4)
-
-query T
-SELECT TRY_CAST(4294967295::uint4 AS int4)::text
-----
-NULL
-
-# uint4 -> int8
-query TBB
-SELECT TRY_CAST(1::uint4 AS int8)::text, TRY_CAST(1::uint4 AS int8)::text IS NOT DISTINCT FROM CAST(1::uint4 AS int8)::text, TRY_CAST(NULL::uint4 AS int8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS int8)::text, TRY_CAST(4294967295::uint4 AS int8)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS int8)::text, TRY_CAST(NULL::uint4 AS int8) IS NULL
-----
-4294967295 true true
-
-# uint4 -> numeric
-query TBB
-SELECT TRY_CAST(1::uint4 AS numeric)::text, TRY_CAST(1::uint4 AS numeric)::text IS NOT DISTINCT FROM CAST(1::uint4 AS numeric)::text, TRY_CAST(NULL::uint4 AS numeric) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS numeric)::text, TRY_CAST(4294967295::uint4 AS numeric)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS numeric)::text, TRY_CAST(NULL::uint4 AS numeric) IS NULL
-----
-4294967295 true true
-
-# uint4 -> float4
-query TBB
-SELECT TRY_CAST(1::uint4 AS float4)::text, TRY_CAST(1::uint4 AS float4)::text IS NOT DISTINCT FROM CAST(1::uint4 AS float4)::text, TRY_CAST(NULL::uint4 AS float4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS float4)::text, TRY_CAST(4294967295::uint4 AS float4)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS float4)::text, TRY_CAST(NULL::uint4 AS float4) IS NULL
-----
-4294967300 true true
-
-# uint4 -> float8
-query TBB
-SELECT TRY_CAST(1::uint4 AS float8)::text, TRY_CAST(1::uint4 AS float8)::text IS NOT DISTINCT FROM CAST(1::uint4 AS float8)::text, TRY_CAST(NULL::uint4 AS float8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS float8)::text, TRY_CAST(4294967295::uint4 AS float8)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS float8)::text, TRY_CAST(NULL::uint4 AS float8) IS NULL
-----
-4294967295 true true
-
-# uint4 -> text
-query TBB
-SELECT TRY_CAST(1::uint4 AS text)::text, TRY_CAST(1::uint4 AS text)::text IS NOT DISTINCT FROM CAST(1::uint4 AS text)::text, TRY_CAST(NULL::uint4 AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS text)::text, TRY_CAST(4294967295::uint4 AS text)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS text)::text, TRY_CAST(NULL::uint4 AS text) IS NULL
-----
-4294967295 true true
-
-# uint4 -> mz_timestamp
-query TBB
-SELECT TRY_CAST(1::uint4 AS mz_timestamp)::text, TRY_CAST(1::uint4 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(1::uint4 AS mz_timestamp)::text, TRY_CAST(NULL::uint4 AS mz_timestamp) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS mz_timestamp)::text, TRY_CAST(4294967295::uint4 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS mz_timestamp)::text, TRY_CAST(NULL::uint4 AS mz_timestamp) IS NULL
-----
-4294967295 true true
-
-## uint8 sources
-
-# uint8 -> uint2
-query TBB
-SELECT TRY_CAST(1::uint8 AS uint2)::text, TRY_CAST(1::uint8 AS uint2)::text IS NOT DISTINCT FROM CAST(1::uint8 AS uint2)::text, TRY_CAST(NULL::uint8 AS uint2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(18446744073709551615::uint8 AS uint2)
-
-query T
-SELECT TRY_CAST(18446744073709551615::uint8 AS uint2)::text
-----
-NULL
-
-# uint8 -> uint4
-query TBB
-SELECT TRY_CAST(1::uint8 AS uint4)::text, TRY_CAST(1::uint8 AS uint4)::text IS NOT DISTINCT FROM CAST(1::uint8 AS uint4)::text, TRY_CAST(NULL::uint8 AS uint4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(18446744073709551615::uint8 AS uint4)
-
-query T
-SELECT TRY_CAST(18446744073709551615::uint8 AS uint4)::text
-----
-NULL
-
-# uint8 -> int2
-query TBB
-SELECT TRY_CAST(1::uint8 AS int2)::text, TRY_CAST(1::uint8 AS int2)::text IS NOT DISTINCT FROM CAST(1::uint8 AS int2)::text, TRY_CAST(NULL::uint8 AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(18446744073709551615::uint8 AS int2)
-
-query T
-SELECT TRY_CAST(18446744073709551615::uint8 AS int2)::text
-----
-NULL
-
-# uint8 -> int4
-query TBB
-SELECT TRY_CAST(1::uint8 AS int4)::text, TRY_CAST(1::uint8 AS int4)::text IS NOT DISTINCT FROM CAST(1::uint8 AS int4)::text, TRY_CAST(NULL::uint8 AS int4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(18446744073709551615::uint8 AS int4)
-
-query T
-SELECT TRY_CAST(18446744073709551615::uint8 AS int4)::text
-----
-NULL
-
-# uint8 -> int8
-query TBB
-SELECT TRY_CAST(1::uint8 AS int8)::text, TRY_CAST(1::uint8 AS int8)::text IS NOT DISTINCT FROM CAST(1::uint8 AS int8)::text, TRY_CAST(NULL::uint8 AS int8) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST(18446744073709551615::uint8 AS int8)
-
-query T
-SELECT TRY_CAST(18446744073709551615::uint8 AS int8)::text
-----
-NULL
-
-# uint8 -> numeric
-query TBB
-SELECT TRY_CAST(1::uint8 AS numeric)::text, TRY_CAST(1::uint8 AS numeric)::text IS NOT DISTINCT FROM CAST(1::uint8 AS numeric)::text, TRY_CAST(NULL::uint8 AS numeric) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::uint8 AS numeric)::text, TRY_CAST(18446744073709551615::uint8 AS numeric)::text IS NOT DISTINCT FROM CAST(18446744073709551615::uint8 AS numeric)::text, TRY_CAST(NULL::uint8 AS numeric) IS NULL
-----
-18446744073709551615 true true
-
-# uint8 -> float4
-query TBB
-SELECT TRY_CAST(1::uint8 AS float4)::text, TRY_CAST(1::uint8 AS float4)::text IS NOT DISTINCT FROM CAST(1::uint8 AS float4)::text, TRY_CAST(NULL::uint8 AS float4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::uint8 AS float4)::text, TRY_CAST(18446744073709551615::uint8 AS float4)::text IS NOT DISTINCT FROM CAST(18446744073709551615::uint8 AS float4)::text, TRY_CAST(NULL::uint8 AS float4) IS NULL
-----
-1.8446744e+19 true true
-
-# uint8 -> float8
-query TBB
-SELECT TRY_CAST(1::uint8 AS float8)::text, TRY_CAST(1::uint8 AS float8)::text IS NOT DISTINCT FROM CAST(1::uint8 AS float8)::text, TRY_CAST(NULL::uint8 AS float8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::uint8 AS float8)::text, TRY_CAST(18446744073709551615::uint8 AS float8)::text IS NOT DISTINCT FROM CAST(18446744073709551615::uint8 AS float8)::text, TRY_CAST(NULL::uint8 AS float8) IS NULL
-----
-1.8446744073709552e+19 true true
-
-# uint8 -> text
-query TBB
-SELECT TRY_CAST(1::uint8 AS text)::text, TRY_CAST(1::uint8 AS text)::text IS NOT DISTINCT FROM CAST(1::uint8 AS text)::text, TRY_CAST(NULL::uint8 AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::uint8 AS text)::text, TRY_CAST(18446744073709551615::uint8 AS text)::text IS NOT DISTINCT FROM CAST(18446744073709551615::uint8 AS text)::text, TRY_CAST(NULL::uint8 AS text) IS NULL
-----
-18446744073709551615 true true
-
-# uint8 -> mz_timestamp
-query TBB
-SELECT TRY_CAST(1::uint8 AS mz_timestamp)::text, TRY_CAST(1::uint8 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(1::uint8 AS mz_timestamp)::text, TRY_CAST(NULL::uint8 AS mz_timestamp) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::uint8 AS mz_timestamp)::text, TRY_CAST(18446744073709551615::uint8 AS mz_timestamp)::text IS NOT DISTINCT FROM CAST(18446744073709551615::uint8 AS mz_timestamp)::text, TRY_CAST(NULL::uint8 AS mz_timestamp) IS NULL
-----
-18446744073709551615 true true
-
-## mz_timestamp sources
-
-# mz_timestamp -> text
-query TBB
-SELECT TRY_CAST(1::mz_timestamp AS text)::text, TRY_CAST(1::mz_timestamp AS text)::text IS NOT DISTINCT FROM CAST(1::mz_timestamp AS text)::text, TRY_CAST(NULL::mz_timestamp AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::mz_timestamp AS text)::text, TRY_CAST(18446744073709551615::mz_timestamp AS text)::text IS NOT DISTINCT FROM CAST(18446744073709551615::mz_timestamp AS text)::text, TRY_CAST(NULL::mz_timestamp AS text) IS NULL
-----
-18446744073709551615 true true
-
-# mz_timestamp -> timestamp
-query TBB
-SELECT TRY_CAST(1::mz_timestamp AS timestamp)::text, TRY_CAST(1::mz_timestamp AS timestamp)::text IS NOT DISTINCT FROM CAST(1::mz_timestamp AS timestamp)::text, TRY_CAST(NULL::mz_timestamp AS timestamp) IS NULL
-----
-1970-01-01␠00:00:00.001 true true
-
-statement error
-SELECT CAST(18446744073709551615::mz_timestamp AS timestamp)
-
-query T
-SELECT TRY_CAST(18446744073709551615::mz_timestamp AS timestamp)::text
-----
-NULL
-
-# mz_timestamp -> timestamp(3)
-query TBB
-SELECT TRY_CAST(1::mz_timestamp AS timestamp(3))::text, TRY_CAST(1::mz_timestamp AS timestamp(3))::text IS NOT DISTINCT FROM CAST(1::mz_timestamp AS timestamp(3))::text, TRY_CAST(NULL::mz_timestamp AS timestamp(3)) IS NULL
-----
-1970-01-01␠00:00:00.001 true true
-
-statement error
-SELECT CAST(18446744073709551615::mz_timestamp AS timestamp(3))
-
-query T
-SELECT TRY_CAST(18446744073709551615::mz_timestamp AS timestamp(3))::text
-----
-NULL
-
-# mz_timestamp -> timestamptz
-query TBB
-SELECT TRY_CAST(1::mz_timestamp AS timestamptz)::text, TRY_CAST(1::mz_timestamp AS timestamptz)::text IS NOT DISTINCT FROM CAST(1::mz_timestamp AS timestamptz)::text, TRY_CAST(NULL::mz_timestamp AS timestamptz) IS NULL
-----
-1970-01-01␠00:00:00.001+00 true true
-
-statement error
-SELECT CAST(18446744073709551615::mz_timestamp AS timestamptz)
-
-query T
-SELECT TRY_CAST(18446744073709551615::mz_timestamp AS timestamptz)::text
-----
-NULL
-
-## text sources
-
-# text -> mz_timestamp
-query TBB
-SELECT TRY_CAST('1' AS mz_timestamp)::text, TRY_CAST('1' AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('1' AS mz_timestamp)::text, TRY_CAST(NULL AS mz_timestamp) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS mz_timestamp)
-
-query T
-SELECT TRY_CAST('abc' AS mz_timestamp)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS mz_timestamp)
-
-query T
-SELECT TRY_CAST('' AS mz_timestamp)::text
-----
-NULL
-
-# text -> bool
-query TBB
-SELECT TRY_CAST('true' AS bool)::text, TRY_CAST('true' AS bool)::text IS NOT DISTINCT FROM CAST('true' AS bool)::text, TRY_CAST(NULL AS bool) IS NULL
-----
-true true true
-
-statement error
-SELECT CAST('abc' AS bool)
-
-query T
-SELECT TRY_CAST('abc' AS bool)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS bool)
-
-query T
-SELECT TRY_CAST('' AS bool)::text
-----
-NULL
-
-# text -> int2
-query TBB
-SELECT TRY_CAST('1' AS int2)::text, TRY_CAST('1' AS int2)::text IS NOT DISTINCT FROM CAST('1' AS int2)::text, TRY_CAST(NULL AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS int2)
-
-query T
-SELECT TRY_CAST('abc' AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int2)
-
-query T
-SELECT TRY_CAST('' AS int2)::text
-----
-NULL
-
-# text -> int4
-query TBB
-SELECT TRY_CAST('1' AS int4)::text, TRY_CAST('1' AS int4)::text IS NOT DISTINCT FROM CAST('1' AS int4)::text, TRY_CAST(NULL AS int4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS int4)
-
-query T
-SELECT TRY_CAST('abc' AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int4)
-
-query T
-SELECT TRY_CAST('' AS int4)::text
-----
-NULL
-
-# text -> int8
-query TBB
-SELECT TRY_CAST('1' AS int8)::text, TRY_CAST('1' AS int8)::text IS NOT DISTINCT FROM CAST('1' AS int8)::text, TRY_CAST(NULL AS int8) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS int8)
-
-query T
-SELECT TRY_CAST('abc' AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int8)
-
-query T
-SELECT TRY_CAST('' AS int8)::text
-----
-NULL
-
-# text -> uint2
-query TBB
-SELECT TRY_CAST('1' AS uint2)::text, TRY_CAST('1' AS uint2)::text IS NOT DISTINCT FROM CAST('1' AS uint2)::text, TRY_CAST(NULL AS uint2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS uint2)
-
-query T
-SELECT TRY_CAST('abc' AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS uint2)
-
-query T
-SELECT TRY_CAST('' AS uint2)::text
-----
-NULL
-
-# text -> uint4
-query TBB
-SELECT TRY_CAST('1' AS uint4)::text, TRY_CAST('1' AS uint4)::text IS NOT DISTINCT FROM CAST('1' AS uint4)::text, TRY_CAST(NULL AS uint4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS uint4)
-
-query T
-SELECT TRY_CAST('abc' AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS uint4)
-
-query T
-SELECT TRY_CAST('' AS uint4)::text
-----
-NULL
-
-# text -> uint8
-query TBB
-SELECT TRY_CAST('1' AS uint8)::text, TRY_CAST('1' AS uint8)::text IS NOT DISTINCT FROM CAST('1' AS uint8)::text, TRY_CAST(NULL AS uint8) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS uint8)
-
-query T
-SELECT TRY_CAST('abc' AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS uint8)
-
-query T
-SELECT TRY_CAST('' AS uint8)::text
-----
-NULL
-
-# text -> oid
-query TBB
-SELECT TRY_CAST('1' AS oid)::text, TRY_CAST('1' AS oid)::text IS NOT DISTINCT FROM CAST('1' AS oid)::text, TRY_CAST(NULL AS oid) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('abc' AS oid)
-
-query T
-SELECT TRY_CAST('abc' AS oid)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS oid)
-
-query T
-SELECT TRY_CAST('' AS oid)::text
-----
-NULL
-
-# text -> float4
-query TBB
-SELECT TRY_CAST('1.5' AS float4)::text, TRY_CAST('1.5' AS float4)::text IS NOT DISTINCT FROM CAST('1.5' AS float4)::text, TRY_CAST(NULL AS float4) IS NULL
-----
-1.5 true true
-
-statement error
-SELECT CAST('abc' AS float4)
-
-query T
-SELECT TRY_CAST('abc' AS float4)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS float4)
-
-query T
-SELECT TRY_CAST('' AS float4)::text
-----
-NULL
-
-# text -> float8
-query TBB
-SELECT TRY_CAST('1.5' AS float8)::text, TRY_CAST('1.5' AS float8)::text IS NOT DISTINCT FROM CAST('1.5' AS float8)::text, TRY_CAST(NULL AS float8) IS NULL
-----
-1.5 true true
-
-statement error
-SELECT CAST('abc' AS float8)
-
-query T
-SELECT TRY_CAST('abc' AS float8)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS float8)
-
-query T
-SELECT TRY_CAST('' AS float8)::text
-----
-NULL
-
-# text -> numeric
-query TBB
-SELECT TRY_CAST('1.5' AS numeric)::text, TRY_CAST('1.5' AS numeric)::text IS NOT DISTINCT FROM CAST('1.5' AS numeric)::text, TRY_CAST(NULL AS numeric) IS NULL
-----
-1.5 true true
-
-statement error
-SELECT CAST('abc' AS numeric)
-
-query T
-SELECT TRY_CAST('abc' AS numeric)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS numeric)
-
-query T
-SELECT TRY_CAST('' AS numeric)::text
-----
-NULL
-
-# text -> date
-query TBB
-SELECT TRY_CAST('2020-01-01' AS date)::text, TRY_CAST('2020-01-01' AS date)::text IS NOT DISTINCT FROM CAST('2020-01-01' AS date)::text, TRY_CAST(NULL AS date) IS NULL
-----
-2020-01-01 true true
-
-statement error
-SELECT CAST('abc' AS date)
-
-query T
-SELECT TRY_CAST('abc' AS date)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS date)
-
-query T
-SELECT TRY_CAST('' AS date)::text
-----
-NULL
-
-# text -> time
-query TBB
-SELECT TRY_CAST('12:34:56' AS time)::text, TRY_CAST('12:34:56' AS time)::text IS NOT DISTINCT FROM CAST('12:34:56' AS time)::text, TRY_CAST(NULL AS time) IS NULL
-----
-12:34:56 true true
-
-statement error
-SELECT CAST('abc' AS time)
-
-query T
-SELECT TRY_CAST('abc' AS time)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS time)
-
-query T
-SELECT TRY_CAST('' AS time)::text
-----
-NULL
-
-# text -> timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789' AS timestamp)::text, TRY_CAST('2020-01-01 12:34:56.789' AS timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789' AS timestamp)::text, TRY_CAST(NULL AS timestamp) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-statement error
-SELECT CAST('abc' AS timestamp)
-
-query T
-SELECT TRY_CAST('abc' AS timestamp)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS timestamp)
-
-query T
-SELECT TRY_CAST('' AS timestamp)::text
-----
-NULL
-
-# text -> timestamp(3)
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789' AS timestamp(3))::text, TRY_CAST('2020-01-01 12:34:56.789' AS timestamp(3))::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789' AS timestamp(3))::text, TRY_CAST(NULL AS timestamp(3)) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-statement error
-SELECT CAST('abc' AS timestamp(3))
-
-query T
-SELECT TRY_CAST('abc' AS timestamp(3))::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS timestamp(3))
-
-query T
-SELECT TRY_CAST('' AS timestamp(3))::text
-----
-NULL
-
-# text -> timestamptz
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00' AS timestamptz)::text, TRY_CAST('2020-01-01 12:34:56.789+00' AS timestamptz)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00' AS timestamptz)::text, TRY_CAST(NULL AS timestamptz) IS NULL
-----
-2020-01-01␠12:34:56.789+00 true true
-
-statement error
-SELECT CAST('abc' AS timestamptz)
-
-query T
-SELECT TRY_CAST('abc' AS timestamptz)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS timestamptz)
-
-query T
-SELECT TRY_CAST('' AS timestamptz)::text
-----
-NULL
-
-# text -> interval
-query TBB
-SELECT TRY_CAST('1 day' AS interval)::text, TRY_CAST('1 day' AS interval)::text IS NOT DISTINCT FROM CAST('1 day' AS interval)::text, TRY_CAST(NULL AS interval) IS NULL
-----
-1␠day true true
-
-statement error
-SELECT CAST('abc' AS interval)
-
-query T
-SELECT TRY_CAST('abc' AS interval)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('' AS interval)::text, TRY_CAST('' AS interval)::text IS NOT DISTINCT FROM CAST('' AS interval)::text, TRY_CAST(NULL AS interval) IS NULL
-----
-00:00:00 true true
-
-# text -> bytea
-query TBB
-SELECT TRY_CAST('\x0102' AS bytea)::text, TRY_CAST('\x0102' AS bytea)::text IS NOT DISTINCT FROM CAST('\x0102' AS bytea)::text, TRY_CAST(NULL AS bytea) IS NULL
-----
-\x0102 true true
-
-query TBB
-SELECT TRY_CAST('abc' AS bytea)::text, TRY_CAST('abc' AS bytea)::text IS NOT DISTINCT FROM CAST('abc' AS bytea)::text, TRY_CAST(NULL AS bytea) IS NULL
-----
-\x616263 true true
-
-query TBB
-SELECT TRY_CAST('' AS bytea)::text, TRY_CAST('' AS bytea)::text IS NOT DISTINCT FROM CAST('' AS bytea)::text, TRY_CAST(NULL AS bytea) IS NULL
-----
-\x true true
-
-# text -> jsonb
-query TBB
-SELECT TRY_CAST('{"a":1}' AS jsonb)::text, TRY_CAST('{"a":1}' AS jsonb)::text IS NOT DISTINCT FROM CAST('{"a":1}' AS jsonb)::text, TRY_CAST(NULL AS jsonb) IS NULL
-----
-{"a":1} true true
-
-statement error
-SELECT CAST('abc' AS jsonb)
-
-query T
-SELECT TRY_CAST('abc' AS jsonb)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS jsonb)
-
-query T
-SELECT TRY_CAST('' AS jsonb)::text
-----
-NULL
-
-# text -> uuid
-query TBB
-SELECT TRY_CAST('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11' AS uuid)::text, TRY_CAST('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11' AS uuid)::text IS NOT DISTINCT FROM CAST('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11' AS uuid)::text, TRY_CAST(NULL AS uuid) IS NULL
-----
-a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 true true
-
-statement error
-SELECT CAST('abc' AS uuid)
-
-query T
-SELECT TRY_CAST('abc' AS uuid)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS uuid)
-
-query T
-SELECT TRY_CAST('' AS uuid)::text
-----
-NULL
-
-# text -> int8[]
-query TBB
-SELECT TRY_CAST('{1,2}' AS int8[])::text, TRY_CAST('{1,2}' AS int8[])::text IS NOT DISTINCT FROM CAST('{1,2}' AS int8[])::text, TRY_CAST(NULL AS int8[]) IS NULL
-----
-{1,2} true true
-
-statement error
-SELECT CAST('abc' AS int8[])
-
-query T
-SELECT TRY_CAST('abc' AS int8[])::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int8[])
-
-query T
-SELECT TRY_CAST('' AS int8[])::text
-----
-NULL
-
-# text -> int2[]
-query TBB
-SELECT TRY_CAST('{1,2}' AS int2[])::text, TRY_CAST('{1,2}' AS int2[])::text IS NOT DISTINCT FROM CAST('{1,2}' AS int2[])::text, TRY_CAST(NULL AS int2[]) IS NULL
-----
-{1,2} true true
-
-statement error
-SELECT CAST('abc' AS int2[])
-
-query T
-SELECT TRY_CAST('abc' AS int2[])::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int2[])
-
-query T
-SELECT TRY_CAST('' AS int2[])::text
-----
-NULL
-
-# text -> int8 list
-query TBB
-SELECT TRY_CAST('{1,2}' AS int8 list)::text, TRY_CAST('{1,2}' AS int8 list)::text IS NOT DISTINCT FROM CAST('{1,2}' AS int8 list)::text, TRY_CAST(NULL AS int8 list) IS NULL
-----
-{1,2} true true
-
-statement error
-SELECT CAST('abc' AS int8 list)
-
-query T
-SELECT TRY_CAST('abc' AS int8 list)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int8 list)
-
-query T
-SELECT TRY_CAST('' AS int8 list)::text
-----
-NULL
-
-# text -> int2 list
-query TBB
-SELECT TRY_CAST('{1,2}' AS int2 list)::text, TRY_CAST('{1,2}' AS int2 list)::text IS NOT DISTINCT FROM CAST('{1,2}' AS int2 list)::text, TRY_CAST(NULL AS int2 list) IS NULL
-----
-{1,2} true true
-
-statement error
-SELECT CAST('abc' AS int2 list)
-
-query T
-SELECT TRY_CAST('abc' AS int2 list)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int2 list)
-
-query T
-SELECT TRY_CAST('' AS int2 list)::text
-----
-NULL
-
-# text -> map[text=>int8]
-query TBB
-SELECT TRY_CAST('{a=>1}' AS map[text=>int8])::text, TRY_CAST('{a=>1}' AS map[text=>int8])::text IS NOT DISTINCT FROM CAST('{a=>1}' AS map[text=>int8])::text, TRY_CAST(NULL AS map[text=>int8]) IS NULL
-----
-{a=>1} true true
-
-statement error
-SELECT CAST('abc' AS map[text=>int8])
-
-query T
-SELECT TRY_CAST('abc' AS map[text=>int8])::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS map[text=>int8])
-
-query T
-SELECT TRY_CAST('' AS map[text=>int8])::text
-----
-NULL
-
-# text -> int4range
-query TBB
-SELECT TRY_CAST('[1,3)' AS int4range)::text, TRY_CAST('[1,3)' AS int4range)::text IS NOT DISTINCT FROM CAST('[1,3)' AS int4range)::text, TRY_CAST(NULL AS int4range) IS NULL
-----
-[1,3) true true
-
-statement error
-SELECT CAST('abc' AS int4range)
-
-query T
-SELECT TRY_CAST('abc' AS int4range)::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS int4range)
-
-query T
-SELECT TRY_CAST('' AS int4range)::text
-----
-NULL
-
-# text -> int2vector
-query TBB
-SELECT TRY_CAST('1 2' AS int2vector)::text, TRY_CAST('1 2' AS int2vector)::text IS NOT DISTINCT FROM CAST('1 2' AS int2vector)::text, TRY_CAST(NULL AS int2vector) IS NULL
-----
-1␠2 true true
-
-statement error
-SELECT CAST('abc' AS int2vector)
-
-query T
-SELECT TRY_CAST('abc' AS int2vector)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('' AS int2vector)::text, TRY_CAST('' AS int2vector)::text IS NOT DISTINCT FROM CAST('' AS int2vector)::text, TRY_CAST(NULL AS int2vector) IS NULL
-----
-(empty) true true
-
-# text -> char(3)
-query TBB
-SELECT TRY_CAST('abc' AS char(3))::text, TRY_CAST('abc' AS char(3))::text IS NOT DISTINCT FROM CAST('abc' AS char(3))::text, TRY_CAST(NULL AS char(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc' AS char(3))::text, TRY_CAST('abc' AS char(3))::text IS NOT DISTINCT FROM CAST('abc' AS char(3))::text, TRY_CAST(NULL AS char(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('' AS char(3))::text, TRY_CAST('' AS char(3))::text IS NOT DISTINCT FROM CAST('' AS char(3))::text, TRY_CAST(NULL AS char(3)) IS NULL
-----
-(empty) true true
-
-# text -> varchar(3)
-query TBB
-SELECT TRY_CAST('abc' AS varchar(3))::text, TRY_CAST('abc' AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc' AS varchar(3))::text, TRY_CAST(NULL AS varchar(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc' AS varchar(3))::text, TRY_CAST('abc' AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc' AS varchar(3))::text, TRY_CAST(NULL AS varchar(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('' AS varchar(3))::text, TRY_CAST('' AS varchar(3))::text IS NOT DISTINCT FROM CAST('' AS varchar(3))::text, TRY_CAST(NULL AS varchar(3)) IS NULL
-----
-(empty) true true
-
-# text -> "char"
-query TBB
-SELECT TRY_CAST('a' AS "char")::text, TRY_CAST('a' AS "char")::text IS NOT DISTINCT FROM CAST('a' AS "char")::text, TRY_CAST(NULL AS "char") IS NULL
-----
-a true true
-
-query TBB
-SELECT TRY_CAST('abc' AS "char")::text, TRY_CAST('abc' AS "char")::text IS NOT DISTINCT FROM CAST('abc' AS "char")::text, TRY_CAST(NULL AS "char") IS NULL
-----
-a true true
-
-query TBB
-SELECT TRY_CAST('' AS "char")::text, TRY_CAST('' AS "char")::text IS NOT DISTINCT FROM CAST('' AS "char")::text, TRY_CAST(NULL AS "char") IS NULL
-----
- true true
-
-# text -> name
-query TBB
-SELECT TRY_CAST('abc' AS name)::text, TRY_CAST('abc' AS name)::text IS NOT DISTINCT FROM CAST('abc' AS name)::text, TRY_CAST(NULL AS name) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc' AS name)::text, TRY_CAST('abc' AS name)::text IS NOT DISTINCT FROM CAST('abc' AS name)::text, TRY_CAST(NULL AS name) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('' AS name)::text, TRY_CAST('' AS name)::text IS NOT DISTINCT FROM CAST('' AS name)::text, TRY_CAST(NULL AS name) IS NULL
-----
-(empty) true true
-
-## numeric sources
-
-# numeric -> mz_timestamp
-statement error
-SELECT CAST(1.5::numeric AS mz_timestamp)
-
-query T
-SELECT TRY_CAST(1.5::numeric AS mz_timestamp)::text
-----
-NULL
-
-statement error
-SELECT CAST(1e38::numeric AS mz_timestamp)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS mz_timestamp)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::numeric AS mz_timestamp)
-
-query T
-SELECT TRY_CAST((-1.5)::numeric AS mz_timestamp)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::numeric AS mz_timestamp)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS mz_timestamp)::text
-----
-NULL
-
-statement error
-SELECT CAST(123.456::numeric AS mz_timestamp)
-
-query T
-SELECT TRY_CAST(123.456::numeric AS mz_timestamp)::text
-----
-NULL
-
-# numeric -> numeric
-query TBB
-SELECT TRY_CAST(1.5::numeric AS numeric)::text, TRY_CAST(1.5::numeric AS numeric)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS numeric)::text, TRY_CAST(NULL::numeric AS numeric) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST(1e38::numeric AS numeric)::text, TRY_CAST(1e38::numeric AS numeric)::text IS NOT DISTINCT FROM CAST(1e38::numeric AS numeric)::text, TRY_CAST(NULL::numeric AS numeric) IS NULL
-----
-100000000000000000000000000000000000000 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS numeric)::text, TRY_CAST((-1.5)::numeric AS numeric)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS numeric)::text, TRY_CAST(NULL::numeric AS numeric) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::numeric AS numeric)::text, TRY_CAST('NaN'::numeric AS numeric)::text IS NOT DISTINCT FROM CAST('NaN'::numeric AS numeric)::text, TRY_CAST(NULL::numeric AS numeric) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS numeric)::text, TRY_CAST(123.456::numeric AS numeric)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS numeric)::text, TRY_CAST(NULL::numeric AS numeric) IS NULL
-----
-123.456 true true
-
-# numeric -> float4
-query TBB
-SELECT TRY_CAST(1.5::numeric AS float4)::text, TRY_CAST(1.5::numeric AS float4)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS float4)::text, TRY_CAST(NULL::numeric AS float4) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST(1e38::numeric AS float4)::text, TRY_CAST(1e38::numeric AS float4)::text IS NOT DISTINCT FROM CAST(1e38::numeric AS float4)::text, TRY_CAST(NULL::numeric AS float4) IS NULL
-----
-1e+38 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS float4)::text, TRY_CAST((-1.5)::numeric AS float4)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS float4)::text, TRY_CAST(NULL::numeric AS float4) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::numeric AS float4)::text, TRY_CAST('NaN'::numeric AS float4)::text IS NOT DISTINCT FROM CAST('NaN'::numeric AS float4)::text, TRY_CAST(NULL::numeric AS float4) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS float4)::text, TRY_CAST(123.456::numeric AS float4)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS float4)::text, TRY_CAST(NULL::numeric AS float4) IS NULL
-----
-123.456 true true
-
-# numeric -> float8
-query TBB
-SELECT TRY_CAST(1.5::numeric AS float8)::text, TRY_CAST(1.5::numeric AS float8)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS float8)::text, TRY_CAST(NULL::numeric AS float8) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST(1e38::numeric AS float8)::text, TRY_CAST(1e38::numeric AS float8)::text IS NOT DISTINCT FROM CAST(1e38::numeric AS float8)::text, TRY_CAST(NULL::numeric AS float8) IS NULL
-----
-1e+38 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS float8)::text, TRY_CAST((-1.5)::numeric AS float8)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS float8)::text, TRY_CAST(NULL::numeric AS float8) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::numeric AS float8)::text, TRY_CAST('NaN'::numeric AS float8)::text IS NOT DISTINCT FROM CAST('NaN'::numeric AS float8)::text, TRY_CAST(NULL::numeric AS float8) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS float8)::text, TRY_CAST(123.456::numeric AS float8)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS float8)::text, TRY_CAST(NULL::numeric AS float8) IS NULL
-----
-123.456 true true
-
-# numeric -> int2
-query TBB
-SELECT TRY_CAST(1.5::numeric AS int2)::text, TRY_CAST(1.5::numeric AS int2)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS int2)::text, TRY_CAST(NULL::numeric AS int2) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST(1e38::numeric AS int2)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS int2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS int2)::text, TRY_CAST((-1.5)::numeric AS int2)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS int2)::text, TRY_CAST(NULL::numeric AS int2) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::numeric AS int2)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS int2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS int2)::text, TRY_CAST(123.456::numeric AS int2)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS int2)::text, TRY_CAST(NULL::numeric AS int2) IS NULL
-----
-123 true true
-
-# numeric -> int4
-query TBB
-SELECT TRY_CAST(1.5::numeric AS int4)::text, TRY_CAST(1.5::numeric AS int4)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS int4)::text, TRY_CAST(NULL::numeric AS int4) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST(1e38::numeric AS int4)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS int4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS int4)::text, TRY_CAST((-1.5)::numeric AS int4)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS int4)::text, TRY_CAST(NULL::numeric AS int4) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::numeric AS int4)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS int4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS int4)::text, TRY_CAST(123.456::numeric AS int4)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS int4)::text, TRY_CAST(NULL::numeric AS int4) IS NULL
-----
-123 true true
-
-# numeric -> int8
-query TBB
-SELECT TRY_CAST(1.5::numeric AS int8)::text, TRY_CAST(1.5::numeric AS int8)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS int8)::text, TRY_CAST(NULL::numeric AS int8) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST(1e38::numeric AS int8)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS int8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS int8)::text, TRY_CAST((-1.5)::numeric AS int8)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS int8)::text, TRY_CAST(NULL::numeric AS int8) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::numeric AS int8)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS int8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS int8)::text, TRY_CAST(123.456::numeric AS int8)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS int8)::text, TRY_CAST(NULL::numeric AS int8) IS NULL
-----
-123 true true
-
-# numeric -> uint2
-query TBB
-SELECT TRY_CAST(1.5::numeric AS uint2)::text, TRY_CAST(1.5::numeric AS uint2)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS uint2)::text, TRY_CAST(NULL::numeric AS uint2) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST(1e38::numeric AS uint2)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::numeric AS uint2)
-
-query T
-SELECT TRY_CAST((-1.5)::numeric AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::numeric AS uint2)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS uint2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS uint2)::text, TRY_CAST(123.456::numeric AS uint2)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS uint2)::text, TRY_CAST(NULL::numeric AS uint2) IS NULL
-----
-123 true true
-
-# numeric -> uint4
-query TBB
-SELECT TRY_CAST(1.5::numeric AS uint4)::text, TRY_CAST(1.5::numeric AS uint4)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS uint4)::text, TRY_CAST(NULL::numeric AS uint4) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST(1e38::numeric AS uint4)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::numeric AS uint4)
-
-query T
-SELECT TRY_CAST((-1.5)::numeric AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::numeric AS uint4)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS uint4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS uint4)::text, TRY_CAST(123.456::numeric AS uint4)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS uint4)::text, TRY_CAST(NULL::numeric AS uint4) IS NULL
-----
-123 true true
-
-# numeric -> uint8
-query TBB
-SELECT TRY_CAST(1.5::numeric AS uint8)::text, TRY_CAST(1.5::numeric AS uint8)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS uint8)::text, TRY_CAST(NULL::numeric AS uint8) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST(1e38::numeric AS uint8)
-
-query T
-SELECT TRY_CAST(1e38::numeric AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::numeric AS uint8)
-
-query T
-SELECT TRY_CAST((-1.5)::numeric AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::numeric AS uint8)
-
-query T
-SELECT TRY_CAST('NaN'::numeric AS uint8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS uint8)::text, TRY_CAST(123.456::numeric AS uint8)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS uint8)::text, TRY_CAST(NULL::numeric AS uint8) IS NULL
-----
-123 true true
-
-# numeric -> text
-query TBB
-SELECT TRY_CAST(1.5::numeric AS text)::text, TRY_CAST(1.5::numeric AS text)::text IS NOT DISTINCT FROM CAST(1.5::numeric AS text)::text, TRY_CAST(NULL::numeric AS text) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST(1e38::numeric AS text)::text, TRY_CAST(1e38::numeric AS text)::text IS NOT DISTINCT FROM CAST(1e38::numeric AS text)::text, TRY_CAST(NULL::numeric AS text) IS NULL
-----
-100000000000000000000000000000000000000 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS text)::text, TRY_CAST((-1.5)::numeric AS text)::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS text)::text, TRY_CAST(NULL::numeric AS text) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::numeric AS text)::text, TRY_CAST('NaN'::numeric AS text)::text IS NOT DISTINCT FROM CAST('NaN'::numeric AS text)::text, TRY_CAST(NULL::numeric AS text) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS text)::text, TRY_CAST(123.456::numeric AS text)::text IS NOT DISTINCT FROM CAST(123.456::numeric AS text)::text, TRY_CAST(NULL::numeric AS text) IS NULL
-----
-123.456 true true
-
-## timestamp sources
-
-# timestamp -> mz_timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS mz_timestamp)::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS mz_timestamp)::text, TRY_CAST(NULL::timestamp AS mz_timestamp) IS NULL
-----
-1577882096789 true true
-
-statement error
-SELECT CAST('1969-01-01'::timestamp AS mz_timestamp)
-
-query T
-SELECT TRY_CAST('1969-01-01'::timestamp AS mz_timestamp)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS mz_timestamp)::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS mz_timestamp)::text, TRY_CAST(NULL::timestamp AS mz_timestamp) IS NULL
-----
-8210266876799000 true true
-
-# timestamp -> date
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS date)::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS date)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS date)::text, TRY_CAST(NULL::timestamp AS date) IS NULL
-----
-2020-01-01 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01'::timestamp AS date)::text, TRY_CAST('1969-01-01'::timestamp AS date)::text IS NOT DISTINCT FROM CAST('1969-01-01'::timestamp AS date)::text, TRY_CAST(NULL::timestamp AS date) IS NULL
-----
-1969-01-01 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS date)::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS date)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS date)::text, TRY_CAST(NULL::timestamp AS date) IS NULL
-----
-262142-12-31 true true
-
-# timestamp -> timestamptz
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS timestamptz)::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS timestamptz)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS timestamptz)::text, TRY_CAST(NULL::timestamp AS timestamptz) IS NULL
-----
-2020-01-01␠12:34:56.789+00 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01'::timestamp AS timestamptz)::text, TRY_CAST('1969-01-01'::timestamp AS timestamptz)::text IS NOT DISTINCT FROM CAST('1969-01-01'::timestamp AS timestamptz)::text, TRY_CAST(NULL::timestamp AS timestamptz) IS NULL
-----
-1969-01-01␠00:00:00+00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS timestamptz)::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS timestamptz)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS timestamptz)::text, TRY_CAST(NULL::timestamp AS timestamptz) IS NULL
-----
-262142-12-31␠23:59:59+00 true true
-
-# timestamp -> timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS timestamp)::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS timestamp)::text, TRY_CAST(NULL::timestamp AS timestamp) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01'::timestamp AS timestamp)::text, TRY_CAST('1969-01-01'::timestamp AS timestamp)::text IS NOT DISTINCT FROM CAST('1969-01-01'::timestamp AS timestamp)::text, TRY_CAST(NULL::timestamp AS timestamp) IS NULL
-----
-1969-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS timestamp)::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS timestamp)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS timestamp)::text, TRY_CAST(NULL::timestamp AS timestamp) IS NULL
-----
-262142-12-31␠23:59:59 true true
-
-# timestamp -> timestamp(3)
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS timestamp(3))::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS timestamp(3))::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS timestamp(3))::text, TRY_CAST(NULL::timestamp AS timestamp(3)) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01'::timestamp AS timestamp(3))::text, TRY_CAST('1969-01-01'::timestamp AS timestamp(3))::text IS NOT DISTINCT FROM CAST('1969-01-01'::timestamp AS timestamp(3))::text, TRY_CAST(NULL::timestamp AS timestamp(3)) IS NULL
-----
-1969-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS timestamp(3))::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS timestamp(3))::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS timestamp(3))::text, TRY_CAST(NULL::timestamp AS timestamp(3)) IS NULL
-----
-262142-12-31␠23:59:59 true true
-
-# timestamp -> time
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS time)::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS time)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS time)::text, TRY_CAST(NULL::timestamp AS time) IS NULL
-----
-12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01'::timestamp AS time)::text, TRY_CAST('1969-01-01'::timestamp AS time)::text IS NOT DISTINCT FROM CAST('1969-01-01'::timestamp AS time)::text, TRY_CAST(NULL::timestamp AS time) IS NULL
-----
-00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS time)::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS time)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS time)::text, TRY_CAST(NULL::timestamp AS time) IS NULL
-----
-23:59:59 true true
-
-# timestamp -> text
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS text)::text, TRY_CAST('2020-01-01 12:34:56.789'::timestamp AS text)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789'::timestamp AS text)::text, TRY_CAST(NULL::timestamp AS text) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01'::timestamp AS text)::text, TRY_CAST('1969-01-01'::timestamp AS text)::text IS NOT DISTINCT FROM CAST('1969-01-01'::timestamp AS text)::text, TRY_CAST(NULL::timestamp AS text) IS NULL
-----
-1969-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59'::timestamp AS text)::text, TRY_CAST('262142-12-31 23:59:59'::timestamp AS text)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59'::timestamp AS text)::text, TRY_CAST(NULL::timestamp AS text) IS NULL
-----
-262142-12-31␠23:59:59 true true
-
-## timestamp with time zone sources
-
-# timestamp with time zone -> mz_timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS mz_timestamp)::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS mz_timestamp)::text, TRY_CAST(NULL::timestamptz AS mz_timestamp) IS NULL
-----
-1577882096789 true true
-
-statement error
-SELECT CAST('1969-01-01 00:00:00+00'::timestamptz AS mz_timestamp)
-
-query T
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS mz_timestamp)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS mz_timestamp)::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS mz_timestamp)::text, TRY_CAST(NULL::timestamptz AS mz_timestamp) IS NULL
-----
-8210266876799000 true true
-
-# timestamp with time zone -> date
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS date)::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS date)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS date)::text, TRY_CAST(NULL::timestamptz AS date) IS NULL
-----
-2020-01-01 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS date)::text, TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS date)::text IS NOT DISTINCT FROM CAST('1969-01-01 00:00:00+00'::timestamptz AS date)::text, TRY_CAST(NULL::timestamptz AS date) IS NULL
-----
-1969-01-01 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS date)::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS date)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS date)::text, TRY_CAST(NULL::timestamptz AS date) IS NULL
-----
-262142-12-31 true true
-
-# timestamp with time zone -> timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamp)::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamp)::text, TRY_CAST(NULL::timestamptz AS timestamp) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamp)::text, TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamp)::text IS NOT DISTINCT FROM CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamp)::text, TRY_CAST(NULL::timestamptz AS timestamp) IS NULL
-----
-1969-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamp)::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamp)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamp)::text, TRY_CAST(NULL::timestamptz AS timestamp) IS NULL
-----
-262142-12-31␠23:59:59 true true
-
-# timestamp with time zone -> timestamp(3)
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamp(3))::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamp(3))::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamp(3))::text, TRY_CAST(NULL::timestamptz AS timestamp(3)) IS NULL
-----
-2020-01-01␠12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamp(3))::text, TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamp(3))::text IS NOT DISTINCT FROM CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamp(3))::text, TRY_CAST(NULL::timestamptz AS timestamp(3)) IS NULL
-----
-1969-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamp(3))::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamp(3))::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamp(3))::text, TRY_CAST(NULL::timestamptz AS timestamp(3)) IS NULL
-----
-262142-12-31␠23:59:59 true true
-
-# timestamp with time zone -> timestamptz
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamptz)::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamptz)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS timestamptz)::text, TRY_CAST(NULL::timestamptz AS timestamptz) IS NULL
-----
-2020-01-01␠12:34:56.789+00 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamptz)::text, TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamptz)::text IS NOT DISTINCT FROM CAST('1969-01-01 00:00:00+00'::timestamptz AS timestamptz)::text, TRY_CAST(NULL::timestamptz AS timestamptz) IS NULL
-----
-1969-01-01␠00:00:00+00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamptz)::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamptz)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS timestamptz)::text, TRY_CAST(NULL::timestamptz AS timestamptz) IS NULL
-----
-262142-12-31␠23:59:59+00 true true
-
-# timestamp with time zone -> time
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS time)::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS time)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS time)::text, TRY_CAST(NULL::timestamptz AS time) IS NULL
-----
-12:34:56.789 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS time)::text, TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS time)::text IS NOT DISTINCT FROM CAST('1969-01-01 00:00:00+00'::timestamptz AS time)::text, TRY_CAST(NULL::timestamptz AS time) IS NULL
-----
-00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS time)::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS time)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS time)::text, TRY_CAST(NULL::timestamptz AS time) IS NULL
-----
-23:59:59 true true
-
-# timestamp with time zone -> text
-query TBB
-SELECT TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS text)::text, TRY_CAST('2020-01-01 12:34:56.789+00'::timestamptz AS text)::text IS NOT DISTINCT FROM CAST('2020-01-01 12:34:56.789+00'::timestamptz AS text)::text, TRY_CAST(NULL::timestamptz AS text) IS NULL
-----
-2020-01-01␠12:34:56.789+00 true true
-
-query TBB
-SELECT TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS text)::text, TRY_CAST('1969-01-01 00:00:00+00'::timestamptz AS text)::text IS NOT DISTINCT FROM CAST('1969-01-01 00:00:00+00'::timestamptz AS text)::text, TRY_CAST(NULL::timestamptz AS text) IS NULL
-----
-1969-01-01␠00:00:00+00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS text)::text, TRY_CAST('262142-12-31 23:59:59+00'::timestamptz AS text)::text IS NOT DISTINCT FROM CAST('262142-12-31 23:59:59+00'::timestamptz AS text)::text, TRY_CAST(NULL::timestamptz AS text) IS NULL
-----
-262142-12-31␠23:59:59+00 true true
-
-## date sources
-
-# date -> mz_timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01'::date AS mz_timestamp)::text, TRY_CAST('2020-01-01'::date AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01'::date AS mz_timestamp)::text, TRY_CAST(NULL::date AS mz_timestamp) IS NULL
-----
-1577836800000 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31'::date AS mz_timestamp)::text, TRY_CAST('262142-12-31'::date AS mz_timestamp)::text IS NOT DISTINCT FROM CAST('262142-12-31'::date AS mz_timestamp)::text, TRY_CAST(NULL::date AS mz_timestamp) IS NULL
-----
-8210266790400000 true true
-
-# date -> timestamp
-query TBB
-SELECT TRY_CAST('2020-01-01'::date AS timestamp)::text, TRY_CAST('2020-01-01'::date AS timestamp)::text IS NOT DISTINCT FROM CAST('2020-01-01'::date AS timestamp)::text, TRY_CAST(NULL::date AS timestamp) IS NULL
-----
-2020-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31'::date AS timestamp)::text, TRY_CAST('262142-12-31'::date AS timestamp)::text IS NOT DISTINCT FROM CAST('262142-12-31'::date AS timestamp)::text, TRY_CAST(NULL::date AS timestamp) IS NULL
-----
-262142-12-31␠00:00:00 true true
-
-# date -> timestamp(3)
-query TBB
-SELECT TRY_CAST('2020-01-01'::date AS timestamp(3))::text, TRY_CAST('2020-01-01'::date AS timestamp(3))::text IS NOT DISTINCT FROM CAST('2020-01-01'::date AS timestamp(3))::text, TRY_CAST(NULL::date AS timestamp(3)) IS NULL
-----
-2020-01-01␠00:00:00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31'::date AS timestamp(3))::text, TRY_CAST('262142-12-31'::date AS timestamp(3))::text IS NOT DISTINCT FROM CAST('262142-12-31'::date AS timestamp(3))::text, TRY_CAST(NULL::date AS timestamp(3)) IS NULL
-----
-262142-12-31␠00:00:00 true true
-
-# date -> timestamptz
-query TBB
-SELECT TRY_CAST('2020-01-01'::date AS timestamptz)::text, TRY_CAST('2020-01-01'::date AS timestamptz)::text IS NOT DISTINCT FROM CAST('2020-01-01'::date AS timestamptz)::text, TRY_CAST(NULL::date AS timestamptz) IS NULL
-----
-2020-01-01␠00:00:00+00 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31'::date AS timestamptz)::text, TRY_CAST('262142-12-31'::date AS timestamptz)::text IS NOT DISTINCT FROM CAST('262142-12-31'::date AS timestamptz)::text, TRY_CAST(NULL::date AS timestamptz) IS NULL
-----
-262142-12-31␠00:00:00+00 true true
-
-# date -> text
-query TBB
-SELECT TRY_CAST('2020-01-01'::date AS text)::text, TRY_CAST('2020-01-01'::date AS text)::text IS NOT DISTINCT FROM CAST('2020-01-01'::date AS text)::text, TRY_CAST(NULL::date AS text) IS NULL
-----
-2020-01-01 true true
-
-query TBB
-SELECT TRY_CAST('262142-12-31'::date AS text)::text, TRY_CAST('262142-12-31'::date AS text)::text IS NOT DISTINCT FROM CAST('262142-12-31'::date AS text)::text, TRY_CAST(NULL::date AS text) IS NULL
-----
-262142-12-31 true true
-
-## oid sources
-
-# oid -> int4
-query TBB
-SELECT TRY_CAST(1::oid AS int4)::text, TRY_CAST(1::oid AS int4)::text IS NOT DISTINCT FROM CAST(1::oid AS int4)::text, TRY_CAST(NULL::oid AS int4) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid AS int4)::text, TRY_CAST(4294967295::oid AS int4)::text IS NOT DISTINCT FROM CAST(4294967295::oid AS int4)::text, TRY_CAST(NULL::oid AS int4) IS NULL
-----
--1 true true
-
-# oid -> int8
-query TBB
-SELECT TRY_CAST(1::oid AS int8)::text, TRY_CAST(1::oid AS int8)::text IS NOT DISTINCT FROM CAST(1::oid AS int8)::text, TRY_CAST(NULL::oid AS int8) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid AS int8)::text, TRY_CAST(4294967295::oid AS int8)::text IS NOT DISTINCT FROM CAST(4294967295::oid AS int8)::text, TRY_CAST(NULL::oid AS int8) IS NULL
-----
-4294967295 true true
-
-# oid -> text
-query TBB
-SELECT TRY_CAST(1::oid AS text)::text, TRY_CAST(1::oid AS text)::text IS NOT DISTINCT FROM CAST(1::oid AS text)::text, TRY_CAST(NULL::oid AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid AS text)::text, TRY_CAST(4294967295::oid AS text)::text IS NOT DISTINCT FROM CAST(4294967295::oid AS text)::text, TRY_CAST(NULL::oid AS text) IS NULL
-----
-4294967295 true true
-
-# oid -> regclass
-query TBB
-SELECT TRY_CAST(1::oid AS regclass)::text, TRY_CAST(1::oid AS regclass)::text IS NOT DISTINCT FROM CAST(1::oid AS regclass)::text, TRY_CAST(NULL::oid AS regclass) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid AS regclass)::text, TRY_CAST(4294967295::oid AS regclass)::text IS NOT DISTINCT FROM CAST(4294967295::oid AS regclass)::text, TRY_CAST(NULL::oid AS regclass) IS NULL
-----
-4294967295 true true
-
-# oid -> regproc
-query TBB
-SELECT TRY_CAST(1::oid AS regproc)::text, TRY_CAST(1::oid AS regproc)::text IS NOT DISTINCT FROM CAST(1::oid AS regproc)::text, TRY_CAST(NULL::oid AS regproc) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid AS regproc)::text, TRY_CAST(4294967295::oid AS regproc)::text IS NOT DISTINCT FROM CAST(4294967295::oid AS regproc)::text, TRY_CAST(NULL::oid AS regproc) IS NULL
-----
-4294967295 true true
-
-# oid -> regtype
-query TBB
-SELECT TRY_CAST(1::oid AS regtype)::text, TRY_CAST(1::oid AS regtype)::text IS NOT DISTINCT FROM CAST(1::oid AS regtype)::text, TRY_CAST(NULL::oid AS regtype) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid AS regtype)::text, TRY_CAST(4294967295::oid AS regtype)::text IS NOT DISTINCT FROM CAST(4294967295::oid AS regtype)::text, TRY_CAST(NULL::oid AS regtype) IS NULL
-----
-4294967295 true true
-
-## regclass sources
-
-# regclass -> oid
-query TBB
-SELECT TRY_CAST(1::regclass AS oid)::text, TRY_CAST(1::regclass AS oid)::text IS NOT DISTINCT FROM CAST(1::regclass AS oid)::text, TRY_CAST(NULL::regclass AS oid) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid::regclass AS oid)::text, TRY_CAST(4294967295::oid::regclass AS oid)::text IS NOT DISTINCT FROM CAST(4294967295::oid::regclass AS oid)::text, TRY_CAST(NULL::regclass AS oid) IS NULL
-----
-4294967295 true true
-
-## regproc sources
-
-# regproc -> oid
-query TBB
-SELECT TRY_CAST(1::regproc AS oid)::text, TRY_CAST(1::regproc AS oid)::text IS NOT DISTINCT FROM CAST(1::regproc AS oid)::text, TRY_CAST(NULL::regproc AS oid) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid::regproc AS oid)::text, TRY_CAST(4294967295::oid::regproc AS oid)::text IS NOT DISTINCT FROM CAST(4294967295::oid::regproc AS oid)::text, TRY_CAST(NULL::regproc AS oid) IS NULL
-----
-4294967295 true true
-
-## regtype sources
-
-# regtype -> oid
-query TBB
-SELECT TRY_CAST(1::regtype AS oid)::text, TRY_CAST(1::regtype AS oid)::text IS NOT DISTINCT FROM CAST(1::regtype AS oid)::text, TRY_CAST(NULL::regtype AS oid) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::oid::regtype AS oid)::text, TRY_CAST(4294967295::oid::regtype AS oid)::text IS NOT DISTINCT FROM CAST(4294967295::oid::regtype AS oid)::text, TRY_CAST(NULL::regtype AS oid) IS NULL
-----
-4294967295 true true
-
-## real sources
-
-# real -> int2
-query TBB
-SELECT TRY_CAST(1.5::float4 AS int2)::text, TRY_CAST(1.5::float4 AS int2)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS int2)::text, TRY_CAST(NULL::float4 AS int2) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS int2)
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS int2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS int2)::text, TRY_CAST((-1.5)::float4 AS int2)::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS int2)::text, TRY_CAST(NULL::float4 AS int2) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::float4 AS int2)
-
-query T
-SELECT TRY_CAST('NaN'::float4 AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float4 AS int2)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS int2)::text
-----
-NULL
-
-# real -> int4
-query TBB
-SELECT TRY_CAST(1.5::float4 AS int4)::text, TRY_CAST(1.5::float4 AS int4)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS int4)::text, TRY_CAST(NULL::float4 AS int4) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS int4)
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS int4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS int4)::text, TRY_CAST((-1.5)::float4 AS int4)::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS int4)::text, TRY_CAST(NULL::float4 AS int4) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::float4 AS int4)
-
-query T
-SELECT TRY_CAST('NaN'::float4 AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float4 AS int4)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS int4)::text
-----
-NULL
-
-# real -> int8
-query TBB
-SELECT TRY_CAST(1.5::float4 AS int8)::text, TRY_CAST(1.5::float4 AS int8)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS int8)::text, TRY_CAST(NULL::float4 AS int8) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS int8)
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS int8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS int8)::text, TRY_CAST((-1.5)::float4 AS int8)::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS int8)::text, TRY_CAST(NULL::float4 AS int8) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::float4 AS int8)
-
-query T
-SELECT TRY_CAST('NaN'::float4 AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float4 AS int8)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS int8)::text
-----
-NULL
-
-# real -> uint2
-query TBB
-SELECT TRY_CAST(1.5::float4 AS uint2)::text, TRY_CAST(1.5::float4 AS uint2)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS uint2)::text, TRY_CAST(NULL::float4 AS uint2) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS uint2)
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::float4 AS uint2)
-
-query T
-SELECT TRY_CAST((-1.5)::float4 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::float4 AS uint2)
-
-query T
-SELECT TRY_CAST('NaN'::float4 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float4 AS uint2)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS uint2)::text
-----
-NULL
-
-# real -> uint4
-query TBB
-SELECT TRY_CAST(1.5::float4 AS uint4)::text, TRY_CAST(1.5::float4 AS uint4)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS uint4)::text, TRY_CAST(NULL::float4 AS uint4) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS uint4)
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::float4 AS uint4)
-
-query T
-SELECT TRY_CAST((-1.5)::float4 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::float4 AS uint4)
-
-query T
-SELECT TRY_CAST('NaN'::float4 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float4 AS uint4)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS uint4)::text
-----
-NULL
-
-# real -> uint8
-query TBB
-SELECT TRY_CAST(1.5::float4 AS uint8)::text, TRY_CAST(1.5::float4 AS uint8)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS uint8)::text, TRY_CAST(NULL::float4 AS uint8) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS uint8)
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::float4 AS uint8)
-
-query T
-SELECT TRY_CAST((-1.5)::float4 AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::float4 AS uint8)
-
-query T
-SELECT TRY_CAST('NaN'::float4 AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float4 AS uint8)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS uint8)::text
-----
-NULL
-
-# real -> float8
-query TBB
-SELECT TRY_CAST(1.5::float4 AS float8)::text, TRY_CAST(1.5::float4 AS float8)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS float8)::text, TRY_CAST(NULL::float4 AS float8) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST('3.4e38'::float4 AS float8)::text, TRY_CAST('3.4e38'::float4 AS float8)::text IS NOT DISTINCT FROM CAST('3.4e38'::float4 AS float8)::text, TRY_CAST(NULL::float4 AS float8) IS NULL
-----
-3.3999999521443642e+38 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS float8)::text, TRY_CAST((-1.5)::float4 AS float8)::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS float8)::text, TRY_CAST(NULL::float4 AS float8) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float4 AS float8)::text, TRY_CAST('NaN'::float4 AS float8)::text IS NOT DISTINCT FROM CAST('NaN'::float4 AS float8)::text, TRY_CAST(NULL::float4 AS float8) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST('Infinity'::float4 AS float8)::text, TRY_CAST('Infinity'::float4 AS float8)::text IS NOT DISTINCT FROM CAST('Infinity'::float4 AS float8)::text, TRY_CAST(NULL::float4 AS float8) IS NULL
-----
-Infinity true true
-
-# real -> numeric
-query TBB
-SELECT TRY_CAST(1.5::float4 AS numeric)::text, TRY_CAST(1.5::float4 AS numeric)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS numeric)::text, TRY_CAST(NULL::float4 AS numeric) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST('3.4e38'::float4 AS numeric)::text, TRY_CAST('3.4e38'::float4 AS numeric)::text IS NOT DISTINCT FROM CAST('3.4e38'::float4 AS numeric)::text, TRY_CAST(NULL::float4 AS numeric) IS NULL
-----
-340000000000000000000000000000000000000 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS numeric)::text, TRY_CAST((-1.5)::float4 AS numeric)::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS numeric)::text, TRY_CAST(NULL::float4 AS numeric) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float4 AS numeric)::text, TRY_CAST('NaN'::float4 AS numeric)::text IS NOT DISTINCT FROM CAST('NaN'::float4 AS numeric)::text, TRY_CAST(NULL::float4 AS numeric) IS NULL
-----
-NaN true true
-
-statement error
-SELECT CAST('Infinity'::float4 AS numeric)
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS numeric)::text
-----
-NULL
-
-# real -> text
-query TBB
-SELECT TRY_CAST(1.5::float4 AS text)::text, TRY_CAST(1.5::float4 AS text)::text IS NOT DISTINCT FROM CAST(1.5::float4 AS text)::text, TRY_CAST(NULL::float4 AS text) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST('3.4e38'::float4 AS text)::text, TRY_CAST('3.4e38'::float4 AS text)::text IS NOT DISTINCT FROM CAST('3.4e38'::float4 AS text)::text, TRY_CAST(NULL::float4 AS text) IS NULL
-----
-3.4e+38 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS text)::text, TRY_CAST((-1.5)::float4 AS text)::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS text)::text, TRY_CAST(NULL::float4 AS text) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float4 AS text)::text, TRY_CAST('NaN'::float4 AS text)::text IS NOT DISTINCT FROM CAST('NaN'::float4 AS text)::text, TRY_CAST(NULL::float4 AS text) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST('Infinity'::float4 AS text)::text, TRY_CAST('Infinity'::float4 AS text)::text IS NOT DISTINCT FROM CAST('Infinity'::float4 AS text)::text, TRY_CAST(NULL::float4 AS text) IS NULL
-----
-Infinity true true
-
-## double precision sources
-
-# double precision -> int2
-query TBB
-SELECT TRY_CAST(1.5::float8 AS int2)::text, TRY_CAST(1.5::float8 AS int2)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS int2)::text, TRY_CAST(NULL::float8 AS int2) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS int2)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS int2)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS int2)::text, TRY_CAST((-1.5)::float8 AS int2)::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS int2)::text, TRY_CAST(NULL::float8 AS int2) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::float8 AS int2)
-
-query T
-SELECT TRY_CAST('NaN'::float8 AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float8 AS int2)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS int2)::text
-----
-NULL
-
-# double precision -> int4
-query TBB
-SELECT TRY_CAST(1.5::float8 AS int4)::text, TRY_CAST(1.5::float8 AS int4)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS int4)::text, TRY_CAST(NULL::float8 AS int4) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS int4)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS int4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS int4)::text, TRY_CAST((-1.5)::float8 AS int4)::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS int4)::text, TRY_CAST(NULL::float8 AS int4) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::float8 AS int4)
-
-query T
-SELECT TRY_CAST('NaN'::float8 AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float8 AS int4)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS int4)::text
-----
-NULL
-
-# double precision -> int8
-query TBB
-SELECT TRY_CAST(1.5::float8 AS int8)::text, TRY_CAST(1.5::float8 AS int8)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS int8)::text, TRY_CAST(NULL::float8 AS int8) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS int8)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS int8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS int8)::text, TRY_CAST((-1.5)::float8 AS int8)::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS int8)::text, TRY_CAST(NULL::float8 AS int8) IS NULL
-----
--2 true true
-
-statement error
-SELECT CAST('NaN'::float8 AS int8)
-
-query T
-SELECT TRY_CAST('NaN'::float8 AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float8 AS int8)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS int8)::text
-----
-NULL
-
-# double precision -> uint2
-query TBB
-SELECT TRY_CAST(1.5::float8 AS uint2)::text, TRY_CAST(1.5::float8 AS uint2)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS uint2)::text, TRY_CAST(NULL::float8 AS uint2) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS uint2)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::float8 AS uint2)
-
-query T
-SELECT TRY_CAST((-1.5)::float8 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::float8 AS uint2)
-
-query T
-SELECT TRY_CAST('NaN'::float8 AS uint2)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float8 AS uint2)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS uint2)::text
-----
-NULL
-
-# double precision -> uint4
-query TBB
-SELECT TRY_CAST(1.5::float8 AS uint4)::text, TRY_CAST(1.5::float8 AS uint4)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS uint4)::text, TRY_CAST(NULL::float8 AS uint4) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS uint4)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::float8 AS uint4)
-
-query T
-SELECT TRY_CAST((-1.5)::float8 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::float8 AS uint4)
-
-query T
-SELECT TRY_CAST('NaN'::float8 AS uint4)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float8 AS uint4)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS uint4)::text
-----
-NULL
-
-# double precision -> uint8
-query TBB
-SELECT TRY_CAST(1.5::float8 AS uint8)::text, TRY_CAST(1.5::float8 AS uint8)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS uint8)::text, TRY_CAST(NULL::float8 AS uint8) IS NULL
-----
-2 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS uint8)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST((-1.5)::float8 AS uint8)
-
-query T
-SELECT TRY_CAST((-1.5)::float8 AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST('NaN'::float8 AS uint8)
-
-query T
-SELECT TRY_CAST('NaN'::float8 AS uint8)::text
-----
-NULL
-
-statement error
-SELECT CAST('Infinity'::float8 AS uint8)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS uint8)::text
-----
-NULL
-
-# double precision -> float4
-query TBB
-SELECT TRY_CAST(1.5::float8 AS float4)::text, TRY_CAST(1.5::float8 AS float4)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS float4)::text, TRY_CAST(NULL::float8 AS float4) IS NULL
-----
-1.5 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS float4)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS float4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS float4)::text, TRY_CAST((-1.5)::float8 AS float4)::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS float4)::text, TRY_CAST(NULL::float8 AS float4) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float8 AS float4)::text, TRY_CAST('NaN'::float8 AS float4)::text IS NOT DISTINCT FROM CAST('NaN'::float8 AS float4)::text, TRY_CAST(NULL::float8 AS float4) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST('Infinity'::float8 AS float4)::text, TRY_CAST('Infinity'::float8 AS float4)::text IS NOT DISTINCT FROM CAST('Infinity'::float8 AS float4)::text, TRY_CAST(NULL::float8 AS float4) IS NULL
-----
-Infinity true true
-
-# double precision -> numeric
-query TBB
-SELECT TRY_CAST(1.5::float8 AS numeric)::text, TRY_CAST(1.5::float8 AS numeric)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS numeric)::text, TRY_CAST(NULL::float8 AS numeric) IS NULL
-----
-1.5 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS numeric)
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS numeric)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS numeric)::text, TRY_CAST((-1.5)::float8 AS numeric)::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS numeric)::text, TRY_CAST(NULL::float8 AS numeric) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float8 AS numeric)::text, TRY_CAST('NaN'::float8 AS numeric)::text IS NOT DISTINCT FROM CAST('NaN'::float8 AS numeric)::text, TRY_CAST(NULL::float8 AS numeric) IS NULL
-----
-NaN true true
-
-statement error
-SELECT CAST('Infinity'::float8 AS numeric)
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS numeric)::text
-----
-NULL
-
-# double precision -> text
-query TBB
-SELECT TRY_CAST(1.5::float8 AS text)::text, TRY_CAST(1.5::float8 AS text)::text IS NOT DISTINCT FROM CAST(1.5::float8 AS text)::text, TRY_CAST(NULL::float8 AS text) IS NULL
-----
-1.5 true true
-
-query TBB
-SELECT TRY_CAST('1.7e308'::float8 AS text)::text, TRY_CAST('1.7e308'::float8 AS text)::text IS NOT DISTINCT FROM CAST('1.7e308'::float8 AS text)::text, TRY_CAST(NULL::float8 AS text) IS NULL
-----
-1.7e+308 true true
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS text)::text, TRY_CAST((-1.5)::float8 AS text)::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS text)::text, TRY_CAST(NULL::float8 AS text) IS NULL
-----
--1.5 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float8 AS text)::text, TRY_CAST('NaN'::float8 AS text)::text IS NOT DISTINCT FROM CAST('NaN'::float8 AS text)::text, TRY_CAST(NULL::float8 AS text) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST('Infinity'::float8 AS text)::text, TRY_CAST('Infinity'::float8 AS text)::text IS NOT DISTINCT FROM CAST('Infinity'::float8 AS text)::text, TRY_CAST(NULL::float8 AS text) IS NULL
-----
-Infinity true true
-
-## time sources
-
-# time -> interval
-query TBB
-SELECT TRY_CAST('12:34:56'::time AS interval)::text, TRY_CAST('12:34:56'::time AS interval)::text IS NOT DISTINCT FROM CAST('12:34:56'::time AS interval)::text, TRY_CAST(NULL::time AS interval) IS NULL
-----
-12:34:56 true true
-
-# time -> text
-query TBB
-SELECT TRY_CAST('12:34:56'::time AS text)::text, TRY_CAST('12:34:56'::time AS text)::text IS NOT DISTINCT FROM CAST('12:34:56'::time AS text)::text, TRY_CAST(NULL::time AS text) IS NULL
-----
-12:34:56 true true
-
-## interval sources
-
-# interval -> time
-query TBB
-SELECT TRY_CAST('1 day 02:03:04'::interval AS time)::text, TRY_CAST('1 day 02:03:04'::interval AS time)::text IS NOT DISTINCT FROM CAST('1 day 02:03:04'::interval AS time)::text, TRY_CAST(NULL::interval AS time) IS NULL
-----
-02:03:04 true true
-
-query TBB
-SELECT TRY_CAST('178000000 years'::interval AS time)::text, TRY_CAST('178000000 years'::interval AS time)::text IS NOT DISTINCT FROM CAST('178000000 years'::interval AS time)::text, TRY_CAST(NULL::interval AS time) IS NULL
-----
-00:00:00 true true
-
-# interval -> text
-query TBB
-SELECT TRY_CAST('1 day 02:03:04'::interval AS text)::text, TRY_CAST('1 day 02:03:04'::interval AS text)::text IS NOT DISTINCT FROM CAST('1 day 02:03:04'::interval AS text)::text, TRY_CAST(NULL::interval AS text) IS NULL
-----
-1␠day␠02:03:04 true true
-
-query TBB
-SELECT TRY_CAST('178000000 years'::interval AS text)::text, TRY_CAST('178000000 years'::interval AS text)::text IS NOT DISTINCT FROM CAST('178000000 years'::interval AS text)::text, TRY_CAST(NULL::interval AS text) IS NULL
-----
-178000000␠years true true
-
-## bytea sources
-
-# bytea -> text
-query TBB
-SELECT TRY_CAST('\x0102'::bytea AS text)::text, TRY_CAST('\x0102'::bytea AS text)::text IS NOT DISTINCT FROM CAST('\x0102'::bytea AS text)::text, TRY_CAST(NULL::bytea AS text) IS NULL
-----
-\x0102 true true
-
-## char sources
-
-# char -> text
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS text)::text, TRY_CAST('abc'::char(3) AS text)::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS text)::text, TRY_CAST(NULL::char(3) AS text) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS text)::text, TRY_CAST('abc'::char(3) AS text)::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS text)::text, TRY_CAST(NULL::char(3) AS text) IS NULL
-----
-abc true true
-
-# char -> char(3)
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS char(3))::text, TRY_CAST('abc'::char(3) AS char(3))::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS char(3))::text, TRY_CAST(NULL::char(3) AS char(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS char(3))::text, TRY_CAST('abc'::char(3) AS char(3))::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS char(3))::text, TRY_CAST(NULL::char(3) AS char(3)) IS NULL
-----
-abc true true
-
-# char -> varchar(3)
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS varchar(3))::text, TRY_CAST('abc'::char(3) AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS varchar(3))::text, TRY_CAST(NULL::char(3) AS varchar(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS varchar(3))::text, TRY_CAST('abc'::char(3) AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS varchar(3))::text, TRY_CAST(NULL::char(3) AS varchar(3)) IS NULL
-----
-abc true true
-
-# char -> "char"
-query TBB
-SELECT TRY_CAST('a'::char(3) AS "char")::text, TRY_CAST('a'::char(3) AS "char")::text IS NOT DISTINCT FROM CAST('a'::char(3) AS "char")::text, TRY_CAST(NULL::char(3) AS "char") IS NULL
-----
-a true true
-
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS "char")::text, TRY_CAST('abc'::char(3) AS "char")::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS "char")::text, TRY_CAST(NULL::char(3) AS "char") IS NULL
-----
-a true true
-
-# char -> name
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS name)::text, TRY_CAST('abc'::char(3) AS name)::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS name)::text, TRY_CAST(NULL::char(3) AS name) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::char(3) AS name)::text, TRY_CAST('abc'::char(3) AS name)::text IS NOT DISTINCT FROM CAST('abc'::char(3) AS name)::text, TRY_CAST(NULL::char(3) AS name) IS NULL
-----
-abc true true
-
-## varchar sources
-
-# varchar -> text
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS text)::text, TRY_CAST('abc'::varchar(3) AS text)::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS text)::text, TRY_CAST(NULL::varchar(3) AS text) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS text)::text, TRY_CAST('abc'::varchar(3) AS text)::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS text)::text, TRY_CAST(NULL::varchar(3) AS text) IS NULL
-----
-abc true true
-
-# varchar -> char(3)
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS char(3))::text, TRY_CAST('abc'::varchar(3) AS char(3))::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS char(3))::text, TRY_CAST(NULL::varchar(3) AS char(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS char(3))::text, TRY_CAST('abc'::varchar(3) AS char(3))::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS char(3))::text, TRY_CAST(NULL::varchar(3) AS char(3)) IS NULL
-----
-abc true true
-
-# varchar -> varchar(3)
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS varchar(3))::text, TRY_CAST('abc'::varchar(3) AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS varchar(3))::text, TRY_CAST(NULL::varchar(3) AS varchar(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS varchar(3))::text, TRY_CAST('abc'::varchar(3) AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS varchar(3))::text, TRY_CAST(NULL::varchar(3) AS varchar(3)) IS NULL
-----
-abc true true
-
-# varchar -> "char"
-query TBB
-SELECT TRY_CAST('a'::varchar(3) AS "char")::text, TRY_CAST('a'::varchar(3) AS "char")::text IS NOT DISTINCT FROM CAST('a'::varchar(3) AS "char")::text, TRY_CAST(NULL::varchar(3) AS "char") IS NULL
-----
-a true true
-
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS "char")::text, TRY_CAST('abc'::varchar(3) AS "char")::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS "char")::text, TRY_CAST(NULL::varchar(3) AS "char") IS NULL
-----
-a true true
-
-# varchar -> name
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS name)::text, TRY_CAST('abc'::varchar(3) AS name)::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS name)::text, TRY_CAST(NULL::varchar(3) AS name) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::varchar(3) AS name)::text, TRY_CAST('abc'::varchar(3) AS name)::text IS NOT DISTINCT FROM CAST('abc'::varchar(3) AS name)::text, TRY_CAST(NULL::varchar(3) AS name) IS NULL
-----
-abc true true
-
-## "char" sources
-
-# "char" -> text
-query TBB
-SELECT TRY_CAST('a'::"char" AS text)::text, TRY_CAST('a'::"char" AS text)::text IS NOT DISTINCT FROM CAST('a'::"char" AS text)::text, TRY_CAST(NULL::"char" AS text) IS NULL
-----
-a true true
-
-# "char" -> char(3)
-query TBB
-SELECT TRY_CAST('a'::"char" AS char(3))::text, TRY_CAST('a'::"char" AS char(3))::text IS NOT DISTINCT FROM CAST('a'::"char" AS char(3))::text, TRY_CAST(NULL::"char" AS char(3)) IS NULL
-----
-a true true
-
-# "char" -> varchar(3)
-query TBB
-SELECT TRY_CAST('a'::"char" AS varchar(3))::text, TRY_CAST('a'::"char" AS varchar(3))::text IS NOT DISTINCT FROM CAST('a'::"char" AS varchar(3))::text, TRY_CAST(NULL::"char" AS varchar(3)) IS NULL
-----
-a true true
-
-# "char" -> int4 (by byte value)
-query TBB
-SELECT TRY_CAST('a'::"char" AS int4)::text, TRY_CAST('a'::"char" AS int4)::text IS NOT DISTINCT FROM CAST('a'::"char" AS int4)::text, TRY_CAST(NULL::"char" AS int4) IS NULL
-----
-97 true true
-
-# "char" -> int8 (rendered to text, then parsed)
-query TBB
-SELECT TRY_CAST('7'::"char" AS int8)::text, TRY_CAST('7'::"char" AS int8)::text IS NOT DISTINCT FROM CAST('7'::"char" AS int8)::text, TRY_CAST(NULL::"char" AS int8) IS NULL
-----
-7 true true
-
-statement error
-SELECT CAST('a'::"char" AS int8)
-
-query T
-SELECT TRY_CAST('a'::"char" AS int8)::text
-----
-NULL
-
-## name sources
-
-# name -> text
-query TBB
-SELECT TRY_CAST('abc'::name AS text)::text, TRY_CAST('abc'::name AS text)::text IS NOT DISTINCT FROM CAST('abc'::name AS text)::text, TRY_CAST(NULL::name AS text) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::name AS text)::text, TRY_CAST('abc'::name AS text)::text IS NOT DISTINCT FROM CAST('abc'::name AS text)::text, TRY_CAST(NULL::name AS text) IS NULL
-----
-abc true true
-
-# name -> char(3)
-query TBB
-SELECT TRY_CAST('abc'::name AS char(3))::text, TRY_CAST('abc'::name AS char(3))::text IS NOT DISTINCT FROM CAST('abc'::name AS char(3))::text, TRY_CAST(NULL::name AS char(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::name AS char(3))::text, TRY_CAST('abc'::name AS char(3))::text IS NOT DISTINCT FROM CAST('abc'::name AS char(3))::text, TRY_CAST(NULL::name AS char(3)) IS NULL
-----
-abc true true
-
-# name -> varchar(3)
-query TBB
-SELECT TRY_CAST('abc'::name AS varchar(3))::text, TRY_CAST('abc'::name AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc'::name AS varchar(3))::text, TRY_CAST(NULL::name AS varchar(3)) IS NULL
-----
-abc true true
-
-query TBB
-SELECT TRY_CAST('abc'::name AS varchar(3))::text, TRY_CAST('abc'::name AS varchar(3))::text IS NOT DISTINCT FROM CAST('abc'::name AS varchar(3))::text, TRY_CAST(NULL::name AS varchar(3)) IS NULL
-----
-abc true true
-
-## record sources
-
-# record -> text
-query TBB
-SELECT TRY_CAST(ROW(1, 'a') AS text)::text, TRY_CAST(ROW(1, 'a') AS text)::text IS NOT DISTINCT FROM CAST(ROW(1, 'a') AS text)::text, TRY_CAST(NULL::rec8 AS text) IS NULL
-----
-(1,a) true true
-
-query TBB
-SELECT TRY_CAST(ROW(100000, 'a') AS text)::text, TRY_CAST(ROW(100000, 'a') AS text)::text IS NOT DISTINCT FROM CAST(ROW(100000, 'a') AS text)::text, TRY_CAST(NULL::rec8 AS text) IS NULL
-----
-(100000,a) true true
-
-# record -> rec8
-query TBB
-SELECT TRY_CAST(ROW(1, 'a') AS rec8)::text, TRY_CAST(ROW(1, 'a') AS rec8)::text IS NOT DISTINCT FROM CAST(ROW(1, 'a') AS rec8)::text, TRY_CAST(NULL::rec8 AS rec8) IS NULL
-----
-(1,a) true true
-
-query TBB
-SELECT TRY_CAST(ROW(100000, 'a') AS rec8)::text, TRY_CAST(ROW(100000, 'a') AS rec8)::text IS NOT DISTINCT FROM CAST(ROW(100000, 'a') AS rec8)::text, TRY_CAST(NULL::rec8 AS rec8) IS NULL
-----
-(100000,a) true true
-
-# record -> rec2
-query TBB
-SELECT TRY_CAST(ROW(1, 'a') AS rec2)::text, TRY_CAST(ROW(1, 'a') AS rec2)::text IS NOT DISTINCT FROM CAST(ROW(1, 'a') AS rec2)::text, TRY_CAST(NULL::rec8 AS rec2) IS NULL
-----
-(1,a) true true
-
-statement error
-SELECT CAST(ROW(100000, 'a') AS rec2)
-
-query T
-SELECT TRY_CAST(ROW(100000, 'a') AS rec2)::text
-----
-NULL
-
-## array sources
-
-# array -> text
-query TBB
-SELECT TRY_CAST(ARRAY[1, 2] AS text)::text, TRY_CAST(ARRAY[1, 2] AS text)::text IS NOT DISTINCT FROM CAST(ARRAY[1, 2] AS text)::text, TRY_CAST(NULL::int8[] AS text) IS NULL
-----
-{1,2} true true
-
-query TBB
-SELECT TRY_CAST(ARRAY[100000] AS text)::text, TRY_CAST(ARRAY[100000] AS text)::text IS NOT DISTINCT FROM CAST(ARRAY[100000] AS text)::text, TRY_CAST(NULL::int8[] AS text) IS NULL
-----
-{100000} true true
-
-# array -> int8 list
-query TBB
-SELECT TRY_CAST(ARRAY[1, 2] AS int8 list)::text, TRY_CAST(ARRAY[1, 2] AS int8 list)::text IS NOT DISTINCT FROM CAST(ARRAY[1, 2] AS int8 list)::text, TRY_CAST(NULL::int8[] AS int8 list) IS NULL
-----
-{1,2} true true
-
-query TBB
-SELECT TRY_CAST(ARRAY[100000] AS int8 list)::text, TRY_CAST(ARRAY[100000] AS int8 list)::text IS NOT DISTINCT FROM CAST(ARRAY[100000] AS int8 list)::text, TRY_CAST(NULL::int8[] AS int8 list) IS NULL
-----
-{100000} true true
-
-# array -> int2 list
-query TBB
-SELECT TRY_CAST(ARRAY[1, 2] AS int2 list)::text, TRY_CAST(ARRAY[1, 2] AS int2 list)::text IS NOT DISTINCT FROM CAST(ARRAY[1, 2] AS int2 list)::text, TRY_CAST(NULL::int8[] AS int2 list) IS NULL
-----
-{1,2} true true
-
-query TBB
-SELECT TRY_CAST(ARRAY[100000] AS int2 list)::text, TRY_CAST(ARRAY[100000] AS int2 list)::text IS NOT DISTINCT FROM CAST(ARRAY[100000] AS int2 list)::text, TRY_CAST(NULL::int8[] AS int2 list) IS NULL
-----
-{100000} true true
-
-# array -> int8[]
-query TBB
-SELECT TRY_CAST(ARRAY[1, 2] AS int8[])::text, TRY_CAST(ARRAY[1, 2] AS int8[])::text IS NOT DISTINCT FROM CAST(ARRAY[1, 2] AS int8[])::text, TRY_CAST(NULL::int8[] AS int8[]) IS NULL
-----
-{1,2} true true
-
-query TBB
-SELECT TRY_CAST(ARRAY[100000] AS int8[])::text, TRY_CAST(ARRAY[100000] AS int8[])::text IS NOT DISTINCT FROM CAST(ARRAY[100000] AS int8[])::text, TRY_CAST(NULL::int8[] AS int8[]) IS NULL
-----
-{100000} true true
-
-# array -> int2[]
-query TBB
-SELECT TRY_CAST(ARRAY[1, 2] AS int2[])::text, TRY_CAST(ARRAY[1, 2] AS int2[])::text IS NOT DISTINCT FROM CAST(ARRAY[1, 2] AS int2[])::text, TRY_CAST(NULL::int8[] AS int2[]) IS NULL
-----
-{1,2} true true
-
-statement error
-SELECT CAST(ARRAY[100000] AS int2[])
-
-query T
-SELECT TRY_CAST(ARRAY[100000] AS int2[])::text
-----
-NULL
-
-## int2vector sources
-
-# int2vector -> int8[]
-query TBB
-SELECT TRY_CAST('1 2'::int2vector AS int8[])::text, TRY_CAST('1 2'::int2vector AS int8[])::text IS NOT DISTINCT FROM CAST('1 2'::int2vector AS int8[])::text, TRY_CAST(NULL::int2vector AS int8[]) IS NULL
-----
-{1,2} true true
-
-# int2vector -> int2[]
-query TBB
-SELECT TRY_CAST('1 2'::int2vector AS int2[])::text, TRY_CAST('1 2'::int2vector AS int2[])::text IS NOT DISTINCT FROM CAST('1 2'::int2vector AS int2[])::text, TRY_CAST(NULL::int2vector AS int2[]) IS NULL
-----
-{1,2} true true
-
-# int2vector -> text
-query TBB
-SELECT TRY_CAST('1 2'::int2vector AS text)::text, TRY_CAST('1 2'::int2vector AS text)::text IS NOT DISTINCT FROM CAST('1 2'::int2vector AS text)::text, TRY_CAST(NULL::int2vector AS text) IS NULL
-----
-1␠2 true true
-
-## list sources
-
-# list -> text
-query TBB
-SELECT TRY_CAST(LIST[1, 2] AS text)::text, TRY_CAST(LIST[1, 2] AS text)::text IS NOT DISTINCT FROM CAST(LIST[1, 2] AS text)::text, TRY_CAST(NULL::int8 list AS text) IS NULL
-----
-{1,2} true true
-
-query TBB
-SELECT TRY_CAST(LIST[100000] AS text)::text, TRY_CAST(LIST[100000] AS text)::text IS NOT DISTINCT FROM CAST(LIST[100000] AS text)::text, TRY_CAST(NULL::int8 list AS text) IS NULL
-----
-{100000} true true
-
-# list -> int8 list
-query TBB
-SELECT TRY_CAST(LIST[1, 2] AS int8 list)::text, TRY_CAST(LIST[1, 2] AS int8 list)::text IS NOT DISTINCT FROM CAST(LIST[1, 2] AS int8 list)::text, TRY_CAST(NULL::int8 list AS int8 list) IS NULL
-----
-{1,2} true true
-
-query TBB
-SELECT TRY_CAST(LIST[100000] AS int8 list)::text, TRY_CAST(LIST[100000] AS int8 list)::text IS NOT DISTINCT FROM CAST(LIST[100000] AS int8 list)::text, TRY_CAST(NULL::int8 list AS int8 list) IS NULL
-----
-{100000} true true
-
-# list -> int2 list
-query TBB
-SELECT TRY_CAST(LIST[1, 2] AS int2 list)::text, TRY_CAST(LIST[1, 2] AS int2 list)::text IS NOT DISTINCT FROM CAST(LIST[1, 2] AS int2 list)::text, TRY_CAST(NULL::int8 list AS int2 list) IS NULL
-----
-{1,2} true true
-
-statement error
-SELECT CAST(LIST[100000] AS int2 list)
-
-query T
-SELECT TRY_CAST(LIST[100000] AS int2 list)::text
-----
-NULL
-
-## map sources
-
-# map -> text
-query TBB
-SELECT TRY_CAST('{a=>1}'::map[text=>int4] AS text)::text, TRY_CAST('{a=>1}'::map[text=>int4] AS text)::text IS NOT DISTINCT FROM CAST('{a=>1}'::map[text=>int4] AS text)::text, TRY_CAST(NULL::map[text=>int8] AS text) IS NULL
-----
-{a=>1} true true
-
-## jsonb sources
-
-# jsonb -> bool
-statement error
-SELECT CAST('1'::jsonb AS bool)
-
-query T
-SELECT TRY_CAST('1'::jsonb AS bool)::text
-----
-NULL
-
-statement error
-SELECT CAST('"x"'::jsonb AS bool)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS bool)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS bool)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS bool)::text
-----
-NULL
-
-statement error
-SELECT CAST('1e30'::jsonb AS bool)
-
-query T
-SELECT TRY_CAST('1e30'::jsonb AS bool)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('true'::jsonb AS bool)::text, TRY_CAST('true'::jsonb AS bool)::text IS NOT DISTINCT FROM CAST('true'::jsonb AS bool)::text, TRY_CAST(NULL::jsonb AS bool) IS NULL
-----
-true true true
-
-statement error
-SELECT CAST('null'::jsonb AS bool)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS bool)::text
-----
-NULL
-
-# jsonb -> int2
-query TBB
-SELECT TRY_CAST('1'::jsonb AS int2)::text, TRY_CAST('1'::jsonb AS int2)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS int2)::text, TRY_CAST(NULL::jsonb AS int2) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS int2)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS int2)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('1e30'::jsonb AS int2)
-
-query T
-SELECT TRY_CAST('1e30'::jsonb AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('true'::jsonb AS int2)
-
-query T
-SELECT TRY_CAST('true'::jsonb AS int2)::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS int2)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS int2)::text
-----
-NULL
-
-# jsonb -> int4
-query TBB
-SELECT TRY_CAST('1'::jsonb AS int4)::text, TRY_CAST('1'::jsonb AS int4)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS int4)::text, TRY_CAST(NULL::jsonb AS int4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS int4)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS int4)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('1e30'::jsonb AS int4)
-
-query T
-SELECT TRY_CAST('1e30'::jsonb AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('true'::jsonb AS int4)
-
-query T
-SELECT TRY_CAST('true'::jsonb AS int4)::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS int4)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS int4)::text
-----
-NULL
-
-# jsonb -> int8
-query TBB
-SELECT TRY_CAST('1'::jsonb AS int8)::text, TRY_CAST('1'::jsonb AS int8)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS int8)::text, TRY_CAST(NULL::jsonb AS int8) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS int8)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS int8)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('1e30'::jsonb AS int8)
-
-query T
-SELECT TRY_CAST('1e30'::jsonb AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('true'::jsonb AS int8)
-
-query T
-SELECT TRY_CAST('true'::jsonb AS int8)::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS int8)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS int8)::text
-----
-NULL
-
-# jsonb -> float4
-query TBB
-SELECT TRY_CAST('1'::jsonb AS float4)::text, TRY_CAST('1'::jsonb AS float4)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS float4)::text, TRY_CAST(NULL::jsonb AS float4) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS float4)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS float4)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS float4)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS float4)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('1e30'::jsonb AS float4)::text, TRY_CAST('1e30'::jsonb AS float4)::text IS NOT DISTINCT FROM CAST('1e30'::jsonb AS float4)::text, TRY_CAST(NULL::jsonb AS float4) IS NULL
-----
-1e+30 true true
-
-statement error
-SELECT CAST('true'::jsonb AS float4)
-
-query T
-SELECT TRY_CAST('true'::jsonb AS float4)::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS float4)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS float4)::text
-----
-NULL
-
-# jsonb -> float8
-query TBB
-SELECT TRY_CAST('1'::jsonb AS float8)::text, TRY_CAST('1'::jsonb AS float8)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS float8)::text, TRY_CAST(NULL::jsonb AS float8) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS float8)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS float8)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS float8)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS float8)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('1e30'::jsonb AS float8)::text, TRY_CAST('1e30'::jsonb AS float8)::text IS NOT DISTINCT FROM CAST('1e30'::jsonb AS float8)::text, TRY_CAST(NULL::jsonb AS float8) IS NULL
-----
-1e+30 true true
-
-statement error
-SELECT CAST('true'::jsonb AS float8)
-
-query T
-SELECT TRY_CAST('true'::jsonb AS float8)::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS float8)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS float8)::text
-----
-NULL
-
-# jsonb -> numeric
-query TBB
-SELECT TRY_CAST('1'::jsonb AS numeric)::text, TRY_CAST('1'::jsonb AS numeric)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS numeric)::text, TRY_CAST(NULL::jsonb AS numeric) IS NULL
-----
-1 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS numeric)
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS numeric)::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS numeric)
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS numeric)::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('1e30'::jsonb AS numeric)::text, TRY_CAST('1e30'::jsonb AS numeric)::text IS NOT DISTINCT FROM CAST('1e30'::jsonb AS numeric)::text, TRY_CAST(NULL::jsonb AS numeric) IS NULL
-----
-1000000000000000000000000000000 true true
-
-statement error
-SELECT CAST('true'::jsonb AS numeric)
-
-query T
-SELECT TRY_CAST('true'::jsonb AS numeric)::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS numeric)
-
-query T
-SELECT TRY_CAST('null'::jsonb AS numeric)::text
-----
-NULL
-
-# jsonb -> text
-query TBB
-SELECT TRY_CAST('1'::jsonb AS text)::text, TRY_CAST('1'::jsonb AS text)::text IS NOT DISTINCT FROM CAST('1'::jsonb AS text)::text, TRY_CAST(NULL::jsonb AS text) IS NULL
-----
-1 true true
-
-query TBB
-SELECT TRY_CAST('"x"'::jsonb AS text)::text, TRY_CAST('"x"'::jsonb AS text)::text IS NOT DISTINCT FROM CAST('"x"'::jsonb AS text)::text, TRY_CAST(NULL::jsonb AS text) IS NULL
-----
-"x" true true
-
-query TBB
-SELECT TRY_CAST('[1]'::jsonb AS text)::text, TRY_CAST('[1]'::jsonb AS text)::text IS NOT DISTINCT FROM CAST('[1]'::jsonb AS text)::text, TRY_CAST(NULL::jsonb AS text) IS NULL
-----
-[1] true true
-
-query TBB
-SELECT TRY_CAST('1e30'::jsonb AS text)::text, TRY_CAST('1e30'::jsonb AS text)::text IS NOT DISTINCT FROM CAST('1e30'::jsonb AS text)::text, TRY_CAST(NULL::jsonb AS text) IS NULL
-----
-1000000000000000000000000000000 true true
-
-query TBB
-SELECT TRY_CAST('true'::jsonb AS text)::text, TRY_CAST('true'::jsonb AS text)::text IS NOT DISTINCT FROM CAST('true'::jsonb AS text)::text, TRY_CAST(NULL::jsonb AS text) IS NULL
-----
-true true true
-
-query TBB
-SELECT TRY_CAST('null'::jsonb AS text)::text, TRY_CAST('null'::jsonb AS text)::text IS NOT DISTINCT FROM CAST('null'::jsonb AS text)::text, TRY_CAST(NULL::jsonb AS text) IS NULL
-----
-null true true
-
-## uuid sources
-
-# uuid -> text
-query TBB
-SELECT TRY_CAST('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid AS text)::text, TRY_CAST('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid AS text)::text IS NOT DISTINCT FROM CAST('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid AS text)::text, TRY_CAST(NULL::uuid AS text) IS NULL
-----
-a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 true true
-
-## range sources
-
-# range -> text
-query TBB
-SELECT TRY_CAST('[1,3)'::int4range AS text)::text, TRY_CAST('[1,3)'::int4range AS text)::text IS NOT DISTINCT FROM CAST('[1,3)'::int4range AS text)::text, TRY_CAST(NULL::int4range AS text) IS NULL
-----
-[1,3) true true
diff --git a/test/sqllogictest/try_cast_noindex.slt b/test/sqllogictest/try_cast_noindex.slt
deleted file mode 100644
index 9646ee0d468bb..0000000000000
--- a/test/sqllogictest/try_cast_noindex.slt
+++ /dev/null
@@ -1,274 +0,0 @@
-# Copyright Materialize, Inc. and contributors. All rights reserved.
-#
-# Use of this software is governed by the Business Source License
-# included in the LICENSE file at the root of this repository.
-#
-# 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.
-
-# The numeric(5,2) blocks of the TRY_CAST matrix in try_cast.slt. They live
-# apart because a constant-folded numeric(5,2) literal loses its scale on the
-# view path: `SELECT 1.5::numeric(5,2)::text` gives `1.50`, but the same
-# expression in a CREATE VIEW gives `1.5`, for CAST and TRY_CAST alike. The
-# indexed views that --auto-index-selects wraps queries in hit that, so this
-# file is kept out of that mode. The blocks have the same shape as in
-# try_cast.slt.
-
-mode cockroach
-
-simple conn=mz_system,user=mz_system
-ALTER SYSTEM SET enable_try_cast = true
-----
-COMPLETE 0
-
-## numeric(5,2) targets
-
-# smallint -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1::int2 AS numeric(5,2))::text, TRY_CAST(1::int2 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1::int2 AS numeric(5,2))::text, TRY_CAST(NULL::int2 AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-query TBB
-SELECT TRY_CAST(32767::int2 AS numeric(5,2))::text, TRY_CAST(32767::int2 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(32767::int2 AS numeric(5,2))::text, TRY_CAST(NULL::int2 AS numeric(5,2)) IS NULL
-----
-32767.00 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int2 AS numeric(5,2))::text, TRY_CAST((-1)::int2 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST((-1)::int2 AS numeric(5,2))::text, TRY_CAST(NULL::int2 AS numeric(5,2)) IS NULL
-----
--1.00 true true
-
-# integer -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1 AS numeric(5,2))::text, TRY_CAST(1 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1 AS numeric(5,2))::text, TRY_CAST(NULL::int4 AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-query TBB
-SELECT TRY_CAST(2147483647 AS numeric(5,2))::text, TRY_CAST(2147483647 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(2147483647 AS numeric(5,2))::text, TRY_CAST(NULL::int4 AS numeric(5,2)) IS NULL
-----
-2147483647.00 true true
-
-query TBB
-SELECT TRY_CAST(-1 AS numeric(5,2))::text, TRY_CAST(-1 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(-1 AS numeric(5,2))::text, TRY_CAST(NULL::int4 AS numeric(5,2)) IS NULL
-----
--1.00 true true
-
-query TBB
-SELECT TRY_CAST(100000 AS numeric(5,2))::text, TRY_CAST(100000 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(100000 AS numeric(5,2))::text, TRY_CAST(NULL::int4 AS numeric(5,2)) IS NULL
-----
-100000.00 true true
-
-# bigint -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1::int8 AS numeric(5,2))::text, TRY_CAST(1::int8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1::int8 AS numeric(5,2))::text, TRY_CAST(NULL::int8 AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-query TBB
-SELECT TRY_CAST(9223372036854775807::int8 AS numeric(5,2))::text, TRY_CAST(9223372036854775807::int8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(9223372036854775807::int8 AS numeric(5,2))::text, TRY_CAST(NULL::int8 AS numeric(5,2)) IS NULL
-----
-9223372036854775807.00 true true
-
-query TBB
-SELECT TRY_CAST((-1)::int8 AS numeric(5,2))::text, TRY_CAST((-1)::int8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST((-1)::int8 AS numeric(5,2))::text, TRY_CAST(NULL::int8 AS numeric(5,2)) IS NULL
-----
--1.00 true true
-
-query TBB
-SELECT TRY_CAST(3000000000::int8 AS numeric(5,2))::text, TRY_CAST(3000000000::int8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(3000000000::int8 AS numeric(5,2))::text, TRY_CAST(NULL::int8 AS numeric(5,2)) IS NULL
-----
-3000000000.00 true true
-
-# uint2 -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1::uint2 AS numeric(5,2))::text, TRY_CAST(1::uint2 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1::uint2 AS numeric(5,2))::text, TRY_CAST(NULL::uint2 AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-query TBB
-SELECT TRY_CAST(65535::uint2 AS numeric(5,2))::text, TRY_CAST(65535::uint2 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(65535::uint2 AS numeric(5,2))::text, TRY_CAST(NULL::uint2 AS numeric(5,2)) IS NULL
-----
-65535.00 true true
-
-# uint4 -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1::uint4 AS numeric(5,2))::text, TRY_CAST(1::uint4 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1::uint4 AS numeric(5,2))::text, TRY_CAST(NULL::uint4 AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-query TBB
-SELECT TRY_CAST(4294967295::uint4 AS numeric(5,2))::text, TRY_CAST(4294967295::uint4 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(4294967295::uint4 AS numeric(5,2))::text, TRY_CAST(NULL::uint4 AS numeric(5,2)) IS NULL
-----
-4294967295.00 true true
-
-# uint8 -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1::uint8 AS numeric(5,2))::text, TRY_CAST(1::uint8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1::uint8 AS numeric(5,2))::text, TRY_CAST(NULL::uint8 AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-query TBB
-SELECT TRY_CAST(18446744073709551615::uint8 AS numeric(5,2))::text, TRY_CAST(18446744073709551615::uint8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(18446744073709551615::uint8 AS numeric(5,2))::text, TRY_CAST(NULL::uint8 AS numeric(5,2)) IS NULL
-----
-18446744073709551615.00 true true
-
-# text -> numeric(5,2)
-query TBB
-SELECT TRY_CAST('1.5' AS numeric(5,2))::text, TRY_CAST('1.5' AS numeric(5,2))::text IS NOT DISTINCT FROM CAST('1.5' AS numeric(5,2))::text, TRY_CAST(NULL AS numeric(5,2)) IS NULL
-----
-1.50 true true
-
-statement error
-SELECT CAST('abc' AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('abc' AS numeric(5,2))::text
-----
-NULL
-
-statement error
-SELECT CAST('' AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('' AS numeric(5,2))::text
-----
-NULL
-
-# numeric -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1.5::numeric AS numeric(5,2))::text, TRY_CAST(1.5::numeric AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1.5::numeric AS numeric(5,2))::text, TRY_CAST(NULL::numeric AS numeric(5,2)) IS NULL
-----
-1.50 true true
-
-statement error
-SELECT CAST(1e38::numeric AS numeric(5,2))
-
-query T
-SELECT TRY_CAST(1e38::numeric AS numeric(5,2))::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::numeric AS numeric(5,2))::text, TRY_CAST((-1.5)::numeric AS numeric(5,2))::text IS NOT DISTINCT FROM CAST((-1.5)::numeric AS numeric(5,2))::text, TRY_CAST(NULL::numeric AS numeric(5,2)) IS NULL
-----
--1.50 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::numeric AS numeric(5,2))::text, TRY_CAST('NaN'::numeric AS numeric(5,2))::text IS NOT DISTINCT FROM CAST('NaN'::numeric AS numeric(5,2))::text, TRY_CAST(NULL::numeric AS numeric(5,2)) IS NULL
-----
-NaN true true
-
-query TBB
-SELECT TRY_CAST(123.456::numeric AS numeric(5,2))::text, TRY_CAST(123.456::numeric AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(123.456::numeric AS numeric(5,2))::text, TRY_CAST(NULL::numeric AS numeric(5,2)) IS NULL
-----
-123.46 true true
-
-# real -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1.5::float4 AS numeric(5,2))::text, TRY_CAST(1.5::float4 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1.5::float4 AS numeric(5,2))::text, TRY_CAST(NULL::float4 AS numeric(5,2)) IS NULL
-----
-1.50 true true
-
-statement error
-SELECT CAST('3.4e38'::float4 AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('3.4e38'::float4 AS numeric(5,2))::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float4 AS numeric(5,2))::text, TRY_CAST((-1.5)::float4 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST((-1.5)::float4 AS numeric(5,2))::text, TRY_CAST(NULL::float4 AS numeric(5,2)) IS NULL
-----
--1.50 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float4 AS numeric(5,2))::text, TRY_CAST('NaN'::float4 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST('NaN'::float4 AS numeric(5,2))::text, TRY_CAST(NULL::float4 AS numeric(5,2)) IS NULL
-----
-NaN true true
-
-statement error
-SELECT CAST('Infinity'::float4 AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('Infinity'::float4 AS numeric(5,2))::text
-----
-NULL
-
-# double precision -> numeric(5,2)
-query TBB
-SELECT TRY_CAST(1.5::float8 AS numeric(5,2))::text, TRY_CAST(1.5::float8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST(1.5::float8 AS numeric(5,2))::text, TRY_CAST(NULL::float8 AS numeric(5,2)) IS NULL
-----
-1.50 true true
-
-statement error
-SELECT CAST('1.7e308'::float8 AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('1.7e308'::float8 AS numeric(5,2))::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST((-1.5)::float8 AS numeric(5,2))::text, TRY_CAST((-1.5)::float8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST((-1.5)::float8 AS numeric(5,2))::text, TRY_CAST(NULL::float8 AS numeric(5,2)) IS NULL
-----
--1.50 true true
-
-query TBB
-SELECT TRY_CAST('NaN'::float8 AS numeric(5,2))::text, TRY_CAST('NaN'::float8 AS numeric(5,2))::text IS NOT DISTINCT FROM CAST('NaN'::float8 AS numeric(5,2))::text, TRY_CAST(NULL::float8 AS numeric(5,2)) IS NULL
-----
-NaN true true
-
-statement error
-SELECT CAST('Infinity'::float8 AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('Infinity'::float8 AS numeric(5,2))::text
-----
-NULL
-
-# jsonb -> numeric(5,2)
-query TBB
-SELECT TRY_CAST('1'::jsonb AS numeric(5,2))::text, TRY_CAST('1'::jsonb AS numeric(5,2))::text IS NOT DISTINCT FROM CAST('1'::jsonb AS numeric(5,2))::text, TRY_CAST(NULL::jsonb AS numeric(5,2)) IS NULL
-----
-1.00 true true
-
-statement error
-SELECT CAST('"x"'::jsonb AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('"x"'::jsonb AS numeric(5,2))::text
-----
-NULL
-
-statement error
-SELECT CAST('[1]'::jsonb AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('[1]'::jsonb AS numeric(5,2))::text
-----
-NULL
-
-query TBB
-SELECT TRY_CAST('1e30'::jsonb AS numeric(5,2))::text, TRY_CAST('1e30'::jsonb AS numeric(5,2))::text IS NOT DISTINCT FROM CAST('1e30'::jsonb AS numeric(5,2))::text, TRY_CAST(NULL::jsonb AS numeric(5,2)) IS NULL
-----
-1000000000000000000000000000000.00 true true
-
-statement error
-SELECT CAST('true'::jsonb AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('true'::jsonb AS numeric(5,2))::text
-----
-NULL
-
-statement error
-SELECT CAST('null'::jsonb AS numeric(5,2))
-
-query T
-SELECT TRY_CAST('null'::jsonb AS numeric(5,2))::text
-----
-NULL