Skip to content

Commit 4beff8e

Browse files
Rustin170506ti-chi-bot
authored andcommitted
This is an automated cherry-pick of pingcap#47454
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
1 parent 7a83625 commit 4beff8e

File tree

3 files changed

+77
-6
lines changed

3 files changed

+77
-6
lines changed

parser/ast/expressions.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ type ParamMarkerExpr interface {
978978
SetOrder(int)
979979
}
980980

981-
// ParenthesesExpr is the parentheses expression.
981+
// ParenthesesExpr is the parentheses' expression.
982982
type ParenthesesExpr struct {
983983
exprNode
984984
// Expr is the expression in parentheses.

planner/core/plan_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -958,3 +958,29 @@ func TestIssue40535(t *testing.T) {
958958
tk.MustExec("(select /*+ agg_to_cop()*/ locate(t1.c3, t1.c3) as r0, t1.c3 as r1 from t1 where not( IsNull(t1.c1)) order by r0,r1) union all (select concat_ws(',', t2.c2, t2.c1) as r0, t2.c1 as r1 from t2 order by r0, r1) order by 1 limit 273;")
959959
require.Empty(t, tk.Session().LastMessage())
960960
}
961+
<<<<<<< HEAD:planner/core/plan_test.go
962+
=======
963+
964+
func TestIssue47445(t *testing.T) {
965+
store, _ := testkit.CreateMockStoreAndDomain(t)
966+
tk := testkit.NewTestKit(t, store)
967+
tk.MustExec("use test;")
968+
tk.MustExec("CREATE TABLE golang1 ( `fcbpdt` CHAR (8) COLLATE utf8_general_ci NOT NULL, `fcbpsq` VARCHAR (20) COLLATE utf8_general_ci NOT NULL, `procst` char (4) COLLATE utf8_general_ci DEFAULT NULL,`cipstx` VARCHAR (105) COLLATE utf8_general_ci DEFAULT NULL, `cipsst` CHAR (4) COLLATE utf8_general_ci DEFAULT NULL, `dyngtg` VARCHAR(4) COLLATE utf8_general_ci DEFAULT NULL, `blncdt` VARCHAR (8) COLLATE utf8_general_ci DEFAULT NULL, PRIMARY KEY ( fcbpdt, fcbpsq ))")
969+
tk.MustExec("insert into golang1 values('20230925','12023092502158016','abc','','','','')")
970+
tk.MustExec("create table golang2 (`sysgrp` varchar(20) NOT NULL,`procst` varchar(8) NOT NULL,`levlid` int(11) NOT NULL,PRIMARY key (procst));")
971+
tk.MustExec("insert into golang2 VALUES('COMMON','ACSC',90)")
972+
tk.MustExec("insert into golang2 VALUES('COMMON','abc',8)")
973+
tk.MustExec("insert into golang2 VALUES('COMMON','CH02',6)")
974+
tk.MustExec("UPDATE golang1 a SET procst =(CASE WHEN ( SELECT levlid FROM golang2 b WHERE b.sysgrp = 'COMMON' AND b.procst = 'ACSC' ) > ( SELECT levlid FROM golang2 c WHERE c.sysgrp = 'COMMON' AND c.procst = a.procst ) THEN 'ACSC' ELSE a.procst END ), cipstx = 'CI010000', cipsst = 'ACSC', dyngtg = 'EAYT', blncdt= '20230925' WHERE fcbpdt = '20230925' AND fcbpsq = '12023092502158016'")
975+
tk.MustQuery("select * from golang1").Check(testkit.Rows("20230925 12023092502158016 ACSC CI010000 ACSC EAYT 20230925"))
976+
tk.MustExec("UPDATE golang1 a SET procst= (SELECT 1 FROM golang2 c WHERE c.procst = a.procst) WHERE fcbpdt = '20230925' AND fcbpsq = '12023092502158016'")
977+
tk.MustQuery("select * from golang1").Check(testkit.Rows("20230925 12023092502158016 1 CI010000 ACSC EAYT 20230925"))
978+
}
979+
980+
func TestExplainValuesStatement(t *testing.T) {
981+
store, _ := testkit.CreateMockStoreAndDomain(t)
982+
tk := testkit.NewTestKit(t, store)
983+
984+
tk.MustMatchErrMsg("EXPLAIN FORMAT = TRADITIONAL ((VALUES ROW ()) ORDER BY 1)", ".*Unknown table ''.*")
985+
}
986+
>>>>>>> 1c185556710 (planner: do not convert update to point get if the expr has sub-query (#47454)):pkg/planner/core/plan_test.go

planner/core/point_get_plan.go

+50-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"sort"
2020
"strconv"
2121
"strings"
22+
"sync"
2223
"unsafe"
2324

2425
"github.com/pingcap/errors"
@@ -1551,13 +1552,57 @@ func findInPairs(colName string, pairs []nameValuePair) int {
15511552
return -1
15521553
}
15531554

1554-
func tryUpdatePointPlan(ctx sessionctx.Context, updateStmt *ast.UpdateStmt) Plan {
1555-
// avoid using the point_get when assignment_list contains the subquery in the UPDATE.
1556-
for _, list := range updateStmt.List {
1557-
if _, ok := list.Expr.(*ast.SubqueryExpr); ok {
1558-
return nil
1555+
// Use cache to avoid allocating memory every time.
1556+
var subQueryCheckerPool = &sync.Pool{New: func() any { return &subQueryChecker{} }}
1557+
1558+
type subQueryChecker struct {
1559+
hasSubQuery bool
1560+
}
1561+
1562+
func (s *subQueryChecker) Enter(in ast.Node) (node ast.Node, skipChildren bool) {
1563+
if s.hasSubQuery {
1564+
return in, true
1565+
}
1566+
1567+
if _, ok := in.(*ast.SubqueryExpr); ok {
1568+
s.hasSubQuery = true
1569+
return in, true
1570+
}
1571+
1572+
return in, false
1573+
}
1574+
1575+
func (s *subQueryChecker) Leave(in ast.Node) (ast.Node, bool) {
1576+
// Before we enter the sub-query, we should keep visiting its children.
1577+
return in, !s.hasSubQuery
1578+
}
1579+
1580+
func isExprHasSubQuery(expr ast.Node) bool {
1581+
checker := subQueryCheckerPool.Get().(*subQueryChecker)
1582+
defer func() {
1583+
// Do not forget to reset the flag.
1584+
checker.hasSubQuery = false
1585+
subQueryCheckerPool.Put(checker)
1586+
}()
1587+
expr.Accept(checker)
1588+
return checker.hasSubQuery
1589+
}
1590+
1591+
func checkIfAssignmentListHasSubQuery(list []*ast.Assignment) bool {
1592+
for _, a := range list {
1593+
if isExprHasSubQuery(a) {
1594+
return true
15591595
}
15601596
}
1597+
return false
1598+
}
1599+
1600+
func tryUpdatePointPlan(ctx sessionctx.Context, updateStmt *ast.UpdateStmt) Plan {
1601+
// Avoid using the point_get when assignment_list contains the sub-query in the UPDATE.
1602+
if checkIfAssignmentListHasSubQuery(updateStmt.List) {
1603+
return nil
1604+
}
1605+
15611606
selStmt := &ast.SelectStmt{
15621607
Fields: &ast.FieldList{},
15631608
From: updateStmt.TableRefs,

0 commit comments

Comments
 (0)