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:
		
							parent
							
								
									1aa2d4ca89
								
							
						
					
					
						commit
						5597f7eb10
					
				@ -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:
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user