Skip to content

Commit 244062f

Browse files
authored
planner: allow semi_join_rewrite hint to work for in-subquery (#58830)
close #58829
1 parent 5301602 commit 244062f

File tree

5 files changed

+20
-6
lines changed

5 files changed

+20
-6
lines changed

pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,7 +3179,7 @@
31793179
"TableReader 10000.00 root data:TableFullScan",
31803180
"└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
31813181
],
3182-
"Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause."
3182+
"Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not IN/EXISTS clause."
31833183
},
31843184
{
31853185
"SQL": "select * from t where a > (select /*+ SEMI_JOIN_REWRITE() */ min(b) from t t1 where t1.c = t.c)",
@@ -3195,7 +3195,7 @@
31953195
" └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.c))",
31963196
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
31973197
],
3198-
"Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause."
3198+
"Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not IN/EXISTS clause."
31993199
},
32003200
{
32013201
"SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a=t.a)",

pkg/planner/core/expression_rewriter.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,8 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, planCtx *exp
12561256
}
12571257
planCtx.plan = join
12581258
} else {
1259-
planCtx.plan, er.err = planCtx.builder.buildSemiApply(planCtx.plan, np, expression.SplitCNFItems(checkCondition), asScalar, v.Not, false, noDecorrelate)
1259+
semiRewrite := hintFlags&hint.HintFlagSemiJoinRewrite > 0
1260+
planCtx.plan, er.err = planCtx.builder.buildSemiApply(planCtx.plan, np, expression.SplitCNFItems(checkCondition), asScalar, v.Not, semiRewrite, noDecorrelate)
12601261
if er.err != nil {
12611262
return v, true
12621263
}

pkg/planner/core/integration_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,3 +2321,15 @@ func TestNestedVirtualGeneratedColumnUpdate(t *testing.T) {
23212321
tk.MustExec("UPDATE test1 SET col7 = '{\"col10\":\"DDDDD\",\"col9\":[\"abcdefg\"]}';\n")
23222322
tk.MustExec("DELETE FROM test1 WHERE col1 < 0;\n")
23232323
}
2324+
2325+
func TestIssue58829(t *testing.T) {
2326+
store := testkit.CreateMockStore(t)
2327+
tk := testkit.NewTestKit(t, store)
2328+
tk.MustExec("use test")
2329+
2330+
tk.MustExec(`create table t1 (id varchar(64) not null, key(id))`)
2331+
tk.MustExec(`create table t2 (id bigint(20), k int)`)
2332+
2333+
// the semi_join_rewrite hint can convert the semi-join to inner-join and finally allow the optimizer to choose the IndexJoin
2334+
tk.MustHavePlan(`delete from t1 where t1.id in (select /*+ semi_join_rewrite() */ cast(id as char) from t2 where k=1)`, "IndexHashJoin")
2335+
}

pkg/planner/core/logical_plan_builder.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,7 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
36453645
warnHandler := b.ctx.GetSessionVars().StmtCtx
36463646
planHints, subQueryHintFlags, err := h.ParsePlanHints(hints, currentLevel, currentDB,
36473647
b.hintProcessor, b.ctx.GetSessionVars().StmtCtx.StraightJoinOrder,
3648+
b.subQueryCtx == handlingInSubquery,
36483649
b.subQueryCtx == handlingExistsSubquery, b.subQueryCtx == notHandlingSubquery, warnHandler)
36493650
if err != nil {
36503651
return

pkg/util/hint/hint.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ func (*PlanHints) MatchTableName(tables []*HintedTable, hintTables []HintedTable
728728
func ParsePlanHints(hints []*ast.TableOptimizerHint,
729729
currentLevel int, currentDB string,
730730
hintProcessor *QBHintHandler, straightJoinOrder bool,
731-
handlingExistsSubquery, notHandlingSubquery bool,
731+
handlingInSubquery, handlingExistsSubquery, notHandlingSubquery bool,
732732
warnHandler hintWarnHandler) (p *PlanHints, subQueryHintFlags uint64, err error) {
733733
var (
734734
sortMergeTables, inljTables, inlhjTables, inlmjTables, hashJoinTables, bcTables []HintedTable
@@ -872,8 +872,8 @@ func ParsePlanHints(hints []*ast.TableOptimizerHint,
872872
}
873873
leadingHintCnt++
874874
case HintSemiJoinRewrite:
875-
if !handlingExistsSubquery {
876-
warnHandler.SetHintWarning("The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause.")
875+
if !handlingExistsSubquery && !handlingInSubquery {
876+
warnHandler.SetHintWarning("The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not IN/EXISTS clause.")
877877
continue
878878
}
879879
subQueryHintFlags |= HintFlagSemiJoinRewrite

0 commit comments

Comments
 (0)