Skip to content

Support the use of unions in subqueries#178

Merged
gwynne merged 3 commits into
mainfrom
unions-in-subqueries
May 17, 2024
Merged

Support the use of unions in subqueries#178
gwynne merged 3 commits into
mainfrom
unions-in-subqueries

Conversation

@gwynne

@gwynne gwynne commented May 17, 2024

Copy link
Copy Markdown
Member

These changes are now available in 3.30.0

Adds support for the use of UNION queries within subqueries. Unfortunately, thanks to iffy design choices on my part in the original SQLUnion implementation, the usage is slightly awkward. Example usage:

try await db.update("foos")
    .set(SQLIdentifier("bar_id"), to: SQLSubquery
        .union { $0
            .column("id")
            .from("bars")
            .where("baz", .notEqual, "bamf")
        }
        .union(all: { $0
            .column("id")
            .from("bars")
            .where("baz", .equal, "bop")
        })
        .finish()
    )
    .run()

This generates the following query:

UPDATE "foos"
SET "bar_id" = (
        SELECT "id" FROM "bars" WHERE "baz" <> "bamf"
    UNION ALL
        SELECT "id" FROM "bars" WHERE "baz" = "bop"
)

Unfortunately, it is not possible to chain .union() when using SQLSubquery.select(_:); the call chain must start with SQLSubquery.union(_:).

gwynne added 2 commits May 17, 2024 13:13
… to bad design choices in the original union support (my bad), this turns out to be mildly annoying to actually use and extremely painful to follow in the actual implementation.
@gwynne gwynne added enhancement New feature or request semver-minor Contains new APIs labels May 17, 2024
@gwynne gwynne requested review from 0xTim, MahdiBM and ptoffy May 17, 2024 18:19
@codecov

codecov Bot commented May 17, 2024

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (9afdc96) to head (9b9f663).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #178   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           97        98    +1     
  Lines         2551      2565   +14     
=========================================
+ Hits          2551      2565   +14     
Files Coverage Δ
.../Builders/Implementations/SQLSubqueryBuilder.swift 100.00% <100.00%> (ø)
...Kit/Builders/Implementations/SQLUnionBuilder.swift 100.00% <100.00%> (ø)
...it/Builders/Prototypes/SQLCommonUnionBuilder.swift 100.00% <100.00%> (ø)
...urces/SQLKit/Expressions/Clauses/SQLSubquery.swift 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

@gwynne

gwynne commented May 17, 2024

Copy link
Copy Markdown
Member Author

API breakage notes:

  • The change from SQLSelectBuilder to any SQLSubqueryClauseBuilder in the parameters for the SQSelectBuilder extension methods is an API break but has no actual effect, as SQLSelectBuilder provides no API that the protocol doesn't (or at least, none that can be used in the relevant context).
  • The removed methods on SQLUnionBuilder are now provided as extension methods on the SQLCommonUnionBuilder protocol instead.

Comment thread Sources/SQLKit/Builders/Prototypes/SQLCommonUnionBuilder.swift Outdated

@MahdiBM MahdiBM left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're sure about the API breakage.

@gwynne

gwynne commented May 17, 2024

Copy link
Copy Markdown
Member Author

I am, actually 🙂. Look at the definition of SQLSelectBuilder. The only method of its own it defines is an initializer, and the SQLQueryBuilder and SQLQueryFetcher methods aren't callable within sub-builder closures (they're all asynchronous; there's nowhere to go with an ELF (anyone calling .wait() in that context frankly deserves what they get) and you can't await in a non-async closure).

@gwynne gwynne merged commit 25d8170 into main May 17, 2024
@gwynne gwynne deleted the unions-in-subqueries branch May 17, 2024 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request semver-minor Contains new APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants