I am having trouble generating correct select query with joins using go-pg orm where one table record can be soft-deleted and other 2 cant.
DB tables:
| 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 Models:
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
}
The query I am trying to generate:
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
The query getting generated by 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
})
Of all the 3 tables/models mentioned above, only pipeline_triggers table has deleted_at column that is used for soft deletion. My requirement is to include the soft deleted pipeline_triggers rows also in the result set. But go-pg orm is automatically adding the trigger.deleted_at IS NULL condition in the join clause. How can I remove this condition and get all rows including soft deleted ones.
I tried using AllWithDeleted function but it works on the main model, which is pipeline_trigger_events (and this table does not have deleted_at column anyway) and not on pipeline_triggers and therefore fails with this error:
pg: model=PipelineTriggerEvent does not support soft deletes
After looking through the code of pg-go a bit, I don’t know if what you’re trying to do is supported. To know for sure you’d probably want to step through the code below in a debugger.
When the query is being built for the joins, it has this section:
https://github.com/go-pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#L283
The line
j.appendAlias(b)calls theappendAlias()function below: https://github.com/go-pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#L200Since the joins both have a has-one parent relation, it gets added for all the tables: https://github.com/go-pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#L153
I think what would fix this for you would be to only call
appendAlias()for the parent relation and not the other two, but it doesn’t look like that’s supported by pg-go.What you can do for this is just call
pg.Query()orpg.QueryWithContext()and pass in the sql statement you included above.It’s also worth mentioning that pg-go/pg is in maintenance mode so it’s unlikely they’ll ever support this. Depending on how entrenched this project is in pg-go, you might consider using Bun which is actively being developed.
Appendix
Here’s the
appendSoftDelete()function that gets called in the first snippet above:https://github.com/go-pg/pg/blob/c9ee578a38d6866649072df18a3dbb36ff369747/orm/join.go#L189