@@ -85,34 +85,28 @@ func zCompress(src []byte, dst io.Writer) error {
85
85
return nil
86
86
}
87
87
88
- type decompressor struct {
89
- mc * mysqlConn
90
- // read buffer (FIFO).
91
- // We can not reuse already-read buffer until dropping Go 1.20 support.
92
- // It is because of database/mysql's weired behavior.
93
- // See https://github.com/go-sql-driver/mysql/issues/1435
94
- bytesBuf []byte
88
+ type compIO struct {
89
+ mc * mysqlConn
90
+ buff bytes.Buffer
95
91
}
96
92
97
- func newDecompressor (mc * mysqlConn ) * decompressor {
98
- return & decompressor {
93
+ func newCompIO (mc * mysqlConn ) * compIO {
94
+ return & compIO {
99
95
mc : mc ,
100
96
}
101
97
}
102
98
103
- func (c * decompressor ) readNext (need int ) ([]byte , error ) {
104
- for len ( c . bytesBuf ) < need {
99
+ func (c * compIO ) readNext (need int ) ([]byte , error ) {
100
+ for c . buff . Len ( ) < need {
105
101
if err := c .uncompressPacket (); err != nil {
106
102
return nil , err
107
103
}
108
104
}
109
-
110
- data := c .bytesBuf [:need :need ] // prevent caller writes into r.bytesBuf
111
- c .bytesBuf = c .bytesBuf [need :]
112
- return data , nil
105
+ data := c .buff .Next (need )
106
+ return data [:need :need ], nil // prevent caller writes into c.buff
113
107
}
114
108
115
- func (c * decompressor ) uncompressPacket () error {
109
+ func (c * compIO ) uncompressPacket () error {
116
110
header , err := c .mc .buf .readNext (7 ) // size of compressed header
117
111
if err != nil {
118
112
return err
@@ -147,41 +141,37 @@ func (c *decompressor) uncompressPacket() error {
147
141
// if payload is uncompressed, its length will be specified as zero, and its
148
142
// true length is contained in comprLength
149
143
if uncompressedLength == 0 {
150
- c .bytesBuf = append ( c . bytesBuf , comprData ... )
144
+ c .buff . Write ( comprData )
151
145
return nil
152
146
}
153
147
154
148
// use existing capacity in bytesBuf if possible
155
- offset := len (c .bytesBuf )
156
- if cap (c .bytesBuf )- offset < uncompressedLength {
157
- old := c .bytesBuf
158
- c .bytesBuf = make ([]byte , offset , offset + uncompressedLength )
159
- copy (c .bytesBuf , old )
160
- }
161
-
162
- lenRead , err := zDecompress (comprData , c .bytesBuf [offset :offset + uncompressedLength ])
149
+ c .buff .Grow (uncompressedLength )
150
+ dec := c .buff .AvailableBuffer ()[:uncompressedLength ]
151
+ lenRead , err := zDecompress (comprData , dec )
163
152
if err != nil {
164
153
return err
165
154
}
166
155
if lenRead != uncompressedLength {
167
156
return fmt .Errorf ("invalid compressed packet: uncompressed length in header is %d, actual %d" ,
168
157
uncompressedLength , lenRead )
169
158
}
170
- c .bytesBuf = c . bytesBuf [: offset + uncompressedLength ]
159
+ c .buff . Write ( dec ) // fast copy. See bytes.Buffer.AvailableBuffer() doc.
171
160
return nil
172
161
}
173
162
174
163
const maxPayloadLen = maxPacketSize - 4
175
164
176
- // writeCompressed sends one or some packets with compression.
165
+ // writePackets sends one or some packets with compression.
177
166
// Use this instead of mc.netConn.Write() when mc.compress is true.
178
- func (mc * mysqlConn ) writeCompressed (packets []byte ) (int , error ) {
167
+ func (c * compIO ) writePackets (packets []byte ) (int , error ) {
179
168
totalBytes := len (packets )
180
169
dataLen := len (packets )
181
170
blankHeader := make ([]byte , 7 )
182
- var buf bytes. Buffer
171
+ buf := & c . buff
183
172
184
173
for dataLen > 0 {
174
+ buf .Reset ()
185
175
payloadLen := dataLen
186
176
if payloadLen > maxPayloadLen {
187
177
payloadLen = maxPayloadLen
@@ -200,10 +190,10 @@ func (mc *mysqlConn) writeCompressed(packets []byte) (int, error) {
200
190
}
201
191
uncompressedLen = 0
202
192
} else {
203
- zCompress (payload , & buf )
193
+ zCompress (payload , buf )
204
194
}
205
195
206
- if err := mc .writeCompressedPacket (buf .Bytes (), uncompressedLen ); err != nil {
196
+ if err := c .writeCompressedPacket (buf .Bytes (), uncompressedLen ); err != nil {
207
197
return 0 , err
208
198
}
209
199
dataLen -= payloadLen
@@ -216,7 +206,8 @@ func (mc *mysqlConn) writeCompressed(packets []byte) (int, error) {
216
206
217
207
// writeCompressedPacket writes a compressed packet with header.
218
208
// data should start with 7 size space for header followed by payload.
219
- func (mc * mysqlConn ) writeCompressedPacket (data []byte , uncompressedLen int ) error {
209
+ func (c * compIO ) writeCompressedPacket (data []byte , uncompressedLen int ) error {
210
+ mc := c .mc
220
211
comprLength := len (data ) - 7
221
212
if debugTrace {
222
213
fmt .Printf (
0 commit comments