Skip to content

Commit

Permalink
planner: fix column pruning bug for Apply and Join (#24369)
Browse files Browse the repository at this point in the history
  • Loading branch information
guo-shaoge authored May 6, 2021
1 parent 5bd601b commit a6ec081
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 13 deletions.
29 changes: 29 additions & 0 deletions planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3114,6 +3114,35 @@ func (s *testIntegrationSuite) TestReorderSimplifiedOuterJoins(c *C) {
}
}

// Apply operator may got panic because empty Projection is eliminated.
func (s *testIntegrationSerialSuite) TestIssue23887(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("insert into t values(1, 2), (3, 4);")
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
s.testData.GetTestCases(c, &input, &output)
for i, tt := range input {
s.testData.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...))
}

tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1 (c1 int primary key, c2 int, c3 int, index c2 (c2));")
tk.MustQuery("select count(1) from (select count(1) from (select * from t1 where c3 = 100) k) k2;").Check(testkit.Rows("1"))
}

func (s *testIntegrationSerialSuite) TestDeleteStmt(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
26 changes: 26 additions & 0 deletions planner/core/rule_column_pruning.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,13 @@ func (p *LogicalJoin) PruneColumns(parentUsedCols []*expression.Column) error {
if err != nil {
return err
}
addConstOneForEmptyProjection(p.children[0])

err = p.children[1].PruneColumns(rightCols)
if err != nil {
return err
}
addConstOneForEmptyProjection(p.children[1])

p.mergeSchema()
if p.JoinType == LeftOuterSemiJoin || p.JoinType == AntiLeftOuterSemiJoin {
Expand All @@ -337,6 +339,7 @@ func (la *LogicalApply) PruneColumns(parentUsedCols []*expression.Column) error
if err != nil {
return err
}
addConstOneForEmptyProjection(la.children[1])

la.CorCols = extractCorColumnsBySchema4LogicalPlan(la.children[1], la.children[0].Schema())
for _, col := range la.CorCols {
Expand All @@ -347,6 +350,7 @@ func (la *LogicalApply) PruneColumns(parentUsedCols []*expression.Column) error
if err != nil {
return err
}
addConstOneForEmptyProjection(la.children[0])

la.mergeSchema()
return nil
Expand Down Expand Up @@ -431,3 +435,25 @@ func (p *LogicalLimit) PruneColumns(parentUsedCols []*expression.Column) error {
func (*columnPruner) name() string {
return "column_prune"
}

// By add const one, we can avoid empty Projection is eliminated.
// Because in some cases, Projectoin cannot be eliminated even its output is empty.
func addConstOneForEmptyProjection(p LogicalPlan) {
proj, ok := p.(*LogicalProjection)
if !ok {
return
}
if proj.Schema().Len() != 0 {
return
}

constOne := expression.NewOne()
proj.schema.Append(&expression.Column{
UniqueID: proj.ctx.GetSessionVars().AllocPlanColumnID(),
RetType: constOne.GetType(),
})
proj.Exprs = append(proj.Exprs, &expression.Constant{
Value: constOne.Value,
RetType: constOne.GetType(),
})
}
6 changes: 6 additions & 0 deletions planner/core/testdata/integration_serial_suite_in.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,11 @@
"desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b,c limit 10",
"desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b desc, c desc limit 10"
]
},
{
"name": "TestIssue23887",
"cases": [
"select (2) in (select b from t) from (select t.a < (select t.a from t t1 limit 1) from t) t"
]
}
]
54 changes: 41 additions & 13 deletions planner/core/testdata/integration_serial_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,21 @@
{
"SQL": "explain format = 'verbose' select (2) in (select count(*) from t1) from (select t.b < (select t.b from t2 limit 1 ) from t3 t) t",
"Plan": [
"HashJoin_19 3.00 113.61 root CARTESIAN left outer semi join",
"├─Selection_38(Build) 0.80 11.18 root eq(2, Column#18)",
"│ └─StreamAgg_59 1.00 69.50 root funcs:count(Column#27)->Column#18",
"│ └─TableReader_60 1.00 5.17 root data:StreamAgg_43",
"│ └─StreamAgg_43 1.00 8.18 batchCop[tiflash] funcs:count(1)->Column#27",
"│ └─TableFullScan_58 3.00 60.50 batchCop[tiflash] table:t1 keep order:false",
"└─Apply_21(Probe) 3.00 82.03 root CARTESIAN left outer join",
" ├─TableReader_23(Build) 3.00 10.16 root data:TableFullScan_22",
" │ └─TableFullScan_22 3.00 128.00 cop[tikv] table:t keep order:false",
" └─Limit_27(Probe) 1.00 5.36 root offset:0, count:1",
" └─TableReader_33 1.00 5.36 root data:Limit_32",
" └─Limit_32 1.00 56.00 cop[tikv] offset:0, count:1",
" └─TableFullScan_30 1.00 56.00 cop[tikv] table:t2 keep order:false"
"HashJoin_19 3.00 133.41 root CARTESIAN left outer semi join",
"├─Selection_39(Build) 0.80 11.18 root eq(2, Column#18)",
"│ └─StreamAgg_60 1.00 69.50 root funcs:count(Column#32)->Column#18",
"│ └─TableReader_61 1.00 5.17 root data:StreamAgg_44",
"│ └─StreamAgg_44 1.00 8.18 batchCop[tiflash] funcs:count(1)->Column#32",
"│ └─TableFullScan_59 3.00 60.50 batchCop[tiflash] table:t1 keep order:false",
"└─Projection_20(Probe) 3.00 101.83 root 1->Column#28",
" └─Apply_22 3.00 82.03 root CARTESIAN left outer join",
" ├─TableReader_24(Build) 3.00 10.16 root data:TableFullScan_23",
" │ └─TableFullScan_23 3.00 128.00 cop[tikv] table:t keep order:false",
" └─Projection_27(Probe) 1.00 23.96 root 1->Column#26",
" └─Limit_28 1.00 5.36 root offset:0, count:1",
" └─TableReader_34 1.00 5.36 root data:Limit_33",
" └─Limit_33 1.00 56.00 cop[tikv] offset:0, count:1",
" └─TableFullScan_31 1.00 56.00 cop[tikv] table:t2 keep order:false"
]
},
{
Expand Down Expand Up @@ -2552,5 +2554,31 @@
]
}
]
},
{
"Name": "TestIssue23887",
"Cases": [
{
"SQL": "select (2) in (select b from t) from (select t.a < (select t.a from t t1 limit 1) from t) t",
"Plan": [
"HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(2, test.t.b)",
"├─TableReader(Build) 10000.00 root data:TableFullScan",
"│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"└─Projection(Probe) 10000.00 root 1->Column#27",
" └─Apply 10000.00 root CARTESIAN left outer join",
" ├─TableReader(Build) 10000.00 root data:TableFullScan",
" │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
" └─Projection(Probe) 1.00 root 1->Column#25",
" └─Limit 1.00 root offset:0, count:1",
" └─TableReader 1.00 root data:Limit",
" └─Limit 1.00 cop[tikv] offset:0, count:1",
" └─TableFullScan 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
],
"Res": [
"1",
"1"
]
}
]
}
]

0 comments on commit a6ec081

Please sign in to comment.