Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion named.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (n *NamedStmt) Select(dest interface{}, arg interface{}) error {
}
// if something happens here, we want to make sure the rows are Closed
defer rows.Close()
return scanAll(rows, dest, false)
return ScanAll(rows, dest, false)
}

// Get using this NamedStmt
Expand Down
2 changes: 1 addition & 1 deletion named_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (n *NamedStmt) SelectContext(ctx context.Context, dest interface{}, arg int
}
// if something happens here, we want to make sure the rows are Closed
defer rows.Close()
return scanAll(rows, dest, false)
return ScanAll(rows, dest, false)
}

// GetContext using this NamedStmt
Expand Down
37 changes: 24 additions & 13 deletions sqlx.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ func Select(q Queryer, dest interface{}, query string, args ...interface{}) erro
}
// if something happens here, we want to make sure the rows are Closed
defer rows.Close()
return scanAll(rows, dest, false)
return ScanAll(rows, dest, false)
}

// Get does a QueryRow using the provided Queryer, and scans the resulting row
Expand Down Expand Up @@ -746,7 +746,15 @@ func (r *Row) scanAny(dest interface{}, structOnly bool) error {
return r.err
}
defer r.rows.Close()
return ScanSingleRow(r, dest, structOnly)
}

// ScanSingleRow scans a single Row into the dest.
//
// It assumes that r is positioned on a valid row.
// If structOnly is true, an error will be returned if dest is a scannable type (for backwards compatibility with StructScan).
// Callers are responsible for closing r.
func ScanSingleRow(r ColScanner, dest interface{}, structOnly bool) error {
v := reflect.ValueOf(dest)
if v.Kind() != reflect.Ptr {
return errors.New("must pass a pointer, not a value, to StructScan destination")
Expand Down Expand Up @@ -775,11 +783,18 @@ func (r *Row) scanAny(dest interface{}, structOnly bool) error {
return r.Scan(dest)
}

m := r.Mapper

var m *reflectx.Mapper
switch rows := r.(type) {
case *Rows:
m = rows.Mapper
case *Row:
m = rows.Mapper
default:
m = 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 {
if f, err := missingFields(fields); err != nil && !isUnsafe(r) {
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
}
values := make([]interface{}, len(columns))
Expand Down Expand Up @@ -880,7 +895,7 @@ func structOnlyError(t reflect.Type) error {
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
// 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,
Expand All @@ -889,14 +904,10 @@ func structOnlyError(t reflect.Type) error {
//
// rows, _ := db.Query("select id from people;")
// var ids []int
// scanAll(rows, &ids, false)
// 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 {
// and ids will be a list of the id results.
func ScanAll(rows rowsi, dest interface{}, structOnly bool) error {
var v, vp reflect.Value

value := reflect.ValueOf(dest)
Expand Down Expand Up @@ -1003,7 +1014,7 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
// 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)
return ScanAll(rows, dest, true)

}

Expand Down
2 changes: 1 addition & 1 deletion sqlx_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func SelectContext(ctx context.Context, q QueryerContext, dest interface{}, quer
}
// if something happens here, we want to make sure the rows are Closed
defer rows.Close()
return scanAll(rows, dest, false)
return ScanAll(rows, dest, false)
}

// PreparexContext prepares a statement.
Expand Down
2 changes: 1 addition & 1 deletion sqlx_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ func TestUsageContext(t *testing.T) {
if err != nil {
t.Error(err)
}
err = scanAll(rows, &sdest, false)
err = ScanAll(rows, &sdest, false)
if err != nil {
t.Error(err)
}
Expand Down
Loading