vitess.io/vitess@v0.16.2/go/vt/vtgate/semantics/real_table.go (about)

     1  /*
     2  Copyright 2020 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  	"vitess.io/vitess/go/mysql/collations"
    23  	"vitess.io/vitess/go/sqltypes"
    24  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    25  	"vitess.io/vitess/go/vt/sqlparser"
    26  	"vitess.io/vitess/go/vt/vterrors"
    27  	"vitess.io/vitess/go/vt/vtgate/vindexes"
    28  )
    29  
    30  // RealTable contains the alias table expr and vindex table
    31  type RealTable struct {
    32  	dbName, tableName string
    33  	ASTNode           *sqlparser.AliasedTableExpr
    34  	Table             *vindexes.Table
    35  	isInfSchema       bool
    36  }
    37  
    38  var _ TableInfo = (*RealTable)(nil)
    39  
    40  // dependencies implements the TableInfo interface
    41  func (r *RealTable) dependencies(colName string, org originable) (dependencies, error) {
    42  	ts := org.tableSetFor(r.ASTNode)
    43  	for _, info := range r.getColumns() {
    44  		if strings.EqualFold(info.Name, colName) {
    45  			return createCertain(ts, ts, &info.Type), nil
    46  		}
    47  	}
    48  
    49  	if r.authoritative() {
    50  		return &nothing{}, nil
    51  	}
    52  	return createUncertain(ts, ts), nil
    53  }
    54  
    55  // GetTables implements the TableInfo interface
    56  func (r *RealTable) getTableSet(org originable) TableSet {
    57  	return org.tableSetFor(r.ASTNode)
    58  }
    59  
    60  // GetExprFor implements the TableInfo interface
    61  func (r *RealTable) getExprFor(s string) (sqlparser.Expr, error) {
    62  	return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Unknown column '%s' in 'field list'", s)
    63  }
    64  
    65  // IsInfSchema implements the TableInfo interface
    66  func (r *RealTable) IsInfSchema() bool {
    67  	return r.isInfSchema
    68  }
    69  
    70  // GetColumns implements the TableInfo interface
    71  func (r *RealTable) getColumns() []ColumnInfo {
    72  	return vindexTableToColumnInfo(r.Table)
    73  }
    74  
    75  // GetExpr implements the TableInfo interface
    76  func (r *RealTable) getExpr() *sqlparser.AliasedTableExpr {
    77  	return r.ASTNode
    78  }
    79  
    80  // GetVindexTable implements the TableInfo interface
    81  func (r *RealTable) GetVindexTable() *vindexes.Table {
    82  	return r.Table
    83  }
    84  
    85  // Name implements the TableInfo interface
    86  func (r *RealTable) Name() (sqlparser.TableName, error) {
    87  	return r.ASTNode.TableName()
    88  }
    89  
    90  // Authoritative implements the TableInfo interface
    91  func (r *RealTable) authoritative() bool {
    92  	return r.Table != nil && r.Table.ColumnListAuthoritative
    93  }
    94  
    95  // Matches implements the TableInfo interface
    96  func (r *RealTable) matches(name sqlparser.TableName) bool {
    97  	return (name.Qualifier.IsEmpty() || name.Qualifier.String() == r.dbName) && r.tableName == name.Name.String()
    98  }
    99  
   100  func vindexTableToColumnInfo(tbl *vindexes.Table) []ColumnInfo {
   101  	if tbl == nil {
   102  		return nil
   103  	}
   104  	nameMap := map[string]any{}
   105  	cols := make([]ColumnInfo, 0, len(tbl.Columns))
   106  	for _, col := range tbl.Columns {
   107  		var collation collations.ID
   108  		if sqltypes.IsText(col.Type) {
   109  			collation, _ = collations.Local().LookupID(col.CollationName)
   110  		}
   111  		cols = append(cols, ColumnInfo{
   112  			Name: col.Name.String(),
   113  			Type: Type{
   114  				Type:      col.Type,
   115  				Collation: collation,
   116  			},
   117  		})
   118  		nameMap[col.Name.String()] = nil
   119  	}
   120  	// If table is authoritative, we do not need ColumnVindexes to help in resolving the unqualified columns.
   121  	if tbl.ColumnListAuthoritative {
   122  		return cols
   123  	}
   124  	for _, vindex := range tbl.ColumnVindexes {
   125  		for _, column := range vindex.Columns {
   126  			name := column.String()
   127  			if _, exists := nameMap[name]; exists {
   128  				continue
   129  			}
   130  			cols = append(cols, ColumnInfo{
   131  				Name: name,
   132  			})
   133  			nameMap[name] = nil
   134  		}
   135  	}
   136  	return cols
   137  }