scalaimplicit-conversionimplicitziozio-quill

ZIO Quill: Can't find implicit SchemaMeta for type models.Pet


I'm currently working on a pet store application using ZIO and Quill. As part of my learning process, I've set up a local H2 database and configured it to store pet information. However, I'm encountering an issue when trying to fetch pets from the database using ZIO Quill.

I've defined the Pet case class and provided the implicit SchemaMeta inside its companion object. However, when I try to fetch pets, I get the following error:

Can't find an implicit SchemaMeta for type models.Pet.

enter image description here

I'm not sure what's causing this issue. I've checked my imports and dependencies, and they seem to be correct. Additionally, I've ensured that the table name and column names in my database match those specified in my Quill schema definitions.

Could someone please help me understand why I'm encountering this error and how I can resolve it?

    package models

import config.QuillContext.{querySchema, quote}
import io.getquill.{EntityQuery, Quoted}
import zio.json.{DeriveJsonCodec, JsonCodec}
import zio.schema.{DeriveSchema, Schema}
import java.util.UUID
final case class Pet(
                    petId:UUID,
                    name: String,
                    species:String,
                    ownerId:UUID
                    )
object Pet {
  implicit val petSchemaMeta: Quoted[EntityQuery[Pet]] = quote {
    querySchema[Pet](
      "PETS",
      _.petId -> "PET_ID",
      _.name -> "NAME",
      _.species -> "SPECIES",
      _.ownerId -> "OWNER_ID"
    )
  }
  implicit val codec: JsonCodec[Pet] = DeriveJsonCodec.gen[Pet]
  implicit val petSchema: Schema[Pet] = DeriveSchema.gen[Pet]
}

Quill Context

    package config

import com.zaxxer.hikari.{HikariConfig, HikariDataSource}
import io.getquill.{H2ZioJdbcContext, SnakeCase, UpperCase}
import models.Pet
import zio.ZLayer

import javax.sql.DataSource

object QuillContext extends H2ZioJdbcContext(UpperCase){

  val dburl = "jdbc:h2:./test"
  val userName = "sa"
  val password = "password"

  val h2dbConfig = new HikariConfig()
  h2dbConfig.setJdbcUrl(dburl)
  h2dbConfig.setUsername(userName)
  h2dbConfig.setPassword(password)

  val dataSource = new HikariDataSource(h2dbConfig)

  val dataSourceLayer:ZLayer[Any,Throwable,DataSource] = ZLayer.succeed(dataSource)


  //added Schema Meta
  implicit val petSchemaMeta: SchemaMeta[Pet] = schemaMeta[Pet]("pets")


}

build.sbt

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.13"

lazy val root = (project in file("."))
  .settings(
    name := "zio-pets-learn"
  )

libraryDependencies ++= Seq(
  "dev.zio" %% "zio" % "2.1-RC1",
  "io.getquill" %% "quill-zio" % "4.8.0",
  "io.getquill" %% "quill-jdbc-zio" % "4.8.1",
  "com.h2database" % "h2" % "2.2.224",

  "dev.zio" %% "zio-schema"          % "0.4.15",
  "dev.zio" %% "zio-schema-derivation" % "0.4.15",

  "org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided"

)

Thank you!

github-url

Runtime Issues: enter image description here


Solution

  • If implicits of type SomeTypeclass[SomeDatatype] should be found without import, then one should normally put them into companion object of SomeTypeclass or SomeDatatype

    Where does Scala look for implicits?

    Encoding and Decoding for Student Case Class with Animal Trait

    Now

    implicit val petSchemaMeta: SchemaMeta[Pet] = schemaMeta[Pet]("pets")
    

    is defined in object QuillContext, not in companion object of SchemaMeta or Pet, so it's out of implicit scope and should be imported explicitly.

    If you replace

    import config.QuillContext.{run, query}
    

    with

    import config.QuillContext.{run, query, petSchemaMeta}
    

    then compile error

    [error] zio-pets-learn/src/main/scala/PetService.scala:22:26: Can't find an implicit `SchemaMeta` for type `models.Pet`
    [error]                 run(query[Pet]).provideEnvironment(ZEnvironment(dataSource))
    [error]                          ^
    

    changes to

    // (*)
    [error] zio-pets-learn/src/main/scala/PetService.scala:22:26: type mismatch;
    [error]  found   : io.getquill.Quoted[io.getquill.EntityQuery[models.Pet]]
    [error]  required: io.getquill.EntityQuery[models.Pet]
    [error]                 run(query[Pet]).provideEnvironment(ZEnvironment(dataSource))
    [error]                          ^
    

    The thing is that implicit SchemaMeta are expected to be imported with _ (probably because of some macro magic def run[T](quoted: Quoted[Query[T]]): Result[RunQueryResult[T]] = macro QueryMacro.runQuery[T] or some implicit conversion not found)

    https://github.com/zio/zio-quill/issues/1860

    So replace the import with

    import config.QuillContext._
    

    Then the code compiles

    https://github.com/siva3060/zio-pets-learn/pull/1

    https://github.com/DmytroMitin/zio-pets-learn/actions/runs/8128575397/job/22214609741

    Also the following import seems to be working in your case

    import config.QuillContext.{run, query, petSchemaMeta, quote, unquote}
    

    Implicit conversions quote/unquote are necessary for conversions between T and Quoted[T], e.g. EntityQuery[Pet] and Quoted[EntityQuery[Pet]] in (*).

    How to debug implicits (at compile time): In scala 2 or 3, is it possible to debug implicit resolution process in runtime?