Skip to content

Commit

Permalink
planner: fix panic error when subquery + always true predicate in whe…
Browse files Browse the repository at this point in the history
…re clause (#53525) (#57102)

close #46962
  • Loading branch information
ti-chi-bot authored Nov 8, 2024
1 parent eca41cb commit 0a8ae19
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
27 changes: 27 additions & 0 deletions planner/core/casetest/physical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2570,10 +2570,12 @@ func TestConstantPropagateWithCollation(t *testing.T) {
Plan []string
Warning []string
}

planSuiteData := GetPlanSuiteData()
planSuiteData.LoadTestCases(t, &input, &output)
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)

// create table
tk.MustExec("use test")
tk.MustExec("create table t (id int primary key, name varchar(20));")
Expand All @@ -2593,3 +2595,28 @@ func TestConstantPropagateWithCollation(t *testing.T) {
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warning...))
}
}

// Test issue #46962 plan
func TestAlwaysTruePredicateWithSubquery(t *testing.T) {
var (
input []string
output []struct {
SQL string
Plan []string
Warning []string
}
)
planSuiteData := GetPlanSuiteData()
planSuiteData.LoadTestCases(t, &input, &output)
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`CREATE TABLE t ( a int NOT NULL , b int NOT NULL ) `)
for i, ts := range input {
testdata.OnRecord(func() {
output[i].SQL = ts
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Rows())
})
tk.MustQuery(ts).Check(testkit.Rows(output[i].Plan...))
}
}
8 changes: 8 additions & 0 deletions planner/core/casetest/testdata/plan_suite_in.json
Original file line number Diff line number Diff line change
Expand Up @@ -1361,5 +1361,13 @@
"select * from t where name='a' and length(name)=1; -- without constant propagated",
"select * from (select 'test' as b from t) n where length(b) > 2; -- can be substituted"
]
},
{
"name": "TestAlwaysTruePredicateWithSubquery",
"cases" : [
"SHOW ERRORS WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
"explain select * from t WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
"explain select * from t WHERE TRUE = ALL ( SELECT TRUE from t GROUP BY 1 LIMIT 1 ) is null is not null;"
]
}
]
38 changes: 38 additions & 0 deletions planner/core/casetest/testdata/plan_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -8993,5 +8993,43 @@
"Warning": null
}
]
},
{
"Name": "TestAlwaysTruePredicateWithSubquery",
"Cases": [
{
"SQL": "SHOW ERRORS WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
"Plan": null,
"Warning": null
},
{
"SQL": "explain select * from t WHERE TRUE = ALL ( SELECT TRUE GROUP BY 1 LIMIT 1 ) IS NULL IS NOT NULL;",
"Plan": [
"HashJoin_14 10000.00 root CARTESIAN inner join",
"├─StreamAgg_19(Build) 1.00 root funcs:count(1)->Column#13",
"│ └─Limit_22 1.00 root offset:0, count:1",
"│ └─HashAgg_23 1.00 root group by:1, ",
"│ └─TableDual_24 1.00 root rows:1",
"└─TableReader_17(Probe) 10000.00 root data:TableFullScan_16",
" └─TableFullScan_16 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warning": null
},
{
"SQL": "explain select * from t WHERE TRUE = ALL ( SELECT TRUE from t GROUP BY 1 LIMIT 1 ) is null is not null;",
"Plan": [
"HashJoin_14 10000.00 root CARTESIAN inner join",
"├─StreamAgg_19(Build) 1.00 root funcs:count(1)->Column#16",
"│ └─Limit_22 1.00 root offset:0, count:1",
"│ └─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",
"│ └─TableReader_28 1.00 root data:HashAgg_23",
"│ └─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",
"│ └─TableFullScan_26 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"└─TableReader_17(Probe) 10000.00 root data:TableFullScan_16",
" └─TableFullScan_16 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warning": null
}
]
}
]
6 changes: 5 additions & 1 deletion planner/core/rule_build_key_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ func buildKeyInfo(lp LogicalPlan) {

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

0 comments on commit 0a8ae19

Please sign in to comment.