Skip to content

Commit

Permalink
Add aliases to nested subselects (#2335)
Browse files Browse the repository at this point in the history
  • Loading branch information
deusaquilus committed Dec 6, 2021
1 parent 87665a2 commit 5952882
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ trait SqlIdiom extends Idiom {

def astTokenizer(implicit astTokenizer: Tokenizer[Ast], strategy: NamingStrategy): Tokenizer[Ast] =
Tokenizer[Ast] {
case a: Query => SqlQuery(a).token
case a: Query =>
// This case almost exclusively happens when you have a select inside of an insert.
// have a look at the SqlDslSpec `forUpdate` and `insert with subselects` tests
// for more details.
// Right now we are not removing extra select clauses here (via RemoveUnusedSelects) since I am not sure what
// kind of impact that could have on selects. Can try to do that in the future.
RemoveExtraAlias(strategy)(ExpandNestedQueries(SqlQuery(a))).token
case a: Operation => a.token
case a: Infix => a.token
case a: Action => a.token
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.getquill.context.sql

import io.getquill.{ Insert, Spec }
import io.getquill.context.sql.testContext._

class InsertSubquerySpec extends Spec {

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.getquill.context.sql.dsl

import io.getquill.Spec
import io.getquill.{ Insert, Query, Quoted, Spec }
import io.getquill.context.sql.testContext
import io.getquill.context.sql.testContext._

Expand All @@ -22,9 +22,29 @@ class SqlDslSpec extends Spec {
}

"forUpdate" in {
val q = quote {
val q: Quoted[Query[TestEntity]] = quote {
query[TestEntity].filter(t => t.s == "a").forUpdate
}
testContext.run(q).string mustEqual "SELECT t.s, t.i, t.l, t.o, t.b FROM TestEntity t WHERE t.s = 'a' FOR UPDATE"
}

case class Person(name: String, age: Int)

"insert with subselects" - {
// In this case we are not renaming the ages into the table, just the names so technically
// we can exclude the age columns. I am not sure if that has some other potential issues
// for inserts so for now I am just doing ExpandNestedSelects and RemoveUnusedAliases.
// have a look at `astTokenizer` in `SqlIdiom` for details.
val q1 = quote {
(query[Person].map(p => Person("x", p.age)) union query[Person]).map(_.name)
}

val q2 = quote {
infix"INSERT into names $q1".as[Insert[Person]]
}

"should show all field aliases" in {
testContext.run(q2).string mustEqual "INSERT into names SELECT x1.name FROM ((SELECT 'x' AS name, p.age FROM Person p) UNION (SELECT x.name, x.age FROM Person x)) AS x1"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -575,14 +575,14 @@ class SqlIdiomSpec extends Spec {
qr1.filter(t => qr2.filter(u => u.s == t.s).isEmpty)
}
testContext.run(q).string mustEqual
"SELECT t.s, t.i, t.l, t.o, t.b FROM TestEntity t WHERE NOT EXISTS (SELECT u.* FROM TestEntity2 u WHERE u.s = t.s)"
"SELECT t.s, t.i, t.l, t.o, t.b FROM TestEntity t WHERE NOT EXISTS (SELECT u.s, u.i, u.l, u.o FROM TestEntity2 u WHERE u.s = t.s)"
}
"nonEmpty" in {
val q = quote {
qr1.filter(t => qr2.filter(u => u.s == t.s).nonEmpty)
}
testContext.run(q).string mustEqual
"SELECT t.s, t.i, t.l, t.o, t.b FROM TestEntity t WHERE EXISTS (SELECT u.* FROM TestEntity2 u WHERE u.s = t.s)"
"SELECT t.s, t.i, t.l, t.o, t.b FROM TestEntity t WHERE EXISTS (SELECT u.s, u.i, u.l, u.o FROM TestEntity2 u WHERE u.s = t.s)"
}
"toUpperCase" in {
val q = quote {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,14 +327,14 @@ class RenamePropertiesOverrideSpec extends Spec {
e.filter(a => e.filter(b => b.i > 0).isEmpty).map(_.i)
}
testContextUpper.run(q).string mustEqual
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.* FROM test_entity b WHERE b.field_i > 0)"
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.field_s, b.field_i, b.L, b.O, b.B FROM test_entity b WHERE b.field_i > 0)"
}
"binary" in {
val q = quote {
e.filter(a => e.filter(b => b.i > 0).isEmpty && a.s == "test").map(_.i)
}
testContextUpper.run(q).string mustEqual
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.* FROM test_entity b WHERE b.field_i > 0) AND a.field_s = 'test'"
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.field_s, b.field_i, b.L, b.O, b.B FROM test_entity b WHERE b.field_i > 0) AND a.field_s = 'test'"
}
"query body" in {
val q = quote {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,14 +370,14 @@ class RenamePropertiesSpec extends Spec {
e.filter(a => e.filter(b => b.i > 0).isEmpty).map(_.i)
}
testContext.run(q).string mustEqual
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.* FROM test_entity b WHERE b.field_i > 0)"
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.field_s, b.field_i, b.l, b.o, b.b FROM test_entity b WHERE b.field_i > 0)"
}
"binary" in {
val q = quote {
e.filter(a => e.filter(b => b.i > 0).isEmpty && a.s == "test").map(_.i)
}
testContext.run(q).string mustEqual
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.* FROM test_entity b WHERE b.field_i > 0) AND a.field_s = 'test'"
"SELECT a.field_i FROM test_entity a WHERE NOT EXISTS (SELECT b.field_s, b.field_i, b.l, b.o, b.b FROM test_entity b WHERE b.field_i > 0) AND a.field_s = 'test'"
}
"query body" in {
val q = quote {
Expand Down

0 comments on commit 5952882

Please sign in to comment.