From fe07a17dc6eafe7e89f5b343ce0767fdf19126d4 Mon Sep 17 00:00:00 2001 From: inoth Date: Fri, 6 Dec 2024 15:21:41 +0800 Subject: [PATCH 1/2] feat: Added support for datetime format --- mysql/resultset_helper.go | 49 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/mysql/resultset_helper.go b/mysql/resultset_helper.go index 36c0f0a3b..539d40289 100644 --- a/mysql/resultset_helper.go +++ b/mysql/resultset_helper.go @@ -1,13 +1,54 @@ package mysql import ( + "bytes" + "encoding/binary" "math" "strconv" + "time" "github.com/pingcap/errors" "github.com/siddontang/go/hack" ) +func toBinaryDateTime(t time.Time) ([]byte, error) { + var buf bytes.Buffer + + if t.IsZero() { + return nil, nil + } + + year, month, day := t.Year(), t.Month(), t.Day() + hour, min, sec := t.Hour(), t.Minute(), t.Second() + nanosec := t.Nanosecond() + + if nanosec > 0 { + buf.WriteByte(byte(11)) + binary.Write(&buf, binary.LittleEndian, uint16(year)) + buf.WriteByte(byte(month)) + buf.WriteByte(byte(day)) + buf.WriteByte(byte(hour)) + buf.WriteByte(byte(min)) + buf.WriteByte(byte(sec)) + binary.Write(&buf, binary.LittleEndian, uint32(nanosec/1000)) + } else if hour > 0 || min > 0 || sec > 0 { + buf.WriteByte(byte(7)) + binary.Write(&buf, binary.LittleEndian, uint16(year)) + buf.WriteByte(byte(month)) + buf.WriteByte(byte(day)) + buf.WriteByte(byte(hour)) + buf.WriteByte(byte(min)) + buf.WriteByte(byte(sec)) + } else { + buf.WriteByte(byte(4)) + binary.Write(&buf, binary.LittleEndian, uint16(year)) + buf.WriteByte(byte(month)) + buf.WriteByte(byte(day)) + } + + return buf.Bytes(), nil +} + func FormatTextValue(value interface{}) ([]byte, error) { switch v := value.(type) { case int8: @@ -38,6 +79,8 @@ func FormatTextValue(value interface{}) ([]byte, error) { return v, nil case string: return hack.Slice(v), nil + case time.Time: + return hack.Slice(v.Format(time.DateTime)), nil case nil: return nil, nil default: @@ -75,6 +118,8 @@ func formatBinaryValue(value interface{}) ([]byte, error) { return v, nil case string: return hack.Slice(v), nil + case time.Time: + return toBinaryDateTime(v) default: return nil, errors.Errorf("invalid type %T", value) } @@ -90,6 +135,8 @@ func fieldType(value interface{}) (typ uint8, err error) { typ = MYSQL_TYPE_DOUBLE case string, []byte: typ = MYSQL_TYPE_VAR_STRING + case time.Time: + typ = MYSQL_TYPE_DATETIME case nil: typ = MYSQL_TYPE_NULL default: @@ -109,7 +156,7 @@ func formatField(field *Field, value interface{}) error { case float32, float64: field.Charset = 63 field.Flag = BINARY_FLAG | NOT_NULL_FLAG - case string, []byte: + case string, []byte, time.Time: field.Charset = 33 case nil: field.Charset = 33 From aa48110a611838be6e3a3a642a8e2cefa9ba05fa Mon Sep 17 00:00:00 2001 From: inoth Date: Thu, 12 Dec 2024 11:24:58 +0800 Subject: [PATCH 2/2] fix: handler "Error return value of `binary.Write` is not checked" --- mysql/resultset_helper.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql/resultset_helper.go b/mysql/resultset_helper.go index 539d40289..cc59f04de 100644 --- a/mysql/resultset_helper.go +++ b/mysql/resultset_helper.go @@ -24,16 +24,16 @@ func toBinaryDateTime(t time.Time) ([]byte, error) { if nanosec > 0 { buf.WriteByte(byte(11)) - binary.Write(&buf, binary.LittleEndian, uint16(year)) + _ = binary.Write(&buf, binary.LittleEndian, uint16(year)) buf.WriteByte(byte(month)) buf.WriteByte(byte(day)) buf.WriteByte(byte(hour)) buf.WriteByte(byte(min)) buf.WriteByte(byte(sec)) - binary.Write(&buf, binary.LittleEndian, uint32(nanosec/1000)) + _ = binary.Write(&buf, binary.LittleEndian, uint32(nanosec/1000)) } else if hour > 0 || min > 0 || sec > 0 { buf.WriteByte(byte(7)) - binary.Write(&buf, binary.LittleEndian, uint16(year)) + _ = binary.Write(&buf, binary.LittleEndian, uint16(year)) buf.WriteByte(byte(month)) buf.WriteByte(byte(day)) buf.WriteByte(byte(hour)) @@ -41,7 +41,7 @@ func toBinaryDateTime(t time.Time) ([]byte, error) { buf.WriteByte(byte(sec)) } else { buf.WriteByte(byte(4)) - binary.Write(&buf, binary.LittleEndian, uint16(year)) + _ = binary.Write(&buf, binary.LittleEndian, uint16(year)) buf.WriteByte(byte(month)) buf.WriteByte(byte(day)) }