扫描Postgres复合类型

时间:2019-04-01 00:36:08

标签: postgresql go

我为表定义了一种复合类型:

CREATE TYPE duration AS (
    hours NUMERIC,
    minutes NUMERIC
);

CREATE TABLE foo (
    id SERIAL PRIMARY KEY,
    my_duration duration
);

INSERT INTO foo (id, my_duration) VALUES
(1, ROW(1, 30));

如何使用database/sql进行扫描?当我使用

实现扫描仪界面时
func (d *Duration) Scan(value interface{}) error {
    log.Println(value)
    if value == nil {
        *d = Duration{
            Hours:   -1,
            Minutes: -1,
        }
        return nil
    }
    if duration, ok := value.(Duration); ok {
        *d = Duration(duration)
        return nil
    }
    return errors.New("Failed to scan duration")
}

接口的类型为[]uint8,值本身是一个编码数组,类似于[40 50 44 51 51 41]。如何正确解析复合类型?

编辑:我有一个Duration结构定义为

type Duration struct {
    Hours   int
    Minutes int
}

1 个答案:

答案 0 :(得分:1)

字节片[40 50 44 51 51 41]转换为字符串并打印到标准输出后,看起来像这样(2,33)see link

因此,您可以看到从数据库返回的是一个元组,其中两个整数之间用逗号分隔。有了这些知识,您就可以实现用于解析自定义数据类型值的Scanner接口。

func (d *Duration) Scan(value interface{}) error {
    if b, ok := value.([]byte); ok {
        ss := strings.Split(strings.Trim(string(b), "()"), ",")
        if len(ss) != 2 {
            return errors.New("unknown Duration format: " + string(b))
        }

        h, err := strconv.Atoi(ss[0])
        if err != nil {
            return err
        }
        m, err := strconv.Atoi(ss[1])
        if err != nil {
            return err
        }

        d.Hours, d.Minutes = h, m
    } else {
        d.Hours, d.Minutes = -1, -1
    }
    return nil
}