From 7e11f585aac4898822e5aa3a41379f98694e6c81 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 08:39:36 +0800 Subject: [PATCH 01/15] Fix deleted tag attribute zeroTime is not DatabaseTZ --- integrations/session_insert_test.go | 40 +++++++++++++++++++++++++++++ session_insert.go | 3 ++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/integrations/session_insert_test.go b/integrations/session_insert_test.go index 084deb38..03fe74a1 100644 --- a/integrations/session_insert_test.go +++ b/integrations/session_insert_test.go @@ -1202,3 +1202,43 @@ func TestInsertMultipleMap(t *testing.T) { Name: "xiaolunwen", }, res[1]) } + +func TestInsertNotDeleted(t *testing.T) { + assert.NoError(t, PrepareEngine()) + zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, testEngine.GetTZDatabase()) + + type InsertDeletedStructNotRight struct { + ID uint64 `xorm:"'ID' pk autoincr"` + DeletedAt time.Time `xorm:"'DELETED_AT' deleted notnull"` + } + // notnull tag will be ignored + err := testEngine.Sync(new(InsertDeletedStructNotRight)) + assert.NoError(t, err) + + type InsertDeletedStruct struct { + ID uint64 `xorm:"'ID' pk autoincr"` + DeletedAt time.Time `xorm:"'DELETED_AT' deleted"` + } + + assert.NoError(t, testEngine.Sync(new(InsertDeletedStruct))) + + var v1 InsertDeletedStructNotRight + _, err = testEngine.Insert(&v1) + assert.NoError(t, err) + + var v2 InsertDeletedStructNotRight + has, err := testEngine.Get(&v2) + assert.NoError(t, err) + assert.True(t, has) + assert.Equal(t, v2.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) + + var v3 InsertDeletedStruct + _, err = testEngine.Insert(&v3) + assert.NoError(t, err) + + var v4 InsertDeletedStruct + has, err = testEngine.Get(&v4) + assert.NoError(t, err) + assert.True(t, has) + assert.Equal(t, v4.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) +} diff --git a/session_insert.go b/session_insert.go index cfa26d39..4067c3a8 100644 --- a/session_insert.go +++ b/session_insert.go @@ -482,7 +482,8 @@ func (session *Session) genInsertColumns(bean interface{}) ([]string, []interfac } if col.IsDeleted { - arg, err := dialects.FormatColumnTime(session.engine.dialect, session.engine.DatabaseTZ, col, time.Time{}) + zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, session.engine.DatabaseTZ) + arg, err := dialects.FormatColumnTime(session.engine.dialect, session.engine.DatabaseTZ, col, zeroTime) if err != nil { return nil, nil, err } From ff292dfcf3fd4a56ab9768fb71d5728ebb531e54 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 08:57:24 +0800 Subject: [PATCH 02/15] change test Struct name --- integrations/session_insert_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/integrations/session_insert_test.go b/integrations/session_insert_test.go index 03fe74a1..5af5b9e4 100644 --- a/integrations/session_insert_test.go +++ b/integrations/session_insert_test.go @@ -1207,36 +1207,36 @@ func TestInsertNotDeleted(t *testing.T) { assert.NoError(t, PrepareEngine()) zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, testEngine.GetTZDatabase()) - type InsertDeletedStructNotRight struct { + type TestInsertNotDeletedStructNotRight struct { ID uint64 `xorm:"'ID' pk autoincr"` DeletedAt time.Time `xorm:"'DELETED_AT' deleted notnull"` } // notnull tag will be ignored - err := testEngine.Sync(new(InsertDeletedStructNotRight)) + err := testEngine.Sync(new(TestInsertNotDeletedStructNotRight)) assert.NoError(t, err) - type InsertDeletedStruct struct { + type TestInsertNotDeletedStruct struct { ID uint64 `xorm:"'ID' pk autoincr"` DeletedAt time.Time `xorm:"'DELETED_AT' deleted"` } - assert.NoError(t, testEngine.Sync(new(InsertDeletedStruct))) + assert.NoError(t, testEngine.Sync(new(TestInsertNotDeletedStruct))) - var v1 InsertDeletedStructNotRight + var v1 TestInsertNotDeletedStructNotRight _, err = testEngine.Insert(&v1) assert.NoError(t, err) - var v2 InsertDeletedStructNotRight + var v2 TestInsertNotDeletedStructNotRight has, err := testEngine.Get(&v2) assert.NoError(t, err) assert.True(t, has) assert.Equal(t, v2.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) - var v3 InsertDeletedStruct + var v3 TestInsertNotDeletedStruct _, err = testEngine.Insert(&v3) assert.NoError(t, err) - var v4 InsertDeletedStruct + var v4 TestInsertNotDeletedStruct has, err = testEngine.Get(&v4) assert.NoError(t, err) assert.True(t, has) From 158b67964bb039a61ddb08fd31c44581b03f3c75 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 11:13:20 +0800 Subject: [PATCH 03/15] fix time parse layout --- convert/time.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/convert/time.go b/convert/time.go index dab6a9a2..dc36912b 100644 --- a/convert/time.go +++ b/convert/time.go @@ -41,7 +41,7 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t dt = dt.In(convertedLocation) return &dt, nil } else if len(s) >= 21 && s[10] == 'T' && s[19] == '.' { - dt, err := time.Parse(time.RFC3339, s) + dt, err := time.Parse(time.RFC3339Nano, s) if err != nil { return nil, err } From efc4e6ab1dfa78133a63299ca227f8b6b7a15361 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 12:17:34 +0800 Subject: [PATCH 04/15] add test code --- integrations/time_test.go | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/integrations/time_test.go b/integrations/time_test.go index a8447eea..5a17417a 100644 --- a/integrations/time_test.go +++ b/integrations/time_test.go @@ -6,9 +6,11 @@ package integrations import ( "fmt" + "strconv" "strings" "testing" "time" + "xorm.io/xorm/convert" "xorm.io/xorm/internal/utils" @@ -619,3 +621,59 @@ func TestTimestamp(t *testing.T) { assert.EqualValues(t, formatTime(d3.InsertTime, 6), formatTime(d4.InsertTime, 6)) }*/ } + +func TestString2Time(t *testing.T) { + loc, err := time.LoadLocation("Asia/Shanghai") + assert.NoError(t, err) + var timeTmp1 = time.Date(2023, 7, 14, 11, 30, 0, 0, loc) + var timeTmp2 = time.Date(2023, 7, 14, 0, 0, 0, 0, loc) + var time1StampStr = strconv.FormatInt(timeTmp1.Unix(), 10) + var timeStr = "0000-00-00 00:00:00" + dt, err := convert.String2Time(timeStr, time.Local, time.Local) + assert.NoError(t, err) + assert.True(t, dt.Nanosecond() == 0) + + timeStr = "0001-01-01 00:00:00" + dt, err = convert.String2Time(timeStr, time.Local, time.Local) + assert.NoError(t, err) + assert.True(t, dt.Nanosecond() == 0) + + timeStr = "2023-07-14 11:30:00" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, timeTmp1.In(time.UTC).Equal(*dt)) + + timeStr = "2023-07-14T11:30:00Z" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, timeTmp1.In(time.UTC).Equal(*dt)) + + timeStr = "2023-07-14T11:30:00+08:00" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, timeTmp1.In(time.UTC).Equal(*dt)) + + timeStr = "2023-07-14T11:30:00.00000000+08:00" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, timeTmp1.In(time.UTC).Equal(*dt)) + + timeStr = "0000-00-00" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, dt.Nanosecond() == 0) + + timeStr = "0001-01-01" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, dt.Nanosecond() == 0) + + timeStr = "2023-07-14" + dt, err = convert.String2Time(timeStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, timeTmp2.In(time.UTC).Equal(*dt)) + + dt, err = convert.String2Time(time1StampStr, loc, time.UTC) + assert.NoError(t, err) + assert.True(t, timeTmp1.In(time.UTC).Equal(*dt)) +} From 85dd334d2f27d03f86fce9450b00fa85da4e3b64 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 14:17:37 +0800 Subject: [PATCH 05/15] fix zero time --- convert/time.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/convert/time.go b/convert/time.go index dc36912b..120dceaa 100644 --- a/convert/time.go +++ b/convert/time.go @@ -27,6 +27,9 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t dt = dt.In(convertedLocation) return &dt, nil } else if len(s) == 20 && s[10] == 'T' && s[19] == 'Z' { + if strings.HasPrefix(s, "0000-00-00T00:00:00") || strings.HasPrefix(s, "0001-01-01T00:00:00") { + return &time.Time{}, nil + } dt, err := time.ParseInLocation("2006-01-02T15:04:05", s[:19], originalLocation) if err != nil { return nil, err @@ -34,6 +37,9 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t dt = dt.In(convertedLocation) return &dt, nil } else if len(s) == 25 && s[10] == 'T' && s[19] == '+' && s[22] == ':' { + if strings.HasPrefix(s, "0000-00-00T00:00:00") || strings.HasPrefix(s, "0001-01-01T00:00:00") { + return &time.Time{}, nil + } dt, err := time.Parse(time.RFC3339, s) if err != nil { return nil, err @@ -41,6 +47,10 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t dt = dt.In(convertedLocation) return &dt, nil } else if len(s) >= 21 && s[10] == 'T' && s[19] == '.' { + if strings.HasPrefix(s, "0000-00-00T00:00:00."+strings.Repeat("0", len(s)-20)) || + strings.HasPrefix(s, "0001-01-01T00:00:00."+strings.Repeat("0", len(s)-20)) { + return &time.Time{}, nil + } dt, err := time.Parse(time.RFC3339Nano, s) if err != nil { return nil, err @@ -48,6 +58,10 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t dt = dt.In(convertedLocation) return &dt, nil } else if len(s) >= 21 && s[19] == '.' { + if strings.HasPrefix(s, "0000-00-00T00:00:00."+strings.Repeat("0", len(s)-20)) || + strings.HasPrefix(s, "0001-01-01T00:00:00."+strings.Repeat("0", len(s)-20)) { + return &time.Time{}, nil + } var layout = "2006-01-02 15:04:05." + strings.Repeat("0", len(s)-20) dt, err := time.ParseInLocation(layout, s, originalLocation) if err != nil { @@ -68,6 +82,9 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t } else { i, err := strconv.ParseInt(s, 10, 64) if err == nil { + if i == 0 { + return &time.Time{}, nil + } tm := time.Unix(i, 0).In(convertedLocation) return &tm, nil } From 116746586757f7ab7702817388b5c27a6d336e35 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 14:24:21 +0800 Subject: [PATCH 06/15] fix zero time --- convert/time.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/convert/time.go b/convert/time.go index 120dceaa..544eca6f 100644 --- a/convert/time.go +++ b/convert/time.go @@ -111,6 +111,9 @@ func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time. if !t.Valid { return nil, nil } + if utils.IsTimeZero(t.Time) { + return &time.Time{}, nil + } z, _ := t.Time.Zone() if len(z) == 0 || t.Time.Year() == 0 || t.Time.Location().String() != dbLoc.String() { tm := time.Date(t.Time.Year(), t.Time.Month(), t.Time.Day(), t.Time.Hour(), @@ -120,6 +123,9 @@ func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time. tm := t.Time.In(uiLoc) return &tm, nil case *time.Time: + if utils.IsTimeZero(*t) { + return &time.Time{}, nil + } z, _ := t.Zone() if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() { tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), @@ -129,6 +135,9 @@ func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time. tm := t.In(uiLoc) return &tm, nil case time.Time: + if utils.IsTimeZero(t) { + return &time.Time{}, nil + } z, _ := t.Zone() if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() { tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), @@ -138,12 +147,21 @@ func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time. tm := t.In(uiLoc) return &tm, nil case int: + if t == 0 { + return &time.Time{}, nil + } tm := time.Unix(int64(t), 0).In(uiLoc) return &tm, nil case int64: + if t == 0 { + return &time.Time{}, nil + } tm := time.Unix(t, 0).In(uiLoc) return &tm, nil case *sql.NullInt64: + if t.Int64 == 0 { + return &time.Time{}, nil + } tm := time.Unix(t.Int64, 0).In(uiLoc) return &tm, nil } From 93ef9bd84a2e01ecc1aea88e9565560e244b8eb9 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 16:39:06 +0800 Subject: [PATCH 07/15] del not right test struct --- integrations/session_insert_test.go | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/integrations/session_insert_test.go b/integrations/session_insert_test.go index 5af5b9e4..1e1b40e6 100644 --- a/integrations/session_insert_test.go +++ b/integrations/session_insert_test.go @@ -1207,14 +1207,6 @@ func TestInsertNotDeleted(t *testing.T) { assert.NoError(t, PrepareEngine()) zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, testEngine.GetTZDatabase()) - type TestInsertNotDeletedStructNotRight struct { - ID uint64 `xorm:"'ID' pk autoincr"` - DeletedAt time.Time `xorm:"'DELETED_AT' deleted notnull"` - } - // notnull tag will be ignored - err := testEngine.Sync(new(TestInsertNotDeletedStructNotRight)) - assert.NoError(t, err) - type TestInsertNotDeletedStruct struct { ID uint64 `xorm:"'ID' pk autoincr"` DeletedAt time.Time `xorm:"'DELETED_AT' deleted"` @@ -1222,22 +1214,12 @@ func TestInsertNotDeleted(t *testing.T) { assert.NoError(t, testEngine.Sync(new(TestInsertNotDeletedStruct))) - var v1 TestInsertNotDeletedStructNotRight - _, err = testEngine.Insert(&v1) - assert.NoError(t, err) - - var v2 TestInsertNotDeletedStructNotRight - has, err := testEngine.Get(&v2) - assert.NoError(t, err) - assert.True(t, has) - assert.Equal(t, v2.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) - var v3 TestInsertNotDeletedStruct - _, err = testEngine.Insert(&v3) + _, err := testEngine.Insert(&v3) assert.NoError(t, err) var v4 TestInsertNotDeletedStruct - has, err = testEngine.Get(&v4) + has, err := testEngine.Get(&v4) assert.NoError(t, err) assert.True(t, has) assert.Equal(t, v4.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) From a16551c6e710345f2e04e5c88ecb5842500c5095 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 17:13:52 +0800 Subject: [PATCH 08/15] SQL Server database, default mapping of time type to DATETIME2 --- dialects/mssql.go | 6 +----- integrations/session_insert_test.go | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/dialects/mssql.go b/dialects/mssql.go index dcac9c3f..2c64e637 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -320,11 +320,7 @@ func (db *mssql) SQLType(c *schemas.Column) string { res += "(MAX)" } case schemas.TimeStamp, schemas.DateTime: - if c.Length > 3 { - res = "DATETIME2" - } else { - return schemas.DateTime - } + return "DATETIME2" case schemas.TimeStampz: res = "DATETIMEOFFSET" c.Length = 7 diff --git a/integrations/session_insert_test.go b/integrations/session_insert_test.go index 1e1b40e6..5af5b9e4 100644 --- a/integrations/session_insert_test.go +++ b/integrations/session_insert_test.go @@ -1207,6 +1207,14 @@ func TestInsertNotDeleted(t *testing.T) { assert.NoError(t, PrepareEngine()) zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, testEngine.GetTZDatabase()) + type TestInsertNotDeletedStructNotRight struct { + ID uint64 `xorm:"'ID' pk autoincr"` + DeletedAt time.Time `xorm:"'DELETED_AT' deleted notnull"` + } + // notnull tag will be ignored + err := testEngine.Sync(new(TestInsertNotDeletedStructNotRight)) + assert.NoError(t, err) + type TestInsertNotDeletedStruct struct { ID uint64 `xorm:"'ID' pk autoincr"` DeletedAt time.Time `xorm:"'DELETED_AT' deleted"` @@ -1214,12 +1222,22 @@ func TestInsertNotDeleted(t *testing.T) { assert.NoError(t, testEngine.Sync(new(TestInsertNotDeletedStruct))) + var v1 TestInsertNotDeletedStructNotRight + _, err = testEngine.Insert(&v1) + assert.NoError(t, err) + + var v2 TestInsertNotDeletedStructNotRight + has, err := testEngine.Get(&v2) + assert.NoError(t, err) + assert.True(t, has) + assert.Equal(t, v2.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) + var v3 TestInsertNotDeletedStruct - _, err := testEngine.Insert(&v3) + _, err = testEngine.Insert(&v3) assert.NoError(t, err) var v4 TestInsertNotDeletedStruct - has, err := testEngine.Get(&v4) + has, err = testEngine.Get(&v4) assert.NoError(t, err) assert.True(t, has) assert.Equal(t, v4.DeletedAt.In(testEngine.GetTZDatabase()).Format("2006-01-02 15:04:05"), zeroTime.Format("2006-01-02 15:04:05")) From 7bb32241154244a129a9f9fb722c7ce0bff9c6d8 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 17:20:32 +0800 Subject: [PATCH 09/15] SQL Server database, default mapping of time type to DATETIME2 --- dialects/mssql.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dialects/mssql.go b/dialects/mssql.go index 2c64e637..5a825c79 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -320,6 +320,7 @@ func (db *mssql) SQLType(c *schemas.Column) string { res += "(MAX)" } case schemas.TimeStamp, schemas.DateTime: + c.Length = 7 return "DATETIME2" case schemas.TimeStampz: res = "DATETIMEOFFSET" From a6b31d79d7c9649da43022fc5e376fce6e632c8a Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 17:50:54 +0800 Subject: [PATCH 10/15] fix conditions build on MSSQL --- internal/statements/statement.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/statements/statement.go b/internal/statements/statement.go index ae38ca27..306676e5 100644 --- a/internal/statements/statement.go +++ b/internal/statements/statement.go @@ -691,10 +691,7 @@ func (statement *Statement) CondDeleted(col *schemas.Column) builder.Cond { if col.SQLType.IsNumeric() { cond = builder.Eq{colName: 0} } else { - // FIXME: mssql: The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value. - if statement.dialect.URI().DBType != schemas.MSSQL { - cond = builder.Eq{colName: utils.ZeroTime1} - } + cond = builder.Eq{colName: utils.ZeroTime1} } if col.Nullable { From 50ef83d4567363aa728fce60f6fb5d08ba457031 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 18:27:29 +0800 Subject: [PATCH 11/15] fix TestTagTime --- convert/time.go | 7 +++++++ integrations/tags_test.go | 11 ++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/convert/time.go b/convert/time.go index 544eca6f..6e20b510 100644 --- a/convert/time.go +++ b/convert/time.go @@ -69,6 +69,13 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t } dt = dt.In(convertedLocation) return &dt, nil + } else if len(s) == 21 && s[10] == 'T' { + dt, err := time.ParseInLocation("2006-01-02T15:04:05", s[:19], originalLocation) + if err != nil { + return nil, err + } + dt = dt.In(convertedLocation) + return &dt, nil } else if len(s) == 10 && s[4] == '-' { if s == "0000-00-00" || s == "0001-01-01" { return &time.Time{}, nil diff --git a/integrations/tags_test.go b/integrations/tags_test.go index 4c33d56c..bf021058 100644 --- a/integrations/tags_test.go +++ b/integrations/tags_test.go @@ -6,12 +6,11 @@ package integrations import ( "fmt" + "github.com/stretchr/testify/assert" "sort" - "strings" "testing" "time" - - "github.com/stretchr/testify/assert" + "xorm.io/xorm/convert" "xorm.io/xorm/internal/utils" "xorm.io/xorm/names" "xorm.io/xorm/schemas" @@ -1201,8 +1200,10 @@ func TestTagTime(t *testing.T) { has, err = testEngine.Table("tag_u_t_c_struct").Cols("created").Get(&tm) assert.NoError(t, err) assert.True(t, has) - assert.EqualValues(t, s.Created.UTC().Format("2006-01-02 15:04:05"), - strings.ReplaceAll(strings.ReplaceAll(tm, "T", " "), "Z", "")) + + tmTime, err := convert.String2Time(tm, time.UTC, time.UTC) + assert.NoError(t, err) + assert.EqualValues(t, s.Created.UTC().Format("2006-01-02 15:04:05"), tmTime.Format("2006-01-02 15:04:05")) } func TestTagAutoIncr(t *testing.T) { From eb076f4b9408fa2405977408a60f7b18a8ab14e0 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 18:30:23 +0800 Subject: [PATCH 12/15] fix String2Time --- convert/time.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/convert/time.go b/convert/time.go index 6e20b510..544eca6f 100644 --- a/convert/time.go +++ b/convert/time.go @@ -69,13 +69,6 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t } dt = dt.In(convertedLocation) return &dt, nil - } else if len(s) == 21 && s[10] == 'T' { - dt, err := time.ParseInLocation("2006-01-02T15:04:05", s[:19], originalLocation) - if err != nil { - return nil, err - } - dt = dt.In(convertedLocation) - return &dt, nil } else if len(s) == 10 && s[4] == '-' { if s == "0000-00-00" || s == "0001-01-01" { return &time.Time{}, nil From 269811a4979aa32bdc103f097ac5d46c81249288 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 21 Jul 2023 10:14:13 +0800 Subject: [PATCH 13/15] fix code --- integrations/tags_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integrations/tags_test.go b/integrations/tags_test.go index bf021058..642b6140 100644 --- a/integrations/tags_test.go +++ b/integrations/tags_test.go @@ -6,10 +6,11 @@ package integrations import ( "fmt" - "github.com/stretchr/testify/assert" "sort" "testing" "time" + + "github.com/stretchr/testify/assert" "xorm.io/xorm/convert" "xorm.io/xorm/internal/utils" "xorm.io/xorm/names" From 21b54e5d61153c57604488a99dbb4c85516993ea Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 21 Jul 2023 11:12:31 +0800 Subject: [PATCH 14/15] fix code --- dialects/mssql.go | 7 +++++-- integrations/session_insert_test.go | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dialects/mssql.go b/dialects/mssql.go index 5a825c79..dcac9c3f 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -320,8 +320,11 @@ func (db *mssql) SQLType(c *schemas.Column) string { res += "(MAX)" } case schemas.TimeStamp, schemas.DateTime: - c.Length = 7 - return "DATETIME2" + if c.Length > 3 { + res = "DATETIME2" + } else { + return schemas.DateTime + } case schemas.TimeStampz: res = "DATETIMEOFFSET" c.Length = 7 diff --git a/integrations/session_insert_test.go b/integrations/session_insert_test.go index 5af5b9e4..58a2a91d 100644 --- a/integrations/session_insert_test.go +++ b/integrations/session_insert_test.go @@ -1209,7 +1209,7 @@ func TestInsertNotDeleted(t *testing.T) { type TestInsertNotDeletedStructNotRight struct { ID uint64 `xorm:"'ID' pk autoincr"` - DeletedAt time.Time `xorm:"'DELETED_AT' deleted notnull"` + DeletedAt time.Time `xorm:"'DELETED_AT' DATETIME(6) deleted notnull"` } // notnull tag will be ignored err := testEngine.Sync(new(TestInsertNotDeletedStructNotRight)) @@ -1217,7 +1217,7 @@ func TestInsertNotDeleted(t *testing.T) { type TestInsertNotDeletedStruct struct { ID uint64 `xorm:"'ID' pk autoincr"` - DeletedAt time.Time `xorm:"'DELETED_AT' deleted"` + DeletedAt time.Time `xorm:"'DELETED_AT' DATETIME(6) deleted"` } assert.NoError(t, testEngine.Sync(new(TestInsertNotDeletedStruct))) From 58ba01b29928fd0627de7197e3d2599484b21c5f Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 21 Jul 2023 11:35:15 +0800 Subject: [PATCH 15/15] fix code --- integrations/session_insert_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/session_insert_test.go b/integrations/session_insert_test.go index 58a2a91d..5af5b9e4 100644 --- a/integrations/session_insert_test.go +++ b/integrations/session_insert_test.go @@ -1209,7 +1209,7 @@ func TestInsertNotDeleted(t *testing.T) { type TestInsertNotDeletedStructNotRight struct { ID uint64 `xorm:"'ID' pk autoincr"` - DeletedAt time.Time `xorm:"'DELETED_AT' DATETIME(6) deleted notnull"` + DeletedAt time.Time `xorm:"'DELETED_AT' deleted notnull"` } // notnull tag will be ignored err := testEngine.Sync(new(TestInsertNotDeletedStructNotRight)) @@ -1217,7 +1217,7 @@ func TestInsertNotDeleted(t *testing.T) { type TestInsertNotDeletedStruct struct { ID uint64 `xorm:"'ID' pk autoincr"` - DeletedAt time.Time `xorm:"'DELETED_AT' DATETIME(6) deleted"` + DeletedAt time.Time `xorm:"'DELETED_AT' deleted"` } assert.NoError(t, testEngine.Sync(new(TestInsertNotDeletedStruct)))