12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052 |
- 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
- return len(mapper().TypeMap(t).Index) == 0
- }
- // 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 := i.(type) {
- case DB:
- return i.Mapper
- case *DB:
- return i.Mapper
- case Tx:
- return i.Mapper
- case *Tx:
- return i.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)
- }
- // Conn is a wrapper around sql.Conn with extra functionality
- type Conn struct {
- *sql.Conn
- driverName string
- unsafe bool
- Mapper *reflectx.Mapper
- }
- // 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. It resets the slice length to zero before appending each element to
- // the slice. 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
- }
- direct.SetLen(0)
- 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
- }
|