Switch to dep for dependency management
This commit is contained in:
27
vendor/github.com/jmoiron/sqlx/.travis.yml
generated
vendored
Normal file
27
vendor/github.com/jmoiron/sqlx/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# vim: ft=yaml sw=2 ts=2
|
||||
|
||||
language: go
|
||||
|
||||
# enable database services
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
|
||||
# create test database
|
||||
before_install:
|
||||
- mysql -e 'CREATE DATABASE IF NOT EXISTS sqlxtest;'
|
||||
- psql -c 'create database sqlxtest;' -U postgres
|
||||
- go get github.com/mattn/goveralls
|
||||
- export SQLX_MYSQL_DSN="travis:@/sqlxtest?parseTime=true"
|
||||
- export SQLX_POSTGRES_DSN="postgres://postgres:@localhost/sqlxtest?sslmode=disable"
|
||||
- export SQLX_SQLITE_DSN="$HOME/sqlxtest.db"
|
||||
|
||||
# go versions to test
|
||||
go:
|
||||
- "1.8"
|
||||
- "1.9"
|
||||
- "1.10.x"
|
||||
|
||||
# run tests w/ coverage
|
||||
script:
|
||||
- travis_retry $GOPATH/bin/goveralls -service=travis-ci
|
||||
123
vendor/github.com/jmoiron/sqlx/README.md
generated
vendored
123
vendor/github.com/jmoiron/sqlx/README.md
generated
vendored
@@ -1,6 +1,6 @@
|
||||
#sqlx
|
||||
# sqlx
|
||||
|
||||
[](https://drone.io/github.com/jmoiron/sqlx/latest) [](https://godoc.org/github.com/jmoiron/sqlx) [](https://raw.githubusercontent.com/jmoiron/sqlx/master/LICENSE)
|
||||
[](https://travis-ci.org/jmoiron/sqlx) [](https://coveralls.io/github/jmoiron/sqlx?branch=master) [](https://godoc.org/github.com/jmoiron/sqlx) [](https://raw.githubusercontent.com/jmoiron/sqlx/master/LICENSE)
|
||||
|
||||
sqlx is a library which provides a set of extensions on go's standard
|
||||
`database/sql` library. The sqlx versions of `sql.DB`, `sql.TX`, `sql.Stmt`,
|
||||
@@ -13,35 +13,30 @@ Major additional concepts are:
|
||||
* Marshal rows into structs (with embedded struct support), maps, and slices
|
||||
* Named parameter support including prepared statements
|
||||
* `Get` and `Select` to go quickly from query to struct/slice
|
||||
* `LoadFile` for executing statements from a file
|
||||
|
||||
There is now some [fairly comprehensive documentation](http://jmoiron.github.io/sqlx/) for sqlx.
|
||||
You can also read the usage below for a quick sample on how sqlx works, or check out the [API
|
||||
documentation on godoc](http://godoc.org/github.com/jmoiron/sqlx).
|
||||
In addition to the [godoc API documentation](http://godoc.org/github.com/jmoiron/sqlx),
|
||||
there is also some [standard documentation](http://jmoiron.github.io/sqlx/) that
|
||||
explains how to use `database/sql` along with sqlx.
|
||||
|
||||
## Recent Changes
|
||||
|
||||
The ability to use basic types as Select and Get destinations was added. This
|
||||
is only valid when there is one column in the result set, and both functions
|
||||
return an error if this isn't the case. This allows for much simpler patterns
|
||||
of access for single column results:
|
||||
* sqlx/types.JsonText has been renamed to JSONText to follow Go naming conventions.
|
||||
|
||||
```go
|
||||
var count int
|
||||
err := db.Get(&count, "SELECT count(*) FROM person;")
|
||||
This breaks backwards compatibility, but it's in a way that is trivially fixable
|
||||
(`s/JsonText/JSONText/g`). The `types` package is both experimental and not in
|
||||
active development currently.
|
||||
|
||||
var names []string
|
||||
err := db.Select(&names, "SELECT name FROM person;")
|
||||
```
|
||||
|
||||
See the note on Scannability at the bottom of this README for some more info.
|
||||
* Using Go 1.6 and below with `types.JSONText` and `types.GzippedText` can be _potentially unsafe_, **especially** when used with common auto-scan sqlx idioms like `Select` and `Get`. See [golang bug #13905](https://github.com/golang/go/issues/13905).
|
||||
|
||||
### Backwards Compatibility
|
||||
|
||||
There is no Go1-like promise of absolute stability, but I take the issue
|
||||
seriously and will maintain the library in a compatible state unless vital
|
||||
bugs prevent me from doing so. Since [#59](https://github.com/jmoiron/sqlx/issues/59) and [#60](https://github.com/jmoiron/sqlx/issues/60) necessitated
|
||||
breaking behavior, a wider API cleanup was done at the time of fixing.
|
||||
There is no Go1-like promise of absolute stability, but I take the issue seriously
|
||||
and will maintain the library in a compatible state unless vital bugs prevent me
|
||||
from doing so. Since [#59](https://github.com/jmoiron/sqlx/issues/59) and
|
||||
[#60](https://github.com/jmoiron/sqlx/issues/60) necessitated breaking behavior,
|
||||
a wider API cleanup was done at the time of fixing. It's possible this will happen
|
||||
in future; if it does, a git tag will be provided for users requiring the old
|
||||
behavior to continue to use it until such a time as they can migrate.
|
||||
|
||||
## install
|
||||
|
||||
@@ -50,31 +45,33 @@ breaking behavior, a wider API cleanup was done at the time of fixing.
|
||||
## issues
|
||||
|
||||
Row headers can be ambiguous (`SELECT 1 AS a, 2 AS a`), and the result of
|
||||
`Columns()` can have duplicate names on queries like:
|
||||
`Columns()` does not fully qualify column names in queries like:
|
||||
|
||||
```sql
|
||||
SELECT a.id, a.name, b.id, b.name FROM foos AS a JOIN foos AS b ON a.parent = b.id;
|
||||
```
|
||||
|
||||
making a struct or map destination ambiguous. Use `AS` in your queries
|
||||
to give rows distinct names, `rows.Scan` to scan them manually, or
|
||||
to give columns distinct names, `rows.Scan` to scan them manually, or
|
||||
`SliceScan` to get a slice of results.
|
||||
|
||||
## usage
|
||||
|
||||
Below is an example which shows some common use cases for sqlx. Check
|
||||
[sqlx_test.go](https://github.com/jmoiron/sqlx/blob/master/sqlx_test.go) for more
|
||||
usage.
|
||||
usage.
|
||||
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/lib/pq"
|
||||
"database/sql"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
var schema = `
|
||||
@@ -103,7 +100,7 @@ type Place struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// this connects & tries a simple 'SELECT 1', panics on error
|
||||
// this Pings the database trying to connect, panics on error
|
||||
// use sqlx.Open() for sql.Open() semantics
|
||||
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
|
||||
if err != nil {
|
||||
@@ -186,73 +183,3 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
## Scannability
|
||||
|
||||
Get and Select are able to take base types, so the following is now possible:
|
||||
|
||||
```go
|
||||
var name string
|
||||
db.Get(&name, "SELECT first_name FROM person WHERE id=$1", 10)
|
||||
|
||||
var ids []int64
|
||||
db.Select(&ids, "SELECT id FROM person LIMIT 20;")
|
||||
```
|
||||
|
||||
This can get complicated with destination types which are structs, like `sql.NullString`. Because of this, straightforward rules for *scannability* had to be developed. Iff something is "Scannable", then it is used directly in `rows.Scan`; if it's not, then the standard sqlx struct rules apply.
|
||||
|
||||
Something is scannable if any of the following are true:
|
||||
|
||||
* It is not a struct, ie. `reflect.ValueOf(v).Kind() != reflect.Struct`
|
||||
* It implements the `sql.Scanner` interface
|
||||
* It has no exported fields (eg. `time.Time`)
|
||||
|
||||
## embedded structs
|
||||
|
||||
Scan targets obey Go attribute rules directly, including nested embedded structs. Older versions of sqlx would attempt to also descend into non-embedded structs, but this is no longer supported.
|
||||
|
||||
Go makes *accessing* '[ambiguous selectors](http://play.golang.org/p/MGRxdjLaUc)' a compile time error, defining structs with ambiguous selectors is legal. Sqlx will decide which field to use on a struct based on a breadth first search of the struct and any structs it embeds, as specified by the order of the fields as accessible by `reflect`, which generally means in source-order. This means that sqlx chooses the outer-most, top-most matching name for targets, even when the selector might technically be ambiguous.
|
||||
|
||||
## scan safety
|
||||
|
||||
By default, scanning into structs requires the structs to have fields for all of the
|
||||
columns in the query. This was done for a few reasons:
|
||||
|
||||
* A mistake in naming during development could lead you to believe that data is
|
||||
being written to a field when actually it can't be found and it is being dropped
|
||||
* This behavior mirrors the behavior of the Go compiler with respect to unused
|
||||
variables
|
||||
* Selecting more data than you need is wasteful (more data on the wire, more time
|
||||
marshalling, etc)
|
||||
|
||||
Unlike Marshallers in the stdlib, the programmer scanning an sql result into a struct
|
||||
will generally have a full understanding of what the underlying data model is *and*
|
||||
full control over the SQL statement.
|
||||
|
||||
Despite this, there are use cases where it's convenient to be able to ignore unknown
|
||||
columns. In most of these cases, you might be better off with `ScanSlice`, but where
|
||||
you want to still use structs, there is now the `Unsafe` method. Its usage is most
|
||||
simply shown in an example:
|
||||
|
||||
```go
|
||||
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Person {
|
||||
Name string
|
||||
}
|
||||
var p Person
|
||||
|
||||
// This fails, because there is no destination for location in Person
|
||||
err = db.Get(&p, "SELECT name, location FROM person LIMIT 1")
|
||||
|
||||
udb := db.Unsafe()
|
||||
|
||||
// This succeeds and just sets `Name` in the p struct
|
||||
err = udb.Get(&p, "SELECT name, location FROM person LIMIT 1")
|
||||
```
|
||||
|
||||
The `Unsafe` method is implemented on `Tx`, `DB`, and `Stmt`. When you use an unsafe
|
||||
`Tx` or `DB` to create a new `Tx` or `Stmt`, those inherit its lack of safety.
|
||||
|
||||
|
||||
160
vendor/github.com/jmoiron/sqlx/bind.go
generated
vendored
160
vendor/github.com/jmoiron/sqlx/bind.go
generated
vendored
@@ -2,7 +2,12 @@ package sqlx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jmoiron/sqlx/reflectx"
|
||||
)
|
||||
|
||||
// Bindvar types supported by Rebind, BindMap and BindStruct.
|
||||
@@ -16,13 +21,13 @@ const (
|
||||
// BindType returns the bindtype for a given database given a drivername.
|
||||
func BindType(driverName string) int {
|
||||
switch driverName {
|
||||
case "postgres", "pgx":
|
||||
case "postgres", "pgx", "pq-timeouts", "cloudsqlpostgres":
|
||||
return DOLLAR
|
||||
case "mysql":
|
||||
return QUESTION
|
||||
case "sqlite3":
|
||||
return QUESTION
|
||||
case "oci8":
|
||||
case "oci8", "ora", "goracle":
|
||||
return NAMED
|
||||
}
|
||||
return UNKNOWN
|
||||
@@ -31,37 +36,41 @@ func BindType(driverName string) int {
|
||||
// FIXME: this should be able to be tolerant of escaped ?'s in queries without
|
||||
// losing much speed, and should be to avoid confusion.
|
||||
|
||||
// FIXME: this is now produces the wrong results for oracle's NAMED bindtype
|
||||
|
||||
// Rebind a query from the default bindtype (QUESTION) to the target bindtype.
|
||||
func Rebind(bindType int, query string) string {
|
||||
if bindType != DOLLAR {
|
||||
switch bindType {
|
||||
case QUESTION, UNKNOWN:
|
||||
return query
|
||||
}
|
||||
|
||||
qb := []byte(query)
|
||||
// Add space enough for 10 params before we have to allocate
|
||||
rqb := make([]byte, 0, len(qb)+10)
|
||||
j := 1
|
||||
for _, b := range qb {
|
||||
if b == '?' {
|
||||
rqb := make([]byte, 0, len(query)+10)
|
||||
|
||||
var i, j int
|
||||
|
||||
for i = strings.Index(query, "?"); i != -1; i = strings.Index(query, "?") {
|
||||
rqb = append(rqb, query[:i]...)
|
||||
|
||||
switch bindType {
|
||||
case DOLLAR:
|
||||
rqb = append(rqb, '$')
|
||||
for _, b := range strconv.Itoa(j) {
|
||||
rqb = append(rqb, byte(b))
|
||||
}
|
||||
j++
|
||||
} else {
|
||||
rqb = append(rqb, b)
|
||||
case NAMED:
|
||||
rqb = append(rqb, ':', 'a', 'r', 'g')
|
||||
}
|
||||
|
||||
j++
|
||||
rqb = strconv.AppendInt(rqb, int64(j), 10)
|
||||
|
||||
query = query[i+1:]
|
||||
}
|
||||
return string(rqb)
|
||||
|
||||
return string(append(rqb, query...))
|
||||
}
|
||||
|
||||
// Experimental implementation of Rebind which uses a bytes.Buffer. The code is
|
||||
// much simpler and should be more resistant to odd unicode, but it is twice as
|
||||
// slow. Kept here for benchmarking purposes and to possibly replace Rebind if
|
||||
// problems arise with its somewhat naive handling of unicode.
|
||||
|
||||
func rebindBuff(bindType int, query string) string {
|
||||
if bindType != DOLLAR {
|
||||
return query
|
||||
@@ -82,3 +91,118 @@ func rebindBuff(bindType int, query string) string {
|
||||
|
||||
return rqb.String()
|
||||
}
|
||||
|
||||
// In expands slice values in args, returning the modified query string
|
||||
// and a new arg list that can be executed by a database. The `query` should
|
||||
// use the `?` bindVar. The return value uses the `?` bindVar.
|
||||
func In(query string, args ...interface{}) (string, []interface{}, error) {
|
||||
// argMeta stores reflect.Value and length for slices and
|
||||
// the value itself for non-slice arguments
|
||||
type argMeta struct {
|
||||
v reflect.Value
|
||||
i interface{}
|
||||
length int
|
||||
}
|
||||
|
||||
var flatArgsCount int
|
||||
var anySlices bool
|
||||
|
||||
meta := make([]argMeta, len(args))
|
||||
|
||||
for i, arg := range args {
|
||||
v := reflect.ValueOf(arg)
|
||||
t := reflectx.Deref(v.Type())
|
||||
|
||||
// []byte is a driver.Value type so it should not be expanded
|
||||
if t.Kind() == reflect.Slice && t != reflect.TypeOf([]byte{}) {
|
||||
meta[i].length = v.Len()
|
||||
meta[i].v = v
|
||||
|
||||
anySlices = true
|
||||
flatArgsCount += meta[i].length
|
||||
|
||||
if meta[i].length == 0 {
|
||||
return "", nil, errors.New("empty slice passed to 'in' query")
|
||||
}
|
||||
} else {
|
||||
meta[i].i = arg
|
||||
flatArgsCount++
|
||||
}
|
||||
}
|
||||
|
||||
// don't do any parsing if there aren't any slices; note that this means
|
||||
// some errors that we might have caught below will not be returned.
|
||||
if !anySlices {
|
||||
return query, args, nil
|
||||
}
|
||||
|
||||
newArgs := make([]interface{}, 0, flatArgsCount)
|
||||
buf := bytes.NewBuffer(make([]byte, 0, len(query)+len(", ?")*flatArgsCount))
|
||||
|
||||
var arg, offset int
|
||||
|
||||
for i := strings.IndexByte(query[offset:], '?'); i != -1; i = strings.IndexByte(query[offset:], '?') {
|
||||
if arg >= len(meta) {
|
||||
// if an argument wasn't passed, lets return an error; this is
|
||||
// not actually how database/sql Exec/Query works, but since we are
|
||||
// creating an argument list programmatically, we want to be able
|
||||
// to catch these programmer errors earlier.
|
||||
return "", nil, errors.New("number of bindVars exceeds arguments")
|
||||
}
|
||||
|
||||
argMeta := meta[arg]
|
||||
arg++
|
||||
|
||||
// not a slice, continue.
|
||||
// our questionmark will either be written before the next expansion
|
||||
// of a slice or after the loop when writing the rest of the query
|
||||
if argMeta.length == 0 {
|
||||
offset = offset + i + 1
|
||||
newArgs = append(newArgs, argMeta.i)
|
||||
continue
|
||||
}
|
||||
|
||||
// write everything up to and including our ? character
|
||||
buf.WriteString(query[:offset+i+1])
|
||||
|
||||
for si := 1; si < argMeta.length; si++ {
|
||||
buf.WriteString(", ?")
|
||||
}
|
||||
|
||||
newArgs = appendReflectSlice(newArgs, argMeta.v, argMeta.length)
|
||||
|
||||
// slice the query and reset the offset. this avoids some bookkeeping for
|
||||
// the write after the loop
|
||||
query = query[offset+i+1:]
|
||||
offset = 0
|
||||
}
|
||||
|
||||
buf.WriteString(query)
|
||||
|
||||
if arg < len(meta) {
|
||||
return "", nil, errors.New("number of bindVars less than number arguments")
|
||||
}
|
||||
|
||||
return buf.String(), newArgs, nil
|
||||
}
|
||||
|
||||
func appendReflectSlice(args []interface{}, v reflect.Value, vlen int) []interface{} {
|
||||
switch val := v.Interface().(type) {
|
||||
case []interface{}:
|
||||
args = append(args, val...)
|
||||
case []int:
|
||||
for i := range val {
|
||||
args = append(args, val[i])
|
||||
}
|
||||
case []string:
|
||||
for i := range val {
|
||||
args = append(args, val[i])
|
||||
}
|
||||
default:
|
||||
for si := 0; si < vlen; si++ {
|
||||
args = append(args, v.Index(si).Interface())
|
||||
}
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
43
vendor/github.com/jmoiron/sqlx/named.go
generated
vendored
43
vendor/github.com/jmoiron/sqlx/named.go
generated
vendored
@@ -36,6 +36,7 @@ func (n *NamedStmt) Close() error {
|
||||
}
|
||||
|
||||
// Exec executes a named statement using the struct passed.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) Exec(arg interface{}) (sql.Result, error) {
|
||||
args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
|
||||
if err != nil {
|
||||
@@ -45,6 +46,7 @@ func (n *NamedStmt) Exec(arg interface{}) (sql.Result, error) {
|
||||
}
|
||||
|
||||
// Query executes a named statement using the struct argument, returning rows.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) Query(arg interface{}) (*sql.Rows, error) {
|
||||
args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
|
||||
if err != nil {
|
||||
@@ -56,6 +58,7 @@ func (n *NamedStmt) Query(arg interface{}) (*sql.Rows, error) {
|
||||
// QueryRow executes a named statement against the database. Because sqlx cannot
|
||||
// create a *sql.Row with an error condition pre-set for binding errors, sqlx
|
||||
// returns a *sqlx.Row instead.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) QueryRow(arg interface{}) *Row {
|
||||
args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
|
||||
if err != nil {
|
||||
@@ -65,6 +68,7 @@ func (n *NamedStmt) QueryRow(arg interface{}) *Row {
|
||||
}
|
||||
|
||||
// MustExec execs a NamedStmt, panicing on error
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) MustExec(arg interface{}) sql.Result {
|
||||
res, err := n.Exec(arg)
|
||||
if err != nil {
|
||||
@@ -74,23 +78,26 @@ func (n *NamedStmt) MustExec(arg interface{}) sql.Result {
|
||||
}
|
||||
|
||||
// Queryx using this NamedStmt
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) Queryx(arg interface{}) (*Rows, error) {
|
||||
r, err := n.Query(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{Rows: r, Mapper: n.Stmt.Mapper}, err
|
||||
return &Rows{Rows: r, Mapper: n.Stmt.Mapper, unsafe: isUnsafe(n)}, err
|
||||
}
|
||||
|
||||
// QueryRowx this NamedStmt. Because of limitations with QueryRow, this is
|
||||
// an alias for QueryRow.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) QueryRowx(arg interface{}) *Row {
|
||||
return n.QueryRow(arg)
|
||||
}
|
||||
|
||||
// Select using this NamedStmt
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) Select(dest interface{}, arg interface{}) error {
|
||||
rows, err := n.Query(arg)
|
||||
rows, err := n.Queryx(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -100,11 +107,19 @@ func (n *NamedStmt) Select(dest interface{}, arg interface{}) error {
|
||||
}
|
||||
|
||||
// Get using this NamedStmt
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) Get(dest interface{}, arg interface{}) error {
|
||||
r := n.QueryRowx(arg)
|
||||
return r.scanAny(dest, false)
|
||||
}
|
||||
|
||||
// Unsafe creates an unsafe version of the NamedStmt
|
||||
func (n *NamedStmt) Unsafe() *NamedStmt {
|
||||
r := &NamedStmt{Params: n.Params, Stmt: n.Stmt, QueryString: n.QueryString}
|
||||
r.Stmt.unsafe = true
|
||||
return r
|
||||
}
|
||||
|
||||
// A union interface of preparer and binder, required to be able to prepare
|
||||
// named statements (as the bindtype must be determined).
|
||||
type namedPreparer interface {
|
||||
@@ -148,16 +163,18 @@ func bindArgs(names []string, arg interface{}, m *reflectx.Mapper) ([]interface{
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
fields := m.TraversalsByName(v.Type(), names)
|
||||
for i, t := range fields {
|
||||
err := m.TraversalsByNameFunc(v.Type(), names, func(i int, t []int) error {
|
||||
if len(t) == 0 {
|
||||
return arglist, fmt.Errorf("could not find name %s in %#v", names[i], arg)
|
||||
return fmt.Errorf("could not find name %s in %#v", names[i], arg)
|
||||
}
|
||||
|
||||
val := reflectx.FieldByIndexesReadOnly(v, t)
|
||||
arglist = append(arglist, val.Interface())
|
||||
}
|
||||
|
||||
return arglist, nil
|
||||
return nil
|
||||
})
|
||||
|
||||
return arglist, err
|
||||
}
|
||||
|
||||
// like bindArgs, but for maps.
|
||||
@@ -243,7 +260,7 @@ func compileNamedQuery(qs []byte, bindType int) (query string, names []string, e
|
||||
inName = true
|
||||
name = []byte{}
|
||||
// if we're in a name, and this is an allowed character, continue
|
||||
} else if inName && (unicode.IsOneOf(allowedBindRunes, rune(b)) || b == '_') && i != last {
|
||||
} else if inName && (unicode.IsOneOf(allowedBindRunes, rune(b)) || b == '_' || b == '.') && i != last {
|
||||
// append the byte to the name if we are in a name and not on the last byte
|
||||
name = append(name, b)
|
||||
// if we're in a name and it's not an allowed character, the name is done
|
||||
@@ -286,11 +303,19 @@ func compileNamedQuery(qs []byte, bindType int) (query string, names []string, e
|
||||
return string(rebound), names, err
|
||||
}
|
||||
|
||||
// Bind binds a struct or a map to a query with named parameters.
|
||||
// BindNamed binds a struct or a map to a query with named parameters.
|
||||
// DEPRECATED: use sqlx.Named` instead of this, it may be removed in future.
|
||||
func BindNamed(bindType int, query string, arg interface{}) (string, []interface{}, error) {
|
||||
return bindNamedMapper(bindType, query, arg, mapper())
|
||||
}
|
||||
|
||||
// Named takes a query using named parameters and an argument and
|
||||
// returns a new query with a list of args that can be executed by
|
||||
// a database. The return value uses the `?` bindvar.
|
||||
func Named(query string, arg interface{}) (string, []interface{}, error) {
|
||||
return bindNamedMapper(QUESTION, query, arg, mapper())
|
||||
}
|
||||
|
||||
func bindNamedMapper(bindType int, query string, arg interface{}, m *reflectx.Mapper) (string, []interface{}, error) {
|
||||
if maparg, ok := arg.(map[string]interface{}); ok {
|
||||
return bindMap(bindType, query, maparg)
|
||||
|
||||
132
vendor/github.com/jmoiron/sqlx/named_context.go
generated
vendored
Normal file
132
vendor/github.com/jmoiron/sqlx/named_context.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// +build go1.8
|
||||
|
||||
package sqlx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
// A union interface of contextPreparer and binder, required to be able to
|
||||
// prepare named statements with context (as the bindtype must be determined).
|
||||
type namedPreparerContext interface {
|
||||
PreparerContext
|
||||
binder
|
||||
}
|
||||
|
||||
func prepareNamedContext(ctx context.Context, p namedPreparerContext, query string) (*NamedStmt, error) {
|
||||
bindType := BindType(p.DriverName())
|
||||
q, args, err := compileNamedQuery([]byte(query), bindType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stmt, err := PreparexContext(ctx, p, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NamedStmt{
|
||||
QueryString: q,
|
||||
Params: args,
|
||||
Stmt: stmt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExecContext executes a named statement using the struct passed.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) ExecContext(ctx context.Context, arg interface{}) (sql.Result, error) {
|
||||
args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
|
||||
if err != nil {
|
||||
return *new(sql.Result), err
|
||||
}
|
||||
return n.Stmt.ExecContext(ctx, args...)
|
||||
}
|
||||
|
||||
// QueryContext executes a named statement using the struct argument, returning rows.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) QueryContext(ctx context.Context, arg interface{}) (*sql.Rows, error) {
|
||||
args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return n.Stmt.QueryContext(ctx, args...)
|
||||
}
|
||||
|
||||
// QueryRowContext executes a named statement against the database. Because sqlx cannot
|
||||
// create a *sql.Row with an error condition pre-set for binding errors, sqlx
|
||||
// returns a *sqlx.Row instead.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) QueryRowContext(ctx context.Context, arg interface{}) *Row {
|
||||
args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
|
||||
if err != nil {
|
||||
return &Row{err: err}
|
||||
}
|
||||
return n.Stmt.QueryRowxContext(ctx, args...)
|
||||
}
|
||||
|
||||
// MustExecContext execs a NamedStmt, panicing on error
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) MustExecContext(ctx context.Context, arg interface{}) sql.Result {
|
||||
res, err := n.ExecContext(ctx, arg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// QueryxContext using this NamedStmt
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) QueryxContext(ctx context.Context, arg interface{}) (*Rows, error) {
|
||||
r, err := n.QueryContext(ctx, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{Rows: r, Mapper: n.Stmt.Mapper, unsafe: isUnsafe(n)}, err
|
||||
}
|
||||
|
||||
// QueryRowxContext this NamedStmt. Because of limitations with QueryRow, this is
|
||||
// an alias for QueryRow.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) QueryRowxContext(ctx context.Context, arg interface{}) *Row {
|
||||
return n.QueryRowContext(ctx, arg)
|
||||
}
|
||||
|
||||
// SelectContext using this NamedStmt
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) SelectContext(ctx context.Context, dest interface{}, arg interface{}) error {
|
||||
rows, err := n.QueryxContext(ctx, arg)
|
||||
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)
|
||||
}
|
||||
|
||||
// GetContext using this NamedStmt
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (n *NamedStmt) GetContext(ctx context.Context, dest interface{}, arg interface{}) error {
|
||||
r := n.QueryRowxContext(ctx, arg)
|
||||
return r.scanAny(dest, false)
|
||||
}
|
||||
|
||||
// NamedQueryContext binds a named query and then runs Query on the result using the
|
||||
// provided Ext (sqlx.Tx, sqlx.Db). It works with both structs and with
|
||||
// map[string]interface{} types.
|
||||
func NamedQueryContext(ctx context.Context, e ExtContext, query string, arg interface{}) (*Rows, error) {
|
||||
q, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.QueryxContext(ctx, q, args...)
|
||||
}
|
||||
|
||||
// NamedExecContext uses BindStruct to get a query executable by the driver and
|
||||
// then runs Exec on the result. Returns an error from the binding
|
||||
// or the query excution itself.
|
||||
func NamedExecContext(ctx context.Context, e ExtContext, query string, arg interface{}) (sql.Result, error) {
|
||||
q, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.ExecContext(ctx, q, args...)
|
||||
}
|
||||
2
vendor/github.com/jmoiron/sqlx/reflectx/README.md
generated
vendored
2
vendor/github.com/jmoiron/sqlx/reflectx/README.md
generated
vendored
@@ -12,6 +12,6 @@ behavior of standard Go accessors.
|
||||
|
||||
The first two are amply taken care of by `Reflect.Value.FieldByName`, and the third is
|
||||
addressed by `Reflect.Value.FieldByNameFunc`, but these don't quite understand struct
|
||||
tags in the ways that are vital to most marshalers, and they are slow.
|
||||
tags in the ways that are vital to most marshallers, and they are slow.
|
||||
|
||||
This reflectx package extends reflect to achieve these goals.
|
||||
|
||||
340
vendor/github.com/jmoiron/sqlx/reflectx/reflect.go
generated
vendored
340
vendor/github.com/jmoiron/sqlx/reflectx/reflect.go
generated
vendored
@@ -1,45 +1,100 @@
|
||||
// Package reflect implements extensions to the standard reflect lib suitable
|
||||
// for implementing marshaling and unmarshaling packages. The main Mapper type
|
||||
// allows for Go-compatible named atribute access, including accessing embedded
|
||||
// Package reflectx implements extensions to the standard reflect lib suitable
|
||||
// for implementing marshalling and unmarshalling packages. The main Mapper type
|
||||
// allows for Go-compatible named attribute access, including accessing embedded
|
||||
// struct attributes and the ability to use functions and struct tags to
|
||||
// customize field names.
|
||||
//
|
||||
package reflectx
|
||||
|
||||
import "sync"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type fieldMap map[string][]int
|
||||
|
||||
// Mapper is a general purpose mapper of names to struct fields. A Mapper
|
||||
// behaves like most marshallers, optionally obeying a field tag for name
|
||||
// mapping and a function to provide a basic mapping of fields to names.
|
||||
type Mapper struct {
|
||||
cache map[reflect.Type]fieldMap
|
||||
tagName string
|
||||
mapFunc func(string) string
|
||||
mutex sync.Mutex
|
||||
// A FieldInfo is metadata for a struct field.
|
||||
type FieldInfo struct {
|
||||
Index []int
|
||||
Path string
|
||||
Field reflect.StructField
|
||||
Zero reflect.Value
|
||||
Name string
|
||||
Options map[string]string
|
||||
Embedded bool
|
||||
Children []*FieldInfo
|
||||
Parent *FieldInfo
|
||||
}
|
||||
|
||||
// NewMapper returns a new mapper which optionally obeys the field tag given
|
||||
// by tagName. If tagName is the empty string, it is ignored.
|
||||
// A StructMap is an index of field metadata for a struct.
|
||||
type StructMap struct {
|
||||
Tree *FieldInfo
|
||||
Index []*FieldInfo
|
||||
Paths map[string]*FieldInfo
|
||||
Names map[string]*FieldInfo
|
||||
}
|
||||
|
||||
// GetByPath returns a *FieldInfo for a given string path.
|
||||
func (f StructMap) GetByPath(path string) *FieldInfo {
|
||||
return f.Paths[path]
|
||||
}
|
||||
|
||||
// GetByTraversal returns a *FieldInfo for a given integer path. It is
|
||||
// analogous to reflect.FieldByIndex, but using the cached traversal
|
||||
// rather than re-executing the reflect machinery each time.
|
||||
func (f StructMap) GetByTraversal(index []int) *FieldInfo {
|
||||
if len(index) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
tree := f.Tree
|
||||
for _, i := range index {
|
||||
if i >= len(tree.Children) || tree.Children[i] == nil {
|
||||
return nil
|
||||
}
|
||||
tree = tree.Children[i]
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
// Mapper is a general purpose mapper of names to struct fields. A Mapper
|
||||
// behaves like most marshallers in the standard library, obeying a field tag
|
||||
// for name mapping but also providing a basic transform function.
|
||||
type Mapper struct {
|
||||
cache map[reflect.Type]*StructMap
|
||||
tagName string
|
||||
tagMapFunc func(string) string
|
||||
mapFunc func(string) string
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// NewMapper returns a new mapper using the tagName as its struct field tag.
|
||||
// If tagName is the empty string, it is ignored.
|
||||
func NewMapper(tagName string) *Mapper {
|
||||
return &Mapper{
|
||||
cache: make(map[reflect.Type]fieldMap),
|
||||
cache: make(map[reflect.Type]*StructMap),
|
||||
tagName: tagName,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMapperTagFunc returns a new mapper which contains a mapper for field names
|
||||
// AND a mapper for tag values. This is useful for tags like json which can
|
||||
// have values like "name,omitempty".
|
||||
func NewMapperTagFunc(tagName string, mapFunc, tagMapFunc func(string) string) *Mapper {
|
||||
return &Mapper{
|
||||
cache: make(map[reflect.Type]*StructMap),
|
||||
tagName: tagName,
|
||||
mapFunc: mapFunc,
|
||||
tagMapFunc: tagMapFunc,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMapperFunc returns a new mapper which optionally obeys a field tag and
|
||||
// a struct field name mapper func given by f. Tags will take precedence, but
|
||||
// for any other field, the mapped name will be f(field.Name)
|
||||
func NewMapperFunc(tagName string, f func(string) string) *Mapper {
|
||||
return &Mapper{
|
||||
cache: make(map[reflect.Type]fieldMap),
|
||||
cache: make(map[reflect.Type]*StructMap),
|
||||
tagName: tagName,
|
||||
mapFunc: f,
|
||||
}
|
||||
@@ -47,11 +102,11 @@ func NewMapperFunc(tagName string, f func(string) string) *Mapper {
|
||||
|
||||
// TypeMap returns a mapping of field strings to int slices representing
|
||||
// the traversal down the struct to reach the field.
|
||||
func (m *Mapper) TypeMap(t reflect.Type) fieldMap {
|
||||
func (m *Mapper) TypeMap(t reflect.Type) *StructMap {
|
||||
m.mutex.Lock()
|
||||
mapping, ok := m.cache[t]
|
||||
if !ok {
|
||||
mapping = getMapping(t, m.tagName, m.mapFunc)
|
||||
mapping = getMapping(t, m.tagName, m.mapFunc, m.tagMapFunc)
|
||||
m.cache[t] = mapping
|
||||
}
|
||||
m.mutex.Unlock()
|
||||
@@ -65,26 +120,26 @@ func (m *Mapper) FieldMap(v reflect.Value) map[string]reflect.Value {
|
||||
mustBe(v, reflect.Struct)
|
||||
|
||||
r := map[string]reflect.Value{}
|
||||
nm := m.TypeMap(v.Type())
|
||||
for tagName, indexes := range nm {
|
||||
r[tagName] = FieldByIndexes(v, indexes)
|
||||
tm := m.TypeMap(v.Type())
|
||||
for tagName, fi := range tm.Names {
|
||||
r[tagName] = FieldByIndexes(v, fi.Index)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// FieldByName returns a field by the its mapped name as a reflect.Value.
|
||||
// FieldByName returns a field by its mapped name as a reflect.Value.
|
||||
// Panics if v's Kind is not Struct or v is not Indirectable to a struct Kind.
|
||||
// Returns zero Value if the name is not found.
|
||||
func (m *Mapper) FieldByName(v reflect.Value, name string) reflect.Value {
|
||||
v = reflect.Indirect(v)
|
||||
mustBe(v, reflect.Struct)
|
||||
|
||||
nm := m.TypeMap(v.Type())
|
||||
traversal, ok := nm[name]
|
||||
tm := m.TypeMap(v.Type())
|
||||
fi, ok := tm.Names[name]
|
||||
if !ok {
|
||||
return *new(reflect.Value)
|
||||
return v
|
||||
}
|
||||
return FieldByIndexes(v, traversal)
|
||||
return FieldByIndexes(v, fi.Index)
|
||||
}
|
||||
|
||||
// FieldsByName returns a slice of values corresponding to the slice of names
|
||||
@@ -94,45 +149,64 @@ func (m *Mapper) FieldsByName(v reflect.Value, names []string) []reflect.Value {
|
||||
v = reflect.Indirect(v)
|
||||
mustBe(v, reflect.Struct)
|
||||
|
||||
nm := m.TypeMap(v.Type())
|
||||
|
||||
tm := m.TypeMap(v.Type())
|
||||
vals := make([]reflect.Value, 0, len(names))
|
||||
for _, name := range names {
|
||||
traversal, ok := nm[name]
|
||||
fi, ok := tm.Names[name]
|
||||
if !ok {
|
||||
vals = append(vals, *new(reflect.Value))
|
||||
} else {
|
||||
vals = append(vals, FieldByIndexes(v, traversal))
|
||||
vals = append(vals, FieldByIndexes(v, fi.Index))
|
||||
}
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// Traversals by name returns a slice of int slices which represent the struct
|
||||
// TraversalsByName returns a slice of int slices which represent the struct
|
||||
// traversals for each mapped name. Panics if t is not a struct or Indirectable
|
||||
// to a struct. Returns empty int slice for each name not found.
|
||||
func (m *Mapper) TraversalsByName(t reflect.Type, names []string) [][]int {
|
||||
t = Deref(t)
|
||||
mustBe(t, reflect.Struct)
|
||||
nm := m.TypeMap(t)
|
||||
|
||||
r := make([][]int, 0, len(names))
|
||||
for _, name := range names {
|
||||
traversal, ok := nm[name]
|
||||
if !ok {
|
||||
m.TraversalsByNameFunc(t, names, func(_ int, i []int) error {
|
||||
if i == nil {
|
||||
r = append(r, []int{})
|
||||
} else {
|
||||
r = append(r, traversal)
|
||||
r = append(r, i)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
// FieldByIndexes returns a value for a particular struct traversal.
|
||||
// TraversalsByNameFunc traverses the mapped names and calls fn with the index of
|
||||
// each name and the struct traversal represented by that name. Panics if t is not
|
||||
// a struct or Indirectable to a struct. Returns the first error returned by fn or nil.
|
||||
func (m *Mapper) TraversalsByNameFunc(t reflect.Type, names []string, fn func(int, []int) error) error {
|
||||
t = Deref(t)
|
||||
mustBe(t, reflect.Struct)
|
||||
tm := m.TypeMap(t)
|
||||
for i, name := range names {
|
||||
fi, ok := tm.Names[name]
|
||||
if !ok {
|
||||
if err := fn(i, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := fn(i, fi.Index); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FieldByIndexes returns a value for the field given by the struct traversal
|
||||
// for the given value.
|
||||
func FieldByIndexes(v reflect.Value, indexes []int) reflect.Value {
|
||||
for _, i := range indexes {
|
||||
v = reflect.Indirect(v).Field(i)
|
||||
// if this is a pointer, it's possible it is nil
|
||||
// if this is a pointer and it's nil, allocate a new value and set it
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
alloc := reflect.New(Deref(v.Type()))
|
||||
v.Set(alloc)
|
||||
@@ -164,20 +238,19 @@ func Deref(t reflect.Type) reflect.Type {
|
||||
|
||||
// -- helpers & utilities --
|
||||
|
||||
type Kinder interface {
|
||||
type kinder interface {
|
||||
Kind() reflect.Kind
|
||||
}
|
||||
|
||||
// mustBe checks a value against a kind, panicing with a reflect.ValueError
|
||||
// if the kind isn't that which is required.
|
||||
func mustBe(v Kinder, expected reflect.Kind) {
|
||||
k := v.Kind()
|
||||
if k != expected {
|
||||
func mustBe(v kinder, expected reflect.Kind) {
|
||||
if k := v.Kind(); k != expected {
|
||||
panic(&reflect.ValueError{Method: methodName(), Kind: k})
|
||||
}
|
||||
}
|
||||
|
||||
// methodName is returns the caller of the function calling methodName
|
||||
// methodName returns the caller of the function calling methodName
|
||||
func methodName() string {
|
||||
pc, _, _, _ := runtime.Caller(2)
|
||||
f := runtime.FuncForPC(pc)
|
||||
@@ -188,8 +261,9 @@ func methodName() string {
|
||||
}
|
||||
|
||||
type typeQueue struct {
|
||||
t reflect.Type
|
||||
p []int
|
||||
t reflect.Type
|
||||
fi *FieldInfo
|
||||
pp string // Parent path
|
||||
}
|
||||
|
||||
// A copying append that creates a new slice each time.
|
||||
@@ -202,52 +276,166 @@ func apnd(is []int, i int) []int {
|
||||
return x
|
||||
}
|
||||
|
||||
// getMapping returns a mapping for the t type, using the tagName and the mapFunc
|
||||
// to determine the canonical names of fields.
|
||||
func getMapping(t reflect.Type, tagName string, mapFunc func(string) string) fieldMap {
|
||||
type mapf func(string) string
|
||||
|
||||
// parseName parses the tag and the target name for the given field using
|
||||
// the tagName (eg 'json' for `json:"foo"` tags), mapFunc for mapping the
|
||||
// field's name to a target name, and tagMapFunc for mapping the tag to
|
||||
// a target name.
|
||||
func parseName(field reflect.StructField, tagName string, mapFunc, tagMapFunc mapf) (tag, fieldName string) {
|
||||
// first, set the fieldName to the field's name
|
||||
fieldName = field.Name
|
||||
// if a mapFunc is set, use that to override the fieldName
|
||||
if mapFunc != nil {
|
||||
fieldName = mapFunc(fieldName)
|
||||
}
|
||||
|
||||
// if there's no tag to look for, return the field name
|
||||
if tagName == "" {
|
||||
return "", fieldName
|
||||
}
|
||||
|
||||
// if this tag is not set using the normal convention in the tag,
|
||||
// then return the fieldname.. this check is done because according
|
||||
// to the reflect documentation:
|
||||
// If the tag does not have the conventional format,
|
||||
// the value returned by Get is unspecified.
|
||||
// which doesn't sound great.
|
||||
if !strings.Contains(string(field.Tag), tagName+":") {
|
||||
return "", fieldName
|
||||
}
|
||||
|
||||
// at this point we're fairly sure that we have a tag, so lets pull it out
|
||||
tag = field.Tag.Get(tagName)
|
||||
|
||||
// if we have a mapper function, call it on the whole tag
|
||||
// XXX: this is a change from the old version, which pulled out the name
|
||||
// before the tagMapFunc could be run, but I think this is the right way
|
||||
if tagMapFunc != nil {
|
||||
tag = tagMapFunc(tag)
|
||||
}
|
||||
|
||||
// finally, split the options from the name
|
||||
parts := strings.Split(tag, ",")
|
||||
fieldName = parts[0]
|
||||
|
||||
return tag, fieldName
|
||||
}
|
||||
|
||||
// parseOptions parses options out of a tag string, skipping the name
|
||||
func parseOptions(tag string) map[string]string {
|
||||
parts := strings.Split(tag, ",")
|
||||
options := make(map[string]string, len(parts))
|
||||
if len(parts) > 1 {
|
||||
for _, opt := range parts[1:] {
|
||||
// short circuit potentially expensive split op
|
||||
if strings.Contains(opt, "=") {
|
||||
kv := strings.Split(opt, "=")
|
||||
options[kv[0]] = kv[1]
|
||||
continue
|
||||
}
|
||||
options[opt] = ""
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
// getMapping returns a mapping for the t type, using the tagName, mapFunc and
|
||||
// tagMapFunc to determine the canonical names of fields.
|
||||
func getMapping(t reflect.Type, tagName string, mapFunc, tagMapFunc mapf) *StructMap {
|
||||
m := []*FieldInfo{}
|
||||
|
||||
root := &FieldInfo{}
|
||||
queue := []typeQueue{}
|
||||
queue = append(queue, typeQueue{Deref(t), []int{}})
|
||||
m := fieldMap{}
|
||||
queue = append(queue, typeQueue{Deref(t), root, ""})
|
||||
|
||||
QueueLoop:
|
||||
for len(queue) != 0 {
|
||||
// pop the first item off of the queue
|
||||
tq := queue[0]
|
||||
queue = queue[1:]
|
||||
|
||||
// ignore recursive field
|
||||
for p := tq.fi.Parent; p != nil; p = p.Parent {
|
||||
if tq.fi.Field.Type == p.Field.Type {
|
||||
continue QueueLoop
|
||||
}
|
||||
}
|
||||
|
||||
nChildren := 0
|
||||
if tq.t.Kind() == reflect.Struct {
|
||||
nChildren = tq.t.NumField()
|
||||
}
|
||||
tq.fi.Children = make([]*FieldInfo, nChildren)
|
||||
|
||||
// iterate through all of its fields
|
||||
for fieldPos := 0; fieldPos < tq.t.NumField(); fieldPos++ {
|
||||
for fieldPos := 0; fieldPos < nChildren; fieldPos++ {
|
||||
|
||||
f := tq.t.Field(fieldPos)
|
||||
|
||||
name := f.Tag.Get(tagName)
|
||||
if len(name) == 0 {
|
||||
if mapFunc != nil {
|
||||
name = mapFunc(f.Name)
|
||||
} else {
|
||||
name = f.Name
|
||||
}
|
||||
}
|
||||
// parse the tag and the target name using the mapping options for this field
|
||||
tag, name := parseName(f, tagName, mapFunc, tagMapFunc)
|
||||
|
||||
// if the name is "-", disabled via a tag, skip it
|
||||
if name == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
fi := FieldInfo{
|
||||
Field: f,
|
||||
Name: name,
|
||||
Zero: reflect.New(f.Type).Elem(),
|
||||
Options: parseOptions(tag),
|
||||
}
|
||||
|
||||
// if the path is empty this path is just the name
|
||||
if tq.pp == "" {
|
||||
fi.Path = fi.Name
|
||||
} else {
|
||||
fi.Path = tq.pp + "." + fi.Name
|
||||
}
|
||||
|
||||
// skip unexported fields
|
||||
if len(f.PkgPath) != 0 {
|
||||
if len(f.PkgPath) != 0 && !f.Anonymous {
|
||||
continue
|
||||
}
|
||||
|
||||
// bfs search of anonymous embedded structs
|
||||
if f.Anonymous {
|
||||
queue = append(queue, typeQueue{Deref(f.Type), apnd(tq.p, fieldPos)})
|
||||
continue
|
||||
pp := tq.pp
|
||||
if tag != "" {
|
||||
pp = fi.Path
|
||||
}
|
||||
|
||||
fi.Embedded = true
|
||||
fi.Index = apnd(tq.fi.Index, fieldPos)
|
||||
nChildren := 0
|
||||
ft := Deref(f.Type)
|
||||
if ft.Kind() == reflect.Struct {
|
||||
nChildren = ft.NumField()
|
||||
}
|
||||
fi.Children = make([]*FieldInfo, nChildren)
|
||||
queue = append(queue, typeQueue{Deref(f.Type), &fi, pp})
|
||||
} else if fi.Zero.Kind() == reflect.Struct || (fi.Zero.Kind() == reflect.Ptr && fi.Zero.Type().Elem().Kind() == reflect.Struct) {
|
||||
fi.Index = apnd(tq.fi.Index, fieldPos)
|
||||
fi.Children = make([]*FieldInfo, Deref(f.Type).NumField())
|
||||
queue = append(queue, typeQueue{Deref(f.Type), &fi, fi.Path})
|
||||
}
|
||||
|
||||
// if the name is shadowed by an earlier identical name in the search, skip it
|
||||
if _, ok := m[name]; ok {
|
||||
continue
|
||||
}
|
||||
// add it to the map at the current position
|
||||
m[name] = apnd(tq.p, fieldPos)
|
||||
fi.Index = apnd(tq.fi.Index, fieldPos)
|
||||
fi.Parent = tq.fi
|
||||
tq.fi.Children[fieldPos] = &fi
|
||||
m = append(m, &fi)
|
||||
}
|
||||
}
|
||||
return m
|
||||
|
||||
flds := &StructMap{Index: m, Tree: root, Paths: map[string]*FieldInfo{}, Names: map[string]*FieldInfo{}}
|
||||
for _, fi := range flds.Index {
|
||||
flds.Paths[fi.Path] = fi
|
||||
if fi.Name != "" && !fi.Embedded {
|
||||
flds.Names[fi.Path] = fi
|
||||
}
|
||||
}
|
||||
|
||||
return flds
|
||||
}
|
||||
|
||||
139
vendor/github.com/jmoiron/sqlx/sqlx.go
generated
vendored
139
vendor/github.com/jmoiron/sqlx/sqlx.go
generated
vendored
@@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/jmoiron/sqlx/reflectx"
|
||||
)
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
// 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 overridded by your user's application.
|
||||
// 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
|
||||
@@ -30,8 +31,14 @@ var origMapper = reflect.ValueOf(NameMapper)
|
||||
// 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) {
|
||||
@@ -58,7 +65,7 @@ func isScannable(t reflect.Type) bool {
|
||||
// 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)) == 0 {
|
||||
if len(m.TypeMap(t).Index) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -105,29 +112,35 @@ type Preparer interface {
|
||||
|
||||
// determine if any of our extensions are unsafe
|
||||
func isUnsafe(i interface{}) bool {
|
||||
switch i.(type) {
|
||||
switch v := i.(type) {
|
||||
case Row:
|
||||
return i.(Row).unsafe
|
||||
return v.unsafe
|
||||
case *Row:
|
||||
return i.(*Row).unsafe
|
||||
return v.unsafe
|
||||
case Rows:
|
||||
return i.(Rows).unsafe
|
||||
return v.unsafe
|
||||
case *Rows:
|
||||
return i.(*Rows).unsafe
|
||||
return v.unsafe
|
||||
case NamedStmt:
|
||||
return v.Stmt.unsafe
|
||||
case *NamedStmt:
|
||||
return v.Stmt.unsafe
|
||||
case Stmt:
|
||||
return i.(Stmt).unsafe
|
||||
return v.unsafe
|
||||
case *Stmt:
|
||||
return v.unsafe
|
||||
case qStmt:
|
||||
return i.(qStmt).Stmt.unsafe
|
||||
return v.unsafe
|
||||
case *qStmt:
|
||||
return i.(*qStmt).Stmt.unsafe
|
||||
return v.unsafe
|
||||
case DB:
|
||||
return i.(DB).unsafe
|
||||
return v.unsafe
|
||||
case *DB:
|
||||
return i.(*DB).unsafe
|
||||
return v.unsafe
|
||||
case Tx:
|
||||
return i.(Tx).unsafe
|
||||
return v.unsafe
|
||||
case *Tx:
|
||||
return i.(*Tx).unsafe
|
||||
return v.unsafe
|
||||
case sql.Rows, *sql.Rows:
|
||||
return false
|
||||
default:
|
||||
@@ -215,6 +228,14 @@ func (r *Row) Columns() ([]string, error) {
|
||||
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
|
||||
@@ -279,25 +300,30 @@ func (db *DB) Unsafe() *DB {
|
||||
|
||||
// BindNamed binds a query using the DB driver's bindvar type.
|
||||
func (db *DB) BindNamed(query string, arg interface{}) (string, []interface{}, error) {
|
||||
return BindNamed(BindType(db.driverName), query, arg)
|
||||
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...)
|
||||
}
|
||||
@@ -322,6 +348,7 @@ func (db *DB) Beginx() (*Tx, error) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -331,12 +358,14 @@ func (db *DB) Queryx(query string, args ...interface{}) (*Rows, error) {
|
||||
}
|
||||
|
||||
// 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...)
|
||||
}
|
||||
@@ -377,25 +406,29 @@ func (tx *Tx) Unsafe() *Tx {
|
||||
|
||||
// BindNamed binds a query within a transaction's bindvar type.
|
||||
func (tx *Tx) BindNamed(query string, arg interface{}) (string, []interface{}, error) {
|
||||
return BindNamed(BindType(tx.driverName), query, arg)
|
||||
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 {
|
||||
@@ -405,17 +438,21 @@ func (tx *Tx) Queryx(query string, args ...interface{}) (*Rows, error) {
|
||||
}
|
||||
|
||||
// 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...)
|
||||
}
|
||||
@@ -428,18 +465,18 @@ func (tx *Tx) Preparex(query string) (*Stmt, error) {
|
||||
// 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 st sql.Stmt
|
||||
var s *sql.Stmt
|
||||
switch stmt.(type) {
|
||||
case sql.Stmt:
|
||||
st = stmt.(sql.Stmt)
|
||||
s = &st
|
||||
switch v := stmt.(type) {
|
||||
case Stmt:
|
||||
s = stmt.(Stmt).Stmt
|
||||
s = v.Stmt
|
||||
case *Stmt:
|
||||
s = stmt.(*Stmt).Stmt
|
||||
s = v.Stmt
|
||||
case sql.Stmt:
|
||||
s = &v
|
||||
case *sql.Stmt:
|
||||
s = stmt.(*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}
|
||||
}
|
||||
@@ -472,36 +509,42 @@ func (s *Stmt) Unsafe() *Stmt {
|
||||
}
|
||||
|
||||
// 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...)
|
||||
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...)
|
||||
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...)
|
||||
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}
|
||||
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}
|
||||
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 }
|
||||
type qStmt struct{ *Stmt }
|
||||
|
||||
func (q *qStmt) Query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||
return q.Stmt.Query(args...)
|
||||
@@ -558,7 +601,7 @@ func (r *Rows) StructScan(dest interface{}) error {
|
||||
return errors.New("must pass a pointer, not a value, to StructScan destination")
|
||||
}
|
||||
|
||||
v = reflect.Indirect(v)
|
||||
v = v.Elem()
|
||||
|
||||
if !r.started {
|
||||
columns, err := r.Columns()
|
||||
@@ -570,7 +613,7 @@ func (r *Rows) StructScan(dest interface{}) error {
|
||||
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", columns[f])
|
||||
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
|
||||
}
|
||||
r.values = make([]interface{}, len(columns))
|
||||
r.started = true
|
||||
@@ -592,10 +635,14 @@ func (r *Rows) StructScan(dest interface{}) error {
|
||||
func Connect(driverName, dataSourceName string) (*DB, error) {
|
||||
db, err := Open(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return db, err
|
||||
return nil, err
|
||||
}
|
||||
err = db.Ping()
|
||||
return db, err
|
||||
if err != nil {
|
||||
db.Close()
|
||||
return nil, err
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// MustConnect connects to a database and panics on error.
|
||||
@@ -620,6 +667,7 @@ func Preparex(p Preparer, query string) (*Stmt, error) {
|
||||
// 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 {
|
||||
@@ -633,6 +681,8 @@ func Select(q Queryer, dest interface{}, query string, args ...interface{}) erro
|
||||
// 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)
|
||||
@@ -663,6 +713,7 @@ func LoadFile(e Execer, path string) (*sql.Result, error) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -685,6 +736,10 @@ 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)
|
||||
@@ -720,7 +775,7 @@ func (r *Row) scanAny(dest interface{}, structOnly bool) error {
|
||||
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", columns[f])
|
||||
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
|
||||
}
|
||||
values := make([]interface{}, len(columns))
|
||||
|
||||
@@ -738,7 +793,7 @@ func (r *Row) StructScan(dest interface{}) error {
|
||||
}
|
||||
|
||||
// SliceScan a row, returning a []interface{} with values similar to MapScan.
|
||||
// This function is primarly intended for use where the number of columns
|
||||
// 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.
|
||||
@@ -773,7 +828,7 @@ func SliceScan(r ColScanner) ([]interface{}, error) {
|
||||
// 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
|
||||
// eachother!
|
||||
// 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()
|
||||
@@ -886,7 +941,7 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
|
||||
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", columns[f])
|
||||
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
|
||||
}
|
||||
values = make([]interface{}, len(columns))
|
||||
|
||||
@@ -896,6 +951,9 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
|
||||
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...)
|
||||
@@ -913,6 +971,9 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
|
||||
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))
|
||||
@@ -931,7 +992,7 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
|
||||
// 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 need do not want to
|
||||
// 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 {
|
||||
|
||||
348
vendor/github.com/jmoiron/sqlx/sqlx_context.go
generated
vendored
Normal file
348
vendor/github.com/jmoiron/sqlx/sqlx_context.go
generated
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
// +build go1.8
|
||||
|
||||
package sqlx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ConnectContext to a database and verify with a ping.
|
||||
func ConnectContext(ctx context.Context, driverName, dataSourceName string) (*DB, error) {
|
||||
db, err := Open(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return db, err
|
||||
}
|
||||
err = db.PingContext(ctx)
|
||||
return db, err
|
||||
}
|
||||
|
||||
// QueryerContext is an interface used by GetContext and SelectContext
|
||||
type QueryerContext interface {
|
||||
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
|
||||
QueryxContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)
|
||||
QueryRowxContext(ctx context.Context, query string, args ...interface{}) *Row
|
||||
}
|
||||
|
||||
// PreparerContext is an interface used by PreparexContext.
|
||||
type PreparerContext interface {
|
||||
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
|
||||
}
|
||||
|
||||
// ExecerContext is an interface used by MustExecContext and LoadFileContext
|
||||
type ExecerContext interface {
|
||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||
}
|
||||
|
||||
// ExtContext is a union interface which can bind, query, and exec, with Context
|
||||
// used by NamedQueryContext and NamedExecContext.
|
||||
type ExtContext interface {
|
||||
binder
|
||||
QueryerContext
|
||||
ExecerContext
|
||||
}
|
||||
|
||||
// SelectContext 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 SelectContext(ctx context.Context, q QueryerContext, dest interface{}, query string, args ...interface{}) error {
|
||||
rows, err := q.QueryxContext(ctx, 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)
|
||||
}
|
||||
|
||||
// PreparexContext prepares a statement.
|
||||
//
|
||||
// The provided context is used for the preparation of the statement, not for
|
||||
// the execution of the statement.
|
||||
func PreparexContext(ctx context.Context, p PreparerContext, query string) (*Stmt, error) {
|
||||
s, err := p.PrepareContext(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Stmt{Stmt: s, unsafe: isUnsafe(p), Mapper: mapperFor(p)}, err
|
||||
}
|
||||
|
||||
// GetContext 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 GetContext(ctx context.Context, q QueryerContext, dest interface{}, query string, args ...interface{}) error {
|
||||
r := q.QueryRowxContext(ctx, query, args...)
|
||||
return r.scanAny(dest, false)
|
||||
}
|
||||
|
||||
// LoadFileContext exec's every statement in a file (as a single call to Exec).
|
||||
// LoadFileContext 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 LoadFileContext(ctx context.Context, e ExecerContext, 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.ExecContext(ctx, string(contents))
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// MustExecContext execs the query using e and panics if there was an error.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func MustExecContext(ctx context.Context, e ExecerContext, query string, args ...interface{}) sql.Result {
|
||||
res, err := e.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// PrepareNamedContext returns an sqlx.NamedStmt
|
||||
func (db *DB) PrepareNamedContext(ctx context.Context, query string) (*NamedStmt, error) {
|
||||
return prepareNamedContext(ctx, db, query)
|
||||
}
|
||||
|
||||
// NamedQueryContext using this DB.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (db *DB) NamedQueryContext(ctx context.Context, query string, arg interface{}) (*Rows, error) {
|
||||
return NamedQueryContext(ctx, db, query, arg)
|
||||
}
|
||||
|
||||
// NamedExecContext using this DB.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (db *DB) NamedExecContext(ctx context.Context, query string, arg interface{}) (sql.Result, error) {
|
||||
return NamedExecContext(ctx, db, query, arg)
|
||||
}
|
||||
|
||||
// SelectContext using this DB.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (db *DB) SelectContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error {
|
||||
return SelectContext(ctx, db, dest, query, args...)
|
||||
}
|
||||
|
||||
// GetContext using this DB.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
// An error is returned if the result set is empty.
|
||||
func (db *DB) GetContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error {
|
||||
return GetContext(ctx, db, dest, query, args...)
|
||||
}
|
||||
|
||||
// PreparexContext returns an sqlx.Stmt instead of a sql.Stmt.
|
||||
//
|
||||
// The provided context is used for the preparation of the statement, not for
|
||||
// the execution of the statement.
|
||||
func (db *DB) PreparexContext(ctx context.Context, query string) (*Stmt, error) {
|
||||
return PreparexContext(ctx, db, query)
|
||||
}
|
||||
|
||||
// QueryxContext queries the database and returns an *sqlx.Rows.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (db *DB) QueryxContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
|
||||
r, err := db.DB.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{Rows: r, unsafe: db.unsafe, Mapper: db.Mapper}, err
|
||||
}
|
||||
|
||||
// QueryRowxContext queries the database and returns an *sqlx.Row.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (db *DB) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *Row {
|
||||
rows, err := db.DB.QueryContext(ctx, query, args...)
|
||||
return &Row{rows: rows, err: err, unsafe: db.unsafe, Mapper: db.Mapper}
|
||||
}
|
||||
|
||||
// MustBeginTx starts a transaction, and panics on error. Returns an *sqlx.Tx instead
|
||||
// of an *sql.Tx.
|
||||
//
|
||||
// The provided context is used until the transaction is committed or rolled
|
||||
// back. If the context is canceled, the sql package will roll back the
|
||||
// transaction. Tx.Commit will return an error if the context provided to
|
||||
// MustBeginContext is canceled.
|
||||
func (db *DB) MustBeginTx(ctx context.Context, opts *sql.TxOptions) *Tx {
|
||||
tx, err := db.BeginTxx(ctx, opts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tx
|
||||
}
|
||||
|
||||
// MustExecContext (panic) runs MustExec using this database.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (db *DB) MustExecContext(ctx context.Context, query string, args ...interface{}) sql.Result {
|
||||
return MustExecContext(ctx, db, query, args...)
|
||||
}
|
||||
|
||||
// BeginTxx begins a transaction and returns an *sqlx.Tx instead of an
|
||||
// *sql.Tx.
|
||||
//
|
||||
// The provided context is used until the transaction is committed or rolled
|
||||
// back. If the context is canceled, the sql package will roll back the
|
||||
// transaction. Tx.Commit will return an error if the context provided to
|
||||
// BeginxContext is canceled.
|
||||
func (db *DB) BeginTxx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
|
||||
tx, err := db.DB.BeginTx(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Tx{Tx: tx, driverName: db.driverName, unsafe: db.unsafe, Mapper: db.Mapper}, err
|
||||
}
|
||||
|
||||
// StmtxContext 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) StmtxContext(ctx context.Context, 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.StmtContext(ctx, s), Mapper: tx.Mapper}
|
||||
}
|
||||
|
||||
// NamedStmtContext returns a version of the prepared statement which runs
|
||||
// within a transaction.
|
||||
func (tx *Tx) NamedStmtContext(ctx context.Context, stmt *NamedStmt) *NamedStmt {
|
||||
return &NamedStmt{
|
||||
QueryString: stmt.QueryString,
|
||||
Params: stmt.Params,
|
||||
Stmt: tx.StmtxContext(ctx, stmt.Stmt),
|
||||
}
|
||||
}
|
||||
|
||||
// PreparexContext returns an sqlx.Stmt instead of a sql.Stmt.
|
||||
//
|
||||
// The provided context is used for the preparation of the statement, not for
|
||||
// the execution of the statement.
|
||||
func (tx *Tx) PreparexContext(ctx context.Context, query string) (*Stmt, error) {
|
||||
return PreparexContext(ctx, tx, query)
|
||||
}
|
||||
|
||||
// PrepareNamedContext returns an sqlx.NamedStmt
|
||||
func (tx *Tx) PrepareNamedContext(ctx context.Context, query string) (*NamedStmt, error) {
|
||||
return prepareNamedContext(ctx, tx, query)
|
||||
}
|
||||
|
||||
// MustExecContext runs MustExecContext within a transaction.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (tx *Tx) MustExecContext(ctx context.Context, query string, args ...interface{}) sql.Result {
|
||||
return MustExecContext(ctx, tx, query, args...)
|
||||
}
|
||||
|
||||
// QueryxContext within a transaction and context.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (tx *Tx) QueryxContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
|
||||
r, err := tx.Tx.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{Rows: r, unsafe: tx.unsafe, Mapper: tx.Mapper}, err
|
||||
}
|
||||
|
||||
// SelectContext within a transaction and context.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (tx *Tx) SelectContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error {
|
||||
return SelectContext(ctx, tx, dest, query, args...)
|
||||
}
|
||||
|
||||
// GetContext within a transaction and context.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
// An error is returned if the result set is empty.
|
||||
func (tx *Tx) GetContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error {
|
||||
return GetContext(ctx, tx, dest, query, args...)
|
||||
}
|
||||
|
||||
// QueryRowxContext within a transaction and context.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (tx *Tx) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *Row {
|
||||
rows, err := tx.Tx.QueryContext(ctx, query, args...)
|
||||
return &Row{rows: rows, err: err, unsafe: tx.unsafe, Mapper: tx.Mapper}
|
||||
}
|
||||
|
||||
// NamedExecContext using this Tx.
|
||||
// Any named placeholder parameters are replaced with fields from arg.
|
||||
func (tx *Tx) NamedExecContext(ctx context.Context, query string, arg interface{}) (sql.Result, error) {
|
||||
return NamedExecContext(ctx, tx, query, arg)
|
||||
}
|
||||
|
||||
// SelectContext using the prepared statement.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (s *Stmt) SelectContext(ctx context.Context, dest interface{}, args ...interface{}) error {
|
||||
return SelectContext(ctx, &qStmt{s}, dest, "", args...)
|
||||
}
|
||||
|
||||
// GetContext 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) GetContext(ctx context.Context, dest interface{}, args ...interface{}) error {
|
||||
return GetContext(ctx, &qStmt{s}, dest, "", args...)
|
||||
}
|
||||
|
||||
// MustExecContext (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) MustExecContext(ctx context.Context, args ...interface{}) sql.Result {
|
||||
return MustExecContext(ctx, &qStmt{s}, "", args...)
|
||||
}
|
||||
|
||||
// QueryRowxContext using this statement.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (s *Stmt) QueryRowxContext(ctx context.Context, args ...interface{}) *Row {
|
||||
qs := &qStmt{s}
|
||||
return qs.QueryRowxContext(ctx, "", args...)
|
||||
}
|
||||
|
||||
// QueryxContext using this statement.
|
||||
// Any placeholder parameters are replaced with supplied args.
|
||||
func (s *Stmt) QueryxContext(ctx context.Context, args ...interface{}) (*Rows, error) {
|
||||
qs := &qStmt{s}
|
||||
return qs.QueryxContext(ctx, "", args...)
|
||||
}
|
||||
|
||||
func (q *qStmt) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
|
||||
return q.Stmt.QueryContext(ctx, args...)
|
||||
}
|
||||
|
||||
func (q *qStmt) QueryxContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
|
||||
r, err := q.Stmt.QueryContext(ctx, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{Rows: r, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper}, err
|
||||
}
|
||||
|
||||
func (q *qStmt) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *Row {
|
||||
rows, err := q.Stmt.QueryContext(ctx, args...)
|
||||
return &Row{rows: rows, err: err, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper}
|
||||
}
|
||||
|
||||
func (q *qStmt) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||||
return q.Stmt.ExecContext(ctx, args...)
|
||||
}
|
||||
Reference in New Issue
Block a user