diff --git a/build.sbt b/build.sbt index 323041cb3d..a97fd508d4 100644 --- a/build.sbt +++ b/build.sbt @@ -53,8 +53,7 @@ lazy val dbModules = Seq[sbt.ClasspathDep[sbt.ProjectReference]]( lazy val codegenModules = Seq[sbt.ClasspathDep[sbt.ProjectReference]]( `quill-codegen`, - `quill-codegen-jdbc`, - `quill-codegen-tests` + `quill-codegen-jdbc` ) lazy val bigdataModules = Seq[sbt.ClasspathDep[sbt.ProjectReference]]( @@ -93,7 +92,7 @@ lazy val filteredModules = { val moduleStrings = ListSet( modulesStr - .getOrElse("all") + .getOrElse("nocodegen") .split(",") .map(_.trim): _* ) @@ -121,8 +120,10 @@ lazy val filteredModules = { println("SBT =:> Invoking Aggregate Project") Seq[sbt.ClasspathDep[sbt.ProjectReference]]() case _ | "all" => - println("SBT =:> Compiling All Modules") - allModules + println("Compiling Not-Code Generator Modules") + baseModules ++ dbModules ++ bigdataModules + // println("SBT =:> Compiling All Modules") + // allModules } val selectedModules = { @@ -264,39 +265,39 @@ lazy val `quill-codegen-jdbc` = .dependsOn(`quill-codegen` % "compile->compile;test->test") .dependsOn(`quill-jdbc` % "compile->compile") -lazy val `quill-codegen-tests` = - (project in file("quill-codegen-tests")) - .settings(commonSettings: _*) - .settings( - publish / skip := true, - libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value % Test, - Test / fork := true, - (Test / sourceGenerators) += Def.task { - def recursiveList(file: JFile): List[JFile] = - if (file.isDirectory) - Option(file.listFiles()).map(_.flatMap(child => recursiveList(child)).toList).toList.flatten - else - List(file) - val r = (Compile / runner).value - val s = streams.value.log - val sourcePath = sourceManaged.value - val classPath = (`quill-codegen-jdbc` / Test / fullClasspath).value.map(_.data) - - // We could put the code generated products directly in the `sourcePath` directory but for some reason - // intellij doesn't like it unless there's a `main` directory inside. - val fileDir = new File(sourcePath, "main").getAbsoluteFile - val dbs = Seq("testH2DB", "testMysqlDB", "testPostgresDB", "testSqliteDB", "testSqlServerDB", "testOracleDB") - println(s"Running code generation for DBs: ${dbs.mkString(", ")}") - r.run( - "io.getquill.codegen.integration.CodegenTestCaseRunner", - classPath, - fileDir.getAbsolutePath +: dbs, - s - ) - recursiveList(fileDir) - }.tag(CodegenTag) - ) - .dependsOn(`quill-codegen-jdbc` % "compile->test") +//lazy val `quill-codegen-tests` = +// (project in file("quill-codegen-tests")) +// .settings(commonSettings: _*) +// .settings( +// publish / skip := true, +// libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value % Test, +// Test / fork := true, +// (Test / sourceGenerators) += Def.task { +// def recursiveList(file: JFile): List[JFile] = +// if (file.isDirectory) +// Option(file.listFiles()).map(_.flatMap(child => recursiveList(child)).toList).toList.flatten +// else +// List(file) +// val r = (Compile / runner).value +// val s = streams.value.log +// val sourcePath = sourceManaged.value +// val classPath = (`quill-codegen-jdbc` / Test / fullClasspath).value.map(_.data) +// +// // We could put the code generated products directly in the `sourcePath` directory but for some reason +// // intellij doesn't like it unless there's a `main` directory inside. +// val fileDir = new File(sourcePath, "main").getAbsoluteFile +// val dbs = Seq("testH2DB", "testMysqlDB", "testPostgresDB", "testSqliteDB", "testSqlServerDB", "testOracleDB") +// println(s"Running code generation for DBs: ${dbs.mkString(", ")}") +// r.run( +// "io.getquill.codegen.integration.CodegenTestCaseRunner", +// classPath, +// fileDir.getAbsolutePath +: dbs, +// s +// ) +// recursiveList(fileDir) +// }.tag(CodegenTag) +// ) +// .dependsOn(`quill-codegen-jdbc` % "compile->test") val excludeTests = sys.props.getOrElse("excludeTests", "false") match { diff --git a/build/Dockerfile-sqlserver b/build/Dockerfile-sqlserver new file mode 100644 index 0000000000..748b293e61 --- /dev/null +++ b/build/Dockerfile-sqlserver @@ -0,0 +1,6 @@ +# Builds a ubuntu-based postgres image whose latency can be modified to be highe +# for performance experimentation. +FROM mcr.microsoft.com/mssql/server:2022-CU13-ubuntu-22.04 +USER root +RUN apt-get update && \ + apt-get install iproute2 iputils-ping -y diff --git a/docker-compose.yml b/docker-compose.yml index 9d7997bfa2..f3aef64359 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,12 +42,16 @@ services: init: true sqlserver: - image: mcr.microsoft.com/azure-sql-edge:latest # use this because it supports ARM64 architecture for M1 Mac + build: + context: . + dockerfile: ./build/Dockerfile-sqlserver ports: - "11433:1433" environment: - ACCEPT_EULA=Y - SA_PASSWORD=QuillRocks! + cap_add: + - NET_ADMIN oracle: image: quillbuilduser/oracle-18-xe-micro-sq diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/H2CodegenTestCases.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/H2CodegenTestCases.scala deleted file mode 100644 index 6173cd3a25..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/H2CodegenTestCases.scala +++ /dev/null @@ -1,110 +0,0 @@ -package io.getquill.codegen - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.TestH2DB -import io.getquill.codegen.util._ -import org.scalatest.matchers.should.Matchers._ - -class H2CodegenTestCases extends CodegenSpec { - import io.getquill.codegen.generated.h2._ - - type Prefix = TestH2DB - val prefix = TestH2DB - - "trivial generator tests" - { - "use trivial snake case schema" in WithContext[Prefix, `1-simple-snake`].run { ctx => - import `1-simple-snake-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - "use trivial literal schema" in WithContext[Prefix, `2-simple-literal`].run { ctx => - import `2-simple-literal-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - } - - "composable generator" - { - - "1-comp-sanity" in WithContext[Prefix, `1-comp-sanity`].run { ctx => - import `1-comp-sanity-lib`.public._ - import ctx._ - ctx.run(query[Person].filter(_.age > 11)) should contain theSameElementsAs List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - ) - } - - "2-comp-stereo-single" in WithContext[Prefix, `2-comp-stereo-single`].run { ctx => - import `2-comp-stereo-single-lib`.public._ - import ctx._ - (ctx.run(PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs - (List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - )) - } - - "3-comp-stereo-oneschema" in WithContext[Prefix, `3-comp-stereo-oneschema`].run { ctx => - import `3-comp-stereo-oneschema-lib`.public._ - import ctx._ - - (ctx.run(PublicSchema.PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(PublicSchema.AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "4-comp-stereo-twoschema" in WithContext[Prefix, `4-comp-stereo-twoschema`].run { ctx => - import `4-comp-stereo-twoschema-lib`.common._ - import `4-comp-stereo-twoschema-lib`.public._ - import ctx._ - - (ctx.run(PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "5 - non-stereotyped multiple schemas" in WithContext[Prefix, `5-comp-non-stereo-allschema`].run { ctx => - import `5-comp-non-stereo-allschema-lib`.alpha._ - import `5-comp-non-stereo-allschema-lib`.public._ - import ctx._ - - (ctx.run(ctx.AlphaSchema.PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, "blah", 55, "Wonkles"), - Person(2, "Jack", "Ripper", 33, "blah", 66, "Ginkles") - ) - ) - (ctx.run(ctx.PublicSchema.AddressDao.query.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - } -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/MysqlCodegenTestCases.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/MysqlCodegenTestCases.scala deleted file mode 100644 index 5aa6bb1990..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/MysqlCodegenTestCases.scala +++ /dev/null @@ -1,110 +0,0 @@ -package io.getquill.codegen - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.TestMysqlDB -import io.getquill.codegen.util._ -import org.scalatest.matchers.should.Matchers._ - -class MysqlCodegenTestCases extends CodegenSpec { - import io.getquill.codegen.generated.mysql._ - - type Prefix = TestMysqlDB - val prefix = TestMysqlDB - - "trivial generator tests" - { - "use trivial snake case schema" in WithContext[Prefix, `1-simple-snake`].run { ctx => - import `1-simple-snake-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - "use trivial literal schema" in WithContext[Prefix, `2-simple-literal`].run { ctx => - import `2-simple-literal-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - } - - "composable generator" - { - - "1-comp-sanity" in WithContext[Prefix, `1-comp-sanity`].run { ctx => - import `1-comp-sanity-lib`.public._ - import ctx._ - ctx.run(query[Person].filter(_.age > 11)) should contain theSameElementsAs List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - ) - } - - "2-comp-stereo-single" in WithContext[Prefix, `2-comp-stereo-single`].run { ctx => - import `2-comp-stereo-single-lib`.public._ - import ctx._ - (ctx.run(PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs - (List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - )) - } - - "3-comp-stereo-oneschema" in WithContext[Prefix, `3-comp-stereo-oneschema`].run { ctx => - import `3-comp-stereo-oneschema-lib`.public._ - import ctx._ - - (ctx.run(PublicSchema.PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(PublicSchema.AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "4-comp-stereo-twoschema" in WithContext[Prefix, `4-comp-stereo-twoschema`].run { ctx => - import `4-comp-stereo-twoschema-lib`.common._ - import `4-comp-stereo-twoschema-lib`.public._ - import ctx._ - - (ctx.run(PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "5 - non-stereotyped multiple schemas" in WithContext[Prefix, `5-comp-non-stereo-allschema`].run { ctx => - import `5-comp-non-stereo-allschema-lib`.alpha._ - import `5-comp-non-stereo-allschema-lib`.public._ - import ctx._ - - (ctx.run(ctx.AlphaSchema.PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, "blah", 55, "Wonkles"), - Person(2, "Jack", "Ripper", 33, "blah", 66, "Ginkles") - ) - ) - (ctx.run(ctx.PublicSchema.AddressDao.query.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - } -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/OracleCodegenTestCases.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/OracleCodegenTestCases.scala deleted file mode 100644 index 07301cafe2..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/OracleCodegenTestCases.scala +++ /dev/null @@ -1,111 +0,0 @@ -package io.getquill.codegen - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.TestOracleDB -import io.getquill.codegen.util.{WithOracleContextStandalone => WithContext, _} -import WithContext._ -import org.scalatest.matchers.should.Matchers._ - -class OracleCodegenTestCases extends CodegenSpec { - import io.getquill.codegen.generated.oracle._ - - type Prefix = TestOracleDB - val prefix = TestOracleDB - - "trivial generator tests" - { - "use trivial snake case schema" in WithContext[Prefix, `1-simple-snake`].run { ctx => - import `1-simple-snake-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - "use trivial literal schema" in WithContext[Prefix, `2-simple-literal`].run { ctx => - import `2-simple-literal-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - } - - "composable generator" - { - - "1-comp-sanity" in WithContext[Prefix, `1-comp-sanity`].run { ctx => - import `1-comp-sanity-lib`.public._ - import ctx._ - ctx.run(query[Person].filter(_.age > 11)) should contain theSameElementsAs List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - ) - } - - "2-comp-stereo-single" in WithContext[Prefix, `2-comp-stereo-single`].run { ctx => - import `2-comp-stereo-single-lib`.public._ - import ctx._ - (ctx.run(PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs - (List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - )) - } - - "3-comp-stereo-oneschema" in WithContext[Prefix, `3-comp-stereo-oneschema`].run { ctx => - import `3-comp-stereo-oneschema-lib`.public._ - import ctx._ - - (ctx.run(PublicSchema.PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(PublicSchema.AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "4-comp-stereo-twoschema" in WithContext[Prefix, `4-comp-stereo-twoschema`].run { ctx => - import `4-comp-stereo-twoschema-lib`.common._ - import `4-comp-stereo-twoschema-lib`.public._ - import ctx._ - - (ctx.run(PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "5 - non-stereotyped multiple schemas" in WithContext[Prefix, `5-comp-non-stereo-allschema`].run { ctx => - import `5-comp-non-stereo-allschema-lib`.alpha._ - import `5-comp-non-stereo-allschema-lib`.public._ - import ctx._ - - (ctx.run(ctx.AlphaSchema.PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, "blah", 55, "Wonkles"), - Person(2, "Jack", "Ripper", 33, "blah", 66, "Ginkles") - ) - ) - (ctx.run(ctx.PublicSchema.AddressDao.query.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - } -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/PostgresCodegenTestCases.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/PostgresCodegenTestCases.scala deleted file mode 100644 index b2e147c66a..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/PostgresCodegenTestCases.scala +++ /dev/null @@ -1,110 +0,0 @@ -package io.getquill.codegen - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.TestPostgresDB -import io.getquill.codegen.util._ -import org.scalatest.matchers.should.Matchers._ - -class PostgresCodegenTestCases extends CodegenSpec { - import io.getquill.codegen.generated.postgres._ - - type Prefix = TestPostgresDB - val prefix = TestPostgresDB - - "trivial generator tests" - { - "use trivial snake case schema" in WithContext[Prefix, `1-simple-snake`].run { ctx => - import `1-simple-snake-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - "use trivial literal schema" in WithContext[Prefix, `2-simple-literal`].run { ctx => - import `2-simple-literal-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - } - - "composable generator" - { - - "1-comp-sanity" in WithContext[Prefix, `1-comp-sanity`].run { ctx => - import `1-comp-sanity-lib`.public._ - import ctx._ - ctx.run(query[Person].filter(_.age > 11)) should contain theSameElementsAs List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - ) - } - - "2-comp-stereo-single" in WithContext[Prefix, `2-comp-stereo-single`].run { ctx => - import `2-comp-stereo-single-lib`.public._ - import ctx._ - (ctx.run(PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs - (List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - )) - } - - "3-comp-stereo-oneschema" in WithContext[Prefix, `3-comp-stereo-oneschema`].run { ctx => - import `3-comp-stereo-oneschema-lib`.public._ - import ctx._ - - (ctx.run(PublicSchema.PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(PublicSchema.AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "4-comp-stereo-twoschema" in WithContext[Prefix, `4-comp-stereo-twoschema`].run { ctx => - import `4-comp-stereo-twoschema-lib`.common._ - import `4-comp-stereo-twoschema-lib`.public._ - import ctx._ - - (ctx.run(PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "5 - non-stereotyped multiple schemas" in WithContext[Prefix, `5-comp-non-stereo-allschema`].run { ctx => - import `5-comp-non-stereo-allschema-lib`.alpha._ - import `5-comp-non-stereo-allschema-lib`.public._ - import ctx._ - - (ctx.run(ctx.AlphaSchema.PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, "blah", 55, "Wonkles"), - Person(2, "Jack", "Ripper", 33, "blah", 66, "Ginkles") - ) - ) - (ctx.run(ctx.PublicSchema.AddressDao.query.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - } -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/SqlServerCodegenTestCases.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/SqlServerCodegenTestCases.scala deleted file mode 100644 index 73d7cb8a8e..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/SqlServerCodegenTestCases.scala +++ /dev/null @@ -1,110 +0,0 @@ -package io.getquill.codegen - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.TestSqlServerDB -import io.getquill.codegen.util._ -import org.scalatest.matchers.should.Matchers._ - -class SqlServerCodegenTestCases extends CodegenSpec { - import io.getquill.codegen.generated.postgres._ - - type Prefix = TestSqlServerDB - val prefix = TestSqlServerDB - - "trivial generator tests" - { - "use trivial snake case schema" in WithContext[Prefix, `1-simple-snake`].run { ctx => - import `1-simple-snake-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - "use trivial literal schema" in WithContext[Prefix, `2-simple-literal`].run { ctx => - import `2-simple-literal-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - } - - "composable generator" - { - - "1-comp-sanity" in WithContext[Prefix, `1-comp-sanity`].run { ctx => - import `1-comp-sanity-lib`.public._ - import ctx._ - ctx.run(query[Person].filter(_.age > 11)) should contain theSameElementsAs List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - ) - } - - "2-comp-stereo-single" in WithContext[Prefix, `2-comp-stereo-single`].run { ctx => - import `2-comp-stereo-single-lib`.public._ - import ctx._ - (ctx.run(PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs - (List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - )) - } - - "3-comp-stereo-oneschema" in WithContext[Prefix, `3-comp-stereo-oneschema`].run { ctx => - import `3-comp-stereo-oneschema-lib`.public._ - import ctx._ - - (ctx.run(PublicSchema.PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(PublicSchema.AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "4-comp-stereo-twoschema" in WithContext[Prefix, `4-comp-stereo-twoschema`].run { ctx => - import `4-comp-stereo-twoschema-lib`.common._ - import `4-comp-stereo-twoschema-lib`.public._ - import ctx._ - - (ctx.run(PersonDao.alphaPerson.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, 55L, "Wonkles"), - Person(2, "Jack", "Ripper", 33, 66L, "Ginkles") - ) - ) - (ctx.run(AddressDao.publicAddress.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - - "5 - non-stereotyped multiple schemas" in WithContext[Prefix, `5-comp-non-stereo-allschema`].run { ctx => - import `5-comp-non-stereo-allschema-lib`.alpha._ - import `5-comp-non-stereo-allschema-lib`.public._ - import ctx._ - - (ctx.run(ctx.AlphaSchema.PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs ( - List( - Person(1, "Joe", "Bloggs", 22, "blah", 55, "Wonkles"), - Person(2, "Jack", "Ripper", 33, "blah", 66, "Ginkles") - ) - ) - (ctx.run(ctx.PublicSchema.AddressDao.query.filter(_.personFk == 1))) should contain theSameElementsAs ( - List( - Address(1, "123 Someplace", 1001), - Address(1, "678 Blah", 2002) - ) - ) - } - } -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/SqliteCodegenTestCases.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/SqliteCodegenTestCases.scala deleted file mode 100644 index ea88986229..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/SqliteCodegenTestCases.scala +++ /dev/null @@ -1,54 +0,0 @@ -package io.getquill.codegen - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.TestSqliteDB -import io.getquill.codegen.util._ -import org.scalatest.matchers.should.Matchers._ - -class SqliteCodegenTestCases extends CodegenSpec { - import io.getquill.codegen.generated.postgres._ - - type Prefix = TestSqliteDB - val prefix = TestSqliteDB - - "trivial generator tests" - { - "use trivial snake case schema" in WithContext[Prefix, `1-simple-snake`].run { ctx => - import `1-simple-snake-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - "use trivial literal schema" in WithContext[Prefix, `2-simple-literal`].run { ctx => - import `2-simple-literal-lib`.public._ - import ctx._ - - val results = ctx.run(query[Person].filter(_.age > 11)).toSeq - results should contain theSameElementsAs - (List(Person(1, "Joe", "Bloggs", 22), Person(2, "Jack", "Ripper", 33))) - } - } - - "composable generator" - { - - "1-comp-sanity" in WithContext[Prefix, `1-comp-sanity`].run { ctx => - import `1-comp-sanity-lib`.public._ - import ctx._ - ctx.run(query[Person].filter(_.age > 11)) should contain theSameElementsAs List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - ) - } - - "2-comp-stereo-single" in WithContext[Prefix, `2-comp-stereo-single`].run { ctx => - import `2-comp-stereo-single-lib`.public._ - import ctx._ - (ctx.run(PersonDao.query.filter(_.age > 11))) should contain theSameElementsAs - (List( - Person(1, "Joe", "Bloggs", 22), - Person(2, "Jack", "Ripper", 33) - )) - } - } -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithContext.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithContext.scala deleted file mode 100644 index 42a082ac49..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithContext.scala +++ /dev/null @@ -1,42 +0,0 @@ -package io.getquill.codegen.util -import java.io.Closeable - -import io.getquill.codegen.integration.CodegenTestCases -import io.getquill.context.jdbc.JdbcContext -import javax.sql.DataSource - -trait WithContext[Prefix <: ConfigPrefix, CTest <: CodegenTestCases] extends SchemaMaker { - type QuillContext <: JdbcContext[_, _] - - def ctest: CTest - def dbPrefix: Prefix - - protected def makeContext(ds: DataSource with Closeable): QuillContext - def run(testCode: QuillContext => Any): Unit = { - withContext(ctest.schemaMakerCoordinates(dbPrefix))(testCode) - () - } -} - -abstract class WithContextBase[Prefix <: ConfigPrefix, CTest <: CodegenTestCases]( - val dbPrefix: Prefix, - val ctest: CTest -) extends WithContext[Prefix, CTest] - -// Cannot include WithOracleContext here since it is not being compiled in all builds -object WithContext - extends WithContextAux - with WithH2Context - with WithMysqlContext - with WithPostgresContext - with WithSqliteContext - with WithSqlServerContext - -trait WithContextAux { - type Aux[Prefix <: ConfigPrefix, CTest <: CodegenTestCases, Ret] = WithContext[Prefix, CTest] { - type QuillContext = Ret - } - def apply[Prefix <: ConfigPrefix, CTest <: CodegenTestCases](implicit - cft: WithContext[Prefix, CTest] - ): Aux[Prefix, CTest, cft.QuillContext] = cft -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithH2Context.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithH2Context.scala deleted file mode 100644 index 0ec8c0fa1f..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithH2Context.scala +++ /dev/null @@ -1,84 +0,0 @@ -package io.getquill.codegen.util - -import java.io.Closeable - -import io.getquill.{H2Dialect => TheDialect, H2JdbcContext => TheContext, Literal, SnakeCase} -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.{TestH2DB => TheDB} -import javax.sql.DataSource - -trait WithH2Context extends WithContextAux { - import io.getquill.codegen.generated.h2._ - - implicit def h2SimpleContextForTest1: Aux[TheDB, `1-simple-snake`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-simple-snake`](TheDB, `1-simple-snake`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def h2SimpleContextForTest2: Aux[TheDB, `2-simple-literal`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `2-simple-literal`](TheDB, `2-simple-literal`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def h2ContextForTest1: Aux[TheDB, `1-comp-sanity`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-comp-sanity`](TheDB, `1-comp-sanity`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def h2ContextForTest2: Aux[TheDB, `2-comp-stereo-single`, TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase]] = - new WithContextBase[TheDB, `2-comp-stereo-single`](TheDB, `2-comp-stereo-single`) { - override type QuillContext = TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[SnakeCase](SnakeCase, ds) - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - } - - implicit def h2ContextForTest3: Aux[TheDB, `3-comp-stereo-oneschema`, TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal]] = - new WithContextBase[TheDB, `3-comp-stereo-oneschema`](TheDB, `3-comp-stereo-oneschema`) { - override type QuillContext = TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[Literal](Literal, ds) - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - } - - implicit def h2ContextForTest4: Aux[ - TheDB, - `4-comp-stereo-twoschema`, - TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `4-comp-stereo-twoschema`](TheDB, `4-comp-stereo-twoschema`) { - override type QuillContext = TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - } - - implicit def h2ContextForTest5: Aux[ - TheDB, - `5-comp-non-stereo-allschema`, - TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `5-comp-non-stereo-allschema`](TheDB, `5-comp-non-stereo-allschema`) { - override type QuillContext = TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - } - -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithMysqlContext.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithMysqlContext.scala deleted file mode 100644 index 9a543154f6..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithMysqlContext.scala +++ /dev/null @@ -1,84 +0,0 @@ -package io.getquill.codegen.util - -import java.io.Closeable - -import io.getquill.{MySQLDialect => TheDialect, MysqlJdbcContext => TheContext, Literal, SnakeCase} -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.{TestMysqlDB => TheDB} -import javax.sql.DataSource - -trait WithMysqlContext extends WithContextAux { - import io.getquill.codegen.generated.mysql._ - - implicit def mysqlSimpleContextForTest1: Aux[TheDB, `1-simple-snake`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-simple-snake`](TheDB, `1-simple-snake`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def mysqlSimpleContextForTest2: Aux[TheDB, `2-simple-literal`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `2-simple-literal`](TheDB, `2-simple-literal`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def mysqlContextForTest1: Aux[TheDB, `1-comp-sanity`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-comp-sanity`](TheDB, `1-comp-sanity`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def mysqlContextForTest2: Aux[TheDB, `2-comp-stereo-single`, TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase]] = - new WithContextBase[TheDB, `2-comp-stereo-single`](TheDB, `2-comp-stereo-single`) { - override type QuillContext = TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[SnakeCase](SnakeCase, ds) - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - } - - implicit def mysqlContextForTest3: Aux[TheDB, `3-comp-stereo-oneschema`, TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal]] = - new WithContextBase[TheDB, `3-comp-stereo-oneschema`](TheDB, `3-comp-stereo-oneschema`) { - override type QuillContext = TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[Literal](Literal, ds) - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - } - - implicit def mysqlContextForTest4: Aux[ - TheDB, - `4-comp-stereo-twoschema`, - TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `4-comp-stereo-twoschema`](TheDB, `4-comp-stereo-twoschema`) { - override type QuillContext = TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - } - - implicit def mysqlContextForTest5: Aux[ - TheDB, - `5-comp-non-stereo-allschema`, - TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `5-comp-non-stereo-allschema`](TheDB, `5-comp-non-stereo-allschema`) { - override type QuillContext = TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - } - -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithOracleContext.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithOracleContext.scala deleted file mode 100644 index 50f5f21f6f..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithOracleContext.scala +++ /dev/null @@ -1,88 +0,0 @@ -package io.getquill.codegen.util - -import java.io.Closeable - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.{TestOracleDB => TheDB} -import io.getquill.{Literal, SnakeCase, OracleDialect => TheDialect, OracleJdbcContext => TheContext} -import javax.sql.DataSource - -// Need separate object for Oracle contexts since WithOracleContext itself is excluded in builds -// that are not compiling with Oracle -object WithOracleContextStandalone extends WithContextAux with WithOracleContext - -trait WithOracleContext extends WithContextAux { - import io.getquill.codegen.generated.oracle._ - - implicit def oracleSimpleContextForTest1: Aux[TheDB, `1-simple-snake`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-simple-snake`](TheDB, `1-simple-snake`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def oracleSimpleContextForTest2: Aux[TheDB, `2-simple-literal`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `2-simple-literal`](TheDB, `2-simple-literal`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def oracleContextForTest1: Aux[TheDB, `1-comp-sanity`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-comp-sanity`](TheDB, `1-comp-sanity`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def oracleContextForTest2: Aux[TheDB, `2-comp-stereo-single`, TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase]] = - new WithContextBase[TheDB, `2-comp-stereo-single`](TheDB, `2-comp-stereo-single`) { - override type QuillContext = TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[SnakeCase](SnakeCase, ds) - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - } - - implicit def oracleContextForTest3: Aux[TheDB, `3-comp-stereo-oneschema`, TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal]] = - new WithContextBase[TheDB, `3-comp-stereo-oneschema`](TheDB, `3-comp-stereo-oneschema`) { - override type QuillContext = TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[Literal](Literal, ds) - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - } - - implicit def oracleContextForTest4: Aux[ - TheDB, - `4-comp-stereo-twoschema`, - TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `4-comp-stereo-twoschema`](TheDB, `4-comp-stereo-twoschema`) { - override type QuillContext = TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - } - - implicit def oracleContextForTest5: Aux[ - TheDB, - `5-comp-non-stereo-allschema`, - TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `5-comp-non-stereo-allschema`](TheDB, `5-comp-non-stereo-allschema`) { - override type QuillContext = TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - } - -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithPostgresContext.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithPostgresContext.scala deleted file mode 100644 index f27b69ae2e..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithPostgresContext.scala +++ /dev/null @@ -1,84 +0,0 @@ -package io.getquill.codegen.util - -import java.io.Closeable - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.{TestPostgresDB => TheDB} -import io.getquill.{Literal, SnakeCase, PostgresDialect => TheDialect, PostgresJdbcContext => TheContext} -import javax.sql.DataSource - -trait WithPostgresContext extends WithContextAux { - import io.getquill.codegen.generated.postgres._ - - implicit def postgresSimpleContextForTest1: Aux[TheDB, `1-simple-snake`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-simple-snake`](TheDB, `1-simple-snake`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def postgresSimpleContextForTest2: Aux[TheDB, `2-simple-literal`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `2-simple-literal`](TheDB, `2-simple-literal`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def postgresContextForTest1: Aux[TheDB, `1-comp-sanity`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-comp-sanity`](TheDB, `1-comp-sanity`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def postgresContextForTest2: Aux[TheDB, `2-comp-stereo-single`, TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase]] = - new WithContextBase[TheDB, `2-comp-stereo-single`](TheDB, `2-comp-stereo-single`) { - override type QuillContext = TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[SnakeCase](SnakeCase, ds) - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - } - - implicit def postgresContextForTest3: Aux[TheDB, `3-comp-stereo-oneschema`, TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal]] = - new WithContextBase[TheDB, `3-comp-stereo-oneschema`](TheDB, `3-comp-stereo-oneschema`) { - override type QuillContext = TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[Literal](Literal, ds) - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - } - - implicit def postgresContextForTest4: Aux[ - TheDB, - `4-comp-stereo-twoschema`, - TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `4-comp-stereo-twoschema`](TheDB, `4-comp-stereo-twoschema`) { - override type QuillContext = TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - } - - implicit def postgresContextForTest5: Aux[ - TheDB, - `5-comp-non-stereo-allschema`, - TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `5-comp-non-stereo-allschema`](TheDB, `5-comp-non-stereo-allschema`) { - override type QuillContext = TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - } - -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithSqlServerContext.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithSqlServerContext.scala deleted file mode 100644 index 263a9c2f4a..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithSqlServerContext.scala +++ /dev/null @@ -1,84 +0,0 @@ -package io.getquill.codegen.util - -import java.io.Closeable - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.{TestSqlServerDB => TheDB} -import io.getquill.{Literal, SnakeCase, SQLServerDialect => TheDialect, SqlServerJdbcContext => TheContext} -import javax.sql.DataSource - -trait WithSqlServerContext extends WithContextAux { - import io.getquill.codegen.generated.sqlserver._ - - implicit def sqlServerSimpleContextForTest1: Aux[TheDB, `1-simple-snake`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-simple-snake`](TheDB, `1-simple-snake`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def sqlServerSimpleContextForTest2: Aux[TheDB, `2-simple-literal`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `2-simple-literal`](TheDB, `2-simple-literal`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def sqlServerContextForTest1: Aux[TheDB, `1-comp-sanity`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-comp-sanity`](TheDB, `1-comp-sanity`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def sqlServerContextForTest2: Aux[TheDB, `2-comp-stereo-single`, TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase]] = - new WithContextBase[TheDB, `2-comp-stereo-single`](TheDB, `2-comp-stereo-single`) { - override type QuillContext = TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[SnakeCase](SnakeCase, ds) - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - } - - implicit def sqlServerContextForTest3: Aux[TheDB, `3-comp-stereo-oneschema`, TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal]] = - new WithContextBase[TheDB, `3-comp-stereo-oneschema`](TheDB, `3-comp-stereo-oneschema`) { - override type QuillContext = TheContext[Literal] - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[Literal](Literal, ds) - with `3-comp-stereo-oneschema-lib`.public.PublicExtensions[TheDialect, Literal] - } - - implicit def sqlServerContextForTest4: Aux[ - TheDB, - `4-comp-stereo-twoschema`, - TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `4-comp-stereo-twoschema`](TheDB, `4-comp-stereo-twoschema`) { - override type QuillContext = TheContext[Literal] - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `4-comp-stereo-twoschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `4-comp-stereo-twoschema-lib`.common.CommonExtensions[TheDialect, Literal] - } - - implicit def sqlServerContextForTest5: Aux[ - TheDB, - `5-comp-non-stereo-allschema`, - TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - ] = new WithContextBase[TheDB, `5-comp-non-stereo-allschema`](TheDB, `5-comp-non-stereo-allschema`) { - override type QuillContext = TheContext[Literal] - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - override protected def makeContext(ds: DataSource with Closeable) = - new TheContext[Literal](Literal, ds) - with `5-comp-non-stereo-allschema-lib`.public.PublicExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.alpha.AlphaExtensions[TheDialect, Literal] - with `5-comp-non-stereo-allschema-lib`.bravo.BravoExtensions[TheDialect, Literal] - } - -} diff --git a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithSqliteContext.scala b/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithSqliteContext.scala deleted file mode 100644 index 5c0198082c..0000000000 --- a/quill-codegen-tests/src/test/scala/io/getquill/codegen/util/WithSqliteContext.scala +++ /dev/null @@ -1,39 +0,0 @@ -package io.getquill.codegen.util - -import java.io.Closeable - -import io.getquill.codegen.integration.CodegenTestCases._ -import io.getquill.codegen.util.ConfigPrefix.{TestSqliteDB => TheDB} -import io.getquill.{SnakeCase, SqliteDialect => TheDialect, SqliteJdbcContext => TheContext} -import javax.sql.DataSource - -trait WithSqliteContext extends WithContextAux { - import io.getquill.codegen.generated.sqlite._ - - implicit def sqliteSimpleContextForTest1: Aux[TheDB, `1-simple-snake`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-simple-snake`](TheDB, `1-simple-snake`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def sqliteSimpleContextForTest2: Aux[TheDB, `2-simple-literal`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `2-simple-literal`](TheDB, `2-simple-literal`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def sqliteContextForTest1: Aux[TheDB, `1-comp-sanity`, TheContext[SnakeCase]] = - new WithContextBase[TheDB, `1-comp-sanity`](TheDB, `1-comp-sanity`) { - override type QuillContext = TheContext[SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new QuillContext(SnakeCase, ds) - } - - implicit def sqliteContextForTest2: Aux[TheDB, `2-comp-stereo-single`, TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase]] = - new WithContextBase[TheDB, `2-comp-stereo-single`](TheDB, `2-comp-stereo-single`) { - override type QuillContext = TheContext[SnakeCase] - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - override protected def makeContext(ds: DataSource with Closeable) = new TheContext[SnakeCase](SnakeCase, ds) - with `2-comp-stereo-single-lib`.public.PublicExtensions[TheDialect, SnakeCase] - } -} diff --git a/quill-core/src/main/scala/io/getquill/context/ContextMacro.scala b/quill-core/src/main/scala/io/getquill/context/ContextMacro.scala index a1163a5b00..0e24fe86e7 100644 --- a/quill-core/src/main/scala/io/getquill/context/ContextMacro.scala +++ b/quill-core/src/main/scala/io/getquill/context/ContextMacro.scala @@ -8,6 +8,8 @@ import io.getquill.util.MacroContextExt._ import io.getquill.{IdiomContext, NamingStrategy} import io.getquill.idiom._ import io.getquill.quat.Quat +import io.getquill.util.ExceptionOps.ThrowableOpsMethods + import scala.util.Failure import scala.util.Success @@ -89,9 +91,15 @@ trait ContextMacro extends Quotation { ) } catch { case e: Exception => - c.fail(s"Query compilation failed. ${e.getMessage}") + c.fail( + s"""Query compilation failed due to: ${e.getMessage} + |================= Error Stack: ================= + |${e.stackTraceToString} + |""".stripMargin + ) } } + } private def translateStatic(ast: Ast, topLevelQuat: Quat, batchAlias: Option[String]): Tree = { diff --git a/quill-core/src/main/scala/io/getquill/util/ExceptionOps.scala b/quill-core/src/main/scala/io/getquill/util/ExceptionOps.scala new file mode 100644 index 0000000000..867985a00e --- /dev/null +++ b/quill-core/src/main/scala/io/getquill/util/ExceptionOps.scala @@ -0,0 +1,15 @@ +package io.getquill.util + +import java.io.ByteArrayOutputStream + +object ExceptionOps { + implicit final class ThrowableOpsMethods(private val t: Throwable) extends AnyVal { + def stackTraceToString: String = { + val stream = new ByteArrayOutputStream() + val writer = new java.io.BufferedWriter(new java.io.OutputStreamWriter(stream)) + t.printStackTrace(new java.io.PrintWriter(writer)) + writer.flush() + stream.toString + } + } +} diff --git a/quill-engine/src/main/scala/io/getquill/sql/SqlQuery.scala b/quill-engine/src/main/scala/io/getquill/sql/SqlQuery.scala index 61cfc9b85c..0aa9187b76 100644 --- a/quill-engine/src/main/scala/io/getquill/sql/SqlQuery.scala +++ b/quill-engine/src/main/scala/io/getquill/sql/SqlQuery.scala @@ -67,6 +67,14 @@ final case class UnaryOperationSqlQuery( override def quat: Quat = quatType } +// A top-level infix query. This needs special rendering because we don't +// want to tokenize column names, e.g. sql"select foo, bar from baz".as[Person] +// should become just "select foo, bar from baz", not the fully expanded form +// "select p.name, p.age from (select foo, bar from baz) as Person p" +final case class TopInfixQuery(ast: Infix) extends SqlQuery { + override def quat: Quat = ast.quat +} + final case class SelectValue(ast: Ast, alias: Option[String] = None, concat: Boolean = false) extends PseudoAst { override def toString: String = s"${ast.toString}${alias.map("->" + _).getOrElse("")}" } @@ -104,45 +112,59 @@ object CaseClassMake { } } -class SqlQueryApply(traceConfig: TraceConfig) { +class SqlQueryApply(traceConfig: TraceConfig, allowTopLevelInfix: Boolean = true) { val interp: Interpolator = new Interpolator(TraceType.SqlQueryConstruct, traceConfig, 1) import interp._ - def apply(query: Ast): SqlQuery = + def apply(query: Ast) = build(query, true) + + private def build(query: Ast, isTopLevel: Boolean = false): SqlQuery = query match { case Union(a, b) => trace"Construct SqlQuery from: Union" andReturn { - SetOperationSqlQuery(apply(a), UnionOperation, apply(b))(query.quat) + SetOperationSqlQuery(build(a), UnionOperation, build(b))(query.quat) } case UnionAll(a, b) => trace"Construct SqlQuery from: UnionAll" andReturn { - SetOperationSqlQuery(apply(a), UnionAllOperation, apply(b))(query.quat) + SetOperationSqlQuery(build(a), UnionAllOperation, build(b))(query.quat) } case UnaryOperation(op, q: Query) => trace"Construct SqlQuery from: UnaryOperation" andReturn { - UnaryOperationSqlQuery(op, apply(q))(query.quat) + UnaryOperationSqlQuery(op, build(q))(query.quat) } case _: Operation | _: Value => trace"Construct SqlQuery from: Operation/Value" andReturn { FlattenSqlQuery(select = List(SelectValue(query)))(query.quat) } + // i.e. a transparent map that looks like `map(x => x)` + // in this case, don't even consider it a nesting (i.e. if it was top-level, it's still top-level) case Map(q, a, b) if a == b => trace"Construct SqlQuery from: Map" andReturn { - apply(q) + build(q, isTopLevel) } case TakeDropFlatten(q, limit, offset) => trace"Construct SqlQuery from: TakeDropFlatten" andReturn { flatten(q, "x").copy(limit = limit, offset = offset)(q.quat) } + // In the case of sql"select foo, bar from baz".as[Query[...]].nested + // make it only double nested (i.e. FlattenSqlQuery(from: InfixContext)) + // instead of triple: (i.e. FlattenSqlQuery(from: FlattenSqlQuery(from: InfixContext))) + case Nested(infix: Infix) => + trace"Construct SqlQuery from: Nested(Infix)" andReturn { + flatten(infix, "x") + } + case infix: Infix => + if (allowTopLevelInfix && isTopLevel) + TopInfixQuery(infix) + else + trace"Construct SqlQuery from: Infix" andReturn { + flatten(infix, "x") + } case q: Query => trace"Construct SqlQuery from: Query" andReturn { flatten(q, "x") } - case infix: Infix => - trace"Construct SqlQuery from: Infix" andReturn { - flatten(infix, "x") - } case other => trace"Construct SqlQuery from: other" andReturn { fail(s"Query not properly normalized. Please open a bug report. Ast: '$other'") @@ -213,8 +235,8 @@ class SqlQueryApply(traceConfig: TraceConfig) { // case Map(_, _, _) => // trace"base| Nesting Map(a=>ContainsImpurities(a)) $q" andReturn nest(source(q, alias)) - case Nested(q) => trace"base| Nesting Nested $q" andReturn nest(QueryContext(apply(q), alias)) - case q: ConcatMap => trace"base| Nesting ConcatMap $q" andReturn nest(QueryContext(apply(q), alias)) + case Nested(q) => trace"base| Nesting Nested $q" andReturn nest(QueryContext(build(q), alias)) + case q: ConcatMap => trace"base| Nesting ConcatMap $q" andReturn nest(QueryContext(build(q), alias)) case Join(tpe, a, b, iA, iB, on) => trace"base| Collecting join aliases $q" andReturn { val ctx = source(q, alias) @@ -355,7 +377,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { else trace"Flattening| Map(Ident) [Complex]" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, select = selectValues(p) )(quat) @@ -372,7 +394,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { else trace"Flattening| Filter(Ident) [Complex]" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, where = Some(p), select = select(alias, quat) )(quat) @@ -390,7 +412,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { else trace"Flattening| SortBy(Ident) [Complex]" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, orderBy = criteria, select = select(alias, quat) )(quat) @@ -408,7 +430,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { case other => trace"Flattening| Aggregation(Query) [Complex]" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, select = List( SelectValue(Aggregation(op, Ident("*", quat))) ) // Quat of a * aggregation is same as for the entire query @@ -430,7 +452,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { else trace"Flattening| Take [Complex]" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, limit = Some(n), select = select(alias, quat) )(quat) @@ -443,7 +465,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { else trace"Flattening| Drop [Complex]" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, offset = Some(n), select = select(alias, quat) )(quat) @@ -477,7 +499,7 @@ class SqlQueryApply(traceConfig: TraceConfig) { case _ => trace"Flattening| DistinctOn" andReturn FlattenSqlQuery( - from = QueryContext(apply(q), alias) :: Nil, + from = QueryContext(build(q), alias) :: Nil, select = select(alias, quat), distinct = DistinctKind.DistinctOn(distinctList) )(quat) @@ -502,8 +524,8 @@ class SqlQueryApply(traceConfig: TraceConfig) { case infix: Infix => InfixContext(infix, alias) case Join(t, a, b, ia, ib, on) => JoinContext(t, source(a, ia.name), source(b, ib.name), on) case FlatJoin(t, a, ia, on) => FlatJoinContext(t, source(a, ia.name), on) - case Nested(q) => QueryContext(apply(q), alias) - case other => QueryContext(apply(other), alias) + case Nested(q) => QueryContext(build(q), alias) + case other => QueryContext(build(other), alias) } private def orderByCriteria(ast: Ast, ordering: Ast, from: List[FromContext]): List[OrderByCriteria] = diff --git a/quill-engine/src/main/scala/io/getquill/sql/idiom/SqlIdiom.scala b/quill-engine/src/main/scala/io/getquill/sql/idiom/SqlIdiom.scala index 9f6d4af794..136524f971 100644 --- a/quill-engine/src/main/scala/io/getquill/sql/idiom/SqlIdiom.scala +++ b/quill-engine/src/main/scala/io/getquill/sql/idiom/SqlIdiom.scala @@ -249,6 +249,8 @@ trait SqlIdiom extends Idiom { strategy: NamingStrategy, idiomContext: IdiomContext ): Tokenizer[SqlQuery] = Tokenizer[SqlQuery] { + case q: TopInfixQuery => + q.ast.token case q: FlattenSqlQuery => new FlattenSqlQueryTokenizerHelper(q).apply case SetOperationSqlQuery(a, op, b) => diff --git a/quill-engine/src/main/scala/io/getquill/sql/idiom/VerifySqlQuery.scala b/quill-engine/src/main/scala/io/getquill/sql/idiom/VerifySqlQuery.scala index 3c33064475..79636ac957 100644 --- a/quill-engine/src/main/scala/io/getquill/sql/idiom/VerifySqlQuery.scala +++ b/quill-engine/src/main/scala/io/getquill/sql/idiom/VerifySqlQuery.scala @@ -29,6 +29,8 @@ object VerifySqlQuery { private def verify(query: SqlQuery): Option[InvalidSqlQuery] = query match { + // if it's just an infix query no more verification to do + case p: TopInfixQuery => None case q: FlattenSqlQuery => verify(q) case SetOperationSqlQuery(a, op, b) => verify(a).orElse(verify(b)) case UnaryOperationSqlQuery(op, q) => verify(q) diff --git a/quill-engine/src/main/scala/io/getquill/sql/norm/AddDropToNestedOrderBy.scala b/quill-engine/src/main/scala/io/getquill/sql/norm/AddDropToNestedOrderBy.scala index de14e9932d..ce721b00be 100644 --- a/quill-engine/src/main/scala/io/getquill/sql/norm/AddDropToNestedOrderBy.scala +++ b/quill-engine/src/main/scala/io/getquill/sql/norm/AddDropToNestedOrderBy.scala @@ -21,6 +21,7 @@ object AddDropToNestedOrderBy { case SetOperationSqlQuery(a, op, b) => SetOperationSqlQuery(applyInner(a), op, applyInner(b))(q.quat) case UnaryOperationSqlQuery(op, a) => UnaryOperationSqlQuery(op, applyInner(a))(q.quat) + case q: TopInfixQuery => q } private def applyInner(f: FromContext): FromContext = @@ -36,5 +37,6 @@ object AddDropToNestedOrderBy { case q: FlattenSqlQuery => q.copy(from = q.from.map(applyInner(_)))(q.quat) case SetOperationSqlQuery(a, op, b) => SetOperationSqlQuery(applyInner(a), op, applyInner(b))(q.quat) case UnaryOperationSqlQuery(op, a) => UnaryOperationSqlQuery(op, applyInner(a))(q.quat) + case q: TopInfixQuery => q } } diff --git a/quill-engine/src/main/scala/io/getquill/sql/norm/RemoveUnusedSelects.scala b/quill-engine/src/main/scala/io/getquill/sql/norm/RemoveUnusedSelects.scala index dcdb7adc25..ccf1c9acad 100644 --- a/quill-engine/src/main/scala/io/getquill/sql/norm/RemoveUnusedSelects.scala +++ b/quill-engine/src/main/scala/io/getquill/sql/norm/RemoveUnusedSelects.scala @@ -1,7 +1,7 @@ package io.getquill.sql.norm import io.getquill.ast.{Ast, CollectAst, Ident, Property, StatefulTransformer} -import io.getquill.context.sql.{DistinctKind, FlatJoinContext, FlattenSqlQuery, FromContext, InfixContext, JoinContext, QueryContext, SelectValue, SetOperationSqlQuery, SqlQuery, TableContext, UnaryOperationSqlQuery} +import io.getquill.context.sql.{DistinctKind, FlatJoinContext, FlattenSqlQuery, FromContext, InfixContext, JoinContext, TopInfixQuery, QueryContext, SelectValue, SetOperationSqlQuery, SqlQuery, TableContext, UnaryOperationSqlQuery} import io.getquill.norm.PropertyMatryoshka import io.getquill.quat.Quat @@ -61,6 +61,7 @@ object RemoveUnusedSelects { SetOperationSqlQuery(apply(a, references), op, apply(b, references))(q.quat) case UnaryOperationSqlQuery(op, q) => UnaryOperationSqlQuery(op, apply(q, references))(q.quat) + case p: TopInfixQuery => p } private def filterUnused(select: List[SelectValue], references: Set[Property]): List[SelectValue] = { diff --git a/quill-engine/src/main/scala/io/getquill/sql/norm/StatelessQueryTransformer.scala b/quill-engine/src/main/scala/io/getquill/sql/norm/StatelessQueryTransformer.scala index 205207c26a..4527d444b5 100644 --- a/quill-engine/src/main/scala/io/getquill/sql/norm/StatelessQueryTransformer.scala +++ b/quill-engine/src/main/scala/io/getquill/sql/norm/StatelessQueryTransformer.scala @@ -1,6 +1,6 @@ package io.getquill.sql.norm -import io.getquill.context.sql.{FlatJoinContext, FlattenSqlQuery, FromContext, InfixContext, JoinContext, QueryContext, SetOperationSqlQuery, SqlQuery, TableContext, UnaryOperationSqlQuery} +import io.getquill.context.sql.{FlatJoinContext, FlattenSqlQuery, FromContext, InfixContext, JoinContext, TopInfixQuery, QueryContext, SetOperationSqlQuery, SqlQuery, TableContext, UnaryOperationSqlQuery} import io.getquill.quat.Quat sealed trait QueryLevel { @@ -34,6 +34,7 @@ trait StatelessQueryTransformer { protected def apply(q: SqlQuery, level: QueryLevel): SqlQuery = q match { + case p: TopInfixQuery => p case q: FlattenSqlQuery => expandNested(q, level) case SetOperationSqlQuery(a, op, b) => diff --git a/quill-orientdb/src/main/scala/io/getquill/context/orientdb/OrientDBIdiom.scala b/quill-orientdb/src/main/scala/io/getquill/context/orientdb/OrientDBIdiom.scala index 8ae11c5934..205a821a94 100644 --- a/quill-orientdb/src/main/scala/io/getquill/context/orientdb/OrientDBIdiom.scala +++ b/quill-orientdb/src/main/scala/io/getquill/context/orientdb/OrientDBIdiom.scala @@ -5,7 +5,7 @@ import io.getquill.idiom.StatementInterpolator._ import io.getquill.context.sql.norm._ import io.getquill.ast.{AggregationOperator, External, _} import io.getquill.context.sql._ -import io.getquill.{IdiomContext, NamingStrategy} +import io.getquill.{AstPrinter, IdiomContext, NamingStrategy} import io.getquill.context.{CannotReturn, ExecutionType} import io.getquill.util.Messages.{fail, trace} import io.getquill.idiom._ @@ -129,6 +129,9 @@ trait OrientDBIdiom extends Idiom { strategy: NamingStrategy, idiomContext: IdiomContext ): Tokenizer[SqlQuery] = Tokenizer[SqlQuery] { + case q: TopInfixQuery => + q.ast.token + case FlattenSqlQuery(from, where, groupBy, orderBy, limit, offset, select, distinct) => val distinctTokenizer = (if (distinct == DistinctKind.Distinct) "DISTINCT" else "").token @@ -183,8 +186,8 @@ trait OrientDBIdiom extends Idiom { case SetOperationSqlQuery(a, op, b) => val str = f"SELECT $$c LET $$a = (${a.token}), $$b = (${b.token}), $$c = UNIONALL($$a, $$b)" str.token - case _ => - fail("Other operators are not supported yet. Please raise a ticket to support more operations") + case other => + fail("This operator is not supported (below). Please raise a ticket to support more operations\n" + new AstPrinter()(other)) } implicit def operationTokenizer(implicit diff --git a/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBIdiomSpec.scala b/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBIdiomSpec.scala index 6ba79c1b82..855b2f9f35 100644 --- a/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBIdiomSpec.scala +++ b/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBIdiomSpec.scala @@ -330,7 +330,7 @@ class OrientDBIdiomSpec extends Spec { sql"SELECT MODE(i) FROM TestEntity".as[Query[Int]] } ctx.run(q).string mustEqual - "SELECT * FROM (SELECT MODE(i) FROM TestEntity)" + "SELECT MODE(i) FROM TestEntity" } } "action" - { diff --git a/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBQuerySpec.scala b/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBQuerySpec.scala index 731e5b56b3..531e22a6b5 100644 --- a/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBQuerySpec.scala +++ b/quill-orientdb/src/test/scala/io/getquill/context/orientdb/OrientDBQuerySpec.scala @@ -229,7 +229,7 @@ class OrientDBQuerySpec extends Spec { intercept[IllegalStateException]( t.token(UnaryOperationSqlQuery(BooleanOperator.`!`, e)(Quat.Value)) - ).getMessage mustBe "Other operators are not supported yet. Please raise a ticket to support more operations" + ).getMessage must include("This operator is not supported") } "operation" in { val t = implicitly[Tokenizer[Operation]] diff --git a/quill-spark/src/main/scala/io/getquill/context/spark/SparkDialect.scala b/quill-spark/src/main/scala/io/getquill/context/spark/SparkDialect.scala index af47573162..81664c879c 100644 --- a/quill-spark/src/main/scala/io/getquill/context/spark/SparkDialect.scala +++ b/quill-spark/src/main/scala/io/getquill/context/spark/SparkDialect.scala @@ -3,7 +3,7 @@ package io.getquill.context.spark import io.getquill.{IdiomContext, NamingStrategy} import io.getquill.ast.{Ast, BinaryOperation, CaseClass, Constant, ExternalIdent, Ident, Operation, Property, Query, StringOperator, Tuple, Value} import io.getquill.context.spark.norm.EscapeQuestionMarks -import io.getquill.context.sql.{FlattenSqlQuery, SelectValue, SetOperationSqlQuery, SqlQuery, SqlQueryApply, UnaryOperationSqlQuery} +import io.getquill.context.sql.{FlattenSqlQuery, SelectValue, SetOperationSqlQuery, SqlQuery, SqlQueryApply, TopInfixQuery, UnaryOperationSqlQuery} import io.getquill.context.sql.idiom.SqlIdiom import io.getquill.context.sql.norm.SqlNormalize import io.getquill.idiom.StatementInterpolator._ @@ -21,6 +21,10 @@ trait SparkIdiom extends SqlIdiom with CannotReturn { self => def liftingPlaceholder(index: Int): String = "?" + // Do not allow top-level infix queries in spark by default because then run(liftQuery(myDataset)) will fail + // power-users may want to override this in rare cases. + def allowTopLevelInfix = false + override def prepareForProbing(string: String) = string override implicit def externalIdentTokenizer(implicit @@ -39,7 +43,7 @@ trait SparkIdiom extends SqlIdiom with CannotReturn { self => val token = normalizedAst match { case q: Query => - val sql = new SqlQueryApply(idiomContext.config.traceConfig)(q) + val sql = new SqlQueryApply(idiomContext.config.traceConfig, allowTopLevelInfix)(q) trace("sql")(sql) val expanded = SimpleNestedExpansion(sql) trace("expanded sql")(expanded) @@ -129,6 +133,11 @@ trait SparkIdiom extends SqlIdiom with CannotReturn { self => stmt"(${a.token}) ${op.token} (${b.token})" case UnaryOperationSqlQuery(op, q) => stmt"SELECT ${op.token} (${q.token})" + // Technically top-level infix queries are not allowed in Spark because + // run(liftQuery(myDataset)) then won't work but in case the user + // wants to override it, provide the translation. + case q: TopInfixQuery => + q.ast.token } override implicit def propertyTokenizer(implicit diff --git a/quill-spark/src/test/scala/io/getquill/context/spark/QuillSparkContextSpec.scala b/quill-spark/src/test/scala/io/getquill/context/spark/QuillSparkContextSpec.scala index 7c372cfd31..fb7fcd624d 100644 --- a/quill-spark/src/test/scala/io/getquill/context/spark/QuillSparkContextSpec.scala +++ b/quill-spark/src/test/scala/io/getquill/context/spark/QuillSparkContextSpec.scala @@ -1,6 +1,8 @@ package io.getquill.context.spark import io.getquill.base.Spec +import io.getquill.{Test => _, _} + import scala.util.Success class QuillSparkContextSpec extends Spec { diff --git a/quill-sql-test/src/test/scala/io/getquill/context/sql/SqlQuerySpec.scala b/quill-sql-test/src/test/scala/io/getquill/context/sql/SqlQuerySpec.scala index dc9d4fc7e8..735b480eca 100644 --- a/quill-sql-test/src/test/scala/io/getquill/context/sql/SqlQuerySpec.scala +++ b/quill-sql-test/src/test/scala/io/getquill/context/sql/SqlQuerySpec.scala @@ -345,17 +345,38 @@ class SqlQuerySpec extends Spec { "raw queries with sql" - { "using tuples" in { val q = quote { - sql"""SELECT t.s AS "_1", t.i AS "_2" FROM TestEntity t""".as[Query[(String, Int)]] + sql"""SELECT foo, bar FROM baz""".as[Query[(String, Int)]] } testContext.run(q).string mustEqual - """SELECT x._1, x._2 FROM (SELECT t.s AS "_1", t.i AS "_2" FROM TestEntity t) AS x""" + """SELECT foo, bar FROM baz""" + } + "using tuples - pure" in { + val q = quote { + sql"""SELECT foo, bar FROM baz""".pure.as[Query[(String, Int)]] + } + testContext.run(q).string mustEqual + """SELECT foo, bar FROM baz""" + } + "using tuples - nested" in { + val q = quote { + sql"""SELECT foo, bar FROM baz""".as[Query[(String, Int)]].nested + } + testContext.run(q).string mustEqual + """SELECT x._1, x._2 FROM (SELECT foo, bar FROM baz) AS x""" } "using single value" in { val q = quote { - sql"""SELECT t.i FROM TestEntity t""".as[Query[Int]] + sql"""SELECT foo, bar FROM baz""".as[Query[Int]] + } + testContext.run(q).string mustEqual + """SELECT foo, bar FROM baz""" + } + "using single value - nested" in { + val q = quote { + sql"""SELECT foo, bar FROM baz""".as[Query[Int]].nested } testContext.run(q).string mustEqual - """SELECT x.* FROM (SELECT t.i FROM TestEntity t) AS x""" + """SELECT x.* FROM (SELECT foo, bar FROM baz) AS x""" } } diff --git a/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/OracleDialectSpec.scala b/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/OracleDialectSpec.scala index 9549f3a779..421e8ccb8a 100644 --- a/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/OracleDialectSpec.scala +++ b/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/OracleDialectSpec.scala @@ -189,7 +189,7 @@ class OracleDialectSpec extends Spec { case class Person(name: String, age: Int) "No 'AS' aliases" in { ctx.run(sql"SELECT name, age FROM Person p".as[Query[Person]]).string mustEqual - "SELECT x.name, x.age FROM (SELECT name, age FROM Person p) x" + "SELECT name, age FROM Person p" } case class Document(filename: String) diff --git a/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/SqlIdiomSpec.scala b/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/SqlIdiomSpec.scala index 4cce884d8c..26f1237054 100644 --- a/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/SqlIdiomSpec.scala +++ b/quill-sql-test/src/test/scala/io/getquill/context/sql/idiom/SqlIdiomSpec.scala @@ -949,7 +949,7 @@ class SqlIdiomSpec extends Spec { } "full infix query" in { testContext.run(sql"SELECT * FROM TestEntity".as[Query[TestEntity]]).string mustEqual - "SELECT x.s, x.i, x.l, x.o, x.b FROM (SELECT * FROM TestEntity) AS x" + "SELECT * FROM TestEntity" } "full infix action" in { testContext.run(sql"DELETE FROM TestEntity".as[Action[TestEntity]]).string mustEqual diff --git a/quill-sql-test/src/test/scala/io/getquill/context/sql/norm/ExpandNestedQueriesSpec.scala b/quill-sql-test/src/test/scala/io/getquill/context/sql/norm/ExpandNestedQueriesSpec.scala index a5aa55e99b..184de81a45 100644 --- a/quill-sql-test/src/test/scala/io/getquill/context/sql/norm/ExpandNestedQueriesSpec.scala +++ b/quill-sql-test/src/test/scala/io/getquill/context/sql/norm/ExpandNestedQueriesSpec.scala @@ -701,17 +701,26 @@ class ExpandNestedQueriesSpec extends Spec { sql"fromSomewhere()".as[Query[Person]] } testContext.run(q).string mustEqual - "SELECT x.first_name AS firstName, x.last_name AS lastName FROM (fromSomewhere()) AS x" + "fromSomewhere()" } "should be handled correctly in a regular schema - nested" in { + case class Person(firstName: String, lastName: String) + val q = quote { + sql"fromSomewhere()".as[Query[Person]].nested + } + testContext.run(q).string mustEqual + "SELECT x.first_name AS firstName, x.last_name AS lastName FROM (fromSomewhere()) AS x" + } + + "should be handled correctly in a regular schema - multi-level" in { case class Name(firstName: String, lastName: String) case class Person(name: Name, theAge: Int) val q = quote { sql"fromSomewhere()".as[Query[Person]] } testContext.run(q).string mustEqual - "SELECT x.first_name AS firstName, x.last_name AS lastName, x.the_age AS theAge FROM (fromSomewhere()) AS x" + "fromSomewhere()" } } diff --git a/scripts/start_containers.sh b/scripts/start_containers.sh new file mode 100755 index 0000000000..240f75b7d7 --- /dev/null +++ b/scripts/start_containers.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# From 'All In One' of Quill CONTRIBUTING.md +docker compose down && docker compose build && docker compose run --rm --service-ports setup + +# echo "Adding 50ms latency to protoquill_postgres_1" +# docker exec protoquill_postgres_1 tc qdisc add dev eth0 root netem delay 50ms + +# echo "Adding 50ms latency to protoquill_mysql_1" +# docker exec protoquill_mysql_1 tc qdisc add dev eth0 root netem delay 50ms