Skip to content

Commit 0a8ae19

Browse files
authored
planner: fix panic error when subquery + always true predicate in where clause (#53525) (#57102)
close #46962
1 parent eca41cb commit 0a8ae19

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

planner/core/casetest/physical_plan_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2570,10 +2570,12 @@ func TestConstantPropagateWithCollation(t *testing.T) {
25702570
Plan []string
25712571
Warning []string
25722572
}
2573+
25732574
planSuiteData := GetPlanSuiteData()
25742575
planSuiteData.LoadTestCases(t, &input, &output)
25752576
store := testkit.CreateMockStore(t)
25762577
tk := testkit.NewTestKit(t, store)
2578+
25772579
// create table
25782580
tk.MustExec("use test")
25792581
tk.MustExec("create table t (id int primary key, name varchar(20));")
@@ -2593,3 +2595,28 @@ func TestConstantPropagateWithCollation(t *testing.T) {
25932595
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warning...))
25942596
}
25952597
}
2598+
2599+
// Test issue #46962 plan
2600+
func TestAlwaysTruePredicateWithSubquery(t *testing.T) {
2601+
var (
2602+
input []string
2603+
output []struct {
2604+
SQL string
2605+
Plan []string
2606+
Warning []string
2607+
}
2608+
)
2609+
planSuiteData := GetPlanSuiteData()
2610+
planSuiteData.LoadTestCases(t, &input, &output)
2611+
store := testkit.CreateMockStore(t)
2612+
tk := testkit.NewTestKit(t, store)
2613+
tk.MustExec("use test")
2614+
tk.MustExec(`CREATE TABLE t ( a int NOT NULL , b int NOT NULL ) `)
2615+
for i, ts := range input {
2616+
testdata.OnRecord(func() {
2617+
output[i].SQL = ts
2618+
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Rows())
2619+
})
2620+
tk.MustQuery(ts).Check(testkit.Rows(output[i].Plan...))
2621+
}
2622+
}

planner/core/casetest/testdata/plan_suite_in.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,5 +1361,13 @@
13611361
"select * from t where name='a' and length(name)=1; -- without constant propagated",
13621362
"select * from (select 'test' as b from t) n where length(b) > 2; -- can be substituted"
13631363
]
1364+
},
1365+
{
1366+
"name": "TestAlwaysTruePredicateWithSubquery",
1367+
"cases" : [
1368+
"SHOW ERRORS WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
1369+
"explain select * from t WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
1370+
"explain select * from t WHERE TRUE = ALL ( SELECT TRUE from t GROUP BY 1 LIMIT 1 ) is null is not null;"
1371+
]
13641372
}
13651373
]

planner/core/casetest/testdata/plan_suite_out.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8993,5 +8993,43 @@
89938993
"Warning": null
89948994
}
89958995
]
8996+
},
8997+
{
8998+
"Name": "TestAlwaysTruePredicateWithSubquery",
8999+
"Cases": [
9000+
{
9001+
"SQL": "SHOW ERRORS WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
9002+
"Plan": null,
9003+
"Warning": null
9004+
},
9005+
{
9006+
"SQL": "explain select * from t WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
9007+
"Plan": [
9008+
"HashJoin_14 10000.00 root CARTESIAN inner join",
9009+
"├─StreamAgg_19(Build) 1.00 root funcs:count(1)->Column#13",
9010+
"│ └─Limit_22 1.00 root offset:0, count:1",
9011+
"│ └─HashAgg_23 1.00 root group by:1, ",
9012+
"│ └─TableDual_24 1.00 root rows:1",
9013+
"└─TableReader_17(Probe) 10000.00 root data:TableFullScan_16",
9014+
" └─TableFullScan_16 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
9015+
],
9016+
"Warning": null
9017+
},
9018+
{
9019+
"SQL": "explain select * from t WHERE TRUE = ALL ( SELECT TRUE from t GROUP BY 1 LIMIT 1 ) is null is not null;",
9020+
"Plan": [
9021+
"HashJoin_14 10000.00 root CARTESIAN inner join",
9022+
"├─StreamAgg_19(Build) 1.00 root funcs:count(1)->Column#16",
9023+
"│ └─Limit_22 1.00 root offset:0, count:1",
9024+
"│ └─HashAgg_27 1.00 root group by:Column#17, funcs:firstrow(Column#18)->test.t.a, funcs:firstrow(Column#19)->test.t.b, funcs:firstrow(Column#20)->test.t._tidb_rowid",
9025+
"│ └─TableReader_28 1.00 root data:HashAgg_23",
9026+
"│ └─HashAgg_23 1.00 cop[tikv] group by:1, funcs:firstrow(test.t.a)->Column#18, funcs:firstrow(test.t.b)->Column#19, funcs:firstrow(test.t._tidb_rowid)->Column#20",
9027+
"│ └─TableFullScan_26 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
9028+
"└─TableReader_17(Probe) 10000.00 root data:TableFullScan_16",
9029+
" └─TableFullScan_16 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
9030+
],
9031+
"Warning": null
9032+
}
9033+
]
89969034
}
89979035
]

planner/core/rule_build_key_info.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ func buildKeyInfo(lp LogicalPlan) {
4444

4545
// BuildKeyInfo implements LogicalPlan BuildKeyInfo interface.
4646
func (la *LogicalAggregation) BuildKeyInfo(selfSchema *expression.Schema, childSchema []*expression.Schema) {
47-
if la.IsPartialModeAgg() {
47+
// According to the issue#46962, we can ignore the judgment of partial agg
48+
// Sometimes, the agg inside of subquery and there is a true condition in where clause, the agg function is empty.
49+
// For example, ``` select xxxx from xxx WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;
50+
// In this case, the agg is complete mode and we can ignore this check.
51+
if len(la.AggFuncs) != 0 && la.IsPartialModeAgg() {
4852
return
4953
}
5054
la.logicalSchemaProducer.BuildKeyInfo(selfSchema, childSchema)

0 commit comments

Comments
 (0)