我有一叠
type Stack struct {
Name string `json:"name" gorm:"primaryKey"`
Parameters []StackParameter `json:"parameters" gorm:"foreignKey:StackName; references: Name; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
...
}
Stack
有一些参数。多个堆栈可以具有相同的参数,因此我使用参数Name
和StackName
作为主复合键
type StackParameter struct {
Name string `json:"name" gorm:"primaryKey"`
StackName string `json:"-" gorm:"primaryKey"`
DefaultValue *string `json:"defaultValue"`
...
}
我希望能够部署堆栈链。所以我有一条链子
type Chain struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"index:idx_name_and_group,unique"`
Description string `json:"description"`
GroupName string `json:"groupName" gorm:"index:idx_name_and_group,unique; references:Name"`
Group *Group `json:"group,omitempty"`
Links []*Link `json:"links"`
}
Chain
有一些链接
type Link struct {
ID uint `json:"id" gorm:"primaryKey"`
ChainID uint `json:"chainId"`
Chain Chain `json:"chain"`
StackName string `json:"stackName" gorm:"references:Name"`
Stack Stack `json:"stack"`
Parameters []*LinkParameter `json:"parameters" gorm:"foreignKey:LinkID"`
}
Link
是Stack
的一个示例,把它看作类/对象,所以它的参数由Stack
的参数定义。
type LinkParameter struct {
LinkID uint `json:"linkId" gorm:"primaryKey"`
Name string `json:"name" gorm:"primaryKey"`
StackParameter StackParameter `json:"-" gorm:"foreignKey:Name,StackName; references:Name,StackName; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
StackName string `json:"-"`
Value string `json:"value"`
}
因此,LinkParameter
属于Link
,并具有由StackParameter
定义的唯一名称,并为这两个定义了Value
。
为了简洁起见,我将省略处理程序、服务和存储库代码,但主要目标是用LinkParameter
保存Link
,我尝试使用
err := r.db.Session(&gorm.Session{FullSaveAssociations: true}).Save(link).Error
但我得到了以下错误
[im-manager] 2023/08/13 09:29:21 /src/pkg/instance/repository.go:50 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)
[im-manager] [0.291ms] [rows:0] INSERT INTO "link_parameters" ("link_id","stack_parameter_name","stack_name","value") VALUES (5,'STARTUP_PROBE_FAILURE_THRESHOLD','whoami-go','STARTUP_PROBE_FAILURE_THRESHOLD'),(5,'STARTUP_PROBE_PERIOD_SECONDS','whoami-go','STARTUP_PROBE_PERIOD_SECONDS') ON CONFLICT ("link_id","stack_parameter_name") DO UPDATE SET "stack_name"="excluded"."stack_name","value"="excluded"."value"
[im-manager]
[im-manager] 2023/08/13 09:29:21 /src/pkg/instance/repository.go:50 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)
[im-manager] [1.279ms] [rows:1] INSERT INTO "links" ("created_at","updated_at","chain_id","stack_name","preset","preset_id","public","deploy_log") VALUES ('2023-08-13 09:29:21.319','2023-08-13 09:29:21.319',1,'whoami-go',false,0,false,'') RETURNING "id"
背景更新:
我实际上要做的是从部署一个Instance
到部署一个Chain
示例,我现在称之为Link
。这已经工作了很长时间了。所以我基本上只是试图将Instance
结构体拆分为一个包含Link
的Chain
结构体。
根据@TiGo的建议,我现在得到了
[im-manager] 2023/08/14 03:27:24 /src/pkg/instance/repository.go:54 ERROR: ON CONFLICT DO UPDATE requires inference specification or constraint name (SQLSTATE 42601)
[im-manager] [0.237ms] [rows:0] INSERT INTO "link_parameters" ("link_id","stack_parameter_name","stack_name","value") VALUES (18,'REPLICA_COUNT','whoami-go','1'),(18,'IMAGE_PULL_POLICY','whoami-go','Always') ON CONFLICT DO UPDATE SET "link_id"="excluded"."link_id","stack_parameter_name"="excluded"."stack_parameter_name","stack_name"="excluded"."stack_name","value"="excluded"."value"
[im-manager]
[im-manager] 2023/08/14 03:27:24 /src/pkg/instance/repository.go:54 ERROR: ON CONFLICT DO UPDATE requires inference specification or constraint name (SQLSTATE 42601)
[im-manager] [2.106ms] [rows:1] INSERT INTO "links" ("created_at","updated_at","chain_id","stack_name","preset","preset_id","public","deploy_log") VALUES ('2023-08-14 03:27:24.802','2023-08-14 03:27:24.802',1,'whoami-go',false,0,false,'') RETURNING "id"
另一个更新:
如果我将LinkParameter
结构体的Name
属性更改为ParameterName
,这似乎可以工作,因此它看起来如下所示
type LinkParameter struct {
LinkID uint `json:"-" gorm:"primaryKey"`
ParameterName string `json:"name" gorm:"primaryKey"`
StackParameter StackParameter `json:"-" gorm:"foreignKey:ParameterName,StackName; references:Name,StackName; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
StackName string `json:"-"`
Value string `json:"value"`
}
有谁能告诉我为什么要这样做吗?
1条答案
按热度按时间yyyllmsg1#
发生错误的原因是
LinkParameter
表在(link_id, stack_parameter_name)
上没有与ON CONFLICT子句匹配的唯一约束。当使用ON CONFLICT执行INSERT时,PostgreSQL需要在ON CONFLICT中指定的列上存在唯一的索引/约束。这允许它正确地检测冲突。
要修复它,需要在
LinkParameter
表中的(link_id, stack_parameter_name)
上添加一个唯一约束:这将在(link_id,name)上创建唯一约束“link_param_idx”。
然后你的冲突将按预期工作。所以总结一下: