Skip to content

Commit

Permalink
Merge pull request #2046 from tpolecat/remove_lazy_init_modules
Browse files Browse the repository at this point in the history
Remove lazy initialization of modules
  • Loading branch information
jatcwang authored May 29, 2024
2 parents f59932b + 85dcb1e commit 9b6a5dd
Show file tree
Hide file tree
Showing 23 changed files with 326 additions and 271 deletions.
56 changes: 28 additions & 28 deletions modules/core/src/main/scala/doobie/free/Aliases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,34 @@ trait Types {
}

trait Modules {
/** @group Module Aliases - Free API */ lazy val FB = blob
/** @group Module Aliases - Free API */ lazy val FCS = callablestatement
/** @group Module Aliases - Free API */ lazy val FCL = clob
/** @group Module Aliases - Free API */ lazy val FC = connection
/** @group Module Aliases - Free API */ lazy val FDMD = databasemetadata
/** @group Module Aliases - Free API */ lazy val FD = driver
/** @group Module Aliases - Free API */ lazy val FNCL = nclob
/** @group Module Aliases - Free API */ lazy val FPS = preparedstatement
/** @group Module Aliases - Free API */ lazy val FREF = ref
/** @group Module Aliases - Free API */ lazy val FRS = resultset
/** @group Module Aliases - Free API */ lazy val FSD = sqldata
/** @group Module Aliases - Free API */ lazy val FSI = sqlinput
/** @group Module Aliases - Free API */ lazy val FSO = sqloutput
/** @group Module Aliases - Free API */ lazy val FS = statement
/** @group Module Aliases - Free API */ val FB = blob
/** @group Module Aliases - Free API */ val FCS = callablestatement
/** @group Module Aliases - Free API */ val FCL = clob
/** @group Module Aliases - Free API */ val FC = connection
/** @group Module Aliases - Free API */ val FDMD = databasemetadata
/** @group Module Aliases - Free API */ val FD = driver
/** @group Module Aliases - Free API */ val FNCL = nclob
/** @group Module Aliases - Free API */ val FPS = preparedstatement
/** @group Module Aliases - Free API */ val FREF = ref
/** @group Module Aliases - Free API */ val FRS = resultset
/** @group Module Aliases - Free API */ val FSD = sqldata
/** @group Module Aliases - Free API */ val FSI = sqlinput
/** @group Module Aliases - Free API */ val FSO = sqloutput
/** @group Module Aliases - Free API */ val FS = statement
}

trait Instances {

/** @group Typeclass Instances */ implicit lazy val WeakAsyncBlobIO: WeakAsync[BlobIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncBlobIO: WeakAsync[BlobIO] =
blob.WeakAsyncBlobIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncCallableStatementIO: WeakAsync[CallableStatementIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncCallableStatementIO: WeakAsync[CallableStatementIO] =
callablestatement.WeakAsyncCallableStatementIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncClobIO: WeakAsync[ClobIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncClobIO: WeakAsync[ClobIO] =
clob.WeakAsyncClobIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncConnectionIO: WeakAsync[ConnectionIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncConnectionIO: WeakAsync[ConnectionIO] =
connection.WeakAsyncConnectionIO

/** @group Typeclass Instances */ implicit def MonoidConnectionIO[A: Monoid]: Monoid[ConnectionIO[A]] =
Expand All @@ -61,34 +61,34 @@ trait Instances {
/** @group Typeclass Instances */ implicit def SemigroupConnectionIO[A: Semigroup]: Semigroup[ConnectionIO[A]] =
connection.SemigroupConnectionIO[A]

/** @group Typeclass Instances */ implicit lazy val WeakAsyncDatabaseMetaDataIO: WeakAsync[DatabaseMetaDataIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncDatabaseMetaDataIO: WeakAsync[DatabaseMetaDataIO] =
databasemetadata.WeakAsyncDatabaseMetaDataIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncDriverIO: WeakAsync[DriverIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncDriverIO: WeakAsync[DriverIO] =
driver.WeakAsyncDriverIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncNClobIO: WeakAsync[NClobIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncNClobIO: WeakAsync[NClobIO] =
nclob.WeakAsyncNClobIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncPreparedStatementIO: WeakAsync[PreparedStatementIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncPreparedStatementIO: WeakAsync[PreparedStatementIO] =
preparedstatement.WeakAsyncPreparedStatementIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncRefIO: WeakAsync[RefIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncRefIO: WeakAsync[RefIO] =
ref.WeakAsyncRefIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncResultSetIO: WeakAsync[ResultSetIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncResultSetIO: WeakAsync[ResultSetIO] =
resultset.WeakAsyncResultSetIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncSQLDataIO: WeakAsync[SQLDataIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncSQLDataIO: WeakAsync[SQLDataIO] =
sqldata.WeakAsyncSQLDataIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncSQLInputIO: WeakAsync[SQLInputIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncSQLInputIO: WeakAsync[SQLInputIO] =
sqlinput.WeakAsyncSQLInputIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncSQLOutputIO: WeakAsync[SQLOutputIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncSQLOutputIO: WeakAsync[SQLOutputIO] =
sqloutput.WeakAsyncSQLOutputIO

/** @group Typeclass Instances */ implicit lazy val WeakAsyncStatementIO: WeakAsync[StatementIO] =
/** @group Typeclass Instances */ implicit val WeakAsyncStatementIO: WeakAsync[StatementIO] =
statement.WeakAsyncStatementIO

}
8 changes: 4 additions & 4 deletions modules/core/src/main/scala/doobie/hi/Aliases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
package doobie.hi

trait Modules {
/** @group Module Aliases - High level (safer) API */ lazy val HC = doobie.hi.connection
/** @group Module Aliases - High level (safer) API */ lazy val HS = doobie.hi.statement
/** @group Module Aliases - High level (safer) API */ lazy val HPS = doobie.hi.preparedstatement
/** @group Module Aliases - High level (safer) API */ lazy val HRS = doobie.hi.resultset
/** @group Module Aliases - High level (safer) API */ val HC = doobie.hi.connection
/** @group Module Aliases - High level (safer) API */ val HS = doobie.hi.statement
/** @group Module Aliases - High level (safer) API */ val HPS = doobie.hi.preparedstatement
/** @group Module Aliases - High level (safer) API */ val HRS = doobie.hi.resultset
}
101 changes: 55 additions & 46 deletions modules/core/src/main/scala/doobie/hi/connection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ import doobie.util.stream.repeatEvalChunks
import doobie.util.{ Get, Put, Read, Write }
import fs2.Stream
import fs2.Stream.{ eval, bracket }
import doobie.hi.{preparedstatement => IHPS}
import doobie.free.{
preparedstatement => IFPS,
connection => IFC,
resultset => IFRS,
databasemetadata => IFDMD,
statement => IFS,
callablestatement => IFCS
}

import java.sql.{ Savepoint, PreparedStatement, ResultSet }
import scala.collection.immutable.Map
Expand All @@ -36,7 +45,7 @@ object connection {

/** @group Lifting */
def delay[A](a: => A): ConnectionIO[A] =
FC.delay(a)
IFC.delay(a)

private def liftStream[A: Read](
chunkSize: Int,
Expand All @@ -46,18 +55,18 @@ object connection {

def prepared(ps: PreparedStatement): Stream[ConnectionIO, PreparedStatement] =
eval[ConnectionIO, PreparedStatement] {
val fs = FPS.setFetchSize(chunkSize)
FC.embed(ps, fs *> prep).map(_ => ps)
val fs = IFPS.setFetchSize(chunkSize)
IFC.embed(ps, fs *> prep).map(_ => ps)
}

def unrolled(rs: ResultSet): Stream[ConnectionIO, A] =
repeatEvalChunks(FC.embed(rs, resultset.getNextChunk[A](chunkSize)))
repeatEvalChunks(IFC.embed(rs, resultset.getNextChunk[A](chunkSize)))

val preparedStatement: Stream[ConnectionIO, PreparedStatement] =
bracket(create)(FC.embed(_, FPS.close)).flatMap(prepared)
bracket(create)(IFC.embed(_, IFPS.close)).flatMap(prepared)

def results(ps: PreparedStatement): Stream[ConnectionIO, A] =
bracket(FC.embed(ps, exec))(FC.embed(_, FRS.close)).flatMap(unrolled)
bracket(IFC.embed(ps, exec))(IFC.embed(_, IFRS.close)).flatMap(unrolled)

preparedStatement.flatMap(results)

Expand All @@ -69,7 +78,7 @@ object connection {
* @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)
liftStream(chunkSize, IFC.prepareStatement(sql), prep, IFPS.executeQuery)

/**
* Construct a prepared update statement with the given return columns (and readable destination
Expand All @@ -79,31 +88,31 @@ object connection {
* @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)
liftStream(chunkSize, IFC.prepareStatement(sql, cols.toArray), prep, IFPS.executeUpdate *> IFPS.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)
liftStream[B](chunkSize, IFC.prepareStatement(sql, cols.toArray), prep, IHPS.addBatchesAndExecute(fa) *> IFPS.getGeneratedKeys)

/** @group Transaction Control */
val commit: ConnectionIO[Unit] =
FC.commit
IFC.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])
prepareAnalysis(sql, IHPS.getParameterMappings[A], IHPS.getColumnMappings[B])

def prepareQueryAnalysis0[B: Read](sql: String): ConnectionIO[Analysis] =
prepareAnalysis(sql, FPS.pure(Nil), HPS.getColumnMappings[B])
prepareAnalysis(sql, IFPS.pure(Nil), IHPS.getColumnMappings[B])

def prepareUpdateAnalysis[A: Write](sql: String): ConnectionIO[Analysis] =
prepareAnalysis(sql, HPS.getParameterMappings[A], FPS.pure(Nil))
prepareAnalysis(sql, IHPS.getParameterMappings[A], IFPS.pure(Nil))

def prepareUpdateAnalysis0(sql: String): ConnectionIO[Analysis] =
prepareAnalysis(sql, FPS.pure(Nil), FPS.pure(Nil))
prepareAnalysis(sql, IFPS.pure(Nil), IFPS.pure(Nil))

private def prepareAnalysis(
sql: String,
Expand All @@ -113,111 +122,111 @@ object connection {
val mappings = prepareStatement(sql) {
(params, columns).tupled
}
(HC.getMetaData(FDMD.getDriverName), mappings).mapN { case (driver, (p, c)) =>
(getMetaData(IFDMD.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))
IFC.createStatement.bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFS.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))
IFC.createStatement(rst.toInt, rsc.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFS.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))
IFC.createStatement(rst.toInt, rsc.toInt, rsh.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFS.close))

/** @group Connection Properties */
val getCatalog: ConnectionIO[String] =
FC.getCatalog
IFC.getCatalog

/** @group Connection Properties */
def getClientInfo(key: String): ConnectionIO[Option[String]] =
FC.getClientInfo(key).map(Option(_))
IFC.getClientInfo(key).map(Option(_))

/** @group Connection Properties */
val getClientInfo: ConnectionIO[Map[String, String]] =
FC.getClientInfo.map(propertiesToScala)
IFC.getClientInfo.map(propertiesToScala)

/** @group Connection Properties */
val getHoldability: ConnectionIO[Holdability] =
FC.getHoldability.flatMap(Holdability.fromIntF[ConnectionIO])
IFC.getHoldability.flatMap(Holdability.fromIntF[ConnectionIO])

/** @group Connection Properties */
def getMetaData[A](k: DatabaseMetaDataIO[A]): ConnectionIO[A] =
FC.getMetaData.flatMap(s => FC.embed(s, k))
IFC.getMetaData.flatMap(s => IFC.embed(s, k))

/** @group Transaction Control */
val getTransactionIsolation: ConnectionIO[TransactionIsolation] =
FC.getTransactionIsolation.flatMap(TransactionIsolation.fromIntF[ConnectionIO])
IFC.getTransactionIsolation.flatMap(TransactionIsolation.fromIntF[ConnectionIO])

/** @group Connection Properties */
val isReadOnly: ConnectionIO[Boolean] =
FC.isReadOnly
IFC.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))
IFC.prepareCall(sql, rst.toInt, rsc.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFCS.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))
IFC.prepareCall(sql).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFCS.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))
IFC.prepareCall(sql, rst.toInt, rsc.toInt, rsh.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFCS.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))
IFC.prepareStatement(sql, rst.toInt, rsc.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFPS.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))
IFC.prepareStatement(sql).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFPS.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))
IFC.prepareStatement(sql, rst.toInt, rsc.toInt, rsh.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFPS.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))
IFC.prepareStatement(sql, agk.toInt).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFPS.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))
IFC.prepareStatement(sql, columnIndexes.toArray).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFPS.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))
IFC.prepareStatement(sql, columnNames.toArray).bracket(s => IFC.embed(s, k))(s => IFC.embed(s, IFPS.close))

/** @group Transaction Control */
def releaseSavepoint(sp: Savepoint): ConnectionIO[Unit] =
FC.releaseSavepoint(sp)
IFC.releaseSavepoint(sp)

/** @group Transaction Control */
def rollback(sp: Savepoint): ConnectionIO[Unit] =
FC.rollback(sp)
IFC.rollback(sp)

/** @group Transaction Control */
val rollback: ConnectionIO[Unit] =
FC.rollback
IFC.rollback

/** @group Connection Properties */
def setCatalog(catalog: String): ConnectionIO[Unit] =
FC.setCatalog(catalog)
IFC.setCatalog(catalog)

/** @group Connection Properties */
def setClientInfo(key: String, value: String): ConnectionIO[Unit] =
FC.setClientInfo(key, value)
IFC.setClientInfo(key, value)

/** @group Connection Properties */
def setClientInfo(info: Map[String, String]): ConnectionIO[Unit] =
FC.setClientInfo {
IFC.setClientInfo {
// Java 11 overloads the `putAll` method with Map[*,*] along with the existing Map[Obj,Obj]
val ps = new java.util.Properties
info.foreach { case (k, v) =>
Expand All @@ -228,29 +237,29 @@ object connection {

/** @group Connection Properties */
def setHoldability(h: Holdability): ConnectionIO[Unit] =
FC.setHoldability(h.toInt)
IFC.setHoldability(h.toInt)

/** @group Connection Properties */
def setReadOnly(readOnly: Boolean): ConnectionIO[Unit] =
FC.setReadOnly(readOnly)
IFC.setReadOnly(readOnly)

/** @group Transaction Control */
val setSavepoint: ConnectionIO[Savepoint] =
FC.setSavepoint
IFC.setSavepoint

/** @group Transaction Control */
def setSavepoint(name: String): ConnectionIO[Savepoint] =
FC.setSavepoint(name)
IFC.setSavepoint(name)

/** @group Transaction Control */
def setTransactionIsolation(ti: TransactionIsolation): ConnectionIO[Unit] =
FC.setTransactionIsolation(ti.toInt)
IFC.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))))
// getMetaData(IFDMD.getTypeInfo.flatMap(IFDMD.embed(_, HRS.list[(String, JdbcType)].map(_.toMap))))
// }
}
Loading

0 comments on commit 9b6a5dd

Please sign in to comment.