Skip to content

Doobie Type Mapping Issue with PostgreSQL NULL Arrays #2273

@vasylyamnych

Description

@vasylyamnych

during unit tests Doobie's type checker reports errors on PostgreSQL nullable array columns (text[]) even when the Scala model correctly uses Option[List[A]].

✕ C14 my_array_column ARRAY (_text) NULL → Array[A] Reading a NULL value into Array[A] will result in a runtime failure. Fix this by making the schema type NOT NULL or by changing the Scala type to Option[Array[A]]

Context

  • PostgreSQL columns defined as nullable text[] arrays
  • Model class fields correctly defined as Option[List[CustomType]]
  • Custom value classes extending AnyVal around String
    final case class CustomType(string: String) extends AnyVal
  • Appropriate Meta instances defined and in scope

Reproduction

  1. Define PostgreSQL columns as nullable text[]
  2. Define case class with Option[List[ValueClass]] fields
  3. Run Doobie's type checker
  4. Observe type mismatch errors about Array[A] vs Option[Array[A]]

The issue appears to be in Doobie's internal array type handling rather than in our code, as the model is already correctly using Option[List[A]] types.

Also I need to write custom implicits to be able to map to value classes - it would be nice if it will work out of the box

Option[CustomType1] - works out of the box
Option[List[String]] - works out of the box
Option[List[CustomType1]] - doesn't works
  final case class CustomType1(string: String) extends AnyVal
  ...
  final case class CustomType5(string: String) extends AnyVal

  implicit val optionListStringMeta: Meta[Option[List[String]]] =
    implicitly[Meta[Array[Option[String]]]]
      .imap(
        _.toList.sequence
      )(_.sequence.toArray)

  implicit val customType1Meta: Meta[Option[List[CustomType1]]] =
    implicitly[Meta[Option[List[String]]]]
      .imap(_.map(_.map(CustomType1(_))))(_.map(_.map(_.string)))

  ...

  implicit val customType5Meta: Meta[Option[List[CustomType5]]] =
    implicitly[Meta[Option[List[String]]]]
      .imap(_.map(_.map(CustomType5(_))))(_.map(_.map(_.string)))

Scala 2.13.16, Doobie 1.0.0-RC8

following imports are used

import cats.implicits.*

import doobie.*
import doobie.implicits.*
import doobie.postgres.implicits.*

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions