Skip to content

Commit

Permalink
Merge pull request #2091 from typelevel/typecheck_optimizations
Browse files Browse the repository at this point in the history
Improve analysis message + Small optimizations
  • Loading branch information
jatcwang authored Sep 5, 2024
2 parents 57696d9 + c04c180 commit 867e68d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 16 deletions.
35 changes: 19 additions & 16 deletions modules/core/src/main/scala/doobie/util/analysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ object analysis {
override val tag = "P"
override def msg =
s"""|${typeName(put.typeStack.last, n)} is not coercible to ${jdbcType.show.toUpperCase}
|(${vendorTypeName})
|(vendor's name: $vendorTypeName)
|according to the JDBC specification.
|Expected schema type was ${put.jdbcTargets.head.show.toUpperCase}.""".stripMargin.linesIterator.mkString(" ")
}
Expand Down Expand Up @@ -100,16 +100,19 @@ object analysis {
final case class ColumnTypeError(index: Int, get: Get[?], n: NullabilityKnown, schema: ColumnMeta)
extends AlignmentError {
override val tag = "C"
override def msg =
s"""|${schema.jdbcType.show.toUpperCase} (${schema.vendorTypeName}) is not
|coercible to ${typeName(get.typeStack.last, n)} (${get.vendorTypeNames.mkString(
",")}) according to the JDBC specification or any defined
|mapping.
|Fix this by changing the schema type to
override def msg = {
val vendorNamePartFromGet =
if (get.vendorTypeNames.isEmpty) ""
else s" (vendor's name: ${get.vendorTypeNames.mkString(",")})"

s"""|${schema.jdbcType.show.toUpperCase} (vendor name: ${schema.vendorTypeName}) is not
|coercible to ${typeName(get.typeStack.last, n)}$vendorNamePartFromGet based on defined mapping.
|Fix this by changing the column type to
|${get.jdbcSources.toList.map(_.show.toUpperCase).mkString(" or ")}; or the
|Scala type to an appropriate ${if (schema.jdbcType === JdbcType.Array) "array" else "object"}
|type.
|""".stripMargin.linesIterator.mkString(" ")
}
}

final case class ColumnTypeWarning(index: Int, get: Get[?], n: NullabilityKnown, schema: ColumnMeta)
Expand Down Expand Up @@ -139,10 +142,9 @@ object analysis {
}

private def hasParameterTypeErrors[A](put: Put[A], paramMeta: ParameterMeta): Boolean = {
val jdbcTypeMatches = put.jdbcTargets.contains_(paramMeta.jdbcType)
val vendorTypeMatches = put.vendorTypeNames.isEmpty || put.vendorTypeNames.contains_(paramMeta.vendorTypeName)

!jdbcTypeMatches || !vendorTypeMatches
!put.jdbcTargets.contains_(paramMeta.jdbcType) ||
!(put.vendorTypeNames.isEmpty ||
put.vendorTypeNames.contains_(paramMeta.vendorTypeName))
}

def parameterTypeErrors: List[ParameterTypeError] =
Expand All @@ -158,10 +160,11 @@ object analysis {
}

private def hasColumnTypeError[A](get: Get[A], columnMeta: ColumnMeta): Boolean = {
val jdbcTypeMatches = (get.jdbcSources.toList ++ get.jdbcSourceSecondary).contains_(columnMeta.jdbcType)
val vendorTypeMatches = get.vendorTypeNames.isEmpty || get.vendorTypeNames.contains_(columnMeta.vendorTypeName)
!jdbcTypeMatches || !vendorTypeMatches
!get.allJdbcSources.contains_(columnMeta.jdbcType) ||
!(get.vendorTypeNames.isEmpty ||
get.vendorTypeNames.contains_(columnMeta.vendorTypeName))
}

def columnTypeErrors: List[ColumnTypeError] =
columnAlignment.zipWithIndex.collect {
case (Ior.Both((get, n1), p), n) if hasColumnTypeError(get, p) =>
Expand Down Expand Up @@ -190,8 +193,8 @@ object analysis {
columnMisalignments ++ columnTypeErrors ++ columnTypeWarnings ++ nullabilityMisalignments

lazy val alignmentErrors =
(parameterAlignmentErrors).sortBy(m => (m.index, m.msg)) ++
(columnAlignmentErrors).sortBy(m => (m.index, m.msg))
parameterAlignmentErrors.sortBy(m => (m.index, m.msg)) ++
columnAlignmentErrors.sortBy(m => (m.index, m.msg))

/** Description of each parameter, paired with its errors. */
lazy val paramDescriptions: List[(String, List[AlignmentError])] = {
Expand Down
2 changes: 2 additions & 0 deletions modules/core/src/main/scala/doobie/util/get.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ sealed abstract class Get[A](
val get: Coyoneda[(ResultSet, Int) => *, A]
) {

val allJdbcSources: NonEmptyList[JdbcType] = this.jdbcSources ++ this.jdbcSourceSecondary

final def unsafeGetNonNullable(rs: ResultSet, n: Int): A = {
val i = get.fi(rs, n)
if (rs.wasNull)
Expand Down

0 comments on commit 867e68d

Please sign in to comment.