Skip to content

Commit

Permalink
catalog: add a PostDeserializationChange for fixing secondary index e…
Browse files Browse the repository at this point in the history
…ncoding type

Release note (bug fix): Fixed a bug where some secondary indexes would
incorrectly be treated internally as primary indexes, which could cause
some schema change operations to fail. The bug could occur if ALTER
PRIMARY KEY was used on v21.1 or earlier, and the cluster was upgraded.
  • Loading branch information
rafiss committed Jul 7, 2023
1 parent 56ecd40 commit 3b00ec6
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pkg/sql/catalog/post_deserialization_changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,8 @@ const (
// back-reference to something within the descriptor itself was removed
// from the descriptor.
StrippedDanglingSelfBackReferences

// FixSecondaryIndexEncodingType indicates that a secondary index had its
// encoding type fixed, so it is not incorrectly marked as a primary index.
FixSecondaryIndexEncodingType
)
1 change: 1 addition & 0 deletions pkg/sql/catalog/tabledesc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ go_test(
"//pkg/sql/catalog/internal/validate",
"//pkg/sql/catalog/nstree",
"//pkg/sql/privilege",
"//pkg/sql/schemachanger/scpb",
"//pkg/sql/sem/catconstants",
"//pkg/sql/sem/catid",
"//pkg/sql/sem/semenumpb",
Expand Down
106 changes: 106 additions & 0 deletions pkg/sql/catalog/tabledesc/structured_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/desctestutils"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate"
. "github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc"
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb"
"github.com/cockroachdb/cockroach/pkg/sql/types"
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
Expand Down Expand Up @@ -676,6 +677,111 @@ func TestUnvalidateConstraints(t *testing.T) {
}
}

func TestMaybeFixSecondaryIndexEncodingType(t *testing.T) {
tests := []struct {
desc descpb.TableDescriptor
expUpgrade bool
verify func(*testing.T, int, catalog.TableDescriptor) // nil means no extra verification.
}{
{ // 1
desc: descpb.TableDescriptor{
ID: 2,
ParentID: 1,
Name: "foo",
FormatVersion: descpb.InterleavedFormatVersion,
Columns: []descpb.ColumnDescriptor{
{ID: 1, Name: "bar"},
{ID: 2, Name: "baz"},
},
Families: []descpb.ColumnFamilyDescriptor{
{ID: 0, Name: "primary", ColumnIDs: []descpb.ColumnID{1, 2}, ColumnNames: []string{"bar", "baz"}},
},
Privileges: catpb.NewBasePrivilegeDescriptor(username.RootUserName()),
PrimaryIndex: descpb.IndexDescriptor{ID: 1, Name: "primary",
KeyColumnIDs: []descpb.ColumnID{1, 2},
KeyColumnNames: []string{"bar", "baz"},
KeyColumnDirections: []catenumpb.IndexColumn_Direction{catenumpb.IndexColumn_ASC, catenumpb.IndexColumn_ASC},
EncodingType: catenumpb.PrimaryIndexEncoding,
Version: descpb.LatestIndexDescriptorVersion,
ConstraintID: 1,
},
Indexes: []descpb.IndexDescriptor{{
ID: 2,
Name: "secondary",
KeyColumnIDs: []descpb.ColumnID{2},
KeyColumnNames: []string{"baz"},
KeyColumnDirections: []catenumpb.IndexColumn_Direction{catenumpb.IndexColumn_ASC},
EncodingType: catenumpb.PrimaryIndexEncoding,
}},
NextColumnID: 3,
NextFamilyID: 1,
NextIndexID: 3,
NextConstraintID: 2,
},
expUpgrade: true,
verify: func(t *testing.T, _ int, newDesc catalog.TableDescriptor) {
require.Equal(t, catenumpb.SecondaryIndexEncoding, newDesc.TableDesc().Indexes[0].EncodingType)
},
},
{ // 2
desc: descpb.TableDescriptor{
ID: 2,
ParentID: 1,
Name: "foo",
FormatVersion: descpb.InterleavedFormatVersion,
Columns: []descpb.ColumnDescriptor{
{ID: 1, Name: "bar"},
{ID: 2, Name: "baz"},
},
Families: []descpb.ColumnFamilyDescriptor{
{ID: 0, Name: "primary", ColumnIDs: []descpb.ColumnID{1, 2}, ColumnNames: []string{"bar", "baz"}},
},
Privileges: catpb.NewBasePrivilegeDescriptor(username.RootUserName()),
PrimaryIndex: descpb.IndexDescriptor{ID: 1, Name: "primary",
KeyColumnIDs: []descpb.ColumnID{1, 2},
KeyColumnNames: []string{"bar", "baz"},
KeyColumnDirections: []catenumpb.IndexColumn_Direction{catenumpb.IndexColumn_ASC, catenumpb.IndexColumn_ASC},
EncodingType: catenumpb.PrimaryIndexEncoding,
Version: descpb.LatestIndexDescriptorVersion,
ConstraintID: 1,
},
Indexes: []descpb.IndexDescriptor{{
ID: 2,
Name: "secondary",
KeyColumnIDs: []descpb.ColumnID{2},
KeyColumnNames: []string{"baz"},
KeyColumnDirections: []catenumpb.IndexColumn_Direction{catenumpb.IndexColumn_ASC},
EncodingType: catenumpb.PrimaryIndexEncoding,
}},
DeclarativeSchemaChangerState: &scpb.DescriptorState{
JobID: catpb.JobID(1),
},
NextColumnID: 3,
NextFamilyID: 1,
NextIndexID: 3,
NextConstraintID: 2,
},
expUpgrade: false,
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
b := NewBuilder(&test.desc)
require.NoError(t, b.RunPostDeserializationChanges())
desc := b.BuildImmutableTable()
changes, err := GetPostDeserializationChanges(desc)
require.NoError(t, err)
upgraded := changes.Contains(catalog.FixSecondaryIndexEncodingType)
if upgraded != test.expUpgrade {
t.Fatalf("%d: expected upgraded=%t, but got upgraded=%t", i, test.expUpgrade, upgraded)
}
if test.verify != nil {
test.verify(t, i, desc)
}
})
}
}

func TestKeysPerRow(t *testing.T) {
defer leaktest.AfterTest(t)()

Expand Down
16 changes: 16 additions & 0 deletions pkg/sql/catalog/tabledesc/table_desc_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ func maybeFillInDescriptor(
set(catalog.AddedConstraintIDs, maybeAddConstraintIDs(desc))
set(catalog.SetCheckConstraintColumnIDs, maybeSetCheckConstraintColumnIDs(desc))
set(catalog.StrippedDanglingSelfBackReferences, maybeStripDanglingSelfBackReferences(desc))
set(catalog.FixSecondaryIndexEncodingType, maybeFixSecondaryIndexEncodingType(desc))
return changes, nil
}

Expand Down Expand Up @@ -1006,6 +1007,21 @@ func maybeStripDanglingSelfBackReferences(tbl *descpb.TableDescriptor) (hasChang
return hasChanged
}

func maybeFixSecondaryIndexEncodingType(desc *descpb.TableDescriptor) (hasChanged bool) {
if desc.DeclarativeSchemaChangerState != nil || len(desc.Mutations) > 0 {
// Don't try to fix the encoding type if a schema change is in progress.
return false
}
for i := range desc.Indexes {
idx := &desc.Indexes[i]
if idx.EncodingType != catenumpb.SecondaryIndexEncoding {
idx.EncodingType = catenumpb.SecondaryIndexEncoding
hasChanged = true
}
}
return hasChanged
}

// maybeSetCreateAsOfTime ensures that the CreateAsOfTime field is set.
//
// CreateAsOfTime is used for CREATE TABLE ... AS ... and was introduced in
Expand Down

0 comments on commit 3b00ec6

Please sign in to comment.