Skip to content

Commit

Permalink
feat!: Fatal warnings
Browse files Browse the repository at this point in the history
Fix all warnings and enable fatal warnings.

Also remove the dependency on scala-compat.

This is mostly backwards compatible, but won't work with versions of scala before 2.13.

It also adds an implicit conversion from SqlRow => A to RowParser[A], which allows continuing
to pass in a function as the argument instead of an implicit RowParser, but might be subtly
different in some cases.
tmccombs committed Nov 18, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 6fd0fc1 commit f68bd5b
Showing 20 changed files with 180 additions and 156 deletions.
5 changes: 3 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -40,7 +40,8 @@ inScope(Global)(Seq(
licenses += "Apache License 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0"),
scalacOptions ++= Seq(
"-deprecation",
"-feature"
"-feature",
"-Werror"
),
scmInfo := Some(ScmInfo(url("https://github.com/lucidsoftware/relate"), "scm:git:[email protected]:lucidsoftware/relate.git")),
Benchmark / test / tags += benchmarkTag -> 1,
@@ -49,5 +50,5 @@ inScope(Global)(Seq(
version := sys.props.getOrElse("build.version", "0-SNAPSHOT")
))

skip in publish := true
publish / skip := true
publishTo := sonatypePublishToBundle.value
Original file line number Diff line number Diff line change
@@ -16,8 +16,8 @@ package object macros {
@implicitNotFound("A value of type ${A} is never allowed as an RecordOption")
private trait RecordOptionValue[A]
private object RecordOptionValue {
implicit val bool = new RecordOptionValue[Boolean] {}
implicit val map = new RecordOptionValue[Map[String, String]] {}
implicit val bool: RecordOptionValue[Boolean] = new RecordOptionValue[Boolean] {}
implicit val map: RecordOptionValue[Map[String, String]] = new RecordOptionValue[Map[String, String]] {}
}

case class RecordOption[A: RecordOptionValue] private (key: String, value: A)
Original file line number Diff line number Diff line change
@@ -239,7 +239,7 @@ class RowParserTest extends Specification with Mockito {

"fail to compile for anything besides a case class" in {
illTyped("@Record() class Thing", "@Record must be used on a case class")
illTyped("@Record() def f()", "@Record must be used on a case class")
illTyped("@Record() def f(): Unit", "@Record must be used on a case class")
illTyped("@Record() object Thing {}", "@Record must be used on a case class")
illTyped("@Record() trait Thing", "@Record must be used on a case class")

Original file line number Diff line number Diff line change
@@ -6,10 +6,10 @@ import scala.concurrent.duration.FiniteDuration

package object postgres {

implicit val pgIntervalParameterizable =
implicit val pgIntervalParameterizable: Parameterizable[PGInterval] =
Parameterizable(_.setObject(_, _: PGInterval), _.setNull(_, Types.JAVA_OBJECT))

implicit val finiteDurationParameterizable =
Parameterizable.from((value: FiniteDuration) => new PGInterval(0, 0, 0, 0, 0, value.toSeconds))
implicit val finiteDurationParameterizable: Parameterizable[FiniteDuration] =
Parameterizable.from((value: FiniteDuration) => new PGInterval(0, 0, 0, 0, 0, value.toSeconds.toDouble))

}
1 change: 0 additions & 1 deletion relate/build.sbt
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ libraryDependencies ++= Seq(
"com.h2database" % "h2" % "1.4.191" % "test",
"com.storm-enroute" %% "scalameter" % "0.19" % Benchmark,
"com.storm-enroute" %% "scalameter" % "0.19" % Regression,
"org.scala-lang.modules" %% "scala-collection-compat" % "2.1.6"
)

libraryDependencies ++= (CrossVersion.binaryScalaVersion(scalaVersion.value) match {
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.lucidchart.relate

import scala.collection.compat._
import scala.collection.Factory
import scala.language.higherKinds

trait CollectionsParser {
@@ -14,19 +14,19 @@ trait CollectionsParser {
}
}

builder.result
builder.result()
}

implicit def option[B: RowParser] = RowParser[Option[B]] { result =>
implicit def option[B: RowParser]: RowParser[Option[B]] = RowParser[Option[B]] { result =>
limitedCollection[B, List](1).parse(result).headOption
}

implicit def collection[B: RowParser, Col[_]](implicit factory: Factory[B, Col[B]]) =
implicit def collection[B: RowParser, Col[_]](implicit factory: Factory[B, Col[B]]): RowParser[Col[B]] =
limitedCollection[B, Col](Long.MaxValue)

implicit def pairCollection[Key: RowParser, Value: RowParser, PairCol[_, _]](implicit
factory: Factory[(Key, Value), PairCol[Key, Value]]
) =
): RowParser[PairCol[Key, Value]] =
RowParser { result =>

val builder = factory.newBuilder
@@ -37,6 +37,6 @@ trait CollectionsParser {
}
}

builder.result
builder.result()
}
}
18 changes: 9 additions & 9 deletions relate/src/main/scala/com/lucidchart/relate/CollectionsSql.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.lucidchart.relate

import java.sql.{Connection, PreparedStatement, ResultSet}
import scala.collection.compat._
import scala.collection.Factory
import scala.language.higherKinds

/**
@@ -51,9 +51,9 @@ trait CollectionsSql { self: Sql =>
* @return
* the results as an arbitrary collection of records
*/
def asCollection[U, T[_]](parser: SqlRow => U)(implicit factory: Factory[U, T[U]], connection: Connection): T[U] =
normalStatement.execute(_.asCollection(parser))
def asCollection[U: RowParser, T[_]]()(implicit factory: Factory[U, T[U]], connection: Connection): T[U] =
// def asCollection[U, T[_]](parser: SqlRow => U)(implicit factory: Factory[U, T[U]], connection: Connection): T[U] =
// normalStatement.execute(_.asCollection(parser))
def asCollection[U: RowParser, T[_]](implicit factory: Factory[U, T[U]], connection: Connection): T[U] =
normalStatement.execute(_.asCollection[U, T])

/**
@@ -65,11 +65,11 @@ trait CollectionsSql { self: Sql =>
* @return
* the results as an arbitrary collection of key value pairs
*/
def asPairCollection[U, V, T[_, _]](
parser: SqlRow => (U, V)
)(implicit factory: Factory[(U, V), T[U, V]], connection: Connection): T[U, V] =
normalStatement.execute(_.asPairCollection(parser))
def asPairCollection[U, V, T[_, _]]()(implicit
// def asPairCollection[U, V, T[_, _]](
// parser: SqlRow => (U, V)
// )(implicit factory: Factory[(U, V), T[U, V]], connection: Connection): T[U, V] =
// normalStatement.execute(_.asPairCollection(parser))
def asPairCollection[U, V, T[_, _]](implicit
factory: Factory[(U, V), T[U, V]],
connection: Connection,
p: RowParser[(U, V)]
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.lucidchart.relate

import java.sql.ResultSetMetaData
import scala.collection.compat._
import scala.collection.Factory
import scala.collection.mutable
import scala.language.higherKinds

trait CollectionsSqlResult { self: SqlResult =>

def asCollection[U, T[_]](parser: SqlRow => U)(implicit factory: Factory[U, T[U]]): T[U] =
asCollection(parser, Long.MaxValue)
def asCollection[U: RowParser, T[_]]()(implicit factory: Factory[U, T[U]]): T[U] =
def asCollection[U: RowParser, T[_]](implicit factory: Factory[U, T[U]]): T[U] =
asCollection(implicitly[RowParser[U]].parse, Long.MaxValue)
protected def asCollection[U: RowParser, T[_]](maxRows: Long)(implicit factory: Factory[U, T[U]]): T[U] =
asCollection(implicitly[RowParser[U]].parse, maxRows)
@@ -22,10 +22,10 @@ trait CollectionsSqlResult { self: SqlResult =>
}
}

builder.result
builder.result()
}

def asPairCollection[U, V, T[_, _]]()(implicit p: RowParser[(U, V)], factory: Factory[(U, V), T[U, V]]): T[U, V] = {
def asPairCollection[U, V, T[_, _]](implicit p: RowParser[(U, V)], factory: Factory[(U, V), T[U, V]]): T[U, V] = {
asPairCollection(p.parse, Long.MaxValue)
}
def asPairCollection[U, V, T[_, _]](parser: SqlRow => (U, V))(implicit factory: Factory[(U, V), T[U, V]]): T[U, V] =
@@ -45,7 +45,7 @@ trait CollectionsSqlResult { self: SqlResult =>
}
}

builder.result
builder.result()
}

}
62 changes: 33 additions & 29 deletions relate/src/main/scala/com/lucidchart/relate/Parameterizable.scala
Original file line number Diff line number Diff line change
@@ -12,12 +12,12 @@ trait Parameterizable[-A] {
/**
* Set the parameterized value at index {@code i} in the prepared statement to the {@code value}.
*/
def set(statement: PreparedStatement, i: Int, value: A)
def set(statement: PreparedStatement, i: Int, value: A): Unit

/**
* Set the parameterized value at index {@code i} in the prepared statement to {@code null}.
*/
def setNull(statement: PreparedStatement, i: Int)
def setNull(statement: PreparedStatement, i: Int): Unit
final def setOption(statement: PreparedStatement, i: Int, value: Option[A]) =
value.fold(setNull(statement, i))(set(statement, i, _))
}
@@ -39,38 +39,42 @@ object Parameterizable {

def from[A, B: Parameterizable](f: A => B) = implicitly[Parameterizable[B]].contraMap(f)

implicit val array = apply(_.setArray(_, _: Array), _.setNull(_, Types.ARRAY))
implicit val array: Parameterizable[Array] = apply(_.setArray(_, _: Array), _.setNull(_, Types.ARRAY))
// ideally, this would be named jBigDecimal, but that wouldn't be backwards compatibility
implicit val bigDecimal = apply(_.setBigDecimal(_, _: java.math.BigDecimal), _.setNull(_, Types.DECIMAL))
implicit val scalaBigDecimal = apply(
implicit val bigDecimal: Parameterizable[java.math.BigDecimal] =
apply(_.setBigDecimal(_, _: java.math.BigDecimal), _.setNull(_, Types.DECIMAL))
implicit val scalaBigDecimal: Parameterizable[scala.math.BigDecimal] = apply(
(stmt: PreparedStatement, i: Int, v: scala.math.BigDecimal) => stmt.setBigDecimal(i, v.bigDecimal),
_.setNull(_, Types.DECIMAL)
)
implicit val blob = apply(_.setBlob(_, _: Blob), _.setNull(_, Types.BLOB))
implicit val boolean = apply(_.setBoolean(_, _: Boolean), _.setNull(_, Types.BOOLEAN))
implicit val byte = apply(_.setByte(_, _: Byte), _.setNull(_, Types.TINYINT))
implicit val bytes = apply(_.setBytes(_, _: scala.Array[Byte]), _.setNull(_, Types.VARBINARY))
implicit val clob = apply(_.setClob(_, _: Clob), _.setNull(_, Types.CLOB))
implicit val date = apply(_.setDate(_, _: Date), _.setNull(_, Types.DATE))
implicit val double = apply(_.setDouble(_, _: Double), _.setNull(_, Types.DOUBLE))
implicit val float = apply(_.setFloat(_, _: Float), _.setNull(_, Types.FLOAT))
implicit val int = apply(_.setInt(_, _: Int), _.setNull(_, Types.INTEGER))
implicit val long = apply(_.setLong(_, _: Long), _.setNull(_, Types.BIGINT))
implicit val nClob = apply(_.setNClob(_, _: NClob), _.setNull(_, Types.NCLOB))
implicit val ref = apply(_.setRef(_, _: Ref), _.setNull(_, Types.REF))
implicit val rowId = apply(_.setRowId(_, _: RowId), _.setNull(_, Types.ROWID))
implicit val short = apply(_.setShort(_, _: Short), _.setNull(_, Types.SMALLINT))
implicit val sqlXml = apply(_.setSQLXML(_, _: SQLXML), _.setNull(_, Types.SQLXML))
implicit val string = apply(_.setString(_, _: String), _.setNull(_, Types.VARCHAR))
implicit val time = apply(_.setTime(_, _: Time), _.setNull(_, Types.TIME))
implicit val timestamp = apply(_.setTimestamp(_, _: Timestamp), _.setNull(_, Types.TIMESTAMP))
implicit val url = apply(_.setURL(_, _: URL), _.setNull(_, Types.DATALINK))
implicit val blob: Parameterizable[Blob] = apply(_.setBlob(_, _: Blob), _.setNull(_, Types.BLOB))
implicit val boolean: Parameterizable[Boolean] = apply(_.setBoolean(_, _: Boolean), _.setNull(_, Types.BOOLEAN))
implicit val byte: Parameterizable[Byte] = apply(_.setByte(_, _: Byte), _.setNull(_, Types.TINYINT))
implicit val bytes: Parameterizable[scala.Array[Byte]] =
apply(_.setBytes(_, _: scala.Array[Byte]), _.setNull(_, Types.VARBINARY))
implicit val clob: Parameterizable[Clob] = apply(_.setClob(_, _: Clob), _.setNull(_, Types.CLOB))
implicit val date: Parameterizable[Date] = apply(_.setDate(_, _: Date), _.setNull(_, Types.DATE))
implicit val double: Parameterizable[Double] = apply(_.setDouble(_, _: Double), _.setNull(_, Types.DOUBLE))
implicit val float: Parameterizable[Float] = apply(_.setFloat(_, _: Float), _.setNull(_, Types.FLOAT))
implicit val int: Parameterizable[Int] = apply(_.setInt(_, _: Int), _.setNull(_, Types.INTEGER))
implicit val long: Parameterizable[Long] = apply(_.setLong(_, _: Long), _.setNull(_, Types.BIGINT))
implicit val nClob: Parameterizable[NClob] = apply(_.setNClob(_, _: NClob), _.setNull(_, Types.NCLOB))
implicit val ref: Parameterizable[Ref] = apply(_.setRef(_, _: Ref), _.setNull(_, Types.REF))
implicit val rowId: Parameterizable[RowId] = apply(_.setRowId(_, _: RowId), _.setNull(_, Types.ROWID))
implicit val short: Parameterizable[Short] = apply(_.setShort(_, _: Short), _.setNull(_, Types.SMALLINT))
implicit val sqlXml: Parameterizable[SQLXML] = apply(_.setSQLXML(_, _: SQLXML), _.setNull(_, Types.SQLXML))
implicit val string: Parameterizable[String] = apply(_.setString(_, _: String), _.setNull(_, Types.VARCHAR))
implicit val time: Parameterizable[Time] = apply(_.setTime(_, _: Time), _.setNull(_, Types.TIME))
implicit val timestamp: Parameterizable[Timestamp] =
apply(_.setTimestamp(_, _: Timestamp), _.setNull(_, Types.TIMESTAMP))
implicit val url: Parameterizable[URL] = apply(_.setURL(_, _: URL), _.setNull(_, Types.DATALINK))

implicit val javaDate = from((date: java.util.Date) => new Timestamp(date.getTime))
implicit val localDate = from(Date.valueOf(_: LocalDate))
implicit val localTime = from(Time.valueOf(_: LocalTime))
implicit val instant = from(Timestamp.from)
implicit val uuid = from { uuid: UUID =>
// val foo = implicitly[Parameterizable[Timestamp]]
implicit val javaDate: Parameterizable[java.util.Date] = timestamp.contraMap(d => new Timestamp(d.getTime))
implicit val localDate: Parameterizable[LocalDate] = date.contraMap(Date.valueOf)
implicit val localTime: Parameterizable[LocalTime] = time.contraMap(Time.valueOf)
implicit val instant: Parameterizable[java.time.Instant] = timestamp.contraMap(Timestamp.from)
implicit val uuid: Parameterizable[UUID] = from { uuid: UUID =>
val bb = ByteBuffer.wrap(new scala.Array[Byte](16))
bb.putLong(uuid.getMostSignificantBits)
bb.putLong(uuid.getLeastSignificantBits)
Loading

0 comments on commit f68bd5b

Please sign in to comment.