go-gorp / gorp

Go Relational Persistence - an ORM-ish library for Go
MIT License
3.74k stars 369 forks source link

select on conflict #416

Open tcurdt opened 4 years ago

tcurdt commented 4 years ago

I am currently using this to

  err := dbm.Insert(foo)
  if err != nil {
    msg := err.Error()
    if strings.HasPrefix(msg, "pq: duplicate key") || strings.HasPrefix(msg, "UNIQUE") || strings.HasPrefix(msg, "Error 1062:") {
      f := &Foo{}
      err := dbm.SelectOne(f, "select * from foo where a=$1 and b=$2",
        a,
        b,
      )
      if err != nil {
        return nil, err
      }
      return s, nil
    }

Is there a better way to handle a failed uniq constraint?

nelsam commented 4 years ago

As of right now, that's probably your best bet. It might be worth checking with your sql driver (github.com/lib/pq I assume) to see if they have sentinel errors or something to compare against or type check with. Or maybe you can add a PR. Something like if dupErr, ok := err.(pq.DuplicateKey); ok { would be helpful in a lot of scenarios.

bokwoon95 commented 4 years ago
err := dbm.Insert(foo)
if pqerror, _ := err.(*pq.Error); pqerror.Code == "23505" {
    err := dbm.SelectOne(f, "select * from foo where a=$1 and b=$2", a, b)
    if err != nil {
    }
}

Errors from pq expose the postgres error code. The postgres error code for duplicate key violation is 23505 which can be found from this table https://www.postgresql.org/docs/current/errcodes-appendix.html