From cc6f0282f23a832696de959e5dd70ebb11000d07 Mon Sep 17 00:00:00 2001 From: Richard Shurtz Date: Tue, 26 Sep 2023 15:08:48 -0700 Subject: [PATCH 1/2] Use more specific `java.sql.Date` as the return type for strictDate methods. Always use fully qualified name between java.sql.Date and java.util.Date --- .../main/scala/com/lucidchart/relate/SqlRow.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala b/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala index a725c1b..4f1e0e9 100644 --- a/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala +++ b/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala @@ -5,7 +5,7 @@ import java.net.URL import java.nio.ByteBuffer import java.sql.{Blob, Clob, NClob, Ref, RowId, SQLXML, Time, Timestamp} import java.time.Instant -import java.util.{Calendar, Date, UUID} +import java.util.{Calendar, UUID} import scala.collection.JavaConverters._ import scala.language.higherKinds import scala.util.Try @@ -41,10 +41,10 @@ class SqlRow(val resultSet: java.sql.ResultSet) extends ResultSetWrapper { def strictCharacterStreamOption(column: String): Option[Reader] = getResultSetOption(resultSet.getCharacterStream(column)) def strictClob(column: String): Clob = resultSet.getClob(column) def strictClobOption(column: String): Option[Clob] = getResultSetOption(resultSet.getClob(column)) - def strictDate(column: String): Date = resultSet.getDate(column) - def strictDateOption(column: String): Option[Date] = getResultSetOption(resultSet.getDate(column)) - def strictDate(column: String, cal: Calendar): Date = resultSet.getDate(column, cal) - def strictDateOption(column: String, cal: Calendar): Option[Date] = getResultSetOption(resultSet.getDate(column, cal)) + def strictDate(column: String): java.sql.Date = resultSet.getDate(column) + def strictDateOption(column: String): Option[java.sql.Date] = getResultSetOption(resultSet.getDate(column)) + def strictDate(column: String, cal: Calendar): java.sql.Date = resultSet.getDate(column, cal) + def strictDateOption(column: String, cal: Calendar): Option[java.sql.Date] = getResultSetOption(resultSet.getDate(column, cal)) def strictDouble(column: String): Double = resultSet.getDouble(column) def strictDoubleOption(column: String): Option[Double] = getResultSetOption(resultSet.getDouble(column)) def strictFloat(column: String): Float = resultSet.getFloat(column) @@ -138,12 +138,13 @@ class SqlRow(val resultSet: java.sql.ResultSet) extends ResultSetWrapper { def javaBigDecimal(column: String): java.math.BigDecimal = javaBigDecimalOption(column).get def javaBigDecimalOption(column: String): Option[java.math.BigDecimal] = getResultSetOption(resultSet.getBigDecimal(column)) - def date(column: String): Date = dateOption(column).get + def date(column: String): java.util.Date = dateOption(column).get // Timestamp documentation says that "it is recommended that code not view Timestamp values generically as an instance // of java.util.Date." Since this is typed as a Date we should probably return an instance of a Date. // `date == timestamp` can be true but `timestamp == date` is always false "the Timestamp.equals(Object) method is not // symmetric with respect to the java.util.Date.equals(Object)" - def dateOption(column: String): Option[Date] = getResultSetOption(resultSet.getTimestamp(column)).map(ts => new Date(ts.getTime)) + def dateOption(column: String): Option[java.util.Date] = + getResultSetOption(resultSet.getTimestamp(column)).map(ts => new java.util.Date(ts.getTime)) def instant(column: String): Instant = instantOption(column).get def instantOption(column: String): Option[Instant] = getResultSetOption(resultSet.getTimestamp(column)).map(_.toInstant) From 6d145f3237a5f8cf94f6b036369b6724de336a3d Mon Sep 17 00:00:00 2001 From: Richard Shurtz Date: Tue, 26 Sep 2023 15:50:58 -0700 Subject: [PATCH 2/2] Add in LocalDate parsing options --- relate/src/main/scala/com/lucidchart/relate/ColReader.scala | 3 ++- relate/src/main/scala/com/lucidchart/relate/SqlRow.scala | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/relate/src/main/scala/com/lucidchart/relate/ColReader.scala b/relate/src/main/scala/com/lucidchart/relate/ColReader.scala index 5745c4f..8f4f5ad 100644 --- a/relate/src/main/scala/com/lucidchart/relate/ColReader.scala +++ b/relate/src/main/scala/com/lucidchart/relate/ColReader.scala @@ -1,6 +1,6 @@ package com.lucidchart.relate -import java.time.Instant +import java.time.{Instant, LocalDate} import java.util.{Date, UUID} class NullColumnException(col: String) extends Exception(s"Unexpected null value in column: $col") @@ -42,6 +42,7 @@ object ColReader { implicit val byteArrayReader: ColReader[Array[Byte]] = ColReader { (col, row) => row.byteArrayOption(col)} implicit val byteReader: ColReader[Byte] = ColReader { (col, row) => row.byteOption(col)} implicit val dateReader: ColReader[Date] = ColReader { (col, row) => row.dateOption(col)} + implicit val localDateReader: ColReader[LocalDate] = ColReader { (col, row) => row.localDateOption(col)} implicit val instantReader: ColReader[Instant] = ColReader { (col, row) => row.instantOption(col)} implicit val doubleReader: ColReader[Double] = ColReader { (col, row) => row.doubleOption(col)} implicit val intReader: ColReader[Int] = ColReader { (col, row) => row.intOption(col)} diff --git a/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala b/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala index 4f1e0e9..0d367c2 100644 --- a/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala +++ b/relate/src/main/scala/com/lucidchart/relate/SqlRow.scala @@ -4,10 +4,9 @@ import java.io.{InputStream, Reader} import java.net.URL import java.nio.ByteBuffer import java.sql.{Blob, Clob, NClob, Ref, RowId, SQLXML, Time, Timestamp} -import java.time.Instant +import java.time.{Instant, LocalDate} import java.util.{Calendar, UUID} import scala.collection.JavaConverters._ -import scala.language.higherKinds import scala.util.Try object SqlRow { @@ -146,6 +145,9 @@ class SqlRow(val resultSet: java.sql.ResultSet) extends ResultSetWrapper { def dateOption(column: String): Option[java.util.Date] = getResultSetOption(resultSet.getTimestamp(column)).map(ts => new java.util.Date(ts.getTime)) + def localDate(column: String): LocalDate = localDateOption(column).get + def localDateOption(column: String): Option[LocalDate] = strictDateOption(column).map(_.toLocalDate) + def instant(column: String): Instant = instantOption(column).get def instantOption(column: String): Option[Instant] = getResultSetOption(resultSet.getTimestamp(column)).map(_.toInstant)