Skip to content

Commit 2ca99ce

Browse files
committed
database/sql: Add RowsColumnScanner interface
Implementing RowsColumnScanner allows the driver to completely control how values are scanned. Fixes #67546
1 parent 3776465 commit 2ca99ce

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

src/database/sql/driver/driver.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,16 @@ type RowsColumnTypePrecisionScale interface {
515515
ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)
516516
}
517517

518+
// RowsColumnScanner may be implemented by [Rows]. It allows the driver to control
519+
// how values or scanned.
520+
type RowsColumnScanner interface {
521+
Rows
522+
523+
// ScanColumn copies the column in the current row into the value pointed at by
524+
// dest. It returns [ErrSkip] to fall back to the normal [database/sql] scanning path.
525+
ScanColumn(index int, dest any) error
526+
}
527+
518528
// Tx is a transaction.
519529
type Tx interface {
520530
Commit() error

src/database/sql/sql.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3389,7 +3389,16 @@ func (rs *Rows) Scan(dest ...any) error {
33893389
}
33903390

33913391
for i, sv := range rs.lastcols {
3392-
err := convertAssignRows(dest[i], sv, rs)
3392+
err := driver.ErrSkip
3393+
3394+
if rowsColumnScanner, ok := rs.rowsi.(driver.RowsColumnScanner); ok {
3395+
err = rowsColumnScanner.ScanColumn(i, dest[i])
3396+
}
3397+
3398+
if err == driver.ErrSkip {
3399+
err = convertAssignRows(dest[i], sv, rs)
3400+
}
3401+
33933402
if err != nil {
33943403
rs.closemuRUnlockIfHeldByScan()
33953404
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)

0 commit comments

Comments
 (0)