Skip to content

Commit f299fb2

Browse files
eurekakasre-bot
authored andcommitted
planner: support subquery in SHOW statement (#10942) (#11461)
All tests passed, auto merged by Bot
1 parent ba91dbd commit f299fb2

13 files changed

+128
-37
lines changed

executor/builder.go

+1-8
Original file line numberDiff line numberDiff line change
@@ -532,14 +532,7 @@ func (b *executorBuilder) buildShow(v *plannercore.Show) Executor {
532532
b.err = errors.Trace(err)
533533
}
534534
}
535-
if len(v.Conditions) == 0 {
536-
return e
537-
}
538-
sel := &SelectionExec{
539-
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID(), e),
540-
filters: v.Conditions,
541-
}
542-
return sel
535+
return e
543536
}
544537

545538
func (b *executorBuilder) buildSimple(v *plannercore.Simple) Executor {

planner/core/common_plans.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ type Deallocate struct {
301301

302302
// Show represents a show plan.
303303
type Show struct {
304-
baseSchemaProducer
304+
physicalSchemaProducer
305305

306306
Tp ast.ShowStmtType // Databases/Tables/Columns/....
307307
DBName string
@@ -312,8 +312,6 @@ type Show struct {
312312
Full bool
313313
User *auth.UserIdentity // Used for show grants.
314314

315-
Conditions []expression.Expression
316-
317315
// Used by show variables
318316
GlobalScope bool
319317
}

planner/core/find_best_task.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ func (p *LogicalTableDual) findBestTask(prop *property.PhysicalProperty) (task,
7272
if !prop.IsEmpty() {
7373
return invalidTask, nil
7474
}
75-
dual := PhysicalTableDual{RowCount: p.RowCount}.init(p.ctx, p.stats)
75+
dual := PhysicalTableDual{
76+
RowCount: p.RowCount,
77+
placeHolder: p.placeHolder,
78+
}.init(p.ctx, p.stats)
7679
dual.SetSchema(p.schema)
7780
return &rootTask{p: dual}, nil
7881
}

planner/core/initialize.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ func (p Insert) init(ctx sessionctx.Context) *Insert {
225225
}
226226

227227
func (p Show) init(ctx sessionctx.Context) *Show {
228-
p.basePlan = newBasePlan(ctx, TypeShow)
228+
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeShow, &p)
229+
// Just use pseudo stats to avoid panic.
230+
p.stats = &property.StatsInfo{RowCount: 1}
229231
return &p
230232
}
231233

planner/core/integration_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2019 PingCAP, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package core_test
15+
16+
import (
17+
. "github.com/pingcap/check"
18+
"github.com/pingcap/tidb/util/testkit"
19+
)
20+
21+
var _ = Suite(&testIntegrationSuite{})
22+
23+
type testIntegrationSuite struct {
24+
}
25+
26+
func (s *testIntegrationSuite) TestShowSubquery(c *C) {
27+
store, dom, err := newStoreWithBootstrap()
28+
c.Assert(err, IsNil)
29+
tk := testkit.NewTestKit(c, store)
30+
defer func() {
31+
dom.Close()
32+
store.Close()
33+
}()
34+
tk.MustExec("use test")
35+
tk.MustExec("drop table if exists t")
36+
tk.MustExec("create table t(a varchar(10), b int, c int)")
37+
tk.MustQuery("show columns from t where true").Check(testkit.Rows(
38+
"a varchar(10) YES <nil> ",
39+
"b int(11) YES <nil> ",
40+
"c int(11) YES <nil> ",
41+
))
42+
tk.MustQuery("show columns from t where field = 'b'").Check(testkit.Rows(
43+
"b int(11) YES <nil> ",
44+
))
45+
tk.MustQuery("show columns from t where field in (select 'b')").Check(testkit.Rows(
46+
"b int(11) YES <nil> ",
47+
))
48+
tk.MustQuery("show columns from t where field in (select 'b') and true").Check(testkit.Rows(
49+
"b int(11) YES <nil> ",
50+
))
51+
tk.MustQuery("show columns from t where field in (select 'b') and false").Check(testkit.Rows())
52+
tk.MustExec("insert into t values('c', 0, 0)")
53+
tk.MustQuery("show columns from t where field < all (select a from t)").Check(testkit.Rows(
54+
"a varchar(10) YES <nil> ",
55+
"b int(11) YES <nil> ",
56+
))
57+
tk.MustExec("insert into t values('b', 0, 0)")
58+
tk.MustQuery("show columns from t where field < all (select a from t)").Check(testkit.Rows(
59+
"a varchar(10) YES <nil> ",
60+
))
61+
}

planner/core/logical_plan_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ func (s *testPlanSuite) TestPlanBuilder(c *C) {
925925
},
926926
{
927927
sql: "show columns from t where `Key` = 'pri' like 't*'",
928-
plan: "Show([eq(cast(key), 0)])",
928+
plan: "Show->Sel([eq(cast(key), 0)])",
929929
},
930930
{
931931
sql: "do sleep(5)",

planner/core/logical_plans.go

+4
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ type LogicalTableDual struct {
303303
logicalSchemaProducer
304304

305305
RowCount int
306+
// placeHolder indicates if this dual plan is a place holder in query optimization
307+
// for data sources like `Show`, if true, the dual plan would be substituted by
308+
// `Show` in the final plan.
309+
placeHolder bool
306310
}
307311

308312
// LogicalUnionScan is only used in non read-only txn.

planner/core/physical_plans.go

+4
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ type PhysicalTableDual struct {
373373
physicalSchemaProducer
374374

375375
RowCount int
376+
// placeHolder indicates if this dual plan is a place holder in query optimization
377+
// for data sources like `Show`, if true, the dual plan would be substituted by
378+
// `Show` in the final plan.
379+
placeHolder bool
376380
}
377381

378382
// CollectPlanStatsVersion uses to collect the statistics version of the plan.

planner/core/plan.go

+8
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ type PhysicalPlan interface {
136136
// SetChildren sets the children for the plan.
137137
SetChildren(...PhysicalPlan)
138138

139+
// SetChild sets the ith child for the plan.
140+
SetChild(i int, child PhysicalPlan)
141+
139142
// ResolveIndices resolves the indices for columns. After doing this, the columns can evaluate the rows by their indices.
140143
ResolveIndices()
141144
}
@@ -289,6 +292,11 @@ func (p *basePhysicalPlan) SetChildren(children ...PhysicalPlan) {
289292
p.children = children
290293
}
291294

295+
// SetChild implements PhysicalPlan SetChild interface.
296+
func (p *basePhysicalPlan) SetChild(i int, child PhysicalPlan) {
297+
p.children[i] = child
298+
}
299+
292300
func (p *basePlan) context() sessionctx.Context {
293301
return p.ctx
294302
}

planner/core/planbuilder.go

+37-11
Original file line numberDiff line numberDiff line change
@@ -979,32 +979,58 @@ func (b *planBuilder) buildShow(show *ast.ShowStmt) (Plan, error) {
979979
for _, col := range p.schema.Columns {
980980
col.UniqueID = b.ctx.GetSessionVars().AllocPlanColumnID()
981981
}
982-
mockTablePlan := LogicalTableDual{}.init(b.ctx)
982+
mockTablePlan := LogicalTableDual{placeHolder: true}.init(b.ctx)
983983
mockTablePlan.SetSchema(p.schema)
984+
var err error
985+
var np LogicalPlan
986+
np = mockTablePlan
984987
if show.Pattern != nil {
985988
show.Pattern.Expr = &ast.ColumnNameExpr{
986989
Name: &ast.ColumnName{Name: p.Schema().Columns[0].ColName},
987990
}
988-
expr, _, err := b.rewrite(show.Pattern, mockTablePlan, nil, false)
991+
np, err = b.buildSelection(np, show.Pattern, nil)
989992
if err != nil {
990993
return nil, errors.Trace(err)
991994
}
992-
p.Conditions = append(p.Conditions, expr)
993995
}
994996
if show.Where != nil {
995-
conds := splitWhere(show.Where)
996-
for _, cond := range conds {
997-
expr, _, err := b.rewrite(cond, mockTablePlan, nil, false)
998-
if err != nil {
999-
return nil, errors.Trace(err)
1000-
}
1001-
p.Conditions = append(p.Conditions, expr)
997+
np, err = b.buildSelection(np, show.Where, nil)
998+
if err != nil {
999+
return nil, err
1000+
}
1001+
}
1002+
if np != mockTablePlan {
1003+
fieldsLen := len(mockTablePlan.schema.Columns)
1004+
proj := LogicalProjection{Exprs: make([]expression.Expression, 0, fieldsLen)}.init(b.ctx)
1005+
schema := expression.NewSchema(make([]*expression.Column, 0, fieldsLen)...)
1006+
for _, col := range mockTablePlan.schema.Columns {
1007+
proj.Exprs = append(proj.Exprs, col)
1008+
newCol := col.Clone().(*expression.Column)
1009+
newCol.UniqueID = b.ctx.GetSessionVars().AllocPlanColumnID()
1010+
schema.Append(newCol)
1011+
}
1012+
proj.SetSchema(schema)
1013+
proj.SetChildren(np)
1014+
physical, err := doOptimize(b.optFlag|flagEliminateProjection, proj)
1015+
if err != nil {
1016+
return nil, err
10021017
}
1003-
p.ResolveIndices()
1018+
return substitutePlaceHolderDual(physical, p), nil
10041019
}
10051020
return p, nil
10061021
}
10071022

1023+
func substitutePlaceHolderDual(src PhysicalPlan, dst PhysicalPlan) PhysicalPlan {
1024+
if dual, ok := src.(*PhysicalTableDual); ok && dual.placeHolder {
1025+
return dst
1026+
}
1027+
for i, child := range src.Children() {
1028+
newChild := substitutePlaceHolderDual(child, dst)
1029+
src.SetChild(i, newChild)
1030+
}
1031+
return src
1032+
}
1033+
10081034
func (b *planBuilder) buildSimple(node ast.StmtNode) Plan {
10091035
p := &Simple{Statement: node}
10101036

planner/core/point_get_plan.go

+3
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ func (p *PointGetPlan) Children() []PhysicalPlan {
112112
// SetChildren sets the children for the plan.
113113
func (p *PointGetPlan) SetChildren(...PhysicalPlan) {}
114114

115+
// SetChild sets a specific child for the plan.
116+
func (p *PointGetPlan) SetChild(i int, child PhysicalPlan) {}
117+
115118
// ResolveIndices resolves the indices for columns. After doing this, the columns can evaluate the rows by their indices.
116119
func (p *PointGetPlan) ResolveIndices() {}
117120

planner/core/resolve_indices.go

-7
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,6 @@ func (p *Insert) ResolveIndices() {
234234
}
235235
}
236236

237-
// ResolveIndices implements Plan interface.
238-
func (p *Show) ResolveIndices() {
239-
for i, expr := range p.Conditions {
240-
p.Conditions[i] = expr.ResolveIndices(p.schema)
241-
}
242-
}
243-
244237
func (p *physicalSchemaProducer) ResolveIndices() {
245238
p.basePhysicalPlan.ResolveIndices()
246239
if p.schema != nil {

planner/core/stringer.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,7 @@ func toString(in Plan, strs []string, idxs []int) ([]string, []int) {
113113
case *ShowDDL:
114114
str = "ShowDDL"
115115
case *Show:
116-
if len(x.Conditions) == 0 {
117-
str = "Show"
118-
} else {
119-
str = fmt.Sprintf("Show(%s)", x.Conditions)
120-
}
116+
str = "Show"
121117
case *LogicalSort, *PhysicalSort:
122118
str = "Sort"
123119
case *LogicalJoin:

0 commit comments

Comments
 (0)