在 mysql 中使用 gorm 插入类型 []byte 引发 "Error 1241: Operand should contain 1 columns(s)"
Insert typed []byte with gorm in mysql raises "Error 1241: Operand should contain 1 columns(s)"
我有一个类型为 []byte
(密码哈希)的模型,我想使用 gorm:v2
.
将其保存在 MySQL:5.7
中
// this will work
type ModelRaw struct {
Bytes []byte
}
type Hash []byte
// this will NOT work
type ModelTyped struct {
Bytes Hash
}
func main() {
// Migrate database
// Both tables will have a column `bytes` of type `longblob default:NULL`
if err := gormDB.AutoMigrate(&ModelRaw{}, &ModelTyped{}); err != nil {
panic(err)
}
// this works
mdl1 := &ModelRaw{Bytes: []byte("random-bytes")}
if err := gormDB.Debug().Create(mdl1).Error; err != nil {
panic(err)
}
// error here
mdl2 := &ModelTyped{Bytes: Hash("random-bytes")}
if err := gormDB.Debug().Create(mdl2).Error; err != nil {
panic(err)
}
}
以上代码产生以下 gorm
调试输出:
2020/11/06 10:31:29 /go/src/app/main.go:47
[7.715ms] [rows:1] INSERT INTO `model_raws` (`bytes`) VALUES ('random-bytes')
2020/11/06 10:31:29 /go/src/app/main.go:53 Error 1241: Operand should contain 1 column(s)
[0.926ms] [rows:0] INSERT INTO `model_typeds` (`bytes`) VALUES ((114,97,110,100,111,109,45,98,121,116,101,115))
panic: Error 1241: Operand should contain 1 column(s)
回购证明问题:https://github.com/Iyashi/go-gorm-bytes-test
它 在 gorm:v1
工作并在 gorm:v2
闯入。
gorm 的 AutoMigrate() 创建 mysql table 列作为 longblob NULL
.
使用的值必须是字节数组,而不是数字数组。
有人会认为 Bytes []byte
相当于 type Hash []byte
加上 Bytes Hash
,但显然不是。
试一试:
mdl2 := &ModelTyped{Bytes: []byte(Hash("random-bytes"))}
或者也许
mdl2 := &ModelTyped{Bytes: []byte{Hash("random-bytes")}}
另一种可能是去掉Hash
定义中的struct
;它似乎导致了额外的“结构化”效果。
为此,您应该只实现一个 driver.Valuer 接口:
func (h Hash) Value() (driver.Value, error) {
return []byte(h), nil
}
然后您输入的数据将按预期与 Gorm v2 一起使用。
我有一个类型为 []byte
(密码哈希)的模型,我想使用 gorm:v2
.
MySQL:5.7
中
// this will work
type ModelRaw struct {
Bytes []byte
}
type Hash []byte
// this will NOT work
type ModelTyped struct {
Bytes Hash
}
func main() {
// Migrate database
// Both tables will have a column `bytes` of type `longblob default:NULL`
if err := gormDB.AutoMigrate(&ModelRaw{}, &ModelTyped{}); err != nil {
panic(err)
}
// this works
mdl1 := &ModelRaw{Bytes: []byte("random-bytes")}
if err := gormDB.Debug().Create(mdl1).Error; err != nil {
panic(err)
}
// error here
mdl2 := &ModelTyped{Bytes: Hash("random-bytes")}
if err := gormDB.Debug().Create(mdl2).Error; err != nil {
panic(err)
}
}
以上代码产生以下 gorm
调试输出:
2020/11/06 10:31:29 /go/src/app/main.go:47
[7.715ms] [rows:1] INSERT INTO `model_raws` (`bytes`) VALUES ('random-bytes')
2020/11/06 10:31:29 /go/src/app/main.go:53 Error 1241: Operand should contain 1 column(s)
[0.926ms] [rows:0] INSERT INTO `model_typeds` (`bytes`) VALUES ((114,97,110,100,111,109,45,98,121,116,101,115))
panic: Error 1241: Operand should contain 1 column(s)
回购证明问题:https://github.com/Iyashi/go-gorm-bytes-test
它 在 gorm:v1
工作并在 gorm:v2
闯入。
gorm 的 AutoMigrate() 创建 mysql table 列作为 longblob NULL
.
使用的值必须是字节数组,而不是数字数组。
有人会认为 Bytes []byte
相当于 type Hash []byte
加上 Bytes Hash
,但显然不是。
试一试:
mdl2 := &ModelTyped{Bytes: []byte(Hash("random-bytes"))}
或者也许
mdl2 := &ModelTyped{Bytes: []byte{Hash("random-bytes")}}
另一种可能是去掉Hash
定义中的struct
;它似乎导致了额外的“结构化”效果。
为此,您应该只实现一个 driver.Valuer 接口:
func (h Hash) Value() (driver.Value, error) {
return []byte(h), nil
}
然后您输入的数据将按预期与 Gorm v2 一起使用。