vitess.io/vitess@v0.16.2/go/vt/vtgate/semantics/derived_table.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 "strings" 21 22 vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" 23 "vitess.io/vitess/go/vt/sqlparser" 24 "vitess.io/vitess/go/vt/vterrors" 25 "vitess.io/vitess/go/vt/vtgate/vindexes" 26 ) 27 28 // DerivedTable contains the information about the projection, tables involved in derived table. 29 type DerivedTable struct { 30 tableName string 31 ASTNode *sqlparser.AliasedTableExpr 32 columnNames []string 33 cols []sqlparser.Expr 34 tables TableSet 35 isAuthoritative bool 36 } 37 38 var _ TableInfo = (*DerivedTable)(nil) 39 40 func createDerivedTableForExpressions(expressions sqlparser.SelectExprs, cols sqlparser.Columns, tables []TableInfo, org originable) *DerivedTable { 41 vTbl := &DerivedTable{isAuthoritative: true} 42 for i, selectExpr := range expressions { 43 switch expr := selectExpr.(type) { 44 case *sqlparser.AliasedExpr: 45 vTbl.cols = append(vTbl.cols, expr.Expr) 46 if len(cols) > 0 { 47 vTbl.columnNames = append(vTbl.columnNames, cols[i].String()) 48 } else if expr.As.IsEmpty() { 49 switch expr := expr.Expr.(type) { 50 case *sqlparser.ColName: 51 // for projections, we strip out the qualifier and keep only the column name 52 vTbl.columnNames = append(vTbl.columnNames, expr.Name.String()) 53 default: 54 vTbl.columnNames = append(vTbl.columnNames, sqlparser.String(expr)) 55 } 56 } else { 57 vTbl.columnNames = append(vTbl.columnNames, expr.As.String()) 58 } 59 case *sqlparser.StarExpr: 60 for _, table := range tables { 61 vTbl.tables = vTbl.tables.Merge(table.getTableSet(org)) 62 if !table.authoritative() { 63 vTbl.isAuthoritative = false 64 } 65 } 66 } 67 } 68 return vTbl 69 } 70 71 // dependencies implements the TableInfo interface 72 func (dt *DerivedTable) dependencies(colName string, org originable) (dependencies, error) { 73 directDeps := org.tableSetFor(dt.ASTNode) 74 for i, name := range dt.columnNames { 75 if !strings.EqualFold(name, colName) { 76 continue 77 } 78 _, recursiveDeps, qt := org.depsForExpr(dt.cols[i]) 79 80 return createCertain(directDeps, recursiveDeps, qt), nil 81 } 82 83 if !dt.hasStar() { 84 return ¬hing{}, nil 85 } 86 87 return createUncertain(directDeps, dt.tables), nil 88 } 89 90 // IsInfSchema implements the TableInfo interface 91 func (dt *DerivedTable) IsInfSchema() bool { 92 return false 93 } 94 95 func (dt *DerivedTable) matches(name sqlparser.TableName) bool { 96 return dt.tableName == name.Name.String() && name.Qualifier.IsEmpty() 97 } 98 99 func (dt *DerivedTable) authoritative() bool { 100 return dt.isAuthoritative 101 } 102 103 // Name implements the TableInfo interface 104 func (dt *DerivedTable) Name() (sqlparser.TableName, error) { 105 return dt.ASTNode.TableName() 106 } 107 108 func (dt *DerivedTable) getExpr() *sqlparser.AliasedTableExpr { 109 return dt.ASTNode 110 } 111 112 // GetVindexTable implements the TableInfo interface 113 func (dt *DerivedTable) GetVindexTable() *vindexes.Table { 114 return nil 115 } 116 117 func (dt *DerivedTable) getColumns() []ColumnInfo { 118 cols := make([]ColumnInfo, 0, len(dt.columnNames)) 119 for _, col := range dt.columnNames { 120 cols = append(cols, ColumnInfo{ 121 Name: col, 122 }) 123 } 124 return cols 125 } 126 127 func (dt *DerivedTable) hasStar() bool { 128 return dt.tables.NonEmpty() 129 } 130 131 // GetTables implements the TableInfo interface 132 func (dt *DerivedTable) getTableSet(_ originable) TableSet { 133 return dt.tables 134 } 135 136 // GetExprFor implements the TableInfo interface 137 func (dt *DerivedTable) getExprFor(s string) (sqlparser.Expr, error) { 138 for i, colName := range dt.columnNames { 139 if colName == s { 140 return dt.cols[i], nil 141 } 142 } 143 return nil, vterrors.NewErrorf(vtrpcpb.Code_NOT_FOUND, vterrors.BadFieldError, "Unknown column '%s' in 'field list'", s) 144 } 145 146 func (dt *DerivedTable) checkForDuplicates() error { 147 for i, name := range dt.columnNames { 148 for j, name2 := range dt.columnNames { 149 if i == j { 150 continue 151 } 152 if name == name2 { 153 return vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.DupFieldName, "Duplicate column name '%s'", name) 154 } 155 } 156 } 157 return nil 158 }