How do I convert a java.util.UUID to doobie.syntax.SqlInterpolator.SingleFragment?

3.1k views Asked by At

I am trying to set up a simple scala app with database using doobie, http4s and circe.

How do I convert a java.util.UUID to doobie.syntax.SqlInterpolator.SingleFragment ?

final case class User(id: UUID, details: UserDetails)
  implicit val userDecoder: Decoder[User] = deriveDecoder[User]
  implicit def userEntityDecoder[F[_]: Sync]: EntityDecoder[F, User] = jsonOf

  implicit val userEncoder: Encoder[User] = deriveEncoder[User]
  implicit def userEntityEncoder[F[_]: Applicative]: EntityEncoder[F, User] = jsonEncoderOf

  implicit val put: Put[User] =
    Put[Json].contramap(_.asJson)

  implicit val get: Get[User] =
    Get[Json].temap(_.as[User].left.map(_.show))

[info] welcome to sbt 1.3.12 (N/A Java 14.0.1)
[info] loading global plugins from /Users/ryan/.sbt/1.0/plugins
[info] loading settings for project bobbymoore-build from plugins.sbt ...
[info] loading project definition from /Users/ryan/fullStackRyan/bobbymoore/project
[info] loading settings for project root from build.sbt ...
[info] set current project to bobbymoore (in build file:/Users/ryan/fullStackRyan/bobbymoore/)
[info] sbt server started at local:///Users/ryan/.sbt/1.0/server/90f560b1e0964865fc4c/sock
sbt:bobbymoore> compile
[info] Compiling 1 Scala source to /Users/ryan/fullStackRyan/bobbymoore/target/scala-2.13/classes ...
[error] /Users/ryan/fullStackRyan/bobbymoore/src/main/scala/com/c/bobbymoore/database/UserQueries.scala:24:20: type mismatch;
[error]  found   : java.util.UUID
[error]  required: doobie.syntax.SqlInterpolator.SingleFragment
[error]          |  ${user.id},
[error]                    ^
[error] /Users/ryan/fullStackRyan/bobbymoore/src/main/scala/com/c/bobbymoore/database/UserQueries.scala:34:21: type mismatch;
[error]  found   : java.util.UUID
[error]  required: doobie.syntax.SqlInterpolator.SingleFragment
[error]          |WHERE id=$id
[error]                     ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 2 s, completed 13 Oct 2020, 16:31:46

1

There are 1 answers

0
Mateusz Kubuszok On BEST ANSWER

If you are using PostgreSQL and the UUID in Java translate to UUID column in Postgres table, then you have to use a Postgres extensions for Doobie

// other doobie imports
import doobie.postgres._
import doobie.postgres.implicits._

sql"""SELECT id, name FROM users WHERE id = ${user.id}""".query[(UUID, String)]

If you don't use PSQL and this UUID maps to TEXT field you have to either map this yourself in query:

sql"""SELECT id, name FROM users WHERE id = ${user.id.toString}"""
  .query[(String, String)]
  .map { case (uuid, name) => (UUID.fromString(uuid), name) }

or define your own Meta[UUID] instance e.g.

implicit val uuidMeta: Meta[UUID] =
  Meta[String].imap[UUID](UUID.fromString)(_.toString)

This one is needed if you want to derive an instance for e.g. case class that contains UUID. Postgres extensions library delivers one that matches PSQL implementation.

You surely have to define your own Meta instance if you use e.g. Array[Byte] or some other numeric representation on DB side to represent UUIDs.