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

Allow adding extra clauses for recursive CTE queries in PostgreSQL #542

Closed
p-himik opened this issue Sep 19, 2024 · 2 comments
Closed

Allow adding extra clauses for recursive CTE queries in PostgreSQL #542

p-himik opened this issue Sep 19, 2024 · 2 comments
Assignees
Labels
needs analysis I need to think about this!

Comments

@p-himik
Copy link
Contributor

p-himik commented Sep 19, 2024

Initially reported on Slack at https://clojurians.slack.com/archives/C66EM8D5H/p1726737107546879

PostgreSQL (the only SQL DBMS that can do that among the ones I've looked up) has extra syntax for the WITH RECURSIVE clause where each subquery in parentheses can be followed by the CYCLE ... and/or the SEARCH ... clause.

An example from WITH Queries (Common Table Expressions):

WITH RECURSIVE search_graph(id, link, data, depth) AS (
    SELECT g.id, g.link, g.data, 1
    FROM graph g
  UNION ALL
    SELECT g.id, g.link, g.data, sg.depth + 1
    FROM graph g, search_graph sg
    WHERE g.id = sg.link
) CYCLE id SET is_cycle USING path
SELECT * FROM search_graph;

The relevant part of the grammar from the SELECT documentation:

and with_query is:

    with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( select | values | insert | update | delete )
        [ SEARCH { BREADTH | DEPTH } FIRST BY column_name [, ...] SET search_seq_col_name ]
        [ CYCLE column_name [, ...] SET cycle_mark_col_name [ TO cycle_mark_value DEFAULT cycle_mark_default ] USING cycle_path_col_name ]

Other relevant bit of info:

Both the SEARCH and the CYCLE clause are only valid for recursive WITH queries. The with_query must be a UNION (or UNION ALL) of two SELECT (or equivalent) commands (no nested UNIONs). If both clauses are used, the column added by the SEARCH clause appears before the columns added by the CYCLE clause.

@seancorfield seancorfield self-assigned this Sep 19, 2024
@seancorfield seancorfield added the needs analysis I need to think about this! label Sep 19, 2024
@seancorfield
Copy link
Owner

seancorfield commented Sep 19, 2024

Just a note that HoneySQL does no validation on whether the SQL produced is legal, so this will get addressed in a fairly generic way, I expect, and will almost certainly allow illegal SQL to be generated if users get too "creative" 😄

seancorfield added a commit that referenced this issue Sep 22, 2024
Signed-off-by: Sean Corfield <sean@corfield.org>
seancorfield added a commit that referenced this issue Oct 12, 2024
Signed-off-by: Sean Corfield <sean@corfield.org>
@seancorfield
Copy link
Owner

I have a tentative implementation for this in place but need to write documentation for it.

The rough outline is that you can provide these "tail" options after the with query portion:

{:with [[:query {:select [:foo] :from [:bar]} :cycle [:a :b :c] :set :d :to [:abs :e] :default 42 :using :x]]}
;; produces:
["WITH query AS (SELECT foo FROM bar) CYCLE a, b, c SET d TO ABS(e) DEFAULT ? USING x" 42]))

seancorfield added a commit that referenced this issue Oct 12, 2024
Signed-off-by: Sean Corfield <sean@corfield.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs analysis I need to think about this!
Projects
None yet
Development

No branches or pull requests

2 participants