mirror of
https://github.com/golang/go.git
synced 2025-12-28 06:34:04 +00:00
Revert "database/sql: allow drivers to override Scan behavior"
This reverts CL 588435. This new API is difficult to use correctly, and in many cases cannot be used efficiently. We're going to work on this problem a bit more. The release notes are removed by CL 729340, since they were moved to the x/website repository since the original CL was made. Reopens #67546. Change-Id: I2a2bd25f2fce5f02e4d28cd33a9cc651bf35ab50 Reviewed-on: https://go-review.googlesource.com/c/go/+/729360 Reviewed-by: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Sean Liao <sean@liao.dev>
This commit is contained in:
parent
89614ad264
commit
ae62a1bd36
@ -88,11 +88,6 @@ pkg crypto/x509, func OIDFromASN1OID(asn1.ObjectIdentifier) (OID, error) #75325
|
||||
pkg crypto/x509, method (ExtKeyUsage) OID() OID #75325
|
||||
pkg crypto/x509, method (ExtKeyUsage) String() string #56866
|
||||
pkg crypto/x509, method (KeyUsage) String() string #56866
|
||||
pkg database/sql/driver, type RowsColumnScanner interface { Close, Columns, Next, ScanColumn } #67546
|
||||
pkg database/sql/driver, type RowsColumnScanner interface, Close() error #67546
|
||||
pkg database/sql/driver, type RowsColumnScanner interface, Columns() []string #67546
|
||||
pkg database/sql/driver, type RowsColumnScanner interface, Next([]Value) error #67546
|
||||
pkg database/sql/driver, type RowsColumnScanner interface, ScanColumn(interface{}, int) error #67546
|
||||
pkg debug/elf, const R_LARCH_CALL36 = 110 #75562
|
||||
pkg debug/elf, const R_LARCH_CALL36 R_LARCH #75562
|
||||
pkg debug/elf, const R_LARCH_TLS_DESC32 = 13 #75562
|
||||
|
||||
@ -515,18 +515,6 @@ type RowsColumnTypePrecisionScale interface {
|
||||
ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)
|
||||
}
|
||||
|
||||
// RowsColumnScanner may be implemented by [Rows]. It allows the driver to completely
|
||||
// take responsibility for how values are scanned and replace the normal [database/sql].
|
||||
// scanning path. This allows drivers to directly support types that do not implement
|
||||
// [database/sql.Scanner].
|
||||
type RowsColumnScanner interface {
|
||||
Rows
|
||||
|
||||
// ScanColumn copies the column in the current row into the value pointed at by
|
||||
// dest. It returns [ErrSkip] to fall back to the normal [database/sql] scanning path.
|
||||
ScanColumn(dest any, index int) error
|
||||
}
|
||||
|
||||
// Tx is a transaction.
|
||||
type Tx interface {
|
||||
Commit() error
|
||||
|
||||
@ -3396,16 +3396,7 @@ func (rs *Rows) scanLocked(dest ...any) error {
|
||||
}
|
||||
|
||||
for i, sv := range rs.lastcols {
|
||||
err := driver.ErrSkip
|
||||
|
||||
if rcs, ok := rs.rowsi.(driver.RowsColumnScanner); ok {
|
||||
err = rcs.ScanColumn(dest[i], i)
|
||||
}
|
||||
|
||||
if err == driver.ErrSkip {
|
||||
err = convertAssignRows(dest[i], sv, rs)
|
||||
}
|
||||
|
||||
err := convertAssignRows(dest[i], sv, rs)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
|
||||
}
|
||||
|
||||
@ -4200,102 +4200,6 @@ func TestNamedValueCheckerSkip(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type rcsDriver struct {
|
||||
fakeDriver
|
||||
}
|
||||
|
||||
func (d *rcsDriver) Open(dsn string) (driver.Conn, error) {
|
||||
c, err := d.fakeDriver.Open(dsn)
|
||||
fc := c.(*fakeConn)
|
||||
fc.db.allowAny = true
|
||||
return &rcsConn{fc}, err
|
||||
}
|
||||
|
||||
type rcsConn struct {
|
||||
*fakeConn
|
||||
}
|
||||
|
||||
func (c *rcsConn) PrepareContext(ctx context.Context, q string) (driver.Stmt, error) {
|
||||
stmt, err := c.fakeConn.PrepareContext(ctx, q)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return &rcsStmt{stmt.(*fakeStmt)}, nil
|
||||
}
|
||||
|
||||
type rcsStmt struct {
|
||||
*fakeStmt
|
||||
}
|
||||
|
||||
func (s *rcsStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
|
||||
rows, err := s.fakeStmt.QueryContext(ctx, args)
|
||||
if err != nil {
|
||||
return rows, err
|
||||
}
|
||||
return &rcsRows{rows.(*rowsCursor)}, nil
|
||||
}
|
||||
|
||||
type rcsRows struct {
|
||||
*rowsCursor
|
||||
}
|
||||
|
||||
func (r *rcsRows) ScanColumn(dest any, index int) error {
|
||||
switch d := dest.(type) {
|
||||
case *int64:
|
||||
*d = 42
|
||||
return nil
|
||||
}
|
||||
|
||||
return driver.ErrSkip
|
||||
}
|
||||
|
||||
func TestRowsColumnScanner(t *testing.T) {
|
||||
Register("RowsColumnScanner", &rcsDriver{})
|
||||
db, err := Open("RowsColumnScanner", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
_, err = db.ExecContext(ctx, "CREATE|t|str=string,n=int64")
|
||||
if err != nil {
|
||||
t.Fatal("exec create", err)
|
||||
}
|
||||
|
||||
_, err = db.ExecContext(ctx, "INSERT|t|str=?,n=?", "foo", int64(1))
|
||||
if err != nil {
|
||||
t.Fatal("exec insert", err)
|
||||
}
|
||||
var (
|
||||
str string
|
||||
i64 int64
|
||||
i int
|
||||
f64 float64
|
||||
ui uint
|
||||
)
|
||||
err = db.QueryRowContext(ctx, "SELECT|t|str,n,n,n,n|").Scan(&str, &i64, &i, &f64, &ui)
|
||||
if err != nil {
|
||||
t.Fatal("select", err)
|
||||
}
|
||||
|
||||
list := []struct{ got, want any }{
|
||||
{str, "foo"},
|
||||
{i64, int64(42)},
|
||||
{i, int(1)},
|
||||
{f64, float64(1)},
|
||||
{ui, uint(1)},
|
||||
}
|
||||
|
||||
for index, item := range list {
|
||||
if !reflect.DeepEqual(item.got, item.want) {
|
||||
t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenConnector(t *testing.T) {
|
||||
Register("testctx", &fakeDriverCtx{})
|
||||
db, err := Open("testctx", "people")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user