Closed
Description
Reproduce
func TestMysqlDriverBuffer(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 <= 349
)
SELECT
x,
'abc' y
FROM t
`
rows, queryErr := conn.(driver.QueryerContext).QueryContext(context.Background(), sql, nil)
require.NoError(t, queryErr)
result := make([][]driver.Value, 2)
for i := range result {
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])
result[i] = row
}
rows.Close()
for i := range result {
fmt.Printf("result row %d: %v, %v\n", i, result[i][0], result[i][1])
}
}
Expected Output
=== RUN TestMysqlDriverBuffer
conn url: root:testtest@tcp(localhost:3308)/htest?parseTime=true&timeout=10000ms&tls=preferred
row 0: 0, [97 98 99]
row 1: 1, [97 98 99]
result row 0: 0, [97 98 99]
result row 1: 1, [97 98 99]
Actual Output
=== RUN TestMysqlDriverBuffer
conn url: root:testtest@tcp(localhost:3308)/htest?parseTime=true&timeout=10000ms&tls=preferred
row 0: 0, [97 98 99]
row 1: 1, [97 98 99]
result row 0: 0, [97 98 99]
result row 1: 1, [49 3 97]
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
- Tested with Mysql 8.0.42, 9.3.0
- Same issue happens with other data types that are scanned into
[]byte
, such as Decimal (e.g. replace'abc' y
with0.01 y
) - The minimal
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. - Does not happen when not calling
rows.Close()
- Without calling
rows.Close()
- It is not possible to re-use the connection for subsequent queries
- It can lead to unexpected issues