我在使用 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 行也包含在结果集中。但是 go-pg 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中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号