aboutsummaryrefslogtreecommitdiff
path: root/src/database/sql/sql_test.go
diff options
context:
space:
mode:
authorJack Christensen <jack@jackchristensen.com>2025-05-31 15:27:15 +0000
committerSean Liao <sean@liao.dev>2025-08-11 14:27:36 -0700
commit3dbef65bf37f1b7ccd1f884761341a5a15456ffa (patch)
treeaf9f6a80091cf86f6d029849e9de220d231724a1 /src/database/sql/sql_test.go
parent2b804abf0712d45801671232585e0011902a5c48 (diff)
downloadgo-3dbef65bf37f1b7ccd1f884761341a5a15456ffa.tar.xz
database/sql: allow drivers to override Scan behavior
Implementing RowsColumnScanner allows the driver to completely control how values are scanned. Fixes #67546 Change-Id: Id8e7c3a973479c9665e4476fe2d29e1255aee687 GitHub-Last-Rev: ed0cacaec4a4feead56b09c0d6eee86ed58fe1ee GitHub-Pull-Request: golang/go#67648 Reviewed-on: https://go-review.googlesource.com/c/go/+/588435 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Sean Liao <sean@liao.dev> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/database/sql/sql_test.go')
-rw-r--r--src/database/sql/sql_test.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 4750edd471..f706610b87 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -4201,6 +4201,102 @@ 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")