From 0b18440d738b453aa3198fcae26cd38645a26ca7 Mon Sep 17 00:00:00 2001 From: CyJaySong Date: Fri, 14 Jul 2023 07:34:02 +0000 Subject: [PATCH 1/2] fix time parse layout (#2296) Reviewed-on: https://gitea.com/xorm/xorm/pulls/2296 Co-authored-by: CyJaySong Co-committed-by: CyJaySong --- convert/time.go | 2 +- integrations/time_test.go | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 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 } 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 9b71cb49cca4311cc84bcf2997b4d752bc8bfcea Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Fri, 14 Jul 2023 07:35:35 +0000 Subject: [PATCH 2/2] The loadTableInfo function supports passing the context. (#2297) ## `loadTableInfo` add context parameter ### Main change ```diff +++ func (engine *Engine) loadTableInfo(ctx context.Context, table *schemas.Table) error --- func (engine *Engine) loadTableInfo(table *schemas.Table) error ``` ### Situation After #2200, I built custom dialect to control the SQL. I find that everything else is fine, except when the `SYNC` method executes with an exception. The reason is that the `loadTableInfo` method calls the `GetIndexes` and `GetColumns` methods with the dialect during execution. **The context passed to these two methods are all `engine.defaultContext` not the current session's context.** So, I think the `loadTableInfo` method should add the context parameter to ensure that the correct context is used during execution. ### Review Note 1. dialect's `GetColumns` and `GetIndexes` methods are **only** used here, if the context here is incorrect, then the context parameter is invalid. 2. `loadTableInfo` method is only used in `SYNC` and `DBMetas` methods, `SYNC` should pass the session's context, while `DBMetas` has no problem passing `engine.defaultContext`. All in all, I think this change should not affect other function. Reviewed-on: https://gitea.com/xorm/xorm/pulls/2297 Co-authored-by: LinkinStars Co-committed-by: LinkinStars --- engine.go | 8 ++++---- sync.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/engine.go b/engine.go index aa9d8050..0cbfdede 100644 --- a/engine.go +++ b/engine.go @@ -360,15 +360,15 @@ func (engine *Engine) NoAutoCondition(no ...bool) *Session { return session.NoAutoCondition(no...) } -func (engine *Engine) loadTableInfo(table *schemas.Table) error { - colSeq, cols, err := engine.dialect.GetColumns(engine.db, engine.defaultContext, table.Name) +func (engine *Engine) loadTableInfo(ctx context.Context, table *schemas.Table) error { + colSeq, cols, err := engine.dialect.GetColumns(engine.db, ctx, table.Name) if err != nil { return err } for _, name := range colSeq { table.AddColumn(cols[name]) } - indexes, err := engine.dialect.GetIndexes(engine.db, engine.defaultContext, table.Name) + indexes, err := engine.dialect.GetIndexes(engine.db, ctx, table.Name) if err != nil { return err } @@ -404,7 +404,7 @@ func (engine *Engine) DBMetas() ([]*schemas.Table, error) { } for _, table := range tables { - if err = engine.loadTableInfo(table); err != nil { + if err = engine.loadTableInfo(engine.defaultContext, table); err != nil { return nil, err } } diff --git a/sync.go b/sync.go index 11e75404..635a8ba9 100644 --- a/sync.go +++ b/sync.go @@ -116,7 +116,7 @@ func (session *Session) SyncWithOptions(opts SyncOptions, beans ...interface{}) } // this will modify an old table - if err = engine.loadTableInfo(oriTable); err != nil { + if err = engine.loadTableInfo(session.ctx, oriTable); err != nil { return nil, err }