1046 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1046 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package sqlx
 | |
| 
 | |
| import (
 | |
| 	"database/sql"
 | |
| 	"database/sql/driver"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 
 | |
| 	"io/ioutil"
 | |
| 	"path/filepath"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 
 | |
| 	"github.com/jmoiron/sqlx/reflectx"
 | |
| )
 | |
| 
 | |
| // Although the NameMapper is convenient, in practice it should not
 | |
| // be relied on except for application code.  If you are writing a library
 | |
| // that uses sqlx, you should be aware that the name mappings you expect
 | |
| // can be overridden by your user's application.
 | |
| 
 | |
| // NameMapper is used to map column names to struct field names.  By default,
 | |
| // it uses strings.ToLower to lowercase struct field names.  It can be set
 | |
| // to whatever you want, but it is encouraged to be set before sqlx is used
 | |
| // as name-to-field mappings are cached after first use on a type.
 | |
| var NameMapper = strings.ToLower
 | |
| var origMapper = reflect.ValueOf(NameMapper)
 | |
| 
 | |
| // Rather than creating on init, this is created when necessary so that
 | |
| // importers have time to customize the NameMapper.
 | |
| var mpr *reflectx.Mapper
 | |
| 
 | |
| // mprMu protects mpr.
 | |
| var mprMu sync.Mutex
 | |
| 
 | |
| // mapper returns a valid mapper using the configured NameMapper func.
 | |
| func mapper() *reflectx.Mapper {
 | |
| 	mprMu.Lock()
 | |
| 	defer mprMu.Unlock()
 | |
| 
 | |
| 	if mpr == nil {
 | |
| 		mpr = reflectx.NewMapperFunc("db", NameMapper)
 | |
| 	} else if origMapper != reflect.ValueOf(NameMapper) {
 | |
| 		// if NameMapper has changed, create a new mapper
 | |
| 		mpr = reflectx.NewMapperFunc("db", NameMapper)
 | |
| 		origMapper = reflect.ValueOf(NameMapper)
 | |
| 	}
 | |
| 	return mpr
 | |
| }
 | |
| 
 | |
| // isScannable takes the reflect.Type and the actual dest value and returns
 | |
| // whether or not it's Scannable.  Something is scannable if:
 | |
| //   * it is not a struct
 | |
| //   * it implements sql.Scanner
 | |
| //   * it has no exported fields
 | |
| func isScannable(t reflect.Type) bool {
 | |
| 	if reflect.PtrTo(t).Implements(_scannerInterface) {
 | |
| 		return true
 | |
| 	}
 | |
| 	if t.Kind() != reflect.Struct {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	// it's not important that we use the right mapper for this particular object,
 | |
| 	// we're only concerned on how many exported fields this struct has
 | |
| 	m := mapper()
 | |
| 	if len(m.TypeMap(t).Index) == 0 {
 | |
| 		return true
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // ColScanner is an interface used by MapScan and SliceScan
 | |
| type ColScanner interface {
 | |
| 	Columns() ([]string, error)
 | |
| 	Scan(dest ...interface{}) error
 | |
| 	Err() error
 | |
| }
 | |
| 
 | |
| // Queryer is an interface used by Get and Select
 | |
| type Queryer interface {
 | |
| 	Query(query string, args ...interface{}) (*sql.Rows, error)
 | |
| 	Queryx(query string, args ...interface{}) (*Rows, error)
 | |
| 	QueryRowx(query string, args ...interface{}) *Row
 | |
| }
 | |
| 
 | |
| // Execer is an interface used by MustExec and LoadFile
 | |
| type Execer interface {
 | |
| 	Exec(query string, args ...interface{}) (sql.Result, error)
 | |
| }
 | |
| 
 | |
| // Binder is an interface for something which can bind queries (Tx, DB)
 | |
| type binder interface {
 | |
| 	DriverName() string
 | |
| 	Rebind(string) string
 | |
| 	BindNamed(string, interface{}) (string, []interface{}, error)
 | |
| }
 | |
| 
 | |
| // Ext is a union interface which can bind, query, and exec, used by
 | |
| // NamedQuery and NamedExec.
 | |
| type Ext interface {
 | |
| 	binder
 | |
| 	Queryer
 | |
| 	Execer
 | |
| }
 | |
| 
 | |
| // Preparer is an interface used by Preparex.
 | |
| type Preparer interface {
 | |
| 	Prepare(query string) (*sql.Stmt, error)
 | |
| }
 | |
| 
 | |
| // determine if any of our extensions are unsafe
 | |
| func isUnsafe(i interface{}) bool {
 | |
| 	switch v := i.(type) {
 | |
| 	case Row:
 | |
| 		return v.unsafe
 | |
| 	case *Row:
 | |
| 		return v.unsafe
 | |
| 	case Rows:
 | |
| 		return v.unsafe
 | |
| 	case *Rows:
 | |
| 		return v.unsafe
 | |
| 	case NamedStmt:
 | |
| 		return v.Stmt.unsafe
 | |
| 	case *NamedStmt:
 | |
| 		return v.Stmt.unsafe
 | |
| 	case Stmt:
 | |
| 		return v.unsafe
 | |
| 	case *Stmt:
 | |
| 		return v.unsafe
 | |
| 	case qStmt:
 | |
| 		return v.unsafe
 | |
| 	case *qStmt:
 | |
| 		return v.unsafe
 | |
| 	case DB:
 | |
| 		return v.unsafe
 | |
| 	case *DB:
 | |
| 		return v.unsafe
 | |
| 	case Tx:
 | |
| 		return v.unsafe
 | |
| 	case *Tx:
 | |
| 		return v.unsafe
 | |
| 	case sql.Rows, *sql.Rows:
 | |
| 		return false
 | |
| 	default:
 | |
| 		return false
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func mapperFor(i interface{}) *reflectx.Mapper {
 | |
| 	switch i.(type) {
 | |
| 	case DB:
 | |
| 		return i.(DB).Mapper
 | |
| 	case *DB:
 | |
| 		return i.(*DB).Mapper
 | |
| 	case Tx:
 | |
| 		return i.(Tx).Mapper
 | |
| 	case *Tx:
 | |
| 		return i.(*Tx).Mapper
 | |
| 	default:
 | |
| 		return mapper()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var _scannerInterface = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
 | |
| var _valuerInterface = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
 | |
| 
 | |
| // Row is a reimplementation of sql.Row in order to gain access to the underlying
 | |
| // sql.Rows.Columns() data, necessary for StructScan.
 | |
| type Row struct {
 | |
| 	err    error
 | |
| 	unsafe bool
 | |
| 	rows   *sql.Rows
 | |
| 	Mapper *reflectx.Mapper
 | |
| }
 | |
| 
 | |
| // Scan is a fixed implementation of sql.Row.Scan, which does not discard the
 | |
| // underlying error from the internal rows object if it exists.
 | |
| func (r *Row) Scan(dest ...interface{}) error {
 | |
| 	if r.err != nil {
 | |
| 		return r.err
 | |
| 	}
 | |
| 
 | |
| 	// TODO(bradfitz): for now we need to defensively clone all
 | |
| 	// []byte that the driver returned (not permitting
 | |
| 	// *RawBytes in Rows.Scan), since we're about to close
 | |
| 	// the Rows in our defer, when we return from this function.
 | |
| 	// the contract with the driver.Next(...) interface is that it
 | |
| 	// can return slices into read-only temporary memory that's
 | |
| 	// only valid until the next Scan/Close.  But the TODO is that
 | |
| 	// for a lot of drivers, this copy will be unnecessary.  We
 | |
| 	// should provide an optional interface for drivers to
 | |
| 	// implement to say, "don't worry, the []bytes that I return
 | |
| 	// from Next will not be modified again." (for instance, if
 | |
| 	// they were obtained from the network anyway) But for now we
 | |
| 	// don't care.
 | |
| 	defer r.rows.Close()
 | |
| 	for _, dp := range dest {
 | |
| 		if _, ok := dp.(*sql.RawBytes); ok {
 | |
| 			return errors.New("sql: RawBytes isn't allowed on Row.Scan")
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !r.rows.Next() {
 | |
| 		if err := r.rows.Err(); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		return sql.ErrNoRows
 | |
| 	}
 | |
| 	err := r.rows.Scan(dest...)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	// Make sure the query can be processed to completion with no errors.
 | |
| 	if err := r.rows.Close(); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Columns returns the underlying sql.Rows.Columns(), or the deferred error usually
 | |
| // returned by Row.Scan()
 | |
| func (r *Row) Columns() ([]string, error) {
 | |
| 	if r.err != nil {
 | |
| 		return []string{}, r.err
 | |
| 	}
 | |
| 	return r.rows.Columns()
 | |
| }
 | |
| 
 | |
| // ColumnTypes returns the underlying sql.Rows.ColumnTypes(), or the deferred error
 | |
| func (r *Row) ColumnTypes() ([]*sql.ColumnType, error) {
 | |
| 	if r.err != nil {
 | |
| 		return []*sql.ColumnType{}, r.err
 | |
| 	}
 | |
| 	return r.rows.ColumnTypes()
 | |
| }
 | |
| 
 | |
| // Err returns the error encountered while scanning.
 | |
| func (r *Row) Err() error {
 | |
| 	return r.err
 | |
| }
 | |
| 
 | |
| // DB is a wrapper around sql.DB which keeps track of the driverName upon Open,
 | |
| // used mostly to automatically bind named queries using the right bindvars.
 | |
| type DB struct {
 | |
| 	*sql.DB
 | |
| 	driverName string
 | |
| 	unsafe     bool
 | |
| 	Mapper     *reflectx.Mapper
 | |
| }
 | |
| 
 | |
| // NewDb returns a new sqlx DB wrapper for a pre-existing *sql.DB.  The
 | |
| // driverName of the original database is required for named query support.
 | |
| func NewDb(db *sql.DB, driverName string) *DB {
 | |
| 	return &DB{DB: db, driverName: driverName, Mapper: mapper()}
 | |
| }
 | |
| 
 | |
| // DriverName returns the driverName passed to the Open function for this DB.
 | |
| func (db *DB) DriverName() string {
 | |
| 	return db.driverName
 | |
| }
 | |
| 
 | |
| // Open is the same as sql.Open, but returns an *sqlx.DB instead.
 | |
| func Open(driverName, dataSourceName string) (*DB, error) {
 | |
| 	db, err := sql.Open(driverName, dataSourceName)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &DB{DB: db, driverName: driverName, Mapper: mapper()}, err
 | |
| }
 | |
| 
 | |
| // MustOpen is the same as sql.Open, but returns an *sqlx.DB instead and panics on error.
 | |
| func MustOpen(driverName, dataSourceName string) *DB {
 | |
| 	db, err := Open(driverName, dataSourceName)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	return db
 | |
| }
 | |
| 
 | |
| // MapperFunc sets a new mapper for this db using the default sqlx struct tag
 | |
| // and the provided mapper function.
 | |
| func (db *DB) MapperFunc(mf func(string) string) {
 | |
| 	db.Mapper = reflectx.NewMapperFunc("db", mf)
 | |
| }
 | |
| 
 | |
| // Rebind transforms a query from QUESTION to the DB driver's bindvar type.
 | |
| func (db *DB) Rebind(query string) string {
 | |
| 	return Rebind(BindType(db.driverName), query)
 | |
| }
 | |
| 
 | |
| // Unsafe returns a version of DB which will silently succeed to scan when
 | |
| // columns in the SQL result have no fields in the destination struct.
 | |
| // sqlx.Stmt and sqlx.Tx which are created from this DB will inherit its
 | |
| // safety behavior.
 | |
| func (db *DB) Unsafe() *DB {
 | |
| 	return &DB{DB: db.DB, driverName: db.driverName, unsafe: true, Mapper: db.Mapper}
 | |
| }
 | |
| 
 | |
| // BindNamed binds a query using the DB driver's bindvar type.
 | |
| func (db *DB) BindNamed(query string, arg interface{}) (string, []interface{}, error) {
 | |
| 	return bindNamedMapper(BindType(db.driverName), query, arg, db.Mapper)
 | |
| }
 | |
| 
 | |
| // NamedQuery using this DB.
 | |
| // Any named placeholder parameters are replaced with fields from arg.
 | |
| func (db *DB) NamedQuery(query string, arg interface{}) (*Rows, error) {
 | |
| 	return NamedQuery(db, query, arg)
 | |
| }
 | |
| 
 | |
| // NamedExec using this DB.
 | |
| // Any named placeholder parameters are replaced with fields from arg.
 | |
| func (db *DB) NamedExec(query string, arg interface{}) (sql.Result, error) {
 | |
| 	return NamedExec(db, query, arg)
 | |
| }
 | |
| 
 | |
| // Select using this DB.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (db *DB) Select(dest interface{}, query string, args ...interface{}) error {
 | |
| 	return Select(db, dest, query, args...)
 | |
| }
 | |
| 
 | |
| // Get using this DB.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| // An error is returned if the result set is empty.
 | |
| func (db *DB) Get(dest interface{}, query string, args ...interface{}) error {
 | |
| 	return Get(db, dest, query, args...)
 | |
| }
 | |
| 
 | |
| // MustBegin starts a transaction, and panics on error.  Returns an *sqlx.Tx instead
 | |
| // of an *sql.Tx.
 | |
| func (db *DB) MustBegin() *Tx {
 | |
| 	tx, err := db.Beginx()
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	return tx
 | |
| }
 | |
| 
 | |
| // Beginx begins a transaction and returns an *sqlx.Tx instead of an *sql.Tx.
 | |
| func (db *DB) Beginx() (*Tx, error) {
 | |
| 	tx, err := db.DB.Begin()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &Tx{Tx: tx, driverName: db.driverName, unsafe: db.unsafe, Mapper: db.Mapper}, err
 | |
| }
 | |
| 
 | |
| // Queryx queries the database and returns an *sqlx.Rows.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (db *DB) Queryx(query string, args ...interface{}) (*Rows, error) {
 | |
| 	r, err := db.DB.Query(query, args...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &Rows{Rows: r, unsafe: db.unsafe, Mapper: db.Mapper}, err
 | |
| }
 | |
| 
 | |
| // QueryRowx queries the database and returns an *sqlx.Row.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (db *DB) QueryRowx(query string, args ...interface{}) *Row {
 | |
| 	rows, err := db.DB.Query(query, args...)
 | |
| 	return &Row{rows: rows, err: err, unsafe: db.unsafe, Mapper: db.Mapper}
 | |
| }
 | |
| 
 | |
| // MustExec (panic) runs MustExec using this database.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (db *DB) MustExec(query string, args ...interface{}) sql.Result {
 | |
| 	return MustExec(db, query, args...)
 | |
| }
 | |
| 
 | |
| // Preparex returns an sqlx.Stmt instead of a sql.Stmt
 | |
| func (db *DB) Preparex(query string) (*Stmt, error) {
 | |
| 	return Preparex(db, query)
 | |
| }
 | |
| 
 | |
| // PrepareNamed returns an sqlx.NamedStmt
 | |
| func (db *DB) PrepareNamed(query string) (*NamedStmt, error) {
 | |
| 	return prepareNamed(db, query)
 | |
| }
 | |
| 
 | |
| // Tx is an sqlx wrapper around sql.Tx with extra functionality
 | |
| type Tx struct {
 | |
| 	*sql.Tx
 | |
| 	driverName string
 | |
| 	unsafe     bool
 | |
| 	Mapper     *reflectx.Mapper
 | |
| }
 | |
| 
 | |
| // DriverName returns the driverName used by the DB which began this transaction.
 | |
| func (tx *Tx) DriverName() string {
 | |
| 	return tx.driverName
 | |
| }
 | |
| 
 | |
| // Rebind a query within a transaction's bindvar type.
 | |
| func (tx *Tx) Rebind(query string) string {
 | |
| 	return Rebind(BindType(tx.driverName), query)
 | |
| }
 | |
| 
 | |
| // Unsafe returns a version of Tx which will silently succeed to scan when
 | |
| // columns in the SQL result have no fields in the destination struct.
 | |
| func (tx *Tx) Unsafe() *Tx {
 | |
| 	return &Tx{Tx: tx.Tx, driverName: tx.driverName, unsafe: true, Mapper: tx.Mapper}
 | |
| }
 | |
| 
 | |
| // BindNamed binds a query within a transaction's bindvar type.
 | |
| func (tx *Tx) BindNamed(query string, arg interface{}) (string, []interface{}, error) {
 | |
| 	return bindNamedMapper(BindType(tx.driverName), query, arg, tx.Mapper)
 | |
| }
 | |
| 
 | |
| // NamedQuery within a transaction.
 | |
| // Any named placeholder parameters are replaced with fields from arg.
 | |
| func (tx *Tx) NamedQuery(query string, arg interface{}) (*Rows, error) {
 | |
| 	return NamedQuery(tx, query, arg)
 | |
| }
 | |
| 
 | |
| // NamedExec a named query within a transaction.
 | |
| // Any named placeholder parameters are replaced with fields from arg.
 | |
| func (tx *Tx) NamedExec(query string, arg interface{}) (sql.Result, error) {
 | |
| 	return NamedExec(tx, query, arg)
 | |
| }
 | |
| 
 | |
| // Select within a transaction.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (tx *Tx) Select(dest interface{}, query string, args ...interface{}) error {
 | |
| 	return Select(tx, dest, query, args...)
 | |
| }
 | |
| 
 | |
| // Queryx within a transaction.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (tx *Tx) Queryx(query string, args ...interface{}) (*Rows, error) {
 | |
| 	r, err := tx.Tx.Query(query, args...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &Rows{Rows: r, unsafe: tx.unsafe, Mapper: tx.Mapper}, err
 | |
| }
 | |
| 
 | |
| // QueryRowx within a transaction.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (tx *Tx) QueryRowx(query string, args ...interface{}) *Row {
 | |
| 	rows, err := tx.Tx.Query(query, args...)
 | |
| 	return &Row{rows: rows, err: err, unsafe: tx.unsafe, Mapper: tx.Mapper}
 | |
| }
 | |
| 
 | |
| // Get within a transaction.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| // An error is returned if the result set is empty.
 | |
| func (tx *Tx) Get(dest interface{}, query string, args ...interface{}) error {
 | |
| 	return Get(tx, dest, query, args...)
 | |
| }
 | |
| 
 | |
| // MustExec runs MustExec within a transaction.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (tx *Tx) MustExec(query string, args ...interface{}) sql.Result {
 | |
| 	return MustExec(tx, query, args...)
 | |
| }
 | |
| 
 | |
| // Preparex  a statement within a transaction.
 | |
| func (tx *Tx) Preparex(query string) (*Stmt, error) {
 | |
| 	return Preparex(tx, query)
 | |
| }
 | |
| 
 | |
| // Stmtx returns a version of the prepared statement which runs within a transaction.  Provided
 | |
| // stmt can be either *sql.Stmt or *sqlx.Stmt.
 | |
| func (tx *Tx) Stmtx(stmt interface{}) *Stmt {
 | |
| 	var s *sql.Stmt
 | |
| 	switch v := stmt.(type) {
 | |
| 	case Stmt:
 | |
| 		s = v.Stmt
 | |
| 	case *Stmt:
 | |
| 		s = v.Stmt
 | |
| 	case *sql.Stmt:
 | |
| 		s = v
 | |
| 	default:
 | |
| 		panic(fmt.Sprintf("non-statement type %v passed to Stmtx", reflect.ValueOf(stmt).Type()))
 | |
| 	}
 | |
| 	return &Stmt{Stmt: tx.Stmt(s), Mapper: tx.Mapper}
 | |
| }
 | |
| 
 | |
| // NamedStmt returns a version of the prepared statement which runs within a transaction.
 | |
| func (tx *Tx) NamedStmt(stmt *NamedStmt) *NamedStmt {
 | |
| 	return &NamedStmt{
 | |
| 		QueryString: stmt.QueryString,
 | |
| 		Params:      stmt.Params,
 | |
| 		Stmt:        tx.Stmtx(stmt.Stmt),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // PrepareNamed returns an sqlx.NamedStmt
 | |
| func (tx *Tx) PrepareNamed(query string) (*NamedStmt, error) {
 | |
| 	return prepareNamed(tx, query)
 | |
| }
 | |
| 
 | |
| // Stmt is an sqlx wrapper around sql.Stmt with extra functionality
 | |
| type Stmt struct {
 | |
| 	*sql.Stmt
 | |
| 	unsafe bool
 | |
| 	Mapper *reflectx.Mapper
 | |
| }
 | |
| 
 | |
| // Unsafe returns a version of Stmt which will silently succeed to scan when
 | |
| // columns in the SQL result have no fields in the destination struct.
 | |
| func (s *Stmt) Unsafe() *Stmt {
 | |
| 	return &Stmt{Stmt: s.Stmt, unsafe: true, Mapper: s.Mapper}
 | |
| }
 | |
| 
 | |
| // Select using the prepared statement.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (s *Stmt) Select(dest interface{}, args ...interface{}) error {
 | |
| 	return Select(&qStmt{s}, dest, "", args...)
 | |
| }
 | |
| 
 | |
| // Get using the prepared statement.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| // An error is returned if the result set is empty.
 | |
| func (s *Stmt) Get(dest interface{}, args ...interface{}) error {
 | |
| 	return Get(&qStmt{s}, dest, "", args...)
 | |
| }
 | |
| 
 | |
| // MustExec (panic) using this statement.  Note that the query portion of the error
 | |
| // output will be blank, as Stmt does not expose its query.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (s *Stmt) MustExec(args ...interface{}) sql.Result {
 | |
| 	return MustExec(&qStmt{s}, "", args...)
 | |
| }
 | |
| 
 | |
| // QueryRowx using this statement.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (s *Stmt) QueryRowx(args ...interface{}) *Row {
 | |
| 	qs := &qStmt{s}
 | |
| 	return qs.QueryRowx("", args...)
 | |
| }
 | |
| 
 | |
| // Queryx using this statement.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func (s *Stmt) Queryx(args ...interface{}) (*Rows, error) {
 | |
| 	qs := &qStmt{s}
 | |
| 	return qs.Queryx("", args...)
 | |
| }
 | |
| 
 | |
| // qStmt is an unexposed wrapper which lets you use a Stmt as a Queryer & Execer by
 | |
| // implementing those interfaces and ignoring the `query` argument.
 | |
| type qStmt struct{ *Stmt }
 | |
| 
 | |
| func (q *qStmt) Query(query string, args ...interface{}) (*sql.Rows, error) {
 | |
| 	return q.Stmt.Query(args...)
 | |
| }
 | |
| 
 | |
| func (q *qStmt) Queryx(query string, args ...interface{}) (*Rows, error) {
 | |
| 	r, err := q.Stmt.Query(args...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &Rows{Rows: r, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper}, err
 | |
| }
 | |
| 
 | |
| func (q *qStmt) QueryRowx(query string, args ...interface{}) *Row {
 | |
| 	rows, err := q.Stmt.Query(args...)
 | |
| 	return &Row{rows: rows, err: err, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper}
 | |
| }
 | |
| 
 | |
| func (q *qStmt) Exec(query string, args ...interface{}) (sql.Result, error) {
 | |
| 	return q.Stmt.Exec(args...)
 | |
| }
 | |
| 
 | |
| // Rows is a wrapper around sql.Rows which caches costly reflect operations
 | |
| // during a looped StructScan
 | |
| type Rows struct {
 | |
| 	*sql.Rows
 | |
| 	unsafe bool
 | |
| 	Mapper *reflectx.Mapper
 | |
| 	// these fields cache memory use for a rows during iteration w/ structScan
 | |
| 	started bool
 | |
| 	fields  [][]int
 | |
| 	values  []interface{}
 | |
| }
 | |
| 
 | |
| // SliceScan using this Rows.
 | |
| func (r *Rows) SliceScan() ([]interface{}, error) {
 | |
| 	return SliceScan(r)
 | |
| }
 | |
| 
 | |
| // MapScan using this Rows.
 | |
| func (r *Rows) MapScan(dest map[string]interface{}) error {
 | |
| 	return MapScan(r, dest)
 | |
| }
 | |
| 
 | |
| // StructScan is like sql.Rows.Scan, but scans a single Row into a single Struct.
 | |
| // Use this and iterate over Rows manually when the memory load of Select() might be
 | |
| // prohibitive.  *Rows.StructScan caches the reflect work of matching up column
 | |
| // positions to fields to avoid that overhead per scan, which means it is not safe
 | |
| // to run StructScan on the same Rows instance with different struct types.
 | |
| func (r *Rows) StructScan(dest interface{}) error {
 | |
| 	v := reflect.ValueOf(dest)
 | |
| 
 | |
| 	if v.Kind() != reflect.Ptr {
 | |
| 		return errors.New("must pass a pointer, not a value, to StructScan destination")
 | |
| 	}
 | |
| 
 | |
| 	v = v.Elem()
 | |
| 
 | |
| 	if !r.started {
 | |
| 		columns, err := r.Columns()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		m := r.Mapper
 | |
| 
 | |
| 		r.fields = m.TraversalsByName(v.Type(), columns)
 | |
| 		// if we are not unsafe and are missing fields, return an error
 | |
| 		if f, err := missingFields(r.fields); err != nil && !r.unsafe {
 | |
| 			return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
 | |
| 		}
 | |
| 		r.values = make([]interface{}, len(columns))
 | |
| 		r.started = true
 | |
| 	}
 | |
| 
 | |
| 	err := fieldsByTraversal(v, r.fields, r.values, true)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	// scan into the struct field pointers and append to our results
 | |
| 	err = r.Scan(r.values...)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return r.Err()
 | |
| }
 | |
| 
 | |
| // Connect to a database and verify with a ping.
 | |
| func Connect(driverName, dataSourceName string) (*DB, error) {
 | |
| 	db, err := Open(driverName, dataSourceName)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	err = db.Ping()
 | |
| 	if err != nil {
 | |
| 		db.Close()
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return db, nil
 | |
| }
 | |
| 
 | |
| // MustConnect connects to a database and panics on error.
 | |
| func MustConnect(driverName, dataSourceName string) *DB {
 | |
| 	db, err := Connect(driverName, dataSourceName)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	return db
 | |
| }
 | |
| 
 | |
| // Preparex prepares a statement.
 | |
| func Preparex(p Preparer, query string) (*Stmt, error) {
 | |
| 	s, err := p.Prepare(query)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &Stmt{Stmt: s, unsafe: isUnsafe(p), Mapper: mapperFor(p)}, err
 | |
| }
 | |
| 
 | |
| // Select executes a query using the provided Queryer, and StructScans each row
 | |
| // into dest, which must be a slice.  If the slice elements are scannable, then
 | |
| // the result set must have only one column.  Otherwise, StructScan is used.
 | |
| // The *sql.Rows are closed automatically.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func Select(q Queryer, dest interface{}, query string, args ...interface{}) error {
 | |
| 	rows, err := q.Queryx(query, args...)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	// if something happens here, we want to make sure the rows are Closed
 | |
| 	defer rows.Close()
 | |
| 	return scanAll(rows, dest, false)
 | |
| }
 | |
| 
 | |
| // Get does a QueryRow using the provided Queryer, and scans the resulting row
 | |
| // to dest.  If dest is scannable, the result must only have one column.  Otherwise,
 | |
| // StructScan is used.  Get will return sql.ErrNoRows like row.Scan would.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| // An error is returned if the result set is empty.
 | |
| func Get(q Queryer, dest interface{}, query string, args ...interface{}) error {
 | |
| 	r := q.QueryRowx(query, args...)
 | |
| 	return r.scanAny(dest, false)
 | |
| }
 | |
| 
 | |
| // LoadFile exec's every statement in a file (as a single call to Exec).
 | |
| // LoadFile may return a nil *sql.Result if errors are encountered locating or
 | |
| // reading the file at path.  LoadFile reads the entire file into memory, so it
 | |
| // is not suitable for loading large data dumps, but can be useful for initializing
 | |
| // schemas or loading indexes.
 | |
| //
 | |
| // FIXME: this does not really work with multi-statement files for mattn/go-sqlite3
 | |
| // or the go-mysql-driver/mysql drivers;  pq seems to be an exception here.  Detecting
 | |
| // this by requiring something with DriverName() and then attempting to split the
 | |
| // queries will be difficult to get right, and its current driver-specific behavior
 | |
| // is deemed at least not complex in its incorrectness.
 | |
| func LoadFile(e Execer, path string) (*sql.Result, error) {
 | |
| 	realpath, err := filepath.Abs(path)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	contents, err := ioutil.ReadFile(realpath)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	res, err := e.Exec(string(contents))
 | |
| 	return &res, err
 | |
| }
 | |
| 
 | |
| // MustExec execs the query using e and panics if there was an error.
 | |
| // Any placeholder parameters are replaced with supplied args.
 | |
| func MustExec(e Execer, query string, args ...interface{}) sql.Result {
 | |
| 	res, err := e.Exec(query, args...)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	return res
 | |
| }
 | |
| 
 | |
| // SliceScan using this Rows.
 | |
| func (r *Row) SliceScan() ([]interface{}, error) {
 | |
| 	return SliceScan(r)
 | |
| }
 | |
| 
 | |
| // MapScan using this Rows.
 | |
| func (r *Row) MapScan(dest map[string]interface{}) error {
 | |
| 	return MapScan(r, dest)
 | |
| }
 | |
| 
 | |
| func (r *Row) scanAny(dest interface{}, structOnly bool) error {
 | |
| 	if r.err != nil {
 | |
| 		return r.err
 | |
| 	}
 | |
| 	if r.rows == nil {
 | |
| 		r.err = sql.ErrNoRows
 | |
| 		return r.err
 | |
| 	}
 | |
| 	defer r.rows.Close()
 | |
| 
 | |
| 	v := reflect.ValueOf(dest)
 | |
| 	if v.Kind() != reflect.Ptr {
 | |
| 		return errors.New("must pass a pointer, not a value, to StructScan destination")
 | |
| 	}
 | |
| 	if v.IsNil() {
 | |
| 		return errors.New("nil pointer passed to StructScan destination")
 | |
| 	}
 | |
| 
 | |
| 	base := reflectx.Deref(v.Type())
 | |
| 	scannable := isScannable(base)
 | |
| 
 | |
| 	if structOnly && scannable {
 | |
| 		return structOnlyError(base)
 | |
| 	}
 | |
| 
 | |
| 	columns, err := r.Columns()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if scannable && len(columns) > 1 {
 | |
| 		return fmt.Errorf("scannable dest type %s with >1 columns (%d) in result", base.Kind(), len(columns))
 | |
| 	}
 | |
| 
 | |
| 	if scannable {
 | |
| 		return r.Scan(dest)
 | |
| 	}
 | |
| 
 | |
| 	m := r.Mapper
 | |
| 
 | |
| 	fields := m.TraversalsByName(v.Type(), columns)
 | |
| 	// if we are not unsafe and are missing fields, return an error
 | |
| 	if f, err := missingFields(fields); err != nil && !r.unsafe {
 | |
| 		return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
 | |
| 	}
 | |
| 	values := make([]interface{}, len(columns))
 | |
| 
 | |
| 	err = fieldsByTraversal(v, fields, values, true)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	// scan into the struct field pointers and append to our results
 | |
| 	return r.Scan(values...)
 | |
| }
 | |
| 
 | |
| // StructScan a single Row into dest.
 | |
| func (r *Row) StructScan(dest interface{}) error {
 | |
| 	return r.scanAny(dest, true)
 | |
| }
 | |
| 
 | |
| // SliceScan a row, returning a []interface{} with values similar to MapScan.
 | |
| // This function is primarily intended for use where the number of columns
 | |
| // is not known.  Because you can pass an []interface{} directly to Scan,
 | |
| // it's recommended that you do that as it will not have to allocate new
 | |
| // slices per row.
 | |
| func SliceScan(r ColScanner) ([]interface{}, error) {
 | |
| 	// ignore r.started, since we needn't use reflect for anything.
 | |
| 	columns, err := r.Columns()
 | |
| 	if err != nil {
 | |
| 		return []interface{}{}, err
 | |
| 	}
 | |
| 
 | |
| 	values := make([]interface{}, len(columns))
 | |
| 	for i := range values {
 | |
| 		values[i] = new(interface{})
 | |
| 	}
 | |
| 
 | |
| 	err = r.Scan(values...)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return values, err
 | |
| 	}
 | |
| 
 | |
| 	for i := range columns {
 | |
| 		values[i] = *(values[i].(*interface{}))
 | |
| 	}
 | |
| 
 | |
| 	return values, r.Err()
 | |
| }
 | |
| 
 | |
| // MapScan scans a single Row into the dest map[string]interface{}.
 | |
| // Use this to get results for SQL that might not be under your control
 | |
| // (for instance, if you're building an interface for an SQL server that
 | |
| // executes SQL from input).  Please do not use this as a primary interface!
 | |
| // This will modify the map sent to it in place, so reuse the same map with
 | |
| // care.  Columns which occur more than once in the result will overwrite
 | |
| // each other!
 | |
| func MapScan(r ColScanner, dest map[string]interface{}) error {
 | |
| 	// ignore r.started, since we needn't use reflect for anything.
 | |
| 	columns, err := r.Columns()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	values := make([]interface{}, len(columns))
 | |
| 	for i := range values {
 | |
| 		values[i] = new(interface{})
 | |
| 	}
 | |
| 
 | |
| 	err = r.Scan(values...)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	for i, column := range columns {
 | |
| 		dest[column] = *(values[i].(*interface{}))
 | |
| 	}
 | |
| 
 | |
| 	return r.Err()
 | |
| }
 | |
| 
 | |
| type rowsi interface {
 | |
| 	Close() error
 | |
| 	Columns() ([]string, error)
 | |
| 	Err() error
 | |
| 	Next() bool
 | |
| 	Scan(...interface{}) error
 | |
| }
 | |
| 
 | |
| // structOnlyError returns an error appropriate for type when a non-scannable
 | |
| // struct is expected but something else is given
 | |
| func structOnlyError(t reflect.Type) error {
 | |
| 	isStruct := t.Kind() == reflect.Struct
 | |
| 	isScanner := reflect.PtrTo(t).Implements(_scannerInterface)
 | |
| 	if !isStruct {
 | |
| 		return fmt.Errorf("expected %s but got %s", reflect.Struct, t.Kind())
 | |
| 	}
 | |
| 	if isScanner {
 | |
| 		return fmt.Errorf("structscan expects a struct dest but the provided struct type %s implements scanner", t.Name())
 | |
| 	}
 | |
| 	return fmt.Errorf("expected a struct, but struct %s has no exported fields", t.Name())
 | |
| }
 | |
| 
 | |
| // scanAll scans all rows into a destination, which must be a slice of any
 | |
| // type.  If the destination slice type is a Struct, then StructScan will be
 | |
| // used on each row.  If the destination is some other kind of base type, then
 | |
| // each row must only have one column which can scan into that type.  This
 | |
| // allows you to do something like:
 | |
| //
 | |
| //    rows, _ := db.Query("select id from people;")
 | |
| //    var ids []int
 | |
| //    scanAll(rows, &ids, false)
 | |
| //
 | |
| // and ids will be a list of the id results.  I realize that this is a desirable
 | |
| // interface to expose to users, but for now it will only be exposed via changes
 | |
| // to `Get` and `Select`.  The reason that this has been implemented like this is
 | |
| // this is the only way to not duplicate reflect work in the new API while
 | |
| // maintaining backwards compatibility.
 | |
| func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
 | |
| 	var v, vp reflect.Value
 | |
| 
 | |
| 	value := reflect.ValueOf(dest)
 | |
| 
 | |
| 	// json.Unmarshal returns errors for these
 | |
| 	if value.Kind() != reflect.Ptr {
 | |
| 		return errors.New("must pass a pointer, not a value, to StructScan destination")
 | |
| 	}
 | |
| 	if value.IsNil() {
 | |
| 		return errors.New("nil pointer passed to StructScan destination")
 | |
| 	}
 | |
| 	direct := reflect.Indirect(value)
 | |
| 
 | |
| 	slice, err := baseType(value.Type(), reflect.Slice)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	isPtr := slice.Elem().Kind() == reflect.Ptr
 | |
| 	base := reflectx.Deref(slice.Elem())
 | |
| 	scannable := isScannable(base)
 | |
| 
 | |
| 	if structOnly && scannable {
 | |
| 		return structOnlyError(base)
 | |
| 	}
 | |
| 
 | |
| 	columns, err := rows.Columns()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// if it's a base type make sure it only has 1 column;  if not return an error
 | |
| 	if scannable && len(columns) > 1 {
 | |
| 		return fmt.Errorf("non-struct dest type %s with >1 columns (%d)", base.Kind(), len(columns))
 | |
| 	}
 | |
| 
 | |
| 	if !scannable {
 | |
| 		var values []interface{}
 | |
| 		var m *reflectx.Mapper
 | |
| 
 | |
| 		switch rows.(type) {
 | |
| 		case *Rows:
 | |
| 			m = rows.(*Rows).Mapper
 | |
| 		default:
 | |
| 			m = mapper()
 | |
| 		}
 | |
| 
 | |
| 		fields := m.TraversalsByName(base, columns)
 | |
| 		// if we are not unsafe and are missing fields, return an error
 | |
| 		if f, err := missingFields(fields); err != nil && !isUnsafe(rows) {
 | |
| 			return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
 | |
| 		}
 | |
| 		values = make([]interface{}, len(columns))
 | |
| 
 | |
| 		for rows.Next() {
 | |
| 			// create a new struct type (which returns PtrTo) and indirect it
 | |
| 			vp = reflect.New(base)
 | |
| 			v = reflect.Indirect(vp)
 | |
| 
 | |
| 			err = fieldsByTraversal(v, fields, values, true)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 
 | |
| 			// scan into the struct field pointers and append to our results
 | |
| 			err = rows.Scan(values...)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 
 | |
| 			if isPtr {
 | |
| 				direct.Set(reflect.Append(direct, vp))
 | |
| 			} else {
 | |
| 				direct.Set(reflect.Append(direct, v))
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		for rows.Next() {
 | |
| 			vp = reflect.New(base)
 | |
| 			err = rows.Scan(vp.Interface())
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			// append
 | |
| 			if isPtr {
 | |
| 				direct.Set(reflect.Append(direct, vp))
 | |
| 			} else {
 | |
| 				direct.Set(reflect.Append(direct, reflect.Indirect(vp)))
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return rows.Err()
 | |
| }
 | |
| 
 | |
| // FIXME: StructScan was the very first bit of API in sqlx, and now unfortunately
 | |
| // it doesn't really feel like it's named properly.  There is an incongruency
 | |
| // between this and the way that StructScan (which might better be ScanStruct
 | |
| // anyway) works on a rows object.
 | |
| 
 | |
| // StructScan all rows from an sql.Rows or an sqlx.Rows into the dest slice.
 | |
| // StructScan will scan in the entire rows result, so if you do not want to
 | |
| // allocate structs for the entire result, use Queryx and see sqlx.Rows.StructScan.
 | |
| // If rows is sqlx.Rows, it will use its mapper, otherwise it will use the default.
 | |
| func StructScan(rows rowsi, dest interface{}) error {
 | |
| 	return scanAll(rows, dest, true)
 | |
| 
 | |
| }
 | |
| 
 | |
| // reflect helpers
 | |
| 
 | |
| func baseType(t reflect.Type, expected reflect.Kind) (reflect.Type, error) {
 | |
| 	t = reflectx.Deref(t)
 | |
| 	if t.Kind() != expected {
 | |
| 		return nil, fmt.Errorf("expected %s but got %s", expected, t.Kind())
 | |
| 	}
 | |
| 	return t, nil
 | |
| }
 | |
| 
 | |
| // fieldsByName fills a values interface with fields from the passed value based
 | |
| // on the traversals in int.  If ptrs is true, return addresses instead of values.
 | |
| // We write this instead of using FieldsByName to save allocations and map lookups
 | |
| // when iterating over many rows.  Empty traversals will get an interface pointer.
 | |
| // Because of the necessity of requesting ptrs or values, it's considered a bit too
 | |
| // specialized for inclusion in reflectx itself.
 | |
| func fieldsByTraversal(v reflect.Value, traversals [][]int, values []interface{}, ptrs bool) error {
 | |
| 	v = reflect.Indirect(v)
 | |
| 	if v.Kind() != reflect.Struct {
 | |
| 		return errors.New("argument not a struct")
 | |
| 	}
 | |
| 
 | |
| 	for i, traversal := range traversals {
 | |
| 		if len(traversal) == 0 {
 | |
| 			values[i] = new(interface{})
 | |
| 			continue
 | |
| 		}
 | |
| 		f := reflectx.FieldByIndexes(v, traversal)
 | |
| 		if ptrs {
 | |
| 			values[i] = f.Addr().Interface()
 | |
| 		} else {
 | |
| 			values[i] = f.Interface()
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func missingFields(transversals [][]int) (field int, err error) {
 | |
| 	for i, t := range transversals {
 | |
| 		if len(t) == 0 {
 | |
| 			return i, errors.New("missing field")
 | |
| 		}
 | |
| 	}
 | |
| 	return 0, nil
 | |
| }
 |