Skip to content

Doobie Type Mapping Issue with PostgreSQL NULL Arrays #2273

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions