From 81add5ec07f1db652af581b0cee3fa090007d9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bigorajski?= <lbg@touk.pl> Date: Mon, 26 Aug 2024 18:25:20 +0200 Subject: [PATCH] review fixes --- .../sql/db/schema/ColumnDefinition.scala | 90 ++++++++----------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/ColumnDefinition.scala b/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/ColumnDefinition.scala index dd6ef6dc976..9350089a53c 100644 --- a/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/ColumnDefinition.scala +++ b/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/ColumnDefinition.scala @@ -5,58 +5,57 @@ import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypingResult} import java.io.BufferedReader import java.sql.{Clob, ResultSet, ResultSetMetaData} import java.time.{Instant, LocalDate, LocalTime} +import java.util.stream.Collectors import java.{sql, util} -import scala.annotation.tailrec -import scala.collection.mutable.ArrayBuffer import scala.util.Using -object ColumnDefinition { +final case class ColumnDefinition( + name: String, + typing: TypingResult, + valueMapping: Any => Any +) { + + def extractValue(resultSet: ResultSet): Any = { + // we could here use method resultSet.getObject(Int) and pass column number as argument + // but in case of ignite db it is not certain which column index corresponds to which column. + val value = resultSet.getObject(name) + Option(value).map(valueMapping).getOrElse(value) + } - private lazy val sqlTypingMap = Map( - classOf[sql.Array].getName -> Typed.typedClass(classOf[util.List[Any]]), - classOf[sql.Time].getName -> Typed.typedClass(classOf[LocalTime]), - classOf[sql.Date].getName -> Typed.typedClass(classOf[LocalDate]), - classOf[sql.Timestamp].getName -> Typed.typedClass(classOf[Instant]), - classOf[sql.Clob].getName -> Typed.typedClass(classOf[String]), - ) +} - def apply(columnNo: Int, resultMeta: ResultSetMetaData): ColumnDefinition = +object ColumnDefinition { + private val sqlArrayClassName = classOf[sql.Array].getName + private val sqlTimeClassName = classOf[sql.Time].getName + private val sqlDateClassName = classOf[sql.Date].getName + private val sqlTimestampClassName = classOf[sql.Timestamp].getName + private val sqlClobClassName = classOf[sql.Clob].getName + + def apply(columnNo: Int, resultMeta: ResultSetMetaData): ColumnDefinition = { + val (typingResult, valueMapping) = mapValueToSupportedType(resultMeta.getColumnClassName(columnNo)) ColumnDefinition( name = resultMeta.getColumnName(columnNo), - typing = supportedTypeTypingResult(resultMeta.getColumnClassName(columnNo)) + typing = typingResult, + valueMapping = valueMapping ) + } - def apply(typing: (String, String)): ColumnDefinition = + def apply(typing: (String, String)): ColumnDefinition = { + val (typingResult, valueMapping) = mapValueToSupportedType(typing._2) ColumnDefinition( name = typing._1, - typing = supportedTypeTypingResult(typing._2) + typing = typingResult, + valueMapping = valueMapping ) - - private def supportedTypeTypingResult(className: String): TypingResult = - sqlTypingMap.getOrElse(className, Typed.typedClass(Class.forName(className))) -} - -final case class ColumnDefinition( - name: String, - typing: TypingResult -) { - - def extractValue(resultSet: ResultSet): Any = { - // we could here use method resultSet.getObject(Int) and pass column number as argument - // but in case of ignite db it is not certain which column index corresponds to which column. - val value = resultSet.getObject(name) - Option(value) - .map(mapValueToSupportedType) - .getOrElse(value) } - private def mapValueToSupportedType(value: Any): Any = value match { - case v: sql.Array => readArray(v) - case v: sql.Time => v.toLocalTime - case v: sql.Date => v.toLocalDate - case v: sql.Timestamp => v.toInstant - case v: sql.Clob => readClob(v) - case _ => value + private def mapValueToSupportedType(className: String): (TypingResult, Any => Any) = className match { + case `sqlArrayClassName` => (Typed.typedClass(classOf[util.List[Any]]), v => readArray(v.asInstanceOf[sql.Array])) + case `sqlTimeClassName` => (Typed.typedClass(classOf[LocalTime]), v => v.asInstanceOf[sql.Time].toLocalTime) + case `sqlDateClassName` => (Typed.typedClass(classOf[LocalDate]), v => v.asInstanceOf[sql.Date].toLocalDate) + case `sqlTimestampClassName` => (Typed.typedClass(classOf[Instant]), v => v.asInstanceOf[sql.Timestamp].toInstant) + case `sqlClobClassName` => (Typed.typedClass(classOf[String]), v => readClob(v.asInstanceOf[sql.Clob])) + case _ => (Typed.typedClass(Class.forName(className)), identity) } private def readArray(v: sql.Array): util.List[AnyRef] = { @@ -72,17 +71,6 @@ final case class ColumnDefinition( Using.resource(new BufferedReader(v.getCharacterStream))(br => readFromStream(br)) } - @tailrec private def readFromStream( - br: BufferedReader, - acc: ArrayBuffer[String] = new ArrayBuffer[String]() - ): String = { - val string = br.readLine() - if (string == null) { - acc.mkString(System.lineSeparator) - } else { - acc.append(string) - readFromStream(br, acc) - } - } - + private def readFromStream(br: BufferedReader): String = + br.lines().collect(Collectors.joining(System.lineSeparator())) }