vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/simple_projection.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 "fmt" 21 22 "vitess.io/vitess/go/vt/sqlparser" 23 "vitess.io/vitess/go/vt/vterrors" 24 "vitess.io/vitess/go/vt/vtgate/engine" 25 ) 26 27 var _ logicalPlan = (*simpleProjection)(nil) 28 29 // simpleProjection is used for wrapping a derived table. 30 // This primitive wraps any derived table that results 31 // in something that's not a route. It builds a 32 // 'table' for the derived table allowing higher level 33 // constructs to reference its columns. If a derived table 34 // results in a route primitive, we instead build 35 // a new route that keeps the subquery in the FROM 36 // clause, because a route is more versatile than 37 // a simpleProjection. 38 // this should not be used by the gen4 planner 39 type simpleProjection struct { 40 logicalPlanCommon 41 resultColumns []*resultColumn 42 eSimpleProj *engine.SimpleProjection 43 } 44 45 // newSimpleProjection builds a new simpleProjection. 46 func newSimpleProjection(alias sqlparser.IdentifierCS, plan logicalPlan) (*simpleProjection, *symtab, error) { 47 sq := &simpleProjection{ 48 logicalPlanCommon: newBuilderCommon(plan), 49 eSimpleProj: &engine.SimpleProjection{}, 50 } 51 52 // Create a 'table' that represents the derived table. 53 t := &table{ 54 alias: sqlparser.TableName{Name: alias}, 55 origin: sq, 56 } 57 58 // Create column symbols based on the result column names. 59 for _, rc := range plan.ResultColumns() { 60 if _, ok := t.columns[rc.alias.Lowered()]; ok { 61 return nil, nil, vterrors.VT12001(fmt.Sprintf("duplicate column names in subquery: %s", sqlparser.String(rc.alias))) 62 } 63 t.addColumn(rc.alias, &column{origin: sq}) 64 } 65 t.isAuthoritative = true 66 st := newSymtab() 67 // AddTable will not fail because symtab is empty. 68 _ = st.AddTable(t) 69 return sq, st, nil 70 } 71 72 // Primitive implements the logicalPlan interface 73 func (sq *simpleProjection) Primitive() engine.Primitive { 74 sq.eSimpleProj.Input = sq.input.Primitive() 75 return sq.eSimpleProj 76 } 77 78 // ResultColumns implements the logicalPlan interface 79 func (sq *simpleProjection) ResultColumns() []*resultColumn { 80 return sq.resultColumns 81 } 82 83 // SupplyCol implements the logicalPlan interface 84 func (sq *simpleProjection) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) { 85 c := col.Metadata.(*column) 86 for i, rc := range sq.resultColumns { 87 if rc.column == c { 88 return rc, i 89 } 90 } 91 92 // columns that reference subqueries will have their colNumber set. 93 // Let's use it here. 94 sq.eSimpleProj.Cols = append(sq.eSimpleProj.Cols, c.colNumber) 95 sq.resultColumns = append(sq.resultColumns, &resultColumn{column: c}) 96 return rc, len(sq.resultColumns) - 1 97 } 98 99 // OutputColumns implements the logicalPlan interface 100 func (sq *simpleProjection) OutputColumns() []sqlparser.SelectExpr { 101 exprs := make([]sqlparser.SelectExpr, 0, len(sq.eSimpleProj.Cols)) 102 outputCols := sq.input.OutputColumns() 103 for _, colID := range sq.eSimpleProj.Cols { 104 exprs = append(exprs, outputCols[colID]) 105 } 106 return exprs 107 }