github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rename_column.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 16 "github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver" 17 "github.com/cockroachdb/cockroach/pkg/sql/parser" 18 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 19 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 20 "github.com/cockroachdb/cockroach/pkg/sql/privilege" 21 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 22 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 23 "github.com/cockroachdb/errors" 24 ) 25 26 var errEmptyColumnName = pgerror.New(pgcode.Syntax, "empty column name") 27 28 type renameColumnNode struct { 29 n *tree.RenameColumn 30 tableDesc *sqlbase.MutableTableDescriptor 31 } 32 33 // RenameColumn renames the column. 34 // Privileges: CREATE on table. 35 // notes: postgres requires CREATE on the table. 36 // mysql requires ALTER, CREATE, INSERT on the table. 37 func (p *planner) RenameColumn(ctx context.Context, n *tree.RenameColumn) (planNode, error) { 38 // Check if table exists. 39 tableDesc, err := p.ResolveMutableTableDescriptor(ctx, &n.Table, !n.IfExists, resolver.ResolveRequireTableDesc) 40 if err != nil { 41 return nil, err 42 } 43 if tableDesc == nil { 44 return newZeroNode(nil /* columns */), nil 45 } 46 47 if err := p.CheckPrivilege(ctx, tableDesc, privilege.CREATE); err != nil { 48 return nil, err 49 } 50 51 return &renameColumnNode{n: n, tableDesc: tableDesc}, nil 52 } 53 54 // ReadingOwnWrites implements the planNodeReadingOwnWrites interface. 55 // This is because RENAME COLUMN performs multiple KV operations on descriptors 56 // and expects to see its own writes. 57 func (n *renameColumnNode) ReadingOwnWrites() {} 58 59 func (n *renameColumnNode) startExec(params runParams) error { 60 p := params.p 61 ctx := params.ctx 62 tableDesc := n.tableDesc 63 64 const allowRenameOfShardColumn = false 65 descChanged, err := params.p.renameColumn(params.ctx, tableDesc, &n.n.Name, 66 &n.n.NewName, allowRenameOfShardColumn) 67 if err != nil { 68 return err 69 } 70 71 if !descChanged { 72 return nil 73 } 74 75 if err := tableDesc.Validate(ctx, p.txn, p.ExecCfg().Codec); err != nil { 76 return err 77 } 78 79 return p.writeSchemaChange( 80 ctx, tableDesc, sqlbase.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann())) 81 } 82 83 // renameColumn will rename the column in tableDesc from oldName to newName. 84 // If allowRenameOfShardColumn is false, this method will return an error if 85 // the column being renamed is a generated column for a hash sharded index. 86 func (p *planner) renameColumn( 87 ctx context.Context, 88 tableDesc *sqlbase.MutableTableDescriptor, 89 oldName, newName *tree.Name, 90 allowRenameOfShardColumn bool, 91 ) (changed bool, err error) { 92 if *newName == "" { 93 return false, errEmptyColumnName 94 } 95 96 col, _, err := tableDesc.FindColumnByName(*oldName) 97 if err != nil { 98 return false, err 99 } 100 101 for _, tableRef := range tableDesc.DependedOnBy { 102 found := false 103 for _, colID := range tableRef.ColumnIDs { 104 if colID == col.ID { 105 found = true 106 } 107 } 108 if found { 109 return false, p.dependentViewRenameError( 110 ctx, "column", oldName.String(), tableDesc.ParentID, tableRef.ID) 111 } 112 } 113 if *oldName == *newName { 114 // Noop. 115 return false, nil 116 } 117 isShardColumn := tableDesc.IsShardColumn(col) 118 if isShardColumn && !allowRenameOfShardColumn { 119 return false, pgerror.Newf(pgcode.ReservedName, "cannot rename shard column") 120 } 121 // Understand if the active column already exists before checking for column 122 // mutations to detect assertion failure of empty mutation and no column. 123 // Otherwise we would have to make the above call twice. 124 _, columnNotFoundErr := tableDesc.FindActiveColumnByName(string(*newName)) 125 if m := tableDesc.FindColumnMutationByName(*newName); m != nil { 126 switch m.Direction { 127 case sqlbase.DescriptorMutation_ADD: 128 return false, pgerror.Newf(pgcode.DuplicateColumn, 129 "duplicate: column %q in the middle of being added, not yet public", 130 col.Name) 131 case sqlbase.DescriptorMutation_DROP: 132 return false, pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 133 "column %q being dropped, try again later", col.Name) 134 default: 135 if columnNotFoundErr != nil { 136 return false, errors.AssertionFailedf( 137 "mutation in state %s, direction %s, and no column descriptor", 138 errors.Safe(m.State), errors.Safe(m.Direction)) 139 } 140 } 141 } 142 if columnNotFoundErr == nil { 143 return false, sqlbase.NewColumnAlreadyExistsError(tree.ErrString(newName), tableDesc.Name) 144 } 145 146 preFn := func(expr tree.Expr) (recurse bool, newExpr tree.Expr, err error) { 147 if vBase, ok := expr.(tree.VarName); ok { 148 v, err := vBase.NormalizeVarName() 149 if err != nil { 150 return false, nil, err 151 } 152 if c, ok := v.(*tree.ColumnItem); ok { 153 if string(c.ColumnName) == string(*oldName) { 154 c.ColumnName = *newName 155 } 156 } 157 return false, v, nil 158 } 159 return true, expr, nil 160 } 161 162 renameIn := func(expression string) (string, error) { 163 parsed, err := parser.ParseExpr(expression) 164 if err != nil { 165 return "", err 166 } 167 168 renamed, err := tree.SimpleVisit(parsed, preFn) 169 if err != nil { 170 return "", err 171 } 172 173 return renamed.String(), nil 174 } 175 176 // Rename the column in CHECK constraints. 177 // Renaming columns that are being referenced by checks that are being added is not allowed. 178 for i := range tableDesc.Checks { 179 var err error 180 tableDesc.Checks[i].Expr, err = renameIn(tableDesc.Checks[i].Expr) 181 if err != nil { 182 return false, err 183 } 184 } 185 186 // Rename the column in computed columns. 187 for i := range tableDesc.Columns { 188 if otherCol := &tableDesc.Columns[i]; otherCol.IsComputed() { 189 newExpr, err := renameIn(*otherCol.ComputeExpr) 190 if err != nil { 191 return false, err 192 } 193 otherCol.ComputeExpr = &newExpr 194 } 195 } 196 197 // Rename the column in hash-sharded index descriptors. Potentially rename the 198 // shard column too if we haven't already done it. 199 shardColumnsToRename := make(map[tree.Name]tree.Name) // map[oldShardColName]newShardColName 200 maybeUpdateShardedDesc := func(shardedDesc *sqlbase.ShardedDescriptor) { 201 if !shardedDesc.IsSharded { 202 return 203 } 204 oldShardColName := tree.Name(sqlbase.GetShardColumnName( 205 shardedDesc.ColumnNames, shardedDesc.ShardBuckets)) 206 var changed bool 207 for i, c := range shardedDesc.ColumnNames { 208 if c == string(*oldName) { 209 changed = true 210 shardedDesc.ColumnNames[i] = string(*newName) 211 } 212 } 213 if !changed { 214 return 215 } 216 newName, alreadyRenamed := shardColumnsToRename[oldShardColName] 217 if !alreadyRenamed { 218 newName = tree.Name(sqlbase.GetShardColumnName( 219 shardedDesc.ColumnNames, shardedDesc.ShardBuckets)) 220 shardColumnsToRename[oldShardColName] = newName 221 } 222 // Keep the shardedDesc name in sync with the column name. 223 shardedDesc.Name = string(newName) 224 } 225 for _, idx := range tableDesc.AllNonDropIndexes() { 226 maybeUpdateShardedDesc(&idx.Sharded) 227 } 228 229 // Rename the column in the indexes. 230 tableDesc.RenameColumnDescriptor(col, string(*newName)) 231 232 // Rename any shard columns which need to be renamed because their name was 233 // based on this column. 234 for oldShardColName, newShardColName := range shardColumnsToRename { 235 // Recursively call p.renameColumn. We don't need to worry about deeper than 236 // one recursive call because shard columns cannot refer to each other. 237 const allowRenameOfShardColumn = true 238 _, err = p.renameColumn(ctx, tableDesc, &oldShardColName, &newShardColName, 239 allowRenameOfShardColumn) 240 if err != nil { 241 return false, err 242 } 243 } 244 245 return true, nil 246 } 247 248 func (n *renameColumnNode) Next(runParams) (bool, error) { return false, nil } 249 func (n *renameColumnNode) Values() tree.Datums { return tree.Datums{} } 250 func (n *renameColumnNode) Close(context.Context) {}