1932 lines · 49.0 KB · Go
RawDownload
// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file. // Package sql provides a generic interface around SQL (or SQL-like)// databases.//// The sql package must be used in conjunction with a database driver.// See https://golang.org/s/sqldrivers for a list of drivers.//// For more usage examples, see the wiki page at// https://golang.org/s/sqlwiki.package sql import (	"database/sql/driver"	"errors"	"fmt"	"io"	"runtime"	"sort"	"sync"	"sync/atomic"	"time") var (	driversMu sync.RWMutex	drivers   = make(map[string]driver.Driver)) // nowFunc returns the current time; it's overridden in tests.var nowFunc = time.Now // Register makes a database driver available by the provided name.// If Register is called twice with the same name or if driver is nil,// it panics.func Register(name string, driver driver.Driver) {	driversMu.Lock()	defer driversMu.Unlock()	if driver == nil {		panic("sql: Register driver is nil")	}	if _, dup := drivers[name]; dup {		panic("sql: Register called twice for driver " + name)	}	drivers[name] = driver} func unregisterAllDrivers() {	driversMu.Lock()	defer driversMu.Unlock()	// For tests.	drivers = make(map[string]driver.Driver)} // Drivers returns a sorted list of the names of the registered drivers.func Drivers() []string {	driversMu.RLock()	defer driversMu.RUnlock()	var list []string	for name := range drivers {		list = append(list, name)	}	sort.Strings(list)	return list} // RawBytes is a byte slice that holds a reference to memory owned by// the database itself. After a Scan into a RawBytes, the slice is only// valid until the next call to Next, Scan, or Close.type RawBytes []byte // NullString represents a string that may be null.// NullString implements the Scanner interface so// it can be used as a scan destination:////  var s NullString//  err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)//  ...//  if s.Valid {//     // use s.String//  } else {//     // NULL value//  }//type NullString struct {	String string	Valid  bool // Valid is true if String is not NULL} // Scan implements the Scanner interface.func (ns *NullString) Scan(value interface{}) error {	if value == nil {		ns.String, ns.Valid = "", false		return nil	}	ns.Valid = true	return convertAssign(&ns.String, value)} // Value implements the driver Valuer interface.func (ns NullString) Value() (driver.Value, error) {	if !ns.Valid {		return nil, nil	}	return ns.String, nil} // NullInt64 represents an int64 that may be null.// NullInt64 implements the Scanner interface so// it can be used as a scan destination, similar to NullString.type NullInt64 struct {	Int64 int64	Valid bool // Valid is true if Int64 is not NULL} // Scan implements the Scanner interface.func (n *NullInt64) Scan(value interface{}) error {	if value == nil {		n.Int64, n.Valid = 0, false		return nil	}	n.Valid = true	return convertAssign(&n.Int64, value)} // Value implements the driver Valuer interface.func (n NullInt64) Value() (driver.Value, error) {	if !n.Valid {		return nil, nil	}	return n.Int64, nil} // NullFloat64 represents a float64 that may be null.// NullFloat64 implements the Scanner interface so// it can be used as a scan destination, similar to NullString.type NullFloat64 struct {	Float64 float64	Valid   bool // Valid is true if Float64 is not NULL} // Scan implements the Scanner interface.func (n *NullFloat64) Scan(value interface{}) error {	if value == nil {		n.Float64, n.Valid = 0, false		return nil	}	n.Valid = true	return convertAssign(&n.Float64, value)} // Value implements the driver Valuer interface.func (n NullFloat64) Value() (driver.Value, error) {	if !n.Valid {		return nil, nil	}	return n.Float64, nil} // NullBool represents a bool that may be null.// NullBool implements the Scanner interface so// it can be used as a scan destination, similar to NullString.type NullBool struct {	Bool  bool	Valid bool // Valid is true if Bool is not NULL} // Scan implements the Scanner interface.func (n *NullBool) Scan(value interface{}) error {	if value == nil {		n.Bool, n.Valid = false, false		return nil	}	n.Valid = true	return convertAssign(&n.Bool, value)} // Value implements the driver Valuer interface.func (n NullBool) Value() (driver.Value, error) {	if !n.Valid {		return nil, nil	}	return n.Bool, nil} // Scanner is an interface used by Scan.type Scanner interface {	// Scan assigns a value from a database driver.	//	// The src value will be of one of the following restricted	// set of types:	//	//    int64	//    float64	//    bool	//    []byte	//    string	//    time.Time	//    nil - for NULL values	//	// An error should be returned if the value can not be stored	// without loss of information.	Scan(src interface{}) error} // ErrNoRows is returned by Scan when QueryRow doesn't return a// row. In such a case, QueryRow returns a placeholder *Row value that// defers this error until a Scan.var ErrNoRows = errors.New("sql: no rows in result set") // DB is a database handle representing a pool of zero or more// underlying connections. It's safe for concurrent use by multiple// goroutines.//// The sql package creates and frees connections automatically; it// also maintains a free pool of idle connections. If the database has// a concept of per-connection state, such state can only be reliably// observed within a transaction. Once DB.Begin is called, the// returned Tx is bound to a single connection. Once Commit or// Rollback is called on the transaction, that transaction's// connection is returned to DB's idle connection pool. The pool size// can be controlled with SetMaxIdleConns.type DB struct {	driver driver.Driver	dsn    string	// numClosed is an atomic counter which represents a total number of	// closed connections. Stmt.openStmt checks it before cleaning closed	// connections in Stmt.css.	numClosed uint64 	mu           sync.Mutex // protects following fields	freeConn     []*driverConn	connRequests []chan connRequest	numOpen      int // number of opened and pending open connections	// Used to signal the need for new connections	// a goroutine running connectionOpener() reads on this chan and	// maybeOpenNewConnections sends on the chan (one send per needed connection)	// It is closed during db.Close(). The close tells the connectionOpener	// goroutine to exit.	openerCh    chan struct{}	closed      bool	dep         map[finalCloser]depSet	lastPut     map[*driverConn]string // stacktrace of last conn's put; debug only	maxIdle     int                    // zero means defaultMaxIdleConns; negative means 0	maxOpen     int                    // <= 0 means unlimited	maxLifetime time.Duration          // maximum amount of time a connection may be reused	cleanerCh   chan struct{}} // connReuseStrategy determines how (*DB).conn returns database connections.type connReuseStrategy uint8 const (	// alwaysNewConn forces a new connection to the database.	alwaysNewConn connReuseStrategy = iota	// cachedOrNewConn returns a cached connection, if available, else waits	// for one to become available (if MaxOpenConns has been reached) or	// creates a new database connection.	cachedOrNewConn) // driverConn wraps a driver.Conn with a mutex, to// be held during all calls into the Conn. (including any calls onto// interfaces returned via that Conn, such as calls on Tx, Stmt,// Result, Rows)type driverConn struct {	db        *DB	createdAt time.Time 	sync.Mutex  // guards following	ci          driver.Conn	closed      bool	finalClosed bool // ci.Close has been called	openStmt    map[driver.Stmt]bool 	// guarded by db.mu	inUse      bool	onPut      []func() // code (with db.mu held) run when conn is next returned	dbmuClosed bool     // same as closed, but guarded by db.mu, for removeClosedStmtLocked} func (dc *driverConn) releaseConn(err error) {	dc.db.putConn(dc, err)} func (dc *driverConn) removeOpenStmt(si driver.Stmt) {	dc.Lock()	defer dc.Unlock()	delete(dc.openStmt, si)} func (dc *driverConn) expired(timeout time.Duration) bool {	if timeout <= 0 {		return false	}	return dc.createdAt.Add(timeout).Before(nowFunc())} func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) {	si, err := dc.ci.Prepare(query)	if err == nil {		// Track each driverConn's open statements, so we can close them		// before closing the conn.		//		// TODO(bradfitz): let drivers opt out of caring about		// stmt closes if the conn is about to close anyway? For now		// do the safe thing, in case stmts need to be closed.		//		// TODO(bradfitz): after Go 1.2, closing driver.Stmts		// should be moved to driverStmt, using unique		// *driverStmts everywhere (including from		// *Stmt.connStmt, instead of returning a		// driver.Stmt), using driverStmt as a pointer		// everywhere, and making it a finalCloser.		if dc.openStmt == nil {			dc.openStmt = make(map[driver.Stmt]bool)		}		dc.openStmt[si] = true	}	return si, err} // the dc.db's Mutex is held.func (dc *driverConn) closeDBLocked() func() error {	dc.Lock()	defer dc.Unlock()	if dc.closed {		return func() error { return errors.New("sql: duplicate driverConn close") }	}	dc.closed = true	return dc.db.removeDepLocked(dc, dc)} func (dc *driverConn) Close() error {	dc.Lock()	if dc.closed {		dc.Unlock()		return errors.New("sql: duplicate driverConn close")	}	dc.closed = true	dc.Unlock() // not defer; removeDep finalClose calls may need to lock 	// And now updates that require holding dc.mu.Lock.	dc.db.mu.Lock()	dc.dbmuClosed = true	fn := dc.db.removeDepLocked(dc, dc)	dc.db.mu.Unlock()	return fn()} func (dc *driverConn) finalClose() error {	dc.Lock() 	for si := range dc.openStmt {		si.Close()	}	dc.openStmt = nil 	err := dc.ci.Close()	dc.ci = nil	dc.finalClosed = true	dc.Unlock() 	dc.db.mu.Lock()	dc.db.numOpen--	dc.db.maybeOpenNewConnections()	dc.db.mu.Unlock() 	atomic.AddUint64(&dc.db.numClosed, 1)	return err} // driverStmt associates a driver.Stmt with the// *driverConn from which it came, so the driverConn's lock can be// held during calls.type driverStmt struct {	sync.Locker // the *driverConn	si          driver.Stmt} func (ds *driverStmt) Close() error {	ds.Lock()	defer ds.Unlock()	return ds.si.Close()} // depSet is a finalCloser's outstanding dependenciestype depSet map[interface{}]bool // set of true bools // The finalCloser interface is used by (*DB).addDep and related// dependency reference counting.type finalCloser interface {	// finalClose is called when the reference count of an object	// goes to zero. (*DB).mu is not held while calling it.	finalClose() error} // addDep notes that x now depends on dep, and x's finalClose won't be// called until all of x's dependencies are removed with removeDep.func (db *DB) addDep(x finalCloser, dep interface{}) {	//println(fmt.Sprintf("addDep(%T %p, %T %p)", x, x, dep, dep))	db.mu.Lock()	defer db.mu.Unlock()	db.addDepLocked(x, dep)} func (db *DB) addDepLocked(x finalCloser, dep interface{}) {	if db.dep == nil {		db.dep = make(map[finalCloser]depSet)	}	xdep := db.dep[x]	if xdep == nil {		xdep = make(depSet)		db.dep[x] = xdep	}	xdep[dep] = true} // removeDep notes that x no longer depends on dep.// If x still has dependencies, nil is returned.// If x no longer has any dependencies, its finalClose method will be// called and its error value will be returned.func (db *DB) removeDep(x finalCloser, dep interface{}) error {	db.mu.Lock()	fn := db.removeDepLocked(x, dep)	db.mu.Unlock()	return fn()} func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error {	//println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep)) 	xdep, ok := db.dep[x]	if !ok {		panic(fmt.Sprintf("unpaired removeDep: no deps for %T", x))	} 	l0 := len(xdep)	delete(xdep, dep) 	switch len(xdep) {	case l0:		// Nothing removed. Shouldn't happen.		panic(fmt.Sprintf("unpaired removeDep: no %T dep on %T", dep, x))	case 0:		// No more dependencies.		delete(db.dep, x)		return x.finalClose	default:		// Dependencies remain.		return func() error { return nil }	}} // This is the size of the connectionOpener request chan (DB.openerCh).// This value should be larger than the maximum typical value// used for db.maxOpen. If maxOpen is significantly larger than// connectionRequestQueueSize then it is possible for ALL calls into the *DB// to block until the connectionOpener can satisfy the backlog of requests.var connectionRequestQueueSize = 1000000 // Open opens a database specified by its database driver name and a// driver-specific data source name, usually consisting of at least a// database name and connection information.//// Most users will open a database via a driver-specific connection// helper function that returns a *DB. No database drivers are included// in the Go standard library. See https://golang.org/s/sqldrivers for// a list of third-party drivers.//// Open may just validate its arguments without creating a connection// to the database. To verify that the data source name is valid, call// Ping.//// The returned DB is safe for concurrent use by multiple goroutines// and maintains its own pool of idle connections. Thus, the Open// function should be called just once. It is rarely necessary to// close a DB.func Open(driverName, dataSourceName string) (*DB, error) {	driversMu.RLock()	driveri, ok := drivers[driverName]	driversMu.RUnlock()	if !ok {		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)	}	db := &DB{		driver:   driveri,		dsn:      dataSourceName,		openerCh: make(chan struct{}, connectionRequestQueueSize),		lastPut:  make(map[*driverConn]string),	}	go db.connectionOpener()	return db, nil} // Ping verifies a connection to the database is still alive,// establishing a connection if necessary.func (db *DB) Ping() error {

Lines 1–500 of 1932.