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
相关产品推荐
相关产品推荐

