Skip to content

rows.Close() modifying underlying data buffer #1715

Closed
@datbth

Description

@datbth

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):
Image

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 with 0.01 y)
  • The minimal x <= value at which I can reproduce this issue is 349, 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions