github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rename_index.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql 12 13 import ( 14 "context" 15 "fmt" 16 17 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 18 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 19 "github.com/cockroachdb/cockroach/pkg/sql/privilege" 20 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 21 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 22 ) 23 24 var errEmptyIndexName = pgerror.New(pgcode.Syntax, "empty index name") 25 26 type renameIndexNode struct { 27 n *tree.RenameIndex 28 tableDesc *sqlbase.MutableTableDescriptor 29 idx *sqlbase.IndexDescriptor 30 } 31 32 // RenameIndex renames the index. 33 // Privileges: CREATE on table. 34 // notes: postgres requires CREATE on the table. 35 // mysql requires ALTER, CREATE, INSERT on the table. 36 func (p *planner) RenameIndex(ctx context.Context, n *tree.RenameIndex) (planNode, error) { 37 _, tableDesc, err := expandMutableIndexName(ctx, p, n.Index, !n.IfExists /* requireTable */) 38 if err != nil { 39 return nil, err 40 } 41 if tableDesc == nil { 42 // IfExists specified and table did not exist -- noop. 43 return newZeroNode(nil /* columns */), nil 44 } 45 46 idx, _, err := tableDesc.FindIndexByName(string(n.Index.Index)) 47 if err != nil { 48 if n.IfExists { 49 // Noop. 50 return newZeroNode(nil /* columns */), nil 51 } 52 // Index does not exist, but we want it to: error out. 53 return nil, err 54 } 55 56 if err := p.CheckPrivilege(ctx, tableDesc, privilege.CREATE); err != nil { 57 return nil, err 58 } 59 60 return &renameIndexNode{n: n, idx: idx, tableDesc: tableDesc}, nil 61 } 62 63 // ReadingOwnWrites implements the planNodeReadingOwnWrites interface. 64 // This is because RENAME DATABASE performs multiple KV operations on descriptors 65 // and expects to see its own writes. 66 func (n *renameIndexNode) ReadingOwnWrites() {} 67 68 func (n *renameIndexNode) startExec(params runParams) error { 69 p := params.p 70 ctx := params.ctx 71 tableDesc := n.tableDesc 72 idx := n.idx 73 74 for _, tableRef := range tableDesc.DependedOnBy { 75 if tableRef.IndexID != idx.ID { 76 continue 77 } 78 return p.dependentViewRenameError( 79 ctx, "index", n.n.Index.Index.String(), tableDesc.ParentID, tableRef.ID) 80 } 81 82 if n.n.NewName == "" { 83 return errEmptyIndexName 84 } 85 86 if n.n.Index.Index == n.n.NewName { 87 // Noop. 88 return nil 89 } 90 91 if _, _, err := tableDesc.FindIndexByName(string(n.n.NewName)); err == nil { 92 return fmt.Errorf("index name %q already exists", string(n.n.NewName)) 93 } 94 95 if err := tableDesc.RenameIndexDescriptor(idx, string(n.n.NewName)); err != nil { 96 return err 97 } 98 99 if err := tableDesc.Validate(ctx, p.txn, p.ExecCfg().Codec); err != nil { 100 return err 101 } 102 103 return p.writeSchemaChange( 104 ctx, tableDesc, sqlbase.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann())) 105 } 106 107 func (n *renameIndexNode) Next(runParams) (bool, error) { return false, nil } 108 func (n *renameIndexNode) Values() tree.Datums { return tree.Datums{} } 109 func (n *renameIndexNode) Close(context.Context) {}