diff --git a/build.sbt b/build.sbt index a7edbdd3d4..36f9e3b5ef 100644 --- a/build.sbt +++ b/build.sbt @@ -79,8 +79,6 @@ lazy val jasyncModules = Seq[sbt.ClasspathDep[sbt.ProjectReference]]( ) lazy val asyncModules = Seq[sbt.ClasspathDep[sbt.ProjectReference]]( - `quill-finagle-mysql`, - `quill-finagle-postgres`, `quill-ndbc`, `quill-ndbc-postgres`, `quill-ndbc-monix` @@ -106,7 +104,6 @@ lazy val allModules = lazy val scala213Modules = baseModules ++ jsModules ++ dbModules ++ codegenModules ++ Seq[sbt.ClasspathDep[sbt.ProjectReference]]( - `quill-finagle-mysql`, `quill-cassandra`, `quill-cassandra-alpakka`, `quill-cassandra-monix`, @@ -543,34 +540,12 @@ lazy val `quill-spark` = .settings(commonNoLogSettings: _*) .settings( Test / fork := true, - libraryDependencies ++= Seq("org.apache.spark" %% "spark-sql" % "3.2.1"), + libraryDependencies ++= Seq("org.apache.spark" %% "spark-sql" % "3.4.0"), excludeDependencies ++= Seq("ch.qos.logback" % "logback-classic") ) .dependsOn(`quill-sql-jvm` % "compile->compile;test->test") .enablePlugins(MimaPlugin) -lazy val `quill-finagle-mysql` = - (project in file("quill-finagle-mysql")) - .settings(commonSettings: _*) - .settings( - Test / fork := true, - libraryDependencies ++= Seq("com.twitter" %% "finagle-mysql" % "21.9.0") - ) - .dependsOn(`quill-sql-jvm` % "compile->compile;test->test") - .enablePlugins(MimaPlugin) - -lazy val `quill-finagle-postgres` = - (project in file("quill-finagle-postgres")) - .settings(commonSettings: _*) - .settings( - Test / fork := true, - libraryDependencies ++= Seq( - "io.github.finagle" %% "finagle-postgres" % "0.12.0" - ) - ) - .dependsOn(`quill-sql-jvm` % "compile->compile;test->test") - .enablePlugins(MimaPlugin) - lazy val `quill-jasync` = (project in file("quill-jasync")) .settings(commonSettings: _*) @@ -668,8 +643,11 @@ lazy val `quill-cassandra` = .settings( Test / fork := true, libraryDependencies ++= Seq( - "com.datastax.oss" % "java-driver-core" % "4.14.1", - "org.scala-lang.modules" %% "scala-java8-compat" % "0.9.1" + "com.datastax.oss" % "java-driver-core" % "4.15.0", + (CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, 12)) => "org.scala-lang.modules" %% "scala-java8-compat" % "0.8.0" + case _ => "org.scala-lang.modules" %% "scala-java8-compat" % "1.0.2" + }) ) ) .dependsOn(`quill-core-jvm` % "compile->compile;test->test") @@ -705,8 +683,8 @@ lazy val `quill-cassandra-alpakka` = .settings( Test / fork := true, libraryDependencies ++= Seq( - "com.lightbend.akka" %% "akka-stream-alpakka-cassandra" % "3.0.4", - "com.typesafe.akka" %% "akka-testkit" % "2.6.14" % Test + "com.lightbend.akka" %% "akka-stream-alpakka-cassandra" % "6.0.1", + "com.typesafe.akka" %% "akka-testkit" % "2.8.1" % Test ) ) .dependsOn(`quill-cassandra` % "compile->compile;test->test") @@ -822,7 +800,7 @@ def excludePaths(paths: Seq[String]) = { }) } -val scala_v_12 = "2.12.16" +val scala_v_12 = "2.12.17" val scala_v_13 = "2.13.10" val scala_v_30 = "3.2.2" @@ -839,7 +817,7 @@ lazy val basicSettings = excludeFilterSettings ++ Seq( crossScalaVersions := Seq(scala_v_12, scala_v_13, scala_v_30), libraryDependencies ++= Seq( "com.lihaoyi" %% "pprint" % "0.6.6", - "org.scalatest" %%% "scalatest" % "3.2.10" % Test, + "org.scalatest" %%% "scalatest" % "3.2.16" % Test, "com.google.code.findbugs" % "jsr305" % "3.0.2" % Provided // just to avoid warnings during compilation ) ++ { if (debugMacro && isScala2) diff --git a/build/release.sh b/build/release.sh index 6bf4ea79b8..d0ac13bf1c 100755 --- a/build/release.sh +++ b/build/release.sh @@ -11,7 +11,7 @@ then echo "No Artifact Specified" fi -SBT_2_12="sbt ++2.12.16 -Dquill.macro.log=false -Dquill.scala.version=2.12.16" +SBT_2_12="sbt ++2.12.17 -Dquill.macro.log=false -Dquill.scala.version=2.12.17" SBT_2_13="sbt ++2.13.10 -Dquill.macro.log=false -Dquill.scala.version=2.13.10" SBT_3_2="sbt ++3.2.2 -Dquill.macro.log=false -Dquill.scala.version=3.2.2" diff --git a/docs/changelog.md b/docs/changelog.md index 7b92cda27c..2f8f820b4b 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -3,6 +3,10 @@ id: changelog title: "Quill Changelog" --- +# 4.7.0 + +- [Update Scala 2.12 && Drop `quill-finagle-mysql` and `quill-finagle-postgres` modules](https://github.com/zio/zio-quill/pull/2756) + # 4.6.1 - [Remove support of Scala 2.11 && Update ZIO to 2.0.12](https://github.com/zio/zio-quill/pull/2722) diff --git a/project/plugins.sbt b/project/plugins.sbt index 302a6d33f6..53632b400d 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,11 +5,11 @@ resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releas addDependencyTreePlugin addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.0") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.7") addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21") -addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.8.1") +addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.2") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.13.1") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.1") addSbtPlugin("com.etsy" % "sbt-compile-quick-plugin" % "1.4.0") diff --git a/quill-finagle-mysql/src/main/scala/io/getquill/FinagleMysqlContext.scala b/quill-finagle-mysql/src/main/scala/io/getquill/FinagleMysqlContext.scala deleted file mode 100644 index af7f79635a..0000000000 --- a/quill-finagle-mysql/src/main/scala/io/getquill/FinagleMysqlContext.scala +++ /dev/null @@ -1,251 +0,0 @@ -package io.getquill - -import java.util.TimeZone -import scala.util.Try -import com.twitter.concurrent.AsyncStream -import com.twitter.finagle.mysql.{ - Client, - IsolationLevel, - LongValue, - NullValue, - OK, - Parameter, - Row, - TimestampValue, - Transactions, - Result => MysqlResult -} -import com.twitter.util.Await -import com.twitter.util.Future -import com.twitter.util.Local -import com.typesafe.config.Config -import io.getquill.context.finagle.mysql.FinagleMysqlDecoders -import io.getquill.context.finagle.mysql.FinagleMysqlEncoders -import io.getquill.context.finagle.mysql.SingleValueRow -import io.getquill.context.sql.SqlContext -import io.getquill.util.{ContextLogger, LoadConfig} -import io.getquill.util.Messages.fail -import io.getquill.monad.TwitterFutureIOMonad -import io.getquill.context.{Context, ContextVerbStream, ContextVerbTranslate, ExecutionInfo} - -sealed trait OperationType -object OperationType { - case object Read extends OperationType - case object Write extends OperationType -} - -class FinagleMysqlContext[+N <: NamingStrategy]( - val naming: N, - client: OperationType => Client with Transactions, - private[getquill] val injectionTimeZone: TimeZone, - private[getquill] val extractionTimeZone: TimeZone -) extends Context[MySQLDialect, N] - with ContextVerbTranslate - with SqlContext[MySQLDialect, N] - with ContextVerbStream[MySQLDialect, N] - with FinagleMysqlDecoders - with FinagleMysqlEncoders - with TwitterFutureIOMonad { - - import OperationType._ - - def this(naming: N, client: Client with Transactions, injectionTimeZone: TimeZone, extractionTimeZone: TimeZone) = - this(naming, _ => client, injectionTimeZone, extractionTimeZone) - - def this(naming: N, master: Client with Transactions, slave: Client with Transactions, timeZone: TimeZone) = - this( - naming, - _ match { - case OperationType.Read => slave - case OperationType.Write => master - }, - timeZone, - timeZone - ) - - def this(naming: N, config: FinagleMysqlContextConfig) = - this(naming, config.client, config.injectionTimeZone, config.extractionTimeZone) - def this(naming: N, config: Config) = this(naming, FinagleMysqlContextConfig(config)) - def this(naming: N, configPrefix: String) = this(naming, LoadConfig(configPrefix)) - - def this(naming: N, client: Client with Transactions, timeZone: TimeZone) = this(naming, client, timeZone, timeZone) - def this(naming: N, config: FinagleMysqlContextConfig, timeZone: TimeZone) = this(naming, config.client, timeZone) - def this(naming: N, config: Config, timeZone: TimeZone) = this(naming, FinagleMysqlContextConfig(config), timeZone) - def this(naming: N, configPrefix: String, timeZone: TimeZone) = this(naming, LoadConfig(configPrefix), timeZone) - - def this(naming: N, config: FinagleMysqlContextConfig, injectionTimeZone: TimeZone, extractionTimeZone: TimeZone) = - this(naming, config.client, injectionTimeZone, extractionTimeZone) - def this(naming: N, config: Config, injectionTimeZone: TimeZone, extractionTimeZone: TimeZone) = - this(naming, FinagleMysqlContextConfig(config), injectionTimeZone, extractionTimeZone) - def this(naming: N, configPrefix: String, injectionTimeZone: TimeZone, extractionTimeZone: TimeZone) = - this(naming, LoadConfig(configPrefix), injectionTimeZone, extractionTimeZone) - - val idiom = MySQLDialect - - private val logger = ContextLogger(classOf[FinagleMysqlContext[_]]) - - override type PrepareRow = List[Parameter] - override type ResultRow = Row - - override type Result[T] = Future[T] - override type RunQueryResult[T] = List[T] - override type RunQuerySingleResult[T] = T - override type RunActionResult = Long - override type RunActionReturningResult[T] = T - override type RunBatchActionResult = List[Long] - override type RunBatchActionReturningResult[T] = List[T] - override type StreamResult[T] = Future[AsyncStream[T]] - override type Session = Unit - type Runner = Unit - override type NullChecker = LocalNullChecker - class LocalNullChecker extends BaseNullChecker { - override def apply(index: Int, row: Row): Boolean = - row.values(index) == NullValue - } - implicit val nullChecker: LocalNullChecker = new LocalNullChecker() - - protected val timestampValue = - new TimestampValue( - injectionTimeZone, - extractionTimeZone - ) - - override def close = - Await.result( - Future - .join( - client(Write).close(), - client(Read).close() - ) - .unit - ) - - private val currentClient = new Local[Client] - - def probe(sql: String) = - Try(Await.result(client(Write).query(sql))) - - def transaction[T](f: => Future[T]) = - client(Write).transaction { transactional => - currentClient.update(transactional) - f.ensure(currentClient.clear) - } - - def transactionWithIsolation[T](isolationLevel: IsolationLevel)(f: => Future[T]) = - client(Write).transactionWithIsolation(isolationLevel) { transactional => - currentClient.update(transactional) - f.ensure(currentClient.clear) - } - - override def performIO[T](io: IO[T, _], transactional: Boolean = false): Result[T] = - transactional match { - case false => super.performIO(io) - case true => transaction(super.performIO(io)) - } - - def executeQuery[T](sql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor)( - info: ExecutionInfo, - dc: Runner - ): Future[List[T]] = { - val (params, prepared) = prepare(Nil, ()) - logger.logQuery(sql, params) - withClient(Read)(_.prepare(sql).select(prepared: _*)(row => extractor(row, ()))).map(_.toList) - } - - def executeQuerySingle[T]( - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T] = identityExtractor - )(info: ExecutionInfo, dc: Runner): Future[T] = - executeQuery(sql, prepare, extractor)(info, dc).map(handleSingleResult(sql, _)) - - def executeAction(sql: String, prepare: Prepare = identityPrepare)(info: ExecutionInfo, dc: Runner): Future[Long] = { - val (params, prepared) = prepare(Nil, ()) - logger.logQuery(sql, params) - withClient(Write)(_.prepare(sql)(prepared: _*)) - .map(r => toOk(r).affectedRows) - } - - def executeActionReturning[T]( - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T], - returningAction: ReturnAction - )(info: ExecutionInfo, dc: Runner): Future[T] = { - val (params, prepared) = prepare(Nil, ()) - logger.logQuery(sql, params) - withClient(Write)(_.prepare(sql)(prepared: _*)) - .map(extractReturningValue(_, extractor)) - } - - def executeActionReturningMany[T]( - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T], - returningAction: ReturnAction - )(info: ExecutionInfo, dc: Runner): Future[List[T]] = - fail("returningMany is not supported in Finagle MySQL Context") - - def executeBatchAction[B](groups: List[BatchGroup])(info: ExecutionInfo, dc: Runner): Future[List[Long]] = - Future.collect { - groups.map { case BatchGroup(sql, prepare) => - prepare - .foldLeft(Future.value(List.newBuilder[Long])) { case (acc, prepare) => - acc.flatMap { list => - executeAction(sql, prepare)(info, dc).map(list += _) - } - } - .map(_.result()) - } - }.map(_.flatten.toList) - - def executeBatchActionReturning[T]( - groups: List[BatchGroupReturning], - extractor: Extractor[T] - )(info: ExecutionInfo, dc: Runner): Future[List[T]] = - Future.collect { - groups.map { case BatchGroupReturning(sql, column, prepare) => - prepare - .foldLeft(Future.value(List.newBuilder[T])) { case (acc, prepare) => - acc.flatMap { list => - executeActionReturning(sql, prepare, extractor, column)(info, dc).map(list += _) - } - } - .map(_.result()) - } - }.map(_.flatten.toList) - - def streamQuery[T]( - fetchSize: Option[Int], - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T] = identityExtractor - )(info: ExecutionInfo, dc: Runner): Future[AsyncStream[T]] = { - val rowsPerFetch = fetchSize.getOrElse(20) - val (params: List[Any], prepared: List[Parameter]) = prepare(Nil, ()) - logger.logQuery(sql, params) - - withClient(Read) { client => - client.cursor(sql)(rowsPerFetch, prepared: _*)(row => extractor(row, ())).map(_.stream) - } - } - - override private[getquill] def prepareParams(statement: String, prepare: Prepare): Seq[String] = - prepare(Nil, ())._2.map(param => prepareParam(param.value)) - - private def extractReturningValue[T](result: MysqlResult, extractor: Extractor[T]) = - extractor(SingleValueRow(LongValue(toOk(result).insertId)), ()) - - protected def toOk(result: MysqlResult) = - result match { - case ok: OK => ok - case error => fail(error.toString) - } - - def withClient[T](op: OperationType)(f: Client => T) = - currentClient().map { client => - f(client) - }.getOrElse { - f(client(op)) - } -} diff --git a/quill-finagle-mysql/src/main/scala/io/getquill/FinagleMysqlContextConfig.scala b/quill-finagle-mysql/src/main/scala/io/getquill/FinagleMysqlContextConfig.scala deleted file mode 100644 index 5cfc75c19c..0000000000 --- a/quill-finagle-mysql/src/main/scala/io/getquill/FinagleMysqlContextConfig.scala +++ /dev/null @@ -1,51 +0,0 @@ -package io.getquill - -import java.util.TimeZone - -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.Mysql -import com.twitter.finagle.client.DefaultPool -import com.twitter.util.Try -import com.typesafe.config.Config - -case class FinagleMysqlContextConfig(config: Config) { - - def injectionTimeZone = - Try(TimeZone.getTimeZone(config.getString("timezone.injection"))).getOrElse(TimeZone.getDefault) - def extractionTimeZone = - Try(TimeZone.getTimeZone(config.getString("timezone.extraction"))).getOrElse(TimeZone.getDefault) - def user = config.getString("user") - def password = Try(config.getString("password")).getOrElse(null) - def database = config.getString("database") - def dest = config.getString("dest") - def lowWatermark = Try(config.getInt("pool.watermark.low")).getOrElse(0) - def highWatermark = Try(config.getInt("pool.watermark.high")).getOrElse(10) - def idleTime = Try(config.getLong("pool.idleTime")).getOrElse(5L) - def bufferSize = Try(config.getInt("pool.bufferSize")).getOrElse(0) - def maxWaiters = Try(config.getInt("pool.maxWaiters")).getOrElse(Int.MaxValue) - def maxPrepareStatements = Try(config.getInt("maxPrepareStatements")).getOrElse(20) - def connectTimeout = Try(config.getLong("connectTimeout")).getOrElse(1L) - def noFailFast = Try(config.getBoolean("noFailFast")).getOrElse(false) - - def client = { - var client = Mysql.client - .withCredentials(user, password) - .withDatabase(database) - .withMaxConcurrentPrepareStatements(maxPrepareStatements) - .withTransport - .connectTimeout(connectTimeout.seconds) - .configured( - DefaultPool.Param( - low = lowWatermark, - high = highWatermark, - idleTime = idleTime.seconds, - bufferSize = bufferSize, - maxWaiters = maxWaiters - ) - ) - if (noFailFast) { - client = client.withSessionQualifier.noFailFast - } - client.newRichClient(dest) - } -} diff --git a/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/FinagleMysqlDecoders.scala b/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/FinagleMysqlDecoders.scala deleted file mode 100644 index 9003c201fa..0000000000 --- a/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/FinagleMysqlDecoders.scala +++ /dev/null @@ -1,102 +0,0 @@ -package io.getquill.context.finagle.mysql - -import java.time.{LocalDate, LocalDateTime} -import java.util.{Date, UUID} - -import com.twitter.finagle.mysql._ -import io.getquill.FinagleMysqlContext -import io.getquill.util.Messages.fail - -import scala.reflect.{ClassTag, classTag} - -trait FinagleMysqlDecoders { - this: FinagleMysqlContext[_] => - - type Decoder[T] = FinagleMysqlDecoder[T] - - case class FinagleMysqlDecoder[T](decoder: BaseDecoder[T]) extends BaseDecoder[T] { - override def apply(index: Index, row: ResultRow, session: Session) = - decoder(index, row, session) - } - - def decoder[T: ClassTag](f: PartialFunction[Value, T]): Decoder[T] = - FinagleMysqlDecoder { (index, row, session) => - val value = row.values(index) - f.lift(value).getOrElse(fail(s"Value '$value' can't be decoded to '${classTag[T].runtimeClass}'")) - } - - implicit def optionDecoder[T](implicit d: Decoder[T]): Decoder[Option[T]] = - FinagleMysqlDecoder { (index, row, session) => - row.values(index) match { - case NullValue => None - case _ => Some(d.decoder(index, row, session)) - } - } - - implicit def mappedDecoder[I, O](implicit mapped: MappedEncoding[I, O], d: Decoder[I]): Decoder[O] = - FinagleMysqlDecoder(mappedBaseDecoder(mapped, d.decoder)) - - implicit val stringDecoder: Decoder[String] = - decoder[String] { case StringValue(v) => - v - } - implicit val bigDecimalDecoder: Decoder[BigDecimal] = - decoder[BigDecimal] { case BigDecimalValue(v) => - v - } - implicit val booleanDecoder: Decoder[Boolean] = - decoder[Boolean] { - case ByteValue(v) => v == (1: Byte) - case ShortValue(v) => v == (1: Short) - case IntValue(v) => v == 1 - case LongValue(v) => v == 1L - case v: RawValue if v.typ == Type.Bit => v.bytes.head == (1: Byte) - } - implicit val byteDecoder: Decoder[Byte] = - decoder[Byte] { - case ByteValue(v) => v - case ShortValue(v) => v.toByte - } - implicit val shortDecoder: Decoder[Short] = - decoder[Short] { case ShortValue(v) => - v - } - implicit val intDecoder: Decoder[Int] = - decoder[Int] { - case IntValue(v) => v - case LongValue(v) => v.toInt - } - implicit val longDecoder: Decoder[Long] = - decoder[Long] { - case IntValue(v) => v.toLong - case LongValue(v) => v - } - implicit val floatDecoder: Decoder[Float] = - decoder[Float] { case FloatValue(v) => - v - } - implicit val doubleDecoder: Decoder[Double] = - decoder[Double] { case DoubleValue(v) => - v - } - implicit val byteArrayDecoder: Decoder[Array[Byte]] = - decoder[Array[Byte]] { case v: RawValue => - v.bytes - } - implicit val dateDecoder: Decoder[Date] = - decoder[Date] { - case `timestampValue`(v) => new Date(v.getTime) - case DateValue(d) => new Date(d.getTime) - } - - implicit val localDateDecoder: Decoder[LocalDate] = decoder[LocalDate] { - case `timestampValue`(v) => v.toLocalDateTime.toLocalDate - case DateValue(d) => d.toLocalDate - } - - implicit val localDateTimeDecoder: Decoder[LocalDateTime] = decoder[LocalDateTime] { case `timestampValue`(v) => - v.toInstant.atZone(extractionTimeZone.toZoneId).toLocalDateTime - } - - implicit val uuidDecoder: Decoder[UUID] = mappedDecoder(MappedEncoding(UUID.fromString), stringDecoder) -} diff --git a/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/FinagleMysqlEncoders.scala b/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/FinagleMysqlEncoders.scala deleted file mode 100644 index 0188ff0318..0000000000 --- a/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/FinagleMysqlEncoders.scala +++ /dev/null @@ -1,64 +0,0 @@ -package io.getquill.context.finagle.mysql - -import java.sql.Timestamp -import java.time.{LocalDate, LocalDateTime} -import java.util.{Date, UUID} - -import com.twitter.finagle.mysql.CanBeParameter._ -import com.twitter.finagle.mysql.Parameter.wrap -import com.twitter.finagle.mysql._ -import io.getquill.FinagleMysqlContext - -trait FinagleMysqlEncoders { - this: FinagleMysqlContext[_] => - - type Encoder[T] = FinagleMySqlEncoder[T] - - case class FinagleMySqlEncoder[T](encoder: BaseEncoder[T]) extends BaseEncoder[T] { - override def apply(index: Index, value: T, row: PrepareRow, session: Session) = - encoder(index, value, row, session) - } - - def encoder[T](f: T => Parameter): Encoder[T] = - FinagleMySqlEncoder((index, value, row, session) => row :+ f(value)) - - def encoder[T](implicit cbp: CanBeParameter[T]): Encoder[T] = - encoder[T]((v: T) => v: Parameter) - - private[this] val nullEncoder = encoder((_: Null) => Parameter.NullParameter) - - implicit def optionEncoder[T](implicit e: Encoder[T]): Encoder[Option[T]] = - FinagleMySqlEncoder { (index, value, row, session) => - value match { - case None => nullEncoder.encoder(index, null, row, session) - case Some(v) => e.encoder(index, v, row, session) - } - } - - implicit def mappedEncoder[I, O](implicit mapped: MappedEncoding[I, O], e: Encoder[O]): Encoder[I] = - FinagleMySqlEncoder(mappedBaseEncoder(mapped, e.encoder)) - - implicit val stringEncoder: Encoder[String] = encoder[String] - implicit val bigDecimalEncoder: Encoder[BigDecimal] = - encoder[BigDecimal] { (value: BigDecimal) => - BigDecimalValue(value): Parameter - } - implicit val booleanEncoder: Encoder[Boolean] = encoder[Boolean] - implicit val byteEncoder: Encoder[Byte] = encoder[Byte] - implicit val shortEncoder: Encoder[Short] = encoder[Short] - implicit val intEncoder: Encoder[Int] = encoder[Int] - implicit val longEncoder: Encoder[Long] = encoder[Long] - implicit val floatEncoder: Encoder[Float] = encoder[Float] - implicit val doubleEncoder: Encoder[Double] = encoder[Double] - implicit val byteArrayEncoder: Encoder[Array[Byte]] = encoder[Array[Byte]] - implicit val dateEncoder: Encoder[Date] = encoder[Date] { (value: Date) => - timestampValue(new Timestamp(value.getTime)): Parameter - } - implicit val localDateEncoder: Encoder[LocalDate] = encoder[LocalDate] { (d: LocalDate) => - DateValue(java.sql.Date.valueOf(d)): Parameter - } - implicit val localDateTimeEncoder: Encoder[LocalDateTime] = encoder[LocalDateTime] { (d: LocalDateTime) => - timestampValue(new Timestamp(d.atZone(injectionTimeZone.toZoneId).toInstant.toEpochMilli)): Parameter - } - implicit val uuidEncoder: Encoder[UUID] = mappedEncoder(MappedEncoding(_.toString), stringEncoder) -} diff --git a/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/SingleValueRow.scala b/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/SingleValueRow.scala deleted file mode 100644 index f3f0b69502..0000000000 --- a/quill-finagle-mysql/src/main/scala/io/getquill/context/finagle/mysql/SingleValueRow.scala +++ /dev/null @@ -1,10 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.finagle.mysql.Row -import com.twitter.finagle.mysql.Value - -case class SingleValueRow(value: Value) extends Row { - override val values = IndexedSeq(value) - override val fields = IndexedSeq.empty - override def indexOf(columnName: String) = None -} diff --git a/quill-finagle-mysql/src/main/scala/io/getquill/monad/TwitterFutureIOMonad.scala b/quill-finagle-mysql/src/main/scala/io/getquill/monad/TwitterFutureIOMonad.scala deleted file mode 100644 index 7b4e53d7c5..0000000000 --- a/quill-finagle-mysql/src/main/scala/io/getquill/monad/TwitterFutureIOMonad.scala +++ /dev/null @@ -1,41 +0,0 @@ -package io.getquill.monad - -import language.experimental.macros -import com.twitter.util.Future -import io.getquill.context.Context -import com.twitter.util.Try -import scala.collection.compat._ -import io.getquill.{Query, Action, BatchAction, ActionReturning, Quoted} - -trait TwitterFutureIOMonad extends IOMonad { - this: Context[_, _] => - - type Result[T] = Future[T] - - def runIO[T](quoted: Quoted[T]): IO[RunQuerySingleResult[T], Effect.Read] = macro IOMonadMacro.runIO - def runIO[T](quoted: Quoted[Query[T]]): IO[RunQueryResult[T], Effect.Read] = macro IOMonadMacro.runIO - def runIO(quoted: Quoted[Action[_]]): IO[RunActionResult, Effect.Write] = macro IOMonadMacro.runIO - def runIO[T](quoted: Quoted[ActionReturning[_, T]]): IO[RunActionReturningResult[T], Effect.Write] = - macro IOMonadMacro.runIO - def runIO(quoted: Quoted[BatchAction[Action[_]]]): IO[RunBatchActionResult, Effect.Write] = macro IOMonadMacro.runIO - def runIO[T](quoted: Quoted[BatchAction[ActionReturning[_, T]]]): IO[RunBatchActionReturningResult[T], Effect.Write] = - macro IOMonadMacro.runIO - - case class Run[T, E <: Effect](f: () => Result[T]) extends IO[T, E] - - def performIO[T](io: IO[T, _], transactional: Boolean = false): Result[T] = - io match { - case FromTry(t) => Future.const(Try.fromScala(t)) - case Run(f) => f() - case Sequence(in, cbf) => - Future - .collect(in.iterator.map(performIO(_)).iterator.to(Seq)) - .map(r => cbf.newBuilder.++=(r).result) - case TransformWith(a, fA) => - performIO(a).liftToTry - .map(_.asScala) - .flatMap(v => performIO(fA(v))) - case Transactional(io) => - performIO(io, transactional = true) - } -} diff --git a/quill-finagle-mysql/src/test/resources/application.conf b/quill-finagle-mysql/src/test/resources/application.conf deleted file mode 100644 index 1eda8a81b5..0000000000 --- a/quill-finagle-mysql/src/test/resources/application.conf +++ /dev/null @@ -1,4 +0,0 @@ -testDB.dest=${?MYSQL_HOST}":"${?MYSQL_PORT} -testDB.user=finagle -testDB.password=finagle -testDB.database=quill_test \ No newline at end of file diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/CaseClassQueryFinagleSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/CaseClassQueryFinagleSpec.scala deleted file mode 100644 index 00b7823318..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/CaseClassQueryFinagleSpec.scala +++ /dev/null @@ -1,53 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.CaseClassQuerySpec -import org.scalatest.matchers.should.Matchers._ - -class CaseClassQueryFinagleSpec extends CaseClassQuerySpec { - - val context = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeAll = - await { - testContext.transaction { - for { - _ <- testContext.run(query[Contact].delete) - _ <- testContext.run(query[Address].delete) - _ <- testContext.run(liftQuery(peopleEntries).foreach(e => peopleInsert(e))) - _ <- testContext.run(liftQuery(addressEntries).foreach(e => addressInsert(e))) - } yield {} - } - } - - "Example 1 - Single Case Class Mapping" in { - await( - testContext.run(`Ex 1 CaseClass Record Output`) - ) should contain theSameElementsAs `Ex 1 CaseClass Record Output expected result` - } - "Example 1A - Single Case Class Mapping" in { - await( - testContext.run(`Ex 1A CaseClass Record Output`) - ) should contain theSameElementsAs `Ex 1 CaseClass Record Output expected result` - } - "Example 1B - Single Case Class Mapping" in { - await( - testContext.run(`Ex 1B CaseClass Record Output`) - ) should contain theSameElementsAs `Ex 1 CaseClass Record Output expected result` - } - - "Example 2 - Single Record Mapped Join" in { - await( - testContext.run(`Ex 2 Single-Record Join`) - ) should contain theSameElementsAs `Ex 2 Single-Record Join expected result` - } - - "Example 3 - Inline Record as Filter" in { - await( - testContext.run(`Ex 3 Inline Record Usage`) - ) should contain theSameElementsAs `Ex 3 Inline Record Usage exepected result` - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/DepartmentsFinagleMysqlSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/DepartmentsFinagleMysqlSpec.scala deleted file mode 100644 index 142de2a341..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/DepartmentsFinagleMysqlSpec.scala +++ /dev/null @@ -1,42 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.util.Await -import com.twitter.util.Future -import io.getquill.context.sql.base.DepartmentsSpec - -class DepartmentsFinagleMysqlSpec extends DepartmentsSpec { - - val context = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeAll = - await { - testContext.transaction { - for { - _ <- testContext.run(query[Department].delete) - _ <- testContext.run(query[Employee].delete) - _ <- testContext.run(query[Task].delete) - - _ <- testContext.run(liftQuery(departmentEntries).foreach(e => departmentInsert(e))) - _ <- testContext.run(liftQuery(employeeEntries).foreach(e => employeeInsert(e))) - _ <- testContext.run(liftQuery(taskEntries).foreach(e => taskInsert(e))) - } yield {} - } - } - - "Example 8 - nested naive" in { - await(testContext.run(`Example 8 expertise naive`(lift(`Example 8 param`)))) mustEqual `Example 8 expected result` - } - - "Example 9 - nested db" in { - await(testContext.run(`Example 9 expertise`(lift(`Example 9 param`)))) mustEqual `Example 9 expected result` - } - - "Example 9 - streamed result" in { - await( - testContext.stream(`Example 9 expertise`(lift(`Example 9 param`))).flatMap(_.toSeq()) - ) mustEqual `Example 9 expected result` - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/FinagleMysqlContextSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/FinagleMysqlContextSpec.scala deleted file mode 100644 index dc64dd88f8..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/FinagleMysqlContextSpec.scala +++ /dev/null @@ -1,112 +0,0 @@ -package io.getquill.context.finagle.mysql - -import java.util.TimeZone - -import com.twitter.finagle.mysql -import com.twitter.finagle.mysql.{EmptyValue, Error, IsolationLevel} -import com.twitter.util._ -import io.getquill.context.sql.{TestDecoders, TestEncoders} -import io.getquill.FinagleMysqlContext -import io.getquill.Literal -import io.getquill.TestEntities -import io.getquill.base.Spec - -class FinagleMysqlContextSpec extends Spec { - - val context = testContext - import testContext._ - - def await[T](f: Future[T]) = Await.result(f) - - "run non-batched action" in { - val insert = quote { (i: Int) => - qr1.insert(_.i -> i) - } - await(testContext.run(insert(lift(1)))) mustEqual 1 - } - - "Insert with returning with single column table" in { - val inserted: Long = await(testContext.run { - qr4.insertValue(lift(TestEntity4(0))).returningGenerated(_.i) - }) - await(testContext.run(qr4.filter(_.i == lift(inserted)))).head.i mustBe inserted - } - - "SingleValueRow" in { - SingleValueRow(EmptyValue).indexOf("w/e") mustBe None - } - - "probe" in { - probe("select 1").toOption mustBe defined - } - - "performIO" in { - await(performIO(runIO(qr1.filter(_.s == "w/e")).transactional)) mustBe Nil - } - - "transactionWithIsolation" in { - await(testContext.transactionWithIsolation(IsolationLevel.ReadCommitted) { - testContext.run(qr1.filter(_.s == "w/e")) - }) mustBe Nil - } - - "different constructors" in { - new FinagleMysqlContext(Literal, "testDB", TimeZone.getDefault).close - new FinagleMysqlContext(Literal, "testDB", TimeZone.getDefault, TimeZone.getDefault).close - } - - def masterSlaveContext( - master: mysql.Client with mysql.Transactions, - slave: mysql.Client with mysql.Transactions - ): FinagleMysqlContext[Literal] = - new FinagleMysqlContext[Literal](Literal, master, slave, TimeZone.getDefault) - with TestEntities - with TestEncoders - with TestDecoders - - "master & slave client writes to master" in { - val master = new OkTestClient - val slave = new OkTestClient - val context = masterSlaveContext(master, slave) - - import context._ - await(context.run(query[TestEntity4].insertValue(TestEntity4(0)))) - - master.methodCount.get() mustBe 1 - slave.methodCount.get() mustBe 0 - } - - "master & slave client reads from slave" in { - val master = new OkTestClient - val slave = new OkTestClient - val context = masterSlaveContext(master, slave) - - import context._ - await(context.run(query[TestEntity4])) - - master.methodCount.get() mustBe 0 - slave.methodCount.get() mustBe 1 - } - - "fail in toOk" in { - object ctx extends FinagleMysqlContext(Literal, "testDB") { - override def toOk(result: mysql.Result) = super.toOk(result) - } - intercept[IllegalStateException](ctx.toOk(Error(-1, "no ok", "test"))) - ctx.close - } - - "prepare" in { - import com.twitter.finagle.mysql.Parameter - - testContext.prepareParams( - "", - (ps, session) => (Nil, ps ++: List(Parameter.of("Sarah"), Parameter.of(127))) - ) mustEqual List("'Sarah'", "127") - } - - override protected def beforeAll(): Unit = { - await(testContext.run(qr1.delete)) - () - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/FinagleMysqlEncodingSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/FinagleMysqlEncodingSpec.scala deleted file mode 100644 index e193d9db50..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/FinagleMysqlEncodingSpec.scala +++ /dev/null @@ -1,205 +0,0 @@ -package io.getquill.context.finagle.mysql - -import java.time.{LocalDate, LocalDateTime, ZoneId} -import java.util.{Date, TimeZone} - -import com.twitter.util.Await -import io.getquill.context.sql.EncodingSpec -import io.getquill.util.LoadConfig -import io.getquill.{FinagleMysqlContext, FinagleMysqlContextConfig, Literal} -import io.getquill.Query - -import scala.concurrent.duration._ - -class FinagleMysqlEncodingSpec extends EncodingSpec { - - val context = testContext - import testContext._ - - "encodes and decodes types" in { - val r = - for { - _ <- testContext.run(delete) - _ <- testContext.run(liftQuery(insertValues).foreach(e => insert(e))) - result <- testContext.run(query[EncodingTestEntity]) - } yield result - - verify(Await.result(r).toList) - } - - "fails if the column has the wrong type" in { - Await.result(testContext.run(liftQuery(insertValues).foreach(e => insert(e)))) - case class EncodingTestEntity(v1: Int) - val e = intercept[IllegalStateException] { - Await.result(testContext.run(query[EncodingTestEntity])) - } - } - - "encodes sets" in { - val q = quote { (set: Query[Int]) => - query[EncodingTestEntity].filter(t => set.contains(t.v6)) - } - Await.result { - for { - _ <- testContext.run(query[EncodingTestEntity].delete) - _ <- testContext.run(liftQuery(insertValues).foreach(e => query[EncodingTestEntity].insertValue(e))) - r <- testContext.run(q(liftQuery(insertValues.map(_.v6)))) - } yield { - verify(r) - } - } - } - - "Integer type with Long" in { - case class IntLong(o6: Long) - val entity = quote(querySchema[IntLong]("EncodingTestEntity")) - val insert = quote { - entity.insert(_.o6 -> 5589) - } - val q = quote { - entity.filter(_.o6 == 5589) - } - Await.result(testContext.run(insert)) - Await.result(testContext.run(q)).nonEmpty mustEqual true - } - - "decode boolean types" - { - case class BooleanEncodingTestEntity( - v1: Boolean, - v2: Boolean, - v3: Boolean, - v4: Boolean, - v5: Boolean, - v6: Boolean, - v7: Boolean - ) - val decodeBoolean = (entity: BooleanEncodingTestEntity) => { - val r = for { - _ <- testContext.run(query[BooleanEncodingTestEntity].delete) - _ <- testContext.run(query[BooleanEncodingTestEntity].insertValue(lift(entity))) - result <- testContext.run(query[BooleanEncodingTestEntity]) - } yield result - Await.result(r).head - } - "true" in { - val entity = BooleanEncodingTestEntity(true, true, true, true, true, true, true) - val r = decodeBoolean(entity) - r.v1 mustEqual true - r.v2 mustEqual true - r.v3 mustEqual true - r.v4 mustEqual true - r.v5 mustEqual true - r.v6 mustEqual true - r.v7 mustEqual true - } - - "false" in { - val entity = BooleanEncodingTestEntity(false, false, false, false, false, false, false) - val r = decodeBoolean(entity) - r.v1 mustEqual false - r.v2 mustEqual false - r.v3 mustEqual false - r.v4 mustEqual false - r.v5 mustEqual false - r.v6 mustEqual false - r.v7 mustEqual false - } - } - - "decode date types" - { - case class DateEncodingTestEntity( - v1: Date, - v2: Date, - v3: Date - ) - - val date = new Date - val entity = DateEncodingTestEntity(date, date, date) - - def round(milliseconds: Long, duration: Duration): Long = - Math.round(milliseconds / duration.toMillis.toDouble) * duration.toMillis - - def verify(result: DateEncodingTestEntity) = { - round(result.v1.getTime, 24.hours) mustEqual round(entity.v1.getTime, 24.hours) - result.v2.getTime mustEqual entity.v2.getTime - result.v3.getTime mustEqual entity.v3.getTime - } - - "default timezone" in { - val r = for { - _ <- testContext.run(query[DateEncodingTestEntity].delete) - _ <- testContext.run(query[DateEncodingTestEntity].insertValue(lift(entity))) - result <- testContext.run(query[DateEncodingTestEntity]) - } yield result - - verify(Await.result(r).head) - } - - "different timezone" in { - val config = FinagleMysqlContextConfig(LoadConfig("testDB")) - val testTimezoneContext = - new FinagleMysqlContext(Literal, config.client, TimeZone.getTimeZone("KST"), TimeZone.getTimeZone("UTC")) - import testTimezoneContext._ - - val r = for { - _ <- testTimezoneContext.run(query[DateEncodingTestEntity].delete) - _ <- testTimezoneContext.run(query[DateEncodingTestEntity].insertValue(lift(entity))) - result <- testTimezoneContext.run(query[DateEncodingTestEntity]) - } yield result - - // verify(Await.result(r).head) - } - } - - "decode LocalDateTime types" - { - case class LocalDateTimeEncodingTestEntity( - v1: LocalDateTime, - v2: LocalDateTime - ) - - val dt = LocalDateTime.parse("2017-01-01T00:00:00") - val entity = LocalDateTimeEncodingTestEntity(dt, dt) - - def verify(result: LocalDateTimeEncodingTestEntity) = { - result.v1 mustEqual entity.v1 - result.v2 mustEqual entity.v2 - } - - "TimeZone.setDefault() to different timezone than that of FinagleMysqlContext" in { - val config = FinagleMysqlContextConfig(LoadConfig("testDB")) - val testTimezoneContext = new FinagleMysqlContext( - Literal, - config.client, - TimeZone.getTimeZone(ZoneId.of("Asia/Tokyo")), - TimeZone.getTimeZone(ZoneId.of("Asia/Tokyo")) - ) - import testTimezoneContext._ - - val zone = TimeZone.getDefault - TimeZone.setDefault(TimeZone.getTimeZone("UTC")) - - val r = for { - _ <- testTimezoneContext.run(query[LocalDateTimeEncodingTestEntity].delete) - _ <- testTimezoneContext.run(query[LocalDateTimeEncodingTestEntity].insertValue(lift(entity))) - result <- testTimezoneContext.run(query[LocalDateTimeEncodingTestEntity]) - } yield result - - TimeZone.setDefault(zone) - - verify(Await.result(r).head) - } - } - - "timestamp as localdate" in { - case class LocalDateTimeEncodingTestEntity(v2: LocalDate) - val e = LocalDateTimeEncodingTestEntity(LocalDate.now()) - - val r = for { - _ <- testContext.run(query[LocalDateTimeEncodingTestEntity].delete) - _ <- testContext.run(query[LocalDateTimeEncodingTestEntity].insertValue(lift(e))) - result <- testContext.run(query[LocalDateTimeEncodingTestEntity]) - } yield result - - Await.result(r).headOption.map(_.v2) mustBe Some(e.v2) - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OkTestClient.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OkTestClient.scala deleted file mode 100644 index 6b12cd002a..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OkTestClient.scala +++ /dev/null @@ -1,61 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.concurrent.AsyncStream -import com.twitter.finagle.mysql -import com.twitter.util.{Future, Time} -import java.util.concurrent.atomic.AtomicInteger -import com.twitter.finagle.mysql.Transactions -import com.twitter.finagle.mysql.Session -import com.twitter.finagle.mysql.Client - -class OkTestClient extends mysql.Client with mysql.Transactions { - val methodCount = new AtomicInteger - - val ok = mysql.OK(0, 0, 0, 0, "") - - override def query(sql: String): Future[mysql.Result] = { - methodCount.incrementAndGet() - Future(ok) - } - - override def select[T](sql: String)(f: mysql.Row => T): Future[Seq[T]] = { - methodCount.incrementAndGet() - Future(Seq.empty) - } - override def prepare(sql: String): mysql.PreparedStatement = { - methodCount.incrementAndGet() - new mysql.PreparedStatement { - override def apply(params: mysql.Parameter*): Future[mysql.Result] = Future(ok) - } - } - override def cursor(sql: String): mysql.CursoredStatement = { - methodCount.incrementAndGet() - new mysql.CursoredStatement { - override def apply[T](rowsPerFetch: Int, params: mysql.Parameter*)( - f: mysql.Row => T - ): Future[mysql.CursorResult[T]] = Future { - new mysql.CursorResult[T] { - override def stream: AsyncStream[T] = AsyncStream.empty - override def close(deadline: Time): Future[Unit] = Future.Unit - } - } - } - } - - override def ping(): Future[Unit] = { - methodCount.incrementAndGet() - Future.Unit - } - - override def transaction[T](f: mysql.Client => Future[T]): Future[T] = - f(this) - override def transactionWithIsolation[T](isolationLevel: mysql.IsolationLevel)( - f: mysql.Client => Future[T] - ): Future[T] = - f(this) - - override def close(deadline: Time): Future[Unit] = Future.Unit - - def session[T](f: Client with Transactions with Session => Future[T]): Future[T] = - ??? -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OnConflictFinagleSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OnConflictFinagleSpec.scala deleted file mode 100644 index 1773545eec..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OnConflictFinagleSpec.scala +++ /dev/null @@ -1,38 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.OnConflictSpec - -class OnConflictFinagleSpec extends OnConflictSpec { - val ctx = testContext - import ctx._ - - def await[T](future: Future[T]) = Await.result(future) - - override protected def beforeAll(): Unit = { - await(ctx.run(qr1.delete)) - () - } - - "INSERT IGNORE" in { - import `onConflictIgnore`._ - await(ctx.run(testQuery1)) mustEqual res1 - await(ctx.run(testQuery2)) mustEqual res2 - await(ctx.run(testQuery3)) mustEqual res3 - } - - "ON DUPLICATE KEY UPDATE i=i " in { - import `onConflictIgnore(_.i)`._ - await(ctx.run(testQuery1)) mustEqual res1 - await(ctx.run(testQuery2)) mustEqual res2 + 1 - await(ctx.run(testQuery3)) mustEqual res3 - } - - "ON DUPLICATE KEY UPDATE ..." in { - import `onConflictUpdate((t, e) => ...)`._ - await(ctx.run(testQuery(e1))) mustEqual res1 - await(ctx.run(testQuery(e2))) mustEqual res2 + 1 - await(ctx.run(testQuery(e3))) mustEqual res3 + 1 - await(ctx.run(testQuery4)) mustEqual res4 - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OptionalNestedFinagleSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OptionalNestedFinagleSpec.scala deleted file mode 100644 index 85d7a23f3d..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/OptionalNestedFinagleSpec.scala +++ /dev/null @@ -1,100 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.util.{Await, Future} -import io.getquill.context.encoding.OptionalNestedSpec - -class OptionalProductEncodingFinagleSpec extends OptionalNestedSpec { - - val context: testContext.type = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override protected def beforeEach() = { - import Setup._ - await(testContext.run(query[Contact].delete)) - () - } - - "1.Optional Inner Product" - { - import `1.Optional Inner Product`._ - "1.Ex1 - Not null inner product" in { - await(context.run(`1.Ex1 - Not null inner product insert`)) - await(context.run(data)) mustEqual List(`1.Ex1 - Not null inner product result`) - } - "1.Ex1 Auto - Not null inner product" in { - val result = `1.Ex1 - Not null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "1.Ex2 - null inner product" in { - await(context.run(`1.Ex2 - null inner product insert`)) - // Finagle's equivalent to an NPE here is an `IllegalStateException: Value 'NullValue' can't be decoded to 'int'` - assertThrows[IllegalStateException] { - await(context.run(data)) - } - } - "1.Ex2 Auto - null inner product" in { - val result = `1.Ex2 - null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - } - - "2.Optional Inner Product" - { - import `2.Optional Inner Product with Optional Leaf`._ - "2.Ex1 - Not null inner product" in { - await(context.run(`2.Ex1 - not-null insert`)) - await(context.run(data)) mustEqual List(`2.Ex1 - not-null result`) - } - "2.Ex1 Auto - Not null inner product" in { - val result = `2.Ex1 - not-null result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "2.Ex2 - Not null inner product" in { - await(context.run(`2.Ex2 - Null inner product insert`)) - await(context.run(data)) mustEqual List(`2.Ex2 - Null inner product result`) - } - "2.Ex2 Auto - Not null inner product" in { - val result = `2.Ex2 - Null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "2.Ex3 - Null inner leaf" in { - await(context.run(`2.Ex3 - Null inner leaf insert`)) - await(context.run(data)) mustEqual List(`2.Ex3 - Null inner leaf result`) - } - "2.Ex3 Auto - Null inner leaf" in { - val result = `2.Ex3 - Null inner leaf result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - } - - "3.Optional Nested Inner Product" - { - import `3.Optional Nested Inner Product`._ - "3.Ex1 - Null inner product insert" in { - await(context.run(`3.Ex1 - Null inner product insert`)) - await(context.run(data)) mustEqual List(`3.Ex1 - Null inner product result`) - } - "3.Ex1 Auto - Null inner product insert" in { - val result = `3.Ex1 - Null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "3.Ex2 - Null inner leaf" in { - await(context.run(`3.Ex2 - Null inner leaf insert`)) - await(context.run(data)) mustEqual List(`3.Ex2 - Null inner leaf result`) - } - "3.Ex2 Auto - Null inner leaf" in { - val result = `3.Ex2 - Null inner leaf result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/PeopleFinagleMysqlSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/PeopleFinagleMysqlSpec.scala deleted file mode 100644 index 585871bf6f..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/PeopleFinagleMysqlSpec.scala +++ /dev/null @@ -1,63 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.util.Await -import com.twitter.util.Future -import io.getquill.context.sql.base.PeopleSpec - -class PeopleFinagleMysqlSpec extends PeopleSpec { - - val context = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeAll = - await { - testContext.transaction { - for { - _ <- testContext.run(query[Couple].delete) - _ <- testContext.run(query[Person].delete) - _ <- testContext.run(liftQuery(peopleEntries).foreach(e => peopleInsert(e))) - _ <- testContext.run(liftQuery(couplesEntries).foreach(e => couplesInsert(e))) - } yield {} - } - } - - "Example 1 - differences" in { - await(testContext.run(`Ex 1 differences`)) mustEqual `Ex 1 expected result` - } - - "Example 2 - range simple" in { - await( - testContext.run(`Ex 2 rangeSimple`(lift(`Ex 2 param 1`), lift(`Ex 2 param 2`))) - ) mustEqual `Ex 2 expected result` - } - - "Examples 3 - satisfies" in { - await(testContext.run(`Ex 3 satisfies`)) mustEqual `Ex 3 expected result` - } - - "Examples 4 - satisfies" in { - await(testContext.run(`Ex 4 satisfies`)) mustEqual `Ex 4 expected result` - } - - "Example 5 - compose" in { - await(testContext.run(`Ex 5 compose`(lift(`Ex 5 param 1`), lift(`Ex 5 param 2`)))) mustEqual `Ex 5 expected result` - } - - "Example 6 - predicate 0" in { - await(testContext.run(satisfies(eval(`Ex 6 predicate`)))) mustEqual `Ex 6 expected result` - } - - "Example 7 - predicate 1" in { - await(testContext.run(satisfies(eval(`Ex 7 predicate`)))) mustEqual `Ex 7 expected result` - } - - "Example 8 - contains empty" in { - await(testContext.run(`Ex 8 and 9 contains`(liftQuery(`Ex 8 param`)))) mustEqual `Ex 8 expected result` - } - - "Example 9 - contains non empty" in { - await(testContext.run(`Ex 8 and 9 contains`(liftQuery(`Ex 9 param`)))) mustEqual `Ex 9 expected result` - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/ProductFinagleMysqlSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/ProductFinagleMysqlSpec.scala deleted file mode 100644 index b524463796..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/ProductFinagleMysqlSpec.scala +++ /dev/null @@ -1,97 +0,0 @@ -package io.getquill.context.finagle.mysql - -import io.getquill.context.sql.ProductSpec -import com.twitter.util.Await -import com.twitter.util.Future -import io.getquill.context.sql.Id - -class ProductFinagleMysqlSpec extends ProductSpec { - - val context = testContext - import testContext._ - - def await[T](r: Future[T]) = Await.result(r) - - override def beforeAll = { - await(testContext.run(quote(query[Product].delete))) - () - } - - "Product" - { - "Insert multiple products" in { - val inserted = await(Future.collect(productEntries.map(product => testContext.run(productInsert(lift(product)))))) - val product = await(testContext.run(productById(lift(inserted(2))))).head - product.description mustEqual productEntries(2).description - product.id mustEqual inserted(2) - } - "Single insert product" in { - val inserted = await(testContext.run(productSingleInsert)) - val product = await(testContext.run(productById(lift(inserted)))).head - product.description mustEqual "Window" - product.id mustEqual inserted - } - - "Single insert with inlined free variable" in { - val prd = Product(0L, "test1", 1L) - val inserted = await { - testContext.run { - product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) - } - } - val returnedProduct = await(testContext.run(productById(lift(inserted)))).head - returnedProduct.description mustEqual "test1" - returnedProduct.sku mustEqual 1L - returnedProduct.id mustEqual inserted - } - - "Single insert with free variable and explicit quotation" in { - val prd = Product(0L, "test2", 2L) - val q1 = quote { - product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) - } - val inserted = await(testContext.run(q1)) - val returnedProduct = await(testContext.run(productById(lift(inserted)))).head - returnedProduct.description mustEqual "test2" - returnedProduct.sku mustEqual 2L - returnedProduct.id mustEqual inserted - } - - "Single product insert with a method quotation" in { - val prd = Product(0L, "test3", 3L) - val inserted = await(testContext.run(productInsert(lift(prd)))) - val returnedProduct = await(testContext.run(productById(lift(inserted)))).head - returnedProduct.description mustEqual "test3" - returnedProduct.sku mustEqual 3L - returnedProduct.id mustEqual inserted - } - - "Single insert with value class" in { - case class Product(id: Id, description: String, sku: Long) - val prd = Product(Id(0L), "test2", 2L) - val q1 = quote { - query[Product].insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returningGenerated(_.id) - } - await(testContext.run(q1)) mustBe a[Id] - } - - "supports casts from string to number" - { - "toInt" in { - case class Product(id: Long, description: String, sku: Int) - val queried = await { - testContext.run { - query[Product].filter(_.sku == lift("1004").toInt) - } - }.head - queried.sku mustEqual 1004L - } - "toLong" in { - val queried = await { - testContext.run { - query[Product].filter(_.sku == lift("1004").toLong) - } - }.head - queried.sku mustEqual 1004L - } - } - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/QueryResultTypeFinagleMysqlSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/QueryResultTypeFinagleMysqlSpec.scala deleted file mode 100644 index e7d9019052..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/QueryResultTypeFinagleMysqlSpec.scala +++ /dev/null @@ -1,147 +0,0 @@ -package io.getquill.context.finagle.mysql - -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.QueryResultTypeSpec -import java.util.concurrent.ConcurrentLinkedQueue -import scala.jdk.CollectionConverters._ - -class QueryResultTypeFinagleMysqlSpec extends QueryResultTypeSpec { - - val context = testContext - import testContext._ - - def await[T](r: Future[T]) = Await.result(r) - - val insertedProducts = new ConcurrentLinkedQueue[Product] - - override def beforeAll = { - await(testContext.run(deleteAll)) - val rs = await(testContext.run(liftQuery(productEntries).foreach(e => productInsert(e)))) - val inserted = (rs zip productEntries).map { case (r, prod) => - prod.copy(id = r) - } - insertedProducts.addAll(inserted.asJava) - () - } - - def products = insertedProducts.asScala.toList - - "return list" - { - "select" in { - await(testContext.run(selectAll)) must contain theSameElementsAs (products) - } - "map" in { - await(testContext.run(map)) must contain theSameElementsAs (products.map(_.id)) - } - "filter" in { - await(testContext.run(filter)) must contain theSameElementsAs (products) - } - "withFilter" in { - await(testContext.run(withFilter)) must contain theSameElementsAs (products) - } - "sortBy" in { - await(testContext.run(sortBy)) must contain theSameElementsInOrderAs (products) - } - "take" in { - await(testContext.run(take)) must contain theSameElementsAs (products) - } - "drop" in { - await(testContext.run(drop)) must contain theSameElementsAs (products.drop(1)) - } - "++" in { - await(testContext.run(`++`)) must contain theSameElementsAs (products ++ products) - } - "unionAll" in { - await(testContext.run(unionAll)) must contain theSameElementsAs (products ++ products) - } - "union" in { - await(testContext.run(union)) must contain theSameElementsAs (products) - } - "join" in { - await(testContext.run(join)) must contain theSameElementsAs (products zip products) - } - "distinct" in { - await(testContext.run(distinct)) must contain theSameElementsAs (products.map(_.id).distinct) - } - } - - "return single result" - { - "min" - { - "some" in { - await(testContext.run(minExists)) mustEqual Some(products.map(_.sku).min) - } - "none" in { - await(testContext.run(minNonExists)) mustBe None - } - } - "max" - { - "some" in { - await(testContext.run(maxExists)) mustBe Some(products.map(_.sku).max) - } - "none" in { - await(testContext.run(maxNonExists)) mustBe None - } - } - "avg" - { - "some" in { - await(testContext.run(avgExists)) mustBe Some(BigDecimal(products.map(_.sku).sum) / products.size) - } - "none" in { - await(testContext.run(avgNonExists)) mustBe None - } - } - "size" in { - await(testContext.run(productSize)) mustEqual products.size - } - "parametrized size" in { - await(testContext.run(parametrizedSize(lift(10000)))) mustEqual 0 - } - "nonEmpty" in { - await(testContext.run(nonEmpty)) mustEqual true - } - "isEmpty" in { - await(testContext.run(isEmpty)) mustEqual false - } - } - - "return async stream" - { - "select" in { - await(testContext.stream(selectAll).flatMap(_.toSeq())) must contain theSameElementsAs (products) - } - "map" in { - await(testContext.stream(map).flatMap(_.toSeq())) must contain theSameElementsAs (products.map(_.id)) - } - "filter" in { - await(testContext.stream(filter).flatMap(_.toSeq())) must contain theSameElementsAs (products) - } - "withFilter" in { - await(testContext.stream(withFilter).flatMap(_.toSeq())) must contain theSameElementsAs (products) - } - "sortBy" in { - await(testContext.stream(sortBy).flatMap(_.toSeq())) must contain theSameElementsInOrderAs (products) - } - "take" in { - await(testContext.stream(take).flatMap(_.toSeq())) must contain theSameElementsAs (products) - } - "drop" in { - await(testContext.stream(drop).flatMap(_.toSeq())) must contain theSameElementsAs (products.drop(1)) - } - "++" in { - await(testContext.stream(`++`).flatMap(_.toSeq())) must contain theSameElementsAs (products ++ products) - } - "unionAll" in { - await(testContext.stream(unionAll).flatMap(_.toSeq())) must contain theSameElementsAs (products ++ products) - } - "union" in { - await(testContext.stream(union).flatMap(_.toSeq())) must contain theSameElementsAs (products) - } - "join" in { - await(testContext.stream(join).flatMap(_.toSeq())) must contain theSameElementsAs (products zip products) - } - "distinct" in { - await(testContext.stream(distinct).flatMap(_.toSeq())) must contain theSameElementsAs (products - .map(_.id) - .distinct) - } - } -} diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/TestContext.scala b/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/TestContext.scala deleted file mode 100644 index 933d88fa8d..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/context/finagle/mysql/TestContext.scala +++ /dev/null @@ -1,8 +0,0 @@ -package io.getquill.context.finagle.mysql - -import io.getquill.Literal -import io.getquill.TestEntities -import io.getquill.FinagleMysqlContext -import io.getquill.context.sql.{TestDecoders, TestEncoders} - -object testContext extends FinagleMysqlContext(Literal, "testDB") with TestEntities with TestEncoders with TestDecoders diff --git a/quill-finagle-mysql/src/test/scala/io/getquill/monad/TwitterFutureIOMonadSpec.scala b/quill-finagle-mysql/src/test/scala/io/getquill/monad/TwitterFutureIOMonadSpec.scala deleted file mode 100644 index 57de1af059..0000000000 --- a/quill-finagle-mysql/src/test/scala/io/getquill/monad/TwitterFutureIOMonadSpec.scala +++ /dev/null @@ -1,15 +0,0 @@ -package io.getquill.monad - -import io.getquill.context.finagle.mysql.testContext -import com.twitter.util.{Await, Future} - -class TwitterFutureIOMonadSpec extends IOMonadSpec { - - override val ctx = testContext - import ctx._ - - override def eval[T](io: IO[T, _]): T = Await.result(performIO(io)) - - override def resultValue[T](x: T): Result[T] = Future.value[T](x) - -} diff --git a/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresContext.scala b/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresContext.scala deleted file mode 100644 index 3a5ba2824e..0000000000 --- a/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresContext.scala +++ /dev/null @@ -1,166 +0,0 @@ -package io.getquill - -import com.twitter.util.{Await, Future, Local} -import com.twitter.finagle.postgres._ -import com.typesafe.config.Config -import io.getquill.ReturnAction.{ReturnColumns, ReturnNothing, ReturnRecord} -import io.getquill.context.finagle.postgres._ -import io.getquill.context.sql.SqlContext -import io.getquill.util.{ContextLogger, LoadConfig} - -import scala.util.Try -import io.getquill.context.{Context, ExecutionInfo, ContextVerbTranslate} -import io.getquill.monad.TwitterFutureIOMonad - -class FinaglePostgresContext[+N <: NamingStrategy](val naming: N, client: PostgresClient) - extends Context[FinaglePostgresDialect, N] - with ContextVerbTranslate - with SqlContext[FinaglePostgresDialect, N] - with FinaglePostgresEncoders - with FinaglePostgresDecoders - with TwitterFutureIOMonad { - - import FinaglePostgresContext._ - - def this(naming: N, config: FinaglePostgresContextConfig) = this(naming, config.client) - def this(naming: N, config: Config) = this(naming, FinaglePostgresContextConfig(config)) - def this(naming: N, configPrefix: String) = this(naming, LoadConfig(configPrefix)) - - val idiom = FinaglePostgresDialect - - private val logger = ContextLogger(classOf[FinaglePostgresContext[_]]) - - override type PrepareRow = List[Param[_]] - override type ResultRow = Row - override type Session = Unit - - override type Result[T] = Future[T] - override type RunQueryResult[T] = List[T] - override type RunQuerySingleResult[T] = T - override type RunActionResult = Long - override type RunActionReturningResult[T] = T - override type RunBatchActionResult = List[Long] - override type RunBatchActionReturningResult[T] = List[T] - type Runner = Unit - override type NullChecker = LocalNullChecker - class LocalNullChecker extends BaseNullChecker { - override def apply(index: Int, row: Row): Boolean = - row.getAnyOption(index) == None - } - implicit val nullChecker: LocalNullChecker = new LocalNullChecker() - - private val currentClient = new Local[PostgresClient] - - override def close = Await.result(client.close()) - - private def expandAction(sql: String, returningAction: ReturnAction): String = - returningAction match { - // The Postgres dialect will create SQL that has a 'RETURNING' clause so we don't have to add one. - case ReturnRecord => s"$sql" - // The Postgres dialect will not actually use these below variants but in case we decide to plug - // in some other dialect into this context... - case ReturnColumns(columns) => s"$sql RETURNING ${columns.mkString(", ")}" - case ReturnNothing => s"$sql" - } - - def probe(sql: String) = Try(Await.result(client.query(sql))) - - // Only create a client if none exists to allow nested transactions. - def transaction[T](f: => Future[T]) = currentClient() match { - case None => - client.inTransaction { c => - currentClient.let(c)(f) - } - case Some(c) => - f - } - - override def performIO[T](io: IO[T, _], transactional: Boolean = false): Result[T] = - transactional match { - case false => super.performIO(io) - case true => transaction(super.performIO(io)) - } - - def executeQuery[T](sql: String, prepare: Prepare = identityPrepare, extractor: Extractor[T] = identityExtractor)( - info: ExecutionInfo, - dc: Runner - ): Future[List[T]] = { - val (params, prepared) = prepare(Nil, ()) - logger.logQuery(sql, params) - withClient(_.prepareAndQuery(sql, prepared: _*)(row => extractor(row, ())).map(_.toList)) - } - - def executeQuerySingle[T]( - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T] = identityExtractor - )(info: ExecutionInfo, dc: Runner): Future[T] = - executeQuery(sql, prepare, extractor)(info, dc).map(handleSingleResult(sql, _)) - - def executeAction(sql: String, prepare: Prepare = identityPrepare)(info: ExecutionInfo, dc: Runner): Future[Long] = { - val (params, prepared) = prepare(Nil, ()) - logger.logQuery(sql, params) - withClient(_.prepareAndExecute(sql, prepared: _*)).map(_.toLong) - } - - def executeBatchAction[B](groups: List[BatchGroup])(info: ExecutionInfo, dc: Runner): Future[List[Long]] = - Future.collect { - groups.map { case BatchGroup(sql, prepare) => - prepare - .foldLeft(Future.value(List.newBuilder[Long])) { case (acc, prepare) => - acc.flatMap { list => - executeAction(sql, prepare)(info, dc).map(list += _) - } - } - .map(_.result()) - } - }.map(_.flatten.toList) - - def executeActionReturning[T]( - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T], - returningAction: ReturnAction - )(info: ExecutionInfo, dc: Runner): Future[T] = - executeActionReturningMany[T](sql, prepare, extractor, returningAction)(info, dc).map(handleSingleResult(sql, _)) - - def executeActionReturningMany[T]( - sql: String, - prepare: Prepare = identityPrepare, - extractor: Extractor[T], - returningAction: ReturnAction - )(info: ExecutionInfo, dc: Runner): Future[List[T]] = { - val (params, prepared) = prepare(Nil, ()) - logger.logQuery(sql, params) - withClient(_.prepareAndQuery(expandAction(sql, returningAction), prepared: _*)(row => extractor(row, ()))) - .map(_.toList) - } - - def executeBatchActionReturning[T]( - groups: List[BatchGroupReturning], - extractor: Extractor[T] - )(info: ExecutionInfo, dc: Runner): Future[List[T]] = - Future.collect { - groups.map { case BatchGroupReturning(sql, column, prepare) => - prepare - .foldLeft(Future.value(List.newBuilder[T])) { case (acc, prepare) => - acc.flatMap { list => - executeActionReturning(sql, prepare, extractor, column)(info, dc).map(list += _) - } - } - .map(_.result()) - } - }.map(_.flatten.toList) - - override private[getquill] def prepareParams(statement: String, prepare: Prepare): Seq[String] = - prepare(Nil, ())._2.map(param => prepareParam(param.encode())) - - private def withClient[T](f: PostgresClient => T) = - currentClient().map(f).getOrElse(f(client)) -} - -object FinaglePostgresContext { - implicit class EncodeParam[T](val param: Param[T]) extends AnyVal { - def encode(): Option[String] = param.encoder.encodeText(param.value) - } -} diff --git a/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresContextConfig.scala b/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresContextConfig.scala deleted file mode 100644 index c48b5ac4ef..0000000000 --- a/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresContextConfig.scala +++ /dev/null @@ -1,44 +0,0 @@ -package io.getquill - -import com.twitter.finagle.Postgres -import com.twitter.finagle.Postgres.{Client, CustomTypes} -import com.twitter.finagle.postgres.PostgresClient -import com.twitter.finagle.postgres.values._ -import com.twitter.finagle.service.RetryPolicy -import com.typesafe.config.Config - -import scala.util.Try - -case class FinaglePostgresContextConfig(config: Config) { - def host: String = config.getString("host") - def username: String = config.getString("user") - def password: Option[String] = Try(config.getString("password")).toOption - def database: String = config.getString("database") - def useSsl: Boolean = Try(config.getBoolean("useSsl")).getOrElse(false) - def hostConnectionLimit: Int = Try(config.getInt("hostConnectionLimit")).getOrElse(1) - def numRetries: Int = Try(config.getInt("numRetries")).getOrElse(4) - def customTypes: Boolean = Try(config.getBoolean("customTypes")).getOrElse(false) - def customReceiveFunctions: PartialFunction[String, ValueDecoder[T] forSome { type T }] = - ValueDecoder.decoders orElse { case "noop" => ValueDecoder.unknown } - def binaryResults: Boolean = Try(config.getBoolean("binaryResults")).getOrElse(false) - def binaryParams: Boolean = Try(config.getBoolean("binaryParams")).getOrElse(false) - - private def clientSimple: Client = Postgres - .Client() - .withCredentials(username, password) - .database(database) - .withCustomReceiveFunctions(customReceiveFunctions) - .withSessionPool - .maxSize(hostConnectionLimit) - .withBinaryResults(binaryResults) - .withBinaryParams(binaryParams) - .withRetryPolicy(RetryPolicy.tries(numRetries)) - - private def clientCustomTypes: Client = - if (!customTypes) clientSimple.withDefaultTypes() else clientSimple.configured(CustomTypes(None)) - - private def clientWithSSL: Client = if (useSsl) clientCustomTypes.withTransport.tls else clientCustomTypes - - def client: PostgresClient = clientWithSSL - .newRichClient(host) -} diff --git a/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresDialect.scala b/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresDialect.scala deleted file mode 100644 index d5c0c8978f..0000000000 --- a/quill-finagle-postgres/src/main/scala/io/getquill/FinaglePostgresDialect.scala +++ /dev/null @@ -1,7 +0,0 @@ -package io.getquill - -import io.getquill.context.sql.idiom.PositionalBindVariables - -trait FinaglePostgresDialect extends PostgresDialect with PositionalBindVariables - -object FinaglePostgresDialect extends FinaglePostgresDialect diff --git a/quill-finagle-postgres/src/main/scala/io/getquill/context/finagle/postgres/FinaglePostgresDecoders.scala b/quill-finagle-postgres/src/main/scala/io/getquill/context/finagle/postgres/FinaglePostgresDecoders.scala deleted file mode 100644 index 7ee931af1e..0000000000 --- a/quill-finagle-postgres/src/main/scala/io/getquill/context/finagle/postgres/FinaglePostgresDecoders.scala +++ /dev/null @@ -1,83 +0,0 @@ -package io.getquill.context.finagle.postgres - -import java.nio.charset.Charset -import java.time.{LocalDate, LocalDateTime, ZoneId} -import java.util.{Date, UUID} - -import com.twitter.finagle.postgres.values.ValueDecoder -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try -import io.getquill.FinaglePostgresContext -import io.getquill.util.Messages.fail -import io.netty.buffer.ByteBuf - -trait FinaglePostgresDecoders { - this: FinaglePostgresContext[_] => - - import ValueDecoder._ - - type Decoder[T] = FinaglePostgresDecoder[T] - - case class FinaglePostgresDecoder[T]( - vd: ValueDecoder[T], - default: Throwable => T = (e: Throwable) => fail(e.getMessage) - ) extends BaseDecoder[T] { - override def apply(index: Index, row: ResultRow, session: Session): T = - row.getTry[T](index)(vd) match { - case Return(r) => r - case Throw(e) => default(e) - } - - def orElse[U](f: U => T)(implicit vdu: ValueDecoder[U]): FinaglePostgresDecoder[T] = { - val mappedVd = vdu.map[T](f) - FinaglePostgresDecoder[T]( - new ValueDecoder[T] { - def decodeText(recv: String, text: String): Try[T] = { - val t = vd.decodeText(recv, text) - if (t.isReturn) t - else mappedVd.decodeText(recv, text) - } - def decodeBinary(recv: String, bytes: ByteBuf, charset: Charset): Try[T] = { - val t = vd.decodeBinary(recv, bytes, charset) - if (t.isReturn) t - else mappedVd.decodeBinary(recv, bytes, charset) - } - } - ) - } - } - - implicit def decoderDirectly[T](implicit vd: ValueDecoder[T]): Decoder[T] = FinaglePostgresDecoder(vd) - def decoderMapped[U, T](f: U => T)(implicit vd: ValueDecoder[U]): Decoder[T] = FinaglePostgresDecoder(vd.map[T](f)) - - implicit def optionDecoder[T](implicit d: Decoder[T]): Decoder[Option[T]] = - FinaglePostgresDecoder[Option[T]]( - new ValueDecoder[Option[T]] { - def decodeText(recv: String, text: String): Try[Option[T]] = Return(d.vd.decodeText(recv, text).toOption) - def decodeBinary(recv: String, bytes: ByteBuf, charset: Charset): Try[Option[T]] = - Return(d.vd.decodeBinary(recv, bytes, charset).toOption) - }, - _ => None - ) - - implicit def mappedDecoder[I, O](implicit mapped: MappedEncoding[I, O], d: Decoder[I]): Decoder[O] = - decoderMapped[I, O](mapped.f)(d.vd) - - implicit val stringDecoder: Decoder[String] = decoderDirectly[String] - implicit val bigDecimalDecoder: Decoder[BigDecimal] = decoderDirectly[BigDecimal] - implicit val booleanDecoder: Decoder[Boolean] = decoderDirectly[Boolean] - implicit val shortDecoder: Decoder[Short] = decoderDirectly[Short] - implicit val byteDecoder: Decoder[Byte] = decoderMapped[Short, Byte](_.toByte) - implicit val intDecoder: Decoder[Int] = decoderDirectly[Int].orElse[Long](_.toInt) - implicit val longDecoder: Decoder[Long] = decoderDirectly[Long].orElse[Int](_.toLong) - implicit val floatDecoder: Decoder[Float] = decoderDirectly[Float].orElse[Double](_.toFloat) - implicit val doubleDecoder: Decoder[Double] = decoderDirectly[Double] - implicit val byteArrayDecoder: Decoder[Array[Byte]] = decoderDirectly[Array[Byte]] - implicit val dateDecoder: Decoder[Date] = - decoderMapped[LocalDateTime, Date](d => Date.from(d.atZone(ZoneId.systemDefault()).toInstant)) - implicit val localDateDecoder: Decoder[LocalDate] = decoderDirectly[LocalDate].orElse[LocalDateTime](_.toLocalDate) - implicit val localDateTimeDecoder: Decoder[LocalDateTime] = - decoderDirectly[LocalDateTime].orElse[LocalDate](_.atStartOfDay) - implicit val uuidDecoder: Decoder[UUID] = decoderDirectly[UUID] -} diff --git a/quill-finagle-postgres/src/main/scala/io/getquill/context/finagle/postgres/FinaglePostgresEncoders.scala b/quill-finagle-postgres/src/main/scala/io/getquill/context/finagle/postgres/FinaglePostgresEncoders.scala deleted file mode 100644 index e4bd84a837..0000000000 --- a/quill-finagle-postgres/src/main/scala/io/getquill/context/finagle/postgres/FinaglePostgresEncoders.scala +++ /dev/null @@ -1,46 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.finagle.postgres._ -import com.twitter.finagle.postgres.values._ -import com.twitter.finagle.postgres.values.ValueEncoder._ -import io.getquill.FinaglePostgresContext -import java.util.{Date, UUID} -import java.time._ - -trait FinaglePostgresEncoders { - this: FinaglePostgresContext[_] => - - type Encoder[T] = FinaglePostgresEncoder[T] - - case class FinaglePostgresEncoder[T](encoder: ValueEncoder[T]) extends BaseEncoder[T] { - override def apply(index: Index, value: T, row: PrepareRow, session: Session) = - row :+ Param(value)(encoder) - } - - def encoder[T](implicit e: ValueEncoder[T]): Encoder[T] = FinaglePostgresEncoder(e) - - def encoder[T, U](f: U => T)(implicit e: ValueEncoder[T]): Encoder[U] = - encoder[U](e.contraMap(f)) - - implicit def mappedEncoder[I, O](implicit mapped: MappedEncoding[I, O], e: Encoder[O]): Encoder[I] = - FinaglePostgresEncoder(e.encoder.contraMap(mapped.f)) - - implicit def optionEncoder[T](implicit e: Encoder[T]): Encoder[Option[T]] = - FinaglePostgresEncoder[Option[T]](option(e.encoder)) - - implicit val stringEncoder: Encoder[String] = encoder[String] - implicit val bigDecimalEncoder: Encoder[BigDecimal] = encoder[BigDecimal] - implicit val booleanEncoder: Encoder[Boolean] = encoder[Boolean] - implicit val byteEncoder: Encoder[Byte] = encoder[Short, Byte](_.toShort) - implicit val shortEncoder: Encoder[Short] = encoder[Short] - implicit val intEncoder: Encoder[Int] = encoder[Int] - implicit val longEncoder: Encoder[Long] = encoder[Long] - implicit val floatEncoder: Encoder[Float] = encoder[Float] - implicit val doubleEncoder: Encoder[Double] = encoder[Double] - implicit val byteArrayEncoder: Encoder[Array[Byte]] = encoder[Array[Byte]](bytea) - implicit val dateEncoder: Encoder[Date] = - encoder[LocalDateTime, Date]((v: Date) => LocalDateTime.ofInstant(v.toInstant, ZoneId.systemDefault())) - implicit val localDateEncoder: Encoder[LocalDate] = encoder[LocalDate] - implicit val localDateTimeEncoder: Encoder[LocalDateTime] = encoder[LocalDateTime] - implicit val uuidEncoder: Encoder[UUID] = encoder[UUID] -} diff --git a/quill-finagle-postgres/src/main/scala/io/getquill/monad/TwitterFutureIOMonad.scala b/quill-finagle-postgres/src/main/scala/io/getquill/monad/TwitterFutureIOMonad.scala deleted file mode 100644 index 076f02750c..0000000000 --- a/quill-finagle-postgres/src/main/scala/io/getquill/monad/TwitterFutureIOMonad.scala +++ /dev/null @@ -1,46 +0,0 @@ -package io.getquill.monad - -import language.experimental.macros -import com.twitter.util.Future -import io.getquill.context.Context -import com.twitter.util.Return -import scala.util.Success -import com.twitter.util.Throw -import scala.util.Failure -import com.twitter.util.Try -import io.getquill.{Query, Action, ActionReturning, BatchAction, Quoted} - -trait TwitterFutureIOMonad extends IOMonad { - this: Context[_, _] => - - type Result[T] = Future[T] - - def runIO[T](quoted: Quoted[T]): IO[RunQuerySingleResult[T], Effect.Read] = macro IOMonadMacro.runIO - def runIO[T](quoted: Quoted[Query[T]]): IO[RunQueryResult[T], Effect.Read] = macro IOMonadMacro.runIO - def runIO(quoted: Quoted[Action[_]]): IO[RunActionResult, Effect.Write] = macro IOMonadMacro.runIO - def runIO[T](quoted: Quoted[ActionReturning[_, T]]): IO[RunActionReturningResult[T], Effect.Write] = - macro IOMonadMacro.runIO - def runIO(quoted: Quoted[BatchAction[Action[_]]]): IO[RunBatchActionResult, Effect.Write] = macro IOMonadMacro.runIO - def runIO[T](quoted: Quoted[BatchAction[ActionReturning[_, T]]]): IO[RunBatchActionReturningResult[T], Effect.Write] = - macro IOMonadMacro.runIO - - case class Run[T, E <: Effect](f: () => Result[T]) extends IO[T, E] - - def performIO[T](io: IO[T, _], transactional: Boolean = false): Result[T] = - io match { - case FromTry(t) => Future.const(Try(t.get)) - case Run(f) => f() - case Sequence(in, cbf) => - Future - .collect(in.map(performIO(_)).toSeq) - .map(r => cbf().++=(r).result) - case TransformWith(a, fA) => - performIO(a).liftToTry.map { - case Return(v) => Success(v) - case Throw(t) => Failure(t) - } - .flatMap(v => performIO(fA(v))) - case Transactional(io) => - performIO(io, transactional = true) - } -} diff --git a/quill-finagle-postgres/src/test/resources/application.conf b/quill-finagle-postgres/src/test/resources/application.conf deleted file mode 100644 index 9d76f09895..0000000000 --- a/quill-finagle-postgres/src/test/resources/application.conf +++ /dev/null @@ -1,6 +0,0 @@ -testPostgresDB.host=${?POSTGRES_HOST}":"${?POSTGRES_PORT} -testPostgresDB.user=postgres -testPostgresDB.password=${?POSTGRES_PASSWORD} -testPostgresDB.database=quill_test - -testPostgresDB.hostConnectionLimit=3 diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/CaseClassQueryFinagleSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/CaseClassQueryFinagleSpec.scala deleted file mode 100644 index edb42826e4..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/CaseClassQueryFinagleSpec.scala +++ /dev/null @@ -1,53 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.CaseClassQuerySpec -import org.scalatest.matchers.should.Matchers._ - -class CaseClassQueryFinagleSpec extends CaseClassQuerySpec { - - val context = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeAll = - await { - testContext.transaction { - for { - _ <- testContext.run(query[Contact].delete) - _ <- testContext.run(query[Address].delete) - _ <- testContext.run(liftQuery(peopleEntries).foreach(e => peopleInsert(e))) - _ <- testContext.run(liftQuery(addressEntries).foreach(e => addressInsert(e))) - } yield {} - } - } - - "Example 1 - Single Case Class Mapping" in { - await( - testContext.run(`Ex 1 CaseClass Record Output`) - ) should contain theSameElementsAs (`Ex 1 CaseClass Record Output expected result`) - } - "Example 1A - Single Case Class Mapping" in { - await( - testContext.run(`Ex 1A CaseClass Record Output`) - ) should contain theSameElementsAs `Ex 1 CaseClass Record Output expected result` - } - "Example 1B - Single Case Class Mapping" in { - await( - testContext.run(`Ex 1B CaseClass Record Output`) - ) should contain theSameElementsAs `Ex 1 CaseClass Record Output expected result` - } - - "Example 2 - Single Record Mapped Join" in { - await( - testContext.run(`Ex 2 Single-Record Join`) - ) should contain theSameElementsAs `Ex 2 Single-Record Join expected result` - } - - "Example 3 - Inline Record as Filter" in { - await( - testContext.run(`Ex 3 Inline Record Usage`) - ) should contain theSameElementsAs `Ex 3 Inline Record Usage exepected result` - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/DepartmentsFinaglePostgresSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/DepartmentsFinaglePostgresSpec.scala deleted file mode 100644 index 93abae0984..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/DepartmentsFinaglePostgresSpec.scala +++ /dev/null @@ -1,36 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.Await -import com.twitter.util.Future -import io.getquill.context.sql.base.DepartmentsSpec - -class DepartmentsPostgresMysqlSpec extends DepartmentsSpec { - - val context = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeAll = - await { - testContext.transaction { - for { - _ <- testContext.run(query[Department].delete) - _ <- testContext.run(query[Employee].delete) - _ <- testContext.run(query[Task].delete) - - _ <- testContext.run(liftQuery(departmentEntries).foreach(e => departmentInsert(e))) - _ <- testContext.run(liftQuery(employeeEntries).foreach(e => employeeInsert(e))) - _ <- testContext.run(liftQuery(taskEntries).foreach(e => taskInsert(e))) - } yield {} - } - } - - "Example 8 - nested naive" in { - await(testContext.run(`Example 8 expertise naive`(lift(`Example 8 param`)))) mustEqual `Example 8 expected result` - } - - "Example 9 - nested db" in { - await(testContext.run(`Example 9 expertise`(lift(`Example 9 param`)))) mustEqual `Example 9 expected result` - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/FinaglePostgresContextSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/FinaglePostgresContextSpec.scala deleted file mode 100644 index 401715c4b7..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/FinaglePostgresContextSpec.scala +++ /dev/null @@ -1,54 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util._ -import io.getquill._ -import io.getquill.base.Spec -import org.scalatest.BeforeAndAfter - -class FinaglePostgresContextSpec extends Spec with BeforeAndAfter { - - val context = testContext - import testContext._ - - def await[T](f: Future[T]) = Await.result(f) - - before { - await(testContext.run(qr1.delete)) - } - - val insert = quote { (i: Int) => - qr1.insert(_.i -> i) - } - - "run non-batched action" in { - await(context.run(insert(lift(1)))) mustEqual 1 - } - - "Insert with returning with single column table" in { - val inserted: Long = await(testContext.run { - qr4.insertValue(lift(TestEntity4(0))).returningGenerated(_.i) - }) - await(testContext.run(qr4.filter(_.i == lift(inserted)))).head.i mustBe inserted - } - - "performIo" in { - await(context.run(insert(lift(1)))) - await(performIO(runIO(qr1.filter(_.i == 123)).transactional)) mustBe Nil - } - - "probe" in { - val ctx = new FinaglePostgresContext(Literal, "testPostgresDB") - ctx.probe("select 1").toOption mustBe defined - ctx.close - } - - "prepare" in { - import com.twitter.finagle.postgres.Param - import com.twitter.finagle.postgres.values.ValueEncoder._ - - testContext.prepareParams( - "", - (ps, session) => (Nil, ps ++: List(Param("Sarah"), Param(127))) - ) mustEqual List("'Sarah'", "'127'") - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/FinaglePostgresEncodingSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/FinaglePostgresEncodingSpec.scala deleted file mode 100644 index 1a7ea41346..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/FinaglePostgresEncodingSpec.scala +++ /dev/null @@ -1,108 +0,0 @@ -package io.getquill.context.finagle.postgres - -import java.time.{LocalDate, LocalDateTime} - -import io.getquill.context.sql.EncodingSpec -import com.twitter.util.Await -import java.util.Date -import java.util.UUID -import io.getquill.Query - -class FinaglePostgresEncodingSpec extends EncodingSpec { - - val context = testContext - import testContext._ - - "encodes and decodes types" in { - val r = - for { - _ <- testContext.run(delete) - _ <- testContext.run(liftQuery(insertValues).foreach(e => insert(e))) - result <- testContext.run(query[EncodingTestEntity]) - } yield result - verify(Await.result(r).toList) - } - - "encodes and decodes uuids" in { - case class EncodingUUIDTestEntity(v1: UUID) - val testUUID = UUID.fromString("e5240c08-6ee7-474a-b5e4-91f79c48338f") - - // delete old values - val q0 = quote(query[EncodingUUIDTestEntity].delete) - val rez0 = Await.result(testContext.run(q0)) - - // insert new uuid - val rez1 = - Await.result(testContext.run(query[EncodingUUIDTestEntity].insertValue(lift(EncodingUUIDTestEntity(testUUID))))) - - // verify you can get the uuid back from the db - val q2 = quote(query[EncodingUUIDTestEntity].map(p => p.v1)) - val rez2 = Await.result(testContext.run(q2)) - - rez2 mustEqual List(testUUID) - } - - "fails if the column has the wrong type" - { - "numeric" in { - Await.result(testContext.run(liftQuery(insertValues).foreach(e => insert(e)))) - case class EncodingTestEntity(v1: Int) - val e = intercept[IllegalStateException] { - Await.result(testContext.run(query[EncodingTestEntity])) - } - } - "non-numeric" in { - Await.result(testContext.run(liftQuery(insertValues).foreach(e => insert(e)))) - case class EncodingTestEntity(v1: Date) - val e = intercept[IllegalStateException] { - Await.result(testContext.run(query[EncodingTestEntity])) - } - } - } - - "encodes sets" in { - val q = quote { (set: Query[Int]) => - query[EncodingTestEntity].filter(t => set.contains(t.v6)) - } - val fut = - for { - _ <- testContext.run(query[EncodingTestEntity].delete) - _ <- testContext.run(liftQuery(insertValues).foreach(e => query[EncodingTestEntity].insertValue(e))) - r <- testContext.run(q(liftQuery(insertValues.map(_.v6)))) - } yield { - r - } - verify(Await.result(fut)) - } - - "returning UUID" in { - val success = for { - uuid <- Await.result(testContext.run(insertBarCode(lift(barCodeEntry)))) - barCode <- Await.result(testContext.run(findBarCodeByUuid(uuid))).headOption - } yield { - verifyBarcode(barCode) - } - success must not be empty - } - - "encodes localdate type" in { - case class DateEncodingTestEntity(v1: LocalDate, v2: LocalDate) - val entity = DateEncodingTestEntity(LocalDate.now, LocalDate.now) - val r = for { - _ <- testContext.run(query[DateEncodingTestEntity].delete) - _ <- testContext.run(query[DateEncodingTestEntity].insertValue(lift(entity))) - result <- testContext.run(query[DateEncodingTestEntity]) - } yield result - Await.result(r) must contain(entity) - } - - "encodes localdatetime type" in { - case class DateEncodingTestEntity(v1: LocalDateTime, v2: LocalDateTime) - val entity = DateEncodingTestEntity(LocalDateTime.now, LocalDateTime.now) - val r = for { - _ <- testContext.run(query[DateEncodingTestEntity].delete) - _ <- testContext.run(query[DateEncodingTestEntity].insertValue(lift(entity))) - result <- testContext.run(query[DateEncodingTestEntity]) - } yield result - Await.result(r) - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/OnConflictFinagleSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/OnConflictFinagleSpec.scala deleted file mode 100644 index 2142a3f8c1..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/OnConflictFinagleSpec.scala +++ /dev/null @@ -1,38 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.OnConflictSpec - -class OnConflictFinagleSpec extends OnConflictSpec { - val ctx = testContext - import ctx._ - - def await[T](future: Future[T]) = Await.result(future) - - override protected def beforeAll(): Unit = { - await(ctx.run(qr1.delete)) - () - } - - "ON CONFLICT DO NOTHING" in { - import `onConflictIgnore`._ - await(ctx.run(testQuery1)) mustEqual res1 - await(ctx.run(testQuery2)) mustEqual res2 - await(ctx.run(testQuery3)) mustEqual res3 - } - - "ON CONFLICT (i) DO NOTHING" in { - import `onConflictIgnore(_.i)`._ - await(ctx.run(testQuery1)) mustEqual res1 - await(ctx.run(testQuery2)) mustEqual res2 - await(ctx.run(testQuery3)) mustEqual res3 - } - - "ON CONFLICT (i) DO UPDATE ..." in { - import `onConflictUpdate(_.i)((t, e) => ...)`._ - await(ctx.run(testQuery(e1))) mustEqual res1 - await(ctx.run(testQuery(e2))) mustEqual res2 - await(ctx.run(testQuery(e3))) mustEqual res3 - await(ctx.run(testQuery4)) mustEqual res4 - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/OptionalProductEncodingFinagleSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/OptionalProductEncodingFinagleSpec.scala deleted file mode 100644 index 992074a7c4..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/OptionalProductEncodingFinagleSpec.scala +++ /dev/null @@ -1,100 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.{Await, Future} -import io.getquill.context.encoding.OptionalNestedSpec - -class OptionalProductEncodingFinagleSpec extends OptionalNestedSpec { - - val context: testContext.type = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override protected def beforeEach() = { - import Setup._ - await(testContext.run(query[Contact].delete)) - () - } - - "1.Optional Inner Product" - { - import `1.Optional Inner Product`._ - "1.Ex1 - Not null inner product" in { - await(context.run(`1.Ex1 - Not null inner product insert`)) - await(context.run(data)) mustEqual List(`1.Ex1 - Not null inner product result`) - } - "1.Ex1 Auto - Not null inner product" in { - val result = `1.Ex1 - Not null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "1.Ex2 - null inner product" in { - await(context.run(`1.Ex2 - null inner product insert`)) - // Finagle's equivalent to an NPE here is an `IllegalStateException: Value 'NullValue' can't be decoded to 'int'` - assertThrows[IllegalStateException] { - await(context.run(data)) - } - } - "1.Ex2 Auto - null inner product" in { - val result = `1.Ex2 - null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - } - - "2.Optional Inner Product" - { - import `2.Optional Inner Product with Optional Leaf`._ - "2.Ex1 - Not null inner product" in { - await(context.run(`2.Ex1 - not-null insert`)) - await(context.run(data)) mustEqual List(`2.Ex1 - not-null result`) - } - "2.Ex1 Auto - Not null inner product" in { - val result = `2.Ex1 - not-null result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "2.Ex2 - Not null inner product" in { - await(context.run(`2.Ex2 - Null inner product insert`)) - await(context.run(data)) mustEqual List(`2.Ex2 - Null inner product result`) - } - "2.Ex2 Auto - Not null inner product" in { - val result = `2.Ex2 - Null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "2.Ex3 - Null inner leaf" in { - await(context.run(`2.Ex3 - Null inner leaf insert`)) - await(context.run(data)) mustEqual List(`2.Ex3 - Null inner leaf result`) - } - "2.Ex3 Auto - Null inner leaf" in { - val result = `2.Ex3 - Null inner leaf result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - } - - "3.Optional Nested Inner Product" - { - import `3.Optional Nested Inner Product`._ - "3.Ex1 - Null inner product insert" in { - await(context.run(`3.Ex1 - Null inner product insert`)) - await(context.run(data)) mustEqual List(`3.Ex1 - Null inner product result`) - } - "3.Ex1 Auto - Null inner product insert" in { - val result = `3.Ex1 - Null inner product result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - - "3.Ex2 - Null inner leaf" in { - await(context.run(`3.Ex2 - Null inner leaf insert`)) - await(context.run(data)) mustEqual List(`3.Ex2 - Null inner leaf result`) - } - "3.Ex2 Auto - Null inner leaf" in { - val result = `3.Ex2 - Null inner leaf result` - await(context.run(data.insertValue(lift(result)))) - await(context.run(data)) mustEqual List(result) - } - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/PeopleFinaglePostgresSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/PeopleFinaglePostgresSpec.scala deleted file mode 100644 index d7fc95b792..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/PeopleFinaglePostgresSpec.scala +++ /dev/null @@ -1,63 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.Await -import com.twitter.util.Future -import io.getquill.context.sql.base.PeopleSpec - -class PeopleFinaglePostgresSpec extends PeopleSpec { - - val context = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeAll = - await { - testContext.transaction { - for { - _ <- testContext.run(query[Couple].delete) - _ <- testContext.run(query[Person].delete) - _ <- testContext.run(liftQuery(peopleEntries).foreach(e => peopleInsert(e))) - _ <- testContext.run(liftQuery(couplesEntries).foreach(e => couplesInsert(e))) - } yield {} - } - } - - "Example 1 - differences" in { - await(testContext.run(`Ex 1 differences`)) mustEqual `Ex 1 expected result` - } - - "Example 2 - range simple" in { - await( - testContext.run(`Ex 2 rangeSimple`(lift(`Ex 2 param 1`), lift(`Ex 2 param 2`))) - ) mustEqual `Ex 2 expected result` - } - - "Examples 3 - satisfies" in { - await(testContext.run(`Ex 3 satisfies`)) mustEqual `Ex 3 expected result` - } - - "Examples 4 - satisfies" in { - await(testContext.run(`Ex 4 satisfies`)) mustEqual `Ex 4 expected result` - } - - "Example 5 - compose" in { - await(testContext.run(`Ex 5 compose`(lift(`Ex 5 param 1`), lift(`Ex 5 param 2`)))) mustEqual `Ex 5 expected result` - } - - "Example 6 - predicate 0" in { - await(testContext.run(satisfies(eval(`Ex 6 predicate`)))) mustEqual `Ex 6 expected result` - } - - "Example 7 - predicate 1" in { - await(testContext.run(satisfies(eval(`Ex 7 predicate`)))) mustEqual `Ex 7 expected result` - } - - "Example 8 - contains empty" in { - await(testContext.run(`Ex 8 and 9 contains`(liftQuery(`Ex 8 param`)))) mustEqual `Ex 8 expected result` - } - - "Example 9 - contains non empty" in { - await(testContext.run(`Ex 8 and 9 contains`(liftQuery(`Ex 9 param`)))) mustEqual `Ex 9 expected result` - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/PeopleFinagleReturningSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/PeopleFinagleReturningSpec.scala deleted file mode 100644 index 0efa7fa916..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/PeopleFinagleReturningSpec.scala +++ /dev/null @@ -1,76 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.PeopleReturningSpec - -class PeopleFinagleReturningSpec extends PeopleReturningSpec { - - val context: testContext.type = testContext - import testContext._ - - def await[T](future: Future[T]) = Await.result(future) - - override def beforeEach(): Unit = { - await { - testContext.transaction { - for { - _ <- testContext.run(query[Contact].delete) - _ <- testContext.run(query[Product].delete) - _ <- testContext.run(liftQuery(people).foreach(p => peopleInsert(p))) - } yield () - } - } - super.beforeEach() - } - - "Ex 0 insert.returning(_.generatedColumn) mod" in { - import `Ex 0 insert.returning(_.generatedColumn) mod`._ - await(for { - id <- testContext.run(op) - output <- testContext.run(get) - } yield (output.toSet mustEqual result(id).toSet)) - } - - "Ex 0.5 insert.returning(wholeRecord) mod" in { - import `Ex 0.5 insert.returning(wholeRecord) mod`._ - await(for { - product <- testContext.run(op) - output <- testContext.run(get) - } yield (output mustEqual result(product))) - } - - "Ex 1 insert.returningMany(_.generatedColumn) mod" in { - import `Ex 1 insert.returningMany(_.generatedColumn) mod`._ - await(for { - id <- testContext.run(op) - output <- testContext.run(get) - } yield (output mustEqual result(id.head))) - } - - "Ex 2 update.returningMany(_.singleColumn) mod" in { - import `Ex 2 update.returningMany(_.singleColumn) mod`._ - await(for { - opResult <- testContext.run(op) - _ = opResult.toSet mustEqual expect.toSet - output <- testContext.run(get) - } yield (output.toSet mustEqual result.toSet)) - } - - "Ex 3 delete.returningMany(wholeRecord)" in { - import `Ex 3 delete.returningMany(wholeRecord)`._ - await(for { - opResult <- testContext.run(op) - _ = opResult.toSet mustEqual expect.toSet - output <- testContext.run(get) - } yield (output.toSet mustEqual result.toSet)) - } - - "Ex 4 update.returningMany(query)" in { - import `Ex 4 update.returningMany(query)`._ - await(for { - opResult <- testContext.run(op) - _ = opResult.toSet mustEqual expect.toSet - output <- testContext.run(get) - } yield (output.toSet mustEqual result.toSet)) - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/ProductFinaglePostgresSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/ProductFinaglePostgresSpec.scala deleted file mode 100644 index 710b1a1f6c..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/ProductFinaglePostgresSpec.scala +++ /dev/null @@ -1,97 +0,0 @@ -package io.getquill.context.finagle.postgres - -import io.getquill.context.sql.ProductSpec -import com.twitter.util.Await -import com.twitter.util.Future -import io.getquill.context.sql.Id - -class ProductFinaglePostgresSpec extends ProductSpec { - - val context = testContext - import testContext._ - - def await[T](r: Future[T]) = Await.result(r) - - override def beforeAll = { - await(testContext.run(quote(query[Product].delete))) - () - } - - "Product" - { - "Insert multiple products" in { - val inserted = await(Future.collect(productEntries.map(product => testContext.run(productInsert(lift(product)))))) - val product = await(testContext.run(productById(lift(inserted(2))))).head - product.description mustEqual productEntries(2).description - product.id mustEqual inserted(2) - } - "Single insert product" in { - val inserted = await(testContext.run(productSingleInsert)) - val product = await(testContext.run(productById(lift(inserted)))).head - product.description mustEqual "Window" - product.id mustEqual inserted - } - - "Single insert with inlined free variable" in { - val prd = Product(0L, "test1", 1L) - val inserted = await { - testContext.run { - product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returning(_.id) - } - } - val returnedProduct = await(testContext.run(productById(lift(inserted)))).head - returnedProduct.description mustEqual "test1" - returnedProduct.sku mustEqual 1L - returnedProduct.id mustEqual inserted - } - - "Single insert with free variable and explicit quotation" in { - val prd = Product(0L, "test2", 2L) - val q1 = quote { - product.insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returning(_.id) - } - val inserted = await(testContext.run(q1)) - val returnedProduct = await(testContext.run(productById(lift(inserted)))).head - returnedProduct.description mustEqual "test2" - returnedProduct.sku mustEqual 2L - returnedProduct.id mustEqual inserted - } - - "Single product insert with a method quotation" in { - val prd = Product(0L, "test3", 3L) - val inserted = await(testContext.run(productInsert(lift(prd)))) - val returnedProduct = await(testContext.run(productById(lift(inserted)))).head - returnedProduct.description mustEqual "test3" - returnedProduct.sku mustEqual 3L - returnedProduct.id mustEqual inserted - } - - "Single insert with value class" in { - case class Product(id: Id, description: String, sku: Long) - val prd = Product(Id(0L), "test2", 2L) - val q1 = quote { - query[Product].insert(_.sku -> lift(prd.sku), _.description -> lift(prd.description)).returning(_.id) - } - await(testContext.run(q1)) mustBe a[Id] - } - - "supports casts from string to number" - { - "toInt" in { - case class Product(id: Long, description: String, sku: Int) - val queried = await { - testContext.run { - query[Product].filter(_.sku == lift("1004").toInt) - } - }.head - queried.sku mustEqual 1004L - } - "toLong" in { - val queried = await { - testContext.run { - query[Product].filter(_.sku == lift("1004").toLong) - } - }.head - queried.sku mustEqual 1004L - } - } - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/QueryResultTypeFinaglePostgresSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/QueryResultTypeFinaglePostgresSpec.scala deleted file mode 100644 index eec2e6e4db..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/QueryResultTypeFinaglePostgresSpec.scala +++ /dev/null @@ -1,108 +0,0 @@ -package io.getquill.context.finagle.postgres - -import io.getquill.context.sql._ -import com.twitter.util.{Await, Future} -import io.getquill.context.sql.base.QueryResultTypeSpec - -import java.util.concurrent.ConcurrentLinkedQueue -import scala.jdk.CollectionConverters._ - -class QueryResultTypeFinaglePostgresSpec extends QueryResultTypeSpec { - - val context = testContext - import testContext._ - - def await[T](r: Future[T]) = Await.result(r) - - val insertedProducts = new ConcurrentLinkedQueue[Product] - - override def beforeAll = { - await(testContext.run(deleteAll)) - val rs = await(testContext.run(liftQuery(productEntries).foreach(e => productInsert(e)))) - val inserted = (rs zip productEntries).map { case (r, prod) => - prod.copy(id = r) - } - insertedProducts.addAll(inserted.asJava) - () - } - - def products = insertedProducts.asScala.toList - - "return list" - { - "select" in { - await(testContext.run(selectAll)) must contain theSameElementsAs (products) - } - "map" in { - await(testContext.run(map)) must contain theSameElementsAs (products.map(_.id)) - } - "filter" in { - await(testContext.run(filter)) must contain theSameElementsAs (products) - } - "withFilter" in { - await(testContext.run(withFilter)) must contain theSameElementsAs (products) - } - "sortBy" in { - await(testContext.run(sortBy)) must contain theSameElementsInOrderAs (products) - } - "take" in { - await(testContext.run(take)) must contain theSameElementsAs (products) - } - "drop" in { - await(testContext.run(drop)) must contain theSameElementsAs (products.drop(1)) - } - "++" in { - await(testContext.run(`++`)) must contain theSameElementsAs (products ++ products) - } - "unionAll" in { - await(testContext.run(unionAll)) must contain theSameElementsAs (products ++ products) - } - "union" in { - await(testContext.run(union)) must contain theSameElementsAs (products) - } - "join" in { - await(testContext.run(join)) must contain theSameElementsAs (products zip products) - } - "distinct" in { - await(testContext.run(distinct)) must contain theSameElementsAs (products.map(_.id).distinct) - } - } - - "return single result" - { - "min" - { - "some" in { - await(testContext.run(minExists)) mustEqual Some(products.map(_.sku).min) - } - "none" in { - await(testContext.run(minNonExists)) mustBe None - } - } - "max" - { - "some" in { - await(testContext.run(maxExists)) mustBe Some(products.map(_.sku).max) - } - "none" in { - await(testContext.run(maxNonExists)) mustBe None - } - } - "avg" - { - "some" in { - await(testContext.run(avgExists)) mustBe Some(BigDecimal(products.map(_.sku).sum) / products.size) - } - "none" in { - await(testContext.run(avgNonExists)) mustBe None - } - } - "size" in { - await(testContext.run(productSize)) mustEqual products.size - } - "parametrized size" in { - await(testContext.run(parametrizedSize(lift(10000)))) mustEqual 0 - } - "nonEmpty" in { - await(testContext.run(nonEmpty)) mustEqual true - } - "isEmpty" in { - await(testContext.run(isEmpty)) mustEqual false - } - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/TestContext.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/TestContext.scala deleted file mode 100644 index b2a8bef253..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/TestContext.scala +++ /dev/null @@ -1,11 +0,0 @@ -package io.getquill.context.finagle.postgres - -import io.getquill._ -import io.getquill.context.sql.{TestDecoders, TestEncoders} -import io.getquill.FinaglePostgresContext - -object testContext - extends FinaglePostgresContext(Literal, "testPostgresDB") - with TestEntities - with TestEncoders - with TestDecoders diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/TransactionSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/TransactionSpec.scala deleted file mode 100644 index 36dbc197d3..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/context/finagle/postgres/TransactionSpec.scala +++ /dev/null @@ -1,58 +0,0 @@ -package io.getquill.context.finagle.postgres - -import com.twitter.util.{Await, Future, Throw} - -import io.getquill.context.sql.ProductSpec - -class TransactionSpec extends ProductSpec { - val context = testContext - import context._ - - def await[T](future: Future[T]) = Await.result(future) - - val p = Product(0L, "Scala Compiler", 1L) - - "If outer transaction fails, inner transactions shouldn't commit" in { - val id: Long = await { - context.transaction { - for { - id <- context.transaction { - context.run(productInsert(lift(p))) - } - Throw(_) <- context.transaction { - context - .run(quote { - query[Product].insertValue(lift(p.copy(id = id))) - }) - .liftToTry - } - } yield id - } - } - // Since a query inside a transaction failed, the outermost transaction had - // to rollback. - val res: List[Product] = await(context.run(productById(lift(id)))) - res mustEqual List() - } - - "Transaction inside transaction should not open a new client" in { - val res: Product = await { - context.transaction { - for { - id: Long <- context.run(productInsert(lift(p))) - // A subtransaction should have access to the previous queries of an - // outer transaction. - res: List[Product] <- context.transaction { - context.run(productById(lift(id))) - } - } yield res.head - } - } - res mustEqual p.copy(id = res.id) - } - - override def beforeAll = { - await(context.run(quote(query[Product].delete))) - () - } -} diff --git a/quill-finagle-postgres/src/test/scala/io/getquill/monad/TwitterFutureIOMonadSpec.scala b/quill-finagle-postgres/src/test/scala/io/getquill/monad/TwitterFutureIOMonadSpec.scala deleted file mode 100644 index cd83ae03b3..0000000000 --- a/quill-finagle-postgres/src/test/scala/io/getquill/monad/TwitterFutureIOMonadSpec.scala +++ /dev/null @@ -1,16 +0,0 @@ -package io.getquill.monad - -import io.getquill.context.finagle.postgres.testContext -import com.twitter.util.{Await, Future} - -class TwitterFutureIOMonadSpec extends IOMonadSpec { - - override val ctx = testContext - import ctx._ - - override def eval[T](io: IO[T, _]): T = - Await.result(performIO(io)) - - override def resultValue[T](x: T): Result[T] = Future.value[T](x) - -}