// newSourceInfoForSingleTable creates a simple dataSourceInfo // which maps the same tableAlias to all columns. func newSourceInfoForSingleTable(tn parser.TableName, columns []ResultColumn) *dataSourceInfo { norm := sqlbase.NormalizeTableName(tn) return &dataSourceInfo{ sourceColumns: columns, sourceAliases: sourceAliases{norm: fillColumnRange(0, len(columns)-1)}, } }
// findUnaliasedColumn looks up the column specified by a VarName, not // taking column renames into account (but table renames will be taken // into account). That is, given a table "blah" with single column "y", // findUnaliasedColumn("y") returns a valid index even in the context // of: // SELECT * FROM blah as foo(x) // If the VarName specifies a table name, only columns that have that // name as their source alias are considered. If the VarName does not // specify a table name, all columns in the data source are // considered. If no column is found, invalidColIdx is returned with // no error. func (p *planDataSource) findUnaliasedColumn( c *parser.ColumnItem, ) (colIdx int, err error) { colName := sqlbase.NormalizeName(c.ColumnName) tableName := sqlbase.NormalizeTableName(c.TableName) if tableName.Table() != "" { tn, err := p.info.checkDatabaseName(tableName) if err != nil { return invalidColIdx, nil } tableName = tn } colIdx = invalidColIdx planColumns := p.plan.Columns() selCol := func(colIdx int, idx int) (int, error) { col := planColumns[idx] if sqlbase.ReNormalizeName(col.Name) == colName { if colIdx != invalidColIdx { return invalidColIdx, fmt.Errorf("column reference \"%s\" is ambiguous", parser.AsString(c)) } colIdx = idx } return colIdx, nil } if tableName.Table() == "" { for idx := 0; idx < len(p.info.sourceColumns); idx++ { colIdx, err = selCol(colIdx, idx) if err != nil { return colIdx, err } } } else { colRange, ok := p.info.sourceAliases[tableName] if !ok { // A table name is specified, but there is no column with this // table name. return invalidColIdx, nil } for _, idx := range colRange { colIdx, err = selCol(colIdx, idx) if err != nil { return colIdx, err } } } return colIdx, nil }
// expandStar returns the array of column metadata and name // expressions that correspond to the expansion of a star. func (src *dataSourceInfo) expandStar( v parser.VarName, qvals qvalMap, ) (columns []ResultColumn, exprs []parser.TypedExpr, err error) { if len(src.sourceColumns) == 0 { return nil, nil, fmt.Errorf("cannot use \"%s\" without a FROM clause", v) } colSel := func(idx int) { col := src.sourceColumns[idx] if !col.hidden { qval := qvals.getQVal(columnRef{src, idx}) columns = append(columns, ResultColumn{Name: col.Name, Typ: qval.datum}) exprs = append(exprs, qval) } } tableName := parser.TableName{} if a, ok := v.(*parser.AllColumnsSelector); ok { tableName = a.TableName } if tableName.Table() == "" { for i := 0; i < len(src.sourceColumns); i++ { colSel(i) } } else { norm := sqlbase.NormalizeTableName(tableName) qualifiedTn, err := src.checkDatabaseName(norm) if err != nil { return nil, nil, err } colRange, ok := src.sourceAliases[qualifiedTn] if !ok { return nil, nil, fmt.Errorf("table %q not found", tableName.String()) } for _, i := range colRange { colSel(i) } } return columns, exprs, nil }
// findColumn looks up the column specified by a VarName. The normalized VarName // is returned. func (sources multiSourceInfo) findColumn( c *parser.ColumnItem, ) (info *dataSourceInfo, colIdx int, err error) { if len(c.Selector) > 0 { return nil, invalidColIdx, util.UnimplementedWithIssueErrorf(8318, "compound types not supported yet: %q", c) } colName := sqlbase.NormalizeName(c.ColumnName) var tableName parser.TableName if c.TableName.Table() != "" { tableName = sqlbase.NormalizeTableName(c.TableName) tn, err := sources.checkDatabaseName(tableName) if err != nil { return nil, invalidColIdx, err } tableName = tn // Propagate the discovered database name back to the original VarName. // (to clarify the output of e.g. EXPLAIN) c.TableName.DatabaseName = tableName.DatabaseName } colIdx = invalidColIdx for _, src := range sources { findCol := func(src, info *dataSourceInfo, colIdx int, idx int) (*dataSourceInfo, int, error) { col := src.sourceColumns[idx] if sqlbase.ReNormalizeName(col.Name) == colName { if colIdx != invalidColIdx { return nil, invalidColIdx, fmt.Errorf("column reference %q is ambiguous", c) } info = src colIdx = idx } return info, colIdx, nil } if tableName.Table() == "" { for idx := 0; idx < len(src.sourceColumns); idx++ { info, colIdx, err = findCol(src, info, colIdx, idx) if err != nil { return info, colIdx, err } } } else { colRange, ok := src.sourceAliases[tableName] if !ok { // The data source "src" has no column for table tableName. // Try again with the net one. continue } for _, idx := range colRange { info, colIdx, err = findCol(src, info, colIdx, idx) if err != nil { return info, colIdx, err } } } } if colIdx == invalidColIdx { return nil, invalidColIdx, fmt.Errorf("column name %q not found", c) } return info, colIdx, nil }