You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的参数结构),二者类型不兼容导致编译错误。

解决方式(任选其一)

  1. 去掉显式类型声明:让Scala自动推导Skunk生成的正确类型,这是最简单的方案:
val query = sql"""
  SELECT field1, field2
  FROM   sample_table
  WHERE  field1 = $text
  AND field2 = $int4
""".query(ValueObject.decoder)
  1. 修正显式类型声明:将类型改为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)
  1. 使用标准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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:35:04