@@ -233,6 +233,25 @@ func (c *Conn) readResult(binary bool) (*Result, error) {
233
233
return c .readResultset (firstPkgBuf , binary )
234
234
}
235
235
236
+ func (c * Conn ) readResultStreaming (binary bool , result * Result , perRowCb SelectPerRowCallback ) error {
237
+ firstPkgBuf , err := c .ReadPacketReuseMem (utils .ByteSliceGet (16 )[:0 ])
238
+ defer utils .ByteSlicePut (firstPkgBuf )
239
+
240
+ if err != nil {
241
+ return errors .Trace (err )
242
+ }
243
+
244
+ if firstPkgBuf [0 ] == OK_HEADER {
245
+ return ErrMalformPacket // Streaming allowed only for SELECT queries
246
+ } else if firstPkgBuf [0 ] == ERR_HEADER {
247
+ return c .handleErrorPacket (append ([]byte {}, firstPkgBuf ... ))
248
+ } else if firstPkgBuf [0 ] == LocalInFile_HEADER {
249
+ return ErrMalformPacket
250
+ }
251
+
252
+ return c .readResultsetStreaming (firstPkgBuf , binary , result , perRowCb )
253
+ }
254
+
236
255
func (c * Conn ) readResultset (data []byte , binary bool ) (* Result , error ) {
237
256
// column count
238
257
count , _ , n := LengthEncodedInt (data )
@@ -256,6 +275,31 @@ func (c *Conn) readResultset(data []byte, binary bool) (*Result, error) {
256
275
return result , nil
257
276
}
258
277
278
+ func (c * Conn ) readResultsetStreaming (data []byte , binary bool , result * Result , perRowCb SelectPerRowCallback ) error {
279
+ columnCount , _ , n := LengthEncodedInt (data )
280
+
281
+ if n - len (data ) != 0 {
282
+ return ErrMalformPacket
283
+ }
284
+
285
+ if result .Resultset == nil {
286
+ result .Resultset = NewResultset (int (columnCount ))
287
+ } else {
288
+ // Reuse memory if can
289
+ result .Reset (int (columnCount ))
290
+ }
291
+
292
+ if err := c .readResultColumns (result ); err != nil {
293
+ return errors .Trace (err )
294
+ }
295
+
296
+ if err := c .readResultRowsStreaming (result , binary , perRowCb ); err != nil {
297
+ return errors .Trace (err )
298
+ }
299
+
300
+ return nil
301
+ }
302
+
259
303
func (c * Conn ) readResultColumns (result * Result ) (err error ) {
260
304
var i int = 0
261
305
var data []byte
@@ -344,3 +388,47 @@ func (c *Conn) readResultRows(result *Result, isBinary bool) (err error) {
344
388
345
389
return nil
346
390
}
391
+
392
+ func (c * Conn ) readResultRowsStreaming (result * Result , isBinary bool , perRowCb SelectPerRowCallback ) (err error ) {
393
+ var (
394
+ data []byte
395
+ row []FieldValue
396
+ )
397
+
398
+ for {
399
+ data , err = c .ReadPacketReuseMem (data [:0 ])
400
+ if err != nil {
401
+ return
402
+ }
403
+
404
+ // EOF Packet
405
+ if c .isEOFPacket (data ) {
406
+ if c .capability & CLIENT_PROTOCOL_41 > 0 {
407
+ // result.Warnings = binary.LittleEndian.Uint16(data[1:])
408
+ // todo add strict_mode, warning will be treat as error
409
+ result .Status = binary .LittleEndian .Uint16 (data [3 :])
410
+ c .status = result .Status
411
+ }
412
+
413
+ break
414
+ }
415
+
416
+ if data [0 ] == ERR_HEADER {
417
+ return c .handleErrorPacket (data )
418
+ }
419
+
420
+ // Parse this row
421
+ row , err = RowData (data ).Parse (result .Fields , isBinary , row )
422
+ if err != nil {
423
+ return errors .Trace (err )
424
+ }
425
+
426
+ // Send the row to "userland" code
427
+ err = perRowCb (row )
428
+ if err != nil {
429
+ return errors .Trace (err )
430
+ }
431
+ }
432
+
433
+ return nil
434
+ }
0 commit comments