@@ -503,62 +503,84 @@ func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Va
503
503
return nil , fmt .Errorf ("Invalid DATETIME-packet length %d" , num )
504
504
}
505
505
506
+ // zeroDateTime is used in formatBinaryDateTime to avoid an allocation
507
+ // if the DATE or DATETIME has the zero value.
508
+ // It must never be changed.
509
+ // The current behavior depends on database/sql copying the result.
510
+ var zeroDateTime = []byte ("0000-00-00 00:00:00" )
511
+
506
512
func formatBinaryDateTime (src []byte , withTime bool ) (driver.Value , error ) {
507
- const zeroDateTimeMicros = "0000-00-00 00:00:00.000000"
513
+ if len (src ) == 0 {
514
+ if withTime {
515
+ return zeroDateTime , nil
516
+ }
517
+ return zeroDateTime [:10 ], nil
518
+ }
508
519
var dst []byte
509
520
if withTime {
510
521
if len (src ) == 11 {
511
- dst = []byte (zeroDateTimeMicros )
522
+ dst = []byte ("0000-00-00 00:00:00.000000" )
512
523
} else {
513
- dst = []byte (zeroDateTimeMicros [: 19 ] )
524
+ dst = []byte ("0000-00-00 00:00:00" )
514
525
}
515
526
} else {
516
- dst = []byte (zeroDateTimeMicros [: 10 ] )
527
+ dst = []byte ("0000-00-00" )
517
528
}
518
529
switch len (src ) {
519
530
case 11 :
520
531
microsecs := binary .LittleEndian .Uint32 (src [7 :11 ])
521
- dst [20 ] += byte ((microsecs / 100000 ) % 10 )
522
- dst [21 ] += byte ((microsecs / 10000 ) % 10 )
523
- dst [22 ] += byte ((microsecs / 1000 ) % 10 )
524
- dst [23 ] += byte ((microsecs / 100 ) % 10 )
525
- dst [24 ] += byte ((microsecs / 10 ) % 10 )
526
- dst [25 ] += byte (microsecs % 10 )
532
+ tmp32 := microsecs / 10
533
+ dst [25 ] += byte (microsecs - 10 * tmp32 )
534
+ tmp32 , microsecs = tmp32 / 10 , tmp32
535
+ dst [24 ] += byte (microsecs - 10 * tmp32 )
536
+ tmp32 , microsecs = tmp32 / 10 , tmp32
537
+ dst [23 ] += byte (microsecs - 10 * tmp32 )
538
+ tmp32 , microsecs = tmp32 / 10 , tmp32
539
+ dst [22 ] += byte (microsecs - 10 * tmp32 )
540
+ tmp32 , microsecs = tmp32 / 10 , tmp32
541
+ dst [21 ] += byte (microsecs - 10 * tmp32 )
542
+ dst [20 ] += byte (microsecs / 10 )
527
543
fallthrough
528
544
case 7 :
529
- hour := src [4 ]
530
- minute := src [5 ]
531
545
second := src [6 ]
532
- dst [11 ] += (hour / 10 ) % 10
533
- dst [12 ] += hour % 10
534
- dst [14 ] += (minute / 10 ) % 10
535
- dst [15 ] += minute % 10
536
- dst [17 ] += (second / 10 ) % 10
537
- dst [18 ] += second % 10
546
+ tmp := second / 10
547
+ dst [18 ] += second - 10 * tmp
548
+ dst [17 ] += tmp
549
+ minute := src [5 ]
550
+ tmp = minute / 10
551
+ dst [15 ] += minute - 10 * tmp
552
+ dst [14 ] += tmp
553
+ hour := src [4 ]
554
+ tmp = hour / 10
555
+ dst [12 ] += hour - 10 * tmp
556
+ dst [11 ] += tmp
538
557
fallthrough
539
558
case 4 :
540
- year := binary .LittleEndian .Uint16 (src [:2 ])
541
- month := src [2 ]
542
559
day := src [3 ]
543
- dst [0 ] += byte ((year / 1000 ) % 10 )
544
- dst [1 ] += byte ((year / 100 ) % 10 )
545
- dst [2 ] += byte ((year / 10 ) % 10 )
546
- dst [3 ] += byte (year % 10 )
547
- dst [5 ] += (month / 10 ) % 10
548
- dst [6 ] += month % 10
549
- dst [8 ] += (day / 10 ) % 10
550
- dst [9 ] += day % 10
551
- return dst , nil
552
- case 0 :
560
+ tmp := day / 10
561
+ dst [9 ] += day - 10 * tmp
562
+ dst [8 ] += tmp
563
+ month := src [2 ]
564
+ tmp = month / 10
565
+ dst [6 ] += month - 10 * tmp
566
+ dst [5 ] += tmp
567
+ year := binary .LittleEndian .Uint16 (src [:2 ])
568
+ tmp16 := year / 10
569
+ dst [3 ] += byte (year - 10 * tmp16 )
570
+ tmp16 , year = tmp16 / 10 , tmp16
571
+ dst [2 ] += byte (year - 10 * tmp16 )
572
+ tmp16 , year = tmp16 / 10 , tmp16
573
+ dst [1 ] += byte (year - 10 * tmp16 )
574
+ dst [0 ] += byte (tmp16 )
553
575
return dst , nil
554
576
}
555
- var mode string
577
+ var t string
556
578
if withTime {
557
- mode = "DATETIME"
579
+ t = "DATETIME"
558
580
} else {
559
- mode = "DATE"
581
+ t = "DATE"
560
582
}
561
- return nil , fmt .Errorf ("invalid %s-packet length %d" , mode , len (src ))
583
+ return nil , fmt .Errorf ("invalid %s-packet length %d" , t , len (src ))
562
584
}
563
585
564
586
/******************************************************************************
0 commit comments