标准库 database/sql/driver 翻译

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")
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容