From 55de62a5a73026c977df4bbe09457162e33556eb Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sun, 17 Aug 2025 13:22:42 +1000 Subject: [PATCH 1/7] Simplify No more free monad for every JDBC method, instead just a simple one for `ConnectionIO`. No more `fs2` support. There is no reason to stream results from a database. If the result is small enough then use a collection. If it is too large then do multiple database calls using cursor pagination on the tables primary key. This means that the core module no longer depends on `cats-effect` or `fs2`. Also no more support for testing libraries that have test methods that return `Unit`. Use a testing library that requires tests return value. --- build.sbt | 138 +- .../src/main/scala/doobie/bench/select.scala | 36 +- .../src/main/scala/doobie/bench/text.scala | 75 - .../scala/doobie/enumerated/package.scala | 11 - .../doobie/free/connection/ConnectionIO.scala | 360 ++++ .../doobie/free/connection/package.scala | 8 + .../src/main/scala/doobie/hi/connection.scala | 321 ---- .../src/main/scala/doobie/hi/package.scala | 30 - .../scala/doobie/hi/preparedstatement.scala | 263 --- .../src/main/scala/doobie/hi/resultset.scala | 341 ---- .../src/main/scala/doobie/hi/statement.scala | 129 -- .../core/src/main/scala/doobie/package.scala | 20 - .../scala/doobie/syntax/connectionio.scala | 36 +- .../src/main/scala/doobie/syntax/stream.scala | 31 - .../scala/doobie/util/ExecutionContexts.scala | 45 - .../src/main/scala/doobie/util/fragment.scala | 12 - .../core/src/main/scala/doobie/util/get.scala | 2 +- .../main/scala/doobie/util/invariant.scala | 2 +- .../core/src/main/scala/doobie/util/io.scala | 105 -- .../src/main/scala/doobie/util/lens.scala | 50 - .../main/scala/doobie/util/meta/meta.scala | 2 +- .../core/src/main/scala/doobie/util/put.scala | 2 +- .../src/main/scala/doobie/util/query.scala | 97 +- .../src/main/scala/doobie/util/read.scala | 4 - .../src/main/scala/doobie/util/stream.scala | 15 - .../scala/doobie/util/testing/analysis.scala | 10 +- .../scala/doobie/util/testing/package.scala | 1 + .../main/scala/doobie/util/transactor.scala | 403 +---- .../src/main/scala/doobie/util/update.scala | 108 +- .../src/main/scala/doobie/util/write.scala | 7 - .../src/main/scala/doobie/util/yolo.scala | 114 -- .../src/test/scala/doobie/issue/262.scala | 40 - .../scala/doobie}/stub/StubConnection.scala | 29 +- .../doobie}/stub/StubPreparedStatement.scala | 21 +- .../scala/doobie}/stub/StubResultSet.scala | 24 +- .../scala/doobie/util/ConnectionIOSuite.scala | 2 + .../test/scala/doobie/util/LensSuite.scala | 51 - .../test/scala/doobie/util/ProcessSuite.scala | 37 - .../scala/doobie/util/StrategySuite.scala | 206 +-- .../scala/doobie/util/TransactorSuite.scala | 87 - .../test/scala/doobie/util/UpdateSuite.scala | 10 - modules/docs/src/main/mdoc/docs/17-FAQ.md | 221 --- .../example/CallableStatementExample.scala | 62 - .../src/main/scala/example/Coproduct.scala | 123 -- .../src/main/scala/example/Dynamic.scala | 64 - .../src/main/scala/example/FirstExample.scala | 42 +- .../main/scala/example/FragmentExample.scala | 21 +- .../src/main/scala/example/FreeUsage.scala | 77 - .../main/scala/example/GenericStream.scala | 113 -- .../src/main/scala/example/HiUsage.scala | 50 - .../main/scala/example/HikariExample.scala | 34 - .../main/scala/example/LoggingExample.scala | 60 - .../src/main/scala/example/OtherSchema.scala | 26 +- .../scala/example/PostgresCopyInCsv.scala | 81 - .../scala/example/PostgresLargeObject.scala | 43 - .../main/scala/example/PostgresNotify.scala | 74 - .../main/scala/example/PostgresPoint.scala | 15 +- .../src/main/scala/example/StreamToFile.scala | 38 - .../main/scala/example/StreamingCopy.scala | 182 -- .../src/main/scala/doobie/free/blob.scala | 212 --- .../scala/doobie/free/callablestatement.scala | 1365 --------------- .../src/main/scala/doobie/free/clob.scala | 224 --- .../main/scala/doobie/free/connection.scala | 474 ----- .../scala/doobie/free/databasemetadata.scala | 1096 ------------ .../src/main/scala/doobie/free/driver.scala | 194 --- .../src/main/scala/doobie/free/embedded.scala | 46 - .../doobie/free/kleisliinterpreter.scala | 1549 ----------------- .../src/main/scala/doobie/free/nclob.scala | 225 --- .../scala/doobie/free/preparedstatement.scala | 754 -------- .../free/src/main/scala/doobie/free/ref.scala | 173 -- .../main/scala/doobie/free/resultset.scala | 1130 ------------ .../src/main/scala/doobie/free/sqldata.scala | 172 -- .../src/main/scala/doobie/free/sqlinput.scala | 309 ---- .../main/scala/doobie/free/sqloutput.scala | 312 ---- .../main/scala/doobie/free/statement.scala | 438 ----- .../src/main/scala/doobie/h2/H2Helper.scala | 11 +- .../main/scala/doobie/h2/H2Transactor.scala | 18 +- .../h2/src/main/scala/doobie/h2/package.scala | 4 +- .../test/scala/doobie/h2/H2DatabaseSpec.scala | 3 +- .../src/main/scala/doobie/hikari/Config.scala | 109 -- .../doobie/hikari/HikariTransactor.scala | 162 -- .../main/scala/doobie/hikari/package.scala | 14 - .../test/scala/doobie/hikari/ConfigSpec.scala | 62 - .../scala-2/doobie/util/PosPlatform.scala | 0 .../doobie/util/TypeNamePlatform.scala | 31 + .../scala-3/doobie/util/PosPlatform.scala | 0 .../doobie/util/TypeNamePlatform.scala.scala | 22 + .../src/main/scala/doobie/util/pos.scala | 0 .../src/main/scala/doobie/util/typename.scala | 12 + .../scala/doobie/munit/analysisspec.scala | 82 - .../src/main/scala/doobie/munit/package.scala | 12 - .../scala/doobie/munit/CheckerTests.scala | 43 - .../doobie/postgis/instances/geography.scala | 2 +- .../doobie/postgis/instances/geometry.scala | 2 +- .../doobie/postgis/PostgisDatabaseSpec.scala | 14 +- .../src/main/scala/doobie/postgres/Text.scala | 5 + .../scala/doobie/postgres/free/copyin.scala | 206 --- .../doobie/postgres/free/copymanager.scala | 215 --- .../scala/doobie/postgres/free/copyout.scala | 195 --- .../scala/doobie/postgres/free/embedded.scala | 31 - .../postgres/free/kleisliinterpreter.scala | 361 ---- .../doobie/postgres/free/largeobject.scala | 254 --- .../postgres/free/largeobjectmanager.scala | 221 --- .../doobie/postgres/free/pgconnection.scala | 277 --- .../main/scala/doobie/postgres/fs2io.scala | 91 - .../scala/doobie/postgres/hi/connection.scala | 91 - .../doobie/postgres/hi/largeobject.scala | 35 - .../postgres/hi/largeobjectmanager.scala | 52 - .../doobie/postgres/hi/lostreaming.scala | 44 - .../scala/doobie/postgres/hi/package.scala | 14 - .../doobie/postgres/hi/pgconnection.scala | 37 - .../postgres/instances/enumeration.scala | 2 +- .../doobie/postgres/instances/json.scala | 2 +- .../main/scala/doobie/postgres/package.scala | 21 - .../doobie/postgres/syntax/explain.scala | 131 -- .../doobie/postgres/syntax/fragment.scala | 90 - .../doobie/postgres/LOStreamingSuite.scala | 41 - .../test/scala/doobie/postgres/LOSuite.scala | 66 - .../scala/doobie/postgres/ManyRowsSuite.scala | 30 - .../scala/doobie/postgres/NotifySuite.scala | 74 - .../scala/doobie/postgres/PGCopySuite.scala | 104 -- .../postgres/PostgresDatabaseSpec.scala | 21 +- .../scala/doobie/postgres/SyntaxSuite.scala | 4 +- .../scala/doobie/postgres/TextSuite.scala | 54 +- .../doobie/scalatest/AnalysisMatchers.scala | 59 - .../main/scala/doobie/scalatest/Checker.scala | 93 - .../scala/doobie/scalatest/CheckerTests.scala | 25 - .../scala/doobie/scalatest/MatcherTests.scala | 36 - .../main/scala/doobie/weaver/Checker.scala | 11 +- .../zoobie/TransactorIntegrationSpec.scala | 71 + ...ec.scala => PostgresIntegrationSpec.scala} | 15 +- .../SQLCommenterIntegrationSpec.scala | 40 +- .../main/scala/zoobie/ConnectionProxy.scala | 2 +- .../src/main/scala/zoobie/Transactor.scala | 113 +- .../sqlcommenter/TraceInterpreter.scala | 128 +- .../src/main/scala/zoobie/test/Checker.scala | 5 +- .../scala/zoobie/ConnectionPoolSpec.scala | 2 +- .../scala/zoobie/ConnectionProxySpec.scala | 2 +- .../test/scala/zoobie/TransactorSpec.scala | 6 +- project/FreeGen2.scala | 570 ------ project/build.properties | 2 +- project/build.sbt | 3 - 142 files changed, 979 insertions(+), 16860 deletions(-) delete mode 100644 modules/bench/src/main/scala/doobie/bench/text.scala delete mode 100644 modules/core/src/main/scala/doobie/enumerated/package.scala create mode 100644 modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala create mode 100644 modules/core/src/main/scala/doobie/free/connection/package.scala delete mode 100644 modules/core/src/main/scala/doobie/hi/connection.scala delete mode 100644 modules/core/src/main/scala/doobie/hi/package.scala delete mode 100644 modules/core/src/main/scala/doobie/hi/preparedstatement.scala delete mode 100644 modules/core/src/main/scala/doobie/hi/resultset.scala delete mode 100644 modules/core/src/main/scala/doobie/hi/statement.scala delete mode 100644 modules/core/src/main/scala/doobie/syntax/stream.scala delete mode 100644 modules/core/src/main/scala/doobie/util/ExecutionContexts.scala delete mode 100644 modules/core/src/main/scala/doobie/util/io.scala delete mode 100644 modules/core/src/main/scala/doobie/util/lens.scala delete mode 100644 modules/core/src/main/scala/doobie/util/stream.scala delete mode 100644 modules/core/src/main/scala/doobie/util/yolo.scala delete mode 100644 modules/core/src/test/scala/doobie/issue/262.scala rename modules/{zio/src/test/scala/zoobie => core/src/test/scala/doobie}/stub/StubConnection.scala (86%) rename modules/{zio/src/test/scala/zoobie => core/src/test/scala/doobie}/stub/StubPreparedStatement.scala (92%) rename modules/{zio/src/test/scala/zoobie => core/src/test/scala/doobie}/stub/StubResultSet.scala (95%) delete mode 100644 modules/core/src/test/scala/doobie/util/LensSuite.scala delete mode 100644 modules/core/src/test/scala/doobie/util/ProcessSuite.scala delete mode 100644 modules/core/src/test/scala/doobie/util/TransactorSuite.scala delete mode 100644 modules/docs/src/main/mdoc/docs/17-FAQ.md delete mode 100644 modules/example/src/main/scala/example/CallableStatementExample.scala delete mode 100644 modules/example/src/main/scala/example/Coproduct.scala delete mode 100644 modules/example/src/main/scala/example/Dynamic.scala delete mode 100644 modules/example/src/main/scala/example/FreeUsage.scala delete mode 100644 modules/example/src/main/scala/example/GenericStream.scala delete mode 100644 modules/example/src/main/scala/example/HiUsage.scala delete mode 100644 modules/example/src/main/scala/example/HikariExample.scala delete mode 100644 modules/example/src/main/scala/example/LoggingExample.scala delete mode 100644 modules/example/src/main/scala/example/PostgresCopyInCsv.scala delete mode 100644 modules/example/src/main/scala/example/PostgresLargeObject.scala delete mode 100644 modules/example/src/main/scala/example/PostgresNotify.scala delete mode 100644 modules/example/src/main/scala/example/StreamToFile.scala delete mode 100644 modules/example/src/main/scala/example/StreamingCopy.scala delete mode 100644 modules/free/src/main/scala/doobie/free/blob.scala delete mode 100644 modules/free/src/main/scala/doobie/free/callablestatement.scala delete mode 100644 modules/free/src/main/scala/doobie/free/clob.scala delete mode 100644 modules/free/src/main/scala/doobie/free/connection.scala delete mode 100644 modules/free/src/main/scala/doobie/free/databasemetadata.scala delete mode 100644 modules/free/src/main/scala/doobie/free/driver.scala delete mode 100644 modules/free/src/main/scala/doobie/free/embedded.scala delete mode 100644 modules/free/src/main/scala/doobie/free/kleisliinterpreter.scala delete mode 100644 modules/free/src/main/scala/doobie/free/nclob.scala delete mode 100644 modules/free/src/main/scala/doobie/free/preparedstatement.scala delete mode 100644 modules/free/src/main/scala/doobie/free/ref.scala delete mode 100644 modules/free/src/main/scala/doobie/free/resultset.scala delete mode 100644 modules/free/src/main/scala/doobie/free/sqldata.scala delete mode 100644 modules/free/src/main/scala/doobie/free/sqlinput.scala delete mode 100644 modules/free/src/main/scala/doobie/free/sqloutput.scala delete mode 100644 modules/free/src/main/scala/doobie/free/statement.scala delete mode 100644 modules/hikari/src/main/scala/doobie/hikari/Config.scala delete mode 100644 modules/hikari/src/main/scala/doobie/hikari/HikariTransactor.scala delete mode 100644 modules/hikari/src/main/scala/doobie/hikari/package.scala delete mode 100644 modules/hikari/src/test/scala/doobie/hikari/ConfigSpec.scala rename modules/{free => macros}/src/main/scala-2/doobie/util/PosPlatform.scala (100%) create mode 100644 modules/macros/src/main/scala-2/doobie/util/TypeNamePlatform.scala rename modules/{free => macros}/src/main/scala-3/doobie/util/PosPlatform.scala (100%) create mode 100644 modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala rename modules/{free => macros}/src/main/scala/doobie/util/pos.scala (100%) create mode 100644 modules/macros/src/main/scala/doobie/util/typename.scala delete mode 100644 modules/munit/src/main/scala/doobie/munit/analysisspec.scala delete mode 100644 modules/munit/src/main/scala/doobie/munit/package.scala delete mode 100644 modules/munit/src/test/scala/doobie/munit/CheckerTests.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/copyin.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/copymanager.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/copyout.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/embedded.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/kleisliinterpreter.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/largeobject.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/largeobjectmanager.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/free/pgconnection.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/fs2io.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/hi/connection.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/hi/largeobject.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/hi/largeobjectmanager.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/hi/lostreaming.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/hi/package.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/hi/pgconnection.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/package.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/syntax/explain.scala delete mode 100644 modules/postgres/src/main/scala/doobie/postgres/syntax/fragment.scala delete mode 100644 modules/postgres/src/test/scala/doobie/postgres/LOStreamingSuite.scala delete mode 100644 modules/postgres/src/test/scala/doobie/postgres/LOSuite.scala delete mode 100644 modules/postgres/src/test/scala/doobie/postgres/ManyRowsSuite.scala delete mode 100644 modules/postgres/src/test/scala/doobie/postgres/NotifySuite.scala delete mode 100644 modules/postgres/src/test/scala/doobie/postgres/PGCopySuite.scala delete mode 100644 modules/scalatest/src/main/scala/doobie/scalatest/AnalysisMatchers.scala delete mode 100644 modules/scalatest/src/main/scala/doobie/scalatest/Checker.scala delete mode 100644 modules/scalatest/src/test/scala/doobie/scalatest/CheckerTests.scala delete mode 100644 modules/scalatest/src/test/scala/doobie/scalatest/MatcherTests.scala create mode 100644 modules/zio/src/it/scala/zoobie/TransactorIntegrationSpec.scala rename modules/zio/src/it/scala/zoobie/postgres/{PostgreSQLIntegrationSpec.scala => PostgresIntegrationSpec.scala} (92%) delete mode 100644 project/FreeGen2.scala delete mode 100644 project/build.sbt diff --git a/build.sbt b/build.sbt index 4d7b0b23f..96b0f6c07 100644 --- a/build.sbt +++ b/build.sbt @@ -1,20 +1,14 @@ // format: off -import FreeGen2.* - val catsVersion = "2.13.0" val catsEffectVersion = "3.6.3" val circeVersion = "0.14.14" -val fs2Version = "3.12.0" val h2Version = "2.3.232" -val hikariVersion = "7.0.1" val magnoliaVersion = "1.1.10" -val munitVersion = "1.1.1" val mysqlVersion = "9.4.0" val openTelemetryVersion = "1.53.0" val postgisVersion = "2025.1.1" val postgresVersion = "42.7.7" -val scalatestVersion = "3.2.19" -val shapelessVersion = "2.3.12" +val shapelessVersion = "2.3.13" val slf4jVersion = "2.0.17" val weaverVersion = "0.8.4" val zioInteropCats = "23.1.0.5" @@ -165,19 +159,18 @@ lazy val foobie = project.in(file(".")) ) .aggregate( modules, integrationTests, - example, bench, docs, + example, bench, /*docs,*/ ) lazy val modules = project.in(file("project/.root")) .settings(commonSettings) .settings(noPublishSettings) .aggregate( - free, core, + core, macros, h2, `h2-circe`, mysql, postgres, `postgres-circe`, postgis, - hikari, - munit, scalatest, weaver, + weaver, zio, ) .disablePlugins(MimaPlugin) @@ -187,66 +180,43 @@ lazy val integrationTests = project.in(file("project/.root-integration")) .settings(noPublishSettings) .aggregate(`zio-it`) -lazy val free = module("free") - .settings(freeGen2Settings) +lazy val macros = module("macros") .settings( libraryDependencies ++= Seq( "org.typelevel" %% "cats-core" % catsVersion, - "org.typelevel" %% "cats-free" % catsVersion, - "org.typelevel" %% "cats-effect-kernel" % catsEffectVersion, ), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, _)) => Seq(scalaOrganization.value % "scala-reflect" % scalaVersion.value) // for macros + case Some((2, _)) => Seq(scalaOrganization.value % "scala-reflect" % scalaVersion.value) case _ => Seq.empty }), - freeGen2Dir := (Compile / scalaSource).value / "doobie" / "free", - freeGen2Package := "doobie.free", - freeGen2Classes := List[Class[?]]( - classOf[java.sql.NClob], - classOf[java.sql.Blob], - classOf[java.sql.Clob], - classOf[java.sql.DatabaseMetaData], - classOf[java.sql.Driver], - classOf[java.sql.Ref], - classOf[java.sql.SQLData], - classOf[java.sql.SQLInput], - classOf[java.sql.SQLOutput], - classOf[java.sql.Connection], - classOf[java.sql.Statement], - classOf[java.sql.PreparedStatement], - classOf[java.sql.CallableStatement], - classOf[java.sql.ResultSet] - ), ) lazy val core = module("core") .settings( libraryDependencies ++= Seq( "org.typelevel" %% "cats-core" % catsVersion, - "org.typelevel" %% "cats-effect-kernel" % catsEffectVersion, - "co.fs2" %% "fs2-core" % fs2Version, - "org.tpolecat" %% "typename" % "1.1.0", + "org.typelevel" %% "cats-free" % catsVersion, + "org.typelevel" %% "cats-effect-kernel" % catsEffectVersion % Optional, "com.h2database" % "h2" % h2Version % Test, "dev.zio" %% "zio-interop-cats" % zioInteropCats % Test, + "org.typelevel" %% "cats-effect" % catsEffectVersion % Test, "dev.zio" %% "zio-test" % zioVersion % Test, "dev.zio" %% "zio-test-sbt" % zioVersion % Test, ), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((2, _)) => Seq( - "com.softwaremill.magnolia1_2" %% "magnolia" % magnoliaVersion, "com.chuusai" %% "shapeless" % shapelessVersion % Test, + "com.softwaremill.magnolia1_2" %% "magnolia" % magnoliaVersion, ) case _ => Seq.empty }), ) - .dependsOn(free) + .dependsOn(macros) lazy val postgres = module("postgres") - .settings(freeGen2Settings) .settings( libraryDependencies ++= Seq( - "co.fs2" %% "fs2-core" % fs2Version, "org.postgresql" % "postgresql" % postgresVersion, "dev.zio" %% "zio-test" % zioVersion % Test, @@ -256,24 +226,8 @@ lazy val postgres = module("postgres") case Some((2, _)) => Seq("com.chuusai" %% "shapeless" % shapelessVersion) case _ => Seq.empty }), - freeGen2Dir := (Compile / scalaSource).value / "doobie" / "postgres" / "free", - freeGen2Package := "doobie.postgres.free", - freeGen2Classes := List[Class[?]]( - classOf[org.postgresql.copy.CopyIn], - classOf[org.postgresql.copy.CopyManager], - classOf[org.postgresql.copy.CopyOut], - classOf[org.postgresql.largeobject.LargeObject], - classOf[org.postgresql.largeobject.LargeObjectManager], - classOf[org.postgresql.PGConnection] - ), - freeGen2Renames ++= Map( - classOf[org.postgresql.copy.CopyDual] -> "PGCopyDual", - classOf[org.postgresql.copy.CopyIn] -> "PGCopyIn", - classOf[org.postgresql.copy.CopyManager] -> "PGCopyManager", - classOf[org.postgresql.copy.CopyOut] -> "PGCopyOut", - ), ) - .dependsOn(core % "compile->compile;test->test", zio % "test->compile") + .dependsOn(core, core % "test->test", zio % "test->compile") lazy val postgis = module("postgis") .settings( @@ -301,14 +255,16 @@ lazy val mysql = module("mysql") "dev.zio" %% "zio-test-sbt" % zioVersion % Test, ), ) - .dependsOn(core % "compile->compile;test->test", zio % "test->compile") + .dependsOn(core, core % "test->test", zio % "test->compile") lazy val h2 = module("h2") .settings( libraryDependencies ++= Seq( "com.h2database" % "h2" % h2Version, + "org.typelevel" %% "cats-effect-kernel" % catsEffectVersion, "dev.zio" %% "zio-interop-cats" % zioInteropCats % Test, + "org.typelevel" %% "cats-effect" % catsEffectVersion % Test, "dev.zio" %% "zio-test" % zioVersion % Test, "dev.zio" %% "zio-test-sbt" % zioVersion % Test, ) @@ -324,39 +280,6 @@ lazy val `h2-circe` = module("h2-circe") ) .dependsOn(core, h2 % "compile->compile;test->test") -lazy val hikari = module("hikari") - .settings( - libraryDependencies ++= Seq( - "com.zaxxer" % "HikariCP" % hikariVersion, - "org.slf4j" % "slf4j-api" % slf4jVersion, - - "org.slf4j" % "slf4j-nop" % slf4jVersion % Test, - "dev.zio" %% "zio-test" % zioVersion % Test, - "dev.zio" %% "zio-test-sbt" % zioVersion % Test, - ) - ) - .dependsOn(core) - -lazy val munit = module("munit") - .settings( - libraryDependencies ++= Seq( - "org.scalameta" %% "munit" % munitVersion, - - "com.h2database" % "h2" % h2Version % Test, - ) - ) - .dependsOn(core) - -lazy val scalatest = module("scalatest") - .settings( - libraryDependencies ++= Seq( - "org.scalatest" %% "scalatest" % scalatestVersion, - - "com.h2database" % "h2" % h2Version % Test, - ) - ) - .dependsOn(core) - lazy val weaver = module("weaver") .settings( libraryDependencies ++= Seq( @@ -371,8 +294,15 @@ lazy val zio = module("zio") .settings( libraryDependencies ++= Seq( "dev.zio" %% "zio" % zioVersion, - "dev.zio" %% "zio-streams" % zioVersion, - "dev.zio" %% "zio-interop-cats" % zioInteropCats, + ("dev.zio" %% "zio-interop-cats" % zioInteropCats) // optional deps in 2.13 but not in 3 ... + .excludeAll("co.fs2" %% "fs2-core") + .excludeAll("co.fs2" %% "fs2-io") + //.excludeAll("dev.zio" %% "zio-managed") required for compilation + .excludeAll("dev.zio" %% "zio-streams") + .excludeAll("org.typelevel" %% "cats-effect-std") + .excludeAll("org.typelevel" %% "cats-mtl"), + // urgh "Cannot resolve reference to type cats.effect.type.LiftIO" + "org.typelevel" %% "cats-effect" % catsEffectVersion, "dev.zio" %% "zio-test" % zioVersion % Optional, "com.mysql" % "mysql-connector-j" % mysqlVersion % Optional, @@ -384,7 +314,7 @@ lazy val zio = module("zio") "dev.zio" %% "zio-test-sbt" % zioVersion % Test, ), ) - .dependsOn(core) + .dependsOn(core, core % "test->test") lazy val `zio-it` = moduleIT("zio") .settings(moduleName := "zoobie-it") @@ -395,30 +325,35 @@ lazy val `zio-it` = moduleIT("zio") "io.opentelemetry" % "opentelemetry-api" % openTelemetryVersion % Test, ), ) - .dependsOn(zio, postgres) + .dependsOn(zio, postgres, postgres % "test->test") lazy val example = project.in(file("modules/example")) .settings(commonSettings) .settings(noPublishSettings) - .settings(Compile / compile / wartremoverErrors := Nil) - .settings(Test / compile / wartremoverErrors := Nil) .settings( libraryDependencies ++= Seq( - "co.fs2" %% "fs2-io" % fs2Version, + "org.typelevel" %% "cats-effect" % catsEffectVersion, ) ) - .dependsOn(core, postgres, scalatest, hikari, h2) + .settings(Compile / compile / wartremoverErrors := Nil) + .settings(Test / compile / wartremoverErrors := Nil) + .dependsOn(core, postgres, h2) lazy val bench = project.in(file("modules/bench")) .settings(commonSettings) .settings(noPublishSettings) + .settings( + libraryDependencies ++= Seq( + "org.typelevel" %% "cats-effect" % catsEffectVersion, + ) + ) .settings(Compile / compile / wartremoverErrors := Nil) .settings(mimaPreviousArtifacts := Set.empty) .enablePlugins(JmhPlugin) .dependsOn(core, postgres) lazy val docs = project.in(file("modules/docs")) - .dependsOn(core, postgres, postgis, h2, hikari, munit, scalatest, weaver) + .dependsOn(core, postgres, postgis, h2, weaver) .settings(commonSettings) .settings(noPublishSettings) .settings(Compile / compile / wartremoverErrors := Nil) @@ -455,7 +390,6 @@ lazy val docs = project.in(file("modules/docs")) "scala.binary.version" -> CrossVersion.binaryScalaVersion(scalaVersion.value), "version" -> version.value, "catsVersion" -> catsVersion, - "fs2Version" -> fs2Version, "shapelessVersion" -> shapelessVersion, "h2Version" -> h2Version, "postgresVersion" -> postgresVersion, diff --git a/modules/bench/src/main/scala/doobie/bench/select.scala b/modules/bench/src/main/scala/doobie/bench/select.scala index 52b29410a..b95f7f807 100644 --- a/modules/bench/src/main/scala/doobie/bench/select.scala +++ b/modules/bench/src/main/scala/doobie/bench/select.scala @@ -5,6 +5,7 @@ package doobie.bench import cats.effect.IO +import cats.effect.kernel.Resource import cats.syntax.apply.* import doobie.syntax.connectionio.* import doobie.syntax.string.* @@ -17,16 +18,27 @@ import java.sql.DriverManager object shared { @State(Scope.Benchmark) - val xa = Transactor.fromDriverManager[IO]("org.postgresql.Driver", "jdbc:postgresql:world", "postgres", "password") + val xa = { + val conn = Resource.fromAutoCloseable(IO.blocking { + DriverManager.getConnection("jdbc:postgresql:world", "postgres", "password") + }) + Transactor.catsEffect((), conn) + } } +object bench { + implicit val read3Strings: Read[(String, String, String)] = ( + Read[String], + Read[String], + Read[String], + ).tupled +} class bench { import cats.effect.unsafe.implicits.global import shared.* // Baseline hand-written JDBC code def jdbcBench(n: Int): Int = { - Class.forName("org.postgresql.Driver") val co = DriverManager.getConnection("jdbc:postgresql:world", "postgres", "password") try { co.setAutoCommit(false) @@ -51,22 +63,6 @@ class bench { } } - implicit val read3Strings: Read[(String, String, String)] = ( - Read[String], - Read[String], - Read[String], - ).tupled - - // Reading via .stream, which adds a fair amount of overhead - def doobieBenchP(n: Int): Int = - sql"select a.name, b.name, c.name from country a, country b, country c limit $n" - .query[(String, String, String)] - .stream - .compile.toList - .transact(xa) - .map(_.length) - .unsafeRunSync() - // Reading via .list, which uses a lower-level collector def doobieBench(n: Int): Int = sql"select a.name, b.name, c.name from country a, country b, country c limit $n" @@ -97,8 +93,4 @@ class bench { @OperationsPerInvocation(1000) def vector_accum_1000: Int = doobieBenchV(1000) - @Benchmark - @OperationsPerInvocation(1000) - def stream_accum_1000: Int = doobieBenchP(1000) - } diff --git a/modules/bench/src/main/scala/doobie/bench/text.scala b/modules/bench/src/main/scala/doobie/bench/text.scala deleted file mode 100644 index c967164a1..000000000 --- a/modules/bench/src/main/scala/doobie/bench/text.scala +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.bench - -import cats.syntax.apply.* -import cats.syntax.foldable.* -import cats.syntax.functor.* -import doobie.FPS -import doobie.HC -import doobie.HPS -import doobie.free.connection.ConnectionIO -import doobie.postgres.syntax.fragment.* -import doobie.syntax.connectionio.* -import doobie.syntax.string.* -import doobie.util.Write -import fs2.Stream -import org.openjdk.jmh.annotations.* - -final case class Person(name: String, age: Int) -object Person { - implicit val write: Write[Person] = Write.derived -} - -class text { - import cats.effect.unsafe.implicits.global - import shared.* - - def people(n: Int): List[Person] = - List.fill(n)(Person("Bob", 42)) - - def ddl: ConnectionIO[Unit] = - sql"drop table if exists bench_person".update.run *> - sql"create table bench_person (name varchar not null, age integer not null)".update.run.void - - def naive(n: Int): ConnectionIO[Int] = - ddl *> HC.prepareStatement("insert into bench_person (name, age) values (?, ?)")( - people(n).foldRight(HPS.executeBatch)((p, k) => HPS.set(p) *> HPS.addBatch *> k), - ).map(_.combineAll) - - def optimized(n: Int): ConnectionIO[Int] = - ddl *> HC.prepareStatement("insert into bench_person (name, age) values (?, ?)")( - FPS.raw { ps => - people(n).foreach { p => - ps.setString(1, p.name) - ps.setInt(2, p.age) - ps.addBatch() - } - ps.executeBatch.sum - }, - ) - - def copyin_stream(n: Int): ConnectionIO[Long] = - ddl *> sql"COPY bench_person (name, age) FROM STDIN".copyIn(Stream.emits[ConnectionIO, Person](people(n)), 10000) - - def copyin_foldable(n: Int): ConnectionIO[Long] = - ddl *> sql"COPY bench_person (name, age) FROM STDIN".copyIn(people(n)) - - @Benchmark - @OperationsPerInvocation(10000) - def naive_copyin: Int = naive(10000).transact(xa).unsafeRunSync() - - @Benchmark - @OperationsPerInvocation(10000) - def jdbc_copyin: Int = optimized(10000).transact(xa).unsafeRunSync() - - @Benchmark - @OperationsPerInvocation(10000) - def fast_copyin_stream: Long = copyin_stream(10000).transact(xa).unsafeRunSync() - - @Benchmark - @OperationsPerInvocation(10000) - def fast_copyin_foldable: Long = copyin_foldable(10000).transact(xa).unsafeRunSync() -} diff --git a/modules/core/src/main/scala/doobie/enumerated/package.scala b/modules/core/src/main/scala/doobie/enumerated/package.scala deleted file mode 100644 index 3b9933038..000000000 --- a/modules/core/src/main/scala/doobie/enumerated/package.scala +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie - -/** - * Enumerated types for JDBC constants. enumerated values are provided by - * companion modules. - */ -package object enumerated diff --git a/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala b/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala new file mode 100644 index 000000000..fda4346fa --- /dev/null +++ b/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala @@ -0,0 +1,360 @@ +package doobie.free.connection + +import cats.Foldable +import cats.Id +import cats.MonadError +import cats.Monoid +import cats.data.Ior +import cats.data.NonEmptyList +import cats.free.Free +import cats.syntax.foldable.* +import cats.syntax.option.* +import cats.~> +import doobie.enumerated.ColumnNullable +import doobie.enumerated.JdbcType +import doobie.enumerated.Nullability +import doobie.enumerated.ParameterMode +import doobie.enumerated.ParameterNullable +import doobie.syntax.align.* +import doobie.util.Get +import doobie.util.Put +import doobie.util.Read +import doobie.util.Write +import doobie.util.analysis.Analysis +import doobie.util.analysis.ColumnMeta +import doobie.util.analysis.ParameterMeta +import doobie.util.invariant.InvalidOrdinal +import doobie.util.invariant.UnexpectedContinuation +import doobie.util.invariant.UnexpectedEnd + +import java.sql.Connection +import java.sql.DatabaseMetaData +import java.sql.PreparedStatement +import java.sql.ResultSet +import scala.collection.Factory +import scala.util.Using +import scala.util.control.NonFatal + +sealed abstract class ConnectionOp[T] +object ConnectionOp { + + final case class Raw[A](f: Connection => A) extends ConnectionOp[A] + + final case class Delay[A](v: () => A) extends ConnectionOp[A] + + final case class RaiseError[A](t: Throwable) extends ConnectionOp[A] + final case class HandleErrorWith[A](fa: ConnectionIO[A], f: Throwable => ConnectionIO[A]) extends ConnectionOp[A] + + final case class WithPreparedStatement[A]( + sql: String, + create: (Connection, String) => PreparedStatement, + f: PreparedStatement => A, + ) extends ConnectionOp[A] +} + +@SuppressWarnings(Array( + "org.wartremover.warts.MutableDataStructures", + "org.wartremover.warts.Throw", + "org.wartremover.warts.TryPartial", + "org.wartremover.warts.While", +)) +object ConnectionIO { self => + import ConnectionOp.* + import Free.liftF + + def delay[A](a: => A): ConnectionIO[A] = liftF(Delay(() => a)) + val unit: ConnectionIO[Unit] = delay(()) + + val commit: ConnectionIO[Unit] = liftF(Raw(_.commit())) + val rollback: ConnectionIO[Unit] = liftF(Raw(_.rollback())) + def setAutoCommit(autoCommit: Boolean): ConnectionIO[Unit] = liftF(Raw(_.setAutoCommit(autoCommit))) + + def raiseError[A](t: Throwable): ConnectionIO[A] = liftF(RaiseError(t)) + def handleErrorWith[A](fa: ConnectionIO[A])(f: Throwable => ConnectionIO[A]): ConnectionIO[A] = liftF(HandleErrorWith(fa, f)) + + object query { + + def iterator[A, B, C](sql: String, a: A, f: Iterator[B] => C)(implicit R: Read[B], W: Write[A]): ConnectionIO[C] = { + def resultSet(rs: ResultSet) = { + val iterator = new Iterator[B] { + override def hasNext: Boolean = rs.next() + override def next(): B = R.unsafeGet(rs, 1) + } + f(iterator) + } + withPreparedStatementExecuteQuery(sql, a, resultSet) + } + + def collect[F[_], A, B](sql: String, a: A)(implicit R: Read[B], W: Write[A], factory: Factory[B, F[B]]): ConnectionIO[F[B]] = { + withPreparedStatementExecuteQuery(sql, a, resultSetCollect[F, B]) + } + + private[ConnectionIO] def resultSetCollect[F[_], B](rs: ResultSet)(implicit R: Read[B], factory: Factory[B, F[B]]) = { + val b = factory.newBuilder + while (rs.next) { + val _ = b += R.unsafeGet(rs, 1) + } + b.result() + } + + def collectPair[F[_], A, K, V](sql: String, a: A)(implicit + R: Read[(K, V)], + W: Write[A], + factory: Factory[(K, V), Map[K, V]], + ): ConnectionIO[Map[K, V]] = { + def resultSet(rs: ResultSet) = { + val b = factory.newBuilder + while (rs.next) { + val _ = b += R.unsafeGet(rs, 1) + } + b.result() + } + withPreparedStatementExecuteQuery(sql, a, resultSet) + } + + def unique[A, B](sql: String, a: A)(implicit R: Read[B], W: Write[A]): ConnectionIO[B] = { + withPreparedStatementExecuteQuery(sql, a, resultSetUnique[B]) + } + + private[ConnectionIO] def resultSetUnique[B](rs: ResultSet)(implicit R: Read[B]) = { + if (!rs.next()) { + throw UnexpectedEnd() + } + val r = R.unsafeGet(rs, 1) + if (rs.next()) { + throw UnexpectedContinuation() + } + r + } + + def option[A, B](sql: String, a: A)(implicit R: Read[B], W: Write[A]): ConnectionIO[Option[B]] = { + def resultSet(rs: ResultSet) = { + val r = Option.when(rs.next())(R.unsafeGet(rs, 1)) + if (rs.next()) { + throw UnexpectedContinuation() + } + r + } + withPreparedStatementExecuteQuery(sql, a, resultSet) + } + + def nel[A, B](sql: String, a: A)(implicit R: Read[B], W: Write[A]): ConnectionIO[NonEmptyList[B]] = { + def resultSet(rs: ResultSet) = { + if (!rs.next()) { + throw UnexpectedEnd() + } + val head = R.unsafeGet(rs, 1) + val tail = { + val b = List.newBuilder[B] + while (rs.next) { + val _ = b += R.unsafeGet(rs, 1) + } + b.result() + } + NonEmptyList(head, tail) + } + withPreparedStatementExecuteQuery(sql, a, resultSet) + } + + private def withPreparedStatementExecuteQuery[A, B](sql: String, a: A, f: ResultSet => B)(implicit W: Write[A]) = { + withPreparedStatement( + sql, + _.prepareStatement(_), + statement => { + W.unsafeSet(statement, 1, a) + Using.resource(statement.executeQuery())(f) + }, + ) + } + } + + object update { + + def run[A](sql: String, a: A)(implicit W: Write[A]): ConnectionIO[Int] = { + def statement(ps: PreparedStatement) = { + W.unsafeSet(ps, 1, a) + ps.executeUpdate() + } + withPreparedStatement(sql, _.prepareStatement(_), statement) + } + + def many[F[_]: Foldable, A](sql: String, fa: F[A])(implicit W: Write[A]): ConnectionIO[Int] = { + def statement(ps: PreparedStatement) = { + if (fa.isEmpty) { + 0 + } else { + fa.toIterable.foreach { a => + W.unsafeSet(ps, 1, a) + ps.addBatch() + } + ps.executeBatch().foldLeft(0)((acc, n) => acc + n.max(0)) // treat negatives (failures) as no rows updated + } + } + withPreparedStatement(sql, _.prepareStatement(_), statement) + } + + def manyReturningGeneratedKeys[F[_]: Foldable, A, B]( + sql: String, + fa: F[A], + columns: List[String], + )(implicit W: Write[A], R: Read[B], F: Factory[B, F[B]]): ConnectionIO[F[B]] = { + def statement(ps: PreparedStatement) = { + if (fa.isEmpty) { + F.newBuilder.result() + } else { + fa.toIterable.foreach { a => + W.unsafeSet(ps, 1, a) + ps.addBatch() + } + val _ = ps.executeBatch() + Using.resource(ps.getGeneratedKeys)(query.resultSetCollect[F, B]) + } + } + withPreparedStatement(sql, _.prepareStatement(_, columns.toArray), statement) + } + + def generatedKeysUnique[A, B](sql: String, a: A, columns: List[String])(implicit W: Write[A], R: Read[B]): ConnectionIO[B] = { + def statement(ps: PreparedStatement) = { + W.unsafeSet(ps, 1, a) + val _ = ps.executeUpdate() + Using.resource(ps.getGeneratedKeys)(query.resultSetUnique[B]) + } + withPreparedStatement(sql, _.prepareStatement(_, columns.toArray), statement) + } + } + + private def withPreparedStatement[A]( + sql: String, + create: (Connection, String) => PreparedStatement, + f: PreparedStatement => A, + ): ConnectionIO[A] = { + liftF[ConnectionOp, A](WithPreparedStatement(sql, create, f)) + } + + def prepareQueryAnalysis[A, B](sql: String)(implicit W: Write[A], R: Read[B]): ConnectionIO[Analysis] = + prepareAnalysis(sql, W.some, R.some) + + def prepareQueryAnalysis0[B](sql: String)(implicit R: Read[B]): ConnectionIO[Analysis] = + prepareAnalysis(sql, None, R.some) + + def prepareUpdateAnalysis[A](sql: String)(implicit W: Write[A]): ConnectionIO[Analysis] = + prepareAnalysis(sql, W.some, None) + + def prepareUpdateAnalysis0(sql: String): ConnectionIO[Analysis] = + prepareAnalysis(sql, None, None) + + type PrepareAnalysisMeta = ( + List[Ior[(Put[?], Nullability.NullabilityKnown), ParameterMeta]], + List[Ior[(Get[?], Nullability.NullabilityKnown), ColumnMeta]], + ) + + private def prepareAnalysis[A, B]( + sql: String, + write: Option[Write[A]], + read: Option[Read[B]], + ): ConnectionIO[Analysis] = for { + dbMetaData <- liftF[ConnectionOp, DatabaseMetaData](Raw(_.getMetaData())) + driver = dbMetaData.getDriverName + tuple <- liftF[ConnectionOp, PrepareAnalysisMeta](WithPreparedStatement( + sql, + (c, s) => c.prepareStatement(s), + s => (parameterMetadata(write, s), columnMeta(read, s)), + )) + (p, c) = tuple + } yield { + Analysis(driver, sql, p, c) + } + + private def columnMeta(read: Option[Read[?]], statement: PreparedStatement) = (for { + r <- read + md <- Option(statement.getMetaData) + } yield { + val m = (1 to md.getColumnCount).toList.map { i => + val n = ColumnNullable.fromInt(md.isNullable(i)).getOrElse { + throw InvalidOrdinal[ColumnNullable](i) + } + val j = JdbcType.fromInt(md.getColumnType(i)) + val s = md.getColumnTypeName(i) + val c = md.getColumnName(i) + ColumnMeta(j, s, n.toNullability, c) + } + r.gets.toList.align(m) + }).orEmpty + + private def parameterMetadata(write: Option[Write[?]], statement: PreparedStatement) = (for { + w <- write + md <- Option(statement.getParameterMetaData) + } yield { + val m = (1 to md.getParameterCount).toList.map { i => + val n = ParameterNullable.fromInt(md.isNullable(i)).getOrElse { + throw InvalidOrdinal[ParameterNullable](i) + } + val m = ParameterMode.fromInt(md.getParameterMode(i)).getOrElse { + throw InvalidOrdinal[ParameterMode](i) + } + val j = JdbcType.fromInt(md.getParameterType(i)) + val s = md.getParameterTypeName(i) + ParameterMeta(j, s, n.toNullability, m) + } + w.puts.toList.align(m) + }).orEmpty + + private val monad = Free.catsFreeMonadForFree[ConnectionOp] + + implicit val MonadErrorConnectionIO: MonadError[ConnectionIO, Throwable] = new MonadError[ConnectionIO, Throwable] { + override def pure[A](x: A) = monad.pure(x) + override def map[A, B](fa: ConnectionIO[A])(f: A => B) = monad.map(fa)(f) + override def flatMap[A, B](fa: ConnectionIO[A])(f: A => ConnectionIO[B]) = monad.flatMap(fa)(f) + override def tailRecM[A, B](a: A)(f: A => ConnectionIO[Either[A, B]]) = monad.tailRecM(a)(f) + override def raiseError[A](e: Throwable) = self.raiseError[A](e) + override def handleErrorWith[A](fa: ConnectionIO[A])(f: Throwable => ConnectionIO[A]) = self.handleErrorWith(fa)(f) + } + + implicit def MonoidConnectionIO[A](implicit M: Monoid[A]): Monoid[ConnectionIO[A]] = + new Monoid[ConnectionIO[A]] { + override val empty = monad.pure(M.empty) + override def combine(x: ConnectionIO[A], y: ConnectionIO[A]) = + monad.product(x, y).map { case (x, y) => M.combine(x, y) } + } + + @SuppressWarnings(Array("org.wartremover.warts.Throw")) + def interpreter(conn: Connection): ConnectionOp ~> Id = new (ConnectionOp ~> Id) { + override def apply[A](fa: ConnectionOp[A]) = fa match { + case Raw(f) => f(conn) + case Delay(f) => f() + case RaiseError(t) => throw t + case HandleErrorWith(fa, f) => + val run = Free.foldMap(this) + try { + run(fa) + } catch { + case NonFatal(t) => run(f(t)) + } + + case WithPreparedStatement(sql, create, f) => + Using.resource(create(conn, sql)) { stmt => + stmt.setFetchSize(1024) + f(stmt) + } + } + } + + def interpreterCatsEffect[M[_]](conn: Connection)(implicit M: cats.effect.kernel.Sync[M]): ConnectionOp ~> M = new (ConnectionOp ~> M) { + override def apply[A](fa: ConnectionOp[A]) = fa match { + case Raw(f) => M.blocking(f(conn)) + case Delay(f) => M.delay(f()) + case RaiseError(t) => M.raiseError(t) + case HandleErrorWith(fa, f) => + val run = Free.foldMap(this) + M.handleErrorWith(run(fa))(t => run(f(t))) + + case WithPreparedStatement(sql, create, f) => + cats.effect.kernel.Resource.fromAutoCloseable(M.blocking(create(conn, sql))).use { stmt => + M.blocking { + stmt.setFetchSize(1024) + f(stmt) + } + } + } + } +} diff --git a/modules/core/src/main/scala/doobie/free/connection/package.scala b/modules/core/src/main/scala/doobie/free/connection/package.scala new file mode 100644 index 000000000..320be22a1 --- /dev/null +++ b/modules/core/src/main/scala/doobie/free/connection/package.scala @@ -0,0 +1,8 @@ +package doobie.free + +import cats.free.Free + +package object connection { + + type ConnectionIO[A] = Free[ConnectionOp, A] +} diff --git a/modules/core/src/main/scala/doobie/hi/connection.scala b/modules/core/src/main/scala/doobie/hi/connection.scala deleted file mode 100644 index a3186cc40..000000000 --- a/modules/core/src/main/scala/doobie/hi/connection.scala +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.hi - -import cats.Foldable -import cats.data.Ior -import cats.effect.kernel.syntax.monadCancel.* -import cats.syntax.apply.* -import cats.syntax.foldable.* -import doobie.FC -import doobie.FCS -import doobie.FDMD -import doobie.FPS -import doobie.FRS -import doobie.FS -import doobie.enumerated.AutoGeneratedKeys -import doobie.enumerated.Holdability -import doobie.enumerated.Nullability -import doobie.enumerated.ResultSetConcurrency -import doobie.enumerated.ResultSetType -import doobie.enumerated.TransactionIsolation -import doobie.free.callablestatement.CallableStatementIO -import doobie.free.connection.ConnectionIO -import doobie.free.databasemetadata.DatabaseMetaDataIO -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.statement.StatementIO -import doobie.util.Get -import doobie.util.Put -import doobie.util.Read -import doobie.util.Write -import doobie.util.analysis.Analysis -import doobie.util.analysis.ColumnMeta -import doobie.util.analysis.ParameterMeta -import doobie.util.stream.repeatEvalChunks -import fs2.Stream - -import java.sql.PreparedStatement -import java.sql.ResultSet -import java.sql.Savepoint -import scala.collection.Factory -import scala.jdk.CollectionConverters.* - -/** - * Module of high-level constructors for `ConnectionIO` actions. - * @group Modules - */ -object connection { - - /** @group Lifting */ - def delay[A](a: => A): ConnectionIO[A] = - FC.delay(a) - - private def liftStream[A: Read]( - chunkSize: Int, - create: ConnectionIO[PreparedStatement], - prep: PreparedStatementIO[Unit], - exec: PreparedStatementIO[ResultSet], - ): Stream[ConnectionIO, A] = { - - def prepared(ps: PreparedStatement): Stream[ConnectionIO, PreparedStatement] = - Stream.eval[ConnectionIO, PreparedStatement] { - val fs = FPS.setFetchSize(chunkSize) - FC.embed(ps, fs *> prep).map(_ => ps) - } - - def unrolled(rs: ResultSet): Stream[ConnectionIO, A] = - repeatEvalChunks(FC.embed(rs, resultset.getNextChunk[A](chunkSize))) - - val preparedStatement: Stream[ConnectionIO, PreparedStatement] = - Stream.bracket(create)(FC.embed(_, FPS.close)).flatMap(prepared) - - def results(ps: PreparedStatement): Stream[ConnectionIO, A] = - Stream.bracket(FC.embed(ps, exec))(FC.embed(_, FRS.close)).flatMap(unrolled) - - preparedStatement.flatMap(results) - - } - - /** - * Construct a prepared statement from the given `sql`, configure it with the - * given `PreparedStatementIO` action, and return results via a `Stream`. - * @group Prepared Statements - */ - def stream[A: Read](sql: String, prep: PreparedStatementIO[Unit], chunkSize: Int): Stream[ConnectionIO, A] = - liftStream(chunkSize, FC.prepareStatement(sql), prep, FPS.executeQuery) - - /** - * Construct a prepared update statement with the given return columns (and - * readable destination type `A`) and sql source, configure it with the given - * `PreparedStatementIO` action, and return the generated key results via a - * `Stream`. - * @group Prepared Statements - */ - def updateWithGeneratedKeys[A: Read](cols: List[String])( - sql: String, - prep: PreparedStatementIO[Unit], - chunkSize: Int, - ): Stream[ConnectionIO, A] = - liftStream(chunkSize, FC.prepareStatement(sql, cols.toArray), prep, FPS.executeUpdate *> FPS.getGeneratedKeys) - - /** @group Prepared Statements */ - def updateManyWithGeneratedKeys[F[_]: Foldable, A: Write, B: Read](cols: List[String])( - sql: String, - prep: PreparedStatementIO[Unit], - fa: F[A], - chunkSize: Int, - ): Stream[ConnectionIO, B] = - liftStream[B]( - chunkSize, - FC.prepareStatement(sql, cols.toArray), - prep, - HPS.addBatchesAndExecute(fa) *> FPS.getGeneratedKeys, - ) - - def updateManyReturningGeneratedKeys[F[_]: Foldable, A: Write, K: Read](cols: List[String])( - sql: String, - fa: F[A], - )(implicit B: Factory[K, F[K]]): ConnectionIO[F[K]] = { - if (fa.isEmpty) { - FC.delay(B.newBuilder.result()) - } else { - val readRows = FPS.getGeneratedKeys.bracket { rs => - FPS.embed(rs, resultset.build[F, K]) - }(FPS.embed(_, FRS.close)) - - prepareStatementS(sql, cols)(HPS.addBatches(fa) *> FPS.executeBatch *> readRows) - } - } - - /** @group Transaction Control */ - val commit: ConnectionIO[Unit] = - FC.commit - - /** - * Construct an analysis for the provided `sql` query, given writable - * parameter type `A` and readable resultset row type `B`. - */ - def prepareQueryAnalysis[A: Write, B: Read](sql: String): ConnectionIO[Analysis] = - prepareAnalysis(sql, HPS.getParameterMappings[A], HPS.getColumnMappings[B]) - - def prepareQueryAnalysis0[B: Read](sql: String): ConnectionIO[Analysis] = - prepareAnalysis(sql, FPS.pure(Nil), HPS.getColumnMappings[B]) - - def prepareUpdateAnalysis[A: Write](sql: String): ConnectionIO[Analysis] = - prepareAnalysis(sql, HPS.getParameterMappings[A], FPS.pure(Nil)) - - def prepareUpdateAnalysis0(sql: String): ConnectionIO[Analysis] = - prepareAnalysis(sql, FPS.pure(Nil), FPS.pure(Nil)) - - private def prepareAnalysis( - sql: String, - params: PreparedStatementIO[List[Ior[(Put[?], Nullability.NullabilityKnown), ParameterMeta]]], - columns: PreparedStatementIO[List[Ior[(Get[?], Nullability.NullabilityKnown), ColumnMeta]]], - ) = { - val mappings = prepareStatement(sql) { - (params, columns).tupled - } - (HC.getMetaData(FDMD.getDriverName), mappings).mapN { case (driver, (p, c)) => - Analysis(driver, sql, p, c) - } - } - - /** @group Statements */ - def createStatement[A](k: StatementIO[A]): ConnectionIO[A] = - FC.createStatement.bracket(s => FC.embed(s, k))(s => FC.embed(s, FS.close)) - - /** @group Statements */ - def createStatement[A](rst: ResultSetType, rsc: ResultSetConcurrency)(k: StatementIO[A]): ConnectionIO[A] = - FC.createStatement(rst.toInt, rsc.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FS.close)) - - /** @group Statements */ - def createStatement[A]( - rst: ResultSetType, - rsc: ResultSetConcurrency, - rsh: Holdability, - )(k: StatementIO[A]): ConnectionIO[A] = - FC.createStatement(rst.toInt, rsc.toInt, rsh.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FS.close)) - - /** @group Connection Properties */ - val getCatalog: ConnectionIO[String] = - FC.getCatalog - - /** @group Connection Properties */ - def getClientInfo(key: String): ConnectionIO[Option[String]] = - FC.getClientInfo(key).map(Option(_)) - - /** @group Connection Properties */ - val getClientInfo: ConnectionIO[Map[String, String]] = - FC.getClientInfo.map(_.asScala.toMap) - - /** @group Connection Properties */ - val getHoldability: ConnectionIO[Holdability] = - FC.getHoldability.flatMap(Holdability.fromIntF[ConnectionIO]) - - /** @group Connection Properties */ - def getMetaData[A](k: DatabaseMetaDataIO[A]): ConnectionIO[A] = - FC.getMetaData.flatMap(s => FC.embed(s, k)) - - /** @group Transaction Control */ - val getTransactionIsolation: ConnectionIO[TransactionIsolation] = - FC.getTransactionIsolation.flatMap(TransactionIsolation.fromIntF[ConnectionIO]) - - /** @group Connection Properties */ - val isReadOnly: ConnectionIO[Boolean] = - FC.isReadOnly - - /** @group Callable Statements */ - def prepareCall[A]( - sql: String, - rst: ResultSetType, - rsc: ResultSetConcurrency, - )(k: CallableStatementIO[A]): ConnectionIO[A] = - FC.prepareCall(sql, rst.toInt, rsc.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FCS.close)) - - /** @group Callable Statements */ - def prepareCall[A](sql: String)(k: CallableStatementIO[A]): ConnectionIO[A] = - FC.prepareCall(sql).bracket(s => FC.embed(s, k))(s => FC.embed(s, FCS.close)) - - /** @group Callable Statements */ - def prepareCall[A]( - sql: String, - rst: ResultSetType, - rsc: ResultSetConcurrency, - rsh: Holdability, - )(k: CallableStatementIO[A]): ConnectionIO[A] = - FC.prepareCall(sql, rst.toInt, rsc.toInt, rsh.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FCS.close)) - - /** @group Prepared Statements */ - def prepareStatement[A]( - sql: String, - rst: ResultSetType, - rsc: ResultSetConcurrency, - )(k: PreparedStatementIO[A]): ConnectionIO[A] = - FC.prepareStatement(sql, rst.toInt, rsc.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FPS.close)) - - /** @group Prepared Statements */ - def prepareStatement[A](sql: String)(k: PreparedStatementIO[A]): ConnectionIO[A] = - FC.prepareStatement(sql).bracket(s => FC.embed(s, k))(s => FC.embed(s, FPS.close)) - - /** @group Prepared Statements */ - def prepareStatement[A]( - sql: String, - rst: ResultSetType, - rsc: ResultSetConcurrency, - rsh: Holdability, - )(k: PreparedStatementIO[A]): ConnectionIO[A] = - FC.prepareStatement(sql, rst.toInt, rsc.toInt, rsh.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FPS.close)) - - /** @group Prepared Statements */ - def prepareStatement[A](sql: String, agk: AutoGeneratedKeys)(k: PreparedStatementIO[A]): ConnectionIO[A] = - FC.prepareStatement(sql, agk.toInt).bracket(s => FC.embed(s, k))(s => FC.embed(s, FPS.close)) - - /** @group Prepared Statements */ - def prepareStatementI[A](sql: String, columnIndexes: List[Int])(k: PreparedStatementIO[A]): ConnectionIO[A] = - FC.prepareStatement(sql, columnIndexes.toArray).bracket(s => FC.embed(s, k))(s => FC.embed(s, FPS.close)) - - /** @group Prepared Statements */ - def prepareStatementS[A](sql: String, columnNames: List[String])(k: PreparedStatementIO[A]): ConnectionIO[A] = - FC.prepareStatement(sql, columnNames.toArray).bracket(s => FC.embed(s, k))(s => FC.embed(s, FPS.close)) - - /** @group Transaction Control */ - def releaseSavepoint(sp: Savepoint): ConnectionIO[Unit] = - FC.releaseSavepoint(sp) - - /** @group Transaction Control */ - def rollback(sp: Savepoint): ConnectionIO[Unit] = - FC.rollback(sp) - - /** @group Transaction Control */ - val rollback: ConnectionIO[Unit] = - FC.rollback - - /** @group Connection Properties */ - def setCatalog(catalog: String): ConnectionIO[Unit] = - FC.setCatalog(catalog) - - /** @group Connection Properties */ - def setClientInfo(key: String, value: String): ConnectionIO[Unit] = - FC.setClientInfo(key, value) - - /** @group Connection Properties */ - def setClientInfo(info: Map[String, String]): ConnectionIO[Unit] = - FC.setClientInfo { - // Java 11 overloads the `putAll` method with Map[*,*] along with the existing Map[Obj,Obj] - val ps = new java.util.Properties - info.foreachEntry { case (k, v) => - ps.put(k, v) - } - ps - } - - /** @group Connection Properties */ - def setHoldability(h: Holdability): ConnectionIO[Unit] = - FC.setHoldability(h.toInt) - - /** @group Connection Properties */ - def setReadOnly(readOnly: Boolean): ConnectionIO[Unit] = - FC.setReadOnly(readOnly) - - /** @group Transaction Control */ - val setSavepoint: ConnectionIO[Savepoint] = - FC.setSavepoint - - /** @group Transaction Control */ - def setSavepoint(name: String): ConnectionIO[Savepoint] = - FC.setSavepoint(name) - - /** @group Transaction Control */ - def setTransactionIsolation(ti: TransactionIsolation): ConnectionIO[Unit] = - FC.setTransactionIsolation(ti.toInt) - - // /** - // * Compute a map from native type to closest-matching JDBC type. - // * @group MetaData - // */ - // val nativeTypeMap: ConnectionIO[Map[String, JdbcType]] = { - // getMetaData(FDMD.getTypeInfo.flatMap(FDMD.embed(_, HRS.list[(String, JdbcType)].map(_.toMap)))) - // } -} diff --git a/modules/core/src/main/scala/doobie/hi/package.scala b/modules/core/src/main/scala/doobie/hi/package.scala deleted file mode 100644 index bfe2f5b6c..000000000 --- a/modules/core/src/main/scala/doobie/hi/package.scala +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie - -/** - * High-level database API. The constructors here are defined in terms of those - * in `doobie.free.connection` but differ in the following ways: - * - * - Enumerated values represented by `Int` values in JDBC are mapped to one - * of the proper types defined in `doobie.enumerated`. - * - Nullable values are represented in terms of `Option`. - * - Java collection types are translated to immutable Scala equivalents. - * - Actions that compute lifetime-managed resources do not return the - * resource directly, but rather take a continuation in the resource's - * monad. - * - Actions that compute values of impure types (`CLOB`, `InputStream`, etc.) - * do not appear in this API. They are available in the low-level API but - * must be used with considerable caution. - * - Lifting actions, low-level type mapping actions, and resource management - * actions do not appear in this API. - */ -package object hi { - - val HC = doobie.hi.connection - val HS = doobie.hi.statement - val HPS = doobie.hi.preparedstatement - val HRS = doobie.hi.resultset -} diff --git a/modules/core/src/main/scala/doobie/hi/preparedstatement.scala b/modules/core/src/main/scala/doobie/hi/preparedstatement.scala deleted file mode 100644 index 5d8dd0f0e..000000000 --- a/modules/core/src/main/scala/doobie/hi/preparedstatement.scala +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.hi - -import cats.Foldable -import cats.data.Ior -import cats.effect.kernel.syntax.monadCancel.* -import cats.syntax.apply.* -import cats.syntax.foldable.* -import cats.syntax.traverse.* -import doobie.FPS -import doobie.FRS -import doobie.enumerated.ColumnNullable -import doobie.enumerated.FetchDirection -import doobie.enumerated.Holdability -import doobie.enumerated.JdbcType -import doobie.enumerated.Nullability.NullabilityKnown -import doobie.enumerated.ParameterMode -import doobie.enumerated.ParameterNullable -import doobie.enumerated.ResultSetConcurrency -import doobie.enumerated.ResultSetType -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.resultset.ResultSetIO -import doobie.syntax.align.* -import doobie.util.Get -import doobie.util.Put -import doobie.util.Read -import doobie.util.Write -import doobie.util.analysis.* -import doobie.util.stream.repeatEvalChunks -import fs2.Stream - -import java.sql.ParameterMetaData -import java.sql.ResultSetMetaData -import java.sql.SQLWarning - -/** - * Module of high-level constructors for `PreparedStatementIO` actions. Batching - * operations are not provided; see the `statement` module for this - * functionality. - * @group Modules - */ -object preparedstatement { - - // fs2 handler, not public - private def unrolled[A: Read](rs: java.sql.ResultSet, chunkSize: Int): Stream[PreparedStatementIO, A] = - repeatEvalChunks(FPS.embed(rs, resultset.getNextChunk[A](chunkSize))) - - /** @group Execution */ - def stream[A: Read](chunkSize: Int): Stream[PreparedStatementIO, A] = - Stream.bracket(FPS.executeQuery)(FPS.embed(_, FRS.close)).flatMap(unrolled[A](_, chunkSize)) - - /** - * Non-strict unit for capturing effects. - * @group Constructors (Lifting) - */ - def delay[A](a: => A): PreparedStatementIO[A] = - FPS.delay(a) - - /** @group Batching */ - val executeBatch: PreparedStatementIO[List[Int]] = - FPS.executeBatch.map(_.toList) - - /** @group Batching */ - val addBatch: PreparedStatementIO[Unit] = - FPS.addBatch - - /** - * Add many sets of parameters and execute as a batch update, returning total - * rows updated. Note that failed updates are not reported (see - * https://github.com/tpolecat/doobie/issues/706). This API is likely to - * change. - * @group Batching - */ - def addBatchesAndExecute[F[_]: Foldable, A: Write](fa: F[A]): PreparedStatementIO[Int] = { - val ps = if (fa.isEmpty) { - delay(Nil) - } else { - addBatches(fa) *> executeBatch - } - ps.map(_.foldLeft(0)((acc, n) => acc + n.max(0))) // treat negatives (failures) as no rows updated - } - - /** - * Add many sets of parameters. - * @group Batching - */ - def addBatches[F[_]: Foldable, A: Write](fa: F[A]): PreparedStatementIO[Unit] = - addBatchesIterable(fa.toIterable) - - private def addBatchesIterable[A](fa: Iterable[A])(implicit W: Write[A]): PreparedStatementIO[Unit] = - FPS.raw { ps => - fa.foreach { a => - W.unsafeSet(ps, 1, a) - ps.addBatch() - } - } - - /** @group Execution */ - def executeQuery[A](k: ResultSetIO[A]): PreparedStatementIO[A] = - FPS.executeQuery.bracket(s => FPS.embed(s, k))(s => FPS.embed(s, FRS.close)) - - /** @group Execution */ - val executeUpdate: PreparedStatementIO[Int] = - FPS.executeUpdate - - /** @group Execution */ - def executeUpdateWithUniqueGeneratedKeys[A: Read]: PreparedStatementIO[A] = - executeUpdate *> getUniqueGeneratedKeys[A] - - /** @group Execution */ - def executeUpdateWithGeneratedKeys[A: Read](chunkSize: Int): Stream[PreparedStatementIO, A] = - Stream.bracket(FPS.executeUpdate *> FPS.getGeneratedKeys)(FPS.embed(_, FRS.close)).flatMap(unrolled[A](_, chunkSize)) - - /** - * Compute the column `JdbcMeta` list for this `PreparedStatement`. - * @group Metadata - */ - @SuppressWarnings(Array("org.wartremover.warts.Null")) - def getColumnJdbcMeta: PreparedStatementIO[List[ColumnMeta]] = - FPS.getMetaData.flatMap { - case null => FPS.pure(Nil) // https://github.com/tpolecat/doobie/issues/262 - case md => - (1 to md.getColumnCount).toList.traverse { i => - for { - n <- ColumnNullable.fromIntF[PreparedStatementIO](md.isNullable(i)) - } yield { - val j = JdbcType.fromInt(md.getColumnType(i)) - val s = md.getColumnTypeName(i) - val c = md.getColumnName(i) - ColumnMeta(j, s, n.toNullability, c) - } - } - } - - /** - * Compute the column mappings for this `PreparedStatement` by aligning its - * `JdbcMeta` with the `JdbcMeta` provided by a `Write` instance. - * @group Metadata - */ - def getColumnMappings[A](implicit - A: Read[A], - ): PreparedStatementIO[List[Ior[(Get[?], NullabilityKnown), ColumnMeta]]] = - getColumnJdbcMeta.map(m => A.gets.toList.align(m)) - - /** @group Properties */ - val getFetchDirection: PreparedStatementIO[FetchDirection] = - FPS.getFetchDirection.flatMap(FetchDirection.fromIntF[PreparedStatementIO]) - - /** @group Properties */ - val getFetchSize: PreparedStatementIO[Int] = - FPS.getFetchSize - - /** @group Results */ - def getGeneratedKeys[A](k: ResultSetIO[A]): PreparedStatementIO[A] = - FPS.getGeneratedKeys.bracket(s => FPS.embed(s, k))(s => FPS.embed(s, FRS.close)) - - /** @group Results */ - def getUniqueGeneratedKeys[A: Read]: PreparedStatementIO[A] = - getGeneratedKeys(resultset.getUnique[A]) - - /** - * Compute the parameter `JdbcMeta` list for this `PreparedStatement`. - * @group Metadata - */ - def getParameterJdbcMeta: PreparedStatementIO[List[ParameterMeta]] = - FPS.getParameterMetaData.flatMap { md => - (1 to md.getParameterCount).toList.traverse { i => - for { - n <- ParameterNullable.fromIntF[PreparedStatementIO](md.isNullable(i)) - m <- ParameterMode.fromIntF[PreparedStatementIO](md.getParameterMode(i)) - } yield { - val j = JdbcType.fromInt(md.getParameterType(i)) - val s = md.getParameterTypeName(i) - ParameterMeta(j, s, n.toNullability, m) - } - } - } - - /** - * Compute the parameter mappings for this `PreparedStatement` by aligning its - * `JdbcMeta` with the `JdbcMeta` provided by a `Write` instance. - * @group Metadata - */ - def getParameterMappings[A](implicit - A: Write[A], - ): PreparedStatementIO[List[Ior[(Put[?], NullabilityKnown), ParameterMeta]]] = - getParameterJdbcMeta.map(m => A.puts.toList.align(m)) - - /** @group Properties */ - val getMaxFieldSize: PreparedStatementIO[Int] = - FPS.getMaxFieldSize - - /** @group Properties */ - val getMaxRows: PreparedStatementIO[Int] = - FPS.getMaxRows - - /** @group MetaData */ - val getMetaData: PreparedStatementIO[ResultSetMetaData] = - FPS.getMetaData - - /** @group MetaData */ - val getParameterMetaData: PreparedStatementIO[ParameterMetaData] = - FPS.getParameterMetaData - - /** @group Properties */ - val getQueryTimeout: PreparedStatementIO[Int] = - FPS.getQueryTimeout - - /** @group Properties */ - val getResultSetConcurrency: PreparedStatementIO[ResultSetConcurrency] = - FPS.getResultSetConcurrency.flatMap(ResultSetConcurrency.fromIntF[PreparedStatementIO]) - - /** @group Properties */ - val getResultSetHoldability: PreparedStatementIO[Holdability] = - FPS.getResultSetHoldability.flatMap(Holdability.fromIntF[PreparedStatementIO]) - - /** @group Properties */ - val getResultSetType: PreparedStatementIO[ResultSetType] = - FPS.getResultSetType.flatMap(ResultSetType.fromIntF[PreparedStatementIO]) - - /** @group Results */ - val getWarnings: PreparedStatementIO[SQLWarning] = - FPS.getWarnings - - /** - * Set the given writable value. - * @group Parameters - */ - def set[A](a: A)(implicit A: Write[A]): PreparedStatementIO[Unit] = - A.set(a) - - /** @group Properties */ - def setCursorName(name: String): PreparedStatementIO[Unit] = - FPS.setCursorName(name) - - /** @group Properties */ - def setEscapeProcessing(a: Boolean): PreparedStatementIO[Unit] = - FPS.setEscapeProcessing(a) - - /** @group Properties */ - def setFetchDirection(fd: FetchDirection): PreparedStatementIO[Unit] = - FPS.setFetchDirection(fd.toInt) - - /** @group Properties */ - def setFetchSize(n: Int): PreparedStatementIO[Unit] = - FPS.setFetchSize(n) - - /** @group Properties */ - def setMaxFieldSize(n: Int): PreparedStatementIO[Unit] = - FPS.setMaxFieldSize(n) - - /** @group Properties */ - def setMaxRows(n: Int): PreparedStatementIO[Unit] = - FPS.setMaxRows(n) - - /** @group Properties */ - def setQueryTimeout(a: Int): PreparedStatementIO[Unit] = - FPS.setQueryTimeout(a) - -} diff --git a/modules/core/src/main/scala/doobie/hi/resultset.scala b/modules/core/src/main/scala/doobie/hi/resultset.scala deleted file mode 100644 index 705e2f725..000000000 --- a/modules/core/src/main/scala/doobie/hi/resultset.scala +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.hi - -import cats.Alternative -import cats.Monad -import cats.data.NonEmptyList -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.monad.* -import doobie.FRS -import doobie.enumerated.FetchDirection -import doobie.enumerated.Holdability -import doobie.free.resultset.ResultSetIO -import doobie.util.Read -import doobie.util.Write -import doobie.util.invariant.* -import doobie.util.stream.repeatEvalChunks -import fs2.Stream - -import java.sql.ResultSetMetaData -import java.sql.SQLWarning -import scala.collection.Factory - -/** - * Module of high-level constructors for `ResultSetIO` actions. - * @group Modules - */ -object resultset { - - /** - * Non-strict unit for capturing effects. - * @group Constructors (Lifting) - */ - def delay[A](a: => A): ResultSetIO[A] = - FRS.delay(a) - - /** @group Cursor Control */ - def absolute(row: Int): ResultSetIO[Boolean] = - FRS.absolute(row) - - /** @group Cursor Control */ - val afterLast: ResultSetIO[Unit] = - FRS.afterLast - - /** @group Cursor Control */ - val beforeFirst: ResultSetIO[Unit] = - FRS.beforeFirst - - /** @group Updating */ - val cancelRowUpdates: ResultSetIO[Unit] = - FRS.cancelRowUpdates - - /** @group Warnings */ - val clearWarnings: ResultSetIO[Unit] = - FRS.clearWarnings - - /** @group Updating */ - val deleteRow: ResultSetIO[Unit] = - FRS.deleteRow - - /** @group Cursor Control */ - val first: ResultSetIO[Boolean] = - FRS.first - - /** - * Read a value of type `A`. - * @group Results - */ - def get[A](implicit A: Read[A]): ResultSetIO[A] = - A.get - - /** - * Consumes the remainder of the resultset, reading each row as a value of - * type `A` and accumulating them in a standard library collection via - * `CanBuildFrom`. - * @group Results - */ - @SuppressWarnings(Array("org.wartremover.warts.MutableDataStructures", "org.wartremover.warts.While")) - def build[F[_], A](implicit F: Factory[A, F[A]], A: Read[A]): ResultSetIO[F[A]] = - FRS.raw { rs => - val b = F.newBuilder - while (rs.next) { - val _ = b += A.unsafeGet(rs, 1) - } - b.result() - } - - /** - * Consumes the remainder of the resultset, reading each row as a value of - * type `(A, B)` and accumulating them in a standard library collection via - * `CanBuildFrom`. - * @group Results - */ - @SuppressWarnings(Array("org.wartremover.warts.MutableDataStructures", "org.wartremover.warts.While")) - def buildPair[F[_, _], A, B](implicit F: Factory[(A, B), F[A, B]], A: Read[(A, B)]): ResultSetIO[F[A, B]] = - FRS.raw { rs => - val b = F.newBuilder - while (rs.next) { - val _ = b += A.unsafeGet(rs, 1) - } - b.result() - } - - /** - * Consumes the remainder of the resultset, reading each row as a value of - * type `A`, mapping to `B`, and accumulating them in a standard library - * collection via `CanBuildFrom`. This unusual constructor is a workaround for - * the CanBuildFrom not having a sensible contravariant functor instance. - * @group Results - */ - @SuppressWarnings(Array("org.wartremover.warts.MutableDataStructures", "org.wartremover.warts.While")) - def buildMap[F[_], A, B](f: A => B)(implicit F: Factory[B, F[B]], A: Read[A]): ResultSetIO[F[B]] = - FRS.raw { rs => - val b = F.newBuilder - while (rs.next) { - val _ = b += f(A.unsafeGet(rs, 1)) - } - b.result() - } - - /** - * Consumes the remainder of the resultset, reading each row as a value of - * type `A` and accumulating them in a `Vector`. - * @group Results - */ - def vector[A: Read]: ResultSetIO[Vector[A]] = - build[Vector, A] - - /** - * Consumes the remainder of the resultset, reading each row as a value of - * type `A` and accumulating them in a `List`. - * @group Results - */ - def list[A: Read]: ResultSetIO[List[A]] = - build[List, A] - - /** - * Like `getNext` but loops until the end of the resultset, gathering results - * in a `MonadPlus`. - * @group Results - */ - def accumulate[G[_]: Alternative, A: Read]: ResultSetIO[G[A]] = - get[A].whileM(next) - - /** - * Updates a value of type `A`. - * @group Updating - */ - def update[A](a: A)(implicit A: Write[A]): ResultSetIO[Unit] = - A.update(a) - - /** - * Similar to `next >> get` but lifted into `Option`; returns `None` when no - * more rows are available. - * @group Results - */ - def getNext[A: Read]: ResultSetIO[Option[A]] = - next >>= { - case true => get[A].map(Some(_)) - case false => Monad[ResultSetIO].pure(None) - } - - /** - * Similar to `getNext` but reads `chunkSize` rows at a time (the final chunk - * in a resultset may be smaller). A non-positive `chunkSize` yields an empty - * `Seq` and consumes no rows. This method delegates to `getNextChunkV` and - * widens to `Seq` for easier interoperability with streaming libraries that - * like `Seq` better. - * @group Results - */ - def getNextChunk[A: Read](chunkSize: Int): ResultSetIO[Seq[A]] = - getNextChunkV[A](chunkSize).widen[Seq[A]] - - /** - * Similar to `getNext` but reads `chunkSize` rows at a time (the final chunk - * in a resultset may be smaller). A non-positive `chunkSize` yields an empty - * `Vector` and consumes no rows. - * @group Results - */ - @SuppressWarnings(Array( - "org.wartremover.warts.MutableDataStructures", - "org.wartremover.warts.Var", - "org.wartremover.warts.While", - )) - def getNextChunkV[A](chunkSize: Int)(implicit A: Read[A]): ResultSetIO[Vector[A]] = - FRS.raw { rs => - var n = chunkSize - val b = Vector.newBuilder[A] - while (n > 0 && rs.next) { - val _ = b += A.unsafeGet(rs, 1) - n -= 1 - } - b.result() - } - - /** - * Equivalent to `getNext`, but verifies that there is exactly one row - * remaining. - * @throws doobie.util.invariant.UnexpectedCursorPosition - * if there is not exactly one row remaining - * @group Results - */ - def getUnique[A: Read]: ResultSetIO[A] = - (getNext[A], next).tupled.flatMap { - case (Some(a), false) => FRS.delay(a) - case (Some(_), true) => FRS.raiseError(UnexpectedContinuation()) - case (None, _) => FRS.raiseError(UnexpectedEnd()) - } - - /** - * Equivalent to `getNext`, but verifies that there is at most one row - * remaining. - * @throws doobie.util.invariant.UnexpectedContinuation - * if there is more than one row remaining - * @group Results - */ - def getOption[A: Read]: ResultSetIO[Option[A]] = - (getNext[A], next).tupled.flatMap { - case (a @ Some(_), false) => FRS.delay(a) - case (Some(_), true) => FRS.raiseError(UnexpectedContinuation()) - case (None, _) => FRS.delay(None) - } - - /** - * Consumes the remainder of the resultset, but verifies that there is at - * least one row remaining. - * @throws doobie.util.invariant.UnexpectedEnd - * if there is not at least one row remaining - * @group Results - */ - def nel[A: Read]: ResultSetIO[NonEmptyList[A]] = - (getNext[A], list).tupled.flatMap { - case (Some(a), as) => FRS.delay(NonEmptyList(a, as)) - case (None, _) => FRS.raiseError(UnexpectedEnd()) - } - - /** - * Stream that reads from the `ResultSet` and returns a stream of `A`s. This - * is the preferred mechanism for dealing with query results. - * @group Results - */ - def stream[A: Read](chunkSize: Int): Stream[ResultSetIO, A] = - repeatEvalChunks(getNextChunk[A](chunkSize)) - - /** @group Properties */ - val getFetchDirection: ResultSetIO[FetchDirection] = - FRS.getFetchDirection.flatMap(FetchDirection.fromIntF[ResultSetIO]) - - /** @group Properties */ - val getFetchSize: ResultSetIO[Int] = - FRS.getFetchSize - - /** @group Properties */ - val getHoldability: ResultSetIO[Holdability] = - FRS.getHoldability.flatMap(Holdability.fromIntF[ResultSetIO]) - - /** @group Properties */ - val getMetaData: ResultSetIO[ResultSetMetaData] = - FRS.getMetaData - - /** @group Cursor Control */ - val getRow: ResultSetIO[Int] = - FRS.getRow - - /** @group Warnings */ - val getWarnings: ResultSetIO[Option[SQLWarning]] = - FRS.getWarnings.map(Option(_)) - - /** @group Updating */ - val insertRow: ResultSetIO[Unit] = - FRS.insertRow - - /** @group Cursor Control */ - val isAfterLast: ResultSetIO[Boolean] = - FRS.isAfterLast - - /** @group Cursor Control */ - val isBeforeFirst: ResultSetIO[Boolean] = - FRS.isBeforeFirst - - /** @group Cursor Control */ - val isFirst: ResultSetIO[Boolean] = - FRS.isFirst - - /** @group Cursor Control */ - val isLast: ResultSetIO[Boolean] = - FRS.isLast - - /** @group Cursor Control */ - val last: ResultSetIO[Boolean] = - FRS.last - - /** @group Cursor Control */ - val moveToCurrentRow: ResultSetIO[Unit] = - FRS.moveToCurrentRow - - /** @group Cursor Control */ - val moveToInsertRow: ResultSetIO[Unit] = - FRS.moveToInsertRow - - /** @group Cursor Control */ - val next: ResultSetIO[Boolean] = - FRS.next - - /** @group Cursor Control */ - val previous: ResultSetIO[Boolean] = - FRS.previous - - /** @group Cursor Control */ - val refreshRow: ResultSetIO[Unit] = - FRS.refreshRow - - /** @group Cursor Control */ - def relative(n: Int): ResultSetIO[Boolean] = - FRS.relative(n) - - /** @group Cursor Control */ - val rowDeleted: ResultSetIO[Boolean] = - FRS.rowDeleted - - /** @group Cursor Control */ - val rowInserted: ResultSetIO[Boolean] = - FRS.rowInserted - - /** @group Cursor Control */ - val rowUpdated: ResultSetIO[Boolean] = - FRS.rowUpdated - - /** @group Properties */ - def setFetchDirection(fd: FetchDirection): ResultSetIO[Unit] = - FRS.setFetchDirection(fd.toInt) - - /** @group Properties */ - def setFetchSize(n: Int): ResultSetIO[Unit] = - FRS.setFetchSize(n) - -} diff --git a/modules/core/src/main/scala/doobie/hi/statement.scala b/modules/core/src/main/scala/doobie/hi/statement.scala deleted file mode 100644 index d4c38e4e2..000000000 --- a/modules/core/src/main/scala/doobie/hi/statement.scala +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.hi - -import cats.effect.kernel.syntax.monadCancel.* -import doobie.FRS -import doobie.FS -import doobie.enumerated.FetchDirection -import doobie.enumerated.Holdability -import doobie.enumerated.ResultSetConcurrency -import doobie.enumerated.ResultSetType -import doobie.free.resultset.ResultSetIO -import doobie.free.statement.StatementIO - -import java.sql.SQLWarning - -/** - * Module of high-level constructors for `StatementIO` actions. - * @group Modules - */ -object statement { - - /** @group Batching */ - def addBatch(sql: String): StatementIO[Unit] = - FS.addBatch(sql) - - /** @group Batching */ - val clearBatch: StatementIO[Unit] = - FS.clearBatch - - /** @group Execution */ - val executeBatch: StatementIO[List[Int]] = - FS.executeBatch.map(_.toList) - - /** @group Execution */ - def executeQuery[A](sql: String)(k: ResultSetIO[A]): StatementIO[A] = - FS.executeQuery(sql).bracket(s => FS.embed(s, k))(s => FS.embed(s, FRS.close)) - - /** @group Execution */ - def executeUpdate(sql: String): StatementIO[Int] = - FS.executeUpdate(sql) - - /** @group Properties */ - val getFetchDirection: StatementIO[FetchDirection] = - FS.getFetchDirection.flatMap(FetchDirection.fromIntF[StatementIO]) - - /** @group Properties */ - val getFetchSize: StatementIO[Int] = - FS.getFetchSize - - /** @group Results */ - def getGeneratedKeys[A](k: ResultSetIO[A]): StatementIO[A] = - FS.getGeneratedKeys.bracket(s => FS.embed(s, k))(s => FS.embed(s, FRS.close)) - - /** @group Properties */ - val getMaxFieldSize: StatementIO[Int] = - FS.getMaxFieldSize - - /** @group Properties */ - val getMaxRows: StatementIO[Int] = - FS.getMaxRows - - // /** @group Batching */ - // def getMoreResults(a: Int): StatementIO[Boolean] = - // Predef.??? - - /** @group Batching */ - val getMoreResults: StatementIO[Boolean] = - FS.getMoreResults - - /** @group Properties */ - val getQueryTimeout: StatementIO[Int] = - FS.getQueryTimeout - - /** @group Batching */ - def getResultSet[A](k: ResultSetIO[A]): StatementIO[A] = - FS.getResultSet.flatMap(s => FS.embed(s, k)) - - /** @group Properties */ - val getResultSetConcurrency: StatementIO[ResultSetConcurrency] = - FS.getResultSetConcurrency.flatMap(ResultSetConcurrency.fromIntF[StatementIO]) - - /** @group Properties */ - val getResultSetHoldability: StatementIO[Holdability] = - FS.getResultSetHoldability.flatMap(Holdability.fromIntF[StatementIO]) - - /** @group Properties */ - val getResultSetType: StatementIO[ResultSetType] = - FS.getResultSetType.flatMap(ResultSetType.fromIntF[StatementIO]) - - /** @group Results */ - val getUpdateCount: StatementIO[Int] = - FS.getUpdateCount - - /** @group Results */ - val getWarnings: StatementIO[SQLWarning] = - FS.getWarnings - - /** @group Properties */ - def setCursorName(name: String): StatementIO[Unit] = - FS.setCursorName(name) - - /** @group Properties */ - def setEscapeProcessing(a: Boolean): StatementIO[Unit] = - FS.setEscapeProcessing(a) - - /** @group Properties */ - def setFetchDirection(fd: FetchDirection): StatementIO[Unit] = - FS.setFetchDirection(fd.toInt) - - /** @group Properties */ - def setFetchSize(n: Int): StatementIO[Unit] = - FS.setFetchSize(n) - - /** @group Properties */ - def setMaxFieldSize(n: Int): StatementIO[Unit] = - FS.setMaxFieldSize(n) - - /** @group Properties */ - def setMaxRows(n: Int): StatementIO[Unit] = - FS.setMaxRows(n) - - /** @group Properties */ - def setQueryTimeout(a: Int): StatementIO[Unit] = - FS.setQueryTimeout(a) - -} diff --git a/modules/core/src/main/scala/doobie/package.scala b/modules/core/src/main/scala/doobie/package.scala index 538158c22..29f4f4060 100644 --- a/modules/core/src/main/scala/doobie/package.scala +++ b/modules/core/src/main/scala/doobie/package.scala @@ -4,26 +4,6 @@ package object doobie { - val FB = doobie.free.blob - val FCS = doobie.free.callablestatement - val FCL = doobie.free.clob - val FC = doobie.free.connection - val FDMD = doobie.free.databasemetadata - val FD = doobie.free.driver - val FNCL = doobie.free.nclob - val FPS = doobie.free.preparedstatement - val FREF = doobie.free.ref - val FRS = doobie.free.resultset - val FSD = doobie.free.sqldata - val FSI = doobie.free.sqlinput - val FSO = doobie.free.sqloutput - val FS = doobie.free.statement - - val HC = doobie.hi.HC - val HS = doobie.hi.HS - val HPS = doobie.hi.HPS - val HRS = doobie.hi.HRS - val Fragments = doobie.util.fragments } diff --git a/modules/core/src/main/scala/doobie/syntax/connectionio.scala b/modules/core/src/main/scala/doobie/syntax/connectionio.scala index 2365ec03f..aae92869c 100644 --- a/modules/core/src/main/scala/doobie/syntax/connectionio.scala +++ b/modules/core/src/main/scala/doobie/syntax/connectionio.scala @@ -4,52 +4,18 @@ package doobie.syntax -import cats.data.EitherT -import cats.data.Kleisli -import cats.data.OptionT -import cats.effect.kernel.MonadCancelThrow -import cats.syntax.functor.* -import doobie.HC import doobie.free.connection.ConnectionIO import doobie.util.transactor.Transactor import scala.language.implicitConversions class ConnectionIOOps[A](ma: ConnectionIO[A]) { - def transact[M[_]](xa: Transactor[M])(implicit M: MonadCancelThrow[M]): M[A] = xa.trans.apply(ma) -} - -class OptionTConnectionIOOps[A](ma: OptionT[ConnectionIO, A]) { - def transact[M[_]: MonadCancelThrow](xa: Transactor[M]): OptionT[M, A] = - OptionT( - xa.trans.apply(ma.orElseF(HC.rollback.as(None)).value), - ) -} - -class EitherTConnectionIOOps[E, A](ma: EitherT[ConnectionIO, E, A]) { - def transact[M[_]: MonadCancelThrow](xa: Transactor[M]): EitherT[M, E, A] = - EitherT( - xa.trans.apply(ma.leftSemiflatMap(HC.rollback.as(_)).value), - ) -} - -class KleisliConnectionIOOps[A, B](ma: Kleisli[ConnectionIO, A, B]) { - def transact[M[_]: MonadCancelThrow](xa: Transactor[M]): Kleisli[M, A, B] = - ma.mapK(xa.trans) + def transact[M[_]](xa: Transactor[M]): M[A] = xa.run(ma) } trait ToConnectionIOOps { implicit def toConnectionIOOps[A](ma: ConnectionIO[A]): ConnectionIOOps[A] = new ConnectionIOOps(ma) - - implicit def toOptionTConnectionIOOps[A](ma: OptionT[ConnectionIO, A]): OptionTConnectionIOOps[A] = - new OptionTConnectionIOOps(ma) - - implicit def toEitherTConnectionIOOps[E, A](ma: EitherT[ConnectionIO, E, A]): EitherTConnectionIOOps[E, A] = - new EitherTConnectionIOOps(ma) - - implicit def toKleisliConnectionIOOps[A, B](ma: Kleisli[ConnectionIO, A, B]): KleisliConnectionIOOps[A, B] = - new KleisliConnectionIOOps[A, B](ma) } object connectionio extends ToConnectionIOOps diff --git a/modules/core/src/main/scala/doobie/syntax/stream.scala b/modules/core/src/main/scala/doobie/syntax/stream.scala deleted file mode 100644 index e4a638df4..000000000 --- a/modules/core/src/main/scala/doobie/syntax/stream.scala +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.syntax - -import cats.data.Kleisli -import cats.effect.kernel.MonadCancelThrow -import doobie.free.connection.ConnectionIO -import doobie.util.transactor.Transactor -import fs2.Stream - -import scala.language.implicitConversions - -class StreamOps[F[_], A](fa: Stream[F, A]) { - def transact[M[_]: MonadCancelThrow](xa: Transactor[M])(implicit - ev: Stream[F, A] =:= Stream[ConnectionIO, A], - ): Stream[M, A] = xa.transP.apply(fa) -} -class KleisliStreamOps[A, B](fa: Stream[Kleisli[ConnectionIO, A, *], B]) { - def transact[M[_]: MonadCancelThrow](xa: Transactor[M]): Stream[Kleisli[M, A, *], B] = xa.transPK[A].apply(fa) -} - -trait ToStreamOps { - implicit def toDoobieStreamOps[F[_], A](fa: Stream[F, A]): StreamOps[F, A] = - new StreamOps(fa) - implicit def toDoobieKleisliStreamOps[A, B](fa: Stream[Kleisli[ConnectionIO, A, *], B]): KleisliStreamOps[A, B] = - new KleisliStreamOps(fa) -} - -object stream extends ToStreamOps diff --git a/modules/core/src/main/scala/doobie/util/ExecutionContexts.scala b/modules/core/src/main/scala/doobie/util/ExecutionContexts.scala deleted file mode 100644 index de75d9ad6..000000000 --- a/modules/core/src/main/scala/doobie/util/ExecutionContexts.scala +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import cats.effect.kernel.Resource -import cats.effect.kernel.Sync - -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import scala.concurrent.ExecutionContext - -object ExecutionContexts { - - /** Resource yielding an `ExecutionContext` backed by a fixed-size pool. */ - def fixedThreadPool[F[_]](size: Int)( - implicit sf: Sync[F], - ): Resource[F, ExecutionContext] = { - val alloc = sf.delay(Executors.newFixedThreadPool(size)) - val free = (es: ExecutorService) => sf.delay(es.shutdown()) - Resource.make(alloc)(free).map(ExecutionContext.fromExecutor) - } - - /** - * Resource yielding an `ExecutionContext` backed by an unbounded thread pool. - */ - def cachedThreadPool[F[_]]( - implicit sf: Sync[F], - ): Resource[F, ExecutionContext] = { - val alloc = sf.delay(Executors.newCachedThreadPool) - val free = (es: ExecutorService) => sf.delay(es.shutdown()) - Resource.make(alloc)(free).map(ExecutionContext.fromExecutor) - } - - /** - * Execution context that runs everything synchronously. This can be useful - * for testing. - */ - object synchronous extends ExecutionContext { - def execute(runnable: Runnable): Unit = runnable.run() - def reportFailure(cause: Throwable): Unit = cause.printStackTrace() - } - -} diff --git a/modules/core/src/main/scala/doobie/util/fragment.scala b/modules/core/src/main/scala/doobie/util/fragment.scala index e63f7ad29..bc6dcfeec 100644 --- a/modules/core/src/main/scala/doobie/util/fragment.scala +++ b/modules/core/src/main/scala/doobie/util/fragment.scala @@ -6,11 +6,7 @@ package doobie.util import cats.Monoid import cats.data.Chain -import cats.syntax.apply.* -import doobie.HC import doobie.enumerated.Nullability.* -import doobie.free.connection.ConnectionIO -import doobie.free.preparedstatement.PreparedStatementIO import doobie.util.pos.Pos import doobie.util.query.Query import doobie.util.query.Query0 @@ -82,14 +78,6 @@ object fragment { } - /** - * Construct a program in ConnectionIO that constructs and prepares a - * PreparedStatement, with further handling delegated to the provided - * program. - */ - def execWith[B](fa: PreparedStatementIO[B]): ConnectionIO[B] = - HC.prepareStatement(sql)(write.set(elems) *> fa) - /** Concatenate this fragment with another, yielding a larger fragment. */ def ++(fb: Fragment): Fragment = new Fragment(sql + fb.sql, elems ++ fb.elems, pos orElse fb.pos) diff --git a/modules/core/src/main/scala/doobie/util/get.scala b/modules/core/src/main/scala/doobie/util/get.scala index 23ed213a0..c6c36d8bb 100644 --- a/modules/core/src/main/scala/doobie/util/get.scala +++ b/modules/core/src/main/scala/doobie/util/get.scala @@ -13,7 +13,7 @@ import doobie.util.invariant.InvalidObjectMapping import doobie.util.invariant.InvalidValue import doobie.util.invariant.NonNullableColumnRead import doobie.util.meta.Meta -import org.tpolecat.typename.* +import doobie.util.typename.* import java.sql.ResultSet import scala.reflect.ClassTag diff --git a/modules/core/src/main/scala/doobie/util/invariant.scala b/modules/core/src/main/scala/doobie/util/invariant.scala index 95f5ac1ee..cd40e6f00 100644 --- a/modules/core/src/main/scala/doobie/util/invariant.scala +++ b/modules/core/src/main/scala/doobie/util/invariant.scala @@ -7,7 +7,7 @@ package doobie.util import cats.Show import cats.syntax.show.* import doobie.enumerated.JdbcType -import org.tpolecat.typename.* +import doobie.util.typename.* /** * Module defining the type of exceptions representing unmet expectations. These diff --git a/modules/core/src/main/scala/doobie/util/io.scala b/modules/core/src/main/scala/doobie/util/io.scala deleted file mode 100644 index c1c917964..000000000 --- a/modules/core/src/main/scala/doobie/util/io.scala +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import cats.effect.kernel.Sync -import cats.effect.kernel.syntax.monadCancel.* -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.monad.* - -import java.io.File -import java.io.FileInputStream -import java.io.FileOutputStream -import java.io.InputStream -import java.io.OutputStream - -/** - * Module for a constructor of modules of IO operations for effectful monads. - */ -object io { - - /** - * Constructor for a module of IO operations in some effectful monad. This is - * by no means complete; contributions welcome. The construtors here expose - * naked lifetime-managed objects and should be used with caution; they are - * mostly intended for library authors who wish to integrate vendor- specific - * behavior that relies on JDK IO. - */ - class IOActions[M[_]](implicit M: Sync[M]) { - - private def delay[A](a: => A): M[A] = M.delay(a) - - /** - * Print to `Console.out` - * @group Console Operations - */ - def putStr(s: String): M[Unit] = - delay(Console.out.print(s)) - - /** - * Print to `Console.out` - * @group Console Operations - */ - def putStrLn(s: String): M[Unit] = - delay(Console.out.println(s)) - - /** - * Copy a block from `is` to `os` using naked buffer `buf`, which will be - * clobbered. - * @group Stream Operations - */ - def copyBlock(buf: Array[Byte])(is: InputStream, os: OutputStream): M[Int] = - delay(is.read(buf)) flatMap { n => delay(os.write(buf, 0, n)).whenA(n >= 0).as(n) } - - /** - * Copy the contents of `file` to a `os` in blocks of size `bufSize`. - * @group File Operations - */ - def copyFileToStream(bufSize: Int, file: File, os: OutputStream): M[Unit] = - withFileInputStream(file)(copyStream(new Array[Byte](bufSize))(_, os)) - - /** - * Copy the remainder of `is` to `file` in blocks of size `bufSize`. - * @group File Operations - */ - def copyStreamToFile(bufSize: Int, file: File, is: InputStream): M[Unit] = - withFileOutputStream(file)(copyStream(new Array[Byte](bufSize))(is, _)) - - /** - * Copy the remainder of `is` into `os` using naked buffer `buf`, which will - * be clobbered. - * @group Stream Operations - */ - def copyStream(buf: Array[Byte])(is: InputStream, os: OutputStream): M[Unit] = - copyBlock(buf)(is, os).iterateUntil(_ < 0).void - - /** - * Perform an operation with a `FileInputStream`, which will be closed - * afterward. - * @group File Operations - */ - def withFileInputStream[A](file: File)(f: FileInputStream => M[A]): M[A] = - delay(new FileInputStream(file)).bracket(f)(i => delay(i.close())) - - /** - * Perform an operation with a `FileOutputStream`, which will be closed - * afterward. - * @group File Operations - */ - def withFileOutputStream[A](file: File)(f: FileOutputStream => M[A]): M[A] = - delay(new FileOutputStream(file)).bracket(f)(i => delay(i.close())) - - /** - * Flush `os`. - * @group Stream Operations - */ - def flush(os: OutputStream): M[Unit] = - delay(os.flush()) - - } - -} diff --git a/modules/core/src/main/scala/doobie/util/lens.scala b/modules/core/src/main/scala/doobie/util/lens.scala deleted file mode 100644 index ca7e60ff0..000000000 --- a/modules/core/src/main/scala/doobie/util/lens.scala +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import cats.data.State - -// embarrassigly minimal lens implementation to avoid a lib conflict -object lens { - - final case class Lens[A, B](get: A => B, set: (A, B) => A) { - - def andThen[C](bc: Lens[B, C]): Lens[A, C] = - Lens(a => bc.get(get(a)), (a, c) => set(a, bc.set(get(a), c))) - - def >=>[C](bc: Lens[B, C]): Lens[A, C] = - andThen(bc) - - def compose[C](bc: Lens[C, A]): Lens[C, B] = - bc.andThen(this) - - def modify(a: A, f: B => B): A = - set(a, f(get(a))) - - def xmapA[AA](f: AA => A, g: A => AA): Lens[AA, B] = - Lens(aa => get(f(aa)), (aa, b) => g(set(f(aa), b))) - - def xmapB[BB](f: BB => B, g: B => BB): Lens[A, BB] = - Lens(a => g(get(a)), (a, bb) => set(a, f(bb))) - - def mods(f: B => B): State[A, B] = - State { a => - val b = get(a) - val b_ = f(b) - val a_ = set(a, b_) - (a_, b_) - } - - def %=(f: B => B): State[A, B] = - mods(f) - - def :=(b: => B): State[A, B] = - mods(_ => b) - - } - - type @>[A, B] = Lens[A, B] - -} diff --git a/modules/core/src/main/scala/doobie/util/meta/meta.scala b/modules/core/src/main/scala/doobie/util/meta/meta.scala index 414ef19af..889bbebc5 100644 --- a/modules/core/src/main/scala/doobie/util/meta/meta.scala +++ b/modules/core/src/main/scala/doobie/util/meta/meta.scala @@ -10,7 +10,7 @@ import cats.data.NonEmptyList import doobie.enumerated.JdbcType import doobie.util.Get import doobie.util.Put -import org.tpolecat.typename.TypeName +import doobie.util.typename.TypeName import java.sql.PreparedStatement import java.sql.ResultSet diff --git a/modules/core/src/main/scala/doobie/util/put.scala b/modules/core/src/main/scala/doobie/util/put.scala index 40ea44168..8f081d690 100644 --- a/modules/core/src/main/scala/doobie/util/put.scala +++ b/modules/core/src/main/scala/doobie/util/put.scala @@ -9,7 +9,7 @@ import cats.data.NonEmptyList import cats.free.ContravariantCoyoneda import doobie.enumerated.JdbcType import doobie.util.meta.Meta -import org.tpolecat.typename.TypeName +import doobie.util.typename.TypeName import java.sql.PreparedStatement import java.sql.ResultSet diff --git a/modules/core/src/main/scala/doobie/util/query.scala b/modules/core/src/main/scala/doobie/util/query.scala index f18ab456d..79e1b212e 100644 --- a/modules/core/src/main/scala/doobie/util/query.scala +++ b/modules/core/src/main/scala/doobie/util/query.scala @@ -4,22 +4,14 @@ package doobie.util -import cats.Alternative import cats.Contravariant import cats.Functor import cats.arrow.Profunctor import cats.data.NonEmptyList -import cats.syntax.apply.* -import doobie.HC -import doobie.HPS -import doobie.HRS import doobie.free.connection.ConnectionIO -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.resultset.ResultSetIO import doobie.util.analysis.Analysis import doobie.util.fragment.Fragment import doobie.util.pos.Pos -import fs2.Stream import scala.collection.Factory @@ -62,7 +54,7 @@ object query { * @group Diagnostics */ def analysis: ConnectionIO[Analysis] = - HC.prepareQueryAnalysis[A, B](sql) + ConnectionIO.prepareQueryAnalysis[A, B](sql) /** * Program to construct an analysis of this query's SQL statement and result @@ -70,34 +62,10 @@ object query { * @group Diagnostics */ def outputAnalysis: ConnectionIO[Analysis] = - HC.prepareQueryAnalysis0[B](sql) + ConnectionIO.prepareQueryAnalysis0[B](sql) - /** - * Program to construct an inspection of the query. Given arguments `a`, - * calls `f` with the SQL representation of the query and a statement with - * all arguments set. Returns the result of the `ConnectionIO` program - * constructed. - * - * @group Diagnostics - */ - def inspect[R](a: A)(f: (String, PreparedStatementIO[Unit]) => ConnectionIO[R]): ConnectionIO[R] = - f(sql, HPS.set(a)) - - /** - * Apply the argument `a` to construct a `Stream` with the given chunking - * factor, with effect type [[ConnectionIO]] yielding elements of type `B`. - * @group Results - */ - def streamWithChunkSize(a: A, chunkSize: Int): Stream[ConnectionIO, B] = - HC.stream[B](sql, HPS.set(a), chunkSize) - - /** - * Apply the argument `a` to construct a `Stream` with `DefaultChunkSize`, - * with effect type [[ConnectionIO]] yielding elements of type `B`. - * @group Results - */ - def stream(a: A): Stream[ConnectionIO, B] = - streamWithChunkSize(a, DefaultChunkSize) + def iterator[C](a: A)(f: Iterator[B] => C): ConnectionIO[C] = + ConnectionIO.query.iterator(sql, a, f)(read, write) /** * Apply the argument `a` to construct a program in [[ConnectionIO]] @@ -105,7 +73,7 @@ object query { * @group Results */ def to[F[_]](a: A)(implicit f: Factory[B, F[B]]): ConnectionIO[F[B]] = - withPrepareStatement(a, HRS.build[F, B]) + ConnectionIO.query.collect(sql, a)(read, write, f) /** * Apply the argument `a` to construct a program in [[ConnectionIO]] @@ -115,16 +83,7 @@ object query { * @group Results */ def toMap[K, V](a: A)(implicit ev: B =:= (K, V), f: Factory[(K, V), Map[K, V]]): ConnectionIO[Map[K, V]] = - withPrepareStatement(a, HRS.buildPair[Map, K, V](f, read.map(ev))) - - /** - * Apply the argument `a` to construct a program in [[ConnectionIO]] - * yielding an `F[B]` accumulated via `MonadPlus` append. This method is - * more general but less efficient than `to`. - * @group Results - */ - def accumulate[F[_]: Alternative](a: A): ConnectionIO[F[B]] = - withPrepareStatement(a, HRS.accumulate[F, B]) + ConnectionIO.query.collectPair(sql, a)(read.map(ev(_)), write, f) /** * Apply the argument `a` to construct a program in [[ConnectionIO]] @@ -133,7 +92,7 @@ object query { * @group Results */ def unique(a: A): ConnectionIO[B] = - withPrepareStatement(a, HRS.getUnique[B]) + ConnectionIO.query.unique(sql, a)(read, write) /** * Apply the argument `a` to construct a program in [[ConnectionIO]] @@ -142,7 +101,7 @@ object query { * @group Results */ def option(a: A): ConnectionIO[Option[B]] = - withPrepareStatement(a, HRS.getOption[B]) + ConnectionIO.query.option(sql, a)(read, write) /** * Apply the argument `a` to construct a program in [[ConnectionIO]] @@ -151,10 +110,7 @@ object query { * @group Results */ def nel(a: A): ConnectionIO[NonEmptyList[B]] = - withPrepareStatement(a, HRS.nel[B]) - - private def withPrepareStatement[T](a: A, k: ResultSetIO[T]): ConnectionIO[T] = - HC.prepareStatement(sql)(HPS.set(a) *> HPS.executeQuery(k)) + ConnectionIO.query.nel(sql, a)(read, write) /** @group Transformations */ def map[C](f: B => C): Query[A, C] = @@ -186,15 +142,12 @@ object query { def toFragment = outer.toFragment(a) def analysis = outer.analysis def outputAnalysis = outer.outputAnalysis - def streamWithChunkSize(n: Int) = outer.streamWithChunkSize(a, n) - def accumulate[F[_]: Alternative] = outer.accumulate[F](a) def to[F[_]](implicit f: Factory[B, F[B]]) = outer.to[F](a) def toMap[K, V](implicit ev: B =:= (K, V), f: Factory[(K, V), Map[K, V]]) = outer.toMap(a) def unique = outer.unique(a) def option = outer.option(a) def nel = outer.nel(a) def map[C](f: B => C): Query0[C] = outer.map(f).toQuery0(a) - def inspect[R](f: (String, PreparedStatementIO[Unit]) => ConnectionIO[R]) = outer.inspect(a)(f) } } @@ -266,15 +219,6 @@ object query { /** Convert this Query0 to a `Fragment`. */ def toFragment: Fragment - /** - * Program to construct an inspection of the query. Calls `f` with the SQL - * representation of the query and a statement with all statement arguments - * set. Returns the result of the `ConnectionIO` program constructed. - * - * @group Diagnostics - */ - def inspect[R](f: (String, PreparedStatementIO[Unit]) => ConnectionIO[R]): ConnectionIO[R] - /** * Program to construct an analysis of this query's SQL statement and result * set column types. @@ -282,21 +226,6 @@ object query { */ def outputAnalysis: ConnectionIO[Analysis] - /** - * `Stream` with default chunk factor, with effect type [[ConnectionIO]] - * yielding elements of type `B`. - * @group Results - */ - def stream: Stream[ConnectionIO, B] = - streamWithChunkSize(DefaultChunkSize) - - /** - * `Stream` with given chunk factor, with effect type [[ConnectionIO]] - * yielding elements of type `B`. - * @group Results - */ - def streamWithChunkSize(n: Int): Stream[ConnectionIO, B] - /** * Program in [[ConnectionIO]] yielding an `F[B]` accumulated via the * provided `CanBuildFrom`. This is the fastest way to accumulate a @@ -314,14 +243,6 @@ object query { */ def toMap[K, V](implicit ev: B =:= (K, V), f: Factory[(K, V), Map[K, V]]): ConnectionIO[Map[K, V]] - /** - * Program in [[ConnectionIO]] yielding an `F[B]` accumulated via - * `MonadPlus` append. This method is more general but less efficient than - * `to`. - * @group Results - */ - def accumulate[F[_]: Alternative]: ConnectionIO[F[B]] - /** * Program in [[ConnectionIO]] yielding a unique `B` and raising an * exception if the resultset does not have exactly one row. See also diff --git a/modules/core/src/main/scala/doobie/util/read.scala b/modules/core/src/main/scala/doobie/util/read.scala index 740360d89..2f528ce01 100644 --- a/modules/core/src/main/scala/doobie/util/read.scala +++ b/modules/core/src/main/scala/doobie/util/read.scala @@ -6,10 +6,8 @@ package doobie.util import cats.Apply import cats.syntax.apply.* -import doobie.FRS import doobie.enumerated.Nullability import doobie.enumerated.Nullability.* -import doobie.free.resultset.ResultSetIO import java.sql.ResultSet import scala.annotation.implicitNotFound @@ -47,8 +45,6 @@ trait Read[A] { self => def unsafeGet(rs: ResultSet, i: Int): A - final def get: ResultSetIO[A] = FRS.raw(unsafeGet(_, 1)) - final def map[B](f: A => B): Read[B] = new Read[B] { override val gets = self.gets override def unsafeGet(rs: ResultSet, i: Int) = f(self.unsafeGet(rs, i)) diff --git a/modules/core/src/main/scala/doobie/util/stream.scala b/modules/core/src/main/scala/doobie/util/stream.scala deleted file mode 100644 index c0b687902..000000000 --- a/modules/core/src/main/scala/doobie/util/stream.scala +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import fs2.Stream - -/** Additional functions for manipulating `Stream` values. */ -object stream { - - /** Stream constructor for effectful source of chunks. */ - def repeatEvalChunks[F[_], T](fa: F[Seq[T]]): Stream[F, T] = - Stream.repeatEval(fa).takeWhile(_.nonEmpty).flatMap(Stream.emits(_)) -} diff --git a/modules/core/src/main/scala/doobie/util/testing/analysis.scala b/modules/core/src/main/scala/doobie/util/testing/analysis.scala index f99bfc24e..8322e000a 100644 --- a/modules/core/src/main/scala/doobie/util/testing/analysis.scala +++ b/modules/core/src/main/scala/doobie/util/testing/analysis.scala @@ -4,7 +4,6 @@ package doobie.util.testing -import cats.effect.kernel.Sync import cats.syntax.show.* import doobie.free.connection.ConnectionIO import doobie.util.Colors @@ -16,19 +15,12 @@ import doobie.util.query.Query0 import doobie.util.transactor.Transactor import doobie.util.update.Update import doobie.util.update.Update0 -import org.tpolecat.typename.* - -trait UnsafeRun[F[_]] { - def unsafeRunSync[A](fa: F[A]): A -} +import doobie.util.typename.* /** * Common base trait for various checkers and matchers. */ trait CheckerBase[M[_]] { - // Effect type, required instances - implicit def M: Sync[M] - implicit def U: UnsafeRun[M] def transactor: Transactor[M] def colors: Colors = Colors.Ansi } diff --git a/modules/core/src/main/scala/doobie/util/testing/package.scala b/modules/core/src/main/scala/doobie/util/testing/package.scala index d412997bb..76e9e50c5 100644 --- a/modules/core/src/main/scala/doobie/util/testing/package.scala +++ b/modules/core/src/main/scala/doobie/util/testing/package.scala @@ -9,6 +9,7 @@ import cats.syntax.applicativeError.* import cats.syntax.foldable.* import cats.syntax.list.* import doobie.free.connection.ConnectionIO +import doobie.free.connection.ConnectionIO.MonadErrorConnectionIO import doobie.util.analysis.* import doobie.util.pretty.* diff --git a/modules/core/src/main/scala/doobie/util/transactor.scala b/modules/core/src/main/scala/doobie/util/transactor.scala index 77747ea09..6f86f116b 100644 --- a/modules/core/src/main/scala/doobie/util/transactor.scala +++ b/modules/core/src/main/scala/doobie/util/transactor.scala @@ -4,35 +4,16 @@ package doobie.util -import cats.Monad -import cats.data.Kleisli -import cats.effect.kernel.Async -import cats.effect.kernel.MonadCancelThrow -import cats.effect.kernel.Resource -import cats.effect.kernel.Resource.ExitCase -import cats.effect.kernel.Sync -import cats.~> -import doobie.free.KleisliInterpreter +import cats.Id +import cats.free.Free import doobie.free.connection.ConnectionIO -import doobie.free.connection.ConnectionOp -import doobie.free.connection.commit -import doobie.free.connection.rollback -import doobie.free.connection.setAutoCommit -import doobie.free.connection.unit -import doobie.util.lens.* -import doobie.util.yolo.Yolo -import fs2.Stream import java.sql.Connection -import java.sql.DriverManager -import javax.sql.DataSource -import scala.concurrent.ExecutionContext +import scala.util.Using +import scala.util.control.NonFatal object transactor { - /** @group Type Aliases */ - type Interpreter[M[_]] = ConnectionOp ~> Kleisli[M, Connection, *] - /** * Data type representing the common setup, error-handling, and cleanup * strategy associated with an SQL transaction. A [[Transactor]] uses a @@ -52,31 +33,9 @@ object transactor { after: ConnectionIO[Unit], oops: ConnectionIO[Unit], always: ConnectionIO[Unit], - ) { - val resource: Resource[ConnectionIO, Unit] = for { - _ <- Resource.make(doobie.FC.unit)(_ => always) - _ <- Resource.makeCase(before) { case (_, exitCase) => - exitCase match { - case ExitCase.Succeeded => after - case ExitCase.Errored(_) | ExitCase.Canceled => oops - } - } - } yield () - } - + ) object Strategy { - - /** @group Lenses */ - val before: Strategy @> ConnectionIO[Unit] = Lens(_.before, (a, b) => a.copy(before = b)) - - /** @group Lenses */ - val after: Strategy @> ConnectionIO[Unit] = Lens(_.after, (a, b) => a.copy(after = b)) - - /** @group Lenses */ - val oops: Strategy @> ConnectionIO[Unit] = Lens(_.oops, (a, b) => a.copy(oops = b)) - - /** @group Lenses */ - val always: Strategy @> ConnectionIO[Unit] = Lens(_.always, (a, b) => a.copy(always = b)) + import ConnectionIO.* /** * A default `Strategy` with the following properties: @@ -112,21 +71,9 @@ object transactor { /** An arbitrary value, meaningful to the instance * */ def kernel: A - /** - * A program in `M` that can provide a database connection, given the kernel - * * - */ - def connect: A => Resource[M, Connection] - - /** A natural transformation for interpreting `ConnectionIO` * */ - def interpret: Interpreter[M] - /** A `Strategy` for running a program on a connection * */ def strategy: Strategy - /** Construct a [[doobie.util.yolo.Yolo]] for REPL experimentation. */ - def yolo(implicit ev: MonadCancelThrow[M]): Yolo[M] = new Yolo(this) - /** * Construct a program to perform arbitrary configuration on the kernel * value (changing the timeout on a connection pool, for example). This can @@ -138,310 +85,66 @@ object transactor { def configure[B](f: A => M[B]): M[B] = f(kernel) - /** - * Natural transformation equivalent to `exec` that does not use the - * provided `Strategy` and instead directly binds the `Connection` provided - * by `connect`. This can be useful in cases where transactional handling is - * unsupported or undesired. - * @group Natural Transformations - */ - def rawExec(implicit ev: MonadCancelThrow[M]): Kleisli[M, Connection, *] ~> M = - new (Kleisli[M, Connection, *] ~> M) { - def apply[T](k: Kleisli[M, Connection, T]): M[T] = connect(kernel).use(k.run) - } - - /** - * Natural transformation that provides a connection and binds through a - * `Kleisli` program using the given `Strategy`, yielding an independent - * program in `M`. - * @group Natural Transformations - */ - def exec(implicit ev: MonadCancelThrow[M]): Kleisli[M, Connection, *] ~> M = - new (Kleisli[M, Connection, *] ~> M) { - def apply[T](ka: Kleisli[M, Connection, T]): M[T] = - connect(kernel).use { conn => - strategy.resource.mapK(run(conn)).use { _ => - ka.run(conn) - } - } - } - - /** - * Natural transformation equivalent to `trans` that does not use the - * provided `Strategy` and instead directly binds the `Connection` provided - * by `connect`. This can be useful in cases where transactional handling is - * unsupported or undesired. - * @group Natural Transformations - */ - def rawTrans(implicit ev: MonadCancelThrow[M]): ConnectionIO ~> M = - new (ConnectionIO ~> M) { - def apply[T](f: ConnectionIO[T]): M[T] = - connect(kernel).use { conn => - f.foldMap(interpret).run(conn) - } - } - - /** - * Natural transformation that provides a connection and binds through a - * `ConnectionIO` program interpreted via the given interpreter, using the - * given `Strategy`, yielding an independent program in `M`. This is the - * most common way to run a doobie program. - * @group Natural Transformations - */ - def trans(implicit ev: MonadCancelThrow[M]): ConnectionIO ~> M = - new (ConnectionIO ~> M) { - def apply[T](f: ConnectionIO[T]): M[T] = - connect(kernel).use { conn => - strategy.resource.use(_ => f).foldMap(interpret).run(conn) - } - } - - def rawTransP(implicit ev: MonadCancelThrow[M]): Stream[ConnectionIO, *] ~> Stream[M, *] = - new (Stream[ConnectionIO, *] ~> Stream[M, *]) { - def apply[T](s: Stream[ConnectionIO, T]) = - Stream.resource(connect(kernel)).flatMap { conn => - s.translate(run(conn)) - }.scope - } - - def transP(implicit ev: MonadCancelThrow[M]): Stream[ConnectionIO, *] ~> Stream[M, *] = - new (Stream[ConnectionIO, *] ~> Stream[M, *]) { - def apply[T](s: Stream[ConnectionIO, T]) = - Stream.resource(connect(kernel)).flatMap { c => - Stream.resource(strategy.resource).flatMap(_ => s).translate(run(c)) - }.scope - } - - def rawTransPK[I](implicit - ev: MonadCancelThrow[M], - ): Stream[Kleisli[ConnectionIO, I, *], *] ~> Stream[Kleisli[M, I, *], *] = - new (Stream[Kleisli[ConnectionIO, I, *], *] ~> Stream[Kleisli[M, I, *], *]) { - def apply[T](s: Stream[Kleisli[ConnectionIO, I, *], T]) = - Stream.resource(connect(kernel)).translate(Kleisli.liftK[M, I]).flatMap { c => - s.translate(runKleisli[I](c)) - }.scope - } - - def transPK[I](implicit - ev: MonadCancelThrow[M], - ): Stream[Kleisli[ConnectionIO, I, *], *] ~> Stream[Kleisli[M, I, *], *] = - new (Stream[Kleisli[ConnectionIO, I, *], *] ~> Stream[Kleisli[M, I, *], *]) { - def apply[T](s: Stream[Kleisli[ConnectionIO, I, *], T]) = - Stream.resource(connect(kernel)).translate(Kleisli.liftK[M, I]).flatMap { c => - Stream.resource(strategy.resource.mapK(Kleisli.liftK[ConnectionIO, I])).flatMap(_ => s) - .translate(runKleisli[I](c)) - }.scope - } - - private def run(c: Connection)(implicit ev: Monad[M]): ConnectionIO ~> M = - new (ConnectionIO ~> M) { - def apply[T](f: ConnectionIO[T]) = - f.foldMap(interpret).run(c) - } - - private def runKleisli[B](c: Connection)(implicit ev: Monad[M]): Kleisli[ConnectionIO, B, *] ~> Kleisli[M, B, *] = - new (Kleisli[ConnectionIO, B, *] ~> Kleisli[M, B, *]) { - def apply[T](f: Kleisli[ConnectionIO, B, T]) = - Kleisli(f.run(_).foldMap(interpret).run(c)) - } - - @SuppressWarnings(Array("org.wartremover.warts.DefaultArguments")) - def copy( - kernel0: A = self.kernel, - connect0: A => Resource[M, Connection] = self.connect, - interpret0: Interpreter[M] = self.interpret, - strategy0: Strategy = self.strategy, - ): Transactor.Aux[M, A] = new Transactor[M] { - type A = self.A - val kernel = kernel0 - val connect = connect0 - val interpret = interpret0 - val strategy = strategy0 - } - - /* - * Convert the effect type of this transactor from M to M0 - */ - def mapK[M0[_]](fk: M ~> M0)(implicit ev1: MonadCancelThrow[M], ev2: MonadCancelThrow[M0]): Transactor.Aux[M0, A] = - Transactor[M0, A]( - kernel, - connect.andThen(_.mapK(fk)), - interpret.andThen( - new (Kleisli[M, Connection, *] ~> Kleisli[M0, Connection, *]) { - def apply[T](f: Kleisli[M, Connection, T]) = f.mapK(fk) - }, - ), - strategy, - ) + def run[T](io: ConnectionIO[T]): M[T] } object Transactor { - def apply[M[_], A0]( - kernel0: A0, - connect0: A0 => Resource[M, Connection], - interpret0: Interpreter[M], - strategy0: Strategy, - ): Transactor.Aux[M, A0] = new Transactor[M] { - type A = A0 - val kernel = kernel0 - val connect = connect0 - val interpret = interpret0 - val strategy = strategy0 - } - type Aux[M[_], A0] = Transactor[M] { type A = A0 } - /** @group Lenses */ - def kernel[M[_], A]: Lens[Transactor.Aux[M, A], A] = Lens(_.kernel, (a, b) => a.copy(kernel0 = b)) - - /** @group Lenses */ - def connect[M[_], A]: Lens[Transactor.Aux[M, A], (A => Resource[M, Connection])] = - Lens(_.connect, (a, b) => a.copy(connect0 = b)) + def id( + connect: () => Connection, + strategy0: Strategy = Strategy.default, + ) = new Transactor[Id] { + override type A = Unit + override val kernel = () + override val strategy = strategy0 - /** @group Lenses */ - def interpret[M[_]]: Lens[Transactor[M], Interpreter[M]] = Lens(_.interpret, (a, b) => a.copy(interpret0 = b)) - - /** @group Lenses */ - def strategy[M[_]]: Lens[Transactor[M], Strategy] = Lens(_.strategy, (a, b) => a.copy(strategy0 = b)) - - /** @group Lenses */ - def before[M[_]]: Lens[Transactor[M], ConnectionIO[Unit]] = strategy[M] >=> Strategy.before - - /** @group Lenses */ - def after[M[_]]: Lens[Transactor[M], ConnectionIO[Unit]] = strategy[M] >=> Strategy.after - - /** @group Lenses */ - def oops[M[_]]: Lens[Transactor[M], ConnectionIO[Unit]] = strategy[M] >=> Strategy.oops - - /** @group Lenses */ - def always[M[_]]: Lens[Transactor[M], ConnectionIO[Unit]] = strategy[M] >=> Strategy.always - - /** - * Construct a constructor of `Transactor[M, D]` for some `D <: DataSource` - * by partial application of `M`, which cannot be inferred in general. - * @group Constructors - */ - object fromDataSource { - def apply[M[_]] = new FromDataSourceUnapplied[M] + override def run[T](io: ConnectionIO[T]) = { + Using.resource(connect())(runWithConnection(_)(io)) + } - /** - * Constructor of `Transactor[M, D]` fixed for `M`; see the `apply` method - * for details. - * @group Constructors (Partially Applied) - */ - class FromDataSourceUnapplied[M[_]] { - def apply[A <: DataSource]( - dataSource: A, - connectEC: ExecutionContext, - )(implicit ev: Async[M]): Transactor.Aux[M, A] = { - val connect = (dataSource: A) => { - Resource.fromAutoCloseable(ev.evalOn(ev.delay(dataSource.getConnection()), connectEC)) - } - val interp = KleisliInterpreter[M].ConnectionInterpreter - Transactor(dataSource, connect, interp, Strategy.default) + @SuppressWarnings(Array("org.wartremover.warts.Throw")) + private def runWithConnection[T](c: Connection)(io: ConnectionIO[T]): Id[T] = { + val interpret = Free.foldMap(ConnectionIO.interpreter(c)) + try { + interpret(strategy.before) + val result = interpret(io) + interpret(strategy.after) + result + } catch { + case NonFatal(t) => + interpret(strategy.oops) + throw t + } finally { + interpret(strategy.always) } } - } - /** - * Construct a [[Transactor]] that wraps an existing - * [[java.sql.Connection]]. Closing the connection is the responsibility of - * the caller. - * @group Constructors - */ - def fromConnection[M[_]]: FromConnectionUnapplied[M] = new FromConnectionUnapplied[M] - - class FromConnectionUnapplied[M[_]] { - def apply(connection: Connection)(implicit sync: Sync[M]): Transactor.Aux[M, Connection] = { - val connect = (c: Connection) => Resource.pure[M, Connection](c) - val interp = KleisliInterpreter[M].ConnectionInterpreter - Transactor(connection, connect, interp, Strategy.default) + def catsEffect[M[_], A0]( + kernel0: A0, + connect: cats.effect.kernel.Resource[M, Connection], + strategy0: Strategy = Strategy.default, + )(implicit S: cats.effect.kernel.Sync[M]): Transactor.Aux[M, A0] = new Transactor[M] { + override type A = A0 + override val kernel = kernel0 + override val strategy = strategy0 + + override def run[T](io: ConnectionIO[T]) = { + connect.use { conn => + val interpret = Free.foldMap(ConnectionIO.interpreterCatsEffect(conn)) + (for { + _ <- cats.effect.kernel.Resource.make(S.unit)(_ => interpret(strategy.always)) + _ <- cats.effect.kernel.Resource.makeCase(interpret(strategy.before)) { case (_, exitCase) => + exitCase match { + case cats.effect.kernel.Resource.ExitCase.Succeeded => interpret(strategy.after) + case cats.effect.kernel.Resource.ExitCase.Errored(_) | cats.effect.kernel.Resource.ExitCase.Canceled => interpret(strategy.oops) + } + } + } yield ()).use(_ => interpret(io)) + } } } - - /** - * Module of constructors for [[Transactor]] that use the JDBC - * [[java.sql.DriverManager]] to allocate connections. Note that - * [[java.sql.DriverManager]] is unbounded and will happily allocate new - * connections until server resources are exhausted. It is usually - * preferable to use a [[Transactor]] backed by a [[javax.sql.DataSource]] - * with an underlying bounded connection pool (as with `H2Transactor` and - * `HikariTransactor` for instance). Blocking operations are executed on an - * unbounded cached daemon thread pool by default, so you are also at risk - * of exhausting system threads. TL;DR this is fine for console apps but - * don't use it for a web application. - * @group Constructors - */ - def fromDriverManager[M[_]] = new FromDriverManagerUnapplied[M] - - @SuppressWarnings(Array("org.wartremover.warts.Overloading")) - class FromDriverManagerUnapplied[M[_]] { - @SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements")) - private def create( - driver: String, - conn: () => Connection, - strategy: Strategy, - )(implicit ev: Sync[M]): Transactor.Aux[M, Unit] = - Transactor( - (), - _ => Resource.fromAutoCloseable(ev.blocking { Class.forName(driver); conn() }), - KleisliInterpreter[M].ConnectionInterpreter, - strategy, - ) - - /** - * Construct a new [[Transactor]] that uses the JDBC - * [[java.sql.DriverManager]] to allocate connections. - * @param driver - * the class name of the JDBC driver, like "org.h2.Driver" - * @param url - * a connection URL, specific to your driver - */ - def apply(driver: String, url: String)(implicit ev: Sync[M]): Transactor.Aux[M, Unit] = - create(driver, () => DriverManager.getConnection(url), Strategy.default) - - /** - * Construct a new [[Transactor]] that uses the JDBC - * [[java.sql.DriverManager]] to allocate connections. - * @param driver - * the class name of the JDBC driver, like "org.h2.Driver" - * @param url - * a connection URL, specific to your driver - * @param user - * database username - * @param pass - * database password - */ - def apply( - driver: String, - url: String, - user: String, - pass: String, - )(implicit ev: Sync[M]): Transactor.Aux[M, Unit] = - create(driver, () => DriverManager.getConnection(url, user, pass), Strategy.default) - - /** - * Construct a new [[Transactor]] that uses the JDBC - * [[java.sql.DriverManager]] to allocate connections. - * @param driver - * the class name of the JDBC driver, like "org.h2.Driver" - * @param url - * a connection URL, specific to your driver - * @param info - * a [[java.util.Properties]] containing connection information (see - * documentation for the JDBC driver being used) - */ - def apply( - driver: String, - url: String, - info: java.util.Properties, - )(implicit ev: Sync[M]): Transactor.Aux[M, Unit] = - create(driver, () => DriverManager.getConnection(url, info), Strategy.default) - - } - } - } diff --git a/modules/core/src/main/scala/doobie/util/update.scala b/modules/core/src/main/scala/doobie/util/update.scala index ae7bb469e..f04a0b190 100644 --- a/modules/core/src/main/scala/doobie/util/update.scala +++ b/modules/core/src/main/scala/doobie/util/update.scala @@ -6,38 +6,20 @@ package doobie.util import cats.Contravariant import cats.Foldable -import cats.syntax.apply.* -import doobie.FPS -import doobie.HC -import doobie.HPS import doobie.free.connection.ConnectionIO -import doobie.free.preparedstatement.PreparedStatementIO import doobie.util.analysis.Analysis import doobie.util.fragment.Fragment import doobie.util.pos.Pos -import fs2.Stream import scala.collection.Factory /** Module defining updates parameterized by input type. */ object update { - val DefaultChunkSize = query.DefaultChunkSize - trait UpdateManyReturningGeneratedKeysPartiallyApplied[A, K] { def apply[F[_]](as: F[A])(implicit F: Foldable[F], K: Read[K], B: Factory[K, F[K]]): ConnectionIO[F[K]] } - /** - * Partial application hack to allow calling updateManyWithGeneratedKeys - * without passing the F[_] type argument explicitly. - */ - trait UpdateManyWithGeneratedKeysPartiallyApplied[A, K] { - def apply[F[_]](as: F[A])(implicit F: Foldable[F], K: Read[K]): Stream[ConnectionIO, K] = - withChunkSize(as, DefaultChunkSize) - def withChunkSize[F[_]](as: F[A], chunkSize: Int)(implicit F: Foldable[F], K: Read[K]): Stream[ConnectionIO, K] - } - /** * An update parameterized by some input type `A`. This is the type * constructed by the `sql` interpolator. @@ -70,7 +52,7 @@ object update { * @group Diagnostics */ def analysis: ConnectionIO[Analysis] = - HC.prepareUpdateAnalysis[A](sql) + ConnectionIO.prepareUpdateAnalysis[A](sql) /** * Program to construct an analysis of this query's SQL statement and result @@ -78,18 +60,7 @@ object update { * @group Diagnostics */ def outputAnalysis: ConnectionIO[Analysis] = - HC.prepareUpdateAnalysis0(sql) - - /** - * Program to construct an inspection of the query. Given arguments `a`, - * calls `f` with the SQL representation of the query and a statement with - * all arguments set. Returns the result of the `ConnectionIO` program - * constructed. - * - * @group Diagnostics - */ - def inspect[R](a: A)(f: (String, PreparedStatementIO[Unit]) => ConnectionIO[R]): ConnectionIO[R] = - f(sql, HPS.set(a)) + ConnectionIO.prepareUpdateAnalysis0(sql) /** * Construct a program to execute the update and yield a count of affected @@ -97,7 +68,7 @@ object update { * @group Execution */ def run(a: A): ConnectionIO[Int] = - HC.prepareStatement(sql)(HPS.set(a) *> FPS.executeUpdate) + ConnectionIO.update.run(sql, a) /** * Program to execute a batch update and yield a count of affected rows. @@ -107,7 +78,7 @@ object update { * @group Execution */ def updateMany[F[_]: Foldable](fa: F[A]): ConnectionIO[Int] = - HC.prepareStatement(sql)(HPS.addBatchesAndExecute(fa)) + ConnectionIO.update.many(sql, fa) /** * Perform a batch update as with [[updateMany]] yielding generated keys of @@ -119,42 +90,9 @@ object update { def updateManyReturningGeneratedKeys[K](columns: String*): UpdateManyReturningGeneratedKeysPartiallyApplied[A, K] = new UpdateManyReturningGeneratedKeysPartiallyApplied[A, K] { override def apply[F[_]](fa: F[A])(implicit F: Foldable[F], K: Read[K], B: Factory[K, F[K]]) = - HC.updateManyReturningGeneratedKeys(columns.toList)(sql, fa) + ConnectionIO.update.manyReturningGeneratedKeys(sql, fa, columns.toList) } - /** - * Construct a stream that performs a batch update as with [[updateMany]], - * yielding generated keys of readable type `K`, identified by the specified - * columns. Note that not all drivers support generated keys, and some - * support only a single key column. - * @group Execution - */ - def updateManyWithGeneratedKeys[K](columns: String*): UpdateManyWithGeneratedKeysPartiallyApplied[A, K] = - new UpdateManyWithGeneratedKeysPartiallyApplied[A, K] { - override def withChunkSize[F[_]](as: F[A], chunkSize: Int)(implicit F: Foldable[F], K: Read[K]) = - HC.updateManyWithGeneratedKeys(columns.toList)(sql, FPS.unit, as, chunkSize) - } - - /** - * Construct a stream that performs the update, yielding generated keys of - * readable type `K`, identified by the specified columns, given a writable - * argument `a`. Note that not all drivers support generated keys, and some - * support only a single key column. - * @group Execution - */ - def withGeneratedKeys[K: Read](columns: String*)(a: A): Stream[ConnectionIO, K] = - withGeneratedKeysWithChunkSize[K](columns*)(a, DefaultChunkSize) - - /** - * Construct a stream that performs the update, yielding generated keys of - * readable type `K`, identified by the specified columns, given a writable - * argument `a` and `chunkSize`. Note that not all drivers support generated - * keys, and some support only a single key column. - * @group Execution - */ - def withGeneratedKeysWithChunkSize[K: Read](columns: String*)(a: A, chunkSize: Int): Stream[ConnectionIO, K] = - HC.updateWithGeneratedKeys[K](columns.toList)(sql, HPS.set(a), chunkSize) - /** * Construct a program that performs the update, yielding a single set of * generated keys of readable type `K`, identified by the specified columns, @@ -163,7 +101,7 @@ object update { * @group Execution */ def withUniqueGeneratedKeys[K: Read](columns: String*)(a: A): ConnectionIO[K] = - HC.prepareStatementS(sql, columns.toList)(HPS.set(a) *> HPS.executeUpdateWithUniqueGeneratedKeys) + ConnectionIO.update.generatedKeysUnique(sql, a, columns.toList) /** * Update is a contravariant functor. @@ -186,11 +124,7 @@ object update { def analysis = u.analysis def outputAnalysis = u.outputAnalysis def run = u.run(a) - def withGeneratedKeysWithChunkSize[K: Read](columns: String*)(chunkSize: Int) = - u.withGeneratedKeysWithChunkSize[K](columns*)(a, chunkSize) - def withUniqueGeneratedKeys[K: Read](columns: String*) = - u.withUniqueGeneratedKeys(columns*)(a) - def inspect[R](f: (String, PreparedStatementIO[Unit]) => ConnectionIO[R]) = u.inspect(a)(f) + def withUniqueGeneratedKeys[K: Read](columns: String*) = u.withUniqueGeneratedKeys(columns*)(a) } } @@ -252,40 +186,12 @@ object update { */ def outputAnalysis: ConnectionIO[Analysis] - /** - * Program to construct an inspection of the query. Calls `f` with the SQL - * representation of the query and a statement with all statement arguments - * set. Returns the result of the `ConnectionIO` program constructed. - * - * @group Diagnostics - */ - def inspect[R](f: (String, PreparedStatementIO[Unit]) => ConnectionIO[R]): ConnectionIO[R] - /** * Program to execute the update and yield a count of affected rows. * @group Execution */ def run: ConnectionIO[Int] - /** - * Construct a stream that performs the update, yielding generated keys of - * readable type `K`, identified by the specified columns. Note that not all - * drivers support generated keys, and some support only a single key - * column. - * @group Execution - */ - def withGeneratedKeys[K: Read](columns: String*): Stream[ConnectionIO, K] = - withGeneratedKeysWithChunkSize(columns*)(DefaultChunkSize) - - /** - * Construct a stream that performs the update, yielding generated keys of - * readable type `K`, identified by the specified columns, given a - * `chunkSize`. Note that not all drivers support generated keys, and some - * support only a single key column. - * @group Execution - */ - def withGeneratedKeysWithChunkSize[K: Read](columns: String*)(chunkSize: Int): Stream[ConnectionIO, K] - /** * Construct a program that performs the update, yielding a single set of * generated keys of readable type `K`, identified by the specified columns. diff --git a/modules/core/src/main/scala/doobie/util/write.scala b/modules/core/src/main/scala/doobie/util/write.scala index 80fec2eb8..4ffc331ac 100644 --- a/modules/core/src/main/scala/doobie/util/write.scala +++ b/modules/core/src/main/scala/doobie/util/write.scala @@ -6,11 +6,7 @@ package doobie.util import cats.ContravariantSemigroupal import cats.syntax.apply.* -import doobie.FPS -import doobie.FRS import doobie.enumerated.Nullability.* -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.resultset.ResultSetIO import doobie.util.fragment.Elem import doobie.util.fragment.Fragment @@ -27,9 +23,6 @@ trait Write[A] { self => def unsafeSet(ps: PreparedStatement, i: Int, a: A): Unit def unsafeUpdate(rs: ResultSet, i: Int, a: A): Unit - def set(a: A): PreparedStatementIO[Unit] = FPS.raw(unsafeSet(_, 1, a)) - def update(a: A): ResultSetIO[Unit] = FRS.raw(unsafeUpdate(_, 1, a)) - def contramap[B](f: B => A): Write[B] = new Write[B] { override val puts = self.puts override def values(b: B) = self.values(f(b)) diff --git a/modules/core/src/main/scala/doobie/util/yolo.scala b/modules/core/src/main/scala/doobie/util/yolo.scala deleted file mode 100644 index 8d12bd81d..000000000 --- a/modules/core/src/main/scala/doobie/util/yolo.scala +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import cats.effect.kernel.MonadCancelThrow -import cats.syntax.show.* -import doobie.free.connection.ConnectionIO -import doobie.free.connection.delay -import doobie.syntax.connectionio.* -import doobie.util.query.Query -import doobie.util.query.Query0 -import doobie.util.testing.AnalysisArgs -import doobie.util.testing.Analyzable -import doobie.util.testing.analyze -import doobie.util.testing.formatReport -import doobie.util.transactor.Transactor -import doobie.util.update.Update -import doobie.util.update.Update0 -import fs2.Stream -import org.tpolecat.typename.* - -/** Module for implicit syntax useful in REPL session. */ -object yolo { - - class Yolo[M[_]](xa: Transactor[M])(implicit ev: MonadCancelThrow[M]) { - - private def out(s: String, colors: Colors): ConnectionIO[Unit] = - delay(Console.println(show"${colors.BLUE} $s${colors.RESET}")) - - implicit class Query0YoloOps[A: TypeName](q: Query0[A]) { - - @SuppressWarnings(Array("org.wartremover.warts.ToString")) - def quick(implicit colors: Colors = Colors.Ansi): M[Unit] = - q.stream - .map(_.toString) - .evalMap(out(_, colors)) - .compile - .drain - .transact(xa)(ev) - - def check(implicit colors: Colors = Colors.Ansi): M[Unit] = - checkImpl(Analyzable.unpack(q), colors) - - def checkOutput(implicit colors: Colors = Colors.Ansi): M[Unit] = - checkImpl( - AnalysisArgs( - show"Query0[${typeName[A]}]", - q.pos, - q.sql, - q.outputAnalysis, - ), - colors, - ) - } - - implicit class QueryYoloOps[I: TypeName, A: TypeName](q: Query[I, A]) { - - def quick(i: I): M[Unit] = - q.toQuery0(i).quick - - def check(implicit colors: Colors = Colors.Ansi): M[Unit] = - checkImpl(Analyzable.unpack(q), colors) - - def checkOutput(implicit colors: Colors = Colors.Ansi): M[Unit] = - checkImpl( - AnalysisArgs( - show"Query[${typeName[I]}, ${typeName[A]}]", - q.pos, - q.sql, - q.outputAnalysis, - ), - colors, - ) - } - - implicit class Update0YoloOps(u: Update0) { - - def quick(implicit colors: Colors = Colors.Ansi): M[Unit] = - u.run.flatMap(a => out(show"$a row(s) updated", colors)).transact(xa)(ev) - - def check(implicit colors: Colors = Colors.Ansi): M[Unit] = - checkImpl(Analyzable.unpack(u), colors) - } - - implicit class UpdateYoloOps[I: TypeName](u: Update[I]) { - - def quick(i: I)(implicit colors: Colors = Colors.Ansi): M[Unit] = - u.toUpdate0(i).quick - - def check(implicit colors: Colors = Colors.Ansi): M[Unit] = - checkImpl(Analyzable.unpack(u), colors) - } - - implicit class ConnectionIOYoloOps[A](ca: ConnectionIO[A]) { - @SuppressWarnings(Array("org.wartremover.warts.ToString")) - def quick(implicit colors: Colors = Colors.Ansi): M[Unit] = - ca.flatMap(a => out(a.toString, colors)).transact(xa)(ev) - } - - implicit class StreamYoloOps[A](pa: Stream[ConnectionIO, A]) { - @SuppressWarnings(Array("org.wartremover.warts.ToString")) - def quick(implicit colors: Colors = Colors.Ansi): M[Unit] = - pa.evalMap(a => out(a.toString, colors)).compile.drain.transact(xa)(ev) - } - - private def checkImpl(args: AnalysisArgs, colors: Colors): M[Unit] = - analyze(args).flatMap { report => - val formatted = formatReport(args, report, colors) - delay(println(formatted.padLeft(" "))) - }.transact(xa)(ev) - } -} diff --git a/modules/core/src/test/scala/doobie/issue/262.scala b/modules/core/src/test/scala/doobie/issue/262.scala deleted file mode 100644 index 451173916..000000000 --- a/modules/core/src/test/scala/doobie/issue/262.scala +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.issue - -import doobie.H2DatabaseSpec -import doobie.HC -import doobie.HPS -import doobie.free.KleisliInterpreter -import doobie.util.transactor.Transactor -import zio.Task -import zio.ZIO -import zio.test.assertTrue - -object `262` extends H2DatabaseSpec { - - // an interpreter that returns null when we ask for statement metadata - @SuppressWarnings(Array("org.wartremover.warts.Null")) - object Interp extends KleisliInterpreter[Task] { - override lazy val PreparedStatementInterpreter = - new PreparedStatementInterpreter { - override def getMetaData = primitive(_ => null) - } - } - - override val spec = suite("262")( - test("getColumnJdbcMeta should handle null metadata") { - for { - transactor <- ZIO.service[Transactor[Task]] - xa = Transactor.interpret.set(transactor, Interp.ConnectionInterpreter) - prog = HC.prepareStatement("select 1")(HPS.getColumnJdbcMeta) - result <- xa.trans(instance)(prog) - } yield { - assertTrue(result == Nil) - } - }, - ) - -} diff --git a/modules/zio/src/test/scala/zoobie/stub/StubConnection.scala b/modules/core/src/test/scala/doobie/stub/StubConnection.scala similarity index 86% rename from modules/zio/src/test/scala/zoobie/stub/StubConnection.scala rename to modules/core/src/test/scala/doobie/stub/StubConnection.scala index a5fc2e0d7..41d6cb6cf 100644 --- a/modules/zio/src/test/scala/zoobie/stub/StubConnection.scala +++ b/modules/core/src/test/scala/doobie/stub/StubConnection.scala @@ -1,4 +1,4 @@ -package zoobie.stub +package doobie.stub import java.sql import java.sql.Blob @@ -17,9 +17,14 @@ import java.util import java.util.Properties import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicInteger +import scala.collection.mutable +object StubConnection { + val InvalidSQL = "INVALID SQL" + val Select1 = "select 1" +} @SuppressWarnings(Array("org.wartremover.warts.Null")) -class StubConnection(valid: Int => Boolean) extends Connection { +class StubConnection(valid: Int => Boolean = _ => true) extends Connection { private var closed = false private var autoCommit = true @@ -34,6 +39,9 @@ class StubConnection(valid: Int => Boolean) extends Connection { private val _numRollbacks = new AtomicInteger(0) def numRollbacks = _numRollbacks.get() + private val _preparedStatements = mutable.ListBuffer.empty[StubPreparedStatement] + def preparedStatements = _preparedStatements.toList + override def commit(): Unit = { val _ = _numCommits.updateAndGet(_ + 1) } @@ -83,10 +91,7 @@ class StubConnection(valid: Int => Boolean) extends Connection { resultSetConcurrency: Int, resultSetHoldability: Int, ): Statement = ??? - override def prepareStatement(sql: String): PreparedStatement = { - val fail = sql == "INVALID SQL" - new StubPreparedStatement(fail) - } + override def prepareStatement(sql: String): PreparedStatement = newPreparedStatement(sql) override def prepareStatement(sql: String, resultSetType: Int, resultSetConcurrency: Int): PreparedStatement = ??? override def prepareStatement( sql: String, @@ -99,6 +104,18 @@ class StubConnection(valid: Int => Boolean) extends Connection { override def prepareStatement(sql: String, columnIndexes: Array[Int]): PreparedStatement = ??? override def prepareStatement(sql: String, columnNames: Array[String]): PreparedStatement = ??? + private def newPreparedStatement(sql: String) = { + val fail = sql == StubConnection.InvalidSQL + val results = { + if (sql.trim == StubConnection.Select1) { + List(Vector[AnyRef](1: java.lang.Integer)) + } else Nil + } + val ps = new StubPreparedStatement(results, fail) + val _ = _preparedStatements.addOne(ps) + ps + } + override def prepareCall(sql: String): CallableStatement = ??? override def prepareCall(sql: String, resultSetType: Int, resultSetConcurrency: Int): CallableStatement = ??? override def prepareCall( diff --git a/modules/zio/src/test/scala/zoobie/stub/StubPreparedStatement.scala b/modules/core/src/test/scala/doobie/stub/StubPreparedStatement.scala similarity index 92% rename from modules/zio/src/test/scala/zoobie/stub/StubPreparedStatement.scala rename to modules/core/src/test/scala/doobie/stub/StubPreparedStatement.scala index 133e693fa..a875242d4 100644 --- a/modules/zio/src/test/scala/zoobie/stub/StubPreparedStatement.scala +++ b/modules/core/src/test/scala/doobie/stub/StubPreparedStatement.scala @@ -1,4 +1,4 @@ -package zoobie.stub +package doobie.stub import java.io.InputStream import java.io.Reader @@ -21,10 +21,14 @@ import java.sql.SQLXML import java.sql.Time import java.sql.Timestamp import java.util.Calendar +import scala.collection.mutable -class StubPreparedStatement(fail: Boolean = false) extends PreparedStatement { +class StubPreparedStatement(results: List[Vector[AnyRef]] = Nil, fail: Boolean = false) extends PreparedStatement { private var closed = false + private val _resultSets = mutable.ListBuffer.empty[ResultSet] + def resultSets = _resultSets.toList + override def addBatch(sql: String): Unit = ??? override def addBatch(): Unit = ??? override def cancel(): Unit = ??? @@ -42,11 +46,16 @@ class StubPreparedStatement(fail: Boolean = false) extends PreparedStatement { override def executeBatch(): Array[Int] = ??? override def execute(): Boolean = ??? - override def executeQuery(): ResultSet = { - if (fail) throw new SQLSyntaxErrorException() else new StubResultSet - } + override def executeQuery(): ResultSet = newResultSet() override def executeQuery(sql: String): ResultSet = ??? + private def newResultSet() = { + if (fail) throw new SQLSyntaxErrorException() + val rs = new StubResultSet(results) + val _ = _resultSets.addOne(rs) + rs + } + override def execute(sql: String, autoGeneratedKeys: Int): Boolean = ??? override def execute(sql: String): Boolean = ??? override def execute(sql: String, columnIndexes: Array[Int]): Boolean = ??? @@ -100,7 +109,7 @@ class StubPreparedStatement(fail: Boolean = false) extends PreparedStatement { override def setDouble(parameterIndex: Int, x: Double): Unit = ??? override def setEscapeProcessing(enable: Boolean): Unit = ??? override def setFetchDirection(direction: Int): Unit = ??? - override def setFetchSize(rows: Int): Unit = ??? + override def setFetchSize(rows: Int): Unit = () override def setFloat(parameterIndex: Int, x: Float): Unit = ??? override def setInt(parameterIndex: Int, x: Int): Unit = ??? override def setLong(parameterIndex: Int, x: Long): Unit = ??? diff --git a/modules/zio/src/test/scala/zoobie/stub/StubResultSet.scala b/modules/core/src/test/scala/doobie/stub/StubResultSet.scala similarity index 95% rename from modules/zio/src/test/scala/zoobie/stub/StubResultSet.scala rename to modules/core/src/test/scala/doobie/stub/StubResultSet.scala index 57ae05d06..7f56c7bfd 100644 --- a/modules/zio/src/test/scala/zoobie/stub/StubResultSet.scala +++ b/modules/core/src/test/scala/doobie/stub/StubResultSet.scala @@ -1,4 +1,4 @@ -package zoobie.stub +package doobie.stub import java.io.InputStream import java.io.Reader @@ -20,20 +20,34 @@ import java.sql.Timestamp import java.util import java.util.Calendar -class StubResultSet extends ResultSet { +@SuppressWarnings(Array("org.wartremover.warts.Null")) +class StubResultSet(results: List[Vector[AnyRef]] = Nil) extends ResultSet { private var closed = false + private var _wasNull = false + private var current: Vector[AnyRef] = _ + private var remaining = results - override def next(): Boolean = false + override def next(): Boolean = { + val nonEmpty = remaining.nonEmpty + if (nonEmpty) { + current = remaining.head + remaining = remaining.tail + } + nonEmpty + } override def isClosed: Boolean = closed override def close(): Unit = closed = true - override def wasNull(): Boolean = ??? + override def wasNull(): Boolean = _wasNull override def getString(columnIndex: Int): String = ??? override def getBoolean(columnIndex: Int): Boolean = ??? override def getByte(columnIndex: Int): Byte = ??? override def getShort(columnIndex: Int): Short = ??? - override def getInt(columnIndex: Int): Int = ??? + override def getInt(columnIndex: Int): Int = { + _wasNull = false + current(columnIndex - 1).asInstanceOf[Int] + } override def getLong(columnIndex: Int): Long = ??? override def getFloat(columnIndex: Int): Float = ??? override def getDouble(columnIndex: Int): Double = ??? diff --git a/modules/core/src/test/scala/doobie/util/ConnectionIOSuite.scala b/modules/core/src/test/scala/doobie/util/ConnectionIOSuite.scala index c5b62a1eb..f01a0163f 100644 --- a/modules/core/src/test/scala/doobie/util/ConnectionIOSuite.scala +++ b/modules/core/src/test/scala/doobie/util/ConnectionIOSuite.scala @@ -10,6 +10,8 @@ import cats.syntax.applicative.* import cats.syntax.semigroup.* import doobie.H2DatabaseSpec import doobie.free.connection.ConnectionIO +import doobie.free.connection.ConnectionIO.MonadErrorConnectionIO +import doobie.free.connection.ConnectionIO.MonoidConnectionIO import zio.test.assertCompletes import zio.test.assertTrue diff --git a/modules/core/src/test/scala/doobie/util/LensSuite.scala b/modules/core/src/test/scala/doobie/util/LensSuite.scala deleted file mode 100644 index bb426ca46..000000000 --- a/modules/core/src/test/scala/doobie/util/LensSuite.scala +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import cats.data.State -import doobie.util.lens.* -import zio.test.ZIOSpecDefault -import zio.test.assertTrue - -object LensSuite extends ZIOSpecDefault { - - case class Name(first: String, last: String) - object Name { - val first: Name @> String = Lens(_.first, (a, b) => a.copy(first = b)) - val last: Name @> String = Lens(_.last, (a, b) => a.copy(last = b)) - } - - case class Address(name: Name, street: String) - object Address { - val name: Address @> Name = Lens(_.name, (a, b) => a.copy(name = b)) - val street: Address @> String = Lens(_.street, (a, b) => a.copy(street = b)) - val first: Address @> String = name >=> Name.first - val last: Address @> String = name >=> Name.last - } - - private val bob = Address(Name("Bob", "Dole"), "123 Foo St.") - - private def exec[S](st: State[S, ?], s: S): S = st.runS(s).value - - override val spec = suite("Lens")( - test("modify") { - val prog: State[Address, Unit] = for { - _ <- Address.first %= (_.toUpperCase) - _ <- Address.last %= (_.toLowerCase) - _ <- Address.street %= (_.replace('o', '*')) - } yield () - assertTrue(exec(prog, bob) == Address(Name("BOB", "dole"), "123 F** St.")) - }, - test("set") { - val prog: State[Address, Unit] = for { - _ <- Address.first := "Jimmy" - _ <- Address.last := "Carter" - _ <- Address.street := "12 Peanut Dr." - } yield () - assertTrue(exec(prog, bob) == Address(Name("Jimmy", "Carter"), "12 Peanut Dr.")) - }, - ) - -} diff --git a/modules/core/src/test/scala/doobie/util/ProcessSuite.scala b/modules/core/src/test/scala/doobie/util/ProcessSuite.scala deleted file mode 100644 index 2f462ecb9..000000000 --- a/modules/core/src/test/scala/doobie/util/ProcessSuite.scala +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import cats.effect.SyncIO -import doobie.util.stream.repeatEvalChunks -import zio.test.Gen -import zio.test.ZIOSpecDefault -import zio.test.assertTrue -import zio.test.check - -import scala.util.Random - -object ProcessSuite extends ZIOSpecDefault { - - override val spec = suite("Process")( - test("repeatEvalChunks must yield the same result irrespective of chunk size") { - check(Gen.int(1, 1000)) { chunkSize => - val dataSize = 1000 - val data = Seq.fill(dataSize)(Random.nextInt()) - val fa = { - var temp = data - SyncIO { - val (h, t) = temp.splitAt(chunkSize) - temp = t - h - } - } - val result = repeatEvalChunks(fa).compile.toVector.unsafeRunSync() - assertTrue(result == data.toVector) - } - }, - ) - -} diff --git a/modules/core/src/test/scala/doobie/util/StrategySuite.scala b/modules/core/src/test/scala/doobie/util/StrategySuite.scala index bb145499b..6f1ee1964 100644 --- a/modules/core/src/test/scala/doobie/util/StrategySuite.scala +++ b/modules/core/src/test/scala/doobie/util/StrategySuite.scala @@ -4,171 +4,79 @@ package doobie.util -import cats.syntax.apply.* +import cats.effect.IO +import cats.effect.kernel.Resource import doobie.H2DatabaseSpec -import doobie.free.KleisliInterpreter import doobie.free.connection.ConnectionIO +import doobie.stub.StubConnection import doobie.syntax.string.* import doobie.util.transactor.Transactor -import zio.Task import zio.ZIO import zio.test.assertTrue object StrategySuite extends H2DatabaseSpec { override val spec = suite("Strategy")( - test("Connection.autoCommit should be set to false") { - interp(fr"select 1".query[Int].unique).map { case (i, result) => - val autoCommit = i.Connection.autoCommit - assertTrue(result == Right(1)) && assertTrue(autoCommit == Some(false)) - } - }, - test("Connection.commit should be called on success") { - interp(fr"select 1".query[Int].unique).map { case (i, result) => - val commit = i.Connection.commit - assertTrue(result == Right(1)) && assertTrue(commit == Some(())) - } - }, - test("Connection.commit should NOT be called on failure") { - interp(fr"abc".query[Int].unique).map { case (i, result) => - val commit = i.Connection.commit - assertTrue(result.isLeft) && assertTrue(commit == None) - } - }, - test("Connection.rollback should NOT be called on success") { - interp(fr"select 1".query[Int].unique).map { case (i, result) => - val rollback = i.Connection.rollback - assertTrue(result == Right(1)) && assertTrue(rollback == None) - } - }, - test("Connection.rollback should be called on failure") { - interp(fr"abc".query[Int].unique).map { case (i, result) => - val rollback = i.Connection.rollback - assertTrue(result.isLeft) && assertTrue(rollback == Some(())) - } - }, - test("[Streaming] Connection.autoCommit should be set to false") { - interp(fr"select 1".query[Int].stream.compile.toList).map { case (i, result) => - val autoCommit = i.Connection.autoCommit - assertTrue(result == Right(List(1))) && assertTrue(autoCommit == Some(false)) - } - }, - test("[Streaming] Connection.commit should be called on success") { - interp(fr"select 1".query[Int].stream.compile.toList).map { case (i, result) => - val commit = i.Connection.commit - assertTrue(result == Right(List(1))) && assertTrue(commit == Some(())) - } - }, - test("[Streaming] Connection.commit should NOT be called on failure") { - interp(fr"abc".query[Int].stream.compile.toList).map { case (i, result) => - val commit = i.Connection.commit - assertTrue(result.isLeft) && assertTrue(commit == None) - } - }, - test("[Streaming] Connection.rollback should NOT be called on success") { - interp(fr"select 1".query[Int].stream.compile.toList).map { case (i, result) => - val rollback = i.Connection.rollback - assertTrue(result == Right(List(1))) && assertTrue(rollback == None) - } - }, - test("[Streaming] Connection.rollback should be called on failure") { - interp(fr"abc".query[Int].stream.compile.toList).map { case (i, result) => - val rollback = i.Connection.rollback - assertTrue(result.isLeft) && assertTrue(rollback == Some(())) - } - }, - test("PreparedStatement.close should be called on success") { - interp(fr"select 1".query[Int].unique).map { case (i, result) => - val close = i.PreparedStatement.close - assertTrue(result == Right(1)) && assertTrue(close == Some(())) - } - }, - test("PreparedStatement.close should be called on failure") { - interp(fr"select 'x'".query[Int].unique).map { case (i, result) => - val close = i.PreparedStatement.close - assertTrue(result.isLeft) && assertTrue(close == Some(())) - } - }, - test("[Streaming] PreparedStatement.close should be called on success") { - interp(fr"select 1".query[Int].stream.compile.toList).map { case (i, result) => - val close = i.PreparedStatement.close - assertTrue(result == Right(List(1))) && assertTrue(close == Some(())) - } - }, - test("[Streaming] PreparedStatement.close should be called on failure") { - interp(fr"select 'x'".query[Int].stream.compile.toList).map { case (i, result) => - val close = i.PreparedStatement.close - assertTrue(result.isLeft) && assertTrue(close == Some(())) - } - }, - test("ResultSet.close should be called on success") { - interp(fr"select 1".query[Int].unique).map { case (i, result) => - val close = i.ResultSet.close - assertTrue(result == Right(1)) && assertTrue(close == Some(())) - } - }, - test("ResultSet.close should be called on failure") { - interp(fr"select 'x'".query[Int].unique).map { case (i, result) => - val close = i.ResultSet.close - assertTrue(result.isLeft) && assertTrue(close == Some(())) - } - }, - test("[Streaming] ResultSet.close should be called on success") { - interp(fr"select 1".query[Int].stream.compile.toList).map { case (i, result) => - val close = i.ResultSet.close - assertTrue(result == Right(List(1))) && assertTrue(close == Some(())) - } - }, - test("[Streaming] ResultSet.close should be called on failure") { - interp(fr"select 'x'".query[Int].stream.compile.toList).map { case (i, result) => - val close = i.ResultSet.close - assertTrue(result.isLeft) && assertTrue(close == Some(())) + specTransactor("id", interpId), + specTransactor("cats", interpCats), + ) + + private[doobie] def specTransactor( + name: String, + interp: ConnectionIO[Int] => ZIO[Any, Nothing, (StubConnection, Either[Throwable, Int])], + ) = suite(name)( + test("success") { + interp(fr"select 1".query[Int].unique).map { case (c, result) => + assertTrue(result == Right(1)) && + assertTrue( + !c.getAutoCommit && + c.numCommits == 1 && + c.numRollbacks == 0 && + c.isClosed, + ) && + assertTrue( + c.preparedStatements.size == 1 && + c.preparedStatements.forall(_.isClosed), + ) && + assertTrue( + c.preparedStatements.forall(_.resultSets.size == 1) && + c.preparedStatements.forall(_.resultSets.forall(_.isClosed)), + ) + } + }, + test("failure") { + interp(fr"abc".query[Int].unique).map { case (c, result) => + assertTrue(result.isLeft) && + assertTrue( + !c.getAutoCommit && + c.numCommits == 0 && + c.numRollbacks == 1 && + c.isClosed, + ) && + assertTrue( + c.preparedStatements.size == 1 && + c.preparedStatements.forall(_.isClosed), + ) && + assertTrue( + c.preparedStatements.forall(_.resultSets.size == 1) && + c.preparedStatements.forall(_.resultSets.forall(_.isClosed)), + ) } }, ) - private def interp[A](c: ConnectionIO[A]): ZIO[Transactor[Task], Nothing, (Interp, Either[Throwable, A])] = for { - transactor <- ZIO.service[Transactor[Task]] - i = new Interp - xa = Transactor.interpret[Task].set(transactor, i.ConnectionInterpreter) - result <- xa.trans(instance)(c).either - } yield { - (i, result) - } -} - -// an instrumented interpreter -@SuppressWarnings(Array("org.wartremover.warts.Var")) -class Interp extends KleisliInterpreter[Task]()(zio.interop.catz.asyncInstance[Any]) { - - object Connection { - var autoCommit: Option[Boolean] = None - var close: Option[Unit] = None - var commit: Option[Unit] = None - var rollback: Option[Unit] = None - } - - object PreparedStatement { - var close: Option[Unit] = None + private def interpId[A](c: ConnectionIO[A]) = { + val conn = new StubConnection() + val transactor = Transactor.id(() => conn) + ZIO.attempt(transactor.run(c)).either.map((conn, _)) } - object ResultSet { - var close: Option[Unit] = None - } - - override lazy val ConnectionInterpreter = new ConnectionInterpreter { - override val close = delay(Connection.close = Some(())) *> super.close - override val rollback = delay(Connection.rollback = Some(())) *> super.rollback - override val commit = delay(Connection.commit = Some(())) *> super.commit - override def setAutoCommit(b: Boolean) = delay(Connection.autoCommit = Option(b)) *> super.setAutoCommit(b) - } + private def interpCats[A](c: ConnectionIO[A]) = { + val conn = new StubConnection() + val create = Resource.fromAutoCloseable(IO.delay(conn)) + val transactor = Transactor.catsEffect((), create) - override lazy val PreparedStatementInterpreter = new PreparedStatementInterpreter { - override val close = delay(PreparedStatement.close = Some(())) *> super.close + import cats.effect.unsafe.implicits.global + ZIO.fromFuture(_ => transactor.run(c).unsafeToFuture()).either.map((conn, _)) } - - override lazy val ResultSetInterpreter = new ResultSetInterpreter { - override val close = delay(ResultSet.close = Some(())) *> super.close - } - } diff --git a/modules/core/src/test/scala/doobie/util/TransactorSuite.scala b/modules/core/src/test/scala/doobie/util/TransactorSuite.scala deleted file mode 100644 index 8c141a437..000000000 --- a/modules/core/src/test/scala/doobie/util/TransactorSuite.scala +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.util - -import doobie.H2DatabaseSpec -import doobie.free.connection.ConnectionIO -import doobie.syntax.string.* -import doobie.util.transactor.Transactor -import fs2.Stream -import zio.Task -import zio.ZIO -import zio.durationInt -import zio.test.assertCompletes -import zio.test.assertTrue - -object TransactorSuite extends H2DatabaseSpec { - - override val spec = suite("Transactor")( - test("Connection.close should be called on success") { - withTracker(fr"select 1".query[Int].unique).map { case (tracker, result) => - assertTrue(result == Right(1)) && - assertTrue(tracker.connections.map(_.isClosed) == List(true)) - } - }, - test("Connection.close should be called on failure") { - withTracker(fr"abc".query[Int].unique).map { case (tracker, result) => - assertTrue(result.isLeft) && - assertTrue(tracker.connections.map(_.isClosed) == List(true)) - } - }, - test("[Streaming] Connection.close should be called on success") { - withTracker(fr"select 1".query[Int].stream.compile.toList).map { case (tracker, result) => - assertTrue(result == Right(List(1))) && - assertTrue(tracker.connections.map(_.isClosed) == List(true)) - } - }, - test("[Streaming] Connection.close should be called on failure") { - withTracker(fr"abc".query[Int].stream.compile.toList).map { case (tracker, result) => - assertTrue(result.isLeft) && - assertTrue(tracker.connections.map(_.isClosed) == List(true)) - } - }, - test("Not leak connections with recursive query streams") { - for { - transactor <- ZIO.service[Transactor[Task]] - poll = transactor.transP(instance)(fr"select 1".query[Int].stream) ++ Stream.exec(ZIO.sleep(50.millis)) - _ <- Stream.emits(List.fill(4)(poll.repeat)) - .parJoinUnbounded(zio.interop.catz.asyncInstance[Any]) - .take(20) - .compile - .drain - } yield { - assertCompletes - } - }, - ) - - private def withTracker[A](c: ConnectionIO[A]) = for { - xa <- ZIO.service[Transactor[Task]] - tracker = new ConnectionTracker - transactor = tracker.track(xa) - result <- transactor.trans(instance)(c).either - } yield (tracker, result) -} - -@SuppressWarnings(Array("org.wartremover.warts.Var")) -class ConnectionTracker { - var connections = List.empty[java.sql.Connection] - - def track[F[_]](xa: Transactor[F]) = { - def withA(t: Transactor[F]): Transactor.Aux[F, t.A] = { - Transactor.connect.modify( - t, - f => - a => { - f(a).map { conn => - connections = conn :: connections - conn - } - }, - ) - } - withA(xa) - } -} diff --git a/modules/core/src/test/scala/doobie/util/UpdateSuite.scala b/modules/core/src/test/scala/doobie/util/UpdateSuite.scala index 546679673..505ee61eb 100644 --- a/modules/core/src/test/scala/doobie/util/UpdateSuite.scala +++ b/modules/core/src/test/scala/doobie/util/UpdateSuite.scala @@ -71,16 +71,6 @@ object UpdateSuite extends H2DatabaseSpec { } conn.transact }, - test("many returning with generated keys") { - val conn = for { - _ <- fr"CREATE LOCAL TEMPORARY TABLE IF NOT EXISTS test_update_many_w (v INT) NOT PERSISTENT".update.run - result <- Update[Int]("INSERT INTO test_update_many_w VALUES (?)") - .updateManyWithGeneratedKeys[Int]("v")((1 to 10).toList).compile.toList - } yield { - assertTrue(result == (1 to 10).toList) - } - conn.transact - }, ), ) diff --git a/modules/docs/src/main/mdoc/docs/17-FAQ.md b/modules/docs/src/main/mdoc/docs/17-FAQ.md deleted file mode 100644 index b74721336..000000000 --- a/modules/docs/src/main/mdoc/docs/17-FAQ.md +++ /dev/null @@ -1,221 +0,0 @@ -## Frequently-Asked Questions - -In this chapter we address some frequently-asked questions, in no particular order. First a bit of set-up. - -```scala mdoc:silent -import cats.* -import cats.data.* -import cats.effect.* -import cats.effect.implicits.* -import cats.implicits.* -import doobie.FC -import doobie.free.connection.ConnectionIO -import doobie.syntax.string.* -import doobie.util.ExecutionContexts -import doobie.util.Read -import doobie.util.Write -import doobie.util.meta.Meta -import doobie.util.query.Query0 -import doobie.util.transactor.Transactor -import java.awt.geom.Point2D -import java.util.UUID - -// This is just for testing. Consider using cats.effect.IOApp instead of calling -// unsafe methods directly. -import cats.effect.unsafe.implicits.global - -// A transactor that gets connections from java.sql.DriverManager. -// See the chapter on connection handling for more info. -val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", // driver classname - "jdbc:postgresql:world", // connect URL (driver-specific) - "postgres", // user - "password", // password -) -``` - -```scala mdoc:invisible -implicit val mdocColors: doobie.util.Colors = doobie.util.Colors.None -``` - -### How do I do an `IN` clause? - -This used to be very irritating, but as of 0.4.0 there is a good solution. See the section on `IN` clauses in [Chapter 5](05-Parameterized.html) and [Chapter 8](08-Fragments.html) on statement fragments. - -### How do I ascribe an SQL type to an interpolated parameter? - -Interpolated parameters are replaced with `?` placeholders, so if you need to ascribe an SQL type you can use vendor-specific syntax in conjunction with the interpolated value. For example, in PostgreSQL you use `:: type`: - -```scala mdoc -{ - val y = xa.yolo - import y.* - val s = "foo" - sql"select $s".query[String].check.unsafeRunSync() - sql"select $s :: char".query[String].check.unsafeRunSync() -} -``` - -### How do I do several things in the same transaction? - -You can use a `for` comprehension to compose any number of `ConnectionIO` programs, and then call `.transact(xa)` on the result. All of the composed programs will run in the same transaction. For this reason it's useful for your APIs to expose values in `ConnectionIO`, so higher-level code can place transaction boundaries as needed. - -### How do I run something outside of a transaction? - -`Transactor.transact` takes a `ConnectionIO` and constructs an `IO` or similar that will run it in a single transaction, but it is also possible to include transaction boundaries *within* a `ConnectionIO`, and to disable transaction handling altogether. Some kinds of DDL statements may require this for some databases. You can define a combinator to do this for you. - -```scala mdoc:silent -/** - * Take a program `p` and return an equivalent one that first commits - * any ongoing transaction, runs `p` without transaction handling, then - * starts a new transaction. - */ -def withoutTransaction[A](p: ConnectionIO[A]): ConnectionIO[A] = - FC.setAutoCommit(true).bracket(_ => p)(_ => FC.setAutoCommit(false)) -``` - -Note that you need both of these operations if you are using a `Transactor` because it will always start a transaction and will try to commit on completion. - - -### How do I turn an arbitrary SQL string into a `Query0/Update0`? - -As of **doobie** 0.4.0 this is done via [statement fragments](08-Fragments.html). Here we choose the sort order dynamically. - -```scala mdoc:silent -case class Code(country: String) -object Code { - implicit val read: Read[Code] = Read.derived - implicit val write: Write[Code] = Write.derived -} -case class City(code: Code, name: String, population: Int) -object City { - implicit val read: Read[City] = Read.derived -} - -def cities(code: Code, asc: Boolean): Query0[City] = { - val ord = if (asc) fr"ASC" else fr"DESC" - val sql = fr""" - SELECT countrycode, name, population - FROM city - WHERE countrycode = $code - ORDER BY name""" ++ ord - sql.query[City] -} -``` - -We can check the resulting `Query0` as expected. - -```scala mdoc -{ - val y = xa.yolo - import y.* - cities(Code("USA"), true).check.unsafeRunSync() -} -``` - -And it works! - -```scala mdoc -{ - val y = xa.yolo - import y.* - cities(Code("USA"), true).stream.take(5).quick.unsafeRunSync() - cities(Code("USA"), false).stream.take(5).quick.unsafeRunSync() -} -``` - -### How do I handle outer joins? - -With an outer join you end up with set of nullable columns, which you typically want to map to a single `Option` of some composite type, which doobie can do for you. If all columns are null you will get back `None`. - -```scala mdoc:silent -case class Country(name: String, code: String) -object Country { - implicit val read: Read[Country] = Read.derived -} -case class City2(name: String, district: String) -object City2 { - implicit val read: Read[City2] = Read.derived -} - -val join = - sql""" - select c.name, c.code, - k.name, k.district - from country c - left outer join city k - on c.capital = k.id - """.query[(Country, Option[City2])] -``` - -Some examples, filtered for size. - -```scala mdoc -{ - val y = xa.yolo - import y.* - join.stream.filter(_._1.name.startsWith("United")).quick.unsafeRunSync() -} -``` - -### How do I log the SQL produced for my query after interpolation? - -As of **doobie** 0.4 there is a reasonable solution to the logging/instrumentation question. See [Chapter 10](10-Logging.html) for more details. - -### Why is there no `Get` or `Put` for `SQLXML`? - -There are a lot of ways to handle `SQLXML` so there is no pre-defined strategy, but here is one that maps `scala.xml.Elem` to `SQLXML` via streaming. - -```scala mdoc:silent -import doobie.enumerated.JdbcType.Other -import java.sql.SQLXML -import scala.xml.{ XML, Elem } - -implicit val XmlMeta: Meta[Elem] = - Meta.Advanced.one[Elem]( - Other, - NonEmptyList.of("xml"), - (rs, n) => XML.load(rs.getObject(n).asInstanceOf[SQLXML].getBinaryStream), - (ps, n, e) => { - val sqlXml = ps.getConnection.createSQLXML - val osw = new java.io.OutputStreamWriter(sqlXml.setBinaryStream) - XML.write(osw, e, "UTF-8", false, null) - osw.close - ps.setObject(n, sqlXml) - }, - (_, _, _) => sys.error("update not supported, sorry") - ) -``` - -## How do I set the chunk size for streaming results? - -By default streams constructed with the `sql` interpolator are fetched `Query.DefaultChunkSize` rows at a time (currently 512). If you wish to change this chunk size you can use `streamWithChunkSize` for queries, and `withGeneratedKeysWithChunkSize` for updates that return results. - -## My Postgres domains are all type checking as DISTINCT! How can I get my Yolo tests to pass? - -Domains with check constraints will type check as DISTINCT. For Doobie later than 0.4.4, in order to get the type checks to pass, you can define a `Meta` of with target type Distinct and `xmap` that instances. For example, - -```scala mdoc:silent -import cats.data.NonEmptyList -import doobie.* -import doobie.enumerated.JdbcType - -object distinct { - - def string(name: String): Meta[String] = - Meta.Advanced.many( - NonEmptyList.of(JdbcType.Distinct, JdbcType.VarChar), - NonEmptyList.of(name), - _ getString _, - _.setString(_, _), - _.updateString(_, _) - ) -} - -case class NonEmptyString(value: String) - -// If the domain for NonEmptyStrings is nes -implicit val nesMeta: Meta[NonEmptyString] = { - distinct.string("nes").imap(NonEmptyString.apply)(_.value) -} -``` diff --git a/modules/example/src/main/scala/example/CallableStatementExample.scala b/modules/example/src/main/scala/example/CallableStatementExample.scala deleted file mode 100644 index 352a7d1b1..000000000 --- a/modules/example/src/main/scala/example/CallableStatementExample.scala +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.effect.syntax.monadCancel.* -import cats.syntax.traverse.* -import doobie.FCS -import doobie.FRS -import doobie.HC -import doobie.HRS -import doobie.HS -import doobie.enumerated.JdbcType.Other -import doobie.free.connection.ConnectionIO -import doobie.syntax.connectionio.* -import doobie.util.transactor.Transactor - -object CallableStatementExample extends IOApp.Simple { - - // cant be in world.sql as H2 does not support SQL functions - def createFunc: ConnectionIO[Int] = { - val sql = """ - CREATE OR REPLACE FUNCTION getCountries(n integer, OUT c refcursor) AS ' - BEGIN - OPEN c FOR SELECT name FROM country LIMIT n; - END; - ' LANGUAGE plpgsql; - """ - HC.createStatement(HS.executeUpdate(sql)) - } - - def names(limit: Int): ConnectionIO[List[String]] = - HC.prepareCall("{ call getCountries(?, ?) }") { - for { - _ <- FCS.setInt(1, limit) - _ <- FCS.registerOutParameter(2, Other.toInt) - _ <- FCS.execute - ns <- FCS.getObject(2).map(_.asInstanceOf[java.sql.ResultSet]).bracket { rs => - FCS.embed(rs, HRS.list[String]) - }(FCS.embed(_, FRS.close)) - } yield ns - } - - val xa: Transactor[IO] = - Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - def run: IO[Unit] = - for { - _ <- createFunc.transact(xa) - ns <- names(10).transact(xa) - _ <- ns.traverse(s => IO(println(s))) - } yield () - -} diff --git a/modules/example/src/main/scala/example/Coproduct.scala b/modules/example/src/main/scala/example/Coproduct.scala deleted file mode 100644 index 088f0c0ea..000000000 --- a/modules/example/src/main/scala/example/Coproduct.scala +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.InjectK -import cats.data.EitherK -import cats.data.Kleisli -import cats.effect.IO -import cats.effect.IOApp -import cats.free.Free -import cats.syntax.traverse.* -import cats.~> -import doobie.free.KleisliInterpreter -import doobie.free.connection.ConnectionOp -import doobie.syntax.string.* -import doobie.util.transactor.Transactor - -import java.sql.Connection -import scala.io.StdIn - -object Coproduct extends IOApp.Simple { - - // This is merged in cats - implicit class MoreFreeOps[F[_], A](fa: Free[F, A]) { - def inject[G[_]](implicit ev: InjectK[F, G]): Free[G, A] = - fa.compile { - new (F ~> G) { - def apply[T](fa: F[T]) = ev.inj(fa) - } - } - } - - // This is kind of eh … we need to interpret into Kleisli so this is helpful - implicit class MoreNaturalTransformationOps[F[_], G[_]](nat: F ~> G) { - def liftK[E] = new (F ~> Kleisli[G, E, *]) { - def apply[A](fa: F[A]) = Kleisli(_ => nat(fa)) - } - } - - // A console algebra - sealed trait ConsoleOp[A] - case object ReadLn extends ConsoleOp[String] - final case class PrintLn(s: String) extends ConsoleOp[Unit] - - // A module of ConsoleOp constructors, parameterized over a coproduct - class ConsoleOps[F[_]](implicit ev: InjectK[ConsoleOp, F]) { - val readLn = Free.liftInject[F](ReadLn) - def printLn(s: String) = Free.liftInject[F](PrintLn(s)) - } - object ConsoleOps { - implicit def instance[F[_]](implicit ev: InjectK[ConsoleOp, F]): ConsoleOps[F] = new ConsoleOps - } - - // An interpreter into IO - val consoleInterp = - new (ConsoleOp ~> IO) { - def apply[A](fa: ConsoleOp[A]) = - fa match { - case ReadLn => IO(StdIn.readLine()) - case PrintLn(s) => IO(Console.println(s)) - } - } - - // A module of ConnectionOp programs, parameterized over a coproduct. The trick here is that these - // are domain-specific operations that are injected as programs, not as constructors (which would - // work but is too low-level to be useful). - class ConnectionOps[F[_]](implicit ev: InjectK[ConnectionOp, F]) { - def select(pat: String): Free[F, List[String]] = - sql"select name from country where name like $pat".query[String].to[List].inject[F] - } - object ConnectionOps { - implicit def instance[F[_]](implicit ev: InjectK[ConnectionOp, F]): ConnectionOps[F] = new ConnectionOps - } - - // A program - def prog[F[_]](implicit ev1: ConsoleOps[F], ev2: ConnectionOps[F]): Free[F, Unit] = { - import ev1.* - import ev2.* - for { - _ <- printLn("Enter a pattern:") - pat <- readLn - ns <- select(pat) - _ <- ns.traverse(printLn) - } yield () - } - - // Our coproduct - type Cop[A] = EitherK[ConsoleOp, ConnectionOp, A] - - // Our interpreter must be parameterized over a connection so we can add transaction boundaries - // before and after. - val interp: Cop ~> Kleisli[IO, Connection, *] = { - consoleInterp.liftK[Connection].or(KleisliInterpreter[IO].ConnectionInterpreter) - } - - // Our interpreted program - val iprog: Kleisli[IO, Connection, Unit] = prog[Cop].foldMap(interp) - - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - // Exec it! - def run: IO[Unit] = - xa.exec.apply(iprog) - - // Enter a pattern: - // U% - // United Arab Emirates - // United Kingdom - // Uganda - // Ukraine - // Uruguay - // Uzbekistan - // United States - // United States Minor Outlying Islands - -} diff --git a/modules/example/src/main/scala/example/Dynamic.scala b/modules/example/src/main/scala/example/Dynamic.scala deleted file mode 100644 index 8c3e26006..000000000 --- a/modules/example/src/main/scala/example/Dynamic.scala +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.syntax.monad.* -import cats.syntax.traverse.* -import doobie.FRS -import doobie.HPS -import doobie.HRS -import doobie.free.connection.ConnectionIO -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.resultset.ResultSetIO -import doobie.syntax.connectionio.* -import doobie.syntax.string.* -import doobie.util.transactor.Transactor - -// Sketch of a program to run a query and get the output without knowing how many columns will -// come back, or their types. This can be useful for building query tools, etc. -object Dynamic extends IOApp.Simple { - - type Headers = List[String] - type Data = List[List[Object]] - - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - // Entry point. Run a query and print the results out. - def run: IO[Unit] = - connProg("U%").transact(xa).flatMap { case (headers, data) => - for { - _ <- IO(println(headers)) - _ <- data.traverse(d => IO(println(d))) - } yield () - } - - // Construct a parameterized query and execute it with a custom program. - def connProg(pattern: String): ConnectionIO[(Headers, Data)] = - sql"select code, name, population from country where code like $pattern".execWith(exec) - - // Exec our PreparedStatement, examining metadata to figure out column count. - def exec: PreparedStatementIO[(Headers, Data)] = - for { - md <- HPS.getMetaData // lots of useful info here - cols = (1 to md.getColumnCount).toList - data <- HPS.executeQuery(readAll(cols)) - } yield (cols.map(md.getColumnName), data) - - // Read the specified columns from the resultset. - def readAll(cols: List[Int]): ResultSetIO[Data] = - readOne(cols).whileM[List](HRS.next) - - // Take a list of column offsets and read a parallel list of values. - def readOne(cols: List[Int]): ResultSetIO[List[Object]] = - cols.traverse(FRS.getObject) // always works - -} diff --git a/modules/example/src/main/scala/example/FirstExample.scala b/modules/example/src/main/scala/example/FirstExample.scala index 80e9b544b..b46797c1a 100644 --- a/modules/example/src/main/scala/example/FirstExample.scala +++ b/modules/example/src/main/scala/example/FirstExample.scala @@ -8,9 +8,10 @@ package example import cats.Show import cats.effect.IO import cats.effect.IOApp +import cats.effect.kernel.Resource import cats.syntax.functor.* import cats.syntax.show.* -import doobie.FC +import cats.syntax.traverse.* import doobie.free.connection.ConnectionIO import doobie.syntax.connectionio.* import doobie.syntax.string.* @@ -20,7 +21,8 @@ import doobie.util.query.Query0 import doobie.util.transactor.Transactor import doobie.util.update.Update import doobie.util.update.Update0 -import fs2.Stream + +import java.sql.DriverManager // Example lifted from slick object FirstExample extends IOApp.Simple { @@ -66,30 +68,22 @@ object FirstExample extends IOApp.Simple { _ <- putStrLn(show"Inserted $ns suppliers and $nc coffees.") // Select and stream the coffees to stdout - _ <- DAO.allCoffees.evalMap(c => putStrLn(show"$c")).compile.drain + coffees <- DAO.allCoffees + _ <- coffees.traverse(c => putStrLn(show"$c")) // Get the names and supplier names for all coffees costing less than $9.00, - // again streamed directly to stdout - _ <- DAO.coffeesLessThan(9.0).evalMap(p => putStrLn(show"$p")).compile.drain - - // Same thing, but read into a list this time - l <- DAO.coffeesLessThan(9.0).compile.toList + l <- DAO.coffeesLessThan(9.0) _ <- putStrLn(l.toString) - - // Read into a vector this time, with some stream processing - v <- DAO.coffeesLessThan(9.0).take(2).map(p => p._1 + "*" + p._2).compile.toVector - _ <- putStrLn(v.toString) - } yield "All done!" // Entry point. def run: IO[Unit] = { - val db = Transactor.fromDriverManager[IO]( - "org.h2.Driver", - "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", - "sa", - "", - ) + val db = { + val conn = Resource.fromAutoCloseable(IO.blocking { + DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", "") + }) + Transactor.catsEffect((), conn) + } for { a <- examples.transact(db).attempt _ <- IO(println(a)) @@ -99,8 +93,8 @@ object FirstExample extends IOApp.Simple { /** DAO module provides ConnectionIO constructors for end users. */ object DAO { - def coffeesLessThan(price: Double): Stream[ConnectionIO, (String, String)] = - Queries.coffeesLessThan(price).stream + def coffeesLessThan(price: Double): ConnectionIO[List[(String, String)]] = + Queries.coffeesLessThan(price).to(List) def insertSuppliers(ss: List[Supplier]): ConnectionIO[Int] = Queries.insertSupplier.updateMany(ss) // bulk insert (!) @@ -108,8 +102,8 @@ object FirstExample extends IOApp.Simple { def insertCoffees(cs: List[Coffee]): ConnectionIO[Int] = Queries.insertCoffee.updateMany(cs) - def allCoffees: Stream[ConnectionIO, Coffee] = - Queries.allCoffees.stream + def allCoffees: ConnectionIO[List[Coffee]] = + Queries.allCoffees.to(List) def create: ConnectionIO[Unit] = Queries.create.run.void @@ -160,6 +154,6 @@ object FirstExample extends IOApp.Simple { // Lifted println def putStrLn(s: => String): ConnectionIO[Unit] = - FC.delay(println(s)) + ConnectionIO.delay(println(s)) } diff --git a/modules/example/src/main/scala/example/FragmentExample.scala b/modules/example/src/main/scala/example/FragmentExample.scala index 0f7c3b5ef..ef1b7f7e6 100644 --- a/modules/example/src/main/scala/example/FragmentExample.scala +++ b/modules/example/src/main/scala/example/FragmentExample.scala @@ -6,6 +6,7 @@ package example import cats.effect.IO import cats.effect.IOApp +import cats.effect.kernel.Resource import cats.syntax.list.* import cats.syntax.traverse.* import doobie.syntax.string.* @@ -13,6 +14,8 @@ import doobie.util.Read import doobie.util.fragment.Fragment import doobie.util.transactor.Transactor +import java.sql.DriverManager + object FragmentExample extends IOApp.Simple { // Import some convenience constructors. @@ -46,12 +49,12 @@ object FragmentExample extends IOApp.Simple { } // Our world database - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) + val xa = { + val conn = Resource.fromAutoCloseable(IO.blocking { + DriverManager.getConnection("jdbc:postgresql:world", "postgres", "password") + }) + Transactor.catsEffect((), conn) + } // Some quick examples. val prog = List( @@ -61,12 +64,10 @@ object FragmentExample extends IOApp.Simple { select(Some("U%"), None, List("USA", "GBR", "FRA"), 10), select(Some("U%"), Some(100000000), List("USA", "GBR", "FRA"), 10), ).traverse { q => - val y = xa.yolo - import y.* - q.check *> q.quick + q.to[List] } def run: IO[Unit] = - prog.void + xa.run(prog).void } diff --git a/modules/example/src/main/scala/example/FreeUsage.scala b/modules/example/src/main/scala/example/FreeUsage.scala deleted file mode 100644 index 2c018a72a..000000000 --- a/modules/example/src/main/scala/example/FreeUsage.scala +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.effect.syntax.monadCancel.* -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.traverse.* -import doobie.FC -import doobie.FPS -import doobie.FRS -import doobie.free.connection.ConnectionIO -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.resultset.ResultSetIO -import doobie.util.transactor.Transactor - -import java.io.File - -// JDBC program using the low-level API -object FreeUsage extends IOApp.Simple { - - final case class CountryCode(code: String) - - def run: IO[Unit] = { - val db = Transactor.fromDriverManager[IO]( - "org.h2.Driver", - "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", - "sa", - "", - ) - db.trans.apply(examples.void) - } - - def examples: ConnectionIO[String] = - for { - _ <- FC.delay(println("Loading database...")) - _ <- loadDatabase(new File("example/world.sql")) - s <- speakerQuery("English", 10) - _ <- s.traverse(a => FC.delay(println(a))) - } yield "Ok" - - def loadDatabase(f: File): ConnectionIO[Boolean] = - FC.prepareStatement("RUNSCRIPT FROM ? CHARSET 'UTF-8'").bracket { ps => - FC.embed(ps, FPS.setString(1, f.getName) *> FPS.execute) - }(FC.embed(_, FPS.close)) - - def speakerQuery(s: String, p: Double): ConnectionIO[List[CountryCode]] = - FC.prepareStatement("SELECT COUNTRYCODE FROM COUNTRYLANGUAGE WHERE LANGUAGE = ? AND PERCENTAGE > ?").bracket { ps => - FC.embed(ps, speakerPS(s, p)) - }(FC.embed(_, FPS.close)) - - def speakerPS(s: String, p: Double): PreparedStatementIO[List[CountryCode]] = - for { - _ <- FPS.setString(1, s) - _ <- FPS.setDouble(2, p) - l <- FPS.executeQuery.bracket { rs => - FPS.embed(rs, unroll(FRS.getString(1).map(CountryCode(_)))) - }(FPS.embed(_, FRS.close)) - } yield l - - @SuppressWarnings(Array("org.wartremover.warts.Recursion")) - def unroll[A](a: ResultSetIO[A]): ResultSetIO[List[A]] = { - def unroll0(as: List[A]): ResultSetIO[List[A]] = - FRS.next >>= { - case false => as.pure[ResultSetIO] - case true => a >>= { a => unroll0(a :: as) } - } - unroll0(Nil).map(_.reverse) - } - -} diff --git a/modules/example/src/main/scala/example/GenericStream.scala b/modules/example/src/main/scala/example/GenericStream.scala deleted file mode 100644 index 1da835f62..000000000 --- a/modules/example/src/main/scala/example/GenericStream.scala +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.ExitCode -import cats.effect.IO -import cats.effect.IOApp -import cats.syntax.applicative.* -import cats.syntax.apply.* -import doobie.FC -import doobie.FPS -import doobie.FRS -import doobie.free.connection.ConnectionIO -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.resultset.ResultSetIO -import doobie.syntax.stream.* -import doobie.util.stream.repeatEvalChunks -import doobie.util.transactor.Transactor -import fs2.Stream -import fs2.Stream.bracket -import fs2.Stream.eval - -import java.sql.PreparedStatement -import java.sql.ResultSet - -/** - * From a user question on Gitter, how can we have an equivalent to `Stream[A]` - * that constructs a stream of untyped maps. - */ -object GenericStream extends IOApp { - - type Row = Map[String, Any] - - // This escapes to raw JDBC for efficiency. - @SuppressWarnings(Array( - "org.wartremover.warts.Var", - "org.wartremover.warts.While", - "org.wartremover.warts.NonUnitStatements", - )) - def getNextChunkGeneric(chunkSize: Int): ResultSetIO[Seq[Row]] = - FRS.raw { rs => - val md = rs.getMetaData - val ks = (1 to md.getColumnCount).map(md.getColumnLabel).toList - var n = chunkSize - val b = Vector.newBuilder[Row] - while (n > 0 && rs.next) { - val mb = Map.newBuilder[String, Any] - ks.foreach(k => mb += (k -> rs.getObject(k))) - b += mb.result() - n -= 1 - } - b.result() - } - - def liftProcessGeneric( - chunkSize: Int, - create: ConnectionIO[PreparedStatement], - prep: PreparedStatementIO[Unit], - exec: PreparedStatementIO[ResultSet], - ): Stream[ConnectionIO, Row] = { - - def prepared(ps: PreparedStatement): Stream[ConnectionIO, PreparedStatement] = - eval[ConnectionIO, PreparedStatement] { - val fs = FPS.setFetchSize(chunkSize) - FC.embed(ps, fs *> prep).map(_ => ps) - } - - def unrolled(rs: ResultSet): Stream[ConnectionIO, Row] = - repeatEvalChunks(FC.embed(rs, getNextChunkGeneric(chunkSize))) - - val preparedStatement: Stream[ConnectionIO, PreparedStatement] = - bracket(create)(FC.embed(_, FPS.close)).flatMap(prepared) - - def results(ps: PreparedStatement): Stream[ConnectionIO, Row] = - bracket(FC.embed(ps, exec))(FC.embed(_, FRS.close)).flatMap(unrolled) - - preparedStatement.flatMap(results) - - } - - def processGeneric(sql: String, prep: PreparedStatementIO[Unit], chunkSize: Int): Stream[ConnectionIO, Row] = - liftProcessGeneric(chunkSize, FC.prepareStatement(sql), prep, FPS.executeQuery) - - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - def run(args: List[String]): IO[ExitCode] = - args match { - case sql :: Nil => processGeneric(sql, ().pure[PreparedStatementIO], 100).transact(xa).evalMap(m => - IO(Console.println(m)), - ).compile.drain.as(ExitCode.Success) - case _ => IO(Console.println("expected on arg, a query")).as(ExitCode.Error) - } - - // > runMain example.GenericStream "select * from city limit 10" - // Map(name -> Kabul, population -> 1780000, id -> 1, district -> Kabol, countrycode -> AFG) - // Map(name -> Qandahar, population -> 237500, id -> 2, district -> Qandahar, countrycode -> AFG) - // Map(name -> Herat, population -> 186800, id -> 3, district -> Herat, countrycode -> AFG) - // Map(name -> Mazar-e-Sharif, population -> 127800, id -> 4, district -> Balkh, countrycode -> AFG) - // Map(name -> Amsterdam, population -> 731200, id -> 5, district -> Noord-Holland, countrycode -> NLD) - // Map(name -> Rotterdam, population -> 593321, id -> 6, district -> Zuid-Holland, countrycode -> NLD) - // Map(name -> Haag, population -> 440900, id -> 7, district -> Zuid-Holland, countrycode -> NLD) - // Map(name -> Utrecht, population -> 234323, id -> 8, district -> Utrecht, countrycode -> NLD) - // Map(name -> Eindhoven, population -> 201843, id -> 9, district -> Noord-Brabant, countrycode -> NLD) - // Map(name -> Tilburg, population -> 193238, id -> 10, district -> Noord-Brabant, countrycode -> NLD) - -} diff --git a/modules/example/src/main/scala/example/HiUsage.scala b/modules/example/src/main/scala/example/HiUsage.scala deleted file mode 100644 index c7923ef93..000000000 --- a/modules/example/src/main/scala/example/HiUsage.scala +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.Show -import cats.effect.IO -import cats.effect.IOApp -import cats.syntax.show.* -import doobie.FC -import doobie.free.connection.ConnectionIO -import doobie.syntax.connectionio.* -import doobie.syntax.string.* -import doobie.util.Read -import doobie.util.transactor.Transactor -import fs2.Stream - -// JDBC program using the high-level API -object HiUsage extends IOApp.Simple { - - // A very simple data type we will read - final case class CountryCode(code: Option[String]) - object CountryCode { - implicit val show: Show[CountryCode] = Show.fromToString - - implicit val read: Read[CountryCode] = Read.derived - } - - // Program entry point - def run: IO[Unit] = { - val db = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - example.transact(db) - } - - // An example action. Streams results to stdout - lazy val example: ConnectionIO[Unit] = - speakerQuery("English", 10).evalMap(c => FC.delay(println(show"~> $c"))).compile.drain - - // Construct an action to find countries where more than `pct` of the population speaks `lang`. - // The result is a fs2.Stream that can be further manipulated by the caller. - def speakerQuery(lang: String, pct: Double): Stream[ConnectionIO, CountryCode] = - sql"SELECT COUNTRYCODE FROM COUNTRYLANGUAGE WHERE LANGUAGE = $lang AND PERCENTAGE > $pct".query[CountryCode].stream - -} diff --git a/modules/example/src/main/scala/example/HikariExample.scala b/modules/example/src/main/scala/example/HikariExample.scala deleted file mode 100644 index 98c04d00e..000000000 --- a/modules/example/src/main/scala/example/HikariExample.scala +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.effect.Resource -import doobie.hikari.* -import doobie.syntax.connectionio.* -import doobie.util.ExecutionContexts - -object HikariExample extends IOApp.Simple { - - // Typically you construct a transactor this way, using lifetime-managed thread pools. - val transactor: Resource[IO, HikariTransactor[IO]] = - for { - ce <- ExecutionContexts.fixedThreadPool[IO](32) - xa <- HikariTransactor.newHikariTransactor[IO]( - "org.h2.Driver", - "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", - "sa", - "", - ce, - ) - } yield xa - - def run: IO[Unit] = - transactor.use { xa => - FirstExample.examples.transact(xa).void - } - -} diff --git a/modules/example/src/main/scala/example/LoggingExample.scala b/modules/example/src/main/scala/example/LoggingExample.scala deleted file mode 100644 index aca9ce62d..000000000 --- a/modules/example/src/main/scala/example/LoggingExample.scala +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -// relies on streaming, so no cats for now -package example - -import cats.data.Kleisli -import cats.effect.IO -import cats.effect.IOApp -import cats.effect.IOLocal -import doobie.free.KleisliInterpreter -import doobie.syntax.connectionio.* -import doobie.syntax.string.* -import doobie.util.transactor.Transactor - -import java.sql.Connection - -object LoggingExample extends IOApp.Simple { - - case class User(name: String) - - private val db = Transactor.fromDriverManager[IO]( - "org.h2.Driver", - "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", - "sa", - "", - ) - - def run: IO[Unit] = { - val currentUser = IOLocal[Option[User]](None).unsafeRunSync()(runtime) - - def logSQL[T](sql: String, result: Kleisli[IO, Connection, T]): Kleisli[IO, Connection, T] = { - result.tapWithF { case (_, t) => - for { - user <- currentUser.get - _ <- IO.delay { - println(s"user $user; sql: '$sql'") - } - } yield t - } - } - - val i = KleisliInterpreter[IO] - val LoggingConnectionInterpreter = new i.ConnectionInterpreter { - override def prepareStatement(a: String) = logSQL(a, super.prepareStatement(a)) - } - - val loggingDb = db.copy(interpret0 = LoggingConnectionInterpreter) - - for { - _ <- currentUser.set(Some(User("a"))) - _ <- fr"SELECT 1".query[Int].unique.transact(loggingDb) - - _ <- currentUser.set(Some(User("b"))) - _ <- fr"SELECT 2".query[Int].unique.transact(loggingDb) - } yield () - } - -} diff --git a/modules/example/src/main/scala/example/OtherSchema.scala b/modules/example/src/main/scala/example/OtherSchema.scala index 9d88f4a28..790ce7fa3 100644 --- a/modules/example/src/main/scala/example/OtherSchema.scala +++ b/modules/example/src/main/scala/example/OtherSchema.scala @@ -7,12 +7,15 @@ package example import cats.data.NonEmptyList import cats.effect.IO import cats.effect.IOApp +import cats.effect.kernel.Resource import doobie.enumerated.JdbcType import doobie.syntax.string.* import doobie.util.meta.Meta import doobie.util.transactor.Transactor import org.postgresql.util.* +import java.sql.DriverManager + /** * The normal string mapping doesn't work for enums defined in another schema. * Here we have @@ -55,25 +58,24 @@ object OtherSchema extends IOApp.Simple { def run: IO[Unit] = { // Some setup - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - val y = xa.yolo - import y.* + val xa = { + val conn = Resource.fromAutoCloseable(IO.blocking { + DriverManager.getConnection("jdbc:postgresql:world", "postgres", "password") + }) + Transactor.catsEffect((), conn) + } // Check as column value only val q1 = sql"SELECT 'INITIAL'::returns_data.return_status".query[ReturnStatus.Value] - val p1 = q1.check *> q1.unique.quick // Check as parameter too val q2 = sql"SELECT ${ReturnStatus.IN_PROGRESS}::returns_data.return_status".query[ReturnStatus.Value] - val p2 = q2.check *> q2.unique.quick - - (p1 *> p2) + val conn = for { + _ <- q1.unique + _ <- q2.unique + } yield () + xa.run(conn) } } diff --git a/modules/example/src/main/scala/example/PostgresCopyInCsv.scala b/modules/example/src/main/scala/example/PostgresCopyInCsv.scala deleted file mode 100644 index e810edee1..000000000 --- a/modules/example/src/main/scala/example/PostgresCopyInCsv.scala +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.show.* -import doobie.free.connection.ConnectionIO -import doobie.postgres.* -import doobie.postgres.free.copymanager.CopyManagerIO -import doobie.syntax.connectionio.* -import doobie.syntax.string.* -import doobie.util.transactor.Transactor -import fs2.* -import fs2.text.utf8 - -import java.io.ByteArrayInputStream -import java.io.InputStream -import java.nio.charset.StandardCharsets - -object PostgresCopyInCsv extends IOApp.Simple { - - def putStrLn(s: String): IO[Unit] = IO(println(s)) - - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql://localhost/postgres", - "postgres", - "super-secret", - ) - - val csv = """name,food - |piglet,haycorns - |eeyore,thistles - |pooh,honey - |tigger,extract of malt""".stripMargin - - // The postgres driver expects an InputStream containing the data to load - // We wrap this in IO because a BAIS allocated visible mutable state - val is: IO[InputStream] = IO.delay(new ByteArrayInputStream(csv.getBytes(StandardCharsets.UTF_8))).widen[InputStream] - - // We can also convert a Stream[F, Byte] into an input stream to pass to the pg driver - val byteStream = Stream.emit(csv).through(utf8.encode).covary[IO] - - // Create a temorary table to hold the input data - val createTable: ConnectionIO[Int] = sql"CREATE TEMP TABLE favorite_foods(name TEXT, food TEXT)".update.run - - def copyIn(is: InputStream): ConnectionIO[Long] = { - // construct a CopyManagerIO with the postgres extensions - // The structure of the sql expression itself is described in https://www.postgresql.org/docs/current/sql-copy.html - // Here we describe our input format as csv with a header and the standard delimiter - // The header line is ignored by postgres, column ordering comes from the table statement - val copyInIO: CopyManagerIO[Long] = - PFCM.copyIn("COPY favorite_foods(name, food) FROM STDIN WITH (FORMAT CSV, HEADER, DELIMITER ',')", is) - // Lift the CopyManagerIO into ConnectionIO so it can be transacted - PHC.pgGetCopyAPI(copyInIO) - } - - val simpleExample = - // Construct a copy from an InputStream - is.flatMap(is => (createTable >> copyIn(is)).transact(xa)) - .map(_.toString) - .flatMap(ct => putStrLn(show"loaded $ct from InputStream")) - - val fromByteStreamExample = - // Construct a copy by converting a Stream[IO, Byte] into an InputStream - io.toInputStreamResource(byteStream) - .use(is => (createTable >> copyIn(is)).transact(xa)) - .map(_.toString) - .flatMap(ct => putStrLn(show"loaded $ct from Stream[IO, Byte]")) - - def run: IO[Unit] = { - // Should print "loaded 4 from Stream[IO, Byte]" twice - simpleExample >> fromByteStreamExample - } - -} diff --git a/modules/example/src/main/scala/example/PostgresLargeObject.scala b/modules/example/src/main/scala/example/PostgresLargeObject.scala deleted file mode 100644 index 84c9f9e13..000000000 --- a/modules/example/src/main/scala/example/PostgresLargeObject.scala +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -// relies on whenM, etc. so no cats for now -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.syntax.show.* -import doobie.postgres.* -import doobie.postgres.free.largeobjectmanager.LargeObjectManagerIO -import doobie.syntax.connectionio.* -import doobie.util.transactor.Transactor - -import java.io.File - -/** - * Example of using the high-level Large Object API. See the Postgres JDBC - * driver doc and the source in doobie.contrib.postgresql for more information. - */ -object PostgresLargeObject extends IOApp.Simple { - - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - val prog: LargeObjectManagerIO[Long] = - for { - oid <- PHLOM.createLOFromFile(1024, new File("world.sql")) - _ <- PHLOM.createFileFromLO(1024, oid, new File("world2.sql")) - _ <- PHLOM.delete(oid) - } yield oid - - def run: IO[Unit] = - PHC.pgGetLargeObjectAPI(prog).transact(xa).flatMap { oid => - IO(Console.println(show"oid was $oid")) - } - -} diff --git a/modules/example/src/main/scala/example/PostgresNotify.scala b/modules/example/src/main/scala/example/PostgresNotify.scala deleted file mode 100644 index d947b8ef8..000000000 --- a/modules/example/src/main/scala/example/PostgresNotify.scala +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -// relies on streaming, so no cats for now -package example - -import cats.effect.* -import cats.syntax.apply.* -import cats.syntax.functor.* -import cats.syntax.show.* -import doobie.HC -import doobie.free.connection.ConnectionIO -import doobie.postgres.* -import doobie.syntax.stream.* -import doobie.syntax.string.* -import doobie.util.transactor.Transactor -import fs2.Stream -import org.postgresql.* - -import scala.concurrent.duration.* - -/** - * Example exposing PostgreSQL NOTIFY as a Process[ConnectionIO, - * PGNotification]. This will likely be provided as a standard service in - * doobie-postgres in a future version. To play with this program, run it and - * then in another window do: - * - * > psql -d world -U postgres -c "notify foo, 'abc'" - * - * to send a notification. The program will exit after reading five - * notifications. - */ -object PostgresNotify extends IOApp.Simple { - - /** A resource that listens on a channel and unlistens when we're done. */ - def channel(name: String): Resource[ConnectionIO, Unit] = - Resource.make(PHC.pgListen(name) *> HC.commit)(_ => PHC.pgUnlisten(name) *> HC.commit) - - /** - * Stream of PGNotifications on the specified channel, polling at the - * specified rate. Note that this stream, when run, will commit the current - * transaction. - */ - def notificationStream( - channelName: String, - pollingInterval: FiniteDuration, - ): Stream[IO, PGNotification] = { - val stream = Stream.resource(channel(channelName)) *> - Stream.eval(pgSleep(pollingInterval.toSeconds) *> PHC.pgGetNotifications <* HC.commit) - .flatMap(Stream.emits(_)) - stream.transact(xa) - } - - /** A transactor that knows how to connect to a PostgreSQL database. */ - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - /** - * Construct a stream of PGNotifications that prints to the console. Transform - * it to a runnable process using the transcactor above, and run it. - */ - def run: IO[Unit] = - notificationStream("foo", 1.second) - .map(n => show"${n.getPID} ${n.getName} ${n.getParameter}") - .take(5) - .evalMap(s => IO.delay(Console.println(s))).compile.drain - - private def pgSleep(seconds: Long) = fr"SELECT pg_sleep($seconds)".query[Unit].option.as(()) -} diff --git a/modules/example/src/main/scala/example/PostgresPoint.scala b/modules/example/src/main/scala/example/PostgresPoint.scala index b18bd360a..e0a5a609d 100644 --- a/modules/example/src/main/scala/example/PostgresPoint.scala +++ b/modules/example/src/main/scala/example/PostgresPoint.scala @@ -6,6 +6,7 @@ package example import cats.effect.IO import cats.effect.IOApp +import cats.effect.kernel.Resource import doobie.postgres.instances.geometric.* import doobie.syntax.connectionio.* import doobie.syntax.string.* @@ -14,14 +15,16 @@ import doobie.util.meta.Meta import doobie.util.transactor.Transactor import org.postgresql.geometric.PGpoint +import java.sql.DriverManager + object PostgresPoint extends IOApp.Simple { - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) + val xa = { + val conn = Resource.fromAutoCloseable(IO.blocking { + DriverManager.getConnection("jdbc:postgresql:world", "postgres", "password") + }) + Transactor.catsEffect((), conn) + } // A custom Point type with a Meta instance xmapped from the PostgreSQL native type (which // would be weird to use directly in a data model). Note that the presence of this `Meta` diff --git a/modules/example/src/main/scala/example/StreamToFile.scala b/modules/example/src/main/scala/example/StreamToFile.scala deleted file mode 100644 index c5b5fd9d0..000000000 --- a/modules/example/src/main/scala/example/StreamToFile.scala +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.effect.IO -import cats.effect.IOApp -import cats.syntax.show.* -import doobie.syntax.stream.* -import doobie.syntax.string.* -import doobie.util.transactor.Transactor -import fs2.io.file.Files -import fs2.io.file.Path -import fs2.text.utf8 - -object StreamToFile extends IOApp.Simple { - - val xa = Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - ) - - def run: IO[Unit] = - sql"select name, population from country" - .query[(String, Int)] - .stream - .map { case (n, p) => show"$n, $p" } - .intersperse("\n") - .through(utf8.encode) - .transact(xa) - .through(Files[IO].writeAll(Path("/tmp/out.txt"))) - .compile - .drain - -} diff --git a/modules/example/src/main/scala/example/StreamingCopy.scala b/modules/example/src/main/scala/example/StreamingCopy.scala deleted file mode 100644 index 2ec16f783..000000000 --- a/modules/example/src/main/scala/example/StreamingCopy.scala +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package example - -import cats.data.* -import cats.effect.* -import cats.syntax.applicativeError.* -import cats.syntax.apply.* -import cats.syntax.functor.* -import cats.syntax.show.* -import doobie.FC -import doobie.HC -import doobie.free.connection.ConnectionIO -import doobie.syntax.connectionio.* -import doobie.syntax.stream.* -import doobie.syntax.string.* -import doobie.util.Read -import doobie.util.transactor.Transactor -import fs2.Stream - -import java.sql.Connection -import scala.util.control.NonFatal - -/** - * Example of resource-safe transactional database-to-database copy with fs2. If - * you induce failures on either side (by putting a typo in the `read` or - * `write` statements) both transactions will roll back. - */ -object StreamingCopy extends IOApp.Simple { - - /** - * Cross-transactor streaming when the `source` and `sink` have the same - * schema. - */ - def fuseMap[F[_], A, B]( - source: Stream[ConnectionIO, A], - sink: A => ConnectionIO[B], - )( - sourceXA: Transactor[F], - sinkXA: Transactor[F], - )( - implicit ev: MonadCancelThrow[F], - ): Stream[F, B] = - fuseMapGeneric(source, identity[A], sink)(sourceXA, sinkXA) - - /** - * Stream from `source` through `sink`, where source and sink run on distinct - * transactors. To do this we have to wrap one transactor around the other. - * The source output and sink input types can differ. This enables data - * transformations involving potentially different database schemas. - */ - def fuseMapGeneric[F[_], A, B, C]( - source: Stream[ConnectionIO, A], - sourceToSink: A => B, - sink: B => ConnectionIO[C], - )( - sourceXA: Transactor[F], - sinkXA: Transactor[F], - )( - implicit ev: MonadCancelThrow[F], - ): Stream[F, C] = { - - // Interpret a ConnectionIO into a Kleisli arrow for F via the sink interpreter. - def interpS[T](f: ConnectionIO[T]): Connection => F[T] = - f.foldMap(sinkXA.interpret).run - - // Open a connection in `F` via the sink transactor. Need patmat due to the existential. - val conn: Resource[F, Connection] = - sinkXA match { case xa => xa.connect(xa.kernel) } - - // Given a Connection we can construct the stream we want. - def mkStream(c: Connection): Stream[F, C] = { - - // Now we can interpret a ConnectionIO into a Stream of F via the sink interpreter. - def evalS(f: ConnectionIO[?]): Stream[F, Nothing] = - Stream.eval(interpS(f)(c)).drain - - // And can thus lift all the sink operations into Stream of F - val sinkʹ = (a: A) => evalS(sink(sourceToSink(a))) - val before = evalS(sinkXA.strategy.before) - val after = evalS(sinkXA.strategy.after) - def oops(t: Throwable) = evalS(sinkXA.strategy.oops <* FC.raiseError(t)) - - // And construct our final stream. - (before ++ source.transact(sourceXA).flatMap(sinkʹ) ++ after).onError { - case NonFatal(e) => oops(e) - } - - } - - // And we're done! - Stream.resource(conn).flatMap(mkStream) - - } - - // Everything below is code to demonstrate the combinator above. - - /** Prepend a ConnectionIO program with a log message. */ - def printBefore(tag: String, s: String): ConnectionIO[Unit] => ConnectionIO[Unit] = - HC.delay(Console.println(s"$tag: $s")) <* _ - - /** Derive a new transactor that logs stuff. */ - def addLogging[F[_]](name: String)(xa: Transactor[F]): Transactor[F] = { - import Transactor.* // bring the lenses into scope - val update: State[Transactor[F], Unit] = - for { - _ <- before %= printBefore(name, "before - setting up the connection") - _ <- after %= printBefore(name, "after - committing") - _ <- oops %= printBefore(name, "oops - rolling back") - _ <- always %= printBefore(name, "always - closing") - } yield () - update.runS(xa).value - } - - // A data type to move. - final case class City(id: Int, name: String, countrycode: String, district: String, population: Int) - object City { - implicit val read: Read[City] = Read.derived - } - - // A producer of cities, to be run on database 1 - def read: Stream[ConnectionIO, City] = - sql""" - SELECT id, name, countrycode, district, population - FROM city - WHERE name like 'X%' - """.query[City].stream - - // A consumer of cities, to be run on database 2 - @SuppressWarnings(Array("org.wartremover.warts.ToString")) - def write(c: City): ConnectionIO[Unit] = - printBefore("write", c.toString)( - sql""" - INSERT INTO city (id, name, countrycode, district, population) - VALUES (${c.id}, ${c.name}, ${c.countrycode}, ${c.district}, ${c.population}) - """.update.run.void, - ) - - /** - * Table creation for our destination DB. We assume the source is populated. - */ - val ddl: ConnectionIO[Unit] = - sql""" - CREATE TABLE IF NOT EXISTS city ( - id integer NOT NULL, - name varchar NOT NULL, - countrycode character(3) NOT NULL, - district varchar NOT NULL, - population integer NOT NULL - ) - """.update.run.void - - // A postges transactor for our source. We assume the WORLD database is set up already. - val pg = addLogging("Postgres")(Transactor.fromDriverManager[IO]( - "org.postgresql.Driver", - "jdbc:postgresql:world", - "postgres", - "password", - )) - - // An h2 transactor for our sink. - val h2 = addLogging("H2") { - val xa = Transactor.fromDriverManager[IO]( - "org.h2.Driver", - "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", - "sa", - "", - ) - Transactor.before.modify(xa, _ *> ddl) // Run our DDL on every connection - } - - // Our main program - def run: IO[Unit] = - for { - _ <- fuseMap(read, write)(pg, h2).compile.drain // do the copy with fuseMap - n <- sql"select count(*) from city".query[Int].unique.transact(h2) - _ <- IO(Console.println(show"Copied $n cities!")) - } yield () - -} diff --git a/modules/free/src/main/scala/doobie/free/blob.scala b/modules/free/src/main/scala/doobie/free/blob.scala deleted file mode 100644 index ce3d56d58..000000000 --- a/modules/free/src/main/scala/doobie/free/blob.scala +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.OutputStream -import java.sql.Blob -import scala.concurrent.duration.FiniteDuration - -object blob { module => - - // Algebra of operations for Blob. Each accepts a visitor as an alternative to pattern-matching. - sealed trait BlobOp[A] { - def visit[F[_]](v: BlobOp.Visitor[F]): F[A] - } - - // Free monad over BlobOp. - type BlobIO[A] = FF[BlobOp, A] - - // Module of instances and constructors of BlobOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object BlobOp { - - // Given a Blob we can embed a BlobIO program in any algebra that understands embedding. - implicit val BlobOpEmbeddable: Embeddable[BlobOp, Blob] = - new Embeddable[BlobOp, Blob] { - def embed[A](j: Blob, fa: FF[BlobOp, A]) = Embedded.Blob(j, fa) - } - - // Interface for a natural transformation BlobOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (BlobOp ~> F) { - final def apply[A](fa: BlobOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: Blob => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: BlobIO[A])(f: Throwable => BlobIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: BlobIO[A])(fb: BlobIO[B]): F[B] - def uncancelable[A](body: Poll[BlobIO] => BlobIO[A]): F[A] - def poll[A](poll: Any, fa: BlobIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: BlobIO[A], fin: BlobIO[Unit]): F[A] - - // Blob - def free: F[Unit] - def getBinaryStream: F[InputStream] - def getBinaryStream(a: Long, b: Long): F[InputStream] - def getBytes(a: Long, b: Int): F[Array[Byte]] - def length: F[Long] - def position(a: Array[Byte], b: Long): F[Long] - def position(a: Blob, b: Long): F[Long] - def setBinaryStream(a: Long): F[OutputStream] - def setBytes(a: Long, b: Array[Byte]): F[Int] - def setBytes(a: Long, b: Array[Byte], c: Int, d: Int): F[Int] - def truncate(a: Long): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: Blob => A) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: BlobIO[A], f: Throwable => BlobIO[A]) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends BlobOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends BlobOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: BlobIO[A], fb: BlobIO[B]) extends BlobOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[BlobIO] => BlobIO[A]) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: BlobIO[A]) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends BlobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: BlobIO[A], fin: BlobIO[Unit]) extends BlobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // Blob-specific operations. - case object Free extends BlobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.free - } - case object GetBinaryStream extends BlobOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getBinaryStream - } - final case class GetBinaryStream1(a: Long, b: Long) extends BlobOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getBinaryStream(a, b) - } - final case class GetBytes(a: Long, b: Int) extends BlobOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.getBytes(a, b) - } - case object Length extends BlobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.length - } - final case class Position(a: Array[Byte], b: Long) extends BlobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.position(a, b) - } - final case class Position1(a: Blob, b: Long) extends BlobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.position(a, b) - } - final case class SetBinaryStream(a: Long) extends BlobOp[OutputStream] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a) - } - final case class SetBytes(a: Long, b: Array[Byte]) extends BlobOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.setBytes(a, b) - } - final case class SetBytes1(a: Long, b: Array[Byte], c: Int, d: Int) extends BlobOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.setBytes(a, b, c, d) - } - final case class Truncate(a: Long) extends BlobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.truncate(a) - } - - } - import BlobOp.* - - // Smart constructors for operations common to all algebras. - val unit: BlobIO[Unit] = FF.pure[BlobOp, Unit](()) - def pure[A](a: A): BlobIO[A] = FF.pure[BlobOp, A](a) - def raw[A](f: Blob => A): BlobIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[BlobOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): BlobIO[A] = FF.liftF[BlobOp, A](RaiseError(err)) - def handleErrorWith[A](fa: BlobIO[A])(f: Throwable => BlobIO[A]): BlobIO[A] = - FF.liftF[BlobOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[BlobOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[BlobOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[BlobOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[BlobOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: BlobIO[A])(fb: BlobIO[B]) = FF.liftF[BlobOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[BlobIO] => BlobIO[A]) = FF.liftF[BlobOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[BlobIO] { - def apply[A](fa: BlobIO[A]) = FF.liftF[BlobOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[BlobOp, Unit](Canceled) - def onCancel[A](fa: BlobIO[A], fin: BlobIO[Unit]) = FF.liftF[BlobOp, A](OnCancel(fa, fin)) - - // Smart constructors for Blob-specific operations. - val free: BlobIO[Unit] = FF.liftF(Free) - val getBinaryStream: BlobIO[InputStream] = FF.liftF(GetBinaryStream) - def getBinaryStream(a: Long, b: Long): BlobIO[InputStream] = FF.liftF(GetBinaryStream1(a, b)) - def getBytes(a: Long, b: Int): BlobIO[Array[Byte]] = FF.liftF(GetBytes(a, b)) - val length: BlobIO[Long] = FF.liftF(Length) - def position(a: Array[Byte], b: Long): BlobIO[Long] = FF.liftF(Position(a, b)) - def position(a: Blob, b: Long): BlobIO[Long] = FF.liftF(Position1(a, b)) - def setBinaryStream(a: Long): BlobIO[OutputStream] = FF.liftF(SetBinaryStream(a)) - def setBytes(a: Long, b: Array[Byte]): BlobIO[Int] = FF.liftF(SetBytes(a, b)) - def setBytes(a: Long, b: Array[Byte], c: Int, d: Int): BlobIO[Int] = FF.liftF(SetBytes1(a, b, c, d)) - def truncate(a: Long): BlobIO[Unit] = FF.liftF(Truncate(a)) - - private val monad = FF.catsFreeMonadForFree[BlobOp] - - // Typeclass instances for BlobIO - implicit val SyncBlobIO: Sync[BlobIO] = - new Sync[BlobIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): BlobIO[A] = monad.pure(x) - override def map[A, B](fa: BlobIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: BlobIO[A])(f: A => BlobIO[B]): BlobIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => BlobIO[Either[A, B]]): BlobIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): BlobIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: BlobIO[A])(f: Throwable => BlobIO[A]): BlobIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: BlobIO[FiniteDuration] = module.monotonic - override def realTime: BlobIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): BlobIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: BlobIO[A])(fb: BlobIO[B]): BlobIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[BlobIO] => BlobIO[A]): BlobIO[A] = module.uncancelable(body) - override def canceled: BlobIO[Unit] = module.canceled - override def onCancel[A](fa: BlobIO[A], fin: BlobIO[Unit]): BlobIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidBlobIO[A](implicit M: Monoid[A]): Monoid[BlobIO[A]] = - new Monoid[BlobIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: BlobIO[A], y: BlobIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/callablestatement.scala b/modules/free/src/main/scala/doobie/free/callablestatement.scala deleted file mode 100644 index 134bb99b5..000000000 --- a/modules/free/src/main/scala/doobie/free/callablestatement.scala +++ /dev/null @@ -1,1365 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.Reader -import java.math.BigDecimal -import java.net.URL -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.CallableStatement -import java.sql.Clob -import java.sql.Connection -import java.sql.Date -import java.sql.NClob -import java.sql.ParameterMetaData -import java.sql.Ref -import java.sql.ResultSet -import java.sql.ResultSetMetaData -import java.sql.RowId -import java.sql.SQLType -import java.sql.SQLWarning -import java.sql.SQLXML -import java.sql.Time -import java.sql.Timestamp -import java.util.Calendar -import scala.concurrent.duration.FiniteDuration - -object callablestatement { module => - - // Algebra of operations for CallableStatement. Each accepts a visitor as an alternative to pattern-matching. - sealed trait CallableStatementOp[A] { - def visit[F[_]](v: CallableStatementOp.Visitor[F]): F[A] - } - - // Free monad over CallableStatementOp. - type CallableStatementIO[A] = FF[CallableStatementOp, A] - - // Module of instances and constructors of CallableStatementOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object CallableStatementOp { - - // Given a CallableStatement we can embed a CallableStatementIO program in any algebra that understands embedding. - implicit val CallableStatementOpEmbeddable: Embeddable[CallableStatementOp, CallableStatement] = - new Embeddable[CallableStatementOp, CallableStatement] { - def embed[A](j: CallableStatement, fa: FF[CallableStatementOp, A]) = Embedded.CallableStatement(j, fa) - } - - // Interface for a natural transformation CallableStatementOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (CallableStatementOp ~> F) { - final def apply[A](fa: CallableStatementOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: CallableStatement => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: CallableStatementIO[A])(f: Throwable => CallableStatementIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: CallableStatementIO[A])(fb: CallableStatementIO[B]): F[B] - def uncancelable[A](body: Poll[CallableStatementIO] => CallableStatementIO[A]): F[A] - def poll[A](poll: Any, fa: CallableStatementIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: CallableStatementIO[A], fin: CallableStatementIO[Unit]): F[A] - - // CallableStatement - def addBatch: F[Unit] - def addBatch(a: String): F[Unit] - def cancel: F[Unit] - def clearBatch: F[Unit] - def clearParameters: F[Unit] - def clearWarnings: F[Unit] - def close: F[Unit] - def closeOnCompletion: F[Unit] - def enquoteIdentifier(a: String, b: Boolean): F[String] - def enquoteLiteral(a: String): F[String] - def enquoteNCharLiteral(a: String): F[String] - def execute: F[Boolean] - def execute(a: String): F[Boolean] - def execute(a: String, b: Array[Int]): F[Boolean] - def execute(a: String, b: Array[String]): F[Boolean] - def execute(a: String, b: Int): F[Boolean] - def executeBatch: F[Array[Int]] - def executeLargeBatch: F[Array[Long]] - def executeLargeUpdate: F[Long] - def executeLargeUpdate(a: String): F[Long] - def executeLargeUpdate(a: String, b: Array[Int]): F[Long] - def executeLargeUpdate(a: String, b: Array[String]): F[Long] - def executeLargeUpdate(a: String, b: Int): F[Long] - def executeQuery: F[ResultSet] - def executeQuery(a: String): F[ResultSet] - def executeUpdate: F[Int] - def executeUpdate(a: String): F[Int] - def executeUpdate(a: String, b: Array[Int]): F[Int] - def executeUpdate(a: String, b: Array[String]): F[Int] - def executeUpdate(a: String, b: Int): F[Int] - def getArray(a: Int): F[SqlArray] - def getArray(a: String): F[SqlArray] - def getBigDecimal(a: Int): F[BigDecimal] - def getBigDecimal(a: String): F[BigDecimal] - def getBlob(a: Int): F[Blob] - def getBlob(a: String): F[Blob] - def getBoolean(a: Int): F[Boolean] - def getBoolean(a: String): F[Boolean] - def getByte(a: Int): F[Byte] - def getByte(a: String): F[Byte] - def getBytes(a: Int): F[Array[Byte]] - def getBytes(a: String): F[Array[Byte]] - def getCharacterStream(a: Int): F[Reader] - def getCharacterStream(a: String): F[Reader] - def getClob(a: Int): F[Clob] - def getClob(a: String): F[Clob] - def getConnection: F[Connection] - def getDate(a: Int): F[Date] - def getDate(a: Int, b: Calendar): F[Date] - def getDate(a: String): F[Date] - def getDate(a: String, b: Calendar): F[Date] - def getDouble(a: Int): F[Double] - def getDouble(a: String): F[Double] - def getFetchDirection: F[Int] - def getFetchSize: F[Int] - def getFloat(a: Int): F[Float] - def getFloat(a: String): F[Float] - def getGeneratedKeys: F[ResultSet] - def getInt(a: Int): F[Int] - def getInt(a: String): F[Int] - def getLargeMaxRows: F[Long] - def getLargeUpdateCount: F[Long] - def getLong(a: Int): F[Long] - def getLong(a: String): F[Long] - def getMaxFieldSize: F[Int] - def getMaxRows: F[Int] - def getMetaData: F[ResultSetMetaData] - def getMoreResults: F[Boolean] - def getMoreResults(a: Int): F[Boolean] - def getNCharacterStream(a: Int): F[Reader] - def getNCharacterStream(a: String): F[Reader] - def getNClob(a: Int): F[NClob] - def getNClob(a: String): F[NClob] - def getNString(a: Int): F[String] - def getNString(a: String): F[String] - def getObject(a: Int): F[AnyRef] - def getObject[T](a: Int, b: Class[T]): F[T] - def getObject(a: Int, b: java.util.Map[String, Class[?]]): F[AnyRef] - def getObject(a: String): F[AnyRef] - def getObject[T](a: String, b: Class[T]): F[T] - def getObject(a: String, b: java.util.Map[String, Class[?]]): F[AnyRef] - def getParameterMetaData: F[ParameterMetaData] - def getQueryTimeout: F[Int] - def getRef(a: Int): F[Ref] - def getRef(a: String): F[Ref] - def getResultSet: F[ResultSet] - def getResultSetConcurrency: F[Int] - def getResultSetHoldability: F[Int] - def getResultSetType: F[Int] - def getRowId(a: Int): F[RowId] - def getRowId(a: String): F[RowId] - def getSQLXML(a: Int): F[SQLXML] - def getSQLXML(a: String): F[SQLXML] - def getShort(a: Int): F[Short] - def getShort(a: String): F[Short] - def getString(a: Int): F[String] - def getString(a: String): F[String] - def getTime(a: Int): F[Time] - def getTime(a: Int, b: Calendar): F[Time] - def getTime(a: String): F[Time] - def getTime(a: String, b: Calendar): F[Time] - def getTimestamp(a: Int): F[Timestamp] - def getTimestamp(a: Int, b: Calendar): F[Timestamp] - def getTimestamp(a: String): F[Timestamp] - def getTimestamp(a: String, b: Calendar): F[Timestamp] - def getURL(a: Int): F[URL] - def getURL(a: String): F[URL] - def getUpdateCount: F[Int] - def getWarnings: F[SQLWarning] - def isCloseOnCompletion: F[Boolean] - def isClosed: F[Boolean] - def isPoolable: F[Boolean] - def isSimpleIdentifier(a: String): F[Boolean] - def isWrapperFor(a: Class[?]): F[Boolean] - def registerOutParameter(a: Int, b: Int): F[Unit] - def registerOutParameter(a: Int, b: Int, c: Int): F[Unit] - def registerOutParameter(a: Int, b: Int, c: String): F[Unit] - def registerOutParameter(a: Int, b: SQLType): F[Unit] - def registerOutParameter(a: Int, b: SQLType, c: Int): F[Unit] - def registerOutParameter(a: Int, b: SQLType, c: String): F[Unit] - def registerOutParameter(a: String, b: Int): F[Unit] - def registerOutParameter(a: String, b: Int, c: Int): F[Unit] - def registerOutParameter(a: String, b: Int, c: String): F[Unit] - def registerOutParameter(a: String, b: SQLType): F[Unit] - def registerOutParameter(a: String, b: SQLType, c: Int): F[Unit] - def registerOutParameter(a: String, b: SQLType, c: String): F[Unit] - def setArray(a: Int, b: SqlArray): F[Unit] - def setAsciiStream(a: Int, b: InputStream): F[Unit] - def setAsciiStream(a: Int, b: InputStream, c: Int): F[Unit] - def setAsciiStream(a: Int, b: InputStream, c: Long): F[Unit] - def setAsciiStream(a: String, b: InputStream): F[Unit] - def setAsciiStream(a: String, b: InputStream, c: Int): F[Unit] - def setAsciiStream(a: String, b: InputStream, c: Long): F[Unit] - def setBigDecimal(a: Int, b: BigDecimal): F[Unit] - def setBigDecimal(a: String, b: BigDecimal): F[Unit] - def setBinaryStream(a: Int, b: InputStream): F[Unit] - def setBinaryStream(a: Int, b: InputStream, c: Int): F[Unit] - def setBinaryStream(a: Int, b: InputStream, c: Long): F[Unit] - def setBinaryStream(a: String, b: InputStream): F[Unit] - def setBinaryStream(a: String, b: InputStream, c: Int): F[Unit] - def setBinaryStream(a: String, b: InputStream, c: Long): F[Unit] - def setBlob(a: Int, b: Blob): F[Unit] - def setBlob(a: Int, b: InputStream): F[Unit] - def setBlob(a: Int, b: InputStream, c: Long): F[Unit] - def setBlob(a: String, b: Blob): F[Unit] - def setBlob(a: String, b: InputStream): F[Unit] - def setBlob(a: String, b: InputStream, c: Long): F[Unit] - def setBoolean(a: Int, b: Boolean): F[Unit] - def setBoolean(a: String, b: Boolean): F[Unit] - def setByte(a: Int, b: Byte): F[Unit] - def setByte(a: String, b: Byte): F[Unit] - def setBytes(a: Int, b: Array[Byte]): F[Unit] - def setBytes(a: String, b: Array[Byte]): F[Unit] - def setCharacterStream(a: Int, b: Reader): F[Unit] - def setCharacterStream(a: Int, b: Reader, c: Int): F[Unit] - def setCharacterStream(a: Int, b: Reader, c: Long): F[Unit] - def setCharacterStream(a: String, b: Reader): F[Unit] - def setCharacterStream(a: String, b: Reader, c: Int): F[Unit] - def setCharacterStream(a: String, b: Reader, c: Long): F[Unit] - def setClob(a: Int, b: Clob): F[Unit] - def setClob(a: Int, b: Reader): F[Unit] - def setClob(a: Int, b: Reader, c: Long): F[Unit] - def setClob(a: String, b: Clob): F[Unit] - def setClob(a: String, b: Reader): F[Unit] - def setClob(a: String, b: Reader, c: Long): F[Unit] - def setCursorName(a: String): F[Unit] - def setDate(a: Int, b: Date): F[Unit] - def setDate(a: Int, b: Date, c: Calendar): F[Unit] - def setDate(a: String, b: Date): F[Unit] - def setDate(a: String, b: Date, c: Calendar): F[Unit] - def setDouble(a: Int, b: Double): F[Unit] - def setDouble(a: String, b: Double): F[Unit] - def setEscapeProcessing(a: Boolean): F[Unit] - def setFetchDirection(a: Int): F[Unit] - def setFetchSize(a: Int): F[Unit] - def setFloat(a: Int, b: Float): F[Unit] - def setFloat(a: String, b: Float): F[Unit] - def setInt(a: Int, b: Int): F[Unit] - def setInt(a: String, b: Int): F[Unit] - def setLargeMaxRows(a: Long): F[Unit] - def setLong(a: Int, b: Long): F[Unit] - def setLong(a: String, b: Long): F[Unit] - def setMaxFieldSize(a: Int): F[Unit] - def setMaxRows(a: Int): F[Unit] - def setNCharacterStream(a: Int, b: Reader): F[Unit] - def setNCharacterStream(a: Int, b: Reader, c: Long): F[Unit] - def setNCharacterStream(a: String, b: Reader): F[Unit] - def setNCharacterStream(a: String, b: Reader, c: Long): F[Unit] - def setNClob(a: Int, b: NClob): F[Unit] - def setNClob(a: Int, b: Reader): F[Unit] - def setNClob(a: Int, b: Reader, c: Long): F[Unit] - def setNClob(a: String, b: NClob): F[Unit] - def setNClob(a: String, b: Reader): F[Unit] - def setNClob(a: String, b: Reader, c: Long): F[Unit] - def setNString(a: Int, b: String): F[Unit] - def setNString(a: String, b: String): F[Unit] - def setNull(a: Int, b: Int): F[Unit] - def setNull(a: Int, b: Int, c: String): F[Unit] - def setNull(a: String, b: Int): F[Unit] - def setNull(a: String, b: Int, c: String): F[Unit] - def setObject(a: Int, b: AnyRef): F[Unit] - def setObject(a: Int, b: AnyRef, c: Int): F[Unit] - def setObject(a: Int, b: AnyRef, c: Int, d: Int): F[Unit] - def setObject(a: Int, b: AnyRef, c: SQLType): F[Unit] - def setObject(a: Int, b: AnyRef, c: SQLType, d: Int): F[Unit] - def setObject(a: String, b: AnyRef): F[Unit] - def setObject(a: String, b: AnyRef, c: Int): F[Unit] - def setObject(a: String, b: AnyRef, c: Int, d: Int): F[Unit] - def setObject(a: String, b: AnyRef, c: SQLType): F[Unit] - def setObject(a: String, b: AnyRef, c: SQLType, d: Int): F[Unit] - def setPoolable(a: Boolean): F[Unit] - def setQueryTimeout(a: Int): F[Unit] - def setRef(a: Int, b: Ref): F[Unit] - def setRowId(a: Int, b: RowId): F[Unit] - def setRowId(a: String, b: RowId): F[Unit] - def setSQLXML(a: Int, b: SQLXML): F[Unit] - def setSQLXML(a: String, b: SQLXML): F[Unit] - def setShort(a: Int, b: Short): F[Unit] - def setShort(a: String, b: Short): F[Unit] - def setString(a: Int, b: String): F[Unit] - def setString(a: String, b: String): F[Unit] - def setTime(a: Int, b: Time): F[Unit] - def setTime(a: Int, b: Time, c: Calendar): F[Unit] - def setTime(a: String, b: Time): F[Unit] - def setTime(a: String, b: Time, c: Calendar): F[Unit] - def setTimestamp(a: Int, b: Timestamp): F[Unit] - def setTimestamp(a: Int, b: Timestamp, c: Calendar): F[Unit] - def setTimestamp(a: String, b: Timestamp): F[Unit] - def setTimestamp(a: String, b: Timestamp, c: Calendar): F[Unit] - def setURL(a: Int, b: URL): F[Unit] - def setURL(a: String, b: URL): F[Unit] - def unwrap[T](a: Class[T]): F[T] - def wasNull: F[Boolean] - - } - - // Common operations for all algebras. - final case class Raw[A](f: CallableStatement => A) extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: CallableStatementIO[A], f: Throwable => CallableStatementIO[A]) - extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends CallableStatementOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends CallableStatementOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: CallableStatementIO[A], fb: CallableStatementIO[B]) extends CallableStatementOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[CallableStatementIO] => CallableStatementIO[A]) - extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: CallableStatementIO[A]) extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: CallableStatementIO[A], fin: CallableStatementIO[Unit]) - extends CallableStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // CallableStatement-specific operations. - case object AddBatch extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.addBatch - } - final case class AddBatch1(a: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.addBatch(a) - } - case object Cancel extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancel - } - case object ClearBatch extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearBatch - } - case object ClearParameters extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearParameters - } - case object ClearWarnings extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearWarnings - } - case object Close extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.close - } - case object CloseOnCompletion extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.closeOnCompletion - } - final case class EnquoteIdentifier(a: String, b: Boolean) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteIdentifier(a, b) - } - final case class EnquoteLiteral(a: String) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteLiteral(a) - } - final case class EnquoteNCharLiteral(a: String) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteNCharLiteral(a) - } - case object Execute extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute - } - final case class Execute1(a: String) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a) - } - final case class Execute2(a: String, b: Array[Int]) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - final case class Execute3(a: String, b: Array[String]) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - final case class Execute4(a: String, b: Int) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - case object ExecuteBatch extends CallableStatementOp[Array[Int]] { - def visit[F[_]](v: Visitor[F]) = v.executeBatch - } - case object ExecuteLargeBatch extends CallableStatementOp[Array[Long]] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeBatch - } - case object ExecuteLargeUpdate extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate - } - final case class ExecuteLargeUpdate1(a: String) extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a) - } - final case class ExecuteLargeUpdate2(a: String, b: Array[Int]) extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteLargeUpdate3(a: String, b: Array[String]) extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteLargeUpdate4(a: String, b: Int) extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - case object ExecuteQuery extends CallableStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.executeQuery - } - final case class ExecuteQuery1(a: String) extends CallableStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.executeQuery(a) - } - case object ExecuteUpdate extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate - } - final case class ExecuteUpdate1(a: String) extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a) - } - final case class ExecuteUpdate2(a: String, b: Array[Int]) extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class ExecuteUpdate3(a: String, b: Array[String]) extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class ExecuteUpdate4(a: String, b: Int) extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class GetArray(a: Int) extends CallableStatementOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.getArray(a) - } - final case class GetArray1(a: String) extends CallableStatementOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.getArray(a) - } - final case class GetBigDecimal(a: Int) extends CallableStatementOp[BigDecimal] { - def visit[F[_]](v: Visitor[F]) = v.getBigDecimal(a) - } - final case class GetBigDecimal1(a: String) extends CallableStatementOp[BigDecimal] { - def visit[F[_]](v: Visitor[F]) = v.getBigDecimal(a) - } - final case class GetBlob(a: Int) extends CallableStatementOp[Blob] { - def visit[F[_]](v: Visitor[F]) = v.getBlob(a) - } - final case class GetBlob1(a: String) extends CallableStatementOp[Blob] { - def visit[F[_]](v: Visitor[F]) = v.getBlob(a) - } - final case class GetBoolean(a: Int) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getBoolean(a) - } - final case class GetBoolean1(a: String) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getBoolean(a) - } - final case class GetByte(a: Int) extends CallableStatementOp[Byte] { - def visit[F[_]](v: Visitor[F]) = v.getByte(a) - } - final case class GetByte1(a: String) extends CallableStatementOp[Byte] { - def visit[F[_]](v: Visitor[F]) = v.getByte(a) - } - final case class GetBytes(a: Int) extends CallableStatementOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.getBytes(a) - } - final case class GetBytes1(a: String) extends CallableStatementOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.getBytes(a) - } - final case class GetCharacterStream(a: Int) extends CallableStatementOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream(a) - } - final case class GetCharacterStream1(a: String) extends CallableStatementOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream(a) - } - final case class GetClob(a: Int) extends CallableStatementOp[Clob] { - def visit[F[_]](v: Visitor[F]) = v.getClob(a) - } - final case class GetClob1(a: String) extends CallableStatementOp[Clob] { - def visit[F[_]](v: Visitor[F]) = v.getClob(a) - } - case object GetConnection extends CallableStatementOp[Connection] { - def visit[F[_]](v: Visitor[F]) = v.getConnection - } - final case class GetDate(a: Int) extends CallableStatementOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a) - } - final case class GetDate1(a: Int, b: Calendar) extends CallableStatementOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a, b) - } - final case class GetDate2(a: String) extends CallableStatementOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a) - } - final case class GetDate3(a: String, b: Calendar) extends CallableStatementOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a, b) - } - final case class GetDouble(a: Int) extends CallableStatementOp[Double] { - def visit[F[_]](v: Visitor[F]) = v.getDouble(a) - } - final case class GetDouble1(a: String) extends CallableStatementOp[Double] { - def visit[F[_]](v: Visitor[F]) = v.getDouble(a) - } - case object GetFetchDirection extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchDirection - } - case object GetFetchSize extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchSize - } - final case class GetFloat(a: Int) extends CallableStatementOp[Float] { - def visit[F[_]](v: Visitor[F]) = v.getFloat(a) - } - final case class GetFloat1(a: String) extends CallableStatementOp[Float] { - def visit[F[_]](v: Visitor[F]) = v.getFloat(a) - } - case object GetGeneratedKeys extends CallableStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getGeneratedKeys - } - final case class GetInt(a: Int) extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getInt(a) - } - final case class GetInt1(a: String) extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getInt(a) - } - case object GetLargeMaxRows extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLargeMaxRows - } - case object GetLargeUpdateCount extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLargeUpdateCount - } - final case class GetLong(a: Int) extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLong(a) - } - final case class GetLong1(a: String) extends CallableStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLong(a) - } - case object GetMaxFieldSize extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxFieldSize - } - case object GetMaxRows extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxRows - } - case object GetMetaData extends CallableStatementOp[ResultSetMetaData] { - def visit[F[_]](v: Visitor[F]) = v.getMetaData - } - case object GetMoreResults extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getMoreResults - } - final case class GetMoreResults1(a: Int) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getMoreResults(a) - } - final case class GetNCharacterStream(a: Int) extends CallableStatementOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getNCharacterStream(a) - } - final case class GetNCharacterStream1(a: String) extends CallableStatementOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getNCharacterStream(a) - } - final case class GetNClob(a: Int) extends CallableStatementOp[NClob] { - def visit[F[_]](v: Visitor[F]) = v.getNClob(a) - } - final case class GetNClob1(a: String) extends CallableStatementOp[NClob] { - def visit[F[_]](v: Visitor[F]) = v.getNClob(a) - } - final case class GetNString(a: Int) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getNString(a) - } - final case class GetNString1(a: String) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getNString(a) - } - final case class GetObject(a: Int) extends CallableStatementOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a) - } - final case class GetObject1[T](a: Int, b: Class[T]) extends CallableStatementOp[T] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetObject2(a: Int, b: java.util.Map[String, Class[?]]) extends CallableStatementOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetObject3(a: String) extends CallableStatementOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a) - } - final case class GetObject4[T](a: String, b: Class[T]) extends CallableStatementOp[T] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetObject5(a: String, b: java.util.Map[String, Class[?]]) extends CallableStatementOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - case object GetParameterMetaData extends CallableStatementOp[ParameterMetaData] { - def visit[F[_]](v: Visitor[F]) = v.getParameterMetaData - } - case object GetQueryTimeout extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getQueryTimeout - } - final case class GetRef(a: Int) extends CallableStatementOp[Ref] { - def visit[F[_]](v: Visitor[F]) = v.getRef(a) - } - final case class GetRef1(a: String) extends CallableStatementOp[Ref] { - def visit[F[_]](v: Visitor[F]) = v.getRef(a) - } - case object GetResultSet extends CallableStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getResultSet - } - case object GetResultSetConcurrency extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetConcurrency - } - case object GetResultSetHoldability extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetHoldability - } - case object GetResultSetType extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetType - } - final case class GetRowId(a: Int) extends CallableStatementOp[RowId] { - def visit[F[_]](v: Visitor[F]) = v.getRowId(a) - } - final case class GetRowId1(a: String) extends CallableStatementOp[RowId] { - def visit[F[_]](v: Visitor[F]) = v.getRowId(a) - } - final case class GetSQLXML(a: Int) extends CallableStatementOp[SQLXML] { - def visit[F[_]](v: Visitor[F]) = v.getSQLXML(a) - } - final case class GetSQLXML1(a: String) extends CallableStatementOp[SQLXML] { - def visit[F[_]](v: Visitor[F]) = v.getSQLXML(a) - } - final case class GetShort(a: Int) extends CallableStatementOp[Short] { - def visit[F[_]](v: Visitor[F]) = v.getShort(a) - } - final case class GetShort1(a: String) extends CallableStatementOp[Short] { - def visit[F[_]](v: Visitor[F]) = v.getShort(a) - } - final case class GetString(a: Int) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getString(a) - } - final case class GetString1(a: String) extends CallableStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getString(a) - } - final case class GetTime(a: Int) extends CallableStatementOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a) - } - final case class GetTime1(a: Int, b: Calendar) extends CallableStatementOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a, b) - } - final case class GetTime2(a: String) extends CallableStatementOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a) - } - final case class GetTime3(a: String, b: Calendar) extends CallableStatementOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a, b) - } - final case class GetTimestamp(a: Int) extends CallableStatementOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a) - } - final case class GetTimestamp1(a: Int, b: Calendar) extends CallableStatementOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a, b) - } - final case class GetTimestamp2(a: String) extends CallableStatementOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a) - } - final case class GetTimestamp3(a: String, b: Calendar) extends CallableStatementOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a, b) - } - final case class GetURL(a: Int) extends CallableStatementOp[URL] { - def visit[F[_]](v: Visitor[F]) = v.getURL(a) - } - final case class GetURL1(a: String) extends CallableStatementOp[URL] { - def visit[F[_]](v: Visitor[F]) = v.getURL(a) - } - case object GetUpdateCount extends CallableStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getUpdateCount - } - case object GetWarnings extends CallableStatementOp[SQLWarning] { - def visit[F[_]](v: Visitor[F]) = v.getWarnings - } - case object IsCloseOnCompletion extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isCloseOnCompletion - } - case object IsClosed extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isClosed - } - case object IsPoolable extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isPoolable - } - final case class IsSimpleIdentifier(a: String) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isSimpleIdentifier(a) - } - final case class IsWrapperFor(a: Class[?]) extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isWrapperFor(a) - } - final case class RegisterOutParameter(a: Int, b: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b) - } - final case class RegisterOutParameter1(a: Int, b: Int, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter2(a: Int, b: Int, c: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter3(a: Int, b: SQLType) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b) - } - final case class RegisterOutParameter4(a: Int, b: SQLType, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter5(a: Int, b: SQLType, c: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter6(a: String, b: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b) - } - final case class RegisterOutParameter7(a: String, b: Int, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter8(a: String, b: Int, c: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter9(a: String, b: SQLType) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b) - } - final case class RegisterOutParameter10(a: String, b: SQLType, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class RegisterOutParameter11(a: String, b: SQLType, c: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.registerOutParameter(a, b, c) - } - final case class SetArray(a: Int, b: SqlArray) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setArray(a, b) - } - final case class SetAsciiStream(a: Int, b: InputStream) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b) - } - final case class SetAsciiStream1(a: Int, b: InputStream, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b, c) - } - final case class SetAsciiStream2(a: Int, b: InputStream, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b, c) - } - final case class SetAsciiStream3(a: String, b: InputStream) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b) - } - final case class SetAsciiStream4(a: String, b: InputStream, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b, c) - } - final case class SetAsciiStream5(a: String, b: InputStream, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b, c) - } - final case class SetBigDecimal(a: Int, b: BigDecimal) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBigDecimal(a, b) - } - final case class SetBigDecimal1(a: String, b: BigDecimal) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBigDecimal(a, b) - } - final case class SetBinaryStream(a: Int, b: InputStream) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b) - } - final case class SetBinaryStream1(a: Int, b: InputStream, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b, c) - } - final case class SetBinaryStream2(a: Int, b: InputStream, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b, c) - } - final case class SetBinaryStream3(a: String, b: InputStream) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b) - } - final case class SetBinaryStream4(a: String, b: InputStream, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b, c) - } - final case class SetBinaryStream5(a: String, b: InputStream, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b, c) - } - final case class SetBlob(a: Int, b: Blob) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b) - } - final case class SetBlob1(a: Int, b: InputStream) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b) - } - final case class SetBlob2(a: Int, b: InputStream, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b, c) - } - final case class SetBlob3(a: String, b: Blob) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b) - } - final case class SetBlob4(a: String, b: InputStream) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b) - } - final case class SetBlob5(a: String, b: InputStream, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b, c) - } - final case class SetBoolean(a: Int, b: Boolean) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBoolean(a, b) - } - final case class SetBoolean1(a: String, b: Boolean) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBoolean(a, b) - } - final case class SetByte(a: Int, b: Byte) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setByte(a, b) - } - final case class SetByte1(a: String, b: Byte) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setByte(a, b) - } - final case class SetBytes(a: Int, b: Array[Byte]) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBytes(a, b) - } - final case class SetBytes1(a: String, b: Array[Byte]) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBytes(a, b) - } - final case class SetCharacterStream(a: Int, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b) - } - final case class SetCharacterStream1(a: Int, b: Reader, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b, c) - } - final case class SetCharacterStream2(a: Int, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b, c) - } - final case class SetCharacterStream3(a: String, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b) - } - final case class SetCharacterStream4(a: String, b: Reader, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b, c) - } - final case class SetCharacterStream5(a: String, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b, c) - } - final case class SetClob(a: Int, b: Clob) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b) - } - final case class SetClob1(a: Int, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b) - } - final case class SetClob2(a: Int, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b, c) - } - final case class SetClob3(a: String, b: Clob) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b) - } - final case class SetClob4(a: String, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b) - } - final case class SetClob5(a: String, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b, c) - } - final case class SetCursorName(a: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCursorName(a) - } - final case class SetDate(a: Int, b: Date) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDate(a, b) - } - final case class SetDate1(a: Int, b: Date, c: Calendar) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDate(a, b, c) - } - final case class SetDate2(a: String, b: Date) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDate(a, b) - } - final case class SetDate3(a: String, b: Date, c: Calendar) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDate(a, b, c) - } - final case class SetDouble(a: Int, b: Double) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDouble(a, b) - } - final case class SetDouble1(a: String, b: Double) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDouble(a, b) - } - final case class SetEscapeProcessing(a: Boolean) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setEscapeProcessing(a) - } - final case class SetFetchDirection(a: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchDirection(a) - } - final case class SetFetchSize(a: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchSize(a) - } - final case class SetFloat(a: Int, b: Float) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFloat(a, b) - } - final case class SetFloat1(a: String, b: Float) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFloat(a, b) - } - final case class SetInt(a: Int, b: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setInt(a, b) - } - final case class SetInt1(a: String, b: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setInt(a, b) - } - final case class SetLargeMaxRows(a: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setLargeMaxRows(a) - } - final case class SetLong(a: Int, b: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setLong(a, b) - } - final case class SetLong1(a: String, b: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setLong(a, b) - } - final case class SetMaxFieldSize(a: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setMaxFieldSize(a) - } - final case class SetMaxRows(a: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setMaxRows(a) - } - final case class SetNCharacterStream(a: Int, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNCharacterStream(a, b) - } - final case class SetNCharacterStream1(a: Int, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNCharacterStream(a, b, c) - } - final case class SetNCharacterStream2(a: String, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNCharacterStream(a, b) - } - final case class SetNCharacterStream3(a: String, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNCharacterStream(a, b, c) - } - final case class SetNClob(a: Int, b: NClob) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b) - } - final case class SetNClob1(a: Int, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b) - } - final case class SetNClob2(a: Int, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b, c) - } - final case class SetNClob3(a: String, b: NClob) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b) - } - final case class SetNClob4(a: String, b: Reader) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b) - } - final case class SetNClob5(a: String, b: Reader, c: Long) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b, c) - } - final case class SetNString(a: Int, b: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNString(a, b) - } - final case class SetNString1(a: String, b: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNString(a, b) - } - final case class SetNull(a: Int, b: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNull(a, b) - } - final case class SetNull1(a: Int, b: Int, c: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNull(a, b, c) - } - final case class SetNull2(a: String, b: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNull(a, b) - } - final case class SetNull3(a: String, b: Int, c: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNull(a, b, c) - } - final case class SetObject(a: Int, b: AnyRef) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b) - } - final case class SetObject1(a: Int, b: AnyRef, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c) - } - final case class SetObject2(a: Int, b: AnyRef, c: Int, d: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c, d) - } - final case class SetObject3(a: Int, b: AnyRef, c: SQLType) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c) - } - final case class SetObject4(a: Int, b: AnyRef, c: SQLType, d: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c, d) - } - final case class SetObject5(a: String, b: AnyRef) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b) - } - final case class SetObject6(a: String, b: AnyRef, c: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c) - } - final case class SetObject7(a: String, b: AnyRef, c: Int, d: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c, d) - } - final case class SetObject8(a: String, b: AnyRef, c: SQLType) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c) - } - final case class SetObject9(a: String, b: AnyRef, c: SQLType, d: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c, d) - } - final case class SetPoolable(a: Boolean) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setPoolable(a) - } - final case class SetQueryTimeout(a: Int) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setQueryTimeout(a) - } - final case class SetRef(a: Int, b: Ref) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setRef(a, b) - } - final case class SetRowId(a: Int, b: RowId) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setRowId(a, b) - } - final case class SetRowId1(a: String, b: RowId) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setRowId(a, b) - } - final case class SetSQLXML(a: Int, b: SQLXML) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setSQLXML(a, b) - } - final case class SetSQLXML1(a: String, b: SQLXML) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setSQLXML(a, b) - } - final case class SetShort(a: Int, b: Short) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setShort(a, b) - } - final case class SetShort1(a: String, b: Short) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setShort(a, b) - } - final case class SetString(a: Int, b: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b) - } - final case class SetString1(a: String, b: String) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b) - } - final case class SetTime(a: Int, b: Time) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTime(a, b) - } - final case class SetTime1(a: Int, b: Time, c: Calendar) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTime(a, b, c) - } - final case class SetTime2(a: String, b: Time) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTime(a, b) - } - final case class SetTime3(a: String, b: Time, c: Calendar) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTime(a, b, c) - } - final case class SetTimestamp(a: Int, b: Timestamp) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTimestamp(a, b) - } - final case class SetTimestamp1(a: Int, b: Timestamp, c: Calendar) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTimestamp(a, b, c) - } - final case class SetTimestamp2(a: String, b: Timestamp) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTimestamp(a, b) - } - final case class SetTimestamp3(a: String, b: Timestamp, c: Calendar) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTimestamp(a, b, c) - } - final case class SetURL(a: Int, b: URL) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setURL(a, b) - } - final case class SetURL1(a: String, b: URL) extends CallableStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setURL(a, b) - } - final case class Unwrap[T](a: Class[T]) extends CallableStatementOp[T] { - def visit[F[_]](v: Visitor[F]) = v.unwrap(a) - } - case object WasNull extends CallableStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.wasNull - } - - } - import CallableStatementOp.* - - // Smart constructors for operations common to all algebras. - val unit: CallableStatementIO[Unit] = FF.pure[CallableStatementOp, Unit](()) - def pure[A](a: A): CallableStatementIO[A] = FF.pure[CallableStatementOp, A](a) - def raw[A](f: CallableStatement => A): CallableStatementIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[CallableStatementOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): CallableStatementIO[A] = FF.liftF[CallableStatementOp, A](RaiseError(err)) - def handleErrorWith[A](fa: CallableStatementIO[A])(f: Throwable => CallableStatementIO[A]): CallableStatementIO[A] = - FF.liftF[CallableStatementOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[CallableStatementOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[CallableStatementOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[CallableStatementOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[CallableStatementOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: CallableStatementIO[A])(fb: CallableStatementIO[B]) = - FF.liftF[CallableStatementOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[CallableStatementIO] => CallableStatementIO[A]) = - FF.liftF[CallableStatementOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[CallableStatementIO] { - def apply[A](fa: CallableStatementIO[A]) = FF.liftF[CallableStatementOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[CallableStatementOp, Unit](Canceled) - def onCancel[A](fa: CallableStatementIO[A], fin: CallableStatementIO[Unit]) = - FF.liftF[CallableStatementOp, A](OnCancel(fa, fin)) - - // Smart constructors for CallableStatement-specific operations. - val addBatch: CallableStatementIO[Unit] = FF.liftF(AddBatch) - def addBatch(a: String): CallableStatementIO[Unit] = FF.liftF(AddBatch1(a)) - val cancel: CallableStatementIO[Unit] = FF.liftF(Cancel) - val clearBatch: CallableStatementIO[Unit] = FF.liftF(ClearBatch) - val clearParameters: CallableStatementIO[Unit] = FF.liftF(ClearParameters) - val clearWarnings: CallableStatementIO[Unit] = FF.liftF(ClearWarnings) - val close: CallableStatementIO[Unit] = FF.liftF(Close) - val closeOnCompletion: CallableStatementIO[Unit] = FF.liftF(CloseOnCompletion) - def enquoteIdentifier(a: String, b: Boolean): CallableStatementIO[String] = FF.liftF(EnquoteIdentifier(a, b)) - def enquoteLiteral(a: String): CallableStatementIO[String] = FF.liftF(EnquoteLiteral(a)) - def enquoteNCharLiteral(a: String): CallableStatementIO[String] = FF.liftF(EnquoteNCharLiteral(a)) - val execute: CallableStatementIO[Boolean] = FF.liftF(Execute) - def execute(a: String): CallableStatementIO[Boolean] = FF.liftF(Execute1(a)) - def execute(a: String, b: Array[Int]): CallableStatementIO[Boolean] = FF.liftF(Execute2(a, b)) - def execute(a: String, b: Array[String]): CallableStatementIO[Boolean] = FF.liftF(Execute3(a, b)) - def execute(a: String, b: Int): CallableStatementIO[Boolean] = FF.liftF(Execute4(a, b)) - val executeBatch: CallableStatementIO[Array[Int]] = FF.liftF(ExecuteBatch) - val executeLargeBatch: CallableStatementIO[Array[Long]] = FF.liftF(ExecuteLargeBatch) - val executeLargeUpdate: CallableStatementIO[Long] = FF.liftF(ExecuteLargeUpdate) - def executeLargeUpdate(a: String): CallableStatementIO[Long] = FF.liftF(ExecuteLargeUpdate1(a)) - def executeLargeUpdate(a: String, b: Array[Int]): CallableStatementIO[Long] = FF.liftF(ExecuteLargeUpdate2(a, b)) - def executeLargeUpdate(a: String, b: Array[String]): CallableStatementIO[Long] = FF.liftF(ExecuteLargeUpdate3(a, b)) - def executeLargeUpdate(a: String, b: Int): CallableStatementIO[Long] = FF.liftF(ExecuteLargeUpdate4(a, b)) - val executeQuery: CallableStatementIO[ResultSet] = FF.liftF(ExecuteQuery) - def executeQuery(a: String): CallableStatementIO[ResultSet] = FF.liftF(ExecuteQuery1(a)) - val executeUpdate: CallableStatementIO[Int] = FF.liftF(ExecuteUpdate) - def executeUpdate(a: String): CallableStatementIO[Int] = FF.liftF(ExecuteUpdate1(a)) - def executeUpdate(a: String, b: Array[Int]): CallableStatementIO[Int] = FF.liftF(ExecuteUpdate2(a, b)) - def executeUpdate(a: String, b: Array[String]): CallableStatementIO[Int] = FF.liftF(ExecuteUpdate3(a, b)) - def executeUpdate(a: String, b: Int): CallableStatementIO[Int] = FF.liftF(ExecuteUpdate4(a, b)) - def getArray(a: Int): CallableStatementIO[SqlArray] = FF.liftF(GetArray(a)) - def getArray(a: String): CallableStatementIO[SqlArray] = FF.liftF(GetArray1(a)) - def getBigDecimal(a: Int): CallableStatementIO[BigDecimal] = FF.liftF(GetBigDecimal(a)) - def getBigDecimal(a: String): CallableStatementIO[BigDecimal] = FF.liftF(GetBigDecimal1(a)) - def getBlob(a: Int): CallableStatementIO[Blob] = FF.liftF(GetBlob(a)) - def getBlob(a: String): CallableStatementIO[Blob] = FF.liftF(GetBlob1(a)) - def getBoolean(a: Int): CallableStatementIO[Boolean] = FF.liftF(GetBoolean(a)) - def getBoolean(a: String): CallableStatementIO[Boolean] = FF.liftF(GetBoolean1(a)) - def getByte(a: Int): CallableStatementIO[Byte] = FF.liftF(GetByte(a)) - def getByte(a: String): CallableStatementIO[Byte] = FF.liftF(GetByte1(a)) - def getBytes(a: Int): CallableStatementIO[Array[Byte]] = FF.liftF(GetBytes(a)) - def getBytes(a: String): CallableStatementIO[Array[Byte]] = FF.liftF(GetBytes1(a)) - def getCharacterStream(a: Int): CallableStatementIO[Reader] = FF.liftF(GetCharacterStream(a)) - def getCharacterStream(a: String): CallableStatementIO[Reader] = FF.liftF(GetCharacterStream1(a)) - def getClob(a: Int): CallableStatementIO[Clob] = FF.liftF(GetClob(a)) - def getClob(a: String): CallableStatementIO[Clob] = FF.liftF(GetClob1(a)) - val getConnection: CallableStatementIO[Connection] = FF.liftF(GetConnection) - def getDate(a: Int): CallableStatementIO[Date] = FF.liftF(GetDate(a)) - def getDate(a: Int, b: Calendar): CallableStatementIO[Date] = FF.liftF(GetDate1(a, b)) - def getDate(a: String): CallableStatementIO[Date] = FF.liftF(GetDate2(a)) - def getDate(a: String, b: Calendar): CallableStatementIO[Date] = FF.liftF(GetDate3(a, b)) - def getDouble(a: Int): CallableStatementIO[Double] = FF.liftF(GetDouble(a)) - def getDouble(a: String): CallableStatementIO[Double] = FF.liftF(GetDouble1(a)) - val getFetchDirection: CallableStatementIO[Int] = FF.liftF(GetFetchDirection) - val getFetchSize: CallableStatementIO[Int] = FF.liftF(GetFetchSize) - def getFloat(a: Int): CallableStatementIO[Float] = FF.liftF(GetFloat(a)) - def getFloat(a: String): CallableStatementIO[Float] = FF.liftF(GetFloat1(a)) - val getGeneratedKeys: CallableStatementIO[ResultSet] = FF.liftF(GetGeneratedKeys) - def getInt(a: Int): CallableStatementIO[Int] = FF.liftF(GetInt(a)) - def getInt(a: String): CallableStatementIO[Int] = FF.liftF(GetInt1(a)) - val getLargeMaxRows: CallableStatementIO[Long] = FF.liftF(GetLargeMaxRows) - val getLargeUpdateCount: CallableStatementIO[Long] = FF.liftF(GetLargeUpdateCount) - def getLong(a: Int): CallableStatementIO[Long] = FF.liftF(GetLong(a)) - def getLong(a: String): CallableStatementIO[Long] = FF.liftF(GetLong1(a)) - val getMaxFieldSize: CallableStatementIO[Int] = FF.liftF(GetMaxFieldSize) - val getMaxRows: CallableStatementIO[Int] = FF.liftF(GetMaxRows) - val getMetaData: CallableStatementIO[ResultSetMetaData] = FF.liftF(GetMetaData) - val getMoreResults: CallableStatementIO[Boolean] = FF.liftF(GetMoreResults) - def getMoreResults(a: Int): CallableStatementIO[Boolean] = FF.liftF(GetMoreResults1(a)) - def getNCharacterStream(a: Int): CallableStatementIO[Reader] = FF.liftF(GetNCharacterStream(a)) - def getNCharacterStream(a: String): CallableStatementIO[Reader] = FF.liftF(GetNCharacterStream1(a)) - def getNClob(a: Int): CallableStatementIO[NClob] = FF.liftF(GetNClob(a)) - def getNClob(a: String): CallableStatementIO[NClob] = FF.liftF(GetNClob1(a)) - def getNString(a: Int): CallableStatementIO[String] = FF.liftF(GetNString(a)) - def getNString(a: String): CallableStatementIO[String] = FF.liftF(GetNString1(a)) - def getObject(a: Int): CallableStatementIO[AnyRef] = FF.liftF(GetObject(a)) - def getObject[T](a: Int, b: Class[T]): CallableStatementIO[T] = FF.liftF(GetObject1(a, b)) - def getObject(a: Int, b: java.util.Map[String, Class[?]]): CallableStatementIO[AnyRef] = FF.liftF(GetObject2(a, b)) - def getObject(a: String): CallableStatementIO[AnyRef] = FF.liftF(GetObject3(a)) - def getObject[T](a: String, b: Class[T]): CallableStatementIO[T] = FF.liftF(GetObject4(a, b)) - def getObject(a: String, b: java.util.Map[String, Class[?]]): CallableStatementIO[AnyRef] = FF.liftF(GetObject5(a, b)) - val getParameterMetaData: CallableStatementIO[ParameterMetaData] = FF.liftF(GetParameterMetaData) - val getQueryTimeout: CallableStatementIO[Int] = FF.liftF(GetQueryTimeout) - def getRef(a: Int): CallableStatementIO[Ref] = FF.liftF(GetRef(a)) - def getRef(a: String): CallableStatementIO[Ref] = FF.liftF(GetRef1(a)) - val getResultSet: CallableStatementIO[ResultSet] = FF.liftF(GetResultSet) - val getResultSetConcurrency: CallableStatementIO[Int] = FF.liftF(GetResultSetConcurrency) - val getResultSetHoldability: CallableStatementIO[Int] = FF.liftF(GetResultSetHoldability) - val getResultSetType: CallableStatementIO[Int] = FF.liftF(GetResultSetType) - def getRowId(a: Int): CallableStatementIO[RowId] = FF.liftF(GetRowId(a)) - def getRowId(a: String): CallableStatementIO[RowId] = FF.liftF(GetRowId1(a)) - def getSQLXML(a: Int): CallableStatementIO[SQLXML] = FF.liftF(GetSQLXML(a)) - def getSQLXML(a: String): CallableStatementIO[SQLXML] = FF.liftF(GetSQLXML1(a)) - def getShort(a: Int): CallableStatementIO[Short] = FF.liftF(GetShort(a)) - def getShort(a: String): CallableStatementIO[Short] = FF.liftF(GetShort1(a)) - def getString(a: Int): CallableStatementIO[String] = FF.liftF(GetString(a)) - def getString(a: String): CallableStatementIO[String] = FF.liftF(GetString1(a)) - def getTime(a: Int): CallableStatementIO[Time] = FF.liftF(GetTime(a)) - def getTime(a: Int, b: Calendar): CallableStatementIO[Time] = FF.liftF(GetTime1(a, b)) - def getTime(a: String): CallableStatementIO[Time] = FF.liftF(GetTime2(a)) - def getTime(a: String, b: Calendar): CallableStatementIO[Time] = FF.liftF(GetTime3(a, b)) - def getTimestamp(a: Int): CallableStatementIO[Timestamp] = FF.liftF(GetTimestamp(a)) - def getTimestamp(a: Int, b: Calendar): CallableStatementIO[Timestamp] = FF.liftF(GetTimestamp1(a, b)) - def getTimestamp(a: String): CallableStatementIO[Timestamp] = FF.liftF(GetTimestamp2(a)) - def getTimestamp(a: String, b: Calendar): CallableStatementIO[Timestamp] = FF.liftF(GetTimestamp3(a, b)) - def getURL(a: Int): CallableStatementIO[URL] = FF.liftF(GetURL(a)) - def getURL(a: String): CallableStatementIO[URL] = FF.liftF(GetURL1(a)) - val getUpdateCount: CallableStatementIO[Int] = FF.liftF(GetUpdateCount) - val getWarnings: CallableStatementIO[SQLWarning] = FF.liftF(GetWarnings) - val isCloseOnCompletion: CallableStatementIO[Boolean] = FF.liftF(IsCloseOnCompletion) - val isClosed: CallableStatementIO[Boolean] = FF.liftF(IsClosed) - val isPoolable: CallableStatementIO[Boolean] = FF.liftF(IsPoolable) - def isSimpleIdentifier(a: String): CallableStatementIO[Boolean] = FF.liftF(IsSimpleIdentifier(a)) - def isWrapperFor(a: Class[?]): CallableStatementIO[Boolean] = FF.liftF(IsWrapperFor(a)) - def registerOutParameter(a: Int, b: Int): CallableStatementIO[Unit] = FF.liftF(RegisterOutParameter(a, b)) - def registerOutParameter(a: Int, b: Int, c: Int): CallableStatementIO[Unit] = FF.liftF(RegisterOutParameter1(a, b, c)) - def registerOutParameter(a: Int, b: Int, c: String): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter2(a, b, c)) - def registerOutParameter(a: Int, b: SQLType): CallableStatementIO[Unit] = FF.liftF(RegisterOutParameter3(a, b)) - def registerOutParameter(a: Int, b: SQLType, c: Int): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter4(a, b, c)) - def registerOutParameter(a: Int, b: SQLType, c: String): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter5(a, b, c)) - def registerOutParameter(a: String, b: Int): CallableStatementIO[Unit] = FF.liftF(RegisterOutParameter6(a, b)) - def registerOutParameter(a: String, b: Int, c: Int): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter7(a, b, c)) - def registerOutParameter(a: String, b: Int, c: String): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter8(a, b, c)) - def registerOutParameter(a: String, b: SQLType): CallableStatementIO[Unit] = FF.liftF(RegisterOutParameter9(a, b)) - def registerOutParameter(a: String, b: SQLType, c: Int): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter10(a, b, c)) - def registerOutParameter(a: String, b: SQLType, c: String): CallableStatementIO[Unit] = - FF.liftF(RegisterOutParameter11(a, b, c)) - def setArray(a: Int, b: SqlArray): CallableStatementIO[Unit] = FF.liftF(SetArray(a, b)) - def setAsciiStream(a: Int, b: InputStream): CallableStatementIO[Unit] = FF.liftF(SetAsciiStream(a, b)) - def setAsciiStream(a: Int, b: InputStream, c: Int): CallableStatementIO[Unit] = FF.liftF(SetAsciiStream1(a, b, c)) - def setAsciiStream(a: Int, b: InputStream, c: Long): CallableStatementIO[Unit] = FF.liftF(SetAsciiStream2(a, b, c)) - def setAsciiStream(a: String, b: InputStream): CallableStatementIO[Unit] = FF.liftF(SetAsciiStream3(a, b)) - def setAsciiStream(a: String, b: InputStream, c: Int): CallableStatementIO[Unit] = FF.liftF(SetAsciiStream4(a, b, c)) - def setAsciiStream(a: String, b: InputStream, c: Long): CallableStatementIO[Unit] = FF.liftF(SetAsciiStream5(a, b, c)) - def setBigDecimal(a: Int, b: BigDecimal): CallableStatementIO[Unit] = FF.liftF(SetBigDecimal(a, b)) - def setBigDecimal(a: String, b: BigDecimal): CallableStatementIO[Unit] = FF.liftF(SetBigDecimal1(a, b)) - def setBinaryStream(a: Int, b: InputStream): CallableStatementIO[Unit] = FF.liftF(SetBinaryStream(a, b)) - def setBinaryStream(a: Int, b: InputStream, c: Int): CallableStatementIO[Unit] = FF.liftF(SetBinaryStream1(a, b, c)) - def setBinaryStream(a: Int, b: InputStream, c: Long): CallableStatementIO[Unit] = FF.liftF(SetBinaryStream2(a, b, c)) - def setBinaryStream(a: String, b: InputStream): CallableStatementIO[Unit] = FF.liftF(SetBinaryStream3(a, b)) - def setBinaryStream(a: String, b: InputStream, c: Int): CallableStatementIO[Unit] = FF.liftF(SetBinaryStream4(a, b, c)) - def setBinaryStream(a: String, b: InputStream, c: Long): CallableStatementIO[Unit] = - FF.liftF(SetBinaryStream5(a, b, c)) - def setBlob(a: Int, b: Blob): CallableStatementIO[Unit] = FF.liftF(SetBlob(a, b)) - def setBlob(a: Int, b: InputStream): CallableStatementIO[Unit] = FF.liftF(SetBlob1(a, b)) - def setBlob(a: Int, b: InputStream, c: Long): CallableStatementIO[Unit] = FF.liftF(SetBlob2(a, b, c)) - def setBlob(a: String, b: Blob): CallableStatementIO[Unit] = FF.liftF(SetBlob3(a, b)) - def setBlob(a: String, b: InputStream): CallableStatementIO[Unit] = FF.liftF(SetBlob4(a, b)) - def setBlob(a: String, b: InputStream, c: Long): CallableStatementIO[Unit] = FF.liftF(SetBlob5(a, b, c)) - def setBoolean(a: Int, b: Boolean): CallableStatementIO[Unit] = FF.liftF(SetBoolean(a, b)) - def setBoolean(a: String, b: Boolean): CallableStatementIO[Unit] = FF.liftF(SetBoolean1(a, b)) - def setByte(a: Int, b: Byte): CallableStatementIO[Unit] = FF.liftF(SetByte(a, b)) - def setByte(a: String, b: Byte): CallableStatementIO[Unit] = FF.liftF(SetByte1(a, b)) - def setBytes(a: Int, b: Array[Byte]): CallableStatementIO[Unit] = FF.liftF(SetBytes(a, b)) - def setBytes(a: String, b: Array[Byte]): CallableStatementIO[Unit] = FF.liftF(SetBytes1(a, b)) - def setCharacterStream(a: Int, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetCharacterStream(a, b)) - def setCharacterStream(a: Int, b: Reader, c: Int): CallableStatementIO[Unit] = FF.liftF(SetCharacterStream1(a, b, c)) - def setCharacterStream(a: Int, b: Reader, c: Long): CallableStatementIO[Unit] = FF.liftF(SetCharacterStream2(a, b, c)) - def setCharacterStream(a: String, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetCharacterStream3(a, b)) - def setCharacterStream(a: String, b: Reader, c: Int): CallableStatementIO[Unit] = - FF.liftF(SetCharacterStream4(a, b, c)) - def setCharacterStream(a: String, b: Reader, c: Long): CallableStatementIO[Unit] = - FF.liftF(SetCharacterStream5(a, b, c)) - def setClob(a: Int, b: Clob): CallableStatementIO[Unit] = FF.liftF(SetClob(a, b)) - def setClob(a: Int, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetClob1(a, b)) - def setClob(a: Int, b: Reader, c: Long): CallableStatementIO[Unit] = FF.liftF(SetClob2(a, b, c)) - def setClob(a: String, b: Clob): CallableStatementIO[Unit] = FF.liftF(SetClob3(a, b)) - def setClob(a: String, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetClob4(a, b)) - def setClob(a: String, b: Reader, c: Long): CallableStatementIO[Unit] = FF.liftF(SetClob5(a, b, c)) - def setCursorName(a: String): CallableStatementIO[Unit] = FF.liftF(SetCursorName(a)) - def setDate(a: Int, b: Date): CallableStatementIO[Unit] = FF.liftF(SetDate(a, b)) - def setDate(a: Int, b: Date, c: Calendar): CallableStatementIO[Unit] = FF.liftF(SetDate1(a, b, c)) - def setDate(a: String, b: Date): CallableStatementIO[Unit] = FF.liftF(SetDate2(a, b)) - def setDate(a: String, b: Date, c: Calendar): CallableStatementIO[Unit] = FF.liftF(SetDate3(a, b, c)) - def setDouble(a: Int, b: Double): CallableStatementIO[Unit] = FF.liftF(SetDouble(a, b)) - def setDouble(a: String, b: Double): CallableStatementIO[Unit] = FF.liftF(SetDouble1(a, b)) - def setEscapeProcessing(a: Boolean): CallableStatementIO[Unit] = FF.liftF(SetEscapeProcessing(a)) - def setFetchDirection(a: Int): CallableStatementIO[Unit] = FF.liftF(SetFetchDirection(a)) - def setFetchSize(a: Int): CallableStatementIO[Unit] = FF.liftF(SetFetchSize(a)) - def setFloat(a: Int, b: Float): CallableStatementIO[Unit] = FF.liftF(SetFloat(a, b)) - def setFloat(a: String, b: Float): CallableStatementIO[Unit] = FF.liftF(SetFloat1(a, b)) - def setInt(a: Int, b: Int): CallableStatementIO[Unit] = FF.liftF(SetInt(a, b)) - def setInt(a: String, b: Int): CallableStatementIO[Unit] = FF.liftF(SetInt1(a, b)) - def setLargeMaxRows(a: Long): CallableStatementIO[Unit] = FF.liftF(SetLargeMaxRows(a)) - def setLong(a: Int, b: Long): CallableStatementIO[Unit] = FF.liftF(SetLong(a, b)) - def setLong(a: String, b: Long): CallableStatementIO[Unit] = FF.liftF(SetLong1(a, b)) - def setMaxFieldSize(a: Int): CallableStatementIO[Unit] = FF.liftF(SetMaxFieldSize(a)) - def setMaxRows(a: Int): CallableStatementIO[Unit] = FF.liftF(SetMaxRows(a)) - def setNCharacterStream(a: Int, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetNCharacterStream(a, b)) - def setNCharacterStream(a: Int, b: Reader, c: Long): CallableStatementIO[Unit] = - FF.liftF(SetNCharacterStream1(a, b, c)) - def setNCharacterStream(a: String, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetNCharacterStream2(a, b)) - def setNCharacterStream(a: String, b: Reader, c: Long): CallableStatementIO[Unit] = - FF.liftF(SetNCharacterStream3(a, b, c)) - def setNClob(a: Int, b: NClob): CallableStatementIO[Unit] = FF.liftF(SetNClob(a, b)) - def setNClob(a: Int, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetNClob1(a, b)) - def setNClob(a: Int, b: Reader, c: Long): CallableStatementIO[Unit] = FF.liftF(SetNClob2(a, b, c)) - def setNClob(a: String, b: NClob): CallableStatementIO[Unit] = FF.liftF(SetNClob3(a, b)) - def setNClob(a: String, b: Reader): CallableStatementIO[Unit] = FF.liftF(SetNClob4(a, b)) - def setNClob(a: String, b: Reader, c: Long): CallableStatementIO[Unit] = FF.liftF(SetNClob5(a, b, c)) - def setNString(a: Int, b: String): CallableStatementIO[Unit] = FF.liftF(SetNString(a, b)) - def setNString(a: String, b: String): CallableStatementIO[Unit] = FF.liftF(SetNString1(a, b)) - def setNull(a: Int, b: Int): CallableStatementIO[Unit] = FF.liftF(SetNull(a, b)) - def setNull(a: Int, b: Int, c: String): CallableStatementIO[Unit] = FF.liftF(SetNull1(a, b, c)) - def setNull(a: String, b: Int): CallableStatementIO[Unit] = FF.liftF(SetNull2(a, b)) - def setNull(a: String, b: Int, c: String): CallableStatementIO[Unit] = FF.liftF(SetNull3(a, b, c)) - def setObject(a: Int, b: AnyRef): CallableStatementIO[Unit] = FF.liftF(SetObject(a, b)) - def setObject(a: Int, b: AnyRef, c: Int): CallableStatementIO[Unit] = FF.liftF(SetObject1(a, b, c)) - def setObject(a: Int, b: AnyRef, c: Int, d: Int): CallableStatementIO[Unit] = FF.liftF(SetObject2(a, b, c, d)) - def setObject(a: Int, b: AnyRef, c: SQLType): CallableStatementIO[Unit] = FF.liftF(SetObject3(a, b, c)) - def setObject(a: Int, b: AnyRef, c: SQLType, d: Int): CallableStatementIO[Unit] = FF.liftF(SetObject4(a, b, c, d)) - def setObject(a: String, b: AnyRef): CallableStatementIO[Unit] = FF.liftF(SetObject5(a, b)) - def setObject(a: String, b: AnyRef, c: Int): CallableStatementIO[Unit] = FF.liftF(SetObject6(a, b, c)) - def setObject(a: String, b: AnyRef, c: Int, d: Int): CallableStatementIO[Unit] = FF.liftF(SetObject7(a, b, c, d)) - def setObject(a: String, b: AnyRef, c: SQLType): CallableStatementIO[Unit] = FF.liftF(SetObject8(a, b, c)) - def setObject(a: String, b: AnyRef, c: SQLType, d: Int): CallableStatementIO[Unit] = FF.liftF(SetObject9(a, b, c, d)) - def setPoolable(a: Boolean): CallableStatementIO[Unit] = FF.liftF(SetPoolable(a)) - def setQueryTimeout(a: Int): CallableStatementIO[Unit] = FF.liftF(SetQueryTimeout(a)) - def setRef(a: Int, b: Ref): CallableStatementIO[Unit] = FF.liftF(SetRef(a, b)) - def setRowId(a: Int, b: RowId): CallableStatementIO[Unit] = FF.liftF(SetRowId(a, b)) - def setRowId(a: String, b: RowId): CallableStatementIO[Unit] = FF.liftF(SetRowId1(a, b)) - def setSQLXML(a: Int, b: SQLXML): CallableStatementIO[Unit] = FF.liftF(SetSQLXML(a, b)) - def setSQLXML(a: String, b: SQLXML): CallableStatementIO[Unit] = FF.liftF(SetSQLXML1(a, b)) - def setShort(a: Int, b: Short): CallableStatementIO[Unit] = FF.liftF(SetShort(a, b)) - def setShort(a: String, b: Short): CallableStatementIO[Unit] = FF.liftF(SetShort1(a, b)) - def setString(a: Int, b: String): CallableStatementIO[Unit] = FF.liftF(SetString(a, b)) - def setString(a: String, b: String): CallableStatementIO[Unit] = FF.liftF(SetString1(a, b)) - def setTime(a: Int, b: Time): CallableStatementIO[Unit] = FF.liftF(SetTime(a, b)) - def setTime(a: Int, b: Time, c: Calendar): CallableStatementIO[Unit] = FF.liftF(SetTime1(a, b, c)) - def setTime(a: String, b: Time): CallableStatementIO[Unit] = FF.liftF(SetTime2(a, b)) - def setTime(a: String, b: Time, c: Calendar): CallableStatementIO[Unit] = FF.liftF(SetTime3(a, b, c)) - def setTimestamp(a: Int, b: Timestamp): CallableStatementIO[Unit] = FF.liftF(SetTimestamp(a, b)) - def setTimestamp(a: Int, b: Timestamp, c: Calendar): CallableStatementIO[Unit] = FF.liftF(SetTimestamp1(a, b, c)) - def setTimestamp(a: String, b: Timestamp): CallableStatementIO[Unit] = FF.liftF(SetTimestamp2(a, b)) - def setTimestamp(a: String, b: Timestamp, c: Calendar): CallableStatementIO[Unit] = FF.liftF(SetTimestamp3(a, b, c)) - def setURL(a: Int, b: URL): CallableStatementIO[Unit] = FF.liftF(SetURL(a, b)) - def setURL(a: String, b: URL): CallableStatementIO[Unit] = FF.liftF(SetURL1(a, b)) - def unwrap[T](a: Class[T]): CallableStatementIO[T] = FF.liftF(Unwrap(a)) - val wasNull: CallableStatementIO[Boolean] = FF.liftF(WasNull) - - private val monad = FF.catsFreeMonadForFree[CallableStatementOp] - - // Typeclass instances for CallableStatementIO - implicit val SyncCallableStatementIO: Sync[CallableStatementIO] = - new Sync[CallableStatementIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): CallableStatementIO[A] = monad.pure(x) - override def map[A, B](fa: CallableStatementIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: CallableStatementIO[A])(f: A => CallableStatementIO[B]): CallableStatementIO[B] = - monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => CallableStatementIO[Either[A, B]]): CallableStatementIO[B] = - monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): CallableStatementIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: CallableStatementIO[A])( - f: Throwable => CallableStatementIO[A], - ): CallableStatementIO[A] = module.handleErrorWith(fa)(f) - override def monotonic: CallableStatementIO[FiniteDuration] = module.monotonic - override def realTime: CallableStatementIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): CallableStatementIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: CallableStatementIO[A])(fb: CallableStatementIO[B]): CallableStatementIO[B] = - module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[CallableStatementIO] => CallableStatementIO[A]): CallableStatementIO[A] = - module.uncancelable(body) - override def canceled: CallableStatementIO[Unit] = module.canceled - override def onCancel[A](fa: CallableStatementIO[A], fin: CallableStatementIO[Unit]): CallableStatementIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidCallableStatementIO[A](implicit M: Monoid[A]): Monoid[CallableStatementIO[A]] = - new Monoid[CallableStatementIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: CallableStatementIO[A], y: CallableStatementIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/clob.scala b/modules/free/src/main/scala/doobie/free/clob.scala deleted file mode 100644 index fe5b2b190..000000000 --- a/modules/free/src/main/scala/doobie/free/clob.scala +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.OutputStream -import java.io.Reader -import java.io.Writer -import java.sql.Clob -import scala.concurrent.duration.FiniteDuration - -object clob { module => - - // Algebra of operations for Clob. Each accepts a visitor as an alternative to pattern-matching. - sealed trait ClobOp[A] { - def visit[F[_]](v: ClobOp.Visitor[F]): F[A] - } - - // Free monad over ClobOp. - type ClobIO[A] = FF[ClobOp, A] - - // Module of instances and constructors of ClobOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object ClobOp { - - // Given a Clob we can embed a ClobIO program in any algebra that understands embedding. - implicit val ClobOpEmbeddable: Embeddable[ClobOp, Clob] = - new Embeddable[ClobOp, Clob] { - def embed[A](j: Clob, fa: FF[ClobOp, A]) = Embedded.Clob(j, fa) - } - - // Interface for a natural transformation ClobOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (ClobOp ~> F) { - final def apply[A](fa: ClobOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: Clob => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: ClobIO[A])(f: Throwable => ClobIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: ClobIO[A])(fb: ClobIO[B]): F[B] - def uncancelable[A](body: Poll[ClobIO] => ClobIO[A]): F[A] - def poll[A](poll: Any, fa: ClobIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: ClobIO[A], fin: ClobIO[Unit]): F[A] - - // Clob - def free: F[Unit] - def getAsciiStream: F[InputStream] - def getCharacterStream: F[Reader] - def getCharacterStream(a: Long, b: Long): F[Reader] - def getSubString(a: Long, b: Int): F[String] - def length: F[Long] - def position(a: Clob, b: Long): F[Long] - def position(a: String, b: Long): F[Long] - def setAsciiStream(a: Long): F[OutputStream] - def setCharacterStream(a: Long): F[Writer] - def setString(a: Long, b: String): F[Int] - def setString(a: Long, b: String, c: Int, d: Int): F[Int] - def truncate(a: Long): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: Clob => A) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: ClobIO[A], f: Throwable => ClobIO[A]) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends ClobOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends ClobOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: ClobIO[A], fb: ClobIO[B]) extends ClobOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[ClobIO] => ClobIO[A]) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: ClobIO[A]) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends ClobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: ClobIO[A], fin: ClobIO[Unit]) extends ClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // Clob-specific operations. - case object Free extends ClobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.free - } - case object GetAsciiStream extends ClobOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getAsciiStream - } - case object GetCharacterStream extends ClobOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream - } - final case class GetCharacterStream1(a: Long, b: Long) extends ClobOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream(a, b) - } - final case class GetSubString(a: Long, b: Int) extends ClobOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSubString(a, b) - } - case object Length extends ClobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.length - } - final case class Position(a: Clob, b: Long) extends ClobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.position(a, b) - } - final case class Position1(a: String, b: Long) extends ClobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.position(a, b) - } - final case class SetAsciiStream(a: Long) extends ClobOp[OutputStream] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a) - } - final case class SetCharacterStream(a: Long) extends ClobOp[Writer] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a) - } - final case class SetString(a: Long, b: String) extends ClobOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b) - } - final case class SetString1(a: Long, b: String, c: Int, d: Int) extends ClobOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b, c, d) - } - final case class Truncate(a: Long) extends ClobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.truncate(a) - } - - } - import ClobOp.* - - // Smart constructors for operations common to all algebras. - val unit: ClobIO[Unit] = FF.pure[ClobOp, Unit](()) - def pure[A](a: A): ClobIO[A] = FF.pure[ClobOp, A](a) - def raw[A](f: Clob => A): ClobIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[ClobOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): ClobIO[A] = FF.liftF[ClobOp, A](RaiseError(err)) - def handleErrorWith[A](fa: ClobIO[A])(f: Throwable => ClobIO[A]): ClobIO[A] = - FF.liftF[ClobOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[ClobOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[ClobOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[ClobOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[ClobOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: ClobIO[A])(fb: ClobIO[B]) = FF.liftF[ClobOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[ClobIO] => ClobIO[A]) = FF.liftF[ClobOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[ClobIO] { - def apply[A](fa: ClobIO[A]) = FF.liftF[ClobOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[ClobOp, Unit](Canceled) - def onCancel[A](fa: ClobIO[A], fin: ClobIO[Unit]) = FF.liftF[ClobOp, A](OnCancel(fa, fin)) - - // Smart constructors for Clob-specific operations. - val free: ClobIO[Unit] = FF.liftF(Free) - val getAsciiStream: ClobIO[InputStream] = FF.liftF(GetAsciiStream) - val getCharacterStream: ClobIO[Reader] = FF.liftF(GetCharacterStream) - def getCharacterStream(a: Long, b: Long): ClobIO[Reader] = FF.liftF(GetCharacterStream1(a, b)) - def getSubString(a: Long, b: Int): ClobIO[String] = FF.liftF(GetSubString(a, b)) - val length: ClobIO[Long] = FF.liftF(Length) - def position(a: Clob, b: Long): ClobIO[Long] = FF.liftF(Position(a, b)) - def position(a: String, b: Long): ClobIO[Long] = FF.liftF(Position1(a, b)) - def setAsciiStream(a: Long): ClobIO[OutputStream] = FF.liftF(SetAsciiStream(a)) - def setCharacterStream(a: Long): ClobIO[Writer] = FF.liftF(SetCharacterStream(a)) - def setString(a: Long, b: String): ClobIO[Int] = FF.liftF(SetString(a, b)) - def setString(a: Long, b: String, c: Int, d: Int): ClobIO[Int] = FF.liftF(SetString1(a, b, c, d)) - def truncate(a: Long): ClobIO[Unit] = FF.liftF(Truncate(a)) - - private val monad = FF.catsFreeMonadForFree[ClobOp] - - // Typeclass instances for ClobIO - implicit val SyncClobIO: Sync[ClobIO] = - new Sync[ClobIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): ClobIO[A] = monad.pure(x) - override def map[A, B](fa: ClobIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: ClobIO[A])(f: A => ClobIO[B]): ClobIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => ClobIO[Either[A, B]]): ClobIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): ClobIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: ClobIO[A])(f: Throwable => ClobIO[A]): ClobIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: ClobIO[FiniteDuration] = module.monotonic - override def realTime: ClobIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): ClobIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: ClobIO[A])(fb: ClobIO[B]): ClobIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[ClobIO] => ClobIO[A]): ClobIO[A] = module.uncancelable(body) - override def canceled: ClobIO[Unit] = module.canceled - override def onCancel[A](fa: ClobIO[A], fin: ClobIO[Unit]): ClobIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidClobIO[A](implicit M: Monoid[A]): Monoid[ClobIO[A]] = - new Monoid[ClobIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: ClobIO[A], y: ClobIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/connection.scala b/modules/free/src/main/scala/doobie/free/connection.scala deleted file mode 100644 index 417523f20..000000000 --- a/modules/free/src/main/scala/doobie/free/connection.scala +++ /dev/null @@ -1,474 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.CallableStatement -import java.sql.Clob -import java.sql.Connection -import java.sql.DatabaseMetaData -import java.sql.NClob -import java.sql.PreparedStatement -import java.sql.SQLWarning -import java.sql.SQLXML -import java.sql.Savepoint -import java.sql.ShardingKey -import java.sql.Statement -import java.sql.Struct -import java.util.Properties -import java.util.concurrent.Executor -import scala.concurrent.duration.FiniteDuration - -object connection { module => - - // Algebra of operations for Connection. Each accepts a visitor as an alternative to pattern-matching. - sealed trait ConnectionOp[A] { - def visit[F[_]](v: ConnectionOp.Visitor[F]): F[A] - } - - // Free monad over ConnectionOp. - type ConnectionIO[A] = FF[ConnectionOp, A] - - // Module of instances and constructors of ConnectionOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object ConnectionOp { - - // Given a Connection we can embed a ConnectionIO program in any algebra that understands embedding. - implicit val ConnectionOpEmbeddable: Embeddable[ConnectionOp, Connection] = - new Embeddable[ConnectionOp, Connection] { - def embed[A](j: Connection, fa: FF[ConnectionOp, A]) = Embedded.Connection(j, fa) - } - - // Interface for a natural transformation ConnectionOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (ConnectionOp ~> F) { - final def apply[A](fa: ConnectionOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: Connection => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: ConnectionIO[A])(f: Throwable => ConnectionIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: ConnectionIO[A])(fb: ConnectionIO[B]): F[B] - def uncancelable[A](body: Poll[ConnectionIO] => ConnectionIO[A]): F[A] - def poll[A](poll: Any, fa: ConnectionIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: ConnectionIO[A], fin: ConnectionIO[Unit]): F[A] - - // Connection - def abort(a: Executor): F[Unit] - def beginRequest: F[Unit] - def clearWarnings: F[Unit] - def close: F[Unit] - def commit: F[Unit] - def createArrayOf(a: String, b: Array[AnyRef]): F[SqlArray] - def createBlob: F[Blob] - def createClob: F[Clob] - def createNClob: F[NClob] - def createSQLXML: F[SQLXML] - def createStatement: F[Statement] - def createStatement(a: Int, b: Int): F[Statement] - def createStatement(a: Int, b: Int, c: Int): F[Statement] - def createStruct(a: String, b: Array[AnyRef]): F[Struct] - def endRequest: F[Unit] - def getAutoCommit: F[Boolean] - def getCatalog: F[String] - def getClientInfo: F[Properties] - def getClientInfo(a: String): F[String] - def getHoldability: F[Int] - def getMetaData: F[DatabaseMetaData] - def getNetworkTimeout: F[Int] - def getSchema: F[String] - def getTransactionIsolation: F[Int] - def getTypeMap: F[java.util.Map[String, Class[?]]] - def getWarnings: F[SQLWarning] - def isClosed: F[Boolean] - def isReadOnly: F[Boolean] - def isValid(a: Int): F[Boolean] - def isWrapperFor(a: Class[?]): F[Boolean] - def nativeSQL(a: String): F[String] - def prepareCall(a: String): F[CallableStatement] - def prepareCall(a: String, b: Int, c: Int): F[CallableStatement] - def prepareCall(a: String, b: Int, c: Int, d: Int): F[CallableStatement] - def prepareStatement(a: String): F[PreparedStatement] - def prepareStatement(a: String, b: Array[Int]): F[PreparedStatement] - def prepareStatement(a: String, b: Array[String]): F[PreparedStatement] - def prepareStatement(a: String, b: Int): F[PreparedStatement] - def prepareStatement(a: String, b: Int, c: Int): F[PreparedStatement] - def prepareStatement(a: String, b: Int, c: Int, d: Int): F[PreparedStatement] - def releaseSavepoint(a: Savepoint): F[Unit] - def rollback: F[Unit] - def rollback(a: Savepoint): F[Unit] - def setAutoCommit(a: Boolean): F[Unit] - def setCatalog(a: String): F[Unit] - def setClientInfo(a: Properties): F[Unit] - def setClientInfo(a: String, b: String): F[Unit] - def setHoldability(a: Int): F[Unit] - def setNetworkTimeout(a: Executor, b: Int): F[Unit] - def setReadOnly(a: Boolean): F[Unit] - def setSavepoint: F[Savepoint] - def setSavepoint(a: String): F[Savepoint] - def setSchema(a: String): F[Unit] - def setShardingKey(a: ShardingKey): F[Unit] - def setShardingKey(a: ShardingKey, b: ShardingKey): F[Unit] - def setShardingKeyIfValid(a: ShardingKey, b: Int): F[Boolean] - def setShardingKeyIfValid(a: ShardingKey, b: ShardingKey, c: Int): F[Boolean] - def setTransactionIsolation(a: Int): F[Unit] - def setTypeMap(a: java.util.Map[String, Class[?]]): F[Unit] - def unwrap[T](a: Class[T]): F[T] - - } - - // Common operations for all algebras. - final case class Raw[A](f: Connection => A) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: ConnectionIO[A], f: Throwable => ConnectionIO[A]) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends ConnectionOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends ConnectionOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: ConnectionIO[A], fb: ConnectionIO[B]) extends ConnectionOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[ConnectionIO] => ConnectionIO[A]) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: ConnectionIO[A]) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: ConnectionIO[A], fin: ConnectionIO[Unit]) extends ConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // Connection-specific operations. - final case class Abort(a: Executor) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.abort(a) - } - case object BeginRequest extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.beginRequest - } - case object ClearWarnings extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearWarnings - } - case object Close extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.close - } - case object Commit extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.commit - } - final case class CreateArrayOf(a: String, b: Array[AnyRef]) extends ConnectionOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.createArrayOf(a, b) - } - case object CreateBlob extends ConnectionOp[Blob] { - def visit[F[_]](v: Visitor[F]) = v.createBlob - } - case object CreateClob extends ConnectionOp[Clob] { - def visit[F[_]](v: Visitor[F]) = v.createClob - } - case object CreateNClob extends ConnectionOp[NClob] { - def visit[F[_]](v: Visitor[F]) = v.createNClob - } - case object CreateSQLXML extends ConnectionOp[SQLXML] { - def visit[F[_]](v: Visitor[F]) = v.createSQLXML - } - case object CreateStatement extends ConnectionOp[Statement] { - def visit[F[_]](v: Visitor[F]) = v.createStatement - } - final case class CreateStatement1(a: Int, b: Int) extends ConnectionOp[Statement] { - def visit[F[_]](v: Visitor[F]) = v.createStatement(a, b) - } - final case class CreateStatement2(a: Int, b: Int, c: Int) extends ConnectionOp[Statement] { - def visit[F[_]](v: Visitor[F]) = v.createStatement(a, b, c) - } - final case class CreateStruct(a: String, b: Array[AnyRef]) extends ConnectionOp[Struct] { - def visit[F[_]](v: Visitor[F]) = v.createStruct(a, b) - } - case object EndRequest extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.endRequest - } - case object GetAutoCommit extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getAutoCommit - } - case object GetCatalog extends ConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getCatalog - } - case object GetClientInfo extends ConnectionOp[Properties] { - def visit[F[_]](v: Visitor[F]) = v.getClientInfo - } - final case class GetClientInfo1(a: String) extends ConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getClientInfo(a) - } - case object GetHoldability extends ConnectionOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getHoldability - } - case object GetMetaData extends ConnectionOp[DatabaseMetaData] { - def visit[F[_]](v: Visitor[F]) = v.getMetaData - } - case object GetNetworkTimeout extends ConnectionOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getNetworkTimeout - } - case object GetSchema extends ConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSchema - } - case object GetTransactionIsolation extends ConnectionOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getTransactionIsolation - } - case object GetTypeMap extends ConnectionOp[java.util.Map[String, Class[?]]] { - def visit[F[_]](v: Visitor[F]) = v.getTypeMap - } - case object GetWarnings extends ConnectionOp[SQLWarning] { - def visit[F[_]](v: Visitor[F]) = v.getWarnings - } - case object IsClosed extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isClosed - } - case object IsReadOnly extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isReadOnly - } - final case class IsValid(a: Int) extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isValid(a) - } - final case class IsWrapperFor(a: Class[?]) extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isWrapperFor(a) - } - final case class NativeSQL(a: String) extends ConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.nativeSQL(a) - } - final case class PrepareCall(a: String) extends ConnectionOp[CallableStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareCall(a) - } - final case class PrepareCall1(a: String, b: Int, c: Int) extends ConnectionOp[CallableStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareCall(a, b, c) - } - final case class PrepareCall2(a: String, b: Int, c: Int, d: Int) extends ConnectionOp[CallableStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareCall(a, b, c, d) - } - final case class PrepareStatement(a: String) extends ConnectionOp[PreparedStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareStatement(a) - } - final case class PrepareStatement1(a: String, b: Array[Int]) extends ConnectionOp[PreparedStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareStatement(a, b) - } - final case class PrepareStatement2(a: String, b: Array[String]) extends ConnectionOp[PreparedStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareStatement(a, b) - } - final case class PrepareStatement3(a: String, b: Int) extends ConnectionOp[PreparedStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareStatement(a, b) - } - final case class PrepareStatement4(a: String, b: Int, c: Int) extends ConnectionOp[PreparedStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareStatement(a, b, c) - } - final case class PrepareStatement5(a: String, b: Int, c: Int, d: Int) extends ConnectionOp[PreparedStatement] { - def visit[F[_]](v: Visitor[F]) = v.prepareStatement(a, b, c, d) - } - final case class ReleaseSavepoint(a: Savepoint) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.releaseSavepoint(a) - } - case object Rollback extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.rollback - } - final case class Rollback1(a: Savepoint) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.rollback(a) - } - final case class SetAutoCommit(a: Boolean) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAutoCommit(a) - } - final case class SetCatalog(a: String) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCatalog(a) - } - final case class SetClientInfo(a: Properties) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClientInfo(a) - } - final case class SetClientInfo1(a: String, b: String) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClientInfo(a, b) - } - final case class SetHoldability(a: Int) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setHoldability(a) - } - final case class SetNetworkTimeout(a: Executor, b: Int) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNetworkTimeout(a, b) - } - final case class SetReadOnly(a: Boolean) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setReadOnly(a) - } - case object SetSavepoint extends ConnectionOp[Savepoint] { - def visit[F[_]](v: Visitor[F]) = v.setSavepoint - } - final case class SetSavepoint1(a: String) extends ConnectionOp[Savepoint] { - def visit[F[_]](v: Visitor[F]) = v.setSavepoint(a) - } - final case class SetSchema(a: String) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setSchema(a) - } - final case class SetShardingKey(a: ShardingKey) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setShardingKey(a) - } - final case class SetShardingKey1(a: ShardingKey, b: ShardingKey) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setShardingKey(a, b) - } - final case class SetShardingKeyIfValid(a: ShardingKey, b: Int) extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.setShardingKeyIfValid(a, b) - } - final case class SetShardingKeyIfValid1(a: ShardingKey, b: ShardingKey, c: Int) extends ConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.setShardingKeyIfValid(a, b, c) - } - final case class SetTransactionIsolation(a: Int) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTransactionIsolation(a) - } - final case class SetTypeMap(a: java.util.Map[String, Class[?]]) extends ConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTypeMap(a) - } - final case class Unwrap[T](a: Class[T]) extends ConnectionOp[T] { - def visit[F[_]](v: Visitor[F]) = v.unwrap(a) - } - - } - import ConnectionOp.* - - // Smart constructors for operations common to all algebras. - val unit: ConnectionIO[Unit] = FF.pure[ConnectionOp, Unit](()) - def pure[A](a: A): ConnectionIO[A] = FF.pure[ConnectionOp, A](a) - def raw[A](f: Connection => A): ConnectionIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[ConnectionOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): ConnectionIO[A] = FF.liftF[ConnectionOp, A](RaiseError(err)) - def handleErrorWith[A](fa: ConnectionIO[A])(f: Throwable => ConnectionIO[A]): ConnectionIO[A] = - FF.liftF[ConnectionOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[ConnectionOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[ConnectionOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[ConnectionOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[ConnectionOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: ConnectionIO[A])(fb: ConnectionIO[B]) = FF.liftF[ConnectionOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[ConnectionIO] => ConnectionIO[A]) = FF.liftF[ConnectionOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[ConnectionIO] { - def apply[A](fa: ConnectionIO[A]) = FF.liftF[ConnectionOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[ConnectionOp, Unit](Canceled) - def onCancel[A](fa: ConnectionIO[A], fin: ConnectionIO[Unit]) = FF.liftF[ConnectionOp, A](OnCancel(fa, fin)) - - // Smart constructors for Connection-specific operations. - def abort(a: Executor): ConnectionIO[Unit] = FF.liftF(Abort(a)) - val beginRequest: ConnectionIO[Unit] = FF.liftF(BeginRequest) - val clearWarnings: ConnectionIO[Unit] = FF.liftF(ClearWarnings) - val close: ConnectionIO[Unit] = FF.liftF(Close) - val commit: ConnectionIO[Unit] = FF.liftF(Commit) - def createArrayOf(a: String, b: Array[AnyRef]): ConnectionIO[SqlArray] = FF.liftF(CreateArrayOf(a, b)) - val createBlob: ConnectionIO[Blob] = FF.liftF(CreateBlob) - val createClob: ConnectionIO[Clob] = FF.liftF(CreateClob) - val createNClob: ConnectionIO[NClob] = FF.liftF(CreateNClob) - val createSQLXML: ConnectionIO[SQLXML] = FF.liftF(CreateSQLXML) - val createStatement: ConnectionIO[Statement] = FF.liftF(CreateStatement) - def createStatement(a: Int, b: Int): ConnectionIO[Statement] = FF.liftF(CreateStatement1(a, b)) - def createStatement(a: Int, b: Int, c: Int): ConnectionIO[Statement] = FF.liftF(CreateStatement2(a, b, c)) - def createStruct(a: String, b: Array[AnyRef]): ConnectionIO[Struct] = FF.liftF(CreateStruct(a, b)) - val endRequest: ConnectionIO[Unit] = FF.liftF(EndRequest) - val getAutoCommit: ConnectionIO[Boolean] = FF.liftF(GetAutoCommit) - val getCatalog: ConnectionIO[String] = FF.liftF(GetCatalog) - val getClientInfo: ConnectionIO[Properties] = FF.liftF(GetClientInfo) - def getClientInfo(a: String): ConnectionIO[String] = FF.liftF(GetClientInfo1(a)) - val getHoldability: ConnectionIO[Int] = FF.liftF(GetHoldability) - val getMetaData: ConnectionIO[DatabaseMetaData] = FF.liftF(GetMetaData) - val getNetworkTimeout: ConnectionIO[Int] = FF.liftF(GetNetworkTimeout) - val getSchema: ConnectionIO[String] = FF.liftF(GetSchema) - val getTransactionIsolation: ConnectionIO[Int] = FF.liftF(GetTransactionIsolation) - val getTypeMap: ConnectionIO[java.util.Map[String, Class[?]]] = FF.liftF(GetTypeMap) - val getWarnings: ConnectionIO[SQLWarning] = FF.liftF(GetWarnings) - val isClosed: ConnectionIO[Boolean] = FF.liftF(IsClosed) - val isReadOnly: ConnectionIO[Boolean] = FF.liftF(IsReadOnly) - def isValid(a: Int): ConnectionIO[Boolean] = FF.liftF(IsValid(a)) - def isWrapperFor(a: Class[?]): ConnectionIO[Boolean] = FF.liftF(IsWrapperFor(a)) - def nativeSQL(a: String): ConnectionIO[String] = FF.liftF(NativeSQL(a)) - def prepareCall(a: String): ConnectionIO[CallableStatement] = FF.liftF(PrepareCall(a)) - def prepareCall(a: String, b: Int, c: Int): ConnectionIO[CallableStatement] = FF.liftF(PrepareCall1(a, b, c)) - def prepareCall(a: String, b: Int, c: Int, d: Int): ConnectionIO[CallableStatement] = - FF.liftF(PrepareCall2(a, b, c, d)) - def prepareStatement(a: String): ConnectionIO[PreparedStatement] = FF.liftF(PrepareStatement(a)) - def prepareStatement(a: String, b: Array[Int]): ConnectionIO[PreparedStatement] = FF.liftF(PrepareStatement1(a, b)) - def prepareStatement(a: String, b: Array[String]): ConnectionIO[PreparedStatement] = FF.liftF(PrepareStatement2(a, b)) - def prepareStatement(a: String, b: Int): ConnectionIO[PreparedStatement] = FF.liftF(PrepareStatement3(a, b)) - def prepareStatement(a: String, b: Int, c: Int): ConnectionIO[PreparedStatement] = FF.liftF(PrepareStatement4(a, b, c)) - def prepareStatement(a: String, b: Int, c: Int, d: Int): ConnectionIO[PreparedStatement] = - FF.liftF(PrepareStatement5(a, b, c, d)) - def releaseSavepoint(a: Savepoint): ConnectionIO[Unit] = FF.liftF(ReleaseSavepoint(a)) - val rollback: ConnectionIO[Unit] = FF.liftF(Rollback) - def rollback(a: Savepoint): ConnectionIO[Unit] = FF.liftF(Rollback1(a)) - def setAutoCommit(a: Boolean): ConnectionIO[Unit] = FF.liftF(SetAutoCommit(a)) - def setCatalog(a: String): ConnectionIO[Unit] = FF.liftF(SetCatalog(a)) - def setClientInfo(a: Properties): ConnectionIO[Unit] = FF.liftF(SetClientInfo(a)) - def setClientInfo(a: String, b: String): ConnectionIO[Unit] = FF.liftF(SetClientInfo1(a, b)) - def setHoldability(a: Int): ConnectionIO[Unit] = FF.liftF(SetHoldability(a)) - def setNetworkTimeout(a: Executor, b: Int): ConnectionIO[Unit] = FF.liftF(SetNetworkTimeout(a, b)) - def setReadOnly(a: Boolean): ConnectionIO[Unit] = FF.liftF(SetReadOnly(a)) - val setSavepoint: ConnectionIO[Savepoint] = FF.liftF(SetSavepoint) - def setSavepoint(a: String): ConnectionIO[Savepoint] = FF.liftF(SetSavepoint1(a)) - def setSchema(a: String): ConnectionIO[Unit] = FF.liftF(SetSchema(a)) - def setShardingKey(a: ShardingKey): ConnectionIO[Unit] = FF.liftF(SetShardingKey(a)) - def setShardingKey(a: ShardingKey, b: ShardingKey): ConnectionIO[Unit] = FF.liftF(SetShardingKey1(a, b)) - def setShardingKeyIfValid(a: ShardingKey, b: Int): ConnectionIO[Boolean] = FF.liftF(SetShardingKeyIfValid(a, b)) - def setShardingKeyIfValid(a: ShardingKey, b: ShardingKey, c: Int): ConnectionIO[Boolean] = - FF.liftF(SetShardingKeyIfValid1(a, b, c)) - def setTransactionIsolation(a: Int): ConnectionIO[Unit] = FF.liftF(SetTransactionIsolation(a)) - def setTypeMap(a: java.util.Map[String, Class[?]]): ConnectionIO[Unit] = FF.liftF(SetTypeMap(a)) - def unwrap[T](a: Class[T]): ConnectionIO[T] = FF.liftF(Unwrap(a)) - - private val monad = FF.catsFreeMonadForFree[ConnectionOp] - - // Typeclass instances for ConnectionIO - implicit val SyncConnectionIO: Sync[ConnectionIO] = - new Sync[ConnectionIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): ConnectionIO[A] = monad.pure(x) - override def map[A, B](fa: ConnectionIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: ConnectionIO[A])(f: A => ConnectionIO[B]): ConnectionIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => ConnectionIO[Either[A, B]]): ConnectionIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): ConnectionIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: ConnectionIO[A])(f: Throwable => ConnectionIO[A]): ConnectionIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: ConnectionIO[FiniteDuration] = module.monotonic - override def realTime: ConnectionIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): ConnectionIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: ConnectionIO[A])(fb: ConnectionIO[B]): ConnectionIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[ConnectionIO] => ConnectionIO[A]): ConnectionIO[A] = - module.uncancelable(body) - override def canceled: ConnectionIO[Unit] = module.canceled - override def onCancel[A](fa: ConnectionIO[A], fin: ConnectionIO[Unit]): ConnectionIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidConnectionIO[A](implicit M: Monoid[A]): Monoid[ConnectionIO[A]] = - new Monoid[ConnectionIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: ConnectionIO[A], y: ConnectionIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/databasemetadata.scala b/modules/free/src/main/scala/doobie/free/databasemetadata.scala deleted file mode 100644 index aecc90f59..000000000 --- a/modules/free/src/main/scala/doobie/free/databasemetadata.scala +++ /dev/null @@ -1,1096 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.sql.Connection -import java.sql.DatabaseMetaData -import java.sql.ResultSet -import java.sql.RowIdLifetime -import scala.concurrent.duration.FiniteDuration - -object databasemetadata { module => - - // Algebra of operations for DatabaseMetaData. Each accepts a visitor as an alternative to pattern-matching. - sealed trait DatabaseMetaDataOp[A] { - def visit[F[_]](v: DatabaseMetaDataOp.Visitor[F]): F[A] - } - - // Free monad over DatabaseMetaDataOp. - type DatabaseMetaDataIO[A] = FF[DatabaseMetaDataOp, A] - - // Module of instances and constructors of DatabaseMetaDataOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object DatabaseMetaDataOp { - - // Given a DatabaseMetaData we can embed a DatabaseMetaDataIO program in any algebra that understands embedding. - implicit val DatabaseMetaDataOpEmbeddable: Embeddable[DatabaseMetaDataOp, DatabaseMetaData] = - new Embeddable[DatabaseMetaDataOp, DatabaseMetaData] { - def embed[A](j: DatabaseMetaData, fa: FF[DatabaseMetaDataOp, A]) = Embedded.DatabaseMetaData(j, fa) - } - - // Interface for a natural transformation DatabaseMetaDataOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (DatabaseMetaDataOp ~> F) { - final def apply[A](fa: DatabaseMetaDataOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: DatabaseMetaData => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: DatabaseMetaDataIO[A])(f: Throwable => DatabaseMetaDataIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: DatabaseMetaDataIO[A])(fb: DatabaseMetaDataIO[B]): F[B] - def uncancelable[A](body: Poll[DatabaseMetaDataIO] => DatabaseMetaDataIO[A]): F[A] - def poll[A](poll: Any, fa: DatabaseMetaDataIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: DatabaseMetaDataIO[A], fin: DatabaseMetaDataIO[Unit]): F[A] - - // DatabaseMetaData - def allProceduresAreCallable: F[Boolean] - def allTablesAreSelectable: F[Boolean] - def autoCommitFailureClosesAllResultSets: F[Boolean] - def dataDefinitionCausesTransactionCommit: F[Boolean] - def dataDefinitionIgnoredInTransactions: F[Boolean] - def deletesAreDetected(a: Int): F[Boolean] - def doesMaxRowSizeIncludeBlobs: F[Boolean] - def generatedKeyAlwaysReturned: F[Boolean] - def getAttributes(a: String, b: String, c: String, d: String): F[ResultSet] - def getBestRowIdentifier(a: String, b: String, c: String, d: Int, e: Boolean): F[ResultSet] - def getCatalogSeparator: F[String] - def getCatalogTerm: F[String] - def getCatalogs: F[ResultSet] - def getClientInfoProperties: F[ResultSet] - def getColumnPrivileges(a: String, b: String, c: String, d: String): F[ResultSet] - def getColumns(a: String, b: String, c: String, d: String): F[ResultSet] - def getConnection: F[Connection] - def getCrossReference(a: String, b: String, c: String, d: String, e: String, f: String): F[ResultSet] - def getDatabaseMajorVersion: F[Int] - def getDatabaseMinorVersion: F[Int] - def getDatabaseProductName: F[String] - def getDatabaseProductVersion: F[String] - def getDefaultTransactionIsolation: F[Int] - def getDriverMajorVersion: F[Int] - def getDriverMinorVersion: F[Int] - def getDriverName: F[String] - def getDriverVersion: F[String] - def getExportedKeys(a: String, b: String, c: String): F[ResultSet] - def getExtraNameCharacters: F[String] - def getFunctionColumns(a: String, b: String, c: String, d: String): F[ResultSet] - def getFunctions(a: String, b: String, c: String): F[ResultSet] - def getIdentifierQuoteString: F[String] - def getImportedKeys(a: String, b: String, c: String): F[ResultSet] - def getIndexInfo(a: String, b: String, c: String, d: Boolean, e: Boolean): F[ResultSet] - def getJDBCMajorVersion: F[Int] - def getJDBCMinorVersion: F[Int] - def getMaxBinaryLiteralLength: F[Int] - def getMaxCatalogNameLength: F[Int] - def getMaxCharLiteralLength: F[Int] - def getMaxColumnNameLength: F[Int] - def getMaxColumnsInGroupBy: F[Int] - def getMaxColumnsInIndex: F[Int] - def getMaxColumnsInOrderBy: F[Int] - def getMaxColumnsInSelect: F[Int] - def getMaxColumnsInTable: F[Int] - def getMaxConnections: F[Int] - def getMaxCursorNameLength: F[Int] - def getMaxIndexLength: F[Int] - def getMaxLogicalLobSize: F[Long] - def getMaxProcedureNameLength: F[Int] - def getMaxRowSize: F[Int] - def getMaxSchemaNameLength: F[Int] - def getMaxStatementLength: F[Int] - def getMaxStatements: F[Int] - def getMaxTableNameLength: F[Int] - def getMaxTablesInSelect: F[Int] - def getMaxUserNameLength: F[Int] - def getNumericFunctions: F[String] - def getPrimaryKeys(a: String, b: String, c: String): F[ResultSet] - def getProcedureColumns(a: String, b: String, c: String, d: String): F[ResultSet] - def getProcedureTerm: F[String] - def getProcedures(a: String, b: String, c: String): F[ResultSet] - def getPseudoColumns(a: String, b: String, c: String, d: String): F[ResultSet] - def getResultSetHoldability: F[Int] - def getRowIdLifetime: F[RowIdLifetime] - def getSQLKeywords: F[String] - def getSQLStateType: F[Int] - def getSchemaTerm: F[String] - def getSchemas: F[ResultSet] - def getSchemas(a: String, b: String): F[ResultSet] - def getSearchStringEscape: F[String] - def getStringFunctions: F[String] - def getSuperTables(a: String, b: String, c: String): F[ResultSet] - def getSuperTypes(a: String, b: String, c: String): F[ResultSet] - def getSystemFunctions: F[String] - def getTablePrivileges(a: String, b: String, c: String): F[ResultSet] - def getTableTypes: F[ResultSet] - def getTables(a: String, b: String, c: String, d: Array[String]): F[ResultSet] - def getTimeDateFunctions: F[String] - def getTypeInfo: F[ResultSet] - def getUDTs(a: String, b: String, c: String, d: Array[Int]): F[ResultSet] - def getURL: F[String] - def getUserName: F[String] - def getVersionColumns(a: String, b: String, c: String): F[ResultSet] - def insertsAreDetected(a: Int): F[Boolean] - def isCatalogAtStart: F[Boolean] - def isReadOnly: F[Boolean] - def isWrapperFor(a: Class[?]): F[Boolean] - def locatorsUpdateCopy: F[Boolean] - def nullPlusNonNullIsNull: F[Boolean] - def nullsAreSortedAtEnd: F[Boolean] - def nullsAreSortedAtStart: F[Boolean] - def nullsAreSortedHigh: F[Boolean] - def nullsAreSortedLow: F[Boolean] - def othersDeletesAreVisible(a: Int): F[Boolean] - def othersInsertsAreVisible(a: Int): F[Boolean] - def othersUpdatesAreVisible(a: Int): F[Boolean] - def ownDeletesAreVisible(a: Int): F[Boolean] - def ownInsertsAreVisible(a: Int): F[Boolean] - def ownUpdatesAreVisible(a: Int): F[Boolean] - def storesLowerCaseIdentifiers: F[Boolean] - def storesLowerCaseQuotedIdentifiers: F[Boolean] - def storesMixedCaseIdentifiers: F[Boolean] - def storesMixedCaseQuotedIdentifiers: F[Boolean] - def storesUpperCaseIdentifiers: F[Boolean] - def storesUpperCaseQuotedIdentifiers: F[Boolean] - def supportsANSI92EntryLevelSQL: F[Boolean] - def supportsANSI92FullSQL: F[Boolean] - def supportsANSI92IntermediateSQL: F[Boolean] - def supportsAlterTableWithAddColumn: F[Boolean] - def supportsAlterTableWithDropColumn: F[Boolean] - def supportsBatchUpdates: F[Boolean] - def supportsCatalogsInDataManipulation: F[Boolean] - def supportsCatalogsInIndexDefinitions: F[Boolean] - def supportsCatalogsInPrivilegeDefinitions: F[Boolean] - def supportsCatalogsInProcedureCalls: F[Boolean] - def supportsCatalogsInTableDefinitions: F[Boolean] - def supportsColumnAliasing: F[Boolean] - def supportsConvert: F[Boolean] - def supportsConvert(a: Int, b: Int): F[Boolean] - def supportsCoreSQLGrammar: F[Boolean] - def supportsCorrelatedSubqueries: F[Boolean] - def supportsDataDefinitionAndDataManipulationTransactions: F[Boolean] - def supportsDataManipulationTransactionsOnly: F[Boolean] - def supportsDifferentTableCorrelationNames: F[Boolean] - def supportsExpressionsInOrderBy: F[Boolean] - def supportsExtendedSQLGrammar: F[Boolean] - def supportsFullOuterJoins: F[Boolean] - def supportsGetGeneratedKeys: F[Boolean] - def supportsGroupBy: F[Boolean] - def supportsGroupByBeyondSelect: F[Boolean] - def supportsGroupByUnrelated: F[Boolean] - def supportsIntegrityEnhancementFacility: F[Boolean] - def supportsLikeEscapeClause: F[Boolean] - def supportsLimitedOuterJoins: F[Boolean] - def supportsMinimumSQLGrammar: F[Boolean] - def supportsMixedCaseIdentifiers: F[Boolean] - def supportsMixedCaseQuotedIdentifiers: F[Boolean] - def supportsMultipleOpenResults: F[Boolean] - def supportsMultipleResultSets: F[Boolean] - def supportsMultipleTransactions: F[Boolean] - def supportsNamedParameters: F[Boolean] - def supportsNonNullableColumns: F[Boolean] - def supportsOpenCursorsAcrossCommit: F[Boolean] - def supportsOpenCursorsAcrossRollback: F[Boolean] - def supportsOpenStatementsAcrossCommit: F[Boolean] - def supportsOpenStatementsAcrossRollback: F[Boolean] - def supportsOrderByUnrelated: F[Boolean] - def supportsOuterJoins: F[Boolean] - def supportsPositionedDelete: F[Boolean] - def supportsPositionedUpdate: F[Boolean] - def supportsRefCursors: F[Boolean] - def supportsResultSetConcurrency(a: Int, b: Int): F[Boolean] - def supportsResultSetHoldability(a: Int): F[Boolean] - def supportsResultSetType(a: Int): F[Boolean] - def supportsSavepoints: F[Boolean] - def supportsSchemasInDataManipulation: F[Boolean] - def supportsSchemasInIndexDefinitions: F[Boolean] - def supportsSchemasInPrivilegeDefinitions: F[Boolean] - def supportsSchemasInProcedureCalls: F[Boolean] - def supportsSchemasInTableDefinitions: F[Boolean] - def supportsSelectForUpdate: F[Boolean] - def supportsSharding: F[Boolean] - def supportsStatementPooling: F[Boolean] - def supportsStoredFunctionsUsingCallSyntax: F[Boolean] - def supportsStoredProcedures: F[Boolean] - def supportsSubqueriesInComparisons: F[Boolean] - def supportsSubqueriesInExists: F[Boolean] - def supportsSubqueriesInIns: F[Boolean] - def supportsSubqueriesInQuantifieds: F[Boolean] - def supportsTableCorrelationNames: F[Boolean] - def supportsTransactionIsolationLevel(a: Int): F[Boolean] - def supportsTransactions: F[Boolean] - def supportsUnion: F[Boolean] - def supportsUnionAll: F[Boolean] - def unwrap[T](a: Class[T]): F[T] - def updatesAreDetected(a: Int): F[Boolean] - def usesLocalFilePerTable: F[Boolean] - def usesLocalFiles: F[Boolean] - - } - - // Common operations for all algebras. - final case class Raw[A](f: DatabaseMetaData => A) extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: DatabaseMetaDataIO[A], f: Throwable => DatabaseMetaDataIO[A]) - extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends DatabaseMetaDataOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends DatabaseMetaDataOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: DatabaseMetaDataIO[A], fb: DatabaseMetaDataIO[B]) extends DatabaseMetaDataOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[DatabaseMetaDataIO] => DatabaseMetaDataIO[A]) - extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: DatabaseMetaDataIO[A]) extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends DatabaseMetaDataOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: DatabaseMetaDataIO[A], fin: DatabaseMetaDataIO[Unit]) extends DatabaseMetaDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // DatabaseMetaData-specific operations. - case object AllProceduresAreCallable extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.allProceduresAreCallable - } - case object AllTablesAreSelectable extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.allTablesAreSelectable - } - case object AutoCommitFailureClosesAllResultSets extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.autoCommitFailureClosesAllResultSets - } - case object DataDefinitionCausesTransactionCommit extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.dataDefinitionCausesTransactionCommit - } - case object DataDefinitionIgnoredInTransactions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.dataDefinitionIgnoredInTransactions - } - final case class DeletesAreDetected(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.deletesAreDetected(a) - } - case object DoesMaxRowSizeIncludeBlobs extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.doesMaxRowSizeIncludeBlobs - } - case object GeneratedKeyAlwaysReturned extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.generatedKeyAlwaysReturned - } - final case class GetAttributes(a: String, b: String, c: String, d: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getAttributes(a, b, c, d) - } - final case class GetBestRowIdentifier(a: String, b: String, c: String, d: Int, e: Boolean) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getBestRowIdentifier(a, b, c, d, e) - } - case object GetCatalogSeparator extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getCatalogSeparator - } - case object GetCatalogTerm extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getCatalogTerm - } - case object GetCatalogs extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getCatalogs - } - case object GetClientInfoProperties extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getClientInfoProperties - } - final case class GetColumnPrivileges(a: String, b: String, c: String, d: String) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getColumnPrivileges(a, b, c, d) - } - final case class GetColumns(a: String, b: String, c: String, d: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getColumns(a, b, c, d) - } - case object GetConnection extends DatabaseMetaDataOp[Connection] { - def visit[F[_]](v: Visitor[F]) = v.getConnection - } - final case class GetCrossReference(a: String, b: String, c: String, d: String, e: String, f: String) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getCrossReference(a, b, c, d, e, f) - } - case object GetDatabaseMajorVersion extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getDatabaseMajorVersion - } - case object GetDatabaseMinorVersion extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getDatabaseMinorVersion - } - case object GetDatabaseProductName extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getDatabaseProductName - } - case object GetDatabaseProductVersion extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getDatabaseProductVersion - } - case object GetDefaultTransactionIsolation extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getDefaultTransactionIsolation - } - case object GetDriverMajorVersion extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getDriverMajorVersion - } - case object GetDriverMinorVersion extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getDriverMinorVersion - } - case object GetDriverName extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getDriverName - } - case object GetDriverVersion extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getDriverVersion - } - final case class GetExportedKeys(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getExportedKeys(a, b, c) - } - case object GetExtraNameCharacters extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getExtraNameCharacters - } - final case class GetFunctionColumns(a: String, b: String, c: String, d: String) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getFunctionColumns(a, b, c, d) - } - final case class GetFunctions(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getFunctions(a, b, c) - } - case object GetIdentifierQuoteString extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getIdentifierQuoteString - } - final case class GetImportedKeys(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getImportedKeys(a, b, c) - } - final case class GetIndexInfo(a: String, b: String, c: String, d: Boolean, e: Boolean) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getIndexInfo(a, b, c, d, e) - } - case object GetJDBCMajorVersion extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getJDBCMajorVersion - } - case object GetJDBCMinorVersion extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getJDBCMinorVersion - } - case object GetMaxBinaryLiteralLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxBinaryLiteralLength - } - case object GetMaxCatalogNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxCatalogNameLength - } - case object GetMaxCharLiteralLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxCharLiteralLength - } - case object GetMaxColumnNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxColumnNameLength - } - case object GetMaxColumnsInGroupBy extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxColumnsInGroupBy - } - case object GetMaxColumnsInIndex extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxColumnsInIndex - } - case object GetMaxColumnsInOrderBy extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxColumnsInOrderBy - } - case object GetMaxColumnsInSelect extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxColumnsInSelect - } - case object GetMaxColumnsInTable extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxColumnsInTable - } - case object GetMaxConnections extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxConnections - } - case object GetMaxCursorNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxCursorNameLength - } - case object GetMaxIndexLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxIndexLength - } - case object GetMaxLogicalLobSize extends DatabaseMetaDataOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getMaxLogicalLobSize - } - case object GetMaxProcedureNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxProcedureNameLength - } - case object GetMaxRowSize extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxRowSize - } - case object GetMaxSchemaNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxSchemaNameLength - } - case object GetMaxStatementLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxStatementLength - } - case object GetMaxStatements extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxStatements - } - case object GetMaxTableNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxTableNameLength - } - case object GetMaxTablesInSelect extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxTablesInSelect - } - case object GetMaxUserNameLength extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxUserNameLength - } - case object GetNumericFunctions extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getNumericFunctions - } - final case class GetPrimaryKeys(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getPrimaryKeys(a, b, c) - } - final case class GetProcedureColumns(a: String, b: String, c: String, d: String) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getProcedureColumns(a, b, c, d) - } - case object GetProcedureTerm extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getProcedureTerm - } - final case class GetProcedures(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getProcedures(a, b, c) - } - final case class GetPseudoColumns(a: String, b: String, c: String, d: String) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getPseudoColumns(a, b, c, d) - } - case object GetResultSetHoldability extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetHoldability - } - case object GetRowIdLifetime extends DatabaseMetaDataOp[RowIdLifetime] { - def visit[F[_]](v: Visitor[F]) = v.getRowIdLifetime - } - case object GetSQLKeywords extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSQLKeywords - } - case object GetSQLStateType extends DatabaseMetaDataOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getSQLStateType - } - case object GetSchemaTerm extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSchemaTerm - } - case object GetSchemas extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getSchemas - } - final case class GetSchemas1(a: String, b: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getSchemas(a, b) - } - case object GetSearchStringEscape extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSearchStringEscape - } - case object GetStringFunctions extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getStringFunctions - } - final case class GetSuperTables(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getSuperTables(a, b, c) - } - final case class GetSuperTypes(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getSuperTypes(a, b, c) - } - case object GetSystemFunctions extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSystemFunctions - } - final case class GetTablePrivileges(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getTablePrivileges(a, b, c) - } - case object GetTableTypes extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getTableTypes - } - final case class GetTables(a: String, b: String, c: String, d: Array[String]) - extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getTables(a, b, c, d) - } - case object GetTimeDateFunctions extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getTimeDateFunctions - } - case object GetTypeInfo extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getTypeInfo - } - final case class GetUDTs(a: String, b: String, c: String, d: Array[Int]) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getUDTs(a, b, c, d) - } - case object GetURL extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getURL - } - case object GetUserName extends DatabaseMetaDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getUserName - } - final case class GetVersionColumns(a: String, b: String, c: String) extends DatabaseMetaDataOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getVersionColumns(a, b, c) - } - final case class InsertsAreDetected(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.insertsAreDetected(a) - } - case object IsCatalogAtStart extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isCatalogAtStart - } - case object IsReadOnly extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isReadOnly - } - final case class IsWrapperFor(a: Class[?]) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isWrapperFor(a) - } - case object LocatorsUpdateCopy extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.locatorsUpdateCopy - } - case object NullPlusNonNullIsNull extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.nullPlusNonNullIsNull - } - case object NullsAreSortedAtEnd extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.nullsAreSortedAtEnd - } - case object NullsAreSortedAtStart extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.nullsAreSortedAtStart - } - case object NullsAreSortedHigh extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.nullsAreSortedHigh - } - case object NullsAreSortedLow extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.nullsAreSortedLow - } - final case class OthersDeletesAreVisible(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.othersDeletesAreVisible(a) - } - final case class OthersInsertsAreVisible(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.othersInsertsAreVisible(a) - } - final case class OthersUpdatesAreVisible(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.othersUpdatesAreVisible(a) - } - final case class OwnDeletesAreVisible(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.ownDeletesAreVisible(a) - } - final case class OwnInsertsAreVisible(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.ownInsertsAreVisible(a) - } - final case class OwnUpdatesAreVisible(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.ownUpdatesAreVisible(a) - } - case object StoresLowerCaseIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.storesLowerCaseIdentifiers - } - case object StoresLowerCaseQuotedIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.storesLowerCaseQuotedIdentifiers - } - case object StoresMixedCaseIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.storesMixedCaseIdentifiers - } - case object StoresMixedCaseQuotedIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.storesMixedCaseQuotedIdentifiers - } - case object StoresUpperCaseIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.storesUpperCaseIdentifiers - } - case object StoresUpperCaseQuotedIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.storesUpperCaseQuotedIdentifiers - } - case object SupportsANSI92EntryLevelSQL extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsANSI92EntryLevelSQL - } - case object SupportsANSI92FullSQL extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsANSI92FullSQL - } - case object SupportsANSI92IntermediateSQL extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsANSI92IntermediateSQL - } - case object SupportsAlterTableWithAddColumn extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsAlterTableWithAddColumn - } - case object SupportsAlterTableWithDropColumn extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsAlterTableWithDropColumn - } - case object SupportsBatchUpdates extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsBatchUpdates - } - case object SupportsCatalogsInDataManipulation extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCatalogsInDataManipulation - } - case object SupportsCatalogsInIndexDefinitions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCatalogsInIndexDefinitions - } - case object SupportsCatalogsInPrivilegeDefinitions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCatalogsInPrivilegeDefinitions - } - case object SupportsCatalogsInProcedureCalls extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCatalogsInProcedureCalls - } - case object SupportsCatalogsInTableDefinitions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCatalogsInTableDefinitions - } - case object SupportsColumnAliasing extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsColumnAliasing - } - case object SupportsConvert extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsConvert - } - final case class SupportsConvert1(a: Int, b: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsConvert(a, b) - } - case object SupportsCoreSQLGrammar extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCoreSQLGrammar - } - case object SupportsCorrelatedSubqueries extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsCorrelatedSubqueries - } - case object SupportsDataDefinitionAndDataManipulationTransactions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsDataDefinitionAndDataManipulationTransactions - } - case object SupportsDataManipulationTransactionsOnly extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsDataManipulationTransactionsOnly - } - case object SupportsDifferentTableCorrelationNames extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsDifferentTableCorrelationNames - } - case object SupportsExpressionsInOrderBy extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsExpressionsInOrderBy - } - case object SupportsExtendedSQLGrammar extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsExtendedSQLGrammar - } - case object SupportsFullOuterJoins extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsFullOuterJoins - } - case object SupportsGetGeneratedKeys extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsGetGeneratedKeys - } - case object SupportsGroupBy extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsGroupBy - } - case object SupportsGroupByBeyondSelect extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsGroupByBeyondSelect - } - case object SupportsGroupByUnrelated extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsGroupByUnrelated - } - case object SupportsIntegrityEnhancementFacility extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsIntegrityEnhancementFacility - } - case object SupportsLikeEscapeClause extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsLikeEscapeClause - } - case object SupportsLimitedOuterJoins extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsLimitedOuterJoins - } - case object SupportsMinimumSQLGrammar extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsMinimumSQLGrammar - } - case object SupportsMixedCaseIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsMixedCaseIdentifiers - } - case object SupportsMixedCaseQuotedIdentifiers extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsMixedCaseQuotedIdentifiers - } - case object SupportsMultipleOpenResults extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsMultipleOpenResults - } - case object SupportsMultipleResultSets extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsMultipleResultSets - } - case object SupportsMultipleTransactions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsMultipleTransactions - } - case object SupportsNamedParameters extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsNamedParameters - } - case object SupportsNonNullableColumns extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsNonNullableColumns - } - case object SupportsOpenCursorsAcrossCommit extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsOpenCursorsAcrossCommit - } - case object SupportsOpenCursorsAcrossRollback extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsOpenCursorsAcrossRollback - } - case object SupportsOpenStatementsAcrossCommit extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsOpenStatementsAcrossCommit - } - case object SupportsOpenStatementsAcrossRollback extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsOpenStatementsAcrossRollback - } - case object SupportsOrderByUnrelated extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsOrderByUnrelated - } - case object SupportsOuterJoins extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsOuterJoins - } - case object SupportsPositionedDelete extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsPositionedDelete - } - case object SupportsPositionedUpdate extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsPositionedUpdate - } - case object SupportsRefCursors extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsRefCursors - } - final case class SupportsResultSetConcurrency(a: Int, b: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsResultSetConcurrency(a, b) - } - final case class SupportsResultSetHoldability(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsResultSetHoldability(a) - } - final case class SupportsResultSetType(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsResultSetType(a) - } - case object SupportsSavepoints extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSavepoints - } - case object SupportsSchemasInDataManipulation extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSchemasInDataManipulation - } - case object SupportsSchemasInIndexDefinitions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSchemasInIndexDefinitions - } - case object SupportsSchemasInPrivilegeDefinitions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSchemasInPrivilegeDefinitions - } - case object SupportsSchemasInProcedureCalls extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSchemasInProcedureCalls - } - case object SupportsSchemasInTableDefinitions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSchemasInTableDefinitions - } - case object SupportsSelectForUpdate extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSelectForUpdate - } - case object SupportsSharding extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSharding - } - case object SupportsStatementPooling extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsStatementPooling - } - case object SupportsStoredFunctionsUsingCallSyntax extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsStoredFunctionsUsingCallSyntax - } - case object SupportsStoredProcedures extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsStoredProcedures - } - case object SupportsSubqueriesInComparisons extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSubqueriesInComparisons - } - case object SupportsSubqueriesInExists extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSubqueriesInExists - } - case object SupportsSubqueriesInIns extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSubqueriesInIns - } - case object SupportsSubqueriesInQuantifieds extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsSubqueriesInQuantifieds - } - case object SupportsTableCorrelationNames extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsTableCorrelationNames - } - final case class SupportsTransactionIsolationLevel(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsTransactionIsolationLevel(a) - } - case object SupportsTransactions extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsTransactions - } - case object SupportsUnion extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsUnion - } - case object SupportsUnionAll extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.supportsUnionAll - } - final case class Unwrap[T](a: Class[T]) extends DatabaseMetaDataOp[T] { - def visit[F[_]](v: Visitor[F]) = v.unwrap(a) - } - final case class UpdatesAreDetected(a: Int) extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.updatesAreDetected(a) - } - case object UsesLocalFilePerTable extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.usesLocalFilePerTable - } - case object UsesLocalFiles extends DatabaseMetaDataOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.usesLocalFiles - } - - } - import DatabaseMetaDataOp.* - - // Smart constructors for operations common to all algebras. - val unit: DatabaseMetaDataIO[Unit] = FF.pure[DatabaseMetaDataOp, Unit](()) - def pure[A](a: A): DatabaseMetaDataIO[A] = FF.pure[DatabaseMetaDataOp, A](a) - def raw[A](f: DatabaseMetaData => A): DatabaseMetaDataIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[DatabaseMetaDataOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): DatabaseMetaDataIO[A] = FF.liftF[DatabaseMetaDataOp, A](RaiseError(err)) - def handleErrorWith[A](fa: DatabaseMetaDataIO[A])(f: Throwable => DatabaseMetaDataIO[A]): DatabaseMetaDataIO[A] = - FF.liftF[DatabaseMetaDataOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[DatabaseMetaDataOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[DatabaseMetaDataOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[DatabaseMetaDataOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[DatabaseMetaDataOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: DatabaseMetaDataIO[A])(fb: DatabaseMetaDataIO[B]) = - FF.liftF[DatabaseMetaDataOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[DatabaseMetaDataIO] => DatabaseMetaDataIO[A]) = - FF.liftF[DatabaseMetaDataOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[DatabaseMetaDataIO] { - def apply[A](fa: DatabaseMetaDataIO[A]) = FF.liftF[DatabaseMetaDataOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[DatabaseMetaDataOp, Unit](Canceled) - def onCancel[A](fa: DatabaseMetaDataIO[A], fin: DatabaseMetaDataIO[Unit]) = - FF.liftF[DatabaseMetaDataOp, A](OnCancel(fa, fin)) - - // Smart constructors for DatabaseMetaData-specific operations. - val allProceduresAreCallable: DatabaseMetaDataIO[Boolean] = FF.liftF(AllProceduresAreCallable) - val allTablesAreSelectable: DatabaseMetaDataIO[Boolean] = FF.liftF(AllTablesAreSelectable) - val autoCommitFailureClosesAllResultSets: DatabaseMetaDataIO[Boolean] = FF.liftF(AutoCommitFailureClosesAllResultSets) - val dataDefinitionCausesTransactionCommit: DatabaseMetaDataIO[Boolean] = - FF.liftF(DataDefinitionCausesTransactionCommit) - val dataDefinitionIgnoredInTransactions: DatabaseMetaDataIO[Boolean] = FF.liftF(DataDefinitionIgnoredInTransactions) - def deletesAreDetected(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(DeletesAreDetected(a)) - val doesMaxRowSizeIncludeBlobs: DatabaseMetaDataIO[Boolean] = FF.liftF(DoesMaxRowSizeIncludeBlobs) - val generatedKeyAlwaysReturned: DatabaseMetaDataIO[Boolean] = FF.liftF(GeneratedKeyAlwaysReturned) - def getAttributes(a: String, b: String, c: String, d: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetAttributes(a, b, c, d)) - def getBestRowIdentifier(a: String, b: String, c: String, d: Int, e: Boolean): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetBestRowIdentifier(a, b, c, d, e)) - val getCatalogSeparator: DatabaseMetaDataIO[String] = FF.liftF(GetCatalogSeparator) - val getCatalogTerm: DatabaseMetaDataIO[String] = FF.liftF(GetCatalogTerm) - val getCatalogs: DatabaseMetaDataIO[ResultSet] = FF.liftF(GetCatalogs) - val getClientInfoProperties: DatabaseMetaDataIO[ResultSet] = FF.liftF(GetClientInfoProperties) - def getColumnPrivileges(a: String, b: String, c: String, d: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetColumnPrivileges(a, b, c, d)) - def getColumns(a: String, b: String, c: String, d: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetColumns(a, b, c, d)) - val getConnection: DatabaseMetaDataIO[Connection] = FF.liftF(GetConnection) - def getCrossReference(a: String, b: String, c: String, d: String, e: String, f: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetCrossReference(a, b, c, d, e, f)) - val getDatabaseMajorVersion: DatabaseMetaDataIO[Int] = FF.liftF(GetDatabaseMajorVersion) - val getDatabaseMinorVersion: DatabaseMetaDataIO[Int] = FF.liftF(GetDatabaseMinorVersion) - val getDatabaseProductName: DatabaseMetaDataIO[String] = FF.liftF(GetDatabaseProductName) - val getDatabaseProductVersion: DatabaseMetaDataIO[String] = FF.liftF(GetDatabaseProductVersion) - val getDefaultTransactionIsolation: DatabaseMetaDataIO[Int] = FF.liftF(GetDefaultTransactionIsolation) - val getDriverMajorVersion: DatabaseMetaDataIO[Int] = FF.liftF(GetDriverMajorVersion) - val getDriverMinorVersion: DatabaseMetaDataIO[Int] = FF.liftF(GetDriverMinorVersion) - val getDriverName: DatabaseMetaDataIO[String] = FF.liftF(GetDriverName) - val getDriverVersion: DatabaseMetaDataIO[String] = FF.liftF(GetDriverVersion) - def getExportedKeys(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetExportedKeys(a, b, c)) - val getExtraNameCharacters: DatabaseMetaDataIO[String] = FF.liftF(GetExtraNameCharacters) - def getFunctionColumns(a: String, b: String, c: String, d: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetFunctionColumns(a, b, c, d)) - def getFunctions(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = FF.liftF(GetFunctions(a, b, c)) - val getIdentifierQuoteString: DatabaseMetaDataIO[String] = FF.liftF(GetIdentifierQuoteString) - def getImportedKeys(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetImportedKeys(a, b, c)) - def getIndexInfo(a: String, b: String, c: String, d: Boolean, e: Boolean): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetIndexInfo(a, b, c, d, e)) - val getJDBCMajorVersion: DatabaseMetaDataIO[Int] = FF.liftF(GetJDBCMajorVersion) - val getJDBCMinorVersion: DatabaseMetaDataIO[Int] = FF.liftF(GetJDBCMinorVersion) - val getMaxBinaryLiteralLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxBinaryLiteralLength) - val getMaxCatalogNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxCatalogNameLength) - val getMaxCharLiteralLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxCharLiteralLength) - val getMaxColumnNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxColumnNameLength) - val getMaxColumnsInGroupBy: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxColumnsInGroupBy) - val getMaxColumnsInIndex: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxColumnsInIndex) - val getMaxColumnsInOrderBy: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxColumnsInOrderBy) - val getMaxColumnsInSelect: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxColumnsInSelect) - val getMaxColumnsInTable: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxColumnsInTable) - val getMaxConnections: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxConnections) - val getMaxCursorNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxCursorNameLength) - val getMaxIndexLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxIndexLength) - val getMaxLogicalLobSize: DatabaseMetaDataIO[Long] = FF.liftF(GetMaxLogicalLobSize) - val getMaxProcedureNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxProcedureNameLength) - val getMaxRowSize: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxRowSize) - val getMaxSchemaNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxSchemaNameLength) - val getMaxStatementLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxStatementLength) - val getMaxStatements: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxStatements) - val getMaxTableNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxTableNameLength) - val getMaxTablesInSelect: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxTablesInSelect) - val getMaxUserNameLength: DatabaseMetaDataIO[Int] = FF.liftF(GetMaxUserNameLength) - val getNumericFunctions: DatabaseMetaDataIO[String] = FF.liftF(GetNumericFunctions) - def getPrimaryKeys(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = FF.liftF(GetPrimaryKeys(a, b, c)) - def getProcedureColumns(a: String, b: String, c: String, d: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetProcedureColumns(a, b, c, d)) - val getProcedureTerm: DatabaseMetaDataIO[String] = FF.liftF(GetProcedureTerm) - def getProcedures(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = FF.liftF(GetProcedures(a, b, c)) - def getPseudoColumns(a: String, b: String, c: String, d: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetPseudoColumns(a, b, c, d)) - val getResultSetHoldability: DatabaseMetaDataIO[Int] = FF.liftF(GetResultSetHoldability) - val getRowIdLifetime: DatabaseMetaDataIO[RowIdLifetime] = FF.liftF(GetRowIdLifetime) - val getSQLKeywords: DatabaseMetaDataIO[String] = FF.liftF(GetSQLKeywords) - val getSQLStateType: DatabaseMetaDataIO[Int] = FF.liftF(GetSQLStateType) - val getSchemaTerm: DatabaseMetaDataIO[String] = FF.liftF(GetSchemaTerm) - val getSchemas: DatabaseMetaDataIO[ResultSet] = FF.liftF(GetSchemas) - def getSchemas(a: String, b: String): DatabaseMetaDataIO[ResultSet] = FF.liftF(GetSchemas1(a, b)) - val getSearchStringEscape: DatabaseMetaDataIO[String] = FF.liftF(GetSearchStringEscape) - val getStringFunctions: DatabaseMetaDataIO[String] = FF.liftF(GetStringFunctions) - def getSuperTables(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = FF.liftF(GetSuperTables(a, b, c)) - def getSuperTypes(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = FF.liftF(GetSuperTypes(a, b, c)) - val getSystemFunctions: DatabaseMetaDataIO[String] = FF.liftF(GetSystemFunctions) - def getTablePrivileges(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetTablePrivileges(a, b, c)) - val getTableTypes: DatabaseMetaDataIO[ResultSet] = FF.liftF(GetTableTypes) - def getTables(a: String, b: String, c: String, d: Array[String]): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetTables(a, b, c, d)) - val getTimeDateFunctions: DatabaseMetaDataIO[String] = FF.liftF(GetTimeDateFunctions) - val getTypeInfo: DatabaseMetaDataIO[ResultSet] = FF.liftF(GetTypeInfo) - def getUDTs(a: String, b: String, c: String, d: Array[Int]): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetUDTs(a, b, c, d)) - val getURL: DatabaseMetaDataIO[String] = FF.liftF(GetURL) - val getUserName: DatabaseMetaDataIO[String] = FF.liftF(GetUserName) - def getVersionColumns(a: String, b: String, c: String): DatabaseMetaDataIO[ResultSet] = - FF.liftF(GetVersionColumns(a, b, c)) - def insertsAreDetected(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(InsertsAreDetected(a)) - val isCatalogAtStart: DatabaseMetaDataIO[Boolean] = FF.liftF(IsCatalogAtStart) - val isReadOnly: DatabaseMetaDataIO[Boolean] = FF.liftF(IsReadOnly) - def isWrapperFor(a: Class[?]): DatabaseMetaDataIO[Boolean] = FF.liftF(IsWrapperFor(a)) - val locatorsUpdateCopy: DatabaseMetaDataIO[Boolean] = FF.liftF(LocatorsUpdateCopy) - val nullPlusNonNullIsNull: DatabaseMetaDataIO[Boolean] = FF.liftF(NullPlusNonNullIsNull) - val nullsAreSortedAtEnd: DatabaseMetaDataIO[Boolean] = FF.liftF(NullsAreSortedAtEnd) - val nullsAreSortedAtStart: DatabaseMetaDataIO[Boolean] = FF.liftF(NullsAreSortedAtStart) - val nullsAreSortedHigh: DatabaseMetaDataIO[Boolean] = FF.liftF(NullsAreSortedHigh) - val nullsAreSortedLow: DatabaseMetaDataIO[Boolean] = FF.liftF(NullsAreSortedLow) - def othersDeletesAreVisible(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(OthersDeletesAreVisible(a)) - def othersInsertsAreVisible(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(OthersInsertsAreVisible(a)) - def othersUpdatesAreVisible(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(OthersUpdatesAreVisible(a)) - def ownDeletesAreVisible(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(OwnDeletesAreVisible(a)) - def ownInsertsAreVisible(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(OwnInsertsAreVisible(a)) - def ownUpdatesAreVisible(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(OwnUpdatesAreVisible(a)) - val storesLowerCaseIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(StoresLowerCaseIdentifiers) - val storesLowerCaseQuotedIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(StoresLowerCaseQuotedIdentifiers) - val storesMixedCaseIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(StoresMixedCaseIdentifiers) - val storesMixedCaseQuotedIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(StoresMixedCaseQuotedIdentifiers) - val storesUpperCaseIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(StoresUpperCaseIdentifiers) - val storesUpperCaseQuotedIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(StoresUpperCaseQuotedIdentifiers) - val supportsANSI92EntryLevelSQL: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsANSI92EntryLevelSQL) - val supportsANSI92FullSQL: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsANSI92FullSQL) - val supportsANSI92IntermediateSQL: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsANSI92IntermediateSQL) - val supportsAlterTableWithAddColumn: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsAlterTableWithAddColumn) - val supportsAlterTableWithDropColumn: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsAlterTableWithDropColumn) - val supportsBatchUpdates: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsBatchUpdates) - val supportsCatalogsInDataManipulation: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsCatalogsInDataManipulation) - val supportsCatalogsInIndexDefinitions: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsCatalogsInIndexDefinitions) - val supportsCatalogsInPrivilegeDefinitions: DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsCatalogsInPrivilegeDefinitions) - val supportsCatalogsInProcedureCalls: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsCatalogsInProcedureCalls) - val supportsCatalogsInTableDefinitions: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsCatalogsInTableDefinitions) - val supportsColumnAliasing: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsColumnAliasing) - val supportsConvert: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsConvert) - def supportsConvert(a: Int, b: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsConvert1(a, b)) - val supportsCoreSQLGrammar: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsCoreSQLGrammar) - val supportsCorrelatedSubqueries: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsCorrelatedSubqueries) - val supportsDataDefinitionAndDataManipulationTransactions: DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsDataDefinitionAndDataManipulationTransactions) - val supportsDataManipulationTransactionsOnly: DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsDataManipulationTransactionsOnly) - val supportsDifferentTableCorrelationNames: DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsDifferentTableCorrelationNames) - val supportsExpressionsInOrderBy: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsExpressionsInOrderBy) - val supportsExtendedSQLGrammar: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsExtendedSQLGrammar) - val supportsFullOuterJoins: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsFullOuterJoins) - val supportsGetGeneratedKeys: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsGetGeneratedKeys) - val supportsGroupBy: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsGroupBy) - val supportsGroupByBeyondSelect: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsGroupByBeyondSelect) - val supportsGroupByUnrelated: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsGroupByUnrelated) - val supportsIntegrityEnhancementFacility: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsIntegrityEnhancementFacility) - val supportsLikeEscapeClause: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsLikeEscapeClause) - val supportsLimitedOuterJoins: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsLimitedOuterJoins) - val supportsMinimumSQLGrammar: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsMinimumSQLGrammar) - val supportsMixedCaseIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsMixedCaseIdentifiers) - val supportsMixedCaseQuotedIdentifiers: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsMixedCaseQuotedIdentifiers) - val supportsMultipleOpenResults: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsMultipleOpenResults) - val supportsMultipleResultSets: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsMultipleResultSets) - val supportsMultipleTransactions: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsMultipleTransactions) - val supportsNamedParameters: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsNamedParameters) - val supportsNonNullableColumns: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsNonNullableColumns) - val supportsOpenCursorsAcrossCommit: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsOpenCursorsAcrossCommit) - val supportsOpenCursorsAcrossRollback: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsOpenCursorsAcrossRollback) - val supportsOpenStatementsAcrossCommit: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsOpenStatementsAcrossCommit) - val supportsOpenStatementsAcrossRollback: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsOpenStatementsAcrossRollback) - val supportsOrderByUnrelated: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsOrderByUnrelated) - val supportsOuterJoins: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsOuterJoins) - val supportsPositionedDelete: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsPositionedDelete) - val supportsPositionedUpdate: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsPositionedUpdate) - val supportsRefCursors: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsRefCursors) - def supportsResultSetConcurrency(a: Int, b: Int): DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsResultSetConcurrency(a, b)) - def supportsResultSetHoldability(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsResultSetHoldability(a)) - def supportsResultSetType(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsResultSetType(a)) - val supportsSavepoints: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSavepoints) - val supportsSchemasInDataManipulation: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSchemasInDataManipulation) - val supportsSchemasInIndexDefinitions: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSchemasInIndexDefinitions) - val supportsSchemasInPrivilegeDefinitions: DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsSchemasInPrivilegeDefinitions) - val supportsSchemasInProcedureCalls: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSchemasInProcedureCalls) - val supportsSchemasInTableDefinitions: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSchemasInTableDefinitions) - val supportsSelectForUpdate: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSelectForUpdate) - val supportsSharding: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSharding) - val supportsStatementPooling: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsStatementPooling) - val supportsStoredFunctionsUsingCallSyntax: DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsStoredFunctionsUsingCallSyntax) - val supportsStoredProcedures: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsStoredProcedures) - val supportsSubqueriesInComparisons: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSubqueriesInComparisons) - val supportsSubqueriesInExists: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSubqueriesInExists) - val supportsSubqueriesInIns: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSubqueriesInIns) - val supportsSubqueriesInQuantifieds: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsSubqueriesInQuantifieds) - val supportsTableCorrelationNames: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsTableCorrelationNames) - def supportsTransactionIsolationLevel(a: Int): DatabaseMetaDataIO[Boolean] = - FF.liftF(SupportsTransactionIsolationLevel(a)) - val supportsTransactions: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsTransactions) - val supportsUnion: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsUnion) - val supportsUnionAll: DatabaseMetaDataIO[Boolean] = FF.liftF(SupportsUnionAll) - def unwrap[T](a: Class[T]): DatabaseMetaDataIO[T] = FF.liftF(Unwrap(a)) - def updatesAreDetected(a: Int): DatabaseMetaDataIO[Boolean] = FF.liftF(UpdatesAreDetected(a)) - val usesLocalFilePerTable: DatabaseMetaDataIO[Boolean] = FF.liftF(UsesLocalFilePerTable) - val usesLocalFiles: DatabaseMetaDataIO[Boolean] = FF.liftF(UsesLocalFiles) - - private val monad = FF.catsFreeMonadForFree[DatabaseMetaDataOp] - - // Typeclass instances for DatabaseMetaDataIO - implicit val SyncDatabaseMetaDataIO: Sync[DatabaseMetaDataIO] = - new Sync[DatabaseMetaDataIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): DatabaseMetaDataIO[A] = monad.pure(x) - override def map[A, B](fa: DatabaseMetaDataIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: DatabaseMetaDataIO[A])(f: A => DatabaseMetaDataIO[B]): DatabaseMetaDataIO[B] = - monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => DatabaseMetaDataIO[Either[A, B]]): DatabaseMetaDataIO[B] = - monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): DatabaseMetaDataIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: DatabaseMetaDataIO[A])( - f: Throwable => DatabaseMetaDataIO[A], - ): DatabaseMetaDataIO[A] = module.handleErrorWith(fa)(f) - override def monotonic: DatabaseMetaDataIO[FiniteDuration] = module.monotonic - override def realTime: DatabaseMetaDataIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): DatabaseMetaDataIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: DatabaseMetaDataIO[A])(fb: DatabaseMetaDataIO[B]): DatabaseMetaDataIO[B] = - module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[DatabaseMetaDataIO] => DatabaseMetaDataIO[A]): DatabaseMetaDataIO[A] = - module.uncancelable(body) - override def canceled: DatabaseMetaDataIO[Unit] = module.canceled - override def onCancel[A](fa: DatabaseMetaDataIO[A], fin: DatabaseMetaDataIO[Unit]): DatabaseMetaDataIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidDatabaseMetaDataIO[A](implicit M: Monoid[A]): Monoid[DatabaseMetaDataIO[A]] = - new Monoid[DatabaseMetaDataIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: DatabaseMetaDataIO[A], y: DatabaseMetaDataIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/driver.scala b/modules/free/src/main/scala/doobie/free/driver.scala deleted file mode 100644 index 67450f7c9..000000000 --- a/modules/free/src/main/scala/doobie/free/driver.scala +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.sql.Connection -import java.sql.Driver -import java.sql.DriverPropertyInfo -import java.util.Properties -import java.util.logging.Logger -import scala.concurrent.duration.FiniteDuration - -object driver { module => - - // Algebra of operations for Driver. Each accepts a visitor as an alternative to pattern-matching. - sealed trait DriverOp[A] { - def visit[F[_]](v: DriverOp.Visitor[F]): F[A] - } - - // Free monad over DriverOp. - type DriverIO[A] = FF[DriverOp, A] - - // Module of instances and constructors of DriverOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object DriverOp { - - // Given a Driver we can embed a DriverIO program in any algebra that understands embedding. - implicit val DriverOpEmbeddable: Embeddable[DriverOp, Driver] = - new Embeddable[DriverOp, Driver] { - def embed[A](j: Driver, fa: FF[DriverOp, A]) = Embedded.Driver(j, fa) - } - - // Interface for a natural transformation DriverOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (DriverOp ~> F) { - final def apply[A](fa: DriverOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: Driver => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: DriverIO[A])(f: Throwable => DriverIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: DriverIO[A])(fb: DriverIO[B]): F[B] - def uncancelable[A](body: Poll[DriverIO] => DriverIO[A]): F[A] - def poll[A](poll: Any, fa: DriverIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: DriverIO[A], fin: DriverIO[Unit]): F[A] - - // Driver - def acceptsURL(a: String): F[Boolean] - def connect(a: String, b: Properties): F[Connection] - def getMajorVersion: F[Int] - def getMinorVersion: F[Int] - def getParentLogger: F[Logger] - def getPropertyInfo(a: String, b: Properties): F[Array[DriverPropertyInfo]] - def jdbcCompliant: F[Boolean] - - } - - // Common operations for all algebras. - final case class Raw[A](f: Driver => A) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: DriverIO[A], f: Throwable => DriverIO[A]) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends DriverOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends DriverOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: DriverIO[A], fb: DriverIO[B]) extends DriverOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[DriverIO] => DriverIO[A]) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: DriverIO[A]) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends DriverOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: DriverIO[A], fin: DriverIO[Unit]) extends DriverOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // Driver-specific operations. - final case class AcceptsURL(a: String) extends DriverOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.acceptsURL(a) - } - final case class Connect(a: String, b: Properties) extends DriverOp[Connection] { - def visit[F[_]](v: Visitor[F]) = v.connect(a, b) - } - case object GetMajorVersion extends DriverOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMajorVersion - } - case object GetMinorVersion extends DriverOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMinorVersion - } - case object GetParentLogger extends DriverOp[Logger] { - def visit[F[_]](v: Visitor[F]) = v.getParentLogger - } - final case class GetPropertyInfo(a: String, b: Properties) extends DriverOp[Array[DriverPropertyInfo]] { - def visit[F[_]](v: Visitor[F]) = v.getPropertyInfo(a, b) - } - case object JdbcCompliant extends DriverOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.jdbcCompliant - } - - } - import DriverOp.* - - // Smart constructors for operations common to all algebras. - val unit: DriverIO[Unit] = FF.pure[DriverOp, Unit](()) - def pure[A](a: A): DriverIO[A] = FF.pure[DriverOp, A](a) - def raw[A](f: Driver => A): DriverIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[DriverOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): DriverIO[A] = FF.liftF[DriverOp, A](RaiseError(err)) - def handleErrorWith[A](fa: DriverIO[A])(f: Throwable => DriverIO[A]): DriverIO[A] = - FF.liftF[DriverOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[DriverOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[DriverOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[DriverOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[DriverOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: DriverIO[A])(fb: DriverIO[B]) = FF.liftF[DriverOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[DriverIO] => DriverIO[A]) = FF.liftF[DriverOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[DriverIO] { - def apply[A](fa: DriverIO[A]) = FF.liftF[DriverOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[DriverOp, Unit](Canceled) - def onCancel[A](fa: DriverIO[A], fin: DriverIO[Unit]) = FF.liftF[DriverOp, A](OnCancel(fa, fin)) - - // Smart constructors for Driver-specific operations. - def acceptsURL(a: String): DriverIO[Boolean] = FF.liftF(AcceptsURL(a)) - def connect(a: String, b: Properties): DriverIO[Connection] = FF.liftF(Connect(a, b)) - val getMajorVersion: DriverIO[Int] = FF.liftF(GetMajorVersion) - val getMinorVersion: DriverIO[Int] = FF.liftF(GetMinorVersion) - val getParentLogger: DriverIO[Logger] = FF.liftF(GetParentLogger) - def getPropertyInfo(a: String, b: Properties): DriverIO[Array[DriverPropertyInfo]] = FF.liftF(GetPropertyInfo(a, b)) - val jdbcCompliant: DriverIO[Boolean] = FF.liftF(JdbcCompliant) - - private val monad = FF.catsFreeMonadForFree[DriverOp] - - // Typeclass instances for DriverIO - implicit val SyncDriverIO: Sync[DriverIO] = - new Sync[DriverIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): DriverIO[A] = monad.pure(x) - override def map[A, B](fa: DriverIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: DriverIO[A])(f: A => DriverIO[B]): DriverIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => DriverIO[Either[A, B]]): DriverIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): DriverIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: DriverIO[A])(f: Throwable => DriverIO[A]): DriverIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: DriverIO[FiniteDuration] = module.monotonic - override def realTime: DriverIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): DriverIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: DriverIO[A])(fb: DriverIO[B]): DriverIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[DriverIO] => DriverIO[A]): DriverIO[A] = module.uncancelable(body) - override def canceled: DriverIO[Unit] = module.canceled - override def onCancel[A](fa: DriverIO[A], fin: DriverIO[Unit]): DriverIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidDriverIO[A](implicit M: Monoid[A]): Monoid[DriverIO[A]] = - new Monoid[DriverIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: DriverIO[A], y: DriverIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/embedded.scala b/modules/free/src/main/scala/doobie/free/embedded.scala deleted file mode 100644 index 5a134ffef..000000000 --- a/modules/free/src/main/scala/doobie/free/embedded.scala +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import blob.BlobIO -import callablestatement.CallableStatementIO -import cats.free.Free -import clob.ClobIO -import connection.ConnectionIO -import databasemetadata.DatabaseMetaDataIO -import driver.DriverIO -import nclob.NClobIO -import preparedstatement.PreparedStatementIO -import ref.RefIO -import resultset.ResultSetIO -import sqldata.SQLDataIO -import sqlinput.SQLInputIO -import sqloutput.SQLOutputIO -import statement.StatementIO - -// A pair (J, Free[F, A]) with constructors that tie down J and F. -sealed trait Embedded[A] - -object Embedded { - final case class NClob[A](j: java.sql.NClob, fa: NClobIO[A]) extends Embedded[A] - final case class Blob[A](j: java.sql.Blob, fa: BlobIO[A]) extends Embedded[A] - final case class Clob[A](j: java.sql.Clob, fa: ClobIO[A]) extends Embedded[A] - final case class DatabaseMetaData[A](j: java.sql.DatabaseMetaData, fa: DatabaseMetaDataIO[A]) extends Embedded[A] - final case class Driver[A](j: java.sql.Driver, fa: DriverIO[A]) extends Embedded[A] - final case class Ref[A](j: java.sql.Ref, fa: RefIO[A]) extends Embedded[A] - final case class SQLData[A](j: java.sql.SQLData, fa: SQLDataIO[A]) extends Embedded[A] - final case class SQLInput[A](j: java.sql.SQLInput, fa: SQLInputIO[A]) extends Embedded[A] - final case class SQLOutput[A](j: java.sql.SQLOutput, fa: SQLOutputIO[A]) extends Embedded[A] - final case class Connection[A](j: java.sql.Connection, fa: ConnectionIO[A]) extends Embedded[A] - final case class Statement[A](j: java.sql.Statement, fa: StatementIO[A]) extends Embedded[A] - final case class PreparedStatement[A](j: java.sql.PreparedStatement, fa: PreparedStatementIO[A]) extends Embedded[A] - final case class CallableStatement[A](j: java.sql.CallableStatement, fa: CallableStatementIO[A]) extends Embedded[A] - final case class ResultSet[A](j: java.sql.ResultSet, fa: ResultSetIO[A]) extends Embedded[A] -} - -// Typeclass for embeddable pairs (J, F) -trait Embeddable[F[_], J] { - def embed[A](j: J, fa: Free[F, A]): Embedded[A] -} diff --git a/modules/free/src/main/scala/doobie/free/kleisliinterpreter.scala b/modules/free/src/main/scala/doobie/free/kleisliinterpreter.scala deleted file mode 100644 index 9aa8c9dec..000000000 --- a/modules/free/src/main/scala/doobie/free/kleisliinterpreter.scala +++ /dev/null @@ -1,1549 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.data.Kleisli -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free -import cats.~> -import doobie.free.blob.BlobIO -import doobie.free.blob.BlobOp -import doobie.free.callablestatement.CallableStatementIO -import doobie.free.callablestatement.CallableStatementOp -import doobie.free.clob.ClobIO -import doobie.free.clob.ClobOp -import doobie.free.connection.ConnectionIO -import doobie.free.connection.ConnectionOp -import doobie.free.databasemetadata.DatabaseMetaDataIO -import doobie.free.databasemetadata.DatabaseMetaDataOp -import doobie.free.driver.DriverIO -import doobie.free.driver.DriverOp -import doobie.free.nclob.NClobIO -import doobie.free.nclob.NClobOp -import doobie.free.preparedstatement.PreparedStatementIO -import doobie.free.preparedstatement.PreparedStatementOp -import doobie.free.ref.RefIO -import doobie.free.ref.RefOp -import doobie.free.resultset.ResultSetIO -import doobie.free.resultset.ResultSetOp -import doobie.free.sqldata.SQLDataIO -import doobie.free.sqldata.SQLDataOp -import doobie.free.sqlinput.SQLInputIO -import doobie.free.sqlinput.SQLInputOp -import doobie.free.sqloutput.SQLOutputIO -import doobie.free.sqloutput.SQLOutputOp -import doobie.free.statement.StatementIO -import doobie.free.statement.StatementOp - -import java.io.InputStream -import java.io.Reader -import java.math.BigDecimal -import java.net.URL -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.CallableStatement -import java.sql.Clob -import java.sql.Connection -import java.sql.DatabaseMetaData -import java.sql.Date -import java.sql.Driver -import java.sql.NClob -import java.sql.ParameterMetaData -import java.sql.PreparedStatement -import java.sql.Ref -import java.sql.ResultSet -import java.sql.ResultSetMetaData -import java.sql.RowId -import java.sql.RowIdLifetime -import java.sql.SQLData -import java.sql.SQLInput -import java.sql.SQLOutput -import java.sql.SQLType -import java.sql.SQLWarning -import java.sql.SQLXML -import java.sql.Savepoint -import java.sql.ShardingKey -import java.sql.Statement -import java.sql.Struct -import java.sql.Time -import java.sql.Timestamp -import java.util.Calendar -import java.util.Properties -import java.util.concurrent.Executor -import java.util.logging.Logger -import scala.concurrent.duration.FiniteDuration - -object KleisliInterpreter { - def apply[M[_]](implicit M: Sync[M]): KleisliInterpreter[M] = new KleisliInterpreter[M] -} - -// Family of interpreters into Kleisli arrows for some monad M. -class KleisliInterpreter[M[_]](implicit val syncM: Sync[M]) { outer => - - // The 14 interpreters, with definitions below. These can be overridden to customize behavior. - lazy val NClobInterpreter: NClobOp ~> Kleisli[M, NClob, *] = new NClobInterpreter {} - lazy val BlobInterpreter: BlobOp ~> Kleisli[M, Blob, *] = new BlobInterpreter {} - lazy val ClobInterpreter: ClobOp ~> Kleisli[M, Clob, *] = new ClobInterpreter {} - lazy val DatabaseMetaDataInterpreter: DatabaseMetaDataOp ~> Kleisli[M, DatabaseMetaData, *] = - new DatabaseMetaDataInterpreter {} - lazy val DriverInterpreter: DriverOp ~> Kleisli[M, Driver, *] = new DriverInterpreter {} - lazy val RefInterpreter: RefOp ~> Kleisli[M, Ref, *] = new RefInterpreter {} - lazy val SQLDataInterpreter: SQLDataOp ~> Kleisli[M, SQLData, *] = new SQLDataInterpreter {} - lazy val SQLInputInterpreter: SQLInputOp ~> Kleisli[M, SQLInput, *] = new SQLInputInterpreter {} - lazy val SQLOutputInterpreter: SQLOutputOp ~> Kleisli[M, SQLOutput, *] = new SQLOutputInterpreter {} - lazy val ConnectionInterpreter: ConnectionOp ~> Kleisli[M, Connection, *] = new ConnectionInterpreter {} - lazy val StatementInterpreter: StatementOp ~> Kleisli[M, Statement, *] = new StatementInterpreter {} - lazy val PreparedStatementInterpreter: PreparedStatementOp ~> Kleisli[M, PreparedStatement, *] = - new PreparedStatementInterpreter {} - lazy val CallableStatementInterpreter: CallableStatementOp ~> Kleisli[M, CallableStatement, *] = - new CallableStatementInterpreter {} - lazy val ResultSetInterpreter: ResultSetOp ~> Kleisli[M, ResultSet, *] = new ResultSetInterpreter {} - - // Some methods are common to all interpreters and can be overridden to change behavior globally. - def primitive[J, A](f: J => A): Kleisli[M, J, A] = Kleisli { a => - // primitive JDBC methods throw exceptions and so do we when reading values - // so catch any non-fatal exceptions and lift them into the effect - try { - syncM.blocking(f(a)) - } catch { - case e if scala.util.control.NonFatal(e) => syncM.raiseError(e) - } - } - def raw[J, A](f: J => A): Kleisli[M, J, A] = primitive(f) - def raiseError[J, A](e: Throwable): Kleisli[M, J, A] = Kleisli(_ => syncM.raiseError(e)) - def monotonic[J]: Kleisli[M, J, FiniteDuration] = Kleisli(_ => syncM.monotonic) - def realTime[J]: Kleisli[M, J, FiniteDuration] = Kleisli(_ => syncM.realTime) - def delay[J, A](thunk: => A): Kleisli[M, J, A] = Kleisli(_ => syncM.delay(thunk)) - def suspend[J, A](hint: Sync.Type)(thunk: => A): Kleisli[M, J, A] = Kleisli(_ => syncM.suspend(hint)(thunk)) - def canceled[J]: Kleisli[M, J, Unit] = Kleisli(_ => syncM.canceled) - - // for operations using free structures we call the interpreter recursively - def handleErrorWith[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A])(f: Throwable => Free[ - G, - A, - ]): Kleisli[M, J, A] = Kleisli { j => - syncM.handleErrorWith(fa.foldMap(interpreter).run(j))(f.andThen(_.foldMap(interpreter).run(j))) - } - def forceR[G[_], J, A, B](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A])(fb: Free[G, B]): Kleisli[M, J, B] = - Kleisli { j => - syncM.forceR(fa.foldMap(interpreter).run(j))(fb.foldMap(interpreter).run(j)) - } - def uncancelable[G[_], J, A]( - interpreter: G ~> Kleisli[M, J, *], - capture: Poll[M] => Poll[Free[G, *]], - )(body: Poll[Free[G, *]] => Free[G, A]): Kleisli[M, J, A] = Kleisli { j => - syncM.uncancelable(body.compose(capture).andThen(_.foldMap(interpreter).run(j))) - } - @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf")) - def poll[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(mpoll: Any, fa: Free[G, A]): Kleisli[M, J, A] = - Kleisli { j => - mpoll.asInstanceOf[Poll[M]].apply(fa.foldMap(interpreter).run(j)) - } - def onCancel[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A], fin: Free[G, Unit]): Kleisli[M, J, A] = - Kleisli { j => - syncM.onCancel(fa.foldMap(interpreter).run(j), fin.foldMap(interpreter).run(j)) - } - def embed[J, A](e: Embedded[A]): Kleisli[M, J, A] = e match { - case Embedded.NClob(j, fa) => Kleisli(_ => fa.foldMap(NClobInterpreter).run(j)) - case Embedded.Blob(j, fa) => Kleisli(_ => fa.foldMap(BlobInterpreter).run(j)) - case Embedded.Clob(j, fa) => Kleisli(_ => fa.foldMap(ClobInterpreter).run(j)) - case Embedded.DatabaseMetaData(j, fa) => Kleisli(_ => fa.foldMap(DatabaseMetaDataInterpreter).run(j)) - case Embedded.Driver(j, fa) => Kleisli(_ => fa.foldMap(DriverInterpreter).run(j)) - case Embedded.Ref(j, fa) => Kleisli(_ => fa.foldMap(RefInterpreter).run(j)) - case Embedded.SQLData(j, fa) => Kleisli(_ => fa.foldMap(SQLDataInterpreter).run(j)) - case Embedded.SQLInput(j, fa) => Kleisli(_ => fa.foldMap(SQLInputInterpreter).run(j)) - case Embedded.SQLOutput(j, fa) => Kleisli(_ => fa.foldMap(SQLOutputInterpreter).run(j)) - case Embedded.Connection(j, fa) => Kleisli(_ => fa.foldMap(ConnectionInterpreter).run(j)) - case Embedded.Statement(j, fa) => Kleisli(_ => fa.foldMap(StatementInterpreter).run(j)) - case Embedded.PreparedStatement(j, fa) => Kleisli(_ => fa.foldMap(PreparedStatementInterpreter).run(j)) - case Embedded.CallableStatement(j, fa) => Kleisli(_ => fa.foldMap(CallableStatementInterpreter).run(j)) - case Embedded.ResultSet(j, fa) => Kleisli(_ => fa.foldMap(ResultSetInterpreter).run(j)) - } - - // Interpreters - trait NClobInterpreter extends NClobOp.Visitor[Kleisli[M, NClob, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: NClob => A): Kleisli[M, NClob, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, NClob, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, NClob, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, NClob, FiniteDuration] = outer.monotonic[NClob] - override def realTime: Kleisli[M, NClob, FiniteDuration] = outer.realTime[NClob] - override def delay[A](thunk: => A): Kleisli[M, NClob, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, NClob, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, NClob, Unit] = outer.canceled[NClob] - - // for operations using NClobIO we must call ourself recursively - override def handleErrorWith[A](fa: NClobIO[A])(f: Throwable => NClobIO[A]): Kleisli[M, NClob, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: NClobIO[A])(fb: NClobIO[B]): Kleisli[M, NClob, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[NClobIO] => NClobIO[A]): Kleisli[M, NClob, A] = - outer.uncancelable(this, doobie.free.nclob.capturePoll)(body) - override def poll[A](poll: Any, fa: NClobIO[A]): Kleisli[M, NClob, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: NClobIO[A], fin: NClobIO[Unit]): Kleisli[M, NClob, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def free: Kleisli[M, NClob, Unit] = primitive(_.free) - override def getAsciiStream: Kleisli[M, NClob, InputStream] = primitive(_.getAsciiStream) - override def getCharacterStream: Kleisli[M, NClob, Reader] = primitive(_.getCharacterStream) - override def getCharacterStream(a: Long, b: Long) = primitive(_.getCharacterStream(a, b)) - override def getSubString(a: Long, b: Int) = primitive(_.getSubString(a, b)) - override def length: Kleisli[M, NClob, Long] = primitive(_.length) - override def position(a: Clob, b: Long) = primitive(_.position(a, b)) - override def position(a: String, b: Long) = primitive(_.position(a, b)) - override def setAsciiStream(a: Long) = primitive(_.setAsciiStream(a)) - override def setCharacterStream(a: Long) = primitive(_.setCharacterStream(a)) - override def setString(a: Long, b: String) = primitive(_.setString(a, b)) - override def setString(a: Long, b: String, c: Int, d: Int) = primitive(_.setString(a, b, c, d)) - override def truncate(a: Long) = primitive(_.truncate(a)) - - } - - trait BlobInterpreter extends BlobOp.Visitor[Kleisli[M, Blob, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: Blob => A): Kleisli[M, Blob, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, Blob, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, Blob, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, Blob, FiniteDuration] = outer.monotonic[Blob] - override def realTime: Kleisli[M, Blob, FiniteDuration] = outer.realTime[Blob] - override def delay[A](thunk: => A): Kleisli[M, Blob, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, Blob, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, Blob, Unit] = outer.canceled[Blob] - - // for operations using BlobIO we must call ourself recursively - override def handleErrorWith[A](fa: BlobIO[A])(f: Throwable => BlobIO[A]): Kleisli[M, Blob, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: BlobIO[A])(fb: BlobIO[B]): Kleisli[M, Blob, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[BlobIO] => BlobIO[A]): Kleisli[M, Blob, A] = - outer.uncancelable(this, doobie.free.blob.capturePoll)(body) - override def poll[A](poll: Any, fa: BlobIO[A]): Kleisli[M, Blob, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: BlobIO[A], fin: BlobIO[Unit]): Kleisli[M, Blob, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def free: Kleisli[M, Blob, Unit] = primitive(_.free) - override def getBinaryStream: Kleisli[M, Blob, InputStream] = primitive(_.getBinaryStream) - override def getBinaryStream(a: Long, b: Long) = primitive(_.getBinaryStream(a, b)) - override def getBytes(a: Long, b: Int) = primitive(_.getBytes(a, b)) - override def length: Kleisli[M, Blob, Long] = primitive(_.length) - override def position(a: Array[Byte], b: Long) = primitive(_.position(a, b)) - override def position(a: Blob, b: Long) = primitive(_.position(a, b)) - override def setBinaryStream(a: Long) = primitive(_.setBinaryStream(a)) - override def setBytes(a: Long, b: Array[Byte]) = primitive(_.setBytes(a, b)) - override def setBytes(a: Long, b: Array[Byte], c: Int, d: Int) = primitive(_.setBytes(a, b, c, d)) - override def truncate(a: Long) = primitive(_.truncate(a)) - - } - - trait ClobInterpreter extends ClobOp.Visitor[Kleisli[M, Clob, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: Clob => A): Kleisli[M, Clob, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, Clob, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, Clob, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, Clob, FiniteDuration] = outer.monotonic[Clob] - override def realTime: Kleisli[M, Clob, FiniteDuration] = outer.realTime[Clob] - override def delay[A](thunk: => A): Kleisli[M, Clob, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, Clob, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, Clob, Unit] = outer.canceled[Clob] - - // for operations using ClobIO we must call ourself recursively - override def handleErrorWith[A](fa: ClobIO[A])(f: Throwable => ClobIO[A]): Kleisli[M, Clob, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: ClobIO[A])(fb: ClobIO[B]): Kleisli[M, Clob, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[ClobIO] => ClobIO[A]): Kleisli[M, Clob, A] = - outer.uncancelable(this, doobie.free.clob.capturePoll)(body) - override def poll[A](poll: Any, fa: ClobIO[A]): Kleisli[M, Clob, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: ClobIO[A], fin: ClobIO[Unit]): Kleisli[M, Clob, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def free: Kleisli[M, Clob, Unit] = primitive(_.free) - override def getAsciiStream: Kleisli[M, Clob, InputStream] = primitive(_.getAsciiStream) - override def getCharacterStream: Kleisli[M, Clob, Reader] = primitive(_.getCharacterStream) - override def getCharacterStream(a: Long, b: Long) = primitive(_.getCharacterStream(a, b)) - override def getSubString(a: Long, b: Int) = primitive(_.getSubString(a, b)) - override def length: Kleisli[M, Clob, Long] = primitive(_.length) - override def position(a: Clob, b: Long) = primitive(_.position(a, b)) - override def position(a: String, b: Long) = primitive(_.position(a, b)) - override def setAsciiStream(a: Long) = primitive(_.setAsciiStream(a)) - override def setCharacterStream(a: Long) = primitive(_.setCharacterStream(a)) - override def setString(a: Long, b: String) = primitive(_.setString(a, b)) - override def setString(a: Long, b: String, c: Int, d: Int) = primitive(_.setString(a, b, c, d)) - override def truncate(a: Long) = primitive(_.truncate(a)) - - } - - trait DatabaseMetaDataInterpreter extends DatabaseMetaDataOp.Visitor[Kleisli[M, DatabaseMetaData, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: DatabaseMetaData => A): Kleisli[M, DatabaseMetaData, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, DatabaseMetaData, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, DatabaseMetaData, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, DatabaseMetaData, FiniteDuration] = outer.monotonic[DatabaseMetaData] - override def realTime: Kleisli[M, DatabaseMetaData, FiniteDuration] = outer.realTime[DatabaseMetaData] - override def delay[A](thunk: => A): Kleisli[M, DatabaseMetaData, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, DatabaseMetaData, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, DatabaseMetaData, Unit] = outer.canceled[DatabaseMetaData] - - // for operations using DatabaseMetaDataIO we must call ourself recursively - override def handleErrorWith[A](fa: DatabaseMetaDataIO[A])( - f: Throwable => DatabaseMetaDataIO[A], - ): Kleisli[M, DatabaseMetaData, A] = outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: DatabaseMetaDataIO[A])(fb: DatabaseMetaDataIO[B]): Kleisli[M, DatabaseMetaData, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A]( - body: Poll[DatabaseMetaDataIO] => DatabaseMetaDataIO[A], - ): Kleisli[M, DatabaseMetaData, A] = outer.uncancelable(this, doobie.free.databasemetadata.capturePoll)(body) - override def poll[A](poll: Any, fa: DatabaseMetaDataIO[A]): Kleisli[M, DatabaseMetaData, A] = - outer.poll(this)(poll, fa) - override def onCancel[A]( - fa: DatabaseMetaDataIO[A], - fin: DatabaseMetaDataIO[Unit], - ): Kleisli[M, DatabaseMetaData, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def allProceduresAreCallable: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.allProceduresAreCallable) - override def allTablesAreSelectable: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.allTablesAreSelectable) - override def autoCommitFailureClosesAllResultSets: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.autoCommitFailureClosesAllResultSets) - override def dataDefinitionCausesTransactionCommit: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.dataDefinitionCausesTransactionCommit) - override def dataDefinitionIgnoredInTransactions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.dataDefinitionIgnoredInTransactions) - override def deletesAreDetected(a: Int) = primitive(_.deletesAreDetected(a)) - override def doesMaxRowSizeIncludeBlobs: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.doesMaxRowSizeIncludeBlobs) - override def generatedKeyAlwaysReturned: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.generatedKeyAlwaysReturned) - override def getAttributes(a: String, b: String, c: String, d: String) = primitive(_.getAttributes(a, b, c, d)) - override def getBestRowIdentifier(a: String, b: String, c: String, d: Int, e: Boolean) = - primitive(_.getBestRowIdentifier(a, b, c, d, e)) - override def getCatalogSeparator: Kleisli[M, DatabaseMetaData, String] = primitive(_.getCatalogSeparator) - override def getCatalogTerm: Kleisli[M, DatabaseMetaData, String] = primitive(_.getCatalogTerm) - override def getCatalogs: Kleisli[M, DatabaseMetaData, ResultSet] = primitive(_.getCatalogs) - override def getClientInfoProperties: Kleisli[M, DatabaseMetaData, ResultSet] = primitive(_.getClientInfoProperties) - override def getColumnPrivileges(a: String, b: String, c: String, d: String) = - primitive(_.getColumnPrivileges(a, b, c, d)) - override def getColumns(a: String, b: String, c: String, d: String) = primitive(_.getColumns(a, b, c, d)) - override def getConnection: Kleisli[M, DatabaseMetaData, Connection] = primitive(_.getConnection) - override def getCrossReference(a: String, b: String, c: String, d: String, e: String, f: String) = - primitive(_.getCrossReference(a, b, c, d, e, f)) - override def getDatabaseMajorVersion: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getDatabaseMajorVersion) - override def getDatabaseMinorVersion: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getDatabaseMinorVersion) - override def getDatabaseProductName: Kleisli[M, DatabaseMetaData, String] = primitive(_.getDatabaseProductName) - override def getDatabaseProductVersion: Kleisli[M, DatabaseMetaData, String] = primitive(_.getDatabaseProductVersion) - override def getDefaultTransactionIsolation: Kleisli[M, DatabaseMetaData, Int] = - primitive(_.getDefaultTransactionIsolation) - override def getDriverMajorVersion: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getDriverMajorVersion) - override def getDriverMinorVersion: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getDriverMinorVersion) - override def getDriverName: Kleisli[M, DatabaseMetaData, String] = primitive(_.getDriverName) - override def getDriverVersion: Kleisli[M, DatabaseMetaData, String] = primitive(_.getDriverVersion) - override def getExportedKeys(a: String, b: String, c: String) = primitive(_.getExportedKeys(a, b, c)) - override def getExtraNameCharacters: Kleisli[M, DatabaseMetaData, String] = primitive(_.getExtraNameCharacters) - override def getFunctionColumns(a: String, b: String, c: String, d: String) = - primitive(_.getFunctionColumns(a, b, c, d)) - override def getFunctions(a: String, b: String, c: String) = primitive(_.getFunctions(a, b, c)) - override def getIdentifierQuoteString: Kleisli[M, DatabaseMetaData, String] = primitive(_.getIdentifierQuoteString) - override def getImportedKeys(a: String, b: String, c: String) = primitive(_.getImportedKeys(a, b, c)) - override def getIndexInfo(a: String, b: String, c: String, d: Boolean, e: Boolean) = - primitive(_.getIndexInfo(a, b, c, d, e)) - override def getJDBCMajorVersion: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getJDBCMajorVersion) - override def getJDBCMinorVersion: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getJDBCMinorVersion) - override def getMaxBinaryLiteralLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxBinaryLiteralLength) - override def getMaxCatalogNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxCatalogNameLength) - override def getMaxCharLiteralLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxCharLiteralLength) - override def getMaxColumnNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxColumnNameLength) - override def getMaxColumnsInGroupBy: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxColumnsInGroupBy) - override def getMaxColumnsInIndex: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxColumnsInIndex) - override def getMaxColumnsInOrderBy: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxColumnsInOrderBy) - override def getMaxColumnsInSelect: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxColumnsInSelect) - override def getMaxColumnsInTable: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxColumnsInTable) - override def getMaxConnections: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxConnections) - override def getMaxCursorNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxCursorNameLength) - override def getMaxIndexLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxIndexLength) - override def getMaxLogicalLobSize: Kleisli[M, DatabaseMetaData, Long] = primitive(_.getMaxLogicalLobSize) - override def getMaxProcedureNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxProcedureNameLength) - override def getMaxRowSize: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxRowSize) - override def getMaxSchemaNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxSchemaNameLength) - override def getMaxStatementLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxStatementLength) - override def getMaxStatements: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxStatements) - override def getMaxTableNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxTableNameLength) - override def getMaxTablesInSelect: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxTablesInSelect) - override def getMaxUserNameLength: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getMaxUserNameLength) - override def getNumericFunctions: Kleisli[M, DatabaseMetaData, String] = primitive(_.getNumericFunctions) - override def getPrimaryKeys(a: String, b: String, c: String) = primitive(_.getPrimaryKeys(a, b, c)) - override def getProcedureColumns(a: String, b: String, c: String, d: String) = - primitive(_.getProcedureColumns(a, b, c, d)) - override def getProcedureTerm: Kleisli[M, DatabaseMetaData, String] = primitive(_.getProcedureTerm) - override def getProcedures(a: String, b: String, c: String) = primitive(_.getProcedures(a, b, c)) - override def getPseudoColumns(a: String, b: String, c: String, d: String) = primitive(_.getPseudoColumns(a, b, c, d)) - override def getResultSetHoldability: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getResultSetHoldability) - override def getRowIdLifetime: Kleisli[M, DatabaseMetaData, RowIdLifetime] = primitive(_.getRowIdLifetime) - override def getSQLKeywords: Kleisli[M, DatabaseMetaData, String] = primitive(_.getSQLKeywords) - override def getSQLStateType: Kleisli[M, DatabaseMetaData, Int] = primitive(_.getSQLStateType) - override def getSchemaTerm: Kleisli[M, DatabaseMetaData, String] = primitive(_.getSchemaTerm) - override def getSchemas: Kleisli[M, DatabaseMetaData, ResultSet] = primitive(_.getSchemas) - override def getSchemas(a: String, b: String) = primitive(_.getSchemas(a, b)) - override def getSearchStringEscape: Kleisli[M, DatabaseMetaData, String] = primitive(_.getSearchStringEscape) - override def getStringFunctions: Kleisli[M, DatabaseMetaData, String] = primitive(_.getStringFunctions) - override def getSuperTables(a: String, b: String, c: String) = primitive(_.getSuperTables(a, b, c)) - override def getSuperTypes(a: String, b: String, c: String) = primitive(_.getSuperTypes(a, b, c)) - override def getSystemFunctions: Kleisli[M, DatabaseMetaData, String] = primitive(_.getSystemFunctions) - override def getTablePrivileges(a: String, b: String, c: String) = primitive(_.getTablePrivileges(a, b, c)) - override def getTableTypes: Kleisli[M, DatabaseMetaData, ResultSet] = primitive(_.getTableTypes) - override def getTables(a: String, b: String, c: String, d: Array[String]) = primitive(_.getTables(a, b, c, d)) - override def getTimeDateFunctions: Kleisli[M, DatabaseMetaData, String] = primitive(_.getTimeDateFunctions) - override def getTypeInfo: Kleisli[M, DatabaseMetaData, ResultSet] = primitive(_.getTypeInfo) - override def getUDTs(a: String, b: String, c: String, d: Array[Int]) = primitive(_.getUDTs(a, b, c, d)) - override def getURL: Kleisli[M, DatabaseMetaData, String] = primitive(_.getURL) - override def getUserName: Kleisli[M, DatabaseMetaData, String] = primitive(_.getUserName) - override def getVersionColumns(a: String, b: String, c: String) = primitive(_.getVersionColumns(a, b, c)) - override def insertsAreDetected(a: Int) = primitive(_.insertsAreDetected(a)) - override def isCatalogAtStart: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.isCatalogAtStart) - override def isReadOnly: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.isReadOnly) - override def isWrapperFor(a: Class[?]) = primitive(_.isWrapperFor(a)) - override def locatorsUpdateCopy: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.locatorsUpdateCopy) - override def nullPlusNonNullIsNull: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.nullPlusNonNullIsNull) - override def nullsAreSortedAtEnd: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.nullsAreSortedAtEnd) - override def nullsAreSortedAtStart: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.nullsAreSortedAtStart) - override def nullsAreSortedHigh: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.nullsAreSortedHigh) - override def nullsAreSortedLow: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.nullsAreSortedLow) - override def othersDeletesAreVisible(a: Int) = primitive(_.othersDeletesAreVisible(a)) - override def othersInsertsAreVisible(a: Int) = primitive(_.othersInsertsAreVisible(a)) - override def othersUpdatesAreVisible(a: Int) = primitive(_.othersUpdatesAreVisible(a)) - override def ownDeletesAreVisible(a: Int) = primitive(_.ownDeletesAreVisible(a)) - override def ownInsertsAreVisible(a: Int) = primitive(_.ownInsertsAreVisible(a)) - override def ownUpdatesAreVisible(a: Int) = primitive(_.ownUpdatesAreVisible(a)) - override def storesLowerCaseIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.storesLowerCaseIdentifiers) - override def storesLowerCaseQuotedIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.storesLowerCaseQuotedIdentifiers) - override def storesMixedCaseIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.storesMixedCaseIdentifiers) - override def storesMixedCaseQuotedIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.storesMixedCaseQuotedIdentifiers) - override def storesUpperCaseIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.storesUpperCaseIdentifiers) - override def storesUpperCaseQuotedIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.storesUpperCaseQuotedIdentifiers) - override def supportsANSI92EntryLevelSQL: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsANSI92EntryLevelSQL) - override def supportsANSI92FullSQL: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsANSI92FullSQL) - override def supportsANSI92IntermediateSQL: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsANSI92IntermediateSQL) - override def supportsAlterTableWithAddColumn: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsAlterTableWithAddColumn) - override def supportsAlterTableWithDropColumn: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsAlterTableWithDropColumn) - override def supportsBatchUpdates: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsBatchUpdates) - override def supportsCatalogsInDataManipulation: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsCatalogsInDataManipulation) - override def supportsCatalogsInIndexDefinitions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsCatalogsInIndexDefinitions) - override def supportsCatalogsInPrivilegeDefinitions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsCatalogsInPrivilegeDefinitions) - override def supportsCatalogsInProcedureCalls: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsCatalogsInProcedureCalls) - override def supportsCatalogsInTableDefinitions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsCatalogsInTableDefinitions) - override def supportsColumnAliasing: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsColumnAliasing) - override def supportsConvert: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsConvert) - override def supportsConvert(a: Int, b: Int) = primitive(_.supportsConvert(a, b)) - override def supportsCoreSQLGrammar: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsCoreSQLGrammar) - override def supportsCorrelatedSubqueries: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsCorrelatedSubqueries) - override def supportsDataDefinitionAndDataManipulationTransactions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsDataDefinitionAndDataManipulationTransactions) - override def supportsDataManipulationTransactionsOnly: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsDataManipulationTransactionsOnly) - override def supportsDifferentTableCorrelationNames: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsDifferentTableCorrelationNames) - override def supportsExpressionsInOrderBy: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsExpressionsInOrderBy) - override def supportsExtendedSQLGrammar: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsExtendedSQLGrammar) - override def supportsFullOuterJoins: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsFullOuterJoins) - override def supportsGetGeneratedKeys: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsGetGeneratedKeys) - override def supportsGroupBy: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsGroupBy) - override def supportsGroupByBeyondSelect: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsGroupByBeyondSelect) - override def supportsGroupByUnrelated: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsGroupByUnrelated) - override def supportsIntegrityEnhancementFacility: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsIntegrityEnhancementFacility) - override def supportsLikeEscapeClause: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsLikeEscapeClause) - override def supportsLimitedOuterJoins: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsLimitedOuterJoins) - override def supportsMinimumSQLGrammar: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsMinimumSQLGrammar) - override def supportsMixedCaseIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsMixedCaseIdentifiers) - override def supportsMixedCaseQuotedIdentifiers: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsMixedCaseQuotedIdentifiers) - override def supportsMultipleOpenResults: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsMultipleOpenResults) - override def supportsMultipleResultSets: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsMultipleResultSets) - override def supportsMultipleTransactions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsMultipleTransactions) - override def supportsNamedParameters: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsNamedParameters) - override def supportsNonNullableColumns: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsNonNullableColumns) - override def supportsOpenCursorsAcrossCommit: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsOpenCursorsAcrossCommit) - override def supportsOpenCursorsAcrossRollback: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsOpenCursorsAcrossRollback) - override def supportsOpenStatementsAcrossCommit: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsOpenStatementsAcrossCommit) - override def supportsOpenStatementsAcrossRollback: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsOpenStatementsAcrossRollback) - override def supportsOrderByUnrelated: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsOrderByUnrelated) - override def supportsOuterJoins: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsOuterJoins) - override def supportsPositionedDelete: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsPositionedDelete) - override def supportsPositionedUpdate: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsPositionedUpdate) - override def supportsRefCursors: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsRefCursors) - override def supportsResultSetConcurrency(a: Int, b: Int) = primitive(_.supportsResultSetConcurrency(a, b)) - override def supportsResultSetHoldability(a: Int) = primitive(_.supportsResultSetHoldability(a)) - override def supportsResultSetType(a: Int) = primitive(_.supportsResultSetType(a)) - override def supportsSavepoints: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsSavepoints) - override def supportsSchemasInDataManipulation: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSchemasInDataManipulation) - override def supportsSchemasInIndexDefinitions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSchemasInIndexDefinitions) - override def supportsSchemasInPrivilegeDefinitions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSchemasInPrivilegeDefinitions) - override def supportsSchemasInProcedureCalls: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSchemasInProcedureCalls) - override def supportsSchemasInTableDefinitions: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSchemasInTableDefinitions) - override def supportsSelectForUpdate: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsSelectForUpdate) - override def supportsSharding: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsSharding) - override def supportsStatementPooling: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsStatementPooling) - override def supportsStoredFunctionsUsingCallSyntax: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsStoredFunctionsUsingCallSyntax) - override def supportsStoredProcedures: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsStoredProcedures) - override def supportsSubqueriesInComparisons: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSubqueriesInComparisons) - override def supportsSubqueriesInExists: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSubqueriesInExists) - override def supportsSubqueriesInIns: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsSubqueriesInIns) - override def supportsSubqueriesInQuantifieds: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsSubqueriesInQuantifieds) - override def supportsTableCorrelationNames: Kleisli[M, DatabaseMetaData, Boolean] = - primitive(_.supportsTableCorrelationNames) - override def supportsTransactionIsolationLevel(a: Int) = primitive(_.supportsTransactionIsolationLevel(a)) - override def supportsTransactions: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsTransactions) - override def supportsUnion: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsUnion) - override def supportsUnionAll: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.supportsUnionAll) - override def unwrap[T](a: Class[T]) = primitive(_.unwrap(a)) - override def updatesAreDetected(a: Int) = primitive(_.updatesAreDetected(a)) - override def usesLocalFilePerTable: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.usesLocalFilePerTable) - override def usesLocalFiles: Kleisli[M, DatabaseMetaData, Boolean] = primitive(_.usesLocalFiles) - - } - - trait DriverInterpreter extends DriverOp.Visitor[Kleisli[M, Driver, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: Driver => A): Kleisli[M, Driver, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, Driver, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, Driver, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, Driver, FiniteDuration] = outer.monotonic[Driver] - override def realTime: Kleisli[M, Driver, FiniteDuration] = outer.realTime[Driver] - override def delay[A](thunk: => A): Kleisli[M, Driver, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, Driver, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, Driver, Unit] = outer.canceled[Driver] - - // for operations using DriverIO we must call ourself recursively - override def handleErrorWith[A](fa: DriverIO[A])(f: Throwable => DriverIO[A]): Kleisli[M, Driver, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: DriverIO[A])(fb: DriverIO[B]): Kleisli[M, Driver, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[DriverIO] => DriverIO[A]): Kleisli[M, Driver, A] = - outer.uncancelable(this, doobie.free.driver.capturePoll)(body) - override def poll[A](poll: Any, fa: DriverIO[A]): Kleisli[M, Driver, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: DriverIO[A], fin: DriverIO[Unit]): Kleisli[M, Driver, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def acceptsURL(a: String) = primitive(_.acceptsURL(a)) - override def connect(a: String, b: Properties) = primitive(_.connect(a, b)) - override def getMajorVersion: Kleisli[M, Driver, Int] = primitive(_.getMajorVersion) - override def getMinorVersion: Kleisli[M, Driver, Int] = primitive(_.getMinorVersion) - override def getParentLogger: Kleisli[M, Driver, Logger] = primitive(_.getParentLogger) - override def getPropertyInfo(a: String, b: Properties) = primitive(_.getPropertyInfo(a, b)) - override def jdbcCompliant: Kleisli[M, Driver, Boolean] = primitive(_.jdbcCompliant) - - } - - trait RefInterpreter extends RefOp.Visitor[Kleisli[M, Ref, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: Ref => A): Kleisli[M, Ref, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, Ref, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, Ref, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, Ref, FiniteDuration] = outer.monotonic[Ref] - override def realTime: Kleisli[M, Ref, FiniteDuration] = outer.realTime[Ref] - override def delay[A](thunk: => A): Kleisli[M, Ref, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, Ref, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, Ref, Unit] = outer.canceled[Ref] - - // for operations using RefIO we must call ourself recursively - override def handleErrorWith[A](fa: RefIO[A])(f: Throwable => RefIO[A]): Kleisli[M, Ref, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: RefIO[A])(fb: RefIO[B]): Kleisli[M, Ref, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[RefIO] => RefIO[A]): Kleisli[M, Ref, A] = - outer.uncancelable(this, doobie.free.ref.capturePoll)(body) - override def poll[A](poll: Any, fa: RefIO[A]): Kleisli[M, Ref, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: RefIO[A], fin: RefIO[Unit]): Kleisli[M, Ref, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def getBaseTypeName: Kleisli[M, Ref, String] = primitive(_.getBaseTypeName) - override def getObject: Kleisli[M, Ref, AnyRef] = primitive(_.getObject) - override def getObject(a: java.util.Map[String, Class[?]]) = primitive(_.getObject(a)) - override def setObject(a: AnyRef) = primitive(_.setObject(a)) - - } - - trait SQLDataInterpreter extends SQLDataOp.Visitor[Kleisli[M, SQLData, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: SQLData => A): Kleisli[M, SQLData, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, SQLData, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, SQLData, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, SQLData, FiniteDuration] = outer.monotonic[SQLData] - override def realTime: Kleisli[M, SQLData, FiniteDuration] = outer.realTime[SQLData] - override def delay[A](thunk: => A): Kleisli[M, SQLData, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, SQLData, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, SQLData, Unit] = outer.canceled[SQLData] - - // for operations using SQLDataIO we must call ourself recursively - override def handleErrorWith[A](fa: SQLDataIO[A])(f: Throwable => SQLDataIO[A]): Kleisli[M, SQLData, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: SQLDataIO[A])(fb: SQLDataIO[B]): Kleisli[M, SQLData, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[SQLDataIO] => SQLDataIO[A]): Kleisli[M, SQLData, A] = - outer.uncancelable(this, doobie.free.sqldata.capturePoll)(body) - override def poll[A](poll: Any, fa: SQLDataIO[A]): Kleisli[M, SQLData, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: SQLDataIO[A], fin: SQLDataIO[Unit]): Kleisli[M, SQLData, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def getSQLTypeName: Kleisli[M, SQLData, String] = primitive(_.getSQLTypeName) - override def readSQL(a: SQLInput, b: String) = primitive(_.readSQL(a, b)) - override def writeSQL(a: SQLOutput) = primitive(_.writeSQL(a)) - - } - - trait SQLInputInterpreter extends SQLInputOp.Visitor[Kleisli[M, SQLInput, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: SQLInput => A): Kleisli[M, SQLInput, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, SQLInput, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, SQLInput, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, SQLInput, FiniteDuration] = outer.monotonic[SQLInput] - override def realTime: Kleisli[M, SQLInput, FiniteDuration] = outer.realTime[SQLInput] - override def delay[A](thunk: => A): Kleisli[M, SQLInput, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, SQLInput, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, SQLInput, Unit] = outer.canceled[SQLInput] - - // for operations using SQLInputIO we must call ourself recursively - override def handleErrorWith[A](fa: SQLInputIO[A])(f: Throwable => SQLInputIO[A]): Kleisli[M, SQLInput, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: SQLInputIO[A])(fb: SQLInputIO[B]): Kleisli[M, SQLInput, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[SQLInputIO] => SQLInputIO[A]): Kleisli[M, SQLInput, A] = - outer.uncancelable(this, doobie.free.sqlinput.capturePoll)(body) - override def poll[A](poll: Any, fa: SQLInputIO[A]): Kleisli[M, SQLInput, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: SQLInputIO[A], fin: SQLInputIO[Unit]): Kleisli[M, SQLInput, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def readArray: Kleisli[M, SQLInput, SqlArray] = primitive(_.readArray) - override def readAsciiStream: Kleisli[M, SQLInput, InputStream] = primitive(_.readAsciiStream) - override def readBigDecimal: Kleisli[M, SQLInput, BigDecimal] = primitive(_.readBigDecimal) - override def readBinaryStream: Kleisli[M, SQLInput, InputStream] = primitive(_.readBinaryStream) - override def readBlob: Kleisli[M, SQLInput, Blob] = primitive(_.readBlob) - override def readBoolean: Kleisli[M, SQLInput, Boolean] = primitive(_.readBoolean) - override def readByte: Kleisli[M, SQLInput, Byte] = primitive(_.readByte) - override def readBytes: Kleisli[M, SQLInput, Array[Byte]] = primitive(_.readBytes) - override def readCharacterStream: Kleisli[M, SQLInput, Reader] = primitive(_.readCharacterStream) - override def readClob: Kleisli[M, SQLInput, Clob] = primitive(_.readClob) - override def readDate: Kleisli[M, SQLInput, Date] = primitive(_.readDate) - override def readDouble: Kleisli[M, SQLInput, Double] = primitive(_.readDouble) - override def readFloat: Kleisli[M, SQLInput, Float] = primitive(_.readFloat) - override def readInt: Kleisli[M, SQLInput, Int] = primitive(_.readInt) - override def readLong: Kleisli[M, SQLInput, Long] = primitive(_.readLong) - override def readNClob: Kleisli[M, SQLInput, NClob] = primitive(_.readNClob) - override def readNString: Kleisli[M, SQLInput, String] = primitive(_.readNString) - override def readObject: Kleisli[M, SQLInput, AnyRef] = primitive(_.readObject) - override def readObject[T](a: Class[T]) = primitive(_.readObject(a)) - override def readRef: Kleisli[M, SQLInput, Ref] = primitive(_.readRef) - override def readRowId: Kleisli[M, SQLInput, RowId] = primitive(_.readRowId) - override def readSQLXML: Kleisli[M, SQLInput, SQLXML] = primitive(_.readSQLXML) - override def readShort: Kleisli[M, SQLInput, Short] = primitive(_.readShort) - override def readString: Kleisli[M, SQLInput, String] = primitive(_.readString) - override def readTime: Kleisli[M, SQLInput, Time] = primitive(_.readTime) - override def readTimestamp: Kleisli[M, SQLInput, Timestamp] = primitive(_.readTimestamp) - override def readURL: Kleisli[M, SQLInput, URL] = primitive(_.readURL) - override def wasNull: Kleisli[M, SQLInput, Boolean] = primitive(_.wasNull) - - } - - trait SQLOutputInterpreter extends SQLOutputOp.Visitor[Kleisli[M, SQLOutput, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: SQLOutput => A): Kleisli[M, SQLOutput, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, SQLOutput, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, SQLOutput, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, SQLOutput, FiniteDuration] = outer.monotonic[SQLOutput] - override def realTime: Kleisli[M, SQLOutput, FiniteDuration] = outer.realTime[SQLOutput] - override def delay[A](thunk: => A): Kleisli[M, SQLOutput, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, SQLOutput, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, SQLOutput, Unit] = outer.canceled[SQLOutput] - - // for operations using SQLOutputIO we must call ourself recursively - override def handleErrorWith[A](fa: SQLOutputIO[A])(f: Throwable => SQLOutputIO[A]): Kleisli[M, SQLOutput, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: SQLOutputIO[A])(fb: SQLOutputIO[B]): Kleisli[M, SQLOutput, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[SQLOutputIO] => SQLOutputIO[A]): Kleisli[M, SQLOutput, A] = - outer.uncancelable(this, doobie.free.sqloutput.capturePoll)(body) - override def poll[A](poll: Any, fa: SQLOutputIO[A]): Kleisli[M, SQLOutput, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: SQLOutputIO[A], fin: SQLOutputIO[Unit]): Kleisli[M, SQLOutput, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def writeArray(a: SqlArray) = primitive(_.writeArray(a)) - override def writeAsciiStream(a: InputStream) = primitive(_.writeAsciiStream(a)) - override def writeBigDecimal(a: BigDecimal) = primitive(_.writeBigDecimal(a)) - override def writeBinaryStream(a: InputStream) = primitive(_.writeBinaryStream(a)) - override def writeBlob(a: Blob) = primitive(_.writeBlob(a)) - override def writeBoolean(a: Boolean) = primitive(_.writeBoolean(a)) - override def writeByte(a: Byte) = primitive(_.writeByte(a)) - override def writeBytes(a: Array[Byte]) = primitive(_.writeBytes(a)) - override def writeCharacterStream(a: Reader) = primitive(_.writeCharacterStream(a)) - override def writeClob(a: Clob) = primitive(_.writeClob(a)) - override def writeDate(a: Date) = primitive(_.writeDate(a)) - override def writeDouble(a: Double) = primitive(_.writeDouble(a)) - override def writeFloat(a: Float) = primitive(_.writeFloat(a)) - override def writeInt(a: Int) = primitive(_.writeInt(a)) - override def writeLong(a: Long) = primitive(_.writeLong(a)) - override def writeNClob(a: NClob) = primitive(_.writeNClob(a)) - override def writeNString(a: String) = primitive(_.writeNString(a)) - override def writeObject(a: AnyRef, b: SQLType) = primitive(_.writeObject(a, b)) - override def writeObject(a: SQLData) = primitive(_.writeObject(a)) - override def writeRef(a: Ref) = primitive(_.writeRef(a)) - override def writeRowId(a: RowId) = primitive(_.writeRowId(a)) - override def writeSQLXML(a: SQLXML) = primitive(_.writeSQLXML(a)) - override def writeShort(a: Short) = primitive(_.writeShort(a)) - override def writeString(a: String) = primitive(_.writeString(a)) - override def writeStruct(a: Struct) = primitive(_.writeStruct(a)) - override def writeTime(a: Time) = primitive(_.writeTime(a)) - override def writeTimestamp(a: Timestamp) = primitive(_.writeTimestamp(a)) - override def writeURL(a: URL) = primitive(_.writeURL(a)) - - } - - trait ConnectionInterpreter extends ConnectionOp.Visitor[Kleisli[M, Connection, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: Connection => A): Kleisli[M, Connection, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, Connection, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, Connection, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, Connection, FiniteDuration] = outer.monotonic[Connection] - override def realTime: Kleisli[M, Connection, FiniteDuration] = outer.realTime[Connection] - override def delay[A](thunk: => A): Kleisli[M, Connection, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, Connection, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, Connection, Unit] = outer.canceled[Connection] - - // for operations using ConnectionIO we must call ourself recursively - override def handleErrorWith[A](fa: ConnectionIO[A])(f: Throwable => ConnectionIO[A]): Kleisli[M, Connection, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: ConnectionIO[A])(fb: ConnectionIO[B]): Kleisli[M, Connection, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[ConnectionIO] => ConnectionIO[A]): Kleisli[M, Connection, A] = - outer.uncancelable(this, doobie.free.connection.capturePoll)(body) - override def poll[A](poll: Any, fa: ConnectionIO[A]): Kleisli[M, Connection, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: ConnectionIO[A], fin: ConnectionIO[Unit]): Kleisli[M, Connection, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def abort(a: Executor) = primitive(_.abort(a)) - override def beginRequest: Kleisli[M, Connection, Unit] = primitive(_.beginRequest) - override def clearWarnings: Kleisli[M, Connection, Unit] = primitive(_.clearWarnings) - override def close: Kleisli[M, Connection, Unit] = primitive(_.close) - override def commit: Kleisli[M, Connection, Unit] = primitive(_.commit) - override def createArrayOf(a: String, b: Array[AnyRef]) = primitive(_.createArrayOf(a, b)) - override def createBlob: Kleisli[M, Connection, Blob] = primitive(_.createBlob) - override def createClob: Kleisli[M, Connection, Clob] = primitive(_.createClob) - override def createNClob: Kleisli[M, Connection, NClob] = primitive(_.createNClob) - override def createSQLXML: Kleisli[M, Connection, SQLXML] = primitive(_.createSQLXML) - override def createStatement: Kleisli[M, Connection, Statement] = primitive(_.createStatement) - override def createStatement(a: Int, b: Int) = primitive(_.createStatement(a, b)) - override def createStatement(a: Int, b: Int, c: Int) = primitive(_.createStatement(a, b, c)) - override def createStruct(a: String, b: Array[AnyRef]) = primitive(_.createStruct(a, b)) - override def endRequest: Kleisli[M, Connection, Unit] = primitive(_.endRequest) - override def getAutoCommit: Kleisli[M, Connection, Boolean] = primitive(_.getAutoCommit) - override def getCatalog: Kleisli[M, Connection, String] = primitive(_.getCatalog) - override def getClientInfo: Kleisli[M, Connection, Properties] = primitive(_.getClientInfo) - override def getClientInfo(a: String) = primitive(_.getClientInfo(a)) - override def getHoldability: Kleisli[M, Connection, Int] = primitive(_.getHoldability) - override def getMetaData: Kleisli[M, Connection, DatabaseMetaData] = primitive(_.getMetaData) - override def getNetworkTimeout: Kleisli[M, Connection, Int] = primitive(_.getNetworkTimeout) - override def getSchema: Kleisli[M, Connection, String] = primitive(_.getSchema) - override def getTransactionIsolation: Kleisli[M, Connection, Int] = primitive(_.getTransactionIsolation) - override def getTypeMap: Kleisli[M, Connection, java.util.Map[String, Class[?]]] = primitive(_.getTypeMap) - override def getWarnings: Kleisli[M, Connection, SQLWarning] = primitive(_.getWarnings) - override def isClosed: Kleisli[M, Connection, Boolean] = primitive(_.isClosed) - override def isReadOnly: Kleisli[M, Connection, Boolean] = primitive(_.isReadOnly) - override def isValid(a: Int) = primitive(_.isValid(a)) - override def isWrapperFor(a: Class[?]) = primitive(_.isWrapperFor(a)) - override def nativeSQL(a: String) = primitive(_.nativeSQL(a)) - override def prepareCall(a: String) = primitive(_.prepareCall(a)) - override def prepareCall(a: String, b: Int, c: Int) = primitive(_.prepareCall(a, b, c)) - override def prepareCall(a: String, b: Int, c: Int, d: Int) = primitive(_.prepareCall(a, b, c, d)) - override def prepareStatement(a: String) = primitive(_.prepareStatement(a)) - override def prepareStatement(a: String, b: Array[Int]) = primitive(_.prepareStatement(a, b)) - override def prepareStatement(a: String, b: Array[String]) = primitive(_.prepareStatement(a, b)) - override def prepareStatement(a: String, b: Int) = primitive(_.prepareStatement(a, b)) - override def prepareStatement(a: String, b: Int, c: Int) = primitive(_.prepareStatement(a, b, c)) - override def prepareStatement(a: String, b: Int, c: Int, d: Int) = primitive(_.prepareStatement(a, b, c, d)) - override def releaseSavepoint(a: Savepoint) = primitive(_.releaseSavepoint(a)) - override def rollback: Kleisli[M, Connection, Unit] = primitive(_.rollback) - override def rollback(a: Savepoint) = primitive(_.rollback(a)) - override def setAutoCommit(a: Boolean) = primitive(_.setAutoCommit(a)) - override def setCatalog(a: String) = primitive(_.setCatalog(a)) - override def setClientInfo(a: Properties) = primitive(_.setClientInfo(a)) - override def setClientInfo(a: String, b: String) = primitive(_.setClientInfo(a, b)) - override def setHoldability(a: Int) = primitive(_.setHoldability(a)) - override def setNetworkTimeout(a: Executor, b: Int) = primitive(_.setNetworkTimeout(a, b)) - override def setReadOnly(a: Boolean) = primitive(_.setReadOnly(a)) - override def setSavepoint: Kleisli[M, Connection, Savepoint] = primitive(_.setSavepoint) - override def setSavepoint(a: String) = primitive(_.setSavepoint(a)) - override def setSchema(a: String) = primitive(_.setSchema(a)) - override def setShardingKey(a: ShardingKey) = primitive(_.setShardingKey(a)) - override def setShardingKey(a: ShardingKey, b: ShardingKey) = primitive(_.setShardingKey(a, b)) - override def setShardingKeyIfValid(a: ShardingKey, b: Int) = primitive(_.setShardingKeyIfValid(a, b)) - override def setShardingKeyIfValid(a: ShardingKey, b: ShardingKey, c: Int) = - primitive(_.setShardingKeyIfValid(a, b, c)) - override def setTransactionIsolation(a: Int) = primitive(_.setTransactionIsolation(a)) - override def setTypeMap(a: java.util.Map[String, Class[?]]) = primitive(_.setTypeMap(a)) - override def unwrap[T](a: Class[T]) = primitive(_.unwrap(a)) - - } - - trait StatementInterpreter extends StatementOp.Visitor[Kleisli[M, Statement, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: Statement => A): Kleisli[M, Statement, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, Statement, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, Statement, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, Statement, FiniteDuration] = outer.monotonic[Statement] - override def realTime: Kleisli[M, Statement, FiniteDuration] = outer.realTime[Statement] - override def delay[A](thunk: => A): Kleisli[M, Statement, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, Statement, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, Statement, Unit] = outer.canceled[Statement] - - // for operations using StatementIO we must call ourself recursively - override def handleErrorWith[A](fa: StatementIO[A])(f: Throwable => StatementIO[A]): Kleisli[M, Statement, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: StatementIO[A])(fb: StatementIO[B]): Kleisli[M, Statement, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[StatementIO] => StatementIO[A]): Kleisli[M, Statement, A] = - outer.uncancelable(this, doobie.free.statement.capturePoll)(body) - override def poll[A](poll: Any, fa: StatementIO[A]): Kleisli[M, Statement, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: StatementIO[A], fin: StatementIO[Unit]): Kleisli[M, Statement, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def addBatch(a: String) = primitive(_.addBatch(a)) - override def cancel: Kleisli[M, Statement, Unit] = primitive(_.cancel) - override def clearBatch: Kleisli[M, Statement, Unit] = primitive(_.clearBatch) - override def clearWarnings: Kleisli[M, Statement, Unit] = primitive(_.clearWarnings) - override def close: Kleisli[M, Statement, Unit] = primitive(_.close) - override def closeOnCompletion: Kleisli[M, Statement, Unit] = primitive(_.closeOnCompletion) - override def enquoteIdentifier(a: String, b: Boolean) = primitive(_.enquoteIdentifier(a, b)) - override def enquoteLiteral(a: String) = primitive(_.enquoteLiteral(a)) - override def enquoteNCharLiteral(a: String) = primitive(_.enquoteNCharLiteral(a)) - override def execute(a: String) = primitive(_.execute(a)) - override def execute(a: String, b: Array[Int]) = primitive(_.execute(a, b)) - override def execute(a: String, b: Array[String]) = primitive(_.execute(a, b)) - override def execute(a: String, b: Int) = primitive(_.execute(a, b)) - override def executeBatch: Kleisli[M, Statement, Array[Int]] = primitive(_.executeBatch) - override def executeLargeBatch: Kleisli[M, Statement, Array[Long]] = primitive(_.executeLargeBatch) - override def executeLargeUpdate(a: String) = primitive(_.executeLargeUpdate(a)) - override def executeLargeUpdate(a: String, b: Array[Int]) = primitive(_.executeLargeUpdate(a, b)) - override def executeLargeUpdate(a: String, b: Array[String]) = primitive(_.executeLargeUpdate(a, b)) - override def executeLargeUpdate(a: String, b: Int) = primitive(_.executeLargeUpdate(a, b)) - override def executeQuery(a: String) = primitive(_.executeQuery(a)) - override def executeUpdate(a: String) = primitive(_.executeUpdate(a)) - override def executeUpdate(a: String, b: Array[Int]) = primitive(_.executeUpdate(a, b)) - override def executeUpdate(a: String, b: Array[String]) = primitive(_.executeUpdate(a, b)) - override def executeUpdate(a: String, b: Int) = primitive(_.executeUpdate(a, b)) - override def getConnection: Kleisli[M, Statement, Connection] = primitive(_.getConnection) - override def getFetchDirection: Kleisli[M, Statement, Int] = primitive(_.getFetchDirection) - override def getFetchSize: Kleisli[M, Statement, Int] = primitive(_.getFetchSize) - override def getGeneratedKeys: Kleisli[M, Statement, ResultSet] = primitive(_.getGeneratedKeys) - override def getLargeMaxRows: Kleisli[M, Statement, Long] = primitive(_.getLargeMaxRows) - override def getLargeUpdateCount: Kleisli[M, Statement, Long] = primitive(_.getLargeUpdateCount) - override def getMaxFieldSize: Kleisli[M, Statement, Int] = primitive(_.getMaxFieldSize) - override def getMaxRows: Kleisli[M, Statement, Int] = primitive(_.getMaxRows) - override def getMoreResults: Kleisli[M, Statement, Boolean] = primitive(_.getMoreResults) - override def getMoreResults(a: Int) = primitive(_.getMoreResults(a)) - override def getQueryTimeout: Kleisli[M, Statement, Int] = primitive(_.getQueryTimeout) - override def getResultSet: Kleisli[M, Statement, ResultSet] = primitive(_.getResultSet) - override def getResultSetConcurrency: Kleisli[M, Statement, Int] = primitive(_.getResultSetConcurrency) - override def getResultSetHoldability: Kleisli[M, Statement, Int] = primitive(_.getResultSetHoldability) - override def getResultSetType: Kleisli[M, Statement, Int] = primitive(_.getResultSetType) - override def getUpdateCount: Kleisli[M, Statement, Int] = primitive(_.getUpdateCount) - override def getWarnings: Kleisli[M, Statement, SQLWarning] = primitive(_.getWarnings) - override def isCloseOnCompletion: Kleisli[M, Statement, Boolean] = primitive(_.isCloseOnCompletion) - override def isClosed: Kleisli[M, Statement, Boolean] = primitive(_.isClosed) - override def isPoolable: Kleisli[M, Statement, Boolean] = primitive(_.isPoolable) - override def isSimpleIdentifier(a: String) = primitive(_.isSimpleIdentifier(a)) - override def isWrapperFor(a: Class[?]) = primitive(_.isWrapperFor(a)) - override def setCursorName(a: String) = primitive(_.setCursorName(a)) - override def setEscapeProcessing(a: Boolean) = primitive(_.setEscapeProcessing(a)) - override def setFetchDirection(a: Int) = primitive(_.setFetchDirection(a)) - override def setFetchSize(a: Int) = primitive(_.setFetchSize(a)) - override def setLargeMaxRows(a: Long) = primitive(_.setLargeMaxRows(a)) - override def setMaxFieldSize(a: Int) = primitive(_.setMaxFieldSize(a)) - override def setMaxRows(a: Int) = primitive(_.setMaxRows(a)) - override def setPoolable(a: Boolean) = primitive(_.setPoolable(a)) - override def setQueryTimeout(a: Int) = primitive(_.setQueryTimeout(a)) - override def unwrap[T](a: Class[T]) = primitive(_.unwrap(a)) - - } - - trait PreparedStatementInterpreter extends PreparedStatementOp.Visitor[Kleisli[M, PreparedStatement, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: PreparedStatement => A): Kleisli[M, PreparedStatement, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, PreparedStatement, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, PreparedStatement, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, PreparedStatement, FiniteDuration] = outer.monotonic[PreparedStatement] - override def realTime: Kleisli[M, PreparedStatement, FiniteDuration] = outer.realTime[PreparedStatement] - override def delay[A](thunk: => A): Kleisli[M, PreparedStatement, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, PreparedStatement, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, PreparedStatement, Unit] = outer.canceled[PreparedStatement] - - // for operations using PreparedStatementIO we must call ourself recursively - override def handleErrorWith[A](fa: PreparedStatementIO[A])( - f: Throwable => PreparedStatementIO[A], - ): Kleisli[M, PreparedStatement, A] = outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: PreparedStatementIO[A])( - fb: PreparedStatementIO[B], - ): Kleisli[M, PreparedStatement, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A]( - body: Poll[PreparedStatementIO] => PreparedStatementIO[A], - ): Kleisli[M, PreparedStatement, A] = outer.uncancelable(this, doobie.free.preparedstatement.capturePoll)(body) - override def poll[A](poll: Any, fa: PreparedStatementIO[A]): Kleisli[M, PreparedStatement, A] = - outer.poll(this)(poll, fa) - override def onCancel[A]( - fa: PreparedStatementIO[A], - fin: PreparedStatementIO[Unit], - ): Kleisli[M, PreparedStatement, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def addBatch: Kleisli[M, PreparedStatement, Unit] = primitive(_.addBatch) - override def addBatch(a: String) = primitive(_.addBatch(a)) - override def cancel: Kleisli[M, PreparedStatement, Unit] = primitive(_.cancel) - override def clearBatch: Kleisli[M, PreparedStatement, Unit] = primitive(_.clearBatch) - override def clearParameters: Kleisli[M, PreparedStatement, Unit] = primitive(_.clearParameters) - override def clearWarnings: Kleisli[M, PreparedStatement, Unit] = primitive(_.clearWarnings) - override def close: Kleisli[M, PreparedStatement, Unit] = primitive(_.close) - override def closeOnCompletion: Kleisli[M, PreparedStatement, Unit] = primitive(_.closeOnCompletion) - override def enquoteIdentifier(a: String, b: Boolean) = primitive(_.enquoteIdentifier(a, b)) - override def enquoteLiteral(a: String) = primitive(_.enquoteLiteral(a)) - override def enquoteNCharLiteral(a: String) = primitive(_.enquoteNCharLiteral(a)) - override def execute: Kleisli[M, PreparedStatement, Boolean] = primitive(_.execute) - override def execute(a: String) = primitive(_.execute(a)) - override def execute(a: String, b: Array[Int]) = primitive(_.execute(a, b)) - override def execute(a: String, b: Array[String]) = primitive(_.execute(a, b)) - override def execute(a: String, b: Int) = primitive(_.execute(a, b)) - override def executeBatch: Kleisli[M, PreparedStatement, Array[Int]] = primitive(_.executeBatch) - override def executeLargeBatch: Kleisli[M, PreparedStatement, Array[Long]] = primitive(_.executeLargeBatch) - override def executeLargeUpdate: Kleisli[M, PreparedStatement, Long] = primitive(_.executeLargeUpdate) - override def executeLargeUpdate(a: String) = primitive(_.executeLargeUpdate(a)) - override def executeLargeUpdate(a: String, b: Array[Int]) = primitive(_.executeLargeUpdate(a, b)) - override def executeLargeUpdate(a: String, b: Array[String]) = primitive(_.executeLargeUpdate(a, b)) - override def executeLargeUpdate(a: String, b: Int) = primitive(_.executeLargeUpdate(a, b)) - override def executeQuery: Kleisli[M, PreparedStatement, ResultSet] = primitive(_.executeQuery) - override def executeQuery(a: String) = primitive(_.executeQuery(a)) - override def executeUpdate: Kleisli[M, PreparedStatement, Int] = primitive(_.executeUpdate) - override def executeUpdate(a: String) = primitive(_.executeUpdate(a)) - override def executeUpdate(a: String, b: Array[Int]) = primitive(_.executeUpdate(a, b)) - override def executeUpdate(a: String, b: Array[String]) = primitive(_.executeUpdate(a, b)) - override def executeUpdate(a: String, b: Int) = primitive(_.executeUpdate(a, b)) - override def getConnection: Kleisli[M, PreparedStatement, Connection] = primitive(_.getConnection) - override def getFetchDirection: Kleisli[M, PreparedStatement, Int] = primitive(_.getFetchDirection) - override def getFetchSize: Kleisli[M, PreparedStatement, Int] = primitive(_.getFetchSize) - override def getGeneratedKeys: Kleisli[M, PreparedStatement, ResultSet] = primitive(_.getGeneratedKeys) - override def getLargeMaxRows: Kleisli[M, PreparedStatement, Long] = primitive(_.getLargeMaxRows) - override def getLargeUpdateCount: Kleisli[M, PreparedStatement, Long] = primitive(_.getLargeUpdateCount) - override def getMaxFieldSize: Kleisli[M, PreparedStatement, Int] = primitive(_.getMaxFieldSize) - override def getMaxRows: Kleisli[M, PreparedStatement, Int] = primitive(_.getMaxRows) - override def getMetaData: Kleisli[M, PreparedStatement, ResultSetMetaData] = primitive(_.getMetaData) - override def getMoreResults: Kleisli[M, PreparedStatement, Boolean] = primitive(_.getMoreResults) - override def getMoreResults(a: Int) = primitive(_.getMoreResults(a)) - override def getParameterMetaData: Kleisli[M, PreparedStatement, ParameterMetaData] = - primitive(_.getParameterMetaData) - override def getQueryTimeout: Kleisli[M, PreparedStatement, Int] = primitive(_.getQueryTimeout) - override def getResultSet: Kleisli[M, PreparedStatement, ResultSet] = primitive(_.getResultSet) - override def getResultSetConcurrency: Kleisli[M, PreparedStatement, Int] = primitive(_.getResultSetConcurrency) - override def getResultSetHoldability: Kleisli[M, PreparedStatement, Int] = primitive(_.getResultSetHoldability) - override def getResultSetType: Kleisli[M, PreparedStatement, Int] = primitive(_.getResultSetType) - override def getUpdateCount: Kleisli[M, PreparedStatement, Int] = primitive(_.getUpdateCount) - override def getWarnings: Kleisli[M, PreparedStatement, SQLWarning] = primitive(_.getWarnings) - override def isCloseOnCompletion: Kleisli[M, PreparedStatement, Boolean] = primitive(_.isCloseOnCompletion) - override def isClosed: Kleisli[M, PreparedStatement, Boolean] = primitive(_.isClosed) - override def isPoolable: Kleisli[M, PreparedStatement, Boolean] = primitive(_.isPoolable) - override def isSimpleIdentifier(a: String) = primitive(_.isSimpleIdentifier(a)) - override def isWrapperFor(a: Class[?]) = primitive(_.isWrapperFor(a)) - override def setArray(a: Int, b: SqlArray) = primitive(_.setArray(a, b)) - override def setAsciiStream(a: Int, b: InputStream) = primitive(_.setAsciiStream(a, b)) - override def setAsciiStream(a: Int, b: InputStream, c: Int) = primitive(_.setAsciiStream(a, b, c)) - override def setAsciiStream(a: Int, b: InputStream, c: Long) = primitive(_.setAsciiStream(a, b, c)) - override def setBigDecimal(a: Int, b: BigDecimal) = primitive(_.setBigDecimal(a, b)) - override def setBinaryStream(a: Int, b: InputStream) = primitive(_.setBinaryStream(a, b)) - override def setBinaryStream(a: Int, b: InputStream, c: Int) = primitive(_.setBinaryStream(a, b, c)) - override def setBinaryStream(a: Int, b: InputStream, c: Long) = primitive(_.setBinaryStream(a, b, c)) - override def setBlob(a: Int, b: Blob) = primitive(_.setBlob(a, b)) - override def setBlob(a: Int, b: InputStream) = primitive(_.setBlob(a, b)) - override def setBlob(a: Int, b: InputStream, c: Long) = primitive(_.setBlob(a, b, c)) - override def setBoolean(a: Int, b: Boolean) = primitive(_.setBoolean(a, b)) - override def setByte(a: Int, b: Byte) = primitive(_.setByte(a, b)) - override def setBytes(a: Int, b: Array[Byte]) = primitive(_.setBytes(a, b)) - override def setCharacterStream(a: Int, b: Reader) = primitive(_.setCharacterStream(a, b)) - override def setCharacterStream(a: Int, b: Reader, c: Int) = primitive(_.setCharacterStream(a, b, c)) - override def setCharacterStream(a: Int, b: Reader, c: Long) = primitive(_.setCharacterStream(a, b, c)) - override def setClob(a: Int, b: Clob) = primitive(_.setClob(a, b)) - override def setClob(a: Int, b: Reader) = primitive(_.setClob(a, b)) - override def setClob(a: Int, b: Reader, c: Long) = primitive(_.setClob(a, b, c)) - override def setCursorName(a: String) = primitive(_.setCursorName(a)) - override def setDate(a: Int, b: Date) = primitive(_.setDate(a, b)) - override def setDate(a: Int, b: Date, c: Calendar) = primitive(_.setDate(a, b, c)) - override def setDouble(a: Int, b: Double) = primitive(_.setDouble(a, b)) - override def setEscapeProcessing(a: Boolean) = primitive(_.setEscapeProcessing(a)) - override def setFetchDirection(a: Int) = primitive(_.setFetchDirection(a)) - override def setFetchSize(a: Int) = primitive(_.setFetchSize(a)) - override def setFloat(a: Int, b: Float) = primitive(_.setFloat(a, b)) - override def setInt(a: Int, b: Int) = primitive(_.setInt(a, b)) - override def setLargeMaxRows(a: Long) = primitive(_.setLargeMaxRows(a)) - override def setLong(a: Int, b: Long) = primitive(_.setLong(a, b)) - override def setMaxFieldSize(a: Int) = primitive(_.setMaxFieldSize(a)) - override def setMaxRows(a: Int) = primitive(_.setMaxRows(a)) - override def setNCharacterStream(a: Int, b: Reader) = primitive(_.setNCharacterStream(a, b)) - override def setNCharacterStream(a: Int, b: Reader, c: Long) = primitive(_.setNCharacterStream(a, b, c)) - override def setNClob(a: Int, b: NClob) = primitive(_.setNClob(a, b)) - override def setNClob(a: Int, b: Reader) = primitive(_.setNClob(a, b)) - override def setNClob(a: Int, b: Reader, c: Long) = primitive(_.setNClob(a, b, c)) - override def setNString(a: Int, b: String) = primitive(_.setNString(a, b)) - override def setNull(a: Int, b: Int) = primitive(_.setNull(a, b)) - override def setNull(a: Int, b: Int, c: String) = primitive(_.setNull(a, b, c)) - override def setObject(a: Int, b: AnyRef) = primitive(_.setObject(a, b)) - override def setObject(a: Int, b: AnyRef, c: Int) = primitive(_.setObject(a, b, c)) - override def setObject(a: Int, b: AnyRef, c: Int, d: Int) = primitive(_.setObject(a, b, c, d)) - override def setObject(a: Int, b: AnyRef, c: SQLType) = primitive(_.setObject(a, b, c)) - override def setObject(a: Int, b: AnyRef, c: SQLType, d: Int) = primitive(_.setObject(a, b, c, d)) - override def setPoolable(a: Boolean) = primitive(_.setPoolable(a)) - override def setQueryTimeout(a: Int) = primitive(_.setQueryTimeout(a)) - override def setRef(a: Int, b: Ref) = primitive(_.setRef(a, b)) - override def setRowId(a: Int, b: RowId) = primitive(_.setRowId(a, b)) - override def setSQLXML(a: Int, b: SQLXML) = primitive(_.setSQLXML(a, b)) - override def setShort(a: Int, b: Short) = primitive(_.setShort(a, b)) - override def setString(a: Int, b: String) = primitive(_.setString(a, b)) - override def setTime(a: Int, b: Time) = primitive(_.setTime(a, b)) - override def setTime(a: Int, b: Time, c: Calendar) = primitive(_.setTime(a, b, c)) - override def setTimestamp(a: Int, b: Timestamp) = primitive(_.setTimestamp(a, b)) - override def setTimestamp(a: Int, b: Timestamp, c: Calendar) = primitive(_.setTimestamp(a, b, c)) - override def setURL(a: Int, b: URL) = primitive(_.setURL(a, b)) - override def unwrap[T](a: Class[T]) = primitive(_.unwrap(a)) - - } - - trait CallableStatementInterpreter extends CallableStatementOp.Visitor[Kleisli[M, CallableStatement, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: CallableStatement => A): Kleisli[M, CallableStatement, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, CallableStatement, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, CallableStatement, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, CallableStatement, FiniteDuration] = outer.monotonic[CallableStatement] - override def realTime: Kleisli[M, CallableStatement, FiniteDuration] = outer.realTime[CallableStatement] - override def delay[A](thunk: => A): Kleisli[M, CallableStatement, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, CallableStatement, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, CallableStatement, Unit] = outer.canceled[CallableStatement] - - // for operations using CallableStatementIO we must call ourself recursively - override def handleErrorWith[A](fa: CallableStatementIO[A])( - f: Throwable => CallableStatementIO[A], - ): Kleisli[M, CallableStatement, A] = outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: CallableStatementIO[A])( - fb: CallableStatementIO[B], - ): Kleisli[M, CallableStatement, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A]( - body: Poll[CallableStatementIO] => CallableStatementIO[A], - ): Kleisli[M, CallableStatement, A] = outer.uncancelable(this, doobie.free.callablestatement.capturePoll)(body) - override def poll[A](poll: Any, fa: CallableStatementIO[A]): Kleisli[M, CallableStatement, A] = - outer.poll(this)(poll, fa) - override def onCancel[A]( - fa: CallableStatementIO[A], - fin: CallableStatementIO[Unit], - ): Kleisli[M, CallableStatement, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def addBatch: Kleisli[M, CallableStatement, Unit] = primitive(_.addBatch) - override def addBatch(a: String) = primitive(_.addBatch(a)) - override def cancel: Kleisli[M, CallableStatement, Unit] = primitive(_.cancel) - override def clearBatch: Kleisli[M, CallableStatement, Unit] = primitive(_.clearBatch) - override def clearParameters: Kleisli[M, CallableStatement, Unit] = primitive(_.clearParameters) - override def clearWarnings: Kleisli[M, CallableStatement, Unit] = primitive(_.clearWarnings) - override def close: Kleisli[M, CallableStatement, Unit] = primitive(_.close) - override def closeOnCompletion: Kleisli[M, CallableStatement, Unit] = primitive(_.closeOnCompletion) - override def enquoteIdentifier(a: String, b: Boolean) = primitive(_.enquoteIdentifier(a, b)) - override def enquoteLiteral(a: String) = primitive(_.enquoteLiteral(a)) - override def enquoteNCharLiteral(a: String) = primitive(_.enquoteNCharLiteral(a)) - override def execute: Kleisli[M, CallableStatement, Boolean] = primitive(_.execute) - override def execute(a: String) = primitive(_.execute(a)) - override def execute(a: String, b: Array[Int]) = primitive(_.execute(a, b)) - override def execute(a: String, b: Array[String]) = primitive(_.execute(a, b)) - override def execute(a: String, b: Int) = primitive(_.execute(a, b)) - override def executeBatch: Kleisli[M, CallableStatement, Array[Int]] = primitive(_.executeBatch) - override def executeLargeBatch: Kleisli[M, CallableStatement, Array[Long]] = primitive(_.executeLargeBatch) - override def executeLargeUpdate: Kleisli[M, CallableStatement, Long] = primitive(_.executeLargeUpdate) - override def executeLargeUpdate(a: String) = primitive(_.executeLargeUpdate(a)) - override def executeLargeUpdate(a: String, b: Array[Int]) = primitive(_.executeLargeUpdate(a, b)) - override def executeLargeUpdate(a: String, b: Array[String]) = primitive(_.executeLargeUpdate(a, b)) - override def executeLargeUpdate(a: String, b: Int) = primitive(_.executeLargeUpdate(a, b)) - override def executeQuery: Kleisli[M, CallableStatement, ResultSet] = primitive(_.executeQuery) - override def executeQuery(a: String) = primitive(_.executeQuery(a)) - override def executeUpdate: Kleisli[M, CallableStatement, Int] = primitive(_.executeUpdate) - override def executeUpdate(a: String) = primitive(_.executeUpdate(a)) - override def executeUpdate(a: String, b: Array[Int]) = primitive(_.executeUpdate(a, b)) - override def executeUpdate(a: String, b: Array[String]) = primitive(_.executeUpdate(a, b)) - override def executeUpdate(a: String, b: Int) = primitive(_.executeUpdate(a, b)) - override def getArray(a: Int) = primitive(_.getArray(a)) - override def getArray(a: String) = primitive(_.getArray(a)) - override def getBigDecimal(a: Int) = primitive(_.getBigDecimal(a)) - override def getBigDecimal(a: String) = primitive(_.getBigDecimal(a)) - override def getBlob(a: Int) = primitive(_.getBlob(a)) - override def getBlob(a: String) = primitive(_.getBlob(a)) - override def getBoolean(a: Int) = primitive(_.getBoolean(a)) - override def getBoolean(a: String) = primitive(_.getBoolean(a)) - override def getByte(a: Int) = primitive(_.getByte(a)) - override def getByte(a: String) = primitive(_.getByte(a)) - override def getBytes(a: Int) = primitive(_.getBytes(a)) - override def getBytes(a: String) = primitive(_.getBytes(a)) - override def getCharacterStream(a: Int) = primitive(_.getCharacterStream(a)) - override def getCharacterStream(a: String) = primitive(_.getCharacterStream(a)) - override def getClob(a: Int) = primitive(_.getClob(a)) - override def getClob(a: String) = primitive(_.getClob(a)) - override def getConnection: Kleisli[M, CallableStatement, Connection] = primitive(_.getConnection) - override def getDate(a: Int) = primitive(_.getDate(a)) - override def getDate(a: Int, b: Calendar) = primitive(_.getDate(a, b)) - override def getDate(a: String) = primitive(_.getDate(a)) - override def getDate(a: String, b: Calendar) = primitive(_.getDate(a, b)) - override def getDouble(a: Int) = primitive(_.getDouble(a)) - override def getDouble(a: String) = primitive(_.getDouble(a)) - override def getFetchDirection: Kleisli[M, CallableStatement, Int] = primitive(_.getFetchDirection) - override def getFetchSize: Kleisli[M, CallableStatement, Int] = primitive(_.getFetchSize) - override def getFloat(a: Int) = primitive(_.getFloat(a)) - override def getFloat(a: String) = primitive(_.getFloat(a)) - override def getGeneratedKeys: Kleisli[M, CallableStatement, ResultSet] = primitive(_.getGeneratedKeys) - override def getInt(a: Int) = primitive(_.getInt(a)) - override def getInt(a: String) = primitive(_.getInt(a)) - override def getLargeMaxRows: Kleisli[M, CallableStatement, Long] = primitive(_.getLargeMaxRows) - override def getLargeUpdateCount: Kleisli[M, CallableStatement, Long] = primitive(_.getLargeUpdateCount) - override def getLong(a: Int) = primitive(_.getLong(a)) - override def getLong(a: String) = primitive(_.getLong(a)) - override def getMaxFieldSize: Kleisli[M, CallableStatement, Int] = primitive(_.getMaxFieldSize) - override def getMaxRows: Kleisli[M, CallableStatement, Int] = primitive(_.getMaxRows) - override def getMetaData: Kleisli[M, CallableStatement, ResultSetMetaData] = primitive(_.getMetaData) - override def getMoreResults: Kleisli[M, CallableStatement, Boolean] = primitive(_.getMoreResults) - override def getMoreResults(a: Int) = primitive(_.getMoreResults(a)) - override def getNCharacterStream(a: Int) = primitive(_.getNCharacterStream(a)) - override def getNCharacterStream(a: String) = primitive(_.getNCharacterStream(a)) - override def getNClob(a: Int) = primitive(_.getNClob(a)) - override def getNClob(a: String) = primitive(_.getNClob(a)) - override def getNString(a: Int) = primitive(_.getNString(a)) - override def getNString(a: String) = primitive(_.getNString(a)) - override def getObject(a: Int) = primitive(_.getObject(a)) - override def getObject[T](a: Int, b: Class[T]) = primitive(_.getObject(a, b)) - override def getObject(a: Int, b: java.util.Map[String, Class[?]]) = primitive(_.getObject(a, b)) - override def getObject(a: String) = primitive(_.getObject(a)) - override def getObject[T](a: String, b: Class[T]) = primitive(_.getObject(a, b)) - override def getObject(a: String, b: java.util.Map[String, Class[?]]) = primitive(_.getObject(a, b)) - override def getParameterMetaData: Kleisli[M, CallableStatement, ParameterMetaData] = - primitive(_.getParameterMetaData) - override def getQueryTimeout: Kleisli[M, CallableStatement, Int] = primitive(_.getQueryTimeout) - override def getRef(a: Int) = primitive(_.getRef(a)) - override def getRef(a: String) = primitive(_.getRef(a)) - override def getResultSet: Kleisli[M, CallableStatement, ResultSet] = primitive(_.getResultSet) - override def getResultSetConcurrency: Kleisli[M, CallableStatement, Int] = primitive(_.getResultSetConcurrency) - override def getResultSetHoldability: Kleisli[M, CallableStatement, Int] = primitive(_.getResultSetHoldability) - override def getResultSetType: Kleisli[M, CallableStatement, Int] = primitive(_.getResultSetType) - override def getRowId(a: Int) = primitive(_.getRowId(a)) - override def getRowId(a: String) = primitive(_.getRowId(a)) - override def getSQLXML(a: Int) = primitive(_.getSQLXML(a)) - override def getSQLXML(a: String) = primitive(_.getSQLXML(a)) - override def getShort(a: Int) = primitive(_.getShort(a)) - override def getShort(a: String) = primitive(_.getShort(a)) - override def getString(a: Int) = primitive(_.getString(a)) - override def getString(a: String) = primitive(_.getString(a)) - override def getTime(a: Int) = primitive(_.getTime(a)) - override def getTime(a: Int, b: Calendar) = primitive(_.getTime(a, b)) - override def getTime(a: String) = primitive(_.getTime(a)) - override def getTime(a: String, b: Calendar) = primitive(_.getTime(a, b)) - override def getTimestamp(a: Int) = primitive(_.getTimestamp(a)) - override def getTimestamp(a: Int, b: Calendar) = primitive(_.getTimestamp(a, b)) - override def getTimestamp(a: String) = primitive(_.getTimestamp(a)) - override def getTimestamp(a: String, b: Calendar) = primitive(_.getTimestamp(a, b)) - override def getURL(a: Int) = primitive(_.getURL(a)) - override def getURL(a: String) = primitive(_.getURL(a)) - override def getUpdateCount: Kleisli[M, CallableStatement, Int] = primitive(_.getUpdateCount) - override def getWarnings: Kleisli[M, CallableStatement, SQLWarning] = primitive(_.getWarnings) - override def isCloseOnCompletion: Kleisli[M, CallableStatement, Boolean] = primitive(_.isCloseOnCompletion) - override def isClosed: Kleisli[M, CallableStatement, Boolean] = primitive(_.isClosed) - override def isPoolable: Kleisli[M, CallableStatement, Boolean] = primitive(_.isPoolable) - override def isSimpleIdentifier(a: String) = primitive(_.isSimpleIdentifier(a)) - override def isWrapperFor(a: Class[?]) = primitive(_.isWrapperFor(a)) - override def registerOutParameter(a: Int, b: Int) = primitive(_.registerOutParameter(a, b)) - override def registerOutParameter(a: Int, b: Int, c: Int) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: Int, b: Int, c: String) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: Int, b: SQLType) = primitive(_.registerOutParameter(a, b)) - override def registerOutParameter(a: Int, b: SQLType, c: Int) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: Int, b: SQLType, c: String) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: String, b: Int) = primitive(_.registerOutParameter(a, b)) - override def registerOutParameter(a: String, b: Int, c: Int) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: String, b: Int, c: String) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: String, b: SQLType) = primitive(_.registerOutParameter(a, b)) - override def registerOutParameter(a: String, b: SQLType, c: Int) = primitive(_.registerOutParameter(a, b, c)) - override def registerOutParameter(a: String, b: SQLType, c: String) = primitive(_.registerOutParameter(a, b, c)) - override def setArray(a: Int, b: SqlArray) = primitive(_.setArray(a, b)) - override def setAsciiStream(a: Int, b: InputStream) = primitive(_.setAsciiStream(a, b)) - override def setAsciiStream(a: Int, b: InputStream, c: Int) = primitive(_.setAsciiStream(a, b, c)) - override def setAsciiStream(a: Int, b: InputStream, c: Long) = primitive(_.setAsciiStream(a, b, c)) - override def setAsciiStream(a: String, b: InputStream) = primitive(_.setAsciiStream(a, b)) - override def setAsciiStream(a: String, b: InputStream, c: Int) = primitive(_.setAsciiStream(a, b, c)) - override def setAsciiStream(a: String, b: InputStream, c: Long) = primitive(_.setAsciiStream(a, b, c)) - override def setBigDecimal(a: Int, b: BigDecimal) = primitive(_.setBigDecimal(a, b)) - override def setBigDecimal(a: String, b: BigDecimal) = primitive(_.setBigDecimal(a, b)) - override def setBinaryStream(a: Int, b: InputStream) = primitive(_.setBinaryStream(a, b)) - override def setBinaryStream(a: Int, b: InputStream, c: Int) = primitive(_.setBinaryStream(a, b, c)) - override def setBinaryStream(a: Int, b: InputStream, c: Long) = primitive(_.setBinaryStream(a, b, c)) - override def setBinaryStream(a: String, b: InputStream) = primitive(_.setBinaryStream(a, b)) - override def setBinaryStream(a: String, b: InputStream, c: Int) = primitive(_.setBinaryStream(a, b, c)) - override def setBinaryStream(a: String, b: InputStream, c: Long) = primitive(_.setBinaryStream(a, b, c)) - override def setBlob(a: Int, b: Blob) = primitive(_.setBlob(a, b)) - override def setBlob(a: Int, b: InputStream) = primitive(_.setBlob(a, b)) - override def setBlob(a: Int, b: InputStream, c: Long) = primitive(_.setBlob(a, b, c)) - override def setBlob(a: String, b: Blob) = primitive(_.setBlob(a, b)) - override def setBlob(a: String, b: InputStream) = primitive(_.setBlob(a, b)) - override def setBlob(a: String, b: InputStream, c: Long) = primitive(_.setBlob(a, b, c)) - override def setBoolean(a: Int, b: Boolean) = primitive(_.setBoolean(a, b)) - override def setBoolean(a: String, b: Boolean) = primitive(_.setBoolean(a, b)) - override def setByte(a: Int, b: Byte) = primitive(_.setByte(a, b)) - override def setByte(a: String, b: Byte) = primitive(_.setByte(a, b)) - override def setBytes(a: Int, b: Array[Byte]) = primitive(_.setBytes(a, b)) - override def setBytes(a: String, b: Array[Byte]) = primitive(_.setBytes(a, b)) - override def setCharacterStream(a: Int, b: Reader) = primitive(_.setCharacterStream(a, b)) - override def setCharacterStream(a: Int, b: Reader, c: Int) = primitive(_.setCharacterStream(a, b, c)) - override def setCharacterStream(a: Int, b: Reader, c: Long) = primitive(_.setCharacterStream(a, b, c)) - override def setCharacterStream(a: String, b: Reader) = primitive(_.setCharacterStream(a, b)) - override def setCharacterStream(a: String, b: Reader, c: Int) = primitive(_.setCharacterStream(a, b, c)) - override def setCharacterStream(a: String, b: Reader, c: Long) = primitive(_.setCharacterStream(a, b, c)) - override def setClob(a: Int, b: Clob) = primitive(_.setClob(a, b)) - override def setClob(a: Int, b: Reader) = primitive(_.setClob(a, b)) - override def setClob(a: Int, b: Reader, c: Long) = primitive(_.setClob(a, b, c)) - override def setClob(a: String, b: Clob) = primitive(_.setClob(a, b)) - override def setClob(a: String, b: Reader) = primitive(_.setClob(a, b)) - override def setClob(a: String, b: Reader, c: Long) = primitive(_.setClob(a, b, c)) - override def setCursorName(a: String) = primitive(_.setCursorName(a)) - override def setDate(a: Int, b: Date) = primitive(_.setDate(a, b)) - override def setDate(a: Int, b: Date, c: Calendar) = primitive(_.setDate(a, b, c)) - override def setDate(a: String, b: Date) = primitive(_.setDate(a, b)) - override def setDate(a: String, b: Date, c: Calendar) = primitive(_.setDate(a, b, c)) - override def setDouble(a: Int, b: Double) = primitive(_.setDouble(a, b)) - override def setDouble(a: String, b: Double) = primitive(_.setDouble(a, b)) - override def setEscapeProcessing(a: Boolean) = primitive(_.setEscapeProcessing(a)) - override def setFetchDirection(a: Int) = primitive(_.setFetchDirection(a)) - override def setFetchSize(a: Int) = primitive(_.setFetchSize(a)) - override def setFloat(a: Int, b: Float) = primitive(_.setFloat(a, b)) - override def setFloat(a: String, b: Float) = primitive(_.setFloat(a, b)) - override def setInt(a: Int, b: Int) = primitive(_.setInt(a, b)) - override def setInt(a: String, b: Int) = primitive(_.setInt(a, b)) - override def setLargeMaxRows(a: Long) = primitive(_.setLargeMaxRows(a)) - override def setLong(a: Int, b: Long) = primitive(_.setLong(a, b)) - override def setLong(a: String, b: Long) = primitive(_.setLong(a, b)) - override def setMaxFieldSize(a: Int) = primitive(_.setMaxFieldSize(a)) - override def setMaxRows(a: Int) = primitive(_.setMaxRows(a)) - override def setNCharacterStream(a: Int, b: Reader) = primitive(_.setNCharacterStream(a, b)) - override def setNCharacterStream(a: Int, b: Reader, c: Long) = primitive(_.setNCharacterStream(a, b, c)) - override def setNCharacterStream(a: String, b: Reader) = primitive(_.setNCharacterStream(a, b)) - override def setNCharacterStream(a: String, b: Reader, c: Long) = primitive(_.setNCharacterStream(a, b, c)) - override def setNClob(a: Int, b: NClob) = primitive(_.setNClob(a, b)) - override def setNClob(a: Int, b: Reader) = primitive(_.setNClob(a, b)) - override def setNClob(a: Int, b: Reader, c: Long) = primitive(_.setNClob(a, b, c)) - override def setNClob(a: String, b: NClob) = primitive(_.setNClob(a, b)) - override def setNClob(a: String, b: Reader) = primitive(_.setNClob(a, b)) - override def setNClob(a: String, b: Reader, c: Long) = primitive(_.setNClob(a, b, c)) - override def setNString(a: Int, b: String) = primitive(_.setNString(a, b)) - override def setNString(a: String, b: String) = primitive(_.setNString(a, b)) - override def setNull(a: Int, b: Int) = primitive(_.setNull(a, b)) - override def setNull(a: Int, b: Int, c: String) = primitive(_.setNull(a, b, c)) - override def setNull(a: String, b: Int) = primitive(_.setNull(a, b)) - override def setNull(a: String, b: Int, c: String) = primitive(_.setNull(a, b, c)) - override def setObject(a: Int, b: AnyRef) = primitive(_.setObject(a, b)) - override def setObject(a: Int, b: AnyRef, c: Int) = primitive(_.setObject(a, b, c)) - override def setObject(a: Int, b: AnyRef, c: Int, d: Int) = primitive(_.setObject(a, b, c, d)) - override def setObject(a: Int, b: AnyRef, c: SQLType) = primitive(_.setObject(a, b, c)) - override def setObject(a: Int, b: AnyRef, c: SQLType, d: Int) = primitive(_.setObject(a, b, c, d)) - override def setObject(a: String, b: AnyRef) = primitive(_.setObject(a, b)) - override def setObject(a: String, b: AnyRef, c: Int) = primitive(_.setObject(a, b, c)) - override def setObject(a: String, b: AnyRef, c: Int, d: Int) = primitive(_.setObject(a, b, c, d)) - override def setObject(a: String, b: AnyRef, c: SQLType) = primitive(_.setObject(a, b, c)) - override def setObject(a: String, b: AnyRef, c: SQLType, d: Int) = primitive(_.setObject(a, b, c, d)) - override def setPoolable(a: Boolean) = primitive(_.setPoolable(a)) - override def setQueryTimeout(a: Int) = primitive(_.setQueryTimeout(a)) - override def setRef(a: Int, b: Ref) = primitive(_.setRef(a, b)) - override def setRowId(a: Int, b: RowId) = primitive(_.setRowId(a, b)) - override def setRowId(a: String, b: RowId) = primitive(_.setRowId(a, b)) - override def setSQLXML(a: Int, b: SQLXML) = primitive(_.setSQLXML(a, b)) - override def setSQLXML(a: String, b: SQLXML) = primitive(_.setSQLXML(a, b)) - override def setShort(a: Int, b: Short) = primitive(_.setShort(a, b)) - override def setShort(a: String, b: Short) = primitive(_.setShort(a, b)) - override def setString(a: Int, b: String) = primitive(_.setString(a, b)) - override def setString(a: String, b: String) = primitive(_.setString(a, b)) - override def setTime(a: Int, b: Time) = primitive(_.setTime(a, b)) - override def setTime(a: Int, b: Time, c: Calendar) = primitive(_.setTime(a, b, c)) - override def setTime(a: String, b: Time) = primitive(_.setTime(a, b)) - override def setTime(a: String, b: Time, c: Calendar) = primitive(_.setTime(a, b, c)) - override def setTimestamp(a: Int, b: Timestamp) = primitive(_.setTimestamp(a, b)) - override def setTimestamp(a: Int, b: Timestamp, c: Calendar) = primitive(_.setTimestamp(a, b, c)) - override def setTimestamp(a: String, b: Timestamp) = primitive(_.setTimestamp(a, b)) - override def setTimestamp(a: String, b: Timestamp, c: Calendar) = primitive(_.setTimestamp(a, b, c)) - override def setURL(a: Int, b: URL) = primitive(_.setURL(a, b)) - override def setURL(a: String, b: URL) = primitive(_.setURL(a, b)) - override def unwrap[T](a: Class[T]) = primitive(_.unwrap(a)) - override def wasNull: Kleisli[M, CallableStatement, Boolean] = primitive(_.wasNull) - - } - - trait ResultSetInterpreter extends ResultSetOp.Visitor[Kleisli[M, ResultSet, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: ResultSet => A): Kleisli[M, ResultSet, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, ResultSet, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, ResultSet, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, ResultSet, FiniteDuration] = outer.monotonic[ResultSet] - override def realTime: Kleisli[M, ResultSet, FiniteDuration] = outer.realTime[ResultSet] - override def delay[A](thunk: => A): Kleisli[M, ResultSet, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, ResultSet, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, ResultSet, Unit] = outer.canceled[ResultSet] - - // for operations using ResultSetIO we must call ourself recursively - override def handleErrorWith[A](fa: ResultSetIO[A])(f: Throwable => ResultSetIO[A]): Kleisli[M, ResultSet, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: ResultSetIO[A])(fb: ResultSetIO[B]): Kleisli[M, ResultSet, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[ResultSetIO] => ResultSetIO[A]): Kleisli[M, ResultSet, A] = - outer.uncancelable(this, doobie.free.resultset.capturePoll)(body) - override def poll[A](poll: Any, fa: ResultSetIO[A]): Kleisli[M, ResultSet, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: ResultSetIO[A], fin: ResultSetIO[Unit]): Kleisli[M, ResultSet, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def absolute(a: Int) = primitive(_.absolute(a)) - override def afterLast: Kleisli[M, ResultSet, Unit] = primitive(_.afterLast) - override def beforeFirst: Kleisli[M, ResultSet, Unit] = primitive(_.beforeFirst) - override def cancelRowUpdates: Kleisli[M, ResultSet, Unit] = primitive(_.cancelRowUpdates) - override def clearWarnings: Kleisli[M, ResultSet, Unit] = primitive(_.clearWarnings) - override def close: Kleisli[M, ResultSet, Unit] = primitive(_.close) - override def deleteRow: Kleisli[M, ResultSet, Unit] = primitive(_.deleteRow) - override def findColumn(a: String) = primitive(_.findColumn(a)) - override def first: Kleisli[M, ResultSet, Boolean] = primitive(_.first) - override def getArray(a: Int) = primitive(_.getArray(a)) - override def getArray(a: String) = primitive(_.getArray(a)) - override def getAsciiStream(a: Int) = primitive(_.getAsciiStream(a)) - override def getAsciiStream(a: String) = primitive(_.getAsciiStream(a)) - override def getBigDecimal(a: Int) = primitive(_.getBigDecimal(a)) - override def getBigDecimal(a: String) = primitive(_.getBigDecimal(a)) - override def getBinaryStream(a: Int) = primitive(_.getBinaryStream(a)) - override def getBinaryStream(a: String) = primitive(_.getBinaryStream(a)) - override def getBlob(a: Int) = primitive(_.getBlob(a)) - override def getBlob(a: String) = primitive(_.getBlob(a)) - override def getBoolean(a: Int) = primitive(_.getBoolean(a)) - override def getBoolean(a: String) = primitive(_.getBoolean(a)) - override def getByte(a: Int) = primitive(_.getByte(a)) - override def getByte(a: String) = primitive(_.getByte(a)) - override def getBytes(a: Int) = primitive(_.getBytes(a)) - override def getBytes(a: String) = primitive(_.getBytes(a)) - override def getCharacterStream(a: Int) = primitive(_.getCharacterStream(a)) - override def getCharacterStream(a: String) = primitive(_.getCharacterStream(a)) - override def getClob(a: Int) = primitive(_.getClob(a)) - override def getClob(a: String) = primitive(_.getClob(a)) - override def getConcurrency: Kleisli[M, ResultSet, Int] = primitive(_.getConcurrency) - override def getCursorName: Kleisli[M, ResultSet, String] = primitive(_.getCursorName) - override def getDate(a: Int) = primitive(_.getDate(a)) - override def getDate(a: Int, b: Calendar) = primitive(_.getDate(a, b)) - override def getDate(a: String) = primitive(_.getDate(a)) - override def getDate(a: String, b: Calendar) = primitive(_.getDate(a, b)) - override def getDouble(a: Int) = primitive(_.getDouble(a)) - override def getDouble(a: String) = primitive(_.getDouble(a)) - override def getFetchDirection: Kleisli[M, ResultSet, Int] = primitive(_.getFetchDirection) - override def getFetchSize: Kleisli[M, ResultSet, Int] = primitive(_.getFetchSize) - override def getFloat(a: Int) = primitive(_.getFloat(a)) - override def getFloat(a: String) = primitive(_.getFloat(a)) - override def getHoldability: Kleisli[M, ResultSet, Int] = primitive(_.getHoldability) - override def getInt(a: Int) = primitive(_.getInt(a)) - override def getInt(a: String) = primitive(_.getInt(a)) - override def getLong(a: Int) = primitive(_.getLong(a)) - override def getLong(a: String) = primitive(_.getLong(a)) - override def getMetaData: Kleisli[M, ResultSet, ResultSetMetaData] = primitive(_.getMetaData) - override def getNCharacterStream(a: Int) = primitive(_.getNCharacterStream(a)) - override def getNCharacterStream(a: String) = primitive(_.getNCharacterStream(a)) - override def getNClob(a: Int) = primitive(_.getNClob(a)) - override def getNClob(a: String) = primitive(_.getNClob(a)) - override def getNString(a: Int) = primitive(_.getNString(a)) - override def getNString(a: String) = primitive(_.getNString(a)) - override def getObject(a: Int) = primitive(_.getObject(a)) - override def getObject[T](a: Int, b: Class[T]) = primitive(_.getObject(a, b)) - override def getObject(a: Int, b: java.util.Map[String, Class[?]]) = primitive(_.getObject(a, b)) - override def getObject(a: String) = primitive(_.getObject(a)) - override def getObject[T](a: String, b: Class[T]) = primitive(_.getObject(a, b)) - override def getObject(a: String, b: java.util.Map[String, Class[?]]) = primitive(_.getObject(a, b)) - override def getRef(a: Int) = primitive(_.getRef(a)) - override def getRef(a: String) = primitive(_.getRef(a)) - override def getRow: Kleisli[M, ResultSet, Int] = primitive(_.getRow) - override def getRowId(a: Int) = primitive(_.getRowId(a)) - override def getRowId(a: String) = primitive(_.getRowId(a)) - override def getSQLXML(a: Int) = primitive(_.getSQLXML(a)) - override def getSQLXML(a: String) = primitive(_.getSQLXML(a)) - override def getShort(a: Int) = primitive(_.getShort(a)) - override def getShort(a: String) = primitive(_.getShort(a)) - override def getStatement: Kleisli[M, ResultSet, Statement] = primitive(_.getStatement) - override def getString(a: Int) = primitive(_.getString(a)) - override def getString(a: String) = primitive(_.getString(a)) - override def getTime(a: Int) = primitive(_.getTime(a)) - override def getTime(a: Int, b: Calendar) = primitive(_.getTime(a, b)) - override def getTime(a: String) = primitive(_.getTime(a)) - override def getTime(a: String, b: Calendar) = primitive(_.getTime(a, b)) - override def getTimestamp(a: Int) = primitive(_.getTimestamp(a)) - override def getTimestamp(a: Int, b: Calendar) = primitive(_.getTimestamp(a, b)) - override def getTimestamp(a: String) = primitive(_.getTimestamp(a)) - override def getTimestamp(a: String, b: Calendar) = primitive(_.getTimestamp(a, b)) - override def getType: Kleisli[M, ResultSet, Int] = primitive(_.getType) - override def getURL(a: Int) = primitive(_.getURL(a)) - override def getURL(a: String) = primitive(_.getURL(a)) - override def getWarnings: Kleisli[M, ResultSet, SQLWarning] = primitive(_.getWarnings) - override def insertRow: Kleisli[M, ResultSet, Unit] = primitive(_.insertRow) - override def isAfterLast: Kleisli[M, ResultSet, Boolean] = primitive(_.isAfterLast) - override def isBeforeFirst: Kleisli[M, ResultSet, Boolean] = primitive(_.isBeforeFirst) - override def isClosed: Kleisli[M, ResultSet, Boolean] = primitive(_.isClosed) - override def isFirst: Kleisli[M, ResultSet, Boolean] = primitive(_.isFirst) - override def isLast: Kleisli[M, ResultSet, Boolean] = primitive(_.isLast) - override def isWrapperFor(a: Class[?]) = primitive(_.isWrapperFor(a)) - override def last: Kleisli[M, ResultSet, Boolean] = primitive(_.last) - override def moveToCurrentRow: Kleisli[M, ResultSet, Unit] = primitive(_.moveToCurrentRow) - override def moveToInsertRow: Kleisli[M, ResultSet, Unit] = primitive(_.moveToInsertRow) - override def next: Kleisli[M, ResultSet, Boolean] = primitive(_.next) - override def previous: Kleisli[M, ResultSet, Boolean] = primitive(_.previous) - override def refreshRow: Kleisli[M, ResultSet, Unit] = primitive(_.refreshRow) - override def relative(a: Int) = primitive(_.relative(a)) - override def rowDeleted: Kleisli[M, ResultSet, Boolean] = primitive(_.rowDeleted) - override def rowInserted: Kleisli[M, ResultSet, Boolean] = primitive(_.rowInserted) - override def rowUpdated: Kleisli[M, ResultSet, Boolean] = primitive(_.rowUpdated) - override def setFetchDirection(a: Int) = primitive(_.setFetchDirection(a)) - override def setFetchSize(a: Int) = primitive(_.setFetchSize(a)) - override def unwrap[T](a: Class[T]) = primitive(_.unwrap(a)) - override def updateArray(a: Int, b: SqlArray) = primitive(_.updateArray(a, b)) - override def updateArray(a: String, b: SqlArray) = primitive(_.updateArray(a, b)) - override def updateAsciiStream(a: Int, b: InputStream) = primitive(_.updateAsciiStream(a, b)) - override def updateAsciiStream(a: Int, b: InputStream, c: Int) = primitive(_.updateAsciiStream(a, b, c)) - override def updateAsciiStream(a: Int, b: InputStream, c: Long) = primitive(_.updateAsciiStream(a, b, c)) - override def updateAsciiStream(a: String, b: InputStream) = primitive(_.updateAsciiStream(a, b)) - override def updateAsciiStream(a: String, b: InputStream, c: Int) = primitive(_.updateAsciiStream(a, b, c)) - override def updateAsciiStream(a: String, b: InputStream, c: Long) = primitive(_.updateAsciiStream(a, b, c)) - override def updateBigDecimal(a: Int, b: BigDecimal) = primitive(_.updateBigDecimal(a, b)) - override def updateBigDecimal(a: String, b: BigDecimal) = primitive(_.updateBigDecimal(a, b)) - override def updateBinaryStream(a: Int, b: InputStream) = primitive(_.updateBinaryStream(a, b)) - override def updateBinaryStream(a: Int, b: InputStream, c: Int) = primitive(_.updateBinaryStream(a, b, c)) - override def updateBinaryStream(a: Int, b: InputStream, c: Long) = primitive(_.updateBinaryStream(a, b, c)) - override def updateBinaryStream(a: String, b: InputStream) = primitive(_.updateBinaryStream(a, b)) - override def updateBinaryStream(a: String, b: InputStream, c: Int) = primitive(_.updateBinaryStream(a, b, c)) - override def updateBinaryStream(a: String, b: InputStream, c: Long) = primitive(_.updateBinaryStream(a, b, c)) - override def updateBlob(a: Int, b: Blob) = primitive(_.updateBlob(a, b)) - override def updateBlob(a: Int, b: InputStream) = primitive(_.updateBlob(a, b)) - override def updateBlob(a: Int, b: InputStream, c: Long) = primitive(_.updateBlob(a, b, c)) - override def updateBlob(a: String, b: Blob) = primitive(_.updateBlob(a, b)) - override def updateBlob(a: String, b: InputStream) = primitive(_.updateBlob(a, b)) - override def updateBlob(a: String, b: InputStream, c: Long) = primitive(_.updateBlob(a, b, c)) - override def updateBoolean(a: Int, b: Boolean) = primitive(_.updateBoolean(a, b)) - override def updateBoolean(a: String, b: Boolean) = primitive(_.updateBoolean(a, b)) - override def updateByte(a: Int, b: Byte) = primitive(_.updateByte(a, b)) - override def updateByte(a: String, b: Byte) = primitive(_.updateByte(a, b)) - override def updateBytes(a: Int, b: Array[Byte]) = primitive(_.updateBytes(a, b)) - override def updateBytes(a: String, b: Array[Byte]) = primitive(_.updateBytes(a, b)) - override def updateCharacterStream(a: Int, b: Reader) = primitive(_.updateCharacterStream(a, b)) - override def updateCharacterStream(a: Int, b: Reader, c: Int) = primitive(_.updateCharacterStream(a, b, c)) - override def updateCharacterStream(a: Int, b: Reader, c: Long) = primitive(_.updateCharacterStream(a, b, c)) - override def updateCharacterStream(a: String, b: Reader) = primitive(_.updateCharacterStream(a, b)) - override def updateCharacterStream(a: String, b: Reader, c: Int) = primitive(_.updateCharacterStream(a, b, c)) - override def updateCharacterStream(a: String, b: Reader, c: Long) = primitive(_.updateCharacterStream(a, b, c)) - override def updateClob(a: Int, b: Clob) = primitive(_.updateClob(a, b)) - override def updateClob(a: Int, b: Reader) = primitive(_.updateClob(a, b)) - override def updateClob(a: Int, b: Reader, c: Long) = primitive(_.updateClob(a, b, c)) - override def updateClob(a: String, b: Clob) = primitive(_.updateClob(a, b)) - override def updateClob(a: String, b: Reader) = primitive(_.updateClob(a, b)) - override def updateClob(a: String, b: Reader, c: Long) = primitive(_.updateClob(a, b, c)) - override def updateDate(a: Int, b: Date) = primitive(_.updateDate(a, b)) - override def updateDate(a: String, b: Date) = primitive(_.updateDate(a, b)) - override def updateDouble(a: Int, b: Double) = primitive(_.updateDouble(a, b)) - override def updateDouble(a: String, b: Double) = primitive(_.updateDouble(a, b)) - override def updateFloat(a: Int, b: Float) = primitive(_.updateFloat(a, b)) - override def updateFloat(a: String, b: Float) = primitive(_.updateFloat(a, b)) - override def updateInt(a: Int, b: Int) = primitive(_.updateInt(a, b)) - override def updateInt(a: String, b: Int) = primitive(_.updateInt(a, b)) - override def updateLong(a: Int, b: Long) = primitive(_.updateLong(a, b)) - override def updateLong(a: String, b: Long) = primitive(_.updateLong(a, b)) - override def updateNCharacterStream(a: Int, b: Reader) = primitive(_.updateNCharacterStream(a, b)) - override def updateNCharacterStream(a: Int, b: Reader, c: Long) = primitive(_.updateNCharacterStream(a, b, c)) - override def updateNCharacterStream(a: String, b: Reader) = primitive(_.updateNCharacterStream(a, b)) - override def updateNCharacterStream(a: String, b: Reader, c: Long) = primitive(_.updateNCharacterStream(a, b, c)) - override def updateNClob(a: Int, b: NClob) = primitive(_.updateNClob(a, b)) - override def updateNClob(a: Int, b: Reader) = primitive(_.updateNClob(a, b)) - override def updateNClob(a: Int, b: Reader, c: Long) = primitive(_.updateNClob(a, b, c)) - override def updateNClob(a: String, b: NClob) = primitive(_.updateNClob(a, b)) - override def updateNClob(a: String, b: Reader) = primitive(_.updateNClob(a, b)) - override def updateNClob(a: String, b: Reader, c: Long) = primitive(_.updateNClob(a, b, c)) - override def updateNString(a: Int, b: String) = primitive(_.updateNString(a, b)) - override def updateNString(a: String, b: String) = primitive(_.updateNString(a, b)) - override def updateNull(a: Int) = primitive(_.updateNull(a)) - override def updateNull(a: String) = primitive(_.updateNull(a)) - override def updateObject(a: Int, b: AnyRef) = primitive(_.updateObject(a, b)) - override def updateObject(a: Int, b: AnyRef, c: Int) = primitive(_.updateObject(a, b, c)) - override def updateObject(a: Int, b: AnyRef, c: SQLType) = primitive(_.updateObject(a, b, c)) - override def updateObject(a: Int, b: AnyRef, c: SQLType, d: Int) = primitive(_.updateObject(a, b, c, d)) - override def updateObject(a: String, b: AnyRef) = primitive(_.updateObject(a, b)) - override def updateObject(a: String, b: AnyRef, c: Int) = primitive(_.updateObject(a, b, c)) - override def updateObject(a: String, b: AnyRef, c: SQLType) = primitive(_.updateObject(a, b, c)) - override def updateObject(a: String, b: AnyRef, c: SQLType, d: Int) = primitive(_.updateObject(a, b, c, d)) - override def updateRef(a: Int, b: Ref) = primitive(_.updateRef(a, b)) - override def updateRef(a: String, b: Ref) = primitive(_.updateRef(a, b)) - override def updateRow: Kleisli[M, ResultSet, Unit] = primitive(_.updateRow) - override def updateRowId(a: Int, b: RowId) = primitive(_.updateRowId(a, b)) - override def updateRowId(a: String, b: RowId) = primitive(_.updateRowId(a, b)) - override def updateSQLXML(a: Int, b: SQLXML) = primitive(_.updateSQLXML(a, b)) - override def updateSQLXML(a: String, b: SQLXML) = primitive(_.updateSQLXML(a, b)) - override def updateShort(a: Int, b: Short) = primitive(_.updateShort(a, b)) - override def updateShort(a: String, b: Short) = primitive(_.updateShort(a, b)) - override def updateString(a: Int, b: String) = primitive(_.updateString(a, b)) - override def updateString(a: String, b: String) = primitive(_.updateString(a, b)) - override def updateTime(a: Int, b: Time) = primitive(_.updateTime(a, b)) - override def updateTime(a: String, b: Time) = primitive(_.updateTime(a, b)) - override def updateTimestamp(a: Int, b: Timestamp) = primitive(_.updateTimestamp(a, b)) - override def updateTimestamp(a: String, b: Timestamp) = primitive(_.updateTimestamp(a, b)) - override def wasNull: Kleisli[M, ResultSet, Boolean] = primitive(_.wasNull) - - } - -} diff --git a/modules/free/src/main/scala/doobie/free/nclob.scala b/modules/free/src/main/scala/doobie/free/nclob.scala deleted file mode 100644 index 1c758964a..000000000 --- a/modules/free/src/main/scala/doobie/free/nclob.scala +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.OutputStream -import java.io.Reader -import java.io.Writer -import java.sql.Clob -import java.sql.NClob -import scala.concurrent.duration.FiniteDuration - -object nclob { module => - - // Algebra of operations for NClob. Each accepts a visitor as an alternative to pattern-matching. - sealed trait NClobOp[A] { - def visit[F[_]](v: NClobOp.Visitor[F]): F[A] - } - - // Free monad over NClobOp. - type NClobIO[A] = FF[NClobOp, A] - - // Module of instances and constructors of NClobOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object NClobOp { - - // Given a NClob we can embed a NClobIO program in any algebra that understands embedding. - implicit val NClobOpEmbeddable: Embeddable[NClobOp, NClob] = - new Embeddable[NClobOp, NClob] { - def embed[A](j: NClob, fa: FF[NClobOp, A]) = Embedded.NClob(j, fa) - } - - // Interface for a natural transformation NClobOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (NClobOp ~> F) { - final def apply[A](fa: NClobOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: NClob => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: NClobIO[A])(f: Throwable => NClobIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: NClobIO[A])(fb: NClobIO[B]): F[B] - def uncancelable[A](body: Poll[NClobIO] => NClobIO[A]): F[A] - def poll[A](poll: Any, fa: NClobIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: NClobIO[A], fin: NClobIO[Unit]): F[A] - - // NClob - def free: F[Unit] - def getAsciiStream: F[InputStream] - def getCharacterStream: F[Reader] - def getCharacterStream(a: Long, b: Long): F[Reader] - def getSubString(a: Long, b: Int): F[String] - def length: F[Long] - def position(a: Clob, b: Long): F[Long] - def position(a: String, b: Long): F[Long] - def setAsciiStream(a: Long): F[OutputStream] - def setCharacterStream(a: Long): F[Writer] - def setString(a: Long, b: String): F[Int] - def setString(a: Long, b: String, c: Int, d: Int): F[Int] - def truncate(a: Long): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: NClob => A) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: NClobIO[A], f: Throwable => NClobIO[A]) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends NClobOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends NClobOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: NClobIO[A], fb: NClobIO[B]) extends NClobOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[NClobIO] => NClobIO[A]) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: NClobIO[A]) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends NClobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: NClobIO[A], fin: NClobIO[Unit]) extends NClobOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // NClob-specific operations. - case object Free extends NClobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.free - } - case object GetAsciiStream extends NClobOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getAsciiStream - } - case object GetCharacterStream extends NClobOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream - } - final case class GetCharacterStream1(a: Long, b: Long) extends NClobOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream(a, b) - } - final case class GetSubString(a: Long, b: Int) extends NClobOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSubString(a, b) - } - case object Length extends NClobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.length - } - final case class Position(a: Clob, b: Long) extends NClobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.position(a, b) - } - final case class Position1(a: String, b: Long) extends NClobOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.position(a, b) - } - final case class SetAsciiStream(a: Long) extends NClobOp[OutputStream] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a) - } - final case class SetCharacterStream(a: Long) extends NClobOp[Writer] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a) - } - final case class SetString(a: Long, b: String) extends NClobOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b) - } - final case class SetString1(a: Long, b: String, c: Int, d: Int) extends NClobOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b, c, d) - } - final case class Truncate(a: Long) extends NClobOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.truncate(a) - } - - } - import NClobOp.* - - // Smart constructors for operations common to all algebras. - val unit: NClobIO[Unit] = FF.pure[NClobOp, Unit](()) - def pure[A](a: A): NClobIO[A] = FF.pure[NClobOp, A](a) - def raw[A](f: NClob => A): NClobIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[NClobOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): NClobIO[A] = FF.liftF[NClobOp, A](RaiseError(err)) - def handleErrorWith[A](fa: NClobIO[A])(f: Throwable => NClobIO[A]): NClobIO[A] = - FF.liftF[NClobOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[NClobOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[NClobOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[NClobOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[NClobOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: NClobIO[A])(fb: NClobIO[B]) = FF.liftF[NClobOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[NClobIO] => NClobIO[A]) = FF.liftF[NClobOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[NClobIO] { - def apply[A](fa: NClobIO[A]) = FF.liftF[NClobOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[NClobOp, Unit](Canceled) - def onCancel[A](fa: NClobIO[A], fin: NClobIO[Unit]) = FF.liftF[NClobOp, A](OnCancel(fa, fin)) - - // Smart constructors for NClob-specific operations. - val free: NClobIO[Unit] = FF.liftF(Free) - val getAsciiStream: NClobIO[InputStream] = FF.liftF(GetAsciiStream) - val getCharacterStream: NClobIO[Reader] = FF.liftF(GetCharacterStream) - def getCharacterStream(a: Long, b: Long): NClobIO[Reader] = FF.liftF(GetCharacterStream1(a, b)) - def getSubString(a: Long, b: Int): NClobIO[String] = FF.liftF(GetSubString(a, b)) - val length: NClobIO[Long] = FF.liftF(Length) - def position(a: Clob, b: Long): NClobIO[Long] = FF.liftF(Position(a, b)) - def position(a: String, b: Long): NClobIO[Long] = FF.liftF(Position1(a, b)) - def setAsciiStream(a: Long): NClobIO[OutputStream] = FF.liftF(SetAsciiStream(a)) - def setCharacterStream(a: Long): NClobIO[Writer] = FF.liftF(SetCharacterStream(a)) - def setString(a: Long, b: String): NClobIO[Int] = FF.liftF(SetString(a, b)) - def setString(a: Long, b: String, c: Int, d: Int): NClobIO[Int] = FF.liftF(SetString1(a, b, c, d)) - def truncate(a: Long): NClobIO[Unit] = FF.liftF(Truncate(a)) - - private val monad = FF.catsFreeMonadForFree[NClobOp] - - // Typeclass instances for NClobIO - implicit val SyncNClobIO: Sync[NClobIO] = - new Sync[NClobIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): NClobIO[A] = monad.pure(x) - override def map[A, B](fa: NClobIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: NClobIO[A])(f: A => NClobIO[B]): NClobIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => NClobIO[Either[A, B]]): NClobIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): NClobIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: NClobIO[A])(f: Throwable => NClobIO[A]): NClobIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: NClobIO[FiniteDuration] = module.monotonic - override def realTime: NClobIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): NClobIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: NClobIO[A])(fb: NClobIO[B]): NClobIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[NClobIO] => NClobIO[A]): NClobIO[A] = module.uncancelable(body) - override def canceled: NClobIO[Unit] = module.canceled - override def onCancel[A](fa: NClobIO[A], fin: NClobIO[Unit]): NClobIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidNClobIO[A](implicit M: Monoid[A]): Monoid[NClobIO[A]] = - new Monoid[NClobIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: NClobIO[A], y: NClobIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/preparedstatement.scala b/modules/free/src/main/scala/doobie/free/preparedstatement.scala deleted file mode 100644 index 8ac3f1864..000000000 --- a/modules/free/src/main/scala/doobie/free/preparedstatement.scala +++ /dev/null @@ -1,754 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.Reader -import java.math.BigDecimal -import java.net.URL -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.Clob -import java.sql.Connection -import java.sql.Date -import java.sql.NClob -import java.sql.ParameterMetaData -import java.sql.PreparedStatement -import java.sql.Ref -import java.sql.ResultSet -import java.sql.ResultSetMetaData -import java.sql.RowId -import java.sql.SQLType -import java.sql.SQLWarning -import java.sql.SQLXML -import java.sql.Time -import java.sql.Timestamp -import java.util.Calendar -import scala.concurrent.duration.FiniteDuration - -object preparedstatement { module => - - // Algebra of operations for PreparedStatement. Each accepts a visitor as an alternative to pattern-matching. - sealed trait PreparedStatementOp[A] { - def visit[F[_]](v: PreparedStatementOp.Visitor[F]): F[A] - } - - // Free monad over PreparedStatementOp. - type PreparedStatementIO[A] = FF[PreparedStatementOp, A] - - // Module of instances and constructors of PreparedStatementOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object PreparedStatementOp { - - // Given a PreparedStatement we can embed a PreparedStatementIO program in any algebra that understands embedding. - implicit val PreparedStatementOpEmbeddable: Embeddable[PreparedStatementOp, PreparedStatement] = - new Embeddable[PreparedStatementOp, PreparedStatement] { - def embed[A](j: PreparedStatement, fa: FF[PreparedStatementOp, A]) = Embedded.PreparedStatement(j, fa) - } - - // Interface for a natural transformation PreparedStatementOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (PreparedStatementOp ~> F) { - final def apply[A](fa: PreparedStatementOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: PreparedStatement => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: PreparedStatementIO[A])(f: Throwable => PreparedStatementIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: PreparedStatementIO[A])(fb: PreparedStatementIO[B]): F[B] - def uncancelable[A](body: Poll[PreparedStatementIO] => PreparedStatementIO[A]): F[A] - def poll[A](poll: Any, fa: PreparedStatementIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: PreparedStatementIO[A], fin: PreparedStatementIO[Unit]): F[A] - - // PreparedStatement - def addBatch: F[Unit] - def addBatch(a: String): F[Unit] - def cancel: F[Unit] - def clearBatch: F[Unit] - def clearParameters: F[Unit] - def clearWarnings: F[Unit] - def close: F[Unit] - def closeOnCompletion: F[Unit] - def enquoteIdentifier(a: String, b: Boolean): F[String] - def enquoteLiteral(a: String): F[String] - def enquoteNCharLiteral(a: String): F[String] - def execute: F[Boolean] - def execute(a: String): F[Boolean] - def execute(a: String, b: Array[Int]): F[Boolean] - def execute(a: String, b: Array[String]): F[Boolean] - def execute(a: String, b: Int): F[Boolean] - def executeBatch: F[Array[Int]] - def executeLargeBatch: F[Array[Long]] - def executeLargeUpdate: F[Long] - def executeLargeUpdate(a: String): F[Long] - def executeLargeUpdate(a: String, b: Array[Int]): F[Long] - def executeLargeUpdate(a: String, b: Array[String]): F[Long] - def executeLargeUpdate(a: String, b: Int): F[Long] - def executeQuery: F[ResultSet] - def executeQuery(a: String): F[ResultSet] - def executeUpdate: F[Int] - def executeUpdate(a: String): F[Int] - def executeUpdate(a: String, b: Array[Int]): F[Int] - def executeUpdate(a: String, b: Array[String]): F[Int] - def executeUpdate(a: String, b: Int): F[Int] - def getConnection: F[Connection] - def getFetchDirection: F[Int] - def getFetchSize: F[Int] - def getGeneratedKeys: F[ResultSet] - def getLargeMaxRows: F[Long] - def getLargeUpdateCount: F[Long] - def getMaxFieldSize: F[Int] - def getMaxRows: F[Int] - def getMetaData: F[ResultSetMetaData] - def getMoreResults: F[Boolean] - def getMoreResults(a: Int): F[Boolean] - def getParameterMetaData: F[ParameterMetaData] - def getQueryTimeout: F[Int] - def getResultSet: F[ResultSet] - def getResultSetConcurrency: F[Int] - def getResultSetHoldability: F[Int] - def getResultSetType: F[Int] - def getUpdateCount: F[Int] - def getWarnings: F[SQLWarning] - def isCloseOnCompletion: F[Boolean] - def isClosed: F[Boolean] - def isPoolable: F[Boolean] - def isSimpleIdentifier(a: String): F[Boolean] - def isWrapperFor(a: Class[?]): F[Boolean] - def setArray(a: Int, b: SqlArray): F[Unit] - def setAsciiStream(a: Int, b: InputStream): F[Unit] - def setAsciiStream(a: Int, b: InputStream, c: Int): F[Unit] - def setAsciiStream(a: Int, b: InputStream, c: Long): F[Unit] - def setBigDecimal(a: Int, b: BigDecimal): F[Unit] - def setBinaryStream(a: Int, b: InputStream): F[Unit] - def setBinaryStream(a: Int, b: InputStream, c: Int): F[Unit] - def setBinaryStream(a: Int, b: InputStream, c: Long): F[Unit] - def setBlob(a: Int, b: Blob): F[Unit] - def setBlob(a: Int, b: InputStream): F[Unit] - def setBlob(a: Int, b: InputStream, c: Long): F[Unit] - def setBoolean(a: Int, b: Boolean): F[Unit] - def setByte(a: Int, b: Byte): F[Unit] - def setBytes(a: Int, b: Array[Byte]): F[Unit] - def setCharacterStream(a: Int, b: Reader): F[Unit] - def setCharacterStream(a: Int, b: Reader, c: Int): F[Unit] - def setCharacterStream(a: Int, b: Reader, c: Long): F[Unit] - def setClob(a: Int, b: Clob): F[Unit] - def setClob(a: Int, b: Reader): F[Unit] - def setClob(a: Int, b: Reader, c: Long): F[Unit] - def setCursorName(a: String): F[Unit] - def setDate(a: Int, b: Date): F[Unit] - def setDate(a: Int, b: Date, c: Calendar): F[Unit] - def setDouble(a: Int, b: Double): F[Unit] - def setEscapeProcessing(a: Boolean): F[Unit] - def setFetchDirection(a: Int): F[Unit] - def setFetchSize(a: Int): F[Unit] - def setFloat(a: Int, b: Float): F[Unit] - def setInt(a: Int, b: Int): F[Unit] - def setLargeMaxRows(a: Long): F[Unit] - def setLong(a: Int, b: Long): F[Unit] - def setMaxFieldSize(a: Int): F[Unit] - def setMaxRows(a: Int): F[Unit] - def setNCharacterStream(a: Int, b: Reader): F[Unit] - def setNCharacterStream(a: Int, b: Reader, c: Long): F[Unit] - def setNClob(a: Int, b: NClob): F[Unit] - def setNClob(a: Int, b: Reader): F[Unit] - def setNClob(a: Int, b: Reader, c: Long): F[Unit] - def setNString(a: Int, b: String): F[Unit] - def setNull(a: Int, b: Int): F[Unit] - def setNull(a: Int, b: Int, c: String): F[Unit] - def setObject(a: Int, b: AnyRef): F[Unit] - def setObject(a: Int, b: AnyRef, c: Int): F[Unit] - def setObject(a: Int, b: AnyRef, c: Int, d: Int): F[Unit] - def setObject(a: Int, b: AnyRef, c: SQLType): F[Unit] - def setObject(a: Int, b: AnyRef, c: SQLType, d: Int): F[Unit] - def setPoolable(a: Boolean): F[Unit] - def setQueryTimeout(a: Int): F[Unit] - def setRef(a: Int, b: Ref): F[Unit] - def setRowId(a: Int, b: RowId): F[Unit] - def setSQLXML(a: Int, b: SQLXML): F[Unit] - def setShort(a: Int, b: Short): F[Unit] - def setString(a: Int, b: String): F[Unit] - def setTime(a: Int, b: Time): F[Unit] - def setTime(a: Int, b: Time, c: Calendar): F[Unit] - def setTimestamp(a: Int, b: Timestamp): F[Unit] - def setTimestamp(a: Int, b: Timestamp, c: Calendar): F[Unit] - def setURL(a: Int, b: URL): F[Unit] - def unwrap[T](a: Class[T]): F[T] - - } - - // Common operations for all algebras. - final case class Raw[A](f: PreparedStatement => A) extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: PreparedStatementIO[A], f: Throwable => PreparedStatementIO[A]) - extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends PreparedStatementOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends PreparedStatementOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: PreparedStatementIO[A], fb: PreparedStatementIO[B]) extends PreparedStatementOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[PreparedStatementIO] => PreparedStatementIO[A]) - extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: PreparedStatementIO[A]) extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: PreparedStatementIO[A], fin: PreparedStatementIO[Unit]) - extends PreparedStatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // PreparedStatement-specific operations. - case object AddBatch extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.addBatch - } - final case class AddBatch1(a: String) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.addBatch(a) - } - case object Cancel extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancel - } - case object ClearBatch extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearBatch - } - case object ClearParameters extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearParameters - } - case object ClearWarnings extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearWarnings - } - case object Close extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.close - } - case object CloseOnCompletion extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.closeOnCompletion - } - final case class EnquoteIdentifier(a: String, b: Boolean) extends PreparedStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteIdentifier(a, b) - } - final case class EnquoteLiteral(a: String) extends PreparedStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteLiteral(a) - } - final case class EnquoteNCharLiteral(a: String) extends PreparedStatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteNCharLiteral(a) - } - case object Execute extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute - } - final case class Execute1(a: String) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a) - } - final case class Execute2(a: String, b: Array[Int]) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - final case class Execute3(a: String, b: Array[String]) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - final case class Execute4(a: String, b: Int) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - case object ExecuteBatch extends PreparedStatementOp[Array[Int]] { - def visit[F[_]](v: Visitor[F]) = v.executeBatch - } - case object ExecuteLargeBatch extends PreparedStatementOp[Array[Long]] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeBatch - } - case object ExecuteLargeUpdate extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate - } - final case class ExecuteLargeUpdate1(a: String) extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a) - } - final case class ExecuteLargeUpdate2(a: String, b: Array[Int]) extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteLargeUpdate3(a: String, b: Array[String]) extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteLargeUpdate4(a: String, b: Int) extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - case object ExecuteQuery extends PreparedStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.executeQuery - } - final case class ExecuteQuery1(a: String) extends PreparedStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.executeQuery(a) - } - case object ExecuteUpdate extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate - } - final case class ExecuteUpdate1(a: String) extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a) - } - final case class ExecuteUpdate2(a: String, b: Array[Int]) extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class ExecuteUpdate3(a: String, b: Array[String]) extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class ExecuteUpdate4(a: String, b: Int) extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - case object GetConnection extends PreparedStatementOp[Connection] { - def visit[F[_]](v: Visitor[F]) = v.getConnection - } - case object GetFetchDirection extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchDirection - } - case object GetFetchSize extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchSize - } - case object GetGeneratedKeys extends PreparedStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getGeneratedKeys - } - case object GetLargeMaxRows extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLargeMaxRows - } - case object GetLargeUpdateCount extends PreparedStatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLargeUpdateCount - } - case object GetMaxFieldSize extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxFieldSize - } - case object GetMaxRows extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxRows - } - case object GetMetaData extends PreparedStatementOp[ResultSetMetaData] { - def visit[F[_]](v: Visitor[F]) = v.getMetaData - } - case object GetMoreResults extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getMoreResults - } - final case class GetMoreResults1(a: Int) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getMoreResults(a) - } - case object GetParameterMetaData extends PreparedStatementOp[ParameterMetaData] { - def visit[F[_]](v: Visitor[F]) = v.getParameterMetaData - } - case object GetQueryTimeout extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getQueryTimeout - } - case object GetResultSet extends PreparedStatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getResultSet - } - case object GetResultSetConcurrency extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetConcurrency - } - case object GetResultSetHoldability extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetHoldability - } - case object GetResultSetType extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetType - } - case object GetUpdateCount extends PreparedStatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getUpdateCount - } - case object GetWarnings extends PreparedStatementOp[SQLWarning] { - def visit[F[_]](v: Visitor[F]) = v.getWarnings - } - case object IsCloseOnCompletion extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isCloseOnCompletion - } - case object IsClosed extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isClosed - } - case object IsPoolable extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isPoolable - } - final case class IsSimpleIdentifier(a: String) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isSimpleIdentifier(a) - } - final case class IsWrapperFor(a: Class[?]) extends PreparedStatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isWrapperFor(a) - } - final case class SetArray(a: Int, b: SqlArray) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setArray(a, b) - } - final case class SetAsciiStream(a: Int, b: InputStream) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b) - } - final case class SetAsciiStream1(a: Int, b: InputStream, c: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b, c) - } - final case class SetAsciiStream2(a: Int, b: InputStream, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAsciiStream(a, b, c) - } - final case class SetBigDecimal(a: Int, b: BigDecimal) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBigDecimal(a, b) - } - final case class SetBinaryStream(a: Int, b: InputStream) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b) - } - final case class SetBinaryStream1(a: Int, b: InputStream, c: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b, c) - } - final case class SetBinaryStream2(a: Int, b: InputStream, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBinaryStream(a, b, c) - } - final case class SetBlob(a: Int, b: Blob) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b) - } - final case class SetBlob1(a: Int, b: InputStream) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b) - } - final case class SetBlob2(a: Int, b: InputStream, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBlob(a, b, c) - } - final case class SetBoolean(a: Int, b: Boolean) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBoolean(a, b) - } - final case class SetByte(a: Int, b: Byte) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setByte(a, b) - } - final case class SetBytes(a: Int, b: Array[Byte]) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setBytes(a, b) - } - final case class SetCharacterStream(a: Int, b: Reader) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b) - } - final case class SetCharacterStream1(a: Int, b: Reader, c: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b, c) - } - final case class SetCharacterStream2(a: Int, b: Reader, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCharacterStream(a, b, c) - } - final case class SetClob(a: Int, b: Clob) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b) - } - final case class SetClob1(a: Int, b: Reader) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b) - } - final case class SetClob2(a: Int, b: Reader, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setClob(a, b, c) - } - final case class SetCursorName(a: String) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCursorName(a) - } - final case class SetDate(a: Int, b: Date) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDate(a, b) - } - final case class SetDate1(a: Int, b: Date, c: Calendar) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDate(a, b, c) - } - final case class SetDouble(a: Int, b: Double) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDouble(a, b) - } - final case class SetEscapeProcessing(a: Boolean) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setEscapeProcessing(a) - } - final case class SetFetchDirection(a: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchDirection(a) - } - final case class SetFetchSize(a: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchSize(a) - } - final case class SetFloat(a: Int, b: Float) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFloat(a, b) - } - final case class SetInt(a: Int, b: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setInt(a, b) - } - final case class SetLargeMaxRows(a: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setLargeMaxRows(a) - } - final case class SetLong(a: Int, b: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setLong(a, b) - } - final case class SetMaxFieldSize(a: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setMaxFieldSize(a) - } - final case class SetMaxRows(a: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setMaxRows(a) - } - final case class SetNCharacterStream(a: Int, b: Reader) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNCharacterStream(a, b) - } - final case class SetNCharacterStream1(a: Int, b: Reader, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNCharacterStream(a, b, c) - } - final case class SetNClob(a: Int, b: NClob) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b) - } - final case class SetNClob1(a: Int, b: Reader) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b) - } - final case class SetNClob2(a: Int, b: Reader, c: Long) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNClob(a, b, c) - } - final case class SetNString(a: Int, b: String) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNString(a, b) - } - final case class SetNull(a: Int, b: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNull(a, b) - } - final case class SetNull1(a: Int, b: Int, c: String) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setNull(a, b, c) - } - final case class SetObject(a: Int, b: AnyRef) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b) - } - final case class SetObject1(a: Int, b: AnyRef, c: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c) - } - final case class SetObject2(a: Int, b: AnyRef, c: Int, d: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c, d) - } - final case class SetObject3(a: Int, b: AnyRef, c: SQLType) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c) - } - final case class SetObject4(a: Int, b: AnyRef, c: SQLType, d: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a, b, c, d) - } - final case class SetPoolable(a: Boolean) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setPoolable(a) - } - final case class SetQueryTimeout(a: Int) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setQueryTimeout(a) - } - final case class SetRef(a: Int, b: Ref) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setRef(a, b) - } - final case class SetRowId(a: Int, b: RowId) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setRowId(a, b) - } - final case class SetSQLXML(a: Int, b: SQLXML) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setSQLXML(a, b) - } - final case class SetShort(a: Int, b: Short) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setShort(a, b) - } - final case class SetString(a: Int, b: String) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setString(a, b) - } - final case class SetTime(a: Int, b: Time) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTime(a, b) - } - final case class SetTime1(a: Int, b: Time, c: Calendar) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTime(a, b, c) - } - final case class SetTimestamp(a: Int, b: Timestamp) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTimestamp(a, b) - } - final case class SetTimestamp1(a: Int, b: Timestamp, c: Calendar) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setTimestamp(a, b, c) - } - final case class SetURL(a: Int, b: URL) extends PreparedStatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setURL(a, b) - } - final case class Unwrap[T](a: Class[T]) extends PreparedStatementOp[T] { - def visit[F[_]](v: Visitor[F]) = v.unwrap(a) - } - - } - import PreparedStatementOp.* - - // Smart constructors for operations common to all algebras. - val unit: PreparedStatementIO[Unit] = FF.pure[PreparedStatementOp, Unit](()) - def pure[A](a: A): PreparedStatementIO[A] = FF.pure[PreparedStatementOp, A](a) - def raw[A](f: PreparedStatement => A): PreparedStatementIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[PreparedStatementOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): PreparedStatementIO[A] = FF.liftF[PreparedStatementOp, A](RaiseError(err)) - def handleErrorWith[A](fa: PreparedStatementIO[A])(f: Throwable => PreparedStatementIO[A]): PreparedStatementIO[A] = - FF.liftF[PreparedStatementOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[PreparedStatementOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[PreparedStatementOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[PreparedStatementOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[PreparedStatementOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: PreparedStatementIO[A])(fb: PreparedStatementIO[B]) = - FF.liftF[PreparedStatementOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[PreparedStatementIO] => PreparedStatementIO[A]) = - FF.liftF[PreparedStatementOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[PreparedStatementIO] { - def apply[A](fa: PreparedStatementIO[A]) = FF.liftF[PreparedStatementOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[PreparedStatementOp, Unit](Canceled) - def onCancel[A](fa: PreparedStatementIO[A], fin: PreparedStatementIO[Unit]) = - FF.liftF[PreparedStatementOp, A](OnCancel(fa, fin)) - - // Smart constructors for PreparedStatement-specific operations. - val addBatch: PreparedStatementIO[Unit] = FF.liftF(AddBatch) - def addBatch(a: String): PreparedStatementIO[Unit] = FF.liftF(AddBatch1(a)) - val cancel: PreparedStatementIO[Unit] = FF.liftF(Cancel) - val clearBatch: PreparedStatementIO[Unit] = FF.liftF(ClearBatch) - val clearParameters: PreparedStatementIO[Unit] = FF.liftF(ClearParameters) - val clearWarnings: PreparedStatementIO[Unit] = FF.liftF(ClearWarnings) - val close: PreparedStatementIO[Unit] = FF.liftF(Close) - val closeOnCompletion: PreparedStatementIO[Unit] = FF.liftF(CloseOnCompletion) - def enquoteIdentifier(a: String, b: Boolean): PreparedStatementIO[String] = FF.liftF(EnquoteIdentifier(a, b)) - def enquoteLiteral(a: String): PreparedStatementIO[String] = FF.liftF(EnquoteLiteral(a)) - def enquoteNCharLiteral(a: String): PreparedStatementIO[String] = FF.liftF(EnquoteNCharLiteral(a)) - val execute: PreparedStatementIO[Boolean] = FF.liftF(Execute) - def execute(a: String): PreparedStatementIO[Boolean] = FF.liftF(Execute1(a)) - def execute(a: String, b: Array[Int]): PreparedStatementIO[Boolean] = FF.liftF(Execute2(a, b)) - def execute(a: String, b: Array[String]): PreparedStatementIO[Boolean] = FF.liftF(Execute3(a, b)) - def execute(a: String, b: Int): PreparedStatementIO[Boolean] = FF.liftF(Execute4(a, b)) - val executeBatch: PreparedStatementIO[Array[Int]] = FF.liftF(ExecuteBatch) - val executeLargeBatch: PreparedStatementIO[Array[Long]] = FF.liftF(ExecuteLargeBatch) - val executeLargeUpdate: PreparedStatementIO[Long] = FF.liftF(ExecuteLargeUpdate) - def executeLargeUpdate(a: String): PreparedStatementIO[Long] = FF.liftF(ExecuteLargeUpdate1(a)) - def executeLargeUpdate(a: String, b: Array[Int]): PreparedStatementIO[Long] = FF.liftF(ExecuteLargeUpdate2(a, b)) - def executeLargeUpdate(a: String, b: Array[String]): PreparedStatementIO[Long] = FF.liftF(ExecuteLargeUpdate3(a, b)) - def executeLargeUpdate(a: String, b: Int): PreparedStatementIO[Long] = FF.liftF(ExecuteLargeUpdate4(a, b)) - val executeQuery: PreparedStatementIO[ResultSet] = FF.liftF(ExecuteQuery) - def executeQuery(a: String): PreparedStatementIO[ResultSet] = FF.liftF(ExecuteQuery1(a)) - val executeUpdate: PreparedStatementIO[Int] = FF.liftF(ExecuteUpdate) - def executeUpdate(a: String): PreparedStatementIO[Int] = FF.liftF(ExecuteUpdate1(a)) - def executeUpdate(a: String, b: Array[Int]): PreparedStatementIO[Int] = FF.liftF(ExecuteUpdate2(a, b)) - def executeUpdate(a: String, b: Array[String]): PreparedStatementIO[Int] = FF.liftF(ExecuteUpdate3(a, b)) - def executeUpdate(a: String, b: Int): PreparedStatementIO[Int] = FF.liftF(ExecuteUpdate4(a, b)) - val getConnection: PreparedStatementIO[Connection] = FF.liftF(GetConnection) - val getFetchDirection: PreparedStatementIO[Int] = FF.liftF(GetFetchDirection) - val getFetchSize: PreparedStatementIO[Int] = FF.liftF(GetFetchSize) - val getGeneratedKeys: PreparedStatementIO[ResultSet] = FF.liftF(GetGeneratedKeys) - val getLargeMaxRows: PreparedStatementIO[Long] = FF.liftF(GetLargeMaxRows) - val getLargeUpdateCount: PreparedStatementIO[Long] = FF.liftF(GetLargeUpdateCount) - val getMaxFieldSize: PreparedStatementIO[Int] = FF.liftF(GetMaxFieldSize) - val getMaxRows: PreparedStatementIO[Int] = FF.liftF(GetMaxRows) - val getMetaData: PreparedStatementIO[ResultSetMetaData] = FF.liftF(GetMetaData) - val getMoreResults: PreparedStatementIO[Boolean] = FF.liftF(GetMoreResults) - def getMoreResults(a: Int): PreparedStatementIO[Boolean] = FF.liftF(GetMoreResults1(a)) - val getParameterMetaData: PreparedStatementIO[ParameterMetaData] = FF.liftF(GetParameterMetaData) - val getQueryTimeout: PreparedStatementIO[Int] = FF.liftF(GetQueryTimeout) - val getResultSet: PreparedStatementIO[ResultSet] = FF.liftF(GetResultSet) - val getResultSetConcurrency: PreparedStatementIO[Int] = FF.liftF(GetResultSetConcurrency) - val getResultSetHoldability: PreparedStatementIO[Int] = FF.liftF(GetResultSetHoldability) - val getResultSetType: PreparedStatementIO[Int] = FF.liftF(GetResultSetType) - val getUpdateCount: PreparedStatementIO[Int] = FF.liftF(GetUpdateCount) - val getWarnings: PreparedStatementIO[SQLWarning] = FF.liftF(GetWarnings) - val isCloseOnCompletion: PreparedStatementIO[Boolean] = FF.liftF(IsCloseOnCompletion) - val isClosed: PreparedStatementIO[Boolean] = FF.liftF(IsClosed) - val isPoolable: PreparedStatementIO[Boolean] = FF.liftF(IsPoolable) - def isSimpleIdentifier(a: String): PreparedStatementIO[Boolean] = FF.liftF(IsSimpleIdentifier(a)) - def isWrapperFor(a: Class[?]): PreparedStatementIO[Boolean] = FF.liftF(IsWrapperFor(a)) - def setArray(a: Int, b: SqlArray): PreparedStatementIO[Unit] = FF.liftF(SetArray(a, b)) - def setAsciiStream(a: Int, b: InputStream): PreparedStatementIO[Unit] = FF.liftF(SetAsciiStream(a, b)) - def setAsciiStream(a: Int, b: InputStream, c: Int): PreparedStatementIO[Unit] = FF.liftF(SetAsciiStream1(a, b, c)) - def setAsciiStream(a: Int, b: InputStream, c: Long): PreparedStatementIO[Unit] = FF.liftF(SetAsciiStream2(a, b, c)) - def setBigDecimal(a: Int, b: BigDecimal): PreparedStatementIO[Unit] = FF.liftF(SetBigDecimal(a, b)) - def setBinaryStream(a: Int, b: InputStream): PreparedStatementIO[Unit] = FF.liftF(SetBinaryStream(a, b)) - def setBinaryStream(a: Int, b: InputStream, c: Int): PreparedStatementIO[Unit] = FF.liftF(SetBinaryStream1(a, b, c)) - def setBinaryStream(a: Int, b: InputStream, c: Long): PreparedStatementIO[Unit] = FF.liftF(SetBinaryStream2(a, b, c)) - def setBlob(a: Int, b: Blob): PreparedStatementIO[Unit] = FF.liftF(SetBlob(a, b)) - def setBlob(a: Int, b: InputStream): PreparedStatementIO[Unit] = FF.liftF(SetBlob1(a, b)) - def setBlob(a: Int, b: InputStream, c: Long): PreparedStatementIO[Unit] = FF.liftF(SetBlob2(a, b, c)) - def setBoolean(a: Int, b: Boolean): PreparedStatementIO[Unit] = FF.liftF(SetBoolean(a, b)) - def setByte(a: Int, b: Byte): PreparedStatementIO[Unit] = FF.liftF(SetByte(a, b)) - def setBytes(a: Int, b: Array[Byte]): PreparedStatementIO[Unit] = FF.liftF(SetBytes(a, b)) - def setCharacterStream(a: Int, b: Reader): PreparedStatementIO[Unit] = FF.liftF(SetCharacterStream(a, b)) - def setCharacterStream(a: Int, b: Reader, c: Int): PreparedStatementIO[Unit] = FF.liftF(SetCharacterStream1(a, b, c)) - def setCharacterStream(a: Int, b: Reader, c: Long): PreparedStatementIO[Unit] = FF.liftF(SetCharacterStream2(a, b, c)) - def setClob(a: Int, b: Clob): PreparedStatementIO[Unit] = FF.liftF(SetClob(a, b)) - def setClob(a: Int, b: Reader): PreparedStatementIO[Unit] = FF.liftF(SetClob1(a, b)) - def setClob(a: Int, b: Reader, c: Long): PreparedStatementIO[Unit] = FF.liftF(SetClob2(a, b, c)) - def setCursorName(a: String): PreparedStatementIO[Unit] = FF.liftF(SetCursorName(a)) - def setDate(a: Int, b: Date): PreparedStatementIO[Unit] = FF.liftF(SetDate(a, b)) - def setDate(a: Int, b: Date, c: Calendar): PreparedStatementIO[Unit] = FF.liftF(SetDate1(a, b, c)) - def setDouble(a: Int, b: Double): PreparedStatementIO[Unit] = FF.liftF(SetDouble(a, b)) - def setEscapeProcessing(a: Boolean): PreparedStatementIO[Unit] = FF.liftF(SetEscapeProcessing(a)) - def setFetchDirection(a: Int): PreparedStatementIO[Unit] = FF.liftF(SetFetchDirection(a)) - def setFetchSize(a: Int): PreparedStatementIO[Unit] = FF.liftF(SetFetchSize(a)) - def setFloat(a: Int, b: Float): PreparedStatementIO[Unit] = FF.liftF(SetFloat(a, b)) - def setInt(a: Int, b: Int): PreparedStatementIO[Unit] = FF.liftF(SetInt(a, b)) - def setLargeMaxRows(a: Long): PreparedStatementIO[Unit] = FF.liftF(SetLargeMaxRows(a)) - def setLong(a: Int, b: Long): PreparedStatementIO[Unit] = FF.liftF(SetLong(a, b)) - def setMaxFieldSize(a: Int): PreparedStatementIO[Unit] = FF.liftF(SetMaxFieldSize(a)) - def setMaxRows(a: Int): PreparedStatementIO[Unit] = FF.liftF(SetMaxRows(a)) - def setNCharacterStream(a: Int, b: Reader): PreparedStatementIO[Unit] = FF.liftF(SetNCharacterStream(a, b)) - def setNCharacterStream(a: Int, b: Reader, c: Long): PreparedStatementIO[Unit] = - FF.liftF(SetNCharacterStream1(a, b, c)) - def setNClob(a: Int, b: NClob): PreparedStatementIO[Unit] = FF.liftF(SetNClob(a, b)) - def setNClob(a: Int, b: Reader): PreparedStatementIO[Unit] = FF.liftF(SetNClob1(a, b)) - def setNClob(a: Int, b: Reader, c: Long): PreparedStatementIO[Unit] = FF.liftF(SetNClob2(a, b, c)) - def setNString(a: Int, b: String): PreparedStatementIO[Unit] = FF.liftF(SetNString(a, b)) - def setNull(a: Int, b: Int): PreparedStatementIO[Unit] = FF.liftF(SetNull(a, b)) - def setNull(a: Int, b: Int, c: String): PreparedStatementIO[Unit] = FF.liftF(SetNull1(a, b, c)) - def setObject(a: Int, b: AnyRef): PreparedStatementIO[Unit] = FF.liftF(SetObject(a, b)) - def setObject(a: Int, b: AnyRef, c: Int): PreparedStatementIO[Unit] = FF.liftF(SetObject1(a, b, c)) - def setObject(a: Int, b: AnyRef, c: Int, d: Int): PreparedStatementIO[Unit] = FF.liftF(SetObject2(a, b, c, d)) - def setObject(a: Int, b: AnyRef, c: SQLType): PreparedStatementIO[Unit] = FF.liftF(SetObject3(a, b, c)) - def setObject(a: Int, b: AnyRef, c: SQLType, d: Int): PreparedStatementIO[Unit] = FF.liftF(SetObject4(a, b, c, d)) - def setPoolable(a: Boolean): PreparedStatementIO[Unit] = FF.liftF(SetPoolable(a)) - def setQueryTimeout(a: Int): PreparedStatementIO[Unit] = FF.liftF(SetQueryTimeout(a)) - def setRef(a: Int, b: Ref): PreparedStatementIO[Unit] = FF.liftF(SetRef(a, b)) - def setRowId(a: Int, b: RowId): PreparedStatementIO[Unit] = FF.liftF(SetRowId(a, b)) - def setSQLXML(a: Int, b: SQLXML): PreparedStatementIO[Unit] = FF.liftF(SetSQLXML(a, b)) - def setShort(a: Int, b: Short): PreparedStatementIO[Unit] = FF.liftF(SetShort(a, b)) - def setString(a: Int, b: String): PreparedStatementIO[Unit] = FF.liftF(SetString(a, b)) - def setTime(a: Int, b: Time): PreparedStatementIO[Unit] = FF.liftF(SetTime(a, b)) - def setTime(a: Int, b: Time, c: Calendar): PreparedStatementIO[Unit] = FF.liftF(SetTime1(a, b, c)) - def setTimestamp(a: Int, b: Timestamp): PreparedStatementIO[Unit] = FF.liftF(SetTimestamp(a, b)) - def setTimestamp(a: Int, b: Timestamp, c: Calendar): PreparedStatementIO[Unit] = FF.liftF(SetTimestamp1(a, b, c)) - def setURL(a: Int, b: URL): PreparedStatementIO[Unit] = FF.liftF(SetURL(a, b)) - def unwrap[T](a: Class[T]): PreparedStatementIO[T] = FF.liftF(Unwrap(a)) - - private val monad = FF.catsFreeMonadForFree[PreparedStatementOp] - - // Typeclass instances for PreparedStatementIO - implicit val SyncPreparedStatementIO: Sync[PreparedStatementIO] = - new Sync[PreparedStatementIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): PreparedStatementIO[A] = monad.pure(x) - override def map[A, B](fa: PreparedStatementIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: PreparedStatementIO[A])(f: A => PreparedStatementIO[B]): PreparedStatementIO[B] = - monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => PreparedStatementIO[Either[A, B]]): PreparedStatementIO[B] = - monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): PreparedStatementIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: PreparedStatementIO[A])( - f: Throwable => PreparedStatementIO[A], - ): PreparedStatementIO[A] = module.handleErrorWith(fa)(f) - override def monotonic: PreparedStatementIO[FiniteDuration] = module.monotonic - override def realTime: PreparedStatementIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): PreparedStatementIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: PreparedStatementIO[A])(fb: PreparedStatementIO[B]): PreparedStatementIO[B] = - module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[PreparedStatementIO] => PreparedStatementIO[A]): PreparedStatementIO[A] = - module.uncancelable(body) - override def canceled: PreparedStatementIO[Unit] = module.canceled - override def onCancel[A](fa: PreparedStatementIO[A], fin: PreparedStatementIO[Unit]): PreparedStatementIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidPreparedStatementIO[A](implicit M: Monoid[A]): Monoid[PreparedStatementIO[A]] = - new Monoid[PreparedStatementIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: PreparedStatementIO[A], y: PreparedStatementIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/ref.scala b/modules/free/src/main/scala/doobie/free/ref.scala deleted file mode 100644 index ba2065740..000000000 --- a/modules/free/src/main/scala/doobie/free/ref.scala +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.sql.Ref -import scala.concurrent.duration.FiniteDuration - -object ref { module => - - // Algebra of operations for Ref. Each accepts a visitor as an alternative to pattern-matching. - sealed trait RefOp[A] { - def visit[F[_]](v: RefOp.Visitor[F]): F[A] - } - - // Free monad over RefOp. - type RefIO[A] = FF[RefOp, A] - - // Module of instances and constructors of RefOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object RefOp { - - // Given a Ref we can embed a RefIO program in any algebra that understands embedding. - implicit val RefOpEmbeddable: Embeddable[RefOp, Ref] = - new Embeddable[RefOp, Ref] { - def embed[A](j: Ref, fa: FF[RefOp, A]) = Embedded.Ref(j, fa) - } - - // Interface for a natural transformation RefOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (RefOp ~> F) { - final def apply[A](fa: RefOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: Ref => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: RefIO[A])(f: Throwable => RefIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: RefIO[A])(fb: RefIO[B]): F[B] - def uncancelable[A](body: Poll[RefIO] => RefIO[A]): F[A] - def poll[A](poll: Any, fa: RefIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: RefIO[A], fin: RefIO[Unit]): F[A] - - // Ref - def getBaseTypeName: F[String] - def getObject: F[AnyRef] - def getObject(a: java.util.Map[String, Class[?]]): F[AnyRef] - def setObject(a: AnyRef): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: Ref => A) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: RefIO[A], f: Throwable => RefIO[A]) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends RefOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends RefOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: RefIO[A], fb: RefIO[B]) extends RefOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[RefIO] => RefIO[A]) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: RefIO[A]) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends RefOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: RefIO[A], fin: RefIO[Unit]) extends RefOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // Ref-specific operations. - case object GetBaseTypeName extends RefOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getBaseTypeName - } - case object GetObject extends RefOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject - } - final case class GetObject1(a: java.util.Map[String, Class[?]]) extends RefOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a) - } - final case class SetObject(a: AnyRef) extends RefOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setObject(a) - } - - } - import RefOp.* - - // Smart constructors for operations common to all algebras. - val unit: RefIO[Unit] = FF.pure[RefOp, Unit](()) - def pure[A](a: A): RefIO[A] = FF.pure[RefOp, A](a) - def raw[A](f: Ref => A): RefIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[RefOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): RefIO[A] = FF.liftF[RefOp, A](RaiseError(err)) - def handleErrorWith[A](fa: RefIO[A])(f: Throwable => RefIO[A]): RefIO[A] = FF.liftF[RefOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[RefOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[RefOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[RefOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[RefOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: RefIO[A])(fb: RefIO[B]) = FF.liftF[RefOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[RefIO] => RefIO[A]) = FF.liftF[RefOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[RefIO] { - def apply[A](fa: RefIO[A]) = FF.liftF[RefOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[RefOp, Unit](Canceled) - def onCancel[A](fa: RefIO[A], fin: RefIO[Unit]) = FF.liftF[RefOp, A](OnCancel(fa, fin)) - - // Smart constructors for Ref-specific operations. - val getBaseTypeName: RefIO[String] = FF.liftF(GetBaseTypeName) - val getObject: RefIO[AnyRef] = FF.liftF(GetObject) - def getObject(a: java.util.Map[String, Class[?]]): RefIO[AnyRef] = FF.liftF(GetObject1(a)) - def setObject(a: AnyRef): RefIO[Unit] = FF.liftF(SetObject(a)) - - private val monad = FF.catsFreeMonadForFree[RefOp] - - // Typeclass instances for RefIO - implicit val SyncRefIO: Sync[RefIO] = - new Sync[RefIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): RefIO[A] = monad.pure(x) - override def map[A, B](fa: RefIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: RefIO[A])(f: A => RefIO[B]): RefIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => RefIO[Either[A, B]]): RefIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): RefIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: RefIO[A])(f: Throwable => RefIO[A]): RefIO[A] = module.handleErrorWith(fa)(f) - override def monotonic: RefIO[FiniteDuration] = module.monotonic - override def realTime: RefIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): RefIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: RefIO[A])(fb: RefIO[B]): RefIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[RefIO] => RefIO[A]): RefIO[A] = module.uncancelable(body) - override def canceled: RefIO[Unit] = module.canceled - override def onCancel[A](fa: RefIO[A], fin: RefIO[Unit]): RefIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidRefIO[A](implicit M: Monoid[A]): Monoid[RefIO[A]] = - new Monoid[RefIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: RefIO[A], y: RefIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/resultset.scala b/modules/free/src/main/scala/doobie/free/resultset.scala deleted file mode 100644 index 23516d0fb..000000000 --- a/modules/free/src/main/scala/doobie/free/resultset.scala +++ /dev/null @@ -1,1130 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.Reader -import java.math.BigDecimal -import java.net.URL -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.Clob -import java.sql.Date -import java.sql.NClob -import java.sql.Ref -import java.sql.ResultSet -import java.sql.ResultSetMetaData -import java.sql.RowId -import java.sql.SQLType -import java.sql.SQLWarning -import java.sql.SQLXML -import java.sql.Statement -import java.sql.Time -import java.sql.Timestamp -import java.util.Calendar -import scala.concurrent.duration.FiniteDuration - -object resultset { module => - - // Algebra of operations for ResultSet. Each accepts a visitor as an alternative to pattern-matching. - sealed trait ResultSetOp[A] { - def visit[F[_]](v: ResultSetOp.Visitor[F]): F[A] - } - - // Free monad over ResultSetOp. - type ResultSetIO[A] = FF[ResultSetOp, A] - - // Module of instances and constructors of ResultSetOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object ResultSetOp { - - // Given a ResultSet we can embed a ResultSetIO program in any algebra that understands embedding. - implicit val ResultSetOpEmbeddable: Embeddable[ResultSetOp, ResultSet] = - new Embeddable[ResultSetOp, ResultSet] { - def embed[A](j: ResultSet, fa: FF[ResultSetOp, A]) = Embedded.ResultSet(j, fa) - } - - // Interface for a natural transformation ResultSetOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (ResultSetOp ~> F) { - final def apply[A](fa: ResultSetOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: ResultSet => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: ResultSetIO[A])(f: Throwable => ResultSetIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: ResultSetIO[A])(fb: ResultSetIO[B]): F[B] - def uncancelable[A](body: Poll[ResultSetIO] => ResultSetIO[A]): F[A] - def poll[A](poll: Any, fa: ResultSetIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: ResultSetIO[A], fin: ResultSetIO[Unit]): F[A] - - // ResultSet - def absolute(a: Int): F[Boolean] - def afterLast: F[Unit] - def beforeFirst: F[Unit] - def cancelRowUpdates: F[Unit] - def clearWarnings: F[Unit] - def close: F[Unit] - def deleteRow: F[Unit] - def findColumn(a: String): F[Int] - def first: F[Boolean] - def getArray(a: Int): F[SqlArray] - def getArray(a: String): F[SqlArray] - def getAsciiStream(a: Int): F[InputStream] - def getAsciiStream(a: String): F[InputStream] - def getBigDecimal(a: Int): F[BigDecimal] - def getBigDecimal(a: String): F[BigDecimal] - def getBinaryStream(a: Int): F[InputStream] - def getBinaryStream(a: String): F[InputStream] - def getBlob(a: Int): F[Blob] - def getBlob(a: String): F[Blob] - def getBoolean(a: Int): F[Boolean] - def getBoolean(a: String): F[Boolean] - def getByte(a: Int): F[Byte] - def getByte(a: String): F[Byte] - def getBytes(a: Int): F[Array[Byte]] - def getBytes(a: String): F[Array[Byte]] - def getCharacterStream(a: Int): F[Reader] - def getCharacterStream(a: String): F[Reader] - def getClob(a: Int): F[Clob] - def getClob(a: String): F[Clob] - def getConcurrency: F[Int] - def getCursorName: F[String] - def getDate(a: Int): F[Date] - def getDate(a: Int, b: Calendar): F[Date] - def getDate(a: String): F[Date] - def getDate(a: String, b: Calendar): F[Date] - def getDouble(a: Int): F[Double] - def getDouble(a: String): F[Double] - def getFetchDirection: F[Int] - def getFetchSize: F[Int] - def getFloat(a: Int): F[Float] - def getFloat(a: String): F[Float] - def getHoldability: F[Int] - def getInt(a: Int): F[Int] - def getInt(a: String): F[Int] - def getLong(a: Int): F[Long] - def getLong(a: String): F[Long] - def getMetaData: F[ResultSetMetaData] - def getNCharacterStream(a: Int): F[Reader] - def getNCharacterStream(a: String): F[Reader] - def getNClob(a: Int): F[NClob] - def getNClob(a: String): F[NClob] - def getNString(a: Int): F[String] - def getNString(a: String): F[String] - def getObject(a: Int): F[AnyRef] - def getObject[T](a: Int, b: Class[T]): F[T] - def getObject(a: Int, b: java.util.Map[String, Class[?]]): F[AnyRef] - def getObject(a: String): F[AnyRef] - def getObject[T](a: String, b: Class[T]): F[T] - def getObject(a: String, b: java.util.Map[String, Class[?]]): F[AnyRef] - def getRef(a: Int): F[Ref] - def getRef(a: String): F[Ref] - def getRow: F[Int] - def getRowId(a: Int): F[RowId] - def getRowId(a: String): F[RowId] - def getSQLXML(a: Int): F[SQLXML] - def getSQLXML(a: String): F[SQLXML] - def getShort(a: Int): F[Short] - def getShort(a: String): F[Short] - def getStatement: F[Statement] - def getString(a: Int): F[String] - def getString(a: String): F[String] - def getTime(a: Int): F[Time] - def getTime(a: Int, b: Calendar): F[Time] - def getTime(a: String): F[Time] - def getTime(a: String, b: Calendar): F[Time] - def getTimestamp(a: Int): F[Timestamp] - def getTimestamp(a: Int, b: Calendar): F[Timestamp] - def getTimestamp(a: String): F[Timestamp] - def getTimestamp(a: String, b: Calendar): F[Timestamp] - def getType: F[Int] - def getURL(a: Int): F[URL] - def getURL(a: String): F[URL] - def getWarnings: F[SQLWarning] - def insertRow: F[Unit] - def isAfterLast: F[Boolean] - def isBeforeFirst: F[Boolean] - def isClosed: F[Boolean] - def isFirst: F[Boolean] - def isLast: F[Boolean] - def isWrapperFor(a: Class[?]): F[Boolean] - def last: F[Boolean] - def moveToCurrentRow: F[Unit] - def moveToInsertRow: F[Unit] - def next: F[Boolean] - def previous: F[Boolean] - def refreshRow: F[Unit] - def relative(a: Int): F[Boolean] - def rowDeleted: F[Boolean] - def rowInserted: F[Boolean] - def rowUpdated: F[Boolean] - def setFetchDirection(a: Int): F[Unit] - def setFetchSize(a: Int): F[Unit] - def unwrap[T](a: Class[T]): F[T] - def updateArray(a: Int, b: SqlArray): F[Unit] - def updateArray(a: String, b: SqlArray): F[Unit] - def updateAsciiStream(a: Int, b: InputStream): F[Unit] - def updateAsciiStream(a: Int, b: InputStream, c: Int): F[Unit] - def updateAsciiStream(a: Int, b: InputStream, c: Long): F[Unit] - def updateAsciiStream(a: String, b: InputStream): F[Unit] - def updateAsciiStream(a: String, b: InputStream, c: Int): F[Unit] - def updateAsciiStream(a: String, b: InputStream, c: Long): F[Unit] - def updateBigDecimal(a: Int, b: BigDecimal): F[Unit] - def updateBigDecimal(a: String, b: BigDecimal): F[Unit] - def updateBinaryStream(a: Int, b: InputStream): F[Unit] - def updateBinaryStream(a: Int, b: InputStream, c: Int): F[Unit] - def updateBinaryStream(a: Int, b: InputStream, c: Long): F[Unit] - def updateBinaryStream(a: String, b: InputStream): F[Unit] - def updateBinaryStream(a: String, b: InputStream, c: Int): F[Unit] - def updateBinaryStream(a: String, b: InputStream, c: Long): F[Unit] - def updateBlob(a: Int, b: Blob): F[Unit] - def updateBlob(a: Int, b: InputStream): F[Unit] - def updateBlob(a: Int, b: InputStream, c: Long): F[Unit] - def updateBlob(a: String, b: Blob): F[Unit] - def updateBlob(a: String, b: InputStream): F[Unit] - def updateBlob(a: String, b: InputStream, c: Long): F[Unit] - def updateBoolean(a: Int, b: Boolean): F[Unit] - def updateBoolean(a: String, b: Boolean): F[Unit] - def updateByte(a: Int, b: Byte): F[Unit] - def updateByte(a: String, b: Byte): F[Unit] - def updateBytes(a: Int, b: Array[Byte]): F[Unit] - def updateBytes(a: String, b: Array[Byte]): F[Unit] - def updateCharacterStream(a: Int, b: Reader): F[Unit] - def updateCharacterStream(a: Int, b: Reader, c: Int): F[Unit] - def updateCharacterStream(a: Int, b: Reader, c: Long): F[Unit] - def updateCharacterStream(a: String, b: Reader): F[Unit] - def updateCharacterStream(a: String, b: Reader, c: Int): F[Unit] - def updateCharacterStream(a: String, b: Reader, c: Long): F[Unit] - def updateClob(a: Int, b: Clob): F[Unit] - def updateClob(a: Int, b: Reader): F[Unit] - def updateClob(a: Int, b: Reader, c: Long): F[Unit] - def updateClob(a: String, b: Clob): F[Unit] - def updateClob(a: String, b: Reader): F[Unit] - def updateClob(a: String, b: Reader, c: Long): F[Unit] - def updateDate(a: Int, b: Date): F[Unit] - def updateDate(a: String, b: Date): F[Unit] - def updateDouble(a: Int, b: Double): F[Unit] - def updateDouble(a: String, b: Double): F[Unit] - def updateFloat(a: Int, b: Float): F[Unit] - def updateFloat(a: String, b: Float): F[Unit] - def updateInt(a: Int, b: Int): F[Unit] - def updateInt(a: String, b: Int): F[Unit] - def updateLong(a: Int, b: Long): F[Unit] - def updateLong(a: String, b: Long): F[Unit] - def updateNCharacterStream(a: Int, b: Reader): F[Unit] - def updateNCharacterStream(a: Int, b: Reader, c: Long): F[Unit] - def updateNCharacterStream(a: String, b: Reader): F[Unit] - def updateNCharacterStream(a: String, b: Reader, c: Long): F[Unit] - def updateNClob(a: Int, b: NClob): F[Unit] - def updateNClob(a: Int, b: Reader): F[Unit] - def updateNClob(a: Int, b: Reader, c: Long): F[Unit] - def updateNClob(a: String, b: NClob): F[Unit] - def updateNClob(a: String, b: Reader): F[Unit] - def updateNClob(a: String, b: Reader, c: Long): F[Unit] - def updateNString(a: Int, b: String): F[Unit] - def updateNString(a: String, b: String): F[Unit] - def updateNull(a: Int): F[Unit] - def updateNull(a: String): F[Unit] - def updateObject(a: Int, b: AnyRef): F[Unit] - def updateObject(a: Int, b: AnyRef, c: Int): F[Unit] - def updateObject(a: Int, b: AnyRef, c: SQLType): F[Unit] - def updateObject(a: Int, b: AnyRef, c: SQLType, d: Int): F[Unit] - def updateObject(a: String, b: AnyRef): F[Unit] - def updateObject(a: String, b: AnyRef, c: Int): F[Unit] - def updateObject(a: String, b: AnyRef, c: SQLType): F[Unit] - def updateObject(a: String, b: AnyRef, c: SQLType, d: Int): F[Unit] - def updateRef(a: Int, b: Ref): F[Unit] - def updateRef(a: String, b: Ref): F[Unit] - def updateRow: F[Unit] - def updateRowId(a: Int, b: RowId): F[Unit] - def updateRowId(a: String, b: RowId): F[Unit] - def updateSQLXML(a: Int, b: SQLXML): F[Unit] - def updateSQLXML(a: String, b: SQLXML): F[Unit] - def updateShort(a: Int, b: Short): F[Unit] - def updateShort(a: String, b: Short): F[Unit] - def updateString(a: Int, b: String): F[Unit] - def updateString(a: String, b: String): F[Unit] - def updateTime(a: Int, b: Time): F[Unit] - def updateTime(a: String, b: Time): F[Unit] - def updateTimestamp(a: Int, b: Timestamp): F[Unit] - def updateTimestamp(a: String, b: Timestamp): F[Unit] - def wasNull: F[Boolean] - - } - - // Common operations for all algebras. - final case class Raw[A](f: ResultSet => A) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: ResultSetIO[A], f: Throwable => ResultSetIO[A]) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends ResultSetOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends ResultSetOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: ResultSetIO[A], fb: ResultSetIO[B]) extends ResultSetOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[ResultSetIO] => ResultSetIO[A]) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: ResultSetIO[A]) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: ResultSetIO[A], fin: ResultSetIO[Unit]) extends ResultSetOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // ResultSet-specific operations. - final case class Absolute(a: Int) extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.absolute(a) - } - case object AfterLast extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.afterLast - } - case object BeforeFirst extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.beforeFirst - } - case object CancelRowUpdates extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancelRowUpdates - } - case object ClearWarnings extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearWarnings - } - case object Close extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.close - } - case object DeleteRow extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.deleteRow - } - final case class FindColumn(a: String) extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.findColumn(a) - } - case object First extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.first - } - final case class GetArray(a: Int) extends ResultSetOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.getArray(a) - } - final case class GetArray1(a: String) extends ResultSetOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.getArray(a) - } - final case class GetAsciiStream(a: Int) extends ResultSetOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getAsciiStream(a) - } - final case class GetAsciiStream1(a: String) extends ResultSetOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getAsciiStream(a) - } - final case class GetBigDecimal(a: Int) extends ResultSetOp[BigDecimal] { - def visit[F[_]](v: Visitor[F]) = v.getBigDecimal(a) - } - final case class GetBigDecimal1(a: String) extends ResultSetOp[BigDecimal] { - def visit[F[_]](v: Visitor[F]) = v.getBigDecimal(a) - } - final case class GetBinaryStream(a: Int) extends ResultSetOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getBinaryStream(a) - } - final case class GetBinaryStream1(a: String) extends ResultSetOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getBinaryStream(a) - } - final case class GetBlob(a: Int) extends ResultSetOp[Blob] { - def visit[F[_]](v: Visitor[F]) = v.getBlob(a) - } - final case class GetBlob1(a: String) extends ResultSetOp[Blob] { - def visit[F[_]](v: Visitor[F]) = v.getBlob(a) - } - final case class GetBoolean(a: Int) extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getBoolean(a) - } - final case class GetBoolean1(a: String) extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getBoolean(a) - } - final case class GetByte(a: Int) extends ResultSetOp[Byte] { - def visit[F[_]](v: Visitor[F]) = v.getByte(a) - } - final case class GetByte1(a: String) extends ResultSetOp[Byte] { - def visit[F[_]](v: Visitor[F]) = v.getByte(a) - } - final case class GetBytes(a: Int) extends ResultSetOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.getBytes(a) - } - final case class GetBytes1(a: String) extends ResultSetOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.getBytes(a) - } - final case class GetCharacterStream(a: Int) extends ResultSetOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream(a) - } - final case class GetCharacterStream1(a: String) extends ResultSetOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getCharacterStream(a) - } - final case class GetClob(a: Int) extends ResultSetOp[Clob] { - def visit[F[_]](v: Visitor[F]) = v.getClob(a) - } - final case class GetClob1(a: String) extends ResultSetOp[Clob] { - def visit[F[_]](v: Visitor[F]) = v.getClob(a) - } - case object GetConcurrency extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getConcurrency - } - case object GetCursorName extends ResultSetOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getCursorName - } - final case class GetDate(a: Int) extends ResultSetOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a) - } - final case class GetDate1(a: Int, b: Calendar) extends ResultSetOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a, b) - } - final case class GetDate2(a: String) extends ResultSetOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a) - } - final case class GetDate3(a: String, b: Calendar) extends ResultSetOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.getDate(a, b) - } - final case class GetDouble(a: Int) extends ResultSetOp[Double] { - def visit[F[_]](v: Visitor[F]) = v.getDouble(a) - } - final case class GetDouble1(a: String) extends ResultSetOp[Double] { - def visit[F[_]](v: Visitor[F]) = v.getDouble(a) - } - case object GetFetchDirection extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchDirection - } - case object GetFetchSize extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchSize - } - final case class GetFloat(a: Int) extends ResultSetOp[Float] { - def visit[F[_]](v: Visitor[F]) = v.getFloat(a) - } - final case class GetFloat1(a: String) extends ResultSetOp[Float] { - def visit[F[_]](v: Visitor[F]) = v.getFloat(a) - } - case object GetHoldability extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getHoldability - } - final case class GetInt(a: Int) extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getInt(a) - } - final case class GetInt1(a: String) extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getInt(a) - } - final case class GetLong(a: Int) extends ResultSetOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLong(a) - } - final case class GetLong1(a: String) extends ResultSetOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLong(a) - } - case object GetMetaData extends ResultSetOp[ResultSetMetaData] { - def visit[F[_]](v: Visitor[F]) = v.getMetaData - } - final case class GetNCharacterStream(a: Int) extends ResultSetOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getNCharacterStream(a) - } - final case class GetNCharacterStream1(a: String) extends ResultSetOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.getNCharacterStream(a) - } - final case class GetNClob(a: Int) extends ResultSetOp[NClob] { - def visit[F[_]](v: Visitor[F]) = v.getNClob(a) - } - final case class GetNClob1(a: String) extends ResultSetOp[NClob] { - def visit[F[_]](v: Visitor[F]) = v.getNClob(a) - } - final case class GetNString(a: Int) extends ResultSetOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getNString(a) - } - final case class GetNString1(a: String) extends ResultSetOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getNString(a) - } - final case class GetObject(a: Int) extends ResultSetOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a) - } - final case class GetObject1[T](a: Int, b: Class[T]) extends ResultSetOp[T] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetObject2(a: Int, b: java.util.Map[String, Class[?]]) extends ResultSetOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetObject3(a: String) extends ResultSetOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a) - } - final case class GetObject4[T](a: String, b: Class[T]) extends ResultSetOp[T] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetObject5(a: String, b: java.util.Map[String, Class[?]]) extends ResultSetOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.getObject(a, b) - } - final case class GetRef(a: Int) extends ResultSetOp[Ref] { - def visit[F[_]](v: Visitor[F]) = v.getRef(a) - } - final case class GetRef1(a: String) extends ResultSetOp[Ref] { - def visit[F[_]](v: Visitor[F]) = v.getRef(a) - } - case object GetRow extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getRow - } - final case class GetRowId(a: Int) extends ResultSetOp[RowId] { - def visit[F[_]](v: Visitor[F]) = v.getRowId(a) - } - final case class GetRowId1(a: String) extends ResultSetOp[RowId] { - def visit[F[_]](v: Visitor[F]) = v.getRowId(a) - } - final case class GetSQLXML(a: Int) extends ResultSetOp[SQLXML] { - def visit[F[_]](v: Visitor[F]) = v.getSQLXML(a) - } - final case class GetSQLXML1(a: String) extends ResultSetOp[SQLXML] { - def visit[F[_]](v: Visitor[F]) = v.getSQLXML(a) - } - final case class GetShort(a: Int) extends ResultSetOp[Short] { - def visit[F[_]](v: Visitor[F]) = v.getShort(a) - } - final case class GetShort1(a: String) extends ResultSetOp[Short] { - def visit[F[_]](v: Visitor[F]) = v.getShort(a) - } - case object GetStatement extends ResultSetOp[Statement] { - def visit[F[_]](v: Visitor[F]) = v.getStatement - } - final case class GetString(a: Int) extends ResultSetOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getString(a) - } - final case class GetString1(a: String) extends ResultSetOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getString(a) - } - final case class GetTime(a: Int) extends ResultSetOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a) - } - final case class GetTime1(a: Int, b: Calendar) extends ResultSetOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a, b) - } - final case class GetTime2(a: String) extends ResultSetOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a) - } - final case class GetTime3(a: String, b: Calendar) extends ResultSetOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.getTime(a, b) - } - final case class GetTimestamp(a: Int) extends ResultSetOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a) - } - final case class GetTimestamp1(a: Int, b: Calendar) extends ResultSetOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a, b) - } - final case class GetTimestamp2(a: String) extends ResultSetOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a) - } - final case class GetTimestamp3(a: String, b: Calendar) extends ResultSetOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.getTimestamp(a, b) - } - case object GetType extends ResultSetOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getType - } - final case class GetURL(a: Int) extends ResultSetOp[URL] { - def visit[F[_]](v: Visitor[F]) = v.getURL(a) - } - final case class GetURL1(a: String) extends ResultSetOp[URL] { - def visit[F[_]](v: Visitor[F]) = v.getURL(a) - } - case object GetWarnings extends ResultSetOp[SQLWarning] { - def visit[F[_]](v: Visitor[F]) = v.getWarnings - } - case object InsertRow extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.insertRow - } - case object IsAfterLast extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isAfterLast - } - case object IsBeforeFirst extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isBeforeFirst - } - case object IsClosed extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isClosed - } - case object IsFirst extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isFirst - } - case object IsLast extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isLast - } - final case class IsWrapperFor(a: Class[?]) extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isWrapperFor(a) - } - case object Last extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.last - } - case object MoveToCurrentRow extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.moveToCurrentRow - } - case object MoveToInsertRow extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.moveToInsertRow - } - case object Next extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.next - } - case object Previous extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.previous - } - case object RefreshRow extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.refreshRow - } - final case class Relative(a: Int) extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.relative(a) - } - case object RowDeleted extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.rowDeleted - } - case object RowInserted extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.rowInserted - } - case object RowUpdated extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.rowUpdated - } - final case class SetFetchDirection(a: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchDirection(a) - } - final case class SetFetchSize(a: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchSize(a) - } - final case class Unwrap[T](a: Class[T]) extends ResultSetOp[T] { - def visit[F[_]](v: Visitor[F]) = v.unwrap(a) - } - final case class UpdateArray(a: Int, b: SqlArray) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateArray(a, b) - } - final case class UpdateArray1(a: String, b: SqlArray) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateArray(a, b) - } - final case class UpdateAsciiStream(a: Int, b: InputStream) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateAsciiStream(a, b) - } - final case class UpdateAsciiStream1(a: Int, b: InputStream, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateAsciiStream(a, b, c) - } - final case class UpdateAsciiStream2(a: Int, b: InputStream, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateAsciiStream(a, b, c) - } - final case class UpdateAsciiStream3(a: String, b: InputStream) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateAsciiStream(a, b) - } - final case class UpdateAsciiStream4(a: String, b: InputStream, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateAsciiStream(a, b, c) - } - final case class UpdateAsciiStream5(a: String, b: InputStream, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateAsciiStream(a, b, c) - } - final case class UpdateBigDecimal(a: Int, b: BigDecimal) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBigDecimal(a, b) - } - final case class UpdateBigDecimal1(a: String, b: BigDecimal) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBigDecimal(a, b) - } - final case class UpdateBinaryStream(a: Int, b: InputStream) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBinaryStream(a, b) - } - final case class UpdateBinaryStream1(a: Int, b: InputStream, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBinaryStream(a, b, c) - } - final case class UpdateBinaryStream2(a: Int, b: InputStream, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBinaryStream(a, b, c) - } - final case class UpdateBinaryStream3(a: String, b: InputStream) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBinaryStream(a, b) - } - final case class UpdateBinaryStream4(a: String, b: InputStream, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBinaryStream(a, b, c) - } - final case class UpdateBinaryStream5(a: String, b: InputStream, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBinaryStream(a, b, c) - } - final case class UpdateBlob(a: Int, b: Blob) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBlob(a, b) - } - final case class UpdateBlob1(a: Int, b: InputStream) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBlob(a, b) - } - final case class UpdateBlob2(a: Int, b: InputStream, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBlob(a, b, c) - } - final case class UpdateBlob3(a: String, b: Blob) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBlob(a, b) - } - final case class UpdateBlob4(a: String, b: InputStream) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBlob(a, b) - } - final case class UpdateBlob5(a: String, b: InputStream, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBlob(a, b, c) - } - final case class UpdateBoolean(a: Int, b: Boolean) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBoolean(a, b) - } - final case class UpdateBoolean1(a: String, b: Boolean) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBoolean(a, b) - } - final case class UpdateByte(a: Int, b: Byte) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateByte(a, b) - } - final case class UpdateByte1(a: String, b: Byte) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateByte(a, b) - } - final case class UpdateBytes(a: Int, b: Array[Byte]) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBytes(a, b) - } - final case class UpdateBytes1(a: String, b: Array[Byte]) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateBytes(a, b) - } - final case class UpdateCharacterStream(a: Int, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateCharacterStream(a, b) - } - final case class UpdateCharacterStream1(a: Int, b: Reader, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateCharacterStream(a, b, c) - } - final case class UpdateCharacterStream2(a: Int, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateCharacterStream(a, b, c) - } - final case class UpdateCharacterStream3(a: String, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateCharacterStream(a, b) - } - final case class UpdateCharacterStream4(a: String, b: Reader, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateCharacterStream(a, b, c) - } - final case class UpdateCharacterStream5(a: String, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateCharacterStream(a, b, c) - } - final case class UpdateClob(a: Int, b: Clob) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateClob(a, b) - } - final case class UpdateClob1(a: Int, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateClob(a, b) - } - final case class UpdateClob2(a: Int, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateClob(a, b, c) - } - final case class UpdateClob3(a: String, b: Clob) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateClob(a, b) - } - final case class UpdateClob4(a: String, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateClob(a, b) - } - final case class UpdateClob5(a: String, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateClob(a, b, c) - } - final case class UpdateDate(a: Int, b: Date) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateDate(a, b) - } - final case class UpdateDate1(a: String, b: Date) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateDate(a, b) - } - final case class UpdateDouble(a: Int, b: Double) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateDouble(a, b) - } - final case class UpdateDouble1(a: String, b: Double) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateDouble(a, b) - } - final case class UpdateFloat(a: Int, b: Float) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateFloat(a, b) - } - final case class UpdateFloat1(a: String, b: Float) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateFloat(a, b) - } - final case class UpdateInt(a: Int, b: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateInt(a, b) - } - final case class UpdateInt1(a: String, b: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateInt(a, b) - } - final case class UpdateLong(a: Int, b: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateLong(a, b) - } - final case class UpdateLong1(a: String, b: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateLong(a, b) - } - final case class UpdateNCharacterStream(a: Int, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNCharacterStream(a, b) - } - final case class UpdateNCharacterStream1(a: Int, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNCharacterStream(a, b, c) - } - final case class UpdateNCharacterStream2(a: String, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNCharacterStream(a, b) - } - final case class UpdateNCharacterStream3(a: String, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNCharacterStream(a, b, c) - } - final case class UpdateNClob(a: Int, b: NClob) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNClob(a, b) - } - final case class UpdateNClob1(a: Int, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNClob(a, b) - } - final case class UpdateNClob2(a: Int, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNClob(a, b, c) - } - final case class UpdateNClob3(a: String, b: NClob) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNClob(a, b) - } - final case class UpdateNClob4(a: String, b: Reader) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNClob(a, b) - } - final case class UpdateNClob5(a: String, b: Reader, c: Long) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNClob(a, b, c) - } - final case class UpdateNString(a: Int, b: String) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNString(a, b) - } - final case class UpdateNString1(a: String, b: String) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNString(a, b) - } - final case class UpdateNull(a: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNull(a) - } - final case class UpdateNull1(a: String) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateNull(a) - } - final case class UpdateObject(a: Int, b: AnyRef) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b) - } - final case class UpdateObject1(a: Int, b: AnyRef, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b, c) - } - final case class UpdateObject2(a: Int, b: AnyRef, c: SQLType) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b, c) - } - final case class UpdateObject3(a: Int, b: AnyRef, c: SQLType, d: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b, c, d) - } - final case class UpdateObject4(a: String, b: AnyRef) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b) - } - final case class UpdateObject5(a: String, b: AnyRef, c: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b, c) - } - final case class UpdateObject6(a: String, b: AnyRef, c: SQLType) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b, c) - } - final case class UpdateObject7(a: String, b: AnyRef, c: SQLType, d: Int) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateObject(a, b, c, d) - } - final case class UpdateRef(a: Int, b: Ref) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateRef(a, b) - } - final case class UpdateRef1(a: String, b: Ref) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateRef(a, b) - } - case object UpdateRow extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateRow - } - final case class UpdateRowId(a: Int, b: RowId) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateRowId(a, b) - } - final case class UpdateRowId1(a: String, b: RowId) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateRowId(a, b) - } - final case class UpdateSQLXML(a: Int, b: SQLXML) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateSQLXML(a, b) - } - final case class UpdateSQLXML1(a: String, b: SQLXML) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateSQLXML(a, b) - } - final case class UpdateShort(a: Int, b: Short) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateShort(a, b) - } - final case class UpdateShort1(a: String, b: Short) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateShort(a, b) - } - final case class UpdateString(a: Int, b: String) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateString(a, b) - } - final case class UpdateString1(a: String, b: String) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateString(a, b) - } - final case class UpdateTime(a: Int, b: Time) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateTime(a, b) - } - final case class UpdateTime1(a: String, b: Time) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateTime(a, b) - } - final case class UpdateTimestamp(a: Int, b: Timestamp) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateTimestamp(a, b) - } - final case class UpdateTimestamp1(a: String, b: Timestamp) extends ResultSetOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.updateTimestamp(a, b) - } - case object WasNull extends ResultSetOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.wasNull - } - - } - import ResultSetOp.* - - // Smart constructors for operations common to all algebras. - val unit: ResultSetIO[Unit] = FF.pure[ResultSetOp, Unit](()) - def pure[A](a: A): ResultSetIO[A] = FF.pure[ResultSetOp, A](a) - def raw[A](f: ResultSet => A): ResultSetIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[ResultSetOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): ResultSetIO[A] = FF.liftF[ResultSetOp, A](RaiseError(err)) - def handleErrorWith[A](fa: ResultSetIO[A])(f: Throwable => ResultSetIO[A]): ResultSetIO[A] = - FF.liftF[ResultSetOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[ResultSetOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[ResultSetOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[ResultSetOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[ResultSetOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: ResultSetIO[A])(fb: ResultSetIO[B]) = FF.liftF[ResultSetOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[ResultSetIO] => ResultSetIO[A]) = FF.liftF[ResultSetOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[ResultSetIO] { - def apply[A](fa: ResultSetIO[A]) = FF.liftF[ResultSetOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[ResultSetOp, Unit](Canceled) - def onCancel[A](fa: ResultSetIO[A], fin: ResultSetIO[Unit]) = FF.liftF[ResultSetOp, A](OnCancel(fa, fin)) - - // Smart constructors for ResultSet-specific operations. - def absolute(a: Int): ResultSetIO[Boolean] = FF.liftF(Absolute(a)) - val afterLast: ResultSetIO[Unit] = FF.liftF(AfterLast) - val beforeFirst: ResultSetIO[Unit] = FF.liftF(BeforeFirst) - val cancelRowUpdates: ResultSetIO[Unit] = FF.liftF(CancelRowUpdates) - val clearWarnings: ResultSetIO[Unit] = FF.liftF(ClearWarnings) - val close: ResultSetIO[Unit] = FF.liftF(Close) - val deleteRow: ResultSetIO[Unit] = FF.liftF(DeleteRow) - def findColumn(a: String): ResultSetIO[Int] = FF.liftF(FindColumn(a)) - val first: ResultSetIO[Boolean] = FF.liftF(First) - def getArray(a: Int): ResultSetIO[SqlArray] = FF.liftF(GetArray(a)) - def getArray(a: String): ResultSetIO[SqlArray] = FF.liftF(GetArray1(a)) - def getAsciiStream(a: Int): ResultSetIO[InputStream] = FF.liftF(GetAsciiStream(a)) - def getAsciiStream(a: String): ResultSetIO[InputStream] = FF.liftF(GetAsciiStream1(a)) - def getBigDecimal(a: Int): ResultSetIO[BigDecimal] = FF.liftF(GetBigDecimal(a)) - def getBigDecimal(a: String): ResultSetIO[BigDecimal] = FF.liftF(GetBigDecimal1(a)) - def getBinaryStream(a: Int): ResultSetIO[InputStream] = FF.liftF(GetBinaryStream(a)) - def getBinaryStream(a: String): ResultSetIO[InputStream] = FF.liftF(GetBinaryStream1(a)) - def getBlob(a: Int): ResultSetIO[Blob] = FF.liftF(GetBlob(a)) - def getBlob(a: String): ResultSetIO[Blob] = FF.liftF(GetBlob1(a)) - def getBoolean(a: Int): ResultSetIO[Boolean] = FF.liftF(GetBoolean(a)) - def getBoolean(a: String): ResultSetIO[Boolean] = FF.liftF(GetBoolean1(a)) - def getByte(a: Int): ResultSetIO[Byte] = FF.liftF(GetByte(a)) - def getByte(a: String): ResultSetIO[Byte] = FF.liftF(GetByte1(a)) - def getBytes(a: Int): ResultSetIO[Array[Byte]] = FF.liftF(GetBytes(a)) - def getBytes(a: String): ResultSetIO[Array[Byte]] = FF.liftF(GetBytes1(a)) - def getCharacterStream(a: Int): ResultSetIO[Reader] = FF.liftF(GetCharacterStream(a)) - def getCharacterStream(a: String): ResultSetIO[Reader] = FF.liftF(GetCharacterStream1(a)) - def getClob(a: Int): ResultSetIO[Clob] = FF.liftF(GetClob(a)) - def getClob(a: String): ResultSetIO[Clob] = FF.liftF(GetClob1(a)) - val getConcurrency: ResultSetIO[Int] = FF.liftF(GetConcurrency) - val getCursorName: ResultSetIO[String] = FF.liftF(GetCursorName) - def getDate(a: Int): ResultSetIO[Date] = FF.liftF(GetDate(a)) - def getDate(a: Int, b: Calendar): ResultSetIO[Date] = FF.liftF(GetDate1(a, b)) - def getDate(a: String): ResultSetIO[Date] = FF.liftF(GetDate2(a)) - def getDate(a: String, b: Calendar): ResultSetIO[Date] = FF.liftF(GetDate3(a, b)) - def getDouble(a: Int): ResultSetIO[Double] = FF.liftF(GetDouble(a)) - def getDouble(a: String): ResultSetIO[Double] = FF.liftF(GetDouble1(a)) - val getFetchDirection: ResultSetIO[Int] = FF.liftF(GetFetchDirection) - val getFetchSize: ResultSetIO[Int] = FF.liftF(GetFetchSize) - def getFloat(a: Int): ResultSetIO[Float] = FF.liftF(GetFloat(a)) - def getFloat(a: String): ResultSetIO[Float] = FF.liftF(GetFloat1(a)) - val getHoldability: ResultSetIO[Int] = FF.liftF(GetHoldability) - def getInt(a: Int): ResultSetIO[Int] = FF.liftF(GetInt(a)) - def getInt(a: String): ResultSetIO[Int] = FF.liftF(GetInt1(a)) - def getLong(a: Int): ResultSetIO[Long] = FF.liftF(GetLong(a)) - def getLong(a: String): ResultSetIO[Long] = FF.liftF(GetLong1(a)) - val getMetaData: ResultSetIO[ResultSetMetaData] = FF.liftF(GetMetaData) - def getNCharacterStream(a: Int): ResultSetIO[Reader] = FF.liftF(GetNCharacterStream(a)) - def getNCharacterStream(a: String): ResultSetIO[Reader] = FF.liftF(GetNCharacterStream1(a)) - def getNClob(a: Int): ResultSetIO[NClob] = FF.liftF(GetNClob(a)) - def getNClob(a: String): ResultSetIO[NClob] = FF.liftF(GetNClob1(a)) - def getNString(a: Int): ResultSetIO[String] = FF.liftF(GetNString(a)) - def getNString(a: String): ResultSetIO[String] = FF.liftF(GetNString1(a)) - def getObject(a: Int): ResultSetIO[AnyRef] = FF.liftF(GetObject(a)) - def getObject[T](a: Int, b: Class[T]): ResultSetIO[T] = FF.liftF(GetObject1(a, b)) - def getObject(a: Int, b: java.util.Map[String, Class[?]]): ResultSetIO[AnyRef] = FF.liftF(GetObject2(a, b)) - def getObject(a: String): ResultSetIO[AnyRef] = FF.liftF(GetObject3(a)) - def getObject[T](a: String, b: Class[T]): ResultSetIO[T] = FF.liftF(GetObject4(a, b)) - def getObject(a: String, b: java.util.Map[String, Class[?]]): ResultSetIO[AnyRef] = FF.liftF(GetObject5(a, b)) - def getRef(a: Int): ResultSetIO[Ref] = FF.liftF(GetRef(a)) - def getRef(a: String): ResultSetIO[Ref] = FF.liftF(GetRef1(a)) - val getRow: ResultSetIO[Int] = FF.liftF(GetRow) - def getRowId(a: Int): ResultSetIO[RowId] = FF.liftF(GetRowId(a)) - def getRowId(a: String): ResultSetIO[RowId] = FF.liftF(GetRowId1(a)) - def getSQLXML(a: Int): ResultSetIO[SQLXML] = FF.liftF(GetSQLXML(a)) - def getSQLXML(a: String): ResultSetIO[SQLXML] = FF.liftF(GetSQLXML1(a)) - def getShort(a: Int): ResultSetIO[Short] = FF.liftF(GetShort(a)) - def getShort(a: String): ResultSetIO[Short] = FF.liftF(GetShort1(a)) - val getStatement: ResultSetIO[Statement] = FF.liftF(GetStatement) - def getString(a: Int): ResultSetIO[String] = FF.liftF(GetString(a)) - def getString(a: String): ResultSetIO[String] = FF.liftF(GetString1(a)) - def getTime(a: Int): ResultSetIO[Time] = FF.liftF(GetTime(a)) - def getTime(a: Int, b: Calendar): ResultSetIO[Time] = FF.liftF(GetTime1(a, b)) - def getTime(a: String): ResultSetIO[Time] = FF.liftF(GetTime2(a)) - def getTime(a: String, b: Calendar): ResultSetIO[Time] = FF.liftF(GetTime3(a, b)) - def getTimestamp(a: Int): ResultSetIO[Timestamp] = FF.liftF(GetTimestamp(a)) - def getTimestamp(a: Int, b: Calendar): ResultSetIO[Timestamp] = FF.liftF(GetTimestamp1(a, b)) - def getTimestamp(a: String): ResultSetIO[Timestamp] = FF.liftF(GetTimestamp2(a)) - def getTimestamp(a: String, b: Calendar): ResultSetIO[Timestamp] = FF.liftF(GetTimestamp3(a, b)) - val getType: ResultSetIO[Int] = FF.liftF(GetType) - def getURL(a: Int): ResultSetIO[URL] = FF.liftF(GetURL(a)) - def getURL(a: String): ResultSetIO[URL] = FF.liftF(GetURL1(a)) - val getWarnings: ResultSetIO[SQLWarning] = FF.liftF(GetWarnings) - val insertRow: ResultSetIO[Unit] = FF.liftF(InsertRow) - val isAfterLast: ResultSetIO[Boolean] = FF.liftF(IsAfterLast) - val isBeforeFirst: ResultSetIO[Boolean] = FF.liftF(IsBeforeFirst) - val isClosed: ResultSetIO[Boolean] = FF.liftF(IsClosed) - val isFirst: ResultSetIO[Boolean] = FF.liftF(IsFirst) - val isLast: ResultSetIO[Boolean] = FF.liftF(IsLast) - def isWrapperFor(a: Class[?]): ResultSetIO[Boolean] = FF.liftF(IsWrapperFor(a)) - val last: ResultSetIO[Boolean] = FF.liftF(Last) - val moveToCurrentRow: ResultSetIO[Unit] = FF.liftF(MoveToCurrentRow) - val moveToInsertRow: ResultSetIO[Unit] = FF.liftF(MoveToInsertRow) - val next: ResultSetIO[Boolean] = FF.liftF(Next) - val previous: ResultSetIO[Boolean] = FF.liftF(Previous) - val refreshRow: ResultSetIO[Unit] = FF.liftF(RefreshRow) - def relative(a: Int): ResultSetIO[Boolean] = FF.liftF(Relative(a)) - val rowDeleted: ResultSetIO[Boolean] = FF.liftF(RowDeleted) - val rowInserted: ResultSetIO[Boolean] = FF.liftF(RowInserted) - val rowUpdated: ResultSetIO[Boolean] = FF.liftF(RowUpdated) - def setFetchDirection(a: Int): ResultSetIO[Unit] = FF.liftF(SetFetchDirection(a)) - def setFetchSize(a: Int): ResultSetIO[Unit] = FF.liftF(SetFetchSize(a)) - def unwrap[T](a: Class[T]): ResultSetIO[T] = FF.liftF(Unwrap(a)) - def updateArray(a: Int, b: SqlArray): ResultSetIO[Unit] = FF.liftF(UpdateArray(a, b)) - def updateArray(a: String, b: SqlArray): ResultSetIO[Unit] = FF.liftF(UpdateArray1(a, b)) - def updateAsciiStream(a: Int, b: InputStream): ResultSetIO[Unit] = FF.liftF(UpdateAsciiStream(a, b)) - def updateAsciiStream(a: Int, b: InputStream, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateAsciiStream1(a, b, c)) - def updateAsciiStream(a: Int, b: InputStream, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateAsciiStream2(a, b, c)) - def updateAsciiStream(a: String, b: InputStream): ResultSetIO[Unit] = FF.liftF(UpdateAsciiStream3(a, b)) - def updateAsciiStream(a: String, b: InputStream, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateAsciiStream4(a, b, c)) - def updateAsciiStream(a: String, b: InputStream, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateAsciiStream5(a, b, c)) - def updateBigDecimal(a: Int, b: BigDecimal): ResultSetIO[Unit] = FF.liftF(UpdateBigDecimal(a, b)) - def updateBigDecimal(a: String, b: BigDecimal): ResultSetIO[Unit] = FF.liftF(UpdateBigDecimal1(a, b)) - def updateBinaryStream(a: Int, b: InputStream): ResultSetIO[Unit] = FF.liftF(UpdateBinaryStream(a, b)) - def updateBinaryStream(a: Int, b: InputStream, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateBinaryStream1(a, b, c)) - def updateBinaryStream(a: Int, b: InputStream, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateBinaryStream2(a, b, c)) - def updateBinaryStream(a: String, b: InputStream): ResultSetIO[Unit] = FF.liftF(UpdateBinaryStream3(a, b)) - def updateBinaryStream(a: String, b: InputStream, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateBinaryStream4(a, b, c)) - def updateBinaryStream(a: String, b: InputStream, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateBinaryStream5(a, b, c)) - def updateBlob(a: Int, b: Blob): ResultSetIO[Unit] = FF.liftF(UpdateBlob(a, b)) - def updateBlob(a: Int, b: InputStream): ResultSetIO[Unit] = FF.liftF(UpdateBlob1(a, b)) - def updateBlob(a: Int, b: InputStream, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateBlob2(a, b, c)) - def updateBlob(a: String, b: Blob): ResultSetIO[Unit] = FF.liftF(UpdateBlob3(a, b)) - def updateBlob(a: String, b: InputStream): ResultSetIO[Unit] = FF.liftF(UpdateBlob4(a, b)) - def updateBlob(a: String, b: InputStream, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateBlob5(a, b, c)) - def updateBoolean(a: Int, b: Boolean): ResultSetIO[Unit] = FF.liftF(UpdateBoolean(a, b)) - def updateBoolean(a: String, b: Boolean): ResultSetIO[Unit] = FF.liftF(UpdateBoolean1(a, b)) - def updateByte(a: Int, b: Byte): ResultSetIO[Unit] = FF.liftF(UpdateByte(a, b)) - def updateByte(a: String, b: Byte): ResultSetIO[Unit] = FF.liftF(UpdateByte1(a, b)) - def updateBytes(a: Int, b: Array[Byte]): ResultSetIO[Unit] = FF.liftF(UpdateBytes(a, b)) - def updateBytes(a: String, b: Array[Byte]): ResultSetIO[Unit] = FF.liftF(UpdateBytes1(a, b)) - def updateCharacterStream(a: Int, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateCharacterStream(a, b)) - def updateCharacterStream(a: Int, b: Reader, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateCharacterStream1(a, b, c)) - def updateCharacterStream(a: Int, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateCharacterStream2(a, b, c)) - def updateCharacterStream(a: String, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateCharacterStream3(a, b)) - def updateCharacterStream(a: String, b: Reader, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateCharacterStream4(a, b, c)) - def updateCharacterStream(a: String, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateCharacterStream5(a, b, c)) - def updateClob(a: Int, b: Clob): ResultSetIO[Unit] = FF.liftF(UpdateClob(a, b)) - def updateClob(a: Int, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateClob1(a, b)) - def updateClob(a: Int, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateClob2(a, b, c)) - def updateClob(a: String, b: Clob): ResultSetIO[Unit] = FF.liftF(UpdateClob3(a, b)) - def updateClob(a: String, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateClob4(a, b)) - def updateClob(a: String, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateClob5(a, b, c)) - def updateDate(a: Int, b: Date): ResultSetIO[Unit] = FF.liftF(UpdateDate(a, b)) - def updateDate(a: String, b: Date): ResultSetIO[Unit] = FF.liftF(UpdateDate1(a, b)) - def updateDouble(a: Int, b: Double): ResultSetIO[Unit] = FF.liftF(UpdateDouble(a, b)) - def updateDouble(a: String, b: Double): ResultSetIO[Unit] = FF.liftF(UpdateDouble1(a, b)) - def updateFloat(a: Int, b: Float): ResultSetIO[Unit] = FF.liftF(UpdateFloat(a, b)) - def updateFloat(a: String, b: Float): ResultSetIO[Unit] = FF.liftF(UpdateFloat1(a, b)) - def updateInt(a: Int, b: Int): ResultSetIO[Unit] = FF.liftF(UpdateInt(a, b)) - def updateInt(a: String, b: Int): ResultSetIO[Unit] = FF.liftF(UpdateInt1(a, b)) - def updateLong(a: Int, b: Long): ResultSetIO[Unit] = FF.liftF(UpdateLong(a, b)) - def updateLong(a: String, b: Long): ResultSetIO[Unit] = FF.liftF(UpdateLong1(a, b)) - def updateNCharacterStream(a: Int, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateNCharacterStream(a, b)) - def updateNCharacterStream(a: Int, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateNCharacterStream1(a, b, c)) - def updateNCharacterStream(a: String, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateNCharacterStream2(a, b)) - def updateNCharacterStream(a: String, b: Reader, c: Long): ResultSetIO[Unit] = - FF.liftF(UpdateNCharacterStream3(a, b, c)) - def updateNClob(a: Int, b: NClob): ResultSetIO[Unit] = FF.liftF(UpdateNClob(a, b)) - def updateNClob(a: Int, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateNClob1(a, b)) - def updateNClob(a: Int, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateNClob2(a, b, c)) - def updateNClob(a: String, b: NClob): ResultSetIO[Unit] = FF.liftF(UpdateNClob3(a, b)) - def updateNClob(a: String, b: Reader): ResultSetIO[Unit] = FF.liftF(UpdateNClob4(a, b)) - def updateNClob(a: String, b: Reader, c: Long): ResultSetIO[Unit] = FF.liftF(UpdateNClob5(a, b, c)) - def updateNString(a: Int, b: String): ResultSetIO[Unit] = FF.liftF(UpdateNString(a, b)) - def updateNString(a: String, b: String): ResultSetIO[Unit] = FF.liftF(UpdateNString1(a, b)) - def updateNull(a: Int): ResultSetIO[Unit] = FF.liftF(UpdateNull(a)) - def updateNull(a: String): ResultSetIO[Unit] = FF.liftF(UpdateNull1(a)) - def updateObject(a: Int, b: AnyRef): ResultSetIO[Unit] = FF.liftF(UpdateObject(a, b)) - def updateObject(a: Int, b: AnyRef, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateObject1(a, b, c)) - def updateObject(a: Int, b: AnyRef, c: SQLType): ResultSetIO[Unit] = FF.liftF(UpdateObject2(a, b, c)) - def updateObject(a: Int, b: AnyRef, c: SQLType, d: Int): ResultSetIO[Unit] = FF.liftF(UpdateObject3(a, b, c, d)) - def updateObject(a: String, b: AnyRef): ResultSetIO[Unit] = FF.liftF(UpdateObject4(a, b)) - def updateObject(a: String, b: AnyRef, c: Int): ResultSetIO[Unit] = FF.liftF(UpdateObject5(a, b, c)) - def updateObject(a: String, b: AnyRef, c: SQLType): ResultSetIO[Unit] = FF.liftF(UpdateObject6(a, b, c)) - def updateObject(a: String, b: AnyRef, c: SQLType, d: Int): ResultSetIO[Unit] = FF.liftF(UpdateObject7(a, b, c, d)) - def updateRef(a: Int, b: Ref): ResultSetIO[Unit] = FF.liftF(UpdateRef(a, b)) - def updateRef(a: String, b: Ref): ResultSetIO[Unit] = FF.liftF(UpdateRef1(a, b)) - val updateRow: ResultSetIO[Unit] = FF.liftF(UpdateRow) - def updateRowId(a: Int, b: RowId): ResultSetIO[Unit] = FF.liftF(UpdateRowId(a, b)) - def updateRowId(a: String, b: RowId): ResultSetIO[Unit] = FF.liftF(UpdateRowId1(a, b)) - def updateSQLXML(a: Int, b: SQLXML): ResultSetIO[Unit] = FF.liftF(UpdateSQLXML(a, b)) - def updateSQLXML(a: String, b: SQLXML): ResultSetIO[Unit] = FF.liftF(UpdateSQLXML1(a, b)) - def updateShort(a: Int, b: Short): ResultSetIO[Unit] = FF.liftF(UpdateShort(a, b)) - def updateShort(a: String, b: Short): ResultSetIO[Unit] = FF.liftF(UpdateShort1(a, b)) - def updateString(a: Int, b: String): ResultSetIO[Unit] = FF.liftF(UpdateString(a, b)) - def updateString(a: String, b: String): ResultSetIO[Unit] = FF.liftF(UpdateString1(a, b)) - def updateTime(a: Int, b: Time): ResultSetIO[Unit] = FF.liftF(UpdateTime(a, b)) - def updateTime(a: String, b: Time): ResultSetIO[Unit] = FF.liftF(UpdateTime1(a, b)) - def updateTimestamp(a: Int, b: Timestamp): ResultSetIO[Unit] = FF.liftF(UpdateTimestamp(a, b)) - def updateTimestamp(a: String, b: Timestamp): ResultSetIO[Unit] = FF.liftF(UpdateTimestamp1(a, b)) - val wasNull: ResultSetIO[Boolean] = FF.liftF(WasNull) - - private val monad = FF.catsFreeMonadForFree[ResultSetOp] - - // Typeclass instances for ResultSetIO - implicit val SyncResultSetIO: Sync[ResultSetIO] = - new Sync[ResultSetIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): ResultSetIO[A] = monad.pure(x) - override def map[A, B](fa: ResultSetIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: ResultSetIO[A])(f: A => ResultSetIO[B]): ResultSetIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => ResultSetIO[Either[A, B]]): ResultSetIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): ResultSetIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: ResultSetIO[A])(f: Throwable => ResultSetIO[A]): ResultSetIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: ResultSetIO[FiniteDuration] = module.monotonic - override def realTime: ResultSetIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): ResultSetIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: ResultSetIO[A])(fb: ResultSetIO[B]): ResultSetIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[ResultSetIO] => ResultSetIO[A]): ResultSetIO[A] = module.uncancelable(body) - override def canceled: ResultSetIO[Unit] = module.canceled - override def onCancel[A](fa: ResultSetIO[A], fin: ResultSetIO[Unit]): ResultSetIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidResultSetIO[A](implicit M: Monoid[A]): Monoid[ResultSetIO[A]] = - new Monoid[ResultSetIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: ResultSetIO[A], y: ResultSetIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/sqldata.scala b/modules/free/src/main/scala/doobie/free/sqldata.scala deleted file mode 100644 index 9b981fe4c..000000000 --- a/modules/free/src/main/scala/doobie/free/sqldata.scala +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.sql.SQLData -import java.sql.SQLInput -import java.sql.SQLOutput -import scala.concurrent.duration.FiniteDuration - -object sqldata { module => - - // Algebra of operations for SQLData. Each accepts a visitor as an alternative to pattern-matching. - sealed trait SQLDataOp[A] { - def visit[F[_]](v: SQLDataOp.Visitor[F]): F[A] - } - - // Free monad over SQLDataOp. - type SQLDataIO[A] = FF[SQLDataOp, A] - - // Module of instances and constructors of SQLDataOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object SQLDataOp { - - // Given a SQLData we can embed a SQLDataIO program in any algebra that understands embedding. - implicit val SQLDataOpEmbeddable: Embeddable[SQLDataOp, SQLData] = - new Embeddable[SQLDataOp, SQLData] { - def embed[A](j: SQLData, fa: FF[SQLDataOp, A]) = Embedded.SQLData(j, fa) - } - - // Interface for a natural transformation SQLDataOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (SQLDataOp ~> F) { - final def apply[A](fa: SQLDataOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: SQLData => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: SQLDataIO[A])(f: Throwable => SQLDataIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: SQLDataIO[A])(fb: SQLDataIO[B]): F[B] - def uncancelable[A](body: Poll[SQLDataIO] => SQLDataIO[A]): F[A] - def poll[A](poll: Any, fa: SQLDataIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: SQLDataIO[A], fin: SQLDataIO[Unit]): F[A] - - // SQLData - def getSQLTypeName: F[String] - def readSQL(a: SQLInput, b: String): F[Unit] - def writeSQL(a: SQLOutput): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: SQLData => A) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: SQLDataIO[A], f: Throwable => SQLDataIO[A]) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends SQLDataOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends SQLDataOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: SQLDataIO[A], fb: SQLDataIO[B]) extends SQLDataOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[SQLDataIO] => SQLDataIO[A]) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: SQLDataIO[A]) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends SQLDataOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: SQLDataIO[A], fin: SQLDataIO[Unit]) extends SQLDataOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // SQLData-specific operations. - case object GetSQLTypeName extends SQLDataOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getSQLTypeName - } - final case class ReadSQL(a: SQLInput, b: String) extends SQLDataOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.readSQL(a, b) - } - final case class WriteSQL(a: SQLOutput) extends SQLDataOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeSQL(a) - } - - } - import SQLDataOp.* - - // Smart constructors for operations common to all algebras. - val unit: SQLDataIO[Unit] = FF.pure[SQLDataOp, Unit](()) - def pure[A](a: A): SQLDataIO[A] = FF.pure[SQLDataOp, A](a) - def raw[A](f: SQLData => A): SQLDataIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[SQLDataOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): SQLDataIO[A] = FF.liftF[SQLDataOp, A](RaiseError(err)) - def handleErrorWith[A](fa: SQLDataIO[A])(f: Throwable => SQLDataIO[A]): SQLDataIO[A] = - FF.liftF[SQLDataOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[SQLDataOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[SQLDataOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[SQLDataOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[SQLDataOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: SQLDataIO[A])(fb: SQLDataIO[B]) = FF.liftF[SQLDataOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[SQLDataIO] => SQLDataIO[A]) = FF.liftF[SQLDataOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[SQLDataIO] { - def apply[A](fa: SQLDataIO[A]) = FF.liftF[SQLDataOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[SQLDataOp, Unit](Canceled) - def onCancel[A](fa: SQLDataIO[A], fin: SQLDataIO[Unit]) = FF.liftF[SQLDataOp, A](OnCancel(fa, fin)) - - // Smart constructors for SQLData-specific operations. - val getSQLTypeName: SQLDataIO[String] = FF.liftF(GetSQLTypeName) - def readSQL(a: SQLInput, b: String): SQLDataIO[Unit] = FF.liftF(ReadSQL(a, b)) - def writeSQL(a: SQLOutput): SQLDataIO[Unit] = FF.liftF(WriteSQL(a)) - - private val monad = FF.catsFreeMonadForFree[SQLDataOp] - - // Typeclass instances for SQLDataIO - implicit val SyncSQLDataIO: Sync[SQLDataIO] = - new Sync[SQLDataIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): SQLDataIO[A] = monad.pure(x) - override def map[A, B](fa: SQLDataIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: SQLDataIO[A])(f: A => SQLDataIO[B]): SQLDataIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => SQLDataIO[Either[A, B]]): SQLDataIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): SQLDataIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: SQLDataIO[A])(f: Throwable => SQLDataIO[A]): SQLDataIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: SQLDataIO[FiniteDuration] = module.monotonic - override def realTime: SQLDataIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): SQLDataIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: SQLDataIO[A])(fb: SQLDataIO[B]): SQLDataIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[SQLDataIO] => SQLDataIO[A]): SQLDataIO[A] = module.uncancelable(body) - override def canceled: SQLDataIO[Unit] = module.canceled - override def onCancel[A](fa: SQLDataIO[A], fin: SQLDataIO[Unit]): SQLDataIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidSQLDataIO[A](implicit M: Monoid[A]): Monoid[SQLDataIO[A]] = - new Monoid[SQLDataIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: SQLDataIO[A], y: SQLDataIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/sqlinput.scala b/modules/free/src/main/scala/doobie/free/sqlinput.scala deleted file mode 100644 index 9ee5d2407..000000000 --- a/modules/free/src/main/scala/doobie/free/sqlinput.scala +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.Reader -import java.math.BigDecimal -import java.net.URL -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.Clob -import java.sql.Date -import java.sql.NClob -import java.sql.Ref -import java.sql.RowId -import java.sql.SQLInput -import java.sql.SQLXML -import java.sql.Time -import java.sql.Timestamp -import scala.concurrent.duration.FiniteDuration - -object sqlinput { module => - - // Algebra of operations for SQLInput. Each accepts a visitor as an alternative to pattern-matching. - sealed trait SQLInputOp[A] { - def visit[F[_]](v: SQLInputOp.Visitor[F]): F[A] - } - - // Free monad over SQLInputOp. - type SQLInputIO[A] = FF[SQLInputOp, A] - - // Module of instances and constructors of SQLInputOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object SQLInputOp { - - // Given a SQLInput we can embed a SQLInputIO program in any algebra that understands embedding. - implicit val SQLInputOpEmbeddable: Embeddable[SQLInputOp, SQLInput] = - new Embeddable[SQLInputOp, SQLInput] { - def embed[A](j: SQLInput, fa: FF[SQLInputOp, A]) = Embedded.SQLInput(j, fa) - } - - // Interface for a natural transformation SQLInputOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (SQLInputOp ~> F) { - final def apply[A](fa: SQLInputOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: SQLInput => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: SQLInputIO[A])(f: Throwable => SQLInputIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: SQLInputIO[A])(fb: SQLInputIO[B]): F[B] - def uncancelable[A](body: Poll[SQLInputIO] => SQLInputIO[A]): F[A] - def poll[A](poll: Any, fa: SQLInputIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: SQLInputIO[A], fin: SQLInputIO[Unit]): F[A] - - // SQLInput - def readArray: F[SqlArray] - def readAsciiStream: F[InputStream] - def readBigDecimal: F[BigDecimal] - def readBinaryStream: F[InputStream] - def readBlob: F[Blob] - def readBoolean: F[Boolean] - def readByte: F[Byte] - def readBytes: F[Array[Byte]] - def readCharacterStream: F[Reader] - def readClob: F[Clob] - def readDate: F[Date] - def readDouble: F[Double] - def readFloat: F[Float] - def readInt: F[Int] - def readLong: F[Long] - def readNClob: F[NClob] - def readNString: F[String] - def readObject: F[AnyRef] - def readObject[T](a: Class[T]): F[T] - def readRef: F[Ref] - def readRowId: F[RowId] - def readSQLXML: F[SQLXML] - def readShort: F[Short] - def readString: F[String] - def readTime: F[Time] - def readTimestamp: F[Timestamp] - def readURL: F[URL] - def wasNull: F[Boolean] - - } - - // Common operations for all algebras. - final case class Raw[A](f: SQLInput => A) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: SQLInputIO[A], f: Throwable => SQLInputIO[A]) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends SQLInputOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends SQLInputOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: SQLInputIO[A], fb: SQLInputIO[B]) extends SQLInputOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[SQLInputIO] => SQLInputIO[A]) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: SQLInputIO[A]) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends SQLInputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: SQLInputIO[A], fin: SQLInputIO[Unit]) extends SQLInputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // SQLInput-specific operations. - case object ReadArray extends SQLInputOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.readArray - } - case object ReadAsciiStream extends SQLInputOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.readAsciiStream - } - case object ReadBigDecimal extends SQLInputOp[BigDecimal] { - def visit[F[_]](v: Visitor[F]) = v.readBigDecimal - } - case object ReadBinaryStream extends SQLInputOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.readBinaryStream - } - case object ReadBlob extends SQLInputOp[Blob] { - def visit[F[_]](v: Visitor[F]) = v.readBlob - } - case object ReadBoolean extends SQLInputOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.readBoolean - } - case object ReadByte extends SQLInputOp[Byte] { - def visit[F[_]](v: Visitor[F]) = v.readByte - } - case object ReadBytes extends SQLInputOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.readBytes - } - case object ReadCharacterStream extends SQLInputOp[Reader] { - def visit[F[_]](v: Visitor[F]) = v.readCharacterStream - } - case object ReadClob extends SQLInputOp[Clob] { - def visit[F[_]](v: Visitor[F]) = v.readClob - } - case object ReadDate extends SQLInputOp[Date] { - def visit[F[_]](v: Visitor[F]) = v.readDate - } - case object ReadDouble extends SQLInputOp[Double] { - def visit[F[_]](v: Visitor[F]) = v.readDouble - } - case object ReadFloat extends SQLInputOp[Float] { - def visit[F[_]](v: Visitor[F]) = v.readFloat - } - case object ReadInt extends SQLInputOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.readInt - } - case object ReadLong extends SQLInputOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.readLong - } - case object ReadNClob extends SQLInputOp[NClob] { - def visit[F[_]](v: Visitor[F]) = v.readNClob - } - case object ReadNString extends SQLInputOp[String] { - def visit[F[_]](v: Visitor[F]) = v.readNString - } - case object ReadObject extends SQLInputOp[AnyRef] { - def visit[F[_]](v: Visitor[F]) = v.readObject - } - final case class ReadObject1[T](a: Class[T]) extends SQLInputOp[T] { - def visit[F[_]](v: Visitor[F]) = v.readObject(a) - } - case object ReadRef extends SQLInputOp[Ref] { - def visit[F[_]](v: Visitor[F]) = v.readRef - } - case object ReadRowId extends SQLInputOp[RowId] { - def visit[F[_]](v: Visitor[F]) = v.readRowId - } - case object ReadSQLXML extends SQLInputOp[SQLXML] { - def visit[F[_]](v: Visitor[F]) = v.readSQLXML - } - case object ReadShort extends SQLInputOp[Short] { - def visit[F[_]](v: Visitor[F]) = v.readShort - } - case object ReadString extends SQLInputOp[String] { - def visit[F[_]](v: Visitor[F]) = v.readString - } - case object ReadTime extends SQLInputOp[Time] { - def visit[F[_]](v: Visitor[F]) = v.readTime - } - case object ReadTimestamp extends SQLInputOp[Timestamp] { - def visit[F[_]](v: Visitor[F]) = v.readTimestamp - } - case object ReadURL extends SQLInputOp[URL] { - def visit[F[_]](v: Visitor[F]) = v.readURL - } - case object WasNull extends SQLInputOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.wasNull - } - - } - import SQLInputOp.* - - // Smart constructors for operations common to all algebras. - val unit: SQLInputIO[Unit] = FF.pure[SQLInputOp, Unit](()) - def pure[A](a: A): SQLInputIO[A] = FF.pure[SQLInputOp, A](a) - def raw[A](f: SQLInput => A): SQLInputIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[SQLInputOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): SQLInputIO[A] = FF.liftF[SQLInputOp, A](RaiseError(err)) - def handleErrorWith[A](fa: SQLInputIO[A])(f: Throwable => SQLInputIO[A]): SQLInputIO[A] = - FF.liftF[SQLInputOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[SQLInputOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[SQLInputOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[SQLInputOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[SQLInputOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: SQLInputIO[A])(fb: SQLInputIO[B]) = FF.liftF[SQLInputOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[SQLInputIO] => SQLInputIO[A]) = FF.liftF[SQLInputOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[SQLInputIO] { - def apply[A](fa: SQLInputIO[A]) = FF.liftF[SQLInputOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[SQLInputOp, Unit](Canceled) - def onCancel[A](fa: SQLInputIO[A], fin: SQLInputIO[Unit]) = FF.liftF[SQLInputOp, A](OnCancel(fa, fin)) - - // Smart constructors for SQLInput-specific operations. - val readArray: SQLInputIO[SqlArray] = FF.liftF(ReadArray) - val readAsciiStream: SQLInputIO[InputStream] = FF.liftF(ReadAsciiStream) - val readBigDecimal: SQLInputIO[BigDecimal] = FF.liftF(ReadBigDecimal) - val readBinaryStream: SQLInputIO[InputStream] = FF.liftF(ReadBinaryStream) - val readBlob: SQLInputIO[Blob] = FF.liftF(ReadBlob) - val readBoolean: SQLInputIO[Boolean] = FF.liftF(ReadBoolean) - val readByte: SQLInputIO[Byte] = FF.liftF(ReadByte) - val readBytes: SQLInputIO[Array[Byte]] = FF.liftF(ReadBytes) - val readCharacterStream: SQLInputIO[Reader] = FF.liftF(ReadCharacterStream) - val readClob: SQLInputIO[Clob] = FF.liftF(ReadClob) - val readDate: SQLInputIO[Date] = FF.liftF(ReadDate) - val readDouble: SQLInputIO[Double] = FF.liftF(ReadDouble) - val readFloat: SQLInputIO[Float] = FF.liftF(ReadFloat) - val readInt: SQLInputIO[Int] = FF.liftF(ReadInt) - val readLong: SQLInputIO[Long] = FF.liftF(ReadLong) - val readNClob: SQLInputIO[NClob] = FF.liftF(ReadNClob) - val readNString: SQLInputIO[String] = FF.liftF(ReadNString) - val readObject: SQLInputIO[AnyRef] = FF.liftF(ReadObject) - def readObject[T](a: Class[T]): SQLInputIO[T] = FF.liftF(ReadObject1(a)) - val readRef: SQLInputIO[Ref] = FF.liftF(ReadRef) - val readRowId: SQLInputIO[RowId] = FF.liftF(ReadRowId) - val readSQLXML: SQLInputIO[SQLXML] = FF.liftF(ReadSQLXML) - val readShort: SQLInputIO[Short] = FF.liftF(ReadShort) - val readString: SQLInputIO[String] = FF.liftF(ReadString) - val readTime: SQLInputIO[Time] = FF.liftF(ReadTime) - val readTimestamp: SQLInputIO[Timestamp] = FF.liftF(ReadTimestamp) - val readURL: SQLInputIO[URL] = FF.liftF(ReadURL) - val wasNull: SQLInputIO[Boolean] = FF.liftF(WasNull) - - private val monad = FF.catsFreeMonadForFree[SQLInputOp] - - // Typeclass instances for SQLInputIO - implicit val SyncSQLInputIO: Sync[SQLInputIO] = - new Sync[SQLInputIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): SQLInputIO[A] = monad.pure(x) - override def map[A, B](fa: SQLInputIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: SQLInputIO[A])(f: A => SQLInputIO[B]): SQLInputIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => SQLInputIO[Either[A, B]]): SQLInputIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): SQLInputIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: SQLInputIO[A])(f: Throwable => SQLInputIO[A]): SQLInputIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: SQLInputIO[FiniteDuration] = module.monotonic - override def realTime: SQLInputIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): SQLInputIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: SQLInputIO[A])(fb: SQLInputIO[B]): SQLInputIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[SQLInputIO] => SQLInputIO[A]): SQLInputIO[A] = module.uncancelable(body) - override def canceled: SQLInputIO[Unit] = module.canceled - override def onCancel[A](fa: SQLInputIO[A], fin: SQLInputIO[Unit]): SQLInputIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidSQLInputIO[A](implicit M: Monoid[A]): Monoid[SQLInputIO[A]] = - new Monoid[SQLInputIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: SQLInputIO[A], y: SQLInputIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/sqloutput.scala b/modules/free/src/main/scala/doobie/free/sqloutput.scala deleted file mode 100644 index 0bec4dd26..000000000 --- a/modules/free/src/main/scala/doobie/free/sqloutput.scala +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.io.InputStream -import java.io.Reader -import java.math.BigDecimal -import java.net.URL -import java.sql.Array as SqlArray -import java.sql.Blob -import java.sql.Clob -import java.sql.Date -import java.sql.NClob -import java.sql.Ref -import java.sql.RowId -import java.sql.SQLData -import java.sql.SQLOutput -import java.sql.SQLType -import java.sql.SQLXML -import java.sql.Struct -import java.sql.Time -import java.sql.Timestamp -import scala.concurrent.duration.FiniteDuration - -object sqloutput { module => - - // Algebra of operations for SQLOutput. Each accepts a visitor as an alternative to pattern-matching. - sealed trait SQLOutputOp[A] { - def visit[F[_]](v: SQLOutputOp.Visitor[F]): F[A] - } - - // Free monad over SQLOutputOp. - type SQLOutputIO[A] = FF[SQLOutputOp, A] - - // Module of instances and constructors of SQLOutputOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object SQLOutputOp { - - // Given a SQLOutput we can embed a SQLOutputIO program in any algebra that understands embedding. - implicit val SQLOutputOpEmbeddable: Embeddable[SQLOutputOp, SQLOutput] = - new Embeddable[SQLOutputOp, SQLOutput] { - def embed[A](j: SQLOutput, fa: FF[SQLOutputOp, A]) = Embedded.SQLOutput(j, fa) - } - - // Interface for a natural transformation SQLOutputOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (SQLOutputOp ~> F) { - final def apply[A](fa: SQLOutputOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: SQLOutput => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: SQLOutputIO[A])(f: Throwable => SQLOutputIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: SQLOutputIO[A])(fb: SQLOutputIO[B]): F[B] - def uncancelable[A](body: Poll[SQLOutputIO] => SQLOutputIO[A]): F[A] - def poll[A](poll: Any, fa: SQLOutputIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: SQLOutputIO[A], fin: SQLOutputIO[Unit]): F[A] - - // SQLOutput - def writeArray(a: SqlArray): F[Unit] - def writeAsciiStream(a: InputStream): F[Unit] - def writeBigDecimal(a: BigDecimal): F[Unit] - def writeBinaryStream(a: InputStream): F[Unit] - def writeBlob(a: Blob): F[Unit] - def writeBoolean(a: Boolean): F[Unit] - def writeByte(a: Byte): F[Unit] - def writeBytes(a: Array[Byte]): F[Unit] - def writeCharacterStream(a: Reader): F[Unit] - def writeClob(a: Clob): F[Unit] - def writeDate(a: Date): F[Unit] - def writeDouble(a: Double): F[Unit] - def writeFloat(a: Float): F[Unit] - def writeInt(a: Int): F[Unit] - def writeLong(a: Long): F[Unit] - def writeNClob(a: NClob): F[Unit] - def writeNString(a: String): F[Unit] - def writeObject(a: AnyRef, b: SQLType): F[Unit] - def writeObject(a: SQLData): F[Unit] - def writeRef(a: Ref): F[Unit] - def writeRowId(a: RowId): F[Unit] - def writeSQLXML(a: SQLXML): F[Unit] - def writeShort(a: Short): F[Unit] - def writeString(a: String): F[Unit] - def writeStruct(a: Struct): F[Unit] - def writeTime(a: Time): F[Unit] - def writeTimestamp(a: Timestamp): F[Unit] - def writeURL(a: URL): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: SQLOutput => A) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: SQLOutputIO[A], f: Throwable => SQLOutputIO[A]) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends SQLOutputOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends SQLOutputOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: SQLOutputIO[A], fb: SQLOutputIO[B]) extends SQLOutputOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[SQLOutputIO] => SQLOutputIO[A]) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: SQLOutputIO[A]) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: SQLOutputIO[A], fin: SQLOutputIO[Unit]) extends SQLOutputOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // SQLOutput-specific operations. - final case class WriteArray(a: SqlArray) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeArray(a) - } - final case class WriteAsciiStream(a: InputStream) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeAsciiStream(a) - } - final case class WriteBigDecimal(a: BigDecimal) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeBigDecimal(a) - } - final case class WriteBinaryStream(a: InputStream) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeBinaryStream(a) - } - final case class WriteBlob(a: Blob) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeBlob(a) - } - final case class WriteBoolean(a: Boolean) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeBoolean(a) - } - final case class WriteByte(a: Byte) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeByte(a) - } - final case class WriteBytes(a: Array[Byte]) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeBytes(a) - } - final case class WriteCharacterStream(a: Reader) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeCharacterStream(a) - } - final case class WriteClob(a: Clob) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeClob(a) - } - final case class WriteDate(a: Date) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeDate(a) - } - final case class WriteDouble(a: Double) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeDouble(a) - } - final case class WriteFloat(a: Float) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeFloat(a) - } - final case class WriteInt(a: Int) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeInt(a) - } - final case class WriteLong(a: Long) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeLong(a) - } - final case class WriteNClob(a: NClob) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeNClob(a) - } - final case class WriteNString(a: String) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeNString(a) - } - final case class WriteObject(a: AnyRef, b: SQLType) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeObject(a, b) - } - final case class WriteObject1(a: SQLData) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeObject(a) - } - final case class WriteRef(a: Ref) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeRef(a) - } - final case class WriteRowId(a: RowId) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeRowId(a) - } - final case class WriteSQLXML(a: SQLXML) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeSQLXML(a) - } - final case class WriteShort(a: Short) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeShort(a) - } - final case class WriteString(a: String) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeString(a) - } - final case class WriteStruct(a: Struct) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeStruct(a) - } - final case class WriteTime(a: Time) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeTime(a) - } - final case class WriteTimestamp(a: Timestamp) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeTimestamp(a) - } - final case class WriteURL(a: URL) extends SQLOutputOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeURL(a) - } - - } - import SQLOutputOp.* - - // Smart constructors for operations common to all algebras. - val unit: SQLOutputIO[Unit] = FF.pure[SQLOutputOp, Unit](()) - def pure[A](a: A): SQLOutputIO[A] = FF.pure[SQLOutputOp, A](a) - def raw[A](f: SQLOutput => A): SQLOutputIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[SQLOutputOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): SQLOutputIO[A] = FF.liftF[SQLOutputOp, A](RaiseError(err)) - def handleErrorWith[A](fa: SQLOutputIO[A])(f: Throwable => SQLOutputIO[A]): SQLOutputIO[A] = - FF.liftF[SQLOutputOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[SQLOutputOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[SQLOutputOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[SQLOutputOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[SQLOutputOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: SQLOutputIO[A])(fb: SQLOutputIO[B]) = FF.liftF[SQLOutputOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[SQLOutputIO] => SQLOutputIO[A]) = FF.liftF[SQLOutputOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[SQLOutputIO] { - def apply[A](fa: SQLOutputIO[A]) = FF.liftF[SQLOutputOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[SQLOutputOp, Unit](Canceled) - def onCancel[A](fa: SQLOutputIO[A], fin: SQLOutputIO[Unit]) = FF.liftF[SQLOutputOp, A](OnCancel(fa, fin)) - - // Smart constructors for SQLOutput-specific operations. - def writeArray(a: SqlArray): SQLOutputIO[Unit] = FF.liftF(WriteArray(a)) - def writeAsciiStream(a: InputStream): SQLOutputIO[Unit] = FF.liftF(WriteAsciiStream(a)) - def writeBigDecimal(a: BigDecimal): SQLOutputIO[Unit] = FF.liftF(WriteBigDecimal(a)) - def writeBinaryStream(a: InputStream): SQLOutputIO[Unit] = FF.liftF(WriteBinaryStream(a)) - def writeBlob(a: Blob): SQLOutputIO[Unit] = FF.liftF(WriteBlob(a)) - def writeBoolean(a: Boolean): SQLOutputIO[Unit] = FF.liftF(WriteBoolean(a)) - def writeByte(a: Byte): SQLOutputIO[Unit] = FF.liftF(WriteByte(a)) - def writeBytes(a: Array[Byte]): SQLOutputIO[Unit] = FF.liftF(WriteBytes(a)) - def writeCharacterStream(a: Reader): SQLOutputIO[Unit] = FF.liftF(WriteCharacterStream(a)) - def writeClob(a: Clob): SQLOutputIO[Unit] = FF.liftF(WriteClob(a)) - def writeDate(a: Date): SQLOutputIO[Unit] = FF.liftF(WriteDate(a)) - def writeDouble(a: Double): SQLOutputIO[Unit] = FF.liftF(WriteDouble(a)) - def writeFloat(a: Float): SQLOutputIO[Unit] = FF.liftF(WriteFloat(a)) - def writeInt(a: Int): SQLOutputIO[Unit] = FF.liftF(WriteInt(a)) - def writeLong(a: Long): SQLOutputIO[Unit] = FF.liftF(WriteLong(a)) - def writeNClob(a: NClob): SQLOutputIO[Unit] = FF.liftF(WriteNClob(a)) - def writeNString(a: String): SQLOutputIO[Unit] = FF.liftF(WriteNString(a)) - def writeObject(a: AnyRef, b: SQLType): SQLOutputIO[Unit] = FF.liftF(WriteObject(a, b)) - def writeObject(a: SQLData): SQLOutputIO[Unit] = FF.liftF(WriteObject1(a)) - def writeRef(a: Ref): SQLOutputIO[Unit] = FF.liftF(WriteRef(a)) - def writeRowId(a: RowId): SQLOutputIO[Unit] = FF.liftF(WriteRowId(a)) - def writeSQLXML(a: SQLXML): SQLOutputIO[Unit] = FF.liftF(WriteSQLXML(a)) - def writeShort(a: Short): SQLOutputIO[Unit] = FF.liftF(WriteShort(a)) - def writeString(a: String): SQLOutputIO[Unit] = FF.liftF(WriteString(a)) - def writeStruct(a: Struct): SQLOutputIO[Unit] = FF.liftF(WriteStruct(a)) - def writeTime(a: Time): SQLOutputIO[Unit] = FF.liftF(WriteTime(a)) - def writeTimestamp(a: Timestamp): SQLOutputIO[Unit] = FF.liftF(WriteTimestamp(a)) - def writeURL(a: URL): SQLOutputIO[Unit] = FF.liftF(WriteURL(a)) - - private val monad = FF.catsFreeMonadForFree[SQLOutputOp] - - // Typeclass instances for SQLOutputIO - implicit val SyncSQLOutputIO: Sync[SQLOutputIO] = - new Sync[SQLOutputIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): SQLOutputIO[A] = monad.pure(x) - override def map[A, B](fa: SQLOutputIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: SQLOutputIO[A])(f: A => SQLOutputIO[B]): SQLOutputIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => SQLOutputIO[Either[A, B]]): SQLOutputIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): SQLOutputIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: SQLOutputIO[A])(f: Throwable => SQLOutputIO[A]): SQLOutputIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: SQLOutputIO[FiniteDuration] = module.monotonic - override def realTime: SQLOutputIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): SQLOutputIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: SQLOutputIO[A])(fb: SQLOutputIO[B]): SQLOutputIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[SQLOutputIO] => SQLOutputIO[A]): SQLOutputIO[A] = module.uncancelable(body) - override def canceled: SQLOutputIO[Unit] = module.canceled - override def onCancel[A](fa: SQLOutputIO[A], fin: SQLOutputIO[Unit]): SQLOutputIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidSQLOutputIO[A](implicit M: Monoid[A]): Monoid[SQLOutputIO[A]] = - new Monoid[SQLOutputIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: SQLOutputIO[A], y: SQLOutputIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/free/src/main/scala/doobie/free/statement.scala b/modules/free/src/main/scala/doobie/free/statement.scala deleted file mode 100644 index 437f9014d..000000000 --- a/modules/free/src/main/scala/doobie/free/statement.scala +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> - -import java.sql.Connection -import java.sql.ResultSet -import java.sql.SQLWarning -import java.sql.Statement -import scala.concurrent.duration.FiniteDuration - -object statement { module => - - // Algebra of operations for Statement. Each accepts a visitor as an alternative to pattern-matching. - sealed trait StatementOp[A] { - def visit[F[_]](v: StatementOp.Visitor[F]): F[A] - } - - // Free monad over StatementOp. - type StatementIO[A] = FF[StatementOp, A] - - // Module of instances and constructors of StatementOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object StatementOp { - - // Given a Statement we can embed a StatementIO program in any algebra that understands embedding. - implicit val StatementOpEmbeddable: Embeddable[StatementOp, Statement] = - new Embeddable[StatementOp, Statement] { - def embed[A](j: Statement, fa: FF[StatementOp, A]) = Embedded.Statement(j, fa) - } - - // Interface for a natural transformation StatementOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (StatementOp ~> F) { - final def apply[A](fa: StatementOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: Statement => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: StatementIO[A])(f: Throwable => StatementIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: StatementIO[A])(fb: StatementIO[B]): F[B] - def uncancelable[A](body: Poll[StatementIO] => StatementIO[A]): F[A] - def poll[A](poll: Any, fa: StatementIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: StatementIO[A], fin: StatementIO[Unit]): F[A] - - // Statement - def addBatch(a: String): F[Unit] - def cancel: F[Unit] - def clearBatch: F[Unit] - def clearWarnings: F[Unit] - def close: F[Unit] - def closeOnCompletion: F[Unit] - def enquoteIdentifier(a: String, b: Boolean): F[String] - def enquoteLiteral(a: String): F[String] - def enquoteNCharLiteral(a: String): F[String] - def execute(a: String): F[Boolean] - def execute(a: String, b: Array[Int]): F[Boolean] - def execute(a: String, b: Array[String]): F[Boolean] - def execute(a: String, b: Int): F[Boolean] - def executeBatch: F[Array[Int]] - def executeLargeBatch: F[Array[Long]] - def executeLargeUpdate(a: String): F[Long] - def executeLargeUpdate(a: String, b: Array[Int]): F[Long] - def executeLargeUpdate(a: String, b: Array[String]): F[Long] - def executeLargeUpdate(a: String, b: Int): F[Long] - def executeQuery(a: String): F[ResultSet] - def executeUpdate(a: String): F[Int] - def executeUpdate(a: String, b: Array[Int]): F[Int] - def executeUpdate(a: String, b: Array[String]): F[Int] - def executeUpdate(a: String, b: Int): F[Int] - def getConnection: F[Connection] - def getFetchDirection: F[Int] - def getFetchSize: F[Int] - def getGeneratedKeys: F[ResultSet] - def getLargeMaxRows: F[Long] - def getLargeUpdateCount: F[Long] - def getMaxFieldSize: F[Int] - def getMaxRows: F[Int] - def getMoreResults: F[Boolean] - def getMoreResults(a: Int): F[Boolean] - def getQueryTimeout: F[Int] - def getResultSet: F[ResultSet] - def getResultSetConcurrency: F[Int] - def getResultSetHoldability: F[Int] - def getResultSetType: F[Int] - def getUpdateCount: F[Int] - def getWarnings: F[SQLWarning] - def isCloseOnCompletion: F[Boolean] - def isClosed: F[Boolean] - def isPoolable: F[Boolean] - def isSimpleIdentifier(a: String): F[Boolean] - def isWrapperFor(a: Class[?]): F[Boolean] - def setCursorName(a: String): F[Unit] - def setEscapeProcessing(a: Boolean): F[Unit] - def setFetchDirection(a: Int): F[Unit] - def setFetchSize(a: Int): F[Unit] - def setLargeMaxRows(a: Long): F[Unit] - def setMaxFieldSize(a: Int): F[Unit] - def setMaxRows(a: Int): F[Unit] - def setPoolable(a: Boolean): F[Unit] - def setQueryTimeout(a: Int): F[Unit] - def unwrap[T](a: Class[T]): F[T] - - } - - // Common operations for all algebras. - final case class Raw[A](f: Statement => A) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: StatementIO[A], f: Throwable => StatementIO[A]) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends StatementOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends StatementOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: StatementIO[A], fb: StatementIO[B]) extends StatementOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[StatementIO] => StatementIO[A]) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: StatementIO[A]) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: StatementIO[A], fin: StatementIO[Unit]) extends StatementOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // Statement-specific operations. - final case class AddBatch(a: String) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.addBatch(a) - } - case object Cancel extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancel - } - case object ClearBatch extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearBatch - } - case object ClearWarnings extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.clearWarnings - } - case object Close extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.close - } - case object CloseOnCompletion extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.closeOnCompletion - } - final case class EnquoteIdentifier(a: String, b: Boolean) extends StatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteIdentifier(a, b) - } - final case class EnquoteLiteral(a: String) extends StatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteLiteral(a) - } - final case class EnquoteNCharLiteral(a: String) extends StatementOp[String] { - def visit[F[_]](v: Visitor[F]) = v.enquoteNCharLiteral(a) - } - final case class Execute(a: String) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a) - } - final case class Execute1(a: String, b: Array[Int]) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - final case class Execute2(a: String, b: Array[String]) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - final case class Execute3(a: String, b: Int) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.execute(a, b) - } - case object ExecuteBatch extends StatementOp[Array[Int]] { - def visit[F[_]](v: Visitor[F]) = v.executeBatch - } - case object ExecuteLargeBatch extends StatementOp[Array[Long]] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeBatch - } - final case class ExecuteLargeUpdate(a: String) extends StatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a) - } - final case class ExecuteLargeUpdate1(a: String, b: Array[Int]) extends StatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteLargeUpdate2(a: String, b: Array[String]) extends StatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteLargeUpdate3(a: String, b: Int) extends StatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.executeLargeUpdate(a, b) - } - final case class ExecuteQuery(a: String) extends StatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.executeQuery(a) - } - final case class ExecuteUpdate(a: String) extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a) - } - final case class ExecuteUpdate1(a: String, b: Array[Int]) extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class ExecuteUpdate2(a: String, b: Array[String]) extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - final case class ExecuteUpdate3(a: String, b: Int) extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.executeUpdate(a, b) - } - case object GetConnection extends StatementOp[Connection] { - def visit[F[_]](v: Visitor[F]) = v.getConnection - } - case object GetFetchDirection extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchDirection - } - case object GetFetchSize extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFetchSize - } - case object GetGeneratedKeys extends StatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getGeneratedKeys - } - case object GetLargeMaxRows extends StatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLargeMaxRows - } - case object GetLargeUpdateCount extends StatementOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLargeUpdateCount - } - case object GetMaxFieldSize extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxFieldSize - } - case object GetMaxRows extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getMaxRows - } - case object GetMoreResults extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getMoreResults - } - final case class GetMoreResults1(a: Int) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getMoreResults(a) - } - case object GetQueryTimeout extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getQueryTimeout - } - case object GetResultSet extends StatementOp[ResultSet] { - def visit[F[_]](v: Visitor[F]) = v.getResultSet - } - case object GetResultSetConcurrency extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetConcurrency - } - case object GetResultSetHoldability extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetHoldability - } - case object GetResultSetType extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getResultSetType - } - case object GetUpdateCount extends StatementOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getUpdateCount - } - case object GetWarnings extends StatementOp[SQLWarning] { - def visit[F[_]](v: Visitor[F]) = v.getWarnings - } - case object IsCloseOnCompletion extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isCloseOnCompletion - } - case object IsClosed extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isClosed - } - case object IsPoolable extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isPoolable - } - final case class IsSimpleIdentifier(a: String) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isSimpleIdentifier(a) - } - final case class IsWrapperFor(a: Class[?]) extends StatementOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isWrapperFor(a) - } - final case class SetCursorName(a: String) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setCursorName(a) - } - final case class SetEscapeProcessing(a: Boolean) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setEscapeProcessing(a) - } - final case class SetFetchDirection(a: Int) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchDirection(a) - } - final case class SetFetchSize(a: Int) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setFetchSize(a) - } - final case class SetLargeMaxRows(a: Long) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setLargeMaxRows(a) - } - final case class SetMaxFieldSize(a: Int) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setMaxFieldSize(a) - } - final case class SetMaxRows(a: Int) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setMaxRows(a) - } - final case class SetPoolable(a: Boolean) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setPoolable(a) - } - final case class SetQueryTimeout(a: Int) extends StatementOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setQueryTimeout(a) - } - final case class Unwrap[T](a: Class[T]) extends StatementOp[T] { - def visit[F[_]](v: Visitor[F]) = v.unwrap(a) - } - - } - import StatementOp.* - - // Smart constructors for operations common to all algebras. - val unit: StatementIO[Unit] = FF.pure[StatementOp, Unit](()) - def pure[A](a: A): StatementIO[A] = FF.pure[StatementOp, A](a) - def raw[A](f: Statement => A): StatementIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[StatementOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): StatementIO[A] = FF.liftF[StatementOp, A](RaiseError(err)) - def handleErrorWith[A](fa: StatementIO[A])(f: Throwable => StatementIO[A]): StatementIO[A] = - FF.liftF[StatementOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[StatementOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[StatementOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[StatementOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[StatementOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: StatementIO[A])(fb: StatementIO[B]) = FF.liftF[StatementOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[StatementIO] => StatementIO[A]) = FF.liftF[StatementOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[StatementIO] { - def apply[A](fa: StatementIO[A]) = FF.liftF[StatementOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[StatementOp, Unit](Canceled) - def onCancel[A](fa: StatementIO[A], fin: StatementIO[Unit]) = FF.liftF[StatementOp, A](OnCancel(fa, fin)) - - // Smart constructors for Statement-specific operations. - def addBatch(a: String): StatementIO[Unit] = FF.liftF(AddBatch(a)) - val cancel: StatementIO[Unit] = FF.liftF(Cancel) - val clearBatch: StatementIO[Unit] = FF.liftF(ClearBatch) - val clearWarnings: StatementIO[Unit] = FF.liftF(ClearWarnings) - val close: StatementIO[Unit] = FF.liftF(Close) - val closeOnCompletion: StatementIO[Unit] = FF.liftF(CloseOnCompletion) - def enquoteIdentifier(a: String, b: Boolean): StatementIO[String] = FF.liftF(EnquoteIdentifier(a, b)) - def enquoteLiteral(a: String): StatementIO[String] = FF.liftF(EnquoteLiteral(a)) - def enquoteNCharLiteral(a: String): StatementIO[String] = FF.liftF(EnquoteNCharLiteral(a)) - def execute(a: String): StatementIO[Boolean] = FF.liftF(Execute(a)) - def execute(a: String, b: Array[Int]): StatementIO[Boolean] = FF.liftF(Execute1(a, b)) - def execute(a: String, b: Array[String]): StatementIO[Boolean] = FF.liftF(Execute2(a, b)) - def execute(a: String, b: Int): StatementIO[Boolean] = FF.liftF(Execute3(a, b)) - val executeBatch: StatementIO[Array[Int]] = FF.liftF(ExecuteBatch) - val executeLargeBatch: StatementIO[Array[Long]] = FF.liftF(ExecuteLargeBatch) - def executeLargeUpdate(a: String): StatementIO[Long] = FF.liftF(ExecuteLargeUpdate(a)) - def executeLargeUpdate(a: String, b: Array[Int]): StatementIO[Long] = FF.liftF(ExecuteLargeUpdate1(a, b)) - def executeLargeUpdate(a: String, b: Array[String]): StatementIO[Long] = FF.liftF(ExecuteLargeUpdate2(a, b)) - def executeLargeUpdate(a: String, b: Int): StatementIO[Long] = FF.liftF(ExecuteLargeUpdate3(a, b)) - def executeQuery(a: String): StatementIO[ResultSet] = FF.liftF(ExecuteQuery(a)) - def executeUpdate(a: String): StatementIO[Int] = FF.liftF(ExecuteUpdate(a)) - def executeUpdate(a: String, b: Array[Int]): StatementIO[Int] = FF.liftF(ExecuteUpdate1(a, b)) - def executeUpdate(a: String, b: Array[String]): StatementIO[Int] = FF.liftF(ExecuteUpdate2(a, b)) - def executeUpdate(a: String, b: Int): StatementIO[Int] = FF.liftF(ExecuteUpdate3(a, b)) - val getConnection: StatementIO[Connection] = FF.liftF(GetConnection) - val getFetchDirection: StatementIO[Int] = FF.liftF(GetFetchDirection) - val getFetchSize: StatementIO[Int] = FF.liftF(GetFetchSize) - val getGeneratedKeys: StatementIO[ResultSet] = FF.liftF(GetGeneratedKeys) - val getLargeMaxRows: StatementIO[Long] = FF.liftF(GetLargeMaxRows) - val getLargeUpdateCount: StatementIO[Long] = FF.liftF(GetLargeUpdateCount) - val getMaxFieldSize: StatementIO[Int] = FF.liftF(GetMaxFieldSize) - val getMaxRows: StatementIO[Int] = FF.liftF(GetMaxRows) - val getMoreResults: StatementIO[Boolean] = FF.liftF(GetMoreResults) - def getMoreResults(a: Int): StatementIO[Boolean] = FF.liftF(GetMoreResults1(a)) - val getQueryTimeout: StatementIO[Int] = FF.liftF(GetQueryTimeout) - val getResultSet: StatementIO[ResultSet] = FF.liftF(GetResultSet) - val getResultSetConcurrency: StatementIO[Int] = FF.liftF(GetResultSetConcurrency) - val getResultSetHoldability: StatementIO[Int] = FF.liftF(GetResultSetHoldability) - val getResultSetType: StatementIO[Int] = FF.liftF(GetResultSetType) - val getUpdateCount: StatementIO[Int] = FF.liftF(GetUpdateCount) - val getWarnings: StatementIO[SQLWarning] = FF.liftF(GetWarnings) - val isCloseOnCompletion: StatementIO[Boolean] = FF.liftF(IsCloseOnCompletion) - val isClosed: StatementIO[Boolean] = FF.liftF(IsClosed) - val isPoolable: StatementIO[Boolean] = FF.liftF(IsPoolable) - def isSimpleIdentifier(a: String): StatementIO[Boolean] = FF.liftF(IsSimpleIdentifier(a)) - def isWrapperFor(a: Class[?]): StatementIO[Boolean] = FF.liftF(IsWrapperFor(a)) - def setCursorName(a: String): StatementIO[Unit] = FF.liftF(SetCursorName(a)) - def setEscapeProcessing(a: Boolean): StatementIO[Unit] = FF.liftF(SetEscapeProcessing(a)) - def setFetchDirection(a: Int): StatementIO[Unit] = FF.liftF(SetFetchDirection(a)) - def setFetchSize(a: Int): StatementIO[Unit] = FF.liftF(SetFetchSize(a)) - def setLargeMaxRows(a: Long): StatementIO[Unit] = FF.liftF(SetLargeMaxRows(a)) - def setMaxFieldSize(a: Int): StatementIO[Unit] = FF.liftF(SetMaxFieldSize(a)) - def setMaxRows(a: Int): StatementIO[Unit] = FF.liftF(SetMaxRows(a)) - def setPoolable(a: Boolean): StatementIO[Unit] = FF.liftF(SetPoolable(a)) - def setQueryTimeout(a: Int): StatementIO[Unit] = FF.liftF(SetQueryTimeout(a)) - def unwrap[T](a: Class[T]): StatementIO[T] = FF.liftF(Unwrap(a)) - - private val monad = FF.catsFreeMonadForFree[StatementOp] - - // Typeclass instances for StatementIO - implicit val SyncStatementIO: Sync[StatementIO] = - new Sync[StatementIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): StatementIO[A] = monad.pure(x) - override def map[A, B](fa: StatementIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: StatementIO[A])(f: A => StatementIO[B]): StatementIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => StatementIO[Either[A, B]]): StatementIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): StatementIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: StatementIO[A])(f: Throwable => StatementIO[A]): StatementIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: StatementIO[FiniteDuration] = module.monotonic - override def realTime: StatementIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): StatementIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: StatementIO[A])(fb: StatementIO[B]): StatementIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[StatementIO] => StatementIO[A]): StatementIO[A] = module.uncancelable(body) - override def canceled: StatementIO[Unit] = module.canceled - override def onCancel[A](fa: StatementIO[A], fin: StatementIO[Unit]): StatementIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidStatementIO[A](implicit M: Monoid[A]): Monoid[StatementIO[A]] = - new Monoid[StatementIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: StatementIO[A], y: StatementIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/h2/src/main/scala/doobie/h2/H2Helper.scala b/modules/h2/src/main/scala/doobie/h2/H2Helper.scala index 7f614b934..dc9299bf3 100644 --- a/modules/h2/src/main/scala/doobie/h2/H2Helper.scala +++ b/modules/h2/src/main/scala/doobie/h2/H2Helper.scala @@ -7,7 +7,6 @@ package doobie.h2 import cats.effect.kernel.Resource import cats.effect.kernel.Sync import cats.syntax.show.* -import doobie.free.KleisliInterpreter import doobie.util.transactor.Strategy import doobie.util.transactor.Transactor import org.h2.jdbcx.JdbcConnectionPool @@ -34,14 +33,14 @@ object H2Helper { } val conn = Resource.fromAutoCloseable(M.blocking { driver.connect(url, props) }) - shutdownDatabase(conn).map(_ => createTransactor(conn, strategy)) + shutdownDatabase(conn).map(_ => Transactor.catsEffect((), conn, strategy)) } def inMemoryPooled[M[_]]( database: String, maxConnections: Int = 10, strategy: Strategy = Strategy.default, - )(implicit M: Sync[M]): Resource[M, Transactor[M]] = { + )(implicit M: Sync[M]): Resource[M, Transactor.Aux[M, JdbcConnectionPool]] = { def createPool = { val pool = JdbcConnectionPool.create(jdbcUrl(database), "sa", "") @@ -53,7 +52,7 @@ object H2Helper { pool <- Resource.make(M.delay(createPool)) { pool => M.delay(pool.dispose()) } conn = Resource.fromAutoCloseable(M.blocking { pool.getConnection }) _ <- shutdownDatabase(conn) - } yield createTransactor(conn, strategy) + } yield Transactor.catsEffect(pool, conn, strategy) } private def jdbcUrl(database: String) = show"jdbc:h2:mem:$database" @@ -63,8 +62,4 @@ object H2Helper { conn } - private def createTransactor[M[_]](conn: Resource[M, Connection], strategy: Strategy)(implicit M: Sync[M]) = { - Transactor[M, Unit]((), _ => conn, KleisliInterpreter[M].ConnectionInterpreter, strategy) - } - } diff --git a/modules/h2/src/main/scala/doobie/h2/H2Transactor.scala b/modules/h2/src/main/scala/doobie/h2/H2Transactor.scala index c25af0b43..9a9048016 100644 --- a/modules/h2/src/main/scala/doobie/h2/H2Transactor.scala +++ b/modules/h2/src/main/scala/doobie/h2/H2Transactor.scala @@ -4,25 +4,25 @@ package doobie.h2 -import cats.effect.kernel.Async import cats.effect.kernel.Resource +import cats.effect.kernel.Sync import doobie.util.transactor.Transactor import org.h2.jdbcx.JdbcConnectionPool -import scala.concurrent.ExecutionContext - object H2Transactor { /** Resource yielding a new H2Transactor. */ - def newH2Transactor[M[_]: Async]( + def newH2Transactor[M[_]]( url: String, user: String, pass: String, - connectEC: ExecutionContext, - ): Resource[M, H2Transactor[M]] = { - val alloc = Async[M].delay(JdbcConnectionPool.create(url, user, pass)) - val free = (ds: JdbcConnectionPool) => Async[M].delay(ds.dispose()) - Resource.make(alloc)(free).map(Transactor.fromDataSource[M](_, connectEC)) + )(implicit M: Sync[M]): Resource[M, H2Transactor[M]] = { + val alloc = M.delay(JdbcConnectionPool.create(url, user, pass)) + val free = (ds: JdbcConnectionPool) => M.delay(ds.dispose()) + Resource.make(alloc)(free).map { pool => + val connect = Resource.fromAutoCloseable(M.blocking(pool.getConnection)) + Transactor.catsEffect(pool, connect) + } } } diff --git a/modules/h2/src/main/scala/doobie/h2/package.scala b/modules/h2/src/main/scala/doobie/h2/package.scala index 80351d575..a7843b4d0 100644 --- a/modules/h2/src/main/scala/doobie/h2/package.scala +++ b/modules/h2/src/main/scala/doobie/h2/package.scala @@ -4,8 +4,8 @@ package doobie -import cats.effect.kernel.Async import cats.effect.kernel.Resource +import cats.effect.kernel.Sync import doobie.util.transactor.Strategy import doobie.util.transactor.Transactor import org.h2.jdbcx.JdbcConnectionPool @@ -21,6 +21,6 @@ package object h2 { def inMemory[M[_]]( database: String, strategy: Strategy = Strategy.default, - )(implicit M: Async[M]): Resource[M, Transactor[M]] = H2Helper.inMemory(database, strategy) + )(implicit M: Sync[M]): Resource[M, Transactor[M]] = H2Helper.inMemory(database, strategy) } diff --git a/modules/h2/src/test/scala/doobie/h2/H2DatabaseSpec.scala b/modules/h2/src/test/scala/doobie/h2/H2DatabaseSpec.scala index cf4acfb7d..c7b3c1b4f 100644 --- a/modules/h2/src/test/scala/doobie/h2/H2DatabaseSpec.scala +++ b/modules/h2/src/test/scala/doobie/h2/H2DatabaseSpec.scala @@ -12,10 +12,9 @@ import zio.test.TestAspect import zio.test.ZIOSpec abstract class BaseH2DatabaseSpec extends ZIOSpec[Transactor[Task]] { self => - protected implicit val instance: Sync[Task] = H2DatabaseSpec.instance def transact[A](io: ConnectionIO[A]): ZIO[Transactor[Task], Throwable, A] = { - ZIO.serviceWithZIO[Transactor[Task]](_.trans(instance)(io)) + ZIO.serviceWithZIO[Transactor[Task]](_.run(io)) } implicit class ConnectionIOExtension[A](c: ConnectionIO[A]) { diff --git a/modules/hikari/src/main/scala/doobie/hikari/Config.scala b/modules/hikari/src/main/scala/doobie/hikari/Config.scala deleted file mode 100644 index 5fcea104b..000000000 --- a/modules/hikari/src/main/scala/doobie/hikari/Config.scala +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.hikari - -import cats.effect.kernel.Sync -import cats.syntax.show.* -import com.zaxxer.hikari.HikariConfig -import com.zaxxer.hikari.metrics.MetricsTrackerFactory -import doobie.enumerated.TransactionIsolation - -import java.util.Properties -import java.util.concurrent.ScheduledExecutorService -import java.util.concurrent.ThreadFactory -import java.util.concurrent.TimeUnit -import javax.sql.DataSource -import scala.concurrent.duration.Duration - -/** - * Configuration case class, susceptible to PureConfig. Helps with creating - * `com.zaxxer.hikari.HikariConfig`, which in turn is used to create - * `doobie.hikari.HikariTransactor`. See the method - * `HikariTransactor.fromConfigAutoEc` - */ -final case class Config( - jdbcUrl: String, - catalog: Option[String] = None, - connectionTimeout: Duration = Duration(30, TimeUnit.SECONDS), - idleTimeout: Duration = Duration(10, TimeUnit.MINUTES), - leakDetectionThreshold: Duration = Duration.Zero, - maximumPoolSize: Int = 10, - maxLifetime: Duration = Duration(30, TimeUnit.MINUTES), - minimumIdle: Int = 10, - password: Option[String] = None, - poolName: Option[String] = None, - username: Option[String] = None, - validationTimeout: Duration = Duration(5, TimeUnit.SECONDS), - allowPoolSuspension: Boolean = false, - autoCommit: Boolean = true, - connectionInitSql: Option[String] = None, - connectionTestQuery: Option[String] = None, - dataSourceClassName: Option[String] = None, - dataSourceJNDI: Option[String] = None, - driverClassName: Option[String] = None, - initializationFailTimeout: Duration = Duration(1, TimeUnit.MILLISECONDS), - isolateInternalQueries: Boolean = false, - readOnly: Boolean = false, - registerMbeans: Boolean = false, - schema: Option[String] = None, - transactionIsolation: Option[TransactionIsolation] = None, -) - -object Config { - def makeHikariConfig[F[_]]( - config: Config, - dataSource: Option[DataSource] = None, - dataSourceProperties: Option[Properties] = None, - healthCheckProperties: Option[Properties] = None, - healthCheckRegistry: Option[Object] = None, - metricRegistry: Option[Object] = None, - metricsTrackerFactory: Option[MetricsTrackerFactory] = None, - scheduledExecutor: Option[ScheduledExecutorService] = None, - threadFactory: Option[ThreadFactory] = None, - )(implicit F: Sync[F]): F[HikariConfig] = - F.delay { - val c = new HikariConfig() - - c.setJdbcUrl(config.jdbcUrl) - - config.catalog.foreach(c.setCatalog) - c.setConnectionTimeout(config.connectionTimeout.toMillis) - c.setIdleTimeout(config.idleTimeout.toMillis) - c.setLeakDetectionThreshold(config.leakDetectionThreshold.toMillis) - c.setMaximumPoolSize(config.maximumPoolSize) - c.setMaxLifetime(config.maxLifetime.toMillis) - c.setMinimumIdle(config.minimumIdle) - config.password.foreach(c.setPassword) - config.poolName.foreach(c.setPoolName) - config.username.foreach(c.setUsername) - c.setValidationTimeout(config.validationTimeout.toMillis) - - c.setAllowPoolSuspension(config.allowPoolSuspension) - c.setAutoCommit(config.autoCommit) - config.connectionInitSql.foreach(c.setConnectionInitSql) - config.connectionTestQuery.foreach(c.setConnectionTestQuery) - config.dataSourceClassName.foreach(c.setDataSourceClassName) - config.dataSourceJNDI.foreach(c.setDataSourceJNDI) - config.driverClassName.foreach(c.setDriverClassName) - c.setInitializationFailTimeout(config.initializationFailTimeout.toMillis) - c.setIsolateInternalQueries(config.isolateInternalQueries) - c.setReadOnly(config.readOnly) - c.setRegisterMbeans(config.registerMbeans) - config.schema.foreach(c.setSchema) - config.transactionIsolation.map(_.show).foreach(c.setTransactionIsolation) - - dataSource.foreach(c.setDataSource) - dataSourceProperties.foreach(c.setDataSourceProperties) - healthCheckProperties.foreach(c.setHealthCheckProperties) - healthCheckRegistry.foreach(c.setHealthCheckRegistry) - metricRegistry.foreach(c.setMetricRegistry) - metricsTrackerFactory.foreach(c.setMetricsTrackerFactory) - scheduledExecutor.foreach(c.setScheduledExecutor) - threadFactory.foreach(c.setThreadFactory) - - c - } - -} diff --git a/modules/hikari/src/main/scala/doobie/hikari/HikariTransactor.scala b/modules/hikari/src/main/scala/doobie/hikari/HikariTransactor.scala deleted file mode 100644 index 1fb0c777d..000000000 --- a/modules/hikari/src/main/scala/doobie/hikari/HikariTransactor.scala +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie -package hikari - -import cats.effect.kernel.Async -import cats.effect.kernel.Resource -import cats.effect.kernel.Sync -import cats.effect.syntax.resource.* -import com.zaxxer.hikari.HikariConfig -import com.zaxxer.hikari.HikariDataSource -import com.zaxxer.hikari.metrics.MetricsTrackerFactory -import doobie.util.ExecutionContexts -import doobie.util.transactor.Transactor - -import java.util.Properties -import java.util.concurrent.ScheduledExecutorService -import java.util.concurrent.ThreadFactory -import javax.sql.DataSource -import scala.concurrent.ExecutionContext - -object HikariTransactor { - - /** Construct a `HikariTransactor` from an existing `HikariDatasource`. */ - def apply[M[_]: Async]( - hikariDataSource: HikariDataSource, - connectEC: ExecutionContext, - ): HikariTransactor[M] = - Transactor.fromDataSource[M](hikariDataSource, connectEC) - - /** Resource yielding an unconfigured `HikariTransactor`. */ - def initial[M[_]: Async]( - connectEC: ExecutionContext, - ): Resource[M, HikariTransactor[M]] = { - Resource.fromAutoCloseable(Sync[M].delay(new HikariDataSource)) - .map(Transactor.fromDataSource[M](_, connectEC)) - } - - /** - * Resource yielding a new `HikariTransactor` configured with the given - * Config. Unless you have a good reason, consider using `fromConfig` which - * creates the `connectEC` for you. - */ - def fromConfigCustomEc[M[_]: Async]( - config: Config, - connectEC: ExecutionContext, - dataSource: Option[DataSource] = None, - dataSourceProperties: Option[Properties] = None, - healthCheckProperties: Option[Properties] = None, - healthCheckRegistry: Option[Object] = None, - metricRegistry: Option[Object] = None, - metricsTrackerFactory: Option[MetricsTrackerFactory] = None, - scheduledExecutor: Option[ScheduledExecutorService] = None, - threadFactory: Option[ThreadFactory] = None, - ): Resource[M, HikariTransactor[M]] = { - Resource - .liftK( - Config.makeHikariConfig( - config, - dataSource, - dataSourceProperties, - healthCheckProperties, - healthCheckRegistry, - metricRegistry, - metricsTrackerFactory, - scheduledExecutor, - threadFactory, - ), - ) - .flatMap(fromHikariConfig(_, connectEC)) - } - - /** - * Resource yielding a new `HikariTransactor` configured with the given - * Config. The `connectEC` is created automatically, with the same size as the - * Hikari pool. - */ - def fromConfig[M[_]: Async]( - config: Config, - dataSource: Option[DataSource] = None, - dataSourceProperties: Option[Properties] = None, - healthCheckProperties: Option[Properties] = None, - healthCheckRegistry: Option[Object] = None, - metricRegistry: Option[Object] = None, - metricsTrackerFactory: Option[MetricsTrackerFactory] = None, - scheduledExecutor: Option[ScheduledExecutorService] = None, - threadFactory: Option[ThreadFactory] = None, - ): Resource[M, HikariTransactor[M]] = { - Resource - .liftK( - Config.makeHikariConfig( - config, - dataSource, - dataSourceProperties, - healthCheckProperties, - healthCheckRegistry, - metricRegistry, - metricsTrackerFactory, - scheduledExecutor, - threadFactory, - ), - ) - .flatMap(fromHikariConfig(_)) - } - - /** - * Resource yielding a new `HikariTransactor` configured with the given - * HikariConfig. Unless you have a good reason, consider using the overload - * without explicit `connectEC`, it will be created automatically for you. - */ - def fromHikariConfig[M[_]: Async]( - hikariConfig: HikariConfig, - connectEC: ExecutionContext, - ): Resource[M, HikariTransactor[M]] = Resource - .fromAutoCloseable(Sync[M].delay(new HikariDataSource(hikariConfig))) - .map(Transactor.fromDataSource[M](_, connectEC)) - - /** - * Resource yielding a new `HikariTransactor` configured with the given - * HikariConfig. The `connectEC` is created automatically, with the same size - * as the Hikari pool. - */ - def fromHikariConfig[M[_]: Async](hikariConfig: HikariConfig): Resource[M, HikariTransactor[M]] = - for { - // to populate unset fields with default values, like `maximumPoolSize` - _ <- Sync[M].delay(hikariConfig.validate()).toResource - // Note that the number of JDBC connections is usually limited by the underlying JDBC pool. - // You may therefore want to limit your connection pool to the same size as the underlying JDBC pool - // as any additional threads are guaranteed to be blocked. - // https://tpolecat.github.io/doobie/docs/14-Managing-Connections.html#about-threading - connectEC <- ExecutionContexts.fixedThreadPool(hikariConfig.getMaximumPoolSize) - result <- fromHikariConfig(hikariConfig, connectEC) - } yield result - - /** - * Resource yielding a new `HikariTransactor` configured with the given info. - * Consider using `fromConfig` for better configurability. - */ - def newHikariTransactor[M[_]: Async]( - driverClassName: String, - url: String, - user: String, - pass: String, - connectEC: ExecutionContext, - ): Resource[M, HikariTransactor[M]] = - for { - _ <- Resource.eval(Async[M].delay(Class.forName(driverClassName))) - t <- initial[M](connectEC) - _ <- Resource.eval { - t.configure { ds => - Async[M].delay { - ds.setJdbcUrl(url) - ds.setUsername(user) - ds.setPassword(pass) - } - } - } - } yield t - -} diff --git a/modules/hikari/src/main/scala/doobie/hikari/package.scala b/modules/hikari/src/main/scala/doobie/hikari/package.scala deleted file mode 100644 index 68cc2728c..000000000 --- a/modules/hikari/src/main/scala/doobie/hikari/package.scala +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie - -import com.zaxxer.hikari.HikariDataSource -import doobie.util.transactor.Transactor - -package object hikari { - - type HikariTransactor[M[_]] = Transactor.Aux[M, HikariDataSource] - -} diff --git a/modules/hikari/src/test/scala/doobie/hikari/ConfigSpec.scala b/modules/hikari/src/test/scala/doobie/hikari/ConfigSpec.scala deleted file mode 100644 index 15d6bfdbe..000000000 --- a/modules/hikari/src/test/scala/doobie/hikari/ConfigSpec.scala +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.hikari - -import cats.effect.SyncIO -import com.zaxxer.hikari.HikariConfig -import zio.test.ZIOSpecDefault -import zio.test.assertTrue - -object ConfigSpec extends ZIOSpecDefault { - - override val spec = suite("Config")( - test("Default should be the same as unmodified HikariConfig") { - val poolName = "poolName" - - val actual = Config.makeHikariConfig[SyncIO](Config("jdbcUrl", poolName = Some(poolName))).unsafeRunSync() - val expected = { - val c = new HikariConfig() - c.setJdbcUrl("jdbcUrl") // mandatory argument - c.setPoolName(poolName) // otherwise the pool name is generated - c.validate() - c - } - - assertTrue(actual.getJdbcUrl == expected.getJdbcUrl) && - assertTrue(actual.getCatalog == expected.getCatalog) && - assertTrue(actual.getConnectionTimeout == expected.getConnectionTimeout) && - assertTrue(actual.getIdleTimeout == expected.getIdleTimeout) && - assertTrue(actual.getLeakDetectionThreshold == expected.getLeakDetectionThreshold) && - assertTrue(actual.getMaximumPoolSize == expected.getMaximumPoolSize) && - assertTrue(actual.getMaxLifetime == expected.getMaxLifetime) && - assertTrue(actual.getMinimumIdle == expected.getMinimumIdle) && - assertTrue(actual.getPassword == expected.getPassword) && - assertTrue(actual.getPoolName == expected.getPoolName) && - assertTrue(actual.getUsername == expected.getUsername) && - assertTrue(actual.getValidationTimeout == expected.getValidationTimeout) && - assertTrue(actual.isAllowPoolSuspension == expected.isAllowPoolSuspension) && - assertTrue(actual.isAutoCommit == expected.isAutoCommit) && - assertTrue(actual.getConnectionInitSql == expected.getConnectionInitSql) && - assertTrue(actual.getConnectionTestQuery == expected.getConnectionTestQuery) && - assertTrue(actual.getDataSourceClassName == expected.getDataSourceClassName) && - assertTrue(actual.getDataSourceJNDI == expected.getDataSourceJNDI) && - assertTrue(actual.getDriverClassName == expected.getDriverClassName) && - assertTrue(actual.getInitializationFailTimeout == expected.getInitializationFailTimeout) && - assertTrue(actual.isIsolateInternalQueries == expected.isIsolateInternalQueries) && - assertTrue(actual.isReadOnly == expected.isReadOnly) && - assertTrue(actual.isRegisterMbeans == expected.isRegisterMbeans) && - assertTrue(actual.getSchema == expected.getSchema) && - assertTrue(actual.getTransactionIsolation == expected.getTransactionIsolation) && - assertTrue(actual.getDataSource == expected.getDataSource) && - assertTrue(actual.getDataSourceProperties == expected.getDataSourceProperties) && - assertTrue(actual.getHealthCheckProperties == expected.getHealthCheckProperties) && - assertTrue(actual.getHealthCheckRegistry == expected.getHealthCheckRegistry) && - assertTrue(actual.getMetricRegistry == expected.getMetricRegistry) && - assertTrue(actual.getMetricsTrackerFactory == expected.getMetricsTrackerFactory) && - assertTrue(actual.getScheduledExecutor == expected.getScheduledExecutor) && - assertTrue(actual.getThreadFactory == expected.getThreadFactory) - }, - ) -} diff --git a/modules/free/src/main/scala-2/doobie/util/PosPlatform.scala b/modules/macros/src/main/scala-2/doobie/util/PosPlatform.scala similarity index 100% rename from modules/free/src/main/scala-2/doobie/util/PosPlatform.scala rename to modules/macros/src/main/scala-2/doobie/util/PosPlatform.scala diff --git a/modules/macros/src/main/scala-2/doobie/util/TypeNamePlatform.scala b/modules/macros/src/main/scala-2/doobie/util/TypeNamePlatform.scala new file mode 100644 index 000000000..b320317b8 --- /dev/null +++ b/modules/macros/src/main/scala-2/doobie/util/TypeNamePlatform.scala @@ -0,0 +1,31 @@ +// Copyright (c) 2020-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package doobie.util + +import doobie.util.typename.TypeName + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox + +trait TypeNamePlatform { + + implicit def typeName[T]: TypeName[T] = + macro TypeNamePlatform.typeName_impl[T] + +} + +object TypeNamePlatform { + + // https://stackoverflow.com/questions/15649720 + def typeName_impl[T](c: blackbox.Context): c.Expr[TypeName[T]] = { + import c.universe.* + val typeTree = c.macroApplication match { + case TypeApply(_, List(typeTree)) => typeTree + case _ => c.abort(c.enclosingPosition, "Type parameter is not a TypeApply") + } + c.Expr(q"doobie.util.typename.TypeName(${typeTree.toString})") + } + +} diff --git a/modules/free/src/main/scala-3/doobie/util/PosPlatform.scala b/modules/macros/src/main/scala-3/doobie/util/PosPlatform.scala similarity index 100% rename from modules/free/src/main/scala-3/doobie/util/PosPlatform.scala rename to modules/macros/src/main/scala-3/doobie/util/PosPlatform.scala diff --git a/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala b/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala new file mode 100644 index 000000000..2dcab6de8 --- /dev/null +++ b/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala @@ -0,0 +1,22 @@ +// Copyright (c) 2020-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package doobie.util + +import doobie.util.typename.TypeName +import scala.quoted.* + +trait TypeNamePlatform { + + inline given [A]: TypeName[A] = + ${TypeNamePlatform.impl[A]} + +} + +object TypeNamePlatform { + + def impl[A](using t: Type[A], ctx: Quotes): Expr[TypeName[A]] = + '{TypeName[A](${Expr(Type.show[A])})} + +} diff --git a/modules/free/src/main/scala/doobie/util/pos.scala b/modules/macros/src/main/scala/doobie/util/pos.scala similarity index 100% rename from modules/free/src/main/scala/doobie/util/pos.scala rename to modules/macros/src/main/scala/doobie/util/pos.scala diff --git a/modules/macros/src/main/scala/doobie/util/typename.scala b/modules/macros/src/main/scala/doobie/util/typename.scala new file mode 100644 index 000000000..c6442f698 --- /dev/null +++ b/modules/macros/src/main/scala/doobie/util/typename.scala @@ -0,0 +1,12 @@ +// Copyright (c) 2020-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package doobie.util + +object typename { + final case class TypeName[A](value: String) + object TypeName extends TypeNamePlatform + + def typeName[A](implicit ev: TypeName[A]): String = ev.value +} diff --git a/modules/munit/src/main/scala/doobie/munit/analysisspec.scala b/modules/munit/src/main/scala/doobie/munit/analysisspec.scala deleted file mode 100644 index 3a004bea7..000000000 --- a/modules/munit/src/main/scala/doobie/munit/analysisspec.scala +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.munit - -import cats.effect.IO -import cats.effect.kernel.Sync -import doobie.munit.analysisspec.Checker.ErrorItems -import doobie.syntax.connectionio.* -import doobie.util.query.Query -import doobie.util.query.Query0 -import doobie.util.testing.* -import munit.Assertions -import munit.Location -import org.tpolecat.typename.* - -/** - * Module with a mix-in trait for specifications that enables checking of doobie - * `Query` and `Update` values. - * - * {{{ - * class ExampleSuite extends FunSuite with IOChecker { - * - * // The transactor to use for the tests. - * val transactor = Transactor.fromDriverManager[IO](...) - * - * // Now just mention the queries. Arguments are not used. - * test("findByNameAndAge") { check(MyDaoModule.findByNameAndAge(null, 0)) } - * test("allWoozles") { check(MyDaoModule.allWoozles) } - * - * } - * }}} - */ -object analysisspec { - - trait Checker[M[_]] extends CheckerBase[M] { this: Assertions => - - def check[A: Analyzable](a: A)(implicit loc: Location): Unit = checkImpl(Analyzable.unpack(a)) - - def checkOutput[A: TypeName](q: Query0[A])(implicit loc: Location): Unit = - checkImpl(AnalysisArgs( - s"Query0[${typeName[A]}]", - q.pos, - q.sql, - q.outputAnalysis, - )) - - def checkOutput[A: TypeName, B: TypeName](q: Query[A, B])(implicit loc: Location): Unit = - checkImpl(AnalysisArgs( - s"Query[${typeName[A]}, ${typeName[B]}]", - q.pos, - q.sql, - q.outputAnalysis, - )) - - private def checkImpl(args: AnalysisArgs)(implicit loc: Location): Unit = { - val report = U.unsafeRunSync(analyze(args).transact(transactor)) - if (!report.succeeded) { - fail( - message = formatReport(args, report, colors) - .padLeft(" ") - .toString, - cause = ErrorItems(report.items.filter(_.error.isDefined)), - ) - } - } - } - - object Checker { - final case class ErrorItems(errors: List[AnalysisReport.Item]) extends Exception - } - - /** Implementation of Checker[IO] */ - trait IOChecker extends Checker[IO] { self: Assertions => - import cats.effect.unsafe.implicits.global - override implicit val M: Sync[IO] = IO.asyncForIO - override implicit val U: UnsafeRun[IO] = new UnsafeRun[IO] { - def unsafeRunSync[A](ioa: IO[A]) = ioa.unsafeRunSync() - } - } -} diff --git a/modules/munit/src/main/scala/doobie/munit/package.scala b/modules/munit/src/main/scala/doobie/munit/package.scala deleted file mode 100644 index b7fceaaf6..000000000 --- a/modules/munit/src/main/scala/doobie/munit/package.scala +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie - -package object munit { - - type Checker[M[_]] = analysisspec.Checker[M] - type IOChecker = analysisspec.IOChecker - -} diff --git a/modules/munit/src/test/scala/doobie/munit/CheckerTests.scala b/modules/munit/src/test/scala/doobie/munit/CheckerTests.scala deleted file mode 100644 index ebb259812..000000000 --- a/modules/munit/src/test/scala/doobie/munit/CheckerTests.scala +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.munit - -import cats.effect.IO -import doobie.syntax.string.* -import doobie.util.Read -import doobie.util.transactor.Transactor -import munit.* - -trait CheckerChecks[M[_]] extends FunSuite with Checker[M] { - - lazy val transactor = Transactor.fromDriverManager[M]( - "org.h2.Driver", - "jdbc:h2:mem:queryspec;DB_CLOSE_DELAY=-1", - "sa", - "", - ) - - test("trivial") { - check(sql"select 1".query[Int]) - } - - test("fail".fail) { - check(sql"select 1".query[String]) - } - - test("trivial case-class") { - check(sql"select 1".query[CheckerChecks.Foo]) - } - -} - -object CheckerChecks { - final case class Foo(x: Int) - object Foo { - implicit val read: Read[Foo] = Read.derived - } -} - -class IOCheckerCheck extends CheckerChecks[IO] with IOChecker {} diff --git a/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala b/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala index 756608a03..80a96fb14 100644 --- a/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala +++ b/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala @@ -8,7 +8,7 @@ import doobie.util.invariant.* import doobie.util.meta.Meta import net.postgis.jdbc.PGgeography import net.postgis.jdbc.geometry.* -import org.tpolecat.typename.* +import doobie.util.typename.* import scala.reflect.ClassTag diff --git a/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala b/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala index ad1496ce5..e1d8768e9 100644 --- a/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala +++ b/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala @@ -8,7 +8,7 @@ import doobie.util.invariant.* import doobie.util.meta.Meta import net.postgis.jdbc.* import net.postgis.jdbc.geometry.* -import org.tpolecat.typename.* +import doobie.util.typename.* import scala.reflect.ClassTag diff --git a/modules/postgis/src/test/scala/doobie/postgis/PostgisDatabaseSpec.scala b/modules/postgis/src/test/scala/doobie/postgis/PostgisDatabaseSpec.scala index 71ce0daa9..6e1c73cdd 100644 --- a/modules/postgis/src/test/scala/doobie/postgis/PostgisDatabaseSpec.scala +++ b/modules/postgis/src/test/scala/doobie/postgis/PostgisDatabaseSpec.scala @@ -1,7 +1,9 @@ package doobie.postgis import doobie.postgres.PostgresDatabaseSpec +import zio.ZIO import zio.ZLayer +import zoobie.ConnectionPool import zoobie.Transactor abstract class PostgisDatabaseSpec extends PostgresDatabaseSpec { self => @@ -10,16 +12,14 @@ abstract class PostgisDatabaseSpec extends PostgresDatabaseSpec { self => } object PostgisDatabaseSpec { - val layer: ZLayer[Any, Nothing, Transactor] = ZLayer.scoped[Any] { - createTransactor - } - - private def createTransactor = { + val layer: ZLayer[Any, Nothing, ConnectionPool & Transactor] = { import PostgresDatabaseSpec.config import PostgresDatabaseSpec.connectionConfig - zoobie.postgres.postgis(connectionConfig, config).map { pool => - Transactor.fromPoolTransactional(pool) + ZLayer.scoped[Any] { + zoobie.postgres.postgis(connectionConfig, config) + } >+> ZLayer.fromZIO { + ZIO.serviceWith[ConnectionPool](Transactor.fromPoolTransactional(_)) } } } diff --git a/modules/postgres/src/main/scala/doobie/postgres/Text.scala b/modules/postgres/src/main/scala/doobie/postgres/Text.scala index a9dac0112..d352f7414 100644 --- a/modules/postgres/src/main/scala/doobie/postgres/Text.scala +++ b/modules/postgres/src/main/scala/doobie/postgres/Text.scala @@ -159,6 +159,11 @@ object Text extends TextInstances0 with TextPlatform { case (None, sb) => val _ = sb.append(Text.NULL) } + def foldToString[F[_]: Foldable, A](fa: F[A])(implicit ev: Text[A]): String = + fa.foldLeft(new StringBuilder) { (b, a) => + ev.unsafeEncode(a, b) + b.append("\n") + }.toString } trait TextInstances0 extends TextInstances1 { this: Text.type => diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/copyin.scala b/modules/postgres/src/main/scala/doobie/postgres/free/copyin.scala deleted file mode 100644 index f017382ed..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/copyin.scala +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> -import org.postgresql.copy.CopyIn as PGCopyIn -import org.postgresql.util.ByteStreamWriter - -import scala.concurrent.duration.FiniteDuration - -object copyin { module => - - // Algebra of operations for PGCopyIn. Each accepts a visitor as an alternative to pattern-matching. - sealed trait CopyInOp[A] { - def visit[F[_]](v: CopyInOp.Visitor[F]): F[A] - } - - // Free monad over CopyInOp. - type CopyInIO[A] = FF[CopyInOp, A] - - // Module of instances and constructors of CopyInOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object CopyInOp { - - // Given a PGCopyIn we can embed a CopyInIO program in any algebra that understands embedding. - implicit val CopyInOpEmbeddable: Embeddable[CopyInOp, PGCopyIn] = - new Embeddable[CopyInOp, PGCopyIn] { - def embed[A](j: PGCopyIn, fa: FF[CopyInOp, A]) = Embedded.CopyIn(j, fa) - } - - // Interface for a natural transformation CopyInOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (CopyInOp ~> F) { - final def apply[A](fa: CopyInOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: PGCopyIn => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: CopyInIO[A])(f: Throwable => CopyInIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: CopyInIO[A])(fb: CopyInIO[B]): F[B] - def uncancelable[A](body: Poll[CopyInIO] => CopyInIO[A]): F[A] - def poll[A](poll: Any, fa: CopyInIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: CopyInIO[A], fin: CopyInIO[Unit]): F[A] - - // PGCopyIn - def cancelCopy: F[Unit] - def endCopy: F[Long] - def flushCopy: F[Unit] - def getFieldCount: F[Int] - def getFieldFormat(a: Int): F[Int] - def getFormat: F[Int] - def getHandledRowCount: F[Long] - def isActive: F[Boolean] - def writeToCopy(a: Array[Byte], b: Int, c: Int): F[Unit] - def writeToCopy(a: ByteStreamWriter): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: PGCopyIn => A) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: CopyInIO[A], f: Throwable => CopyInIO[A]) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends CopyInOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends CopyInOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: CopyInIO[A], fb: CopyInIO[B]) extends CopyInOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[CopyInIO] => CopyInIO[A]) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: CopyInIO[A]) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends CopyInOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: CopyInIO[A], fin: CopyInIO[Unit]) extends CopyInOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // PGCopyIn-specific operations. - case object CancelCopy extends CopyInOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancelCopy - } - case object EndCopy extends CopyInOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.endCopy - } - case object FlushCopy extends CopyInOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.flushCopy - } - case object GetFieldCount extends CopyInOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFieldCount - } - final case class GetFieldFormat(a: Int) extends CopyInOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFieldFormat(a) - } - case object GetFormat extends CopyInOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFormat - } - case object GetHandledRowCount extends CopyInOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getHandledRowCount - } - case object IsActive extends CopyInOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isActive - } - final case class WriteToCopy(a: Array[Byte], b: Int, c: Int) extends CopyInOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeToCopy(a, b, c) - } - final case class WriteToCopy1(a: ByteStreamWriter) extends CopyInOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.writeToCopy(a) - } - - } - import CopyInOp.* - - // Smart constructors for operations common to all algebras. - val unit: CopyInIO[Unit] = FF.pure[CopyInOp, Unit](()) - def pure[A](a: A): CopyInIO[A] = FF.pure[CopyInOp, A](a) - def raw[A](f: PGCopyIn => A): CopyInIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[CopyInOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): CopyInIO[A] = FF.liftF[CopyInOp, A](RaiseError(err)) - def handleErrorWith[A](fa: CopyInIO[A])(f: Throwable => CopyInIO[A]): CopyInIO[A] = - FF.liftF[CopyInOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[CopyInOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[CopyInOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[CopyInOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[CopyInOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: CopyInIO[A])(fb: CopyInIO[B]) = FF.liftF[CopyInOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[CopyInIO] => CopyInIO[A]) = FF.liftF[CopyInOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[CopyInIO] { - def apply[A](fa: CopyInIO[A]) = FF.liftF[CopyInOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[CopyInOp, Unit](Canceled) - def onCancel[A](fa: CopyInIO[A], fin: CopyInIO[Unit]) = FF.liftF[CopyInOp, A](OnCancel(fa, fin)) - - // Smart constructors for CopyIn-specific operations. - val cancelCopy: CopyInIO[Unit] = FF.liftF(CancelCopy) - val endCopy: CopyInIO[Long] = FF.liftF(EndCopy) - val flushCopy: CopyInIO[Unit] = FF.liftF(FlushCopy) - val getFieldCount: CopyInIO[Int] = FF.liftF(GetFieldCount) - def getFieldFormat(a: Int): CopyInIO[Int] = FF.liftF(GetFieldFormat(a)) - val getFormat: CopyInIO[Int] = FF.liftF(GetFormat) - val getHandledRowCount: CopyInIO[Long] = FF.liftF(GetHandledRowCount) - val isActive: CopyInIO[Boolean] = FF.liftF(IsActive) - def writeToCopy(a: Array[Byte], b: Int, c: Int): CopyInIO[Unit] = FF.liftF(WriteToCopy(a, b, c)) - def writeToCopy(a: ByteStreamWriter): CopyInIO[Unit] = FF.liftF(WriteToCopy1(a)) - - private val monad = FF.catsFreeMonadForFree[CopyInOp] - - // Typeclass instances for CopyInIO - implicit val SyncCopyInIO: Sync[CopyInIO] = - new Sync[CopyInIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): CopyInIO[A] = monad.pure(x) - override def map[A, B](fa: CopyInIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: CopyInIO[A])(f: A => CopyInIO[B]): CopyInIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => CopyInIO[Either[A, B]]): CopyInIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): CopyInIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: CopyInIO[A])(f: Throwable => CopyInIO[A]): CopyInIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: CopyInIO[FiniteDuration] = module.monotonic - override def realTime: CopyInIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): CopyInIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: CopyInIO[A])(fb: CopyInIO[B]): CopyInIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[CopyInIO] => CopyInIO[A]): CopyInIO[A] = module.uncancelable(body) - override def canceled: CopyInIO[Unit] = module.canceled - override def onCancel[A](fa: CopyInIO[A], fin: CopyInIO[Unit]): CopyInIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidCopyInIO[A](implicit M: Monoid[A]): Monoid[CopyInIO[A]] = - new Monoid[CopyInIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: CopyInIO[A], y: CopyInIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/copymanager.scala b/modules/postgres/src/main/scala/doobie/postgres/free/copymanager.scala deleted file mode 100644 index cb6a2e8bd..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/copymanager.scala +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> -import org.postgresql.copy.CopyDual as PGCopyDual -import org.postgresql.copy.CopyIn as PGCopyIn -import org.postgresql.copy.CopyManager as PGCopyManager -import org.postgresql.copy.CopyOut as PGCopyOut -import org.postgresql.util.ByteStreamWriter - -import java.io.InputStream -import java.io.OutputStream -import java.io.Reader -import java.io.Writer -import scala.concurrent.duration.FiniteDuration - -object copymanager { module => - - // Algebra of operations for PGCopyManager. Each accepts a visitor as an alternative to pattern-matching. - sealed trait CopyManagerOp[A] { - def visit[F[_]](v: CopyManagerOp.Visitor[F]): F[A] - } - - // Free monad over CopyManagerOp. - type CopyManagerIO[A] = FF[CopyManagerOp, A] - - // Module of instances and constructors of CopyManagerOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object CopyManagerOp { - - // Given a PGCopyManager we can embed a CopyManagerIO program in any algebra that understands embedding. - implicit val CopyManagerOpEmbeddable: Embeddable[CopyManagerOp, PGCopyManager] = - new Embeddable[CopyManagerOp, PGCopyManager] { - def embed[A](j: PGCopyManager, fa: FF[CopyManagerOp, A]) = Embedded.CopyManager(j, fa) - } - - // Interface for a natural transformation CopyManagerOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (CopyManagerOp ~> F) { - final def apply[A](fa: CopyManagerOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: PGCopyManager => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: CopyManagerIO[A])(f: Throwable => CopyManagerIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: CopyManagerIO[A])(fb: CopyManagerIO[B]): F[B] - def uncancelable[A](body: Poll[CopyManagerIO] => CopyManagerIO[A]): F[A] - def poll[A](poll: Any, fa: CopyManagerIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: CopyManagerIO[A], fin: CopyManagerIO[Unit]): F[A] - - // PGCopyManager - def copyDual(a: String): F[PGCopyDual] - def copyIn(a: String): F[PGCopyIn] - def copyIn(a: String, b: ByteStreamWriter): F[Long] - def copyIn(a: String, b: InputStream): F[Long] - def copyIn(a: String, b: InputStream, c: Int): F[Long] - def copyIn(a: String, b: Reader): F[Long] - def copyIn(a: String, b: Reader, c: Int): F[Long] - def copyOut(a: String): F[PGCopyOut] - def copyOut(a: String, b: OutputStream): F[Long] - def copyOut(a: String, b: Writer): F[Long] - - } - - // Common operations for all algebras. - final case class Raw[A](f: PGCopyManager => A) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: CopyManagerIO[A], f: Throwable => CopyManagerIO[A]) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends CopyManagerOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends CopyManagerOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: CopyManagerIO[A], fb: CopyManagerIO[B]) extends CopyManagerOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[CopyManagerIO] => CopyManagerIO[A]) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: CopyManagerIO[A]) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends CopyManagerOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: CopyManagerIO[A], fin: CopyManagerIO[Unit]) extends CopyManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // PGCopyManager-specific operations. - final case class CopyDual(a: String) extends CopyManagerOp[PGCopyDual] { - def visit[F[_]](v: Visitor[F]) = v.copyDual(a) - } - final case class CopyIn(a: String) extends CopyManagerOp[PGCopyIn] { - def visit[F[_]](v: Visitor[F]) = v.copyIn(a) - } - final case class CopyIn1(a: String, b: ByteStreamWriter) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyIn(a, b) - } - final case class CopyIn2(a: String, b: InputStream) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyIn(a, b) - } - final case class CopyIn3(a: String, b: InputStream, c: Int) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyIn(a, b, c) - } - final case class CopyIn4(a: String, b: Reader) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyIn(a, b) - } - final case class CopyIn5(a: String, b: Reader, c: Int) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyIn(a, b, c) - } - final case class CopyOut(a: String) extends CopyManagerOp[PGCopyOut] { - def visit[F[_]](v: Visitor[F]) = v.copyOut(a) - } - final case class CopyOut1(a: String, b: OutputStream) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyOut(a, b) - } - final case class CopyOut2(a: String, b: Writer) extends CopyManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.copyOut(a, b) - } - - } - import CopyManagerOp.* - - // Smart constructors for operations common to all algebras. - val unit: CopyManagerIO[Unit] = FF.pure[CopyManagerOp, Unit](()) - def pure[A](a: A): CopyManagerIO[A] = FF.pure[CopyManagerOp, A](a) - def raw[A](f: PGCopyManager => A): CopyManagerIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[CopyManagerOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): CopyManagerIO[A] = FF.liftF[CopyManagerOp, A](RaiseError(err)) - def handleErrorWith[A](fa: CopyManagerIO[A])(f: Throwable => CopyManagerIO[A]): CopyManagerIO[A] = - FF.liftF[CopyManagerOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[CopyManagerOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[CopyManagerOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[CopyManagerOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[CopyManagerOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: CopyManagerIO[A])(fb: CopyManagerIO[B]) = FF.liftF[CopyManagerOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[CopyManagerIO] => CopyManagerIO[A]) = FF.liftF[CopyManagerOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[CopyManagerIO] { - def apply[A](fa: CopyManagerIO[A]) = FF.liftF[CopyManagerOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[CopyManagerOp, Unit](Canceled) - def onCancel[A](fa: CopyManagerIO[A], fin: CopyManagerIO[Unit]) = FF.liftF[CopyManagerOp, A](OnCancel(fa, fin)) - - // Smart constructors for CopyManager-specific operations. - def copyDual(a: String): CopyManagerIO[PGCopyDual] = FF.liftF(CopyDual(a)) - def copyIn(a: String): CopyManagerIO[PGCopyIn] = FF.liftF(CopyIn(a)) - def copyIn(a: String, b: ByteStreamWriter): CopyManagerIO[Long] = FF.liftF(CopyIn1(a, b)) - def copyIn(a: String, b: InputStream): CopyManagerIO[Long] = FF.liftF(CopyIn2(a, b)) - def copyIn(a: String, b: InputStream, c: Int): CopyManagerIO[Long] = FF.liftF(CopyIn3(a, b, c)) - def copyIn(a: String, b: Reader): CopyManagerIO[Long] = FF.liftF(CopyIn4(a, b)) - def copyIn(a: String, b: Reader, c: Int): CopyManagerIO[Long] = FF.liftF(CopyIn5(a, b, c)) - def copyOut(a: String): CopyManagerIO[PGCopyOut] = FF.liftF(CopyOut(a)) - def copyOut(a: String, b: OutputStream): CopyManagerIO[Long] = FF.liftF(CopyOut1(a, b)) - def copyOut(a: String, b: Writer): CopyManagerIO[Long] = FF.liftF(CopyOut2(a, b)) - - private val monad = FF.catsFreeMonadForFree[CopyManagerOp] - - // Typeclass instances for CopyManagerIO - implicit val SyncCopyManagerIO: Sync[CopyManagerIO] = - new Sync[CopyManagerIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): CopyManagerIO[A] = monad.pure(x) - override def map[A, B](fa: CopyManagerIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: CopyManagerIO[A])(f: A => CopyManagerIO[B]): CopyManagerIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => CopyManagerIO[Either[A, B]]): CopyManagerIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): CopyManagerIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: CopyManagerIO[A])(f: Throwable => CopyManagerIO[A]): CopyManagerIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: CopyManagerIO[FiniteDuration] = module.monotonic - override def realTime: CopyManagerIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): CopyManagerIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: CopyManagerIO[A])(fb: CopyManagerIO[B]): CopyManagerIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[CopyManagerIO] => CopyManagerIO[A]): CopyManagerIO[A] = - module.uncancelable(body) - override def canceled: CopyManagerIO[Unit] = module.canceled - override def onCancel[A](fa: CopyManagerIO[A], fin: CopyManagerIO[Unit]): CopyManagerIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidCopyManagerIO[A](implicit M: Monoid[A]): Monoid[CopyManagerIO[A]] = - new Monoid[CopyManagerIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: CopyManagerIO[A], y: CopyManagerIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/copyout.scala b/modules/postgres/src/main/scala/doobie/postgres/free/copyout.scala deleted file mode 100644 index 489a2bc6c..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/copyout.scala +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> -import org.postgresql.copy.CopyOut as PGCopyOut - -import scala.concurrent.duration.FiniteDuration - -object copyout { module => - - // Algebra of operations for PGCopyOut. Each accepts a visitor as an alternative to pattern-matching. - sealed trait CopyOutOp[A] { - def visit[F[_]](v: CopyOutOp.Visitor[F]): F[A] - } - - // Free monad over CopyOutOp. - type CopyOutIO[A] = FF[CopyOutOp, A] - - // Module of instances and constructors of CopyOutOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object CopyOutOp { - - // Given a PGCopyOut we can embed a CopyOutIO program in any algebra that understands embedding. - implicit val CopyOutOpEmbeddable: Embeddable[CopyOutOp, PGCopyOut] = - new Embeddable[CopyOutOp, PGCopyOut] { - def embed[A](j: PGCopyOut, fa: FF[CopyOutOp, A]) = Embedded.CopyOut(j, fa) - } - - // Interface for a natural transformation CopyOutOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (CopyOutOp ~> F) { - final def apply[A](fa: CopyOutOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: PGCopyOut => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: CopyOutIO[A])(f: Throwable => CopyOutIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: CopyOutIO[A])(fb: CopyOutIO[B]): F[B] - def uncancelable[A](body: Poll[CopyOutIO] => CopyOutIO[A]): F[A] - def poll[A](poll: Any, fa: CopyOutIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: CopyOutIO[A], fin: CopyOutIO[Unit]): F[A] - - // PGCopyOut - def cancelCopy: F[Unit] - def getFieldCount: F[Int] - def getFieldFormat(a: Int): F[Int] - def getFormat: F[Int] - def getHandledRowCount: F[Long] - def isActive: F[Boolean] - def readFromCopy: F[Array[Byte]] - def readFromCopy(a: Boolean): F[Array[Byte]] - - } - - // Common operations for all algebras. - final case class Raw[A](f: PGCopyOut => A) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: CopyOutIO[A], f: Throwable => CopyOutIO[A]) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends CopyOutOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends CopyOutOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: CopyOutIO[A], fb: CopyOutIO[B]) extends CopyOutOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[CopyOutIO] => CopyOutIO[A]) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: CopyOutIO[A]) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends CopyOutOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: CopyOutIO[A], fin: CopyOutIO[Unit]) extends CopyOutOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // PGCopyOut-specific operations. - case object CancelCopy extends CopyOutOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancelCopy - } - case object GetFieldCount extends CopyOutOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFieldCount - } - final case class GetFieldFormat(a: Int) extends CopyOutOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFieldFormat(a) - } - case object GetFormat extends CopyOutOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getFormat - } - case object GetHandledRowCount extends CopyOutOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getHandledRowCount - } - case object IsActive extends CopyOutOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.isActive - } - case object ReadFromCopy extends CopyOutOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.readFromCopy - } - final case class ReadFromCopy1(a: Boolean) extends CopyOutOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.readFromCopy(a) - } - - } - import CopyOutOp.* - - // Smart constructors for operations common to all algebras. - val unit: CopyOutIO[Unit] = FF.pure[CopyOutOp, Unit](()) - def pure[A](a: A): CopyOutIO[A] = FF.pure[CopyOutOp, A](a) - def raw[A](f: PGCopyOut => A): CopyOutIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[CopyOutOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): CopyOutIO[A] = FF.liftF[CopyOutOp, A](RaiseError(err)) - def handleErrorWith[A](fa: CopyOutIO[A])(f: Throwable => CopyOutIO[A]): CopyOutIO[A] = - FF.liftF[CopyOutOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[CopyOutOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[CopyOutOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[CopyOutOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[CopyOutOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: CopyOutIO[A])(fb: CopyOutIO[B]) = FF.liftF[CopyOutOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[CopyOutIO] => CopyOutIO[A]) = FF.liftF[CopyOutOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[CopyOutIO] { - def apply[A](fa: CopyOutIO[A]) = FF.liftF[CopyOutOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[CopyOutOp, Unit](Canceled) - def onCancel[A](fa: CopyOutIO[A], fin: CopyOutIO[Unit]) = FF.liftF[CopyOutOp, A](OnCancel(fa, fin)) - - // Smart constructors for CopyOut-specific operations. - val cancelCopy: CopyOutIO[Unit] = FF.liftF(CancelCopy) - val getFieldCount: CopyOutIO[Int] = FF.liftF(GetFieldCount) - def getFieldFormat(a: Int): CopyOutIO[Int] = FF.liftF(GetFieldFormat(a)) - val getFormat: CopyOutIO[Int] = FF.liftF(GetFormat) - val getHandledRowCount: CopyOutIO[Long] = FF.liftF(GetHandledRowCount) - val isActive: CopyOutIO[Boolean] = FF.liftF(IsActive) - val readFromCopy: CopyOutIO[Array[Byte]] = FF.liftF(ReadFromCopy) - def readFromCopy(a: Boolean): CopyOutIO[Array[Byte]] = FF.liftF(ReadFromCopy1(a)) - - private val monad = FF.catsFreeMonadForFree[CopyOutOp] - - // Typeclass instances for CopyOutIO - implicit val SyncCopyOutIO: Sync[CopyOutIO] = - new Sync[CopyOutIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): CopyOutIO[A] = monad.pure(x) - override def map[A, B](fa: CopyOutIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: CopyOutIO[A])(f: A => CopyOutIO[B]): CopyOutIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => CopyOutIO[Either[A, B]]): CopyOutIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): CopyOutIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: CopyOutIO[A])(f: Throwable => CopyOutIO[A]): CopyOutIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: CopyOutIO[FiniteDuration] = module.monotonic - override def realTime: CopyOutIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): CopyOutIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: CopyOutIO[A])(fb: CopyOutIO[B]): CopyOutIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[CopyOutIO] => CopyOutIO[A]): CopyOutIO[A] = module.uncancelable(body) - override def canceled: CopyOutIO[Unit] = module.canceled - override def onCancel[A](fa: CopyOutIO[A], fin: CopyOutIO[Unit]): CopyOutIO[A] = module.onCancel(fa, fin) - } - - implicit def MonoidCopyOutIO[A](implicit M: Monoid[A]): Monoid[CopyOutIO[A]] = - new Monoid[CopyOutIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: CopyOutIO[A], y: CopyOutIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/embedded.scala b/modules/postgres/src/main/scala/doobie/postgres/free/embedded.scala deleted file mode 100644 index a15c2642b..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/embedded.scala +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.free.Free -import copyin.CopyInIO -import copymanager.CopyManagerIO -import copyout.CopyOutIO -import largeobject.LargeObjectIO -import largeobjectmanager.LargeObjectManagerIO -import pgconnection.PGConnectionIO - -// A pair (J, Free[F, A]) with constructors that tie down J and F. -sealed trait Embedded[A] - -object Embedded { - final case class CopyIn[A](j: org.postgresql.copy.CopyIn, fa: CopyInIO[A]) extends Embedded[A] - final case class CopyManager[A](j: org.postgresql.copy.CopyManager, fa: CopyManagerIO[A]) extends Embedded[A] - final case class CopyOut[A](j: org.postgresql.copy.CopyOut, fa: CopyOutIO[A]) extends Embedded[A] - final case class LargeObject[A](j: org.postgresql.largeobject.LargeObject, fa: LargeObjectIO[A]) extends Embedded[A] - final case class LargeObjectManager[A](j: org.postgresql.largeobject.LargeObjectManager, fa: LargeObjectManagerIO[A]) - extends Embedded[A] - final case class PGConnection[A](j: org.postgresql.PGConnection, fa: PGConnectionIO[A]) extends Embedded[A] -} - -// Typeclass for embeddable pairs (J, F) -trait Embeddable[F[_], J] { - def embed[A](j: J, fa: Free[F, A]): Embedded[A] -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/kleisliinterpreter.scala b/modules/postgres/src/main/scala/doobie/postgres/free/kleisliinterpreter.scala deleted file mode 100644 index 7e548c27d..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/kleisliinterpreter.scala +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.data.Kleisli -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free -import cats.~> -import doobie.postgres.free.copyin.CopyInIO -import doobie.postgres.free.copyin.CopyInOp -import doobie.postgres.free.copymanager.CopyManagerIO -import doobie.postgres.free.copymanager.CopyManagerOp -import doobie.postgres.free.copyout.CopyOutIO -import doobie.postgres.free.copyout.CopyOutOp -import doobie.postgres.free.largeobject.LargeObjectIO -import doobie.postgres.free.largeobject.LargeObjectOp -import doobie.postgres.free.largeobjectmanager.LargeObjectManagerIO -import doobie.postgres.free.largeobjectmanager.LargeObjectManagerOp -import doobie.postgres.free.pgconnection.PGConnectionIO -import doobie.postgres.free.pgconnection.PGConnectionOp -import org.postgresql.PGConnection -import org.postgresql.PGNotification -import org.postgresql.copy.CopyIn as PGCopyIn -import org.postgresql.copy.CopyManager as PGCopyManager -import org.postgresql.copy.CopyOut as PGCopyOut -import org.postgresql.jdbc.AutoSave -import org.postgresql.jdbc.PreferQueryMode -import org.postgresql.largeobject.LargeObject -import org.postgresql.largeobject.LargeObjectManager -import org.postgresql.replication.PGReplicationConnection -import org.postgresql.util.ByteStreamWriter - -import java.io.InputStream -import java.io.OutputStream -import java.io.Reader -import java.io.Writer -import scala.concurrent.duration.FiniteDuration - -object KleisliInterpreter { - def apply[M[_]](implicit M: Sync[M]): KleisliInterpreter[M] = new KleisliInterpreter[M] -} - -// Family of interpreters into Kleisli arrows for some monad M. -class KleisliInterpreter[M[_]](implicit val syncM: Sync[M]) { outer => - - // The 6 interpreters, with definitions below. These can be overridden to customize behavior. - lazy val CopyInInterpreter: CopyInOp ~> Kleisli[M, PGCopyIn, *] = new CopyInInterpreter {} - lazy val CopyManagerInterpreter: CopyManagerOp ~> Kleisli[M, PGCopyManager, *] = new CopyManagerInterpreter {} - lazy val CopyOutInterpreter: CopyOutOp ~> Kleisli[M, PGCopyOut, *] = new CopyOutInterpreter {} - lazy val LargeObjectInterpreter: LargeObjectOp ~> Kleisli[M, LargeObject, *] = new LargeObjectInterpreter {} - lazy val LargeObjectManagerInterpreter: LargeObjectManagerOp ~> Kleisli[M, LargeObjectManager, *] = - new LargeObjectManagerInterpreter {} - lazy val PGConnectionInterpreter: PGConnectionOp ~> Kleisli[M, PGConnection, *] = new PGConnectionInterpreter {} - - // Some methods are common to all interpreters and can be overridden to change behavior globally. - def primitive[J, A](f: J => A): Kleisli[M, J, A] = Kleisli { a => - // primitive JDBC methods throw exceptions and so do we when reading values - // so catch any non-fatal exceptions and lift them into the effect - try { - syncM.blocking(f(a)) - } catch { - case e if scala.util.control.NonFatal(e) => syncM.raiseError(e) - } - } - def raw[J, A](f: J => A): Kleisli[M, J, A] = primitive(f) - def raiseError[J, A](e: Throwable): Kleisli[M, J, A] = Kleisli(_ => syncM.raiseError(e)) - def monotonic[J]: Kleisli[M, J, FiniteDuration] = Kleisli(_ => syncM.monotonic) - def realTime[J]: Kleisli[M, J, FiniteDuration] = Kleisli(_ => syncM.realTime) - def delay[J, A](thunk: => A): Kleisli[M, J, A] = Kleisli(_ => syncM.delay(thunk)) - def suspend[J, A](hint: Sync.Type)(thunk: => A): Kleisli[M, J, A] = Kleisli(_ => syncM.suspend(hint)(thunk)) - def canceled[J]: Kleisli[M, J, Unit] = Kleisli(_ => syncM.canceled) - - // for operations using free structures we call the interpreter recursively - def handleErrorWith[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A])(f: Throwable => Free[ - G, - A, - ]): Kleisli[M, J, A] = Kleisli { j => - syncM.handleErrorWith(fa.foldMap(interpreter).run(j))(f.andThen(_.foldMap(interpreter).run(j))) - } - def forceR[G[_], J, A, B](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A])(fb: Free[G, B]): Kleisli[M, J, B] = - Kleisli { j => - syncM.forceR(fa.foldMap(interpreter).run(j))(fb.foldMap(interpreter).run(j)) - } - def uncancelable[G[_], J, A]( - interpreter: G ~> Kleisli[M, J, *], - capture: Poll[M] => Poll[Free[G, *]], - )(body: Poll[Free[G, *]] => Free[G, A]): Kleisli[M, J, A] = Kleisli { j => - syncM.uncancelable(body.compose(capture).andThen(_.foldMap(interpreter).run(j))) - } - @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf")) - def poll[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(mpoll: Any, fa: Free[G, A]): Kleisli[M, J, A] = - Kleisli { j => - mpoll.asInstanceOf[Poll[M]].apply(fa.foldMap(interpreter).run(j)) - } - def onCancel[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A], fin: Free[G, Unit]): Kleisli[M, J, A] = - Kleisli { j => - syncM.onCancel(fa.foldMap(interpreter).run(j), fin.foldMap(interpreter).run(j)) - } - def embed[J, A](e: Embedded[A]): Kleisli[M, J, A] = e match { - case Embedded.CopyIn(j, fa) => Kleisli(_ => fa.foldMap(CopyInInterpreter).run(j)) - case Embedded.CopyManager(j, fa) => Kleisli(_ => fa.foldMap(CopyManagerInterpreter).run(j)) - case Embedded.CopyOut(j, fa) => Kleisli(_ => fa.foldMap(CopyOutInterpreter).run(j)) - case Embedded.LargeObject(j, fa) => Kleisli(_ => fa.foldMap(LargeObjectInterpreter).run(j)) - case Embedded.LargeObjectManager(j, fa) => Kleisli(_ => fa.foldMap(LargeObjectManagerInterpreter).run(j)) - case Embedded.PGConnection(j, fa) => Kleisli(_ => fa.foldMap(PGConnectionInterpreter).run(j)) - } - - // Interpreters - trait CopyInInterpreter extends CopyInOp.Visitor[Kleisli[M, PGCopyIn, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: PGCopyIn => A): Kleisli[M, PGCopyIn, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, PGCopyIn, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, PGCopyIn, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, PGCopyIn, FiniteDuration] = outer.monotonic[PGCopyIn] - override def realTime: Kleisli[M, PGCopyIn, FiniteDuration] = outer.realTime[PGCopyIn] - override def delay[A](thunk: => A): Kleisli[M, PGCopyIn, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, PGCopyIn, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, PGCopyIn, Unit] = outer.canceled[PGCopyIn] - - // for operations using CopyInIO we must call ourself recursively - override def handleErrorWith[A](fa: CopyInIO[A])(f: Throwable => CopyInIO[A]): Kleisli[M, PGCopyIn, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: CopyInIO[A])(fb: CopyInIO[B]): Kleisli[M, PGCopyIn, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[CopyInIO] => CopyInIO[A]): Kleisli[M, PGCopyIn, A] = - outer.uncancelable(this, doobie.postgres.free.copyin.capturePoll)(body) - override def poll[A](poll: Any, fa: CopyInIO[A]): Kleisli[M, PGCopyIn, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: CopyInIO[A], fin: CopyInIO[Unit]): Kleisli[M, PGCopyIn, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def cancelCopy: Kleisli[M, PGCopyIn, Unit] = primitive(_.cancelCopy) - override def endCopy: Kleisli[M, PGCopyIn, Long] = primitive(_.endCopy) - override def flushCopy: Kleisli[M, PGCopyIn, Unit] = primitive(_.flushCopy) - override def getFieldCount: Kleisli[M, PGCopyIn, Int] = primitive(_.getFieldCount) - override def getFieldFormat(a: Int) = primitive(_.getFieldFormat(a)) - override def getFormat: Kleisli[M, PGCopyIn, Int] = primitive(_.getFormat) - override def getHandledRowCount: Kleisli[M, PGCopyIn, Long] = primitive(_.getHandledRowCount) - override def isActive: Kleisli[M, PGCopyIn, Boolean] = primitive(_.isActive) - override def writeToCopy(a: Array[Byte], b: Int, c: Int) = primitive(_.writeToCopy(a, b, c)) - override def writeToCopy(a: ByteStreamWriter) = primitive(_.writeToCopy(a)) - - } - - trait CopyManagerInterpreter extends CopyManagerOp.Visitor[Kleisli[M, PGCopyManager, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: PGCopyManager => A): Kleisli[M, PGCopyManager, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, PGCopyManager, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, PGCopyManager, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, PGCopyManager, FiniteDuration] = outer.monotonic[PGCopyManager] - override def realTime: Kleisli[M, PGCopyManager, FiniteDuration] = outer.realTime[PGCopyManager] - override def delay[A](thunk: => A): Kleisli[M, PGCopyManager, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, PGCopyManager, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, PGCopyManager, Unit] = outer.canceled[PGCopyManager] - - // for operations using CopyManagerIO we must call ourself recursively - override def handleErrorWith[A](fa: CopyManagerIO[A])(f: Throwable => CopyManagerIO[A]): Kleisli[M, PGCopyManager, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: CopyManagerIO[A])(fb: CopyManagerIO[B]): Kleisli[M, PGCopyManager, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[CopyManagerIO] => CopyManagerIO[A]): Kleisli[M, PGCopyManager, A] = - outer.uncancelable(this, doobie.postgres.free.copymanager.capturePoll)(body) - override def poll[A](poll: Any, fa: CopyManagerIO[A]): Kleisli[M, PGCopyManager, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: CopyManagerIO[A], fin: CopyManagerIO[Unit]): Kleisli[M, PGCopyManager, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def copyDual(a: String) = primitive(_.copyDual(a)) - override def copyIn(a: String) = primitive(_.copyIn(a)) - override def copyIn(a: String, b: ByteStreamWriter) = primitive(_.copyIn(a, b)) - override def copyIn(a: String, b: InputStream) = primitive(_.copyIn(a, b)) - override def copyIn(a: String, b: InputStream, c: Int) = primitive(_.copyIn(a, b, c)) - override def copyIn(a: String, b: Reader) = primitive(_.copyIn(a, b)) - override def copyIn(a: String, b: Reader, c: Int) = primitive(_.copyIn(a, b, c)) - override def copyOut(a: String) = primitive(_.copyOut(a)) - override def copyOut(a: String, b: OutputStream) = primitive(_.copyOut(a, b)) - override def copyOut(a: String, b: Writer) = primitive(_.copyOut(a, b)) - - } - - trait CopyOutInterpreter extends CopyOutOp.Visitor[Kleisli[M, PGCopyOut, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: PGCopyOut => A): Kleisli[M, PGCopyOut, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, PGCopyOut, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, PGCopyOut, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, PGCopyOut, FiniteDuration] = outer.monotonic[PGCopyOut] - override def realTime: Kleisli[M, PGCopyOut, FiniteDuration] = outer.realTime[PGCopyOut] - override def delay[A](thunk: => A): Kleisli[M, PGCopyOut, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, PGCopyOut, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, PGCopyOut, Unit] = outer.canceled[PGCopyOut] - - // for operations using CopyOutIO we must call ourself recursively - override def handleErrorWith[A](fa: CopyOutIO[A])(f: Throwable => CopyOutIO[A]): Kleisli[M, PGCopyOut, A] = - outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: CopyOutIO[A])(fb: CopyOutIO[B]): Kleisli[M, PGCopyOut, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[CopyOutIO] => CopyOutIO[A]): Kleisli[M, PGCopyOut, A] = - outer.uncancelable(this, doobie.postgres.free.copyout.capturePoll)(body) - override def poll[A](poll: Any, fa: CopyOutIO[A]): Kleisli[M, PGCopyOut, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: CopyOutIO[A], fin: CopyOutIO[Unit]): Kleisli[M, PGCopyOut, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def cancelCopy: Kleisli[M, PGCopyOut, Unit] = primitive(_.cancelCopy) - override def getFieldCount: Kleisli[M, PGCopyOut, Int] = primitive(_.getFieldCount) - override def getFieldFormat(a: Int) = primitive(_.getFieldFormat(a)) - override def getFormat: Kleisli[M, PGCopyOut, Int] = primitive(_.getFormat) - override def getHandledRowCount: Kleisli[M, PGCopyOut, Long] = primitive(_.getHandledRowCount) - override def isActive: Kleisli[M, PGCopyOut, Boolean] = primitive(_.isActive) - override def readFromCopy: Kleisli[M, PGCopyOut, Array[Byte]] = primitive(_.readFromCopy) - override def readFromCopy(a: Boolean) = primitive(_.readFromCopy(a)) - - } - - trait LargeObjectInterpreter extends LargeObjectOp.Visitor[Kleisli[M, LargeObject, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: LargeObject => A): Kleisli[M, LargeObject, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, LargeObject, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, LargeObject, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, LargeObject, FiniteDuration] = outer.monotonic[LargeObject] - override def realTime: Kleisli[M, LargeObject, FiniteDuration] = outer.realTime[LargeObject] - override def delay[A](thunk: => A): Kleisli[M, LargeObject, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, LargeObject, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, LargeObject, Unit] = outer.canceled[LargeObject] - - // for operations using LargeObjectIO we must call ourself recursively - override def handleErrorWith[A](fa: LargeObjectIO[A])( - f: Throwable => LargeObjectIO[A], - ): Kleisli[M, LargeObject, A] = outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: LargeObjectIO[A])(fb: LargeObjectIO[B]): Kleisli[M, LargeObject, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[LargeObjectIO] => LargeObjectIO[A]): Kleisli[M, LargeObject, A] = - outer.uncancelable(this, doobie.postgres.free.largeobject.capturePoll)(body) - override def poll[A](poll: Any, fa: LargeObjectIO[A]): Kleisli[M, LargeObject, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: LargeObjectIO[A], fin: LargeObjectIO[Unit]): Kleisli[M, LargeObject, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def close: Kleisli[M, LargeObject, Unit] = primitive(_.close) - override def copy: Kleisli[M, LargeObject, LargeObject] = primitive(_.copy) - override def getInputStream: Kleisli[M, LargeObject, InputStream] = primitive(_.getInputStream) - override def getInputStream(a: Long) = primitive(_.getInputStream(a)) - override def getLongOID: Kleisli[M, LargeObject, Long] = primitive(_.getLongOID) - override def getOutputStream: Kleisli[M, LargeObject, OutputStream] = primitive(_.getOutputStream) - override def read(a: Array[Byte], b: Int, c: Int) = primitive(_.read(a, b, c)) - override def read(a: Int) = primitive(_.read(a)) - override def seek(a: Int) = primitive(_.seek(a)) - override def seek(a: Int, b: Int) = primitive(_.seek(a, b)) - override def seek64(a: Long, b: Int) = primitive(_.seek64(a, b)) - override def size: Kleisli[M, LargeObject, Int] = primitive(_.size) - override def size64: Kleisli[M, LargeObject, Long] = primitive(_.size64) - override def tell: Kleisli[M, LargeObject, Int] = primitive(_.tell) - override def tell64: Kleisli[M, LargeObject, Long] = primitive(_.tell64) - override def truncate(a: Int) = primitive(_.truncate(a)) - override def truncate64(a: Long) = primitive(_.truncate64(a)) - override def write(a: Array[Byte]) = primitive(_.write(a)) - override def write(a: Array[Byte], b: Int, c: Int) = primitive(_.write(a, b, c)) - - } - - trait LargeObjectManagerInterpreter extends LargeObjectManagerOp.Visitor[Kleisli[M, LargeObjectManager, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: LargeObjectManager => A): Kleisli[M, LargeObjectManager, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, LargeObjectManager, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, LargeObjectManager, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, LargeObjectManager, FiniteDuration] = outer.monotonic[LargeObjectManager] - override def realTime: Kleisli[M, LargeObjectManager, FiniteDuration] = outer.realTime[LargeObjectManager] - override def delay[A](thunk: => A): Kleisli[M, LargeObjectManager, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, LargeObjectManager, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, LargeObjectManager, Unit] = outer.canceled[LargeObjectManager] - - // for operations using LargeObjectManagerIO we must call ourself recursively - override def handleErrorWith[A](fa: LargeObjectManagerIO[A])( - f: Throwable => LargeObjectManagerIO[A], - ): Kleisli[M, LargeObjectManager, A] = outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: LargeObjectManagerIO[A])( - fb: LargeObjectManagerIO[B], - ): Kleisli[M, LargeObjectManager, B] = outer.forceR(this)(fa)(fb) - override def uncancelable[A]( - body: Poll[LargeObjectManagerIO] => LargeObjectManagerIO[A], - ): Kleisli[M, LargeObjectManager, A] = - outer.uncancelable(this, doobie.postgres.free.largeobjectmanager.capturePoll)(body) - override def poll[A](poll: Any, fa: LargeObjectManagerIO[A]): Kleisli[M, LargeObjectManager, A] = - outer.poll(this)(poll, fa) - override def onCancel[A]( - fa: LargeObjectManagerIO[A], - fin: LargeObjectManagerIO[Unit], - ): Kleisli[M, LargeObjectManager, A] = outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def createLO: Kleisli[M, LargeObjectManager, Long] = primitive(_.createLO) - override def createLO(a: Int) = primitive(_.createLO(a)) - override def delete(a: Long) = primitive(_.delete(a)) - override def open(a: Int, b: Boolean) = primitive(_.open(a, b)) - override def open(a: Int, b: Int, c: Boolean) = primitive(_.open(a, b, c)) - override def open(a: Long) = primitive(_.open(a)) - override def open(a: Long, b: Boolean) = primitive(_.open(a, b)) - override def open(a: Long, b: Int) = primitive(_.open(a, b)) - override def open(a: Long, b: Int, c: Boolean) = primitive(_.open(a, b, c)) - override def unlink(a: Long) = primitive(_.unlink(a)) - - } - - trait PGConnectionInterpreter extends PGConnectionOp.Visitor[Kleisli[M, PGConnection, *]] { - - // common operations delegate to outer interpreter - override def raw[A](f: PGConnection => A): Kleisli[M, PGConnection, A] = outer.raw(f) - override def embed[A](e: Embedded[A]): Kleisli[M, PGConnection, A] = outer.embed(e) - override def raiseError[A](e: Throwable): Kleisli[M, PGConnection, A] = outer.raiseError(e) - override def monotonic: Kleisli[M, PGConnection, FiniteDuration] = outer.monotonic[PGConnection] - override def realTime: Kleisli[M, PGConnection, FiniteDuration] = outer.realTime[PGConnection] - override def delay[A](thunk: => A): Kleisli[M, PGConnection, A] = outer.delay(thunk) - override def suspend[A](hint: Sync.Type)(thunk: => A): Kleisli[M, PGConnection, A] = outer.suspend(hint)(thunk) - override def canceled: Kleisli[M, PGConnection, Unit] = outer.canceled[PGConnection] - - // for operations using PGConnectionIO we must call ourself recursively - override def handleErrorWith[A](fa: PGConnectionIO[A])( - f: Throwable => PGConnectionIO[A], - ): Kleisli[M, PGConnection, A] = outer.handleErrorWith(this)(fa)(f) - override def forceR[A, B](fa: PGConnectionIO[A])(fb: PGConnectionIO[B]): Kleisli[M, PGConnection, B] = - outer.forceR(this)(fa)(fb) - override def uncancelable[A](body: Poll[PGConnectionIO] => PGConnectionIO[A]): Kleisli[M, PGConnection, A] = - outer.uncancelable(this, doobie.postgres.free.pgconnection.capturePoll)(body) - override def poll[A](poll: Any, fa: PGConnectionIO[A]): Kleisli[M, PGConnection, A] = outer.poll(this)(poll, fa) - override def onCancel[A](fa: PGConnectionIO[A], fin: PGConnectionIO[Unit]): Kleisli[M, PGConnection, A] = - outer.onCancel(this)(fa, fin) - - // domain-specific operations are implemented in terms of `primitive` - override def addDataType(a: String, b: Class[? <: org.postgresql.util.PGobject]) = primitive(_.addDataType(a, b)) - override def cancelQuery: Kleisli[M, PGConnection, Unit] = primitive(_.cancelQuery) - override def createArrayOf(a: String, b: AnyRef) = primitive(_.createArrayOf(a, b)) - override def escapeIdentifier(a: String) = primitive(_.escapeIdentifier(a)) - override def escapeLiteral(a: String) = primitive(_.escapeLiteral(a)) - override def getAdaptiveFetch: Kleisli[M, PGConnection, Boolean] = primitive(_.getAdaptiveFetch) - override def getAutosave: Kleisli[M, PGConnection, AutoSave] = primitive(_.getAutosave) - override def getBackendPID: Kleisli[M, PGConnection, Int] = primitive(_.getBackendPID) - override def getCopyAPI: Kleisli[M, PGConnection, PGCopyManager] = primitive(_.getCopyAPI) - override def getDefaultFetchSize: Kleisli[M, PGConnection, Int] = primitive(_.getDefaultFetchSize) - override def getLargeObjectAPI: Kleisli[M, PGConnection, LargeObjectManager] = primitive(_.getLargeObjectAPI) - override def getNotifications: Kleisli[M, PGConnection, Array[PGNotification]] = primitive(_.getNotifications) - override def getNotifications(a: Int) = primitive(_.getNotifications(a)) - override def getParameterStatus(a: String) = primitive(_.getParameterStatus(a)) - override def getParameterStatuses: Kleisli[M, PGConnection, java.util.Map[String, String]] = - primitive(_.getParameterStatuses) - override def getPreferQueryMode: Kleisli[M, PGConnection, PreferQueryMode] = primitive(_.getPreferQueryMode) - override def getPrepareThreshold: Kleisli[M, PGConnection, Int] = primitive(_.getPrepareThreshold) - override def getReplicationAPI: Kleisli[M, PGConnection, PGReplicationConnection] = primitive(_.getReplicationAPI) - override def setAdaptiveFetch(a: Boolean) = primitive(_.setAdaptiveFetch(a)) - override def setAutosave(a: AutoSave) = primitive(_.setAutosave(a)) - override def setDefaultFetchSize(a: Int) = primitive(_.setDefaultFetchSize(a)) - override def setPrepareThreshold(a: Int) = primitive(_.setPrepareThreshold(a)) - - } - -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/largeobject.scala b/modules/postgres/src/main/scala/doobie/postgres/free/largeobject.scala deleted file mode 100644 index caad6e2c8..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/largeobject.scala +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> -import org.postgresql.largeobject.LargeObject - -import java.io.InputStream -import java.io.OutputStream -import scala.concurrent.duration.FiniteDuration - -object largeobject { module => - - // Algebra of operations for LargeObject. Each accepts a visitor as an alternative to pattern-matching. - sealed trait LargeObjectOp[A] { - def visit[F[_]](v: LargeObjectOp.Visitor[F]): F[A] - } - - // Free monad over LargeObjectOp. - type LargeObjectIO[A] = FF[LargeObjectOp, A] - - // Module of instances and constructors of LargeObjectOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object LargeObjectOp { - - // Given a LargeObject we can embed a LargeObjectIO program in any algebra that understands embedding. - implicit val LargeObjectOpEmbeddable: Embeddable[LargeObjectOp, LargeObject] = - new Embeddable[LargeObjectOp, LargeObject] { - def embed[A](j: LargeObject, fa: FF[LargeObjectOp, A]) = Embedded.LargeObject(j, fa) - } - - // Interface for a natural transformation LargeObjectOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (LargeObjectOp ~> F) { - final def apply[A](fa: LargeObjectOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: LargeObject => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: LargeObjectIO[A])(f: Throwable => LargeObjectIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: LargeObjectIO[A])(fb: LargeObjectIO[B]): F[B] - def uncancelable[A](body: Poll[LargeObjectIO] => LargeObjectIO[A]): F[A] - def poll[A](poll: Any, fa: LargeObjectIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: LargeObjectIO[A], fin: LargeObjectIO[Unit]): F[A] - - // LargeObject - def close: F[Unit] - def copy: F[LargeObject] - def getInputStream: F[InputStream] - def getInputStream(a: Long): F[InputStream] - def getLongOID: F[Long] - def getOutputStream: F[OutputStream] - def read(a: Array[Byte], b: Int, c: Int): F[Int] - def read(a: Int): F[Array[Byte]] - def seek(a: Int): F[Unit] - def seek(a: Int, b: Int): F[Unit] - def seek64(a: Long, b: Int): F[Unit] - def size: F[Int] - def size64: F[Long] - def tell: F[Int] - def tell64: F[Long] - def truncate(a: Int): F[Unit] - def truncate64(a: Long): F[Unit] - def write(a: Array[Byte]): F[Unit] - def write(a: Array[Byte], b: Int, c: Int): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: LargeObject => A) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: LargeObjectIO[A], f: Throwable => LargeObjectIO[A]) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends LargeObjectOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends LargeObjectOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: LargeObjectIO[A], fb: LargeObjectIO[B]) extends LargeObjectOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[LargeObjectIO] => LargeObjectIO[A]) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: LargeObjectIO[A]) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: LargeObjectIO[A], fin: LargeObjectIO[Unit]) extends LargeObjectOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // LargeObject-specific operations. - case object Close extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.close - } - case object Copy extends LargeObjectOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.copy - } - case object GetInputStream extends LargeObjectOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getInputStream - } - final case class GetInputStream1(a: Long) extends LargeObjectOp[InputStream] { - def visit[F[_]](v: Visitor[F]) = v.getInputStream(a) - } - case object GetLongOID extends LargeObjectOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.getLongOID - } - case object GetOutputStream extends LargeObjectOp[OutputStream] { - def visit[F[_]](v: Visitor[F]) = v.getOutputStream - } - final case class Read(a: Array[Byte], b: Int, c: Int) extends LargeObjectOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.read(a, b, c) - } - final case class Read1(a: Int) extends LargeObjectOp[Array[Byte]] { - def visit[F[_]](v: Visitor[F]) = v.read(a) - } - final case class Seek(a: Int) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.seek(a) - } - final case class Seek1(a: Int, b: Int) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.seek(a, b) - } - final case class Seek64(a: Long, b: Int) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.seek64(a, b) - } - case object Size extends LargeObjectOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.size - } - case object Size64 extends LargeObjectOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.size64 - } - case object Tell extends LargeObjectOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.tell - } - case object Tell64 extends LargeObjectOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.tell64 - } - final case class Truncate(a: Int) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.truncate(a) - } - final case class Truncate64(a: Long) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.truncate64(a) - } - final case class Write(a: Array[Byte]) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.write(a) - } - final case class Write1(a: Array[Byte], b: Int, c: Int) extends LargeObjectOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.write(a, b, c) - } - - } - import LargeObjectOp.* - - // Smart constructors for operations common to all algebras. - val unit: LargeObjectIO[Unit] = FF.pure[LargeObjectOp, Unit](()) - def pure[A](a: A): LargeObjectIO[A] = FF.pure[LargeObjectOp, A](a) - def raw[A](f: LargeObject => A): LargeObjectIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[LargeObjectOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): LargeObjectIO[A] = FF.liftF[LargeObjectOp, A](RaiseError(err)) - def handleErrorWith[A](fa: LargeObjectIO[A])(f: Throwable => LargeObjectIO[A]): LargeObjectIO[A] = - FF.liftF[LargeObjectOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[LargeObjectOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[LargeObjectOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[LargeObjectOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[LargeObjectOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: LargeObjectIO[A])(fb: LargeObjectIO[B]) = FF.liftF[LargeObjectOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[LargeObjectIO] => LargeObjectIO[A]) = FF.liftF[LargeObjectOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[LargeObjectIO] { - def apply[A](fa: LargeObjectIO[A]) = FF.liftF[LargeObjectOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[LargeObjectOp, Unit](Canceled) - def onCancel[A](fa: LargeObjectIO[A], fin: LargeObjectIO[Unit]) = FF.liftF[LargeObjectOp, A](OnCancel(fa, fin)) - - // Smart constructors for LargeObject-specific operations. - val close: LargeObjectIO[Unit] = FF.liftF(Close) - val copy: LargeObjectIO[LargeObject] = FF.liftF(Copy) - val getInputStream: LargeObjectIO[InputStream] = FF.liftF(GetInputStream) - def getInputStream(a: Long): LargeObjectIO[InputStream] = FF.liftF(GetInputStream1(a)) - val getLongOID: LargeObjectIO[Long] = FF.liftF(GetLongOID) - val getOutputStream: LargeObjectIO[OutputStream] = FF.liftF(GetOutputStream) - def read(a: Array[Byte], b: Int, c: Int): LargeObjectIO[Int] = FF.liftF(Read(a, b, c)) - def read(a: Int): LargeObjectIO[Array[Byte]] = FF.liftF(Read1(a)) - def seek(a: Int): LargeObjectIO[Unit] = FF.liftF(Seek(a)) - def seek(a: Int, b: Int): LargeObjectIO[Unit] = FF.liftF(Seek1(a, b)) - def seek64(a: Long, b: Int): LargeObjectIO[Unit] = FF.liftF(Seek64(a, b)) - val size: LargeObjectIO[Int] = FF.liftF(Size) - val size64: LargeObjectIO[Long] = FF.liftF(Size64) - val tell: LargeObjectIO[Int] = FF.liftF(Tell) - val tell64: LargeObjectIO[Long] = FF.liftF(Tell64) - def truncate(a: Int): LargeObjectIO[Unit] = FF.liftF(Truncate(a)) - def truncate64(a: Long): LargeObjectIO[Unit] = FF.liftF(Truncate64(a)) - def write(a: Array[Byte]): LargeObjectIO[Unit] = FF.liftF(Write(a)) - def write(a: Array[Byte], b: Int, c: Int): LargeObjectIO[Unit] = FF.liftF(Write1(a, b, c)) - - private val monad = FF.catsFreeMonadForFree[LargeObjectOp] - - // Typeclass instances for LargeObjectIO - implicit val SyncLargeObjectIO: Sync[LargeObjectIO] = - new Sync[LargeObjectIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): LargeObjectIO[A] = monad.pure(x) - override def map[A, B](fa: LargeObjectIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: LargeObjectIO[A])(f: A => LargeObjectIO[B]): LargeObjectIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => LargeObjectIO[Either[A, B]]): LargeObjectIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): LargeObjectIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: LargeObjectIO[A])(f: Throwable => LargeObjectIO[A]): LargeObjectIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: LargeObjectIO[FiniteDuration] = module.monotonic - override def realTime: LargeObjectIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): LargeObjectIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: LargeObjectIO[A])(fb: LargeObjectIO[B]): LargeObjectIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[LargeObjectIO] => LargeObjectIO[A]): LargeObjectIO[A] = - module.uncancelable(body) - override def canceled: LargeObjectIO[Unit] = module.canceled - override def onCancel[A](fa: LargeObjectIO[A], fin: LargeObjectIO[Unit]): LargeObjectIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidLargeObjectIO[A](implicit M: Monoid[A]): Monoid[LargeObjectIO[A]] = - new Monoid[LargeObjectIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: LargeObjectIO[A], y: LargeObjectIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/largeobjectmanager.scala b/modules/postgres/src/main/scala/doobie/postgres/free/largeobjectmanager.scala deleted file mode 100644 index 325ad4e3d..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/largeobjectmanager.scala +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> -import org.postgresql.largeobject.LargeObject -import org.postgresql.largeobject.LargeObjectManager - -import scala.concurrent.duration.FiniteDuration - -object largeobjectmanager { module => - - // Algebra of operations for LargeObjectManager. Each accepts a visitor as an alternative to pattern-matching. - sealed trait LargeObjectManagerOp[A] { - def visit[F[_]](v: LargeObjectManagerOp.Visitor[F]): F[A] - } - - // Free monad over LargeObjectManagerOp. - type LargeObjectManagerIO[A] = FF[LargeObjectManagerOp, A] - - // Module of instances and constructors of LargeObjectManagerOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object LargeObjectManagerOp { - - // Given a LargeObjectManager we can embed a LargeObjectManagerIO program in any algebra that understands embedding. - implicit val LargeObjectManagerOpEmbeddable: Embeddable[LargeObjectManagerOp, LargeObjectManager] = - new Embeddable[LargeObjectManagerOp, LargeObjectManager] { - def embed[A](j: LargeObjectManager, fa: FF[LargeObjectManagerOp, A]) = Embedded.LargeObjectManager(j, fa) - } - - // Interface for a natural transformation LargeObjectManagerOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (LargeObjectManagerOp ~> F) { - final def apply[A](fa: LargeObjectManagerOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: LargeObjectManager => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: LargeObjectManagerIO[A])(f: Throwable => LargeObjectManagerIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: LargeObjectManagerIO[A])(fb: LargeObjectManagerIO[B]): F[B] - def uncancelable[A](body: Poll[LargeObjectManagerIO] => LargeObjectManagerIO[A]): F[A] - def poll[A](poll: Any, fa: LargeObjectManagerIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: LargeObjectManagerIO[A], fin: LargeObjectManagerIO[Unit]): F[A] - - // LargeObjectManager - def createLO: F[Long] - def createLO(a: Int): F[Long] - def delete(a: Long): F[Unit] - def open(a: Int, b: Boolean): F[LargeObject] - def open(a: Int, b: Int, c: Boolean): F[LargeObject] - def open(a: Long): F[LargeObject] - def open(a: Long, b: Boolean): F[LargeObject] - def open(a: Long, b: Int): F[LargeObject] - def open(a: Long, b: Int, c: Boolean): F[LargeObject] - def unlink(a: Long): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: LargeObjectManager => A) extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: LargeObjectManagerIO[A], f: Throwable => LargeObjectManagerIO[A]) - extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends LargeObjectManagerOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends LargeObjectManagerOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: LargeObjectManagerIO[A], fb: LargeObjectManagerIO[B]) - extends LargeObjectManagerOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[LargeObjectManagerIO] => LargeObjectManagerIO[A]) - extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: LargeObjectManagerIO[A]) extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends LargeObjectManagerOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: LargeObjectManagerIO[A], fin: LargeObjectManagerIO[Unit]) - extends LargeObjectManagerOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // LargeObjectManager-specific operations. - case object CreateLO extends LargeObjectManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.createLO - } - final case class CreateLO1(a: Int) extends LargeObjectManagerOp[Long] { - def visit[F[_]](v: Visitor[F]) = v.createLO(a) - } - final case class Delete(a: Long) extends LargeObjectManagerOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.delete(a) - } - final case class Open(a: Int, b: Boolean) extends LargeObjectManagerOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.open(a, b) - } - final case class Open1(a: Int, b: Int, c: Boolean) extends LargeObjectManagerOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.open(a, b, c) - } - final case class Open2(a: Long) extends LargeObjectManagerOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.open(a) - } - final case class Open3(a: Long, b: Boolean) extends LargeObjectManagerOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.open(a, b) - } - final case class Open4(a: Long, b: Int) extends LargeObjectManagerOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.open(a, b) - } - final case class Open5(a: Long, b: Int, c: Boolean) extends LargeObjectManagerOp[LargeObject] { - def visit[F[_]](v: Visitor[F]) = v.open(a, b, c) - } - final case class Unlink(a: Long) extends LargeObjectManagerOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.unlink(a) - } - - } - import LargeObjectManagerOp.* - - // Smart constructors for operations common to all algebras. - val unit: LargeObjectManagerIO[Unit] = FF.pure[LargeObjectManagerOp, Unit](()) - def pure[A](a: A): LargeObjectManagerIO[A] = FF.pure[LargeObjectManagerOp, A](a) - def raw[A](f: LargeObjectManager => A): LargeObjectManagerIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[LargeObjectManagerOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): LargeObjectManagerIO[A] = FF.liftF[LargeObjectManagerOp, A](RaiseError(err)) - def handleErrorWith[A](fa: LargeObjectManagerIO[A])( - f: Throwable => LargeObjectManagerIO[A], - ): LargeObjectManagerIO[A] = FF.liftF[LargeObjectManagerOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[LargeObjectManagerOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[LargeObjectManagerOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[LargeObjectManagerOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[LargeObjectManagerOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: LargeObjectManagerIO[A])(fb: LargeObjectManagerIO[B]) = - FF.liftF[LargeObjectManagerOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[LargeObjectManagerIO] => LargeObjectManagerIO[A]) = - FF.liftF[LargeObjectManagerOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[LargeObjectManagerIO] { - def apply[A](fa: LargeObjectManagerIO[A]) = FF.liftF[LargeObjectManagerOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[LargeObjectManagerOp, Unit](Canceled) - def onCancel[A](fa: LargeObjectManagerIO[A], fin: LargeObjectManagerIO[Unit]) = - FF.liftF[LargeObjectManagerOp, A](OnCancel(fa, fin)) - - // Smart constructors for LargeObjectManager-specific operations. - val createLO: LargeObjectManagerIO[Long] = FF.liftF(CreateLO) - def createLO(a: Int): LargeObjectManagerIO[Long] = FF.liftF(CreateLO1(a)) - def delete(a: Long): LargeObjectManagerIO[Unit] = FF.liftF(Delete(a)) - def open(a: Int, b: Boolean): LargeObjectManagerIO[LargeObject] = FF.liftF(Open(a, b)) - def open(a: Int, b: Int, c: Boolean): LargeObjectManagerIO[LargeObject] = FF.liftF(Open1(a, b, c)) - def open(a: Long): LargeObjectManagerIO[LargeObject] = FF.liftF(Open2(a)) - def open(a: Long, b: Boolean): LargeObjectManagerIO[LargeObject] = FF.liftF(Open3(a, b)) - def open(a: Long, b: Int): LargeObjectManagerIO[LargeObject] = FF.liftF(Open4(a, b)) - def open(a: Long, b: Int, c: Boolean): LargeObjectManagerIO[LargeObject] = FF.liftF(Open5(a, b, c)) - def unlink(a: Long): LargeObjectManagerIO[Unit] = FF.liftF(Unlink(a)) - - private val monad = FF.catsFreeMonadForFree[LargeObjectManagerOp] - - // Typeclass instances for LargeObjectManagerIO - implicit val SyncLargeObjectManagerIO: Sync[LargeObjectManagerIO] = - new Sync[LargeObjectManagerIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): LargeObjectManagerIO[A] = monad.pure(x) - override def map[A, B](fa: LargeObjectManagerIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: LargeObjectManagerIO[A])( - f: A => LargeObjectManagerIO[B], - ): LargeObjectManagerIO[B] = monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => LargeObjectManagerIO[Either[A, B]]): LargeObjectManagerIO[B] = - monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): LargeObjectManagerIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: LargeObjectManagerIO[A])( - f: Throwable => LargeObjectManagerIO[A], - ): LargeObjectManagerIO[A] = module.handleErrorWith(fa)(f) - override def monotonic: LargeObjectManagerIO[FiniteDuration] = module.monotonic - override def realTime: LargeObjectManagerIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): LargeObjectManagerIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: LargeObjectManagerIO[A])(fb: LargeObjectManagerIO[B]): LargeObjectManagerIO[B] = - module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[LargeObjectManagerIO] => LargeObjectManagerIO[A]): LargeObjectManagerIO[A] = - module.uncancelable(body) - override def canceled: LargeObjectManagerIO[Unit] = module.canceled - override def onCancel[A](fa: LargeObjectManagerIO[A], fin: LargeObjectManagerIO[Unit]): LargeObjectManagerIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidLargeObjectManagerIO[A](implicit M: Monoid[A]): Monoid[LargeObjectManagerIO[A]] = - new Monoid[LargeObjectManagerIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: LargeObjectManagerIO[A], y: LargeObjectManagerIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/free/pgconnection.scala b/modules/postgres/src/main/scala/doobie/postgres/free/pgconnection.scala deleted file mode 100644 index e66ddff1d..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/free/pgconnection.scala +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.free - -import cats.Monoid -import cats.effect.kernel.CancelScope -import cats.effect.kernel.Poll -import cats.effect.kernel.Sync -import cats.free.Free as FF // alias because some algebras have an op called Free -import cats.~> -import org.postgresql.PGConnection -import org.postgresql.PGNotification -import org.postgresql.copy.CopyManager as PGCopyManager -import org.postgresql.jdbc.AutoSave -import org.postgresql.jdbc.PreferQueryMode -import org.postgresql.largeobject.LargeObjectManager -import org.postgresql.replication.PGReplicationConnection - -import java.sql.Array as SqlArray -import scala.concurrent.duration.FiniteDuration - -object pgconnection { module => - - // Algebra of operations for PGConnection. Each accepts a visitor as an alternative to pattern-matching. - sealed trait PGConnectionOp[A] { - def visit[F[_]](v: PGConnectionOp.Visitor[F]): F[A] - } - - // Free monad over PGConnectionOp. - type PGConnectionIO[A] = FF[PGConnectionOp, A] - - // Module of instances and constructors of PGConnectionOp. - @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - object PGConnectionOp { - - // Given a PGConnection we can embed a PGConnectionIO program in any algebra that understands embedding. - implicit val PGConnectionOpEmbeddable: Embeddable[PGConnectionOp, PGConnection] = - new Embeddable[PGConnectionOp, PGConnection] { - def embed[A](j: PGConnection, fa: FF[PGConnectionOp, A]) = Embedded.PGConnection(j, fa) - } - - // Interface for a natural transformation PGConnectionOp ~> F encoded via the visitor pattern. - // This approach is much more efficient than pattern-matching for large algebras. - trait Visitor[F[_]] extends (PGConnectionOp ~> F) { - final def apply[A](fa: PGConnectionOp[A]): F[A] = fa.visit(this) - - // Common - def raw[A](f: PGConnection => A): F[A] - def embed[A](e: Embedded[A]): F[A] - def raiseError[A](e: Throwable): F[A] - def handleErrorWith[A](fa: PGConnectionIO[A])(f: Throwable => PGConnectionIO[A]): F[A] - def monotonic: F[FiniteDuration] - def realTime: F[FiniteDuration] - def delay[A](thunk: => A): F[A] - def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - def forceR[A, B](fa: PGConnectionIO[A])(fb: PGConnectionIO[B]): F[B] - def uncancelable[A](body: Poll[PGConnectionIO] => PGConnectionIO[A]): F[A] - def poll[A](poll: Any, fa: PGConnectionIO[A]): F[A] - def canceled: F[Unit] - def onCancel[A](fa: PGConnectionIO[A], fin: PGConnectionIO[Unit]): F[A] - - // PGConnection - def addDataType(a: String, b: Class[? <: org.postgresql.util.PGobject]): F[Unit] - def cancelQuery: F[Unit] - def createArrayOf(a: String, b: AnyRef): F[SqlArray] - def escapeIdentifier(a: String): F[String] - def escapeLiteral(a: String): F[String] - def getAdaptiveFetch: F[Boolean] - def getAutosave: F[AutoSave] - def getBackendPID: F[Int] - def getCopyAPI: F[PGCopyManager] - def getDefaultFetchSize: F[Int] - def getLargeObjectAPI: F[LargeObjectManager] - def getNotifications: F[Array[PGNotification]] - def getNotifications(a: Int): F[Array[PGNotification]] - def getParameterStatus(a: String): F[String] - def getParameterStatuses: F[java.util.Map[String, String]] - def getPreferQueryMode: F[PreferQueryMode] - def getPrepareThreshold: F[Int] - def getReplicationAPI: F[PGReplicationConnection] - def setAdaptiveFetch(a: Boolean): F[Unit] - def setAutosave(a: AutoSave): F[Unit] - def setDefaultFetchSize(a: Int): F[Unit] - def setPrepareThreshold(a: Int): F[Unit] - - } - - // Common operations for all algebras. - final case class Raw[A](f: PGConnection => A) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raw(f) - } - final case class Embed[A](e: Embedded[A]) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.embed(e) - } - final case class RaiseError[A](e: Throwable) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - } - final case class HandleErrorWith[A](fa: PGConnectionIO[A], f: Throwable => PGConnectionIO[A]) - extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - } - case object Monotonic extends PGConnectionOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.monotonic - } - case object Realtime extends PGConnectionOp[FiniteDuration] { - def visit[F[_]](v: Visitor[F]) = v.realTime - } - final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - } - final case class ForceR[A, B](fa: PGConnectionIO[A], fb: PGConnectionIO[B]) extends PGConnectionOp[B] { - def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - } - final case class Uncancelable[A](body: Poll[PGConnectionIO] => PGConnectionIO[A]) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - } - final case class Poll1[A](poll: Any, fa: PGConnectionIO[A]) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - } - case object Canceled extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.canceled - } - final case class OnCancel[A](fa: PGConnectionIO[A], fin: PGConnectionIO[Unit]) extends PGConnectionOp[A] { - def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - } - - // PGConnection-specific operations. - final case class AddDataType(a: String, b: Class[? <: org.postgresql.util.PGobject]) extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.addDataType(a, b) - } - case object CancelQuery extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.cancelQuery - } - final case class CreateArrayOf(a: String, b: AnyRef) extends PGConnectionOp[SqlArray] { - def visit[F[_]](v: Visitor[F]) = v.createArrayOf(a, b) - } - final case class EscapeIdentifier(a: String) extends PGConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.escapeIdentifier(a) - } - final case class EscapeLiteral(a: String) extends PGConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.escapeLiteral(a) - } - case object GetAdaptiveFetch extends PGConnectionOp[Boolean] { - def visit[F[_]](v: Visitor[F]) = v.getAdaptiveFetch - } - case object GetAutosave extends PGConnectionOp[AutoSave] { - def visit[F[_]](v: Visitor[F]) = v.getAutosave - } - case object GetBackendPID extends PGConnectionOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getBackendPID - } - case object GetCopyAPI extends PGConnectionOp[PGCopyManager] { - def visit[F[_]](v: Visitor[F]) = v.getCopyAPI - } - case object GetDefaultFetchSize extends PGConnectionOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getDefaultFetchSize - } - case object GetLargeObjectAPI extends PGConnectionOp[LargeObjectManager] { - def visit[F[_]](v: Visitor[F]) = v.getLargeObjectAPI - } - case object GetNotifications extends PGConnectionOp[Array[PGNotification]] { - def visit[F[_]](v: Visitor[F]) = v.getNotifications - } - final case class GetNotifications1(a: Int) extends PGConnectionOp[Array[PGNotification]] { - def visit[F[_]](v: Visitor[F]) = v.getNotifications(a) - } - final case class GetParameterStatus(a: String) extends PGConnectionOp[String] { - def visit[F[_]](v: Visitor[F]) = v.getParameterStatus(a) - } - case object GetParameterStatuses extends PGConnectionOp[java.util.Map[String, String]] { - def visit[F[_]](v: Visitor[F]) = v.getParameterStatuses - } - case object GetPreferQueryMode extends PGConnectionOp[PreferQueryMode] { - def visit[F[_]](v: Visitor[F]) = v.getPreferQueryMode - } - case object GetPrepareThreshold extends PGConnectionOp[Int] { - def visit[F[_]](v: Visitor[F]) = v.getPrepareThreshold - } - case object GetReplicationAPI extends PGConnectionOp[PGReplicationConnection] { - def visit[F[_]](v: Visitor[F]) = v.getReplicationAPI - } - final case class SetAdaptiveFetch(a: Boolean) extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAdaptiveFetch(a) - } - final case class SetAutosave(a: AutoSave) extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setAutosave(a) - } - final case class SetDefaultFetchSize(a: Int) extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setDefaultFetchSize(a) - } - final case class SetPrepareThreshold(a: Int) extends PGConnectionOp[Unit] { - def visit[F[_]](v: Visitor[F]) = v.setPrepareThreshold(a) - } - - } - import PGConnectionOp.* - - // Smart constructors for operations common to all algebras. - val unit: PGConnectionIO[Unit] = FF.pure[PGConnectionOp, Unit](()) - def pure[A](a: A): PGConnectionIO[A] = FF.pure[PGConnectionOp, A](a) - def raw[A](f: PGConnection => A): PGConnectionIO[A] = FF.liftF(Raw(f)) - def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[PGConnectionOp, A] = - FF.liftF(Embed(ev.embed(j, fa))) - def raiseError[A](err: Throwable): PGConnectionIO[A] = FF.liftF[PGConnectionOp, A](RaiseError(err)) - def handleErrorWith[A](fa: PGConnectionIO[A])(f: Throwable => PGConnectionIO[A]): PGConnectionIO[A] = - FF.liftF[PGConnectionOp, A](HandleErrorWith(fa, f)) - val monotonic = FF.liftF[PGConnectionOp, FiniteDuration](Monotonic) - val realtime = FF.liftF[PGConnectionOp, FiniteDuration](Realtime) - def delay[A](thunk: => A) = FF.liftF[PGConnectionOp, A](Suspend(Sync.Type.Delay, () => thunk)) - def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[PGConnectionOp, A](Suspend(hint, () => thunk)) - def forceR[A, B](fa: PGConnectionIO[A])(fb: PGConnectionIO[B]) = FF.liftF[PGConnectionOp, B](ForceR(fa, fb)) - def uncancelable[A](body: Poll[PGConnectionIO] => PGConnectionIO[A]) = FF.liftF[PGConnectionOp, A](Uncancelable(body)) - def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[PGConnectionIO] { - def apply[A](fa: PGConnectionIO[A]) = FF.liftF[PGConnectionOp, A](Poll1(mpoll, fa)) - } - val canceled = FF.liftF[PGConnectionOp, Unit](Canceled) - def onCancel[A](fa: PGConnectionIO[A], fin: PGConnectionIO[Unit]) = FF.liftF[PGConnectionOp, A](OnCancel(fa, fin)) - - // Smart constructors for PGConnection-specific operations. - def addDataType(a: String, b: Class[? <: org.postgresql.util.PGobject]): PGConnectionIO[Unit] = - FF.liftF(AddDataType(a, b)) - val cancelQuery: PGConnectionIO[Unit] = FF.liftF(CancelQuery) - def createArrayOf(a: String, b: AnyRef): PGConnectionIO[SqlArray] = FF.liftF(CreateArrayOf(a, b)) - def escapeIdentifier(a: String): PGConnectionIO[String] = FF.liftF(EscapeIdentifier(a)) - def escapeLiteral(a: String): PGConnectionIO[String] = FF.liftF(EscapeLiteral(a)) - val getAdaptiveFetch: PGConnectionIO[Boolean] = FF.liftF(GetAdaptiveFetch) - val getAutosave: PGConnectionIO[AutoSave] = FF.liftF(GetAutosave) - val getBackendPID: PGConnectionIO[Int] = FF.liftF(GetBackendPID) - val getCopyAPI: PGConnectionIO[PGCopyManager] = FF.liftF(GetCopyAPI) - val getDefaultFetchSize: PGConnectionIO[Int] = FF.liftF(GetDefaultFetchSize) - val getLargeObjectAPI: PGConnectionIO[LargeObjectManager] = FF.liftF(GetLargeObjectAPI) - val getNotifications: PGConnectionIO[Array[PGNotification]] = FF.liftF(GetNotifications) - def getNotifications(a: Int): PGConnectionIO[Array[PGNotification]] = FF.liftF(GetNotifications1(a)) - def getParameterStatus(a: String): PGConnectionIO[String] = FF.liftF(GetParameterStatus(a)) - val getParameterStatuses: PGConnectionIO[java.util.Map[String, String]] = FF.liftF(GetParameterStatuses) - val getPreferQueryMode: PGConnectionIO[PreferQueryMode] = FF.liftF(GetPreferQueryMode) - val getPrepareThreshold: PGConnectionIO[Int] = FF.liftF(GetPrepareThreshold) - val getReplicationAPI: PGConnectionIO[PGReplicationConnection] = FF.liftF(GetReplicationAPI) - def setAdaptiveFetch(a: Boolean): PGConnectionIO[Unit] = FF.liftF(SetAdaptiveFetch(a)) - def setAutosave(a: AutoSave): PGConnectionIO[Unit] = FF.liftF(SetAutosave(a)) - def setDefaultFetchSize(a: Int): PGConnectionIO[Unit] = FF.liftF(SetDefaultFetchSize(a)) - def setPrepareThreshold(a: Int): PGConnectionIO[Unit] = FF.liftF(SetPrepareThreshold(a)) - - private val monad = FF.catsFreeMonadForFree[PGConnectionOp] - - // Typeclass instances for PGConnectionIO - implicit val SyncPGConnectionIO: Sync[PGConnectionIO] = - new Sync[PGConnectionIO] { - override val rootCancelScope = CancelScope.Cancelable - override def pure[A](x: A): PGConnectionIO[A] = monad.pure(x) - override def map[A, B](fa: PGConnectionIO[A])(f: A => B) = monad.map(fa)(f) - override def flatMap[A, B](fa: PGConnectionIO[A])(f: A => PGConnectionIO[B]): PGConnectionIO[B] = - monad.flatMap(fa)(f) - override def tailRecM[A, B](a: A)(f: A => PGConnectionIO[Either[A, B]]): PGConnectionIO[B] = monad.tailRecM(a)(f) - override def raiseError[A](e: Throwable): PGConnectionIO[A] = module.raiseError(e) - override def handleErrorWith[A](fa: PGConnectionIO[A])(f: Throwable => PGConnectionIO[A]): PGConnectionIO[A] = - module.handleErrorWith(fa)(f) - override def monotonic: PGConnectionIO[FiniteDuration] = module.monotonic - override def realTime: PGConnectionIO[FiniteDuration] = module.realtime - override def suspend[A](hint: Sync.Type)(thunk: => A): PGConnectionIO[A] = module.suspend(hint)(thunk) - override def forceR[A, B](fa: PGConnectionIO[A])(fb: PGConnectionIO[B]): PGConnectionIO[B] = module.forceR(fa)(fb) - override def uncancelable[A](body: Poll[PGConnectionIO] => PGConnectionIO[A]): PGConnectionIO[A] = - module.uncancelable(body) - override def canceled: PGConnectionIO[Unit] = module.canceled - override def onCancel[A](fa: PGConnectionIO[A], fin: PGConnectionIO[Unit]): PGConnectionIO[A] = - module.onCancel(fa, fin) - } - - implicit def MonoidPGConnectionIO[A](implicit M: Monoid[A]): Monoid[PGConnectionIO[A]] = - new Monoid[PGConnectionIO[A]] { - override val empty = monad.pure(M.empty) - override def combine(x: PGConnectionIO[A], y: PGConnectionIO[A]) = - monad.product(x, y).map { case (x, y) => M.combine(x, y) } - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/fs2io.scala b/modules/postgres/src/main/scala/doobie/postgres/fs2io.scala deleted file mode 100644 index 0f6871046..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/fs2io.scala +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2013 Functional Streams for Scala - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package doobie.postgres - -import cats.effect.kernel.Sync -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import fs2.Chunk -import fs2.Pipe -import fs2.Stream - -import java.io.InputStream -import java.io.OutputStream - -// Inlined from FS2 to avoid depending on fs2-io -// https://github.com/typelevel/fs2/blob/v3.9.1/io/shared/src/main/scala/fs2/io/io.scala -object fs2io { - - def readInputStream[F[_]]( - fis: F[InputStream], - chunkSize: Int, - closeAfterUse: Boolean = true, - )(implicit F: Sync[F]): Stream[F, Byte] = { - - def read(is: InputStream, buf: Array[Byte]) = { - F.blocking(is.read(buf)).map { numBytes => - if (numBytes < 0) None - else if (numBytes == 0) Some(Chunk.empty) - else if (numBytes < buf.length) Some(Chunk.array(buf, 0, numBytes)) - else Some(Chunk.array(buf)) - } - } - - val buf = F.delay(new Array[Byte](chunkSize)) - - def useIs(is: InputStream) = - Stream - .eval(buf.flatMap(read(is, _))) - .repeat - .unNoneTerminate - .flatMap(Stream.chunk(_)) - - withResource(fis, closeAfterUse).flatMap(useIs) - } - - def writeOutputStream[F[_]]( - fos: F[OutputStream], - closeAfterUse: Boolean = true, - )(implicit F: Sync[F]): Pipe[F, Byte, Nothing] = s => { - - def write(os: OutputStream, b: Array[Byte], off: Int, len: Int) = { - F.interruptible { - os.write(b, off, len) - os.flush() - } - } - - def useOs(os: OutputStream): Stream[F, Nothing] = - s.chunks.foreach { c => - val Chunk.ArraySlice(b, off, len) = c.toArraySlice[Byte] - write(os, b, off, len) - } - - withResource(fos, closeAfterUse).flatMap(os => useOs(os) ++ Stream.exec(F.blocking(os.flush()))) - } - - private def withResource[F[_], V <: AutoCloseable](fv: F[V], closeAfterUse: Boolean)(implicit F: Sync[F]) = { - if (closeAfterUse) { - Stream.bracket(fv)(v => F.blocking(v.close())) - } else Stream.eval(fv) - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/hi/connection.scala b/modules/postgres/src/main/scala/doobie/postgres/hi/connection.scala deleted file mode 100644 index 3c32c95da..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/hi/connection.scala +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.hi - -import cats.data.Kleisli -import cats.free.Free -import cats.~> -import doobie.FC -import doobie.HC -import doobie.HPS -import doobie.free.connection.ConnectionIO -import doobie.postgres.PFPC -import doobie.postgres.free.Embeddable -import doobie.postgres.free.KleisliInterpreter -import doobie.postgres.free.copymanager.CopyManagerIO -import doobie.postgres.free.largeobjectmanager.LargeObjectManagerIO -import doobie.postgres.free.pgconnection.PGConnectionIO -import org.postgresql.PGConnection -import org.postgresql.PGNotification - -/** Module of safe `PGConnectionIO` operations lifted into `ConnectionIO`. */ -object connection { - - // An intepreter for lifting PGConnectionIO into ConnectionIO - val defaultInterpreter: PFPC.PGConnectionOp ~> Kleisli[ConnectionIO, PGConnection, *] = - KleisliInterpreter[ConnectionIO].PGConnectionInterpreter - - val pgGetBackendPID: ConnectionIO[Int] = - pgGetConnection(PFPC.getBackendPID) - - def pgGetConnection[A](k: PGConnectionIO[A]): ConnectionIO[A] = - FC.unwrap(classOf[PGConnection]).flatMap(k.foldMap(defaultInterpreter).run) - - def embed[F[_], J, B](j: J, op: Free[F, B])(implicit ev: Embeddable[F, J]): ConnectionIO[B] = - pgGetConnection(PFPC.embed(j, op)) - - def pgGetCopyAPI[A](k: CopyManagerIO[A]): ConnectionIO[A] = - pgGetConnection(pgconnection.getCopyAPI(k)) - - def pgGetLargeObjectAPI[A](k: LargeObjectManagerIO[A]): ConnectionIO[A] = - pgGetConnection(pgconnection.getLargeObjectAPI(k)) - - val pgGetNotifications: ConnectionIO[List[PGNotification]] = - pgGetConnection(pgconnection.getNotifications) - - val pgGetPrepareThreshold: ConnectionIO[Int] = - pgGetConnection(pgconnection.getPrepareThreshold) - - def pgSetPrepareThreshold(threshold: Int): ConnectionIO[Unit] = - pgGetConnection(pgconnection.setPrepareThreshold(threshold)) - - /** - * Construct a program that notifies on the given channel. Note that the - * channel is NOT sanitized; it cannot be passed as a parameter and is simply - * interpolated into the statement. DO NOT pass user input here. - */ - def pgNotify(channel: String): ConnectionIO[Unit] = - execVoid("NOTIFY " + channel) - - /** - * Construct a program that notifies on the given channel, with a payload. - * Note that neither the channel nor the payload are sanitized; neither can be - * passed as parameters and are simply interpolated into the statement. DO NOT - * pass user input here. - */ - def pgNotify(channel: String, payload: String): ConnectionIO[Unit] = - execVoid(s"NOTIFY $channel, '$payload'") - - /** - * Construct a program that starts listening on the given channel. Note that - * the channel is NOT sanitized; it cannot be passed as a parameter and is - * simply interpolated into the statement. DO NOT pass user input here. - */ - def pgListen(channel: String): ConnectionIO[Unit] = - execVoid("LISTEN " + channel) - - /** - * Construct a program that stops listening on the given channel. Note that - * the channel is NOT sanitized; it cannot be passed as a parameter and is - * simply interpolated into the statement. DO NOT pass user input here. - */ - def pgUnlisten(channel: String): ConnectionIO[Unit] = - execVoid("UNLISTEN " + channel) - - // a helper - private def execVoid(sql: String): ConnectionIO[Unit] = - HC.prepareStatement(sql)(HPS.executeUpdate).map(_ => ()) - -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/hi/largeobject.scala b/modules/postgres/src/main/scala/doobie/postgres/hi/largeobject.scala deleted file mode 100644 index 55857e4c5..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/hi/largeobject.scala +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.hi - -import cats.syntax.apply.* -import doobie.postgres.PFLO -import doobie.postgres.free.largeobject.LargeObjectIO -import doobie.util.io.IOActions - -import java.io.File -import java.io.InputStream -import java.io.OutputStream - -object largeobject { - - val io = new IOActions[LargeObjectIO] - - def copyFromFile(blockSize: Int, file: File): LargeObjectIO[Unit] = - PFLO.getOutputStream.flatMap { os => io.copyFileToStream(blockSize, file, os) *> io.flush(os) } - - def copyToFile(blockSize: Int, file: File): LargeObjectIO[Unit] = - PFLO.getInputStream.flatMap { is => io.copyStreamToFile(blockSize, file, is) } - - def copyFromStream(blockSize: Int, is: InputStream): LargeObjectIO[Unit] = - PFLO.getOutputStream.flatMap { os => - io.copyStream(new Array[Byte](blockSize))(is, os) - } - - def copyToStream(blockSize: Int, os: OutputStream): LargeObjectIO[Unit] = - PFLO.getInputStream.flatMap { is => - io.copyStream(new Array[Byte](blockSize))(is, os) - } -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/hi/largeobjectmanager.scala b/modules/postgres/src/main/scala/doobie/postgres/hi/largeobjectmanager.scala deleted file mode 100644 index 265e09ce8..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/hi/largeobjectmanager.scala +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.hi - -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import doobie.postgres.PFLO -import doobie.postgres.PFLOM -import doobie.postgres.free.largeobject.LargeObjectIO -import doobie.postgres.free.largeobjectmanager.LargeObjectManagerIO - -import java.io.File -import java.io.InputStream -import java.io.OutputStream - -object largeobjectmanager { - - val createLO: LargeObjectManagerIO[Long] = - PFLOM.createLO - - def createLO(a: Int): LargeObjectManagerIO[Long] = - PFLOM.createLO(a) - - def delete(a: Long): LargeObjectManagerIO[Unit] = - PFLOM.delete(a) - - def open[A](a: Long, b: Int)(k: LargeObjectIO[A]): LargeObjectManagerIO[A] = - PFLOM.open(a, b) >>= (PFLOM.embed(_, k <* PFLO.close)) - - def open[A](a: Long)(k: LargeObjectIO[A]): LargeObjectManagerIO[A] = - PFLOM.open(a) >>= (PFLOM.embed(_, k <* PFLO.close)) - - def unlink(a: Long): LargeObjectManagerIO[Unit] = - PFLOM.unlink(a) - - def createLOFromFile(blockSize: Int, file: File): LargeObjectManagerIO[Long] = - createLO >>= { oid => open(oid)(largeobject.copyFromFile(blockSize, file)).as(oid) } - - def createFileFromLO(blockSize: Int, oid: Long, file: File): LargeObjectManagerIO[Unit] = - open(oid)(largeobject.copyToFile(blockSize, file)) - - def createLOFromStream(blockSize: Int, is: InputStream): LargeObjectManagerIO[Long] = - largeobjectmanager.createLO >>= { oid => - largeobjectmanager.open(oid)(largeobject.copyFromStream(blockSize, is)).as(oid) - } - - def createStreamFromLO(blockSize: Int, oid: Long, os: OutputStream): LargeObjectManagerIO[Unit] = - open(oid)(largeobject.copyToStream(blockSize, os)) -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/hi/lostreaming.scala b/modules/postgres/src/main/scala/doobie/postgres/hi/lostreaming.scala deleted file mode 100644 index 4a2968490..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/hi/lostreaming.scala +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.hi - -import cats.syntax.functor.* -import doobie.free.connection.ConnectionIO -import doobie.postgres.PFLO -import doobie.postgres.PFLOM -import fs2.Stream -import org.postgresql.largeobject.LargeObject - -import java.io.InputStream -import java.io.OutputStream - -object lostreaming { - - def createLOFromStream(data: Stream[ConnectionIO, Byte]): ConnectionIO[Long] = - createLO.flatMap { oid => - Stream.bracket(openLO(oid))(closeLO) - .flatMap(lo => data.through(doobie.postgres.fs2io.writeOutputStream(getOutputStream(lo)))) - .compile.drain.as(oid) - } - - def createStreamFromLO(oid: Long, chunkSize: Int): Stream[ConnectionIO, Byte] = - Stream.bracket(openLO(oid))(closeLO) - .flatMap(lo => doobie.postgres.fs2io.readInputStream(getInputStream(lo), chunkSize)) - - private val createLO: ConnectionIO[Long] = - connection.pgGetLargeObjectAPI(PFLOM.createLO) - - private def openLO(oid: Long): ConnectionIO[LargeObject] = - connection.pgGetLargeObjectAPI(PFLOM.open(oid)) - - private def closeLO(lo: LargeObject): ConnectionIO[Unit] = - connection.pgGetLargeObjectAPI(PFLOM.embed(lo, PFLO.close)) - - private def getOutputStream(lo: LargeObject): ConnectionIO[OutputStream] = - connection.pgGetLargeObjectAPI(PFLOM.embed(lo, PFLO.getOutputStream)) - - private def getInputStream(lo: LargeObject): ConnectionIO[InputStream] = - connection.pgGetLargeObjectAPI(PFLOM.embed(lo, PFLO.getInputStream)) -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/hi/package.scala b/modules/postgres/src/main/scala/doobie/postgres/hi/package.scala deleted file mode 100644 index 375f1019a..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/hi/package.scala +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres - -package object hi { - - val PHPC = pgconnection - val PHC = connection - val PHLO = largeobject - val PHLOM = largeobjectmanager - val PHLOS = lostreaming -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/hi/pgconnection.scala b/modules/postgres/src/main/scala/doobie/postgres/hi/pgconnection.scala deleted file mode 100644 index 8291a4508..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/hi/pgconnection.scala +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.hi - -import doobie.postgres.PFPC -import doobie.postgres.free.copymanager.CopyManagerIO -import doobie.postgres.free.largeobjectmanager.LargeObjectManagerIO -import doobie.postgres.free.pgconnection.PGConnectionIO -import org.postgresql.PGNotification - -object pgconnection { - - val getBackendPID: PGConnectionIO[Int] = - PFPC.getBackendPID - - def getCopyAPI[A](k: CopyManagerIO[A]): PGConnectionIO[A] = - PFPC.getCopyAPI.flatMap(s => PFPC.embed(s, k)) // N.B. no need to close() - - def getLargeObjectAPI[A](k: LargeObjectManagerIO[A]): PGConnectionIO[A] = - PFPC.getLargeObjectAPI.flatMap(s => PFPC.embed(s, k)) // N.B. no need to close() - - @SuppressWarnings(Array("org.wartremover.warts.Null")) - val getNotifications: PGConnectionIO[List[PGNotification]] = - PFPC.getNotifications map { - case null => Nil - case ns => ns.toList - } - - val getPrepareThreshold: PGConnectionIO[Int] = - PFPC.getPrepareThreshold - - def setPrepareThreshold(threshold: Int): PGConnectionIO[Unit] = - PFPC.setPrepareThreshold(threshold) - -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala b/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala index ebbaa7c55..5351ab653 100644 --- a/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala +++ b/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala @@ -9,7 +9,7 @@ import doobie.enumerated.JdbcType import doobie.util.invariant.* import doobie.util.meta.Meta import org.postgresql.util.* -import org.tpolecat.typename.* +import doobie.util.typename.* import scala.reflect.ClassTag diff --git a/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala b/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala index 7d4bf0ae1..39de77d01 100644 --- a/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala +++ b/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala @@ -8,7 +8,7 @@ import cats.data.NonEmptyList import doobie.util.Get import doobie.util.Put import org.postgresql.util.PGobject -import org.tpolecat.typename.TypeName +import doobie.util.typename.TypeName object json { diff --git a/modules/postgres/src/main/scala/doobie/postgres/package.scala b/modules/postgres/src/main/scala/doobie/postgres/package.scala deleted file mode 100644 index 1b7fe8611..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/package.scala +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie - -package object postgres { - - val PFCI = doobie.postgres.free.copyin - val PFCM = doobie.postgres.free.copymanager - val PFCO = doobie.postgres.free.copyout - val PFLO = doobie.postgres.free.largeobject - val PFLOM = doobie.postgres.free.largeobjectmanager - val PFPC = doobie.postgres.free.pgconnection - - val PHPC = doobie.postgres.hi.PHPC - val PHC = doobie.postgres.hi.PHC - val PHLO = doobie.postgres.hi.PHLO - val PHLOM = doobie.postgres.hi.PHLOM - val PHLOS = doobie.postgres.hi.PHLOS -} diff --git a/modules/postgres/src/main/scala/doobie/postgres/syntax/explain.scala b/modules/postgres/src/main/scala/doobie/postgres/syntax/explain.scala deleted file mode 100644 index f473c23a8..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/syntax/explain.scala +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.syntax - -import cats.syntax.apply.* -import doobie.free.connection.ConnectionIO -import doobie.hi.HC -import doobie.hi.HPS -import doobie.hi.HRS -import doobie.util.query.Query -import doobie.util.query.Query0 -import doobie.util.update.Update -import doobie.util.update.Update0 - -import scala.language.implicitConversions - -trait ToPostgresExplainOps { - implicit def toPostgresExplainQuery0Ops(q: Query0[?]): PostgresExplainQuery0Ops = - new PostgresExplainQuery0Ops(q) - - implicit def toPostgresExplainQueryOps[A](q: Query[A, ?]): PostgresExplainQueryOps[A] = - new PostgresExplainQueryOps(q) - - implicit def toPostgresExplainUpdate0Ops(u: Update0): PostgresExplainUpdate0Ops = - new PostgresExplainUpdate0Ops(u) - - implicit def toPostgresExplainUpdateOps[A](u: Update[A]): PostgresExplainUpdateOps[A] = - new PostgresExplainUpdateOps(u) -} - -class PostgresExplainQuery0Ops(self: Query0[?]) { - - /** - * Construct a program in [[ConnectionIO]] which returns the server's query - * plan for the query (i.e., `EXPLAIN` output). The query is not actually - * executed. - */ - def explain: ConnectionIO[List[String]] = - self.inspect { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } - - /** - * Construct a program in [[ConnectionIO]] which returns the server's query - * plan for the query, with a comparison to the actual execution (i.e., - * `EXPLAIN ANALYZE` output). The query will be executed, but no results are - * returned. - */ - def explainAnalyze: ConnectionIO[List[String]] = - self.inspect { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN ANALYZE $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } -} - -class PostgresExplainQueryOps[A](self: Query[A, ?]) { - - /** - * Apply the argument `a` to construct a program in [[ConnectionIO]] which - * returns the server's query plan for the query (i.e., `EXPLAIN` output). The - * query is not actually executed. - */ - def explain(a: A): ConnectionIO[List[String]] = { - self.inspect(a) { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } - } - - /** - * Apply the argument `a` to construct a program in [[ConnectionIO]] which - * returns the server's query plan for the query, with a comparison to the - * actual execution (i.e., `EXPLAIN ANALYZE` output). The query will be - * executed, but no results are returned. - */ - def explainAnalyze(a: A): ConnectionIO[List[String]] = - self.inspect(a) { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN ANALYZE $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } -} - -class PostgresExplainUpdate0Ops(self: Update0) { - - /** - * Construct a program in [[ConnectionIO]] which returns the server's query - * plan for the query (i.e., `EXPLAIN` output). The query is not actually - * executed. - */ - def explain: ConnectionIO[List[String]] = - self.inspect { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } - - /** - * Construct a program in [[ConnectionIO]] which returns the server's query - * plan for the query, with a comparison to the actual execution (i.e., - * `EXPLAIN ANALYZE` output). The query will be executed, but no results are - * returned. - */ - def explainAnalyze: ConnectionIO[List[String]] = - self.inspect { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN ANALYZE $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } -} - -class PostgresExplainUpdateOps[A](self: Update[A]) { - - /** - * Apply the argument `a` to construct a program in [[ConnectionIO]] which - * returns the server's query plan for the query (i.e., `EXPLAIN` output). The - * query is not actually executed. - */ - def explain(a: A): ConnectionIO[List[String]] = { - self.inspect(a) { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } - } - - /** - * Apply the argument `a` to construct a program in [[ConnectionIO]] which - * returns the server's query plan for the query, with a comparison to the - * actual execution (i.e., `EXPLAIN ANALYZE` output). The query will be - * executed, but no results are returned. - */ - def explainAnalyze(a: A): ConnectionIO[List[String]] = - self.inspect(a) { (sql, prepare) => - HC.prepareStatement(s"EXPLAIN ANALYZE $sql")(prepare *> HPS.executeQuery(HRS.build[List, String])) - } -} - -object explain extends ToPostgresExplainOps diff --git a/modules/postgres/src/main/scala/doobie/postgres/syntax/fragment.scala b/modules/postgres/src/main/scala/doobie/postgres/syntax/fragment.scala deleted file mode 100644 index cbd5f4a50..000000000 --- a/modules/postgres/src/main/scala/doobie/postgres/syntax/fragment.scala +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres.syntax - -import cats.Foldable -import cats.effect.kernel.Ref -import cats.effect.kernel.Resource -import cats.syntax.applicative.* -import cats.syntax.foldable.* -import doobie.free.connection.ConnectionIO -import doobie.postgres.* -import doobie.util.fragment.Fragment -import fs2.Stream -import fs2.text.utf8.encode - -import java.io.StringReader -import scala.language.implicitConversions - -class FragmentOps(f: Fragment) { - - /** - * Given a fragment of the form `COPY table (col, ...) FROM STDIN` construct a - * `ConnectionIO` that inserts the values provided in `fa`, returning the - * number of affected rows. - */ - def copyIn[F[_]: Foldable, A](fa: F[A])(implicit ev: Text[A]): ConnectionIO[Long] = { - // Fold with a StringBuilder and unsafeEncode to minimize allocations. Note that inserting no - // rows is an error so we shortcut on empty input. - // TODO: stream this rather than constructing the string in memory. - if (fa.isEmpty) 0L.pure[ConnectionIO] - else { - val data = foldToString(fa) - PHC.pgGetCopyAPI(PFCM.copyIn(f.query[Unit].sql, new StringReader(data))) - } - } - - /** - * Given a fragment of the form `COPY table (col, ...) FROM STDIN` construct a - * `ConnectionIO` that inserts the values provided by `stream`, returning the - * number of affected rows. Chunks input `stream` for more efficient sending - * to `STDIN` with `minChunkSize`. - */ - def copyIn[A: Text]( - stream: Stream[ConnectionIO, A], - minChunkSize: Int, - ): ConnectionIO[Long] = { - - val byteStream: Stream[ConnectionIO, Byte] = - stream.chunkMin(minChunkSize).map(foldToString(_)).through(encode) - - // use a reference to capture the number of affected rows, as determined by `endCopy`. - // we need to run that in the finalizer of the `bracket`, and the result from that is ignored. - Ref.of[ConnectionIO, Long](-1L).flatMap { numRowsRef => - val copyAll: ConnectionIO[Unit] = - Stream.bracketCase(PHC.pgGetCopyAPI(PFCM.copyIn(f.query[Unit].sql))) { - case (copyIn, Resource.ExitCase.Succeeded) => - PHC.embed(copyIn, PFCI.endCopy).flatMap(numRowsRef.set) - case (copyIn, _) => - PHC.embed(copyIn, PFCI.cancelCopy) - }.flatMap { copyIn => - byteStream.chunks.evalMap(bytes => - PHC.embed(copyIn, PFCI.writeToCopy(bytes.toArray, 0, bytes.size)), - ) - }.compile.drain - - copyAll.flatMap(_ => numRowsRef.get) - } - } - - /** - * Folds given `F` to string, encoding each `A` with `Text` instance and - * joining resulting strings with `\n` - */ - @SuppressWarnings(Array("org.wartremover.warts.MutableDataStructures", "org.wartremover.warts.ToString")) - private def foldToString[F[_]: Foldable, A](fa: F[A])(implicit ev: Text[A]): String = - fa.foldLeft(new StringBuilder) { (b, a) => - ev.unsafeEncode(a, b) - b.append("\n") - }.toString - -} - -trait ToFragmentOps { - implicit def toFragmentOps(f: Fragment): FragmentOps = - new FragmentOps(f) -} - -object fragment extends ToFragmentOps diff --git a/modules/postgres/src/test/scala/doobie/postgres/LOStreamingSuite.scala b/modules/postgres/src/test/scala/doobie/postgres/LOStreamingSuite.scala deleted file mode 100644 index f2fa29206..000000000 --- a/modules/postgres/src/test/scala/doobie/postgres/LOStreamingSuite.scala +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres - -import doobie.free.connection.ConnectionIO -import fs2.Chunk -import fs2.Pure -import fs2.Stream -import zio.test.Gen -import zio.test.assertTrue -import zio.test.check - -import java.nio.charset.StandardCharsets - -object LOStreamingSuite extends PostgresDatabaseSpec { - - override val spec = suite("LOStreaming")( - test("large object streaming should round-trip") { - val genString = Gen.bounded(2048, 10480)(i => Gen.fromRandom(_.nextString(i))) - val gen = Gen.vectorOfBounded(10, 30)(genString).map { chunks => - chunks.map { str => - Stream.chunk(Chunk.array(str.getBytes(StandardCharsets.UTF_8))) - }.foldLeft(Stream.empty.covaryAll[Pure, Byte])(_ ++ _) - } - check(gen) { data => - val stream = data.covary[ConnectionIO] - - Stream.bracket( - PHLOS.createLOFromStream(stream), - )(oid => PHC.pgGetLargeObjectAPI(PFLOM.unlink(oid))) - .flatMap(oid => PHLOS.createStreamFromLO(oid, chunkSize = 1024 * 5)) - .compile.toVector.transact - .map { result => - assertTrue(result == data.toVector) - } - } - }, - ) -} diff --git a/modules/postgres/src/test/scala/doobie/postgres/LOSuite.scala b/modules/postgres/src/test/scala/doobie/postgres/LOSuite.scala deleted file mode 100644 index 99d59f0b4..000000000 --- a/modules/postgres/src/test/scala/doobie/postgres/LOSuite.scala +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres - -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import zio.ZIO -import zio.test.assertTrue - -import java.io.File -import java.io.FileInputStream -import java.io.FileOutputStream -import java.nio.file.Files - -object LOSuite extends PostgresDatabaseSpec { - - // A big file. Contents are irrelevant. - private val in = new File("init/postgres/test-db.sql") - - override val spec = suite("LO")( - test("large object support should allow round-trip from file to large object and back") { - for { - out <- tempFile - prog = PHLOM.createLOFromFile(1024 * 16, in) >>= { oid => - PHLOM.createFileFromLO(1024 * 16, oid, out) *> PHLOM.delete(oid) - } - _ <- PHC.pgGetLargeObjectAPI(prog).transact - eq <- filesEqual(in, out) - } yield { - assertTrue(eq) - } - }, - test("large object support should allow round-trip from stream to large object and back") { - for { - out <- tempFile - is <- ZIO.acquireRelease( - ZIO.attemptBlocking(new FileInputStream(in)), - )(is => ZIO.attemptBlocking(is.close()).ignoreLogged) - os <- ZIO.acquireRelease( - ZIO.attemptBlocking(new FileOutputStream(out)), - )(os => ZIO.attemptBlocking(os.close()).ignoreLogged) - prog = PHLOM.createLOFromStream(1024 * 16, is) >>= { oid => - PHLOM.createStreamFromLO(1024 * 16, oid, os) *> PHLOM.delete(oid) - } - _ <- PHC.pgGetLargeObjectAPI(prog).transact - eq <- filesEqual(in, out) - } yield { - assertTrue(eq) - } - }, - ) - - private def tempFile = { - ZIO.acquireRelease( - ZIO.attemptBlocking(File.createTempFile("doobie", "tst")), - )(file => ZIO.attemptBlocking(file.delete()).ignoreLogged) - } - - private def filesEqual(f1: File, f2: File) = { - ZIO.attemptBlocking { - Files.readAllBytes(f1.toPath) sameElements Files.readAllBytes(f2.toPath) - } - } -} diff --git a/modules/postgres/src/test/scala/doobie/postgres/ManyRowsSuite.scala b/modules/postgres/src/test/scala/doobie/postgres/ManyRowsSuite.scala deleted file mode 100644 index 0a146bb8b..000000000 --- a/modules/postgres/src/test/scala/doobie/postgres/ManyRowsSuite.scala +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres - -import cats.syntax.apply.* -import doobie.syntax.string.* -import doobie.util.Read -import zio.ZIO -import zio.test.assertTrue -import zoobie.Transactor - -object ManyRowsSuite extends PostgresDatabaseSpec { - - implicit val readTuple: Read[(String, String)] = (Read[String], Read[String]).tupled - - override val spec = suite("ManyRows")( - test("select should take consistent memory") { - for { - transactor <- ZIO.service[Transactor] - q = fr"SELECT a.name, b.name FROM city a, city b".query[(String, String)] - count <- transactor.streamSingleConnection(q.stream).runCount - } yield { - assertTrue(count == 16_638_241) - } - }, - ) - -} diff --git a/modules/postgres/src/test/scala/doobie/postgres/NotifySuite.scala b/modules/postgres/src/test/scala/doobie/postgres/NotifySuite.scala deleted file mode 100644 index 9af21323c..000000000 --- a/modules/postgres/src/test/scala/doobie/postgres/NotifySuite.scala +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres - -import cats.syntax.apply.* -import cats.syntax.show.* -import cats.syntax.traverse.* -import doobie.FC -import doobie.free.connection.ConnectionIO -import zio.Promise -import zio.ZIO -import zio.test.Live -import zio.test.assertTrue -import zoobie.Transactor - -object NotifySuite extends PostgresDatabaseSpec { - - override val spec = suite("Notify")( - test("LISTEN/NOTIFY should allow cross-connection notification") { - for { - channel <- randomChannelName - result <- listen(channel, PHC.pgNotify(channel)) - } yield { - assertTrue(result.length == 1) - } - }, - test("LISTEN/NOTIFY should allow cross-connection notification with parameter") { - for { - channel <- randomChannelName - messages = List("foo", "bar", "baz", "qux") - notify = messages.traverse(PHC.pgNotify(channel, _)) - result <- listen(channel, notify) - } yield { - assertTrue(result.map(_.getParameter) == messages) - } - }, - test("LISTEN/NOTIFY should collapse identical notifications") { - for { - channel <- randomChannelName - messages = List("foo", "bar", "bar", "baz", "qux", "foo") - notify = messages.traverse(PHC.pgNotify(channel, _)) - result <- listen(channel, notify) - } yield { - assertTrue(result.map(_.getParameter) == messages.distinct) - } - }, - ) - - private def listen[A](channel: String, notify: ConnectionIO[A]) = for { - transactor <- ZIO.service[Transactor] - listenConfigured <- Promise.make[Nothing, Unit] - notifySent <- Promise.make[Nothing, Unit] - - fiber <- ZIO.scoped[Any](for { - conn <- transactor.connection - run = transactor.translate(conn) - _ <- run(FC.setAutoCommit(false) *> PHC.pgListen(channel) *> FC.commit) - _ <- listenConfigured.succeed(()) - _ <- notifySent.await - result <- run(PHC.pgGetNotifications) - } yield result).fork - - _ <- listenConfigured.await - _ <- notify.transact - _ <- notifySent.succeed(()) - result <- fiber.join - } yield result - - private def randomChannelName = Live.live(zio.Random.nextUUID).map { uuid => - show"cha_${uuid.toString.replaceAll("-", "")}" - } -} diff --git a/modules/postgres/src/test/scala/doobie/postgres/PGCopySuite.scala b/modules/postgres/src/test/scala/doobie/postgres/PGCopySuite.scala deleted file mode 100644 index 6980fc258..000000000 --- a/modules/postgres/src/test/scala/doobie/postgres/PGCopySuite.scala +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.postgres - -import cats.effect.kernel.Sync -import cats.syntax.applicative.* -import cats.syntax.show.* -import doobie.free.connection.ConnectionIO -import doobie.postgres.syntax.fragment.* -import doobie.syntax.string.* -import doobie.util.fragment.Fragment -import fs2.Stream -import zio.ZIO -import zio.test.Live -import zio.test.assertTrue - -import java.io.ByteArrayOutputStream -import java.nio.charset.StandardCharsets - -object PGCopySuite extends PostgresDatabaseSpec { - - private val minChunkSize = 200 - - override val spec = suite("PGCopy")( - test("copy out should read csv in utf-8 and match expectations") { - - val query = """ - copy ( - select code, name, population - from country - where name like 'U%' - order by code - ) to stdout (encoding 'utf-8', format csv) - """ - - val prog = for { - out <- Sync[ConnectionIO].delay(new ByteArrayOutputStream) - _ <- PHC.pgGetCopyAPI(PFCM.copyOut(query, out)) - } yield new String(out.toByteArray, StandardCharsets.UTF_8) - - prog.transact.map { result => - val expected = """ - |ARE,United Arab Emirates,2441000 - |GBR,United Kingdom,59623400 - |UGA,Uganda,21778000 - |UKR,Ukraine,50456000 - |UMI,United States Minor Outlying Islands,0 - |URY,Uruguay,3337000 - |USA,United States,278357000 - |UZB,Uzbekistan,24318000 - | - """.trim.stripMargin - assertTrue(result == expected) - } - }, - test("A stream with a Pure effect inserts items properly") { - for { - table <- createTable - // A pure stream is fine - can copy many items - count = 10000 - stream = Stream.emits(1 to count) - _ <- fr"COPY $table(data) FROM STDIN".copyIn(stream, minChunkSize).transact - queryCount <- fr"SELECT count(*) FROM $table".query[Int].unique.transact - } yield { - assertTrue(queryCount == count) - } - }, - test("A stream with a ConnectionIO effect copies <= than minChunkSize items") { - for { - table <- createTable - // Can copy up to minChunkSize just fine with ConnectionIO - inputs = 1 to minChunkSize - stream = Stream.emits[ConnectionIO, Int](inputs).evalMap(i => (i + 2).pure[ConnectionIO]) - copiedRows <- fr"COPY $table(data) FROM STDIN".copyIn(stream, minChunkSize).transact - queryCount <- fr"SELECT count(*) FROM $table".query[Int].unique.transact - } yield { - assertTrue(copiedRows == inputs.size.toLong) && - assertTrue(queryCount == minChunkSize) - } - }, - test("A stream with a ConnectionIO effect copies items with count > minChunkSize") { - for { - table <- createTable - inputs = 1 to minChunkSize + 1 - stream = Stream.emits[ConnectionIO, Int](inputs).evalMap(i => (i + 2).pure[ConnectionIO]) - copiedRows <- fr"COPY $table(data) FROM STDIN".copyIn(stream, minChunkSize).transact - queryCount <- fr"SELECT count(*) FROM $table".query[Int].unique.transact - } yield { - assertTrue(copiedRows == inputs.size.toLong) && - assertTrue(queryCount == minChunkSize + 1) - } - }, - ) - - private def createTable = for { - uuid <- Live.live(zio.Random.nextUUID) - table = Fragment.const(show"copy_${uuid.toString.replaceAll("-", "")}") - create = fr"CREATE UNLOGGED TABLE $table(id BIGSERIAL PRIMARY KEY, data BIGINT NOT NULL)".update.run - drop = fr"DROP TABLE IF EXISTS $table".update.run - _ <- ZIO.acquireRelease(create.transact)(_ => drop.transact.ignoreLogged) - } yield table -} diff --git a/modules/postgres/src/test/scala/doobie/postgres/PostgresDatabaseSpec.scala b/modules/postgres/src/test/scala/doobie/postgres/PostgresDatabaseSpec.scala index 5ac2b0c46..67f3dbfd5 100644 --- a/modules/postgres/src/test/scala/doobie/postgres/PostgresDatabaseSpec.scala +++ b/modules/postgres/src/test/scala/doobie/postgres/PostgresDatabaseSpec.scala @@ -1,29 +1,24 @@ package doobie.postgres import doobie.free.connection.ConnectionIO -import fs2.Stream import zio.Chunk import zio.ZIO import zio.ZLayer import zio.durationInt -import zio.stream.ZStream import zio.test.TestAspect import zio.test.ZIOSpec +import zoobie.ConnectionPool import zoobie.ConnectionPoolConfig import zoobie.DatabaseError import zoobie.Transactor import zoobie.postgres.PostgreSQLConnectionConfig -abstract class PostgresDatabaseSpec extends ZIOSpec[Transactor] { self => +abstract class PostgresDatabaseSpec extends ZIOSpec[ConnectionPool & Transactor] { self => def transact[A](io: ConnectionIO[A]): ZIO[Transactor, DatabaseError, A] = { ZIO.serviceWithZIO[Transactor](_.run(io)) } - def transactStream[A](s: Stream[ConnectionIO, A]): ZStream[Transactor, DatabaseError, A] = { - ZStream.serviceWithStream[Transactor](_.stream(s)) - } - implicit class ConnectionIOExtension[A](c: ConnectionIO[A]) { def transact: ZIO[Transactor, DatabaseError, A] = self.transact(c) } @@ -58,13 +53,11 @@ object PostgresDatabaseSpec { validationTimeout = 1.second, ) - val layer: ZLayer[Any, Nothing, Transactor] = ZLayer.scoped[Any] { - createTransactor - } - - private def createTransactor = { - zoobie.postgres.pool(connectionConfig, config).map { pool => + val layer: ZLayer[Any, Nothing, ConnectionPool & Transactor] = { + ZLayer.scoped[Any] { + zoobie.postgres.pool(connectionConfig, config) + } >+> ZLayer.fromZIO(ZIO.serviceWith[ConnectionPool] { pool => Transactor.fromPoolTransactional(pool) - } + }) } } diff --git a/modules/postgres/src/test/scala/doobie/postgres/SyntaxSuite.scala b/modules/postgres/src/test/scala/doobie/postgres/SyntaxSuite.scala index 0d1e9ecf7..e060708bc 100644 --- a/modules/postgres/src/test/scala/doobie/postgres/SyntaxSuite.scala +++ b/modules/postgres/src/test/scala/doobie/postgres/SyntaxSuite.scala @@ -6,8 +6,8 @@ package doobie.postgres import cats.syntax.applicative.* import cats.syntax.functor.* -import doobie.FC import doobie.free.connection.ConnectionIO +import doobie.free.connection.ConnectionIO.MonadErrorConnectionIO import doobie.postgres.syntax.applicativeerror.* import zio.test.ZIOSpecDefault import zio.test.assertCompletes @@ -21,7 +21,7 @@ object SyntaxSuite extends ZIOSpecDefault { assertCompletes }, test("syntax should not overflow the stack on direct recursion") { - def prog: ConnectionIO[Unit] = FC.delay(()).onUniqueViolation(prog) + def prog: ConnectionIO[Unit] = ConnectionIO.delay(()).onUniqueViolation(prog) val _ = prog assertCompletes }, diff --git a/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala b/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala index c9fd5d8e1..feead425f 100644 --- a/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala +++ b/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala @@ -4,17 +4,21 @@ package doobie.postgres -import cats.syntax.apply.* import cats.syntax.functor.* import doobie.free.connection.ConnectionIO import doobie.postgres.instances.array.* -import doobie.postgres.syntax.fragment.* import doobie.syntax.string.* import doobie.util.Read -import fs2.Stream +import org.postgresql.copy.CopyManager +import org.postgresql.jdbc.PgConnection +import zio.ZIO +import zio.interop.catz.core.* +import zio.stream.ZStream import zio.test.Gen import zio.test.assertTrue import zio.test.check +import zoobie.ConnectionProxy +import zoobie.Transactor import java.nio.charset.StandardCharsets @@ -47,18 +51,40 @@ object TextSuite extends PostgresDatabaseSpec { suite("copyIn")( test("insert batches of rows") { check(genRows) { rs => - val copyIn = insert.copyIn(rs) - (create *> copyIn *> selectAll).transact.map { results => - assertTrue(results == rs) - } - } - }, - test("insert batches of rows via Stream") { - check(genRows) { rs => - val copyIn = insert.copyIn(Stream.emits[ConnectionIO, Row](rs), 200) - (create *> copyIn *> selectAll).transact.map { results => + ZIO.scoped(for { + transactor <- ZIO.service[Transactor] + conn <- transactor.connection + interpret = transactor.interpret(conn) + _ <- interpret(ConnectionIO.setAutoCommit(false)) + _ <- interpret(create) + + pgConn = conn.asInstanceOf[ConnectionProxy].connection.asInstanceOf[PgConnection] + copyIn <- ZIO.acquireRelease(ZIO.succeed { + val copy = new CopyManager(pgConn) + copy.copyIn(insert.update.sql) + })(copyIn => { + ZIO.attemptBlocking { + if (copyIn.isActive) { + copyIn.cancelCopy() + } + }.ignoreLogged + }) + _ <- ZStream.fromIterable(rs) + .grouped(200) + .mapZIO { rows => + ZIO.attemptBlocking { + val str = Text.foldToString(rows) + val bytes = pgConn.getEncoding.encode(str) + copyIn.writeToCopy(bytes, 0, bytes.length) + } + } + .runDrain + _ <- ZIO.attemptBlocking(copyIn.endCopy()).ignoreLogged + + results <- interpret(selectAll) + } yield { assertTrue(results == rs) - } + }) } }, ), diff --git a/modules/scalatest/src/main/scala/doobie/scalatest/AnalysisMatchers.scala b/modules/scalatest/src/main/scala/doobie/scalatest/AnalysisMatchers.scala deleted file mode 100644 index 15ee8f901..000000000 --- a/modules/scalatest/src/main/scala/doobie/scalatest/AnalysisMatchers.scala +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.scalatest - -import cats.effect.IO -import cats.effect.kernel.Sync -import doobie.syntax.connectionio.* -import doobie.util.testing.* -import org.scalatest.matchers.LazyArg -import org.scalatest.matchers.MatchResult -import org.scalatest.matchers.Matcher -import org.scalatest.matchers.dsl.MatcherFactory2 - -import scala.reflect.ClassTag - -/** - * Provides matcher syntax for query checking: - * - * {{{ - * sql"select 1".query[Int] must typecheck - * }}} - */ -trait AnalysisMatchers[F[_]] extends CheckerBase[F] { - - val typecheck: MatcherFactory2[Any, Analyzable, ClassTag] = - new MatcherFactory2[Any, Analyzable, ClassTag] { - override def matcher[T: Analyzable: ClassTag]: Matcher[T] = - Matcher(matchTypecheck[T](_)) - } - - private def matchTypecheck[T](t: T)( - implicit analyzable: Analyzable[T], - ): MatchResult = { - val args = analyzable.unpack(t) - val report = U.unsafeRunSync(analyze(args).transact(transactor)) - - MatchResult( - report.succeeded, - s"${args.typeName} failed to typecheck:\n{0}", - s"${args.typeName} did typecheck:\n{0}", - Vector( - // Avoid formatting if the check performed as expected - LazyArg(()) { _ => - formatReport(args, report, colors).padLeft(" ").toString - }, - ), - ) - } -} - -trait IOAnalysisMatchers extends AnalysisMatchers[IO] { - import cats.effect.unsafe.implicits.global - override implicit val M: Sync[IO] = IO.asyncForIO - override implicit val U: UnsafeRun[IO] = new UnsafeRun[IO] { - def unsafeRunSync[A](ioa: IO[A]) = ioa.unsafeRunSync() - } -} diff --git a/modules/scalatest/src/main/scala/doobie/scalatest/Checker.scala b/modules/scalatest/src/main/scala/doobie/scalatest/Checker.scala deleted file mode 100644 index 1fc811e36..000000000 --- a/modules/scalatest/src/main/scala/doobie/scalatest/Checker.scala +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.scalatest - -import cats.effect.IO -import cats.effect.kernel.Sync -import doobie.syntax.connectionio.* -import doobie.util.query.Query -import doobie.util.query.Query0 -import doobie.util.testing.* -import doobie.util.update.Update -import doobie.util.update.Update0 -import org.scalatest.Assertions -import org.tpolecat.typename.* - -/** - * Mix-in trait for specifications that enables checking of doobie `Query` and - * `Update` values. Users must provide an effect type `M` as well as a - * `Transactor[M]` and instances. As a convenience doobie provides - * specializations for common effect types (see other types in this package). - * - * {{{ - * // An example specification, taken from the examples project. - * class ExampleSpec extends AnyFunSuite with IOChecker { - * - * // The transactor to use for the tests. - * val transactor = Transactor.fromDriverManager[IO](...) - * - * // Now just mention the queries. Arguments are not used. - * test("findByNameAndAge") { check(MyDaoModule.findByNameAndAge(null, 0)) } - * test("allWoozles") { check(MyDaoModule.allWoozles) } - * - * } - * }}} - */ -trait Checker[M[_]] extends CheckerBase[M] { self: Assertions => - - def check[A: Analyzable](a: A) = checkImpl(Analyzable.unpack(a)) - - def checkOutput[A: TypeName](q: Query0[A]) = - checkImpl(AnalysisArgs( - s"Query0[${typeName[A]}]", - q.pos, - q.sql, - q.outputAnalysis, - )) - - def checkOutput[A: TypeName, B: TypeName](q: Query[A, B]) = - checkImpl(AnalysisArgs( - s"Query[${typeName[A]}, ${typeName[B]}]", - q.pos, - q.sql, - q.outputAnalysis, - )) - - def checkOutput[A: TypeName](u: Update[A]) = - checkImpl(AnalysisArgs( - s"Update[${typeName[A]}]", - u.pos, - u.sql, - u.analysis, - )) - - def checkOutput(u: Update0) = - checkImpl(AnalysisArgs( - "Update0", - u.pos, - u.sql, - u.analysis, - )) - - private def checkImpl(args: AnalysisArgs) = { - val report = U.unsafeRunSync(analyze(args).transact(transactor)) - if (!report.succeeded) { - fail( - formatReport(args, report, colors) - .padLeft(" ") - .toString, - ) - } - } -} - -/** Implementation of Checker[IO] */ -trait IOChecker extends Checker[IO] { self: Assertions => - import cats.effect.unsafe.implicits.global - override implicit val M: Sync[IO] = IO.asyncForIO - override implicit val U: UnsafeRun[IO] = new UnsafeRun[IO] { - def unsafeRunSync[A](ioa: IO[A]) = ioa.unsafeRunSync() - } -} diff --git a/modules/scalatest/src/test/scala/doobie/scalatest/CheckerTests.scala b/modules/scalatest/src/test/scala/doobie/scalatest/CheckerTests.scala deleted file mode 100644 index 860b2ed3d..000000000 --- a/modules/scalatest/src/test/scala/doobie/scalatest/CheckerTests.scala +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.scalatest - -import cats.effect.IO -import doobie.syntax.string.* -import doobie.util.transactor.Transactor -import org.scalatest.* - -trait CheckerChecks[M[_]] extends funsuite.AnyFunSuite with Checker[M] { - - lazy val transactor = Transactor.fromDriverManager[M]( - "org.h2.Driver", - "jdbc:h2:mem:queryspec;DB_CLOSE_DELAY=-1", - "sa", - "", - ) - - test("trivial") { check(sql"select 1".query[Int]) } - -} - -class IOCheckerCheck extends CheckerChecks[IO] with IOChecker diff --git a/modules/scalatest/src/test/scala/doobie/scalatest/MatcherTests.scala b/modules/scalatest/src/test/scala/doobie/scalatest/MatcherTests.scala deleted file mode 100644 index c12821df9..000000000 --- a/modules/scalatest/src/test/scala/doobie/scalatest/MatcherTests.scala +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2013-2020 Rob Norris and Contributors -// This software is licensed under the MIT License (MIT). -// For more information see LICENSE or https://opensource.org/licenses/MIT - -package doobie.scalatest - -import cats.effect.IO -import doobie.syntax.string.* -import doobie.util.transactor.Transactor -import org.scalatest.* - -trait MatcherChecks[M[_]] extends funsuite.AnyFunSuite - with matchers.must.Matchers - with AnalysisMatchers[M] { - - lazy val transactor = Transactor.fromDriverManager[M]( - "org.h2.Driver", - "jdbc:h2:mem:queryspec;DB_CLOSE_DELAY=-1", - "sa", - "", - ) - - test("valid query should pass") { - sql"select 1".query[Int] must typecheck - } - - test("malformed sql should fail") { - sql"not a valid sql".query[Int].must(not(typecheck)) - } - - test("query with mismatched type should fail") { - sql"select 'foo'".query[Int].must(not(typecheck)) - } -} - -class IOMatcherCheck extends MatcherChecks[IO] with IOChecker diff --git a/modules/weaver/src/main/scala/doobie/weaver/Checker.scala b/modules/weaver/src/main/scala/doobie/weaver/Checker.scala index 731671b7f..59ee630ae 100644 --- a/modules/weaver/src/main/scala/doobie/weaver/Checker.scala +++ b/modules/weaver/src/main/scala/doobie/weaver/Checker.scala @@ -4,6 +4,7 @@ package doobie.weaver +import cats.Functor import cats.effect.kernel.Sync import cats.syntax.functor.* import doobie.syntax.connectionio.* @@ -15,8 +16,8 @@ import doobie.util.testing.Analyzable import doobie.util.testing.analyze import doobie.util.testing.formatReport import doobie.util.transactor.Transactor -import org.tpolecat.typename.TypeName -import org.tpolecat.typename.typeName +import doobie.util.typename.TypeName +import doobie.util.typename.typeName import weaver.Expectations import weaver.Expectations.Helpers.* import weaver.SourceLocation @@ -41,7 +42,7 @@ import weaver.SourceLocation * }}} */ trait Checker[M[_]] { - def check[A: Analyzable](a: A)(implicit M: Sync[M], pos: SourceLocation, transactor: Transactor[M]): M[Expectations] = + def check[A: Analyzable](a: A)(implicit M: Functor[M], pos: SourceLocation, transactor: Transactor[M]): M[Expectations] = checkImpl(Analyzable.unpack(a)) def checkOutput[A: TypeName](q: Query0[A])(implicit @@ -57,7 +58,7 @@ trait Checker[M[_]] { )) def checkOutput[A: TypeName, B: TypeName](q: Query[A, B])(implicit - M: Sync[M], + M: Functor[M], pos: SourceLocation, transactor: Transactor[M], ): M[Expectations] = @@ -68,7 +69,7 @@ trait Checker[M[_]] { q.outputAnalysis, )) - private def checkImpl(args: AnalysisArgs)(implicit M: Sync[M], pos: SourceLocation, transactor: Transactor[M]) = { + private def checkImpl(args: AnalysisArgs)(implicit M: Functor[M], pos: SourceLocation, transactor: Transactor[M]) = { analyze(args).transact(transactor).map { report => if (!report.succeeded) failure(formatReport(args, report, Colors.Ansi) diff --git a/modules/zio/src/it/scala/zoobie/TransactorIntegrationSpec.scala b/modules/zio/src/it/scala/zoobie/TransactorIntegrationSpec.scala new file mode 100644 index 000000000..d33623c50 --- /dev/null +++ b/modules/zio/src/it/scala/zoobie/TransactorIntegrationSpec.scala @@ -0,0 +1,71 @@ +package zoobie + +import cats.syntax.apply.* +import doobie.postgres.PostgresDatabaseSpec +import doobie.syntax.string.* +import zio.ZIO +import zio.durationInt +import zio.test.assertTrue + +object TransactorIntegrationSpec extends PostgresDatabaseSpec { + + override val spec = suite("Transactor")( + test("commits on success") { + for { + transactor <- ZIO.service[Transactor] + + clean = sql"DELETE FROM city WHERE id = 0".update.run + _ <- transactor.run(clean) + + insert = sql""" + INSERT INTO city + (id, name, countrycode, district, population) + VALUES + (0, 'empty', 'ABC', '9', 1) + ON CONFLICT DO NOTHING + """.update.run + _ <- transactor.run(insert) + + select = sql"SELECT name FROM city WHERE id = 0".query[String].option + name <- transactor.run(select) + + _ <- transact(clean) + } yield { + assertTrue(name == Some("empty")) + } + }, + test("rollback on failure") { + for { + transactor <- ZIO.service[Transactor] + select = sql"SELECT name FROM city WHERE id = -1".query[String].option + exists1 <- transactor.run(select) + + insert = sql""" + INSERT INTO city + (id, name, countrycode, district, population) + VALUES + (-1, 'never', 'ABC', '9', 1) + """.update.run + invalid = sql"INVALID SQL".query.option + result <- transactor.run(insert *> invalid).either + + exists2 <- transactor.run(select) + } yield { + assertTrue(exists1 == None) && + assertTrue(result.isLeft) && + assertTrue(exists2 == None) + } + }, + test("cancels query on interrupt") { + for { + transactor <- ZIO.service[Transactor] + sleep = sql"SELECT pg_sleep(30)".update.run + fiber <- transactor.run(sleep).fork + _ <- ZIO.sleep(100.millis) + result <- fiber.interrupt + } yield { + assertTrue(result.isInterrupted) + } + }, + ) +} diff --git a/modules/zio/src/it/scala/zoobie/postgres/PostgreSQLIntegrationSpec.scala b/modules/zio/src/it/scala/zoobie/postgres/PostgresIntegrationSpec.scala similarity index 92% rename from modules/zio/src/it/scala/zoobie/postgres/PostgreSQLIntegrationSpec.scala rename to modules/zio/src/it/scala/zoobie/postgres/PostgresIntegrationSpec.scala index b3ef338f9..6af2de465 100644 --- a/modules/zio/src/it/scala/zoobie/postgres/PostgreSQLIntegrationSpec.scala +++ b/modules/zio/src/it/scala/zoobie/postgres/PostgresIntegrationSpec.scala @@ -4,6 +4,7 @@ import cats.Monoid import cats.syntax.foldable.* import cats.syntax.semigroup.* import cats.syntax.show.* +import doobie.postgres.PostgresDatabaseSpec import doobie.syntax.string.* import zio.Chunk import zio.ZIO @@ -20,7 +21,7 @@ import zoobie.ConnectionPoolConfig import zoobie.DatabaseError import zoobie.Transactor -object PostgreSQLIntegrationSpec extends ZIOSpecDefault { +object PostgresIntegrationSpec extends ZIOSpecDefault { private val AvailableProcessors = Runtime.getRuntime.availableProcessors private val PoolSize = (AvailableProcessors * 2).max(4) @@ -74,7 +75,7 @@ object PostgreSQLIntegrationSpec extends ZIOSpecDefault { for { _ <- TestRandom.setSeed(1234567890) - p <- pool(connectionConfig, config) + p <- pool(PostgresDatabaseSpec.connectionConfig, config) transactor = Transactor.fromPoolTransactional(p) results <- run(transactor) metrics <- ZIO.metrics.map(_.metrics) @@ -97,7 +98,7 @@ object PostgreSQLIntegrationSpec extends ZIOSpecDefault { failure = 24757, error = 24942, )) && - assertTrue(metricPairs == Set( + assertTrue(metricPairs.filter { case (k, _) => k.endsWith("{pool=zoobie-postgres-it}") } == Set( ("zoobie_connections_waiting{pool=zoobie-postgres-it}", 0.0), ("zoobie_connections_in_use{pool=zoobie-postgres-it}", 0.0), ("zoobie_connections_created{pool=zoobie-postgres-it}", (PoolSize * 2).toDouble), @@ -112,14 +113,6 @@ object PostgreSQLIntegrationSpec extends ZIOSpecDefault { TestAspect.withLiveClock, ) - private lazy val connectionConfig = PostgreSQLConnectionConfig( - host = "localhost", - database = "world", - username = "postgres", - password = "password", - applicationName = "doobie", - ) - private lazy val config = ConnectionPoolConfig( name = "zoobie-postgres-it", size = PoolSize, diff --git a/modules/zio/src/it/scala/zoobie/sqlcommenter/SQLCommenterIntegrationSpec.scala b/modules/zio/src/it/scala/zoobie/sqlcommenter/SQLCommenterIntegrationSpec.scala index a34c1ddae..11f2f3e9d 100644 --- a/modules/zio/src/it/scala/zoobie/sqlcommenter/SQLCommenterIntegrationSpec.scala +++ b/modules/zio/src/it/scala/zoobie/sqlcommenter/SQLCommenterIntegrationSpec.scala @@ -1,5 +1,6 @@ package zoobie.sqlcommenter +import doobie.postgres.PostgresDatabaseSpec import doobie.syntax.string.* import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.api.common.Attributes @@ -8,20 +9,15 @@ import io.opentelemetry.api.trace.SpanContext import io.opentelemetry.api.trace.StatusCode import io.opentelemetry.api.trace.TraceFlags import io.opentelemetry.api.trace.TraceState -import zio.Chunk import zio.ZIO -import zio.durationInt -import zio.test.TestAspect -import zio.test.ZIOSpecDefault import zio.test.assertCompletes -import zoobie.ConnectionPoolConfig +import zoobie.ConnectionPool import zoobie.Transactor -import zoobie.postgres.PostgreSQLConnectionConfig -import zoobie.postgres.pool +import java.sql.Connection import java.util.concurrent.TimeUnit -object SQLCommenterIntegrationSpec extends ZIOSpecDefault { +object SQLCommenterIntegrationSpec extends PostgresDatabaseSpec { override val spec = test("SQLCommenterIntegrationSpec") { val spanContext = new SpanContext { @@ -45,34 +41,12 @@ object SQLCommenterIntegrationSpec extends ZIOSpecDefault { } for { - p <- pool(connectionConfig, config) - interpreter = TraceInterpreter.create(Transactor.kleisliInterpreter, ZIO.succeed(Some(span))) - transactor = Transactor(p.get, interpreter.ConnectionInterpreter, Transactor.strategies.transactional) + p <- ZIO.service[ConnectionPool] + interpreter = (c: Connection) => TraceInterpreter.create(Transactor.interpreter(c), ZIO.succeed(Some(span))) + transactor = Transactor(p.get, interpreter, Transactor.strategies.transactional) _ <- transactor.run(fr"SELECT 1".query[Int].unique) } yield { assertCompletes } } - - override val aspects = super.aspects ++ Chunk( - TestAspect.timed, - TestAspect.timeout(90.seconds), - TestAspect.withLiveClock, - ) - - private lazy val connectionConfig = PostgreSQLConnectionConfig( - host = "localhost", - database = "world", - username = "postgres", - password = "password", - applicationName = "doobie", - ) - - private lazy val config = ConnectionPoolConfig( - name = "zoobie-postgres-it", - size = 5, - queueSize = 1_000, - maxConnectionLifetime = 30.seconds, - validationTimeout = 2.seconds, - ) } diff --git a/modules/zio/src/main/scala/zoobie/ConnectionProxy.scala b/modules/zio/src/main/scala/zoobie/ConnectionProxy.scala index 13e94ddf9..646b5c272 100644 --- a/modules/zio/src/main/scala/zoobie/ConnectionProxy.scala +++ b/modules/zio/src/main/scala/zoobie/ConnectionProxy.scala @@ -7,7 +7,7 @@ import java.util.Properties import java.util.concurrent.Executor @SuppressWarnings(Array("org.wartremover.warts.Var")) -class ConnectionProxy(connection: Connection) extends Connection { +class ConnectionProxy(val connection: Connection) extends Connection { private var closed: Boolean = false diff --git a/modules/zio/src/main/scala/zoobie/Transactor.scala b/modules/zio/src/main/scala/zoobie/Transactor.scala index a4d970605..6db81853b 100644 --- a/modules/zio/src/main/scala/zoobie/Transactor.scala +++ b/modules/zio/src/main/scala/zoobie/Transactor.scala @@ -1,79 +1,45 @@ package zoobie import cats.Monad -import cats.effect.kernel.Sync +import cats.free.Free import cats.~> -import doobie.free.KleisliInterpreter import doobie.free.connection.ConnectionIO -import doobie.util.transactor.Interpreter +import doobie.free.connection.ConnectionOp import doobie.util.transactor.Strategy -import fs2.Stream +import zio.Exit import zio.Scope import zio.Task import zio.Trace import zio.ZIO -import zio.stream.ZStream import java.sql.Connection sealed abstract class Transactor { self => - - private val chunkSize = doobie.util.query.DefaultChunkSize + import Transactor.monadTask def connection: ZIO[Scope, DatabaseError.Connection, Connection] - def interpreter: Interpreter[Task] + def interpreter: Connection => ConnectionOp ~> Task + + def interpret(conn: Connection): ConnectionIO ~> Task = Free.foldMap(self.interpreter(conn)) def strategy: Strategy /** * Execute the given [[ConnectionIO]] on a connection using the strategy. */ - def run[A](io: ConnectionIO[A])(implicit trace: Trace): ZIO[Any, DatabaseError, A] = ZIO.scoped { - connection.flatMap(interpret(io)(_)) - } - - /** - * Executes each [[ConnectionIO]] in the stream individually on a connection - * using the strategy. - */ - def stream[A](s: Stream[ConnectionIO, A])(implicit trace: Trace): ZStream[Any, DatabaseError, A] = { - import zio.stream.interop.fs2z.* - - s.translate(new (ConnectionIO ~> Task) { - override def apply[T](io: ConnectionIO[T]) = run(io) - }).toZStream(chunkSize).mapError(DatabaseError(_)) - } - - /** - * Executes each [[ConnectionIO]] in the stream on a single connection using - * the strategy. - * - * Use with care with a strategy that is transactional as the transaction will - * be open until the stream completes. This means if the connection came from - * a pool it will not be returned until the stream completes. - */ - def streamSingleConnection[A](s: Stream[ConnectionIO, A])(implicit trace: Trace): ZStream[Any, DatabaseError, A] = { - import zio.stream.interop.fs2z.* - - ZStream.scoped[Any](connection).flatMap { conn => - Stream.resource(strategy.resource).flatMap(_ => s) - .translate(translate(conn)).toZStream(chunkSize).mapError(DatabaseError(_)) - } - } - - def interpret[A](io: ConnectionIO[A])(c: Connection): ZIO[Any, DatabaseError, A] = { - translate(c) { strategy.resource.use(_ => io) } - .mapError(DatabaseError(_)) - } - - def translate(c: Connection): ConnectionIO ~> Task = { - implicit val monad: Monad[Task] = Transactor.sync - - new (ConnectionIO ~> Task) { - override def apply[T](io: ConnectionIO[T]) = io.foldMap(interpreter).run(c) - } - } + def run[A](io: ConnectionIO[A])(implicit trace: Trace): ZIO[Any, DatabaseError, A] = ZIO.scoped[Any] { + for { + conn <- connection + interpret = Free.foldMap(interpreter(conn)) + _ <- ZIO.acquireRelease(Exit.unit)(_ => interpret(strategy.always).ignoreLogged) + _ <- ZIO.acquireReleaseExit(interpret(strategy.before)) { + case (_, Exit.Success(_)) => interpret(strategy.after).ignoreLogged + case (_, Exit.Failure(_)) => interpret(strategy.oops).ignoreLogged + } + result <- interpret(io) + } yield result + }.mapError(DatabaseError(_)) def withStrategy(s: Strategy): Transactor = new Transactor { override val connection = self.connection @@ -85,21 +51,44 @@ sealed abstract class Transactor { self => object Transactor { - private val sync: Sync[Task] = zio.interop.catz.asyncInstance[Any] - - val kleisliInterpreter: KleisliInterpreter[Task] = KleisliInterpreter(sync) - - val interpreter: Interpreter[Task] = kleisliInterpreter.ConnectionInterpreter - object strategies { val noop: Strategy = Strategy.void val transactional: Strategy = Strategy.default - val rollback: Strategy = Strategy.after.set(transactional, doobie.free.connection.rollback) + val rollback: Strategy = transactional.copy(after = doobie.free.connection.ConnectionIO.rollback) + } + + implicit val monadTask: Monad[Task] = zio.interop.catz.monadErrorInstance + + def interpreter(conn: Connection, fetchSize: Int = 0): ConnectionOp ~> Task = new (ConnectionOp ~> Task) { + import ConnectionOp.* + override def apply[A](fa: ConnectionOp[A]) = fa match { + case Raw(f) => ZIO.attemptBlocking(f(conn)) + case Delay(f) => ZIO.succeed(f()) + case RaiseError(t) => ZIO.fail(t) + case HandleErrorWith(fa, f) => + val run = Free.foldMap(this) + run(fa).catchAll(t => run(f(t))) + + case WithPreparedStatement(sql, create, f) => + ZIO.scoped { + for { + stmt <- ZIO.acquireRelease( + ZIO.attemptBlocking(create(conn, sql)), + )(stmt => ZIO.attemptBlocking(stmt.close()).ignoreLogged) + result <- ZIO.attemptBlockingCancelable({ + if (fetchSize > 0) { + stmt.setFetchSize(fetchSize) + } + f(stmt) + })(ZIO.attemptBlocking(stmt.cancel()).ignoreLogged) + } yield result + } + } } def apply( connection0: ZIO[Scope, DatabaseError.Connection, Connection], - interpreter0: Interpreter[Task], + interpreter0: Connection => ConnectionOp ~> Task, strategy0: Strategy, ): Transactor = new Transactor { override val connection = connection0 @@ -108,7 +97,7 @@ object Transactor { } def fromPool(pool: ConnectionPool, strategy: Strategy): Transactor = { - apply(pool.get, interpreter, strategy) + apply(pool.get, interpreter(_), strategy) } def fromPoolTransactional(pool: ConnectionPool): Transactor = { diff --git a/modules/zio/src/main/scala/zoobie/sqlcommenter/TraceInterpreter.scala b/modules/zio/src/main/scala/zoobie/sqlcommenter/TraceInterpreter.scala index 9992a6209..f3ece7530 100644 --- a/modules/zio/src/main/scala/zoobie/sqlcommenter/TraceInterpreter.scala +++ b/modules/zio/src/main/scala/zoobie/sqlcommenter/TraceInterpreter.scala @@ -1,117 +1,37 @@ package zoobie.sqlcommenter -import cats.data.Kleisli -import cats.effect.kernel.Sync -import doobie.free.KleisliInterpreter +import cats.~> +import doobie.free.connection.ConnectionOp import zio.Task import zio.ZIO object TraceInterpreter { def create( - i: KleisliInterpreter[Task], + i: ConnectionOp ~> Task, currentSpan: ZIO[Any, Nothing, Option[io.opentelemetry.api.trace.Span]], - ): KleisliInterpreter[Task] = { - - implicit val syncM: Sync[Task] = i.syncM - - def addTraceInfo[A, B](sql: String, run: String => Kleisli[Task, A, B]): Kleisli[Task, A, B] = { - val a: Task[String] = currentSpan.map { - case None => sql - case Some(span) => - val ctx = SQLCommenter.Trace.fromOpenTelemetryContext(span.getSpanContext) - val state = SQLCommenter(controller = None, action = None, framework = None, ctx) - SQLCommenter.affix(state, sql) + ): ConnectionOp ~> Task = { + + new (ConnectionOp ~> Task) { + import ConnectionOp.* + override def apply[A](fa: ConnectionOp[A]) = fa match { + case op: Raw[A] => i(op) + case op: Delay[A] => i(op) + case op: RaiseError[A] => i(op) + case op: HandleErrorWith[A] => i(op) + + case op @ WithPreparedStatement(sql, _, _) => + for { + sql_ <- currentSpan.map { + case None => sql + case Some(span) => + val ctx = SQLCommenter.Trace.fromOpenTelemetryContext(span.getSpanContext) + val state = SQLCommenter(controller = None, action = None, framework = None, ctx) + SQLCommenter.affix(state, sql) + } + result <- i(op.copy(sql = sql_)) + } yield result } - Kleisli.liftK(a).flatMap(run(_)) - } - - val TraceConnectionInterpreter = new i.ConnectionInterpreter { - override def prepareCall(a: String) = addTraceInfo(a, super.prepareCall(_)) - override def prepareCall(a: String, b: Int, c: Int) = addTraceInfo(a, super.prepareCall(_, b, c)) - override def prepareCall(a: String, b: Int, c: Int, d: Int) = addTraceInfo(a, super.prepareCall(_, b, c, d)) - - override def prepareStatement(a: String) = addTraceInfo(a, super.prepareStatement(_)) - override def prepareStatement(a: String, b: Array[Int]) = addTraceInfo(a, super.prepareStatement(_, b)) - override def prepareStatement(a: String, b: Array[String]) = addTraceInfo(a, super.prepareStatement(_, b)) - override def prepareStatement(a: String, b: Int) = addTraceInfo(a, super.prepareStatement(_, b)) - override def prepareStatement(a: String, b: Int, c: Int) = addTraceInfo(a, super.prepareStatement(_, b, c)) - override def prepareStatement(a: String, b: Int, c: Int, d: Int) = - addTraceInfo(a, super.prepareStatement(_, b, c, d)) - } - - val TraceStatementInterpreter = new i.StatementInterpreter { - override def execute(a: String) = addTraceInfo(a, super.execute(_)) - override def execute(a: String, b: Array[Int]) = addTraceInfo(a, super.execute(_, b)) - override def execute(a: String, b: Array[String]) = addTraceInfo(a, super.execute(_, b)) - override def execute(a: String, b: Int) = addTraceInfo(a, super.execute(_, b)) - - override def executeLargeUpdate(a: String) = addTraceInfo(a, super.executeLargeUpdate(_)) - override def executeLargeUpdate(a: String, b: Array[Int]) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - override def executeLargeUpdate(a: String, b: Array[String]) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - override def executeLargeUpdate(a: String, b: Int) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - - override def executeQuery(a: String) = addTraceInfo(a, super.executeQuery(_)) - - override def executeUpdate(a: String) = addTraceInfo(a, super.executeUpdate(_)) - override def executeUpdate(a: String, b: Array[Int]) = addTraceInfo(a, super.executeUpdate(_, b)) - override def executeUpdate(a: String, b: Array[String]) = addTraceInfo(a, super.executeUpdate(_, b)) - override def executeUpdate(a: String, b: Int) = addTraceInfo(a, super.executeUpdate(_, b)) - } - - val TracePreparedStatementInterpreter = new i.PreparedStatementInterpreter { - override def execute(a: String) = addTraceInfo(a, super.execute(_)) - override def execute(a: String, b: Array[Int]) = addTraceInfo(a, super.execute(_, b)) - override def execute(a: String, b: Array[String]) = addTraceInfo(a, super.execute(_, b)) - override def execute(a: String, b: Int) = addTraceInfo(a, super.execute(_, b)) - - override def executeLargeUpdate(a: String) = addTraceInfo(a, super.executeLargeUpdate(_)) - override def executeLargeUpdate(a: String, b: Array[Int]) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - override def executeLargeUpdate(a: String, b: Array[String]) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - override def executeLargeUpdate(a: String, b: Int) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - - override def executeQuery(a: String) = addTraceInfo(a, super.executeQuery(_)) - - override def executeUpdate(a: String) = addTraceInfo(a, super.executeUpdate(_)) - override def executeUpdate(a: String, b: Array[Int]) = addTraceInfo(a, super.executeUpdate(_, b)) - override def executeUpdate(a: String, b: Array[String]) = addTraceInfo(a, super.executeUpdate(_, b)) - override def executeUpdate(a: String, b: Int) = addTraceInfo(a, super.executeUpdate(_, b)) - } - - val TraceCallableStatementInterpreter = new i.CallableStatementInterpreter { - override def execute(a: String) = addTraceInfo(a, super.execute(_)) - override def execute(a: String, b: Array[Int]) = addTraceInfo(a, super.execute(_, b)) - override def execute(a: String, b: Array[String]) = addTraceInfo(a, super.execute(_, b)) - override def execute(a: String, b: Int) = addTraceInfo(a, super.execute(_, b)) - - override def executeLargeUpdate(a: String) = addTraceInfo(a, super.executeLargeUpdate(_)) - override def executeLargeUpdate(a: String, b: Array[Int]) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - override def executeLargeUpdate(a: String, b: Array[String]) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - override def executeLargeUpdate(a: String, b: Int) = addTraceInfo(a, super.executeLargeUpdate(_, b)) - - override def executeQuery(a: String) = addTraceInfo(a, super.executeQuery(_)) - - override def executeUpdate(a: String) = addTraceInfo(a, super.executeUpdate(_)) - override def executeUpdate(a: String, b: Array[Int]) = addTraceInfo(a, super.executeUpdate(_, b)) - override def executeUpdate(a: String, b: Array[String]) = addTraceInfo(a, super.executeUpdate(_, b)) - override def executeUpdate(a: String, b: Int) = addTraceInfo(a, super.executeUpdate(_, b)) - } - - new KleisliInterpreter[Task] { - override lazy val NClobInterpreter = i.NClobInterpreter - override lazy val BlobInterpreter = i.BlobInterpreter - override lazy val ClobInterpreter = i.ClobInterpreter - override lazy val DatabaseMetaDataInterpreter = i.DatabaseMetaDataInterpreter - override lazy val DriverInterpreter = i.DriverInterpreter - override lazy val RefInterpreter = i.RefInterpreter - override lazy val SQLDataInterpreter = i.SQLDataInterpreter - override lazy val SQLInputInterpreter = i.SQLInputInterpreter - override lazy val SQLOutputInterpreter = i.SQLOutputInterpreter - override lazy val ConnectionInterpreter = TraceConnectionInterpreter - override lazy val StatementInterpreter = TraceStatementInterpreter - override lazy val PreparedStatementInterpreter = TracePreparedStatementInterpreter - override lazy val CallableStatementInterpreter = TraceCallableStatementInterpreter - override lazy val ResultSetInterpreter = i.ResultSetInterpreter } } diff --git a/modules/zio/src/main/scala/zoobie/test/Checker.scala b/modules/zio/src/main/scala/zoobie/test/Checker.scala index f97591202..8e78e4017 100644 --- a/modules/zio/src/main/scala/zoobie/test/Checker.scala +++ b/modules/zio/src/main/scala/zoobie/test/Checker.scala @@ -2,7 +2,6 @@ package zoobie.test import cats.syntax.apply.* import cats.syntax.show.* -import doobie.FC import doobie.free.connection.ConnectionIO import doobie.util.Colors import zio.ZIO @@ -15,7 +14,7 @@ object Checker { import doobie.util.testing.* def check[A: Analyzable](a: A): ZIO[Transactor, DatabaseError, TestResult] = { - checkWith(FC.unit)(a) + checkWith(ConnectionIO.unit)(a) } def checkWith[A: Analyzable](conn: ConnectionIO[Unit])(a: A): ZIO[Transactor, DatabaseError, TestResult] = for { @@ -24,7 +23,7 @@ object Checker { } yield result def checkConnIO[A: Analyzable](a: A): ConnectionIO[TestResult] = { - checkConnIOWith(FC.unit)(a) + checkConnIOWith(ConnectionIO.unit)(a) } def checkConnIOWith[A: Analyzable](conn: ConnectionIO[Unit])(a: A): ConnectionIO[TestResult] = { diff --git a/modules/zio/src/test/scala/zoobie/ConnectionPoolSpec.scala b/modules/zio/src/test/scala/zoobie/ConnectionPoolSpec.scala index 5705750c9..9291f4bfb 100644 --- a/modules/zio/src/test/scala/zoobie/ConnectionPoolSpec.scala +++ b/modules/zio/src/test/scala/zoobie/ConnectionPoolSpec.scala @@ -1,5 +1,6 @@ package zoobie +import doobie.stub.StubConnection import zio.Chunk import zio.Exit import zio.Promise @@ -12,7 +13,6 @@ import zio.test.TestAspect import zio.test.TestClock import zio.test.ZIOSpecDefault import zio.test.assertTrue -import zoobie.stub.StubConnection import java.sql.SQLTransientConnectionException diff --git a/modules/zio/src/test/scala/zoobie/ConnectionProxySpec.scala b/modules/zio/src/test/scala/zoobie/ConnectionProxySpec.scala index a4c85bb71..32d4ab77a 100644 --- a/modules/zio/src/test/scala/zoobie/ConnectionProxySpec.scala +++ b/modules/zio/src/test/scala/zoobie/ConnectionProxySpec.scala @@ -1,8 +1,8 @@ package zoobie +import doobie.stub.StubConnection import zio.test.ZIOSpecDefault import zio.test.assertTrue -import zoobie.stub.StubConnection @SuppressWarnings(Array("org.wartremover.warts.Null")) object ConnectionProxySpec extends ZIOSpecDefault { diff --git a/modules/zio/src/test/scala/zoobie/TransactorSpec.scala b/modules/zio/src/test/scala/zoobie/TransactorSpec.scala index e4e59c341..56f4d218c 100644 --- a/modules/zio/src/test/scala/zoobie/TransactorSpec.scala +++ b/modules/zio/src/test/scala/zoobie/TransactorSpec.scala @@ -1,10 +1,10 @@ package zoobie +import doobie.stub.StubConnection import doobie.syntax.string.* import zio.ZIO import zio.test.ZIOSpecDefault import zio.test.assertTrue -import zoobie.stub.StubConnection object TransactorSpec extends ZIOSpecDefault { @@ -14,7 +14,7 @@ object TransactorSpec extends ZIOSpecDefault { for { _ <- ZIO.unit connection = new StubConnection(_ => true) - transactor = Transactor(ZIO.succeed(connection), Transactor.interpreter, Transactor.strategies.transactional) + transactor = Transactor(ZIO.succeed(connection), Transactor.interpreter(_), Transactor.strategies.transactional) query = sql"SELECT 1".query.option _ <- transactor.run(query) } yield { @@ -26,7 +26,7 @@ object TransactorSpec extends ZIOSpecDefault { for { _ <- ZIO.unit connection = new StubConnection(_ => true) - transactor = Transactor(ZIO.succeed(connection), Transactor.interpreter, Transactor.strategies.transactional) + transactor = Transactor(ZIO.succeed(connection), Transactor.interpreter(_), Transactor.strategies.transactional) query = sql"INVALID SQL".query.option _ <- transactor.run(query).either } yield { diff --git a/project/FreeGen2.scala b/project/FreeGen2.scala deleted file mode 100644 index 89b96f773..000000000 --- a/project/FreeGen2.scala +++ /dev/null @@ -1,570 +0,0 @@ -import sbt.* -import sbt.Keys.* - -import java.lang.reflect.* -import scala.reflect.ClassTag - -object FreeGen2 { - - lazy val freeGen2Classes = settingKey[List[Class[?]]]("classes for which free algebras should be generated") - lazy val freeGen2Dir = settingKey[File]("directory where free algebras go") - lazy val freeGen2Package = settingKey[String]("package where free algebras go") - lazy val freeGen2Renames = settingKey[Map[Class[?], String]]("map of imports that must be renamed") - lazy val freeGen2 = taskKey[Seq[File]]("generate free algebras") - - lazy val freeGen2Settings = Seq( - freeGen2Classes := Nil, - freeGen2Dir := (Compile / sourceManaged).value, - freeGen2Package := "doobie.free", - freeGen2Renames := Map(classOf[java.sql.Array] -> "SqlArray"), - freeGen2 := new FreeGen2( - freeGen2Classes.value, - freeGen2Package.value, - freeGen2Renames.value, - state.value.log, - ).gen(freeGen2Dir.value), - ) - -} - -class FreeGen2(managed: List[Class[?]], pkg: String, renames: Map[Class[?], String], log: Logger) { - - // These Java classes will have non-Java names in our generated code - val ClassBoolean = classOf[Boolean] - val ClassByte = classOf[Byte] - val ClassShort = classOf[Short] - val ClassInt = classOf[Int] - val ClassLong = classOf[Long] - val ClassFloat = classOf[Float] - val ClassDouble = classOf[Double] - val ClassObject = classOf[Object] - val ClassVoid = Void.TYPE - - def tparams(t: Type): List[String] = t match { - case t: GenericArrayType => tparams(t.getGenericComponentType) - case t: ParameterizedType => t.getActualTypeArguments.toList.flatMap(tparams) - case t: TypeVariable[_] => List(t.toString) - case _ => Nil - } - - def toScalaType(t: Type): String = t match { - case t: GenericArrayType => s"Array[${toScalaType(t.getGenericComponentType)}]" - case t: ParameterizedType => - s"${toScalaType(t.getRawType)}${t.getActualTypeArguments.map(toScalaType).mkString("[", ", ", "]")}" - case t: WildcardType => - t.getUpperBounds.toList.filterNot(_ == classOf[Object]) match { - case (c: Class[_]) :: Nil => s"? <: ${c.getName}" - case Nil => "?" - case cs => sys.error("unhandled upper bounds: " + cs) - } - case t: TypeVariable[_] => t.toString - case ClassVoid => "Unit" - case ClassBoolean => "Boolean" - case ClassByte => "Byte" - case ClassShort => "Short" - case ClassInt => "Int" - case ClassLong => "Long" - case ClassFloat => "Float" - case ClassDouble => "Double" - case ClassObject => "AnyRef" - case x: Class[_] => - if (x.isArray) { - s"Array[${toScalaType(x.getComponentType)}]" - } else if (x.getName == "java.util.Map") { - x.getName - } else { - renames.getOrElse(x, x.getSimpleName) - } - } - - // Each constructor for our algebra maps to an underlying method, and an index is provided to - // disambiguate in cases of overloading. - case class Ctor(method: Method, index: Int) { - - // The method name, unchanged - def mname: String = - method.getName - - // The case class constructor name, capitalized and with an index when needed - def cname: String = { - val s = mname(0).toUpper +: mname.drop(1) - if (index == 0) s else s"$s$index" - } - - // Constructor parameter type names - def cparams: List[String] = - method.getGenericParameterTypes.toList.map(toScalaType) - - def ctparams: String = { - val ss = (method.getGenericParameterTypes.toList.flatMap(tparams) ++ tparams(method.getGenericReturnType)).toSet - if (ss.isEmpty) "" else ss.mkString("[", ", ", "]") - } - - // Constructor arguments, a .. z zipped with the right type - def cargs: List[String] = - "abcdefghijklmnopqrstuvwxyz".toList.zip(cparams).map { - case (n, t) => s"$n: $t" - } - - // Return type name - def ret: String = - toScalaType(method.getGenericReturnType) - - // Case class/object declaration - def ctor(opname: String): String = - ((cparams match { - case Nil => s"|case object $cname" - case ps => s"|final case class $cname$ctparams(${cargs.mkString(", ")})" - }) + s""" extends ${opname}[$ret] { - | def visit[F[_]](v: Visitor[F]) = v.$mname${if (args.isEmpty) "" else s"($args)"} - | }""").trim.stripMargin - - // Argument list: a, b, c, ... up to the proper arity - def args: String = - "abcdefghijklmnopqrstuvwxyz".toList.take(cparams.length).mkString(", ") - - // Pattern to match the constructor - def pat: String = - cparams match { - case Nil => s"object $cname" - case ps => s"class $cname(${cargs.mkString(", ")})" - } - - // Case clause mapping this constructor to the corresponding primitive action - def prim(sname: String): String = - if (cargs.isEmpty) { - s"case $cname => primitive(_.$mname)" - } else { - s"case $cname($args) => primitive(_.$mname($args))" - } - - // Smart constructor - def lifted(ioname: String): String = - if (cargs.isEmpty) { - s"val $mname: ${ioname}[$ret] = FF.liftF(${cname})" - } else { - s"def $mname$ctparams(${cargs.mkString(", ")}): ${ioname}[$ret] = FF.liftF(${cname}($args))" - } - - def visitor: String = - if (cargs.isEmpty) s"| def $mname: F[$ret]" - else s"| def $mname$ctparams(${cargs.mkString(", ")}): F[$ret]" - - def stub: String = - if (cargs.isEmpty) s"""| def $mname: F[$ret] = sys.error("Not implemented: $mname")""" - else s"""| def $mname$ctparams(${cargs.mkString( - ", ", - )}): F[$ret] = sys.error("Not implemented: $mname$ctparams(${cparams.mkString(", ")})")""" - - def kleisliImpl(oname: String): String = - if (cargs.isEmpty) s"| override def $mname: Kleisli[M, $oname, $ret] = primitive(_.$mname)" - else s"| override def $mname$ctparams(${cargs.mkString(", ")}) = primitive(_.$mname($args))" - - } - - // This class, plus any superclasses and interfaces, "all the way up" - def closure(c: Class[?]): List[Class[?]] = - (c :: (Option(c.getSuperclass).toList ++ c.getInterfaces.toList).flatMap(closure)).distinct - .filterNot(_.getName == "java.lang.AutoCloseable") // not available in jdk1.6 - .filterNot(_.getName == "java.lang.Object") // we don't want .equals, etc. - - implicit class MethodOps(m: Method) { - def isStatic: Boolean = - (m.getModifiers & Modifier.STATIC) != 0 - } - - // All non-deprecated methods for this class and any superclasses/interfaces - def methods(c: Class[?]): List[Method] = - closure(c).flatMap(_.getDeclaredMethods.toList).distinct - .filterNot(_.isStatic) - .filter(_.getAnnotation(classOf[Deprecated]) == null) - - // Ctor values for all methods in of A plus superclasses, interfaces, etc. - def ctors[A](implicit ev: ClassTag[A]): List[Ctor] = - methods(ev.runtimeClass).groupBy(_.getName).toList.flatMap { case (n, ms) => - ms.sortBy(_.getGenericParameterTypes.map(toScalaType).mkString(",")).zipWithIndex.map { - case (m, i) => Ctor(m, i) - } - }.sortBy(c => (c.mname, c.index)) - - // Fully qualified rename, if any - def renameImport(c: Class[?]): String = { - renames.get(c) match { - case None => s"import ${c.getName}" - case Some(renamed) => s"import ${c.getPackage.getName}.${c.getSimpleName} as $renamed" - } - } - - // All types referenced by all methods on A, superclasses, interfaces, etc. - def imports[A](implicit ev: ClassTag[A]): List[String] = { - (renameImport(ev.runtimeClass) :: ctors.map(_.method).flatMap { m => - m.getReturnType :: m.getParameterTypes.toList - }.map { t => - if (t.isArray) t.getComponentType else t - }.filterNot { t => - t.isPrimitive || - t == classOf[Object] || - t.getSimpleName == "Class" || - t.getSimpleName == "String" - }.map { c => - renameImport(c) - }).distinct.sorted - } - - // The algebra module for A - def module[A](implicit ev: ClassTag[A]): String = { - val oname = ev.runtimeClass.getSimpleName // original name, without name mapping - val sname = toScalaType(ev.runtimeClass) - val opname = s"${oname}Op" - val ioname = s"${oname}IO" - val mname = oname.toLowerCase - s""" - |// Copyright (c) 2013-2020 Rob Norris and Contributors - |// This software is licensed under the MIT License (MIT). - |// For more information see LICENSE or https://opensource.org/licenses/MIT - | - |package $pkg - | - |import cats.~> - |import cats.effect.kernel.CancelScope - |import cats.effect.kernel.Poll - |import cats.effect.kernel.Sync - |import cats.free.Free as FF // alias because some algebras have an op called Free - |import cats.Monoid - |import scala.concurrent.duration.FiniteDuration - | - |${imports[A].mkString("\n")} - | - |object $mname { module => - | - | // Algebra of operations for $sname. Each accepts a visitor as an alternative to pattern-matching. - | sealed trait ${opname}[A] { - | def visit[F[_]](v: ${opname}.Visitor[F]): F[A] - | } - | - | // Free monad over ${opname}. - | type ${ioname}[A] = FF[${opname}, A] - | - | // Module of instances and constructors of ${opname}. - | @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals")) - | object ${opname} { - | - | // Given a $sname we can embed a ${ioname} program in any algebra that understands embedding. - | implicit val ${opname}Embeddable: Embeddable[${opname}, ${sname}] = - | new Embeddable[${opname}, ${sname}] { - | def embed[A](j: ${sname}, fa: FF[${opname}, A]) = Embedded.${oname}(j, fa) - | } - | - | // Interface for a natural transformation ${opname} ~> F encoded via the visitor pattern. - | // This approach is much more efficient than pattern-matching for large algebras. - | trait Visitor[F[_]] extends (${opname} ~> F) { - | final def apply[A](fa: ${opname}[A]): F[A] = fa.visit(this) - | - | // Common - | def raw[A](f: $sname => A): F[A] - | def embed[A](e: Embedded[A]): F[A] - | def raiseError[A](e: Throwable): F[A] - | def handleErrorWith[A](fa: ${ioname}[A])(f: Throwable => ${ioname}[A]): F[A] - | def monotonic: F[FiniteDuration] - | def realTime: F[FiniteDuration] - | def delay[A](thunk: => A): F[A] - | def suspend[A](hint: Sync.Type)(thunk: => A): F[A] - | def forceR[A, B](fa: ${ioname}[A])(fb: ${ioname}[B]): F[B] - | def uncancelable[A](body: Poll[${ioname}] => ${ioname}[A]): F[A] - | def poll[A](poll: Any, fa: ${ioname}[A]): F[A] - | def canceled: F[Unit] - | def onCancel[A](fa: ${ioname}[A], fin: ${ioname}[Unit]): F[A] - | - | // $sname - ${ctors[A].map(_.visitor).mkString("\n ")} - | - | } - | - | // Common operations for all algebras. - | final case class Raw[A](f: $sname => A) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.raw(f) - | } - | final case class Embed[A](e: Embedded[A]) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.embed(e) - | } - | final case class RaiseError[A](e: Throwable) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.raiseError(e) - | } - | final case class HandleErrorWith[A](fa: ${ioname}[A], f: Throwable => ${ioname}[A]) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.handleErrorWith(fa)(f) - | } - | case object Monotonic extends ${opname}[FiniteDuration] { - | def visit[F[_]](v: Visitor[F]) = v.monotonic - | } - | case object Realtime extends ${opname}[FiniteDuration] { - | def visit[F[_]](v: Visitor[F]) = v.realTime - | } - | final case class Suspend[A](hint: Sync.Type, thunk: () => A) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.suspend(hint)(thunk()) - | } - | final case class ForceR[A, B](fa: ${ioname}[A], fb: ${ioname}[B]) extends ${opname}[B] { - | def visit[F[_]](v: Visitor[F]) = v.forceR(fa)(fb) - | } - | final case class Uncancelable[A](body: Poll[${ioname}] => ${ioname}[A]) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.uncancelable(body) - | } - | final case class Poll1[A](poll: Any, fa: ${ioname}[A]) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.poll(poll, fa) - | } - | case object Canceled extends ${opname}[Unit] { - | def visit[F[_]](v: Visitor[F]) = v.canceled - | } - | final case class OnCancel[A](fa: ${ioname}[A], fin: ${ioname}[Unit]) extends ${opname}[A] { - | def visit[F[_]](v: Visitor[F]) = v.onCancel(fa, fin) - | } - | - | // $sname-specific operations. - | ${ctors[A].map(_.ctor(opname)).mkString("\n ")} - | - | } - | import ${opname}.* - | - | // Smart constructors for operations common to all algebras. - | val unit: ${ioname}[Unit] = FF.pure[${opname}, Unit](()) - | def pure[A](a: A): ${ioname}[A] = FF.pure[${opname}, A](a) - | def raw[A](f: $sname => A): ${ioname}[A] = FF.liftF(Raw(f)) - | def embed[F[_], J, A](j: J, fa: FF[F, A])(implicit ev: Embeddable[F, J]): FF[${opname}, A] = FF.liftF(Embed(ev.embed(j, fa))) - | def raiseError[A](err: Throwable): ${ioname}[A] = FF.liftF[${opname}, A](RaiseError(err)) - | def handleErrorWith[A](fa: ${ioname}[A])(f: Throwable => ${ioname}[A]): ${ioname}[A] = FF.liftF[${opname}, A](HandleErrorWith(fa, f)) - | val monotonic = FF.liftF[${opname}, FiniteDuration](Monotonic) - | val realtime = FF.liftF[${opname}, FiniteDuration](Realtime) - | def delay[A](thunk: => A) = FF.liftF[${opname}, A](Suspend(Sync.Type.Delay, () => thunk)) - | def suspend[A](hint: Sync.Type)(thunk: => A) = FF.liftF[${opname}, A](Suspend(hint, () => thunk)) - | def forceR[A, B](fa: ${ioname}[A])(fb: ${ioname}[B]) = FF.liftF[${opname}, B](ForceR(fa, fb)) - | def uncancelable[A](body: Poll[${ioname}] => ${ioname}[A]) = FF.liftF[${opname}, A](Uncancelable(body)) - | def capturePoll[M[_]](mpoll: Poll[M]) = new Poll[${ioname}] { - | def apply[A](fa: ${ioname}[A]) = FF.liftF[${opname}, A](Poll1(mpoll, fa)) - | } - | val canceled = FF.liftF[${opname}, Unit](Canceled) - | def onCancel[A](fa: ${ioname}[A], fin: ${ioname}[Unit]) = FF.liftF[${opname}, A](OnCancel(fa, fin)) - | - | // Smart constructors for $oname-specific operations. - | ${ctors[A].map(_.lifted(ioname)).mkString("\n ")} - | - | private val monad = FF.catsFreeMonadForFree[${opname}] - | - | // Typeclass instances for ${ioname} - | implicit val Sync${ioname}: Sync[${ioname}] = - | new Sync[${ioname}] { - | override val rootCancelScope = CancelScope.Cancelable - | override def pure[A](x: A): ${ioname}[A] = monad.pure(x) - | override def map[A, B](fa: ${ioname}[A])(f: A => B) = monad.map(fa)(f) - | override def flatMap[A, B](fa: ${ioname}[A])(f: A => ${ioname}[B]): ${ioname}[B] = monad.flatMap(fa)(f) - | override def tailRecM[A, B](a: A)(f: A => ${ioname}[Either[A, B]]): ${ioname}[B] = monad.tailRecM(a)(f) - | override def raiseError[A](e: Throwable): ${ioname}[A] = module.raiseError(e) - | override def handleErrorWith[A](fa: ${ioname}[A])(f: Throwable => ${ioname}[A]): ${ioname}[A] = module.handleErrorWith(fa)(f) - | override def monotonic: ${ioname}[FiniteDuration] = module.monotonic - | override def realTime: ${ioname}[FiniteDuration] = module.realtime - | override def suspend[A](hint: Sync.Type)(thunk: => A): ${ioname}[A] = module.suspend(hint)(thunk) - | override def forceR[A, B](fa: ${ioname}[A])(fb: ${ioname}[B]): ${ioname}[B] = module.forceR(fa)(fb) - | override def uncancelable[A](body: Poll[${ioname}] => ${ioname}[A]): ${ioname}[A] = module.uncancelable(body) - | override def canceled: ${ioname}[Unit] = module.canceled - | override def onCancel[A](fa: ${ioname}[A], fin: ${ioname}[Unit]): ${ioname}[A] = module.onCancel(fa, fin) - | } - | - | implicit def Monoid${ioname}[A](implicit M: Monoid[A]): Monoid[${ioname}[A]] = - | new Monoid[${ioname}[A]] { - | override val empty = monad.pure(M.empty) - | override def combine(x: ${ioname}[A], y: ${ioname}[A]) = - | monad.product(x, y).map { case (x, y) => M.combine(x, y) } - | } - |} - |""".trim.stripMargin - } - - def embed[A](implicit ev: ClassTag[A]): String = { - val sname = ev.runtimeClass.getSimpleName - s"final case class $sname[A](j: ${ev.runtimeClass.getName}, fa: ${sname}IO[A]) extends Embedded[A]" - } - - // Import for the IO type for a carrer type, with renaming - def ioImport(c: Class[?]): String = { - val sn = c.getSimpleName - s"import ${sn.toLowerCase}.${sn}IO" - } - - // The Embedded definition for all modules. - def embeds: String = - s""" - |// Copyright (c) 2013-2020 Rob Norris and Contributors - |// This software is licensed under the MIT License (MIT). - |// For more information see LICENSE or https://opensource.org/licenses/MIT - | - |package $pkg - | - |import cats.free.Free - | - |${managed.map(ioImport).mkString("\n")} - | - |// A pair (J, Free[F, A]) with constructors that tie down J and F. - |sealed trait Embedded[A] - | - |object Embedded { - | ${managed.map(ClassTag(_)).map(embed(_)).mkString("\n ")} - |} - | - |// Typeclass for embeddable pairs (J, F) - |trait Embeddable[F[_], J] { - | def embed[A](j: J, fa: Free[F, A]): Embedded[A] - |} - |""".trim.stripMargin - - def interp[A](implicit ev: ClassTag[A]): String = { - val oname = ev.runtimeClass.getSimpleName // original name, without name mapping - val sname = toScalaType(ev.runtimeClass) - val opname = s"${oname}Op" - val ioname = s"${oname}IO" - val mname = oname.toLowerCase - - def kles(retType: String) = s"Kleisli[M, $sname, $retType]" - val klesA = kles("A") - val klesUnit = kles("Unit") - s""" - | trait ${oname}Interpreter extends ${oname}Op.Visitor[Kleisli[M, $sname, *]] { - | - | // common operations delegate to outer interpreter - | override def raw[A](f: ${sname} => A): $klesA = outer.raw(f) - | override def embed[A](e: Embedded[A]): $klesA = outer.embed(e) - | override def raiseError[A](e: Throwable): $klesA = outer.raiseError(e) - | override def monotonic: ${kles("FiniteDuration")} = outer.monotonic[${sname}] - | override def realTime: ${kles("FiniteDuration")} = outer.realTime[${sname}] - | override def delay[A](thunk: => A): $klesA = outer.delay(thunk) - | override def suspend[A](hint: Sync.Type)(thunk: => A): $klesA = outer.suspend(hint)(thunk) - | override def canceled: $klesUnit = outer.canceled[${sname}] - | - | // for operations using ${ioname} we must call ourself recursively - | override def handleErrorWith[A](fa: ${ioname}[A])(f: Throwable => ${ioname}[A]): $klesA = outer.handleErrorWith(this)(fa)(f) - | override def forceR[A, B](fa: ${ioname}[A])(fb: ${ioname}[B]): ${kles("B")} = outer.forceR(this)(fa)(fb) - | override def uncancelable[A](body: Poll[${ioname}] => ${ioname}[A]): $klesA = outer.uncancelable(this, ${pkg}.${mname}.capturePoll)(body) - | override def poll[A](poll: Any, fa: ${ioname}[A]): $klesA = outer.poll(this)(poll, fa) - | override def onCancel[A](fa: ${ioname}[A], fin: ${ioname}[Unit]): $klesA = outer.onCancel(this)(fa, fin) - | - | // domain-specific operations are implemented in terms of `primitive` - |${ctors[A].map(_.kleisliImpl(sname)).mkString("\n")} - | - | } - |""".trim.stripMargin - } - - def interpreterDef(c: Class[?]): String = { - val oname = c.getSimpleName // original name, without name mapping - val sname = toScalaType(c) - val opname = s"${oname}Op" - val ioname = s"${oname}IO" - val mname = oname.toLowerCase - s"lazy val ${oname}Interpreter: ${opname} ~> Kleisli[M, $sname, *] = new ${oname}Interpreter { }" - } - - // template for a kleisli interpreter - def kleisliInterpreter: String = - s""" - |// Copyright (c) 2013-2020 Rob Norris and Contributors - |// This software is licensed under the MIT License (MIT). - |// For more information see LICENSE or https://opensource.org/licenses/MIT - | - |package $pkg - | - |import cats.~> - |import cats.data.Kleisli - |import cats.effect.kernel.Poll - |import cats.effect.kernel.Sync - |import cats.free.Free - |import scala.concurrent.duration.FiniteDuration - | - |${managed.map(ClassTag(_)).flatMap(imports(_)).distinct.sorted.mkString("\n")} - | - |${managed.map(_.getSimpleName).map(c => s"import ${pkg}.${c.toLowerCase}.{ ${c}IO, ${c}Op }").mkString("\n")} - | - |object KleisliInterpreter { - | def apply[M[_]](implicit M: Sync[M]): KleisliInterpreter[M] = new KleisliInterpreter[M] - |} - | - |// Family of interpreters into Kleisli arrows for some monad M. - |class KleisliInterpreter[M[_]](implicit val syncM: Sync[M]) { outer => - | - | // The ${managed.length} interpreters, with definitions below. These can be overridden to customize behavior. - | ${managed.map(interpreterDef).mkString("\n ")} - | - | // Some methods are common to all interpreters and can be overridden to change behavior globally. - | def primitive[J, A](f: J => A): Kleisli[M, J, A] = Kleisli { a => - | // primitive JDBC methods throw exceptions and so do we when reading values - | // so catch any non-fatal exceptions and lift them into the effect - | try { - | syncM.blocking(f(a)) - | } catch { - | case e if scala.util.control.NonFatal(e) => syncM.raiseError(e) - | } - | } - | def raw[J, A](f: J => A): Kleisli[M, J, A] = primitive(f) - | def raiseError[J, A](e: Throwable): Kleisli[M, J, A] = Kleisli(_ => syncM.raiseError(e)) - | def monotonic[J]: Kleisli[M, J, FiniteDuration] = Kleisli(_ => syncM.monotonic) - | def realTime[J]: Kleisli[M, J, FiniteDuration] = Kleisli(_ => syncM.realTime) - | def delay[J, A](thunk: => A): Kleisli[M, J, A] = Kleisli(_ => syncM.delay(thunk)) - | def suspend[J, A](hint: Sync.Type)(thunk: => A): Kleisli[M, J, A] = Kleisli(_ => syncM.suspend(hint)(thunk)) - | def canceled[J]: Kleisli[M, J, Unit] = Kleisli(_ => syncM.canceled) - | - | // for operations using free structures we call the interpreter recursively - | def handleErrorWith[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A])(f: Throwable => Free[G, A]): Kleisli[M, J, A] = Kleisli { j => - | syncM.handleErrorWith(fa.foldMap(interpreter).run(j))(f.andThen(_.foldMap(interpreter).run(j))) - | } - | def forceR[G[_], J, A, B](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A])(fb: Free[G, B]): Kleisli[M, J, B] = Kleisli { j => - | syncM.forceR(fa.foldMap(interpreter).run(j))(fb.foldMap(interpreter).run(j)) - | } - | def uncancelable[G[_], J, A](interpreter: G ~> Kleisli[M, J, *], capture: Poll[M] => Poll[Free[G, *]])(body: Poll[Free[G, *]] => Free[G, A]): Kleisli[M, J, A] = Kleisli { j => - | syncM.uncancelable(body.compose(capture).andThen(_.foldMap(interpreter).run(j))) - | } - | @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf")) - | def poll[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(mpoll: Any, fa: Free[G, A]): Kleisli[M, J, A] = Kleisli { j => - | mpoll.asInstanceOf[Poll[M]].apply(fa.foldMap(interpreter).run(j)) - | } - | def onCancel[G[_], J, A](interpreter: G ~> Kleisli[M, J, *])(fa: Free[G, A], fin: Free[G, Unit]): Kleisli[M, J, A] = Kleisli { j => - | syncM.onCancel(fa.foldMap(interpreter).run(j), fin.foldMap(interpreter).run(j)) - | } - | def embed[J, A](e: Embedded[A]): Kleisli[M, J, A] = e match { - | ${managed.map(_.getSimpleName).map(n => - s"case Embedded.${n}(j, fa) => Kleisli(_ => fa.foldMap(${n}Interpreter).run(j))", - ).mkString("\n ")} - | } - | - | // Interpreters - |${managed.map(ClassTag(_)).map(interp(_)).mkString("\n")} - | - |} - |""".trim.stripMargin - - def gen(base: File): Seq[File] = { - log.info("Generating free algebras into " + base) - val fs = managed.map { c => - base.mkdirs - val mod = module(ClassTag(c)) - val file = printToFile(base, s"${c.getSimpleName.toLowerCase}.scala", mod) - log.info(s"${c.getName} -> ${file.getName}") - file - } - val e = { - val file = printToFile(base, "embedded.scala", embeds) - log.info(s"... -> ${file.getName}") - file - } - val ki = { - val file = printToFile(base, "kleisliinterpreter.scala", kleisliInterpreter) - log.info(s"... -> ${file.getName}") - file - } - ki :: e :: fs - } - - private def printToFile(base: File, name: String, data: String) = { - val file = new File(base, name) - val pw = new java.io.PrintWriter(file) - pw.println(data) - pw.close() - file - } - -} diff --git a/project/build.properties b/project/build.properties index 489e0a72d..e480c675f 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.4 +sbt.version=1.11.5 diff --git a/project/build.sbt b/project/build.sbt deleted file mode 100644 index 5f60edc41..000000000 --- a/project/build.sbt +++ /dev/null @@ -1,3 +0,0 @@ -// Required for the freegen definition for postgres in ../build.sbt -val postgresVersion = "42.7.7" -libraryDependencies += "org.postgresql" % "postgresql" % postgresVersion From 2c235c6f3bc528a019d08e723b4d353b2de1459b Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sun, 31 Aug 2025 14:55:16 +1000 Subject: [PATCH 2/7] fmt --- .../src/main/scala/doobie/free/connection/ConnectionIO.scala | 2 +- .../core/src/main/scala/doobie/util/testing/analysis.scala | 2 +- .../main/scala-3/doobie/util/TypeNamePlatform.scala.scala | 5 +++-- .../src/main/scala/doobie/postgis/instances/geography.scala | 2 +- .../src/main/scala/doobie/postgis/instances/geometry.scala | 2 +- .../main/scala/doobie/postgres/instances/enumeration.scala | 2 +- .../src/main/scala/doobie/postgres/instances/json.scala | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala b/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala index fda4346fa..72851b2bc 100644 --- a/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala +++ b/modules/core/src/main/scala/doobie/free/connection/ConnectionIO.scala @@ -97,7 +97,7 @@ object ConnectionIO { self => b.result() } - def collectPair[F[_], A, K, V](sql: String, a: A)(implicit + def collectPair[A, K, V](sql: String, a: A)(implicit R: Read[(K, V)], W: Write[A], factory: Factory[(K, V), Map[K, V]], diff --git a/modules/core/src/main/scala/doobie/util/testing/analysis.scala b/modules/core/src/main/scala/doobie/util/testing/analysis.scala index 8322e000a..f56d61e11 100644 --- a/modules/core/src/main/scala/doobie/util/testing/analysis.scala +++ b/modules/core/src/main/scala/doobie/util/testing/analysis.scala @@ -13,9 +13,9 @@ import doobie.util.pretty.* import doobie.util.query.Query import doobie.util.query.Query0 import doobie.util.transactor.Transactor +import doobie.util.typename.* import doobie.util.update.Update import doobie.util.update.Update0 -import doobie.util.typename.* /** * Common base trait for various checkers and matchers. diff --git a/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala b/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala index 2dcab6de8..5d1163c80 100644 --- a/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala +++ b/modules/macros/src/main/scala-3/doobie/util/TypeNamePlatform.scala.scala @@ -5,18 +5,19 @@ package doobie.util import doobie.util.typename.TypeName + import scala.quoted.* trait TypeNamePlatform { inline given [A]: TypeName[A] = - ${TypeNamePlatform.impl[A]} + ${ TypeNamePlatform.impl[A] } } object TypeNamePlatform { def impl[A](using t: Type[A], ctx: Quotes): Expr[TypeName[A]] = - '{TypeName[A](${Expr(Type.show[A])})} + '{ TypeName[A](${ Expr(Type.show[A]) }) } } diff --git a/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala b/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala index 80a96fb14..8299a61cd 100644 --- a/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala +++ b/modules/postgis/src/main/scala/doobie/postgis/instances/geography.scala @@ -6,9 +6,9 @@ package doobie.postgis.instances import doobie.util.invariant.* import doobie.util.meta.Meta +import doobie.util.typename.* import net.postgis.jdbc.PGgeography import net.postgis.jdbc.geometry.* -import doobie.util.typename.* import scala.reflect.ClassTag diff --git a/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala b/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala index e1d8768e9..c6631b586 100644 --- a/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala +++ b/modules/postgis/src/main/scala/doobie/postgis/instances/geometry.scala @@ -6,9 +6,9 @@ package doobie.postgis.instances import doobie.util.invariant.* import doobie.util.meta.Meta +import doobie.util.typename.* import net.postgis.jdbc.* import net.postgis.jdbc.geometry.* -import doobie.util.typename.* import scala.reflect.ClassTag diff --git a/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala b/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala index 5351ab653..3e7c5d0d8 100644 --- a/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala +++ b/modules/postgres/src/main/scala/doobie/postgres/instances/enumeration.scala @@ -8,8 +8,8 @@ import cats.data.NonEmptyList import doobie.enumerated.JdbcType import doobie.util.invariant.* import doobie.util.meta.Meta -import org.postgresql.util.* import doobie.util.typename.* +import org.postgresql.util.* import scala.reflect.ClassTag diff --git a/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala b/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala index 39de77d01..f8f6cf5e0 100644 --- a/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala +++ b/modules/postgres/src/main/scala/doobie/postgres/instances/json.scala @@ -7,8 +7,8 @@ package doobie.postgres.instances import cats.data.NonEmptyList import doobie.util.Get import doobie.util.Put -import org.postgresql.util.PGobject import doobie.util.typename.TypeName +import org.postgresql.util.PGobject object json { From 5a9c8d7039204023918bd87e7d58319fe8f9378f Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sun, 31 Aug 2025 15:02:03 +1000 Subject: [PATCH 3/7] fix --- .github/workflows/ci.yml | 6 +++--- .../postgres/src/test/scala/doobie/postgres/TextSuite.scala | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 910bf2678..bebd681fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,6 @@ jobs: - name: Test run: sbt ++${{ matrix.scala }} modules/test - - name: Check Doc Site - if: ${{ startsWith(matrix.scala, '2.13.') }} - run: sbt ++${{ matrix.scala }} docs/makeSite +# - name: Check Doc Site +# if: ${{ startsWith(matrix.scala, '2.13.') }} +# run: sbt ++${{ matrix.scala }} docs/makeSite diff --git a/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala b/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala index feead425f..6c50b961a 100644 --- a/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala +++ b/modules/postgres/src/test/scala/doobie/postgres/TextSuite.scala @@ -82,6 +82,7 @@ object TextSuite extends PostgresDatabaseSpec { _ <- ZIO.attemptBlocking(copyIn.endCopy()).ignoreLogged results <- interpret(selectAll) + _ <- interpret(ConnectionIO.commit) } yield { assertTrue(results == rs) }) From 00b171c2c35e30a1df217ab432ed5ac8e001c9c9 Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sat, 6 Sep 2025 09:59:57 +1000 Subject: [PATCH 4/7] custom monad instance to avoid deps --- build.sbt | 12 +-- .../src/main/scala/zoobie/Transactor.scala | 2 +- .../main/scala/zoobie/interop/ZioMonad.scala | 87 +++++++++++++++++++ 3 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala diff --git a/build.sbt b/build.sbt index 96b0f6c07..9de3cdd0e 100644 --- a/build.sbt +++ b/build.sbt @@ -200,6 +200,7 @@ lazy val core = module("core") "com.h2database" % "h2" % h2Version % Test, "dev.zio" %% "zio-interop-cats" % zioInteropCats % Test, + "dev.zio" %% "zio-managed" % zioVersion % Test, "org.typelevel" %% "cats-effect" % catsEffectVersion % Test, "dev.zio" %% "zio-test" % zioVersion % Test, "dev.zio" %% "zio-test-sbt" % zioVersion % Test, @@ -264,6 +265,7 @@ lazy val h2 = module("h2") "org.typelevel" %% "cats-effect-kernel" % catsEffectVersion, "dev.zio" %% "zio-interop-cats" % zioInteropCats % Test, + "dev.zio" %% "zio-managed" % zioVersion % Test, "org.typelevel" %% "cats-effect" % catsEffectVersion % Test, "dev.zio" %% "zio-test" % zioVersion % Test, "dev.zio" %% "zio-test-sbt" % zioVersion % Test, @@ -294,15 +296,7 @@ lazy val zio = module("zio") .settings( libraryDependencies ++= Seq( "dev.zio" %% "zio" % zioVersion, - ("dev.zio" %% "zio-interop-cats" % zioInteropCats) // optional deps in 2.13 but not in 3 ... - .excludeAll("co.fs2" %% "fs2-core") - .excludeAll("co.fs2" %% "fs2-io") - //.excludeAll("dev.zio" %% "zio-managed") required for compilation - .excludeAll("dev.zio" %% "zio-streams") - .excludeAll("org.typelevel" %% "cats-effect-std") - .excludeAll("org.typelevel" %% "cats-mtl"), - // urgh "Cannot resolve reference to type cats.effect.type.LiftIO" - "org.typelevel" %% "cats-effect" % catsEffectVersion, + "dev.zio" %% "zio-interop-tracer" % zioInteropCats, "dev.zio" %% "zio-test" % zioVersion % Optional, "com.mysql" % "mysql-connector-j" % mysqlVersion % Optional, diff --git a/modules/zio/src/main/scala/zoobie/Transactor.scala b/modules/zio/src/main/scala/zoobie/Transactor.scala index 6db81853b..ee9f5889f 100644 --- a/modules/zio/src/main/scala/zoobie/Transactor.scala +++ b/modules/zio/src/main/scala/zoobie/Transactor.scala @@ -57,7 +57,7 @@ object Transactor { val rollback: Strategy = transactional.copy(after = doobie.free.connection.ConnectionIO.rollback) } - implicit val monadTask: Monad[Task] = zio.interop.catz.monadErrorInstance + implicit val monadTask: Monad[Task] = zoobie.interop.ZioMonad def interpreter(conn: Connection, fetchSize: Int = 0): ConnectionOp ~> Task = new (ConnectionOp ~> Task) { import ConnectionOp.* diff --git a/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala b/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala new file mode 100644 index 000000000..5297ad4c1 --- /dev/null +++ b/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala @@ -0,0 +1,87 @@ +/* + * Copyright 2017-2019 John A. De Goes and the ZIO Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zoobie.interop + +import cats.Monad +import zio.Task +import zio.Trace +import zio.ZIO +import zio.internal.stacktracer.InteropTracer +import zio.internal.stacktracer.Tracer as CoreTracer + +/** + * Copied from zio-interop-cats as the Scala 3 version does not have optional + * dependencies on cats-effect and fs2. + * + * @see + * https://github.com/zio/interop-cats/blob/v23.1.0.5/zio-interop-cats/shared/src/main/scala/zio/interop/cats.scala#L563 + */ +object ZioMonad extends Monad[Task] { + + override final def pure[A](a: A) = + ZIO.succeed(a) + + override final def map[A, B](fa: Task[A])(f: A => B) = { + implicit def trace: Trace = InteropTracer.newTrace(f) + + fa.map(f) + } + + override final def flatMap[A, B](fa: Task[A])(f: A => Task[B]) = { + implicit def trace: Trace = InteropTracer.newTrace(f) + + fa.flatMap(f) + } + + override final def flatTap[A, B](fa: Task[A])(f: A => Task[B]) = { + implicit def trace: Trace = InteropTracer.newTrace(f) + + fa.tap(f) + } + + override final def widen[A, B >: A](fa: Task[A]) = + fa + + override final def map2[A, B, Z](fa: Task[A], fb: Task[B])(f: (A, B) => Z) = { + implicit def trace: Trace = InteropTracer.newTrace(f) + + fa.zipWith(fb)(f) + } + + override final def as[A, B](fa: Task[A], b: B) = + fa.as(b)(CoreTracer.newTrace) + + override final def whenA[A](cond: Boolean)(f: => Task[A]) = { + val byName: () => Task[A] = () => f + implicit def trace: Trace = InteropTracer.newTrace(byName) + + ZIO.when(cond)(f).unit + } + + override final def unit = + ZIO.unit + + override final def tailRecM[A, B](a: A)(f: A => Task[Either[A, B]]) = { + @SuppressWarnings(Array("org.wartremover.warts.Recursion")) + def loop(a: A): Task[B] = f(a).flatMap { + case Left(a) => loop(a) + case Right(b) => ZIO.succeed(b) + } + + ZIO.suspendSucceed(loop(a)) + } +} From 2d8a43041e6293e3d49d7929d004529e4b2750c4 Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sat, 6 Sep 2025 13:07:19 +1000 Subject: [PATCH 5/7] better --- .../src/main/scala/zoobie/Transactor.scala | 5 +--- .../main/scala/zoobie/interop/ZioMonad.scala | 24 +++++++++---------- .../main/scala/zoobie/interop/package.scala | 11 +++++++++ 3 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 modules/zio/src/main/scala/zoobie/interop/package.scala diff --git a/modules/zio/src/main/scala/zoobie/Transactor.scala b/modules/zio/src/main/scala/zoobie/Transactor.scala index ee9f5889f..bd1949dc4 100644 --- a/modules/zio/src/main/scala/zoobie/Transactor.scala +++ b/modules/zio/src/main/scala/zoobie/Transactor.scala @@ -1,6 +1,5 @@ package zoobie -import cats.Monad import cats.free.Free import cats.~> import doobie.free.connection.ConnectionIO @@ -11,11 +10,11 @@ import zio.Scope import zio.Task import zio.Trace import zio.ZIO +import zoobie.interop.* import java.sql.Connection sealed abstract class Transactor { self => - import Transactor.monadTask def connection: ZIO[Scope, DatabaseError.Connection, Connection] @@ -57,8 +56,6 @@ object Transactor { val rollback: Strategy = transactional.copy(after = doobie.free.connection.ConnectionIO.rollback) } - implicit val monadTask: Monad[Task] = zoobie.interop.ZioMonad - def interpreter(conn: Connection, fetchSize: Int = 0): ConnectionOp ~> Task = new (ConnectionOp ~> Task) { import ConnectionOp.* override def apply[A](fa: ConnectionOp[A]) = fa match { diff --git a/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala b/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala index 5297ad4c1..99da11513 100644 --- a/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala +++ b/modules/zio/src/main/scala/zoobie/interop/ZioMonad.scala @@ -17,8 +17,8 @@ package zoobie.interop import cats.Monad -import zio.Task import zio.Trace +import zio.UIO import zio.ZIO import zio.internal.stacktracer.InteropTracer import zio.internal.stacktracer.Tracer as CoreTracer @@ -30,43 +30,43 @@ import zio.internal.stacktracer.Tracer as CoreTracer * @see * https://github.com/zio/interop-cats/blob/v23.1.0.5/zio-interop-cats/shared/src/main/scala/zio/interop/cats.scala#L563 */ -object ZioMonad extends Monad[Task] { +object ZioMonad extends Monad[UIO] { override final def pure[A](a: A) = ZIO.succeed(a) - override final def map[A, B](fa: Task[A])(f: A => B) = { + override final def map[A, B](fa: UIO[A])(f: A => B) = { implicit def trace: Trace = InteropTracer.newTrace(f) fa.map(f) } - override final def flatMap[A, B](fa: Task[A])(f: A => Task[B]) = { + override final def flatMap[A, B](fa: UIO[A])(f: A => UIO[B]) = { implicit def trace: Trace = InteropTracer.newTrace(f) fa.flatMap(f) } - override final def flatTap[A, B](fa: Task[A])(f: A => Task[B]) = { + override final def flatTap[A, B](fa: UIO[A])(f: A => UIO[B]) = { implicit def trace: Trace = InteropTracer.newTrace(f) fa.tap(f) } - override final def widen[A, B >: A](fa: Task[A]) = + override final def widen[A, B >: A](fa: UIO[A]) = fa - override final def map2[A, B, Z](fa: Task[A], fb: Task[B])(f: (A, B) => Z) = { + override final def map2[A, B, Z](fa: UIO[A], fb: UIO[B])(f: (A, B) => Z) = { implicit def trace: Trace = InteropTracer.newTrace(f) fa.zipWith(fb)(f) } - override final def as[A, B](fa: Task[A], b: B) = + override final def as[A, B](fa: UIO[A], b: B) = fa.as(b)(CoreTracer.newTrace) - override final def whenA[A](cond: Boolean)(f: => Task[A]) = { - val byName: () => Task[A] = () => f + override final def whenA[A](cond: Boolean)(f: => UIO[A]) = { + val byName: () => UIO[A] = () => f implicit def trace: Trace = InteropTracer.newTrace(byName) ZIO.when(cond)(f).unit @@ -75,9 +75,9 @@ object ZioMonad extends Monad[Task] { override final def unit = ZIO.unit - override final def tailRecM[A, B](a: A)(f: A => Task[Either[A, B]]) = { + override final def tailRecM[A, B](a: A)(f: A => UIO[Either[A, B]]) = { @SuppressWarnings(Array("org.wartremover.warts.Recursion")) - def loop(a: A): Task[B] = f(a).flatMap { + def loop(a: A): UIO[B] = f(a).flatMap { case Left(a) => loop(a) case Right(b) => ZIO.succeed(b) } diff --git a/modules/zio/src/main/scala/zoobie/interop/package.scala b/modules/zio/src/main/scala/zoobie/interop/package.scala new file mode 100644 index 000000000..d4cf1e128 --- /dev/null +++ b/modules/zio/src/main/scala/zoobie/interop/package.scala @@ -0,0 +1,11 @@ +package zoobie + +import cats.Monad +import zio.ZIO + +package object interop { + + @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf")) + implicit def monadCats[R, E]: Monad[ZIO[R, E, *]] = + zoobie.interop.ZioMonad.asInstanceOf[Monad[ZIO[R, E, *]]] +} From 20f69fb0b17a2f1d98f4f28e805861a23137bad9 Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sun, 28 Sep 2025 09:02:19 +1000 Subject: [PATCH 6/7] basic zio monad laws --- .github/workflows/ci.yml | 4 +-- .github/workflows/release.yml | 4 +-- README.md | 2 +- build.sbt | 2 ++ .../scala/zoobie/interop/ZioMonadLaws.scala | 31 +++++++++++++++++++ project/build.properties | 2 +- 6 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 modules/zio/src/test/scala/zoobie/interop/ZioMonadLaws.scala diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bebd681fd..6deef62be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,11 +20,11 @@ jobs: with: fetch-depth: 0 - - name: Install JDK 11 + - name: Install JDK 17 uses: actions/setup-java@v4 with: distribution: zulu - java-version: '11' + java-version: '17' java-package: jdk - name: Install SBT diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5e0cdb793..477489624 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,11 +13,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Install JDK 11 + - name: Install JDK 17 uses: actions/setup-java@v4 with: distribution: zulu - java-version: '11' + java-version: '17' java-package: jdk - name: Install SBT diff --git a/README.md b/README.md index df4bf5093..d5d20621a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Currently contains the following changes: - PostGIS instances have been moved to the new `postgis` module and are available under `doobie.postgis.instances.{geography,geometry}` - `LogHandler` has been removed. Override interpreters if you want to log things. - removed `WeakAsync`, a `ConnectionIO` is pretty much always a database transaction and should not be mixed with an `IO` implementation -- Requires Java 11 +- Requires Java 17 To use add at least the core module to your project: ``` diff --git a/build.sbt b/build.sbt index 9de3cdd0e..939086f0c 100644 --- a/build.sbt +++ b/build.sbt @@ -306,6 +306,8 @@ lazy val zio = module("zio") "dev.zio" %% "zio-test" % zioVersion % Test, "dev.zio" %% "zio-test-sbt" % zioVersion % Test, + "org.typelevel" %% "cats-laws" % catsVersion % Test, + "org.typelevel" %% "discipline-munit" % "2.0.0" % Test, ), ) .dependsOn(core, core % "test->test") diff --git a/modules/zio/src/test/scala/zoobie/interop/ZioMonadLaws.scala b/modules/zio/src/test/scala/zoobie/interop/ZioMonadLaws.scala new file mode 100644 index 000000000..fd950d3df --- /dev/null +++ b/modules/zio/src/test/scala/zoobie/interop/ZioMonadLaws.scala @@ -0,0 +1,31 @@ +package zoobie.interop + +import cats.Eq +import cats.laws.discipline.MonadTests +import munit.DisciplineSuite +import org.scalacheck.Arbitrary +import org.scalacheck.Gen +import zio.Unsafe +import zio.ZIO + +class ZioMonadLaws extends DisciplineSuite { + import ZioMonadLaws.* + + checkAll("Monad", MonadTests[ZIO[Any, Nothing, *]].monad[Int, Int, Int]) +} +object ZioMonadLaws { + + private def run[A](io: ZIO[Any, Nothing, A]): A = Unsafe.unsafe { implicit unsafe => + zio.Runtime.default.unsafe.run(io).getOrThrowFiberFailure() + } + + implicit def eqZIO[A: Eq]: Eq[ZIO[Any, Nothing, A]] = Eq.by(run(_)) + + implicit val arbitraryZIOInt: Arbitrary[ZIO[Any, Nothing, Int]] = Arbitrary { + Arbitrary.arbInt.arbitrary.map(ZIO.succeed(_)) + } + + implicit val arbitraryZIOIntToInt: Arbitrary[ZIO[Any, Nothing, Int => Int]] = Arbitrary { + Gen.function1[Int, Int](Arbitrary.arbInt.arbitrary).map(ZIO.succeed(_)) + } +} diff --git a/project/build.properties b/project/build.properties index e480c675f..5e6884d37 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.5 +sbt.version=1.11.6 From cba74b1b079a4b7a0f7d8379a7f77f8518b21c7a Mon Sep 17 00:00:00 2001 From: Sam Guymer Date: Sat, 18 Oct 2025 06:31:02 +1000 Subject: [PATCH 7/7] default fetch size to 4096 --- modules/zio/src/main/scala/zoobie/Transactor.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/zio/src/main/scala/zoobie/Transactor.scala b/modules/zio/src/main/scala/zoobie/Transactor.scala index bd1949dc4..611dc2be8 100644 --- a/modules/zio/src/main/scala/zoobie/Transactor.scala +++ b/modules/zio/src/main/scala/zoobie/Transactor.scala @@ -56,7 +56,7 @@ object Transactor { val rollback: Strategy = transactional.copy(after = doobie.free.connection.ConnectionIO.rollback) } - def interpreter(conn: Connection, fetchSize: Int = 0): ConnectionOp ~> Task = new (ConnectionOp ~> Task) { + def interpreter(conn: Connection, fetchSize: Int = 4096): ConnectionOp ~> Task = new (ConnectionOp ~> Task) { import ConnectionOp.* override def apply[A](fa: ConnectionOp[A]) = fa match { case Raw(f) => ZIO.attemptBlocking(f(conn))