From 5520c6a5fb7d940e69549040be3ba104a3d05120 Mon Sep 17 00:00:00 2001 From: Jian Zhang Date: Wed, 15 Aug 2018 22:00:00 +0800 Subject: [PATCH 1/3] plan: fix insert onduplicate key update --- executor/insert_test.go | 7 +++++++ plan/planbuilder.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/executor/insert_test.go b/executor/insert_test.go index 6b82a4064d7c4..9d18a7c11c280 100644 --- a/executor/insert_test.go +++ b/executor/insert_test.go @@ -79,4 +79,11 @@ func (s *testSuite) TestInsertOnDuplicateKey(c *C) { tk.MustQuery(`select * from t1`).Check(testkit.Rows("1 400")) tk.MustExec(`insert into t1 select * from t2 on duplicate key update b1 = values(b1) + b2;`) tk.MustQuery(`select * from t1`).Check(testkit.Rows("1 400")) + + tk.MustExec(`drop table if exists t;`) + tk.MustExec(`create table t(k1 bigint, k2 bigint, val bigint, primary key(k1, k2));`) + tk.MustExec(`insert into t (val, k1, k2) values (3, 1, 2);`) + tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) + tk.MustExec(`insert into t (val, k1, k2) select c, a, b from (select 1 as a, 2 as b, 4 as c) tmp on duplicate key update val = tmp.c;`) + tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 4`)) } diff --git a/plan/planbuilder.go b/plan/planbuilder.go index a24fcfe6bedb4..01c02e2135ac1 100644 --- a/plan/planbuilder.go +++ b/plan/planbuilder.go @@ -1187,7 +1187,36 @@ func (b *planBuilder) buildSelectPlanOfInsert(insert *ast.InsertStmt, insertPlan return errors.Trace(err) } - insertPlan.Schema4OnDuplicate = expression.MergeSchema(insertPlan.tableSchema, insertPlan.SelectPlan.Schema()) + tableCols := insertPlan.Table.Cols() + var insertCols []*table.Column + + if len(insertPlan.Columns) > 0 { + colNames := make([]string, 0, len(tableCols)) + for _, col := range insertPlan.Columns { + colNames = append(colNames, col.Name.O) + } + for _, col := range insertPlan.GenCols.Columns { + colNames = append(colNames, col.Name.O) + } + insertCols, err = table.FindCols(tableCols, colNames, insertPlan.Table.Meta().PKIsHandle) + if err != nil { + return errors.Trace(err) + } + } else { + insertCols = tableCols + } + + schema4NewRow := expression.NewSchema(make([]*expression.Column, len(tableCols))...) + for i, selCol := range insertPlan.SelectPlan.Schema().Columns { + ordinal := insertCols[i].Offset + schema4NewRow.Columns[ordinal] = selCol + } + for i := range schema4NewRow.Columns { + if schema4NewRow.Columns[i] == nil { + schema4NewRow.Columns[i] = &expression.Column{UniqueID: insertPlan.ctx.GetSessionVars().AllocPlanColumnID()} + } + } + insertPlan.Schema4OnDuplicate = expression.MergeSchema(insertPlan.tableSchema, schema4NewRow) return nil } From 4f392d52e9f6b71d8bba9281e2276da2d02b7f33 Mon Sep 17 00:00:00 2001 From: Jian Zhang Date: Thu, 16 Aug 2018 16:04:04 +0800 Subject: [PATCH 2/3] fix panic --- executor/insert_test.go | 7 +++++++ plan/planbuilder.go | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/executor/insert_test.go b/executor/insert_test.go index 9d18a7c11c280..b629dc65ebce3 100644 --- a/executor/insert_test.go +++ b/executor/insert_test.go @@ -86,4 +86,11 @@ func (s *testSuite) TestInsertOnDuplicateKey(c *C) { tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) tk.MustExec(`insert into t (val, k1, k2) select c, a, b from (select 1 as a, 2 as b, 4 as c) tmp on duplicate key update val = tmp.c;`) tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 4`)) + + tk.MustExec(`drop table if exists t;`) + tk.MustExec(`create table t(k1 double, k2 double, v double, primary key(k1, k2));`) + tk.MustExec(`insert into t (v, k1, k2) select c, a, b from (select "3" c, "1" a, "2" b) tmp on duplicate key update v=c;`) + tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) + tk.MustExec(`insert into t (v, k1, k2) select c, a, b from (select "3" c, "1" a, "2" b) tmp on duplicate key update v=c;`) + tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) } diff --git a/plan/planbuilder.go b/plan/planbuilder.go index 01c02e2135ac1..75f6db80da2f7 100644 --- a/plan/planbuilder.go +++ b/plan/planbuilder.go @@ -1209,7 +1209,11 @@ func (b *planBuilder) buildSelectPlanOfInsert(insert *ast.InsertStmt, insertPlan schema4NewRow := expression.NewSchema(make([]*expression.Column, len(tableCols))...) for i, selCol := range insertPlan.SelectPlan.Schema().Columns { ordinal := insertCols[i].Offset - schema4NewRow.Columns[ordinal] = selCol + schema4NewRow.Columns[ordinal] = &expression.Column{} + *schema4NewRow.Columns[ordinal] = *selCol + + schema4NewRow.Columns[ordinal].RetType = &types.FieldType{} + *schema4NewRow.Columns[ordinal].RetType = insertCols[i].FieldType } for i := range schema4NewRow.Columns { if schema4NewRow.Columns[i] == nil { From 8d555d1c7967c3f15ec65a85496a91aada38856e Mon Sep 17 00:00:00 2001 From: Jian Zhang Date: Mon, 27 Aug 2018 16:34:31 +0800 Subject: [PATCH 3/3] address comment --- plan/planbuilder.go | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/plan/planbuilder.go b/plan/planbuilder.go index 2597b92be3528..53b6897e064fa 100644 --- a/plan/planbuilder.go +++ b/plan/planbuilder.go @@ -1190,33 +1190,16 @@ func (b *planBuilder) buildSelectPlanOfInsert(insert *ast.InsertStmt, insertPlan return errors.Trace(err) } - tableCols := insertPlan.Table.Cols() - var insertCols []*table.Column - - if len(insertPlan.Columns) > 0 { - colNames := make([]string, 0, len(tableCols)) - for _, col := range insertPlan.Columns { - colNames = append(colNames, col.Name.O) - } - for _, col := range insertPlan.GenCols.Columns { - colNames = append(colNames, col.Name.O) - } - insertCols, err = table.FindCols(tableCols, colNames, insertPlan.Table.Meta().PKIsHandle) - if err != nil { - return errors.Trace(err) - } - } else { - insertCols = tableCols - } - - schema4NewRow := expression.NewSchema(make([]*expression.Column, len(tableCols))...) + // schema4NewRow is the schema for the newly created data record based on + // the result of the select statement. + schema4NewRow := expression.NewSchema(make([]*expression.Column, len(insertPlan.Table.Cols()))...) for i, selCol := range insertPlan.SelectPlan.Schema().Columns { - ordinal := insertCols[i].Offset + ordinal := affectedValuesCols[i].Offset schema4NewRow.Columns[ordinal] = &expression.Column{} *schema4NewRow.Columns[ordinal] = *selCol schema4NewRow.Columns[ordinal].RetType = &types.FieldType{} - *schema4NewRow.Columns[ordinal].RetType = insertCols[i].FieldType + *schema4NewRow.Columns[ordinal].RetType = affectedValuesCols[i].FieldType } for i := range schema4NewRow.Columns { if schema4NewRow.Columns[i] == nil {