-
Notifications
You must be signed in to change notification settings - Fork 2.3k
rows.Close() modifying underlying data buffer #1715
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I managed to reproduce the issue when sending the scanned rows via a channel, without using func TestMysqlDriverDecimal(t *testing.T) {
cntor := makeMysqlConnector(nil)
connUrl, urlErr := cntor.ConnectionUrl()
require.NoError(t, urlErr)
fmt.Printf("conn url: %s\n", connUrl)
conn, connErr := mysql.MySQLDriver{}.Open(connUrl)
require.NoError(t, connErr)
defer conn.Close()
sql := `
WITH RECURSIVE t(x) AS (
SELECT 0 UNION ALL
SELECT x + 1 FROM t WHERE x <= 500
)
SELECT
x,
'abc' y
FROM t
`
rows, queryErr := conn.(driver.QueryerContext).QueryContext(context.Background(), sql, nil)
require.NoError(t, queryErr)
ch := make(chan []driver.Value, 2048)
var wg sync.WaitGroup
wg.Add(1)
go func() {
i := 0
for row := range ch {
time.Sleep(50 * time.Millisecond)
fmt.Printf("result row %d: %v, %v\n", i, row[0], row[1])
i += 1
}
wg.Done()
}()
i := 0
for {
row := make([]driver.Value, 2)
nextErr := rows.Next(row)
if nextErr == io.EOF {
break
}
require.NoError(t, nextErr)
fmt.Printf("row %d: %v, %v\n", i, row[0], row[1])
ch <- row
i += 1
}
close(ch)
wg.Wait()
} Actual Output(snippet)
|
database/sql copies data. So scanned data can be used after Next() or Close(), except sql.RawBytes.
The doc is wrong. After several years, this restriction is removed. They just missed to remove the comment in the |
oh okay. Thank you for your reply. It seems that different drivers are doing this differently. For example, I'm also working with other DB drivers such as pgx, duckdb, bigquery, athena, etc, but I have only encountered this with mysql. (I'll probably need to revise the others). Though within Would it make sense to copy byte arrays by default, except when using |
The commit is in 2015. We had other workaround but removed it in last December. |
Its job of database/sql. database/sql copies buffer. If we copy, two copies happens. |
okay noted. For my case, I want to use the Driver directly to maintain my own connection pooling with custom logics. But it's fair that you are optimizing for Perhaps there could be an inline/README doc for this. Thank you for your time. |
Reproduce
Expected Output
Actual Output
Description
It appears that
row.Close()
is modifying the underlying data buffer, making it not possible to use the scanned data properly after closing (at least without having to iterate and copy the buffers).I believe this does not conform with

database/sql/driver
(ref):Notes
[]byte
, such as Decimal (e.g. replace'abc' y
with0.01 y
)x <=
value at which I can reproduce this issue is349
, but this number varies with the length of the data values. Can try to increase this number to increase the chance of reproducing the issue.rows.Close()
rows.Close()
The text was updated successfully, but these errors were encountered: