forked from sqldelight/sqldelight
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix 5122 add PostgreSql lateral join operator for subquery (sqldeligh…
…t#5337) * Fix 5122 Add LATERAL to grammar LATERAL is used in two positions in the join_operator - for table subqueries and for table joins Add Mixin to expose table/columns in a subquery - avoid recursion stackoverflow if child is same as subquery * Lateral Tests Lateral Tests Fixture test Integration test InterfaceGeneration test
- Loading branch information
Showing
6 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
.../main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/mixins/SqlJoinClauseMixin.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package app.cash.sqldelight.dialects.postgresql.grammar.mixins | ||
|
||
import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlTypes | ||
import com.alecstrong.sql.psi.core.psi.QueryElement | ||
import com.alecstrong.sql.psi.core.psi.impl.SqlJoinClauseImpl | ||
import com.intellij.lang.ASTNode | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.util.elementType | ||
|
||
internal open class SqlJoinClauseMixin(node: ASTNode) : SqlJoinClauseImpl(node) { | ||
|
||
override fun queryAvailable(child: PsiElement): Collection<QueryElement.QueryResult> { | ||
return if (joinOperatorList | ||
.flatMap { it.children.toList() } | ||
.find { it.elementType == PostgreSqlTypes.LATERAL } != null | ||
) { | ||
tableOrSubqueryList.takeWhile { it != child }.flatMap { it.queryExposed() } | ||
} else { | ||
super.queryAvailable(child) | ||
} | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
dialects/postgresql/src/testFixtures/resources/fixtures_postgresql/lateral/Test.s
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
CREATE TABLE A ( | ||
b_id INTEGER | ||
); | ||
|
||
CREATE TABLE B ( | ||
id INTEGER | ||
); | ||
|
||
SELECT * FROM A, LATERAL (SELECT * FROM B WHERE B.id = A.b_id) AB; | ||
|
||
CREATE TABLE Author ( | ||
id INTEGER PRIMARY KEY, | ||
name TEXT | ||
); | ||
|
||
CREATE TABLE Genre ( | ||
id INTEGER PRIMARY KEY, | ||
name TEXT | ||
); | ||
|
||
CREATE TABLE Book ( | ||
id INTEGER PRIMARY KEY, | ||
title TEXT, | ||
author_id INTEGER REFERENCES Author(id), | ||
genre_id INTEGER REFERENCES Genre(id) | ||
); | ||
|
||
SELECT | ||
Author.name AS author_name, | ||
Genre.name AS genre_name, | ||
book_count | ||
FROM | ||
Author, | ||
Genre, | ||
LATERAL ( | ||
SELECT | ||
COUNT(*) AS book_count | ||
FROM | ||
Book | ||
WHERE | ||
Book.author_id = Author.id | ||
AND Book.genre_id = Genre.id | ||
) AS book_counts; | ||
|
||
CREATE TABLE Kickstarter_Data ( | ||
pledged INTEGER, | ||
fx_rate NUMERIC, | ||
backers_count INTEGER, | ||
launched_at NUMERIC, | ||
deadline NUMERIC, | ||
goal INTEGER | ||
); | ||
|
||
SELECT | ||
pledged_usd, | ||
avg_pledge_usd, | ||
duration, | ||
(usd_from_goal / duration) AS usd_needed_daily | ||
FROM Kickstarter_Data, | ||
LATERAL (SELECT pledged / fx_rate AS pledged_usd) pu, | ||
LATERAL (SELECT pledged_usd / backers_count AS avg_pledge_usd) apu, | ||
LATERAL (SELECT goal / fx_rate AS goal_usd) gu, | ||
LATERAL (SELECT goal_usd - pledged_usd AS usd_from_goal) ufg, | ||
LATERAL (SELECT (deadline - launched_at) / 86400.00 AS duration) dr; | ||
|
||
CREATE TABLE Regions ( | ||
id INTEGER, | ||
name VARCHAR(255) | ||
); | ||
|
||
CREATE TABLE SalesPeople ( | ||
id INTEGER, | ||
full_name VARCHAR(255), | ||
home_region_id INTEGER | ||
); | ||
|
||
CREATE TABLE Sales ( | ||
id INTEGER, | ||
amount NUMERIC, | ||
product_id INTEGER, | ||
salesperson_id INTEGER, | ||
region_id INTEGER | ||
); | ||
|
||
SELECT | ||
sp.id salesperson_id, | ||
sp.full_name, | ||
sp.home_region_id, | ||
rg.name AS home_region_name, | ||
home_region_sales.total_sales | ||
FROM SalesPeople sp | ||
JOIN Regions rg ON sp.home_region_id = rg.id | ||
JOIN LATERAL ( | ||
SELECT SUM(amount) AS total_sales | ||
FROM Sales s | ||
WHERE s.salesperson_id = sp.id | ||
AND s.region_id = sp.home_region_id | ||
) home_region_sales ON TRUE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
...tion-postgresql/src/main/sqldelight/app/cash/sqldelight/postgresql/integration/Lateral.sq
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
CREATE TABLE Regions ( | ||
id INTEGER, | ||
name VARCHAR(255) | ||
); | ||
|
||
CREATE TABLE Sales_People ( | ||
id INTEGER, | ||
full_name VARCHAR(255), | ||
home_region_id INTEGER | ||
); | ||
|
||
CREATE TABLE Sales ( | ||
id INTEGER, | ||
amount NUMERIC, | ||
product_id INTEGER, | ||
sales_person_id INTEGER, | ||
region_id INTEGER | ||
); | ||
|
||
insertSales { | ||
INSERT INTO Regions (id, name) VALUES (1, 'North America'); | ||
INSERT INTO Regions (id, name) VALUES (2, 'Europe'); | ||
INSERT INTO Regions (id, name) VALUES (3, 'Asia'); | ||
|
||
INSERT INTO Sales_People (id, full_name, home_region_id) VALUES (1, 'A D', 1); | ||
INSERT INTO Sales_People (id, full_name, home_region_id) VALUES (2, 'L S', 2); | ||
INSERT INTO Sales_People (id, full_name, home_region_id) VALUES (3, 'M J', 3); | ||
|
||
INSERT INTO Sales (id, amount, product_id, sales_person_id, region_id) VALUES (1, 1000.50, 101, 1, 1); | ||
INSERT INTO Sales (id, amount, product_id, sales_person_id, region_id) VALUES (2, 2500.75, 102, 2, 2); | ||
INSERT INTO Sales (id, amount, product_id, sales_person_id, region_id) VALUES (3, 1250.25, 103, 3, 3); | ||
} | ||
|
||
selectSales: | ||
SELECT | ||
sp.id salesperson_id, | ||
sp.full_name, | ||
sp.home_region_id, | ||
rg.name AS home_region_name, | ||
home_region_sales.total_sales | ||
FROM Sales_People AS sp | ||
JOIN Regions rg ON sp.home_region_id = rg.id | ||
JOIN LATERAL ( | ||
SELECT SUM(amount) AS total_sales | ||
FROM Sales AS s | ||
WHERE s.sales_person_id = sp.id | ||
AND s.region_id = sp.home_region_id | ||
) home_region_sales ON TRUE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters