diff --git a/pkg/planner/core/plan_test.go b/pkg/planner/core/plan_test.go index 4baa378a67..cbd923c474 100644 --- a/pkg/planner/core/plan_test.go +++ b/pkg/planner/core/plan_test.go @@ -713,8 +713,8 @@ func TestImportIntoBuildPlan(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("create table t1 (a int, b int);") - tk.MustExec("create table t2 (a int, b int);") + tk.MustExec("create table t1 (a int, b int, c datetime on update CURRENT_TIMESTAMP);") + tk.MustExec("create table t2 (a int, b int, c datetime on update CURRENT_TIMESTAMP);") require.ErrorIs(t, tk.ExecToErr("IMPORT INTO t1 FROM select a from t2;"), plannererrors.ErrWrongValueCountOnRow) require.ErrorIs(t, tk.ExecToErr("IMPORT INTO t1(a) FROM select * from t2;"), diff --git a/pkg/planner/core/planbuilder.go b/pkg/planner/core/planbuilder.go index ad7e07e7e7..0d9d7abb13 100644 --- a/pkg/planner/core/planbuilder.go +++ b/pkg/planner/core/planbuilder.go @@ -3994,13 +3994,12 @@ func (b *PlanBuilder) getDefaultValueForInsert(col *table.Column) (*expression.C } // resolveGeneratedColumns resolves generated columns with their generation expressions respectively. -// onDups indicates which columns are in on-duplicate list -// and it will be **modified** inside this function. +// If not-nil onDups is passed in, it will be **modified in place** and record columns in on-duplicate list func (b *PlanBuilder) resolveGeneratedColumns(ctx context.Context, columns []*table.Column, onDups map[string]struct{}, mockPlan base.LogicalPlan) (igc InsertGeneratedColumns, err error) { for _, column := range columns { if !column.IsGenerated() { // columns having on-update-now flag should also be considered. - if mysql.HasOnUpdateNowFlag(column.GetFlag()) { + if onDups != nil && mysql.HasOnUpdateNowFlag(column.GetFlag()) { onDups[column.Name.L] = struct{}{} } continue diff --git a/tests/realtikvtest/importintotest/import_into_test.go b/tests/realtikvtest/importintotest/import_into_test.go index a9f2bd520a..43220f248d 100644 --- a/tests/realtikvtest/importintotest/import_into_test.go +++ b/tests/realtikvtest/importintotest/import_into_test.go @@ -331,6 +331,22 @@ func (s *mockGCSSuite) TestInputNull() { s.tk.MustQuery("SELECT * FROM t;").Check(testkit.Rows([]string{"1 def 11", "2 test2 22"}...)) } +func (s *mockGCSSuite) TestOnUpdateColumn() { + s.server.CreateObject(fakestorage.Object{ + ObjectAttrs: fakestorage.ObjectAttrs{ + BucketName: "test-on-update", + Name: "on-update.tsv", + }, + Content: []byte("1,2025-08-22 02:35:00"), + }) + s.prepareAndUseDB("load_data") + s.tk.MustExec("drop table if exists t;") + s.tk.MustExec("create table t(id int, c1 datetime on update CURRENT_TIMESTAMP)") + loadDataSQL := fmt.Sprintf(`IMPORT INTO t FROM 'gs://test-on-update/on-update.tsv?endpoint=%s'`, gcsEndpoint) + s.tk.MustQuery(loadDataSQL) + s.tk.MustQuery("SELECT * FROM t;").Check(testkit.Rows([]string{"1 2025-08-22 02:35:00"}...)) +} + func (s *mockGCSSuite) TestIgnoreNLines() { s.server.CreateObject(fakestorage.Object{ ObjectAttrs: fakestorage.ObjectAttrs{BucketName: "test-multi-load", Name: "skip-rows-1.csv"},