Explorar o código

changed binary date / datetime to string

Arne Hormann %!s(int64=12) %!d(string=hai) anos
pai
achega
f38e41de89
Modificáronse 2 ficheiros con 56 adicións e 48 borrados
  1. 2 2
      packets.go
  2. 54 46
      utils.go

+ 2 - 2
packets.go

@@ -1048,7 +1048,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 			if rows.mc.parseTime {
 				dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.loc)
 			} else {
-				dest[i], err = formatBinaryDate(num, data[pos:])
+				dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], false)
 			}
 
 			if err == nil {
@@ -1116,7 +1116,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 			if rows.mc.parseTime {
 				dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.loc)
 			} else {
-				dest[i], err = formatBinaryDateTime(num, data[pos:])
+				dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], true)
 			}
 
 			if err == nil {

+ 54 - 46
utils.go

@@ -503,55 +503,63 @@ func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Va
 	return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num)
 }
 
-func formatBinaryDate(num uint64, data []byte) (driver.Value, error) {
-	switch num {
-	case 0:
-		return []byte("0000-00-00"), nil
+func formatBinaryDateTime(src []byte, withTime bool) (driver.Value, error) {
+	const zeroDateTimeMicros = "0000-00-00 00:00:00.000000"
+	srclen := len(src)
+	var dst []byte
+	if withTime {
+		if srclen == 11 {
+			dst = []byte(zeroDateTimeMicros)
+		} else {
+			dst = []byte(zeroDateTimeMicros[:19])
+		}
+	} else {
+		dst = []byte(zeroDateTimeMicros[:10])
+	}
+	switch srclen {
+	case 11:
+		microsecs := binary.LittleEndian.Uint32(src[7:11])
+		dst[20] += byte((microsecs / 100000) % 10)
+		dst[21] += byte((microsecs / 10000) % 10)
+		dst[22] += byte((microsecs / 1000) % 10)
+		dst[23] += byte((microsecs / 100) % 10)
+		dst[24] += byte((microsecs / 10) % 10)
+		dst[25] += byte(microsecs % 10)
+		fallthrough
+	case 7:
+		hour := src[4]
+		minute := src[5]
+		second := src[6]
+		dst[11] += (hour / 10) % 10
+		dst[12] += hour % 10
+		dst[14] += (minute / 10) % 10
+		dst[15] += minute % 10
+		dst[17] += (second / 10) % 10
+		dst[18] += second % 10
+		fallthrough
 	case 4:
-		return []byte(fmt.Sprintf(
-			"%04d-%02d-%02d",
-			binary.LittleEndian.Uint16(data[:2]),
-			data[2],
-			data[3],
-		)), nil
-	}
-	return nil, fmt.Errorf("Invalid DATE-packet length %d", num)
-}
-
-func formatBinaryDateTime(num uint64, data []byte) (driver.Value, error) {
-	switch num {
+		year := binary.LittleEndian.Uint16(src[:2])
+		month := src[2]
+		day := src[3]
+		dst[0] += byte((year / 1000) % 10)
+		dst[1] += byte((year / 100) % 10)
+		dst[2] += byte((year / 10) % 10)
+		dst[3] += byte(year % 10)
+		dst[5] += (month / 10) % 10
+		dst[6] += month % 10
+		dst[8] += (day / 10) % 10
+		dst[9] += day % 10
+		return dst, nil
 	case 0:
-		return []byte("0000-00-00 00:00:00"), nil
-	case 4:
-		return []byte(fmt.Sprintf(
-			"%04d-%02d-%02d 00:00:00",
-			binary.LittleEndian.Uint16(data[:2]),
-			data[2],
-			data[3],
-		)), nil
-	case 7:
-		return []byte(fmt.Sprintf(
-			"%04d-%02d-%02d %02d:%02d:%02d",
-			binary.LittleEndian.Uint16(data[:2]),
-			data[2],
-			data[3],
-			data[4],
-			data[5],
-			data[6],
-		)), nil
-	case 11:
-		return []byte(fmt.Sprintf(
-			"%04d-%02d-%02d %02d:%02d:%02d.%06d",
-			binary.LittleEndian.Uint16(data[:2]),
-			data[2],
-			data[3],
-			data[4],
-			data[5],
-			data[6],
-			binary.LittleEndian.Uint32(data[7:11]),
-		)), nil
+		return dst, nil
 	}
-	return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num)
+	var mode string
+	if withTime {
+		mode = "DATETIME"
+	} else {
+		mode = "DATE"
+	}
+	return nil, fmt.Errorf("invalid %s-packet length %d", mode, srclen)
 }
 
 /******************************************************************************