我在使用 go-pg
orm 生成正确的连接选择查询时遇到问题,其中一个表记录可以被软删除,而其他 2 个表记录则不能。
数据库表:
pipeline_instances |
---|
instance_id int |
pipeline_id int |
event_id int |
pipeline_triggers |
---|
id int |
pipeline_id int |
deleted_at timestamp |
pipeline_trigger_events |
---|
event_id int |
trigger_id int |
go-pg 型号:
type pipelinetriggerevent struct { tablename struct{} `pg:"pipeline_trigger_events,alias:pte"` trigger *pipelinetrigger `pg:"rel:has-one,join_fk:id"` pipelineinstance *pipelineinstance `pg:"rel:has-one,join_fk:event_id"` *triggerevent } type pipelinetrigger struct { tablename struct{} `pg:"pipeline_triggers,alias:pt"` *trigger } type pipelineinstance struct { tablename struct{} `pg:"pipeline_pipeline_instances,alias:ppi"` *pipelineinstance }
我尝试生成的查询:
select pte.*, trigger.*, pipeline_instance.* from pipeline_trigger_events as pte left join pipeline_triggers as trigger on (trigger.id = pte.trigger_id) left join pipeline_pipeline_instances as pipeline_instance on pipeline_instance.event_id = pte.event_id and trigger.pipeline_id = pipeline_instance.pipeline_id
由 go-pg orm 生成的查询:
select pte.*, trigger.*, pipeline_instance.* from pipeline_trigger_events as pte left join pipeline_triggers as trigger on (trigger.id = pte.trigger_id) and trigger.deleted_at is null -- this is the unwanted line. left join pipeline_pipeline_instances as pipeline_instance on pipeline_instance.event_id = pte.event_id and trigger.pipeline_id = pipeline_instance.pipeline_id
var triggerevents []pipelinetriggerevent q := db.model(&triggerevents). column("pte.*"). relation("trigger"). relation("pipelineinstance", func(q *orm.query) (*orm.query, error) { q = q.join(" and trigger.pipeline_id = pipeline_instance.pipeline_id") return q, nil })
在上述所有3个表/模型中,只有pipeline_triggers表具有用于软删除的deleted_at
列。我的要求是将软删除的 pipeline_triggers 行也包含在结果集中。但是 deleted_at
列。我的要求是将软删除的 pipeline_triggers 行也包含在结果集中。但是 go-pg
orm 会自动在 join
子句中添加 trigger.deleted_at is null
orm 会自动在 join
子句中添加 trigger.deleted_at is null
条件。如何删除此条件并获取所有行,包括软删除的行。
我尝试使用 allwithdeleted 函数,但它适用于主模型,即 pipeline_trigger_events (并且该表无论如何都没有deleted_at 列),而不适用于 pipeline_triggers
,因此失败并出现此错误:
pg: model=pipelinetriggerevent 不支持软删除
稍微浏览了一下 pg-go 的代码后,我不知道是否支持您想要做的事情。为了确定这一点,您可能需要在调试器中单步执行下面的代码。
当为连接构建查询时,它具有以下部分:
https://github.com/go -pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#l283
if issoftdelete { b = append(b, " and "...) b = j.appendalias(b) b = j.appendsoftdelete(b, q.flags) }
j.appendalias(b)
行调用以下 appendalias()
函数:
https://github.com/go-pg/ pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#l200
func appendalias(b []byte, j *join) []byte { if j.hasparent() { b = appendalias(b, j.parent) b = append(b, "__"...) } b = append(b, j.rel.field.sqlname...) return b }
由于连接都具有一对一的父关系,因此会为所有表添加它: https://github.com/go-pg/ pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#l153
func (j *join) hasparent() bool { if j.parent != nil { switch j.parent.rel.type { case hasonerelation, belongstorelation: return true } } return false }
我认为解决这个问题的方法是只为父关系调用 appendalias()
而不是其他两个,但看起来 pg-go 不支持这一点。
为此,您只需调用 pg.query()
或 pg.querywithcontext()
并传入上面包含的 sql 语句即可。
还值得一提的是,pg-go/pg 处于维护模式,因此他们不太可能支持这一点。根据这个项目在 pg-go 中的根深蒂固程度,您可能会考虑使用 bun 正在积极开发中。
附录
这是上面第一个代码片段中调用的 appendsoftdelete()
函数:
https://github.com/go -pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#l189
func (j *join) appendSoftDelete(b []byte, flags queryFlag) []byte { b = append(b, '.') b = append(b, j.JoinModel.Table().SoftDeleteField.Column...) if hasFlag(flags, deletedFlag) { b = append(b, " IS NOT NULL"...) } else { b = append(b, " IS NULL"...) } return b }
以上是包含软删除行的 Join 子句的详细内容。更多信息请关注PHP中文网其他相关文章!