Skip to content

Commit fa81033

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 30c0ad2 commit fa81033

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

696696
subtest end
697+
698+
699+
subtest index_name_conflicts_with_primary_key
700+
701+
statement ok
702+
CREATE TABLE t_index_name_conflicts_with_primary_key (a INT PRIMARY KEY, b INT);
703+
704+
statement error pgcode 42P07 index with name \"t_index_name_conflicts_with_primary_key_pkey\" already exists
705+
CREATE INDEX t_index_name_conflicts_with_primary_key_pkey ON t_index_name_conflicts_with_primary_key (a);
706+
707+
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
@@ -119,20 +119,34 @@ func CreateIndex(b BuildCtx, n *tree.CreateIndex) {
119119
"%q is not a table or materialized view", n.Table.ObjectName))
120120
}
121121
// Resolve the index name and make sure it doesn't exist yet.
122-
{
122+
if len(n.Name) > 0 {
123123
indexElements := b.ResolveIndex(idxSpec.secondary.TableID, n.Name, ResolveParams{
124124
IsExistenceOptional: true,
125125
RequiredPrivilege: privilege.CREATE,
126126
})
127-
if _, target, sec := scpb.FindSecondaryIndex(indexElements); sec != nil {
127+
skipCreation := false
128+
indexElements.ForEach(func(_ scpb.Status, target scpb.TargetStatus, e scpb.Element) {
129+
switch e.(type) {
130+
// Names can conflict on either primary or secondary indexes.
131+
case *scpb.PrimaryIndex:
132+
case *scpb.SecondaryIndex:
133+
default:
134+
// No index element that we care about.
135+
return
136+
}
128137
if n.IfNotExists {
138+
skipCreation = true
129139
return
130140
}
131141
if target == scpb.ToAbsent {
132142
panic(pgerror.Newf(pgcode.ObjectNotInPrerequisiteState,
133143
"index %q being dropped, try again later", n.Name.String()))
134144
}
135145
panic(pgerror.Newf(pgcode.DuplicateRelation, "index with name %q already exists", n.Name))
146+
})
147+
if skipCreation {
148+
return
149+
136150
}
137151
}
138152
if _, _, tbl := scpb.FindTable(relationElements); tbl != nil {

0 commit comments

Comments
 (0)