Skip to content

Commit a465010

Browse files
committed
sql: avoid unnecessary version bumps for UDTs during ALTER TABLE
Previously, in the legacy schema changer, we unconditionally updated backreferences from tables to user-defined types (UDTs) during ALTER TABLE operations. This happened even when the backreferences remained unchanged. While this behavior was functionally harmless, it caused the version of the referenced types to be incremented unnecessarily. This change avoids version bumps unless the backreference actually changes. Fixes: #144293 Epic: none Release note: none
1 parent 04630a1 commit a465010

File tree

7 files changed

+122
-28
lines changed

7 files changed

+122
-28
lines changed

pkg/backup/restore_job.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,7 +1401,7 @@ func createImportingDescriptors(
14011401
if err != nil {
14021402
return err
14031403
}
1404-
typDesc.AddReferencingDescriptorID(table.GetID())
1404+
_ = typDesc.AddReferencingDescriptorID(table.GetID())
14051405
if err := descsCol.WriteDescToBatch(
14061406
ctx, kvTrace, typDesc, b,
14071407
); err != nil {
@@ -3119,7 +3119,7 @@ func (r *restoreResumer) removeExistingTypeBackReferences(
31193119
}
31203120
existing := desc.(*typedesc.Mutable)
31213121
existing.MaybeIncrementVersion()
3122-
existing.RemoveReferencingDescriptorID(tbl.ID)
3122+
_ = existing.RemoveReferencingDescriptorID(tbl.ID)
31233123
}
31243124
}
31253125
}

pkg/sql/alter_table_locality.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -666,9 +666,10 @@ func setNewLocalityConfig(
666666
if err != nil {
667667
return err
668668
}
669-
typ.RemoveReferencingDescriptorID(desc.GetID())
670-
if err := descsCol.WriteDescToBatch(ctx, kvTrace, typ, b); err != nil {
671-
return err
669+
if typ.RemoveReferencingDescriptorID(desc.GetID()) {
670+
if err := descsCol.WriteDescToBatch(ctx, kvTrace, typ, b); err != nil {
671+
return err
672+
}
672673
}
673674
}
674675
desc.LocalityConfig = &config
@@ -678,9 +679,10 @@ func setNewLocalityConfig(
678679
if err != nil {
679680
return err
680681
}
681-
typ.AddReferencingDescriptorID(desc.GetID())
682-
if err := descsCol.WriteDescToBatch(ctx, kvTrace, typ, b); err != nil {
683-
return err
682+
if typ.AddReferencingDescriptorID(desc.GetID()) {
683+
if err := descsCol.WriteDescToBatch(ctx, kvTrace, typ, b); err != nil {
684+
return err
685+
}
684686
}
685687
}
686688
return nil

pkg/sql/catalog/typedesc/type_desc.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,25 +409,29 @@ func (desc *Mutable) AddEnumValue(node *tree.AlterTypeAddValue) error {
409409
}
410410

411411
// AddReferencingDescriptorID adds a new referencing descriptor ID to the
412-
// TypeDescriptor. It ensures that duplicates are not added.
413-
func (desc *Mutable) AddReferencingDescriptorID(new descpb.ID) {
412+
// TypeDescriptor, ensuring no duplicates are added. Returns false if the ID
413+
// was already present and no changes were made.
414+
func (desc *Mutable) AddReferencingDescriptorID(new descpb.ID) bool {
414415
for _, id := range desc.ReferencingDescriptorIDs {
415416
if new == id {
416-
return
417+
return false
417418
}
418419
}
419420
desc.ReferencingDescriptorIDs = append(desc.ReferencingDescriptorIDs, new)
421+
return true
420422
}
421423

422424
// RemoveReferencingDescriptorID removes the desired referencing descriptor ID
423-
// from the catalog.TypeDescriptor. It has no effect if the requested ID is not present.
424-
func (desc *Mutable) RemoveReferencingDescriptorID(remove descpb.ID) {
425+
// from the catalog.TypeDescriptor. If the ID is not present, the method has no
426+
// effect and returns false to indicate that no removal occurred.
427+
func (desc *Mutable) RemoveReferencingDescriptorID(remove descpb.ID) bool {
425428
for i, id := range desc.ReferencingDescriptorIDs {
426429
if id == remove {
427430
desc.ReferencingDescriptorIDs = append(desc.ReferencingDescriptorIDs[:i], desc.ReferencingDescriptorIDs[i+1:]...)
428-
return
431+
return true
429432
}
430433
}
434+
return false
431435
}
432436

433437
// SetParentSchemaID sets the SchemaID of the type.

pkg/sql/create_table.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ func (n *createTableNode) startExec(params runParams) error {
520520
if err != nil {
521521
return errors.Wrap(err, "error resolving multi-region enum")
522522
}
523-
typeDesc.AddReferencingDescriptorID(desc.ID)
523+
_ = typeDesc.AddReferencingDescriptorID(desc.ID)
524524
err = params.p.writeTypeSchemaChange(
525525
params.ctx, typeDesc, "add REGIONAL BY TABLE back reference")
526526
if err != nil {

pkg/sql/drop_type.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,9 @@ func (p *planner) addTypeBackReference(
170170
return err
171171
}
172172

173-
mutDesc.AddReferencingDescriptorID(ref)
173+
if !mutDesc.AddReferencingDescriptorID(ref) {
174+
return nil // no-op
175+
}
174176
return p.writeTypeSchemaChange(ctx, mutDesc, jobDesc)
175177
}
176178

@@ -182,9 +184,10 @@ func (p *planner) removeTypeBackReferences(
182184
if err != nil {
183185
return err
184186
}
185-
mutDesc.RemoveReferencingDescriptorID(ref)
186-
if err := p.writeTypeSchemaChange(ctx, mutDesc, jobDesc); err != nil {
187-
return err
187+
if mutDesc.RemoveReferencingDescriptorID(ref) {
188+
if err := p.writeTypeSchemaChange(ctx, mutDesc, jobDesc); err != nil {
189+
return err
190+
}
188191
}
189192
}
190193
return nil

pkg/sql/logictest/testdata/logic_test/alter_table

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4128,9 +4128,6 @@ alter table roach add column serial_id2 SERIAL
41284128

41294129
subtest end
41304130

4131-
statement ok
4132-
set use_declarative_schema_changer = on
4133-
41344131
# Tests for #131948 where we incorrectly backfilled empty column
41354132
# families for composite datums.
41364133
subtest composite_type_131948
@@ -4454,6 +4451,7 @@ CREATE TABLE alter_table_alter_primary_key_duplicate_storage_params_a (
44544451
b TEXT NOT NULL
44554452
);
44564453

4454+
skipif config local-legacy-schema-changer
44574455
statement error pgcode 22023 pq: parameter "bucket_count" specified more than once
44584456
ALTER TABLE alter_table_alter_primary_key_duplicate_storage_params_a
44594457
ALTER PRIMARY KEY
@@ -4468,6 +4466,11 @@ subtest end
44684466
# when adding a column with an invalid geometry expression.
44694467
subtest alter_table_add_column_with_invalid_geometry_expression
44704468

4469+
let $use_decl_sc
4470+
SHOW use_declarative_schema_changer
4471+
4472+
statement ok
4473+
set use_declarative_schema_changer = on
44714474

44724475
statement ok
44734476
CREATE TABLE alter_table_add_column_with_invalid_geometry_expression (
@@ -4478,4 +4481,85 @@ INSERT INTO alter_table_add_column_with_invalid_geometry_expression VALUES (1);
44784481
statement error pgcode 22023 pq: failed to construct index entries during backfill: error parsing EWKB: unexpected EOF
44794482
ALTER TABLE alter_table_add_column_with_invalid_geometry_expression ADD COLUMN geom GEOMETRY NULL DEFAULT x'001a'
44804483

4484+
statement ok
4485+
SET use_declarative_schema_changer = $use_decl_sc;
4486+
4487+
subtest end
4488+
4489+
# This is a regression test for #144293 where we were bumping the UDT version of
4490+
# all types unconditionally in the legacy schema changer.
4491+
subtest conditional_bump_udt_version
4492+
4493+
statement ok
4494+
CREATE TABLE t_conditional_bump_udt_version (
4495+
id INT PRIMARY KEY
4496+
);
4497+
4498+
statement ok
4499+
CREATE TYPE e1 AS ENUM ('a', 'b', 'c');
4500+
4501+
let $e1_version
4502+
SELECT crdb_internal.pb_to_json('descriptor', descriptor) -> 'type' ->> 'version'
4503+
from system.descriptor
4504+
where id = 'e1'::REGTYPE::INT - 100000;
4505+
4506+
# Add a column using e1. We expect a version bump in the enum.
4507+
statement ok
4508+
ALTER TABLE t_conditional_bump_udt_version ADD COLUMN e1_col e1;
4509+
4510+
query I
4511+
SELECT 1
4512+
FROM system.descriptor
4513+
WHERE id = 'e1'::REGTYPE::INT - 100000 AND
4514+
(crdb_internal.pb_to_json('descriptor', descriptor) -> 'type' ->> 'version')::INT > $e1_version;
4515+
----
4516+
1
4517+
4518+
let $e1_version
4519+
SELECT crdb_internal.pb_to_json('descriptor', descriptor) -> 'type' ->> 'version'
4520+
from system.descriptor
4521+
where id = 'e1'::REGTYPE::INT - 100000;
4522+
4523+
# Add a regular int column. That should not bump the version.
4524+
statement ok
4525+
ALTER TABLE t_conditional_bump_udt_version ADD COLUMN i_col INT;
4526+
4527+
query I
4528+
SELECT 1
4529+
FROM system.descriptor
4530+
WHERE id = 'e1'::REGTYPE::INT - 100000 AND
4531+
(crdb_internal.pb_to_json('descriptor', descriptor) -> 'type' ->> 'version')::INT = $e1_version;
4532+
----
4533+
1
4534+
4535+
# No bump for drop column.
4536+
statement ok
4537+
ALTER TABLE t_conditional_bump_udt_version DROP COLUMN i_col;
4538+
4539+
query I
4540+
SELECT 1
4541+
FROM system.descriptor
4542+
WHERE id = 'e1'::REGTYPE::INT - 100000 AND
4543+
(crdb_internal.pb_to_json('descriptor', descriptor) -> 'type' ->> 'version')::INT = $e1_version;
4544+
----
4545+
1
4546+
4547+
# Ensure version bump happens when we drop the column using the type.
4548+
statement ok
4549+
ALTER TABLE t_conditional_bump_udt_version DROP COLUMN e1_col;
4550+
4551+
query I
4552+
SELECT 1
4553+
FROM system.descriptor
4554+
WHERE id = 'e1'::REGTYPE::INT - 100000 AND
4555+
(crdb_internal.pb_to_json('descriptor', descriptor) -> 'type' ->> 'version')::INT > $e1_version;
4556+
----
4557+
1
4558+
4559+
statement ok
4560+
DROP TABLE t_conditional_bump_udt_version;
4561+
4562+
statement ok
4563+
DROP TYPE e1;
4564+
44814565
subtest end

pkg/sql/schema_changer.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,10 +1160,11 @@ func (sc *SchemaChanger) dropViewDeps(
11601160
log.Warningf(ctx, "error resolving type dependency %d", id)
11611161
continue
11621162
}
1163-
typeDesc.RemoveReferencingDescriptorID(viewDesc.GetID())
1164-
if err := descsCol.WriteDescToBatch(ctx, false /* kvTrace*/, typeDesc, b); err != nil {
1165-
log.Warningf(ctx, "error removing dependency from type ID %d", id)
1166-
return err
1163+
if typeDesc.RemoveReferencingDescriptorID(viewDesc.GetID()) {
1164+
if err := descsCol.WriteDescToBatch(ctx, false /* kvTrace*/, typeDesc, b); err != nil {
1165+
log.Warningf(ctx, "error removing dependency from type ID %d", id)
1166+
return err
1167+
}
11671168
}
11681169
}
11691170
for i := 0; i < col.NumUsesSequences(); i++ {
@@ -1878,9 +1879,9 @@ func (sc *SchemaChanger) done(ctx context.Context) error {
18781879
return err
18791880
}
18801881
if isAddition {
1881-
typ.AddReferencingDescriptorID(scTable.ID)
1882+
_ = typ.AddReferencingDescriptorID(scTable.ID)
18821883
} else {
1883-
typ.RemoveReferencingDescriptorID(scTable.ID)
1884+
_ = typ.RemoveReferencingDescriptorID(scTable.ID)
18841885
}
18851886
if err := txn.Descriptors().WriteDescToBatch(ctx, kvTrace, typ, b); err != nil {
18861887
return err

0 commit comments

Comments
 (0)