vitess.io/vitess@v0.16.2/go/vt/vtgate/semantics/vtable.go (about) 1 /* 2 Copyright 2021 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 semantics 18 19 import ( 20 vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" 21 "vitess.io/vitess/go/vt/sqlparser" 22 "vitess.io/vitess/go/vt/vterrors" 23 "vitess.io/vitess/go/vt/vtgate/vindexes" 24 ) 25 26 // vTableInfo is used to represent projected results, not real tables. It is used for 27 // ORDER BY, GROUP BY and HAVING that need to access result columns 28 type vTableInfo struct { 29 tableName string 30 columnNames []string 31 cols []sqlparser.Expr 32 tables TableSet 33 isAuthoritative bool 34 } 35 36 var _ TableInfo = (*vTableInfo)(nil) 37 38 // dependencies implements the TableInfo interface 39 func (v *vTableInfo) dependencies(colName string, org originable) (dependencies, error) { 40 var deps dependencies = ¬hing{} 41 for i, name := range v.columnNames { 42 if name != colName { 43 continue 44 } 45 directDeps, recursiveDeps, qt := org.depsForExpr(v.cols[i]) 46 47 newDeps := createCertain(directDeps, recursiveDeps, qt) 48 deps = deps.merge(newDeps, false) 49 } 50 if deps.empty() && v.hasStar() { 51 return createUncertain(v.tables, v.tables), nil 52 } 53 return deps, nil 54 } 55 56 // IsInfSchema implements the TableInfo interface 57 func (v *vTableInfo) IsInfSchema() bool { 58 return false 59 } 60 61 func (v *vTableInfo) matches(name sqlparser.TableName) bool { 62 return v.tableName == name.Name.String() && name.Qualifier.IsEmpty() 63 } 64 65 func (v *vTableInfo) authoritative() bool { 66 return v.isAuthoritative 67 } 68 69 func (v *vTableInfo) Name() (sqlparser.TableName, error) { 70 return sqlparser.TableName{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "oh noes") 71 } 72 73 func (v *vTableInfo) getExpr() *sqlparser.AliasedTableExpr { 74 return nil 75 } 76 77 // GetVindexTable implements the TableInfo interface 78 func (v *vTableInfo) GetVindexTable() *vindexes.Table { 79 return nil 80 } 81 82 func (v *vTableInfo) getColumns() []ColumnInfo { 83 cols := make([]ColumnInfo, 0, len(v.columnNames)) 84 for _, col := range v.columnNames { 85 cols = append(cols, ColumnInfo{ 86 Name: col, 87 }) 88 } 89 return cols 90 } 91 92 func (v *vTableInfo) hasStar() bool { 93 return v.tables.NonEmpty() 94 } 95 96 // GetTables implements the TableInfo interface 97 func (v *vTableInfo) getTableSet(_ originable) TableSet { 98 return v.tables 99 } 100 101 // GetExprFor implements the TableInfo interface 102 func (v *vTableInfo) getExprFor(s string) (sqlparser.Expr, error) { 103 for i, colName := range v.columnNames { 104 if colName == s { 105 return v.cols[i], nil 106 } 107 } 108 return nil, vterrors.VT03022(s, "field list") 109 } 110 111 func createVTableInfoForExpressions(expressions sqlparser.SelectExprs, tables []TableInfo, org originable) *vTableInfo { 112 cols, colNames, ts, isAuthoritative := selectExprsToInfos(expressions, tables, org) 113 return &vTableInfo{ 114 columnNames: colNames, 115 cols: cols, 116 tables: ts, 117 isAuthoritative: isAuthoritative, 118 } 119 } 120 121 func selectExprsToInfos( 122 expressions sqlparser.SelectExprs, 123 tables []TableInfo, 124 org originable, 125 ) (cols []sqlparser.Expr, colNames []string, ts TableSet, isAuthoritative bool) { 126 isAuthoritative = true 127 for _, selectExpr := range expressions { 128 switch expr := selectExpr.(type) { 129 case *sqlparser.AliasedExpr: 130 cols = append(cols, expr.Expr) 131 if expr.As.IsEmpty() { 132 switch expr := expr.Expr.(type) { 133 case *sqlparser.ColName: 134 // for projections, we strip out the qualifier and keep only the column name 135 colNames = append(colNames, expr.Name.String()) 136 default: 137 colNames = append(colNames, sqlparser.String(expr)) 138 } 139 } else { 140 colNames = append(colNames, expr.As.String()) 141 } 142 case *sqlparser.StarExpr: 143 for _, table := range tables { 144 ts = ts.Merge(table.getTableSet(org)) 145 if !table.authoritative() { 146 isAuthoritative = false 147 } 148 } 149 } 150 } 151 return 152 }