14

I'm trying to delete a database using the postgres driver (lib/pq) by doing a:

db.Exec("DROP DATABASE dbName;")

But I'd like to do a different conditional based on whether the error received is something strange, or is a "database does not exist" error.

Is there a constant variable or something I can use to check if the error returned is a "database does not exist" error message, or would I have to manually parse the error string myself?

I tried to look in the documentation, but could not find anything for "database does not exist". I did however find this list.

Perhaps it fits under some other error code? Also I'm not quite sure the semantically correct way of fetching and comparing the error codes through the Postgres driver. I presume I should do something like this:

if err.ErrorCode != "xxx"
5
  • 1
    Any reason you don't want to check if the database exists before attempting to drop it? Commented Jun 1, 2016 at 6:05
  • That would be an acceptable solution too, I wasn't aware I could do that :-) Is there a query for that? Commented Jun 1, 2016 at 6:07
  • 1
    Certainly. Check out the pg_database object. SELECT TRUE AS result FROM pg_database WHERE datname='abc'; Commented Jun 1, 2016 at 6:11
  • 1
    Also, if you want to avoid the whole issue, simply: DROP DATABASE IF EXISTS dbName; Commented Jun 1, 2016 at 6:12
  • Oh awesome, thanks, that's perfect. Commented Jun 1, 2016 at 6:25

3 Answers 3

34

The lib/pq package may return errors of type *pq.Error, which is a struct. If it does, you may use all its fields to inspect for details of the error.

This is how it can be done:

if err, ok := err.(*pq.Error); ok {
    // Here err is of type *pq.Error, you may inspect all its fields, e.g.:
    fmt.Println("pq error:", err.Code.Name())
}

pq.Error has the following fields:

type Error struct {
    Severity         string
    Code             ErrorCode
    Message          string
    Detail           string
    Hint             string
    Position         string
    InternalPosition string
    InternalQuery    string
    Where            string
    Schema           string
    Table            string
    Column           string
    DataTypeName     string
    Constraint       string
    File             string
    Line             string
    Routine          string
}

The meaning and possible values of these fields are Postres specific and the full list can be found here: Error and Notice Message Fields

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, this was helpful, however I'm just going to use what Nicarus mentioned above (DROP DATABASE IF EXISTS dbName;). If anyone is curious what the error message returned is though, it was this: pq.Error{Severity:"ERROR", Code:"3D000", Message:"database \"dbname\" does not exist", Detail:"", Hint:"", Position:"", InternalPosition:"", InternalQuery:"", Where:"", Schema:"", Table:"", Column:"", DataTypeName:"", Constraint:"", File:"dbcommands.c", Line:"799", Routine:"dropdb"} Unable to execute setup: pq: database "dbname" does not exist
Here is a list of all the error codes/names postgresql.org/docs/9.3/errcodes-appendix.html
1

You could use this: https://github.com/omeid/pgerror

It has lots of mappings for various postgres errors.

With the package, you can do the following (taken from the README):

// example use:
_, err = stmt.Exec(SomeInsertStateMent, params...)
if err != nil {
  if e := pgerror.UniqueViolation(err); e != nil {
  // you can use e here to check the fields et al
    return SomeThingAlreadyExists
  }

  return err // other cases.
}

Comments

1

This package has all the PG error constants: https://github.com/jackc/pgerrcode

Just import and you're good to go:

import "github.com/jackc/pgerrcode"

// ...

if err, ok := err.(*pq.Error); ok {
  if err.Code == pgerrcode.UniqueViolation {
    return fmt.Errorf("unique field violation on column %s", err.Column)
  }
}

The package is also in the family of one of the 2 or 3 most popular Go PostgreSQL drivers, called "pgx", so it should be reliable enough.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.