vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/pullout_subquery.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package planbuilder 18 19 import ( 20 "vitess.io/vitess/go/vt/sqlparser" 21 "vitess.io/vitess/go/vt/vterrors" 22 "vitess.io/vitess/go/vt/vtgate/engine" 23 "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" 24 "vitess.io/vitess/go/vt/vtgate/semantics" 25 ) 26 27 var _ logicalPlan = (*pulloutSubquery)(nil) 28 29 // pulloutSubquery is the logicalPlan for engine.PulloutSubquery. 30 // This gets built if a subquery is not correlated and can 31 // therefore can be pulled out and executed upfront. 32 type pulloutSubquery struct { 33 order int 34 subquery logicalPlan 35 underlying logicalPlan 36 eSubquery *engine.PulloutSubquery 37 } 38 39 // newPulloutSubquery builds a new pulloutSubquery. 40 func newPulloutSubquery(opcode engine.PulloutOpcode, sqName, hasValues string, subquery logicalPlan) *pulloutSubquery { 41 return &pulloutSubquery{ 42 subquery: subquery, 43 eSubquery: &engine.PulloutSubquery{ 44 Opcode: opcode, 45 SubqueryResult: sqName, 46 HasValues: hasValues, 47 }, 48 } 49 } 50 51 // setUnderlying sets the underlying primitive. 52 func (ps *pulloutSubquery) setUnderlying(underlying logicalPlan) { 53 ps.underlying = underlying 54 ps.underlying.Reorder(ps.subquery.Order()) 55 ps.order = ps.underlying.Order() + 1 56 } 57 58 // Order implements the logicalPlan interface 59 func (ps *pulloutSubquery) Order() int { 60 return ps.order 61 } 62 63 // Reorder implements the logicalPlan interface 64 func (ps *pulloutSubquery) Reorder(order int) { 65 ps.subquery.Reorder(order) 66 ps.underlying.Reorder(ps.subquery.Order()) 67 ps.order = ps.underlying.Order() + 1 68 } 69 70 // Primitive implements the logicalPlan interface 71 func (ps *pulloutSubquery) Primitive() engine.Primitive { 72 ps.eSubquery.Subquery = ps.subquery.Primitive() 73 ps.eSubquery.Underlying = ps.underlying.Primitive() 74 return ps.eSubquery 75 } 76 77 // ResultColumns implements the logicalPlan interface 78 func (ps *pulloutSubquery) ResultColumns() []*resultColumn { 79 return ps.underlying.ResultColumns() 80 } 81 82 // Wireup implements the logicalPlan interface 83 func (ps *pulloutSubquery) Wireup(plan logicalPlan, jt *jointab) error { 84 if err := ps.underlying.Wireup(plan, jt); err != nil { 85 return err 86 } 87 return ps.subquery.Wireup(plan, jt) 88 } 89 90 // Wireup2 implements the logicalPlan interface 91 func (ps *pulloutSubquery) WireupGen4(ctx *plancontext.PlanningContext) error { 92 if err := ps.underlying.WireupGen4(ctx); err != nil { 93 return err 94 } 95 return ps.subquery.WireupGen4(ctx) 96 } 97 98 // SupplyVar implements the logicalPlan interface 99 func (ps *pulloutSubquery) SupplyVar(from, to int, col *sqlparser.ColName, varname string) { 100 if from <= ps.subquery.Order() { 101 ps.subquery.SupplyVar(from, to, col, varname) 102 return 103 } 104 ps.underlying.SupplyVar(from, to, col, varname) 105 } 106 107 // SupplyCol implements the logicalPlan interface 108 func (ps *pulloutSubquery) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) { 109 return ps.underlying.SupplyCol(col) 110 } 111 112 // SupplyWeightString implements the logicalPlan interface 113 func (ps *pulloutSubquery) SupplyWeightString(colNumber int, alsoAddToGroupBy bool) (weightcolNumber int, err error) { 114 return ps.underlying.SupplyWeightString(colNumber, alsoAddToGroupBy) 115 } 116 117 // Rewrite implements the logicalPlan interface 118 func (ps *pulloutSubquery) Rewrite(inputs ...logicalPlan) error { 119 if len(inputs) != 2 { 120 return vterrors.VT13001("pulloutSubquery: wrong number of inputs") 121 } 122 ps.underlying = inputs[0] 123 ps.subquery = inputs[1] 124 return nil 125 } 126 127 // ContainsTables implements the logicalPlan interface 128 func (ps *pulloutSubquery) ContainsTables() semantics.TableSet { 129 return ps.underlying.ContainsTables().Merge(ps.subquery.ContainsTables()) 130 } 131 132 // Inputs implements the logicalPlan interface 133 func (ps *pulloutSubquery) Inputs() []logicalPlan { 134 return []logicalPlan{ps.underlying, ps.subquery} 135 } 136 137 // OutputColumns implements the logicalPlan interface 138 func (ps *pulloutSubquery) OutputColumns() []sqlparser.SelectExpr { 139 return ps.underlying.OutputColumns() 140 }