@@ -828,16 +828,22 @@ func (rc *mysqlRows) readBinaryRow(dest []driver.Value) (err error) {
828828 // Date YYYY-MM-DD
829829 case FIELD_TYPE_DATE , FIELD_TYPE_NEWDATE :
830830 var num uint64
831- // TODO(js): allow nil values
832- num , _ , n , err = readLengthEncodedInteger (data [pos :])
831+ var isNull bool
832+ num , isNull , n , err = readLengthEncodedInteger (data [pos :])
833833 if err != nil {
834834 return
835835 }
836836
837837 if num == 0 {
838- dest [i ] = []byte ("0000-00-00" )
839- pos += n
840- continue
838+ if isNull {
839+ dest [i ] = nil
840+ pos ++ // n = 1
841+ continue
842+ } else {
843+ dest [i ] = []byte ("0000-00-00" )
844+ pos ++ // n = 1
845+ continue
846+ }
841847 } else {
842848 dest [i ] = []byte (fmt .Sprintf ("%04d-%02d-%02d" ,
843849 binary .LittleEndian .Uint16 (data [pos :pos + 2 ]),
@@ -847,62 +853,120 @@ func (rc *mysqlRows) readBinaryRow(dest []driver.Value) (err error) {
847853 continue
848854 }
849855
850- // Time HH:MM:SS
856+ // Time [-][H] HH:MM:SS[.fractal]
851857 case FIELD_TYPE_TIME :
852858 var num uint64
853- // TODO(js): allow nil values
854- num , _ , n , err = readLengthEncodedInteger (data [pos :])
859+ var isNull bool
860+ num , isNull , n , err = readLengthEncodedInteger (data [pos :])
855861 if err != nil {
856862 return
857863 }
858864
859865 if num == 0 {
860- dest [i ] = []byte ("00:00:00" )
861- pos += n
866+ if isNull {
867+ dest [i ] = nil
868+ pos ++ // n = 1
869+ continue
870+ } else {
871+ dest [i ] = []byte ("00:00:00" )
872+ pos ++ // n = 1
873+ continue
874+ }
875+ }
876+
877+ pos += n
878+
879+ var sign byte
880+ if data [pos ] == 1 {
881+ sign = byte ('-' )
882+ }
883+
884+ switch num {
885+ case 8 :
886+ dest [i ] = []byte (fmt .Sprintf (
887+ "%c%02d:%02d:%02d" ,
888+ sign ,
889+ uint16 (data [pos + 1 ])* 24 + uint16 (data [pos + 5 ]),
890+ data [pos + 6 ],
891+ data [pos + 7 ],
892+ ))
893+ pos += 8
862894 continue
863- } else {
864- dest [i ] = []byte (fmt .Sprintf ("%02d:%02d:%02d" ,
895+ case 12 :
896+ dest [i ] = []byte (fmt .Sprintf (
897+ "%c%02d:%02d:%02d.%06d" ,
898+ sign ,
899+ uint16 (data [pos + 1 ])* 24 + uint16 (data [pos + 5 ]),
865900 data [pos + 6 ],
866901 data [pos + 7 ],
867- data [pos + 8 ]))
868- pos += n + int (num )
902+ binary .LittleEndian .Uint32 (data [pos + 8 :pos + 12 ]),
903+ ))
904+ pos += 12
869905 continue
906+ default :
907+ return fmt .Errorf ("Invalid TIME-packet length %d" , num )
870908 }
871909
872- // Timestamp YYYY-MM-DD HH:MM:SS
910+ // Timestamp YYYY-MM-DD HH:MM:SS[.fractal]
873911 case FIELD_TYPE_TIMESTAMP , FIELD_TYPE_DATETIME :
874912 var num uint64
875- // TODO(js): allow nil values
876- num , _ , n , err = readLengthEncodedInteger (data [pos :])
913+ var isNull bool
914+ num , isNull , n , err = readLengthEncodedInteger (data [pos :])
877915 if err != nil {
878916 return
879917 }
880918
919+ if num == 0 {
920+ if isNull {
921+ dest [i ] = nil
922+ pos ++ // n = 1
923+ continue
924+ } else {
925+ dest [i ] = []byte ("0000-00-00 00:00:00" )
926+ pos ++ // n = 1
927+ continue
928+ }
929+ }
930+
931+ pos += n
932+
881933 switch num {
882- case 0 :
883- dest [i ] = []byte ("0000-00-00 00:00:00" )
884- pos += n
885- continue
886934 case 4 :
887- dest [i ] = []byte (fmt .Sprintf ("%04d-%02d-%02d 00:00:00" ,
935+ dest [i ] = []byte (fmt .Sprintf (
936+ "%04d-%02d-%02d 00:00:00" ,
888937 binary .LittleEndian .Uint16 (data [pos :pos + 2 ]),
889938 data [pos + 2 ],
890- data [pos + 3 ]))
891- pos += n + int (num )
939+ data [pos + 3 ],
940+ ))
941+ pos += 5
892942 continue
893- default :
894- if num < 7 {
895- return fmt .Errorf ("Invalid datetime-packet length %d" , num )
896- }
897- dest [i ] = []byte (fmt .Sprintf ("%04d-%02d-%02d %02d:%02d:%02d" ,
943+ case 7 :
944+ dest [i ] = []byte (fmt .Sprintf (
945+ "%04d-%02d-%02d %02d:%02d:%02d" ,
898946 binary .LittleEndian .Uint16 (data [pos :pos + 2 ]),
899947 data [pos + 2 ],
900948 data [pos + 3 ],
901949 data [pos + 4 ],
902950 data [pos + 5 ],
903- data [pos + 6 ]))
904- pos += n + int (num )
951+ data [pos + 6 ],
952+ ))
953+ pos += 7
905954 continue
955+ case 11 :
956+ dest [i ] = []byte (fmt .Sprintf (
957+ "%04d-%02d-%02d %02d:%02d:%02d.%06d" ,
958+ binary .LittleEndian .Uint16 (data [pos :pos + 2 ]),
959+ data [pos + 2 ],
960+ data [pos + 3 ],
961+ data [pos + 4 ],
962+ data [pos + 5 ],
963+ data [pos + 6 ],
964+ binary .LittleEndian .Uint32 (data [pos + 7 :pos + 11 ]),
965+ ))
966+ pos += 11
967+ continue
968+ default :
969+ return fmt .Errorf ("Invalid DATETIME-packet length %d" , num )
906970 }
907971
908972 // Please report if this happens!
0 commit comments