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

sql: CTE source not available as function argument in JOIN target #70342

Closed
nvanbenschoten opened this issue Sep 17, 2021 · 4 comments · Fixed by #71396
Closed

sql: CTE source not available as function argument in JOIN target #70342

nvanbenschoten opened this issue Sep 17, 2021 · 4 comments · Fixed by #71396
Assignees
Labels
A-sql-optimizer SQL logical planning and optimizations. A-sql-pgcompat Semantic compatibility with PostgreSQL A-tools-postgrest C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. T-sql-queries SQL Queries Team

Comments

@nvanbenschoten
Copy link
Member

nvanbenschoten commented Sep 17, 2021

NOTE: the underlying issue here may be misdiagnosed. Feel free to rename.

When passing the Prefer: return=headers-only or Prefer: return=representation HTTP header on a POST request to request a newly inserted row's primary key, PostgREST issues the following query:

  WITH pgrst_source AS (
                             WITH pgrst_payload AS (SELECT $1::JSONB AS json_data),
                                  pgrst_body AS (SELECT CASE WHEN json_typeof(json_data) = 'array' THEN json_data ELSE json_build_array(json_data) END AS val FROM pgrst_payload)
                           INSERT
                             INTO public.promo_codes (code)
                           SELECT code
                             FROM json_populate_recordset(NULL::public.promo_codes, (SELECT val FROM pgrst_body)) AS _
                        RETURNING public.promo_codes.*
                    )
SELECT '' AS total_result_set,
       pg_catalog.count(_postgrest_t) AS page_total,
       CASE
       WHEN pg_catalog.count(_postgrest_t) = 1
       THEN COALESCE(
        (
              WITH data AS (SELECT row_to_json(_) AS row FROM pgrst_source AS _ LIMIT 1)
            SELECT array_agg(json_data.key || '=' || COALESCE('eq.' || json_data.value, 'is.null'))
              FROM data CROSS JOIN json_each_text(data.row) AS json_data
             WHERE json_data.key IN ('code',)
        ),
        ARRAY[]::STRING[]
       )
       ELSE ARRAY[]::STRING[]
       END AS header,
       '' AS body,
       NULLIF(current_setting('response.headers', true), '') AS response_headers,
       NULLIF(current_setting('response.status', true), '') AS response_status
  FROM (SELECT * FROM pgrst_source) AS _postgrest_t;

Currently, this returns the following error:

ERROR: no data source matches prefix: data in this context
SQLSTATE: 42P01

I've simplified this down to the following incompatibility with Postgres:

CockroachDB:

root@127.0.0.1:26257/movr> CREATE TABLE t (i INT PRIMARY KEY);
CREATE TABLE

root@127.0.0.1:26257/movr> WITH data AS (SELECT row_to_json(t) AS row FROM t)
SELECT count(*)
FROM data CROSS JOIN json_each_text(data.row);
ERROR: no data source matches prefix: data in this context
SQLSTATE: 42P01

Postgres:

nathan=# CREATE TABLE t (i INT PRIMARY KEY);
CREATE TABLE

nathan=# WITH data AS (SELECT row_to_json(t) AS row FROM t)
SELECT count(*)
FROM data CROSS JOIN json_each_text(data.row);
 count
-------
     0
(1 row)

It appears that Cockroach does not correctly propagate the CTE source into the JOIN target's scope, so it cannot find data in json_each_text(data.row).

Epic CRDB-10300

@nvanbenschoten nvanbenschoten added C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. A-sql-pgcompat Semantic compatibility with PostgreSQL A-sql-optimizer SQL logical planning and optimizations. A-tools-postgrest labels Sep 17, 2021
@blathers-crl blathers-crl bot added the T-sql-queries SQL Queries Team label Sep 17, 2021
@rafiss
Copy link
Collaborator

rafiss commented Sep 17, 2021

Looks like #59154 but this issue has a nice write up, so I'll close that one.

@RaduBerinde
Copy link
Member

How can the right hand side of a non-lateral join refer to the left-hand side?

Using LATERAL works:

WITH data AS (SELECT row_to_json(t) AS row FROM t)
SELECT count(*)
FROM data CROSS JOIN LATERAL json_each_text(data.row);
  count
---------
      0
(1 row)

My guess is that it just happens to work in postgres for whatever reason. I didn't find anything in the pg documentation that would suggest it should.

@RaduBerinde
Copy link
Member

Maybe we should contribute a change to add the LATERAL keyword to the query? It shouldn't hurt anything when run against postgres.

@RaduBerinde
Copy link
Member

RaduBerinde commented Oct 11, 2021

Ok, I found this in PG docs:

Function Calls in FROM
PostgreSQL allows a function call to be written directly as a member of the FROM list. In the SQL standard it would be necessary to wrap such a function call in a sub-SELECT; that is, the syntax FROM func(...) alias is approximately equivalent to FROM LATERAL (SELECT func(...)) alias. Note that LATERAL is considered to be implicit; this is because the standard requires LATERAL semantics for an UNNEST() item in FROM. PostgreSQL treats UNNEST() the same as other set-returning functions.

RaduBerinde added a commit to RaduBerinde/cockroach that referenced this issue Oct 11, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes cockroachdb#70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
RaduBerinde added a commit to RaduBerinde/cockroach that referenced this issue Oct 11, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes cockroachdb#70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
craig bot pushed a commit that referenced this issue Oct 12, 2021
71396: opt: fix implicit lateral for SRFs when using JOIN syntax r=RaduBerinde a=RaduBerinde

When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes #70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).

Co-authored-by: Radu Berinde <radu@cockroachlabs.com>
@craig craig bot closed this as completed in 9e8d9be Oct 12, 2021
blathers-crl bot pushed a commit that referenced this issue Oct 12, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes #70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
blathers-crl bot pushed a commit that referenced this issue Oct 12, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes #70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
nehageorge pushed a commit to nehageorge/cockroach that referenced this issue Oct 12, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes cockroachdb#70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
ericharmeling pushed a commit to ericharmeling/cockroach that referenced this issue Oct 20, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes cockroachdb#70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
RaduBerinde added a commit that referenced this issue Oct 26, 2021
When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes #70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sql-optimizer SQL logical planning and optimizations. A-sql-pgcompat Semantic compatibility with PostgreSQL A-tools-postgrest C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. T-sql-queries SQL Queries Team
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants