• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

go-sql-driver / mysql / 14570841909

21 Apr 2025 09:10AM UTC coverage: 83.0% (-0.01%) from 83.01%
14570841909

Pull #1692

github

web-flow
Merge branch 'master' into clientDeprecateEOF
Pull Request #1692: MariaDB metadata skipping

170 of 203 new or added lines in 6 files covered. (83.74%)

3 existing lines in 1 file now uncovered.

3320 of 4000 relevant lines covered (83.0%)

2184086.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.71
/connector.go
1
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
2
//
3
// Copyright 2018 The Go-MySQL-Driver Authors. All rights reserved.
4
//
5
// This Source Code Form is subject to the terms of the Mozilla Public
6
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
7
// You can obtain one at http://mozilla.org/MPL/2.0/.
8

9
package mysql
10

11
import (
12
        "context"
13
        "database/sql/driver"
14
        "fmt"
15
        "net"
16
        "os"
17
        "strconv"
18
        "strings"
19
)
20

21
type connector struct {
22
        cfg               *Config // immutable private copy.
23
        encodedAttributes string  // Encoded connection attributes.
24
}
25

26
func encodeConnectionAttributes(cfg *Config) string {
6,658✔
27
        connAttrsBuf := make([]byte, 0)
6,658✔
28

6,658✔
29
        // default connection attributes
6,658✔
30
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrClientName)
6,658✔
31
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrClientNameValue)
6,658✔
32
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrOS)
6,658✔
33
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrOSValue)
6,658✔
34
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrPlatform)
6,658✔
35
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrPlatformValue)
6,658✔
36
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrPid)
6,658✔
37
        connAttrsBuf = appendLengthEncodedString(connAttrsBuf, strconv.Itoa(os.Getpid()))
6,658✔
38
        serverHost, _, _ := net.SplitHostPort(cfg.Addr)
6,658✔
39
        if serverHost != "" {
11,906✔
40
                connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrServerHost)
5,248✔
41
                connAttrsBuf = appendLengthEncodedString(connAttrsBuf, serverHost)
5,248✔
42
        }
5,248✔
43

44
        // user-defined connection attributes
45
        for _, connAttr := range strings.Split(cfg.ConnectionAttributes, ",") {
13,572✔
46
                k, v, found := strings.Cut(connAttr, ":")
6,914✔
47
                if !found {
13,316✔
48
                        continue
6,402✔
49
                }
50
                connAttrsBuf = appendLengthEncodedString(connAttrsBuf, k)
512✔
51
                connAttrsBuf = appendLengthEncodedString(connAttrsBuf, v)
512✔
52
        }
53

54
        return string(connAttrsBuf)
6,658✔
55
}
56

57
func newConnector(cfg *Config) *connector {
6,658✔
58
        encodedAttributes := encodeConnectionAttributes(cfg)
6,658✔
59
        return &connector{
6,658✔
60
                cfg:               cfg,
6,658✔
61
                encodedAttributes: encodedAttributes,
6,658✔
62
        }
6,658✔
63
}
6,658✔
64

65
// Connect implements driver.Connector interface.
66
// Connect returns a connection to the database.
67
func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
17,430✔
68
        var err error
17,430✔
69

17,430✔
70
        // Invoke beforeConnect if present, with a copy of the configuration
17,430✔
71
        cfg := c.cfg
17,430✔
72
        if c.cfg.beforeConnect != nil {
17,462✔
73
                cfg = c.cfg.Clone()
32✔
74
                err = c.cfg.beforeConnect(ctx, cfg)
32✔
75
                if err != nil {
32✔
76
                        return nil, err
×
77
                }
×
78
        }
79

80
        // New mysqlConn
81
        mc := &mysqlConn{
17,430✔
82
                maxAllowedPacket: maxPacketSize,
17,430✔
83
                maxWriteSize:     maxPacketSize - 1,
17,430✔
84
                closech:          make(chan struct{}),
17,430✔
85
                cfg:              cfg,
17,430✔
86
                connector:        c,
17,430✔
87
        }
17,430✔
88
        mc.parseTime = mc.cfg.ParseTime
17,430✔
89

17,430✔
90
        // Connect to Server
17,430✔
91
        dctx := ctx
17,430✔
92
        if mc.cfg.Timeout > 0 {
34,764✔
93
                var cancel context.CancelFunc
17,334✔
94
                dctx, cancel = context.WithTimeout(ctx, c.cfg.Timeout)
17,334✔
95
                defer cancel()
17,334✔
96
        }
17,334✔
97

98
        if c.cfg.DialFunc != nil {
17,430✔
99
                mc.netConn, err = c.cfg.DialFunc(dctx, mc.cfg.Net, mc.cfg.Addr)
×
100
        } else {
17,430✔
101
                dialsLock.RLock()
17,430✔
102
                dial, ok := dials[mc.cfg.Net]
17,430✔
103
                dialsLock.RUnlock()
17,430✔
104
                if ok {
17,654✔
105
                        mc.netConn, err = dial(dctx, mc.cfg.Addr)
224✔
106
                } else {
17,430✔
107
                        nd := net.Dialer{}
17,206✔
108
                        mc.netConn, err = nd.DialContext(dctx, mc.cfg.Net, mc.cfg.Addr)
17,206✔
109
                }
17,206✔
110
        }
111
        if err != nil {
17,706✔
112
                return nil, err
276✔
113
        }
276✔
114
        mc.rawConn = mc.netConn
17,154✔
115

17,154✔
116
        // Enable TCP Keepalives on TCP connections
17,154✔
117
        if tc, ok := mc.netConn.(*net.TCPConn); ok {
34,178✔
118
                if err := tc.SetKeepAlive(true); err != nil {
17,024✔
119
                        c.cfg.Logger.Print(err)
×
120
                }
×
121
        }
122

123
        // Call startWatcher for context support (From Go 1.8)
124
        mc.startWatcher()
17,154✔
125
        if err := mc.watchCancel(ctx); err != nil {
17,260✔
126
                mc.cleanup()
106✔
127
                return nil, err
106✔
128
        }
106✔
129
        defer mc.finish()
17,048✔
130

17,048✔
131
        mc.buf = newBuffer()
17,048✔
132

17,048✔
133
        // Reading Handshake Initialization Packet
17,048✔
134
        authData, serverCapabilities, serverExtendedCapabilities, plugin, err := mc.readHandshakePacket()
17,048✔
135
        if err != nil {
17,206✔
136
                mc.cleanup()
158✔
137
                return nil, err
158✔
138
        }
158✔
139

140
        if plugin == "" {
16,890✔
141
                plugin = defaultAuthPlugin
×
142
        }
×
143

144
        // Send Client Authentication Packet
145
        authResp, err := mc.auth(authData, plugin)
16,890✔
146
        if err != nil {
16,890✔
147
                // try the default auth plugin, if using the requested plugin failed
×
148
                c.cfg.Logger.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
×
149
                plugin = defaultAuthPlugin
×
150
                authResp, err = mc.auth(authData, plugin)
×
151
                if err != nil {
×
152
                        mc.cleanup()
×
153
                        return nil, err
×
154
                }
×
155
        }
156
        if err = mc.writeHandshakeResponsePacket(authResp, serverCapabilities, serverExtendedCapabilities, plugin); err != nil {
19,209✔
157
                mc.cleanup()
2,319✔
158
                return nil, err
2,319✔
159
        }
2,319✔
160

161
        // Handle response to auth packet, switch methods if possible
162
        if err = mc.handleAuthResult(authData, plugin); err != nil {
16,467✔
163
                // Authentication failed and MySQL has already closed the connection
1,896✔
164
                // (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
1,896✔
165
                // Do not send COM_QUIT, just cleanup and return the error.
1,896✔
166
                mc.cleanup()
1,896✔
167
                return nil, err
1,896✔
168
        }
1,896✔
169

170
        if mc.cfg.compress && mc.clientCapabilities&clientCompress > 0 {
16,210✔
171
                mc.compress = true
3,535✔
172
                mc.compIO = newCompIO(mc)
3,535✔
173
        }
3,535✔
174
        if mc.cfg.MaxAllowedPacket > 0 {
25,254✔
175
                mc.maxAllowedPacket = mc.cfg.MaxAllowedPacket
12,579✔
176
        } else {
12,675✔
177
                // Get max allowed packet size
96✔
178
                maxap, err := mc.getSystemVar("max_allowed_packet")
96✔
179
                if err != nil {
96✔
180
                        mc.Close()
×
181
                        return nil, err
×
182
                }
×
183
                n, err := strconv.Atoi(string(maxap))
96✔
184
                if err != nil {
96✔
185
                        mc.Close()
×
186
                        return nil, fmt.Errorf("invalid max_allowed_packet value (%q): %w", maxap, err)
×
187
                }
×
188
                mc.maxAllowedPacket = n - 1
96✔
189
        }
190
        if mc.maxAllowedPacket < maxPacketSize {
12,675✔
191
                mc.maxWriteSize = mc.maxAllowedPacket
×
192
        }
×
193

194
        // Charset: character_set_connection, character_set_client, character_set_results
195
        if len(mc.cfg.charsets) > 0 {
13,123✔
196
                for _, cs := range mc.cfg.charsets {
992✔
197
                        // ignore errors here - a charset may not exist
544✔
198
                        if mc.cfg.Collation != "" {
544✔
199
                                err = mc.exec("SET NAMES " + cs + " COLLATE " + mc.cfg.Collation)
×
200
                        } else {
544✔
201
                                err = mc.exec("SET NAMES " + cs)
544✔
202
                        }
544✔
203
                        if err == nil {
928✔
204
                                break
384✔
205
                        }
206
                }
207
                if err != nil {
512✔
208
                        mc.Close()
64✔
209
                        return nil, err
64✔
210
                }
64✔
211
        }
212

213
        // Handle DSN Params
214
        err = mc.handleParams()
12,611✔
215
        if err != nil {
12,611✔
216
                mc.Close()
×
217
                return nil, err
×
218
        }
×
219

220
        return mc, nil
12,611✔
221
}
222

223
// Driver implements driver.Connector interface.
224
// Driver returns &MySQLDriver{}.
225
func (c *connector) Driver() driver.Driver {
×
226
        return &MySQLDriver{}
×
227
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc