我正在使用sqlc
和pgx/v5
,并获得了用户定义的枚举类型的postgres数组的以下错误:Error: can't scan into dest[1]: cannot scan unknown type (OID 16385) in text format into *pgtype.Array[my-app/sqlc.Option]
schema和query:
CREATE TYPE option AS ENUM (
'OPT_1',
'OPT_2',
'OPT_3'
);
CREATE TABLE IF NOT EXISTS blah (
id BIGINT PRIMARY KEY,
options option[] NOT NULL DEFAULT '{OPT_1}'
);
-- name: CreateBlah :one
INSERT INTO blah (
id
) VALUES (
$1
)
RETURNING *;
sqlc
似乎正确生成了类型:
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.16.0
package sqlc
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgx/v5/pgtype"
)
type Option string
const (
OptionOPT1 Option = "OPT_1"
OptionOPT2 Option = "OPT_2"
OptionOPT3 Option = "OPT_3"
)
func (e *Option) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = Option(s)
case string:
*e = Option(s)
default:
return fmt.Errorf("unsupported scan type for Option: %T", src)
}
return nil
}
type NullOption struct {
Option Option
Valid bool // Valid is true if Option is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullOption) Scan(value interface{}) error {
if value == nil {
ns.Option, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.Option.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullOption) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.Option), nil
}
func (e Option) Valid() bool {
switch e {
case OptionOPT1,
OptionOPT2,
OptionOPT3:
return true
}
return false
}
type Blah struct {
ID int64
Options pgtype.Array[Option]
}
我可以通过定义自己的类型并实现scanner
接口,然后在sqlc
配置中指定重写来解决它:
package types
import (
"fmt"
"strings"
"github.com/jackc/pgx/v5/pgtype"
)
type Options pgtype.Array[string] // <-- cannot be pgtype.Array[sqlc.Option], causes import cycle
func (opts *Options) Scan(src any) error {
opts, ok := src.(string)
if !ok {
return fmt.Errorf("unsupported scan type for Options: %T", src)
}
options := strings.Split(strings.Trim(opts, "{}"), ",")
*opts = Options(pgtype.Array[string]{Elements: options, Valid: true})
return nil
}
// sqlc.yaml
...
overrides:
- column: "blah.options"
go_type: "myapp/pgx/types.Options" // <-- cannot be "sqlc.Options"
但是基础类型必须是pgtype.Array[string]
,不能是pgtype.Array[Option]
,因为:
sqlc
不能重写与生成的代码相同的包中的类型
1.我无法在定义的Options
类型中导入sqlc
生成的Option
类型,因为这会导致导入循环(pkgtypes
导入sqlc.Option
,pkgsqlc
导入types.Options
)
这意味着我失去了类型安全和sqlc
生成的Option
类型的其他方法。
从这个pgx/v5
github issue开始,我想我需要使用pgx/v5
SQLScanner
类型并调用它的RegisterDefaultPgType
方法,但是,我不确定这是否准确,或者如何实际做到这一点。
让pgx
识别用户定义的枚举类型的postgres数组而不失去类型安全性的正确方法是什么?
1条答案
按热度按时间jmo0nnb31#
在pgx上注册类型对我很有效
使用something like this,您可以在不手动定义自定义类型的情况下完成此操作。