Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ARRAY literal syntax (#144) #147

Merged
merged 1 commit into from
Jan 29, 2025
Merged
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
3 changes: 1 addition & 2 deletions website/docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ In case you are wondering why all our releases start with `0.0`, read [this FAQ

:::


### Upcoming Release

*
* Update syntax for [`ARRAY` literals](./sql/datatype/array.md) and fixed bugs with quoting and escaping of text arrays.

### 0.0.21200 [Jan 17 2025]

Expand Down
37 changes: 22 additions & 15 deletions website/docs/sql/datatype/array.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ Arrays can be created in two ways:
- Using the type constructor syntax
```sql
> select array[1,2,3];
{1,2,3}
[1,2,3]

> select array['one','two','three'];
{one,two,three}
["one","two","three"]
```

The constructor syntax consists of the keyword `array` followed by a comma-separated list of element SQL values surrounded by square brackets `[...]`.
Expand All @@ -39,22 +39,24 @@ Arrays can be created in two ways:

- Using a [cast](../scalar_func/conversion.md) from string data
```sql
> select '{1,2,3}'::array(integer);
{1,2,3}
> select '[1,2,3]'::array(integer);
[1,2,3]

> select '{one,two,three}'::array(text);
{one,two,three}
> select '[one,two,three]'::array(text);
["one","two","three"]
```

An array string literal consists of a comma-separated list of element literals surrounded by curly braces `{...}`.
An array string literal consists of a comma-separated list of element literals surrounded by square brackets `[...]`.
The element literal syntax is identical to that of the respective atomic type.

Note that for string array types (such as, e.g., `array(text)`), any upper- or lower-case variant of the element literal `null` will be parsed as a `null` value.
To specify the string `null`, the element literal must be escaped using double quotes, like so:
```sql
> select '{null, "null"}'::array(text)
{NULL,null} # A null element, followed by the string 'null'
> select '[null, "null"]'::array(text)
[NULL,"null"] # A null element, followed by the string 'null'
```

When outputting an array of text types, every non-null element is quoted.

## Element Types and Nullability

Expand All @@ -70,18 +72,18 @@ The following four options all represent different types in Hyper:

|Type|array nullable?|elements nullable?| possible values|
|---|---|---|---|
|`array(integer)`|✅|✅|`{}`,`{1,2,3}`,`{1,2,null}`, `null`|
|`array(integer not null)`|✅|❌|`{}`,`{1,2,3}`,`null`|
|`array(integer) not null`|❌|✅|`{}`,`{1,2,3}`,`{1,2,null}`|
|`array(integer not null) not null`|❌|❌|`{}`,`{1,2,3}`|
|`array(integer)`|✅|✅|`[]`,`[1,2,3]`,`[1,2,null]`, `null`|
|`array(integer not null)`|✅|❌|`[]`,`[1,2,3]`,`null`|
|`array(integer) not null`|❌|✅|`[]`,`[1,2,3]`,`[1,2,null]`|
|`array(integer not null) not null`|❌|❌|`[]`,`[1,2,3]`|

The inner nullability of an array type can be changed by casting, using the conventional [cast syntax](../scalar_func/conversion.md):

```sql
# nullable to non-nullable
> select ('{1,2,3}'::array(integer))::array(integer not null)
> select ('[1,2,3]'::array(integer))::array(integer not null)
# non-nullable to nullable
> select ('{1,2,3}'::array(integer not null))::array(integer)
> select ('[1,2,3]'::array(integer not null))::array(integer)
```

A cast from a non-nullable element type to its nullable counterpart always succeeds.
Expand All @@ -92,6 +94,11 @@ Casts across element types (e.g. from `array(integer not null)` to `array(bigint
Non-nullable element types use less memory and enable optimizations for certain array operations. Users are therefore advised to use the most "restrictive" element type possible, given the use case at hand.
:::

:::note
Hyper used curly braces `{...}` to represent arrays as string literals up to (and including) version 0.0.21200. In those versions, it also tried to avoid quoting every element of a text array when it did not contain special characters.
The new syntax uses square brackets `[...]` and always quotes text elements, which more closely resembles the JSON array syntax.
:::

## Limitations

Arrays are subject to the following limitations:
Expand Down
2 changes: 1 addition & 1 deletion website/docs/sql/scalar_func/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Signature|Description|Example
---|---|---
<code>array(T)**[**int**]**</code> → `T`| Returns the n-th element of the array (1-indexed). | `(array[1,2,3])[1]` → `1`
<code>array(T)**[**int**:**int**]**</code> → `T` | Returns the subarray within the given boundes (1-indexed, inclusive). |`(array[1,2,3])[2:3]` → `{2,3}` |
<code>**array_length(**array**)**</code> → `int` | Returns the length of the array. | `array_length(array[1,2,3])` → `3`
<code>**array_length(**array**)**</code> → `int` | Returns the length of the array. | `array_length(array[1,2,3])` → `3` <br/>`array_length(array[])` → `0`
<code>**array_to_string(**array, text [, text]**)**</code>| Converts the array into a textual representation, with the given element separator and (optional) null indicator. | `array_to_string(array[1,2,3], ';')` → `1;2;3`<br/>`array_to_string(array[3,2,1,null], '⏰', '🎉')` → `3⏰2⏰1⏰🎉`
<code>**array_contains(**array, value**)**</code>| Checks if a given value is contained within the array. | `array_contains(array[1,3,4], 3)` → `true`<br/>`array_contains(array[1,3,4], 2)` → `false`
<code>**array_position(**array, value**)**</code>| Returns the index of the first occurrence of `value` inside `array`. Comparisons are done using `IS NOT DISTINCT FROM` semantics, so it is possible to search for `NULL`. Returns `NULL` if the element is not found. | `array_position(array[1,3,4,3], 3)` → `2`<br/>`array_contains(array[1,3,4,3], 2)` → `NULL`
Expand Down