From 58d29fd16a710f7be365c305cf0e1668d8f272d1 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 10 Dec 2023 09:07:53 -0800 Subject: [PATCH] Db -> Expr --- build.sc | 8 +- docs/design.md | 4 +- docs/generateDocs.sc | 8 +- docs/reference.md | 446 +++++++++--------- docs/tutorial.md | 72 +-- scalasql/core/src/Aggregatable.scala | 4 +- scalasql/core/src/ColumnNamer.scala | 38 -- scalasql/core/src/Config.scala | 16 +- scalasql/core/src/Context.scala | 14 +- scalasql/core/src/DbApi.scala | 2 +- scalasql/core/src/{Db.scala => Expr.scala} | 36 +- scalasql/core/src/JoinNullable.scala | 14 +- scalasql/core/src/LiveSqlExprs.scala | 12 +- scalasql/core/src/Queryable.scala | 6 +- scalasql/core/src/SqlExprsToSql.scala | 20 +- scalasql/core/src/SqlStr.scala | 12 +- scalasql/operations/src/AggNumericOps.scala | 14 +- scalasql/operations/src/AggOps.scala | 58 +-- .../operations/src/BitwiseFunctionOps.scala | 12 +- scalasql/operations/src/CaseWhen.scala | 10 +- scalasql/operations/src/ConcatOps.scala | 6 +- scalasql/operations/src/DbApiOps.scala | 28 +- scalasql/operations/src/DbBooleanOps.scala | 16 - scalasql/operations/src/DbNumericOps.scala | 66 --- scalasql/operations/src/DbOptionOps.scala | 40 -- .../src/{DbAggOps.scala => ExprAggOps.scala} | 8 +- scalasql/operations/src/ExprBooleanOps.scala | 16 + scalasql/operations/src/ExprNumericOps.scala | 66 +++ .../src/{DbOps.scala => ExprOps.scala} | 20 +- scalasql/operations/src/ExprOptionOps.scala | 40 ++ ...gLikeOps.scala => ExprStringLikeOps.scala} | 26 +- ...{DbStringOps.scala => ExprStringOps.scala} | 14 +- .../{DbTypedOps.scala => ExprTypedOps.scala} | 8 +- .../operations/src/HyperbolicMathOps.scala | 8 +- scalasql/operations/src/MathOps.scala | 34 +- scalasql/operations/src/PadOps.scala | 8 +- scalasql/operations/src/TrimOps.scala | 8 +- scalasql/query/src-2/TableMacro.scala | 13 +- scalasql/query/src/Aggregate.scala | 2 +- scalasql/query/src/Column.scala | 10 +- scalasql/query/src/CompoundSelect.scala | 8 +- scalasql/query/src/Delete.scala | 6 +- scalasql/query/src/FlatJoin.scala | 26 +- scalasql/query/src/From.scala | 2 +- scalasql/query/src/Insert.scala | 14 +- scalasql/query/src/InsertColumns.scala | 8 +- scalasql/query/src/InsertSelect.scala | 8 +- scalasql/query/src/JoinOps.scala | 10 +- scalasql/query/src/Joinable.scala | 6 +- scalasql/query/src/JoinsToSql.scala | 2 +- scalasql/query/src/LateralJoinOps.scala | 10 +- scalasql/query/src/Model.scala | 8 +- scalasql/query/src/Query.scala | 4 +- scalasql/query/src/Select.scala | 50 +- scalasql/query/src/SelectBase.scala | 4 +- scalasql/query/src/SelectProxy.scala | 6 +- scalasql/query/src/SimpleSelect.scala | 41 +- scalasql/query/src/SqlWindow.scala | 16 +- scalasql/query/src/Table.scala | 12 +- scalasql/query/src/Update.scala | 18 +- scalasql/query/src/Values.scala | 6 +- scalasql/query/src/WithCte.scala | 11 +- scalasql/src/dialects/Dialect.scala | 68 +-- scalasql/src/dialects/H2Dialect.scala | 48 +- scalasql/src/dialects/MySqlDialect.scala | 68 +-- scalasql/src/dialects/OnConflictOps.scala | 6 +- scalasql/src/dialects/PostgresDialect.scala | 38 +- scalasql/src/dialects/SqliteDialect.scala | 60 +-- scalasql/src/dialects/TableOps.scala | 12 +- scalasql/src/package.scala | 4 +- scalasql/test/src/ConcreteTestSuites.scala | 96 ++-- scalasql/test/src/FailureTests.scala | 18 +- scalasql/test/src/WorldSqlTests.scala | 72 +-- .../test/src/datatypes/OptionalTests.scala | 30 +- .../test/src/dialects/H2DialectTests.scala | 10 +- .../test/src/dialects/MySqlDialectTests.scala | 8 +- .../src/dialects/PostgresDialectTests.scala | 12 +- .../src/dialects/SqliteDialectTests.scala | 8 +- .../test/src/example/CheatSheetExample.scala | 4 +- .../src/operations/DbAggNumericOpsTests.scala | 4 +- .../test/src/operations/DbAggOpsTests.scala | 4 +- .../test/src/operations/DbApiOpsTests.scala | 4 +- .../test/src/operations/DbBlobOpsTests.scala | 36 +- .../src/operations/DbBooleanOpsTests.scala | 14 +- .../test/src/operations/DbMathOpsTests.scala | 2 +- .../src/operations/DbNumericOpsTests.scala | 40 +- scalasql/test/src/operations/DbOpsTests.scala | 48 +- .../src/operations/DbStringOpsTests.scala | 36 +- scalasql/test/src/query/JoinTests.scala | 6 +- .../test/src/query/LateralJoinTests.scala | 6 +- scalasql/test/src/query/OnConflictTests.scala | 2 +- scalasql/test/src/query/SelectTests.scala | 10 +- scalasql/test/src/query/SubQueryTests.scala | 4 +- .../test/src/query/UpdateSubQueryTests.scala | 2 +- scalasql/test/src/query/UpdateTests.scala | 2 +- scalasql/test/src/utils/TestChecker.scala | 6 +- 96 files changed, 1145 insertions(+), 1162 deletions(-) delete mode 100644 scalasql/core/src/ColumnNamer.scala rename scalasql/core/src/{Db.scala => Expr.scala} (62%) delete mode 100644 scalasql/operations/src/DbBooleanOps.scala delete mode 100644 scalasql/operations/src/DbNumericOps.scala delete mode 100644 scalasql/operations/src/DbOptionOps.scala rename scalasql/operations/src/{DbAggOps.scala => ExprAggOps.scala} (51%) create mode 100644 scalasql/operations/src/ExprBooleanOps.scala create mode 100644 scalasql/operations/src/ExprNumericOps.scala rename scalasql/operations/src/{DbOps.scala => ExprOps.scala} (53%) create mode 100644 scalasql/operations/src/ExprOptionOps.scala rename scalasql/operations/src/{DbStringLikeOps.scala => ExprStringLikeOps.scala} (51%) rename scalasql/operations/src/{DbStringOps.scala => ExprStringOps.scala} (59%) rename scalasql/operations/src/{DbTypedOps.scala => ExprTypedOps.scala} (79%) diff --git a/build.sc b/build.sc index 8eabca82..3c234509 100644 --- a/build.sc +++ b/build.sc @@ -95,7 +95,7 @@ trait ScalaSql extends Common{ os.write( T.dest / "Generated.scala", s"""package scalasql.core.generated - |import scalasql.core.{Queryable, Db} + |import scalasql.core.{Queryable, Expr} |trait QueryableRow{ | ${queryableRowDefs.mkString("\n")} |} @@ -133,7 +133,7 @@ trait ScalaSql extends Common{ | |""".stripMargin s"""def batched[${commaSep(j => s"T$j")}](${commaSep(j => s"f$j: V[Column] => Column[T$j]")})( - | items: (${commaSep(j => s"Db[T$j]")})* + | items: (${commaSep(j => s"Expr[T$j]")})* |)(implicit qr: Queryable[V[Column], R]): scalasql.query.InsertColumns[V, R] $impl""".stripMargin } } @@ -173,7 +173,7 @@ trait ScalaSql extends Common{ os.write( T.dest / "Generated.scala", s"""package scalasql.generated - |import scalasql.core.{Queryable, Db} + |import scalasql.core.{Queryable, Expr} |import scalasql.query.Column |trait Insert[V[_[_]], R]{ | ${defs(false).mkString("\n")} @@ -182,7 +182,7 @@ trait ScalaSql extends Common{ | def newInsertValues[R]( | insert: scalasql.query.Insert[V, R], | columns: Seq[Column[_]], - | valuesLists: Seq[Seq[Db[_]]] + | valuesLists: Seq[Seq[Expr[_]]] | )(implicit qr: Queryable[V[Column], R]): scalasql.query.InsertColumns[V, R] | ${defs(true).mkString("\n")} |} diff --git a/docs/design.md b/docs/design.md index 27525da2..9cf25604 100644 --- a/docs/design.md +++ b/docs/design.md @@ -266,13 +266,13 @@ API rather than a SQL-like API: **ScalaSql** ```scala -def songs = MusicDb.songs.filter(_.artistId === id) +def songs = MusicExpr.songs.filter(_.artistId === id) val studentsWithAnAddress = students.filter(s => addresses.filter(a => s.addressId === a.id).nonEmpty) ``` **Squeryl** ```scala -def songs = from(MusicDb.songs)(s => where(s.artistId === id) select(s)) +def songs = from(MusicExpr.songs)(s => where(s.artistId === id) select(s)) val studentsWithAnAddress = from(students)(s => where(exists(from(addresses)((a) => where(s.addressId === a.id) select(a.id)))) diff --git a/docs/generateDocs.sc b/docs/generateDocs.sc index b63e64fa..d32b96a1 100644 --- a/docs/generateDocs.sc +++ b/docs/generateDocs.sc @@ -48,10 +48,10 @@ def generateTutorial(sourcePath: os.Path, destPath: os.Path) = { os.write.over(destPath, outputLines.mkString("\n")) } def generateReference(dest: os.Path, scalafmtCallback: (Seq[os.Path], os.Path) => Unit) = { - def dropDbPrefix(s: String) = s.split('.').drop(2).mkString(".") + def dropExprPrefix(s: String) = s.split('.').drop(2).mkString(".") val records = upickle.default.read[Seq[Record]](os.read.stream(os.pwd / "out" / "recordedTests.json")) val suiteDescriptions = upickle.default.read[Map[String, String]](os.read.stream(os.pwd / "out" / "recordedSuiteDescriptions.json")) - .map{case (k, v) => (dropDbPrefix(k), v)} + .map{case (k, v) => (dropExprPrefix(k), v)} val rawScalaStrs = records.flatMap(r => Seq(r.queryCodeString) ++ r.resultCodeString) val formattedScalaStrs = { @@ -129,8 +129,8 @@ def generateReference(dest: os.Path, scalafmtCallback: (Seq[os.Path], os.Path) = .groupBy(_.suiteName) .toSeq .sortBy(_._2.head.suiteLine) - .distinctBy { case (k, v) => dropDbPrefix(k)} - .map{case (k, vs) => (dropDbPrefix(k), vs.map(r => r.copy(suiteName = dropDbPrefix(r.suiteName))))} + .distinctBy { case (k, v) => dropExprPrefix(k)} + .map{case (k, vs) => (dropExprPrefix(k), vs.map(r => r.copy(suiteName = dropExprPrefix(r.suiteName))))} for((suiteName, suiteGroup) <- recordsWithoutDuplicateSuites) { val seen = mutable.Set.empty[String] diff --git a/docs/reference.md b/docs/reference.md index 218c7aae..f6263c7b 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -494,12 +494,12 @@ dbClient.transaction(_.run(Purchase.select.size)) ==> 1 Basic `SELECT` operations: map, filter, join, etc. ### Select.constant -The most simple thing you can query in the database is an `Db`. These do not need +The most simple thing you can query in the database is an `Expr`. These do not need to be related to any database tables, and translate into raw `SELECT` calls without `FROM`. ```scala -Db(1) + Db(2) +Expr(1) + Expr(2) ``` @@ -835,7 +835,7 @@ Buyer.select.map(c => (c.id, c)) `SELECT` queries that return a single row and column can be used as SQL expressions in standard SQL databases. In ScalaSql, this is done by the `.toExpr` method, -which turns a `Select[T]` into an `Db[T]`. Note that if the `Select` returns more +which turns a `Select[T]` into an `Expr[T]`. Note that if the `Select` returns more than one row or column, the database may select a row arbitrarily or will throw an exception at runtime (depend on implenmentation) @@ -1246,8 +1246,8 @@ Buyer.select ### Select.nestedTuples -Queries can output arbitrarily nested tuples of `Db[T]` and `case class` -instances of `Foo[Db]`, which will be de-serialized into nested tuples +Queries can output arbitrarily nested tuples of `Expr[T]` and `case class` +instances of `Foo[Expr]`, which will be de-serialized into nested tuples of `T` and `Foo[Sc]`s. The `AS` aliases assigned to each column will contain the path of indices and field names used to populate the final returned values @@ -1716,8 +1716,8 @@ Buyer.select ### Join.leftJoinExpr -`JoinNullable[Db[T]]`s can be implicitly used as `Db[Option[T]]`s. This allows -them to participate in any database query logic than any other `Db[Option[T]]`s +`JoinNullable[Expr[T]]`s can be implicitly used as `Expr[Option[T]]`s. This allows +them to participate in any database query logic than any other `Expr[Option[T]]`s can participate in, such as being used as sort key or in computing return values (below). @@ -1823,7 +1823,7 @@ Buyer.select ### Join.leftJoinExprExplicit -The conversion from `JoinNullable[T]` to `Db[Option[T]]` can also be performed +The conversion from `JoinNullable[T]` to `Expr[Option[T]]` can also be performed explicitly via `JoinNullable.toExpr(...)` ```scala @@ -2958,7 +2958,7 @@ Buyer.select.filter(_.name `=` "John Dee").map(_.dateOfBirth) ### Update.dynamic -The values assigned to columns in `Table.update` can also be computed `Db[T]`s, +The values assigned to columns in `Table.update` can also be computed `Expr[T]`s, not just literal Scala constants. This example shows how to to update the name of the row for `James Bond` with it's existing name in uppercase @@ -3947,7 +3947,7 @@ Buyer.select.filter(_.name `=` "James Bond").map(_.dateOfBirth) ### UpdateSubQuery.setSubquery You can use subqueries to compute the values you want to update, using -aggregates like `.maxBy` to convert the `Select[T]` into an `Db[T]` +aggregates like `.maxBy` to convert the `Select[T]` into an `Expr[T]` ```scala Product.update(_ => true).set(_.price := Product.select.maxBy(_.price)) @@ -4387,7 +4387,7 @@ Queries using `ON CONFLICT DO UPDATE` or `ON CONFLICT DO NOTHING` ScalaSql's `.onConflictIgnore` translates into SQL's `ON CONFLICT DO NOTHING` -Note that H2 and HsqlDb do not support `onConflictIgnore` and `onConflictUpdate`, while +Note that H2 and HsqlExpr do not support `onConflictIgnore` and `onConflictUpdate`, while MySql only supports `onConflictUpdate` but not `onConflictIgnore`. ```scala @@ -5057,7 +5057,7 @@ Buyer.select ```scala for { b <- Buyer.select - s <- ShippingInfo.select.filter { s => b.id `=` s.buyerId }.joinLateral(_ => Db(true)) + s <- ShippingInfo.select.filter { s => b.id `=` s.buyerId }.joinLateral(_ => Expr(true)) } yield (b.name, s.shippingDate) ``` @@ -5092,7 +5092,7 @@ ScalaSql supports `LEFT JOIN`s, `RIGHT JOIN`s and `OUTER JOIN`s via the ```scala Buyer.select.leftJoinLateral(b => ShippingInfo.select.filter(b.id `=` _.buyerId))((_, _) => - Db(true) + Expr(true) ) ``` @@ -5146,7 +5146,7 @@ ScalaSql supports `LEFT JOIN`s, `RIGHT JOIN`s and `OUTER JOIN`s via the ```scala for { b <- Buyer.select - s <- ShippingInfo.select.filter(b.id `=` _.buyerId).leftJoinLateral(_ => Db(true)) + s <- ShippingInfo.select.filter(b.id `=` _.buyerId).leftJoinLateral(_ => Expr(true)) } yield (b, s) ``` @@ -6346,8 +6346,8 @@ instead of using `JOIN`s it uses subqueries nested 4 layers deep. While this example is contrived, it demonstrates how nested ScalaSql `.select` calls translate directly into nested SQL subqueries. -To turn the ScalaSql `Select[T]` into an `Db[T]`, you can either use -an aggregate method like `.sumBy(...): Db[Int]` that generates a `SUM(...)` +To turn the ScalaSql `Select[T]` into an `Expr[T]`, you can either use +an aggregate method like `.sumBy(...): Expr[Int]` that generates a `SUM(...)` aggregate, or via the `.toExpr` method that leaves the subquery untouched. SQL requires that subqueries used as expressions must return a single row and single column, and if the query returns some other number of rows/columns @@ -6579,14 +6579,14 @@ db.withCte(Buyer.select) { bs => -## DbOps -Operations that can be performed on `Db[T]` for any `T` -### DbOps.numeric.greaterThan +## ExprOps +Operations that can be performed on `Expr[T]` for any `T` +### ExprOps.numeric.greaterThan ```scala -Db(6) > Db(2) +Expr(6) > Expr(2) ``` @@ -6604,12 +6604,12 @@ Db(6) > Db(2) -### DbOps.numeric.lessThan +### ExprOps.numeric.lessThan ```scala -Db(6) < Db(2) +Expr(6) < Expr(2) ``` @@ -6627,12 +6627,12 @@ Db(6) < Db(2) -### DbOps.numeric.greaterThanOrEquals +### ExprOps.numeric.greaterThanOrEquals ```scala -Db(6) >= Db(2) +Expr(6) >= Expr(2) ``` @@ -6650,12 +6650,12 @@ Db(6) >= Db(2) -### DbOps.numeric.lessThanOrEquals +### ExprOps.numeric.lessThanOrEquals ```scala -Db(6) <= Db(2) +Expr(6) <= Expr(2) ``` @@ -6673,12 +6673,12 @@ Db(6) <= Db(2) -### DbOps.string.greaterThan +### ExprOps.string.greaterThan ```scala -Db("A") > Db("B") +Expr("A") > Expr("B") ``` @@ -6696,12 +6696,12 @@ Db("A") > Db("B") -### DbOps.string.lessThan +### ExprOps.string.lessThan ```scala -Db("A") < Db("B") +Expr("A") < Expr("B") ``` @@ -6719,12 +6719,12 @@ Db("A") < Db("B") -### DbOps.string.greaterThanOrEquals +### ExprOps.string.greaterThanOrEquals ```scala -Db("A") >= Db("B") +Expr("A") >= Expr("B") ``` @@ -6742,12 +6742,12 @@ Db("A") >= Db("B") -### DbOps.string.lessThanOrEquals +### ExprOps.string.lessThanOrEquals ```scala -Db("A") <= Db("B") +Expr("A") <= Expr("B") ``` @@ -6765,12 +6765,12 @@ Db("A") <= Db("B") -### DbOps.boolean.greaterThan +### ExprOps.boolean.greaterThan ```scala -Db(true) > Db(false) +Expr(true) > Expr(false) ``` @@ -6788,12 +6788,12 @@ Db(true) > Db(false) -### DbOps.boolean.lessThan +### ExprOps.boolean.lessThan ```scala -Db(true) < Db(true) +Expr(true) < Expr(true) ``` @@ -6811,12 +6811,12 @@ Db(true) < Db(true) -### DbOps.boolean.greaterThanOrEquals +### ExprOps.boolean.greaterThanOrEquals ```scala -Db(true) >= Db(true) +Expr(true) >= Expr(true) ``` @@ -6834,12 +6834,12 @@ Db(true) >= Db(true) -### DbOps.boolean.lessThanOrEquals +### ExprOps.boolean.lessThanOrEquals ```scala -Db(true) <= Db(true) +Expr(true) <= Expr(true) ``` @@ -6857,12 +6857,12 @@ Db(true) <= Db(true) -### DbOps.cast.byte +### ExprOps.cast.byte ```scala -Db(45.12).cast[Byte] +Expr(45.12).cast[Byte] ``` @@ -6880,12 +6880,12 @@ Db(45.12).cast[Byte] -### DbOps.cast.short +### ExprOps.cast.short ```scala -Db(1234.1234).cast[Short] +Expr(1234.1234).cast[Short] ``` @@ -6903,12 +6903,12 @@ Db(1234.1234).cast[Short] -### DbOps.cast.int +### ExprOps.cast.int ```scala -Db(1234.1234).cast[Int] +Expr(1234.1234).cast[Int] ``` @@ -6926,12 +6926,12 @@ Db(1234.1234).cast[Int] -### DbOps.cast.long +### ExprOps.cast.long ```scala -Db(1234.1234).cast[Long] +Expr(1234.1234).cast[Long] ``` @@ -6949,12 +6949,12 @@ Db(1234.1234).cast[Long] -### DbOps.cast.string +### ExprOps.cast.string ```scala -Db(1234.5678).cast[String] +Expr(1234.5678).cast[String] ``` @@ -6972,12 +6972,12 @@ Db(1234.5678).cast[String] -### DbOps.cast.localdate +### ExprOps.cast.localdate ```scala -Db("2001-02-03").cast[java.time.LocalDate] +Expr("2001-02-03").cast[java.time.LocalDate] ``` @@ -6995,12 +6995,12 @@ Db("2001-02-03").cast[java.time.LocalDate] -### DbOps.cast.localdatetime +### ExprOps.cast.localdatetime ```scala -Db("2023-11-12 03:22:41").cast[java.time.LocalDateTime] +Expr("2023-11-12 03:22:41").cast[java.time.LocalDateTime] ``` @@ -7018,12 +7018,12 @@ Db("2023-11-12 03:22:41").cast[java.time.LocalDateTime] -### DbOps.cast.instant +### ExprOps.cast.instant ```scala -Db("2007-12-03 10:15:30.00").cast[java.time.Instant] +Expr("2007-12-03 10:15:30.00").cast[java.time.Instant] ``` @@ -7041,12 +7041,12 @@ Db("2007-12-03 10:15:30.00").cast[java.time.Instant] -### DbOps.cast.castNamed +### ExprOps.cast.castNamed ```scala -Db(1234.5678).castNamed[String](sql"CHAR(3)") +Expr(1234.5678).castNamed[String](sql"CHAR(3)") ``` @@ -7064,14 +7064,14 @@ Db(1234.5678).castNamed[String](sql"CHAR(3)") -## DbBooleanOps -Operations that can be performed on `Db[Boolean]` -### DbBooleanOps.and +## ExprBooleanOps +Operations that can be performed on `Expr[Boolean]` +### ExprBooleanOps.and ```scala -Db(true) && Db(true) +Expr(true) && Expr(true) ``` @@ -7094,7 +7094,7 @@ Db(true) && Db(true) ```scala -Db(false) && Db(true) +Expr(false) && Expr(true) ``` @@ -7112,12 +7112,12 @@ Db(false) && Db(true) -### DbBooleanOps.or +### ExprBooleanOps.or ```scala -Db(false) || Db(false) +Expr(false) || Expr(false) ``` @@ -7140,7 +7140,7 @@ Db(false) || Db(false) ```scala -!Db(false) +!Expr(false) ``` @@ -7158,14 +7158,14 @@ Db(false) || Db(false) -## DbNumericOps -Operations that can be performed on `Db[T]` when `T` is numeric -### DbNumericOps.plus +## ExprNumericOps +Operations that can be performed on `Expr[T]` when `T` is numeric +### ExprNumericOps.plus ```scala -Db(6) + Db(2) +Expr(6) + Expr(2) ``` @@ -7183,12 +7183,12 @@ Db(6) + Db(2) -### DbNumericOps.minus +### ExprNumericOps.minus ```scala -Db(6) - Db(2) +Expr(6) - Expr(2) ``` @@ -7206,12 +7206,12 @@ Db(6) - Db(2) -### DbNumericOps.times +### ExprNumericOps.times ```scala -Db(6) * Db(2) +Expr(6) * Expr(2) ``` @@ -7229,12 +7229,12 @@ Db(6) * Db(2) -### DbNumericOps.divide +### ExprNumericOps.divide ```scala -Db(6) / Db(2) +Expr(6) / Expr(2) ``` @@ -7252,12 +7252,12 @@ Db(6) / Db(2) -### DbNumericOps.modulo +### ExprNumericOps.modulo ```scala -Db(6) % Db(2) +Expr(6) % Expr(2) ``` @@ -7275,12 +7275,12 @@ Db(6) % Db(2) -### DbNumericOps.bitwiseAnd +### ExprNumericOps.bitwiseAnd ```scala -Db(6) & Db(2) +Expr(6) & Expr(2) ``` @@ -7298,12 +7298,12 @@ Db(6) & Db(2) -### DbNumericOps.bitwiseOr +### ExprNumericOps.bitwiseOr ```scala -Db(6) | Db(3) +Expr(6) | Expr(3) ``` @@ -7321,12 +7321,12 @@ Db(6) | Db(3) -### DbNumericOps.between +### ExprNumericOps.between ```scala -Db(4).between(Db(2), Db(6)) +Expr(4).between(Expr(2), Expr(6)) ``` @@ -7344,12 +7344,12 @@ Db(4).between(Db(2), Db(6)) -### DbNumericOps.unaryPlus +### ExprNumericOps.unaryPlus ```scala -+Db(-4) ++Expr(-4) ``` @@ -7367,12 +7367,12 @@ Db(4).between(Db(2), Db(6)) -### DbNumericOps.unaryMinus +### ExprNumericOps.unaryMinus ```scala --Db(-4) +-Expr(-4) ``` @@ -7390,12 +7390,12 @@ Db(4).between(Db(2), Db(6)) -### DbNumericOps.unaryTilde +### ExprNumericOps.unaryTilde ```scala -~Db(-4) +~Expr(-4) ``` @@ -7413,12 +7413,12 @@ Db(4).between(Db(2), Db(6)) -### DbNumericOps.abs +### ExprNumericOps.abs ```scala -Db(-4).abs +Expr(-4).abs ``` @@ -7436,12 +7436,12 @@ Db(-4).abs -### DbNumericOps.mod +### ExprNumericOps.mod ```scala -Db(8).mod(Db(3)) +Expr(8).mod(Expr(3)) ``` @@ -7459,12 +7459,12 @@ Db(8).mod(Db(3)) -### DbNumericOps.ceil +### ExprNumericOps.ceil ```scala -Db(4.3).ceil +Expr(4.3).ceil ``` @@ -7482,12 +7482,12 @@ Db(4.3).ceil -### DbNumericOps.floor +### ExprNumericOps.floor ```scala -Db(4.7).floor +Expr(4.7).floor ``` @@ -7505,12 +7505,12 @@ Db(4.7).floor -### DbNumericOps.precedence +### ExprNumericOps.precedence ```scala -(Db(2) + Db(3)) * Db(4) +(Expr(2) + Expr(3)) * Expr(4) ``` @@ -7528,12 +7528,12 @@ Db(4.7).floor -### DbNumericOps.sign +### ExprNumericOps.sign ```scala -Db(-100).sign +Expr(-100).sign ``` @@ -7551,9 +7551,9 @@ Db(-100).sign -## DbSeqNumericOps -Operations that can be performed on `Db[Seq[T]]` where `T` is numeric -### DbSeqNumericOps.sum +## ExprSeqNumericOps +Operations that can be performed on `Expr[Seq[T]]` where `T` is numeric +### ExprSeqNumericOps.sum @@ -7576,7 +7576,7 @@ Purchase.select.map(_.count).sum -### DbSeqNumericOps.min +### ExprSeqNumericOps.min @@ -7599,7 +7599,7 @@ Purchase.select.map(_.count).min -### DbSeqNumericOps.max +### ExprSeqNumericOps.max @@ -7622,7 +7622,7 @@ Purchase.select.map(_.count).max -### DbSeqNumericOps.avg +### ExprSeqNumericOps.avg @@ -7645,9 +7645,9 @@ Purchase.select.map(_.count).avg -## DbSeqOps -Operations that can be performed on `Db[Seq[_]]` -### DbSeqOps.size +## ExprSeqOps +Operations that can be performed on `Expr[Seq[_]]` +### ExprSeqOps.size @@ -7670,7 +7670,7 @@ Purchase.select.size -### DbSeqOps.sumBy.simple +### ExprSeqOps.sumBy.simple @@ -7693,7 +7693,7 @@ Purchase.select.sumBy(_.count) -### DbSeqOps.sumBy.some +### ExprSeqOps.sumBy.some @@ -7716,7 +7716,7 @@ Purchase.select.sumByOpt(_.count) -### DbSeqOps.sumBy.none +### ExprSeqOps.sumBy.none @@ -7739,7 +7739,7 @@ Purchase.select.filter(_ => false).sumByOpt(_.count) -### DbSeqOps.minBy.simple +### ExprSeqOps.minBy.simple @@ -7762,7 +7762,7 @@ Purchase.select.minBy(_.count) -### DbSeqOps.minBy.some +### ExprSeqOps.minBy.some @@ -7785,7 +7785,7 @@ Purchase.select.minByOpt(_.count) -### DbSeqOps.minBy.none +### ExprSeqOps.minBy.none @@ -7808,7 +7808,7 @@ Purchase.select.filter(_ => false).minByOpt(_.count) -### DbSeqOps.maxBy.simple +### ExprSeqOps.maxBy.simple @@ -7831,7 +7831,7 @@ Purchase.select.maxBy(_.count) -### DbSeqOps.maxBy.some +### ExprSeqOps.maxBy.some @@ -7854,7 +7854,7 @@ Purchase.select.maxByOpt(_.count) -### DbSeqOps.maxBy.none +### ExprSeqOps.maxBy.none @@ -7877,7 +7877,7 @@ Purchase.select.filter(_ => false).maxByOpt(_.count) -### DbSeqOps.avgBy.simple +### ExprSeqOps.avgBy.simple @@ -7900,7 +7900,7 @@ Purchase.select.avgBy(_.count) -### DbSeqOps.avgBy.some +### ExprSeqOps.avgBy.some @@ -7923,7 +7923,7 @@ Purchase.select.avgByOpt(_.count) -### DbSeqOps.avgBy.none +### ExprSeqOps.avgBy.none @@ -7946,7 +7946,7 @@ Purchase.select.filter(_ => false).avgByOpt(_.count) -### DbSeqOps.mkString.simple +### ExprSeqOps.mkString.simple @@ -7969,7 +7969,7 @@ Buyer.select.map(_.name).mkString() -### DbSeqOps.mkString.sep +### ExprSeqOps.mkString.sep @@ -7992,14 +7992,14 @@ Buyer.select.map(_.name).mkString(", ") -## DbStringOps -Operations that can be performed on `Db[String]` -### DbStringOps.plus +## ExprStringOps +Operations that can be performed on `Expr[String]` +### ExprStringOps.plus ```scala -Db("hello") + Db("world") +Expr("hello") + Expr("world") ``` @@ -8017,12 +8017,12 @@ Db("hello") + Db("world") -### DbStringOps.like +### ExprStringOps.like ```scala -Db("hello").like("he%") +Expr("hello").like("he%") ``` @@ -8040,12 +8040,12 @@ Db("hello").like("he%") -### DbStringOps.length +### ExprStringOps.length ```scala -Db("hello").length +Expr("hello").length ``` @@ -8063,12 +8063,12 @@ Db("hello").length -### DbStringOps.octetLength +### ExprStringOps.octetLength ```scala -Db("叉烧包").octetLength +Expr("叉烧包").octetLength ``` @@ -8086,12 +8086,12 @@ Db("叉烧包").octetLength -### DbStringOps.position +### ExprStringOps.position ```scala -Db("hello").indexOf("ll") +Expr("hello").indexOf("ll") ``` @@ -8109,12 +8109,12 @@ Db("hello").indexOf("ll") -### DbStringOps.toLowerCase +### ExprStringOps.toLowerCase ```scala -Db("Hello").toLowerCase +Expr("Hello").toLowerCase ``` @@ -8132,12 +8132,12 @@ Db("Hello").toLowerCase -### DbStringOps.trim +### ExprStringOps.trim ```scala -Db(" Hello ").trim +Expr(" Hello ").trim ``` @@ -8155,12 +8155,12 @@ Db(" Hello ").trim -### DbStringOps.ltrim +### ExprStringOps.ltrim ```scala -Db(" Hello ").ltrim +Expr(" Hello ").ltrim ``` @@ -8178,12 +8178,12 @@ Db(" Hello ").ltrim -### DbStringOps.rtrim +### ExprStringOps.rtrim ```scala -Db(" Hello ").rtrim +Expr(" Hello ").rtrim ``` @@ -8201,12 +8201,12 @@ Db(" Hello ").rtrim -### DbStringOps.substring +### ExprStringOps.substring ```scala -Db("Hello").substring(2, 2) +Expr("Hello").substring(2, 2) ``` @@ -8224,12 +8224,12 @@ Db("Hello").substring(2, 2) -### DbStringOps.startsWith +### ExprStringOps.startsWith ```scala -Db("Hello").startsWith("Hel") +Expr("Hello").startsWith("Hel") ``` @@ -8247,12 +8247,12 @@ Db("Hello").startsWith("Hel") -### DbStringOps.endsWith +### ExprStringOps.endsWith ```scala -Db("Hello").endsWith("llo") +Expr("Hello").endsWith("llo") ``` @@ -8270,12 +8270,12 @@ Db("Hello").endsWith("llo") -### DbStringOps.contains +### ExprStringOps.contains ```scala -Db("Hello").contains("ll") +Expr("Hello").contains("ll") ``` @@ -8293,12 +8293,12 @@ Db("Hello").contains("ll") -### DbStringOps.replace +### ExprStringOps.replace ```scala -Db("Hello").replace("ll", "rr") +Expr("Hello").replace("ll", "rr") ``` @@ -8316,14 +8316,14 @@ Db("Hello").replace("ll", "rr") -## DbBlobOps -Operations that can be performed on `Db[Bytes]` -### DbBlobOps.plus +## ExprBlobOps +Operations that can be performed on `Expr[Bytes]` +### ExprBlobOps.plus ```scala -Db(Bytes("hello")) + Db(Bytes("world")) +Expr(Bytes("hello")) + Expr(Bytes("world")) ``` @@ -8341,12 +8341,12 @@ Db(Bytes("hello")) + Db(Bytes("world")) -### DbBlobOps.like +### ExprBlobOps.like ```scala -Db(Bytes("hello")).like(Bytes("he%")) +Expr(Bytes("hello")).like(Bytes("he%")) ``` @@ -8364,12 +8364,12 @@ Db(Bytes("hello")).like(Bytes("he%")) -### DbBlobOps.length +### ExprBlobOps.length ```scala -Db(Bytes("hello")).length +Expr(Bytes("hello")).length ``` @@ -8387,12 +8387,12 @@ Db(Bytes("hello")).length -### DbBlobOps.octetLength +### ExprBlobOps.octetLength ```scala -Db(Bytes("叉烧包")).octetLength +Expr(Bytes("叉烧包")).octetLength ``` @@ -8410,12 +8410,12 @@ Db(Bytes("叉烧包")).octetLength -### DbBlobOps.position +### ExprBlobOps.position ```scala -Db(Bytes("hello")).indexOf(Bytes("ll")) +Expr(Bytes("hello")).indexOf(Bytes("ll")) ``` @@ -8433,12 +8433,12 @@ Db(Bytes("hello")).indexOf(Bytes("ll")) -### DbBlobOps.substring +### ExprBlobOps.substring ```scala -Db(Bytes("Hello")).substring(2, 2) +Expr(Bytes("Hello")).substring(2, 2) ``` @@ -8456,12 +8456,12 @@ Db(Bytes("Hello")).substring(2, 2) -### DbBlobOps.startsWith +### ExprBlobOps.startsWith ```scala -Db(Bytes("Hello")).startsWith(Bytes("Hel")) +Expr(Bytes("Hello")).startsWith(Bytes("Hel")) ``` @@ -8479,12 +8479,12 @@ Db(Bytes("Hello")).startsWith(Bytes("Hel")) -### DbBlobOps.endsWith +### ExprBlobOps.endsWith ```scala -Db(Bytes("Hello")).endsWith(Bytes("llo")) +Expr(Bytes("Hello")).endsWith(Bytes("llo")) ``` @@ -8502,12 +8502,12 @@ Db(Bytes("Hello")).endsWith(Bytes("llo")) -### DbBlobOps.contains +### ExprBlobOps.contains ```scala -Db(Bytes("Hello")).contains(Bytes("ll")) +Expr(Bytes("Hello")).contains(Bytes("ll")) ``` @@ -8525,9 +8525,9 @@ Db(Bytes("Hello")).contains(Bytes("ll")) -## DbMathOps +## ExprMathOps Math operations; supported by H2/Postgres/MySql, not supported by Sqlite -### DbMathOps.power +### ExprMathOps.power @@ -8550,7 +8550,7 @@ db.power(10, 3) -### DbMathOps.sqrt +### ExprMathOps.sqrt @@ -8573,7 +8573,7 @@ db.sqrt(9) -### DbMathOps.ln +### ExprMathOps.ln @@ -8591,7 +8591,7 @@ db.ln(16.0) -### DbMathOps.log +### ExprMathOps.log @@ -8609,7 +8609,7 @@ db.log(2, 8) -### DbMathOps.log10 +### ExprMathOps.log10 @@ -8627,7 +8627,7 @@ db.log10(16.0) -### DbMathOps.exp +### ExprMathOps.exp @@ -8645,7 +8645,7 @@ db.exp(16.0) -### DbMathOps.sin +### ExprMathOps.sin @@ -8663,7 +8663,7 @@ db.sin(16.0) -### DbMathOps.cos +### ExprMathOps.cos @@ -8681,7 +8681,7 @@ db.cos(16.0) -### DbMathOps.tan +### ExprMathOps.tan @@ -8699,7 +8699,7 @@ db.tan(16.0) -### DbMathOps.asin +### ExprMathOps.asin @@ -8717,7 +8717,7 @@ db.asin(1.0) -### DbMathOps.acos +### ExprMathOps.acos @@ -8735,7 +8735,7 @@ db.acos(1.0) -### DbMathOps.atan +### ExprMathOps.atan @@ -8753,7 +8753,7 @@ db.atan(1.0) -### DbMathOps.atan2 +### ExprMathOps.atan2 @@ -8771,7 +8771,7 @@ db.atan2(16.0, 23.0) -### DbMathOps.pi +### ExprMathOps.pi @@ -8789,7 +8789,7 @@ db.pi -### DbMathOps.degrees +### ExprMathOps.degrees @@ -8807,7 +8807,7 @@ db.degrees(180) -### DbMathOps.radians +### ExprMathOps.radians @@ -9010,7 +9010,7 @@ db.run(Enclosing.select) ==> Seq(value1, value2) ## Optional -Queries using columns that may be `NULL`, `Db[Option[T]]` or `Option[T]` in Scala +Queries using columns that may be `NULL`, `Expr[Option[T]]` or `Option[T]` in Scala ### Optional @@ -9069,7 +9069,7 @@ OptCols.select ### Optional.groupByMaxGet -Some aggregates return `Db[Option[V]]`s, et.c. `.maxByOpt` +Some aggregates return `Expr[Option[V]]`s, et.c. `.maxByOpt` ```scala OptCols.select.groupBy(_.myInt)(_.maxByOpt(_.myInt2.get)) @@ -9094,7 +9094,7 @@ OptCols.select.groupBy(_.myInt)(_.maxByOpt(_.myInt2.get)) ### Optional.isDefined -`.isDefined` on `Db[Option[V]]` translates to a SQL +`.isDefined` on `Expr[Option[V]]` translates to a SQL `IS NOT NULL` check ```scala @@ -9122,7 +9122,7 @@ OptCols.select.filter(_.myInt.isDefined) ### Optional.isEmpty -`.isEmpty` on `Db[Option[V]]` translates to a SQL +`.isEmpty` on `Expr[Option[V]]` translates to a SQL `IS NULL` check ```scala @@ -9351,11 +9351,11 @@ OptCols.select.filter(_.myInt !== Option.empty[Int]) ### Optional.map You can use operators like `.map` and `.flatMap` to work with -your `Db[Option[V]]` values. These roughly follow the semantics +your `Expr[Option[V]]` values. These roughly follow the semantics that you would be familiar with from Scala. ```scala -OptCols.select.map(d => d.copy[Db](myInt = d.myInt.map(_ + 10))) +OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.map(_ + 10))) ``` @@ -9410,7 +9410,7 @@ OptCols.select.map(_.myInt.map(_ + 10)) ```scala OptCols.select - .map(d => d.copy[Db](myInt = d.myInt.flatMap(v => d.myInt2.map(v2 => v + v2 + 10)))) + .map(d => d.copy[Expr](myInt = d.myInt.flatMap(v => d.myInt2.map(v2 => v + v2 + 10)))) ``` @@ -9439,13 +9439,13 @@ OptCols.select ### Optional.mapGet -You can use `.get` to turn an `Db[Option[V]]` into an `Db[V]`. This follows +You can use `.get` to turn an `Expr[Option[V]]` into an `Expr[V]`. This follows SQL semantics, such that `NULL`s anywhere in that selected column automatically -will turn the whole column `None` (if it's an `Db[Option[V]]` column) or `null` +will turn the whole column `None` (if it's an `Expr[Option[V]]` column) or `null` (if it's not an optional column) ```scala -OptCols.select.map(d => d.copy[Db](myInt = d.myInt.map(_ + d.myInt2.get + 1))) +OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.map(_ + d.myInt2.get + 1))) ``` @@ -9477,7 +9477,7 @@ OptCols.select.map(d => d.copy[Db](myInt = d.myInt.map(_ + d.myInt2.get + 1))) ```scala -OptCols.select.map(d => d.copy[Db](myInt = d.myInt.get + d.myInt2.get + 1)) +OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.get + d.myInt2.get + 1)) ``` @@ -9509,7 +9509,7 @@ OptCols.select.map(d => d.copy[Db](myInt = d.myInt.get + d.myInt2.get + 1)) ```scala -OptCols.select.map(d => d.copy[Db](myInt = d.myInt.getOrElse(-1))) +OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.getOrElse(-1))) ``` @@ -9540,7 +9540,7 @@ OptCols.select.map(d => d.copy[Db](myInt = d.myInt.getOrElse(-1))) ```scala -OptCols.select.map(d => d.copy[Db](myInt = d.myInt.orElse(d.myInt2))) +OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.orElse(d.myInt2))) ``` @@ -9571,7 +9571,7 @@ OptCols.select.map(d => d.copy[Db](myInt = d.myInt.orElse(d.myInt2))) `.filter` follows normal Scala semantics, and translates to a `CASE`/`WHEN (foo)`/`ELSE NULL` ```scala -OptCols.select.map(d => d.copy[Db](myInt = d.myInt.filter(_ < 2))) +OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.filter(_ < 2))) ``` @@ -9822,7 +9822,7 @@ Purchase.select.distinctOn(_.shippingInfoId).sortBy(_.shippingInfoId).desc ```scala -Db("xxHellox").ltrim("x") +Expr("xxHellox").ltrim("x") ``` @@ -9845,7 +9845,7 @@ Db("xxHellox").ltrim("x") ```scala -Db("xxHellox").rtrim("x") +Expr("xxHellox").rtrim("x") ``` @@ -9868,7 +9868,7 @@ Db("xxHellox").rtrim("x") ```scala -Db("Hello").reverse +Expr("Hello").reverse ``` @@ -9891,7 +9891,7 @@ Db("Hello").reverse ```scala -Db("Hello").lpad(10, "xy") +Expr("Hello").lpad(10, "xy") ``` @@ -9914,7 +9914,7 @@ Db("Hello").lpad(10, "xy") ```scala -Db("Hello").rpad(10, "xy") +Expr("Hello").rpad(10, "xy") ``` @@ -10026,7 +10026,7 @@ Operations specific to working with MySql Databases ```scala -Db("Hello").reverse +Expr("Hello").reverse ``` @@ -10049,7 +10049,7 @@ Db("Hello").reverse ```scala -Db("Hello").lpad(10, "xy") +Expr("Hello").lpad(10, "xy") ``` @@ -10072,7 +10072,7 @@ Db("Hello").lpad(10, "xy") ```scala -Db("Hello").rpad(10, "xy") +Expr("Hello").rpad(10, "xy") ``` @@ -10292,7 +10292,7 @@ Operations specific to working with Sqlite Databases ```scala -Db("xxHellox").ltrim("x") +Expr("xxHellox").ltrim("x") ``` @@ -10315,7 +10315,7 @@ Db("xxHellox").ltrim("x") ```scala -Db("xxHellox").rtrim("x") +Expr("xxHellox").rtrim("x") ``` @@ -10338,7 +10338,7 @@ Db("xxHellox").rtrim("x") ```scala -Db("*cop*").glob("roflcopter") +Expr("*cop*").glob("roflcopter") ``` @@ -10555,7 +10555,7 @@ Operations specific to working with H2 Databases ```scala -Db("xxHellox").ltrim("x") +Expr("xxHellox").ltrim("x") ``` @@ -10578,7 +10578,7 @@ Db("xxHellox").ltrim("x") ```scala -Db("xxHellox").rtrim("x") +Expr("xxHellox").rtrim("x") ``` @@ -10601,7 +10601,7 @@ Db("xxHellox").rtrim("x") ```scala -Db("Hello").lpad(10, "xy") +Expr("Hello").lpad(10, "xy") ``` @@ -10624,7 +10624,7 @@ Db("Hello").lpad(10, "xy") ```scala -Db("Hello").rpad(10, "xy") +Expr("Hello").rpad(10, "xy") ``` diff --git a/docs/tutorial.md b/docs/tutorial.md index 7a65d889..13f11e6f 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -15,7 +15,7 @@ import scalasql.H2Dialect._ ``` This readme will use the H2 database for simplicity, but you can change the `Dialect` -above to other databases as necessary. ScalaSql supports H2, Sqlite, HsqlDb, +above to other databases as necessary. ScalaSql supports H2, Sqlite, HsqlExpr, Postgres, and MySql out of the box. The `Dialect` import provides the various operators and functions that may be unique to each specific database @@ -65,7 +65,7 @@ supported databases, to see what kind of set up is necessary for each one * [MySql](scalasql/test/src/example/MySqlExample.scala) * [Sqlite](scalasql/test/src/example/SqliteExample.scala) * [H2](scalasql/test/src/example/H2Example.scala) -* [HsqlDb](scalasql/test/src/example/HsqlDbExample.scala) +* [HsqlExpr](scalasql/test/src/example/HsqlExprExample.scala) * [HikariCP](scalasql/test/src/example/HikariCpExample.scala) (and other connection pools) ### Modeling Your Schema @@ -73,7 +73,7 @@ supported databases, to see what kind of set up is necessary for each one Next, you need to define your data model classes. In ScalaSql, your data model is defined using `case class`es with each field wrapped in the wrapper type parameter `T[_]`. This allows us to re-use the same case class to represent -both database values (when `T` is `scalasql.Db`) as well as Scala values +both database values (when `T` is `scalasql.Expr`) as well as Scala values (when `T` is `scalasql.Sc`). Here, we define three classes `Country` `City` and `CountryLanguage`, modeling @@ -153,27 +153,27 @@ Lastly, we will run the `world.sql` script to initialize the database, and we're ready to begin writing queries! ## Expressions -The simplest thing you can query are `scalasql.Db`s. These represent the SQL +The simplest thing you can query are `scalasql.Expr`s. These represent the SQL expressions that are part of a query, and can be evaluated even without being part of any database table. -Here, we construct `Db`s to represent the SQL query `1 + 3`. We can use +Here, we construct `Expr`s to represent the SQL query `1 + 3`. We can use `db.renderSql` to see the generated SQL code, and `db.run` to send the query to the database and return the output `4` ```scala -val query = Db(1) + Db(3) +val query = Expr(1) + Expr(3) db.renderSql(query) ==> "SELECT (? + ?) AS res" db.run(query) ==> 4 ``` In general, most primitive types that can be mapped to SQL can be converted -to `scalasql.Db`s: `Int`s and other numeric types, `String`s, `Boolean`s, -etc., each returning an `Db[T]` for the respective type `T`. Each type of -`Db[T]` has a set of operations representing what operations the database +to `scalasql.Expr`s: `Int`s and other numeric types, `String`s, `Boolean`s, +etc., each returning an `Expr[T]` for the respective type `T`. Each type of +`Expr[T]` has a set of operations representing what operations the database supports on that type of expression. You can check out the [ScalaSql Reference](reference.md#exprops) if you want a -comprehensive list of built-in operations on various `Db[T]` types. +comprehensive list of built-in operations on various `Expr[T]` types. ## Select @@ -234,13 +234,13 @@ db.run(query) ==> City[Sc](3208, "Singapore", "SGP", district = "", population = ``` Note that we use `===` rather than `==` for the equality comparison. The -function literal passed to `.filter` is given a `City[Db]` as its parameter, +function literal passed to `.filter` is given a `City[Expr]` as its parameter, representing a `City` that is part of the database query, in contrast to the -`City[Sc]`s that `db.run` returns , and so `_.name` is of type `Db[String]` +`City[Sc]`s that `db.run` returns , and so `_.name` is of type `Expr[String]` rather than just `String` or `Sc[String]`. You can use your IDE's -auto-complete to see what operations are available on `Db[String]`: typically +auto-complete to see what operations are available on `Expr[String]`: typically they will represent SQL string functions rather than Scala string functions and -take and return `Db[String]`s rather than plain Scala `String`s. Database +take and return `Expr[String]`s rather than plain Scala `String`s. Database value equality is represented by the `===` operator. Note also the `.single` operator. This tells ScalaSql that you expect exactly @@ -309,9 +309,9 @@ db.run(query).take(2) ==> Seq( ) ``` -Again, all the operations within the query work on `Db`s: `c` is a `City[Db]`, -`c.population` is an `Db[Int]`, `c.countryCode` is an `Db[String]`, and -`===` and `>` and `&&` on `Db`s all return `Db[Boolean]`s that represent +Again, all the operations within the query work on `Expr`s: `c` is a `City[Expr]`, +`c.population` is an `Expr[Int]`, `c.countryCode` is an `Expr[String]`, and +`===` and `>` and `&&` on `Expr`s all return `Expr[Boolean]`s that represent a SQL expression that can be sent to the Database as part of your query. You can also stack multiple separate filters together, as shown below: @@ -335,10 +335,10 @@ db.run(query).take(2) ==> Seq( ``` ### Lifting -Conversion of simple primitive `T`s into `Db[T]`s happens implicitly. Below, -`===` expects both left-hand and right-hand values to be `Db`s. `_.id` is -already an `Db[Int]`, but `cityId` is a normal `Int` that is "lifted" into -a `Db[Int]` automatically +Conversion of simple primitive `T`s into `Expr[T]`s happens implicitly. Below, +`===` expects both left-hand and right-hand values to be `Expr`s. `_.id` is +already an `Expr[Int]`, but `cityId` is a normal `Int` that is "lifted" into +a `Expr[Int]` automatically ```scala def find(cityId: Int) = db.run(City.select.filter(_.id === cityId)) @@ -352,10 +352,10 @@ an implicit `scalasql.TypeMapper[T]` in scope. but you can define `TypeMapper`s for your own types if you want to be able to use them to represent types in the database -This implicit lifting can be done explicitly using the `Db(...)` syntax +This implicit lifting can be done explicitly using the `Expr(...)` syntax as shown below ```scala -def find(cityId: Int) = db.run(City.select.filter(_.id === Db(cityId))) +def find(cityId: Int) = db.run(City.select.filter(_.id === Expr(cityId))) assert(find(3208) == List(City[Sc](3208, "Singapore", "SGP", "", 4017733))) assert(find(3209) == List(City[Sc](3209, "Bratislava", "SVK", "Bratislava", 448292))) @@ -539,10 +539,10 @@ same set of types you can lift into queries. ### Nullable Columns Nullable SQL columns are modeled via `T[Option[V]]` fields in your `case class`, -meaning `Db[Option[V]]` in your query and meaning `Sc[Option[V]]` (or just -meaning `Option[V]`) in the returned data. `Db[Option[V]]` supports a similar +meaning `Expr[Option[V]]` in your query and meaning `Sc[Option[V]]` (or just +meaning `Option[V]`) in the returned data. `Expr[Option[V]]` supports a similar set of operations as `Option[V]`: `isDefined`, `isEmpty`, `map`, `flatMap`, `get`, -`orElse`, etc., but returning `Db[V]`s rather than plain `V`s. +`orElse`, etc., but returning `Expr[V]`s rather than plain `V`s. ```scala val query = Country.select .filter(_.capital.isEmpty) @@ -664,10 +664,10 @@ db.run(query) ==> Seq( ``` Note that when you use a left/right/outer join, the corresponding rows are provided to you as `scalasql.JoinNullable[T]` rather than plain `T`s, e.g. -`cityOpt: scalasql.JoinNullable[City[Db]]` above. `JoinNullable[T]` can be checked +`cityOpt: scalasql.JoinNullable[City[Expr]]` above. `JoinNullable[T]` can be checked for presence/absence using `.isEmpty` and specifying a specific column to check, -and can be converted to an `Db[Option[T]]` by `.map`ing itt to a particular -`Db[T]`. +and can be converted to an `Expr[Option[T]]` by `.map`ing itt to a particular +`Expr[T]`. ScalaSql also supports performing `JOIN`s via Scala's `for`-comprehension syntax and `.join`. @@ -811,7 +811,7 @@ db.run(query) ==> List("Antarctica", "Bouvet Island", "China", "India") ## Window Functions ScalaSql supports window functions via the `.over` operator, which -enables the `.partitionBy` and `.sortBy` operators on `Db[T]`. These +enables the `.partitionBy` and `.sortBy` operators on `Expr[T]`. These translate into SQL's `OVER`/`PARTITION BY`/`ORDER BY` clauses ```scala val query = City.select @@ -1114,7 +1114,7 @@ val query = City.insert.select( c => (c.name, c.countryCode, c.district, c.population), City.select .filter(_.name === "Singapore") - .map(c => (Db("New-") + c.name, c.countryCode, c.district, Db(0L))) + .map(c => (Expr("New-") + c.name, c.countryCode, c.district, Expr(0L))) ) db.renderSql(query) ==> """ @@ -1281,16 +1281,16 @@ dbClient.transaction { implicit db => ## Custom Expressions -You can define custom SQL expressions via the `Db` constructor. This is +You can define custom SQL expressions via the `Expr` constructor. This is useful for enclosing ScalaSql when you need to use some operator or syntax that your Database supports but ScalaSql does not have built in. This example -shows how to define a custom `rawToHex` Scala function working on `Db[T]`s, +shows how to define a custom `rawToHex` Scala function working on `Expr[T]`s, that translates down to the H2 database's `RAWTOHEX` SQL function, and finally using that in a query to return a string. ```scala import scalasql.core.SqlStr.SqlStringSyntax -def rawToHex(v: Db[String]): Db[String] = Db { implicit ctx => sql"RAWTOHEX($v)" } +def rawToHex(v: Expr[String]): Expr[String] = Expr { implicit ctx => sql"RAWTOHEX($v)" } val query = City.select.filter(_.countryCode === "SGP").map(c => rawToHex(c.name)).single @@ -1301,12 +1301,12 @@ db.run(query) ==> "00530069006e006700610070006f00720065" ``` Your custom Scala functions can either be standalone functions or extension -methods. Most of the operators on `Db[T]` that ScalaSql comes bundled with +methods. Most of the operators on `Expr[T]` that ScalaSql comes bundled with are extension methods, with a different set being made available for each database. Different databases have a huge range of functions available. ScalaSql comes with the most commonly-used functions built in, but it is expected that you will -need to build up your own library of custom `Db[T]` functions to to access +need to build up your own library of custom `Expr[T]` functions to to access less commonly used functions that are nonetheless still needed in your application ## Custom Type Mappings diff --git a/scalasql/core/src/Aggregatable.scala b/scalasql/core/src/Aggregatable.scala index cda788a6..c74d8b68 100644 --- a/scalasql/core/src/Aggregatable.scala +++ b/scalasql/core/src/Aggregatable.scala @@ -6,6 +6,6 @@ package scalasql.core */ trait Aggregatable[Q] extends WithSqlExpr[Q] { def aggregateExpr[V: TypeMapper](f: Q => Context => SqlStr)( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] } diff --git a/scalasql/core/src/ColumnNamer.scala b/scalasql/core/src/ColumnNamer.scala deleted file mode 100644 index 0d003f32..00000000 --- a/scalasql/core/src/ColumnNamer.scala +++ /dev/null @@ -1,38 +0,0 @@ -package scalasql.core - -import scalasql.core.SqlStr.Renderable - -/** - * Provides pretty column labels for your SELECT clauses. The mapping is - * are unique, concise, and readable, but does not need to be reversible - * since we do not use the names when re-constructing the final query - * return values. - */ -object ColumnNamer { - def isNormalCharacter(c: Char) = (c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z') || c == '_' - - def getSuffixedName( - tokens: Seq[String], - context: Context - ) = { - val prefixedTokens = - if (tokens.isEmpty || !isNormalCharacter(tokens.head.head)) - context.config.columnLabelDefault +: tokens - else tokens - - prefixedTokens - .map(context.config.tableNameMapper) - .mkString(context.config.columnLabelDelimiter) - } - - def selectColumnSql(walked: Queryable.Walked, ctx: Context): Seq[(String, SqlStr)] = { - walked.map { case (k, v) => (getSuffixedName(k, ctx), Renderable.toSql(v)(ctx)) } - } - - def selectColumnReferences(walked: Queryable.Walked, ctx: Context): Seq[(Db.Identity, SqlStr)] = { - walked.map { case (tokens, expr) => - val dbId = Db.identity(expr) - (dbId, SqlStr.raw(getSuffixedName(tokens, ctx), Array(dbId))) - } - } -} diff --git a/scalasql/core/src/Config.scala b/scalasql/core/src/Config.scala index a9bfc0cd..119b7df2 100644 --- a/scalasql/core/src/Config.scala +++ b/scalasql/core/src/Config.scala @@ -4,8 +4,19 @@ package scalasql.core * Things you to do to configure ScalaSql */ trait Config { - def columnLabelDefault = "res" - def columnLabelDelimiter = "_" + /** + * Render a sequence of tokens to a column label; used primarily for + * making the generated queries more easily human readable. + */ + def renderColumnLabel(tokens: Seq[String]): String = { + val prefixedTokens = + if (tokens.isEmpty || !Config.isNormalCharacter(tokens.head.head)) "res" +: tokens + else tokens + + prefixedTokens + .map(tableNameMapper) + .mkString("_") + } /** * Configures the underlying JDBC connection's `setFetchSize` @@ -42,6 +53,7 @@ trait Config { } object Config { + def isNormalCharacter(c: Char) = (c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z') || c == '_' def camelToSnake(s: String) = { val chars = new collection.mutable.StringBuilder var lowercase = false diff --git a/scalasql/core/src/Context.scala b/scalasql/core/src/Context.scala index 0fc38968..25d1c39c 100644 --- a/scalasql/core/src/Context.scala +++ b/scalasql/core/src/Context.scala @@ -8,17 +8,17 @@ import scalasql.core.SqlStr.SqlStringSyntax * * @param fromNaming any [[From]]/`FROM` clauses that are in scope, and the aliases those * clauses are given - * @param exprNaming any [[Db]]s/SQL-expressions that are present in [[fromNaming]], and + * @param exprNaming any [[Expr]]s/SQL-expressions that are present in [[fromNaming]], and * what those expressions are named in SQL * @param config The ScalaSql configuration */ trait Context { def fromNaming: Map[Context.From, String] - def exprNaming: Map[Db.Identity, SqlStr] + def exprNaming: Map[Expr.Identity, SqlStr] def config: Config def withFromNaming(fromNaming: Map[Context.From, String]): Context - def withExprNaming(exprNaming: Map[Db.Identity, SqlStr]): Context + def withExprNaming(exprNaming: Map[Expr.Identity, SqlStr]): Context } object Context { @@ -30,10 +30,10 @@ object Context { def fromRefPrefix(prevContext: Context): String /** - * A mapping of the [[Db]] expressions that this [[From]] produces along + * A mapping of the [[Expr]] expressions that this [[From]] produces along * with their rendered [[SqlStr]]s */ - def fromLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] + def fromLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] /** * How this [[From]] can be rendered into a [[SqlStr]] for embedding into @@ -47,12 +47,12 @@ object Context { } case class Impl( fromNaming: Map[From, String], - exprNaming: Map[Db.Identity, SqlStr], + exprNaming: Map[Expr.Identity, SqlStr], config: Config ) extends Context { def withFromNaming(fromNaming: Map[From, String]): Context = copy(fromNaming = fromNaming) - def withExprNaming(exprNaming: Map[Db.Identity, SqlStr]): Context = + def withExprNaming(exprNaming: Map[Expr.Identity, SqlStr]): Context = copy(exprNaming = exprNaming) } diff --git a/scalasql/core/src/DbApi.scala b/scalasql/core/src/DbApi.scala index de6893f8..e133364b 100644 --- a/scalasql/core/src/DbApi.scala +++ b/scalasql/core/src/DbApi.scala @@ -251,7 +251,7 @@ object DbApi { fileName: sourcecode.FileName, lineNum: sourcecode.Line ): Int = { - // Sqlite and HsqlDb for some reason blow up if you try to do DDL + // Sqlite and HsqlExpr for some reason blow up if you try to do DDL // like DROP TABLE or CREATE TABLE inside a prepared statement, so // fall back to vanilla `createStatement` if (variables.isEmpty) { diff --git a/scalasql/core/src/Db.scala b/scalasql/core/src/Expr.scala similarity index 62% rename from scalasql/core/src/Db.scala rename to scalasql/core/src/Expr.scala index 600ef961..9d33763f 100644 --- a/scalasql/core/src/Db.scala +++ b/scalasql/core/src/Expr.scala @@ -6,7 +6,7 @@ import scalasql.core.SqlStr.SqlStringSyntax * A single "value" in your SQL query that can be mapped to and from * a Scala value of a particular type [[T]] */ -trait Db[T] extends SqlStr.Renderable { +trait Expr[T] extends SqlStr.Renderable { protected final def renderToSql(ctx: Context): SqlStr = { ctx.exprNaming.get(this.exprIdentity).getOrElse(renderToSql0(ctx)) } @@ -14,34 +14,34 @@ trait Db[T] extends SqlStr.Renderable { protected def renderToSql0(implicit ctx: Context): SqlStr override def toString: String = - throw new Exception("Db#toString is not defined. Use Db#exprToString") + throw new Exception("Expr#toString is not defined. Use Expr#exprToString") override def equals(other: Any): Boolean = throw new Exception( - "Db#equals is not defined. Use Db#exprIdentity for your equality checks" + "Expr#equals is not defined. Use Expr#exprIdentity for your equality checks" ) - private lazy val exprIdentity: Db.Identity = new Db.Identity() + private lazy val exprIdentity: Expr.Identity = new Expr.Identity() private def exprToString: String = super.toString /** - * Some syntax like `for` comprehensions likes to generate spurious `Db(true)` + * Some syntax like `for` comprehensions likes to generate spurious `Expr(true)` * clauses. We need to mark them as such so we can filter them out later during * code generation */ protected def exprIsLiteralTrue: Boolean = false } -object Db { - def isLiteralTrue[T](e: Db[T]): Boolean = e.exprIsLiteralTrue - def toString[T](e: Db[T]): String = e.exprToString +object Expr { + def isLiteralTrue[T](e: Expr[T]): Boolean = e.exprIsLiteralTrue + def toString[T](e: Expr[T]): String = e.exprToString - def identity[T](e: Db[T]): Identity = e.exprIdentity + def identity[T](e: Expr[T]): Identity = e.exprIdentity class Identity() - implicit def ExprQueryable[E[_] <: Db[_], T]( + implicit def ExprQueryable[E[_] <: Expr[_], T]( implicit mt: TypeMapper[T] ): Queryable.Row[E[T], T] = new SqlQueryable[E, T]() - class SqlQueryable[E[_] <: Db[_], T]( + class SqlQueryable[E[_] <: Expr[_], T]( implicit tm: TypeMapper[T] ) extends Queryable.Row[E[T], T] { def walkLabels() = Seq(Nil) @@ -49,30 +49,30 @@ object Db { override def construct(args: Queryable.ResultSetIterator): T = args.get(tm) - def deconstruct(r: T): E[T] = Db[T] { implicit ctx: Context => + def deconstruct(r: T): E[T] = Expr[T] { implicit ctx: Context => sql"$r" }.asInstanceOf[E[T]] } - def apply[T](f: Context => SqlStr): Db[T] = new Simple[T](f) - implicit def optionalize[T](e: Db[T]): Db[Option[T]] = { + def apply[T](f: Context => SqlStr): Expr[T] = new Simple[T](f) + implicit def optionalize[T](e: Expr[T]): Expr[Option[T]] = { new Simple[Option[T]](e.renderToSql0(_)) } - class Simple[T](f: Context => SqlStr) extends Db[T] { + class Simple[T](f: Context => SqlStr) extends Expr[T] { def renderToSql0(implicit ctx: Context): SqlStr = f(ctx) } implicit def apply[T]( x: T - )(implicit conv: T => SqlStr.Interp): Db[T] = { + )(implicit conv: T => SqlStr.Interp): Expr[T] = { apply0[T](x)(conv) } def apply0[T]( x: T, exprIsLiteralTrue0: Boolean = false - )(implicit conv: T => SqlStr.Interp): Db[T] = new Db[T] { + )(implicit conv: T => SqlStr.Interp): Expr[T] = new Expr[T] { override def renderToSql0(implicit ctx: Context): SqlStr = - new SqlStr(Array("", ""), Array(conv(x)), false, Array.empty[Db.Identity]) + new SqlStr(Array("", ""), Array(conv(x)), false, Array.empty[Expr.Identity]) protected override def exprIsLiteralTrue = exprIsLiteralTrue0 } diff --git a/scalasql/core/src/JoinNullable.scala b/scalasql/core/src/JoinNullable.scala index 6eeedac3..ba1a2d8a 100644 --- a/scalasql/core/src/JoinNullable.scala +++ b/scalasql/core/src/JoinNullable.scala @@ -1,6 +1,6 @@ package scalasql.core -import scalasql.core.{Queryable, Db, TypeMapper} +import scalasql.core.{Queryable, Expr, TypeMapper} import scalasql.core.Context import scalasql.core.SqlStr.SqlStringSyntax @@ -10,21 +10,21 @@ import scalasql.core.SqlStr.SqlStringSyntax */ trait JoinNullable[Q] { def get: Q - def isEmpty[T](f: Q => Db[T])(implicit qr: Queryable[Q, _]): Db[Boolean] - def nonEmpty[T](f: Q => Db[T])(implicit qr: Queryable[Q, _]): Db[Boolean] + def isEmpty[T](f: Q => Expr[T])(implicit qr: Queryable[Q, _]): Expr[Boolean] + def nonEmpty[T](f: Q => Expr[T])(implicit qr: Queryable[Q, _]): Expr[Boolean] def map[V](f: Q => V): JoinNullable[V] } object JoinNullable { - implicit def toExpr[T](n: JoinNullable[Db[T]])(implicit mt: TypeMapper[T]): Db[Option[T]] = - Db { implicit ctx => sql"${n.get}" } + implicit def toExpr[T](n: JoinNullable[Expr[T]])(implicit mt: TypeMapper[T]): Expr[Option[T]] = + Expr { implicit ctx => sql"${n.get}" } def apply[Q](t: Q): JoinNullable[Q] = new JoinNullable[Q] { def get: Q = t - def isEmpty[T](f: Q => Db[T])(implicit qr: Queryable[Q, _]): Db[Boolean] = Db { implicit ctx => + def isEmpty[T](f: Q => Expr[T])(implicit qr: Queryable[Q, _]): Expr[Boolean] = Expr { implicit ctx => sql"(${f(t)} IS NULL)" } - def nonEmpty[T](f: Q => Db[T])(implicit qr: Queryable[Q, _]): Db[Boolean] = Db { implicit ctx => + def nonEmpty[T](f: Q => Expr[T])(implicit qr: Queryable[Q, _]): Expr[Boolean] = Expr { implicit ctx => sql"(${f(t)} IS NOT NULL)" } def map[V](f: Q => V) = JoinNullable(f(t)) diff --git a/scalasql/core/src/LiveSqlExprs.scala b/scalasql/core/src/LiveSqlExprs.scala index 3d7e4b1c..ade9c9f2 100644 --- a/scalasql/core/src/LiveSqlExprs.scala +++ b/scalasql/core/src/LiveSqlExprs.scala @@ -1,8 +1,8 @@ package scalasql.core /** - * Models a set of live [[Db]] expressions which need to be rendered; - * [[Db]] expressions not in this set can be skipped during rendering + * Models a set of live [[Expr]] expressions which need to be rendered; + * [[Expr]] expressions not in this set can be skipped during rendering * to improve the conciseness of the rendered SQL string. * * - `None` is used to indicate this is a top-level context and we want @@ -19,12 +19,12 @@ package scalasql.core * columns end up being used in the application code after the query has * finished running, and thus have to preserve all of them */ -class LiveSqlExprs(values: Option[Set[Db.Identity]]) { - def map(f: Set[Db.Identity] => Set[Db.Identity]) = new LiveSqlExprs(values.map(f)) - def isLive(e: Db.Identity) = values.fold(true)(_.contains(e)) +class LiveSqlExprs(values: Option[Set[Expr.Identity]]) { + def map(f: Set[Expr.Identity] => Set[Expr.Identity]) = new LiveSqlExprs(values.map(f)) + def isLive(e: Expr.Identity) = values.fold(true)(_.contains(e)) } object LiveSqlExprs { - def some(v: Set[Db.Identity]) = new LiveSqlExprs(Some(v)) + def some(v: Set[Expr.Identity]) = new LiveSqlExprs(Some(v)) def none = new LiveSqlExprs(None) } diff --git a/scalasql/core/src/Queryable.scala b/scalasql/core/src/Queryable.scala index 6a0bcb0b..488f0dcf 100644 --- a/scalasql/core/src/Queryable.scala +++ b/scalasql/core/src/Queryable.scala @@ -31,7 +31,7 @@ trait Queryable[-Q, R] { * Returns a sequence of expressions created by this queryable value. Used to generate * the column list `SELECT` clauses, both for nested and top level `SELECT`s */ - def walkExprs(q: Q): Seq[Db[_]] + def walkExprs(q: Q): Seq[Expr[_]] def walkLabelsAndExprs(q: Q): Queryable.Walked = walkLabels(q).zip(walkExprs(q)) @@ -55,7 +55,7 @@ trait Queryable[-Q, R] { } object Queryable { - type Walked = Seq[(List[String], Db[_])] + type Walked = Seq[(List[String], Expr[_])] class ResultSetIterator(r: ResultSet) { var index = 0 var nulls = 0 @@ -104,7 +104,7 @@ object Queryable { object Row extends scalasql.core.generated.QueryableRow { private[scalasql] class TupleNQueryable[Q, R <: scala.Product]( val walkLabels0: Seq[Seq[List[String]]], - val walkExprs0: Q => Seq[Seq[Db[_]]], + val walkExprs0: Q => Seq[Seq[Expr[_]]], construct0: ResultSetIterator => R, deconstruct0: R => Q ) extends Queryable.Row[Q, R] { diff --git a/scalasql/core/src/SqlExprsToSql.scala b/scalasql/core/src/SqlExprsToSql.scala index a351d52b..cb327442 100644 --- a/scalasql/core/src/SqlExprsToSql.scala +++ b/scalasql/core/src/SqlExprsToSql.scala @@ -8,9 +8,9 @@ object SqlExprsToSql { } def apply0(walked: Queryable.Walked, context: Context, prefix: SqlStr) = { - ColumnNamer.selectColumnSql(walked, context) match { + selectColumnSql(walked, context) match { case Seq((prefix, singleExpr)) - if prefix == context.config.columnLabelDefault && singleExpr.isCompleteQuery => + if prefix == context.config.renderColumnLabel(Nil) && singleExpr.isCompleteQuery => singleExpr case flatQuery => @@ -25,8 +25,20 @@ object SqlExprsToSql { } } - def booleanExprs(prefix: SqlStr, exprs: Seq[Db[_]])(implicit ctx: Context) = { - SqlStr.optSeq(exprs.filter(!Db.isLiteralTrue(_))) { having => + + def selectColumnSql(walked: Queryable.Walked, ctx: Context): Seq[(String, SqlStr)] = { + walked.map { case (k, v) => (ctx.config.renderColumnLabel(k), Renderable.toSql(v)(ctx)) } + } + + def selectColumnReferences(walked: Queryable.Walked, ctx: Context): Seq[(Expr.Identity, SqlStr)] = { + walked.map { case (tokens, expr) => + val dbId = Expr.identity(expr) + (dbId, SqlStr.raw(ctx.config.renderColumnLabel(tokens), Array(dbId))) + } + } + + def booleanExprs(prefix: SqlStr, exprs: Seq[Expr[_]])(implicit ctx: Context) = { + SqlStr.optSeq(exprs.filter(!Expr.isLiteralTrue(_))) { having => prefix + SqlStr.join(having.map(Renderable.toSql(_)), sql" AND ") } } diff --git a/scalasql/core/src/SqlStr.scala b/scalasql/core/src/SqlStr.scala index b28a46a7..3d498b52 100644 --- a/scalasql/core/src/SqlStr.scala +++ b/scalasql/core/src/SqlStr.scala @@ -10,14 +10,14 @@ class SqlStr( private val queryParts: collection.IndexedSeq[String], private val params: collection.IndexedSeq[SqlStr.Interp], val isCompleteQuery: Boolean, - private val referencedExprs: collection.IndexedSeq[Db.Identity] + private val referencedExprs: collection.IndexedSeq[Expr.Identity] ) extends SqlStr.Renderable { def +(other: SqlStr) = { new SqlStr( SqlStr.plusParts, Array[SqlStr.Interp](this, other), false, - Array.empty[Db.Identity] + Array.empty[Expr.Identity] ) } @@ -33,7 +33,7 @@ object SqlStr { val queryParts: collection.IndexedSeq[String], val params: collection.IndexedSeq[Interp.TypeInterp[_]], isCompleteQuery: Boolean, - val referencedExprs: collection.IndexedSeq[Db.Identity] + val referencedExprs: collection.IndexedSeq[Expr.Identity] ) extends SqlStr(queryParts, params, isCompleteQuery, referencedExprs) /** @@ -56,7 +56,7 @@ object SqlStr { // Implement this in a mutable style because`it's pretty performance sensitive val finalParts = collection.mutable.ArrayBuffer.empty[String] val finalArgs = collection.mutable.ArrayBuffer.empty[Interp.TypeInterp[_]] - val finalExprs = collection.mutable.ArrayBuffer.empty[Db.Identity] + val finalExprs = collection.mutable.ArrayBuffer.empty[Expr.Identity] // Equivalent to `finalParts.last`, cached locally for performance var lastFinalPart: String = null @@ -109,7 +109,7 @@ object SqlStr { */ implicit class SqlStringSyntax(sc: StringContext) { def sql(args: Interp*) = - new SqlStr(sc.parts.toIndexedSeq, args.toIndexedSeq, false, Array.empty[Db.Identity]) + new SqlStr(sc.parts.toIndexedSeq, args.toIndexedSeq, false, Array.empty[Expr.Identity]) } /** @@ -126,7 +126,7 @@ object SqlStr { * Converts a raw `String` into a [[SqlStr]]. Note that this must be used * carefully to avoid SQL injection attacks. */ - def raw(s: String, referencedExprs: Array[Db.Identity] = Array.empty) = + def raw(s: String, referencedExprs: Array[Expr.Identity] = Array.empty) = new SqlStr(Array(s), Array.empty[SqlStr.Interp], false, referencedExprs) trait Renderable { diff --git a/scalasql/operations/src/AggNumericOps.scala b/scalasql/operations/src/AggNumericOps.scala index 967e985f..cf63002e 100644 --- a/scalasql/operations/src/AggNumericOps.scala +++ b/scalasql/operations/src/AggNumericOps.scala @@ -1,22 +1,22 @@ package scalasql.operations -import scalasql.core.{Queryable, Db, TypeMapper} +import scalasql.core.{Queryable, Expr, TypeMapper} import scalasql.core.Aggregatable import scalasql.core.SqlStr.SqlStringSyntax -class AggNumericOps[V: Numeric: TypeMapper](v: Aggregatable[Db[V]])( - implicit qr: Queryable.Row[Db[V], V] +class AggNumericOps[V: Numeric: TypeMapper](v: Aggregatable[Expr[V]])( + implicit qr: Queryable.Row[Expr[V], V] ) { /** Computes the sum of column values */ - def sum: Db[V] = v.aggregateExpr(expr => implicit ctx => sql"SUM($expr)") + def sum: Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"SUM($expr)") /** Finds the minimum value in a column */ - def min: Db[V] = v.aggregateExpr(expr => implicit ctx => sql"MIN($expr)") + def min: Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"MIN($expr)") /** Finds the maximum value in a column */ - def max: Db[V] = v.aggregateExpr(expr => implicit ctx => sql"MAX($expr)") + def max: Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"MAX($expr)") /** Computes the average value of a column */ - def avg: Db[V] = v.aggregateExpr(expr => implicit ctx => sql"AVG($expr)") + def avg: Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"AVG($expr)") } diff --git a/scalasql/operations/src/AggOps.scala b/scalasql/operations/src/AggOps.scala index a1ec7b40..5b9becec 100644 --- a/scalasql/operations/src/AggOps.scala +++ b/scalasql/operations/src/AggOps.scala @@ -1,7 +1,7 @@ package scalasql.operations import scalasql.core.DialectTypeMappers -import scalasql.core.{Queryable, TypeMapper, Db} +import scalasql.core.{Queryable, TypeMapper, Expr} import scalasql.core.Aggregatable import scalasql.core.SqlStr.SqlStringSyntax @@ -9,56 +9,56 @@ class AggOps[T](v: Aggregatable[T])(implicit qr: Queryable.Row[T, _], dialect: D import dialect._ /** Counts the rows */ - def size: Db[Int] = v.aggregateExpr(expr => implicit ctx => sql"COUNT(1)") + def size: Expr[Int] = v.aggregateExpr(expr => implicit ctx => sql"COUNT(1)") /** Computes the sum of column values */ - def sumBy[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] = v.aggregateExpr(expr => implicit ctx => sql"SUM(${f(expr)})") + def sumBy[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"SUM(${f(expr)})") /** Finds the minimum value in a column */ - def minBy[V: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] = v.aggregateExpr(expr => implicit ctx => sql"MIN(${f(expr)})") + def minBy[V: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"MIN(${f(expr)})") /** Finds the maximum value in a column */ - def maxBy[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] = v.aggregateExpr(expr => implicit ctx => sql"MAX(${f(expr)})") + def maxBy[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"MAX(${f(expr)})") /** Computes the average value of a column */ - def avgBy[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] = v.aggregateExpr(expr => implicit ctx => sql"AVG(${f(expr)})") + def avgBy[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] = v.aggregateExpr(expr => implicit ctx => sql"AVG(${f(expr)})") /** Computes the sum of column values */ - def sumByOpt[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"SUM(${f(expr)})") + def sumByOpt[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"SUM(${f(expr)})") /** Finds the minimum value in a column */ - def minByOpt[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"MIN(${f(expr)})") + def minByOpt[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"MIN(${f(expr)})") /** Finds the maximum value in a column */ - def maxByOpt[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"MAX(${f(expr)})") + def maxByOpt[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"MAX(${f(expr)})") /** Computes the average value of a column */ - def avgByOpt[V: Numeric: TypeMapper](f: T => Db[V])( - implicit qr: Queryable.Row[Db[V], V] - ): Db[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"AVG(${f(expr)})") + def avgByOpt[V: Numeric: TypeMapper](f: T => Expr[V])( + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[Option[V]] = v.aggregateExpr(expr => implicit ctx => sql"AVG(${f(expr)})") /** TRUE if any value in a set is TRUE */ - def any(f: T => Db[Boolean]): Db[Boolean] = v + def any(f: T => Expr[Boolean]): Expr[Boolean] = v .aggregateExpr(expr => implicit ctx => sql"ANY(${f(expr)})") /** TRUE if all values in a set are TRUE */ - def all(f: T => Db[Boolean]): Db[Boolean] = v + def all(f: T => Expr[Boolean]): Expr[Boolean] = v .aggregateExpr(expr => implicit ctx => sql"ALL(${f(expr)})") /** TRUE if the operand is equal to one of a list of expressions or one or more rows returned by a subquery */ - // def contains(e: Db[_]): Db[Boolean] = v.queryExpr(implicit ctx => sql"ALL($e in $v})") + // def contains(e: Expr[_]): Expr[Boolean] = v.queryExpr(implicit ctx => sql"ALL($e in $v})") } diff --git a/scalasql/operations/src/BitwiseFunctionOps.scala b/scalasql/operations/src/BitwiseFunctionOps.scala index 0a006abc..e4bd16ef 100644 --- a/scalasql/operations/src/BitwiseFunctionOps.scala +++ b/scalasql/operations/src/BitwiseFunctionOps.scala @@ -1,12 +1,12 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax -trait BitwiseFunctionOps[T] extends scalasql.operations.DbNumericOps[T] { - protected def v: Db[T] - override def &[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"BITAND($v, $x)" } +trait BitwiseFunctionOps[T] extends scalasql.operations.ExprNumericOps[T] { + protected def v: Expr[T] + override def &[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"BITAND($v, $x)" } - override def |[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"BITOR($v, $x)" } + override def |[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"BITOR($v, $x)" } - override def unary_~ : Db[T] = Db { implicit ctx => sql"BITNOT($v)" } + override def unary_~ : Expr[T] = Expr { implicit ctx => sql"BITNOT($v)" } } diff --git a/scalasql/operations/src/CaseWhen.scala b/scalasql/operations/src/CaseWhen.scala index e66cfd3a..195de101 100644 --- a/scalasql/operations/src/CaseWhen.scala +++ b/scalasql/operations/src/CaseWhen.scala @@ -1,23 +1,23 @@ package scalasql.operations import scalasql.core.TypeMapper -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr import scalasql.core.SqlStr.SqlStringSyntax import scalasql.core.Context -class CaseWhen[T: TypeMapper](values: Seq[(Db[Boolean], Db[T])]) extends Db[T] { +class CaseWhen[T: TypeMapper](values: Seq[(Expr[Boolean], Expr[T])]) extends Expr[T] { def renderToSql0(implicit ctx: Context): SqlStr = { val whens = CaseWhen.renderWhens(values) sql"CASE $whens END" } - def `else`(other: Db[T]) = new CaseWhen.Else(values, other) + def `else`(other: Expr[T]) = new CaseWhen.Else(values, other) } object CaseWhen { - private def renderWhens[T](values: Seq[(Db[Boolean], Db[T])])(implicit ctx: Context) = SqlStr + private def renderWhens[T](values: Seq[(Expr[Boolean], Expr[T])])(implicit ctx: Context) = SqlStr .join(values.map { case (when, then_) => sql"WHEN $when THEN $then_" }, sql" ") - class Else[T: TypeMapper](values: Seq[(Db[Boolean], Db[T])], `else`: Db[T]) extends Db[T] { + class Else[T: TypeMapper](values: Seq[(Expr[Boolean], Expr[T])], `else`: Expr[T]) extends Expr[T] { def renderToSql0(implicit ctx: Context): SqlStr = { val whens = renderWhens(values) diff --git a/scalasql/operations/src/ConcatOps.scala b/scalasql/operations/src/ConcatOps.scala index 286517c4..5f379ceb 100644 --- a/scalasql/operations/src/ConcatOps.scala +++ b/scalasql/operations/src/ConcatOps.scala @@ -1,5 +1,5 @@ package scalasql.operations -import scalasql.core.{Db, SqlStr} +import scalasql.core.{Expr, SqlStr} import scalasql.core.SqlStr.SqlStringSyntax trait ConcatOps { @@ -7,7 +7,7 @@ trait ConcatOps { /** * Concatenate all arguments. NULL arguments are ignored. */ - def concat(values: Db[_]*): Db[String] = Db { implicit ctx => + def concat(values: Expr[_]*): Expr[String] = Expr { implicit ctx => sql"CONCAT(${SqlStr.join(values.map(v => sql"$v"), SqlStr.commaSep)})" } @@ -15,7 +15,7 @@ trait ConcatOps { * Concatenate all but first arguments with separators. The first parameter is used * as a separator. NULL arguments are ignored. */ - def concatWs(sep: Db[String], values: Db[_]*): Db[String] = Db { implicit ctx => + def concatWs(sep: Expr[String], values: Expr[_]*): Expr[String] = Expr { implicit ctx => sql"CONCAT_WS($sep, ${SqlStr.join(values.map(v => sql"$v"), SqlStr.commaSep)})" } } diff --git a/scalasql/operations/src/DbApiOps.scala b/scalasql/operations/src/DbApiOps.scala index 40c78f3a..b4a9c320 100644 --- a/scalasql/operations/src/DbApiOps.scala +++ b/scalasql/operations/src/DbApiOps.scala @@ -8,7 +8,7 @@ class DbApiOps(dialect: DialectTypeMappers) { /** * Creates a SQL `CASE`/`WHEN`/`ELSE` clause */ - def caseWhen[T: TypeMapper](values: (Db[Boolean], Db[T])*) = + def caseWhen[T: TypeMapper](values: (Expr[Boolean], Expr[T])*) = new scalasql.operations.CaseWhen(values) /** @@ -16,14 +16,14 @@ class DbApiOps(dialect: DialectTypeMappers) { * with gaps. If there is no ORDER BY clause, then all rows are considered peers and * this function always returns 1. */ - def rank(): Db[Int] = Db { implicit ctx => sql"RANK()" } + def rank(): Expr[Int] = Expr { implicit ctx => sql"RANK()" } /** * The number of the row within the current partition. Rows are numbered starting * from 1 in the order defined by the ORDER BY clause in the window definition, or * in arbitrary order otherwise. */ - def rowNumber(): Db[Int] = Db { implicit ctx => sql"ROW_NUMBER()" } + def rowNumber(): Expr[Int] = Expr { implicit ctx => sql"ROW_NUMBER()" } /** * The number of the current row's peer group within its partition - the rank of the @@ -31,7 +31,7 @@ class DbApiOps(dialect: DialectTypeMappers) { * by the ORDER BY clause in the window definition. If there is no ORDER BY clause, * then all rows are considered peers and this function always returns 1. */ - def denseRank(): Db[Int] = Db { implicit ctx => sql"DENSE_RANK()" } + def denseRank(): Expr[Int] = Expr { implicit ctx => sql"DENSE_RANK()" } /** * Despite the name, this function always returns a value between 0.0 and 1.0 equal to @@ -39,14 +39,14 @@ class DbApiOps(dialect: DialectTypeMappers) { * function rank() and partition-rows is the total number of rows in the partition. If * the partition contains only one row, this function returns 0.0. */ - def percentRank(): Db[Double] = Db { implicit ctx => sql"PERCENT_RANK()" } + def percentRank(): Expr[Double] = Expr { implicit ctx => sql"PERCENT_RANK()" } /** * The cumulative distribution. Calculated as row-number/partition-rows, where row-number * is the value returned by row_number() for the last peer in the group and partition-rows * the number of rows in the partition. */ - def cumeDist(): Db[Double] = Db { implicit ctx => sql"CUME_DIST()" } + def cumeDist(): Expr[Double] = Expr { implicit ctx => sql"CUME_DIST()" } /** * Argument N is handled as an integer. This function divides the partition into N groups @@ -55,10 +55,10 @@ class DbApiOps(dialect: DialectTypeMappers) { * groups occur first. This function returns the integer value assigned to the group that * the current row is a part of. */ - def ntile(n: Int): Db[Int] = Db { implicit ctx => sql"NTILE($n)" } + def ntile(n: Int): Expr[Int] = Expr { implicit ctx => sql"NTILE($n)" } - private def lagLead[T](prefix: SqlStr, e: Db[T], offset: Int, default: Db[T]): Db[T] = - Db { implicit ctx => + private def lagLead[T](prefix: SqlStr, e: Expr[T], offset: Int, default: Expr[T]): Expr[T] = + Expr { implicit ctx => val args = SqlStr.join( Seq( Some(sql"$e"), @@ -85,7 +85,7 @@ class DbApiOps(dialect: DialectTypeMappers) { * If default is also provided, then it is returned instead of NULL if the row identified * by offset does not exist. */ - def lag[T](e: Db[T], offset: Int = -1, default: Db[T] = null): Db[T] = + def lag[T](e: Expr[T], offset: Int = -1, default: Expr[T] = null): Expr[T] = lagLead(sql"LAG", e, offset, default) /** @@ -102,7 +102,7 @@ class DbApiOps(dialect: DialectTypeMappers) { * If default is also provided, then it is returned instead of NULL if the row identified * by offset does not exist. */ - def lead[T](e: Db[T], offset: Int = -1, default: Db[T] = null): Db[T] = + def lead[T](e: Expr[T], offset: Int = -1, default: Expr[T] = null): Expr[T] = lagLead(sql"LEAD", e, offset, default) /** @@ -110,14 +110,14 @@ class DbApiOps(dialect: DialectTypeMappers) { * function. It returns the value of expr evaluated against the first row in the window * frame for each row. */ - def firstValue[T](e: Db[T]): Db[T] = Db { implicit ctx => sql"FIRST_VALUE($e)" } + def firstValue[T](e: Expr[T]): Expr[T] = Expr { implicit ctx => sql"FIRST_VALUE($e)" } /** * Calculates the window frame for each row in the same way as an aggregate window * function. It returns the value of expr evaluated against the last row in the window * frame for each row. */ - def lastValue[T](e: Db[T]): Db[T] = Db { implicit ctx => sql"LAST_VALUE($e)" } + def lastValue[T](e: Expr[T]): Expr[T] = Expr { implicit ctx => sql"LAST_VALUE($e)" } /** * Calculates the window frame for each row in the same way as an aggregate window @@ -126,6 +126,6 @@ class DbApiOps(dialect: DialectTypeMappers) { * defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. * If there is no Nth row in the partition, then NULL is returned. */ - def nthValue[T](e: Db[T], n: Int): Db[T] = Db { implicit ctx => sql"NTH_VALUE($e, $n)" } + def nthValue[T](e: Expr[T], n: Int): Expr[T] = Expr { implicit ctx => sql"NTH_VALUE($e, $n)" } } diff --git a/scalasql/operations/src/DbBooleanOps.scala b/scalasql/operations/src/DbBooleanOps.scala deleted file mode 100644 index 806a27dc..00000000 --- a/scalasql/operations/src/DbBooleanOps.scala +++ /dev/null @@ -1,16 +0,0 @@ -package scalasql.operations - -import scalasql.core.Db -import scalasql.core.SqlStr.SqlStringSyntax - -class DbBooleanOps(v: Db[Boolean]) { - - /** TRUE if both Boolean expressions are TRUE */ - def &&(x: Db[Boolean]): Db[Boolean] = Db { implicit ctx => sql"($v AND $x)" } - - /** TRUE if either Boolean expression is TRUE */ - def ||(x: Db[Boolean]): Db[Boolean] = Db { implicit ctx => sql"($v OR $x)" } - - /** Reverses the value of any other Boolean operator */ - def unary_! : Db[Boolean] = Db { implicit ctx => sql"(NOT $v)" } -} diff --git a/scalasql/operations/src/DbNumericOps.scala b/scalasql/operations/src/DbNumericOps.scala deleted file mode 100644 index 0bfb141b..00000000 --- a/scalasql/operations/src/DbNumericOps.scala +++ /dev/null @@ -1,66 +0,0 @@ -package scalasql.operations - -import scalasql.core.TypeMapper -import scalasql.core.Db -import scalasql.core.SqlStr.SqlStringSyntax - -class DbNumericOps[T: Numeric](v: Db[T])(implicit val m: TypeMapper[T]) { - - /** Addition */ - def +[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v + $x)" } - - /** Subtraction */ - def -[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v - $x)" } - - /** Multiplication */ - def *[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v * $x)" } - - /** Division */ - def /[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v / $x)" } - - /** Remainder */ - def %[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"MOD($v, $x)" } - - /** Bitwise AND */ - def &[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v & $x)" } - - /** Bitwise OR */ - def |[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v | $x)" } - - /** Bitwise XOR */ - def ^[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"($v ^ $x)" } - - /** TRUE if the operand is within a range */ - def between(x: Db[Int], y: Db[Int]): Db[Boolean] = Db { implicit ctx => - sql"$v BETWEEN $x AND $y" - } - - /** Unary Positive Operator */ - def unary_+ : Db[T] = Db { implicit ctx => sql"+$v" } - - /** Unary Negation Operator */ - def unary_- : Db[T] = Db { implicit ctx => sql"-$v" } - - /** Unary Bitwise NOT Operator */ - def unary_~ : Db[T] = Db { implicit ctx => sql"~$v" } - - /** Returns the absolute value of a number. */ - def abs: Db[T] = Db { implicit ctx => sql"ABS($v)" } - - /** Returns the remainder of one number divided into another. */ - def mod[V: Numeric](x: Db[V]): Db[T] = Db { implicit ctx => sql"MOD($v, $x)" } - - /** Rounds a noninteger value upwards to the next greatest integer. Returns an integer value unchanged. */ - def ceil: Db[T] = Db { implicit ctx => sql"CEIL($v)" } - - /** Rounds a noninteger value downwards to the next least integer. Returns an integer value unchanged. */ - def floor: Db[T] = Db { implicit ctx => sql"FLOOR($v)" } - - /** - * The sign(X) function returns -1, 0, or +1 if the argument X is a numeric - * value that is negative, zero, or positive, respectively. If the argument to sign(X) - * is NULL or is a string or blob that cannot be losslessly converted into a number, - * then sign(X) returns NULL. - */ - def sign: Db[T] = Db { implicit ctx => sql"SIGN($v)" } -} diff --git a/scalasql/operations/src/DbOptionOps.scala b/scalasql/operations/src/DbOptionOps.scala deleted file mode 100644 index f52f1408..00000000 --- a/scalasql/operations/src/DbOptionOps.scala +++ /dev/null @@ -1,40 +0,0 @@ -package scalasql.operations - -import scalasql.core.TypeMapper -import scalasql.core.DialectTypeMappers -import scalasql.core.Db -import scalasql.core.Context -import scalasql.core.SqlStr.SqlStringSyntax - -class DbOptionOps[T: TypeMapper](v: Db[Option[T]])(implicit dialect: DialectTypeMappers) { - import dialect._ - - def isDefined: Db[Boolean] = Db { implicit ctx => sql"($v IS NOT NULL)" } - - def isEmpty: Db[Boolean] = Db { implicit ctx => sql"($v IS NULL)" } - - // SQL nulls tend to propagate automatically, so we do not need to explicitly - // generate CASE/WHEN/THEN/ELSE syntax and can just use the final expression directly - // and assume the nulls will propagate as necessary - def map[V: TypeMapper](f: Db[T] => Db[V]): Db[Option[V]] = Db { implicit ctx => - sql"${f(v.asInstanceOf[Db[T]])}" - } - - def flatMap[V: TypeMapper](f: Db[T] => Db[Option[V]]): Db[Option[V]] = - Db { implicit ctx => sql"${f(v.asInstanceOf[Db[T]])}" } - - def get: Db[T] = Db[T] { implicit ctx: Context => sql"$v" } - - def getOrElse(other: Db[T]): Db[T] = Db[T] { implicit ctx: Context => - sql"COALESCE($v, $other)" - } - - def orElse(other: Db[Option[T]]): Db[Option[T]] = Db[T] { implicit ctx: Context => - sql"COALESCE($v, $other)" - } - - def filter(other: Db[T] => Db[Boolean]): Db[Option[T]] = new CaseWhen.Else[Option[T]]( - Seq(other(Db[T] { implicit ctx: Context => sql"$v" }) -> v), - Db { implicit ctx => sql"NULL" } - ) -} diff --git a/scalasql/operations/src/DbAggOps.scala b/scalasql/operations/src/ExprAggOps.scala similarity index 51% rename from scalasql/operations/src/DbAggOps.scala rename to scalasql/operations/src/ExprAggOps.scala index 86689c40..3151f5ef 100644 --- a/scalasql/operations/src/DbAggOps.scala +++ b/scalasql/operations/src/ExprAggOps.scala @@ -2,13 +2,13 @@ package scalasql.operations import scalasql.core.Aggregatable import scalasql.core.SqlStr.SqlStringSyntax -import scalasql.core.{Queryable, TypeMapper, Db} +import scalasql.core.{Queryable, TypeMapper, Expr} -abstract class DbAggOps[T](v: Aggregatable[Db[T]]) { +abstract class ExprAggOps[T](v: Aggregatable[Expr[T]]) { /** Concatenates the given values into one string using the given separator */ - def mkString(sep: Db[String] = null)(implicit tm: TypeMapper[T]): Db[String] + def mkString(sep: Expr[String] = null)(implicit tm: TypeMapper[T]): Expr[String] /** TRUE if the operand is equal to one of a list of expressions or one or more rows returned by a subquery */ - // def contains(e: Db[_]): Db[Boolean] = v.queryExpr(implicit ctx => sql"ALL($e in $v})") + // def contains(e: Expr[_]): Expr[Boolean] = v.queryExpr(implicit ctx => sql"ALL($e in $v})") } diff --git a/scalasql/operations/src/ExprBooleanOps.scala b/scalasql/operations/src/ExprBooleanOps.scala new file mode 100644 index 00000000..64d57806 --- /dev/null +++ b/scalasql/operations/src/ExprBooleanOps.scala @@ -0,0 +1,16 @@ +package scalasql.operations + +import scalasql.core.Expr +import scalasql.core.SqlStr.SqlStringSyntax + +class ExprBooleanOps(v: Expr[Boolean]) { + + /** TRUE if both Boolean expressions are TRUE */ + def &&(x: Expr[Boolean]): Expr[Boolean] = Expr { implicit ctx => sql"($v AND $x)" } + + /** TRUE if either Boolean expression is TRUE */ + def ||(x: Expr[Boolean]): Expr[Boolean] = Expr { implicit ctx => sql"($v OR $x)" } + + /** Reverses the value of any other Boolean operator */ + def unary_! : Expr[Boolean] = Expr { implicit ctx => sql"(NOT $v)" } +} diff --git a/scalasql/operations/src/ExprNumericOps.scala b/scalasql/operations/src/ExprNumericOps.scala new file mode 100644 index 00000000..5c9a4bc7 --- /dev/null +++ b/scalasql/operations/src/ExprNumericOps.scala @@ -0,0 +1,66 @@ +package scalasql.operations + +import scalasql.core.TypeMapper +import scalasql.core.Expr +import scalasql.core.SqlStr.SqlStringSyntax + +class ExprNumericOps[T: Numeric](v: Expr[T])(implicit val m: TypeMapper[T]) { + + /** Addition */ + def +[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v + $x)" } + + /** Subtraction */ + def -[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v - $x)" } + + /** Multiplication */ + def *[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v * $x)" } + + /** Division */ + def /[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v / $x)" } + + /** Remainder */ + def %[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"MOD($v, $x)" } + + /** Bitwise AND */ + def &[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v & $x)" } + + /** Bitwise OR */ + def |[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v | $x)" } + + /** Bitwise XOR */ + def ^[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"($v ^ $x)" } + + /** TRUE if the operand is within a range */ + def between(x: Expr[Int], y: Expr[Int]): Expr[Boolean] = Expr { implicit ctx => + sql"$v BETWEEN $x AND $y" + } + + /** Unary Positive Operator */ + def unary_+ : Expr[T] = Expr { implicit ctx => sql"+$v" } + + /** Unary Negation Operator */ + def unary_- : Expr[T] = Expr { implicit ctx => sql"-$v" } + + /** Unary Bitwise NOT Operator */ + def unary_~ : Expr[T] = Expr { implicit ctx => sql"~$v" } + + /** Returns the absolute value of a number. */ + def abs: Expr[T] = Expr { implicit ctx => sql"ABS($v)" } + + /** Returns the remainder of one number divided into another. */ + def mod[V: Numeric](x: Expr[V]): Expr[T] = Expr { implicit ctx => sql"MOD($v, $x)" } + + /** Rounds a noninteger value upwards to the next greatest integer. Returns an integer value unchanged. */ + def ceil: Expr[T] = Expr { implicit ctx => sql"CEIL($v)" } + + /** Rounds a noninteger value downwards to the next least integer. Returns an integer value unchanged. */ + def floor: Expr[T] = Expr { implicit ctx => sql"FLOOR($v)" } + + /** + * The sign(X) function returns -1, 0, or +1 if the argument X is a numeric + * value that is negative, zero, or positive, respectively. If the argument to sign(X) + * is NULL or is a string or blob that cannot be losslessly converted into a number, + * then sign(X) returns NULL. + */ + def sign: Expr[T] = Expr { implicit ctx => sql"SIGN($v)" } +} diff --git a/scalasql/operations/src/DbOps.scala b/scalasql/operations/src/ExprOps.scala similarity index 53% rename from scalasql/operations/src/DbOps.scala rename to scalasql/operations/src/ExprOps.scala index 9d42521c..cc29ded2 100644 --- a/scalasql/operations/src/DbOps.scala +++ b/scalasql/operations/src/ExprOps.scala @@ -1,36 +1,36 @@ package scalasql.operations import scalasql.core.TypeMapper -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr import scalasql.core.SqlStr.SqlStringSyntax -class DbOps(v: Db[_]) { +class ExprOps(v: Expr[_]) { /** * SQL-style Equals to, translates to SQL `=`. Returns `false` if both values are `NULL` */ - def `=`[T](x: Db[T]): Db[Boolean] = Db { implicit ctx => sql"($v = $x)" } + def `=`[T](x: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v = $x)" } /** * SQL-style Not equals to, translates to SQL `<>`. Returns `false` if both values are `NULL` */ - def <>[T](x: Db[T]): Db[Boolean] = Db { implicit ctx => sql"($v <> $x)" } + def <>[T](x: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v <> $x)" } /** Greater than */ - def >[V](x: Db[V]): Db[Boolean] = Db { implicit ctx => sql"($v > $x)" } + def >[V](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => sql"($v > $x)" } /** Less than */ - def <[V](x: Db[V]): Db[Boolean] = Db { implicit ctx => sql"($v < $x)" } + def <[V](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => sql"($v < $x)" } /** Greater than or equal to */ - def >=[V](x: Db[V]): Db[Boolean] = Db { implicit ctx => sql"($v >= $x)" } + def >=[V](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => sql"($v >= $x)" } /** Less than or equal to */ - def <=[V](x: Db[V]): Db[Boolean] = Db { implicit ctx => sql"($v <= $x)" } + def <=[V](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => sql"($v <= $x)" } /** Translates to a SQL `CAST` from one type to another */ - def cast[V: TypeMapper]: Db[V] = Db { implicit ctx => + def cast[V: TypeMapper]: Expr[V] = Expr { implicit ctx => sql"CAST($v AS ${SqlStr.raw(implicitly[TypeMapper[V]].castTypeString)})" } @@ -38,7 +38,7 @@ class DbOps(v: Db[_]) { * Similar to [[cast]], but allows you to pass in an explicit [[SqlStr]] to * further specify the SQL type you want to cast to */ - def castNamed[V: TypeMapper](typeName: SqlStr): Db[V] = Db { implicit ctx => + def castNamed[V: TypeMapper](typeName: SqlStr): Expr[V] = Expr { implicit ctx => sql"CAST($v AS $typeName)" } } diff --git a/scalasql/operations/src/ExprOptionOps.scala b/scalasql/operations/src/ExprOptionOps.scala new file mode 100644 index 00000000..5420d955 --- /dev/null +++ b/scalasql/operations/src/ExprOptionOps.scala @@ -0,0 +1,40 @@ +package scalasql.operations + +import scalasql.core.TypeMapper +import scalasql.core.DialectTypeMappers +import scalasql.core.Expr +import scalasql.core.Context +import scalasql.core.SqlStr.SqlStringSyntax + +class ExprOptionOps[T: TypeMapper](v: Expr[Option[T]])(implicit dialect: DialectTypeMappers) { + import dialect._ + + def isDefined: Expr[Boolean] = Expr { implicit ctx => sql"($v IS NOT NULL)" } + + def isEmpty: Expr[Boolean] = Expr { implicit ctx => sql"($v IS NULL)" } + + // SQL nulls tend to propagate automatically, so we do not need to explicitly + // generate CASE/WHEN/THEN/ELSE syntax and can just use the final expression directly + // and assume the nulls will propagate as necessary + def map[V: TypeMapper](f: Expr[T] => Expr[V]): Expr[Option[V]] = Expr { implicit ctx => + sql"${f(v.asInstanceOf[Expr[T]])}" + } + + def flatMap[V: TypeMapper](f: Expr[T] => Expr[Option[V]]): Expr[Option[V]] = + Expr { implicit ctx => sql"${f(v.asInstanceOf[Expr[T]])}" } + + def get: Expr[T] = Expr[T] { implicit ctx: Context => sql"$v" } + + def getOrElse(other: Expr[T]): Expr[T] = Expr[T] { implicit ctx: Context => + sql"COALESCE($v, $other)" + } + + def orElse(other: Expr[Option[T]]): Expr[Option[T]] = Expr[T] { implicit ctx: Context => + sql"COALESCE($v, $other)" + } + + def filter(other: Expr[T] => Expr[Boolean]): Expr[Option[T]] = new CaseWhen.Else[Option[T]]( + Seq(other(Expr[T] { implicit ctx: Context => sql"$v" }) -> v), + Expr { implicit ctx => sql"NULL" } + ) +} diff --git a/scalasql/operations/src/DbStringLikeOps.scala b/scalasql/operations/src/ExprStringLikeOps.scala similarity index 51% rename from scalasql/operations/src/DbStringLikeOps.scala rename to scalasql/operations/src/ExprStringLikeOps.scala index fe86bbb4..c2aad1f6 100644 --- a/scalasql/operations/src/DbStringLikeOps.scala +++ b/scalasql/operations/src/ExprStringLikeOps.scala @@ -1,47 +1,47 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax -abstract class DbStringLikeOps[T](v: Db[T]) { +abstract class ExprStringLikeOps[T](v: Expr[T]) { /** Concatenates two strings */ - def +(x: Db[T]): Db[T] = Db { implicit ctx => sql"($v || $x)" } + def +(x: Expr[T]): Expr[T] = Expr { implicit ctx => sql"($v || $x)" } /** TRUE if the operand matches a pattern */ - def like(x: Db[T]): Db[Boolean] = Db { implicit ctx => sql"($v LIKE $x)" } + def like(x: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE $x)" } /** Returns an integer value representing the starting position of a string within the search string. */ - def indexOf(x: Db[T]): Db[Int] + def indexOf(x: Expr[T]): Expr[Int] /** Converts a string to all lowercase characters. */ - def toLowerCase: Db[T] = Db { implicit ctx => sql"LOWER($v)" } + def toLowerCase: Expr[T] = Expr { implicit ctx => sql"LOWER($v)" } /** Converts a string to all uppercase characters. */ - def toUpperCase: Db[T] = Db { implicit ctx => sql"UPPER($v)" } + def toUpperCase: Expr[T] = Expr { implicit ctx => sql"UPPER($v)" } /** Returns the number of characters in this string */ - def length: Db[Int] = Db { implicit ctx => sql"LENGTH($v)" } + def length: Expr[Int] = Expr { implicit ctx => sql"LENGTH($v)" } /** Returns the number of bytes in this string */ - def octetLength: Db[Int] = Db { implicit ctx => sql"OCTET_LENGTH($v)" } + def octetLength: Expr[Int] = Expr { implicit ctx => sql"OCTET_LENGTH($v)" } /** Returns a portion of a string. */ - def substring(start: Db[Int], length: Db[Int]): Db[T] = Db { implicit ctx => + def substring(start: Expr[Int], length: Expr[Int]): Expr[T] = Expr { implicit ctx => sql"SUBSTRING($v, $start, $length)" } /** Returns whether or not this strings starts with the other. */ - def startsWith(other: Db[T]): Db[Boolean] = Db { implicit ctx => + def startsWith(other: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE $other || '%')" } /** Returns whether or not this strings ends with the other. */ - def endsWith(other: Db[T]): Db[Boolean] = Db { implicit ctx => + def endsWith(other: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE '%' || $other)" } /** Returns whether or not this strings contains the other. */ - def contains(other: Db[T]): Db[Boolean] = Db { implicit ctx => + def contains(other: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE '%' || $other || '%')" } diff --git a/scalasql/operations/src/DbStringOps.scala b/scalasql/operations/src/ExprStringOps.scala similarity index 59% rename from scalasql/operations/src/DbStringOps.scala rename to scalasql/operations/src/ExprStringOps.scala index 27d49f78..d7bd8788 100644 --- a/scalasql/operations/src/DbStringOps.scala +++ b/scalasql/operations/src/ExprStringOps.scala @@ -1,25 +1,25 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax -trait DbStringOps[T] { - protected def v: Db[T] +trait ExprStringOps[T] { + protected def v: Expr[T] /** Removes leading and trailing whitespace characters from a character string. */ - def trim: Db[T] = Db { implicit ctx => sql"TRIM($v)" } + def trim: Expr[T] = Expr { implicit ctx => sql"TRIM($v)" } /** Removes leading whitespace characters from a character string. */ - def ltrim: Db[T] = Db { implicit ctx => sql"LTRIM($v)" } + def ltrim: Expr[T] = Expr { implicit ctx => sql"LTRIM($v)" } /** Removes trailing whitespace characters from a character string. */ - def rtrim: Db[T] = Db { implicit ctx => sql"RTRIM($v)" } + def rtrim: Expr[T] = Expr { implicit ctx => sql"RTRIM($v)" } /** * The replace(X,Y,Z) function returns a string formed by substituting string Z * for every occurrence of string Y in string X */ - def replace(y: Db[T], z: Db[T]): Db[T] = Db { implicit ctx => + def replace(y: Expr[T], z: Expr[T]): Expr[T] = Expr { implicit ctx => sql"REPLACE($v, $y, $z)" } diff --git a/scalasql/operations/src/DbTypedOps.scala b/scalasql/operations/src/ExprTypedOps.scala similarity index 79% rename from scalasql/operations/src/DbTypedOps.scala rename to scalasql/operations/src/ExprTypedOps.scala index dbe6dc4d..b6b9bee2 100644 --- a/scalasql/operations/src/DbTypedOps.scala +++ b/scalasql/operations/src/ExprTypedOps.scala @@ -1,11 +1,11 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax import scala.reflect.ClassTag -class DbTypedOps[T: ClassTag](v: Db[T]) { +class ExprTypedOps[T: ClassTag](v: Expr[T]) { protected def isNullable[T: ClassTag] = implicitly[ClassTag[T]].runtimeClass == classOf[Option[_]] @@ -14,7 +14,7 @@ class DbTypedOps[T: ClassTag](v: Db[T]) { * Translates to `IS NOT DISTINCT FROM` if both values are nullable, * otherwise translates to `=` */ - def ===[V: ClassTag](x: Db[V]): Db[Boolean] = Db { implicit ctx => + def ===[V: ClassTag](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => (isNullable[T], isNullable[V]) match { case (true, true) => sql"($v IS NOT DISTINCT FROM $x)" case _ => sql"($v = $x)" @@ -26,7 +26,7 @@ class DbTypedOps[T: ClassTag](v: Db[T]) { * Translates to `IS DISTINCT FROM` if both values are nullable, * otherwise translates to `<>` */ - def !==[V: ClassTag](x: Db[V]): Db[Boolean] = Db { implicit ctx => + def !==[V: ClassTag](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => (isNullable[T], isNullable[V]) match { case (true, true) => sql"($v IS DISTINCT FROM $x)" case _ => sql"($v <> $x)" diff --git a/scalasql/operations/src/HyperbolicMathOps.scala b/scalasql/operations/src/HyperbolicMathOps.scala index c66de680..e5367f78 100644 --- a/scalasql/operations/src/HyperbolicMathOps.scala +++ b/scalasql/operations/src/HyperbolicMathOps.scala @@ -1,15 +1,15 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax trait HyperbolicMathOps { /** Calculate the hyperbolic sine */ - def sinh[T: Numeric](v: Db[T]): Db[T] = Db { implicit ctx => sql"SINH($v)" } + def sinh[T: Numeric](v: Expr[T]): Expr[T] = Expr { implicit ctx => sql"SINH($v)" } /** Calculate the hyperbolic cosine */ - def cosh[T: Numeric](v: Db[T]): Db[T] = Db { implicit ctx => sql"COSH($v)" } + def cosh[T: Numeric](v: Expr[T]): Expr[T] = Expr { implicit ctx => sql"COSH($v)" } /** Calculate the hyperbolic tangent */ - def tanh[T: Numeric](v: Db[T]): Db[T] = Db { implicit ctx => sql"TANH($v)" } + def tanh[T: Numeric](v: Expr[T]): Expr[T] = Expr { implicit ctx => sql"TANH($v)" } } diff --git a/scalasql/operations/src/MathOps.scala b/scalasql/operations/src/MathOps.scala index 21200f47..5964c52c 100644 --- a/scalasql/operations/src/MathOps.scala +++ b/scalasql/operations/src/MathOps.scala @@ -1,55 +1,55 @@ package scalasql.operations import scalasql.core.SqlStr.SqlStringSyntax -import scalasql.core.{Db, SqlStr} +import scalasql.core.{Expr, SqlStr} trait MathOps { /** Converts radians to degrees */ - def degrees[T: Numeric](x: Db[T]): Db[Double] = Db { implicit ctx => sql"DEGREES($x)" } + def degrees[T: Numeric](x: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"DEGREES($x)" } /** Converts degrees to radians */ - def radians[T: Numeric](x: Db[T]): Db[Double] = Db { implicit ctx => sql"RADIANS($x)" } + def radians[T: Numeric](x: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"RADIANS($x)" } /** `x` raised to the power of `y` */ - def power[T: Numeric](x: Db[T], y: Db[T]): Db[Double] = Db { implicit ctx => sql"POWER($x, $y)" } + def power[T: Numeric](x: Expr[T], y: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"POWER($x, $y)" } /** Raises a value to the power of the mathematical constant known as e. */ - def exp[T: Numeric](x: Db[T]): Db[Double] = Db { implicit ctx => sql"EXP($x)" } + def exp[T: Numeric](x: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"EXP($x)" } /** Returns the natural logarithm of a number. */ - def ln[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"LN($v)" } + def ln[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"LN($v)" } /** Logarithm of x to base b */ - def log[T: Numeric](b: Db[Int], x: Db[T]): Db[Double] = Db { implicit ctx => sql"LOG($b, $x)" } + def log[T: Numeric](b: Expr[Int], x: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"LOG($b, $x)" } /** Base 10 logarithm */ - def log10[T: Numeric](x: Db[T]): Db[Double] = Db { implicit ctx => sql"LOG10($x)" } + def log10[T: Numeric](x: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"LOG10($x)" } /** Computes the square root of a number. */ - def sqrt[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"SQRT($v)" } + def sqrt[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"SQRT($v)" } /** Calculate the trigonometric sine */ - def sin[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"SIN($v)" } + def sin[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"SIN($v)" } /** Calculate the trigonometric cosine */ - def cos[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"COS($v)" } + def cos[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"COS($v)" } /** Calculate the trigonometric tangent */ - def tan[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"TAN($v)" } + def tan[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"TAN($v)" } /** Calculate the arc sine */ - def asin[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"ASIN($v)" } + def asin[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"ASIN($v)" } /** Calculate the arc cosine */ - def acos[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"ACOS($v)" } + def acos[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"ACOS($v)" } /** Calculate the arc tangent */ - def atan[T: Numeric](v: Db[T]): Db[Double] = Db { implicit ctx => sql"ATAN($v)" } + def atan[T: Numeric](v: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"ATAN($v)" } /** Calculate the arc tangent */ - def atan2[T: Numeric](v: Db[T], y: Db[T]): Db[Double] = Db { implicit ctx => sql"ATAN2($v, $y)" } + def atan2[T: Numeric](v: Expr[T], y: Expr[T]): Expr[Double] = Expr { implicit ctx => sql"ATAN2($v, $y)" } /** Returns the value of Pi */ - def pi: Db[Double] = Db { implicit ctx => sql"PI()" } + def pi: Expr[Double] = Expr { implicit ctx => sql"PI()" } } diff --git a/scalasql/operations/src/PadOps.scala b/scalasql/operations/src/PadOps.scala index eb83dea5..e8cd41e5 100644 --- a/scalasql/operations/src/PadOps.scala +++ b/scalasql/operations/src/PadOps.scala @@ -1,15 +1,15 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax trait PadOps { - protected def v: Db[_] + protected def v: Expr[_] - def rpad(length: Db[Int], fill: Db[String]): Db[String] = Db { implicit ctx => + def rpad(length: Expr[Int], fill: Expr[String]): Expr[String] = Expr { implicit ctx => sql"RPAD($v, $length, $fill)" } - def lpad(length: Db[Int], fill: Db[String]): Db[String] = Db { implicit ctx => + def lpad(length: Expr[Int], fill: Expr[String]): Expr[String] = Expr { implicit ctx => sql"LPAD($v, $length, $fill)" } } diff --git a/scalasql/operations/src/TrimOps.scala b/scalasql/operations/src/TrimOps.scala index 75581e38..1a0e7463 100644 --- a/scalasql/operations/src/TrimOps.scala +++ b/scalasql/operations/src/TrimOps.scala @@ -1,17 +1,17 @@ package scalasql.operations -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax trait TrimOps { - protected def v: Db[_] + protected def v: Expr[_] /** * Trim [[x]]s from the left hand side of the string [[v]] */ - def ltrim(x: Db[String]): Db[String] = Db { implicit ctx => sql"LTRIM($v, $x)" } + def ltrim(x: Expr[String]): Expr[String] = Expr { implicit ctx => sql"LTRIM($v, $x)" } /** * Trim [[x]]s from the right hand side of the string [[v]] */ - def rtrim(x: Db[String]): Db[String] = Db { implicit ctx => sql"RTRIM($v, $x)" } + def rtrim(x: Expr[String]): Expr[String] = Expr { implicit ctx => sql"RTRIM($v, $x)" } } diff --git a/scalasql/query/src-2/TableMacro.scala b/scalasql/query/src-2/TableMacro.scala index 813a9013..c17cdf05 100644 --- a/scalasql/query/src-2/TableMacro.scala +++ b/scalasql/query/src-2/TableMacro.scala @@ -4,8 +4,7 @@ import scalasql.core.Sc import scala.language.experimental.macros object TableMacros { - type Db[T] = scalasql.core.Db[T] - def cast[T](x: Any): T = x.asInstanceOf[T] + type Expr[T] = scalasql.core.Expr[T] def applyImpl[V[_[_]]]( c: scala.reflect.macros.blackbox.Context )(implicit caseClassType: c.WeakTypeTag[V[Any]]): c.Expr[Table.Metadata[V]] = { @@ -50,19 +49,19 @@ object TableMacros { val queryables = for (param <- constructorParameters) yield { val tpe = subParam(param.info, typeOf[Sc[_]]) - val tpe2 = subParam(param.info, typeOf[Db[_]]) + val tpe2 = subParam(param.info, typeOf[TableMacros.Expr[_]]) q"implicitly[_root_.scalasql.Queryable.Row[$tpe2, $tpe]]" } val constructParams = for ((param, i) <- constructorParameters.zipWithIndex) yield { val tpe = subParam(param.info, typeOf[Sc[_]]) - val tpe2 = subParam(param.info, typeOf[Db[_]]) + val tpe2 = subParam(param.info, typeOf[TableMacros.Expr[_]]) q"queryable[$tpe2, $tpe]($i).construct(args): _root_.scalasql.Sc[$tpe]" } val deconstructParams = for ((param, i) <- constructorParameters.zipWithIndex) yield { val tpe = subParam(param.info, typeOf[Sc[_]]) - val tpe2 = subParam(param.info, typeOf[Db[_]]) + val tpe2 = subParam(param.info, typeOf[TableMacros.Expr[_]]) q"queryable[$tpe2, $tpe]($i).deconstruct(r.${TermName(param.name.toString)})" } @@ -77,7 +76,7 @@ object TableMacros { val flattenExprs = for ((param, i) <- constructorParameters.zipWithIndex) yield { val tpe = subParam(param.info, typeOf[Sc[_]]) - val tpe2 = subParam(param.info, typeOf[Db[_]]) + val tpe2 = subParam(param.info, typeOf[TableMacros.Expr[_]]) q"queryable[$tpe2, $tpe]($i).walkExprs(table.${TermName(param.name.toString)})" } @@ -86,7 +85,7 @@ object TableMacros { val exprRef = TypeRef( pre = typeRef.pre, sym = typeRef.sym, - args = weakTypeOf[V[scalasql.core.Db]].typeArgs + args = weakTypeOf[V[TableMacros.Expr]].typeArgs ) val idRef = TypeRef( pre = typeRef.pre, diff --git a/scalasql/query/src/Aggregate.scala b/scalasql/query/src/Aggregate.scala index 2c637721..0f99424c 100644 --- a/scalasql/query/src/Aggregate.scala +++ b/scalasql/query/src/Aggregate.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{Queryable, Db, SqlStr, TypeMapper, Context} +import scalasql.core.{Queryable, Expr, SqlStr, TypeMapper, Context} class Aggregate[Q, R]( toSqlStr0: Context => SqlStr, diff --git a/scalasql/query/src/Column.scala b/scalasql/query/src/Column.scala index aef4086a..1fa5f1d6 100644 --- a/scalasql/query/src/Column.scala +++ b/scalasql/query/src/Column.scala @@ -1,15 +1,15 @@ package scalasql.query -import scalasql.core.{Context, Db, SqlStr, TypeMapper} +import scalasql.core.{Context, Expr, SqlStr, TypeMapper} import scalasql.core.SqlStr.SqlStringSyntax /** - * A variant of [[Db]] representing a raw table column; allows assignment in updates + * A variant of [[Expr]] representing a raw table column; allows assignment in updates * and inserts */ class Column[T](tableRef: TableRef, val name: String)(implicit val mappedType: TypeMapper[T]) - extends Db[T] { - def :=(v: Db[T]) = Column.Assignment(this, v) + extends Expr[T] { + def :=(v: Expr[T]) = Column.Assignment(this, v) def renderToSql0(implicit ctx: Context) = { val suffix = SqlStr.raw(ctx.config.columnNameMapper(name)) @@ -22,5 +22,5 @@ class Column[T](tableRef: TableRef, val name: String)(implicit val mappedType: T } } object Column { - case class Assignment[T](column: Column[T], value: Db[T]) + case class Assignment[T](column: Column[T], value: Expr[T]) } diff --git a/scalasql/query/src/CompoundSelect.scala b/scalasql/query/src/CompoundSelect.scala index 4a5dce98..ea0cb8f4 100644 --- a/scalasql/query/src/CompoundSelect.scala +++ b/scalasql/query/src/CompoundSelect.scala @@ -7,7 +7,7 @@ import scalasql.core.{ DialectTypeMappers, LiveSqlExprs, Queryable, - Db, + Expr, SqlStr, TypeMapper, WithSqlExpr @@ -49,7 +49,7 @@ class CompoundSelect[Q, R]( } } - override def filter(f: Q => Db[Boolean]): Select[Q, R] = { + override def filter(f: Q => Expr[Boolean]): Select[Q, R] = { (lhs, compoundOps) match { case (s: SimpleSelect[Q, R], Nil) => copy(Select.toSimpleFrom(s.filter(f)), compoundOps, orderBy, limit, offset) @@ -57,7 +57,7 @@ class CompoundSelect[Q, R]( } } - override def sortBy(f: Q => Db[_]) = { + override def sortBy(f: Q => Expr[_]) = { val newOrder = Seq(OrderBy(f(expr), None, None)) if (limit.isEmpty && offset.isEmpty) copy(orderBy = newOrder ++ orderBy) @@ -89,7 +89,7 @@ class CompoundSelect[Q, R]( override protected def selectRenderer(prevContext: Context) = new CompoundSelect.Renderer(this, prevContext) - override protected def selectLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] = { + override protected def selectLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] = { SelectBase.lhsMap(lhs, prevContext) } } diff --git a/scalasql/query/src/Delete.scala b/scalasql/query/src/Delete.scala index 7a08c5b3..c6d0c52f 100644 --- a/scalasql/query/src/Delete.scala +++ b/scalasql/query/src/Delete.scala @@ -2,7 +2,7 @@ package scalasql.query import scalasql.core.DialectTypeMappers import scalasql.core.Context -import scalasql.core.{Queryable, SqlStr, Db} +import scalasql.core.{Queryable, SqlStr, Expr} import scalasql.core.SqlStr.SqlStringSyntax /** @@ -11,7 +11,7 @@ import scalasql.core.SqlStr.SqlStringSyntax trait Delete[Q] extends Query[Int] with Returnable[Q] object Delete { - class Impl[Q](val expr: Q, filter: Db[Boolean], val table: TableRef)( + class Impl[Q](val expr: Q, filter: Expr[Boolean], val table: TableRef)( implicit dialect: DialectTypeMappers ) extends Delete[Q] { import dialect._ @@ -25,7 +25,7 @@ object Delete { protected def queryConstruct(args: Queryable.ResultSetIterator): Int = args.get(IntType) } - class Renderer(table: TableRef, expr: Db[Boolean], prevContext: Context) { + class Renderer(table: TableRef, expr: Expr[Boolean], prevContext: Context) { lazy val tableNameStr = SqlStr.raw(prevContext.config.tableNameMapper(Table.name(table.value))) implicit val implicitCtx = Context.compute(prevContext, Nil, Some(table)) diff --git a/scalasql/query/src/FlatJoin.scala b/scalasql/query/src/FlatJoin.scala index a1ca9da7..de23c3c2 100644 --- a/scalasql/query/src/FlatJoin.scala +++ b/scalasql/query/src/FlatJoin.scala @@ -1,33 +1,33 @@ package scalasql.query -import scalasql.core.{Context, JoinNullable, Queryable, Db} +import scalasql.core.{Context, JoinNullable, Queryable, Expr} object FlatJoin { trait Rhs[Q2, R2] class MapResult[Q, Q2, R, R2]( val prefix: String, val from: Context.From, - val on: Option[Db[Boolean]], + val on: Option[Expr[Boolean]], val qr: Queryable.Row[Q2, R2], val f: Q2, - val where: Seq[Db[Boolean]] + val where: Seq[Expr[Boolean]] ) extends Rhs[Q2, R2] class FlatMapResult[Q, Q2, R, R2]( val prefix: String, val from: Context.From, - val on: Option[Db[Boolean]], + val on: Option[Expr[Boolean]], val qr: Queryable.Row[Q2, R2], val f: Rhs[Q2, R2], - val where: Seq[Db[Boolean]] + val where: Seq[Expr[Boolean]] ) extends Rhs[Q2, R2] class Mapper[Q, Q2, R, R2]( prefix: String, from: Context.From, expr: Q, - on: Option[Db[Boolean]], - where: Seq[Db[Boolean]] + on: Option[Expr[Boolean]], + where: Seq[Expr[Boolean]] ) { def map(f: Q => Q2)(implicit qr: Queryable.Row[Q2, R2]): MapResult[Q, Q2, R, R2] = { new MapResult[Q, Q2, R, R2](prefix, from, on, qr, f(expr), where) @@ -39,16 +39,16 @@ object FlatJoin { new FlatMapResult[Q, Q2, R, R2](prefix, from, on, qr, f(expr), where) } - def filter(x: Q => Db[Boolean]): Mapper[Q, Q2, R, R2] = withFilter(x) - def withFilter(x: Q => Db[Boolean]): Mapper[Q, Q2, R, R2] = + def filter(x: Q => Expr[Boolean]): Mapper[Q, Q2, R, R2] = withFilter(x) + def withFilter(x: Q => Expr[Boolean]): Mapper[Q, Q2, R, R2] = new Mapper(prefix, from, expr, on, where ++ Seq(x(expr))) } class NullableMapper[Q, Q2, R, R2]( prefix: String, from: Context.From, expr: JoinNullable[Q], - on: Option[Db[Boolean]], - where: Seq[Db[Boolean]] + on: Option[Expr[Boolean]], + where: Seq[Expr[Boolean]] ) { def lateral = new NullableMapper[Q, Q2, R, R2](prefix + " LATERAL", from, expr, on, where) def map( @@ -63,8 +63,8 @@ object FlatJoin { new FlatMapResult[Q, Q2, R, R2](prefix, from, on, qr, f(expr), where) } - def filter(x: JoinNullable[Q] => Db[Boolean]): NullableMapper[Q, Q2, R, R2] = withFilter(x) - def withFilter(x: JoinNullable[Q] => Db[Boolean]): NullableMapper[Q, Q2, R, R2] = + def filter(x: JoinNullable[Q] => Expr[Boolean]): NullableMapper[Q, Q2, R, R2] = withFilter(x) + def withFilter(x: JoinNullable[Q] => Expr[Boolean]): NullableMapper[Q, Q2, R, R2] = new NullableMapper("LEFT JOIN", from, expr, on, where ++ Seq(x(expr))) } } diff --git a/scalasql/query/src/From.scala b/scalasql/query/src/From.scala index d7915dfb..de1d15f7 100644 --- a/scalasql/query/src/From.scala +++ b/scalasql/query/src/From.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{Context, LiveSqlExprs, Queryable, Db, SqlStr} +import scalasql.core.{Context, LiveSqlExprs, Queryable, Expr, SqlStr} import scalasql.core.Context.From import scalasql.core.SqlStr.SqlStringSyntax diff --git a/scalasql/query/src/Insert.scala b/scalasql/query/src/Insert.scala index c944d990..37cf825f 100644 --- a/scalasql/query/src/Insert.scala +++ b/scalasql/query/src/Insert.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{DialectTypeMappers, Queryable, Db, SqlStr, WithSqlExpr} +import scalasql.core.{DialectTypeMappers, Queryable, Expr, SqlStr, WithSqlExpr} /** * A SQL `INSERT` query @@ -8,12 +8,12 @@ import scalasql.core.{DialectTypeMappers, Queryable, Db, SqlStr, WithSqlExpr} trait Insert[V[_[_]], R] extends WithSqlExpr[V[Column]] with scalasql.generated.Insert[V, R] { def table: TableRef def qr: Queryable[V[Column], R] - def select[C, R2](columns: V[Db] => C, select: Select[C, R2]): InsertSelect[V, C, R, R2] + def select[C, R2](columns: V[Expr] => C, select: Select[C, R2]): InsertSelect[V, C, R, R2] def columns(f: (V[Column] => Column.Assignment[_])*): InsertColumns[V, R] def values(f: R*): InsertValues[V, R] - def batched[T1](f1: V[Column] => Column[T1])(items: Db[T1]*): InsertColumns[V, R] + def batched[T1](f1: V[Column] => Column[T1])(items: Expr[T1]*): InsertColumns[V, R] } @@ -33,13 +33,13 @@ object Insert { def newInsertValues[R]( insert: Insert[V, R], columns: Seq[Column[_]], - valuesLists: Seq[Seq[Db[_]]] + valuesLists: Seq[Seq[Expr[_]]] )(implicit qr: Queryable[V[Column], R]) = { new InsertColumns.Impl(insert, columns, valuesLists) } - def select[C, R2](columns: V[Db] => C, select: Select[C, R2]): InsertSelect[V, C, R, R2] = { - newInsertSelect(this, columns(expr.asInstanceOf[V[Db]]), select) + def select[C, R2](columns: V[Expr] => C, select: Select[C, R2]): InsertSelect[V, C, R, R2] = { + newInsertSelect(this, columns(expr.asInstanceOf[V[Expr]]), select) } def columns(f: (V[Column] => Column.Assignment[_])*): InsertColumns[V, R] = { @@ -47,7 +47,7 @@ object Insert { newInsertValues(this, columns = kvs.map(_.column), valuesLists = Seq(kvs.map(_.value))) } - def batched[T1](f1: V[Column] => Column[T1])(items: Db[T1]*): InsertColumns[V, R] = { + def batched[T1](f1: V[Column] => Column[T1])(items: Expr[T1]*): InsertColumns[V, R] = { newInsertValues(this, columns = Seq(f1(expr)), valuesLists = items.map(Seq(_))) } diff --git a/scalasql/query/src/InsertColumns.scala b/scalasql/query/src/InsertColumns.scala index 8e75c193..eb85659b 100644 --- a/scalasql/query/src/InsertColumns.scala +++ b/scalasql/query/src/InsertColumns.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{Context, DialectTypeMappers, Queryable, Db, SqlStr, WithSqlExpr} +import scalasql.core.{Context, DialectTypeMappers, Queryable, Expr, SqlStr, WithSqlExpr} import scalasql.core.SqlStr.{Renderable, SqlStringSyntax} /** @@ -8,13 +8,13 @@ import scalasql.core.SqlStr.{Renderable, SqlStringSyntax} */ trait InsertColumns[V[_[_]], R] extends InsertReturnable[V[Column]] with Query[Int] { def columns: Seq[Column[_]] - def valuesLists: Seq[Seq[Db[_]]] + def valuesLists: Seq[Seq[Expr[_]]] } object InsertColumns { class Impl[V[_[_]], R]( insert: Insert[V, R], val columns: Seq[Column[_]], - val valuesLists: Seq[Seq[Db[_]]] + val valuesLists: Seq[Seq[Expr[_]]] )(implicit val qr: Queryable[V[Column], R], dialect: DialectTypeMappers) extends InsertColumns[V, R] { import dialect.{dialectSelf => _, _} @@ -36,7 +36,7 @@ object InsertColumns { class Renderer( columns0: Seq[Column[_]], prevContext: Context, - valuesLists: Seq[Seq[Db[_]]], + valuesLists: Seq[Seq[Expr[_]]], tableName: String ) { diff --git a/scalasql/query/src/InsertSelect.scala b/scalasql/query/src/InsertSelect.scala index 5b371af5..337f4c09 100644 --- a/scalasql/query/src/InsertSelect.scala +++ b/scalasql/query/src/InsertSelect.scala @@ -1,19 +1,19 @@ package scalasql.query -import scalasql.core.{Context, DialectTypeMappers, Queryable, Db, SqlStr, WithSqlExpr} +import scalasql.core.{Context, DialectTypeMappers, Queryable, Expr, SqlStr, WithSqlExpr} import scalasql.core.SqlStr.{Renderable, SqlStringSyntax} /** * A SQL `INSERT SELECT` query */ -trait InsertSelect[V[_[_]], C, R, R2] extends InsertReturnable[V[Db]] with Query[Int] +trait InsertSelect[V[_[_]], C, R, R2] extends InsertReturnable[V[Expr]] with Query[Int] object InsertSelect { class Impl[V[_[_]], C, R, R2](insert: Insert[V, R], columns: C, select: Select[C, R2])( implicit dialect: DialectTypeMappers ) extends InsertSelect[V, C, R, R2] { import dialect.{dialectSelf => _, _} - protected def expr = WithSqlExpr.get(insert).asInstanceOf[V[Db]] + protected def expr = WithSqlExpr.get(insert).asInstanceOf[V[Expr]] def table = insert.table @@ -35,7 +35,7 @@ object InsertSelect { class Renderer( select: Select[_, _], - exprs: Seq[Db[_]], + exprs: Seq[Expr[_]], prevContext: Context, tableName: String ) { diff --git a/scalasql/query/src/JoinOps.scala b/scalasql/query/src/JoinOps.scala index f5cd1178..4c185109 100644 --- a/scalasql/query/src/JoinOps.scala +++ b/scalasql/query/src/JoinOps.scala @@ -1,13 +1,13 @@ package scalasql.query -import scalasql.core.{Queryable, Db, WithSqlExpr} +import scalasql.core.{Queryable, Expr, WithSqlExpr} trait JoinOps[C[_, _], Q, R] extends WithSqlExpr[Q] { /** * Performs a `JOIN`/`INNER JOIN` on the given [[other]], typically a [[Table]] or [[Select]]. */ - def join[Q2, R2, QF, RF](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + def join[Q2, R2, QF, RF](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit ja: JoinAppend[Q, Q2, QF, RF] ): C[QF, RF] = join0("JOIN", other, Some(on)) @@ -21,7 +21,7 @@ trait JoinOps[C[_, _], Q, R] extends WithSqlExpr[Q] { protected def join0[Q2, R2, QF, RF]( prefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] )( implicit ja: JoinAppend[Q, Q2, QF, RF] ): C[QF, RF] @@ -29,7 +29,7 @@ trait JoinOps[C[_, _], Q, R] extends WithSqlExpr[Q] { protected def joinInfo[Q2, R2]( joinPrefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] ) = { val otherSelect = Joinable.toSelect(other) @@ -52,7 +52,7 @@ object JoinOps { v: JoinOps[C, Q, R], prefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] )( implicit ja: JoinAppend[Q, Q2, QF, RF] ) = { diff --git a/scalasql/query/src/Joinable.scala b/scalasql/query/src/Joinable.scala index 6633b41c..c28ec4e0 100644 --- a/scalasql/query/src/Joinable.scala +++ b/scalasql/query/src/Joinable.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{Context, JoinNullable, Db} +import scalasql.core.{Context, JoinNullable, Expr} /** * Something that can be joined; typically a [[Select]] or a [[Table]] @@ -22,7 +22,7 @@ trait Joinable[Q, R] { /** * Version of `join` meant for usage in `for`-comprehensions */ - def join[Q2, R2](on: Q => Db[Boolean]): FlatJoin.Mapper[Q, Q2, R, R2] = { + def join[Q2, R2](on: Q => Expr[Boolean]): FlatJoin.Mapper[Q, Q2, R, R2] = { val (from, expr) = joinableToFromExpr new FlatJoin.Mapper[Q, Q2, R, R2]("JOIN", from, expr, Some(on(expr)), Nil) } @@ -30,7 +30,7 @@ trait Joinable[Q, R] { /** * Version of `leftJoin` meant for usage in `for`-comprehensions */ - def leftJoin[Q2, R2](on: Q => Db[Boolean]): FlatJoin.NullableMapper[Q, Q2, R, R2] = { + def leftJoin[Q2, R2](on: Q => Expr[Boolean]): FlatJoin.NullableMapper[Q, Q2, R, R2] = { val (from, expr) = joinableToFromExpr new FlatJoin.NullableMapper[Q, Q2, R, R2]( "LEFT JOIN", diff --git a/scalasql/query/src/JoinsToSql.scala b/scalasql/query/src/JoinsToSql.scala index f51cd9f4..62b0759a 100644 --- a/scalasql/query/src/JoinsToSql.scala +++ b/scalasql/query/src/JoinsToSql.scala @@ -1,6 +1,6 @@ package scalasql.renderer -import scalasql.core.{ColumnNamer, Context, LiveSqlExprs, Queryable, Db, SqlStr, TypeMapper} +import scalasql.core.{Context, LiveSqlExprs, Queryable, Expr, SqlStr, TypeMapper} import scalasql.core.SqlStr.SqlStringSyntax import scalasql.query.{AscDesc, CompoundSelect, Join, Joinable, Nulls, Select, SimpleSelect} diff --git a/scalasql/query/src/LateralJoinOps.scala b/scalasql/query/src/LateralJoinOps.scala index 70173940..01c870b8 100644 --- a/scalasql/query/src/LateralJoinOps.scala +++ b/scalasql/query/src/LateralJoinOps.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{JoinNullable, Queryable, Db, WithSqlExpr} +import scalasql.core.{JoinNullable, Queryable, Expr, WithSqlExpr} /** * Wrapper class with extension methods to add support for `JOIN LATERAL`, which @@ -26,13 +26,13 @@ class LateralJoinOps[C[_, _], Q, R](wrapped: JoinOps[C, Q, R] with Joinable[Q, R * `JOIN` clause to access the results of earlier `JOIN` and `FROM` clauses. * Only supported by Postgres and MySql */ - def joinLateral[Q2, R2, QF, RF](other: Q => Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + def joinLateral[Q2, R2, QF, RF](other: Q => Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit ja: JoinAppend[Q, Q2, QF, RF] ): C[QF, RF] = JoinOps.join0(wrapped, "JOIN LATERAL", other(WithSqlExpr.get(wrapped)), Some(on)) def leftJoinLateral[Q2, R2](other: Q => Joinable[Q2, R2])( - on: (Q, Q2) => Db[Boolean] + on: (Q, Q2) => Expr[Boolean] )(implicit joinQr: Queryable.Row[Q2, R2]): Select[(Q, JoinNullable[Q2]), (R, Option[R2])] = { SimpleSelect.joinCopy( wrapped.asInstanceOf[SimpleSelect[Q, R]], @@ -53,7 +53,7 @@ class LateralJoinOps[C[_, _], Q, R](wrapped: JoinOps[C, Q, R] with Joinable[Q, R /** * Version of `joinLateral` meant for use in `for`-comprehensions */ - def joinLateral[Q2, R2](on: Q => Db[Boolean]): FlatJoin.Mapper[Q, Q2, R, R2] = { + def joinLateral[Q2, R2](on: Q => Expr[Boolean]): FlatJoin.Mapper[Q, Q2, R, R2] = { val (from, expr) = Joinable.toFromExpr(wrapped) new FlatJoin.Mapper[Q, Q2, R, R2]("JOIN LATERAL", from, expr, Some(on(expr)), Nil) } @@ -61,7 +61,7 @@ class LateralJoinOps[C[_, _], Q, R](wrapped: JoinOps[C, Q, R] with Joinable[Q, R /** * Version of `leftJoinLateral` meant for use in `for`-comprehensions */ - def leftJoinLateral[Q2, R2](on: Q => Db[Boolean]): FlatJoin.NullableMapper[Q, Q2, R, R2] = { + def leftJoinLateral[Q2, R2](on: Q => Expr[Boolean]): FlatJoin.NullableMapper[Q, Q2, R, R2] = { val (from, expr) = Joinable.toFromExpr(wrapped) new FlatJoin.NullableMapper[Q, Q2, R, R2]( "LEFT JOIN LATERAL", diff --git a/scalasql/query/src/Model.scala b/scalasql/query/src/Model.scala index 72b82760..7f77c924 100644 --- a/scalasql/query/src/Model.scala +++ b/scalasql/query/src/Model.scala @@ -1,11 +1,11 @@ package scalasql.query -import scalasql.core.Db +import scalasql.core.Expr /** * Models a SQL `ORDER BY` clause */ -case class OrderBy(expr: Db[_], ascDesc: Option[AscDesc], nulls: Option[Nulls]) +case class OrderBy(expr: Expr[_], ascDesc: Option[AscDesc], nulls: Option[Nulls]) sealed trait AscDesc @@ -40,12 +40,12 @@ object Nulls { /** * Models a SQL `GROUP BY` clause */ -case class GroupBy(key: Db[_], select: () => Select[_, _], having: Seq[Db[_]]) +case class GroupBy(key: Expr[_], select: () => Select[_, _], having: Seq[Expr[_]]) /** * Models a SQL `JOIN` clause */ case class Join(prefix: String, from: Seq[Join.From]) object Join { - case class From(from: scalasql.core.Context.From, on: Option[Db[_]]) + case class From(from: scalasql.core.Context.From, on: Option[Expr[_]]) } diff --git a/scalasql/query/src/Query.scala b/scalasql/query/src/Query.scala index dc9bf70c..0afada26 100644 --- a/scalasql/query/src/Query.scala +++ b/scalasql/query/src/Query.scala @@ -1,7 +1,7 @@ package scalasql.query import scalasql.core.SqlStr.Renderable -import scalasql.core.{Queryable, SqlStr, Db} +import scalasql.core.{Queryable, SqlStr, Expr} import scalasql.core.Context /** @@ -10,7 +10,7 @@ import scalasql.core.Context */ trait Query[R] extends Renderable { protected def queryWalkLabels(): Seq[List[String]] - protected def queryWalkExprs(): Seq[Db[_]] + protected def queryWalkExprs(): Seq[Expr[_]] protected def queryIsSingleRow: Boolean protected def queryIsExecuteUpdate: Boolean = false diff --git a/scalasql/query/src/Select.scala b/scalasql/query/src/Select.scala index eafc57bd..e7000b35 100644 --- a/scalasql/query/src/Select.scala +++ b/scalasql/query/src/Select.scala @@ -7,7 +7,7 @@ import scalasql.core.{ JoinNullable, LiveSqlExprs, Queryable, - Db, + Expr, SqlStr, TypeMapper } @@ -59,7 +59,7 @@ trait Select[Q, R] preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )(implicit qr: Queryable.Row[Q, R], dialect: DialectTypeMappers): SimpleSelect[Q, R] = new SimpleSelect(expr, exprPrefix, preserveAll, from, joins, where, groupBy0) @@ -92,12 +92,12 @@ trait Select[Q, R] /** * Filters this [[Select]] with the given predicate, translates into a SQL `WHERE` clause */ - def filter(f: Q => Db[Boolean]): Select[Q, R] + def filter(f: Q => Expr[Boolean]): Select[Q, R] /** * Alias for [[filter]] */ - def withFilter(f: Q => Db[Boolean]): Select[Q, R] = filter(f) + def withFilter(f: Q => Expr[Boolean]): Select[Q, R] = filter(f) /** * Performs one or more aggregates in a single [[Select]] @@ -126,7 +126,7 @@ trait Select[Q, R] * call to [[sortBy]] taking priority. Can be followed by [[asc]], [[desc]], [[nullsFirst]] * or [[nullsLast]] to configure the sort order */ - def sortBy(f: Q => Db[_]): Select[Q, R] + def sortBy(f: Q => Expr[_]): Select[Q, R] /** * Combined with [[sortBy]] to make the sort order ascending, translates into SQL `ASC` @@ -213,12 +213,12 @@ trait Select[Q, R] def head: Query.Single[R] = take(1).single /** - * Converts this [[Select]] into an [[Db]], assuming it returns a single row and + * Converts this [[Select]] into an [[Expr]], assuming it returns a single row and * a single column. Note that if this returns multiple rows, behavior is database-specific, * with some like Sqlite simply taking the first row while others like Postgres/MySql * throwing exceptions */ - def toExpr(implicit mt: TypeMapper[R]): Db[R] = Db { implicit ctx => this.renderToSql(ctx) } + def toExpr(implicit mt: TypeMapper[R]): Expr[R] = Expr { implicit ctx => this.renderToSql(ctx) } protected def selectToSimpleSelect(): SimpleSelect[Q, R] @@ -234,28 +234,28 @@ trait Select[Q, R] /** * Performs a `LEFT JOIN` on the given [[other]], typically a [[Table]] or [[Select]]. */ - def leftJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + def leftJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(Q, JoinNullable[Q2]), (R, Option[R2])] /** * Performs a `RIGHT JOIN` on the given [[other]], typically a [[Table]] or [[Select]]. */ - def rightJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + def rightJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(JoinNullable[Q], Q2), (Option[R], R2)] /** * Performs a `OUTER JOIN` on the given [[other]], typically a [[Table]] or [[Select]]. */ - def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(JoinNullable[Q], JoinNullable[Q2]), (Option[R], Option[R2])] /** * Returns whether or not the [[Select]] on the left contains the [[other]] value on the right */ - def contains(other: Q): Db[Boolean] = Db { implicit ctx => + def contains(other: Q): Expr[Boolean] = Expr { implicit ctx => val lhs = qr.walkExprs(other).map(e => sql"$e") match { case Seq(single) => single case multiple => sql"(${SqlStr.join(multiple, SqlStr.commaSep)})" @@ -266,12 +266,12 @@ trait Select[Q, R] /** * Returns whether or not the [[Select]] on the left is empty with zero elements */ - def isEmpty: Db[Boolean] = Db { implicit ctx => sql"(NOT EXISTS $this)" } + def isEmpty: Expr[Boolean] = Expr { implicit ctx => sql"(NOT EXISTS $this)" } /** * Returns whether or not the [[Select]] on the left is nonempty with one or more elements */ - def nonEmpty: Db[Boolean] = Db { implicit ctx => sql"(EXISTS $this)" } + def nonEmpty: Expr[Boolean] = Expr { implicit ctx => sql"(EXISTS $this)" } } object Select { @@ -282,7 +282,7 @@ object Select { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )(implicit qr: Queryable.Row[Q, R], dialect: DialectTypeMappers): SimpleSelect[Q, R] = lhs.newSimpleSelect(expr, exprPrefix, preserveAll, from, joins, where, groupBy0) @@ -292,8 +292,8 @@ object Select { def withExprPrefix[Q, R](s: Select[Q, R], preserveAll: Boolean, str: Context => SqlStr) = s.selectWithExprPrefix(preserveAll, str) - implicit class ExprSelectOps[T](s: Select[Db[T], T]) { - def sorted(implicit tm: TypeMapper[T]): Select[Db[T], T] = s.sortBy(identity) + implicit class ExprSelectOps[T](s: Select[Expr[T], T]) { + def sorted(implicit tm: TypeMapper[T]): Select[Expr[T], T] = s.sortBy(identity) } trait Proxy[Q, R] extends Select[Q, R] { @@ -311,7 +311,7 @@ object Select { implicit qr: Queryable.Row[Q2, R2] ): Select[Q2, R2] = selectToSimpleSelect().flatMap(f) - override def filter(f: Q => Db[Boolean]): Select[Q, R] = selectToSimpleSelect().filter(f) + override def filter(f: Q => Expr[Boolean]): Select[Q, R] = selectToSimpleSelect().filter(f) override def aggregate[E, V](f: SelectProxy[Q] => E)( implicit qr: Queryable.Row[E, V] @@ -326,7 +326,7 @@ object Select { )(implicit qrk: Queryable.Row[K, R2], qrv: Queryable.Row[V, R3]): Select[(K, V), (R2, R3)] = selectToSimpleSelect().groupBy(groupKey)(groupAggregate) - override def sortBy(f: Q => Db[_]): Select[Q, R] = selectToSimpleSelect().sortBy(f) + override def sortBy(f: Q => Expr[_]): Select[Q, R] = selectToSimpleSelect().sortBy(f) override def asc: Select[Q, R] = selectToSimpleSelect().asc override def desc: Select[Q, R] = selectToSimpleSelect().desc override def nullsFirst: Select[Q, R] = selectToSimpleSelect().nullsFirst @@ -341,20 +341,20 @@ object Select { override protected def selectRenderer(prevContext: Context): SelectBase.Renderer = SelectBase.renderer(selectToSimpleSelect(), prevContext) - override protected def selectLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] = + override protected def selectLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] = SelectBase.lhsMap(selectToSimpleSelect(), prevContext) override protected def selectToSimpleSelect(): SimpleSelect[Q, R] - override def leftJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + override def leftJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(Q, JoinNullable[Q2]), (R, Option[R2])] = selectToSimpleSelect().leftJoin(other)(on) - override def rightJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + override def rightJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(JoinNullable[Q], Q2), (Option[R], R2)] = selectToSimpleSelect().rightJoin(other)(on) - override def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + override def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(JoinNullable[Q], JoinNullable[Q2]), (Option[R], Option[R2])] = selectToSimpleSelect().outerJoin(other)(on) @@ -365,13 +365,13 @@ object Select { override protected def join0[Q2, R2, QF, RF]( prefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] )(implicit ja: JoinAppend[Q, Q2, QF, RF]): Select[QF, RF] = selectToSimpleSelect().join0(prefix, other, on) override def aggregateExpr[V: TypeMapper](f: Q => Context => SqlStr)( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] = selectToSimpleSelect().aggregateExpr(f) + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] = selectToSimpleSelect().aggregateExpr(f) override protected def expr: Q = selectToSimpleSelect().expr } diff --git a/scalasql/query/src/SelectBase.scala b/scalasql/query/src/SelectBase.scala index b32dc6f0..3d8da65f 100644 --- a/scalasql/query/src/SelectBase.scala +++ b/scalasql/query/src/SelectBase.scala @@ -1,9 +1,9 @@ package scalasql.query -import scalasql.core.{Context, LiveSqlExprs, Db, SqlStr} +import scalasql.core.{Context, LiveSqlExprs, Expr, SqlStr} trait SelectBase { - protected def selectLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] + protected def selectLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] protected def selectRenderer(prevContext: Context): SelectBase.Renderer } object SelectBase { diff --git a/scalasql/query/src/SelectProxy.scala b/scalasql/query/src/SelectProxy.scala index 900fa73f..8b13eb42 100644 --- a/scalasql/query/src/SelectProxy.scala +++ b/scalasql/query/src/SelectProxy.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{Aggregatable, Context, Queryable, Db, SqlStr, TypeMapper} +import scalasql.core.{Aggregatable, Context, Queryable, Expr, SqlStr, TypeMapper} /** * A reference that aggregations for usage within [[Select.aggregate]], to allow @@ -8,6 +8,6 @@ import scalasql.core.{Aggregatable, Context, Queryable, Db, SqlStr, TypeMapper} */ class SelectProxy[Q](val expr: Q) extends Aggregatable[Q] { def aggregateExpr[V: TypeMapper](f: Q => Context => SqlStr)( - implicit qr: Queryable.Row[Db[V], V] - ): Db[V] = { Db[V] { implicit c => f(expr)(c) } } + implicit qr: Queryable.Row[Expr[V], V] + ): Expr[V] = { Expr[V] { implicit c => f(expr)(c) } } } diff --git a/scalasql/query/src/SimpleSelect.scala b/scalasql/query/src/SimpleSelect.scala index 0175d088..aa7e7254 100644 --- a/scalasql/query/src/SimpleSelect.scala +++ b/scalasql/query/src/SimpleSelect.scala @@ -1,14 +1,13 @@ package scalasql.query import scalasql.core.{ - ColumnNamer, Config, Context, DialectTypeMappers, JoinNullable, LiveSqlExprs, Queryable, - Db, + Expr, SqlExprsToSql, SqlStr, TypeMapper, @@ -30,7 +29,7 @@ class SimpleSelect[Q, R]( val preserveAll: Boolean, val from: Seq[Context.From], val joins: Seq[Join], - val where: Seq[Db[_]], + val where: Seq[Expr[_]], val groupBy0: Option[GroupBy] )(implicit val qr: Queryable.Row[Q, R], protected val dialect: DialectTypeMappers) extends Select[Q, R] { @@ -42,7 +41,7 @@ class SimpleSelect[Q, R]( preserveAll: Boolean = this.preserveAll, from: Seq[Context.From] = this.from, joins: Seq[Join] = this.joins, - where: Seq[Db[_]] = this.where, + where: Seq[Expr[_]] = this.where, groupBy0: Option[GroupBy] = this.groupBy0 )(implicit qr: Queryable.Row[Q, R]) = newSimpleSelect(expr, exprPrefix, preserveAll, from, joins, where, groupBy0) @@ -52,10 +51,10 @@ class SimpleSelect[Q, R]( def aggregateExpr[V: TypeMapper]( f: Q => Context => SqlStr - )(implicit qr2: Queryable.Row[Db[V], V]): Db[V] = { - Db[V] { implicit outerCtx: Context => + )(implicit qr2: Queryable.Row[Expr[V], V]): Expr[V] = { + Expr[V] { implicit outerCtx: Context => this - .copy(expr = Db[V] { implicit ctx: Context => + .copy(expr = Expr[V] { implicit ctx: Context => val newCtx = ctx.withFromNaming(outerCtx.fromNaming ++ ctx.fromNaming) f(expr)(newCtx) @@ -76,7 +75,7 @@ class SimpleSelect[Q, R]( def rec( thing: FlatJoin.Rhs[Q2, R2], joinOns: Seq[Join], - wheres: Seq[Db[Boolean]] + wheres: Seq[Expr[Boolean]] ): Select[Q2, R2] = thing match { case other: FlatJoin.MapResult[Q, Q2, R, R2] => @@ -91,7 +90,7 @@ class SimpleSelect[Q, R]( rec(f(expr), Nil, Nil) } - def filter(f: Q => Db[Boolean]): Select[Q, R] = { + def filter(f: Q => Expr[Boolean]): Select[Q, R] = { if (groupBy0.isEmpty) copy(where = where ++ Seq(f(expr))) else copy(groupBy0 = groupBy0.map(g => g.copy(having = g.having ++ Seq(f(expr))))) } @@ -99,7 +98,7 @@ class SimpleSelect[Q, R]( def join0[Q2, R2, QF, RF]( prefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] )( implicit ja: JoinAppend[Q, Q2, QF, RF] ): Select[QF, RF] = { joinCopy(other, on, prefix)(ja.appendTuple(_, _))(ja.qr) } @@ -107,7 +106,7 @@ class SimpleSelect[Q, R]( protected def joinCopy0[Q3, R3]( newExpr: Q3, newJoins: Seq[Join], - newWheres: Seq[Db[Boolean]] + newWheres: Seq[Expr[Boolean]] )( implicit jqr: Queryable.Row[Q3, R3] ): SimpleSelect[Q3, R3] = { @@ -130,18 +129,18 @@ class SimpleSelect[Q, R]( } def leftJoin[Q2, R2](other: Joinable[Q2, R2])( - on: (Q, Q2) => Db[Boolean] + on: (Q, Q2) => Expr[Boolean] )(implicit joinQr: Queryable.Row[Q2, R2]): Select[(Q, JoinNullable[Q2]), (R, Option[R2])] = { joinCopy(other, Some(on), "LEFT JOIN")((e, o) => (e, JoinNullable(o))) } def rightJoin[Q2, R2](other: Joinable[Q2, R2])( - on: (Q, Q2) => Db[Boolean] + on: (Q, Q2) => Expr[Boolean] )(implicit joinQr: Queryable.Row[Q2, R2]): Select[(JoinNullable[Q], Q2), (Option[R], R2)] = { joinCopy(other, Some(on), "RIGHT JOIN")((e, o) => (JoinNullable(e), o)) } - def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): Select[(JoinNullable[Q], JoinNullable[Q2]), (Option[R], Option[R2])] = { joinCopy(other, Some(on), "FULL OUTER JOIN")((e, o) => (JoinNullable(e), JoinNullable(o))) @@ -189,7 +188,7 @@ class SimpleSelect[Q, R]( res } - def sortBy(f: Q => Db[_]) = { + def sortBy(f: Q => Expr[_]) = { newCompoundSelect(this, Nil, Seq(OrderBy(f(expr), None, None)), None, None) } @@ -209,18 +208,18 @@ class SimpleSelect[Q, R]( protected def selectRenderer(prevContext: Context): SimpleSelect.Renderer[_, _] = new SimpleSelect.Renderer(this, prevContext) - protected def selectLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] = { + protected def selectLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] = { lazy val flattenedExpr = qr.walkLabelsAndExprs(expr) - lazy val jsonQueryMap = ColumnNamer.selectColumnReferences(flattenedExpr, prevContext).toMap + lazy val jsonQueryMap = SqlExprsToSql.selectColumnReferences(flattenedExpr, prevContext).toMap jsonQueryMap } protected def joinCopy[Q2, R2, Q3, R3]( other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]], + on: Option[(Q, Q2) => Expr[Boolean]], joinPrefix: String )(f: (Q, Q2) => Q3)(implicit jqr: Queryable.Row[Q3, R3]) = { @@ -239,7 +238,7 @@ object SimpleSelect { def joinCopy[Q, R, Q2, R2, Q3, R3]( self: SimpleSelect[Q, R], other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]], + on: Option[(Q, Q2) => Expr[Boolean]], joinPrefix: String )(f: (Q, Q2) => Q3)(implicit jqr: Queryable.Row[Q3, R3]) = { self.joinCopy(other, on, joinPrefix)(f) @@ -256,7 +255,7 @@ object SimpleSelect { query.joins.map(_.from.map(_.on.map(t => SqlStr.flatten(Renderable.toSql(t))))) lazy val exprsStrs = { - ColumnNamer.selectColumnSql(flattenedExpr, context).map { case (k, v) => + SqlExprsToSql.selectColumnSql(flattenedExpr, context).map { case (k, v) => sql"$v AS ${SqlStr.raw(context.config.tableNameMapper(k))}" } } @@ -273,7 +272,7 @@ object SimpleSelect { val exprStr = SqlStr.flatten( SqlStr.join( flattenedExpr.iterator.zip(exprsStrs).collect { - case ((l, e), s) if liveExprs.isLive(Db.identity(e)) => s + case ((l, e), s) if liveExprs.isLive(Expr.identity(e)) => s }, SqlStr.commaSep ) diff --git a/scalasql/query/src/SqlWindow.scala b/scalasql/query/src/SqlWindow.scala index c7c47e75..35c51945 100644 --- a/scalasql/query/src/SqlWindow.scala +++ b/scalasql/query/src/SqlWindow.scala @@ -1,20 +1,20 @@ package scalasql.query -import scalasql.core.{Db, SqlStr} +import scalasql.core.{Expr, SqlStr} import scalasql.core.DialectTypeMappers import scalasql.query.{AscDesc, CompoundSelect, Nulls, OrderBy} import scalasql.core.SqlStr.SqlStringSyntax import scalasql.core.Context case class SqlWindow[T]( - e: Db[T], - partitionBy0: Option[Db[_]], - filter0: Option[Db[Boolean]], + e: Expr[T], + partitionBy0: Option[Expr[_]], + filter0: Option[Expr[Boolean]], orderBy: Seq[scalasql.query.OrderBy], frameStart0: Option[SqlStr], frameEnd0: Option[SqlStr], exclusions: Option[SqlStr] )(implicit dialect: DialectTypeMappers) - extends Db[T] { + extends Expr[T] { import dialect.{dialectSelf => _, _} protected def renderToSql0(implicit ctx: Context): SqlStr = { val partitionBySql = SqlStr.opt(partitionBy0) { p => sql"PARTITION BY $p" } @@ -37,10 +37,10 @@ case class SqlWindow[T]( } - def partitionBy(e: Db[_]) = this.copy(partitionBy0 = Some(e)) + def partitionBy(e: Expr[_]) = this.copy(partitionBy0 = Some(e)) - def filter(expr: Db[Boolean]) = copy(filter0 = Some(expr)) - def sortBy(expr: Db[_]) = { + def filter(expr: Expr[Boolean]) = copy(filter0 = Some(expr)) + def sortBy(expr: Expr[_]) = { val newOrder = Seq(OrderBy(expr, None, None)) copy(orderBy = newOrder ++ orderBy) diff --git a/scalasql/query/src/Table.scala b/scalasql/query/src/Table.scala index 0ac13768..71263d15 100644 --- a/scalasql/query/src/Table.scala +++ b/scalasql/query/src/Table.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{DialectTypeMappers, Sc, Queryable, Db} +import scalasql.core.{DialectTypeMappers, Sc, Queryable, Expr} import scala.language.experimental.macros @@ -17,14 +17,14 @@ abstract class Table[V[_[_]]]()(implicit name: sourcecode.Name, metadata0: Table protected def tableMetadata: Table.Metadata[V] = metadata0 - implicit def containerQr(implicit dialect: DialectTypeMappers): Queryable.Row[V[Db], V[Sc]] = + implicit def containerQr(implicit dialect: DialectTypeMappers): Queryable.Row[V[Expr], V[Sc]] = tableMetadata .queryable( tableMetadata.walkLabels0, dialect, new Table.Metadata.QueryableProxy(tableMetadata.queryables(dialect, _)) ) - .asInstanceOf[Queryable.Row[V[Db], V[Sc]]] + .asInstanceOf[Queryable.Row[V[Expr], V[Sc]]] protected def tableRef = new TableRef(this) protected[scalasql] def tableLabels: Seq[String] = { @@ -73,7 +73,7 @@ object Table { () => Seq[String], DialectTypeMappers, Metadata.QueryableProxy - ) => Queryable[V[Db], V[Sc]], + ) => Queryable[V[Expr], V[Sc]], val vExpr0: (TableRef, DialectTypeMappers, Metadata.QueryableProxy) => V[Column] ) { def vExpr(t: TableRef, d: DialectTypeMappers) = @@ -89,12 +89,12 @@ object Table { object Internal { class TableQueryable[Q, R <: scala.Product]( walkLabels0: () => Seq[String], - walkExprs0: Q => Seq[Db[_]], + walkExprs0: Q => Seq[Expr[_]], construct0: Queryable.ResultSetIterator => R, deconstruct0: R => Q = ??? ) extends Queryable.Row[Q, R] { def walkLabels(): Seq[List[String]] = walkLabels0().map(List(_)) - def walkExprs(q: Q): Seq[Db[_]] = walkExprs0(q) + def walkExprs(q: Q): Seq[Expr[_]] = walkExprs0(q) def construct(args: Queryable.ResultSetIterator) = construct0(args) diff --git a/scalasql/query/src/Update.scala b/scalasql/query/src/Update.scala index 795e070e..b7a2b197 100644 --- a/scalasql/query/src/Update.scala +++ b/scalasql/query/src/Update.scala @@ -5,7 +5,7 @@ import scalasql.core.{ DialectTypeMappers, LiveSqlExprs, Queryable, - Db, + Expr, SqlExprsToSql, SqlStr, TypeMapper, @@ -18,15 +18,15 @@ import scalasql.renderer.JoinsToSql * A SQL `UPDATE` query */ trait Update[Q, R] extends JoinOps[Update, Q, R] with Returnable[Q] with Query[Int] { - def filter(f: Q => Db[Boolean]): Update[Q, R] - def withFilter(f: Q => Db[Boolean]): Update[Q, R] = filter(f) + def filter(f: Q => Expr[Boolean]): Update[Q, R] + def withFilter(f: Q => Expr[Boolean]): Update[Q, R] = filter(f) def set(f: (Q => Column.Assignment[_])*): Update[Q, R] def join0[Q2, R2, QF, RF]( prefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] )( implicit ja: JoinAppend[Q, Q2, QF, RF] ): Update[QF, RF] @@ -50,7 +50,7 @@ object Update { val table: TableRef, val set0: Seq[Column.Assignment[_]], val joins: Seq[Join], - val where: Seq[Db[_]] + val where: Seq[Expr[_]] )(implicit val qr: Queryable.Row[Q, R], dialect: DialectTypeMappers) extends Update[Q, R] { @@ -60,18 +60,18 @@ object Update { table: TableRef = this.table, set0: Seq[Column.Assignment[_]] = this.set0, joins: Seq[Join] = this.joins, - where: Seq[Db[_]] = this.where + where: Seq[Expr[_]] = this.where )(implicit qr: Queryable.Row[Q, R], dialect: DialectTypeMappers): Update[Q, R] = new Impl(expr, table, set0, joins, where) - def filter(f: Q => Db[Boolean]) = { this.copy(where = where ++ Seq(f(expr))) } + def filter(f: Q => Expr[Boolean]) = { this.copy(where = where ++ Seq(f(expr))) } def set(f: (Q => Column.Assignment[_])*) = { this.copy(set0 = f.map(_(expr))) } def join0[Q2, R2, QF, RF]( prefix: String, other: Joinable[Q2, R2], - on: Option[(Q, Q2) => Db[Boolean]] + on: Option[(Q, Q2) => Expr[Boolean]] )( implicit ja: JoinAppend[Q, Q2, QF, RF] ) = { @@ -98,7 +98,7 @@ object Update { joins0: Seq[Join], table: TableRef, set0: Seq[Column.Assignment[_]], - where0: Seq[Db[_]], + where0: Seq[Expr[_]], prevContext: Context ) { lazy val froms = joins0.flatMap(_.from).map(_.from) diff --git a/scalasql/query/src/Values.scala b/scalasql/query/src/Values.scala index d004cfd0..203853dc 100644 --- a/scalasql/query/src/Values.scala +++ b/scalasql/query/src/Values.scala @@ -1,6 +1,6 @@ package scalasql.query -import scalasql.core.{Context, DialectTypeMappers, LiveSqlExprs, Queryable, Db, SqlStr, TypeMapper} +import scalasql.core.{Context, DialectTypeMappers, LiveSqlExprs, Queryable, Expr, SqlStr, TypeMapper} import scalasql.core.SqlStr.{Renderable, SqlStringSyntax} /** @@ -26,10 +26,10 @@ class Values[Q, R](val ts: Seq[R])( override protected def selectRenderer(prevContext: Context): SelectBase.Renderer = new Values.Renderer(this)(implicitly, prevContext) - override protected def selectLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] = { + override protected def selectLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] = { qr.walkExprs(expr) .zipWithIndex - .map { case (e, i) => (Db.identity(e), SqlStr.raw(columnName(i))) } + .map { case (e, i) => (Expr.identity(e), SqlStr.raw(columnName(i))) } .toMap } } diff --git a/scalasql/query/src/WithCte.scala b/scalasql/query/src/WithCte.scala index bbb37fb8..88768180 100644 --- a/scalasql/query/src/WithCte.scala +++ b/scalasql/query/src/WithCte.scala @@ -1,12 +1,11 @@ package scalasql.query import scalasql.core.{ - ColumnNamer, Context, DialectTypeMappers, LiveSqlExprs, Queryable, - Db, + Expr, SqlExprsToSql, SqlStr, TypeMapper, @@ -34,11 +33,11 @@ class WithCte[Q, R]( new WithCte(lhs, lhsSubQuery, rhs.map(f)) } - override def filter(f: Q => Db[Boolean]): Select[Q, R] = { + override def filter(f: Q => Expr[Boolean]): Select[Q, R] = { new WithCte(rhs.filter(f), lhsSubQuery, rhs) } - override def sortBy(f: Q => Db[_]) = new WithCte(lhs, lhsSubQuery, rhs.sortBy(f)) + override def sortBy(f: Q => Expr[_]) = new WithCte(lhs, lhsSubQuery, rhs.sortBy(f)) override def drop(n: Int) = new WithCte(lhs, lhsSubQuery, rhs.drop(n)) override def take(n: Int) = new WithCte(lhs, lhsSubQuery, rhs.take(n)) @@ -46,7 +45,7 @@ class WithCte[Q, R]( override protected def selectRenderer(prevContext: Context) = new WithCte.Renderer(withPrefix, this, prevContext) - override protected def selectLhsMap(prevContext: Context): Map[Db.Identity, SqlStr] = { + override protected def selectLhsMap(prevContext: Context): Map[Expr.Identity, SqlStr] = { SelectBase.lhsMap(rhs, prevContext) } @@ -97,7 +96,7 @@ object WithCte { .asInstanceOf[Queryable[Any, Any]] .walkLabelsAndExprs(WithSqlExpr.get(query.lhs)) - val newExprNaming = ColumnNamer.selectColumnReferences(walked, prevContext) + val newExprNaming = SqlExprsToSql.selectColumnReferences(walked, prevContext) val newContext = Context.compute(prevContext, Seq(query.lhsSubQuery), None) val cteName = SqlStr.raw(newContext.fromNaming(query.lhsSubQuery)) diff --git a/scalasql/src/dialects/Dialect.scala b/scalasql/src/dialects/Dialect.scala index ff939a4e..7978ee0e 100644 --- a/scalasql/src/dialects/Dialect.scala +++ b/scalasql/src/dialects/Dialect.scala @@ -2,10 +2,10 @@ package scalasql.dialects import scalasql.operations.{CaseWhen, DbApiOps} import scalasql.query.SqlWindow -import scalasql.core.Db.apply0 +import scalasql.core.Expr.apply0 import scalasql.{Table, operations} import scalasql.core.Aggregatable -import scalasql.core.{DbApi, DialectTypeMappers, JoinNullable, Queryable, Db, SqlStr, TypeMapper} +import scalasql.core.{DbApi, DialectTypeMappers, JoinNullable, Queryable, Expr, SqlStr, TypeMapper} import java.sql.{JDBCType, PreparedStatement, ResultSet} import java.time.{ @@ -148,7 +148,7 @@ trait Dialect extends DialectTypeMappers { case l: java.lang.Long => Instant.ofEpochMilli(l) // Sqlite sometimes also returns this case s: java.lang.String => java.sql.Timestamp.valueOf(s).toInstant - // H2 and HsqlDb return this + // H2 and HsqlExpr return this case o: java.time.OffsetDateTime => o.toInstant // MySql returns this case l: java.time.LocalDateTime => @@ -190,17 +190,17 @@ trait Dialect extends DialectTypeMappers { def put(r: PreparedStatement, idx: Int, v: T) = r.setObject(idx, v, java.sql.Types.OTHER) } - implicit def from(x: Int): Db[Int] = Db(x) + implicit def from(x: Int): Expr[Int] = Expr(x) - implicit def from(x: Long): Db[Long] = Db(x) + implicit def from(x: Long): Expr[Long] = Expr(x) - implicit def from(x: Boolean): Db[Boolean] = Db.apply0(x, x) + implicit def from(x: Boolean): Expr[Boolean] = Expr.apply0(x, x) - implicit def from(x: Double): Db[Double] = Db(x) + implicit def from(x: Double): Expr[Double] = Expr(x) - implicit def from(x: scala.math.BigDecimal): Db[scala.math.BigDecimal] = Db(x) + implicit def from(x: scala.math.BigDecimal): Expr[scala.math.BigDecimal] = Expr(x) - implicit def from(x: String): Db[String] = Db(x) + implicit def from(x: String): Expr[String] = Expr(x) implicit def OptionType[T](implicit inner: TypeMapper[T]): TypeMapper[Option[T]] = new TypeMapper[Option[T]] { @@ -217,52 +217,52 @@ trait Dialect extends DialectTypeMappers { } } } - implicit def DbBooleanOpsConv(v: Db[Boolean]): operations.DbBooleanOps = - new operations.DbBooleanOps(v) - implicit def DbNumericOpsConv[T: Numeric: TypeMapper]( - v: Db[T] - ): operations.DbNumericOps[T] = new operations.DbNumericOps(v) + implicit def ExprBooleanOpsConv(v: Expr[Boolean]): operations.ExprBooleanOps = + new operations.ExprBooleanOps(v) + implicit def ExprNumericOpsConv[T: Numeric: TypeMapper]( + v: Expr[T] + ): operations.ExprNumericOps[T] = new operations.ExprNumericOps(v) - implicit def DbOpsConv(v: Db[_]): operations.DbOps = new operations.DbOps(v) + implicit def ExprOpsConv(v: Expr[_]): operations.ExprOps = new operations.ExprOps(v) - implicit def DbTypedOpsConv[T: ClassTag](v: Db[T]): operations.DbTypedOps[T] = - new operations.DbTypedOps(v) + implicit def ExprTypedOpsConv[T: ClassTag](v: Expr[T]): operations.ExprTypedOps[T] = + new operations.ExprTypedOps(v) - implicit def DbOptionOpsConv[T: TypeMapper](v: Db[Option[T]]): operations.DbOptionOps[T] = - new operations.DbOptionOps(v) + implicit def ExprOptionOpsConv[T: TypeMapper](v: Expr[Option[T]]): operations.ExprOptionOps[T] = + new operations.ExprOptionOps(v) - implicit def JoinNullableOpsConv[T: TypeMapper](v: JoinNullable[Db[T]]): operations.DbOps = - new operations.DbOps(JoinNullable.toExpr(v)) + implicit def JoinNullableOpsConv[T: TypeMapper](v: JoinNullable[Expr[T]]): operations.ExprOps = + new operations.ExprOps(JoinNullable.toExpr(v)) implicit def JoinNullableOptionOpsConv[T: TypeMapper]( - v: JoinNullable[Db[T]] - ): operations.DbOptionOps[T] = - new operations.DbOptionOps(JoinNullable.toExpr(v)) + v: JoinNullable[Expr[T]] + ): operations.ExprOptionOps[T] = + new operations.ExprOptionOps(JoinNullable.toExpr(v)) - implicit def DbStringOpsConv( - v: Db[String] - ): operations.DbStringLikeOps[String] with operations.DbStringOps[String] - implicit def DbBlobOpsConv(v: Db[geny.Bytes]): operations.DbStringLikeOps[geny.Bytes] + implicit def ExprStringOpsConv( + v: Expr[String] + ): operations.ExprStringLikeOps[String] with operations.ExprStringOps[String] + implicit def ExprBlobOpsConv(v: Expr[geny.Bytes]): operations.ExprStringLikeOps[geny.Bytes] - implicit def AggNumericOpsConv[V: Numeric: TypeMapper](v: Aggregatable[Db[V]])( - implicit qr: Queryable.Row[Db[V], V] + implicit def AggNumericOpsConv[V: Numeric: TypeMapper](v: Aggregatable[Expr[V]])( + implicit qr: Queryable.Row[Expr[V], V] ): operations.AggNumericOps[V] = new operations.AggNumericOps(v) implicit def AggOpsConv[T](v: Aggregatable[T])( implicit qr: Queryable.Row[T, _] ): operations.AggOps[T] = new operations.AggOps(v) - implicit def DbAggOpsConv[T](v: Aggregatable[Db[T]]): operations.DbAggOps[T] + implicit def ExprAggOpsConv[T](v: Aggregatable[Expr[T]]): operations.ExprAggOps[T] implicit def TableOpsConv[V[_[_]]](t: Table[V]): TableOps[V] = new TableOps(t) implicit def DbApiQueryOpsConv(db: => DbApi): DbApiQueryOps = new DbApiQueryOps(this) implicit def DbApiOpsConv(db: => DbApi): DbApiOps = new DbApiOps(this) - implicit class WindowExtensions[T](e: Db[T]) { + implicit class WindowExtensions[T](e: Expr[T]) { def over = new SqlWindow[T](e, None, None, Nil, None, None, None) } // This is necessary for `runSql` to work. - implicit def DbQueryable[T](implicit mt: TypeMapper[T]): Queryable.Row[Db[T], T] = { - new Db.SqlQueryable[Db, T]() + implicit def ExprQueryable[T](implicit mt: TypeMapper[T]): Queryable.Row[Expr[T], T] = { + new Expr.SqlQueryable[Expr, T]() } } diff --git a/scalasql/src/dialects/H2Dialect.scala b/scalasql/src/dialects/H2Dialect.scala index 7d12c064..eee00e36 100644 --- a/scalasql/src/dialects/H2Dialect.scala +++ b/scalasql/src/dialects/H2Dialect.scala @@ -4,7 +4,7 @@ import scalasql.dialects.MySqlDialect.CompoundSelectRenderer import scalasql.core.{ Aggregatable, Context, - Db, + Expr, DbApi, DialectTypeMappers, JoinNullable, @@ -47,15 +47,15 @@ trait H2Dialect extends Dialect { override def put(r: PreparedStatement, idx: Int, v: T): Unit = r.setString(idx, v.toString) } - override implicit def DbStringOpsConv(v: Db[String]): H2Dialect.DbStringOps[String] = - new H2Dialect.DbStringOps(v) + override implicit def ExprStringOpsConv(v: Expr[String]): H2Dialect.ExprStringOps[String] = + new H2Dialect.ExprStringOps(v) - override implicit def DbBlobOpsConv(v: Db[geny.Bytes]): H2Dialect.DbStringLikeOps[geny.Bytes] = - new H2Dialect.DbStringLikeOps(v) + override implicit def ExprBlobOpsConv(v: Expr[geny.Bytes]): H2Dialect.ExprStringLikeOps[geny.Bytes] = + new H2Dialect.ExprStringLikeOps(v) - override implicit def DbNumericOpsConv[T: Numeric: TypeMapper]( - v: Db[T] - ): H2Dialect.DbNumericOps[T] = new H2Dialect.DbNumericOps(v) + override implicit def ExprNumericOpsConv[T: Numeric: TypeMapper]( + v: Expr[T] + ): H2Dialect.ExprNumericOps[T] = new H2Dialect.ExprNumericOps(v) override implicit def TableOpsConv[V[_[_]]](t: Table[V]): scalasql.dialects.TableOps[V] = new H2Dialect.TableOps(t) @@ -65,8 +65,8 @@ trait H2Dialect extends Dialect { new H2Dialect.Values(ts) } - implicit def DbAggOpsConv[T](v: Aggregatable[Db[T]]): operations.DbAggOps[T] = - new H2Dialect.DbAggOps(v) + implicit def ExprAggOpsConv[T](v: Aggregatable[Expr[T]]): operations.ExprAggOps[T] = + new H2Dialect.ExprAggOps(v) override implicit def DbApiOpsConv(db: => DbApi): H2Dialect.DbApiOps = new H2Dialect.DbApiOps(this) @@ -80,8 +80,8 @@ object H2Dialect extends H2Dialect { with MathOps with HyperbolicMathOps - class DbAggOps[T](v: Aggregatable[Db[T]]) extends scalasql.operations.DbAggOps[T](v) { - def mkString(sep: Db[String] = null)(implicit tm: TypeMapper[T]): Db[String] = { + class ExprAggOps[T](v: Aggregatable[Expr[T]]) extends scalasql.operations.ExprAggOps[T](v) { + def mkString(sep: Expr[String] = null)(implicit tm: TypeMapper[T]): Expr[String] = { assert( sep == null, "H2 database dialect does not support mkString separator due to a bug (?) where " + @@ -93,25 +93,25 @@ object H2Dialect extends H2Dialect { } } - class DbStringOps[T](v: Db[T]) extends DbStringLikeOps(v) with operations.DbStringOps[T] - class DbStringLikeOps[T](protected val v: Db[T]) - extends operations.DbStringLikeOps(v) + class ExprStringOps[T](v: Expr[T]) extends ExprStringLikeOps(v) with operations.ExprStringOps[T] + class ExprStringLikeOps[T](protected val v: Expr[T]) + extends operations.ExprStringLikeOps(v) with TrimOps with PadOps { - def indexOf(x: Db[T]): Db[Int] = Db { implicit ctx => sql"INSTR($v, $x)" } + def indexOf(x: Expr[T]): Expr[Int] = Expr { implicit ctx => sql"INSTR($v, $x)" } } - class DbNumericOps[T: Numeric: TypeMapper](protected val v: Db[T]) - extends operations.DbNumericOps[T](v) + class ExprNumericOps[T: Numeric: TypeMapper](protected val v: Expr[T]) + extends operations.ExprNumericOps[T](v) with BitwiseFunctionOps[T] { - def power(y: Db[T]): Db[T] = Db { implicit ctx => sql"POWER($v, $y)" } + def power(y: Expr[T]): Expr[T] = Expr { implicit ctx => sql"POWER($v, $y)" } } class TableOps[V[_[_]]](t: Table[V]) extends scalasql.dialects.TableOps[V](t) { - protected override def joinableToSelect: Select[V[Db], V[Sc]] = { + protected override def joinableToSelect: Select[V[Expr], V[Sc]] = { val ref = Table.ref(t) new SimpleSelect( - Table.metadata(t).vExpr(ref, dialectSelf).asInstanceOf[V[Db]], + Table.metadata(t).vExpr(ref, dialectSelf).asInstanceOf[V[Expr]], None, false, Seq(ref), @@ -144,7 +144,7 @@ object H2Dialect extends H2Dialect { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )( implicit qr: Queryable.Row[Q, R], @@ -160,7 +160,7 @@ object H2Dialect extends H2Dialect { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )(implicit qr: Queryable.Row[Q, R]) extends scalasql.query.SimpleSelect( @@ -173,7 +173,7 @@ object H2Dialect extends H2Dialect { groupBy0 ) with Select[Q, R] { - override def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + override def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): scalasql.query.Select[(JoinNullable[Q], JoinNullable[Q2]), (Option[R], Option[R2])] = { leftJoin(other)(on) diff --git a/scalasql/src/dialects/MySqlDialect.scala b/scalasql/src/dialects/MySqlDialect.scala index 47942e54..114ff1ca 100644 --- a/scalasql/src/dialects/MySqlDialect.scala +++ b/scalasql/src/dialects/MySqlDialect.scala @@ -21,7 +21,7 @@ import scalasql.query.{ import scalasql.core.{ Aggregatable, Context, - Db, + Expr, DbApi, DialectTypeMappers, JoinNullable, @@ -32,7 +32,7 @@ import scalasql.core.{ WithSqlExpr } import scalasql.core.SqlStr.{Renderable, SqlStringSyntax, optSeq} -import scalasql.operations.{ConcatOps, DbNumericOps, MathOps, PadOps} +import scalasql.operations.{ConcatOps, ExprNumericOps, MathOps, PadOps} import scalasql.renderer.JoinsToSql import java.sql.{JDBCType, PreparedStatement, ResultSet} @@ -81,14 +81,14 @@ trait MySqlDialect extends Dialect { override def put(r: PreparedStatement, idx: Int, v: T): Unit = r.setString(idx, v.toString) } - override implicit def DbTypedOpsConv[T: ClassTag](v: Db[T]): operations.DbTypedOps[T] = - new MySqlDialect.DbTypedOps(v) + override implicit def ExprTypedOpsConv[T: ClassTag](v: Expr[T]): operations.ExprTypedOps[T] = + new MySqlDialect.ExprTypedOps(v) - override implicit def DbStringOpsConv(v: Db[String]): MySqlDialect.DbStringOps[String] = - new MySqlDialect.DbStringOps(v) + override implicit def ExprStringOpsConv(v: Expr[String]): MySqlDialect.ExprStringOps[String] = + new MySqlDialect.ExprStringOps(v) - override implicit def DbBlobOpsConv(v: Db[geny.Bytes]): MySqlDialect.DbStringLikeOps[geny.Bytes] = - new MySqlDialect.DbStringLikeOps(v) + override implicit def ExprBlobOpsConv(v: Expr[geny.Bytes]): MySqlDialect.ExprStringLikeOps[geny.Bytes] = + new MySqlDialect.ExprStringLikeOps(v) override implicit def TableOpsConv[V[_[_]]](t: Table[V]): scalasql.dialects.TableOps[V] = new MySqlDialect.TableOps(t) @@ -107,8 +107,8 @@ trait MySqlDialect extends Dialect { implicit qr: Queryable.Row[Q, R] ) = new LateralJoinOps(wrapped) - implicit def DbAggOpsConv[T](v: Aggregatable[Db[T]]): operations.DbAggOps[T] = - new MySqlDialect.DbAggOps(v) + implicit def ExprAggOpsConv[T](v: Aggregatable[Expr[T]]): operations.ExprAggOps[T] = + new MySqlDialect.ExprAggOps(v) override implicit def DbApiOpsConv(db: => DbApi): MySqlDialect.DbApiOps = new MySqlDialect.DbApiOps(this) @@ -125,11 +125,11 @@ object MySqlDialect extends MySqlDialect { /** * Returns a random value in the range 0.0 <= x < 1.0 */ - def rand: Db[Double] = Db { implicit ctx => sql"RAND()" } + def rand: Expr[Double] = Expr { implicit ctx => sql"RAND()" } } - class DbAggOps[T](v: Aggregatable[Db[T]]) extends scalasql.operations.DbAggOps[T](v) { - def mkString(sep: Db[String] = null)(implicit tm: TypeMapper[T]): Db[String] = { + class ExprAggOps[T](v: Aggregatable[Expr[T]]) extends scalasql.operations.ExprAggOps[T](v) { + def mkString(sep: Expr[String] = null)(implicit tm: TypeMapper[T]): Expr[String] = { val sepRender = Option(sep).getOrElse(sql"''") v.aggregateExpr(expr => implicit ctx => sql"GROUP_CONCAT(CONCAT($expr, '') SEPARATOR ${sepRender})" @@ -137,10 +137,10 @@ object MySqlDialect extends MySqlDialect { } } - class DbTypedOps[T: ClassTag](v: Db[T]) extends operations.DbTypedOps(v) { + class ExprTypedOps[T: ClassTag](v: Expr[T]) extends operations.ExprTypedOps(v) { /** Equals to */ - override def ===[V: ClassTag](x: Db[V]): Db[Boolean] = Db { implicit ctx => + override def ===[V: ClassTag](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => (isNullable[T], isNullable[V]) match { case (true, true) => sql"($v <=> $x)" case _ => sql"($v = $x)" @@ -148,7 +148,7 @@ object MySqlDialect extends MySqlDialect { } /** Not equal to */ - override def !==[V: ClassTag](x: Db[V]): Db[Boolean] = Db { implicit ctx => + override def !==[V: ClassTag](x: Expr[V]): Expr[Boolean] = Expr { implicit ctx => (isNullable[T], isNullable[V]) match { case (true, true) => sql"(NOT ($v <=> $x))" case _ => sql"($v <> $x)" @@ -157,31 +157,31 @@ object MySqlDialect extends MySqlDialect { } - class DbStringOps[T](v: Db[T]) extends DbStringLikeOps(v) with operations.DbStringOps[T] - class DbStringLikeOps[T](protected val v: Db[T]) - extends operations.DbStringLikeOps(v) + class ExprStringOps[T](v: Expr[T]) extends ExprStringLikeOps(v) with operations.ExprStringOps[T] + class ExprStringLikeOps[T](protected val v: Expr[T]) + extends operations.ExprStringLikeOps(v) with PadOps { - override def +(x: Db[T]): Db[T] = Db { implicit ctx => sql"CONCAT($v, $x)" } + override def +(x: Expr[T]): Expr[T] = Expr { implicit ctx => sql"CONCAT($v, $x)" } - override def startsWith(other: Db[T]): Db[Boolean] = Db { implicit ctx => + override def startsWith(other: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE CONCAT($other, '%'))" } - override def endsWith(other: Db[T]): Db[Boolean] = Db { implicit ctx => + override def endsWith(other: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE CONCAT('%', $other))" } - override def contains(other: Db[T]): Db[Boolean] = Db { implicit ctx => + override def contains(other: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"($v LIKE CONCAT('%', $other, '%'))" } - def indexOf(x: Db[T]): Db[Int] = Db { implicit ctx => sql"POSITION($x IN $v)" } - def reverse: Db[T] = Db { implicit ctx => sql"REVERSE($v)" } + def indexOf(x: Expr[T]): Expr[Int] = Expr { implicit ctx => sql"POSITION($x IN $v)" } + def reverse: Expr[T] = Expr { implicit ctx => sql"REVERSE($v)" } } class TableOps[V[_[_]]](t: Table[V]) extends scalasql.dialects.TableOps[V](t) { override def update( - filter: V[Column] => Db[Boolean] + filter: V[Column] => Expr[Boolean] ): Update[V[Column], V[Sc]] = { val ref = Table.ref(t) val metadata = Table.metadata(t) @@ -196,10 +196,10 @@ object MySqlDialect extends MySqlDialect { ) } - protected override def joinableToSelect: Select[V[Db], V[Sc]] = { + protected override def joinableToSelect: Select[V[Expr], V[Sc]] = { val ref = Table.ref(t) new SimpleSelect( - Table.metadata(t).vExpr(ref, dialectSelf).asInstanceOf[V[Db]], + Table.metadata(t).vExpr(ref, dialectSelf).asInstanceOf[V[Expr]], None, false, Seq(ref), @@ -217,7 +217,7 @@ object MySqlDialect extends MySqlDialect { table: TableRef, set0: Seq[Column.Assignment[_]], joins: Seq[Join], - where: Seq[Db[_]] + where: Seq[Expr[_]] )(implicit qr: Queryable.Row[Q, R]) extends scalasql.query.Update.Impl[Q, R](expr, table, set0, joins, where) { @@ -226,7 +226,7 @@ object MySqlDialect extends MySqlDialect { table: TableRef = this.table, set0: Seq[Column.Assignment[_]] = this.set0, joins: Seq[Join] = this.joins, - where: Seq[Db[_]] = this.where + where: Seq[Expr[_]] = this.where )(implicit qr: Queryable.Row[Q, R], dialect: scalasql.core.DialectTypeMappers) = new Update(expr, table, set0, joins, where) @@ -240,7 +240,7 @@ object MySqlDialect extends MySqlDialect { joins0: Seq[Join], table: TableRef, set0: Seq[Column.Assignment[_]], - where0: Seq[Db[_]], + where0: Seq[Expr[_]], prevContext: Context ) extends scalasql.query.Update.Renderer(joins0, table, set0, where0, prevContext) { override lazy val updateList = set0.map { case assign => @@ -310,7 +310,7 @@ object MySqlDialect extends MySqlDialect { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )( implicit qr: Queryable.Row[Q, R], @@ -326,7 +326,7 @@ object MySqlDialect extends MySqlDialect { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )(implicit qr: Queryable.Row[Q, R]) extends scalasql.query.SimpleSelect( @@ -339,7 +339,7 @@ object MySqlDialect extends MySqlDialect { groupBy0 ) with Select[Q, R] { - override def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Db[Boolean])( + override def outerJoin[Q2, R2](other: Joinable[Q2, R2])(on: (Q, Q2) => Expr[Boolean])( implicit joinQr: Queryable.Row[Q2, R2] ): scalasql.query.Select[(JoinNullable[Q], JoinNullable[Q2]), (Option[R], Option[R2])] = { leftJoin(other)(on) diff --git a/scalasql/src/dialects/OnConflictOps.scala b/scalasql/src/dialects/OnConflictOps.scala index 9c48e925..877771a0 100644 --- a/scalasql/src/dialects/OnConflictOps.scala +++ b/scalasql/src/dialects/OnConflictOps.scala @@ -1,6 +1,6 @@ package scalasql.dialects -import scalasql.core.{Db, WithSqlExpr} +import scalasql.core.{Expr, WithSqlExpr} import scalasql.query._ trait OnConflictOps { @@ -11,8 +11,8 @@ trait OnConflictOps { implicit def OnConflictableInsertSelect[V[_[_]], C, R, R2]( query: InsertSelect[V, C, R, R2] - ): OnConflict[V[Db], Int] = { - new OnConflict[V[Db], Int](query, WithSqlExpr.get(query), query.table) + ): OnConflict[V[Expr], Int] = { + new OnConflict[V[Expr], Int](query, WithSqlExpr.get(query), query.table) } } diff --git a/scalasql/src/dialects/PostgresDialect.scala b/scalasql/src/dialects/PostgresDialect.scala index 875e6621..1b0b2edc 100644 --- a/scalasql/src/dialects/PostgresDialect.scala +++ b/scalasql/src/dialects/PostgresDialect.scala @@ -2,7 +2,7 @@ package scalasql.dialects import scalasql.core.{ Aggregatable, - Db, + Expr, DbApi, DialectTypeMappers, Queryable, @@ -25,20 +25,20 @@ trait PostgresDialect extends Dialect with ReturningDialect with OnConflictOps { override implicit def StringType: TypeMapper[String] = new PostgresStringType class PostgresStringType extends StringType { override def castTypeString = "VARCHAR" } - override implicit def DbStringOpsConv(v: Db[String]): PostgresDialect.DbStringOps[String] = - new PostgresDialect.DbStringOps(v) + override implicit def ExprStringOpsConv(v: Expr[String]): PostgresDialect.ExprStringOps[String] = + new PostgresDialect.ExprStringOps(v) - override implicit def DbBlobOpsConv( - v: Db[geny.Bytes] - ): PostgresDialect.DbStringLikeOps[geny.Bytes] = - new PostgresDialect.DbStringOps(v) + override implicit def ExprBlobOpsConv( + v: Expr[geny.Bytes] + ): PostgresDialect.ExprStringLikeOps[geny.Bytes] = + new PostgresDialect.ExprStringOps(v) implicit def LateralJoinOpsConv[C[_, _], Q, R](wrapped: JoinOps[C, Q, R] with Joinable[Q, R])( implicit qr: Queryable.Row[Q, R] ) = new LateralJoinOps(wrapped) - implicit def DbAggOpsConv[T](v: Aggregatable[Db[T]]): operations.DbAggOps[T] = - new PostgresDialect.DbAggOps(v) + implicit def ExprAggOpsConv[T](v: Aggregatable[Expr[T]]): operations.ExprAggOps[T] = + new PostgresDialect.ExprAggOps(v) implicit class SelectDistinctOnConv[Q, R](r: Select[Q, R]) { @@ -49,7 +49,7 @@ trait PostgresDialect extends Dialect with ReturningDialect with OnConflictOps { * row” of each set is unpredictable unless ORDER BY is used to ensure that the desired * row appears first. For example: */ - def distinctOn(f: Q => Db[_]): Select[Q, R] = { + def distinctOn(f: Q => Expr[_]): Select[Q, R] = { Select.withExprPrefix(r, true, implicit ctx => sql"DISTINCT ON (${f(WithSqlExpr.get(r))})") } } @@ -69,29 +69,29 @@ object PostgresDialect extends PostgresDialect { /** * Formats arguments according to a format string. This function is similar to the C function sprintf. */ - def format(template: Db[String], values: Db[_]*): Db[String] = Db { implicit ctx => + def format(template: Expr[String], values: Expr[_]*): Expr[String] = Expr { implicit ctx => sql"FORMAT($template, ${SqlStr.join(values.map(v => sql"$v"), SqlStr.commaSep)})" } /** * Returns a random value in the range 0.0 <= x < 1.0 */ - def random: Db[Double] = Db { implicit ctx => sql"RANDOM()" } + def random: Expr[Double] = Expr { implicit ctx => sql"RANDOM()" } } - class DbAggOps[T](v: Aggregatable[Db[T]]) extends scalasql.operations.DbAggOps[T](v) { - def mkString(sep: Db[String] = null)(implicit tm: TypeMapper[T]): Db[String] = { + class ExprAggOps[T](v: Aggregatable[Expr[T]]) extends scalasql.operations.ExprAggOps[T](v) { + def mkString(sep: Expr[String] = null)(implicit tm: TypeMapper[T]): Expr[String] = { val sepRender = Option(sep).getOrElse(sql"''") v.aggregateExpr(expr => implicit ctx => sql"STRING_AGG($expr || '', $sepRender)") } } - class DbStringOps[T](v: Db[T]) extends DbStringLikeOps(v) with operations.DbStringOps[T] - class DbStringLikeOps[T](protected val v: Db[T]) - extends operations.DbStringLikeOps(v) + class ExprStringOps[T](v: Expr[T]) extends ExprStringLikeOps(v) with operations.ExprStringOps[T] + class ExprStringLikeOps[T](protected val v: Expr[T]) + extends operations.ExprStringLikeOps(v) with TrimOps with PadOps { - def indexOf(x: Db[T]): Db[Int] = Db { implicit ctx => sql"POSITION($x IN $v)" } + def indexOf(x: Expr[T]): Expr[Int] = Expr { implicit ctx => sql"POSITION($x IN $v)" } - def reverse: Db[T] = Db { implicit ctx => sql"REVERSE($v)" } + def reverse: Expr[T] = Expr { implicit ctx => sql"REVERSE($v)" } } } diff --git a/scalasql/src/dialects/SqliteDialect.scala b/scalasql/src/dialects/SqliteDialect.scala index 4cd3f780..9610edf1 100644 --- a/scalasql/src/dialects/SqliteDialect.scala +++ b/scalasql/src/dialects/SqliteDialect.scala @@ -3,7 +3,7 @@ package scalasql.dialects import scalasql.core.{ Aggregatable, Context, - Db, + Expr, DbApi, DialectTypeMappers, Queryable, @@ -31,18 +31,18 @@ trait SqliteDialect extends Dialect with ReturningDialect with OnConflictOps { override implicit def InstantType: TypeMapper[Instant] = new SqliteInstantType class SqliteInstantType extends InstantType { override def castTypeString = "VARCHAR" } - override implicit def DbStringOpsConv(v: Db[String]): SqliteDialect.DbStringOps[String] = - new SqliteDialect.DbStringOps(v) + override implicit def ExprStringOpsConv(v: Expr[String]): SqliteDialect.ExprStringOps[String] = + new SqliteDialect.ExprStringOps(v) - override implicit def DbBlobOpsConv( - v: Db[geny.Bytes] - ): SqliteDialect.DbStringLikeOps[geny.Bytes] = - new SqliteDialect.DbStringLikeOps(v) + override implicit def ExprBlobOpsConv( + v: Expr[geny.Bytes] + ): SqliteDialect.ExprStringLikeOps[geny.Bytes] = + new SqliteDialect.ExprStringLikeOps(v) override implicit def TableOpsConv[V[_[_]]](t: Table[V]): scalasql.dialects.TableOps[V] = new SqliteDialect.TableOps(t) - implicit def DbAggOpsConv[T](v: Aggregatable[Db[T]]): operations.DbAggOps[T] = + implicit def ExprAggOpsConv[T](v: Aggregatable[Expr[T]]): operations.ExprAggOps[T] = new SqliteDialect.AggExprOps(v) override implicit def DbApiOpsConv(db: => DbApi): SqliteDialect.DbApiOps = @@ -59,7 +59,7 @@ object SqliteDialect extends SqliteDialect { * changes() SQL function is a wrapper around the sqlite3_changes64() C/C++ * function and hence follows the same rules for counting changes. */ - def changes: Db[Int] = Db { implicit ctx => sql"CHANGES()" } + def changes: Expr[Int] = Expr { implicit ctx => sql"CHANGES()" } /** * The total_changes() function returns the number of row changes caused by @@ -67,13 +67,13 @@ object SqliteDialect extends SqliteDialect { * was opened. This function is a wrapper around the sqlite3_total_changes64() * C/C++ interface. */ - def totalChanges: Db[Int] = Db { implicit ctx => sql"TOTAL_CHANGES()" } + def totalChanges: Expr[Int] = Expr { implicit ctx => sql"TOTAL_CHANGES()" } /** * The typeof(X) function returns a string that indicates the datatype of the * expression X: "null", "integer", "real", "text", or "blob". */ - def typeOf(v: Db[_]): Db[String] = Db { implicit ctx => sql"TYPEOF($v)" } + def typeOf(v: Expr[_]): Expr[String] = Expr { implicit ctx => sql"TYPEOF($v)" } /** * The last_insert_rowid() function returns the ROWID of the last row insert @@ -81,13 +81,13 @@ object SqliteDialect extends SqliteDialect { * last_insert_rowid() SQL function is a wrapper around the * sqlite3_last_insert_rowid() C/C++ interface function. */ - def lastInsertRowId: Db[Int] = Db { implicit ctx => sql"LAST_INSERT_ROWID()" } + def lastInsertRowId: Expr[Int] = Expr { implicit ctx => sql"LAST_INSERT_ROWID()" } /** * The random() function returns a pseudo-random integer between * -9223372036854775808 and +9223372036854775807. */ - def random: Db[Long] = Db { implicit ctx => sql"RANDOM()" } + def random: Expr[Long] = Expr { implicit ctx => sql"RANDOM()" } /** * The randomblob(N) function return an N-byte blob containing pseudo-random bytes. @@ -99,13 +99,13 @@ object SqliteDialect extends SqliteDialect { * hex(randomblob(16)) * lower(hex(randomblob(16))) */ - def randomBlob(n: Db[Int]): Db[geny.Bytes] = Db { implicit ctx => sql"RANDOMBLOB($n)" } + def randomBlob(n: Expr[Int]): Expr[geny.Bytes] = Expr { implicit ctx => sql"RANDOMBLOB($n)" } /** * The char(X1,X2,...,XN) function returns a string composed of characters * having the unicode code point values of the given integers */ - def char(values: Db[Int]*): Db[String] = Db { implicit ctx => + def char(values: Expr[Int]*): Expr[String] = Expr { implicit ctx => sql"CHAR(${SqlStr.join(values.map(v => sql"$v"), SqlStr.commaSep)})" } @@ -121,7 +121,7 @@ object SqliteDialect extends SqliteDialect { * 0.0 for numeric formats or an empty string for %s. See the built-in printf() * documentation for additional information. */ - def format(template: Db[String], values: Db[_]*): Db[String] = Db { implicit ctx => + def format(template: Expr[String], values: Expr[_]*): Expr[String] = Expr { implicit ctx => sql"FORMAT($template, ${SqlStr.join(values.map(v => sql"$v"), SqlStr.commaSep)})" } @@ -135,7 +135,7 @@ object SqliteDialect extends SqliteDialect { * "hex(12345678)" renders as "3132333435363738" not the binary representation of * the integer value "0000000000BC614E". */ - def hex(value: Db[_]): Db[String] = Db { implicit ctx => sql"HEX($value)" } + def hex(value: Expr[_]): Expr[String] = Expr { implicit ctx => sql"HEX($value)" } /** * The unhex(X,Y) function returns a BLOB value which is the decoding of the @@ -149,7 +149,7 @@ object SqliteDialect extends SqliteDialect { * digits. Hexadecimal digits in Y have no affect on the translation of X. Only * characters in Y that are not hexadecimal digits are ignored in X. */ - def unhex(value: Db[String]): Db[geny.Bytes] = Db { implicit ctx => sql"UNHEX($value)" } + def unhex(value: Expr[String]): Expr[geny.Bytes] = Expr { implicit ctx => sql"UNHEX($value)" } /** * The unhex(X,Y) function returns a BLOB value which is the decoding of the @@ -163,32 +163,32 @@ object SqliteDialect extends SqliteDialect { * digits. Hexadecimal digits in Y have no affect on the translation of X. Only * characters in Y that are not hexadecimal digits are ignored in X. */ - def zeroBlob(n: Db[Int]): Db[geny.Bytes] = Db { implicit ctx => sql"ZEROBLOB($n)" } + def zeroBlob(n: Expr[Int]): Expr[geny.Bytes] = Expr { implicit ctx => sql"ZEROBLOB($n)" } } - class AggExprOps[T](v: Aggregatable[Db[T]]) extends scalasql.operations.DbAggOps[T](v) { + class AggExprOps[T](v: Aggregatable[Expr[T]]) extends scalasql.operations.ExprAggOps[T](v) { /** TRUE if all values in a set are TRUE */ - def mkString(sep: Db[String] = null)(implicit tm: TypeMapper[T]): Db[String] = { + def mkString(sep: Expr[String] = null)(implicit tm: TypeMapper[T]): Expr[String] = { val sepRender = Option(sep).getOrElse(sql"''") v.aggregateExpr(expr => implicit ctx => sql"GROUP_CONCAT($expr || '', $sepRender)") } } - class DbStringOps[T](v: Db[T]) extends DbStringLikeOps(v) with operations.DbStringOps[T] - class DbStringLikeOps[T](protected val v: Db[T]) - extends operations.DbStringLikeOps(v) + class ExprStringOps[T](v: Expr[T]) extends ExprStringLikeOps(v) with operations.ExprStringOps[T] + class ExprStringLikeOps[T](protected val v: Expr[T]) + extends operations.ExprStringLikeOps(v) with TrimOps { - def indexOf(x: Db[T]): Db[Int] = Db { implicit ctx => sql"INSTR($v, $x)" } - def glob(x: Db[T]): Db[Boolean] = Db { implicit ctx => sql"GLOB($v, $x)" } + def indexOf(x: Expr[T]): Expr[Int] = Expr { implicit ctx => sql"INSTR($v, $x)" } + def glob(x: Expr[T]): Expr[Boolean] = Expr { implicit ctx => sql"GLOB($v, $x)" } } class TableOps[V[_[_]]](t: Table[V]) extends scalasql.dialects.TableOps[V](t) { - protected override def joinableToSelect: Select[V[Db], V[Sc]] = { + protected override def joinableToSelect: Select[V[Expr], V[Sc]] = { val ref = Table.ref(t) new SimpleSelect( - Table.metadata(t).vExpr(ref, dialectSelf).asInstanceOf[V[Db]], + Table.metadata(t).vExpr(ref, dialectSelf).asInstanceOf[V[Expr]], None, false, Seq(ref), @@ -221,7 +221,7 @@ object SqliteDialect extends SqliteDialect { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )( implicit qr: Queryable.Row[Q, R], @@ -237,7 +237,7 @@ object SqliteDialect extends SqliteDialect { preserveAll: Boolean, from: Seq[Context.From], joins: Seq[Join], - where: Seq[Db[_]], + where: Seq[Expr[_]], groupBy0: Option[GroupBy] )(implicit qr: Queryable.Row[Q, R]) extends scalasql.query.SimpleSelect( diff --git a/scalasql/src/dialects/TableOps.scala b/scalasql/src/dialects/TableOps.scala index 027b01b6..511461c0 100644 --- a/scalasql/src/dialects/TableOps.scala +++ b/scalasql/src/dialects/TableOps.scala @@ -1,11 +1,11 @@ package scalasql.dialects import scalasql.dialects.Dialect -import scalasql.core.Db +import scalasql.core.Expr import scalasql.Sc import scalasql.query.{Column, Delete, Insert, Joinable, Select, SimpleSelect, Table, Update} -class TableOps[V[_[_]]](val t: Table[V])(implicit dialect: Dialect) extends Joinable[V[Db], V[Sc]] { +class TableOps[V[_[_]]](val t: Table[V])(implicit dialect: Dialect) extends Joinable[V[Expr], V[Sc]] { import dialect.{dialectSelf => _, _} @@ -16,10 +16,10 @@ class TableOps[V[_[_]]](val t: Table[V])(implicit dialect: Dialect) extends Join protected def joinableToFromExpr = { val (ref, expr) = toFromExpr0 - (ref, expr.asInstanceOf[V[Db]]) + (ref, expr.asInstanceOf[V[Expr]]) } - protected def joinableToSelect: Select[V[Db], V[Sc]] = { + protected def joinableToSelect: Select[V[Expr], V[Sc]] = { val (ref, expr) = joinableToFromExpr new SimpleSelect(expr, None, false, Seq(ref), Nil, Nil, None)( t.containerQr, @@ -36,7 +36,7 @@ class TableOps[V[_[_]]](val t: Table[V])(implicit dialect: Dialect) extends Join * Constructs a `UPDATE` query with the given [[filter]] to select the * rows you want to delete */ - def update(filter: V[Column] => Db[Boolean]): Update[V[Column], V[Sc]] = { + def update(filter: V[Column] => Expr[Boolean]): Update[V[Column], V[Sc]] = { val (ref, expr) = toFromExpr0 new Update.Impl(expr, ref, Nil, Nil, Seq(filter(Table.metadata(t).vExpr(ref, dialect))))( t.containerQr2, @@ -56,7 +56,7 @@ class TableOps[V[_[_]]](val t: Table[V])(implicit dialect: Dialect) extends Join * Constructs a `DELETE` query with the given [[filter]] to select the * rows you want to delete */ - def delete(filter: V[Column] => Db[Boolean]): Delete[V[Column]] = { + def delete(filter: V[Column] => Expr[Boolean]): Delete[V[Column]] = { val (ref, expr) = toFromExpr0 new Delete.Impl(expr, filter(Table.metadata(t).vExpr(ref, dialect)), ref) } diff --git a/scalasql/src/package.scala b/scalasql/src/package.scala index fcaa7cf6..85fc9948 100644 --- a/scalasql/src/package.scala +++ b/scalasql/src/package.scala @@ -32,8 +32,8 @@ package object scalasql { val Queryable = core.Queryable type Queryable[Q, R] = core.Queryable[Q, R] - val Db = core.Db - type Db[T] = core.Db[T] + val Expr = core.Expr + type Expr[T] = core.Expr[T] type TypeMapper[T] = core.TypeMapper[T] diff --git a/scalasql/test/src/ConcreteTestSuites.scala b/scalasql/test/src/ConcreteTestSuites.scala index 85ee6c56..36fe3e82 100644 --- a/scalasql/test/src/ConcreteTestSuites.scala +++ b/scalasql/test/src/ConcreteTestSuites.scala @@ -1,15 +1,15 @@ package scalasql import scalasql.api.{TransactionTests, DbApiTests} import operations.{ - DbBooleanOpsTests, - DbNumericOpsTests, - DbAggNumericOpsTests, - DbAggOpsTests, - DbOpsTests, + ExprBooleanOpsTests, + ExprNumericOpsTests, + ExprAggNumericOpsTests, + ExprAggOpsTests, + ExprOpsTests, DbApiOpsTests, - DbStringOpsTests, - DbBlobOpsTests, - DbMathOpsTests + ExprStringOpsTests, + ExprBlobOpsTests, + ExprMathOpsTests } import query.{ InsertTests, @@ -62,14 +62,14 @@ package postgres { object WithCteTests extends WithCteTests with PostgresSuite object DbApiOpsTests extends DbApiOpsTests with PostgresSuite - object DbOpsTests extends DbOpsTests with PostgresSuite - object DbBooleanOpsTests extends DbBooleanOpsTests with PostgresSuite - object DbNumericOpsTests extends DbNumericOpsTests with PostgresSuite - object DbSeqNumericOpsTests extends DbAggNumericOpsTests with PostgresSuite - object DbSeqOpsTests extends DbAggOpsTests with PostgresSuite - object DbStringOpsTests extends DbStringOpsTests with PostgresSuite - object DbBlobOpsTests extends DbBlobOpsTests with PostgresSuite - object DbMathOpsTests extends DbMathOpsTests with PostgresSuite + object ExprOpsTests extends ExprOpsTests with PostgresSuite + object ExprBooleanOpsTests extends ExprBooleanOpsTests with PostgresSuite + object ExprNumericOpsTests extends ExprNumericOpsTests with PostgresSuite + object ExprSeqNumericOpsTests extends ExprAggNumericOpsTests with PostgresSuite + object ExprSeqOpsTests extends ExprAggOpsTests with PostgresSuite + object ExprStringOpsTests extends ExprStringOpsTests with PostgresSuite + object ExprBlobOpsTests extends ExprBlobOpsTests with PostgresSuite + object ExprMathOpsTests extends ExprMathOpsTests with PostgresSuite object DataTypesTests extends datatypes.DataTypesTests with PostgresSuite @@ -105,14 +105,14 @@ package hikari { object WithCteTests extends WithCteTests with HikariSuite object DbApiOpsTests extends DbApiOpsTests with HikariSuite - object DbOpsTests extends DbOpsTests with HikariSuite - object DbBooleanOpsTests extends DbBooleanOpsTests with HikariSuite - object DbNumericOpsTests extends DbNumericOpsTests with HikariSuite - object DbSeqNumericOpsTests extends DbAggNumericOpsTests with HikariSuite - object DbSeqOpsTests extends DbAggOpsTests with HikariSuite - object DbStringOpsTests extends DbStringOpsTests with HikariSuite - object DbBlobOpsTests extends DbBlobOpsTests with HikariSuite - object DbMathOpsTests extends DbMathOpsTests with HikariSuite + object ExprOpsTests extends ExprOpsTests with HikariSuite + object ExprBooleanOpsTests extends ExprBooleanOpsTests with HikariSuite + object ExprNumericOpsTests extends ExprNumericOpsTests with HikariSuite + object ExprSeqNumericOpsTests extends ExprAggNumericOpsTests with HikariSuite + object ExprSeqOpsTests extends ExprAggOpsTests with HikariSuite + object ExprStringOpsTests extends ExprStringOpsTests with HikariSuite + object ExprBlobOpsTests extends ExprBlobOpsTests with HikariSuite + object ExprMathOpsTests extends ExprMathOpsTests with HikariSuite object DataTypesTests extends datatypes.DataTypesTests with HikariSuite @@ -151,14 +151,14 @@ package mysql { object WithCteTests extends WithCteTests with MySqlSuite object DbApiOpsTests extends DbApiOpsTests with MySqlSuite - object DbOpsTests extends DbOpsTests with MySqlSuite - object DbBooleanOpsTests extends DbBooleanOpsTests with MySqlSuite - object DbNumericOpsTests extends DbNumericOpsTests with MySqlSuite - object DbSeqNumericOpsTests extends DbAggNumericOpsTests with MySqlSuite - object DbSeqOpsTests extends DbAggOpsTests with MySqlSuite - object DbStringOpsTests extends DbStringOpsTests with MySqlSuite - object DbBlobOpsTests extends DbBlobOpsTests with MySqlSuite - object DbMathOpsTests extends DbMathOpsTests with MySqlSuite + object ExprOpsTests extends ExprOpsTests with MySqlSuite + object ExprBooleanOpsTests extends ExprBooleanOpsTests with MySqlSuite + object ExprNumericOpsTests extends ExprNumericOpsTests with MySqlSuite + object ExprSeqNumericOpsTests extends ExprAggNumericOpsTests with MySqlSuite + object ExprSeqOpsTests extends ExprAggOpsTests with MySqlSuite + object ExprStringOpsTests extends ExprStringOpsTests with MySqlSuite + object ExprBlobOpsTests extends ExprBlobOpsTests with MySqlSuite + object ExprMathOpsTests extends ExprMathOpsTests with MySqlSuite object DataTypesTests extends datatypes.DataTypesTests with MySqlSuite object OptionalTests extends datatypes.OptionalTests with MySqlSuite @@ -193,15 +193,15 @@ package sqlite { object WithCteTests extends WithCteTests with SqliteSuite object DbApiOpsTests extends DbApiOpsTests with SqliteSuite - object DbOpsTests extends DbOpsTests with SqliteSuite - object DbBooleanOpsTests extends DbBooleanOpsTests with SqliteSuite - object DbNumericOpsTests extends DbNumericOpsTests with SqliteSuite - object DbSeqNumericOpsTests extends DbAggNumericOpsTests with SqliteSuite - object DbSeqOpsTests extends DbAggOpsTests with SqliteSuite - object DbStringOpsTests extends DbStringOpsTests with SqliteSuite - object DbBlobOpsTests extends DbBlobOpsTests with SqliteSuite + object ExprOpsTests extends ExprOpsTests with SqliteSuite + object ExprBooleanOpsTests extends ExprBooleanOpsTests with SqliteSuite + object ExprNumericOpsTests extends ExprNumericOpsTests with SqliteSuite + object ExprSeqNumericOpsTests extends ExprAggNumericOpsTests with SqliteSuite + object ExprSeqOpsTests extends ExprAggOpsTests with SqliteSuite + object ExprStringOpsTests extends ExprStringOpsTests with SqliteSuite + object ExprBlobOpsTests extends ExprBlobOpsTests with SqliteSuite // Sqlite doesn't support all these math operations - // object DbMathOpsTests extends DbMathOpsTests with SqliteSuite + // object ExprMathOpsTests extends ExprMathOpsTests with SqliteSuite object DataTypesTests extends datatypes.DataTypesTests with SqliteSuite object OptionalTests extends datatypes.OptionalTests with SqliteSuite @@ -238,14 +238,14 @@ package h2 { object WithCteTests extends WithCteTests with H2Suite object DbApiOpsTests extends DbApiOpsTests with H2Suite - object DbOpsTests extends DbOpsTests with H2Suite - object DbBooleanOpsTests extends DbBooleanOpsTests with H2Suite - object DbNumericOpsTests extends DbNumericOpsTests with H2Suite - object DbSeqNumericOpsTests extends DbAggNumericOpsTests with H2Suite - object DbSeqOpsTests extends DbAggOpsTests with H2Suite - object DbStringOpsTests extends DbStringOpsTests with H2Suite - object DbBlobOpsTests extends DbBlobOpsTests with H2Suite - object DbMathOpsTests extends DbMathOpsTests with H2Suite + object ExprOpsTests extends ExprOpsTests with H2Suite + object ExprBooleanOpsTests extends ExprBooleanOpsTests with H2Suite + object ExprNumericOpsTests extends ExprNumericOpsTests with H2Suite + object ExprSeqNumericOpsTests extends ExprAggNumericOpsTests with H2Suite + object ExprSeqOpsTests extends ExprAggOpsTests with H2Suite + object ExprStringOpsTests extends ExprStringOpsTests with H2Suite + object ExprBlobOpsTests extends ExprBlobOpsTests with H2Suite + object ExprMathOpsTests extends ExprMathOpsTests with H2Suite object DataTypesTests extends datatypes.DataTypesTests with H2Suite object OptionalTests extends datatypes.OptionalTests with H2Suite diff --git a/scalasql/test/src/FailureTests.scala b/scalasql/test/src/FailureTests.scala index a9f10f8b..12b84603 100644 --- a/scalasql/test/src/FailureTests.scala +++ b/scalasql/test/src/FailureTests.scala @@ -1,5 +1,5 @@ package scalasql -import scalasql.core.Db +import scalasql.core.Expr import utest._ import utils.SqliteSuite @@ -10,18 +10,18 @@ object FailureTests extends SqliteSuite { def description = "Things that should not compile or should give runtime errors" def tests = Tests { test("equals") - { -// val ex = intercept[Exception] { Db(1) == 2 } -// assert(ex.getMessage.contains("Db#equals is not defined")) +// val ex = intercept[Exception] { Expr(1) == 2 } +// assert(ex.getMessage.contains("Expr#equals is not defined")) // - assert(Db.identity(Db(1)) != Db.identity(Db(1))) - val e = Db(1) - assert(Db.identity(e) == Db.identity(e)) + assert(Expr.identity(Expr(1)) != Expr.identity(Expr(1))) + val e = Expr(1) + assert(Expr.identity(e) == Expr.identity(e)) } test("toString") - { - val ex = intercept[Exception] { Db(1).toString } - assert(ex.getMessage.contains("Db#toString is not defined")) + val ex = intercept[Exception] { Expr(1).toString } + assert(ex.getMessage.contains("Expr#toString is not defined")) - val s: String = Db.toString(Db(1)) + val s: String = Expr.toString(Expr(1)) } } diff --git a/scalasql/test/src/WorldSqlTests.scala b/scalasql/test/src/WorldSqlTests.scala index 946b7203..5f1c005a 100644 --- a/scalasql/test/src/WorldSqlTests.scala +++ b/scalasql/test/src/WorldSqlTests.scala @@ -20,7 +20,7 @@ object WorldSqlTests extends TestSuite { import scalasql._ import scalasql.H2Dialect._ // This readme will use the H2 database for simplicity, but you can change the `Dialect` - // above to other databases as necessary. ScalaSql supports H2, Sqlite, HsqlDb, + // above to other databases as necessary. ScalaSql supports H2, Sqlite, HsqlExpr, // Postgres, and MySql out of the box. The `Dialect` import provides the // various operators and functions that may be unique to each specific database // @@ -39,7 +39,7 @@ object WorldSqlTests extends TestSuite { // * [MySql](scalasql/test/src/example/MySqlExample.scala) // * [Sqlite](scalasql/test/src/example/SqliteExample.scala) // * [H2](scalasql/test/src/example/H2Example.scala) - // * [HsqlDb](scalasql/test/src/example/HsqlDbExample.scala) + // * [HsqlExpr](scalasql/test/src/example/HsqlExprExample.scala) // * [HikariCP](scalasql/test/src/example/HikariCpExample.scala) (and other connection pools) // // ### Modeling Your Schema @@ -47,7 +47,7 @@ object WorldSqlTests extends TestSuite { // Next, you need to define your data model classes. In ScalaSql, your data model // is defined using `case class`es with each field wrapped in the wrapper type // parameter `T[_]`. This allows us to re-use the same case class to represent - // both database values (when `T` is `scalasql.Db`) as well as Scala values + // both database values (when `T` is `scalasql.Expr`) as well as Scala values // (when `T` is `scalasql.Sc`). // // Here, we define three classes `Country` `City` and `CountryLanguage`, modeling @@ -150,24 +150,24 @@ object WorldSqlTests extends TestSuite { test("expr") { // +DOCS // ## Expressions - // The simplest thing you can query are `scalasql.Db`s. These represent the SQL + // The simplest thing you can query are `scalasql.Expr`s. These represent the SQL // expressions that are part of a query, and can be evaluated even without being // part of any database table. // - // Here, we construct `Db`s to represent the SQL query `1 + 3`. We can use + // Here, we construct `Expr`s to represent the SQL query `1 + 3`. We can use // `db.renderSql` to see the generated SQL code, and `db.run` to send the // query to the database and return the output `4` - val query = Db(1) + Db(3) + val query = Expr(1) + Expr(3) db.renderSql(query) ==> "SELECT (? + ?) AS res" db.run(query) ==> 4 // In general, most primitive types that can be mapped to SQL can be converted - // to `scalasql.Db`s: `Int`s and other numeric types, `String`s, `Boolean`s, - // etc., each returning an `Db[T]` for the respective type `T`. Each type of - // `Db[T]` has a set of operations representing what operations the database + // to `scalasql.Expr`s: `Int`s and other numeric types, `String`s, `Boolean`s, + // etc., each returning an `Expr[T]` for the respective type `T`. Each type of + // `Expr[T]` has a set of operations representing what operations the database // supports on that type of expression. // // You can check out the [ScalaSql Reference](reference.md#exprops) if you want a - // comprehensive list of built-in operations on various `Db[T]` types. + // comprehensive list of built-in operations on various `Expr[T]` types. // // -DOCS } @@ -233,13 +233,13 @@ object WorldSqlTests extends TestSuite { db.run(query) ==> City[Sc](3208, "Singapore", "SGP", district = "", population = 4017733) // Note that we use `===` rather than `==` for the equality comparison. The - // function literal passed to `.filter` is given a `City[Db]` as its parameter, + // function literal passed to `.filter` is given a `City[Expr]` as its parameter, // representing a `City` that is part of the database query, in contrast to the - // `City[Sc]`s that `db.run` returns , and so `_.name` is of type `Db[String]` + // `City[Sc]`s that `db.run` returns , and so `_.name` is of type `Expr[String]` // rather than just `String` or `Sc[String]`. You can use your IDE's - // auto-complete to see what operations are available on `Db[String]`: typically + // auto-complete to see what operations are available on `Expr[String]`: typically // they will represent SQL string functions rather than Scala string functions and - // take and return `Db[String]`s rather than plain Scala `String`s. Database + // take and return `Expr[String]`s rather than plain Scala `String`s. Database // value equality is represented by the `===` operator. // // Note also the `.single` operator. This tells ScalaSql that you expect exactly @@ -315,9 +315,9 @@ object WorldSqlTests extends TestSuite { City[Sc](1890, "Shanghai", "CHN", district = "Shanghai", population = 9696300), City[Sc](1891, "Peking", "CHN", district = "Peking", population = 7472000) ) - // Again, all the operations within the query work on `Db`s: `c` is a `City[Db]`, - // `c.population` is an `Db[Int]`, `c.countryCode` is an `Db[String]`, and - // `===` and `>` and `&&` on `Db`s all return `Db[Boolean]`s that represent + // Again, all the operations within the query work on `Expr`s: `c` is a `City[Expr]`, + // `c.population` is an `Expr[Int]`, `c.countryCode` is an `Expr[String]`, and + // `===` and `>` and `&&` on `Expr`s all return `Expr[Boolean]`s that represent // a SQL expression that can be sent to the Database as part of your query. // -DOCS } @@ -350,10 +350,10 @@ object WorldSqlTests extends TestSuite { test("implicit") { // +DOCS // ### Lifting - // Conversion of simple primitive `T`s into `Db[T]`s happens implicitly. Below, - // `===` expects both left-hand and right-hand values to be `Db`s. `_.id` is - // already an `Db[Int]`, but `cityId` is a normal `Int` that is "lifted" into - // a `Db[Int]` automatically + // Conversion of simple primitive `T`s into `Expr[T]`s happens implicitly. Below, + // `===` expects both left-hand and right-hand values to be `Expr`s. `_.id` is + // already an `Expr[Int]`, but `cityId` is a normal `Int` that is "lifted" into + // a `Expr[Int]` automatically def find(cityId: Int) = db.run(City.select.filter(_.id === cityId)) assert(find(3208) == List(City[Sc](3208, "Singapore", "SGP", "", 4017733))) @@ -368,9 +368,9 @@ object WorldSqlTests extends TestSuite { test("explicit") { // +DOCS - // This implicit lifting can be done explicitly using the `Db(...)` syntax + // This implicit lifting can be done explicitly using the `Expr(...)` syntax // as shown below - def find(cityId: Int) = db.run(City.select.filter(_.id === Db(cityId))) + def find(cityId: Int) = db.run(City.select.filter(_.id === Expr(cityId))) assert(find(3208) == List(City[Sc](3208, "Singapore", "SGP", "", 4017733))) assert(find(3209) == List(City[Sc](3209, "Bratislava", "SVK", "Bratislava", 448292))) @@ -575,10 +575,10 @@ object WorldSqlTests extends TestSuite { // ### Nullable Columns // // Nullable SQL columns are modeled via `T[Option[V]]` fields in your `case class`, - // meaning `Db[Option[V]]` in your query and meaning `Sc[Option[V]]` (or just - // meaning `Option[V]`) in the returned data. `Db[Option[V]]` supports a similar + // meaning `Expr[Option[V]]` in your query and meaning `Sc[Option[V]]` (or just + // meaning `Option[V]`) in the returned data. `Expr[Option[V]]` supports a similar // set of operations as `Option[V]`: `isDefined`, `isEmpty`, `map`, `flatMap`, `get`, - // `orElse`, etc., but returning `Db[V]`s rather than plain `V`s. + // `orElse`, etc., but returning `Expr[V]`s rather than plain `V`s. val query = Country.select .filter(_.capital.isEmpty) .size @@ -699,10 +699,10 @@ object WorldSqlTests extends TestSuite { ) // Note that when you use a left/right/outer join, the corresponding // rows are provided to you as `scalasql.JoinNullable[T]` rather than plain `T`s, e.g. - // `cityOpt: scalasql.JoinNullable[City[Db]]` above. `JoinNullable[T]` can be checked + // `cityOpt: scalasql.JoinNullable[City[Expr]]` above. `JoinNullable[T]` can be checked // for presence/absence using `.isEmpty` and specifying a specific column to check, - // and can be converted to an `Db[Option[T]]` by `.map`ing itt to a particular - // `Db[T]`. + // and can be converted to an `Expr[Option[T]]` by `.map`ing itt to a particular + // `Expr[T]`. // // -DOCS } @@ -861,7 +861,7 @@ object WorldSqlTests extends TestSuite { // +DOCS // ## Window Functions // ScalaSql supports window functions via the `.over` operator, which - // enables the `.partitionBy` and `.sortBy` operators on `Db[T]`. These + // enables the `.partitionBy` and `.sortBy` operators on `Expr[T]`. These // translate into SQL's `OVER`/`PARTITION BY`/`ORDER BY` clauses val query = City.select .map(c => @@ -1182,7 +1182,7 @@ object WorldSqlTests extends TestSuite { c => (c.name, c.countryCode, c.district, c.population), City.select .filter(_.name === "Singapore") - .map(c => (Db("New-") + c.name, c.countryCode, c.district, Db(0L))) + .map(c => (Expr("New-") + c.name, c.countryCode, c.district, Expr(0L))) ) db.renderSql(query) ==> """ @@ -1370,15 +1370,15 @@ object WorldSqlTests extends TestSuite { // +DOCS // ## Custom Expressions // - // You can define custom SQL expressions via the `Db` constructor. This is + // You can define custom SQL expressions via the `Expr` constructor. This is // useful for enclosing ScalaSql when you need to use some operator or syntax // that your Database supports but ScalaSql does not have built in. This example - // shows how to define a custom `rawToHex` Scala function working on `Db[T]`s, + // shows how to define a custom `rawToHex` Scala function working on `Expr[T]`s, // that translates down to the H2 database's `RAWTOHEX` SQL function, and finally // using that in a query to return a string. import scalasql.core.SqlStr.SqlStringSyntax - def rawToHex(v: Db[String]): Db[String] = Db { implicit ctx => sql"RAWTOHEX($v)" } + def rawToHex(v: Expr[String]): Expr[String] = Expr { implicit ctx => sql"RAWTOHEX($v)" } val query = City.select.filter(_.countryCode === "SGP").map(c => rawToHex(c.name)).single @@ -1387,12 +1387,12 @@ object WorldSqlTests extends TestSuite { db.run(query) ==> "00530069006e006700610070006f00720065" // Your custom Scala functions can either be standalone functions or extension - // methods. Most of the operators on `Db[T]` that ScalaSql comes bundled with + // methods. Most of the operators on `Expr[T]` that ScalaSql comes bundled with // are extension methods, with a different set being made available for each database. // // Different databases have a huge range of functions available. ScalaSql comes // with the most commonly-used functions built in, but it is expected that you will - // need to build up your own library of custom `Db[T]` functions to to access + // need to build up your own library of custom `Expr[T]` functions to to access // less commonly used functions that are nonetheless still needed in your application // -DOCS } diff --git a/scalasql/test/src/datatypes/OptionalTests.scala b/scalasql/test/src/datatypes/OptionalTests.scala index 5ba1a694..d43d027b 100644 --- a/scalasql/test/src/datatypes/OptionalTests.scala +++ b/scalasql/test/src/datatypes/OptionalTests.scala @@ -1,6 +1,6 @@ package scalasql.datatypes -import scalasql.core.Db +import scalasql.core.Expr import scalasql.{datatypes, _} import utest._ import utils.ScalaSqlSuite @@ -12,7 +12,7 @@ object OptCols extends Table[OptCols] trait OptionalTests extends ScalaSqlSuite { def description = - "Queries using columns that may be `NULL`, `Db[Option[T]]` or `Option[T]` in Scala" + "Queries using columns that may be `NULL`, `Expr[Option[T]]` or `Option[T]` in Scala" override def utestBeforeEach(path: Seq[String]): Unit = checker.reset() def tests = Tests { @@ -59,7 +59,7 @@ trait OptionalTests extends ScalaSqlSuite { value = Seq(None -> Some(4), Some(1) -> Some(2), Some(3) -> None), normalize = (x: Seq[(Option[Int], Option[Int])]) => x.sorted, docs = """ - Some aggregates return `Db[Option[V]]`s, et.c. `.maxByOpt` + Some aggregates return `Expr[Option[V]]`s, et.c. `.maxByOpt` """ ) @@ -73,7 +73,7 @@ trait OptionalTests extends ScalaSqlSuite { WHERE (opt_cols0.my_int IS NOT NULL)""", value = Seq(OptCols[Sc](Some(1), Some(2)), OptCols[Sc](Some(3), None)), docs = """ - `.isDefined` on `Db[Option[V]]` translates to a SQL + `.isDefined` on `Expr[Option[V]]` translates to a SQL `IS NOT NULL` check """ ) @@ -88,7 +88,7 @@ trait OptionalTests extends ScalaSqlSuite { WHERE (opt_cols0.my_int IS NULL)""", value = Seq(OptCols[Sc](None, None), OptCols[Sc](None, Some(4))), docs = """ - `.isEmpty` on `Db[Option[V]]` translates to a SQL + `.isEmpty` on `Expr[Option[V]]` translates to a SQL `IS NULL` check """ ) @@ -243,7 +243,7 @@ trait OptionalTests extends ScalaSqlSuite { } test("map") - checker( - query = Text { OptCols.select.map(d => d.copy[Db](myInt = d.myInt.map(_ + 10))) }, + query = Text { OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.map(_ + 10))) }, sql = """ SELECT (opt_cols0.my_int + ?) AS my_int, @@ -258,7 +258,7 @@ trait OptionalTests extends ScalaSqlSuite { ), docs = """ You can use operators like `.map` and `.flatMap` to work with - your `Db[Option[V]]` values. These roughly follow the semantics + your `Expr[Option[V]]` values. These roughly follow the semantics that you would be familiar with from Scala. """ ) @@ -272,7 +272,7 @@ trait OptionalTests extends ScalaSqlSuite { test("flatMap") - checker( query = Text { OptCols.select - .map(d => d.copy[Db](myInt = d.myInt.flatMap(v => d.myInt2.map(v2 => v + v2 + 10)))) + .map(d => d.copy[Expr](myInt = d.myInt.flatMap(v => d.myInt2.map(v2 => v + v2 + 10)))) }, sql = """ SELECT @@ -291,7 +291,7 @@ trait OptionalTests extends ScalaSqlSuite { test("mapGet") - checker( query = Text { - OptCols.select.map(d => d.copy[Db](myInt = d.myInt.map(_ + d.myInt2.get + 1))) + OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.map(_ + d.myInt2.get + 1))) }, sql = """ SELECT @@ -307,16 +307,16 @@ trait OptionalTests extends ScalaSqlSuite { OptCols[Sc](None, Some(4)) ), docs = """ - You can use `.get` to turn an `Db[Option[V]]` into an `Db[V]`. This follows + You can use `.get` to turn an `Expr[Option[V]]` into an `Expr[V]`. This follows SQL semantics, such that `NULL`s anywhere in that selected column automatically - will turn the whole column `None` (if it's an `Db[Option[V]]` column) or `null` + will turn the whole column `None` (if it's an `Expr[Option[V]]` column) or `null` (if it's not an optional column) """ ) test("rawGet") - checker( query = Text { - OptCols.select.map(d => d.copy[Db](myInt = d.myInt.get + d.myInt2.get + 1)) + OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.get + d.myInt2.get + 1)) }, sql = """ SELECT @@ -334,7 +334,7 @@ trait OptionalTests extends ScalaSqlSuite { ) test("getOrElse") - checker( - query = Text { OptCols.select.map(d => d.copy[Db](myInt = d.myInt.getOrElse(-1))) }, + query = Text { OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.getOrElse(-1))) }, sql = """ SELECT COALESCE(opt_cols0.my_int, ?) AS my_int, @@ -350,7 +350,7 @@ trait OptionalTests extends ScalaSqlSuite { ) test("orElse") - checker( - query = Text { OptCols.select.map(d => d.copy[Db](myInt = d.myInt.orElse(d.myInt2))) }, + query = Text { OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.orElse(d.myInt2))) }, sql = """ SELECT COALESCE(opt_cols0.my_int, opt_cols0.my_int2) AS my_int, @@ -366,7 +366,7 @@ trait OptionalTests extends ScalaSqlSuite { ) test("filter") - checker( - query = Text { OptCols.select.map(d => d.copy[Db](myInt = d.myInt.filter(_ < 2))) }, + query = Text { OptCols.select.map(d => d.copy[Expr](myInt = d.myInt.filter(_ < 2))) }, sql = """ SELECT CASE diff --git a/scalasql/test/src/dialects/H2DialectTests.scala b/scalasql/test/src/dialects/H2DialectTests.scala index 814cc122..82f8caa2 100644 --- a/scalasql/test/src/dialects/H2DialectTests.scala +++ b/scalasql/test/src/dialects/H2DialectTests.scala @@ -1,6 +1,6 @@ package scalasql.dialects -import scalasql.core.Db +import scalasql.core.Expr import scalasql.utils.H2Suite import utest._ @@ -9,25 +9,25 @@ trait H2DialectTests extends H2Suite { def tests = Tests { test("ltrim2") - checker( - query = Db("xxHellox").ltrim("x"), + query = Expr("xxHellox").ltrim("x"), sql = "SELECT LTRIM(?, ?) AS res", value = "Hellox" ) test("rtrim2") - checker( - query = Db("xxHellox").rtrim("x"), + query = Expr("xxHellox").rtrim("x"), sql = "SELECT RTRIM(?, ?) AS res", value = "xxHello" ) test("lpad") - checker( - query = Db("Hello").lpad(10, "xy"), + query = Expr("Hello").lpad(10, "xy"), sql = "SELECT LPAD(?, ?, ?) AS res", value = "xxxxxHello" // H2 only uses first character of fill string ) test("rpad") - checker( - query = Db("Hello").rpad(10, "xy"), + query = Expr("Hello").rpad(10, "xy"), sql = "SELECT RPAD(?, ?, ?) AS res", value = "Helloxxxxx" // H2 only uses first character of fill string ) diff --git a/scalasql/test/src/dialects/MySqlDialectTests.scala b/scalasql/test/src/dialects/MySqlDialectTests.scala index ac5cddd4..fcdd3097 100644 --- a/scalasql/test/src/dialects/MySqlDialectTests.scala +++ b/scalasql/test/src/dialects/MySqlDialectTests.scala @@ -1,7 +1,7 @@ package scalasql.dialects import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import sourcecode.Text import utest._ import utils.MySqlSuite @@ -13,16 +13,16 @@ trait MySqlDialectTests extends MySqlSuite { override def utestBeforeEach(path: Seq[String]): Unit = checker.reset() def tests = Tests { test("reverse") - - checker(query = Db("Hello").reverse, sql = "SELECT REVERSE(?) AS res", value = "olleH") + checker(query = Expr("Hello").reverse, sql = "SELECT REVERSE(?) AS res", value = "olleH") test("lpad") - checker( - query = Db("Hello").lpad(10, "xy"), + query = Expr("Hello").lpad(10, "xy"), sql = "SELECT LPAD(?, ?, ?) AS res", value = "xyxyxHello" ) test("rpad") - checker( - query = Db("Hello").rpad(10, "xy"), + query = Expr("Hello").rpad(10, "xy"), sql = "SELECT RPAD(?, ?, ?) AS res", value = "Helloxyxyx" ) diff --git a/scalasql/test/src/dialects/PostgresDialectTests.scala b/scalasql/test/src/dialects/PostgresDialectTests.scala index 4af32dfb..14899459 100644 --- a/scalasql/test/src/dialects/PostgresDialectTests.scala +++ b/scalasql/test/src/dialects/PostgresDialectTests.scala @@ -1,7 +1,7 @@ package scalasql.dialects import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import sourcecode.Text import utest._ import utils.PostgresSuite @@ -36,28 +36,28 @@ trait PostgresDialectTests extends PostgresSuite { ) test("ltrim2") - checker( - query = Db("xxHellox").ltrim("x"), + query = Expr("xxHellox").ltrim("x"), sql = "SELECT LTRIM(?, ?) AS res", value = "Hellox" ) test("rtrim2") - checker( - query = Db("xxHellox").rtrim("x"), + query = Expr("xxHellox").rtrim("x"), sql = "SELECT RTRIM(?, ?) AS res", value = "xxHello" ) test("reverse") - - checker(query = Db("Hello").reverse, sql = "SELECT REVERSE(?) AS res", value = "olleH") + checker(query = Expr("Hello").reverse, sql = "SELECT REVERSE(?) AS res", value = "olleH") test("lpad") - checker( - query = Db("Hello").lpad(10, "xy"), + query = Expr("Hello").lpad(10, "xy"), sql = "SELECT LPAD(?, ?, ?) AS res", value = "xyxyxHello" ) test("rpad") - checker( - query = Db("Hello").rpad(10, "xy"), + query = Expr("Hello").rpad(10, "xy"), sql = "SELECT RPAD(?, ?, ?) AS res", value = "Helloxyxyx" ) diff --git a/scalasql/test/src/dialects/SqliteDialectTests.scala b/scalasql/test/src/dialects/SqliteDialectTests.scala index 65923bc1..a2e06a46 100644 --- a/scalasql/test/src/dialects/SqliteDialectTests.scala +++ b/scalasql/test/src/dialects/SqliteDialectTests.scala @@ -1,7 +1,7 @@ package scalasql.dialects import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import utest._ import utils.SqliteSuite @@ -10,19 +10,19 @@ trait SqliteDialectTests extends SqliteSuite { def tests = Tests { test("ltrim2") - checker( - query = Db("xxHellox").ltrim("x"), + query = Expr("xxHellox").ltrim("x"), sql = "SELECT LTRIM(?, ?) AS res", value = "Hellox" ) test("rtrim2") - checker( - query = Db("xxHellox").rtrim("x"), + query = Expr("xxHellox").rtrim("x"), sql = "SELECT RTRIM(?, ?) AS res", value = "xxHello" ) test("glob") - checker( - query = Db("*cop*").glob("roflcopter"), + query = Expr("*cop*").glob("roflcopter"), sql = "SELECT GLOB(?, ?) AS res", value = true ) diff --git a/scalasql/test/src/example/CheatSheetExample.scala b/scalasql/test/src/example/CheatSheetExample.scala index 2411dad1..1463df5c 100644 --- a/scalasql/test/src/example/CheatSheetExample.scala +++ b/scalasql/test/src/example/CheatSheetExample.scala @@ -28,7 +28,7 @@ object CheatSheetExample { def main(args: Array[String]): Unit = { val db: DbApi = ??? import scalasql.SqliteDialect._ - import scalasql.core.Db + import scalasql.core.Expr val str = "hello" @@ -87,7 +87,7 @@ object CheatSheetExample { Foo.select.filter(_.myStr === "hello") // Seq[Foo[Sc]] // SELECT * FROM foo WHERE my_str = "hello" - Foo.select.filter(_.myStr === Db("hello")) // Seq[Foo[Sc]] + Foo.select.filter(_.myStr === Expr("hello")) // Seq[Foo[Sc]] // SELECT * FROM foo WHERE my_str = "hello" Foo.select.filter(_.myStr === "hello").single // Foo[Sc] diff --git a/scalasql/test/src/operations/DbAggNumericOpsTests.scala b/scalasql/test/src/operations/DbAggNumericOpsTests.scala index 78ae8737..92119c37 100644 --- a/scalasql/test/src/operations/DbAggNumericOpsTests.scala +++ b/scalasql/test/src/operations/DbAggNumericOpsTests.scala @@ -4,8 +4,8 @@ import scalasql._ import utest._ import utils.ScalaSqlSuite -trait DbAggNumericOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[Seq[T]]` where `T` is numeric" +trait ExprAggNumericOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[Seq[T]]` where `T` is numeric" def tests = Tests { test("sum") - checker( query = Purchase.select.map(_.count).sum, diff --git a/scalasql/test/src/operations/DbAggOpsTests.scala b/scalasql/test/src/operations/DbAggOpsTests.scala index 8703f4e5..cd49e6b0 100644 --- a/scalasql/test/src/operations/DbAggOpsTests.scala +++ b/scalasql/test/src/operations/DbAggOpsTests.scala @@ -5,8 +5,8 @@ import scalasql.H2Dialect import utest._ import utils.ScalaSqlSuite -trait DbAggOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[Seq[_]]`" +trait ExprAggOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[Seq[_]]`" def tests = Tests { test("size") - checker( query = Purchase.select.size, diff --git a/scalasql/test/src/operations/DbApiOpsTests.scala b/scalasql/test/src/operations/DbApiOpsTests.scala index 9f7fdd91..f16e4651 100644 --- a/scalasql/test/src/operations/DbApiOpsTests.scala +++ b/scalasql/test/src/operations/DbApiOpsTests.scala @@ -1,12 +1,12 @@ package scalasql.operations import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import scalasql.core.SqlStr.SqlStringSyntax import scalasql.utils.ScalaSqlSuite import utest._ trait DbApiOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[T]` for any `T`" + def description = "Operations that can be performed on `Expr[T]` for any `T`" def tests = Tests {} } diff --git a/scalasql/test/src/operations/DbBlobOpsTests.scala b/scalasql/test/src/operations/DbBlobOpsTests.scala index a1bf8c50..532a5c81 100644 --- a/scalasql/test/src/operations/DbBlobOpsTests.scala +++ b/scalasql/test/src/operations/DbBlobOpsTests.scala @@ -1,65 +1,65 @@ package scalasql.operations -import scalasql.{Db, Bytes} +import scalasql.{Expr, Bytes} import scalasql.utils.ScalaSqlSuite import utest._ -trait DbBlobOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[Bytes]`" +trait ExprBlobOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[Bytes]`" def tests = Tests { test("plus") - checker( - query = Db(Bytes("hello")) + Db(Bytes("world")), + query = Expr(Bytes("hello")) + Expr(Bytes("world")), sqls = Seq("SELECT (? || ?) AS res", "SELECT CONCAT(?, ?) AS res"), value = Bytes("helloworld") ) test("like") - checker( - query = Db(Bytes("hello")).like(Bytes("he%")), + query = Expr(Bytes("hello")).like(Bytes("he%")), sql = "SELECT (? LIKE ?) AS res", value = true ) test("length") - checker( - query = Db(Bytes("hello")).length, + query = Expr(Bytes("hello")).length, sql = "SELECT LENGTH(?) AS res", value = 5 ) test("octetLength") - checker( - query = Db(Bytes("叉烧包")).octetLength, + query = Expr(Bytes("叉烧包")).octetLength, sql = "SELECT OCTET_LENGTH(?) AS res", value = 9, - moreValues = Seq(6) // Not sure why HsqlDb returns different value here ??? + moreValues = Seq(6) // Not sure why HsqlExpr returns different value here ??? ) test("position") - checker( - query = Db(Bytes("hello")).indexOf(Bytes("ll")), + query = Expr(Bytes("hello")).indexOf(Bytes("ll")), sqls = Seq("SELECT POSITION(? IN ?) AS res", "SELECT INSTR(?, ?) AS res"), value = 3 ) // Not supported by postgres // // test("toLowerCase") - -// checker(query = Db(Bytes("Hello").toLowerCase, sql = "SELECT LOWER(?) AS res", value = Bytes("hello")) +// checker(query = Expr(Bytes("Hello").toLowerCase, sql = "SELECT LOWER(?) AS res", value = Bytes("hello")) // // test("trim") - -// checker(query = Db(Bytes(" Hello ").trim, sql = "SELECT TRIM(?) AS res", value = Bytes("Hello")) +// checker(query = Expr(Bytes(" Hello ").trim, sql = "SELECT TRIM(?) AS res", value = Bytes("Hello")) // // test("ltrim") - -// checker(query = Db(Bytes(" Hello ").ltrim, sql = "SELECT LTRIM(?) AS res", value = Bytes("Hello ")) +// checker(query = Expr(Bytes(" Hello ").ltrim, sql = "SELECT LTRIM(?) AS res", value = Bytes("Hello ")) // // test("rtrim") - -// checker(query = Db(Bytes(" Hello ").rtrim, sql = "SELECT RTRIM(?) AS res", value = Bytes(" Hello")) +// checker(query = Expr(Bytes(" Hello ").rtrim, sql = "SELECT RTRIM(?) AS res", value = Bytes(" Hello")) test("substring") - checker( - query = Db(Bytes("Hello")).substring(2, 2), + query = Expr(Bytes("Hello")).substring(2, 2), sql = "SELECT SUBSTRING(?, ?, ?) AS res", value = Bytes("el") ) test("startsWith") - checker( - query = Db(Bytes("Hello")).startsWith(Bytes("Hel")), + query = Expr(Bytes("Hello")).startsWith(Bytes("Hel")), sqls = Seq( "SELECT (? LIKE ? || '%') AS res", "SELECT (? LIKE CONCAT(?, '%')) AS res" @@ -68,7 +68,7 @@ trait DbBlobOpsTests extends ScalaSqlSuite { ) test("endsWith") - checker( - query = Db(Bytes("Hello")).endsWith(Bytes("llo")), + query = Expr(Bytes("Hello")).endsWith(Bytes("llo")), sqls = Seq( "SELECT (? LIKE '%' || ?) AS res", "SELECT (? LIKE CONCAT('%', ?)) AS res" @@ -77,7 +77,7 @@ trait DbBlobOpsTests extends ScalaSqlSuite { ) test("contains") - checker( - query = Db(Bytes("Hello")).contains(Bytes("ll")), + query = Expr(Bytes("Hello")).contains(Bytes("ll")), sqls = Seq( "SELECT (? LIKE '%' || ? || '%') AS res", "SELECT (? LIKE CONCAT('%', ?, '%')) AS res" @@ -86,7 +86,7 @@ trait DbBlobOpsTests extends ScalaSqlSuite { ) // Not supported by postgres // test("replace") - checker( -// query = Db(Bytes("Hello").replace(Bytes("ll"), Bytes("rr")), +// query = Expr(Bytes("Hello").replace(Bytes("ll"), Bytes("rr")), // sqls = Seq( // "SELECT REPLACE(?, ?, ?) AS res" // ), diff --git a/scalasql/test/src/operations/DbBooleanOpsTests.scala b/scalasql/test/src/operations/DbBooleanOpsTests.scala index 220a40fc..bf041146 100644 --- a/scalasql/test/src/operations/DbBooleanOpsTests.scala +++ b/scalasql/test/src/operations/DbBooleanOpsTests.scala @@ -1,21 +1,21 @@ package scalasql.operations import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import utest._ import utils.ScalaSqlSuite -trait DbBooleanOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[Boolean]`" +trait ExprBooleanOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[Boolean]`" def tests = Tests { test("and") { - checker(query = Db(true) && Db(true), sql = "SELECT (? AND ?) AS res", value = true) - checker(query = Db(false) && Db(true), sql = "SELECT (? AND ?) AS res", value = false) + checker(query = Expr(true) && Expr(true), sql = "SELECT (? AND ?) AS res", value = true) + checker(query = Expr(false) && Expr(true), sql = "SELECT (? AND ?) AS res", value = false) } test("or") { - checker(query = Db(false) || Db(false), sql = "SELECT (? OR ?) AS res", value = false) - checker(query = !Db(false), sql = "SELECT (NOT ?) AS res", value = true) + checker(query = Expr(false) || Expr(false), sql = "SELECT (? OR ?) AS res", value = false) + checker(query = !Expr(false), sql = "SELECT (NOT ?) AS res", value = true) } } } diff --git a/scalasql/test/src/operations/DbMathOpsTests.scala b/scalasql/test/src/operations/DbMathOpsTests.scala index 6d0d4154..38b3d043 100644 --- a/scalasql/test/src/operations/DbMathOpsTests.scala +++ b/scalasql/test/src/operations/DbMathOpsTests.scala @@ -4,7 +4,7 @@ import scalasql.core.DbApi import scalasql.utils.ScalaSqlSuite import utest._ -trait DbMathOpsTests extends ScalaSqlSuite { +trait ExprMathOpsTests extends ScalaSqlSuite { override implicit def DbApiOpsConv(db: => DbApi): DbApiOps with MathOps = ??? def description = "Math operations; supported by H2/Postgres/MySql, not supported by Sqlite" def tests = Tests { diff --git a/scalasql/test/src/operations/DbNumericOpsTests.scala b/scalasql/test/src/operations/DbNumericOpsTests.scala index 493f8d88..26d05474 100644 --- a/scalasql/test/src/operations/DbNumericOpsTests.scala +++ b/scalasql/test/src/operations/DbNumericOpsTests.scala @@ -1,68 +1,68 @@ package scalasql.operations import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import utest._ import utils.ScalaSqlSuite -trait DbNumericOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[T]` when `T` is numeric" +trait ExprNumericOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[T]` when `T` is numeric" def tests = Tests { - test("plus") - checker(query = Db(6) + Db(2), sql = "SELECT (? + ?) AS res", value = 8) + test("plus") - checker(query = Expr(6) + Expr(2), sql = "SELECT (? + ?) AS res", value = 8) - test("minus") - checker(query = Db(6) - Db(2), sql = "SELECT (? - ?) AS res", value = 4) + test("minus") - checker(query = Expr(6) - Expr(2), sql = "SELECT (? - ?) AS res", value = 4) - test("times") - checker(query = Db(6) * Db(2), sql = "SELECT (? * ?) AS res", value = 12) + test("times") - checker(query = Expr(6) * Expr(2), sql = "SELECT (? * ?) AS res", value = 12) - test("divide") - checker(query = Db(6) / Db(2), sql = "SELECT (? / ?) AS res", value = 3) + test("divide") - checker(query = Expr(6) / Expr(2), sql = "SELECT (? / ?) AS res", value = 3) - test("modulo") - checker(query = Db(6) % Db(2), sql = "SELECT MOD(?, ?) AS res", value = 0) + test("modulo") - checker(query = Expr(6) % Expr(2), sql = "SELECT MOD(?, ?) AS res", value = 0) test("bitwiseAnd") - checker( - query = Db(6) & Db(2), + query = Expr(6) & Expr(2), sqls = Seq("SELECT (? & ?) AS res", "SELECT BITAND(?, ?) AS res"), value = 2 ) test("bitwiseOr") - checker( - query = Db(6) | Db(3), + query = Expr(6) | Expr(3), sqls = Seq("SELECT (? | ?) AS res", "SELECT BITOR(?, ?) AS res"), value = 7 ) test("between") - checker( - query = Db(4).between(Db(2), Db(6)), + query = Expr(4).between(Expr(2), Expr(6)), sql = "SELECT ? BETWEEN ? AND ? AS res", value = true ) - test("unaryPlus") - checker(query = +Db(-4), sql = "SELECT +? AS res", value = -4) + test("unaryPlus") - checker(query = +Expr(-4), sql = "SELECT +? AS res", value = -4) test("unaryMinus") - - checker(query = -Db(-4), sqls = Seq("SELECT -? AS res", "SELECT -(?) AS res"), value = 4) + checker(query = -Expr(-4), sqls = Seq("SELECT -? AS res", "SELECT -(?) AS res"), value = 4) test("unaryTilde") - checker( - query = ~Db(-4), + query = ~Expr(-4), sqls = Seq("SELECT ~? AS res", "SELECT BITNOT(?) AS res"), value = 3 ) - test("abs") - checker(query = Db(-4).abs, sql = "SELECT ABS(?) AS res", value = 4) + test("abs") - checker(query = Expr(-4).abs, sql = "SELECT ABS(?) AS res", value = 4) - test("mod") - checker(query = Db(8).mod(Db(3)), sql = "SELECT MOD(?, ?) AS res", value = 2) + test("mod") - checker(query = Expr(8).mod(Expr(3)), sql = "SELECT MOD(?, ?) AS res", value = 2) - test("ceil") - checker(query = Db(4.3).ceil, sql = "SELECT CEIL(?) AS res", value = 5.0) + test("ceil") - checker(query = Expr(4.3).ceil, sql = "SELECT CEIL(?) AS res", value = 5.0) - test("floor") - checker(query = Db(4.7).floor, sql = "SELECT FLOOR(?) AS res", value = 4.0) + test("floor") - checker(query = Expr(4.7).floor, sql = "SELECT FLOOR(?) AS res", value = 4.0) test("precedence") - checker( - query = (Db(2) + Db(3)) * Db(4), + query = (Expr(2) + Expr(3)) * Expr(4), sql = "SELECT ((? + ?) * ?) AS res", value = 20 ) test("sign") - checker( - query = Db(-100).sign, + query = Expr(-100).sign, sql = "SELECT SIGN(?) AS res", value = -1 ) diff --git a/scalasql/test/src/operations/DbOpsTests.scala b/scalasql/test/src/operations/DbOpsTests.scala index 461b9563..fa51b478 100644 --- a/scalasql/test/src/operations/DbOpsTests.scala +++ b/scalasql/test/src/operations/DbOpsTests.scala @@ -2,59 +2,59 @@ package scalasql.operations import scalasql._ import scalasql.core.SqlStr.SqlStringSyntax -import scalasql.core.Db +import scalasql.core.Expr import utest._ import utils.ScalaSqlSuite -trait DbOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[T]` for any `T`" +trait ExprOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[T]` for any `T`" def tests = Tests { test("numeric") { test("greaterThan") - - checker(query = Db(6) > Db(2), sql = "SELECT (? > ?) AS res", value = true) + checker(query = Expr(6) > Expr(2), sql = "SELECT (? > ?) AS res", value = true) test("lessThan") - - checker(query = Db(6) < Db(2), sql = "SELECT (? < ?) AS res", value = false) + checker(query = Expr(6) < Expr(2), sql = "SELECT (? < ?) AS res", value = false) test("greaterThanOrEquals") - - checker(query = Db(6) >= Db(2), sql = "SELECT (? >= ?) AS res", value = true) + checker(query = Expr(6) >= Expr(2), sql = "SELECT (? >= ?) AS res", value = true) test("lessThanOrEquals") - - checker(query = Db(6) <= Db(2), sql = "SELECT (? <= ?) AS res", value = false) + checker(query = Expr(6) <= Expr(2), sql = "SELECT (? <= ?) AS res", value = false) } test("string") { test("greaterThan") - - checker(query = Db("A") > Db("B"), sql = "SELECT (? > ?) AS res", value = false) + checker(query = Expr("A") > Expr("B"), sql = "SELECT (? > ?) AS res", value = false) test("lessThan") - - checker(query = Db("A") < Db("B"), sql = "SELECT (? < ?) AS res", value = true) + checker(query = Expr("A") < Expr("B"), sql = "SELECT (? < ?) AS res", value = true) test("greaterThanOrEquals") - - checker(query = Db("A") >= Db("B"), sql = "SELECT (? >= ?) AS res", value = false) + checker(query = Expr("A") >= Expr("B"), sql = "SELECT (? >= ?) AS res", value = false) test("lessThanOrEquals") - - checker(query = Db("A") <= Db("B"), sql = "SELECT (? <= ?) AS res", value = true) + checker(query = Expr("A") <= Expr("B"), sql = "SELECT (? <= ?) AS res", value = true) } test("boolean") { test("greaterThan") - - checker(query = Db(true) > Db(false), sql = "SELECT (? > ?) AS res", value = true) + checker(query = Expr(true) > Expr(false), sql = "SELECT (? > ?) AS res", value = true) test("lessThan") - - checker(query = Db(true) < Db(true), sql = "SELECT (? < ?) AS res", value = false) + checker(query = Expr(true) < Expr(true), sql = "SELECT (? < ?) AS res", value = false) test("greaterThanOrEquals") - - checker(query = Db(true) >= Db(true), sql = "SELECT (? >= ?) AS res", value = true) + checker(query = Expr(true) >= Expr(true), sql = "SELECT (? >= ?) AS res", value = true) test("lessThanOrEquals") - - checker(query = Db(true) <= Db(true), sql = "SELECT (? <= ?) AS res", value = true) + checker(query = Expr(true) <= Expr(true), sql = "SELECT (? <= ?) AS res", value = true) } test("cast") { test("byte") - checker( - query = Db(45.12).cast[Byte], + query = Expr(45.12).cast[Byte], sqls = Seq( "SELECT CAST(? AS TINYINT) AS res", "SELECT CAST(? AS INTEGER) AS res", @@ -64,7 +64,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("short") - checker( - query = Db(1234.1234).cast[Short], + query = Expr(1234.1234).cast[Short], sqls = Seq( "SELECT CAST(? AS SMALLINT) AS res", "SELECT CAST(? AS SIGNED) AS res" @@ -73,7 +73,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("int") - checker( - query = Db(1234.1234).cast[Int], + query = Expr(1234.1234).cast[Int], sqls = Seq( "SELECT CAST(? AS INTEGER) AS res", "SELECT CAST(? AS SIGNED) AS res" @@ -82,7 +82,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("long") - checker( - query = Db(1234.1234).cast[Long], + query = Expr(1234.1234).cast[Long], sqls = Seq( "SELECT CAST(? AS BIGINT) AS res", "SELECT CAST(? AS SIGNED) AS res" @@ -91,7 +91,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("string") - checker( - query = Db(1234.5678).cast[String], + query = Expr(1234.5678).cast[String], sqls = Seq( "SELECT CAST(? AS LONGVARCHAR) AS res", "SELECT CAST(? AS VARCHAR) AS res", @@ -101,7 +101,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("localdate") - checker( - query = Db("2001-02-03").cast[java.time.LocalDate], + query = Expr("2001-02-03").cast[java.time.LocalDate], sqls = Seq( "SELECT CAST(? AS DATE) AS res", "SELECT CAST(? AS VARCHAR) AS res" @@ -110,7 +110,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("localdatetime") - checker( - query = Db("2023-11-12 03:22:41").cast[java.time.LocalDateTime], + query = Expr("2023-11-12 03:22:41").cast[java.time.LocalDateTime], sqls = Seq( "SELECT CAST(? AS DATETIME) AS res", "SELECT CAST(? AS TIMESTAMP) AS res", @@ -120,7 +120,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("instant") - checker( - query = Db("2007-12-03 10:15:30.00").cast[java.time.Instant], + query = Expr("2007-12-03 10:15:30.00").cast[java.time.Instant], sqls = Seq( "SELECT CAST(? AS DATETIME) AS res", "SELECT CAST(? AS TIMESTAMP) AS res", @@ -130,7 +130,7 @@ trait DbOpsTests extends ScalaSqlSuite { ) test("castNamed") - checker( - query = Db(1234.5678).castNamed[String](sql"CHAR(3)"), + query = Expr(1234.5678).castNamed[String](sql"CHAR(3)"), sql = "SELECT CAST(? AS CHAR(3)) AS res", value = "123", moreValues = Seq("1234.5678") // SQLITE doesn't truncate on cast diff --git a/scalasql/test/src/operations/DbStringOpsTests.scala b/scalasql/test/src/operations/DbStringOpsTests.scala index d5e3d4fa..436207ae 100644 --- a/scalasql/test/src/operations/DbStringOpsTests.scala +++ b/scalasql/test/src/operations/DbStringOpsTests.scala @@ -1,76 +1,76 @@ package scalasql.operations import scalasql._ -import scalasql.core.Db +import scalasql.core.Expr import utest._ import utils.ScalaSqlSuite -trait DbStringOpsTests extends ScalaSqlSuite { - def description = "Operations that can be performed on `Db[String]`" +trait ExprStringOpsTests extends ScalaSqlSuite { + def description = "Operations that can be performed on `Expr[String]`" def tests = Tests { test("plus") - checker( - query = Db("hello") + Db("world"), + query = Expr("hello") + Expr("world"), sqls = Seq("SELECT (? || ?) AS res", "SELECT CONCAT(?, ?) AS res"), value = "helloworld" ) test("like") - checker( - query = Db("hello").like("he%"), + query = Expr("hello").like("he%"), sql = "SELECT (? LIKE ?) AS res", value = true ) test("length") - checker( - query = Db("hello").length, + query = Expr("hello").length, sql = "SELECT LENGTH(?) AS res", value = 5 ) test("octetLength") - checker( - query = Db("叉烧包").octetLength, + query = Expr("叉烧包").octetLength, sql = "SELECT OCTET_LENGTH(?) AS res", value = 9, - moreValues = Seq(6) // Not sure why HsqlDb returns different value here ??? + moreValues = Seq(6) // Not sure why HsqlExpr returns different value here ??? ) test("position") - checker( - query = Db("hello").indexOf("ll"), + query = Expr("hello").indexOf("ll"), sqls = Seq("SELECT POSITION(? IN ?) AS res", "SELECT INSTR(?, ?) AS res"), value = 3 ) test("toLowerCase") - checker( - query = Db("Hello").toLowerCase, + query = Expr("Hello").toLowerCase, sql = "SELECT LOWER(?) AS res", value = "hello" ) test("trim") - checker( - query = Db(" Hello ").trim, + query = Expr(" Hello ").trim, sql = "SELECT TRIM(?) AS res", value = "Hello" ) test("ltrim") - checker( - query = Db(" Hello ").ltrim, + query = Expr(" Hello ").ltrim, sql = "SELECT LTRIM(?) AS res", value = "Hello " ) test("rtrim") - checker( - query = Db(" Hello ").rtrim, + query = Expr(" Hello ").rtrim, sql = "SELECT RTRIM(?) AS res", value = " Hello" ) test("substring") - checker( - query = Db("Hello").substring(2, 2), + query = Expr("Hello").substring(2, 2), sql = "SELECT SUBSTRING(?, ?, ?) AS res", value = "el" ) test("startsWith") - checker( - query = Db("Hello").startsWith("Hel"), + query = Expr("Hello").startsWith("Hel"), sqls = Seq( "SELECT (? LIKE ? || '%') AS res", "SELECT (? LIKE CONCAT(?, '%')) AS res" @@ -79,7 +79,7 @@ trait DbStringOpsTests extends ScalaSqlSuite { ) test("endsWith") - checker( - query = Db("Hello").endsWith("llo"), + query = Expr("Hello").endsWith("llo"), sqls = Seq( "SELECT (? LIKE '%' || ?) AS res", "SELECT (? LIKE CONCAT('%', ?)) AS res" @@ -88,7 +88,7 @@ trait DbStringOpsTests extends ScalaSqlSuite { ) test("contains") - checker( - query = Db("Hello").contains("ll"), + query = Expr("Hello").contains("ll"), sqls = Seq( "SELECT (? LIKE '%' || ? || '%') AS res", "SELECT (? LIKE CONCAT('%', ?, '%')) AS res" @@ -97,7 +97,7 @@ trait DbStringOpsTests extends ScalaSqlSuite { ) test("replace") - checker( - query = Db("Hello").replace("ll", "rr"), + query = Expr("Hello").replace("ll", "rr"), sqls = Seq( "SELECT REPLACE(?, ?, ?) AS res" ), diff --git a/scalasql/test/src/query/JoinTests.scala b/scalasql/test/src/query/JoinTests.scala index b58ec593..b4054d42 100644 --- a/scalasql/test/src/query/JoinTests.scala +++ b/scalasql/test/src/query/JoinTests.scala @@ -275,8 +275,8 @@ trait JoinTests extends ScalaSqlSuite { ("叉烧包", Some(LocalDate.parse("2012-05-06"))) ), docs = """ - `JoinNullable[Db[T]]`s can be implicitly used as `Db[Option[T]]`s. This allows - them to participate in any database query logic than any other `Db[Option[T]]`s + `JoinNullable[Expr[T]]`s can be implicitly used as `Expr[Option[T]]`s. This allows + them to participate in any database query logic than any other `Expr[Option[T]]`s can participate in, such as being used as sort key or in computing return values (below). """ @@ -350,7 +350,7 @@ trait JoinTests extends ScalaSqlSuite { ), normalize = (x: Seq[(String, Boolean)]) => x.sorted, docs = """ - The conversion from `JoinNullable[T]` to `Db[Option[T]]` can also be performed + The conversion from `JoinNullable[T]` to `Expr[Option[T]]` can also be performed explicitly via `JoinNullable.toExpr(...)` """ ) diff --git a/scalasql/test/src/query/LateralJoinTests.scala b/scalasql/test/src/query/LateralJoinTests.scala index e202cb52..7e9fc0e6 100644 --- a/scalasql/test/src/query/LateralJoinTests.scala +++ b/scalasql/test/src/query/LateralJoinTests.scala @@ -95,7 +95,7 @@ trait LateralJoinTests extends ScalaSqlSuite { query = Text { for { b <- Buyer.select - s <- ShippingInfo.select.filter { s => b.id `=` s.buyerId }.joinLateral(_ => Db(true)) + s <- ShippingInfo.select.filter { s => b.id `=` s.buyerId }.joinLateral(_ => Expr(true)) } yield (b.name, s.shippingDate) }, sql = """ @@ -119,7 +119,7 @@ trait LateralJoinTests extends ScalaSqlSuite { test("leftJoin") - checker( query = Text { Buyer.select.leftJoinLateral(b => ShippingInfo.select.filter(b.id `=` _.buyerId))((_, _) => - Db(true) + Expr(true) ) }, sql = """ @@ -165,7 +165,7 @@ trait LateralJoinTests extends ScalaSqlSuite { query = Text { for { b <- Buyer.select - s <- ShippingInfo.select.filter(b.id `=` _.buyerId).leftJoinLateral(_ => Db(true)) + s <- ShippingInfo.select.filter(b.id `=` _.buyerId).leftJoinLateral(_ => Expr(true)) } yield (b, s) }, sql = """ diff --git a/scalasql/test/src/query/OnConflictTests.scala b/scalasql/test/src/query/OnConflictTests.scala index 4052f40e..d0ebd442 100644 --- a/scalasql/test/src/query/OnConflictTests.scala +++ b/scalasql/test/src/query/OnConflictTests.scala @@ -31,7 +31,7 @@ trait OnConflictTests extends ScalaSqlSuite { docs = """ ScalaSql's `.onConflictIgnore` translates into SQL's `ON CONFLICT DO NOTHING` - Note that H2 and HsqlDb do not support `onConflictIgnore` and `onConflictUpdate`, while + Note that H2 and HsqlExpr do not support `onConflictIgnore` and `onConflictUpdate`, while MySql only supports `onConflictUpdate` but not `onConflictIgnore`. """ ) diff --git a/scalasql/test/src/query/SelectTests.scala b/scalasql/test/src/query/SelectTests.scala index c357bc91..9ead3168 100644 --- a/scalasql/test/src/query/SelectTests.scala +++ b/scalasql/test/src/query/SelectTests.scala @@ -12,11 +12,11 @@ trait SelectTests extends ScalaSqlSuite { def tests = Tests { test("constant") - checker( - query = Text { Db(1) + Db(2) }, + query = Text { Expr(1) + Expr(2) }, sql = "SELECT (? + ?) AS res", value = 3, docs = """ - The most simple thing you can query in the database is an `Db`. These do not need + The most simple thing you can query in the database is an `Expr`. These do not need to be related to any database tables, and translate into raw `SELECT` calls without `FROM`. """ @@ -256,7 +256,7 @@ trait SelectTests extends ScalaSqlSuite { docs = """ `SELECT` queries that return a single row and column can be used as SQL expressions in standard SQL databases. In ScalaSql, this is done by the `.toExpr` method, - which turns a `Select[T]` into an `Db[T]`. Note that if the `Select` returns more + which turns a `Select[T]` into an `Expr[T]`. Note that if the `Select` returns more than one row or column, the database may select a row arbitrarily or will throw an exception at runtime (depend on implenmentation) """ @@ -515,8 +515,8 @@ trait SelectTests extends ScalaSqlSuite { ) ), docs = """ - Queries can output arbitrarily nested tuples of `Db[T]` and `case class` - instances of `Foo[Db]`, which will be de-serialized into nested tuples + Queries can output arbitrarily nested tuples of `Expr[T]` and `case class` + instances of `Foo[Expr]`, which will be de-serialized into nested tuples of `T` and `Foo[Sc]`s. The `AS` aliases assigned to each column will contain the path of indices and field names used to populate the final returned values """ diff --git a/scalasql/test/src/query/SubQueryTests.scala b/scalasql/test/src/query/SubQueryTests.scala index 2131b4fa..ee3a762a 100644 --- a/scalasql/test/src/query/SubQueryTests.scala +++ b/scalasql/test/src/query/SubQueryTests.scala @@ -383,8 +383,8 @@ trait SubQueryTests extends ScalaSqlSuite { example is contrived, it demonstrates how nested ScalaSql `.select` calls translate directly into nested SQL subqueries. - To turn the ScalaSql `Select[T]` into an `Db[T]`, you can either use - an aggregate method like `.sumBy(...): Db[Int]` that generates a `SUM(...)` + To turn the ScalaSql `Select[T]` into an `Expr[T]`, you can either use + an aggregate method like `.sumBy(...): Expr[Int]` that generates a `SUM(...)` aggregate, or via the `.toExpr` method that leaves the subquery untouched. SQL requires that subqueries used as expressions must return a single row and single column, and if the query returns some other number of rows/columns diff --git a/scalasql/test/src/query/UpdateSubQueryTests.scala b/scalasql/test/src/query/UpdateSubQueryTests.scala index a9d2c824..0befa8db 100644 --- a/scalasql/test/src/query/UpdateSubQueryTests.scala +++ b/scalasql/test/src/query/UpdateSubQueryTests.scala @@ -28,7 +28,7 @@ trait UpdateSubQueryTests extends ScalaSqlSuite { value = 6, docs = """ You can use subqueries to compute the values you want to update, using - aggregates like `.maxBy` to convert the `Select[T]` into an `Db[T]` + aggregates like `.maxBy` to convert the `Select[T]` into an `Expr[T]` """ ) diff --git a/scalasql/test/src/query/UpdateTests.scala b/scalasql/test/src/query/UpdateTests.scala index 7da9d8c7..8266ef86 100644 --- a/scalasql/test/src/query/UpdateTests.scala +++ b/scalasql/test/src/query/UpdateTests.scala @@ -115,7 +115,7 @@ trait UpdateTests extends ScalaSqlSuite { ), value = 1, docs = """ - The values assigned to columns in `Table.update` can also be computed `Db[T]`s, + The values assigned to columns in `Table.update` can also be computed `Expr[T]`s, not just literal Scala constants. This example shows how to to update the name of the row for `James Bond` with it's existing name in uppercase """ diff --git a/scalasql/test/src/utils/TestChecker.scala b/scalasql/test/src/utils/TestChecker.scala index c92d4912..ce477d1a 100644 --- a/scalasql/test/src/utils/TestChecker.scala +++ b/scalasql/test/src/utils/TestChecker.scala @@ -4,7 +4,7 @@ import com.github.vertical_blank.sqlformatter.SqlFormatter import org.testcontainers.containers.{MySQLContainer, PostgreSQLContainer} import pprint.PPrinter import scalasql.query.SubqueryRef -import scalasql.{Config, DbClient, Queryable, Db, UtestFramework} +import scalasql.{Config, DbClient, Queryable, Expr, UtestFramework} import java.sql.Connection @@ -100,7 +100,7 @@ object TestChecker { lazy val pprinter: PPrinter = PPrinter.Color.copy(additionalHandlers = { case v: SubqueryRef => pprinter.treeify(v.value, false, true) - case v: Db[_] if !v.isInstanceOf[scala.Product] => - pprinter.treeify(Db.toString(v), false, true) + case v: Expr[_] if !v.isInstanceOf[scala.Product] => + pprinter.treeify(Expr.toString(v), false, true) }) }