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
CodePudding user response:
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.