我在使用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中文網其他相關文章!