From 8c12c6939aab9106db14ec2d11d983bc5b29fb2c Mon Sep 17 00:00:00 2001 From: Niall Sheridan Date: Sun, 7 Jul 2019 21:33:44 +0100 Subject: Switch to modules --- vendor/github.com/jmoiron/sqlx/sqlx.go | 1047 -------------------------------- 1 file changed, 1047 deletions(-) delete mode 100644 vendor/github.com/jmoiron/sqlx/sqlx.go (limited to 'vendor/github.com/jmoiron/sqlx/sqlx.go') diff --git a/vendor/github.com/jmoiron/sqlx/sqlx.go b/vendor/github.com/jmoiron/sqlx/sqlx.go deleted file mode 100644 index 4385c3f..0000000 --- a/vendor/github.com/jmoiron/sqlx/sqlx.go +++ /dev/null @@ -1,1047 +0,0 @@ -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 - 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 -} -- cgit v1.2.3