`ClassCastException` when reading from `column[List[Double]]` of column type `numeric[]`
TobiasPfeifer opened this issue · 2 comments
slick-pg version: 0.20.3
slick version: 3.3.3
A table with a column of type numeric[]
that is defined as column[List[Double]]
will insert List[Double]
for that column just fine. However, it will not read a List[Double]
but a List[BigDecimal]
at runtime.
This will result in a ClassCastException
when trying to access the values of List[Double]
:
ERROR: java.lang.ClassCastException: class java.math.BigDecimal cannot be cast to class java.lang.Double (java.math.BigDecimal and java.lang.Double are in module java.base of loader 'bootstrap')
create table test
(
id serial primary key,
test numeric[]
);
case class Test(test: List[Double]) //the field test will be read as List[BigDecimal]
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def test = column[List[Double]]("test")
def * =
(
id.? ::
test::
HNil
).<>(applyTest, unapplyTest)
def applyTest(data: Option[Int] :: List[Double] :: HNil): Test = data match {
data match {
case _ :: list => Test(list)
}
}
VPostgresProfile.api._
and VPostgresProfile
is in scope:
trait VPostgresProfile
extends ExPostgresProfile
with PgArraySupport
with PgDate2Support
with PgRangeSupport
with PgHStoreSupport {
def pgjson = "jsonb"
// Add back `capabilities.insertOrUpdate` to enable native `upsert` support; for postgres 9.5+
override protected def computeCapabilities: Set[Capability] =
super.computeCapabilities + slick.jdbc.JdbcCapabilities.insertOrUpdate
override val api = VAPI
object VAPI extends API with ArrayImplicits with DateTimeImplicits with RangeImplicits with HStoreImplicits {
val strSimpleJdbcArrayListType: SimpleArrayJdbcType[String] = new SimpleArrayJdbcType[String]("text")
val longSimpleJdbcArrayListType: SimpleArrayJdbcType[Long] = new SimpleArrayJdbcType[Long]("bigint")
val sqlTSSimpleJdbcArrayListType: SimpleArrayJdbcType[SQLTimestamp] =
new SimpleArrayJdbcType[SQLTimestamp]("timestamp")
implicit val strListTypeMapper: JdbcType[List[String]] =
strSimpleJdbcArrayListType.to(_.toList)
}
}
object VPostgresProfile extends VPostgresProfile
workaround:
def applyTest(data: Option[Int] :: List[Double] :: HNil): Test = data match {
data match {
case _ :: list => Test(list.asInstanceOf[List[java.math.BigDecimal]].map(_.doubleValue))
}
@TobiasPfeifer numeric[]
was bind to List[BigDecimal]
, and float8[]
was bind to List[Double]
.
But pg
can accept double[]
to numeric[]
, so the insert
with List[Double]
is ok.
You can change the declaration of test numeric[]
to test float8[]
, to keep them consistent.
I had the same issue. When I want to use BigDecimal
instead, I get the following compile error:
could not find implicit value for parameter tt: slick.ast.TypedType[Option[List[BigDecimal]]]
def valueNumericArray = column[Option[List[BigDecimal]]]("value_numeric_array")
Declaration looks like: def valueNumericArray = column[Option[List[BigDecimal]]]("value_numeric_array")