Skip to content

Commit 8d0c3b2

Browse files
committed
sql/schemachanger: detect secondary and pk index name collisions
Previously, the declarative schema changer did not properly check if secondary index names and primary index names collided. This meant that instead of getting a query at statement time, one could be hit at runtime instead. To address this, this patch checks if either secondary or primary indexes with the same name exist when creating a new secondary index. Fixes: #153702 Release note (bug fix): Addressed a runtime error that could be hit if a new secondary index had a name collision with a primary index.
1 parent 7f32131 commit 8d0c3b2

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

pkg/sql/logictest/testdata/logic_test/create_index

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,3 +636,14 @@ tbl_with_collate CREATE TABLE public.tbl_with_collate (
636636
)
637637

638638
subtest end
639+
640+
641+
subtest index_name_conflicts_with_primary_key
642+
643+
statement ok
644+
CREATE TABLE t_index_name_conflicts_with_primary_key (a INT PRIMARY KEY, b INT);
645+
646+
statement error pgcode 42P07 index with name \"t_index_name_conflicts_with_primary_key_pkey\" already exists
647+
CREATE INDEX t_index_name_conflicts_with_primary_key_pkey ON t_index_name_conflicts_with_primary_key (a);
648+
649+
subtest end

pkg/sql/schemachanger/scbuild/internal/scbuildstmt/create_index.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,20 +125,34 @@ func CreateIndex(b BuildCtx, n *tree.CreateIndex) {
125125
"%q is not a table or materialized view", n.Table.ObjectName))
126126
}
127127
// Resolve the index name and make sure it doesn't exist yet.
128-
{
128+
if len(n.Name) > 0 {
129129
indexElements := b.ResolveIndex(idxSpec.secondary.TableID, n.Name, ResolveParams{
130130
IsExistenceOptional: true,
131131
RequiredPrivilege: privilege.CREATE,
132132
})
133-
if _, target, sec := scpb.FindSecondaryIndex(indexElements); sec != nil {
133+
skipCreation := false
134+
indexElements.ForEach(func(_ scpb.Status, target scpb.TargetStatus, e scpb.Element) {
135+
switch e.(type) {
136+
// Names can conflict on either primary or secondary indexes.
137+
case *scpb.PrimaryIndex:
138+
case *scpb.SecondaryIndex:
139+
default:
140+
// No index element that we care about.
141+
return
142+
}
134143
if n.IfNotExists {
144+
skipCreation = true
135145
return
136146
}
137147
if target == scpb.ToAbsent {
138148
panic(pgerror.Newf(pgcode.ObjectNotInPrerequisiteState,
139149
"index %q being dropped, try again later", n.Name.String()))
140150
}
141151
panic(pgerror.Newf(pgcode.DuplicateRelation, "index with name %q already exists", n.Name))
152+
})
153+
if skipCreation {
154+
return
155+
142156
}
143157
}
144158
if _, _, tbl := scpb.FindTable(relationElements); tbl != nil {

0 commit comments

Comments
 (0)