// findColumn looks up the column described by a QualifiedName. The qname will be normalized. func (qt qvalResolver) findColumn(qname *parser.QualifiedName) (columnRef, error) { ref := columnRef{colIdx: invalidColIdx} if err := qname.NormalizeColumnName(); err != nil { return ref, err } // We can't resolve stars to a single column. if qname.IsStar() { err := fmt.Errorf("qualified name \"%s\" not found", qname) return ref, err } // TODO(radu): when we support multiple FROMs, we will find the node with the correct alias; if // no alias is given, we will search for the column in all FROMs and make sure there is only // one. For now we just check that the name matches (if given). if qname.Base == "" || sqlbase.EqualName(qt.table.alias, string(qname.Base)) { colName := sqlbase.NormalizeName(qname.Column()) for idx, col := range qt.table.columns { if sqlbase.NormalizeName(col.Name) == colName { ref.table = qt.table ref.colIdx = idx return ref, nil } } } err := fmt.Errorf("qualified name \"%s\" not found", qname) return ref, err }
// findColumn looks up the column described by a QualifiedName. The qname will be normalized. func (qt qvalResolver) findColumn(qname *parser.QualifiedName) (columnRef, error) { ref := columnRef{colIdx: invalidColIdx} if err := qname.NormalizeColumnName(); err != nil { return ref, err } // We can't resolve stars to a single column. if qname.IsStar() { err := fmt.Errorf("qualified name \"%s\" not found", qname) return ref, err } colName := sqlbase.NormalizeName(qname.Column()) for _, table := range qt.tables { if qname.Base == "" || sqlbase.EqualName(table.alias, string(qname.Base)) { for idx, col := range table.columns { if sqlbase.NormalizeName(col.Name) == colName { if ref.colIdx != invalidColIdx { return ref, fmt.Errorf("column reference \"%s\" is ambiguous", qname) } ref.table = table ref.colIdx = idx } } } } if ref.colIdx == invalidColIdx { return ref, fmt.Errorf("qualified name \"%s\" not found", qname) } return ref, nil }
// Initializes a scanNode with a tableName. Returns the table or index name that can be used for // fully-qualified columns if an alias is not specified. func (n *scanNode) initTable( p *planner, tableName *parser.QualifiedName, indexHints *parser.IndexHints, ) (string, error) { var err error n.desc, err = p.getTableLease(tableName) if err != nil { return "", err } if err := p.checkPrivilege(&n.desc, privilege.SELECT); err != nil { return "", err } alias := n.desc.Name if indexHints != nil && indexHints.Index != "" { indexName := sqlbase.NormalizeName(string(indexHints.Index)) if indexName == sqlbase.NormalizeName(n.desc.PrimaryIndex.Name) { n.specifiedIndex = &n.desc.PrimaryIndex } else { for i := range n.desc.Indexes { if indexName == sqlbase.NormalizeName(n.desc.Indexes[i].Name) { n.specifiedIndex = &n.desc.Indexes[i] break } } if n.specifiedIndex == nil { return "", fmt.Errorf("index \"%s\" not found", indexName) } } } n.noIndexJoin = (indexHints != nil && indexHints.NoIndexJoin) n.initDescDefaults() return alias, nil }
// RenameIndex renames the index. // Privileges: CREATE on table. // notes: postgres requires CREATE on the table. // mysql requires ALTER, CREATE, INSERT on the table. func (p *planner) RenameIndex(n *parser.RenameIndex) (planNode, error) { tn, err := n.Index.Table.NormalizeWithDatabaseName(p.session.Database) if err != nil { return nil, err } tableDesc, err := p.mustGetTableDesc(tn) if err != nil { return nil, err } normIdxName := sqlbase.NormalizeName(n.Index.Index) status, i, err := tableDesc.FindIndexByNormalizedName(normIdxName) if err != nil { if n.IfExists { // Noop. return &emptyNode{}, nil } // Index does not exist, but we want it to: error out. return nil, err } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } if n.NewName == "" { return nil, errEmptyIndexName } normNewIdxName := sqlbase.NormalizeName(n.NewName) if normIdxName == normNewIdxName { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindIndexByNormalizedName(normNewIdxName); err == nil { return nil, fmt.Errorf("index name %q already exists", n.NewName) } if status == sqlbase.DescriptorActive { tableDesc.Indexes[i].Name = normNewIdxName } else { tableDesc.Mutations[i].GetIndex().Name = normNewIdxName } if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(p.txn); err != nil { return nil, err } if err := p.txn.Put(descKey, sqlbase.WrapDescriptor(tableDesc)); err != nil { return nil, err } p.notifySchemaChange(tableDesc.ID, sqlbase.InvalidMutationID) return &emptyNode{}, nil }
// Set sets session variables. // Privileges: None. // Notes: postgres/mysql do not require privileges for session variables (some exceptions). func (p *planner) Set(n *parser.Set) (planNode, error) { if n.Name == nil { // A client has sent the reserved internal syntax SET ROW ... // Reject it. return nil, errors.New("invalid statement: SET ROW") } // By using QualifiedName.String() here any variables that are keywords will // be double quoted. name := strings.ToUpper(n.Name.String()) typedValues := make([]parser.TypedExpr, len(n.Values)) for i, expr := range n.Values { typedValue, err := parser.TypeCheck(expr, nil, parser.TypeString) if err != nil { return nil, err } typedValues[i] = typedValue } switch name { case `DATABASE`: dbName, err := p.getStringVal(name, typedValues) if err != nil { return nil, err } if len(dbName) != 0 { // Verify database descriptor exists. dbDesc, err := p.getDatabaseDesc(dbName) if err != nil { return nil, err } if dbDesc == nil { return nil, sqlbase.NewUndefinedDatabaseError(dbName) } } p.session.Database = dbName case `SYNTAX`: s, err := p.getStringVal(name, typedValues) if err != nil { return nil, err } switch sqlbase.NormalizeName(s) { case sqlbase.NormalizeName(parser.Modern.String()): p.session.Syntax = int32(parser.Modern) case sqlbase.NormalizeName(parser.Traditional.String()): p.session.Syntax = int32(parser.Traditional) default: return nil, fmt.Errorf("%s: \"%s\" is not in (%q, %q)", name, s, parser.Modern, parser.Traditional) } case `EXTRA_FLOAT_DIGITS`: // These settings are sent by the JDBC driver but we silently ignore them. default: return nil, fmt.Errorf("unknown variable: %q", name) } return &emptyNode{}, nil }
// getTableLease implements the SchemaAccessor interface. func (p *planner) getTableLease(qname *parser.QualifiedName) (*sqlbase.TableDescriptor, error) { if log.V(2) { log.Infof("planner acquiring lease on table %q", qname) } if err := qname.NormalizeTableName(p.session.Database); err != nil { return nil, err } if qname.Database() == sqlbase.SystemDB.Name || testDisableTableLeases { // We don't go through the normal lease mechanism for system tables. The // system.lease and system.descriptor table, in particular, are problematic // because they are used for acquiring leases itself, creating a // chicken&egg problem. return p.mustGetTableDesc(qname) } dbID, err := p.getDatabaseID(qname.Database()) if err != nil { return nil, err } // First, look to see if we already have a lease for this table. // This ensures that, once a SQL transaction resolved name N to id X, it will // continue to use N to refer to X even if N is renamed during the // transaction. var lease *LeaseState for _, l := range p.leases { if sqlbase.NormalizeName(l.Name) == sqlbase.NormalizeName(qname.Table()) && l.ParentID == dbID { lease = l if log.V(2) { log.Infof("found lease in planner cache for table %q", qname) } break } } // If we didn't find a lease or the lease is about to expire, acquire one. if lease == nil || p.removeLeaseIfExpiring(lease) { var err error lease, err = p.leaseMgr.AcquireByName(p.txn, dbID, qname.Table()) if err != nil { if err == errDescriptorNotFound { // Transform the descriptor error into an error that references the // table's name. return nil, sqlbase.NewUndefinedTableError(qname.String()) } return nil, err } p.leases = append(p.leases, lease) // If the lease we just acquired expires before the txn's deadline, reduce // the deadline. p.txn.UpdateDeadlineMaybe(hlc.Timestamp{WallTime: lease.Expiration().UnixNano()}) } return &lease.TableDescriptor, nil }
// Initializes a scanNode with a tableName. Returns the table or index name that can be used for // fully-qualified columns if an alias is not specified. func (n *scanNode) initTable( p *planner, tableName *parser.QualifiedName, indexHints *parser.IndexHints, scanVisibility scanVisibility, ) (string, error) { var err error // AS OF SYSTEM TIME queries need to fetch the table descriptor at the // specified time, and never lease anything. The proto transaction already // has its timestamps set correctly so getTableDesc will fetch with the // correct timestamp. if p.asOf { desc, err := p.getTableDesc(tableName) if err != nil { return "", err } if desc == nil { return "", sqlbase.NewUndefinedTableError(tableName.String()) } n.desc = *desc } else { n.desc, err = p.getTableLease(tableName) } if err != nil { return "", err } if err := p.checkPrivilege(&n.desc, privilege.SELECT); err != nil { return "", err } alias := n.desc.Name if indexHints != nil && indexHints.Index != "" { indexName := sqlbase.NormalizeName(string(indexHints.Index)) if indexName == sqlbase.NormalizeName(n.desc.PrimaryIndex.Name) { n.specifiedIndex = &n.desc.PrimaryIndex } else { for i := range n.desc.Indexes { if indexName == sqlbase.NormalizeName(n.desc.Indexes[i].Name) { n.specifiedIndex = &n.desc.Indexes[i] break } } if n.specifiedIndex == nil { return "", fmt.Errorf("index \"%s\" not found", indexName) } } } n.noIndexJoin = (indexHints != nil && indexHints.NoIndexJoin) n.initDescDefaults(scanVisibility) return alias, nil }
func queryNamespace(conn *sqlConn, parentID sqlbase.ID, name string) (sqlbase.ID, error) { rows, err := makeQuery( `SELECT id FROM system.namespace WHERE parentID = $1 AND name = $2`, parentID, sqlbase.NormalizeName(name))(conn) if err != nil { return 0, err } defer func() { _ = rows.Close() }() if err != nil { return 0, fmt.Errorf("%s not found: %v", name, err) } if len(rows.Columns()) != 1 { return 0, fmt.Errorf("unexpected result columns: %d", len(rows.Columns())) } vals := make([]driver.Value, 1) if err := rows.Next(vals); err != nil { return 0, err } switch t := vals[0].(type) { case int64: return sqlbase.ID(t), nil default: return 0, fmt.Errorf("unexpected result type: %T", vals[0]) } }
// upsertExprsAndIndex returns the upsert conflict index and the (possibly // synthetic) SET expressions used when a row conflicts. func upsertExprsAndIndex( tableDesc *sqlbase.TableDescriptor, onConflict parser.OnConflict, insertCols []sqlbase.ColumnDescriptor, ) (parser.UpdateExprs, *sqlbase.IndexDescriptor, error) { if onConflict.IsUpsertAlias() { // The UPSERT syntactic sugar is the same as the longhand specifying the // primary index as the conflict index and SET expressions for the columns // in insertCols minus any columns in the conflict index. Example: // `UPSERT INTO abc VALUES (1, 2, 3)` is syntactic sugar for // `INSERT INTO abc VALUES (1, 2, 3) ON CONFLICT a DO UPDATE SET b = 2, c = 3`. conflictIndex := &tableDesc.PrimaryIndex indexColSet := make(map[sqlbase.ColumnID]struct{}, len(conflictIndex.ColumnIDs)) for _, colID := range conflictIndex.ColumnIDs { indexColSet[colID] = struct{}{} } updateExprs := make(parser.UpdateExprs, 0, len(insertCols)) for _, c := range insertCols { if _, ok := indexColSet[c.ID]; !ok { names := parser.UnresolvedNames{ parser.UnresolvedName{parser.Name(c.Name)}, } expr := &parser.ColumnItem{ TableName: upsertExcludedTable, ColumnName: parser.Name(c.Name), } updateExprs = append(updateExprs, &parser.UpdateExpr{Names: names, Expr: expr}) } } return updateExprs, conflictIndex, nil } indexMatch := func(index sqlbase.IndexDescriptor) bool { if !index.Unique { return false } if len(index.ColumnNames) != len(onConflict.Columns) { return false } for i, colName := range index.ColumnNames { if sqlbase.ReNormalizeName(colName) != sqlbase.NormalizeName(onConflict.Columns[i]) { return false } } return true } if indexMatch(tableDesc.PrimaryIndex) { return onConflict.Exprs, &tableDesc.PrimaryIndex, nil } for _, index := range tableDesc.Indexes { if indexMatch(index) { return onConflict.Exprs, &index, nil } } return nil, nil, fmt.Errorf("there is no unique or exclusion constraint matching the ON CONFLICT specification") }
// getVirtualTableEntry checks if the provided name matches a virtual database/table // pair. The function will return the table's virtual table entry if the name matches // a specific table. It will return an error if the name references a virtual database // but the table is non-existent. func getVirtualTableEntry(tn *parser.TableName) (virtualTableEntry, error) { if db, ok := getVirtualSchemaEntry(tn.Database()); ok { if t, ok := db.tables[sqlbase.NormalizeName(tn.TableName)]; ok { return t, nil } return virtualTableEntry{}, sqlbase.NewUndefinedTableError(tn.String()) } return virtualTableEntry{}, nil }
// 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 }
// Initializes a scanNode with a tableName. Returns the table or index name that can be used for // fully-qualified columns if an alias is not specified. func (n *scanNode) initTable( p *planner, tableName *parser.TableName, indexHints *parser.IndexHints, scanVisibility scanVisibility, ) error { descFunc := p.getTableLease if p.asOf { // AS OF SYSTEM TIME queries need to fetch the table descriptor at the // specified time, and never lease anything. The proto transaction already // has its timestamps set correctly so mustGetTableDesc will fetch with the // correct timestamp. descFunc = p.mustGetTableDesc } desc, err := descFunc(tableName) if err != nil { return err } n.desc = *desc if err := p.checkPrivilege(&n.desc, privilege.SELECT); err != nil { return err } if indexHints != nil && indexHints.Index != "" { indexName := sqlbase.NormalizeName(indexHints.Index) if indexName == sqlbase.ReNormalizeName(n.desc.PrimaryIndex.Name) { n.specifiedIndex = &n.desc.PrimaryIndex } else { for i := range n.desc.Indexes { if indexName == sqlbase.ReNormalizeName(n.desc.Indexes[i].Name) { n.specifiedIndex = &n.desc.Indexes[i] break } } if n.specifiedIndex == nil { return fmt.Errorf("index \"%s\" not found", indexName) } } } n.noIndexJoin = (indexHints != nil && indexHints.NoIndexJoin) n.initDescDefaults(scanVisibility) return nil }
func (p *planner) makeUpsertHelper( tn *parser.TableName, tableDesc *sqlbase.TableDescriptor, insertCols []sqlbase.ColumnDescriptor, updateCols []sqlbase.ColumnDescriptor, updateExprs parser.UpdateExprs, upsertConflictIndex *sqlbase.IndexDescriptor, ) (*upsertHelper, error) { defaultExprs, err := makeDefaultExprs(updateCols, &p.parser, &p.evalCtx) if err != nil { return nil, err } untupledExprs := make(parser.Exprs, 0, len(updateExprs)) i := 0 for _, updateExpr := range updateExprs { if updateExpr.Tuple { if t, ok := updateExpr.Expr.(*parser.Tuple); ok { for _, e := range t.Exprs { typ := updateCols[i].Type.ToDatumType() e := fillDefault(e, typ, i, defaultExprs) untupledExprs = append(untupledExprs, e) i++ } } } else { typ := updateCols[i].Type.ToDatumType() e := fillDefault(updateExpr.Expr, typ, i, defaultExprs) untupledExprs = append(untupledExprs, e) i++ } } sourceInfo := newSourceInfoForSingleTable(*tn, makeResultColumns(tableDesc.Columns)) excludedSourceInfo := newSourceInfoForSingleTable(upsertExcludedTable, makeResultColumns(insertCols)) var evalExprs []parser.TypedExpr qvals := make(qvalMap) sources := multiSourceInfo{sourceInfo, excludedSourceInfo} for _, expr := range untupledExprs { normExpr, err := p.analyzeExpr(expr, sources, qvals, parser.NoTypePreference, false, "") if err != nil { return nil, err } evalExprs = append(evalExprs, normExpr) } allExprsIdentity := true for i, expr := range evalExprs { // analyzeExpr above has normalized all direct column names to ColumnItems. c, ok := expr.(*parser.ColumnItem) if !ok { allExprsIdentity = false break } if len(c.Selector) > 0 || !sqlbase.EqualName(c.TableName.TableName, upsertExcludedTable.TableName) || sqlbase.NormalizeName(c.ColumnName) != sqlbase.ReNormalizeName(updateCols[i].Name) { allExprsIdentity = false break } } helper := &upsertHelper{ p: p, qvals: qvals, evalExprs: evalExprs, sourceInfo: sourceInfo, excludedSourceInfo: excludedSourceInfo, allExprsIdentity: allExprsIdentity, } return helper, nil }
func nameMatchesLease(lease *LeaseState, dbID sqlbase.ID, tableName string) bool { return lease.ParentID == dbID && sqlbase.NormalizeName(lease.Name) == sqlbase.NormalizeName(tableName) }
func (c *tableNameCache) makeCacheKey(dbID sqlbase.ID, tableName string) tableNameCacheKey { return tableNameCacheKey{dbID, sqlbase.NormalizeName(tableName)} }
// RenameColumn renames the column. // Privileges: CREATE on table. // notes: postgres requires CREATE on the table. // mysql requires ALTER, CREATE, INSERT on the table. func (p *planner) RenameColumn(n *parser.RenameColumn) (planNode, error) { // Check if table exists. tn, err := n.Table.NormalizeWithDatabaseName(p.session.Database) if err != nil { return nil, err } tableDesc, err := p.getTableDesc(tn) if err != nil { return nil, err } if tableDesc == nil { if n.IfExists { // Noop. return &emptyNode{}, nil } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", tn.Table()) } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } if n.NewName == "" { return nil, errEmptyColumnName } normNewColName := sqlbase.NormalizeName(n.NewName) normColName := sqlbase.NormalizeName(n.Name) status, i, err := tableDesc.FindColumnByNormalizedName(normColName) // n.IfExists only applies to table, no need to check here. if err != nil { return nil, err } var column *sqlbase.ColumnDescriptor if status == sqlbase.DescriptorActive { column = &tableDesc.Columns[i] } else { column = tableDesc.Mutations[i].GetColumn() } if normColName == normNewColName { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindColumnByNormalizedName(normNewColName); err == nil { return nil, fmt.Errorf("column name %q already exists", n.NewName) } preFn := func(expr parser.Expr) (err error, recurse bool, newExpr parser.Expr) { if vBase, ok := expr.(parser.VarName); ok { v, err := vBase.NormalizeVarName() if err != nil { return err, false, nil } if c, ok := v.(*parser.ColumnItem); ok { if sqlbase.NormalizeName(c.ColumnName) == normColName { c.ColumnName = n.NewName } } return nil, false, v } return nil, true, expr } exprStrings := make([]string, len(tableDesc.Checks)) for i, check := range tableDesc.Checks { exprStrings[i] = check.Expr } exprs, err := parser.ParseExprsTraditional(exprStrings) if err != nil { return nil, err } for i := range tableDesc.Checks { expr, err := parser.SimpleVisit(exprs[i], preFn) if err != nil { return nil, err } if after := expr.String(); after != tableDesc.Checks[i].Expr { tableDesc.Checks[i].Expr = after } } // Rename the column in the indexes. tableDesc.RenameColumnNormalized(column.ID, normNewColName) column.Name = normNewColName if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(p.txn); err != nil { return nil, err } if err := p.txn.Put(descKey, sqlbase.WrapDescriptor(tableDesc)); err != nil { return nil, err } p.notifySchemaChange(tableDesc.ID, sqlbase.InvalidMutationID) return &emptyNode{}, nil }
// orderBy constructs a sortNode based on the ORDER BY clause. // // In the general case (SELECT/UNION/VALUES), we can sort by a column index or a // column name. // // However, for a SELECT, we can also sort by the pre-alias column name (SELECT // a AS b ORDER BY b) as well as expressions (SELECT a, b, ORDER BY a+b). In // this case, construction of the sortNode might adjust the number of render // targets in the selectNode if any ordering expressions are specified. // // TODO(dan): SQL also allows sorting a VALUES or UNION by an expression. // Support this. It will reduce some of the special casing below, but requires a // generalization of how to add derived columns to a SelectStatement. func (p *planner) orderBy(orderBy parser.OrderBy, n planNode) (*sortNode, error) { if orderBy == nil { return nil, nil } // We grab a copy of columns here because we might add new render targets // below. This is the set of columns requested by the query. columns := n.Columns() numOriginalCols := len(columns) if s, ok := n.(*selectNode); ok { numOriginalCols = s.numOriginalCols } var ordering columnOrdering for _, o := range orderBy { index := -1 // Unwrap parenthesized expressions like "((a))" to "a". expr := o.Expr for { if paren, ok := expr.(*parser.ParenExpr); ok { expr = paren.Expr } else { break } } if qname, ok := expr.(*parser.QualifiedName); ok { if len(qname.Indirect) == 0 { // Look for an output column that matches the qualified name. This // handles cases like: // // SELECT a AS b FROM t ORDER BY b target := sqlbase.NormalizeName(string(qname.Base)) for j, col := range columns { if sqlbase.NormalizeName(col.Name) == target { index = j break } } } if s, ok := n.(*selectNode); ok && index == -1 { // No output column matched the qualified name, so look for an existing // render target that matches the column name. This handles cases like: // // SELECT a AS b FROM t ORDER BY a if err := qname.NormalizeColumnName(); err != nil { return nil, err } if qname.Table() == "" || sqlbase.EqualName(s.source.info.alias, qname.Table()) { qnameCol := sqlbase.NormalizeName(qname.Column()) for j, r := range s.render { if qval, ok := r.(*qvalue); ok { if sqlbase.NormalizeName(qval.colRef.get().Name) == qnameCol { index = j break } } } } } } if index == -1 { // The order by expression matched neither an output column nor an // existing render target. if col, err := colIndex(numOriginalCols, expr); err != nil { return nil, err } else if col >= 0 { index = col } else if s, ok := n.(*selectNode); ok { // TODO(dan): Once we support VALUES (1), (2) ORDER BY 3*4, this type // check goes away. // Add a new render expression to use for ordering. This handles cases // were the expression is either not a qualified name or is a qualified // name that is otherwise not referenced by the query: // // SELECT a FROM t ORDER by b // SELECT a, b FROM t ORDER by a+b if err := s.addRender(parser.SelectExpr{Expr: expr}, nil); err != nil { return nil, err } index = len(s.columns) - 1 } else { return nil, util.Errorf("column %s does not exist", expr) } } direction := encoding.Ascending if o.Direction == parser.Descending { direction = encoding.Descending } ordering = append(ordering, columnOrderInfo{index, direction}) } return &sortNode{columns: columns, ordering: ordering}, 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 }
// getTableLease implements the SchemaAccessor interface. func (p *planner) getTableLease(tn *parser.TableName) (*sqlbase.TableDescriptor, error) { if log.V(2) { log.Infof(p.ctx(), "planner acquiring lease on table %s", tn) } isSystemDB := tn.Database() == sqlbase.SystemDB.Name isVirtualDB := isVirtualDatabase(tn.Database()) if isSystemDB || isVirtualDB || testDisableTableLeases { // We don't go through the normal lease mechanism for: // - system tables. The system.lease and system.descriptor table, in // particular, are problematic because they are used for acquiring // leases itself, creating a chicken&egg problem. // - virtual tables. These tables' descriptors are not persisted, // so they cannot be leased. Instead, we simply return the static // descriptor and rely on the immutability privileges set on the // descriptors to cause upper layers to reject mutations statements. tbl, err := p.mustGetTableDesc(tn) if err != nil { return nil, err } if err := filterTableState(tbl); err != nil { return nil, err } return tbl, nil } dbID, err := p.getDatabaseID(tn.Database()) if err != nil { return nil, err } // First, look to see if we already have a lease for this table. // This ensures that, once a SQL transaction resolved name N to id X, it will // continue to use N to refer to X even if N is renamed during the // transaction. var lease *LeaseState for _, l := range p.leases { if sqlbase.ReNormalizeName(l.Name) == sqlbase.NormalizeName(tn.TableName) && l.ParentID == dbID { lease = l if log.V(2) { log.Infof(p.ctx(), "found lease in planner cache for table %q", tn) } break } } // If we didn't find a lease or the lease is about to expire, acquire one. if lease == nil || p.removeLeaseIfExpiring(lease) { var err error lease, err = p.leaseMgr.AcquireByName(p.txn, dbID, tn.Table()) if err != nil { if err == sqlbase.ErrDescriptorNotFound { // Transform the descriptor error into an error that references the // table's name. return nil, sqlbase.NewUndefinedTableError(tn.String()) } return nil, err } p.leases = append(p.leases, lease) // If the lease we just acquired expires before the txn's deadline, reduce // the deadline. p.txn.UpdateDeadlineMaybe(hlc.Timestamp{WallTime: lease.Expiration().UnixNano()}) } return &lease.TableDescriptor, nil }
// getDataSource builds a planDataSource from a single data source clause // (TableExpr) in a SelectClause. func (p *planner) getDataSource( src parser.TableExpr, hints *parser.IndexHints, scanVisibility scanVisibility, ) (planDataSource, error) { switch t := src.(type) { case *parser.NormalizableTableName: // Usual case: a table. tn, err := t.NormalizeWithDatabaseName(p.session.Database) if err != nil { return planDataSource{}, err } // Is this perhaps a name for a virtual table? ds, foundVirtual, err := p.getVirtualDataSource(tn) if err != nil { return planDataSource{}, err } if foundVirtual { return ds, nil } // This name designates a real table. scan := p.Scan() if err := scan.initTable(p, tn, hints, scanVisibility); err != nil { return planDataSource{}, err } return planDataSource{ info: newSourceInfoForSingleTable(*tn, scan.Columns()), plan: scan, }, nil case *parser.Subquery: // We have a subquery (this includes a simple "VALUES"). plan, err := p.newPlan(t.Select, nil, false) if err != nil { return planDataSource{}, err } return planDataSource{ info: newSourceInfoForSingleTable(parser.TableName{}, plan.Columns()), plan: plan, }, nil case *parser.JoinTableExpr: // Joins: two sources. left, err := p.getDataSource(t.Left, nil, scanVisibility) if err != nil { return left, err } right, err := p.getDataSource(t.Right, nil, scanVisibility) if err != nil { return right, err } return p.makeJoin(t.Join, left, right, t.Cond) case *parser.ParenTableExpr: return p.getDataSource(t.Expr, hints, scanVisibility) case *parser.AliasedTableExpr: // Alias clause: source AS alias(cols...) src, err := p.getDataSource(t.Expr, t.Hints, scanVisibility) if err != nil { return src, err } var tableAlias parser.TableName if t.As.Alias != "" { // If an alias was specified, use that. tableAlias.TableName = parser.Name(sqlbase.NormalizeName(t.As.Alias)) src.info.sourceAliases = sourceAliases{ tableAlias: fillColumnRange(0, len(src.info.sourceColumns)-1), } } colAlias := t.As.Cols if len(colAlias) > 0 { // Make a copy of the slice since we are about to modify the contents. src.info.sourceColumns = append([]ResultColumn(nil), src.info.sourceColumns...) // The column aliases can only refer to explicit columns. for colIdx, aliasIdx := 0, 0; aliasIdx < len(colAlias); colIdx++ { if colIdx >= len(src.info.sourceColumns) { var srcName string if tableAlias.DatabaseName != "" { srcName = tableAlias.String() } else { srcName = tableAlias.TableName.String() } return planDataSource{}, errors.Errorf( "source %q has %d columns available but %d columns specified", srcName, aliasIdx, len(colAlias)) } if src.info.sourceColumns[colIdx].hidden { continue } src.info.sourceColumns[colIdx].Name = string(colAlias[aliasIdx]) aliasIdx++ } } return src, nil default: return planDataSource{}, errors.Errorf("unsupported FROM type %T", src) } }
// orderBy constructs a sortNode based on the ORDER BY clause. // // In the general case (SELECT/UNION/VALUES), we can sort by a column index or a // column name. // // However, for a SELECT, we can also sort by the pre-alias column name (SELECT // a AS b ORDER BY b) as well as expressions (SELECT a, b, ORDER BY a+b). In // this case, construction of the sortNode might adjust the number of render // targets in the selectNode if any ordering expressions are specified. // // TODO(dan): SQL also allows sorting a VALUES or UNION by an expression. // Support this. It will reduce some of the special casing below, but requires a // generalization of how to add derived columns to a SelectStatement. func (p *planner) orderBy(orderBy parser.OrderBy, n planNode) (*sortNode, error) { if orderBy == nil { return nil, nil } // We grab a copy of columns here because we might add new render targets // below. This is the set of columns requested by the query. columns := n.Columns() numOriginalCols := len(columns) if s, ok := n.(*selectNode); ok { numOriginalCols = s.numOriginalCols } var ordering sqlbase.ColumnOrdering for _, o := range orderBy { index := -1 // Unwrap parenthesized expressions like "((a))" to "a". expr := parser.StripParens(o.Expr) if vBase, ok := expr.(parser.VarName); ok { v, err := vBase.NormalizeVarName() if err != nil { return nil, err } var c *parser.ColumnItem switch t := v.(type) { case *parser.ColumnItem: c = t default: return nil, fmt.Errorf("invalid syntax for ORDER BY: %s", v) } if c.TableName.Table() == "" { // Look for an output column that matches the name. This // handles cases like: // // SELECT a AS b FROM t ORDER BY b target := sqlbase.NormalizeName(c.ColumnName) for j, col := range columns { if sqlbase.ReNormalizeName(col.Name) == target { index = j break } } } if s, ok := n.(*selectNode); ok && index == -1 { // No output column matched the name, so look for an existing // render target that matches the column name. This handles cases like: // // SELECT a AS b FROM t ORDER BY a colIdx, err := s.source.findUnaliasedColumn(c) if err != nil { return nil, err } if colIdx != invalidColIdx { for j, r := range s.render { if qval, ok := r.(*qvalue); ok { if qval.colRef.source == s.source.info && qval.colRef.colIdx == colIdx { index = j break } } } } } } if index == -1 { // The order by expression matched neither an output column nor an // existing render target. if col, err := colIndex(numOriginalCols, expr); err != nil { return nil, err } else if col >= 0 { index = col } else if s, ok := n.(*selectNode); ok { // TODO(dan): Once we support VALUES (1), (2) ORDER BY 3*4, this type // check goes away. // Add a new render expression to use for ordering. This // handles cases were the expression is either not a name or // is a name that is otherwise not referenced by the query: // // SELECT a FROM t ORDER by b // SELECT a, b FROM t ORDER by a+b if err := s.addRender(parser.SelectExpr{Expr: expr}, nil); err != nil { return nil, err } index = len(s.columns) - 1 } else { return nil, errors.Errorf("column %s does not exist", expr) } } direction := encoding.Ascending if o.Direction == parser.Descending { direction = encoding.Descending } ordering = append(ordering, sqlbase.ColumnOrderInfo{ColIdx: index, Direction: direction}) } return &sortNode{ctx: p.ctx(), columns: columns, ordering: ordering}, nil }