2

I am implementing a HTTP PATCH method in golang and postgresql, I need to read the data from the request and update the data provided into the postgresql.

The method works fine if all the values of the struct is provided, but if only partial data is given to a request, the other fields are becoming empty. Can anyone please help me out to deal this problem.

type StudentDetails struct {
    Id int `json:"id"`
    Name string `json:"name"`
    Age int `json:"age"`
    Class int `json:"class"`
}

Query which I am using "UPDATE table_name SET name=$2, age=$3, class=$4 WHERE id=$1"

If all the fields given in the request this works fine, but if I need to update only the AGE and the request json would be {"age": 10} or some other field we dont know. Here Age is set to 10 but remaining all fields will become "" or 0 and that will be updated into the database

Anyone has the solution to this problem, how to update the requested field only and not change other fields.

I have approached using a separate query for all fields, but I think its not the proper one. Please give me a solution

IMSoP
  • 89,526
  • 13
  • 117
  • 169
newCoder
  • 59
  • 2
  • 1
    For the first part of your problem, using pointers instead of primitives should solve the patch data (your StudentDetails struct) having empty (actually default) values. See here https://stackoverflow.com/questions/31048557/assigning-null-to-json-fields-instead-of-empty-strings Then you would need some logic to ignore nil pointers, rather than passing them into the query - I'm not sure what that would do in your example but would most likely return an error or set the column value to NULL – David Hall Jul 04 '22 at 20:55
  • you might have some luck with the `on conflict` approach described here https://stackoverflow.com/questions/61494958/postgres-on-conflict-do-update-only-non-null-values-in-python and here https://stackoverflow.com/questions/45253866/skip-null-values-on-upsert. I haven't used postgresql, so don't know if any golang library helps with this out of the box. There might even be a library that works for the whole patch process, including handling the PATCH message – David Hall Jul 04 '22 at 21:51
  • This post also looks promising, with the go library go-pg https://pg.uptrace.dev/sql-null-go-zero-values/ (it is in maintenance only I see, so perhaps look at Bun which they cite as the replacement) – David Hall Jul 04 '22 at 21:55

1 Answers1

0

Like what @David Hall said in the comments, use pointer to a type in the fields of your struct. See example below:

 type ArticleModel struct {
    gorm.Model
    ID    uuid.UUID `gorm:"primaryKey;type:uuid"`
    Title *string
    Body  *string
 }

I am using gorm, then when unmarshalling the json from http request you will get nil value if not provided. You need to add nil checkers to skip in the construction of your SQL query. Something like this.

 if entity.Title != nil {
    model.Title = entity.Title
 }

 if entity.Body != nil {
    model.Body = entity.Body
 }

 db.Save(&model)

Now the next problem would be how to intentionally empty the field in database (explicitly nulling the value) like UPDATE table SET field = null. Unfortunately I haven't figured it out also.

What I have in mind is checking if empty string and considering it as the setting it to empty value. Although I want to see better options.

mortillan
  • 43
  • 6