从 Gorm 传入查询的 Postgres 数据类型不正确

2024年 2月 15日 86.7k 0

从 gorm 传入查询的 postgres 数据类型不正确

在使用 Gorm 进行 Postgres 数据库查询时,有时会遇到一个常见的问题:“从 Gorm 传入查询的 Postgres 数据类型不正确”。这个问题可能会导致查询结果不准确,给开发者带来困扰。在本文中,php小编鱼仔将为您解析这个问题的原因,并提供解决方案,帮助您正确处理数据类型,确保查询结果的准确性。

问题内容

我正在尝试在 api 中创建一个端点来创建公司。在公司模型中,我有一个 []string 用于存储与允许用户注册的电子邮件相关的允许列出的域。

[]字符串最初是从数组的 json post 请求映射的,并在 postgres 中分配了 text[] 类型。

alloweddomains []string `gorm:"type:text[];default:null" json:"alloweddomains" binding:"required"`

登录后复制

使用 create() 的完整模型

// company is the primary struct type for companies
type company struct {
common.base
name string `gorm:"unique;default:not null" json:"name" binding:"required"`
primarycontactname string `gorm:"unique;default:not null" json:"primarycontactname" binding:"required"`
primarycontactemail string `gorm:"unique;default:not null" json:"primarycontactemail" binding:"required"`
primarycontactphone string `gorm:"unique;default:not null" json:"primarycontactphone" binding:"required"`
secondarycontactname string `gorm:"unique;default:null" json:"secondarycontactname"`
secondarycontactemail string `gorm:"unique;default:null" json:"secondarycontactemail"`
secondarycontactphone string `gorm:"unique;default:null" json:"secondarycontactphone"`
primarydomain string `gorm:"unique;default:not null" json:"primarydomain" binding:"required"`
alloweddomains []string `gorm:"type:text[];default:null" json:"alloweddomains" binding:"required"`
mfaenabled bool `gorm:"not null" json:"mfaenabled" binding:"required"`
isvalidated bool `gorm:"not null"`
}

func (c *company) create() error {
if result := common.db.create(c); result.error != nil {
log.printf("error creating company: %s", c.name)
return result.error
} else {
log.printf("successfully created company: %s", c.name)
return nil
}
}

登录后复制

在实现这个过程中,我遇到了两个问题。

首先,当 alloweddomains 包含单个字符串时,该值不会作为数组写入 postgres,而是作为单个字符串写入。

api | 2023/04/10 19:05:50 /go/src/api/company/model.go:25 error: malformed array literal: "website.co.uk" (sqlstate 22p02)
api | [2.006ms] [rows:0] insert into "companies" ("created_at","updated_at","deleted_at","name","primary_contact_name","primary_contact_email","primary_contact_phone","primary_domain","mfa_enabled","is_validated","secondary_contact_name","secondary_contact_email","secondary_contact_phone","allowed_domains") values ('2023-04-10 19:05:50.551','2023-04-10 19:05:50.551',null,'foo company ltd.','foo','bar','00000000000','website.com',true,false,'foo2','bar2','11111111111',('website.co.uk')) returning "id","uuid","secondary_contact_name","secondary_contact_email","secondary_contact_phone","allowed_domains"
api | [gin] 2023/04/10 - 19:05:50 | 500 | 3.043083ms | 172.21.0.1 | post "/api/company/register"
api | 2023/04/10 19:05:50 error creating company: foo company ltd.
api | 2023/04/10 19:05:50 error: malformed array literal: "website.co.uk" (sqlstate 22p02)
postgres | 2023-04-10 19:06:35.523 utc [19] error: column "allowed_domains" is of type text[] but expression is of type record at character 336
postgres | 2023-04-10 19:06:35.523 utc [19] hint: you will need to rewrite or cast the expression.
postgres | 2023-04-10 19:06:35.523 utc [19] statement: insert into "companies" ("created_at","updated_at","deleted_at","name","primary_contact_name","primary_contact_email","primary_contact_phone","primary_domain","mfa_enabled","is_validated","secondary_contact_name","secondary_contact_email","secondary_contact_phone","allowed_domains") values ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,($14,$15)) returning "id","uuid","secondary_contact_name","secondary_contact_email","secondary_contact_phone","allowed_domains"

登录后复制

其次,当 json 数组包含 > 1 值时,写入数据库的类型为 record 类型,而不是 text[]

api | 2023/04/10 19:06:35 /go/src/api/company/model.go:25 ERROR: column "allowed_domains" is of type text[] but expression is of type record (SQLSTATE 42804)
api | [2.502ms] [rows:0] INSERT INTO "companies" ("created_at","updated_at","deleted_at","name","primary_contact_name","primary_contact_email","primary_contact_phone","primary_domain","mfa_enabled","is_validated","secondary_contact_name","secondary_contact_email","secondary_contact_phone","allowed_domains") VALUES ('2023-04-10 19:06:35.522','2023-04-10 19:06:35.522',NULL,'Foo Company Ltd.','Foo','Bar','00000000000','website.com',true,false,'Foo2','Bar2','11111111111',('website.co.uk','website.net')) RETURNING "id","uuid","secondary_contact_name","secondary_contact_email","secondary_contact_phone","allowed_domains"
api | [GIN] 2023/04/10 - 19:06:35 | 500 | 3.256334ms | 172.21.0.1 | POST "/api/company/register"
api | 2023/04/10 19:06:35 Error creating company: Foo Company Ltd.
api | 2023/04/10 19:06:35 ERROR: column "allowed_domains" is of type text[] but expression is of type record (SQLSTATE 42804)

登录后复制

当我设置断点并在序列化后分析 company 类型时,很明显 alloweddomains 的类型是正确的。

我在这里缺少什么想法或者解决这个问题的最佳方法吗?

解决方法

根据 mkopriva 的评论,解决方案是使用 pq 包,如下所示。

package company

import (
"github.com/lib/pq"
"log"
)

// Company is the primary struct type for companies
type Company struct {
...
AllowedDomains pq.StringArray `gorm:"type:text[];default:NULL" json:"allowedDomains" binding:"required"`
}

func (c *Company) Create() error {
a := pq.StringArray{}
if c.AllowedDomains != nil && len(c.AllowedDomains) > 0 {
for _, v := range c.AllowedDomains {
a = append(a, v)
}
c.AllowedDomains = a
}
if result := common.Db.Create(c); result.Error != nil {
log.Printf("Error creating company: %s", c.Name)
return result.Error
} else {
log.Printf("Successfully created company: %s", c.Name)
return nil
}
}

登录后复制

以上就是从 Gorm 传入查询的 Postgres 数据类型不正确的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论