// 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 }
// 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 }
// 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) { newIdxName := string(n.NewName) if newIdxName == "" { return nil, errEmptyIndexName } if err := n.Index.Table.NormalizeTableName(p.session.Database); err != nil { return nil, err } tableDesc, err := p.mustGetTableDesc(n.Index.Table) if err != nil { return nil, err } idxName := string(n.Index.Index) status, i, err := tableDesc.FindIndexByName(idxName) 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 sqlbase.EqualName(idxName, newIdxName) { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindIndexByName(newIdxName); err == nil { return nil, fmt.Errorf("index name %q already exists", n.NewName) } if status == sqlbase.DescriptorActive { tableDesc.Indexes[i].Name = newIdxName } else { tableDesc.Mutations[i].GetIndex().Name = newIdxName } if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(); 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 }
// checkRenderStar checks if the SelectExpr is a QualifiedName with a StarIndirection suffix. If so, // we match the prefix of the qualified name to one of the tables in the query and then expand the // "*" into a list of columns. The qvalMap is updated to include all the relevant columns. A // ResultColumns and Expr pair is returned for each column. func checkRenderStar( target parser.SelectExpr, table *tableInfo, qvals qvalMap, ) (isStar bool, columns []ResultColumn, exprs []parser.TypedExpr, err error) { qname, ok := target.Expr.(*parser.QualifiedName) if !ok { return false, nil, nil, nil } if err := qname.NormalizeColumnName(); err != nil { return false, nil, nil, err } if !qname.IsStar() { return false, nil, nil, nil } if table.alias == "" { return false, nil, nil, fmt.Errorf("\"%s\" with no tables specified is not valid", qname) } if target.As != "" { return false, nil, nil, fmt.Errorf("\"%s\" cannot be aliased", qname) } // TODO(radu): support multiple FROMs, consolidate with logic in findColumn if tableName := qname.Table(); tableName != "" && !sqlbase.EqualName(table.alias, tableName) { return false, nil, nil, fmt.Errorf("table \"%s\" not found", tableName) } for idx, col := range table.columns { if col.hidden { continue } qval := qvals.getQVal(columnRef{table, idx}) columns = append(columns, ResultColumn{Name: col.Name, Typ: qval.datum}) exprs = append(exprs, qval) } return true, columns, exprs, nil }
// 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) { newColName := string(n.NewName) if newColName == "" { return nil, errEmptyColumnName } if err := n.Table.NormalizeTableName(p.session.Database); err != nil { return nil, err } dbDesc, err := p.getDatabaseDesc(n.Table.Database()) if err != nil { return nil, err } if dbDesc == nil { return nil, databaseDoesNotExistError(n.Table.Database()) } // Check if table exists. tbKey := tableKey{dbDesc.ID, n.Table.Table()}.Key() gr, err := p.txn.Get(tbKey) if err != nil { return nil, err } if !gr.Exists() { 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", n.Table.Table()) } tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } if tableDesc == nil { return nil, tableDoesNotExistError(n.Table.String()) } colName := string(n.Name) status, i, err := tableDesc.FindColumnByName(colName) // 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 err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } if sqlbase.EqualName(colName, newColName) { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindColumnByName(newColName); err == nil { return nil, fmt.Errorf("column name %q already exists", newColName) } // Rename the column in the indexes. renameColumnInIndex := func(idx *sqlbase.IndexDescriptor) { for i, id := range idx.ColumnIDs { if id == column.ID { idx.ColumnNames[i] = newColName } } } for i := range tableDesc.Indexes { renameColumnInIndex(&tableDesc.Indexes[i]) } for _, m := range tableDesc.Mutations { if idx := m.GetIndex(); idx != nil { renameColumnInIndex(idx) } } column.Name = newColName if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(); 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 }
// 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) { newColName := string(n.NewName) if newColName == "" { return nil, errEmptyColumnName } if err := n.Table.NormalizeTableName(p.session.Database); err != nil { return nil, err } dbDesc, err := p.getDatabaseDesc(n.Table.Database()) if err != nil { return nil, err } if dbDesc == nil { return nil, sqlbase.NewUndefinedDatabaseError(n.Table.Database()) } // Check if table exists. tbKey := tableKey{dbDesc.ID, n.Table.Table()}.Key() gr, err := p.txn.Get(tbKey) if err != nil { return nil, err } if !gr.Exists() { 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", n.Table.Table()) } tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } if tableDesc == nil { return nil, sqlbase.NewUndefinedTableError(n.Table.String()) } colName := string(n.Name) status, i, err := tableDesc.FindColumnByName(colName) // 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 err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } if sqlbase.EqualName(colName, newColName) { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindColumnByName(newColName); err == nil { return nil, fmt.Errorf("column name %q already exists", newColName) } preFn := func(expr parser.Expr) (err error, recurse bool, newExpr parser.Expr) { if qname, ok := expr.(*parser.QualifiedName); ok { if err := qname.NormalizeColumnName(); err != nil { return err, false, nil } if qname.Column() == colName { qname.Indirect[0] = parser.NameIndirection(newColName) qname.ClearString() } return nil, false, qname } 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.RenameColumn(column.ID, newColName) column.Name = newColName if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(); 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 }
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 }