From 0f3da55cc59917fdfebfe3b3c90f0658785f8859 Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Sat, 15 Apr 2023 15:54:00 +0200 Subject: [PATCH 1/6] Ensure backward compatibility of Hikari Config --- .../src/main/scala/doobie/hikari/Config.scala | 94 ++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/modules/hikari/src/main/scala/doobie/hikari/Config.scala b/modules/hikari/src/main/scala/doobie/hikari/Config.scala index ebec82f95..299d8f27c 100644 --- a/modules/hikari/src/main/scala/doobie/hikari/Config.scala +++ b/modules/hikari/src/main/scala/doobie/hikari/Config.scala @@ -14,13 +14,18 @@ import com.zaxxer.hikari.metrics.MetricsTrackerFactory import doobie.enumerated.TransactionIsolation import javax.sql.DataSource +import scala.annotation.nowarn 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( +// Whenever you add a new field, add it to `copy` and create a new `apply` to maintain backward compatibility. +// +// The default values in the constructor are not actually applied (defaults from `apply` are). +// But they still need to be present to enable tools like PureConfig. +final case class Config private ( jdbcUrl: String, catalog: Option[String] = None, connectionTimeout: Duration = Duration(30, TimeUnit.SECONDS), @@ -46,7 +51,36 @@ final case class Config( registerMbeans: Boolean = false, schema: Option[String] = None, transactionIsolation: Option[TransactionIsolation] = None, -) +){ + @nowarn("msg=never used") + private def copy( + jdbcUrl: String, + catalog: Option[String], + connectionTimeout: Duration, + idleTimeout: Duration, + leakDetectionThreshold: Duration, + maximumPoolSize: Int, + maxLifetime: Duration, + minimumIdle: Int, + password: Option[String], + poolName: Option[String], + username: Option[String], + validationTimeout: Duration, + allowPoolSuspension: Boolean, + autoCommit: Boolean, + connectionInitSql: Option[String], + connectionTestQuery: Option[String], + dataSourceClassName: Option[String], + dataSourceJNDI: Option[String], + driverClassName: Option[String], + initializationFailTimeout: Duration, + isolateInternalQueries: Boolean, + readOnly: Boolean, + registerMbeans: Boolean, + schema: Option[String], + transactionIsolation: Option[TransactionIsolation], + ): Any = this +} object Config { def makeHikariConfig[F[_]]( @@ -103,4 +137,60 @@ object Config { c } + def apply( + 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, + ): Config = new Config( + jdbcUrl, + catalog, + connectionTimeout, + idleTimeout, + leakDetectionThreshold, + maximumPoolSize, + maxLifetime, + minimumIdle, + password, + poolName, + username, + validationTimeout, + allowPoolSuspension, + autoCommit, + connectionInitSql, + connectionTestQuery, + dataSourceClassName, + dataSourceJNDI, + driverClassName, + initializationFailTimeout, + isolateInternalQueries, + readOnly, + registerMbeans, + schema, + transactionIsolation + ) + + @nowarn("msg=never used") + private def unapply(c: Config): Any = this } From a92aa812351b6271094668720dc7516265f7b945 Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Sat, 15 Apr 2023 16:19:20 +0200 Subject: [PATCH 2/6] fix --- modules/hikari/src/main/scala/doobie/hikari/Config.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/hikari/src/main/scala/doobie/hikari/Config.scala b/modules/hikari/src/main/scala/doobie/hikari/Config.scala index 299d8f27c..9e4d188dc 100644 --- a/modules/hikari/src/main/scala/doobie/hikari/Config.scala +++ b/modules/hikari/src/main/scala/doobie/hikari/Config.scala @@ -25,6 +25,7 @@ import scala.concurrent.duration.Duration // // The default values in the constructor are not actually applied (defaults from `apply` are). // But they still need to be present to enable tools like PureConfig. +@nowarn("msg=never used") final case class Config private ( jdbcUrl: String, catalog: Option[String] = None, From 6cebfbdf5f3974693e2003c4d575ba1db724f2aa Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Sat, 15 Apr 2023 16:53:40 +0200 Subject: [PATCH 3/6] suppress nowarn warning --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index 9a03c891f..7e93bfcda 100644 --- a/build.sbt +++ b/build.sbt @@ -325,6 +325,7 @@ lazy val hikari = project .settings( name := "doobie-hikari", description := "Hikari support for doobie.", + scalacOptions --= Seq("-Xlint:unused", "-Wunused:nowarn"), libraryDependencies ++= Seq( //needs to be excluded, otherwise coursier may resolve slf4j-api 2 if > Java 11 "com.zaxxer" % "HikariCP" % hikariVersion exclude("org.slf4j", "slf4j-api"), From 77ae2868dacb067e7dee9946733b39716e2ae296 Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Mon, 17 Apr 2023 02:07:15 +0200 Subject: [PATCH 4/6] fromProduct --- .../src/main/scala/doobie/hikari/Config.scala | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/modules/hikari/src/main/scala/doobie/hikari/Config.scala b/modules/hikari/src/main/scala/doobie/hikari/Config.scala index 9e4d188dc..7852e0fb0 100644 --- a/modules/hikari/src/main/scala/doobie/hikari/Config.scala +++ b/modules/hikari/src/main/scala/doobie/hikari/Config.scala @@ -192,6 +192,38 @@ object Config { transactionIsolation ) + @nowarn + def fromProduct(p: Product): Config = p.productArity match { + case 25 => + Config( + p.productElement(0).asInstanceOf[String], + p.productElement(1).asInstanceOf[Option[String]], + p.productElement(2).asInstanceOf[Duration], + p.productElement(3).asInstanceOf[Duration], + p.productElement(4).asInstanceOf[Duration], + p.productElement(5).asInstanceOf[Int], + p.productElement(6).asInstanceOf[Duration], + p.productElement(7).asInstanceOf[Int], + p.productElement(8).asInstanceOf[Option[String]], + p.productElement(9).asInstanceOf[Option[String]], + p.productElement(10).asInstanceOf[Option[String]], + p.productElement(11).asInstanceOf[Duration], + p.productElement(12).asInstanceOf[Boolean], + p.productElement(13).asInstanceOf[Boolean], + p.productElement(14).asInstanceOf[Option[String]], + p.productElement(15).asInstanceOf[Option[String]], + p.productElement(16).asInstanceOf[Option[String]], + p.productElement(17).asInstanceOf[Option[String]], + p.productElement(18).asInstanceOf[Option[String]], + p.productElement(19).asInstanceOf[Duration], + p.productElement(20).asInstanceOf[Boolean], + p.productElement(21).asInstanceOf[Boolean], + p.productElement(22).asInstanceOf[Boolean], + p.productElement(23).asInstanceOf[Option[String]], + p.productElement(24).asInstanceOf[Option[TransactionIsolation]], + ) + } + @nowarn("msg=never used") private def unapply(c: Config): Any = this } From 4a32015e13e34c62a6775800cc42ffad25cdd4e0 Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Thu, 20 Apr 2023 20:36:13 +0200 Subject: [PATCH 5/6] Explain bin compatibility --- modules/hikari/src/main/scala/doobie/hikari/Config.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/hikari/src/main/scala/doobie/hikari/Config.scala b/modules/hikari/src/main/scala/doobie/hikari/Config.scala index 7852e0fb0..076689008 100644 --- a/modules/hikari/src/main/scala/doobie/hikari/Config.scala +++ b/modules/hikari/src/main/scala/doobie/hikari/Config.scala @@ -21,7 +21,10 @@ import scala.concurrent.duration.Duration * Helps with creating `com.zaxxer.hikari.HikariConfig`, * which in turn is used to create `doobie.hikari.HikariTransactor`. * See the method `HikariTransactor.fromConfigAutoEc` */ -// Whenever you add a new field, add it to `copy` and create a new `apply` to maintain backward compatibility. +// Whenever you add a new field to maintain backward compatibility: +// * add the field to `copy` +// * create a new `apply` +// * add a new case to `fromProduct` // // The default values in the constructor are not actually applied (defaults from `apply` are). // But they still need to be present to enable tools like PureConfig. From 47fd00cdc9e064dbdc74d201f85099b44be7c361 Mon Sep 17 00:00:00 2001 From: Jacob Wang Date: Fri, 26 Apr 2024 20:50:04 +0100 Subject: [PATCH 6/6] added named params --- .../src/main/scala/doobie/hikari/Config.scala | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/modules/hikari/src/main/scala/doobie/hikari/Config.scala b/modules/hikari/src/main/scala/doobie/hikari/Config.scala index 076689008..3605b65bc 100644 --- a/modules/hikari/src/main/scala/doobie/hikari/Config.scala +++ b/modules/hikari/src/main/scala/doobie/hikari/Config.scala @@ -168,38 +168,38 @@ object Config { schema: Option[String] = None, transactionIsolation: Option[TransactionIsolation] = None, ): Config = new Config( - jdbcUrl, - catalog, - connectionTimeout, - idleTimeout, - leakDetectionThreshold, - maximumPoolSize, - maxLifetime, - minimumIdle, - password, - poolName, - username, - validationTimeout, - allowPoolSuspension, - autoCommit, - connectionInitSql, - connectionTestQuery, - dataSourceClassName, - dataSourceJNDI, - driverClassName, - initializationFailTimeout, - isolateInternalQueries, - readOnly, - registerMbeans, - schema, - transactionIsolation + jdbcUrl = jdbcUrl, + catalog = catalog, + connectionTimeout = connectionTimeout, + idleTimeout = idleTimeout, + leakDetectionThreshold = leakDetectionThreshold, + maximumPoolSize = maximumPoolSize, + maxLifetime = maxLifetime, + minimumIdle = minimumIdle, + password = password, + poolName = poolName, + username = username, + validationTimeout = validationTimeout, + allowPoolSuspension = allowPoolSuspension, + autoCommit = autoCommit, + connectionInitSql = connectionInitSql, + connectionTestQuery = connectionTestQuery, + dataSourceClassName = dataSourceClassName, + dataSourceJNDI = dataSourceJNDI, + driverClassName = driverClassName, + initializationFailTimeout = initializationFailTimeout, + isolateInternalQueries = isolateInternalQueries, + readOnly = readOnly, + registerMbeans = registerMbeans, + schema = schema, + transactionIsolation = transactionIsolation ) @nowarn def fromProduct(p: Product): Config = p.productArity match { case 25 => Config( - p.productElement(0).asInstanceOf[String], + p.productElement(0).asInstanceOf[String], p.productElement(1).asInstanceOf[Option[String]], p.productElement(2).asInstanceOf[Duration], p.productElement(3).asInstanceOf[Duration],