Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException when reading from column[List[Double]] of column type numeric[] #589

Open
TobiasPfeifer opened this issue Nov 10, 2022 · 2 comments

Comments

@TobiasPfeifer
Copy link

TobiasPfeifer commented Nov 10, 2022

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))
      }
@tminglei
Copy link
Owner

@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.

@perotom
Copy link

perotom commented Jun 4, 2024

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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants