go源码解读-database/driver包

  • driver包定义了一系列需要由不同驱动实现的接口,供sql包调用

driver中定义的类型和接口

必选接口

  • Value的值需要能被具体的数据库驱动实现所处理
  • Value的值包括:
    • nil
    • NamedValueChecker可以处理的类型
    • int64
    • float64
    • bool
    • []byte
    • string
    • time.Time
  • 如果数据库驱动实现cursor,返回的Value类型对象需要实现Rows接口
  • NamedValue包含了Value类型的值和其名称
1
2
3
4
5
6
7
type Value interface{}
type NamedValue struct {
Name string // Value的名称
Ordinal int // 参数次序
Value Value // 参数值
}
  • Driver接口是数据库驱动实现必须实现的接口之一
  • 数据库实际上可以实现DriverContext接口来将连接放到连接池中,避免每次操作建立一次连接
  • Driver接口的Open方法返回一个新的数据库连接
  • Open方法可能返回一个之前关闭的缓存连接,但是sql包中实际上是有连接池来处理空闲连接并提高连接的使用率,因此没太必要
  • 返回的Conn连接在同一时间只能被一个线程使用
1
2
3
type Driver interface {
Open(name string) (Conn, error) // 创建连接
}
  • Conn表示一个数据库连接,不能被多个线程同时使用
    • Conn是有状态的
    • Prepare方法返回一个prepared statement,并和当前的连接绑定
    • Close方法会关闭ps语句和事物,释放当前连接
    • sql包中对于连接的管理十分完备,因此不推荐驱动自己管理连接缓存,连接的管理交由sql包完成
    • Conn接口包含Begin方法来开启一个事物,返回Tx对象
  • Stmt接口和一个具体的数据库连接相绑定,不能同时被多个线程使用,preparedStatement
    • Close方法完成statement语句的关闭,基本不调用,语句的关闭由sql包管理
    • NumInput方法返回stmt语句中的占位符的个数
    • Exec方法执行不返回rows数据的数据库操作,比如insert,update操作等,返回Result,目前已经被弃用,driver通过实现StmtExecContext来实现该操作
    • Query方法执行返回rows数据的数据库操作,比如select操作,返回Rows,被弃用,通过实现StmtQueryContext来实现该操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 连接
type Conn interface {
Prepare(query string) (Stmt, error)
Close() error
Begin() (Tx, error)
}
// preparedStatement语句
type Stmt interface {
Close() error
NumInput() int
Exec(args []Value) (Result, error)
Query(args []Value) (Rows, error)
}
// 执行结果,insert,updated
type Result interface {
// 返回上次插入的数据的自增ID
LastInsertId() (int64, error)
// 返回数据库语句被影响的行数
RowsAffected() (int64, error)
}
// Rows是个可迭代的返回结果
type Rows interface {
// 返回列的名字信息
Columns() []string
Close() error
// 获取Rows的下一列数据
Next(dest []Value) error
}
// Tx表示一个数据库事务
type Tx interface {
Commit() error // 数据库提交
Rollback() error // 回滚
}
  • 如果数据库实现了DriverContext接口,则sql.DB会通过调用OpenConnector方法获取一个Connector对象,之后调用Connector的Connect方法来获取数据库连接
  • 实现DriverContext的好处在于可以解析一次连接名称并可以复用之前创建的连接,效率更高
  • OpenConnector解析的数据库连接格式和Driver.Open方法是一致的
  • Connector持有固定的连接,可以创建多个等价的数据库连接支持多线程来使用
1
2
3
4
5
6
7
8
9
10
11
type DriverContext interface {
// OpenConnector解析的数据库连接格式和Driver.Open方法是一致的
OpenConnector(name string) (Connector, error)
}
type Connector interface {
// 创建数据库连接,创建出的连接同时支持一个线程使用
Connect(context.Context) (Conn, error)
// 返回Connector底层的Driver对象,供sql.DB使用
Driver() Driver
}
  • ConnPrepareContext将Conn接口和context结合
1
2
3
type ConnPrepareContext interface {
PrepareContext(ctx context.Context, query string) (Stmt, error)
}
  • IsolationLevel表示事务隔离级别,和sql.IsolationLevel相关联
  • TxOptions结构体持有事务相关选项,取值参考sql.TxOptions
  • ConnBeginTx将Conn和context关联起来
1
2
3
4
5
6
7
8
type IsolationLevel int
type TxOptions struct {
Isolation IsolationLevel
ReadOnly bool
}
type ConnBeginTx interface {
BeginTx(ctx context.Context, opts TxOptions) (Tx, error)
}
  • SessionResetter来实现一个连接的重置
1
2
3
type SessionResetter interface {
ResetSession(ctx context.Context) error
}
  • StmtExecContext,StmtQueryContext接口也是与Context相关联起来
1
2
3
4
5
6
7
type StmtExecContext interface {
ExecContext(ctx context.Context, args []NamedValue) (Result, error)
}
type StmtQueryContext interface {
QueryContext(ctx context.Context, args []NamedValue) (Rows, error)
}
  • NamedValueChecker来实现对NamedValue的检查
1
2
3
type NamedValueChecker interface {
CheckNamedValue(*NamedValue) error
}
  • RowsNextResultSet扩展Rows对象,提供了HasNextResultSet和NextResultSet来实现对结果的多种操作
  • RowsColumnTypeScanType返回Column的Type类型
  • RowsColumnTypeDatabaseTypeName返回Column对应的数据库类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type RowsNextResultSet interface {
Rows
HasNextResultSet() bool
NextResultSet() error
}
type RowsColumnTypeScanType interface {
Rows
ColumnTypeScanType(index int) reflect.Type
}
type RowsColumnTypeDatabaseTypeName interface {
Rows
ColumnTypeDatabaseTypeName(index int) string
}
type RowsColumnTypeLength interface {
Rows
ColumnTypeLength(index int) (length int64, ok bool)
}
type RowsColumnTypeNullable interface {
Rows
ColumnTypeNullable(index int) (nullable, ok bool)
}
type RowsColumnTypePrecisionScale interface {
Rows
ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)
}

可选接口

  • Pinger是一个可选接口,一般由Conn来实现
  • Pinger由sql.DB来调用,根据其返回值来判定是否连接仍然可用,否则将其移除出连接池
1
2
3
type Pinger interface {
Ping(ctx context.Context) error
}
  • ExecerContext由sql.DB.Exec来调用
  • 未实现该接口,会调用Execer的Exec方法,如果仍然没有实现,则会调用stmt,exce, close
  • QueryerContext 和ExecerContext类似
1
2
3
4
5
6
type ExecerContext interface {
ExecContext(ctx context.Context, query string, args []NamedValue) (Result, error)
}
type QueryerContext interface {
QueryContext(ctx context.Context, query string, args []NamedValue) (Rows, error)
}
Donate comment here