/
rename_index.go
123 lines (102 loc) · 3.57 KB
/
rename_index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright 2017 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package sql
import (
"context"
"github.com/cockroachdb/cockroach/pkg/sql/catalog"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
)
var errEmptyIndexName = pgerror.New(pgcode.Syntax, "empty index name")
type renameIndexNode struct {
n *tree.RenameIndex
tableDesc *tabledesc.Mutable
idx catalog.Index
}
// 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(ctx context.Context, n *tree.RenameIndex) (planNode, error) {
if err := checkSchemaChangeEnabled(
ctx,
p.ExecCfg(),
"RENAME INDEX",
); err != nil {
return nil, err
}
_, tableDesc, err := expandMutableIndexName(ctx, p, n.Index, !n.IfExists /* requireTable */)
if err != nil {
return nil, err
}
if tableDesc == nil {
// IfExists specified and table did not exist -- noop.
return newZeroNode(nil /* columns */), nil
}
idx, err := catalog.MustFindIndexByName(tableDesc, string(n.Index.Index))
if err != nil {
if n.IfExists {
// Noop.
return newZeroNode(nil /* columns */), nil
}
// Index does not exist, but we want it to: error out.
return nil, pgerror.WithCandidateCode(err, pgcode.UndefinedObject)
}
if err := p.CheckPrivilege(ctx, tableDesc, privilege.CREATE); err != nil {
return nil, err
}
// Disallow schema changes if this table's schema is locked.
if err := checkTableSchemaUnlocked(tableDesc); err != nil {
return nil, err
}
return &renameIndexNode{n: n, idx: idx, tableDesc: tableDesc}, nil
}
// ReadingOwnWrites implements the planNodeReadingOwnWrites interface.
// This is because RENAME DATABASE performs multiple KV operations on descriptors
// and expects to see its own writes.
func (n *renameIndexNode) ReadingOwnWrites() {}
func (n *renameIndexNode) startExec(params runParams) error {
p := params.p
ctx := params.ctx
tableDesc := n.tableDesc
idx := n.idx
for _, tableRef := range tableDesc.DependedOnBy {
if tableRef.IndexID != idx.GetID() {
continue
}
return p.dependentError(
ctx, "index", n.n.Index.Index.String(), tableDesc.ParentID, tableRef.ID, "rename",
)
}
if n.n.NewName == "" {
return errEmptyIndexName
}
if n.n.Index.Index == n.n.NewName {
// Noop.
return nil
}
if foundIndex := catalog.FindIndexByName(tableDesc, string(n.n.NewName)); foundIndex != nil {
return pgerror.Newf(pgcode.DuplicateRelation, "index name %q already exists", string(n.n.NewName))
}
idx.IndexDesc().Name = string(n.n.NewName)
if err := validateDescriptor(ctx, p, tableDesc); err != nil {
return err
}
return p.writeSchemaChange(
ctx, tableDesc, descpb.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann()))
}
func (n *renameIndexNode) Next(runParams) (bool, error) { return false, nil }
func (n *renameIndexNode) Values() tree.Datums { return tree.Datums{} }
func (n *renameIndexNode) Close(context.Context) {}