Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

为简化示例编写,我们这里实现了一个自定义的MySQL驱动,该驱动继承于gdb模块中已经实现的DriverMysql,并按照需要修改覆盖相应的接口方法。由于所有的SQL语句执行必定会通过DoQuery或者DoExec接口,因此我们在自定义的驱动中实现并覆盖这两个接口方法即可。

Code Block
languagego
package driver

import (
	"context"
	"database/sql"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/os/gtime"
)

// MyDriver is a custom database driver, which is used for testing only.
// For simplifying the unit testing case purpose, MyDriver struct inherits the mysql driver
// gdb.DriverMysql and overwrites its functions DoQuery and DoExec.
// So if there's any sql execution, it goes through MyDriver.DoQuery/MyDriver.DoExec firstly
// and then gdb.DriverMysql.DoQuery/gdb.DriverMysql.DoExec.
// You can call it sql "HOOK" or "HiJack" as your will.
type MyDriver struct {
	*gdb.DriverMysql
}

var (
	// customDriverName is my driver name, which is used for registering.
	customDriverName = "MyDriver"
)

func init() {
	// It here registers my custom driver in package initialization function "init".
	// You can later use this type in the database configuration.
	if err := gdb.Register(customDriverName, &MyDriver{}); err != nil {
		panic(err)
	}
}

// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *MyDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
	return &MyDriver{
		&gdb.DriverMysql{
			Core: core,
		},
	}, nil
}

// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoQuery(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
	tsMilli := gtime.TimestampMilli()
	rows, err = d.DriverMysql.DoQuery(ctx, link, sql, args...)
	link.Exec(
		"INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
		gdb.FormatSqlWithArgs(sql, args),
		gtime.TimestampMilli()-tsMilli,
		gtime.Now(),
		err,
	)
	return
}

// DoExec commits the query string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoExec(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
	tsMilli := gtime.TimestampMilli()
	result, err = d.DriverMysql.DoExec(ctx, link, sql, args...)
	link.Exec(
		"INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
		gdb.FormatSqlWithArgs(sql, args),
		gtime.TimestampMilli()-tsMilli,
		gtime.Now(),
		err,
	)
	return
}

...

我们看到,这里在包初始化方法init中使用了gdb.Register("MyDriver", &MyDriver{})来注册了了一个自定义名称的驱动。我们也可以通过gdb.Register("mysql", &MyDriver{})来覆盖已有的框架mysql驱动为自己的驱动。

...