Permalink
Browse files

New Query Compiler Back-End

- Simplify `Comprehension` and add support for “having” clauses

- Add `TermSymbol` as a supertype for all non-TypeSymbols

- Add a new `Aggregate` node class to represent aggregations in a
  way that is closer to the target language and can perform multiple
  independent aggregations from the same source. The new
  `createAggregates` phase transforms all aggregations into this form.

- The phases `convertToComprehensions` and `fuseComprehensions` are
  replaced by the completely new `mergeToComprehensions` which relies
  on correct applicative joins (as established by `rewriteJoins`) and
  performs aggressive fusion of operations into `Comprehension` nodes
  but no reordering.

- A new phase `removeFieldNames` is spun off from `pruneProjections`
  (formerly `pruneFields). Pruning is done before
  `mergeToComprehensions` in order to remove unreferenced outer join
  discriminator columns (which would otherwise lead to unnecessary
  subqueries) but the translation from StructNodes to ProductNodes is
  delayed until the very end so that all phases after
  `flattenProjections` can rely on dealing exclusively with StructNodes
  in all projections.

- Eliminate unnecessary monadic joins involving `Pure` values in
  `rewriteJoins` instead of translating them into applicative joins.

- The decision to create implicit or explicit join syntax is deferred
  until `codeGen`. All `Comprehension` nodes contain a single “from”
  node which may be a (applicative) `Join`. The code generator optimizes
  purely inner/cross joins to implicit syntax.
  • Loading branch information...
szeiger committed Apr 29, 2015
1 parent 2b14139 commit 8baa07963a96cb7378426ed18d362bfadc37d5e7
Showing with 1,113 additions and 836 deletions.
  1. +4 −4 common-test-resources/logback.xml
  2. +4 −4 slick-testkit/src/doctest/resources/logback.xml
  3. +22 −18 slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/AggregateTest.scala
  4. +1 −1 slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/CountTest.scala
  5. +98 −0 slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/NewQuerySemanticsTest.scala
  6. +12 −12 slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/UnionTest.scala
  7. +8 −7 slick-testkit/src/main/scala/com/typesafe/slick/testkit/util/StandardTestDBs.scala
  8. +5 −5 slick-testkit/src/test/scala/slick/test/lifted/SchemaSupportTest.scala
  9. +3 −3 slick/src/main/scala/slick/ast/ClientSideOp.scala
  10. +29 −37 slick/src/main/scala/slick/ast/Comprehension.scala
  11. +2 −2 slick/src/main/scala/slick/ast/Library.scala
  12. +26 −4 slick/src/main/scala/slick/ast/Node.scala
  13. +11 −8 slick/src/main/scala/slick/ast/Symbol.scala
  14. +14 −16 slick/src/main/scala/slick/ast/Util.scala
  15. +3 −2 slick/src/main/scala/slick/compiler/CodeGen.scala
  16. +0 −61 slick/src/main/scala/slick/compiler/Columnizer.scala
  17. +106 −0 slick/src/main/scala/slick/compiler/CreateAggregates.scala
  18. +20 −15 slick/src/main/scala/slick/compiler/CreateResultSetMapping.scala
  19. +4 −0 slick/src/main/scala/slick/compiler/ExpandSums.scala
  20. +23 −29 slick/src/main/scala/slick/compiler/HoistClientOps.scala
  21. +349 −0 slick/src/main/scala/slick/compiler/MergeToComprehensions.scala
  22. +29 −0 slick/src/main/scala/slick/compiler/PruneProjections.scala
  23. +31 −18 slick/src/main/scala/slick/compiler/QueryCompiler.scala
  24. +20 −0 slick/src/main/scala/slick/compiler/RelabelUnions.scala
  25. +0 −506 slick/src/main/scala/slick/compiler/Relational.scala
  26. +34 −0 slick/src/main/scala/slick/compiler/RemoveFieldNames.scala
  27. +90 −0 slick/src/main/scala/slick/compiler/ResolveZipJoins.scala
  28. +9 −9 slick/src/main/scala/slick/compiler/RewriteBooleans.scala
  29. +5 −1 slick/src/main/scala/slick/compiler/RewriteJoins.scala
  30. +2 −2 slick/src/main/scala/slick/compiler/SpecializeParameters.scala
  31. +3 −0 slick/src/main/scala/slick/compiler/VerifySymbols.scala
  32. +1 −1 slick/src/main/scala/slick/driver/AccessDriver.scala
  33. +1 −0 slick/src/main/scala/slick/driver/DerbyDriver.scala
  34. +2 −0 slick/src/main/scala/slick/driver/H2Driver.scala
  35. +2 −0 slick/src/main/scala/slick/driver/HsqldbDriver.scala
  36. +0 −1 slick/src/main/scala/slick/driver/JdbcProfile.scala
  37. +100 −50 slick/src/main/scala/slick/driver/JdbcStatementBuilderComponent.scala
  38. +31 −19 slick/src/main/scala/slick/driver/MySQLDriver.scala
  39. +1 −0 slick/src/main/scala/slick/driver/SQLiteDriver.scala
  40. +2 −1 slick/src/main/scala/slick/memory/DistributedProfile.scala
  41. +3 −0 slick/src/main/scala/slick/memory/MemoryProfile.scala
  42. +3 −0 slick/src/main/scala/slick/profile/SqlProfile.scala
@@ -24,17 +24,17 @@
<logger name="slick.compiler.ExpandRecords" level="${log.qcomp.expandRecords:-inherited}" />
<logger name="slick.compiler.ExpandConditionals" level="${log.qcomp.expandConditionals:-inherited}" />
<logger name="slick.compiler.FlattenProjections" level="${log.qcomp.flattenProjections:-inherited}" />
<logger name="slick.compiler.CreateAggregates" level="${log.qcomp.createAggregates:-inherited}" />
<logger name="slick.compiler.RewriteJoins" level="${log.qcomp.rewriteJoins:-inherited}" />
<logger name="slick.compiler.RelabelUnions" level="${log.qcomp.relabelUnions:-inherited}" />
<logger name="slick.compiler.PruneFields" level="${log.qcomp.pruneFields:-inherited}" />
<logger name="slick.compiler.ResolveZipJoins" level="${log.qcomp.resolveZipJoins:-inherited}" />
<logger name="slick.compiler.ConvertToComprehensions" level="${log.qcomp.convertToComprehensions:-inherited}" />
<logger name="slick.compiler.FuseComprehensions" level="${log.qcomp.fuseComprehensions:-inherited}" />
<logger name="slick.compiler.MergeToComprehensions" level="${log.qcomp.mergeToComprehensions:-inherited}" />
<logger name="slick.compiler.FixRowNumberOrdering" level="${log.qcomp.fixRowNumberOrdering:-inherited}" />
<logger name="slick.compiler.HoistClientOps" level="${log.qcomp.hoistClientOps:-inherited}" />
<logger name="slick.compiler.PruneProjections" level="${log.qcomp.pruneProjections:-inherited}" />
<logger name="slick.compiler.RewriteBooleans" level="${log.qcomp.rewriteBooleans:-inherited}" />
<logger name="slick.compiler.SpecializeParameters" level="${log.qcomp.specializeParameters:-inherited}" />
<logger name="slick.compiler.CodeGen" level="${log.qcomp.codeGen:-inherited}" />
<logger name="slick.compiler.RemoveFieldNames" level="${log.qcomp.removeFieldNames:-inherited}" />
<logger name="slick.compiler.InsertCompiler" level="${log.qcomp.insertCompiler:-inherited}" />
<logger name="slick.jdbc.JdbcBackend.statement" level="${log.jdbc.statement:-info}" />
<logger name="slick.jdbc.JdbcBackend.benchmark" level="${log.jdbc.bench:-info}" />
@@ -24,17 +24,17 @@
<logger name="slick.compiler.ExpandRecords" level="${log.qcomp.expandRecords:-inherited}" />
<logger name="slick.compiler.ExpandConditionals" level="${log.qcomp.expandConditionals:-inherited}" />
<logger name="slick.compiler.FlattenProjections" level="${log.qcomp.flattenProjections:-inherited}" />
<logger name="slick.compiler.CreateAggregates" level="${log.qcomp.createAggregates:-inherited}" />
<logger name="slick.compiler.RewriteJoins" level="${log.qcomp.rewriteJoins:-inherited}" />
<logger name="slick.compiler.RelabelUnions" level="${log.qcomp.relabelUnions:-inherited}" />
<logger name="slick.compiler.PruneFields" level="${log.qcomp.pruneFields:-inherited}" />
<logger name="slick.compiler.ResolveZipJoins" level="${log.qcomp.resolveZipJoins:-inherited}" />
<logger name="slick.compiler.ConvertToComprehensions" level="${log.qcomp.convertToComprehensions:-inherited}" />
<logger name="slick.compiler.FuseComprehensions" level="${log.qcomp.fuseComprehensions:-inherited}" />
<logger name="slick.compiler.MergeToComprehensions" level="${log.qcomp.mergeToComprehensions:-inherited}" />
<logger name="slick.compiler.FixRowNumberOrdering" level="${log.qcomp.fixRowNumberOrdering:-inherited}" />
<logger name="slick.compiler.HoistClientOps" level="${log.qcomp.hoistClientOps:-inherited}" />
<logger name="slick.compiler.PruneProjections" level="${log.qcomp.pruneProjections:-inherited}" />
<logger name="slick.compiler.RewriteBooleans" level="${log.qcomp.rewriteBooleans:-inherited}" />
<logger name="slick.compiler.SpecializeParameters" level="${log.qcomp.specializeParameters:-inherited}" />
<logger name="slick.compiler.CodeGen" level="${log.qcomp.codeGen:-inherited}" />
<logger name="slick.compiler.RemoveFieldNames" level="${log.qcomp.removeFieldNames:-inherited}" />
<logger name="slick.compiler.InsertCompiler" level="${log.qcomp.insertCompiler:-inherited}" />
<logger name="slick.jdbc.JdbcBackend.statement" level="${log.jdbc.statement:-info}" />
<logger name="slick.jdbc.JdbcBackend.benchmark" level="${log.jdbc.bench:-info}" />
@@ -43,12 +43,12 @@ class AggregateTest extends AsyncTest[RelationalTestDB] {
}.flatMap { _ =>
val q0 = ts.groupBy(_.a)
val q1 = q0.map(_._2.length).sortBy(identity)
db.run(q1.result).map { r0t: Seq[Int] => r0t shouldBe Vector(2, 3, 3) }
db.run(mark("q1", q1.result)).map { r0t: Seq[Int] => r0t shouldBe Vector(2, 3, 3) }
}.flatMap { _ =>
val q = (for {
(k, v) <- ts.groupBy(t => t.a)
} yield (k, v.length, v.map(_.a).sum, v.map(_.b).sum)).sortBy(_._1)
db.run(q.result).map { rt: Seq[(Int, Int, Option[Int], Option[Int])] =>
db.run(mark("q", q.result)).map { rt: Seq[(Int, Int, Option[Int], Option[Int])] =>
rt shouldBe Vector((1, 3, Some(3), Some(6)), (2, 3, Some(6), Some(8)), (3, 2, Some(6), Some(10)))
}
}.flatMap { _ =>
@@ -60,21 +60,21 @@ class AggregateTest extends AsyncTest[RelationalTestDB] {
} yield (u, t)).groupBy(_._1.id).map {
case (id, q) => (id, q.length, q.map(_._2.a).sum, q.map(_._2.b).sum)
}
db.run(q2.result).map { r2t: Seq[(Int, Int, Option[Int], Option[Int])] =>
db.run(mark("q2", q2.result)).map { r2t: Seq[(Int, Int, Option[Int], Option[Int])] =>
r2t.toSet shouldBe Set((1, 3, Some(3), Some(6)), (2, 3, Some(6), Some(8)), (3, 2, Some(6), Some(10)))
}
}.flatMap { _ =>
val q3 = (for {
(x, q) <- ts.map(t => (t.a + 10, t.b)).groupBy(_._1)
} yield (x, q.map(_._2).sum)).sortBy(_._1)
db.run(q3.result).map { r3t: Seq[(Int, Option[Int])] =>
db.run(mark("q3", q3.result)).map { r3t: Seq[(Int, Option[Int])] =>
r3t shouldBe Vector((11, Some(6)), (12, Some(8)), (13, Some(10)))
}
}.flatMap { _ =>
val q4 = (for {
(x, q) <- ts.groupBy(t => (t.a, t.b))
} yield (x, q.length)).sortBy(_._1)
db.run(q4.result).map { r4t: Seq[((Int, Option[Int]), Int)] =>
db.run(mark("q4", q4.result)).map { r4t: Seq[((Int, Option[Int]), Int)] =>
r4t shouldBe Vector(
((1,Some(1)),1), ((1,Some(2)),1), ((1,Some(3)),1),
((2,Some(1)),1), ((2,Some(2)),1), ((2,Some(5)),1),
@@ -89,7 +89,7 @@ class AggregateTest extends AsyncTest[RelationalTestDB] {
.groupBy(x => (x._1, x._2))
.map { case (a, _) => (a._1, a._2) }
.to[Set]
db.run(q5.result).map(_ shouldBe Set((1, Some(1)), (1, Some(2)), (1, Some(3))))
db.run(mark("q5", q5.result)).map(_ shouldBe Set((1, Some(1)), (1, Some(2)), (1, Some(3))))
}.flatMap { _ =>
db.run(us += 4)
}.flatMap { _ =>
@@ -98,23 +98,27 @@ class AggregateTest extends AsyncTest[RelationalTestDB] {
} yield (u, t)).groupBy(_._1.id).map {
case (id, q) => (id, q.length, q.map(_._1).length, q.map(_._2).length)
}).to[Set]
db.run(q6.result).map(_ shouldBe Set((1, 3, 3, 3), (2, 3, 3, 3), (3, 2, 2, 2), (4, 1, 1, 0)))
db.run(mark("q6", q6.result)).map(_ shouldBe Set((1, 3, 3, 3), (2, 3, 3, 3), (3, 2, 2, 2), (4, 1, 1, 0)))
}.flatMap { _ =>
val q7 = ts.groupBy(_.a).map { case (a, ts) =>
(a, ts.map(_.b).sum, ts.map(_.b).min, ts.map(_.b).max, ts.map(_.b).avg)
}.to[Set]
db.run(q7.result).map(_ shouldBe Set(
db.run(mark("q7", q7.result)).map(_ shouldBe Set(
(1, Some(6), Some(1), Some(3), Some(2)),
(2, Some(8), Some(1), Some(5), Some(2)),
(3, Some(10), Some(1), Some(9), Some(5))))
}.flatMap { _ =>
val q8 = us.map( _ => "test").groupBy(x => x).map(_._2.max)
val q8a = us.map(_.id.asColumnOf[String] ++ "test").groupBy(x => x).map(_._2.max)
val q8b = for( (key, group) <- us.map(_ => "x").groupBy(co => co) ) yield (key, group.map(co => co).max )
val q8c = for( (key, group) <- us.map(_ => 5).groupBy(co => co) ) yield (key, group.map(co => co + co).sum )
val q8d = us.map(_ => LiteralColumn("te")++"st").groupBy(x => x).map(_._2.max)
db.run(for {
_ <- q8.result.map(_ shouldBe Seq(Some("test")))
_ <- q8b.result.map(_ shouldBe Seq(("x", Some("x"))))
_ <- q8c.result.map(_ shouldBe Seq((5, Some(40))))
_ <- mark("q8a", q8a.result).map(_.toSet shouldBe Set(Some("1test"), Some("2test"), Some("3test"), Some("4test")))
_ <- mark("q8d", q8d.result).map(_ shouldBe Seq(Some("test")))
_ <- mark("q8", q8.result).map(_ shouldBe Seq(Some("test")))
_ <- mark("q8b", q8b.result).map(_ shouldBe Seq(("x", Some("x"))))
_ <- mark("q8c", q8c.result).map(_ shouldBe Seq((5, Some(40))))
} yield ())
}.flatMap { _ =>
val res9 = Set(
@@ -126,17 +130,17 @@ class AggregateTest extends AsyncTest[RelationalTestDB] {
val q9b = ts.map(x => x).groupBy(_.*).map(_._1).to[Set]
val q9c = ts.map(x => x).groupBy(x => x).map(_._1).to[Set]
db.run(for {
_ <- q9.result.map(_ shouldBe res9)
_ <- q9b.result.map(_ shouldBe res9)
_ <- q9c.result.map(_ shouldBe res9)
_ <- mark("q9", q9.result).map(_ shouldBe res9)
_ <- mark("q9b", q9b.result).map(_ shouldBe res9)
_ <- mark("q9c", q9c.result).map(_ shouldBe res9)
} yield ())
}.flatMap { _ =>
val q10 = ((for {
m <- ts
} yield m) groupBy (_.a) map {
case (id, data) => (id, data.map(_.b.asColumnOf[Option[Double]]).max)
}).to[Set]
db.run(q10.result).map(_ shouldBe Set((2,Some(5.0)), (1,Some(3.0)), (3,Some(9.0))))
db.run(mark("q10", q10.result)).map(_ shouldBe Set((2,Some(5.0)), (1,Some(3.0)), (3,Some(9.0))))
}.flatMap { _ =>
case class Pair(a:Int,b:Option[Int])
class T4(tag: Tag) extends Table[Pair](tag, "t4") {
@@ -155,13 +159,13 @@ class AggregateTest extends AsyncTest[RelationalTestDB] {
val q13 = t4s.map(identity)
val q11 = t4s.groupBy(identity).map(_._1)
db.run(for {
res12 <- q12.result
res12 <- mark("q12", q12.result)
_ = res12.size shouldBe 6
_ = res12.toSet shouldBe expected11
res13 <- q13.result
res13 <- mark("q13", q13.result)
_ = res13.size shouldBe 6
_ = res13.toSet shouldBe expected11
res11 <- q11.result
res11 <- mark("q11", q11.result)
_ = res11.size shouldBe 2
_ = res11.toSet shouldBe expected11
} yield ())
@@ -5,7 +5,7 @@ import com.typesafe.slick.testkit.util.{RelationalTestDB, AsyncTest}
class CountTest extends AsyncTest[RelationalTestDB] {
import tdb.profile.api._
def test = {
def testSimple = {
class TestTable(tag: Tag) extends Table[Int](tag, "TEST") {
def id = column[Int]("ID")
def * = id
@@ -1,5 +1,8 @@
package com.typesafe.slick.testkit.tests
import slick.SlickTreeException
import slick.driver.H2Driver
import scala.language.higherKinds
import com.typesafe.slick.testkit.util.{RelationalTestDB, AsyncTest}
@@ -465,4 +468,99 @@ class NewQuerySemanticsTest extends AsyncTest[RelationalTestDB] {
_ = r2 shouldBe Set((1, "a1"), (1, "a2"), (1, "a3"), (2, "a1"), (2, "a2"), (2, "a3"), (3, "a1"), (3, "a2"), (3, "a3"))
} yield ()
}
def testNewFusion = {
class A(tag: Tag) extends Table[(Int, String, String)](tag, "A_NEWFUSION") {
def id = column[Int]("id")
def a = column[String]("a")
def b = column[String]("b")
def * = (id, a, b)
}
val as = TableQuery[A]
val data = Set((1, "a", "a"), (2, "a", "b"), (3, "c", "b"))
val q1 = (as join as on (_.id === _.id))
val q2 = (as join as on (_.id === _.id) join as on (_._1.id === _.id))
val q3 = q2.map { case ((a1, a2), a3) => (a1.id, a2.a, a3.b) }
val q4 = as.map(a => (a.id, a.a, a.b, a)).filter(_._3 === "b").map { case (id, a1, b, a2) => (id, a2) }
val q5a = as.to[Set].filter(_.b === "b").map(_.id)
val q5b = as.filter(_.b === "b").to[Set].map(_.id)
val q5c = as.filter(_.b === "b").map(_.id).to[Set]
val q6 = (as join as).groupBy(j => (j._1.a, j._1.b)).map { case (ab, rs) => (ab, rs.length, rs.map(_._1).length, rs.map(_._2).length, rs.map(_._1.id).max, rs.map(_._1.id).length) }
val q7 = q6.filter(_._1._1 === "a").map(_._5.getOrElse(0))
val q8 = as.sortBy(_.id.desc).map(_.a)
val q9a = as.sortBy(_.b).sortBy(_.a.desc).map(_.id)
val q9b = as.sortBy(a => (a.a.desc, a.b)).map(_.id)
val q10 = (as join as).map { case (a1, a2) => a1.id * 3 + a2.id - 3 }.sorted
val q11a = q10.take(5)
val q11b = q10.take(5).take(3)
val q11c = q10.take(5).take(3).drop(1)
val q11d = q10.take(5).drop(1).take(3)
val q11e = q10.drop(7)
val q11f = q10.take(6).drop(2).filter(_ =!= 5)
val q12 = as.filter(_.id <= as.map(_.id).max-1).map(_.a)
//val q5 = q1.length
if(tdb.driver == H2Driver) {
assertNesting(q1, 1)
assertNesting(q2, 1)
assertNesting(q3, 1)
assertNesting(q4, 1)
assertNesting(q5a, 1)
assertNesting(q5b, 1)
assertNesting(q5c, 1)
assertNesting(q6, 1)
assertNesting(q7, 1)
assertNesting(q8, 1)
assertNesting(q9a, 1)
assertNesting(q9b, 1)
assertNesting(q10, 1)
assertNesting(q11a, 1)
assertNesting(q11b, 1)
assertNesting(q11c, 1)
assertNesting(q11d, 1)
assertNesting(q11e, 1)
assertNesting(q11f, 2)
}
for {
_ <- as.schema.create
_ <- as ++= data
_ <- mark("as", as.result).map(_.toSet shouldBe data)
_ <- mark("q1", q1.result).map(_.toSet shouldBe data.zip(data))
_ <- mark("q2", q2.result).map(_.toSet shouldBe data.zip(data).zip(data))
_ <- mark("q3", q3.result).map(_.toSet shouldBe data)
_ <- mark("q4", q4.result).map(_.toSet shouldBe data.filter(_._3 == "b").map { case t @ (id, _, _) => (id, t) })
_ <- mark("q5a", q5a.result).map(_ shouldBe Set(2, 3))
_ <- mark("q5b", q5b.result).map(_ shouldBe Set(2, 3))
_ <- mark("q5c", q5c.result).map(_ shouldBe Set(2, 3))
_ <- mark("q6", q6.result).map(_.toSet shouldBe Set((("c","b"),3,3,3,Some(3),3), (("a","a"),3,3,3,Some(1),3), (("a","b"),3,3,3,Some(2),3)))
_ <- mark("q7", q7.result).map(_.toSet shouldBe Set(1, 2))
_ <- mark("q8", q8.result).map(_ shouldBe Seq("c", "a", "a"))
_ <- mark("q9a", q9a.result).map(_ shouldBe Seq(3, 1, 2))
_ <- mark("q9b", q9b.result).map(_ shouldBe Seq(3, 1, 2))
_ <- mark("q10", q10.result).map(_ shouldBe Seq(1, 2, 3, 4, 5, 6, 7, 8, 9))
_ <- mark("q11a", q11a.result).map(_ shouldBe Seq(1, 2, 3, 4, 5))
_ <- mark("q11b", q11b.result).map(_ shouldBe Seq(1, 2, 3))
_ <- mark("q11c", q11c.result).map(_ shouldBe Seq(2, 3))
_ <- mark("q11d", q11d.result).map(_ shouldBe Seq(2, 3, 4))
_ <- mark("q11e", q11e.result).map(_ shouldBe Seq(8, 9))
_ <- mark("q11f", q11f.result).map(_ shouldBe Seq(3, 4, 6))
_ <- mark("q12", q12.result).map(_ shouldBe Seq("a", "a"))
} yield ()
}
def assertNesting(q: Rep[_], exp: Int): Unit = {
import slick.compiler.QueryCompiler
import slick.ast._
import slick.ast.Util._
val qc = new QueryCompiler(tdb.driver.queryCompiler.phases.takeWhile(_.name != "codeGen"))
val cs = qc.run(q.toNode)
val found = cs.tree.collect { case c: Comprehension => c }.size
if(found != exp)
throw cs.symbolNamer.use(new SlickTreeException(s"Found $found Comprehension nodes, should be $exp",
cs.tree, mark = (_.isInstanceOf[Comprehension]), removeUnmarked = false))
}
}
@@ -32,26 +32,26 @@ class UnionTest extends AsyncTest[RelationalTestDB] {
val q4b = q4 union q4
val q4c = q4 union q4 union q4
seq(
(managers.schema ++ employees.schema).create,
managers ++= Seq(
(for {
_ <- (managers.schema ++ employees.schema).create
_ <- managers ++= Seq(
(1, "Peter", "HR"),
(2, "Amy", "IT"),
(3, "Steve", "IT")
),
employees ++= Seq(
)
_ <- employees ++= Seq(
(4, "Jennifer", 1),
(5, "Tom", 1),
(6, "Leonard", 2),
(7, "Ben", 2),
(8, "Greg", 3)
),
q1.result.map(r => r.toSet shouldBe Set((2,"Amy"), (3,"Steve"))),
q2.result.map(r => r.toSet shouldBe Set((7,"Ben"), (8,"Greg"), (6,"Leonard"))),
q3.result.map(_ shouldBe List((2,"Amy"), (7,"Ben"), (8,"Greg"), (6,"Leonard"), (3,"Steve"))),
q4b.result.map(r => r.toSet shouldBe Set(1, 2, 3)),
q4c.result.map(r => r.toSet shouldBe Set(1, 2, 3))
) andFinally (managers.schema ++ employees.schema).drop
)
_ <- mark("q1", q1.result).map(r => r.toSet shouldBe Set((2,"Amy"), (3,"Steve")))
_ <- mark("q2", q2.result).map(r => r.toSet shouldBe Set((7,"Ben"), (8,"Greg"), (6,"Leonard")))
_ <- mark("q3", q3.result).map(_ shouldBe List((2,"Amy"), (7,"Ben"), (8,"Greg"), (6,"Leonard"), (3,"Steve")))
_ <- mark("q4b", q4b.result).map(r => r.toSet shouldBe Set(1, 2, 3))
_ <- mark("q4c", q4c.result).map(r => r.toSet shouldBe Set(1, 2, 3))
} yield ()) andFinally (managers.schema ++ employees.schema).drop
}
def testUnionWithoutProjection = {
@@ -11,7 +11,8 @@ import slick.jdbc.GetResult._
import slick.jdbc.meta.MTable
import org.junit.Assert
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}
object StandardTestDBs {
lazy val H2Mem = new H2TestDB("h2mem", false) {
@@ -220,11 +221,11 @@ abstract class HsqlDB(confName: String) extends InternalJdbcTestDB(confName) {
ResultSetAction[(String,String,String, String)](_.conn.getMetaData().getTables(null, "PUBLIC", null, null)).map { ts =>
ts.map(_._3).sorted
}
override def cleanUpBefore() {
// Try to turn Hsqldb logging off -- does not work :(
System.setProperty("hsqldb.reconfig_logging", "false")
Logger.getLogger("org.hsqldb.persist.Logger").setLevel(Level.OFF)
Logger.getLogger("org.hsqldb").setLevel(Level.OFF)
Logger.getLogger("hsqldb").setLevel(Level.OFF)
override def createDB(): profile.Backend#Database = {
val db = super.createDB()
Await.result(db.run(SimpleJdbcAction(_ => ())), Duration.Inf)
Logger.getLogger("hsqldb.db").setLevel(Level.WARNING)
Logger.getLogger("org.hsqldb").setLevel(Level.WARNING)
db
}
}
Oops, something went wrong.

0 comments on commit 8baa079

Please sign in to comment.