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: multi-use common table expressions #21084

Closed
Tracked by #25470
jordanlewis opened this issue Dec 28, 2017 · 7 comments · Fixed by #38670
Closed
Tracked by #25470

sql: multi-use common table expressions #21084

jordanlewis opened this issue Dec 28, 2017 · 7 comments · Fixed by #38670
Labels
A-sql-execution Relating to SQL execution. A-sql-name-resolution SQL name resolution rules and CTEs. A-sql-optimizer SQL logical planning and optimizations. A-sql-pgcompat Semantic compatibility with PostgreSQL C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) X-anchored-telemetry The issue number is anchored by telemetry references.

Comments

@jordanlewis
Copy link
Member

Split from #7029 which was closed when we merged support for single-use common table expressions in #20359.

Support common table expressions whose clauses are used more than once in the statement. This may require temporary tables or other novel infrastructure, since each referenced statement should be run at most once in the case of DML statements, and in the case of read-only statements, should probably be run at most once anyway for efficiency.

For example,

WITH x AS (SELECT ... FROM table ...),
          y AS (SELECT ... FROM x ...)
SELECT ... FROM table2 JOIN x ON ...

In this statement, the x clause is referenced more than once, which is not currently supported.

@jordanlewis jordanlewis added this to the Later milestone Dec 28, 2017
@petermattis
Copy link
Collaborator

Support common table expressions whose clauses are used more than once in the statement. This may require temporary tables or other novel infrastructure, since each referenced statement should be run at most once in the case of DML statements, and in the case of read-only statements, should probably be run at most once anyway for efficiency.

Note that the decision on whether to run a read-only statement once (and cache the results) or more than once is cost-based. Also, if a read-only statement is used more than once, it may be useful to "unnest" the statement in order to push-down filters or merge projections. I don't have examples on hand, but this is discussed in academic literature regarding optimizing CTEs.

@jordanlewis jordanlewis added C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) A-sql-pgcompat Semantic compatibility with PostgreSQL A-sql-execution Relating to SQL execution. labels Apr 27, 2018
@knz knz added the A-sql-name-resolution SQL name resolution rules and CTEs. label Apr 28, 2018
@knz knz added the A-sql-optimizer SQL logical planning and optimizations. label Apr 28, 2018
@stevenross
Copy link

Would I be correct in saying this would allow the introspection query used in Postgraphile to run on CockroachDB?

The expressiveness of GraphQL for API development has seen the Postgraphile project gain considerable traction. Being able to use it with a database such as CockroachDB for its cloud native features would be very compelling.

I understand that this alone may not allow Postgraphile to run. Maybe a seperate issue could be created and tracked within #25468?

@BramGruneir
Copy link
Member

@stevenross I added PostGraphile to #25470.

@petermattis petermattis removed this from the Later milestone Oct 5, 2018
@knz knz added the X-anchored-telemetry The issue number is anchored by telemetry references. label Mar 13, 2019
justinj pushed a commit to justinj/cockroach that referenced this issue Jul 3, 2019
This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes cockroachdb#24307.
Fixes cockroachdb#21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.
justinj pushed a commit to justinj/cockroach that referenced this issue Jul 10, 2019
This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes cockroachdb#24307.
Fixes cockroachdb#21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.
justinj pushed a commit to justinj/cockroach that referenced this issue Jul 15, 2019
This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes cockroachdb#24307.
Fixes cockroachdb#21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.
justinj pushed a commit to justinj/cockroach that referenced this issue Jul 16, 2019
This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes cockroachdb#24307.
Fixes cockroachdb#21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.
justinj pushed a commit to justinj/cockroach that referenced this issue Jul 17, 2019
This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes cockroachdb#24307.
Fixes cockroachdb#21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.
justinj pushed a commit to justinj/cockroach that referenced this issue Jul 17, 2019
This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes cockroachdb#24307.
Fixes cockroachdb#21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.
craig bot pushed a commit that referenced this issue Jul 18, 2019
38670: opt: add WITH operator r=justinj a=justinj

This commit introduces a With operator to opt, which allows us to
reference CTEs multiple times.

This enables some missing functionality, where we can reference CTEs
multiple times, or not at all, even if they contain mutations. We lose
some optimizations because CTEs now present an optimization fence.

This might be fixable with a rule something like:
```
(With
  $value:*
  $input:(WithRef) & (References $input $value)
)
=>
$value
```
subject to certain side-effect restrictions, along with some rule props
to get the Withs down further in the tree.

Additionally, as they are now, WithExprs present another optimization
fence, since we don't have any rules for pushing them further down the
tree. Ideally, we would get all WithExprs that *can* be inlined down to
their point of use, and all those that cannot up to the very root of the
tree. This is future work.

Fixes #24307.
Fixes #21084.

Release note (sql change): Common Table Expressions (CTEs) may now be
referenced from multiple locations in a query.

Co-authored-by: Justin Jaffray <justin@cockroachlabs.com>
@craig craig bot closed this as completed in #38670 Jul 18, 2019
@Bessonov
Copy link

I'm trying to get the total count of matched rows, but return only a subset of them for pagination, like described in: https://stackoverflow.com/a/28888696/926620 :

WITH cte AS (
   SELECT *
   FROM   tbl
   WHERE  /* whatever */
   )
SELECT *
FROM  (
   TABLE  cte
   ORDER  BY col1
   LIMIT  ?
   OFFSET ?
   ) sub
RIGHT  JOIN (SELECT count(*) FROM cte) c(full_count) ON true;

but I get:

pq: unimplemented: unsupported multiple use of CTE clause "cte"
HINT: See: https://github.com/cockroachdb/cockroach/issues/21084

Is there any way to efficiently do that in CockroachDB?

BTW AFAIK OFFSET is very inefficient in Postgres. It's true for CockroachDB too? Colud it be avoided if instead of OFFSET something like WHERE id > ${lastId from previos page} ORDER BY id ASC LIMIT 10 is used?

@awoods187
Copy link
Contributor

@Bessonov what version of CRDB are you using? In 19.2 (we have just released a release candidate https://www.cockroachlabs.com/docs/releases/#testing-releases) this should be supported but it isn't in early versions. For example:

WITH r AS (SELECT * FROM rides WHERE revenue > 98),
    results AS (SELECT * FROM users AS u, r WHERE r.rider_id = u.id)
  SELECT * FROM results;
                   id                  |     city      |       name       |            address             | credit_card |                  id                  |     city      | vehicle_city  |               rider_id               |              vehicle_id              |           start_address           |        end_address        |        start_time         |         end_time          | revenue
+--------------------------------------+---------------+------------------+--------------------------------+-------------+--------------------------------------+---------------+---------------+--------------------------------------+--------------------------------------+-----------------------------------+---------------------------+---------------------------+---------------------------+---------+
  ae147ae1-47ae-4800-8000-000000000022 | amsterdam     | Tyler Dalton     | 88194 Angela Gardens Suite 94  | 4443538758  | bbe76c8b-4395-4000-8000-00000000016f | amsterdam     | amsterdam     | ae147ae1-47ae-4800-8000-000000000022 | aaaaaaaa-aaaa-4800-8000-00000000000a | 45295 Brewer View Suite 52        | 62188 Jade Causeway       | 2018-12-17 03:04:05+00:00 | 2018-12-17 13:04:05+00:00 |   99.00

We have some documentation in our 19.2 version of the docs https://www.cockroachlabs.com/docs/v19.2/common-table-expressions.html#overview

@Bessonov
Copy link

@awoods187 thank you for your response! I was not able to build cockroachdb from sources. But now tested with 19.2 image and it does work as you stated!

Do you have any thoughts on OFFSET in last part of my question?

@awoods187
Copy link
Contributor

We haven't yet written up docs but good information can be found here cockroachdb/docs#3743

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sql-execution Relating to SQL execution. A-sql-name-resolution SQL name resolution rules and CTEs. A-sql-optimizer SQL logical planning and optimizations. A-sql-pgcompat Semantic compatibility with PostgreSQL C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) X-anchored-telemetry The issue number is anchored by telemetry references.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants