package driver
driver 包定义了应被数据库驱动实现的接口,这些接口会被 sql 包使用。
绝大多数代码应使用 sql 包。
=================================================================================
Value 是 drivers 必须能够操作的值。
它要么是 nil —— 一个被数据库 driver 的 NamedValueChecker 接口操作的类型,或者以下类型的实例:
int64
float64
bool
[]byte
string
-
time.Time
type Value interface{}
NamedValue 装载了 value name 和 value。
type NamedValue struct {
Name string // 如果 Name 字段不是空的,它应该使用关键字参数方式赋值,而不是位置参数方式。
Ordinal int // 位置参数方式赋值。
Value value // 关键字参数方式赋值。
}
Driver 是一个database dirver 必须实现的接口。
Database drivers 应该实现 DriverContext ,用于访问 contexts 和解析一次连接池的名字,而不是每个连接解析一次。
type Driver interface {
Open(name string) (Conn, error) // Open 返回一个新的到数据库的连接。name 参数,是一个 database 特定格式的字符串。
} // Open 可以返回一个缓存的连接,但是这样做没有必要;该 sql 包维持着一个空闲的连接池以便重用。
如果一个 driver 实现了 DriverContext,那么 sql.DB 将能够调用 OpenConnector 来获得一个 连接器,并调用 连接器的 Conn 方法来获得每个所需的连接,而不是使用 Open 方法。这使得 driver 可以提供对连接的 context 的访问。
type DriverContext interface {
OpenConnector(name string) (Connector, error)
}
Connector,连接器,代表了一个固定配置的连接器,可以创建任意数量的 Conns (对象)来被多个 goroutine 使用。
一个连接器能够被传给 sql.OpenDB,以允许 drivers 实现他们自己的 sql.DB 构造器,或者被 DriverContext 的 OpenConnector 方法返回,并允许 driver 访问 context,避免重复解析配置。
type Connector interface {
Connect(context.Context) (Conn, error) // Connect 返回一个到数据库的连接。
Driver() Driver // Driver 返回 Connector 底层的驱动,用于和 sql.DB 上的 Driver 方法兼容。
}
ErrSkip 可以被一些可选的方法返回,用以指示 fast path 在运行时中不可用,并且该 sql 包应该延续,因为该可选参数没有实现。ErrSkip 仅仅被显式说明的地方支持。
var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")
ErrBadConn 应该被 driver 用于表示一个 driver.Conn 处于坏的状态时返回给 sql 包,而 sql 包应该尝试新的连接。
var ErrBadConn = errors.New("driver: bad connection")
Pinger 是一个可选的接口,被 Conn 实现。如果一个 Conn 没有实现 Pinger,sql 包的 DB.Ping 和 DB.PingContext 将检测是否有至少一个 Conn 可用。
Conn.Ping 返回 ErrBadConn,DB.Ping 和 DB.PingContext 将会从连接池中删除 Conn。
type Pinger interface {
Ping(ctx context.Context) error
}
Execer 是一个可选接口,被 Conn 实现。如果 Conn 既没有实现 ExecerContext 和 Execer,那么 sql 包的 DB.Exec 将首先准备一个查询,执行该 statement,并关闭该 statement。
type Execer interface {
Exec(query string, args []Value) (Result, error)
}
ExecerContext 是一个可选接口,被 Conn 实现。如果一个 Conn 没有实现 ExecerContext,该 sql 包的 DB.Exec 将退化为 Execer。
type ExecerContext interface {
ExecContext(ctx context.Context, query string, args []NamedValue) (Result, error)
}
Queryer 是一个可选接口,被 Conn 实现。
type Queryer interface {
Query(query string, args []Value) (Rows, error)
}
type QueryerContext interface {
QueryContext(ctx context.Context, query string, args []NamedValue) (Rows, error)
}
Conn 是一个到 database 的连接。它不可以被多个 goroutine 并发使用。Conn 是有状态的。
type Conn interface {
Prepare(query string) (Stmt, error) // Prepare 返回一个准备好的 statement,绑定到 connection。
Close() error // Close 使当前的 statement 无效,使当前的事务停止,并标记该连接不再使用。
Begin() (Tx, error) // Begin 开始并返回一个事务。
}
ConnPrepareContext 改良了 Conn 接口。
type ConnPrepareContext interface {
PrepareContext(ctx context.Context, query string) (Stmt, error) // Context 用于 preparation,而非 statement。
}
IsolationLevel 是一个在 TxOptions 中存储的事务隔离级别。
该类型,连同值,应该被认为和 sql.IsolationLevel 是一样的。
type IsolationLevel int
TxOptions 保存着 transaction 的参数。
type TxOptions struct {
Isolation IsolationLevel
ReadOnly bool
}
ConnBeginTx 通过 context 和 TxOptions 增强了 Conn 接口。
type ConnBeginTx interface {
BeginTx(ctx context.Context, opts TxOptions) (Tx, error) // 如果 context 被取消,那么用户的 sql 包将在丢弃和关闭连接前调用 Tx.Rollback。这将必须检查 opts.Isolation 来决定是否设置了隔离级别。如果 driver 不支持 非默认级别,并且设置了一个级别,或者是不支持默认级别,那么将返回错误。
}
SessionResetter 可以被 Conn 实现,以允许 drivers 来重置 session 状态,并发送一个 bad connection 信号。
type SessionResetter interface {
ResetSession(ctx context.Context) error // 当一个连接在连接池中时,ResetSession 将被调用。在该方法被调用之前,没有请求被运行。
}
Result 是 查询执行的结果。
type Result interface {
LastInsertId() (int64, error) // LastInsertId 返回 database 自增 ID,比如是在 insert into a table 之后。
RowsAffected() (int64, error) // RowsAffected 返回 生效的 rows 数量。
}
Stmt 是一个准备好的 statement。 它和一个 Conn 绑定,而不被多重 goroutine 使用。
type Stmt interface {
Close() error // 关闭 Stmt
NumInput() int // NumInput 返回占位符参数的数量。如果 NumInput 返回大于等于0,该 sql 包将检查参数个数。
Exec(args []Value) (Result, error) // Exec 执行不返回行数的查询,比如 insert 和 update。
Query(args []Value) (Rows, error) // Query 执行返回行数的查询,比如 select。
}
StmtExecContext 增强 Stmt 接口通过 ExecContext。
type StmtExecContext interface {
ExecContext(ctx context.Context, args []NamedValue) (Result, error)
}
type StmtQueryContext interface {
QueryContext(ctx context.Context, args []NamedValue) (Rows, error)
}
NamedValueChecker 可以被 Conn 或 Stmt 选择实现。它提供给 drivers 在默认允许的值类型以外,更多的控制以操作 go 和 database 类型。
sql 包通过以下的顺序检测值,从以下的顺序找到就停止:Stmt.NamedValueChecker, Conn.NamedValueChecker, Stmt.ColumnConventer, DefaultParameterConventer。
如果 CheckNamedValue 返回 ErrRemoveArgument,该 NamedValue 将被包含在最终的查询参数中。这将可能用于传递特定的参数到请求。
如果 ErrSkip 被列转换器返回,那么 error 检测路径将被用于参数。Drivers 可能希望返回 ErrSkip。
type NamedValueChecker interface {
CheckNameValue(*NamedValue) error // 在参数传递给 driver 之前,CheckNamedValue 方法被调用;并且代替 ColumnConventer。CheckNamedValue 必须做类型验证,并转换为 driver 适用的类型。
}
ColumnConventer 可以被 Stmt 选择实现,如果 statement 意识到它自己的 column 类型,并从到一个驱动值的类型转换。
type ColumnConventer interface {
ColumnConventer(idx int) ValueConventer // ColumnConventer 返回一个 ValueConventer,用于提供列序号。如果指定列的类型未知,或者不应该被操作,DefaultValueConventer 能够被返回。
}
Rows 是一个迭代器,构建于可执行的请求结果。
type Rows interface {
Columns() []string // Columns 返回 列名。结果中的列数,是从结果切片中推断出来的。如果某个列名未知,那么会返回一个空字符串。
Close() error // 关闭该 行迭代器。
Next(dest []Value) error // Next 用于把下一行数据转移到 slice。提供的 slice 应该和 Columns 方法提供的一样宽。如果没有更多的行,那么 Next 应该返回 io.EOF。dest 参数不要写在 Next 方法之外。注意,在关闭 Rows 以后,就不能修改 dest 中装载的数据了。
}
RowsNextResultSet 扩展 Rows 接口,通过把 发送到 driver 的信号发送给 next result set。
type RowsNextResultSet interface {
Rows
HasNextResultSet() bool // HasNextResultSet 在当前结果集的最后被调用,报告是否还有下一结果集
NextResultSet() error
}
RowsColumnTypeScanType 可以被 Rows 实现。它应该返回值类型能够被用于把类型扫描进入。例如,database column 类型 "bigint" 应该被返回 "reflect.TypeOf(int64(0))"。
type RowsColumnTypeScanType interface {
Rows
ColumnTypeScanType(index int) reflect.Type
}
RowsColumnTypeDatabaseTypeName 可以被 Rows 实现。它应该返回该数据库系统中不带长度的类型名称。类型名称应该小写。
type RowsColumnDatabaseTypeName interface {
Rows
ColumnTypeDatabaseTypeName(index int) string
}
RowsColumnTypeLength 可以被 Rows 实现。如果是变长类型,它应该返回 column type 的长度。如果不是变长类型,它应该返回 false。
如果在系统限制之外长度没有限制,它应该返回 math.MaxInt64 类型。以下例子是变长类型的返回值:
TEXT (math.MaxInt64, true)
varchar(10) (10, true)
nvarchar(10) (10, true)
decimal (0, false)
int (0, false)
bytea(30) (30, true)
type RowsColumnTypeLength interface {
Rows
ColumnTypeLength(index int) (length int64, ok bool)
}
RowsColumnTypeNullable 可以被 Rows 实现。nullable 值应该为 true。
type RowsColumnTypeNullable interface {
Rows
ColumnTypeNullable(index int) (nullable, ok bool)
}
RowsColumnTypePrecisionScale 可以被 Rows 实现。它应该返回 decimal 的精度和量级。如果不可应用,ok 参数应该为 false。以下是返回值的例子:
type RowsColumnTypePrecisionScale interface {
Rows
ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)
}
Tx 是一个事务。
type Tx interface {
Commit() error
Rollback() error
}
RowsAffected 实现 insert 和 update 的结果。
type RowsAffected int64
var _ Result = RowsAffected(0)
func (RowsAffected) LastInsertId() (int64, error) {
return 0, errors.New("no LastInsertId available")
}
func (v RowsAffected) RowsAffected() (int64, error) {
return int64(v), nil
}
ResultNoRows 是一个 当 DDL 命令成功时,drivers 预定义的返回结果。当 LastInsertId 和 RowsAffected 同时存在时,返回错误。
var ResultNotRows noRows
type noRows struct{}
var _ Result = noRows{}
func (noRows) LastInsertId() (int64, error) {
return 0, errors.New("no LastInsertId available after DDL statement")
}
func (noRows) RowsAffected() (int64, error) {
return 0, errors.New("no RowsAffected available after DDL statement")
}