Skunk-Scala多参数查询类型不匹配错误排查求助
Skunk 查询类型不匹配问题排查
问题代码
查询代码:
import br.com.gbtech.model.PaymentRequestItem import cats.effect.{IO, Resource} import skunk.codec.all.* import skunk.implicits.* import skunk.{Query, Session, ~} val query: Query[(String *: Int), ValueObject] = sql""" SELECT field1, field2 FROM sample_table WHERE field1 = $text AND field2 = $int4 """.query(ValueObject.decoder) database.use(s => s.option(query)((param1, param2)))
解码器代码:
case class ValueObject(field1: Int, field2: String) object ValueObject { val decoder: Decoder[ValueObject] = (int4 ~ varchar).map { case (f1, f2) => ValueObject(f1, f2) } }
错误信息
type mismatch; found : skunk.Query[String *: Int *: org.typelevel.twiddles.EmptyTuple,br.com.ValueObject] (which expands to) skunk.Query[String :: Int :: shapeless.HNil,br.com.ValueObject] required: skunk.Query[String *: Int,br.com.ValueObject] (which expands to) skunk.Query[String :: Int,br.com.ValueObject] """.query(ValueObject.decoder)
问题原因及解决方法
核心问题
你显式声明的查询参数类型String *: Int是Scala标准二元元组类型,但Skunk在处理多参数查询时,生成的参数类型是带EmptyTuple后缀的链式类型String *: Int *: EmptyTuple(对应Skunk内部基于HList的参数结构),二者类型不兼容导致编译错误。
解决方式(任选其一)
- 去掉显式类型声明:让Scala自动推导Skunk生成的正确类型,这是最简单的方案:
val query = sql""" SELECT field1, field2 FROM sample_table WHERE field1 = $text AND field2 = $int4 """.query(ValueObject.decoder)
- 修正显式类型声明:将类型改为Skunk期望的带
EmptyTuple的形式:
import org.typelevel.twiddles.EmptyTuple val query: Query[String *: Int *: EmptyTuple, ValueObject] = sql""" SELECT field1, field2 FROM sample_table WHERE field1 = $text AND field2 = $int4 """.query(ValueObject.decoder)
- 使用标准Tuple类型声明:直接用Scala的
(String, Int)替代链式类型声明,Skunk会自动兼容:
val query: Query[(String, Int), ValueObject] = sql""" SELECT field1, field2 FROM sample_table WHERE field1 = $text AND field2 = $int4 """.query(ValueObject.decoder)
额外注意点
确保解码器的字段顺序与SQL查询中SELECT的字段顺序完全匹配:你的SQL查询返回field1, field2,解码器用int4 ~ varchar映射到ValueObject(field1: Int, field2: String),需保证数据库中field1是整数类型、field2是字符串类型,避免运行时解码失败。
内容的提问来源于stack exchange,提问作者André Luís Oliveira
相关产品推荐
相关产品推荐

