Skip to content

Commit

Permalink
database/sql: Add RowsColumnScanner interface
Browse files Browse the repository at this point in the history
Implementing RowsColumnScanner allows the driver
to completely control how values are scanned.

Fixes #67546
  • Loading branch information
jackc committed May 25, 2024
1 parent 3776465 commit 2ca99ce
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/database/sql/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,16 @@ type RowsColumnTypePrecisionScale interface {
ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)
}

// RowsColumnScanner may be implemented by [Rows]. It allows the driver to control
// how values or scanned.
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(index int, dest any) error
}

// Tx is a transaction.
type Tx interface {
Commit() error
Expand Down
11 changes: 10 additions & 1 deletion src/database/sql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -3389,7 +3389,16 @@ func (rs *Rows) Scan(dest ...any) error {
}

for i, sv := range rs.lastcols {
err := convertAssignRows(dest[i], sv, rs)
err := driver.ErrSkip

if rowsColumnScanner, ok := rs.rowsi.(driver.RowsColumnScanner); ok {
err = rowsColumnScanner.ScanColumn(i, dest[i])
}

if err == driver.ErrSkip {
err = convertAssignRows(dest[i], sv, rs)
}

if err != nil {
rs.closemuRUnlockIfHeldByScan()
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
Expand Down

0 comments on commit 2ca99ce

Please sign in to comment.