Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

97 changes: 2 additions & 95 deletions doc/user/content/sql/functions/cast.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand Down Expand Up @@ -177,67 +169,6 @@ Source type | Return type

<sup>2</sup> 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
Expand Down Expand Up @@ -271,29 +202,5 @@ SELECT 100.21::numeric(10, 2)::float AS dec_to_float;
100.21
```

<hr/>

```mzsql
SELECT TRY_CAST('42' AS int) AS ok, TRY_CAST('forty-two' AS int) AS bad;
```
```nofmt
ok | bad
----+-----
42 |
```

<hr/>

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/)
11 changes: 0 additions & 11 deletions doc/user/data/examples/sql_functions/cast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,6 @@
description: |
The return value's [type](/sql/types/).

- name: "syntax-try-cast"
code: |
TRY_CAST ( <val> AS <type> )
syntax_elements:
- name: "`<val>`"
description: |
Any value you want to convert.
- name: "**AS** `<type>`"
description: |
The return value's [type](/sql/types/).

- name: "syntax-literal"
code: |
<type> '<val>'
Expand Down
5 changes: 0 additions & 5 deletions doc/user/data/sql_funcs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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_.

Expand Down
1 change: 0 additions & 1 deletion misc/python/materialize/mzcompose/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": (
Expand Down
2 changes: 0 additions & 2 deletions src/adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
Expand Down
Loading
Loading