How sqlhooks works with database/sql drivers
mastersqlhooks allows you to instrument SQL statements by attaching hooks to any database/sql driver. This enables logging queries or measuring execution time without modifying your application's core logic.
To use it, you must:
- Implement the
sqlhook.Hooksinterface by definingBeforeandAftermethods. - Register a wrapped driver using
sqlhooks.Wrap(driver, hooks). - Open the database using the new driver name you registered.
The Hooks Interface
Before(ctx context.Context, query string, args ...interface{}) (context.Context, error): Executed before the query runs. You can use this to log the query or store a timestamp in thecontext.Contextto measure duration.After(ctx context.Context, query string, args ...interface{}) (context.Context, error): Executed after the query completes. You can retrieve data stored in the context by theBeforehook to calculate elapsed time or perform post-query logging.
// This example shows how to instrument sql queries in order to display the time that they consume
package main
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/qustavo/sqlhooks/v2"
"github.com/mattn/go-sqlite3"
)
// Hooks satisfies the sqlhook.Hooks interface
type Hooks struct {}
// Before hook will print the query with it's args and return the context with the timestamp
func (h *Hooks) Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
fmt.Printf("> %s %q", query, args)
return context.WithValue(ctx, "begin", time.Now()), nil
}
// After hook will get the timestamp registered on the Before hook and print the elapsed time
func (h *Hooks) After(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
begin := ctx.Value("begin").(time.Time)
fmt.Printf(". took: %s\n", time.Since(begin))
return ctx, nil
}
func main() {
// First, register the wrapper
sql.Register("sqlite3WithHooks", sqlhooks.Wrap(&sqlite3.SQLiteDriver{}, &Hooks{}))
// Connect to the registered wrapped driver
db, _ := sql.Open("sqlite3WithHooks", ":memory:")
// Do you're stuff
db.Exec("CREATE TABLE t (id INTEGER, text VARCHAR(16))")
db.Exec("INSERT into t (text) VALUES(?), (?)", "foo", "bar")
db.Query("SELECT id, text FROM t")
}