Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: fix insert with select the same table result no error #issue 31363 #33565

Open
wants to merge 58 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
3a5ef3e
fix insert with select the same table no error #issue 31363
fanrenhoo Apr 3, 2022
cc003cf
fix insert with subquery select the same table result no error #issue…
fanrenhoo Apr 16, 2022
f35041a
fix insert with select the same table no error #issue 31363
fanrenhoo Apr 3, 2022
f70fa17
fix the insert with select the same table result no error #issue 31363
fanrenhoo Nov 13, 2022
cf129f8
*: fix merge
xhebox Dec 5, 2022
47d6b5a
*: fix CI
xhebox Dec 27, 2022
e3d9bf5
fix insert with select the same table result no error #issue 31363
fanrenhoo Jan 13, 2023
a45457c
Merge branch 'master' into insertselectsametable
fanrenhoo Jan 13, 2023
06cd6da
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
7490155
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
65b0e64
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
b20423a
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
2abad2b
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
6208e1a
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
320c4f4
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 16, 2023
4e1813d
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 17, 2023
8a0ce45
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 17, 2023
5da545c
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 17, 2023
31f631e
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 17, 2023
c78ce28
Merge branch 'master' into insertselectsametable
ti-chi-bot Jan 17, 2023
ae35ca0
Merge branch 'master' into insertselectsametable
xhebox Feb 1, 2023
ee42902
*: fix build
xhebox Feb 1, 2023
0069d7f
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
89260c4
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
600ee68
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
21f1862
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
cdbf47a
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
103cdfe
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
d2cdd54
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
f74da07
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
019b294
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
88180ed
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 1, 2023
27f5751
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
fb0bc56
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
fb0909b
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
2614a32
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
f2fe0af
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
2b2a909
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
7f747d9
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
8278c4b
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
58fab0a
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
f87e2b8
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
e616b92
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
65122a6
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
ec733ec
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
56526a5
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
aeb131f
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
2982d08
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 2, 2023
c6144f7
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
490b008
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
dbb5bf4
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
c75bcd0
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
012a87c
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
2bae135
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
b945bd0
Merge branch 'master' into insertselectsametable
ti-chi-bot Feb 3, 2023
33ca045
Merge branch 'master' of github.com:pingcap/tidb into insertselectsam…
xhebox Jul 10, 2023
7f2bc97
fix
xhebox Jul 10, 2023
4c69d36
fix
xhebox Jul 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2146,6 +2146,11 @@ error = '''
Not unique table/alias: '%-.192s'
'''

["planner:1093"]
error = '''
You can't specify target table '%-.192s' for update in FROM clause
'''

["planner:1094"]
error = '''
Unknown thread id: %d
Expand Down
3 changes: 3 additions & 0 deletions executor/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,9 @@ func TestInsertIntoSelectError(t *testing.T) {
tk.MustQuery("SHOW WARNINGS;").Check(testkit.Rows("Warning 1210 Incorrect arguments to sleep"))
tk.MustExec("INSERT IGNORE into t1(SELECT SLEEP(1));")
tk.MustQuery("SELECT * FROM t1;").Check(testkit.Rows("0", "0", "0"))
tk.MustExec("TRUNCATE t1;")
tk.MustGetErrCode("INSERT INTO t1 (a) VALUES ((SELECT a FROM t1));", errno.ErrUpdateTableUsed)
tk.MustExec("INSERT INTO t1 (a) VALUES ((SELECT a FROM t1 as t));")
tk.MustExec("DROP TABLE t1;")
}

Expand Down
1 change: 1 addition & 0 deletions planner/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,5 @@ var (
ErrPrepareDDL = dbterror.ClassExecutor.NewStd(mysql.ErrPrepareDDL)
ErrRowIsReferenced2 = dbterror.ClassOptimizer.NewStd(mysql.ErrRowIsReferenced2)
ErrNoReferencedRow2 = dbterror.ClassOptimizer.NewStd(mysql.ErrNoReferencedRow2)
ErrUpdateTableUsed = dbterror.ClassOptimizer.NewStd(mysql.ErrUpdateTableUsed)
)
1 change: 1 addition & 0 deletions planner/core/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func TestError(t *testing.T) {
ErrStmtNotFound,
ErrAmbiguous,
ErrKeyPart0,
ErrUpdateTableUsed,
}
for _, err := range kvErrs {
code := terror.ToSQLError(err).Code
Expand Down
11 changes: 8 additions & 3 deletions planner/core/expression_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (b *PlanBuilder) rewriteWithPreprocess(
p LogicalPlan, aggMapper map[*ast.AggregateFuncExpr]int,
windowMapper map[*ast.WindowFuncExpr]int,
asScalar bool,
preprocess func(ast.Node) ast.Node,
preprocess func(ast.Node) (ast.Node, error),
) (expression.Expression, LogicalPlan, error) {
b.rewriterCounter++
defer func() { b.rewriterCounter-- }()
Expand Down Expand Up @@ -233,7 +233,7 @@ type expressionRewriter struct {
asScalar bool

// preprocess is called for every ast.Node in Leave.
preprocess func(ast.Node) ast.Node
preprocess func(ast.Node) (ast.Node, error)

// insertPlan is only used to rewrite the expressions inside the assignment
// of the "INSERT" statement.
Expand Down Expand Up @@ -1149,7 +1149,12 @@ func (er *expressionRewriter) Leave(originInNode ast.Node) (retNode ast.Node, ok
}
var inNode = originInNode
if er.preprocess != nil {
inNode = er.preprocess(inNode)
nd, err := er.preprocess(inNode)
inNode = nd
if err != nil {
er.err = err
return retNode, false
}
}
switch v := inNode.(type) {
case *ast.AggregateFuncExpr, *ast.ColumnNameExpr, *ast.ParenthesesExpr, *ast.WhenClause,
Expand Down
8 changes: 4 additions & 4 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6066,17 +6066,17 @@ func (b *PlanBuilder) buildUpdateLists(ctx context.Context, tableList []*ast.Tab
dependentColumnsModified[col.UniqueID] = true
} else {
// rewrite with generation expression
rewritePreprocess := func(assign *ast.Assignment) func(expr ast.Node) ast.Node {
return func(expr ast.Node) ast.Node {
rewritePreprocess := func(assign *ast.Assignment) func(expr ast.Node) (ast.Node, error) {
return func(expr ast.Node) (ast.Node, error) {
switch x := expr.(type) {
case *ast.ColumnName:
return &ast.ColumnName{
Schema: assign.Column.Schema,
Table: assign.Column.Table,
Name: x.Name,
}
}, nil
default:
return expr
return expr, nil
}
}
}
Expand Down
49 changes: 44 additions & 5 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3907,15 +3907,54 @@ func (b *PlanBuilder) buildInsert(ctx context.Context, insert *ast.InsertStmt) (
mockTablePlan.SetSchema(insertPlan.tableSchema)
mockTablePlan.names = insertPlan.tableColNames

checkRefColumn := func(n ast.Node) ast.Node {
checkTblName := func(n ast.Node) error {
source := n.(*ast.TableSource).Source
if src, ok := source.(*ast.TableName); ok {
subTblname := src.Name
srcTblname := tn.Name
subAsName := n.(*ast.TableSource).AsName

if srcTblname == subTblname && subAsName.O == "" {
err := ErrUpdateTableUsed.GenWithStackByArgs(srcTblname.O)
return err
}
}
return nil
}

checkRefColumn := func(n ast.Node) (ast.Node, error) {
if insertPlan.NeedFillDefaultValue {
return n
return n, nil
}
switch n.(type) {
case *ast.ColumnName, *ast.ColumnNameExpr:
insertPlan.NeedFillDefaultValue = true
case *ast.SubqueryExpr:
sel := n.(*ast.SubqueryExpr).Query
switch sel.(type) {
case *ast.SelectStmt:
if sel.(*ast.SelectStmt).From != nil {
left := sel.(*ast.SelectStmt).From.TableRefs.Left
switch lnode := left.(type) {
case *ast.Join:
err := checkTblName(lnode.Left)
if err != nil {
return n, err
}
err = checkTblName(lnode.Right)
if err != nil {
return n, err
}
case *ast.TableSource:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late reply. It seems that we need to also handle the following case:

mysql> INSERT INTO t1 (x) VALUES ((SELECT t2.x FROM t2 join t1 on t1.x = t2.x));
ERROR 1093 (HY000): You can't specify target table 't1' for update in FROM clause

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can recursively extract all the tables in TableRefs:

  1. If it is a Join node, then recursively look at the left node and the right node.
  2. Otherwise, if it is a TableSource node, check its table name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thks. Done as guided, please check. BR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

err = checkTblName(lnode)
if err != nil {
return n, err
}
}
}
}
}
return n
return n, nil
}

if len(insert.Lists) > 0 {
Expand Down Expand Up @@ -4038,7 +4077,7 @@ func (*PlanBuilder) getAffectCols(insertStmt *ast.InsertStmt, insertPlan *Insert
return affectedValuesCols, nil
}

func (b PlanBuilder) getInsertColExpr(ctx context.Context, insertPlan *Insert, mockTablePlan *LogicalTableDual, col *table.Column, expr ast.ExprNode, checkRefColumn func(n ast.Node) ast.Node) (outExpr expression.Expression, err error) {
func (b PlanBuilder) getInsertColExpr(ctx context.Context, insertPlan *Insert, mockTablePlan *LogicalTableDual, col *table.Column, expr ast.ExprNode, checkRefColumn func(n ast.Node) (ast.Node, error)) (outExpr expression.Expression, err error) {
if col.Hidden {
return nil, ErrUnknownColumn.GenWithStackByArgs(col.Name, clauseMsg[fieldList])
}
Expand Down Expand Up @@ -4100,7 +4139,7 @@ func (b PlanBuilder) getInsertColExpr(ctx context.Context, insertPlan *Insert, m
return outExpr, nil
}

func (b *PlanBuilder) buildValuesListOfInsert(ctx context.Context, insert *ast.InsertStmt, insertPlan *Insert, mockTablePlan *LogicalTableDual, checkRefColumn func(n ast.Node) ast.Node) error {
func (b *PlanBuilder) buildValuesListOfInsert(ctx context.Context, insert *ast.InsertStmt, insertPlan *Insert, mockTablePlan *LogicalTableDual, checkRefColumn func(n ast.Node) (ast.Node, error)) error {
affectedValuesCols, err := b.getAffectCols(insert, insertPlan)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion planner/core/planbuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func TestRewriterPool(t *testing.T) {
dirtyRewriter := builder.getExpressionRewriter(context.TODO(), nil)
dirtyRewriter.asScalar = true
dirtyRewriter.aggrMap = make(map[*ast.AggregateFuncExpr]int)
dirtyRewriter.preprocess = func(ast.Node) ast.Node { return nil }
dirtyRewriter.preprocess = func(ast.Node) (ast.Node, error) { return nil, nil }
dirtyRewriter.insertPlan = &Insert{}
dirtyRewriter.disableFoldCounter = 1
dirtyRewriter.ctxStack = make([]expression.Expression, 2)
Expand Down