go-sql-driver / go-sql-driver/mysql

No way to access granular results from LOAD DATA

Open
#1,179 1 comment 4 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
15.3k
Forks
2.3k
Avg merge
2h 23m
Merged PRs (30d)
10

Description

### Issue description
This began life as a [question on StackOverflow](https://stackoverflow.com/questions/65136607/how-do-i-get-granular-load-data-results-from-the-golang-mysql-package). Discussion is copied here for ease of access.

#### Question

I am writing a Go program that interacts with a MySQL database. In MySQL, when you do a `LOAD DATA` query, in addition to the regular `X rows affected` line you get a line with more granular information:

```mysql
mysql> LOAD DATA LOCAL INFILE 'many-lines.tsv' REPLACE INTO TABLE test_table (id, timestamp);
Query OK, 6 rows affected (0.01 sec)
Records: 3 Deleted: 3 Skipped: 0 Warnings: 0
```

[As documented here](https://dev.mysql.com/doc/refman/8.0/en/load-data.html) under the section "Statement Result Information".

I would love to be able to access this from my Go program, but I cannot figure out how, or whether it's even possible. [`sql.DB.Exec()` returns a `Result`](https://golang.org/pkg/database/sql/#DB.Exec), but that [only has a `RowsAffected` field](https://golang.org/pkg/database/sql/#Result). This contains a sum of rows written + rows deleted and ignores rows skipped, and is therefore ambiguous (write 3, delete 2 and skip 2 is the same as write 5, delete 0 and skip 0).

I looked through the [documentation for the Go MySQL driver](https://godoc.org/github.com/go-sql-driver/mysql), but couldn't find anything there that does what I want.

Is there a way to get access to this information?

#### Answer

The information is actually a [ER_LOAD_INFO](https://github.com/mysql/mysql-server/blob/mysql-5.7.32/sql/share/errmsg-utf8.txt#L2045) "error" (notionally info) message of the server.

This gets communicated as an informational message in the [OK response](https://github.com/mysql/mysql-server/blob/ee4455a33b10f1b1886044322e4893f587b319ed/sql/sql_load.cc#L624-L658) from the server.

Looking at the decoding of the [OK packet in go](https://github.com/go-sql-driver/mysql/blob/v1.5.0/packets.go#L623), it isn't parsing out the [info (human readable status information)](https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html). When making the connection ensure that [clientSessionTrack](https://github.com/go-sql-driver/mysql/blob/46351a8892976898935f653f5333782579a96fa5/const.go#L57) is part of the connection flags.

So a few small enhancements to the Go MySQL driver and you'll be able to access it.

### Example code

N/A

### Error log

N/A

### Configuration
*Driver version (or git SHA):* v1.4.1

*Go version:*

```
$ go version
go version go1.15.2 darwin/amd64
```

*Server version:*
*Server OS:*

```
mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+------------------------------+
| Variable_name | Value |
+-------------------------+------------------------------+
| innodb_version | 5.6.50 |
| protocol_version | 10 |
| slave_type_conversions | |
| version | 5.6.50 |
| version_comment | MySQL Community Server (GPL) |
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
+-------------------------+------------------------------+
7 rows in set (0.02 sec)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.