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 = &nothing{}
    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  }