Skip to content

Commit 5c7f33a

Browse files
authored
Merge branch 'master' into read_optimization
2 parents f0eee81 + c786d41 commit 5c7f33a

12 files changed

+50
-84
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ jobs:
2929
import os
3030
go = [
3131
# Keep the most recent production release at the top
32-
'1.23',
32+
'1.24',
3333
# Older production releases
34+
'1.23',
3435
'1.22',
35-
'1.21',
3636
]
3737
mysql = [
3838
'9.0',

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## v1.9.2 (2025-04-07)
4+
5+
v1.9.2 is a re-release of v1.9.1 due to a release process issue; no changes were made to the content.
6+
7+
38
## v1.9.1 (2025-03-21)
49

510
### Major Changes

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac
4242

4343
## Requirements
4444

45-
* Go 1.21 or higher. We aim to support the 3 latest versions of Go.
45+
* Go 1.22 or higher. We aim to support the 3 latest versions of Go.
4646
* MySQL (5.7+) and MariaDB (10.5+) are supported.
4747
* [TiDB](https://github.com/pingcap/tidb) is supported by PingCAP.
4848
* Do not ask questions about TiDB in our issue tracker or forum.

benchmark_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func benchmarkQueryHelper(b *testing.B, compr bool) {
9393
defer wg.Wait()
9494
b.StartTimer()
9595

96-
for i := 0; i < concurrencyLevel; i++ {
96+
for range concurrencyLevel {
9797
go func() {
9898
for {
9999
if atomic.AddInt64(&remain, -1) < 0 {
@@ -171,7 +171,7 @@ func BenchmarkExec(b *testing.B) {
171171
defer wg.Wait()
172172
b.StartTimer()
173173

174-
for i := 0; i < concurrencyLevel; i++ {
174+
for range concurrencyLevel {
175175
go func() {
176176
for {
177177
if atomic.AddInt64(&remain, -1) < 0 {
@@ -386,7 +386,7 @@ func BenchmarkQueryRawBytes(b *testing.B) {
386386
for i := range blob {
387387
blob[i] = 42
388388
}
389-
for i := 0; i < 100; i++ {
389+
for i := range 100 {
390390
_, err := db.Exec("INSERT INTO bench_rawbytes VALUES (?, ?)", i, blob)
391391
if err != nil {
392392
b.Fatal(err)
@@ -442,7 +442,7 @@ func BenchmarkReceiveMassiveRows(b *testing.B) {
442442
}
443443
for i := 0; i < 10000; i += 100 {
444444
args := make([]any, 200)
445-
for j := 0; j < 100; j++ {
445+
for j := range 100 {
446446
args[j*2] = i + j
447447
args[j*2+1] = sval
448448
}

connection_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func TestCleanCancel(t *testing.T) {
146146
ctx, cancel := context.WithCancel(context.Background())
147147
cancel()
148148

149-
for i := 0; i < 3; i++ { // Repeat same behavior
149+
for range 3 { // Repeat same behavior
150150
err := mc.Ping(ctx)
151151
if err != context.Canceled {
152152
t.Errorf("expected context.Canceled, got %#v", err)

driver_test.go

Lines changed: 25 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"os"
2727
"reflect"
2828
"runtime"
29+
"slices"
2930
"strconv"
3031
"strings"
3132
"sync"
@@ -1609,68 +1610,32 @@ func TestCollation(t *testing.T) {
16091610
t.Skipf("MySQL server not running on %s", netAddr)
16101611
}
16111612

1612-
defaultCollation := "utf8mb4_general_ci"
1613+
// MariaDB may override collation specified by handshake with `character_set_collations` variable.
1614+
// https://mariadb.com/kb/en/setting-character-sets-and-collations/#changing-default-collation
1615+
// https://mariadb.com/kb/en/server-system-variables/#character_set_collations
1616+
// utf8mb4_general_ci, utf8mb3_general_ci will be overridden by default MariaDB.
1617+
// Collations other than charasets default are not overridden. So utf8mb4_unicode_ci is safe.
16131618
testCollations := []string{
1614-
"", // do not set
1615-
defaultCollation, // driver default
16161619
"latin1_general_ci",
16171620
"binary",
16181621
"utf8mb4_unicode_ci",
16191622
"cp1257_bin",
16201623
}
16211624

16221625
for _, collation := range testCollations {
1623-
var expected, tdsn string
1624-
if collation != "" {
1625-
tdsn = dsn + "&collation=" + collation
1626-
expected = collation
1627-
} else {
1628-
tdsn = dsn
1629-
expected = defaultCollation
1630-
}
1631-
1632-
runTests(t, tdsn, func(dbt *DBTest) {
1633-
// see https://mariadb.com/kb/en/setting-character-sets-and-collations/#changing-default-collation
1634-
// when character_set_collations is set for the charset, it overrides the default collation
1635-
// so we need to check if the default collation is overridden
1636-
forceExpected := expected
1637-
var defaultCollations string
1638-
err := dbt.db.QueryRow("SELECT @@character_set_collations").Scan(&defaultCollations)
1639-
if err == nil {
1640-
// Query succeeded, need to check if we should override expected collation
1641-
collationMap := make(map[string]string)
1642-
pairs := strings.Split(defaultCollations, ",")
1643-
for _, pair := range pairs {
1644-
parts := strings.Split(pair, "=")
1645-
if len(parts) == 2 {
1646-
collationMap[parts[0]] = parts[1]
1647-
}
1648-
}
1626+
t.Run(collation, func(t *testing.T) {
1627+
tdsn := dsn + "&collation=" + collation
1628+
expected := collation
16491629

1650-
// Get charset prefix from expected collation
1651-
parts := strings.Split(expected, "_")
1652-
if len(parts) > 0 {
1653-
charset := parts[0]
1654-
if newCollation, ok := collationMap[charset]; ok {
1655-
forceExpected = newCollation
1656-
}
1630+
runTests(t, tdsn, func(dbt *DBTest) {
1631+
var got string
1632+
if err := dbt.db.QueryRow("SELECT @@collation_connection").Scan(&got); err != nil {
1633+
dbt.Fatal(err)
16571634
}
1658-
}
1659-
1660-
var got string
1661-
if err := dbt.db.QueryRow("SELECT @@collation_connection").Scan(&got); err != nil {
1662-
dbt.Fatal(err)
1663-
}
1664-
1665-
if got != expected {
1666-
if forceExpected != expected {
1667-
if got != forceExpected {
1668-
dbt.Fatalf("expected forced connection collation %s but got %s", forceExpected, got)
1669-
}
1670-
} else {
1635+
if got != expected {
16711636
dbt.Fatalf("expected connection collation %s but got %s", expected, got)
16721637
}
1673-
}
1638+
})
16741639
})
16751640
}
16761641
}
@@ -1959,7 +1924,7 @@ func TestPreparedManyCols(t *testing.T) {
19591924
rows.Close()
19601925

19611926
// Create 0byte string which we can't send via STMT_LONG_DATA.
1962-
for i := 0; i < numParams; i++ {
1927+
for i := range numParams {
19631928
params[i] = ""
19641929
}
19651930
rows, err = stmt.Query(params...)
@@ -2004,7 +1969,7 @@ func TestConcurrent(t *testing.T) {
20041969
})
20051970
}
20061971

2007-
for i := 0; i < max; i++ {
1972+
for i := range max {
20081973
go func(id int) {
20091974
defer wg.Done()
20101975

@@ -2388,7 +2353,7 @@ func TestPing(t *testing.T) {
23882353
q.Close()
23892354

23902355
// Verify that Ping() clears both fields.
2391-
for i := 0; i < 2; i++ {
2356+
for range 2 {
23922357
if err := c.Ping(ctx); err != nil {
23932358
dbt.fail("Pinger", "Ping", err)
23942359
}
@@ -2591,7 +2556,7 @@ func TestMultiResultSet(t *testing.T) {
25912556
}
25922557
defer stmt.Close()
25932558

2594-
for j := 0; j < 2; j++ {
2559+
for j := range 2 {
25952560
rows, err := stmt.Query()
25962561
if err != nil {
25972562
dbt.Fatalf("%v (i=%d) (j=%d)", err, i, j)
@@ -2698,7 +2663,7 @@ func TestQueryMultipleResults(t *testing.T) {
26982663
c := conn.(*mysqlConn)
26992664

27002665
// Demonstrate that repeated queries reset the affectedRows
2701-
for i := 0; i < 2; i++ {
2666+
for range 2 {
27022667
_, err := qr.Query(`
27032668
INSERT INTO test (value) VALUES ('a'), ('b');
27042669
INSERT INTO test (value) VALUES ('c'), ('d'), ('e');
@@ -3326,11 +3291,11 @@ func TestRawBytesAreNotModified(t *testing.T) {
33263291

33273292
runTests(t, dsn, func(dbt *DBTest) {
33283293
dbt.mustExec("CREATE TABLE test (id int, value BLOB) CHARACTER SET utf8")
3329-
for i := 0; i < insertRows; i++ {
3294+
for i := range insertRows {
33303295
dbt.mustExec("INSERT INTO test VALUES (?, ?)", i+1, sqlBlobs[i&1])
33313296
}
33323297

3333-
for i := 0; i < contextRaceIterations; i++ {
3298+
for i := range contextRaceIterations {
33343299
func() {
33353300
ctx, cancel := context.WithCancel(context.Background())
33363301
defer cancel()
@@ -3594,8 +3559,8 @@ func TestConnectionAttributes(t *testing.T) {
35943559
rowsMap[attrName] = attrValue
35953560
}
35963561

3597-
connAttrs := append(append([]string{}, defaultAttrs...), customAttrs...)
3598-
expectedAttrValues := append(append([]string{}, defaultAttrValues...), customAttrValues...)
3562+
connAttrs := slices.Concat(defaultAttrs, customAttrs)
3563+
expectedAttrValues := slices.Concat(defaultAttrValues, customAttrValues)
35993564
for i := range connAttrs {
36003565
if gotValue := rowsMap[connAttrs[i]]; gotValue != expectedAttrValues[i] {
36013566
dbt.Errorf("expected %q, got %q", expectedAttrValues[i], gotValue)
@@ -3679,7 +3644,7 @@ func TestIssue1567(t *testing.T) {
36793644
count = max
36803645
}
36813646

3682-
for i := 0; i < count; i++ {
3647+
for range count {
36833648
timeout := time.Duration(mrand.Int63n(int64(rtt)))
36843649
ctx, cancel := context.WithTimeout(context.Background(), timeout)
36853650
dbt.db.PingContext(ctx)

dsn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ func ParseDSN(dsn string) (cfg *Config, err error) {
414414
if dsn[j] == '@' {
415415
// username[:password]
416416
// Find the first ':' in dsn[:j]
417-
for k = 0; k < j; k++ {
417+
for k = 0; k < j; k++ { // We cannot use k = range j here, because we use dsn[:k] below
418418
if dsn[k] == ':' {
419419
cfg.Passwd = dsn[k+1 : j]
420420
break

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module github.com/go-sql-driver/mysql
22

3-
go 1.21.0
3+
go 1.22.0
44

55
require filippo.io/edwards25519 v1.1.0

infile.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,7 @@ const defaultPacketSize = 16 * 1024 // 16KB is small enough for disk readahead a
9595

9696
func (mc *okHandler) handleInFileRequest(name string) (err error) {
9797
var rdr io.Reader
98-
packetSize := defaultPacketSize
99-
if mc.maxWriteSize < packetSize {
100-
packetSize = mc.maxWriteSize
101-
}
98+
packetSize := min(mc.maxWriteSize, defaultPacketSize)
10299

103100
if idx := strings.Index(name, "Reader::"); idx == 0 || (idx > 0 && name[idx-1] == '/') { // io.Reader
104101
// The server might return an an absolute path. See issue #355.

packets.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -980,10 +980,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
980980
mc := stmt.mc
981981

982982
// Determine threshold dynamically to avoid packet size shortage.
983-
longDataSize := mc.maxAllowedPacket / (stmt.paramCount + 1)
984-
if longDataSize < 64 {
985-
longDataSize = 64
986-
}
983+
longDataSize := max(mc.maxAllowedPacket/(stmt.paramCount+1), 64)
987984

988985
// Reset packet-sequence
989986
mc.resetSequence()

result.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
package mysql
1010

11+
import "slices"
12+
1113
import "database/sql/driver"
1214

1315
// Result exposes data not available through *connection.Result.
@@ -42,9 +44,9 @@ func (res *mysqlResult) RowsAffected() (int64, error) {
4244
}
4345

4446
func (res *mysqlResult) AllLastInsertIds() []int64 {
45-
return append([]int64{}, res.insertIds...) // defensive copy
47+
return slices.Clone(res.insertIds) // defensive copy
4648
}
4749

4850
func (res *mysqlResult) AllRowsAffected() []int64 {
49-
return append([]int64{}, res.affectedRows...) // defensive copy
51+
return slices.Clone(res.affectedRows) // defensive copy
5052
}

utils.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) {
182182

183183
func parseByteYear(b []byte) (int, error) {
184184
year, n := 0, 1000
185-
for i := 0; i < 4; i++ {
185+
for i := range 4 {
186186
v, err := bToi(b[i])
187187
if err != nil {
188188
return 0, err
@@ -207,7 +207,7 @@ func parseByte2Digits(b1, b2 byte) (int, error) {
207207

208208
func parseByteNanoSec(b []byte) (int, error) {
209209
ns, digit := 0, 100000 // max is 6-digits
210-
for i := 0; i < len(b); i++ {
210+
for i := range b {
211211
v, err := bToi(b[i])
212212
if err != nil {
213213
return 0, err
@@ -678,7 +678,7 @@ func escapeStringBackslash(buf []byte, v string) []byte {
678678
pos := len(buf)
679679
buf = reserveBuffer(buf, len(v)*2)
680680

681-
for i := 0; i < len(v); i++ {
681+
for i := range len(v) {
682682
c := v[i]
683683
switch c {
684684
case '\x00':
@@ -746,7 +746,7 @@ func escapeStringQuotes(buf []byte, v string) []byte {
746746
pos := len(buf)
747747
buf = reserveBuffer(buf, len(v)*2)
748748

749-
for i := 0; i < len(v); i++ {
749+
for i := range len(v) {
750750
c := v[i]
751751
if c == '\'' {
752752
buf[pos+1] = '\''

0 commit comments

Comments
 (0)