Skip to content

INSERT with named columns errors with nested structs and arrays #3231

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

Open
hatyo opened this issue Mar 5, 2025 · 0 comments
Open

INSERT with named columns errors with nested structs and arrays #3231

hatyo opened this issue Mar 5, 2025 · 0 comments
Labels
bug Something isn't working relational issues related to relational FDB

Comments

@hatyo
Copy link
Contributor

hatyo commented Mar 5, 2025

Our SQL supports setting only a specific set of columns of a (nested) record, provided this is not prohibited e.g. due to causing constraint violation such as missing (parts of) the primary key constituents, i.e. this works as expected:

create type as struct S(S1 bigint, S2 bigint)
create table B(B1 bigint, B2 bigint, B3 S, primary key(B1))
insert into B (B1, B3(S2)) values (20, (5))
select * from B -- returns (20, null, (null, 5))

However, it is not possible to do this when we have nested arrays and structs:

create type as struct R(R1 bigint, R2 bigint)
create type as struct S(S1 bigint, S2 bigint)
create type as struct T(T1 R, T2 bigint)
create type as struct U(U1 T, U2 S array)
create table C(A1 bigint, A2 S array, primary key (A1))
create table D(A1 bigint, A2 U array, primary key (A1))
insert into C(A1, A2(S1)) values (1, [(10), (30)]), (2, [(100)]) -- error
insert into D(A1, A2(U2(S1))) values (1, [[(100), (200)]]) -- error

As it throws the following error:

Caused by: com.apple.foundationdb.relational.api.exceptions.ContextualSQLException: expected Record but got Array
	at com.apple.foundationdb.relational.api.exceptions.RelationalException.toSqlException(RelationalException.java:74)
	at com.apple.foundationdb.relational.recordlayer.EmbeddedRelationalPreparedStatement.execute(EmbeddedRelationalPreparedStatement.java:80)
	at com.apple.foundationdb.relational.yamltests.command.QueryExecutor.executeStatement(QueryExecutor.java:294)

Arguably, the above syntax can be ambiguous, or at least, it does not align exactly with the row we're trying to set. Perhaps we need to change the aliasing syntax to reflect the fact that A2 is actually an array, but I am not sure.

insert into C(A1, A2[(S1)]) values (1, [(10), (30)]), (2, [(100)]) -- indicate A2 is an array
@hatyo hatyo added bug Something isn't working relational issues related to relational FDB labels Mar 5, 2025
hatyo added a commit that referenced this issue Apr 3, 2025
This provides support to table-valued-functions, it introduces the
necessary framework support across different components: parsing,
semantic analysis, plan generation, planning, and execution, to
pre-defined table-valued functions.

Two pre-defined table-functions are introduced in this PR:

#### 1. `values` function:
Most major SQL vendors support this function, the relational engine now
supports this function as well:
```sql
select * from values (1, 'a', 3.0), (4, 'b', 4.5);
-- returns two rows:
-- 1, 'a', 3.0
-- 4, 'b', 4.5
```
It also enables naming the resulting table along with its columns:
```sql
select * from values (1, 2.0, (3, 4, 'foo')), (10, 90.2, (5, 6.0, 'bar')) as A(B, C, W(X, Y, Z))
-- returns two rows with the following metadata:
-- B  | C    | W(X, Y, Z)
-- 1  | 2.0  | (3, 4.0, 'foo')
-- 10 | 90.2 | (5, 6.0, 'bar')
```
Notice how the value `4` in the first row's nested structure `W.Y` was
promoted to `4.0`, this is because this function analyzes all the rows,
and for each leaf in every (nested) tuple, it looks for a type that
accommodates for all the individual values of the leaf across all rows
(max type) and injects type promotions if necessary.
Also note that the type aliasing works with nested array and structs, to
some degrees addresses some of the issues reported in #3231, and in the
future, the new logic can be leveraged to resolve that ticket as well.

#### 2. `range` function:
This is also a very common function, it returns a range between:
- given start (inclusive), defaulting to `0`.
- given end (exclusive).
- optional step size.
- 
```sql
select ID from range (1, 5)
-- returns 4 rows
-- 1
-- 2
-- 3
-- 4
```
The implementation of this TVF has streaming semantics. In other words,
it does not pre-materialize all the values in the range, but rather
return them on-demand.

With this PR, we can hopefully start adding more advanced TVFs easily.

This resolves #3282.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working relational issues related to relational FDB
Projects
None yet
Development

No branches or pull requests

1 participant