1// Copyright 2011 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package driver defines interfaces to be implemented by database 6// drivers as used by package sql. 7// 8// Most code should use the [database/sql] package. 9// 10// The driver interface has evolved over time. Drivers should implement 11// [Connector] and [DriverContext] interfaces. 12// The Connector.Connect and Driver.Open methods should never return [ErrBadConn]. 13// [ErrBadConn] should only be returned from [Validator], [SessionResetter], or 14// a query method if the connection is already in an invalid (e.g. closed) state. 15// 16// All [Conn] implementations should implement the following interfaces: 17// [Pinger], [SessionResetter], and [Validator]. 18// 19// If named parameters or context are supported, the driver's [Conn] should implement: 20// [ExecerContext], [QueryerContext], [ConnPrepareContext], and [ConnBeginTx]. 21// 22// To support custom data types, implement [NamedValueChecker]. [NamedValueChecker] 23// also allows queries to accept per-query options as a parameter by returning 24// [ErrRemoveArgument] from CheckNamedValue. 25// 26// If multiple result sets are supported, [Rows] should implement [RowsNextResultSet]. 27// If the driver knows how to describe the types present in the returned result 28// it should implement the following interfaces: [RowsColumnTypeScanType], 29// [RowsColumnTypeDatabaseTypeName], [RowsColumnTypeLength], [RowsColumnTypeNullable], 30// and [RowsColumnTypePrecisionScale]. A given row value may also return a [Rows] 31// type, which may represent a database cursor value. 32// 33// If a [Conn] implements [Validator], then the IsValid method is called 34// before returning the connection to the connection pool. If an entry in the 35// connection pool implements [SessionResetter], then ResetSession 36// is called before reusing the connection for another query. If a connection is 37// never returned to the connection pool but is immediately reused, then 38// ResetSession is called prior to reuse but IsValid is not called. 39package driver 40 41import ( 42 "context" 43 "errors" 44 "reflect" 45) 46 47// Value is a value that drivers must be able to handle. 48// It is either nil, a type handled by a database driver's [NamedValueChecker] 49// interface, or an instance of one of these types: 50// 51// int64 52// float64 53// bool 54// []byte 55// string 56// time.Time 57// 58// If the driver supports cursors, a returned Value may also implement the [Rows] interface 59// in this package. This is used, for example, when a user selects a cursor 60// such as "select cursor(select * from my_table) from dual". If the [Rows] 61// from the select is closed, the cursor [Rows] will also be closed. 62type Value any 63 64// NamedValue holds both the value name and value. 65type NamedValue struct { 66 // If the Name is not empty it should be used for the parameter identifier and 67 // not the ordinal position. 68 // 69 // Name will not have a symbol prefix. 70 Name string 71 72 // Ordinal position of the parameter starting from one and is always set. 73 Ordinal int 74 75 // Value is the parameter value. 76 Value Value 77} 78 79// Driver is the interface that must be implemented by a database 80// driver. 81// 82// Database drivers may implement [DriverContext] for access 83// to contexts and to parse the name only once for a pool of connections, 84// instead of once per connection. 85type Driver interface { 86 // Open returns a new connection to the database. 87 // The name is a string in a driver-specific format. 88 // 89 // Open may return a cached connection (one previously 90 // closed), but doing so is unnecessary; the sql package 91 // maintains a pool of idle connections for efficient re-use. 92 // 93 // The returned connection is only used by one goroutine at a 94 // time. 95 Open(name string) (Conn, error) 96} 97 98// If a [Driver] implements DriverContext, then [database/sql.DB] will call 99// OpenConnector to obtain a [Connector] and then invoke 100// that [Connector]'s Connect method to obtain each needed connection, 101// instead of invoking the [Driver]'s Open method for each connection. 102// The two-step sequence allows drivers to parse the name just once 103// and also provides access to per-[Conn] contexts. 104type DriverContext interface { 105 // OpenConnector must parse the name in the same format that Driver.Open 106 // parses the name parameter. 107 OpenConnector(name string) (Connector, error) 108} 109 110// A Connector represents a driver in a fixed configuration 111// and can create any number of equivalent Conns for use 112// by multiple goroutines. 113// 114// A Connector can be passed to [database/sql.OpenDB], to allow drivers 115// to implement their own [database/sql.DB] constructors, or returned by 116// [DriverContext]'s OpenConnector method, to allow drivers 117// access to context and to avoid repeated parsing of driver 118// configuration. 119// 120// If a Connector implements [io.Closer], the [database/sql.DB.Close] 121// method will call the Close method and return error (if any). 122type Connector interface { 123 // Connect returns a connection to the database. 124 // Connect may return a cached connection (one previously 125 // closed), but doing so is unnecessary; the sql package 126 // maintains a pool of idle connections for efficient re-use. 127 // 128 // The provided context.Context is for dialing purposes only 129 // (see net.DialContext) and should not be stored or used for 130 // other purposes. A default timeout should still be used 131 // when dialing as a connection pool may call Connect 132 // asynchronously to any query. 133 // 134 // The returned connection is only used by one goroutine at a 135 // time. 136 Connect(context.Context) (Conn, error) 137 138 // Driver returns the underlying Driver of the Connector, 139 // mainly to maintain compatibility with the Driver method 140 // on sql.DB. 141 Driver() Driver 142} 143 144// ErrSkip may be returned by some optional interfaces' methods to 145// indicate at runtime that the fast path is unavailable and the sql 146// package should continue as if the optional interface was not 147// implemented. ErrSkip is only supported where explicitly 148// documented. 149var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented") 150 151// ErrBadConn should be returned by a driver to signal to the [database/sql] 152// package that a driver.[Conn] is in a bad state (such as the server 153// having earlier closed the connection) and the [database/sql] package should 154// retry on a new connection. 155// 156// To prevent duplicate operations, ErrBadConn should NOT be returned 157// if there's a possibility that the database server might have 158// performed the operation. Even if the server sends back an error, 159// you shouldn't return ErrBadConn. 160// 161// Errors will be checked using [errors.Is]. An error may 162// wrap ErrBadConn or implement the Is(error) bool method. 163var ErrBadConn = errors.New("driver: bad connection") 164 165// Pinger is an optional interface that may be implemented by a [Conn]. 166// 167// If a [Conn] does not implement Pinger, the [database/sql.DB.Ping] and 168// [database/sql.DB.PingContext] will check if there is at least one [Conn] available. 169// 170// If Conn.Ping returns [ErrBadConn], [database/sql.DB.Ping] and [database/sql.DB.PingContext] will remove 171// the [Conn] from pool. 172type Pinger interface { 173 Ping(ctx context.Context) error 174} 175 176// Execer is an optional interface that may be implemented by a [Conn]. 177// 178// If a [Conn] implements neither [ExecerContext] nor [Execer], 179// the [database/sql.DB.Exec] will first prepare a query, execute the statement, 180// and then close the statement. 181// 182// Exec may return [ErrSkip]. 183// 184// Deprecated: Drivers should implement [ExecerContext] instead. 185type Execer interface { 186 Exec(query string, args []Value) (Result, error) 187} 188 189// ExecerContext is an optional interface that may be implemented by a [Conn]. 190// 191// If a [Conn] does not implement [ExecerContext], the [database/sql.DB.Exec] 192// will fall back to [Execer]; if the Conn does not implement Execer either, 193// [database/sql.DB.Exec] will first prepare a query, execute the statement, and then 194// close the statement. 195// 196// ExecContext may return [ErrSkip]. 197// 198// ExecContext must honor the context timeout and return when the context is canceled. 199type ExecerContext interface { 200 ExecContext(ctx context.Context, query string, args []NamedValue) (Result, error) 201} 202 203// Queryer is an optional interface that may be implemented by a [Conn]. 204// 205// If a [Conn] implements neither [QueryerContext] nor [Queryer], 206// the [database/sql.DB.Query] will first prepare a query, execute the statement, 207// and then close the statement. 208// 209// Query may return [ErrSkip]. 210// 211// Deprecated: Drivers should implement [QueryerContext] instead. 212type Queryer interface { 213 Query(query string, args []Value) (Rows, error) 214} 215 216// QueryerContext is an optional interface that may be implemented by a [Conn]. 217// 218// If a [Conn] does not implement QueryerContext, the [database/sql.DB.Query] 219// will fall back to [Queryer]; if the [Conn] does not implement [Queryer] either, 220// [database/sql.DB.Query] will first prepare a query, execute the statement, and then 221// close the statement. 222// 223// QueryContext may return [ErrSkip]. 224// 225// QueryContext must honor the context timeout and return when the context is canceled. 226type QueryerContext interface { 227 QueryContext(ctx context.Context, query string, args []NamedValue) (Rows, error) 228} 229 230// Conn is a connection to a database. It is not used concurrently 231// by multiple goroutines. 232// 233// Conn is assumed to be stateful. 234type Conn interface { 235 // Prepare returns a prepared statement, bound to this connection. 236 Prepare(query string) (Stmt, error) 237 238 // Close invalidates and potentially stops any current 239 // prepared statements and transactions, marking this 240 // connection as no longer in use. 241 // 242 // Because the sql package maintains a free pool of 243 // connections and only calls Close when there's a surplus of 244 // idle connections, it shouldn't be necessary for drivers to 245 // do their own connection caching. 246 // 247 // Drivers must ensure all network calls made by Close 248 // do not block indefinitely (e.g. apply a timeout). 249 Close() error 250 251 // Begin starts and returns a new transaction. 252 // 253 // Deprecated: Drivers should implement ConnBeginTx instead (or additionally). 254 Begin() (Tx, error) 255} 256 257// ConnPrepareContext enhances the [Conn] interface with context. 258type ConnPrepareContext interface { 259 // PrepareContext returns a prepared statement, bound to this connection. 260 // context is for the preparation of the statement, 261 // it must not store the context within the statement itself. 262 PrepareContext(ctx context.Context, query string) (Stmt, error) 263} 264 265// IsolationLevel is the transaction isolation level stored in [TxOptions]. 266// 267// This type should be considered identical to [database/sql.IsolationLevel] along 268// with any values defined on it. 269type IsolationLevel int 270 271// TxOptions holds the transaction options. 272// 273// This type should be considered identical to [database/sql.TxOptions]. 274type TxOptions struct { 275 Isolation IsolationLevel 276 ReadOnly bool 277} 278 279// ConnBeginTx enhances the [Conn] interface with context and [TxOptions]. 280type ConnBeginTx interface { 281 // BeginTx starts and returns a new transaction. 282 // If the context is canceled by the user the sql package will 283 // call Tx.Rollback before discarding and closing the connection. 284 // 285 // This must check opts.Isolation to determine if there is a set 286 // isolation level. If the driver does not support a non-default 287 // level and one is set or if there is a non-default isolation level 288 // that is not supported, an error must be returned. 289 // 290 // This must also check opts.ReadOnly to determine if the read-only 291 // value is true to either set the read-only transaction property if supported 292 // or return an error if it is not supported. 293 BeginTx(ctx context.Context, opts TxOptions) (Tx, error) 294} 295 296// SessionResetter may be implemented by [Conn] to allow drivers to reset the 297// session state associated with the connection and to signal a bad connection. 298type SessionResetter interface { 299 // ResetSession is called prior to executing a query on the connection 300 // if the connection has been used before. If the driver returns ErrBadConn 301 // the connection is discarded. 302 ResetSession(ctx context.Context) error 303} 304 305// Validator may be implemented by [Conn] to allow drivers to 306// signal if a connection is valid or if it should be discarded. 307// 308// If implemented, drivers may return the underlying error from queries, 309// even if the connection should be discarded by the connection pool. 310type Validator interface { 311 // IsValid is called prior to placing the connection into the 312 // connection pool. The connection will be discarded if false is returned. 313 IsValid() bool 314} 315 316// Result is the result of a query execution. 317type Result interface { 318 // LastInsertId returns the database's auto-generated ID 319 // after, for example, an INSERT into a table with primary 320 // key. 321 LastInsertId() (int64, error) 322 323 // RowsAffected returns the number of rows affected by the 324 // query. 325 RowsAffected() (int64, error) 326} 327 328// Stmt is a prepared statement. It is bound to a [Conn] and not 329// used by multiple goroutines concurrently. 330type Stmt interface { 331 // Close closes the statement. 332 // 333 // As of Go 1.1, a Stmt will not be closed if it's in use 334 // by any queries. 335 // 336 // Drivers must ensure all network calls made by Close 337 // do not block indefinitely (e.g. apply a timeout). 338 Close() error 339 340 // NumInput returns the number of placeholder parameters. 341 // 342 // If NumInput returns >= 0, the sql package will sanity check 343 // argument counts from callers and return errors to the caller 344 // before the statement's Exec or Query methods are called. 345 // 346 // NumInput may also return -1, if the driver doesn't know 347 // its number of placeholders. In that case, the sql package 348 // will not sanity check Exec or Query argument counts. 349 NumInput() int 350 351 // Exec executes a query that doesn't return rows, such 352 // as an INSERT or UPDATE. 353 // 354 // Deprecated: Drivers should implement StmtExecContext instead (or additionally). 355 Exec(args []Value) (Result, error) 356 357 // Query executes a query that may return rows, such as a 358 // SELECT. 359 // 360 // Deprecated: Drivers should implement StmtQueryContext instead (or additionally). 361 Query(args []Value) (Rows, error) 362} 363 364// StmtExecContext enhances the [Stmt] interface by providing Exec with context. 365type StmtExecContext interface { 366 // ExecContext executes a query that doesn't return rows, such 367 // as an INSERT or UPDATE. 368 // 369 // ExecContext must honor the context timeout and return when it is canceled. 370 ExecContext(ctx context.Context, args []NamedValue) (Result, error) 371} 372 373// StmtQueryContext enhances the [Stmt] interface by providing Query with context. 374type StmtQueryContext interface { 375 // QueryContext executes a query that may return rows, such as a 376 // SELECT. 377 // 378 // QueryContext must honor the context timeout and return when it is canceled. 379 QueryContext(ctx context.Context, args []NamedValue) (Rows, error) 380} 381 382// ErrRemoveArgument may be returned from [NamedValueChecker] to instruct the 383// [database/sql] package to not pass the argument to the driver query interface. 384// Return when accepting query specific options or structures that aren't 385// SQL query arguments. 386var ErrRemoveArgument = errors.New("driver: remove argument from query") 387 388// NamedValueChecker may be optionally implemented by [Conn] or [Stmt]. It provides 389// the driver more control to handle Go and database types beyond the default 390// [Value] types allowed. 391// 392// The [database/sql] package checks for value checkers in the following order, 393// stopping at the first found match: Stmt.NamedValueChecker, Conn.NamedValueChecker, 394// Stmt.ColumnConverter, [DefaultParameterConverter]. 395// 396// If CheckNamedValue returns [ErrRemoveArgument], the [NamedValue] will not be included in 397// the final query arguments. This may be used to pass special options to 398// the query itself. 399// 400// If [ErrSkip] is returned the column converter error checking 401// path is used for the argument. Drivers may wish to return [ErrSkip] after 402// they have exhausted their own special cases. 403type NamedValueChecker interface { 404 // CheckNamedValue is called before passing arguments to the driver 405 // and is called in place of any ColumnConverter. CheckNamedValue must do type 406 // validation and conversion as appropriate for the driver. 407 CheckNamedValue(*NamedValue) error 408} 409 410// ColumnConverter may be optionally implemented by [Stmt] if the 411// statement is aware of its own columns' types and can convert from 412// any type to a driver [Value]. 413// 414// Deprecated: Drivers should implement [NamedValueChecker]. 415type ColumnConverter interface { 416 // ColumnConverter returns a ValueConverter for the provided 417 // column index. If the type of a specific column isn't known 418 // or shouldn't be handled specially, [DefaultParameterConverter] 419 // can be returned. 420 ColumnConverter(idx int) ValueConverter 421} 422 423// Rows is an iterator over an executed query's results. 424type Rows interface { 425 // Columns returns the names of the columns. The number of 426 // columns of the result is inferred from the length of the 427 // slice. If a particular column name isn't known, an empty 428 // string should be returned for that entry. 429 Columns() []string 430 431 // Close closes the rows iterator. 432 Close() error 433 434 // Next is called to populate the next row of data into 435 // the provided slice. The provided slice will be the same 436 // size as the Columns() are wide. 437 // 438 // Next should return io.EOF when there are no more rows. 439 // 440 // The dest should not be written to outside of Next. Care 441 // should be taken when closing Rows not to modify 442 // a buffer held in dest. 443 Next(dest []Value) error 444} 445 446// RowsNextResultSet extends the [Rows] interface by providing a way to signal 447// the driver to advance to the next result set. 448type RowsNextResultSet interface { 449 Rows 450 451 // HasNextResultSet is called at the end of the current result set and 452 // reports whether there is another result set after the current one. 453 HasNextResultSet() bool 454 455 // NextResultSet advances the driver to the next result set even 456 // if there are remaining rows in the current result set. 457 // 458 // NextResultSet should return io.EOF when there are no more result sets. 459 NextResultSet() error 460} 461 462// RowsColumnTypeScanType may be implemented by [Rows]. It should return 463// the value type that can be used to scan types into. For example, the database 464// column type "bigint" this should return "[reflect.TypeOf](int64(0))". 465type RowsColumnTypeScanType interface { 466 Rows 467 ColumnTypeScanType(index int) reflect.Type 468} 469 470// RowsColumnTypeDatabaseTypeName may be implemented by [Rows]. It should return the 471// database system type name without the length. Type names should be uppercase. 472// Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2", "CHAR", "TEXT", 473// "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT", "JSONB", "XML", 474// "TIMESTAMP". 475type RowsColumnTypeDatabaseTypeName interface { 476 Rows 477 ColumnTypeDatabaseTypeName(index int) string 478} 479 480// RowsColumnTypeLength may be implemented by [Rows]. It should return the length 481// of the column type if the column is a variable length type. If the column is 482// not a variable length type ok should return false. 483// If length is not limited other than system limits, it should return [math.MaxInt64]. 484// The following are examples of returned values for various types: 485// 486// TEXT (math.MaxInt64, true) 487// varchar(10) (10, true) 488// nvarchar(10) (10, true) 489// decimal (0, false) 490// int (0, false) 491// bytea(30) (30, true) 492type RowsColumnTypeLength interface { 493 Rows 494 ColumnTypeLength(index int) (length int64, ok bool) 495} 496 497// RowsColumnTypeNullable may be implemented by [Rows]. The nullable value should 498// be true if it is known the column may be null, or false if the column is known 499// to be not nullable. 500// If the column nullability is unknown, ok should be false. 501type RowsColumnTypeNullable interface { 502 Rows 503 ColumnTypeNullable(index int) (nullable, ok bool) 504} 505 506// RowsColumnTypePrecisionScale may be implemented by [Rows]. It should return 507// the precision and scale for decimal types. If not applicable, ok should be false. 508// The following are examples of returned values for various types: 509// 510// decimal(38, 4) (38, 4, true) 511// int (0, 0, false) 512// decimal (math.MaxInt64, math.MaxInt64, true) 513type RowsColumnTypePrecisionScale interface { 514 Rows 515 ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) 516} 517 518// Tx is a transaction. 519type Tx interface { 520 Commit() error 521 Rollback() error 522} 523 524// RowsAffected implements [Result] for an INSERT or UPDATE operation 525// which mutates a number of rows. 526type RowsAffected int64 527 528var _ Result = RowsAffected(0) 529 530func (RowsAffected) LastInsertId() (int64, error) { 531 return 0, errors.New("LastInsertId is not supported by this driver") 532} 533 534func (v RowsAffected) RowsAffected() (int64, error) { 535 return int64(v), nil 536} 537 538// ResultNoRows is a pre-defined [Result] for drivers to return when a DDL 539// command (such as a CREATE TABLE) succeeds. It returns an error for both 540// LastInsertId and [RowsAffected]. 541var ResultNoRows noRows 542 543type noRows struct{} 544 545var _ Result = noRows{} 546 547func (noRows) LastInsertId() (int64, error) { 548 return 0, errors.New("no LastInsertId available after DDL statement") 549} 550 551func (noRows) RowsAffected() (int64, error) { 552 return 0, errors.New("no RowsAffected available after DDL statement") 553} 554