Enable fractional seconds in Time column for Mysql

Mysql (5.6.4 and up) supports up to 6 digits fractional seconds in
Time values. This patch adds "frac" field annotation to support it.

http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html

Sample usage:
Foo { ts time.Time `sql:"frac:3"` }
This commit is contained in:
Jiulong Wang 2017-01-10 07:10:51 -08:00
parent 1aa2d4ca89
commit 5597f7eb10
2 changed files with 75 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
@ -80,10 +81,18 @@ func (mysql) DataTypeOf(field *StructField) string {
}
case reflect.Struct:
if _, ok := dataValue.Interface().(time.Time); ok {
if _, ok := field.TagSettings["NOT NULL"]; ok {
sqlType = "timestamp"
if num, ok := field.TagSettings["FRAC"]; ok {
frac, err := strconv.Atoi(num)
if err != nil || frac < 0 {
frac = 0
}
if frac > 6 {
frac = 6
}
sqlType = fmt.Sprintf("timestamp(%d)", frac)
} else {
sqlType = "timestamp NULL"
sqlType = "timestamp"
}
}
default:

View File

@ -436,3 +436,66 @@ func TestMultipleIndexes(t *testing.T) {
t.Error("MultipleIndexes unique index failed")
}
}
type FractionalSeconds struct {
Id int
NoFractional time.Time
MillisecFractional time.Time `sql:"frac:3"`
MicrosecFractional *time.Time `sql:"frac:6;not null"`
}
func TestFractionalSeconds(t *testing.T) {
if err := DB.DropTableIfExists(&FractionalSeconds{}).Error; err != nil {
fmt.Printf("Failed to delete table fractional_seconds: %+v\n", err)
return
}
if err := DB.AutoMigrate(&FractionalSeconds{}).Error; err != nil {
t.Error("Auto Migrating FractionalSeconds should not raise any error.")
return
}
testTime := time.Date(2017, 1, 9, 10, 12, 23, 123456789, time.UTC)
record := FractionalSeconds{
Id: 123,
NoFractional: testTime,
MillisecFractional: testTime,
MicrosecFractional: &testTime,
}
if err := DB.Save(&record).Error; err != nil {
t.Error("Saving FractionalSeconds should not raise any error.")
return
}
retrieve := FractionalSeconds{}
if err := DB.First(&retrieve).Error; err != nil {
t.Error("Retrieving FractionalSeconds should not raise any error.")
return
}
if retrieve.NoFractional.Nanosecond() != 0 {
t.Error("NoFractional column value is incorrect.")
}
if retrieve.MillisecFractional.Nanosecond() != 123000000 {
t.Error("MillisecFractional column value is incorrect.")
}
if retrieve.MicrosecFractional.Nanosecond() != 123456000 {
t.Error("MicrosecFractional column value is incorrect.")
}
record = FractionalSeconds{
Id: 456,
NoFractional: testTime,
MillisecFractional: testTime,
MicrosecFractional: nil,
}
if err := DB.Save(&record).Error; err == nil {
t.Error("Saving FractionalSeconds should raise error when not null column is null.")
return
}
}