Maison  >  Article  >  développement back-end  >  Clause de jointure avec lignes supprimées de manière logicielle

Clause de jointure avec lignes supprimées de manière logicielle

PHPz
PHPzavant
2024-02-08 20:42:20682parcourir

包含软删除行的 Join 子句

Contenu de la question

J'ai un problème pour générer une requête de sélection de jointure correcte à l'aide de go-pg orm, l'un des enregistrements de la table peut être supprimé de manière logicielle mais les 2 autres enregistrements de la table ne le peuvent pas.

Tableau de base de données :

pipeline_instances
instance_id int
pipeline_id int
event_id int
pipeline_triggers
id int
pipeline_id int
horodatage supprimé_at
pipeline_trigger_events
event_id int
trigger_id int

go-pg Modèle :

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
}

La requête que j'essaie de générer :

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

Requête générée par 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
        })

Sur les 3 tables/modèles mentionnés ci-dessus, seule la table pipeline_triggers a une colonne deleted_at pour les suppressions logicielles. Mon exigence est d'inclure également les lignes pipeline_triggers supprimées de manière logicielle dans l'ensemble de résultats. Mais deleted_at列。我的要求是将软删除的 pipeline_triggers 行也包含在结果集中。但是 go-pg orm 会自动在 join 子句中添加 trigger.deleted_at is null orm ajoutera automatiquement la condition trigger.deleted_at is null dans la clause join. Comment puis-je supprimer cette condition et obtenir toutes les lignes, y compris les lignes supprimées de manière logicielle.

J'ai essayé d'utiliser la fonction allwithdeleted, mais cela fonctionne pour le modèle principal, qui est pipeline_trigger_events (et la table n'a pas de colonne delete_at de toute façon), mais pas pour pipeline_triggers, donc elle échoue avec cette erreur : pg: model=pipelinetriggerevent 不支持软删除


Bonne réponse


Après avoir parcouru un peu le code de pg-go, je ne sais pas si ce que vous voulez faire est pris en charge. Pour déterminer cela, vous devrez peut-être parcourir le code ci-dessous dans le débogueur.

Lors de la création d'une requête pour une jointure, elle comprend les parties suivantes :

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() Fonction : 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
}

Étant donné que les jointures ont toutes une relation parent un à un, elle est ajoutée pour toutes les tables : 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
}

Je pensais que la solution serait d'appeler appendalias() uniquement pour la relation parentale et pas pour les deux autres, mais il semble que pg-go ne supporte pas cela.

Pour ce faire, il vous suffit d'appeler pg.query()pg.querywithcontext() et de transmettre l'instruction SQL contenue ci-dessus.

Il convient également de mentionner que pg-go/pg est en mode maintenance, il est donc peu probable qu'ils le prennent en charge. En fonction de l'enracinement de ce projet dans pg-go, vous pourriez envisager d'utiliser bun qui est en cours de développement actif.

Annexe

Voici la fonction appendsoftdelete() appelée dans le premier extrait de code ci-dessus :

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
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer