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

sqlc生成Go查询时复合类型字段引用异常问题

问题描述

我有一个PostgreSQL SQL查询,WHERE子句引用了复合类型的字段,查询语句如下:

const getTagFor = -- name: GetTagFor :many 
SELECT create_date, modified_date, id, tenant_id, name, value, system, owner FROM fleetmanager_schema.tag WHERE $1 = (owner).obj_id AND tenant_id=$2

其中owner是复合类型obj_ref(对应Go类型ObjRef),意图是将复合类型的owner.obj_id字段与传入的参数$1匹配。ObjRef定义如下:

type ObjRef struct {
ObjId int64 `json:"obj_id" range:"min=8,max=32"`
ObjType string `json:"obj_type" range:"min=3,max=32"`
}

但sqlc生成的查询代码有问题,它传入了完整的arg.Owner对象,导致pgx报错(无法编码类型)。生成的代码如下:

type GetTagForParams struct {
Owner common.ObjRef
TenantID pgtype.Int8
}

func (q *Queries) GetTagFor(ctx context.Context, arg GetTagForParams) ([]FleetmanagerSchemaTag, error) {
rows, err := q.db.Query(ctx, getTagFor, arg.Owner, arg.TenantID)

该查询因无法将复合类型与int64比较而失败。手动修改生成的代码为以下内容后,查询可正常执行并返回正确结果:

rows, err := q.db.Query(ctx, getTagFor, arg.Owner.ObjId, arg.TenantID)
if err != nil {

请问是否有特定的标记或属性可以配置sqlc以生成正确的代码?

解决方案

可以通过以下几种方式配置sqlc生成正确的参数传递代码:

方法1:给SQL参数添加类型注释

在查询的注释中显式声明参数类型,告诉sqlc$1是int64而非复合类型,修改后的SQL如下:

const getTagFor = -- name: GetTagFor :many 
-- param $1: int64
SELECT create_date, modified_date, id, tenant_id, name, value, system, owner FROM fleetmanager_schema.tag WHERE $1 = (owner).obj_id AND tenant_id=$2

这样sqlc会生成仅包含ObjId(命名为对应参数名)和TenantID的参数结构体,执行时直接传入int64类型的ObjId值。

方法2:调整SQL中的参数引用逻辑

直接在SQL中引用复合类型参数的字段,让sqlc自动识别需要提取的字段,修改后的SQL如下:

const getTagFor = -- name: GetTagFor :many 
SELECT create_date, modified_date, id, tenant_id, name, value, system, owner FROM fleetmanager_schema.tag WHERE $1.obj_id = (owner).obj_id AND tenant_id=$2

此时sqlc生成的参数结构体仍会包含完整的ObjRef对象,但执行时会自动提取obj_id字段传入查询,无需手动修改代码。

方法3:配置sqlc类型映射(适用于全局场景)

如果项目中有sqlc.yaml配置文件,可以添加类型映射规则,明确PostgreSQL复合类型obj_ref与Go类型ObjRef的关联,同时配置参数解析逻辑:

version: "2"
sql:
  - schema: "schema.sql"
    queries: "queries.sql"
    engine: "postgresql"
    gen:
      go:
        package: "db"
        out: "db"
        overrides:
          - db_type: "obj_ref"
            go_type:
              import: "your/project/path/common"
              type: "ObjRef"
            param_type:
              import: "your/project/path/common"
              type: "ObjRef"

这种方式适合全局复用复合类型的场景,确保sqlc在处理参数时能正确解析字段。

内容的提问来源于stack exchange,提问作者Kay Dee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:31:06