为了账号安全,请及时绑定邮箱和手机立即绑定

包含软删除行的连接子句

包含软删除行的连接子句

Go
智慧大石 2023-03-21 10:43:17
我在使用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
查看完整描述

1 回答

?
慕斯709654

TA贡献1840条经验 获得超5个赞

稍微浏览了一下 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()orpg.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

}


查看完整回答
反对 回复 2023-03-21
  • 1 回答
  • 0 关注
  • 167 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号