Skip to content

Commit 6da2410

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 0602bf9 commit 6da2410

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
@@ -693,3 +693,14 @@ tbl_with_collate CREATE TABLE public.tbl_with_collate (
693693
) WITH (schema_locked = true);
694694

695695
subtest end
696+
697+
698+
subtest index_name_conflicts_with_primary_key
699+
700+
statement ok
701+
CREATE TABLE t_index_name_conflicts_with_primary_key (a INT PRIMARY KEY, b INT);
702+
703+
statement error pgcode 42P07 index with name \"t_index_name_conflicts_with_primary_key_pkey\" already exists
704+
CREATE INDEX t_index_name_conflicts_with_primary_key_pkey ON t_index_name_conflicts_with_primary_key (a);
705+
706+
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)