Skip to content

Commit

Permalink
Merge pull request #4499 from duckdb/revert-4491-struct-cast
Browse files Browse the repository at this point in the history
Revert "Struct cast changes"
  • Loading branch information
szarnyasg authored Jan 8, 2025
2 parents 9f97aa4 + ef17a69 commit 8852f95
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 31 deletions.
15 changes: 13 additions & 2 deletions docs/sql/data_types/struct.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ CREATE TABLE t2 AS SELECT row('a');
Invalid Input Error: A table cannot be created from an unnamed struct
```

When casting between structs, the names of at least one field have to match. Therefore, the following query will fail:
When casting structs, the names of fields have to match. Therefore, the following query will fail:

```sql
SELECT a::STRUCT(y INTEGER) AS b
Expand All @@ -198,7 +198,7 @@ FROM
```

```console
Binder Error: STRUCT to STRUCT cast must have at least one matching member
Mismatch Type Error: Type STRUCT(x INTEGER) does not match with STRUCT(y INTEGER). Cannot cast STRUCTs - element "x" in source struct was not found in target struct
```

A workaround for this is to use [`struct_pack`](#creating-structs) instead:
Expand Down Expand Up @@ -267,6 +267,17 @@ These queries return `NULL`.
SELECT {'k1': 2, 'k2': 3} < {'k1': 2, 'k2': NULL} AS result;
```

This query returns a `Binder Error` because the keys do not match positionally.

```sql
SELECT {'k1': 2, 'k2': 3} < {'k2': 2, 'k1': 4} AS result;
```

```console
Binder Error: Cannot compare values of type STRUCT(k1 INTEGER, k2 INTEGER)
and type STRUCT(k2 INTEGER, k1 INTEGER) - an explicit cast is required
```

## Functions

See [Struct Functions]({% link docs/sql/functions/struct.md %}).
30 changes: 1 addition & 29 deletions docs/sql/data_types/typecasting.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,46 +99,18 @@ Arrays follow the same casting rules as lists. In addition, arrays can be implic

### Structs

Structs can be cast to other structs as long as they share at least one child element.

> The rationale behind this requirement is to help avoid unintended errors. If two structs do not have any elements in common, then the cast was likely not intended.
Structs can be cast to other structs as long as the names of the child elements match.

```sql
SELECT CAST({'a': 42} AS STRUCT(a VARCHAR));
```

Child elements that exist in the target struct, but that do not exist in the source struct, default to `NULL`.

```sql
SELECT CAST({'a': 42} AS STRUCT(a VARCHAR, b VARCHAR));
```

Child elements that only exist in the source struct are ignored.

```sql
SELECT CAST({'a': 42, 'b': 43} AS STRUCT(a VARCHAR));
```

The names of the struct can also be in a different order. The fields of the struct will be reshuffled based on the names of the structs.

```sql
SELECT CAST({'a': 42, 'b': 84} AS STRUCT(b VARCHAR, a VARCHAR));
```

Struct casting behaves differently when combined with the [`UNION [ALL] BY NAME`]({% link docs/sql/query_syntax/setops.md %}#union-all-by-name) operation.
In that case, the fields of the resulting struct are the superset of all fields of the input structs.
This logic also applies recursively to potentially nested structs.

```sql
SELECT {'outer1': {'inner1': 42, 'inner2': 42}} AS c
UNION ALL BY NAME
SELECT {'outer1': {'inner2': 'hello', 'inner3': 'world'}, 'outer2': '100'} AS c;
```

```sql
SELECT [{'a': 42}, {'b': 84}];
```

### Unions

Union casting rules can be found on the [`UNION type page`]({% link docs/sql/data_types/union.md %}#casting-to-unions).

0 comments on commit 8852f95

Please sign in to comment.