In my golang project I use gorm and I need to make upsert query with returning clause to get the modified value from the query. I can make upsert, but I cannot figure out how to connect the returnning clause to it. The table name is counters, the code is as follows:
te := struct {
Name string //key column
Counter int
}{
Name: "name_to_update",
Counter: 2,
}
DB.
//Model(te).
Clauses(
//clause.Returning{Columns: []clause.Column{{Name: "counter"}}},
clause.OnConflict{
Columns: []clause.Column{{Name: "name"}}, // key column
DoUpdates: clause.Assignments(map[string]interface{}{
"counter": gorm.Expr("counters.counter + ?", 1),
}),
},
).Create(&te)
The resulting SQL query is:
INSERT INTO "counters" ("counter", "name") VALUES (0, "name_to_update") ON CONFLICT ("name")
DO UPDATE SET "counter"=counters.counter + 1 RETURNING "name" //I need updated counter value here, not name
So the counter is updated and this is OK, but it returns me the key column (in RETURNING) while I need the updated value of the counter. Any ideas how to fix it? Thank you
I'm not sure if the anonymous struct causes an issue.
Also, it's unclear from your code where the table name - "counters" - comes from.
I've tried your solution - but with a dedicated struct for the model - and it works just fine.
type Counter struct {
Name string `gorm:"primaryKey"`
Counter int
}
...
counter := Counter{Name: "name_to_update", Counter: 2}
db.
Clauses(
clause.Returning{Columns: []clause.Column{{Name: "counter"}}},
clause.OnConflict{
Columns: []clause.Column{{Name: "name"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"counter": gorm.Expr("counters.counter + ?", 1),
}),
},
).Create(&counter)
fmt.Println(counter.Counter)
The code above generates the following SQL
INSERT INTO "counters" ("name","counter") VALUES ('name_to_update',10) ON CONFLICT ("name") DO UPDATE SET "counter"=counters.counter + 1 RETURNING "counter"
And counter.Counter
has correct updated value.