proxy

package module
v0.7.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 14, 2023 License: MIT Imports: 12 Imported by: 14

README

go-sql-proxy

Build Status Go Report Card PkgGoDev Coverage Status

The proxy package is a proxy driver for the database/sql package. You can hook SQL executions. It supports Go 1.8 or laster.

SYNOPSIS

Use Ready‐Made SQL tracer

proxy.RegisterTracer is a shortcut for registering a SQL query tracer.

package main

import (
	"context"
	"database/sql"

	"github.com/shogo82148/go-sql-proxy"
)

func main() {
	proxy.RegisterTracer()

	db, _ := sql.Open("origin:trace", "data source")
	db.Exec("CREATE TABLE t1 (id INTEGER PRIMARY KEY)")
	// STDERR: main.go:14: Exec: CREATE TABLE t1 (id INTEGER PRIMARY KEY); args = [] (0s)
}

Use proxy.NewTraceProxy to change the log output destination.

logger := New(os.Stderr, "", LstdFlags)
tracer := NewTraceProxy(&another.Driver{}, logger)
sql.Register("origin:trace", tracer)
db, err := sql.Open("origin:tracer", "data source")
Use with the context package

From Go version 1.8 onward, database/sql supports the context package. You can register your hooks into the context.

package main

import (
	"context"
	"database/sql"

	"github.com/shogo82148/go-sql-proxy"
)

var tracer = proxy.NewTraceHooks(proxy.TracerOptions{})

func main() {
	proxy.RegisterProxy()

	db, _ := sql.Open("origin:proxy", "data source")

	// The tracer is enabled in this context.
	ctx := proxy.WithHooks(context.Background(), tracer)
	db.ExecContext(ctx, "CREATE TABLE t1 (id INTEGER PRIMARY KEY)")
}
Create your own hooks

First, register new proxy driver.

hooks := &proxy.HooksContext{
	// Hook functions here(Open, Exec, Query, etc.)
	// See godoc for more details
}
sql.Register("new-proxy-name", proxy.NewProxyContext(&origin.Driver{}, hooks))

And then, open new database handle with the registered proxy driver.

db, err := sql.Open("new-proxy-name", "data source")

EXAMPLES

EXAMPLE: SQL tracer
package main

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"log"

	"github.com/mattn/go-sqlite3"
	"github.com/shogo82148/go-sql-proxy"
)

func main() {
	sql.Register("sqlite3-proxy", proxy.NewProxyContext(&sqlite3.SQLiteDriver{}, &proxy.HooksContext{
		Open: func(_ context.Context, _ interface{}, conn *proxy.Conn) error {
			log.Println("Open")
			return nil
		},
		Exec: func(_ context.Context, _ interface{}, stmt *proxy.Stmt, args []driver.NamedValue, result driver.Result) error {
			log.Printf("Exec: %s; args = %v\n", stmt.QueryString, args)
			return nil
		},
		Query: func(_ context.Context, _ interface{}, stmt *proxy.Stmt, args []driver.NamedValue, rows driver.Rows) error {
			log.Printf("Query: %s; args = %v\n", stmt.QueryString, args)
			return nil
		},
		Begin: func(_ context.Context, _ interface{}, conn *proxy.Conn) error {
			log.Println("Begin")
			return nil
		},
		Commit: func(_ context.Context, _ interface{}, tx *proxy.Tx) error {
			log.Println("Commit")
			return nil
		},
		Rollback: func(_ context.Context, _ interface{}, tx *proxy.Tx) error {
			log.Println("Rollback")
			return nil
		},

	}))

	db, err := sql.Open("sqlite3-proxy", ":memory:")
	if err != nil {
		log.Fatalf("Open filed: %v", err)
	}
	defer db.Close()

	_, err = db.Exec(
		"CREATE TABLE t1 (id INTEGER PRIMARY KEY)",
	)
	if err != nil {
		log.Fatal(err)
	}
}
EXAMPLE: elapsed time logger
package main

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"log"
	"time"

	"github.com/mattn/go-sqlite3"
	"github.com/shogo82148/go-sql-proxy"
)

func main() {
	sql.Register("sqlite3-proxy", proxy.NewProxyContext(&sqlite3.SQLiteDriver{}, &proxy.HooksContext{
		PreExec: func(_ context.Context, _ *proxy.Stmt, _ []driver.NamedValue) (interface{}, error) {
			// The first return value(time.Now()) is passed to both `Hooks.Exec` and `Hook.ExecPost` callbacks.
			return time.Now(), nil
		},
		PostExec: func(_ context.Context, ctx interface{}, stmt *proxy.Stmt, args []driver.NamedValue, _ driver.Result, _ error) error {
			// The `ctx` parameter is the return value supplied from the `Hooks.PreExec` method, and may be nil.
			log.Printf("Query: %s; args = %v (%s)\n", stmt.QueryString, args, time.Since(ctx.(time.Time)))
			return nil
		},
	}))

	db, err := sql.Open("sqlite3-proxy", ":memory:")
	if err != nil {
		log.Fatalf("Open filed: %v", err)
	}
	defer db.Close()

	_, err = db.Exec(
		"CREATE TABLE t1 (id INTEGER PRIMARY KEY)",
	)
	if err != nil {
		log.Fatal(err)
	}
}

LICENSE

This software is released under the MIT License, see LICENSE file.

godoc

See godoc for more information.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultPackageFilter = PackageFilter{
	"database/sql":                       struct{}{},
	"github.com/shogo82148/go-sql-proxy": struct{}{},
}

DefaultPackageFilter ignores some database util package.

Functions

func NewConnector

func NewConnector(c driver.Connector, hs ...*HooksContext) driver.Connector

NewConnector creates new proxied Connector.

func RegisterProxy

func RegisterProxy()

RegisterProxy creates proxies that do not anything by default, and registers the proxies as sql driver. Use `proxy.WithHooks(ctx, hooks)` to hook query execution. The proxies' names have suffix ":proxy".

Example
package main

import (
	"context"
	"database/sql"
	"fmt"
	"log"

	proxy "github.com/shogo82148/go-sql-proxy"
)

func main() {
	proxy.RegisterProxy()
	db, err := sql.Open("fakedb:proxy", `{"name":"trace"}`)
	if err != nil {
		log.Fatal(err)
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// proxy.RegisterProxy register hook points.
	// do nothing by default.
	if err := db.PingContext(ctx); err != nil {
		log.Fatal(err)
	}

	// proxy.WithHooks enables the hooks in this context.
	ctx = proxy.WithHooks(context.Background(), &proxy.HooksContext{
		Ping: func(c context.Context, ctx interface{}, conn *proxy.Conn) error {
			fmt.Println("Ping")
			return nil
		},
	})
	if err := db.PingContext(ctx); err != nil {
		log.Fatal(err)
	}

	if err := db.Close(); err != nil {
		log.Fatal(err)
	}
}
Output:

Ping

func RegisterTracer

func RegisterTracer()

RegisterTracer creates proxies that log queries from the sql drivers already registered, and registers the proxies as sql driver. The proxies' names have suffix ":trace".

func WithHooks

func WithHooks(ctx context.Context, hs ...*HooksContext) context.Context

WithHooks returns a copy of parent context in which the hooks associated.

Types

type Conn

type Conn struct {
	Conn  driver.Conn
	Proxy *Proxy
}

Conn adds hook points into "database/sql/driver".Conn.

func (*Conn) Begin

func (conn *Conn) Begin() (driver.Tx, error)

Begin starts and returns a new transaction which is wrapped by Tx. It will trigger PreBegin, Begin, PostBegin hooks. NOT SUPPORTED: use BeginContext instead

func (*Conn) BeginTx

func (conn *Conn) BeginTx(c context.Context, opts driver.TxOptions) (driver.Tx, error)

BeginTx starts and returns a new transaction which is wrapped by Tx. It will trigger PreBegin, Begin, PostBegin hooks.

func (*Conn) CheckNamedValue added in v0.2.0

func (conn *Conn) CheckNamedValue(nv *driver.NamedValue) (err error)

CheckNamedValue for implementing driver.NamedValueChecker This function may be unnecessary because `proxy.Stmt` already implements `NamedValueChecker`, but it is implemented just in case.

func (*Conn) Close

func (conn *Conn) Close() error

Close calls the original Close method.

func (*Conn) Exec

func (conn *Conn) Exec(query string, args []driver.Value) (driver.Result, error)

Exec calls the original Exec method of the connection. It will trigger PreExec, Exec, PostExec hooks.

If the original connection does not satisfy "database/sql/driver".Execer, it return ErrSkip error. NOT SUPPORTED: use ExecContext instead

func (*Conn) ExecContext

func (conn *Conn) ExecContext(c context.Context, query string, args []driver.NamedValue) (driver.Result, error)

ExecContext calls the original ExecContext (or Exec as a fallback) method of the connection. It will trigger PreExec, Exec, PostExec hooks.

If the original connection does not satisfy "database/sql/driver".ExecerContext nor "database/sql/driver".Execer, it return ErrSkip error.

func (*Conn) IsValid added in v0.3.0

func (conn *Conn) IsValid() bool

IsValid implements driver.Validator. It calls the IsValid method of the original connection. If the original connection does not satisfy "database/sql/driver".Validator, it always returns true.

func (*Conn) Ping

func (conn *Conn) Ping(c context.Context) error

Ping verifies a connection to the database is still alive. It will trigger PrePing, Ping, PostPing hooks.

If the original connection does not satisfy "database/sql/driver".Pinger, it does nothing.

func (*Conn) Prepare

func (conn *Conn) Prepare(query string) (driver.Stmt, error)

Prepare returns a prepared statement which is wrapped by Stmt. NOT SUPPORTED: use PrepareContext instead

func (*Conn) PrepareContext

func (conn *Conn) PrepareContext(c context.Context, query string) (driver.Stmt, error)

PrepareContext returns a prepared statement which is wrapped by Stmt.

func (*Conn) Query

func (conn *Conn) Query(query string, args []driver.Value) (driver.Rows, error)

Query executes a query that may return rows. It wil trigger PreQuery, Query, PostQuery hooks.

If the original connection does not satisfy "database/sql/driver".Queryer, it return ErrSkip error. NOT SUPPORTED: use QueryContext instead

func (*Conn) QueryContext

func (conn *Conn) QueryContext(c context.Context, query string, args []driver.NamedValue) (driver.Rows, error)

QueryContext executes a query that may return rows. It wil trigger PreQuery, Query, PostQuery hooks.

If the original connection does not satisfy "database/sql/driver".QueryerContext nor "database/sql/driver".Queryer, it return ErrSkip error.

func (*Conn) ResetSession

func (conn *Conn) ResetSession(ctx context.Context) error

ResetSession resets the state of Conn.

type Connector

type Connector struct {
	Proxy     *Proxy
	Connector driver.Connector
	Name      string
}

Connector adds hook points into "database/sql/driver".Connector.

func (*Connector) Close added in v0.6.0

func (c *Connector) Close() error

Close closes the c.Connector if it implements the io.Closer interface. It is called by the DB.Close method from Go 1.17.

func (*Connector) Connect

func (c *Connector) Connect(ctx context.Context) (driver.Conn, error)

Connect returns a connection to the database which wrapped by Conn. It will triggers PreOpen, Open, PostOpen hooks.

func (*Connector) Driver

func (c *Connector) Driver() driver.Driver

Driver returns the underlying Driver of the Connector.

type Filter

type Filter interface {
	DoOutput(packageName string) bool
}

Filter is used by the tracing proxy for skipping database libraries (e.g. O/R mapper).

type Hooks

type Hooks struct {
	// PrePing is a callback that gets called prior to calling
	// `Conn.Ping`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.Ping` and `Hooks.Ping` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Ping` and
	// `Hooks.PostPing` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.Ping` method and `Hooks.Ping`
	// methods are not called.
	PrePing func(conn *Conn) (interface{}, error)

	// Ping is called after the underlying driver's `Conn.Exec` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePing` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.Ping` method.
	Ping func(ctx interface{}, conn *Conn) error

	// PostPing is a callback that gets called at the end of
	// the call to `Conn.Ping`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePing` method, and may be nil.
	PostPing func(ctx interface{}, conn *Conn, err error) error

	// PreOpen is a callback that gets called before any
	// attempt to open the sql connection is made, and is ALWAYS
	// called.
	//
	// The first return value is passed to both `Hooks.Open` and
	// `Hooks.PostOpen` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Driver.Open` method and `Hooks.Open`
	// methods are not called.
	PreOpen func(name string) (interface{}, error)

	// Open is called after the underlying driver's `Driver.Open` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreOpen` method, and may be nil.
	//
	// If this callback returns an error, then the `conn` object is
	// closed by calling the `Close` method, and the error from this
	// callback is returned by the `db.Open` method.
	Open func(ctx interface{}, conn *Conn) error

	// PostOpen is a callback that gets called at the end of
	// the call to `db.Open(). It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreOpen` method, and may be nil.
	PostOpen func(ctx interface{}, conn *Conn) error

	// PreExec is a callback that gets called prior to calling
	// `Stmt.Exec`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Stmt.Exec` and `Hooks.Exec` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Exec` and
	// `Hooks.PostExec` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Driver.Exec` method and `Hooks.Exec`
	// methods are not called.
	PreExec func(stmt *Stmt, args []driver.Value) (interface{}, error)

	// Exec is called after the underlying driver's `Driver.Exec` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreExec` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Stmt.Exec` method.
	Exec func(ctx interface{}, stmt *Stmt, args []driver.Value, result driver.Result) error

	// PostExec is a callback that gets called at the end of
	// the call to `Stmt.Exec`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreExec` method, and may be nil.
	PostExec func(ctx interface{}, stmt *Stmt, args []driver.Value, result driver.Result) error

	// PreQuery is a callback that gets called prior to calling
	// `Stmt.Query`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Stmt.Query` and `Hooks.Query` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Query` and
	// `Hooks.PostQuery` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Stmt.Query` method and `Hooks.Query`
	// methods are not called.
	PreQuery func(stmt *Stmt, args []driver.Value) (interface{}, error)

	// Query is called after the underlying driver's `Stmt.Query` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreQuery` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Stmt.Query` method.
	Query func(ctx interface{}, stmt *Stmt, args []driver.Value, rows driver.Rows) error

	// PostQuery is a callback that gets called at the end of
	// the call to `Stmt.Query`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreQuery` method, and may be nil.
	PostQuery func(ctx interface{}, stmt *Stmt, args []driver.Value, rows driver.Rows) error

	// PreBegin is a callback that gets called prior to calling
	// `Stmt.Begin`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.Begin` and `Hooks.Begin` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Begin` and
	// `Hooks.PostBegin` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.Begin` method and `Hooks.Begin`
	// methods are not called.
	PreBegin func(conn *Conn) (interface{}, error)

	// Begin is called after the underlying driver's `Conn.Begin` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreBegin` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.Begin` method.
	Begin func(ctx interface{}, conn *Conn) error

	// PostBegin is a callback that gets called at the end of
	// the call to `Conn.Begin`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreBegin` method, and may be nil.
	PostBegin func(ctx interface{}, conn *Conn) error

	// PreCommit is a callback that gets called prior to calling
	// `Tx.Commit`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Tx.Commit` and `Hooks.Commit` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Commit` and
	// `Hooks.PostCommit` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Tx.Commit` method and `Hooks.Commit`
	// methods are not called.
	PreCommit func(tx *Tx) (interface{}, error)

	// Commit is called after the underlying driver's `Tx.Commit` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreCommit` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Tx.Commit` method.
	Commit func(ctx interface{}, tx *Tx) error

	// PostCommit is a callback that gets called at the end of
	// the call to `Tx.Commit`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreCommit` method, and may be nil.
	PostCommit func(ctx interface{}, tx *Tx) error

	// PreRollback is a callback that gets called prior to calling
	// `Tx.Rollback`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Tx.Rollback` and `Hooks.Rollback` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Rollback` and
	// `Hooks.PostRollback` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Tx.Rollback` method and `Hooks.Rollback`
	PreRollback func(tx *Tx) (interface{}, error)

	// Rollback is called after the underlying driver's `Tx.Rollback` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreRollback` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Tx.Rollback` method.
	Rollback func(ctx interface{}, tx *Tx) error

	// PostRollback is a callback that gets called at the end of
	// the call to `Tx.Rollback`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreRollback` method, and may be nil.
	PostRollback func(ctx interface{}, tx *Tx) error

	// PreClose is a callback that gets called prior to calling
	// `Conn.Close`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.Close` and `Hooks.Close` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Close` and
	// `Hooks.PostClose` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.Close` method and `Hooks.Close`
	// methods are not called.
	PreClose func(conn *Conn) (interface{}, error)

	// Close is called after the underlying driver's `Conn.Close` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreClose` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.Close` method.
	Close func(ctx interface{}, conn *Conn) error

	// PostClose is a callback that gets called at the end of
	// the call to `Conn.Close`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreClose` method, and may be nil.
	PostClose func(ctx interface{}, conn *Conn, err error) error

	// PreResetSession is a callback that gets called prior to calling
	// `Conn.ResetSession`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.ResetSession` and `Hooks.ResetSession` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.ResetSession` and
	// `Hooks.PostResetSession` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.ResetSession` method and `Hooks.ResetSession`
	// methods are not called.
	PreResetSession func(conn *Conn) (interface{}, error)

	// ResetSession is called after the underlying driver's `Conn.ResetSession` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreResetSession` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.ResetSession` method.
	ResetSession func(ctx interface{}, conn *Conn) error

	// PostResetSession is a callback that gets called at the end of
	// the call to `Conn.ResetSession`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreResetSession` method, and may be nil.
	PostResetSession func(ctx interface{}, conn *Conn, err error) error
}

Hooks is callback functions for the proxy. Deprecated: You should use HooksContext instead.

type HooksContext

type HooksContext struct {
	// PrePing is a callback that gets called prior to calling
	// `Conn.Ping`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.Ping` and `Hooks.Ping` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Ping` and
	// `Hooks.PostPing` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.Ping` method and `Hooks.Ping`
	// methods are not called.
	PrePing func(c context.Context, conn *Conn) (interface{}, error)

	// Ping is called after the underlying driver's `Conn.Ping` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePing` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.Ping` method.
	Ping func(c context.Context, ctx interface{}, conn *Conn) error

	// PostPing is a callback that gets called at the end of
	// the call to `Conn.Ping`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePing` method, and may be nil.
	PostPing func(c context.Context, ctx interface{}, conn *Conn, err error) error

	// PreOpen is a callback that gets called before any
	// attempt to open the sql connection is made, and is ALWAYS
	// called.
	//
	// The first return value is passed to both `Hooks.Open` and
	// `Hooks.PostOpen` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Driver.Open` method and `Hooks.Open`
	// methods are not called.
	PreOpen func(c context.Context, name string) (interface{}, error)

	// Open is called after the underlying driver's `Driver.Open` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreOpen` method, and may be nil.
	//
	// If this callback returns an error, then the `conn` object is
	// closed by calling the `Close` method, and the error from this
	// callback is returned by the `db.Open` method.
	Open func(c context.Context, ctx interface{}, conn *Conn) error

	// PostOpen is a callback that gets called at the end of
	// the call to `db.Open(). It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreOpen` method, and may be nil.
	PostOpen func(c context.Context, ctx interface{}, conn *Conn, err error) error

	// PrePrepare is a callback that gets called prior to calling
	// `db.Prepare`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `db.Exec` and `Hooks.Prepare` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Prepare` and
	// `Hooks.PostPrepare` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook.
	PrePrepare func(c context.Context, stmt *Stmt) (interface{}, error)

	// Prepare is called after the underlying driver's `db.Prepare` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePrepare` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `db.Prepare` method.
	Prepare func(c context.Context, ctx interface{}, stmt *Stmt) error

	// PostPrepare is a callback that gets called at the end of
	// the call to `db.Prepare`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePrepare` method, and may be nil.
	PostPrepare func(c context.Context, ctx interface{}, stmt *Stmt, err error) error

	// PreExec is a callback that gets called prior to calling
	// `Stmt.Exec`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Stmt.Exec` and `Hooks.Exec` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Exec` and
	// `Hooks.PostExec` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Driver.Exec` method and `Hooks.Exec`
	// methods are not called.
	PreExec func(c context.Context, stmt *Stmt, args []driver.NamedValue) (interface{}, error)

	// Exec is called after the underlying driver's `Driver.Exec` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreExec` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Stmt.Exec` method.
	Exec func(c context.Context, ctx interface{}, stmt *Stmt, args []driver.NamedValue, result driver.Result) error

	// PostExec is a callback that gets called at the end of
	// the call to `Stmt.Exec`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreExec` method, and may be nil.
	PostExec func(c context.Context, ctx interface{}, stmt *Stmt, args []driver.NamedValue, result driver.Result, err error) error

	// PreQuery is a callback that gets called prior to calling
	// `Stmt.Query`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Stmt.Query` and `Hooks.Query` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Query` and
	// `Hooks.PostQuery` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Stmt.Query` method and `Hooks.Query`
	// methods are not called.
	PreQuery func(c context.Context, stmt *Stmt, args []driver.NamedValue) (interface{}, error)

	// Query is called after the underlying driver's `Stmt.Query` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreQuery` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Stmt.Query` method.
	Query func(c context.Context, ctx interface{}, stmt *Stmt, args []driver.NamedValue, rows driver.Rows) error

	// PostQuery is a callback that gets called at the end of
	// the call to `Stmt.Query`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreQuery` method, and may be nil.
	PostQuery func(c context.Context, ctx interface{}, stmt *Stmt, args []driver.NamedValue, rows driver.Rows, err error) error

	// PreBegin is a callback that gets called prior to calling
	// `Stmt.Begin`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.Begin` and `Hooks.Begin` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Begin` and
	// `Hooks.PostBegin` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.Begin` method and `Hooks.Begin`
	// methods are not called.
	PreBegin func(c context.Context, conn *Conn) (interface{}, error)

	// Begin is called after the underlying driver's `Conn.Begin` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreBegin` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.Begin` method.
	Begin func(c context.Context, ctx interface{}, conn *Conn) error

	// PostBegin is a callback that gets called at the end of
	// the call to `Conn.Begin`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreBegin` method, and may be nil.
	PostBegin func(c context.Context, ctx interface{}, conn *Conn, err error) error

	// PreCommit is a callback that gets called prior to calling
	// `Tx.Commit`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Tx.Commit` and `Hooks.Commit` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Commit` and
	// `Hooks.PostCommit` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Tx.Commit` method and `Hooks.Commit`
	// methods are not called.
	PreCommit func(c context.Context, tx *Tx) (interface{}, error)

	// Commit is called after the underlying driver's `Tx.Commit` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreCommit` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Tx.Commit` method.
	Commit func(c context.Context, ctx interface{}, tx *Tx) error

	// PostCommit is a callback that gets called at the end of
	// the call to `Tx.Commit`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreCommit` method, and may be nil.
	PostCommit func(c context.Context, ctx interface{}, tx *Tx, err error) error

	// PreRollback is a callback that gets called prior to calling
	// `Tx.Rollback`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Tx.Rollback` and `Hooks.Rollback` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Rollback` and
	// `Hooks.PostRollback` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Tx.Rollback` method and `Hooks.Rollback`
	PreRollback func(c context.Context, tx *Tx) (interface{}, error)

	// Rollback is called after the underlying driver's `Tx.Rollback` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreRollback` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Tx.Rollback` method.
	Rollback func(c context.Context, ctx interface{}, tx *Tx) error

	// PostRollback is a callback that gets called at the end of
	// the call to `Tx.Rollback`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreRollback` method, and may be nil.
	PostRollback func(c context.Context, ctx interface{}, tx *Tx, err error) error

	// PreClose is a callback that gets called prior to calling
	// `Conn.Close`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.Close` and `Hooks.Close` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.Close` and
	// `Hooks.PostClose` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.Close` method and `Hooks.Close`
	// methods are not called.
	PreClose func(c context.Context, conn *Conn) (interface{}, error)

	// Close is called after the underlying driver's `Conn.Close` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreClose` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.Close` method.
	Close func(c context.Context, ctx interface{}, conn *Conn) error

	// PostClose is a callback that gets called at the end of
	// the call to `Conn.Close`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreClose` method, and may be nil.
	PostClose func(c context.Context, ctx interface{}, conn *Conn, err error) error

	// PreResetSession is a callback that gets called prior to calling
	// `Conn.ResetSession`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.ResetSession` and `Hooks.ResetSession` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.ResetSession` and
	// `Hooks.PostResetSession` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the underlying driver's `Conn.ResetSession` method and `Hooks.ResetSession`
	// methods are not called.
	PreResetSession func(c context.Context, conn *Conn) (interface{}, error)

	// ResetSession is called after the underlying driver's `Conn.ResetSession` method
	// returns without any errors.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreResetSession` method, and may be nil.
	//
	// If this callback returns an error, then the error from this
	// callback is returned by the `Conn.ResetSession` method.
	ResetSession func(c context.Context, ctx interface{}, conn *Conn) error

	// PostResetSession is a callback that gets called at the end of
	// the call to `Conn.ResetSession`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreResetSession` method, and may be nil.
	PostResetSession func(c context.Context, ctx interface{}, conn *Conn, err error) error

	// PreIsValid is a callback that gets called prior to calling
	// `Conn.IsValid`, and is ALWAYS called. If this callback returns an
	// error, the underlying driver's `Conn.IsValid` and `Hooks.IsValid` methods
	// are not called.
	//
	// The first return value is passed to both `Hooks.IsValid` and
	// `Hooks.PostIsValid` callbacks. You may specify anything you want.
	// Return nil if you do not need to use it.
	//
	// The second return value is indicates the error found while
	// executing this hook. If this callback returns an error,
	// the connection is marked as invalid.
	PreIsValid func(conn *Conn) (interface{}, error)

	// IsValid is called after the underlying driver's `Conn.IsValid` method
	// returns true.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PreIsValid` method, and may be nil.
	//
	// If this callback returns an error, the connection is marked as invalid.
	IsValid func(ctx interface{}, conn *Conn) error

	// PostPostIsValid is a callback that gets called at the end of
	// the call to `Conn.PostIsValid`. It is ALWAYS called.
	//
	// The `ctx` parameter is the return value supplied from the
	// `Hooks.PrePostIsValid` method, and may be nil.
	PostIsValid func(ctx interface{}, conn *Conn, valid bool) error
}

HooksContext is callback functions with context.Context for the proxy.

func NewTraceHooks

func NewTraceHooks(opt TracerOptions) *HooksContext

NewTraceHooks creates new HooksContext which trace SQL queries.

type Outputter

type Outputter interface {
	Output(calldepth int, s string) error
}

Outputter is what is used by the tracing proxy created via `NewTraceProxy`. Anything that implements a `log.Logger` style `Output` method will satisfy this interface.

type PackageFilter

type PackageFilter map[string]struct{}

PackageFilter is an implementation of Filter.

func (PackageFilter) DoOutput

func (f PackageFilter) DoOutput(packageName string) bool

DoOutput returns false if the package is in the ignored list.

func (PackageFilter) Ignore

func (f PackageFilter) Ignore(packageName string)

Ignore add the package into the ignored list.

type Proxy

type Proxy struct {
	Driver driver.Driver
	// contains filtered or unexported fields
}

Proxy is a sql driver. It adds hook points to other sql drivers.

func NewProxy

func NewProxy(driver driver.Driver, hs ...*Hooks) *Proxy

NewProxy creates new Proxy driver. Deprecated: You should use NewProxyContext instead.

func NewProxyContext

func NewProxyContext(driver driver.Driver, hs ...*HooksContext) *Proxy

NewProxyContext creates new Proxy driver.

func NewTraceProxy

func NewTraceProxy(d driver.Driver, o Outputter) *Proxy

NewTraceProxy generates a proxy that logs queries.

func NewTraceProxyWithFilter

func NewTraceProxyWithFilter(d driver.Driver, o Outputter, f Filter) *Proxy

NewTraceProxyWithFilter generates a proxy that logs queries.

func (*Proxy) Open

func (p *Proxy) Open(name string) (driver.Conn, error)

Open creates new connection which is wrapped by Conn. It will triggers PreOpen, Open, PostOpen hooks.

func (*Proxy) OpenConnector

func (p *Proxy) OpenConnector(name string) (driver.Connector, error)

OpenConnector creates a new connector which is wrapped by Connector. It will triggers PreOpen, Open, PostOpen hooks.

type Stmt

type Stmt struct {
	// Stmt is the original statement.
	// It may be nil because some sql drivers support skipping Prepare.
	Stmt driver.Stmt

	QueryString string
	Proxy       *Proxy
	Conn        *Conn
}

Stmt adds hook points into "database/sql/driver".Stmt.

func (*Stmt) CheckNamedValue added in v0.2.0

func (stmt *Stmt) CheckNamedValue(nv *driver.NamedValue) (err error)

CheckNamedValue for implementing NamedValueChecker

func (*Stmt) Close

func (stmt *Stmt) Close() error

Close closes the statement. It just calls the original Close method.

func (*Stmt) ColumnConverter

func (stmt *Stmt) ColumnConverter(idx int) driver.ValueConverter

ColumnConverter returns a ValueConverter for the provided column index. If the original statement does not satisfy ColumnConverter, it returns driver.DefaultParameterConverter.

func (*Stmt) Exec

func (stmt *Stmt) Exec(args []driver.Value) (driver.Result, error)

Exec executes a query that doesn't return rows. It will trigger PreExec, Exec, PostExec hooks. NOT SUPPORTED: use ExecContext instead

func (*Stmt) ExecContext

func (stmt *Stmt) ExecContext(c context.Context, args []driver.NamedValue) (driver.Result, error)

ExecContext executes a query that doesn't return rows. It will trigger PreExec, Exec, PostExec hooks.

func (*Stmt) NumInput

func (stmt *Stmt) NumInput() int

NumInput returns the number of placeholder parameters. It just calls the original NumInput method.

func (*Stmt) Query

func (stmt *Stmt) Query(args []driver.Value) (driver.Rows, error)

Query executes a query that may return rows. It wil trigger PreQuery, Query, PostQuery hooks. NOT SUPPORTED: use QueryContext instead

func (*Stmt) QueryContext

func (stmt *Stmt) QueryContext(c context.Context, args []driver.NamedValue) (driver.Rows, error)

QueryContext executes a query that may return rows. It wil trigger PreQuery, Query, PostQuery hooks.

type TracerOptions

type TracerOptions struct {
	// Outputter is the output of the log.
	// If is nil nil, log.Output is used.
	Outputter Outputter

	// Filter is used by the tracing proxy for skipping database libraries (e.g. O/R mapper).
	// If it is nil, DefaultPackageFilter is used.
	Filter Filter

	// SlowQuery is a threshold duration to output into log.
	// output all queries if SlowQuery is zero.
	SlowQuery time.Duration
}

TracerOptions holds the tracing option.

type Tx

type Tx struct {
	Tx    driver.Tx
	Proxy *Proxy
	Conn  *Conn
	// contains filtered or unexported fields
}

Tx adds hook points into "database/sql/driver".Tx.

func (*Tx) Commit

func (tx *Tx) Commit() error

Commit commits the transaction. It will trigger PreCommit, Commit, PostCommit hooks.

func (*Tx) Rollback

func (tx *Tx) Rollback() error

Rollback rollbacks the transaction. It will trigger PreRollback, Rollback, PostRollback hooks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL