包含软删除行的连接子句

我在使用go-pgorm 生成正确的选择查询时遇到问题,其中一个表记录可以被软删除,而其他 2 个不能。

数据库表:

管道实例
instance_id 整数
pipeline_id 整数
event_id 整数
管道触发器
你的手
pipeline_id 整数
deleted_at 时间戳
管道触发事件
event_id 整数
trigger_id 整数

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 


在上面提到的所有 3 个表/模型中,只有 pipeline_triggers 表deleted_at具有用于软删除的列。我的要求是在结果集中也包括软删除的 pipeline_triggers 行。但是orm 会自动在子句中go-pg添加条件。如何删除此条件并获取所有行,包括软删除行。trigger.deleted_at IS NULLjoin


我尝试使用AllWithDeleted函数,但它适用于主要模型,即 pipeline_trigger_events(并且该表无论如何都没有 deleted_at 列)而不是 on pipeline_triggers,因此失败并出现此错误: pg: model=PipelineTriggerEvent does not support soft deletes


智慧大石
浏览 168回答 1
1回答

慕斯709654

稍微浏览了一下 pg-go 的代码后,我不知道是否支持您尝试做的事情。要确定您可能想在调试器中单步执行下面的代码。为连接构建查询时,它包含以下部分:https://github.com/go-pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#L283if 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#L200func 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#L153func (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()orpg.QueryWithContext()并传入上面包含的 sql 语句。还值得一提的是,pg-go/pg 处于维护模式,因此他们不太可能永远支持它。根据该项目在 pg-go 中的根深蒂固程度,您可能会考虑使用正在积极开发的Bun 。附录这是appendSoftDelete()在上面的第一个片段中调用的函数:https://github.com/go-pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#L189func (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}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go