Skip to content
Nirbhay Choubey edited this page Feb 16, 2016 · 10 revisions

Introduction

In an application connected to MariaDB/MySQL database server, an error can occur either on server or client side. Almost all the APIs, available through Go's database/sql package, return error. So, its critical for applications to check for its nil-ness on return.

Unknown driver

if db, err := sql.Open("foo", dsn); err != nil {
        fmt.Println(err)
}
// Output:
//sql: unknown driver "foo" (forgotten import?)

Client error: connection failure

if err := db.Ping(); err != nil {
        fmt.Println(err)
}
// Output:
// mysql: [9002] Can't connect to the server (dial tcp 127.0.0.1:16001: getsockopt: connection refused)

Server error: test.t1 already exists

if _, err := db.Exec("CREATE TABLE test.t1(i INT)"); err != nil {
        fmt.Println(err)
}
// Output:
// mysqld: [1050] (42S01) Table 't1' already exists

As seen above, the error messages are prefixed appropriately and they give an idea about the source of their origin.

Vaquita also provides APIs to access error code, SQLSTATE, message and time of error, individually. It can be done using type assertion.

if _, err = db.Exec("CREATE TABLE test.t1(i INT)"); err != nil {
        /* check whether its a mysql.Error */
        if e, ok := err.(*mysql.Error); ok {
                fmt.Println("Code     : ", e.Code())
                fmt.Println("SQLSTATE : ", e.SqlState())
                fmt.Println("Message  : ", e.Message())
                fmt.Println("When     : ", e.When())
        } else {
                fmt.Println(err)
        }
}
// Output:
// Code     :  1050
// SQLSTATE :  42S01
// Message  :  Table 't1' already exists
// When     :  2015-10-16 16:59:05.438575626 -0400 EDT

List of errors

Code Constant Message
0 ErrWarning Execution of last statement resulted in warning(s)
9000 ErrUnknown Unknown error
9001 ErrConnection Can't connect to the server (%s)
9002 ErrRead Can't read data from connection (%s)
9003 ErrWrite Can't write data to connection (%s)
9004 ErrSSLSupport Server does not support SSL connection
9005 ErrSSLConnection Can't establish SSL connection with the server (%s)
9006 ErrCompressionSupport Server does not support packet compression
9007 ErrCompression Compression error (%s)
9008 ErrInvalidType Invalid type (%s)
9009 ErrInvalidDSN Can't parse data source name (%s)
9010 ErrInvalidProperty Invalid value for property '%s' (%s)
9011 ErrScheme Unsupported scheme '%s'
9012 ErrCursor Cursor is closed
9013 ErrFile File operation failed (%s)
9014 ErrInvalidPacket Invalid/unexpected packet received
9015 ErrInvalidPropertyValue Invalid value for property '%s' (%v)
9016 ErrNetPacketTooLarge Got a packet bigger than MaxAllowedPacket
9017 ErrNetPacketsOutOfOrder Got packets out of order
9018 ErrEventChecksumFailure Replication event checksum failed

How to handle warnings?

Go's sql interface does not provide any explicit mechanism to handle warnings. In Vaquita, by default, warnings are not reported. However, this behavior can be changed by setting ReportWarnings connection property. When set, if the execution of a statement results in warning(s), the execution function will return an error with code 0.

dsn = "mysql://root@localhost:16001/test?ReportWarnings=true"
..skip..
// test.t1 already exists
if _, err = db.Exec("CREATE TABLE IF NOT EXISTS test.t1(i INT)"); err != nil {
            fmt.Println(err)
}
// Output:
// mysql: [0] last command resulted in warning(s)

The warnings can further be retrieved using SHOW WARNINGS.