diff --git a/pkg/ccl/schemachangerccl/testdata/explain/drop_database_multiregion_primary_region b/pkg/ccl/schemachangerccl/testdata/explain/drop_database_multiregion_primary_region index 11eba4755f09..4ad12d594dea 100644 --- a/pkg/ccl/schemachangerccl/testdata/explain/drop_database_multiregion_primary_region +++ b/pkg/ccl/schemachangerccl/testdata/explain/drop_database_multiregion_primary_region @@ -19,13 +19,6 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ │ ├── PUBLIC → DROPPED Database:{DescID: 104} │ │ ├── PUBLIC → ABSENT DatabaseRoleSetting:{DescID: 104, Name: __placeholder_role_name__} │ │ ├── PUBLIC → ABSENT DatabaseRegionConfig:{DescID: 104, ReferencedDescID: 106} - │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} - │ │ ├── PUBLIC → ABSENT Owner:{DescID: 105} - │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: admin} - │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: public} - │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: root} - │ │ ├── PUBLIC → DROPPED Schema:{DescID: 105} - │ │ ├── PUBLIC → ABSENT SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Owner:{DescID: 106} │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 106, Name: admin} @@ -36,6 +29,13 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ │ ├── PUBLIC → ABSENT EnumTypeValue:{DescID: 106, Name: us-east2} │ │ ├── PUBLIC → ABSENT EnumTypeValue:{DescID: 106, Name: us-east3} │ │ ├── PUBLIC → ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} + │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} + │ │ ├── PUBLIC → ABSENT Owner:{DescID: 105} + │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: admin} + │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: public} + │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: root} + │ │ ├── PUBLIC → DROPPED Schema:{DescID: 105} + │ │ ├── PUBLIC → ABSENT SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 107, Name: _crdb_internal_region, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Owner:{DescID: 107} │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 107, Name: admin} @@ -84,12 +84,12 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ ├── SetColumnName {"ColumnID":4294967294,"Name":"crdb_internal_co...","TableID":108} │ ├── MakePublicPrimaryIndexWriteOnly {"IndexID":1,"TableID":108} │ ├── SetIndexName {"IndexID":1,"Name":"crdb_internal_in...","TableID":108} - │ ├── MarkDescriptorAsDropped {"DescriptorID":105} - │ ├── RemoveSchemaParent {"Parent":{"ParentDatabaseID":104,"SchemaID":105}} │ ├── NotImplementedForPublicObjects {"DescID":106,"ElementType":"scpb.Owner"} │ ├── RemoveUserPrivileges {"DescriptorID":106,"User":"admin"} │ ├── RemoveUserPrivileges {"DescriptorID":106,"User":"public"} │ ├── RemoveUserPrivileges {"DescriptorID":106,"User":"root"} + │ ├── MarkDescriptorAsDropped {"DescriptorID":105} + │ ├── RemoveSchemaParent {"Parent":{"ParentDatabaseID":104,"SchemaID":105}} │ ├── NotImplementedForPublicObjects {"DescID":107,"ElementType":"scpb.Owner"} │ ├── RemoveUserPrivileges {"DescriptorID":107,"User":"admin"} │ ├── RemoveUserPrivileges {"DescriptorID":107,"User":"public"} @@ -102,12 +102,12 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ ├── MakeWriteOnlyColumnDeleteOnly {"ColumnID":4294967295,"TableID":108} │ ├── MakeWriteOnlyColumnDeleteOnly {"ColumnID":4294967294,"TableID":108} │ ├── MarkDescriptorAsDropped {"DescriptorID":104} + │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":106,"Name":"crdb_internal_re...","SchemaID":105}} │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":105,"Name":"public"}} │ ├── NotImplementedForPublicObjects {"DescID":105,"ElementType":"scpb.Owner"} │ ├── RemoveUserPrivileges {"DescriptorID":105,"User":"admin"} │ ├── RemoveUserPrivileges {"DescriptorID":105,"User":"public"} │ ├── RemoveUserPrivileges {"DescriptorID":105,"User":"root"} - │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":106,"Name":"crdb_internal_re...","SchemaID":105}} │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":107,"Name":"_crdb_internal_r...","SchemaID":105}} │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":108,"Name":"table_regional_b...","SchemaID":105}} │ ├── MakeWriteOnlyColumnDeleteOnly {"ColumnID":1,"TableID":108} @@ -133,13 +133,6 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ │ │ ├── DROPPED → PUBLIC Database:{DescID: 104} │ │ │ ├── ABSENT → PUBLIC DatabaseRoleSetting:{DescID: 104, Name: __placeholder_role_name__} │ │ │ ├── ABSENT → PUBLIC DatabaseRegionConfig:{DescID: 104, ReferencedDescID: 106} - │ │ │ ├── ABSENT → PUBLIC Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} - │ │ │ ├── ABSENT → PUBLIC Owner:{DescID: 105} - │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 105, Name: admin} - │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 105, Name: public} - │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 105, Name: root} - │ │ │ ├── DROPPED → PUBLIC Schema:{DescID: 105} - │ │ │ ├── ABSENT → PUBLIC SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ │ ├── ABSENT → PUBLIC Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} │ │ │ ├── ABSENT → PUBLIC Owner:{DescID: 106} │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 106, Name: admin} @@ -150,6 +143,13 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ │ │ ├── ABSENT → PUBLIC EnumTypeValue:{DescID: 106, Name: us-east2} │ │ │ ├── ABSENT → PUBLIC EnumTypeValue:{DescID: 106, Name: us-east3} │ │ │ ├── ABSENT → PUBLIC SchemaChild:{DescID: 106, ReferencedDescID: 105} + │ │ │ ├── ABSENT → PUBLIC Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} + │ │ │ ├── ABSENT → PUBLIC Owner:{DescID: 105} + │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 105, Name: admin} + │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 105, Name: public} + │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 105, Name: root} + │ │ │ ├── DROPPED → PUBLIC Schema:{DescID: 105} + │ │ │ ├── ABSENT → PUBLIC SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ │ ├── ABSENT → PUBLIC Namespace:{DescID: 107, Name: _crdb_internal_region, ReferencedDescID: 104} │ │ │ ├── ABSENT → PUBLIC Owner:{DescID: 107} │ │ │ ├── ABSENT → PUBLIC UserPrivileges:{DescID: 107, Name: admin} @@ -190,13 +190,6 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ │ ├── PUBLIC → DROPPED Database:{DescID: 104} │ │ ├── PUBLIC → ABSENT DatabaseRoleSetting:{DescID: 104, Name: __placeholder_role_name__} │ │ ├── PUBLIC → ABSENT DatabaseRegionConfig:{DescID: 104, ReferencedDescID: 106} - │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} - │ │ ├── PUBLIC → ABSENT Owner:{DescID: 105} - │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: admin} - │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: public} - │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: root} - │ │ ├── PUBLIC → DROPPED Schema:{DescID: 105} - │ │ ├── PUBLIC → ABSENT SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Owner:{DescID: 106} │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 106, Name: admin} @@ -207,6 +200,13 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ │ ├── PUBLIC → ABSENT EnumTypeValue:{DescID: 106, Name: us-east2} │ │ ├── PUBLIC → ABSENT EnumTypeValue:{DescID: 106, Name: us-east3} │ │ ├── PUBLIC → ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} + │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} + │ │ ├── PUBLIC → ABSENT Owner:{DescID: 105} + │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: admin} + │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: public} + │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 105, Name: root} + │ │ ├── PUBLIC → DROPPED Schema:{DescID: 105} + │ │ ├── PUBLIC → ABSENT SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Namespace:{DescID: 107, Name: _crdb_internal_region, ReferencedDescID: 104} │ │ ├── PUBLIC → ABSENT Owner:{DescID: 107} │ │ ├── PUBLIC → ABSENT UserPrivileges:{DescID: 107, Name: admin} @@ -255,12 +255,12 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ ├── SetColumnName {"ColumnID":4294967294,"Name":"crdb_internal_co...","TableID":108} │ ├── MakePublicPrimaryIndexWriteOnly {"IndexID":1,"TableID":108} │ ├── SetIndexName {"IndexID":1,"Name":"crdb_internal_in...","TableID":108} - │ ├── MarkDescriptorAsDropped {"DescriptorID":105} - │ ├── RemoveSchemaParent {"Parent":{"ParentDatabaseID":104,"SchemaID":105}} │ ├── NotImplementedForPublicObjects {"DescID":106,"ElementType":"scpb.Owner"} │ ├── RemoveUserPrivileges {"DescriptorID":106,"User":"admin"} │ ├── RemoveUserPrivileges {"DescriptorID":106,"User":"public"} │ ├── RemoveUserPrivileges {"DescriptorID":106,"User":"root"} + │ ├── MarkDescriptorAsDropped {"DescriptorID":105} + │ ├── RemoveSchemaParent {"Parent":{"ParentDatabaseID":104,"SchemaID":105}} │ ├── NotImplementedForPublicObjects {"DescID":107,"ElementType":"scpb.Owner"} │ ├── RemoveUserPrivileges {"DescriptorID":107,"User":"admin"} │ ├── RemoveUserPrivileges {"DescriptorID":107,"User":"public"} @@ -274,12 +274,12 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; │ ├── MakeWriteOnlyColumnDeleteOnly {"ColumnID":4294967294,"TableID":108} │ ├── MarkDescriptorAsDropped {"DescriptorID":104} │ ├── RemoveDatabaseRoleSettings {"DatabaseID":104} + │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":106,"Name":"crdb_internal_re...","SchemaID":105}} │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":105,"Name":"public"}} │ ├── NotImplementedForPublicObjects {"DescID":105,"ElementType":"scpb.Owner"} │ ├── RemoveUserPrivileges {"DescriptorID":105,"User":"admin"} │ ├── RemoveUserPrivileges {"DescriptorID":105,"User":"public"} │ ├── RemoveUserPrivileges {"DescriptorID":105,"User":"root"} - │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":106,"Name":"crdb_internal_re...","SchemaID":105}} │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":107,"Name":"_crdb_internal_r...","SchemaID":105}} │ ├── DrainDescriptorName {"Namespace":{"DatabaseID":104,"DescriptorID":108,"Name":"table_regional_b...","SchemaID":105}} │ ├── MakeWriteOnlyColumnDeleteOnly {"ColumnID":1,"TableID":108} @@ -305,8 +305,8 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; ├── 8 elements transitioning toward ABSENT │ ├── DROPPED → ABSENT Database:{DescID: 104} │ ├── PUBLIC → ABSENT DatabaseData:{DescID: 104} - │ ├── DROPPED → ABSENT Schema:{DescID: 105} │ ├── DROPPED → ABSENT EnumType:{DescID: 106} + │ ├── DROPPED → ABSENT Schema:{DescID: 105} │ ├── DROPPED → ABSENT AliasType:{DescID: 107, ReferencedTypeIDs: [106 107]} │ ├── DROPPED → ABSENT Table:{DescID: 108} │ ├── PUBLIC → ABSENT IndexData:{DescID: 108, IndexID: 1} @@ -314,8 +314,8 @@ Schema change plan for DROP DATABASE ‹multi_region_test_db› CASCADE; └── 13 Mutation operations ├── DeleteDescriptor {"DescriptorID":104} ├── CreateGCJobForDatabase {"DatabaseID":104} - ├── DeleteDescriptor {"DescriptorID":105} ├── DeleteDescriptor {"DescriptorID":106} + ├── DeleteDescriptor {"DescriptorID":105} ├── DeleteDescriptor {"DescriptorID":107} ├── CreateGCJobForTable {"DatabaseID":104,"TableID":108} ├── CreateGCJobForIndex {"IndexID":1,"TableID":108} diff --git a/pkg/ccl/schemachangerccl/testdata/explain_verbose/drop_database_multiregion_primary_region b/pkg/ccl/schemachangerccl/testdata/explain_verbose/drop_database_multiregion_primary_region index ca321cc02932..909c969dccaa 100644 --- a/pkg/ccl/schemachangerccl/testdata/explain_verbose/drop_database_multiregion_primary_region +++ b/pkg/ccl/schemachangerccl/testdata/explain_verbose/drop_database_multiregion_primary_region @@ -66,116 +66,116 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ │ └── • SameStagePrecedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor drop right before removing dependent with attr ref" │ │ │ -│ │ ├── • Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} +│ │ ├── • Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} │ │ │ │ PUBLIC → ABSENT │ │ │ │ │ │ │ ├── • SameStagePrecedence dependency from DROPPED Database:{DescID: 104} │ │ │ │ rule: "descriptor drop right before removing dependent with attr ref" │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • Owner:{DescID: 105} +│ │ ├── • Owner:{DescID: 106} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 105, Name: admin} +│ │ ├── • UserPrivileges:{DescID: 106, Name: admin} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 105, Name: public} +│ │ ├── • UserPrivileges:{DescID: 106, Name: public} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 105, Name: root} +│ │ ├── • UserPrivileges:{DescID: 106, Name: root} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • Schema:{DescID: 105} -│ │ │ │ PUBLIC → DROPPED -│ │ │ │ -│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} -│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" -│ │ │ │ -│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 107, ReferencedDescID: 105} -│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" -│ │ │ │ -│ │ │ └── • Precedence dependency from ABSENT SchemaChild:{DescID: 108, ReferencedDescID: 105} -│ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ ├── • EnumType:{DescID: 106} +│ │ │ PUBLIC → DROPPED │ │ │ -│ │ ├── • SchemaParent:{DescID: 105, ReferencedDescID: 104} +│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east1} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • SameStagePrecedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" -│ │ │ rule: "descriptor dropped right before removing back-reference in its parent descriptor" │ │ │ -│ │ ├── • Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} +│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east2} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ ├── • SameStagePrecedence dependency from DROPPED Database:{DescID: 104} -│ │ │ │ rule: "descriptor drop right before removing dependent with attr ref" -│ │ │ │ │ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • Owner:{DescID: 106} +│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east3} │ │ │ │ PUBLIC → ABSENT │ │ │ │ │ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 106, Name: admin} +│ │ ├── • SchemaChild:{DescID: 106, ReferencedDescID: 105} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • SameStagePrecedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" +│ │ │ rule: "descriptor dropped right before removing back-reference in its parent descriptor" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 106, Name: public} +│ │ ├── • Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ ├── • SameStagePrecedence dependency from DROPPED Database:{DescID: 104} +│ │ │ │ rule: "descriptor drop right before removing dependent with attr ref" +│ │ │ │ +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 106, Name: root} +│ │ ├── • Owner:{DescID: 105} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • EnumType:{DescID: 106} -│ │ │ PUBLIC → DROPPED -│ │ │ -│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east1} +│ │ ├── • UserPrivileges:{DescID: 105, Name: admin} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east2} +│ │ ├── • UserPrivileges:{DescID: 105, Name: public} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east3} +│ │ ├── • UserPrivileges:{DescID: 105, Name: root} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • SchemaChild:{DescID: 106, ReferencedDescID: 105} +│ │ ├── • Schema:{DescID: 105} +│ │ │ │ PUBLIC → DROPPED +│ │ │ │ +│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} +│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ │ │ +│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 107, ReferencedDescID: 105} +│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ │ │ +│ │ │ └── • Precedence dependency from ABSENT SchemaChild:{DescID: 108, ReferencedDescID: 105} +│ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ │ +│ │ ├── • SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • SameStagePrecedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • SameStagePrecedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ rule: "descriptor dropped right before removing back-reference in its parent descriptor" │ │ │ @@ -504,14 +504,6 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ Name: crdb_internal_index_1_name_placeholder │ │ TableID: 108 │ │ -│ ├── • MarkDescriptorAsDropped -│ │ DescriptorID: 105 -│ │ -│ ├── • RemoveSchemaParent -│ │ Parent: -│ │ ParentDatabaseID: 104 -│ │ SchemaID: 105 -│ │ │ ├── • NotImplementedForPublicObjects │ │ DescID: 106 │ │ ElementType: scpb.Owner @@ -528,6 +520,14 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ DescriptorID: 106 │ │ User: root │ │ +│ ├── • MarkDescriptorAsDropped +│ │ DescriptorID: 105 +│ │ +│ ├── • RemoveSchemaParent +│ │ Parent: +│ │ ParentDatabaseID: 104 +│ │ SchemaID: 105 +│ │ │ ├── • NotImplementedForPublicObjects │ │ DescID: 107 │ │ ElementType: scpb.Owner @@ -577,6 +577,13 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ ├── • DrainDescriptorName │ │ Namespace: │ │ DatabaseID: 104 +│ │ DescriptorID: 106 +│ │ Name: crdb_internal_region +│ │ SchemaID: 105 +│ │ +│ ├── • DrainDescriptorName +│ │ Namespace: +│ │ DatabaseID: 104 │ │ DescriptorID: 105 │ │ Name: public │ │ @@ -599,13 +606,6 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ ├── • DrainDescriptorName │ │ Namespace: │ │ DatabaseID: 104 -│ │ DescriptorID: 106 -│ │ Name: crdb_internal_region -│ │ SchemaID: 105 -│ │ -│ ├── • DrainDescriptorName -│ │ Namespace: -│ │ DatabaseID: 104 │ │ DescriptorID: 107 │ │ Name: _crdb_internal_region │ │ SchemaID: 105 @@ -697,55 +697,55 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ │ ├── • DatabaseRegionConfig:{DescID: 104, ReferencedDescID: 106} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} +│ │ │ ├── • Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • Owner:{DescID: 105} +│ │ │ ├── • Owner:{DescID: 106} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • UserPrivileges:{DescID: 105, Name: admin} +│ │ │ ├── • UserPrivileges:{DescID: 106, Name: admin} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • UserPrivileges:{DescID: 105, Name: public} +│ │ │ ├── • UserPrivileges:{DescID: 106, Name: public} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • UserPrivileges:{DescID: 105, Name: root} +│ │ │ ├── • UserPrivileges:{DescID: 106, Name: root} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • Schema:{DescID: 105} +│ │ │ ├── • EnumType:{DescID: 106} │ │ │ │ DROPPED → PUBLIC │ │ │ │ -│ │ │ ├── • SchemaParent:{DescID: 105, ReferencedDescID: 104} +│ │ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east1} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} +│ │ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east2} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • Owner:{DescID: 106} +│ │ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east3} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • UserPrivileges:{DescID: 106, Name: admin} +│ │ │ ├── • SchemaChild:{DescID: 106, ReferencedDescID: 105} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • UserPrivileges:{DescID: 106, Name: public} +│ │ │ ├── • Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • UserPrivileges:{DescID: 106, Name: root} +│ │ │ ├── • Owner:{DescID: 105} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • EnumType:{DescID: 106} -│ │ │ │ DROPPED → PUBLIC -│ │ │ │ -│ │ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east1} +│ │ │ ├── • UserPrivileges:{DescID: 105, Name: admin} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east2} +│ │ │ ├── • UserPrivileges:{DescID: 105, Name: public} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east3} +│ │ │ ├── • UserPrivileges:{DescID: 105, Name: root} │ │ │ │ ABSENT → PUBLIC │ │ │ │ -│ │ │ ├── • SchemaChild:{DescID: 106, ReferencedDescID: 105} +│ │ │ ├── • Schema:{DescID: 105} +│ │ │ │ DROPPED → PUBLIC +│ │ │ │ +│ │ │ ├── • SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ │ │ ABSENT → PUBLIC │ │ │ │ │ │ │ ├── • Namespace:{DescID: 107, Name: _crdb_internal_region, ReferencedDescID: 104} @@ -892,116 +892,116 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ │ └── • SameStagePrecedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor drop right before removing dependent with attr ref" │ │ │ -│ │ ├── • Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} +│ │ ├── • Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} │ │ │ │ PUBLIC → ABSENT │ │ │ │ │ │ │ ├── • SameStagePrecedence dependency from DROPPED Database:{DescID: 104} │ │ │ │ rule: "descriptor drop right before removing dependent with attr ref" │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • Owner:{DescID: 105} +│ │ ├── • Owner:{DescID: 106} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 105, Name: admin} +│ │ ├── • UserPrivileges:{DescID: 106, Name: admin} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 105, Name: public} +│ │ ├── • UserPrivileges:{DescID: 106, Name: public} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 105, Name: root} +│ │ ├── • UserPrivileges:{DescID: 106, Name: root} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • Schema:{DescID: 105} -│ │ │ │ PUBLIC → DROPPED -│ │ │ │ -│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} -│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" -│ │ │ │ -│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 107, ReferencedDescID: 105} -│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" -│ │ │ │ -│ │ │ └── • Precedence dependency from ABSENT SchemaChild:{DescID: 108, ReferencedDescID: 105} -│ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ ├── • EnumType:{DescID: 106} +│ │ │ PUBLIC → DROPPED │ │ │ -│ │ ├── • SchemaParent:{DescID: 105, ReferencedDescID: 104} +│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east1} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • SameStagePrecedence dependency from DROPPED Schema:{DescID: 105} +│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" -│ │ │ rule: "descriptor dropped right before removing back-reference in its parent descriptor" │ │ │ -│ │ ├── • Namespace:{DescID: 106, Name: crdb_internal_region, ReferencedDescID: 104} +│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east2} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ ├── • SameStagePrecedence dependency from DROPPED Database:{DescID: 104} -│ │ │ │ rule: "descriptor drop right before removing dependent with attr ref" -│ │ │ │ │ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • Owner:{DescID: 106} +│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east3} │ │ │ │ PUBLIC → ABSENT │ │ │ │ │ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 106, Name: admin} +│ │ ├── • SchemaChild:{DescID: 106, ReferencedDescID: 105} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • SameStagePrecedence dependency from DROPPED EnumType:{DescID: 106} │ │ │ rule: "descriptor dropped before dependent element removal" +│ │ │ rule: "descriptor dropped right before removing back-reference in its parent descriptor" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 106, Name: public} +│ │ ├── • Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ ├── • SameStagePrecedence dependency from DROPPED Database:{DescID: 104} +│ │ │ │ rule: "descriptor drop right before removing dependent with attr ref" +│ │ │ │ +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • UserPrivileges:{DescID: 106, Name: root} +│ │ ├── • Owner:{DescID: 105} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • EnumType:{DescID: 106} -│ │ │ PUBLIC → DROPPED -│ │ │ -│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east1} +│ │ ├── • UserPrivileges:{DescID: 105, Name: admin} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east2} +│ │ ├── • UserPrivileges:{DescID: 105, Name: public} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • EnumTypeValue:{DescID: 106, Name: us-east3} +│ │ ├── • UserPrivileges:{DescID: 105, Name: root} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • Precedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • Precedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ -│ │ ├── • SchemaChild:{DescID: 106, ReferencedDescID: 105} +│ │ ├── • Schema:{DescID: 105} +│ │ │ │ PUBLIC → DROPPED +│ │ │ │ +│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} +│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ │ │ +│ │ │ ├── • Precedence dependency from ABSENT SchemaChild:{DescID: 107, ReferencedDescID: 105} +│ │ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ │ │ +│ │ │ └── • Precedence dependency from ABSENT SchemaChild:{DescID: 108, ReferencedDescID: 105} +│ │ │ rule: "back-reference in parent descriptor is removed before parent descriptor is dropped" +│ │ │ +│ │ ├── • SchemaParent:{DescID: 105, ReferencedDescID: 104} │ │ │ │ PUBLIC → ABSENT │ │ │ │ -│ │ │ └── • SameStagePrecedence dependency from DROPPED EnumType:{DescID: 106} +│ │ │ └── • SameStagePrecedence dependency from DROPPED Schema:{DescID: 105} │ │ │ rule: "descriptor dropped before dependent element removal" │ │ │ rule: "descriptor dropped right before removing back-reference in its parent descriptor" │ │ │ @@ -1330,14 +1330,6 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ Name: crdb_internal_index_1_name_placeholder │ │ TableID: 108 │ │ -│ ├── • MarkDescriptorAsDropped -│ │ DescriptorID: 105 -│ │ -│ ├── • RemoveSchemaParent -│ │ Parent: -│ │ ParentDatabaseID: 104 -│ │ SchemaID: 105 -│ │ │ ├── • NotImplementedForPublicObjects │ │ DescID: 106 │ │ ElementType: scpb.Owner @@ -1354,6 +1346,14 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ DescriptorID: 106 │ │ User: root │ │ +│ ├── • MarkDescriptorAsDropped +│ │ DescriptorID: 105 +│ │ +│ ├── • RemoveSchemaParent +│ │ Parent: +│ │ ParentDatabaseID: 104 +│ │ SchemaID: 105 +│ │ │ ├── • NotImplementedForPublicObjects │ │ DescID: 107 │ │ ElementType: scpb.Owner @@ -1406,6 +1406,13 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ ├── • DrainDescriptorName │ │ Namespace: │ │ DatabaseID: 104 +│ │ DescriptorID: 106 +│ │ Name: crdb_internal_region +│ │ SchemaID: 105 +│ │ +│ ├── • DrainDescriptorName +│ │ Namespace: +│ │ DatabaseID: 104 │ │ DescriptorID: 105 │ │ Name: public │ │ @@ -1428,13 +1435,6 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ ├── • DrainDescriptorName │ │ Namespace: │ │ DatabaseID: 104 -│ │ DescriptorID: 106 -│ │ Name: crdb_internal_region -│ │ SchemaID: 105 -│ │ -│ ├── • DrainDescriptorName -│ │ Namespace: -│ │ DatabaseID: 104 │ │ DescriptorID: 107 │ │ Name: _crdb_internal_region │ │ SchemaID: 105 @@ -1572,30 +1572,6 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ └── • SameStagePrecedence dependency from ABSENT Database:{DescID: 104} │ │ rule: "descriptor removed right before garbage collection" │ │ - │ ├── • Schema:{DescID: 105} - │ │ │ DROPPED → ABSENT - │ │ │ - │ │ ├── • Precedence dependency from ABSENT Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} - │ │ │ rule: "non-data dependents removed before descriptor" - │ │ │ - │ │ ├── • Precedence dependency from ABSENT Owner:{DescID: 105} - │ │ │ rule: "non-data dependents removed before descriptor" - │ │ │ - │ │ ├── • Precedence dependency from ABSENT UserPrivileges:{DescID: 105, Name: admin} - │ │ │ rule: "non-data dependents removed before descriptor" - │ │ │ - │ │ ├── • Precedence dependency from ABSENT UserPrivileges:{DescID: 105, Name: public} - │ │ │ rule: "non-data dependents removed before descriptor" - │ │ │ - │ │ ├── • Precedence dependency from ABSENT UserPrivileges:{DescID: 105, Name: root} - │ │ │ rule: "non-data dependents removed before descriptor" - │ │ │ - │ │ ├── • PreviousTransactionPrecedence dependency from DROPPED Schema:{DescID: 105} - │ │ │ rule: "descriptor dropped in transaction before removal" - │ │ │ - │ │ └── • Precedence dependency from ABSENT SchemaParent:{DescID: 105, ReferencedDescID: 104} - │ │ rule: "non-data dependents removed before descriptor" - │ │ │ ├── • EnumType:{DescID: 106} │ │ │ DROPPED → ABSENT │ │ │ @@ -1629,6 +1605,30 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ │ └── • Precedence dependency from ABSENT SchemaChild:{DescID: 106, ReferencedDescID: 105} │ │ rule: "non-data dependents removed before descriptor" │ │ + │ ├── • Schema:{DescID: 105} + │ │ │ DROPPED → ABSENT + │ │ │ + │ │ ├── • Precedence dependency from ABSENT Namespace:{DescID: 105, Name: public, ReferencedDescID: 104} + │ │ │ rule: "non-data dependents removed before descriptor" + │ │ │ + │ │ ├── • Precedence dependency from ABSENT Owner:{DescID: 105} + │ │ │ rule: "non-data dependents removed before descriptor" + │ │ │ + │ │ ├── • Precedence dependency from ABSENT UserPrivileges:{DescID: 105, Name: admin} + │ │ │ rule: "non-data dependents removed before descriptor" + │ │ │ + │ │ ├── • Precedence dependency from ABSENT UserPrivileges:{DescID: 105, Name: public} + │ │ │ rule: "non-data dependents removed before descriptor" + │ │ │ + │ │ ├── • Precedence dependency from ABSENT UserPrivileges:{DescID: 105, Name: root} + │ │ │ rule: "non-data dependents removed before descriptor" + │ │ │ + │ │ ├── • PreviousTransactionPrecedence dependency from DROPPED Schema:{DescID: 105} + │ │ │ rule: "descriptor dropped in transaction before removal" + │ │ │ + │ │ └── • Precedence dependency from ABSENT SchemaParent:{DescID: 105, ReferencedDescID: 104} + │ │ rule: "non-data dependents removed before descriptor" + │ │ │ ├── • AliasType:{DescID: 107, ReferencedTypeIDs: [106 107]} │ │ │ DROPPED → ABSENT │ │ │ @@ -1745,10 +1745,10 @@ EXPLAIN (ddl, verbose) DROP DATABASE multi_region_test_db CASCADE; │ Statement: DROP DATABASE multi_region_test_db CASCADE │ ├── • DeleteDescriptor - │ DescriptorID: 105 + │ DescriptorID: 106 │ ├── • DeleteDescriptor - │ DescriptorID: 106 + │ DescriptorID: 105 │ ├── • DeleteDescriptor │ DescriptorID: 107 diff --git a/pkg/sql/schema_change_plan_node.go b/pkg/sql/schema_change_plan_node.go index a3d6adb20235..dfd4750cb3ac 100644 --- a/pkg/sql/schema_change_plan_node.go +++ b/pkg/sql/schema_change_plan_node.go @@ -195,16 +195,11 @@ func (p *planner) waitForDescriptorSchemaChanges( // Wait for the descriptor to no longer be claimed by a schema change. start := timeutil.Now() - logEvery := log.Every(30 * time.Second) + logEvery := log.Every(10 * time.Second) + var wasBlocked bool for r := retry.StartWithCtx(ctx, base.DefaultRetryOptions()); r.Next(); { now := p.ExecCfg().Clock.Now() - if logEvery.ShouldLog() { - log.Infof(ctx, - "schema change waiting for concurrent schema changes on descriptor %d,"+ - " waited %v so far", descID, timeutil.Since(start), - ) - } - blocked := false + var isBlocked bool if err := p.ExecCfg().InternalDB.DescsTxn(ctx, func( ctx context.Context, txn descs.Txn, ) error { @@ -215,15 +210,29 @@ func (p *planner) waitForDescriptorSchemaChanges( if err != nil { return err } - blocked = desc.HasConcurrentSchemaChanges() + isBlocked = desc.HasConcurrentSchemaChanges() return nil }); err != nil { return err } - if !blocked { + if isBlocked { + wasBlocked = true + } else { break } + if logEvery.ShouldLog() { + log.Infof(ctx, + "schema change waiting for concurrent schema changes on descriptor %d,"+ + " waited %v so far", descID, timeutil.Since(start), + ) + } } + + if knobs := p.ExecCfg().DeclarativeSchemaChangerTestingKnobs; knobs != nil && + knobs.AfterWaitingForConcurrentSchemaChanges != nil { + knobs.AfterWaitingForConcurrentSchemaChanges(scs.stmts, wasBlocked) + } + log.Infof( ctx, "done waiting for concurrent schema changes on descriptor %d after %v", diff --git a/pkg/sql/schema_changer_test.go b/pkg/sql/schema_changer_test.go index 6f3ca4ed815c..db5a8df28b5a 100644 --- a/pkg/sql/schema_changer_test.go +++ b/pkg/sql/schema_changer_test.go @@ -2586,45 +2586,6 @@ func TestPrimaryKeyChangeWithPrecedingIndexCreation(t *testing.T) { t.Fatal(err) } - t.Run("create-index-before", func(t *testing.T) { - skip.WithIssue(t, 45510, "unskip when finished") - if _, err := sqlDB.Exec(`CREATE TABLE t.test (k INT NOT NULL, v INT)`); err != nil { - t.Fatal(err) - } - if err := sqltestutils.BulkInsertIntoTable(sqlDB, maxValue); err != nil { - t.Fatal(err) - } - - backfillNotif, _ := initBackfillNotification() - var wg sync.WaitGroup - wg.Add(1) - // Create an index on the table that will need to get rewritten. - go func() { - if _, err := sqlDB.Exec(`CREATE INDEX i ON t.test (v)`); err != nil { - t.Error(err) - } - wg.Done() - }() - - // Wait until the create index mutation has progressed before starting the alter primary key. - <-backfillNotif - - if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`); err != nil { - t.Fatal(err) - } - - wg.Wait() - - // There should be 4 k/v pairs per row: - // * the original rowid index. - // * the old index on v. - // * the new primary key on k. - // * the new index for v with k as the unique column. - testutils.SucceedsSoon(t, func() error { - return sqltestutils.CheckTableKeyCount(ctx, kvDB, 4, maxValue) - }) - }) - // Repeat the prior process but with a primary key change before. t.Run("pk-change-before", func(t *testing.T) { var wg sync.WaitGroup diff --git a/pkg/sql/schemachanger/BUILD.bazel b/pkg/sql/schemachanger/BUILD.bazel index ec883fbde8de..ec5cda149da5 100644 --- a/pkg/sql/schemachanger/BUILD.bazel +++ b/pkg/sql/schemachanger/BUILD.bazel @@ -38,22 +38,26 @@ go_test( "//pkg/sql", "//pkg/sql/catalog/descpb", "//pkg/sql/catalog/desctestutils", + "//pkg/sql/execinfra", "//pkg/sql/pgwire/pgcode", "//pkg/sql/rowenc", "//pkg/sql/schemachanger/scexec", "//pkg/sql/schemachanger/scop", "//pkg/sql/schemachanger/scplan", "//pkg/sql/schemachanger/sctest", # keep + "//pkg/sql/sqltestutils", "//pkg/sql/tests", "//pkg/testutils", "//pkg/testutils/serverutils", "//pkg/testutils/sqlutils", "//pkg/testutils/testcluster", + "//pkg/util", "//pkg/util/ctxgroup", "//pkg/util/leaktest", "//pkg/util/log", "//pkg/util/protoutil", "//pkg/util/randutil", + "//pkg/util/syncutil", "@com_github_cockroachdb_cockroach_go_v2//crdb", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_errors//errorspb", diff --git a/pkg/sql/schemachanger/scbackup/job.go b/pkg/sql/schemachanger/scbackup/job.go index e8863b6321a5..e45ff3bddfca 100644 --- a/pkg/sql/schemachanger/scbackup/job.go +++ b/pkg/sql/schemachanger/scbackup/job.go @@ -61,13 +61,14 @@ func CreateDeclarativeSchemaChangeJobs( if err != nil { return err } + const runningStatus = "restored from backup" records = append(records, scexec.MakeDeclarativeSchemaChangeJobRecord( newID, currentState.Statements, !currentState.Revertible, // NonCancelable currentState.Authorization, - screl.AllTargetDescIDs(currentState.TargetState), + screl.AllTargetStateDescIDs(currentState.TargetState), runningStatus, )) } diff --git a/pkg/sql/schemachanger/scbuild/build.go b/pkg/sql/schemachanger/scbuild/build.go index 19c55aa47c4e..352a56afdab6 100644 --- a/pkg/sql/schemachanger/scbuild/build.go +++ b/pkg/sql/schemachanger/scbuild/build.go @@ -17,7 +17,6 @@ import ( "github.com/cockroachdb/cockroach/pkg/clusterversion" "github.com/cockroachdb/cockroach/pkg/settings/cluster" "github.com/cockroachdb/cockroach/pkg/sql/catalog" - "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/privilege" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scbuild/internal/scbuildstmt" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scdecomp" @@ -58,15 +57,18 @@ func Build( redact.Safe(n.StatementTag()), ).HandlePanicAndLogError(ctx, &err) - // localMemAcc is opened to track memory allocation for local objects - // and should be cleared before this function returns. - localMemAcc := makeBoundAccount(memAcc.Monitor()) + // localMemAcc tracks memory allocations for local objects. + var localMemAcc *mon.BoundAccount defer func() { localMemAcc.Clear(ctx) }() - + if monitor := memAcc.Monitor(); monitor != nil { + acc := monitor.MakeBoundAccount() + localMemAcc = &acc + } bs := newBuilderState(ctx, dependencies, incumbent, localMemAcc) els := newEventLogState(dependencies, incumbent, n) + // TODO(fqazi): The optimizer can end up already modifying the statement above // to fully resolve names. We need to take this into account for CTAS/CREATE // VIEW statements. @@ -83,25 +85,43 @@ func Build( SchemaFeatureChecker: dependencies.FeatureChecker(), } scbuildstmt.Process(b, an.GetStatement()) - an.ValidateAnnotations() - currentStatementID := uint32(len(els.statements) - 1) - els.statements[currentStatementID].RedactedStatement = string( - dependencies.AstFormatter().FormatAstAsRedactableString(an.GetStatement(), &an.annotation)) - - // estimatedTargetStateSize is an estimated memory usage of the to-be-return scpb.TargetState. - estimatedTargetStateSize := int(unsafe.Sizeof(scpb.Target{})+2*unsafe.Sizeof(scpb.Status(0))) * len(bs.output) - if err := memAcc.Grow(ctx, int64(estimatedTargetStateSize)); err != nil { - return scpb.CurrentState{}, err + + // Generate redacted statement. + { + an.ValidateAnnotations() + currentStatementID := uint32(len(els.statements) - 1) + els.statements[currentStatementID].RedactedStatement = string( + dependencies.AstFormatter().FormatAstAsRedactableString(an.GetStatement(), &an.annotation)) + } + + // Generate returned state. + ret, loggedTargets := makeState(dependencies.ClusterSettings().Version.ActiveVersion(ctx), bs) + ret.Statements = els.statements + ret.Authorization = els.authorization + + // Update memory accounting. + if err := memAcc.Grow(ctx, ret.ByteSize()); err != nil { + panic(err) } - ts := scpb.TargetState{ - Targets: make([]scpb.Target, 0, len(bs.output)), - Statements: els.statements, - Authorization: els.authorization, + + // Write to event log and return. + logEvents(b, ret.TargetState, loggedTargets) + return ret, nil +} + +// makeState populates the declarative schema changer state returned by Build +// with the targets and the statuses present in the builderState. +func makeState( + version clusterversion.ClusterVersion, bs *builderState, +) (s scpb.CurrentState, loggedTargets []scpb.Target) { + s = scpb.CurrentState{ + TargetState: scpb.TargetState{ + Targets: make([]scpb.Target, 0, len(bs.output)), + }, + Initial: make([]scpb.Status, 0, len(bs.output)), + Current: make([]scpb.Status, 0, len(bs.output)), } - initial := make([]scpb.Status, 0, len(bs.output)) - current := make([]scpb.Status, 0, len(bs.output)) - version := dependencies.ClusterSettings().Version.ActiveVersion(ctx) - withLogEvent := make([]scpb.Target, 0, len(bs.output)) + loggedTargets = make([]scpb.Target, 0, len(bs.output)) for _, e := range bs.output { if e.metadata.Size() == 0 { // Exclude targets which weren't explicitly set. @@ -113,55 +133,20 @@ func Build( // cluster version. continue } - maxVersion := screl.MaxElementVersion(e.element) - if maxVersion != nil && version.IsActive(*maxVersion) { + if maxVersion, exists := screl.MaxElementVersion(e.element); exists && version.IsActive(maxVersion) { // Exclude the target which are no longer allowed at the active // max version. continue } t := scpb.MakeTarget(e.target, e.element, &e.metadata) - ts.Targets = append(ts.Targets, t) - initial = append(initial, e.initial) - current = append(current, e.current) + s.Targets = append(s.Targets, t) + s.Initial = append(s.Initial, e.initial) + s.Current = append(s.Current, e.current) if e.withLogEvent { - withLogEvent = append(withLogEvent, t) + loggedTargets = append(loggedTargets, t) } } - - // Ensure none of the involving descriptors have an ongoing schema change, - // unless it's newly created. - ensureNoConcurrentSchemaChange(&ts, bs) - - // Write to event log and return. - logEvents(b, ts, withLogEvent) - - return scpb.CurrentState{ - TargetState: ts, - Initial: initial, - Current: current, - }, nil -} - -// ensureNoConcurrentSchemaChange panics if any involving descriptor has an -// ongoing schema changer, unless the descriptor is being added. -func ensureNoConcurrentSchemaChange(ts *scpb.TargetState, bs *builderState) { - screl.AllTargetDescIDs(*ts).ForEach(func(id descpb.ID) { - bs.ensureDescriptor(id) - cached := bs.descCache[id] - if !cached.isBeingCreated() && cached.desc.HasConcurrentSchemaChanges() { - panic(scerrors.ConcurrentSchemaChangeError(cached.desc)) - } - }) -} - -// makeBoundAccount is the same as `monitor.MakeBountAccount` -// except that it returns a pointer. -func makeBoundAccount(monitor *mon.BytesMonitor) (ret *mon.BoundAccount) { - if monitor != nil { - memAcc := monitor.MakeBoundAccount() - ret = &memAcc - } - return ret + return s, loggedTargets } // IsFullySupportedWithFalsePositive returns if a statement is fully supported @@ -173,15 +158,6 @@ func IsFullySupportedWithFalsePositive( return scbuildstmt.IsFullySupportedWithFalsePositive(statement, version, sessiondatapb.UseNewSchemaChangerOn) } -// Export dependency interfaces. -// These are defined in the scbuildstmts package instead of scbuild to avoid -// circular import dependencies. -type ( - // FeatureChecker contains operations for checking if a schema change - // feature is allowed by the database administrator. - FeatureChecker = scbuildstmt.SchemaFeatureChecker -) - type elementState struct { // element is the element which identifies this structure. element scpb.Element @@ -255,10 +231,6 @@ type cachedDesc struct { elementIndexMap map[string]int } -func (c *cachedDesc) isBeingCreated() bool { - return c.desc == nil -} - // newBuilderState constructs a builderState. func newBuilderState( ctx context.Context, d Dependencies, incumbent scpb.CurrentState, localMemAcc *mon.BoundAccount, diff --git a/pkg/sql/schemachanger/scbuild/builder_state.go b/pkg/sql/schemachanger/scbuild/builder_state.go index 5f6f17fc8caf..915c31258366 100644 --- a/pkg/sql/schemachanger/scbuild/builder_state.go +++ b/pkg/sql/schemachanger/scbuild/builder_state.go @@ -84,6 +84,20 @@ func (b *builderState) Ensure(e scpb.Element, target scpb.TargetStatus, meta scp // Ignore no-op changes. return } + + // Check that the descriptors relevant to this element are not undergoing any + // concurrent schema changes. + screl.AllTargetDescIDs(e).ForEach(func(id descpb.ID) { + b.ensureDescriptor(id) + if c := b.descCache[id]; c != nil && c.desc != nil && c.desc.HasConcurrentSchemaChanges() { + panic(scerrors.ConcurrentSchemaChangeError(c.desc)) + } + }) + // Re-assign dst because the above function may have mutated the builder + // state. Specifically, the output slice, to which dst points to, might + // have grown and might have been reallocated. + dst = b.getExistingElementState(e) + // Henceforth all possibilities lead to the target and metadata being // overwritten. See below for explanations as to why this is legal. oldTarget, oldStatementID := dst.target, dst.metadata.StatementID diff --git a/pkg/sql/schemachanger/scbuild/dependencies.go b/pkg/sql/schemachanger/scbuild/dependencies.go index 03adf3e0b0bd..57dfd251184d 100644 --- a/pkg/sql/schemachanger/scbuild/dependencies.go +++ b/pkg/sql/schemachanger/scbuild/dependencies.go @@ -244,3 +244,12 @@ type ReferenceProvider interface { type ReferenceProviderFactory interface { NewReferenceProvider(ctx context.Context, stmt tree.Statement) (ReferenceProvider, error) } + +// Export dependency interfaces. +// These are defined in the scbuildstmts package instead of scbuild to avoid +// circular import dependencies. +type ( + // FeatureChecker contains operations for checking if a schema change + // feature is allowed by the database administrator. + FeatureChecker = scbuildstmt.SchemaFeatureChecker +) diff --git a/pkg/sql/schemachanger/scexec/testing_knobs.go b/pkg/sql/schemachanger/scexec/testing_knobs.go index 8869dd4a281b..684318390ece 100644 --- a/pkg/sql/schemachanger/scexec/testing_knobs.go +++ b/pkg/sql/schemachanger/scexec/testing_knobs.go @@ -27,6 +27,10 @@ type TestingKnobs struct { // for concurrent schema changes to finish. BeforeWaitingForConcurrentSchemaChanges func(stmts []string) + // AfterWaitingForConcurrentSchemaChanges is called at the end of waiting + // for concurrent schema changes to finish. + AfterWaitingForConcurrentSchemaChanges func(stmts []string, wasBlocked bool) + // OnPostCommitPlanError is called whenever the schema changer job returns an // error on building the state or on planning the stages. OnPostCommitPlanError func(err error) error diff --git a/pkg/sql/schemachanger/schemachanger_test.go b/pkg/sql/schemachanger/schemachanger_test.go index 07258c6aedb0..0c5736519533 100644 --- a/pkg/sql/schemachanger/schemachanger_test.go +++ b/pkg/sql/schemachanger/schemachanger_test.go @@ -31,19 +31,23 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/catalog/desctestutils" + "github.com/cockroachdb/cockroach/pkg/sql/execinfra" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" "github.com/cockroachdb/cockroach/pkg/sql/rowenc" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scexec" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scop" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scplan" + "github.com/cockroachdb/cockroach/pkg/sql/sqltestutils" "github.com/cockroachdb/cockroach/pkg/sql/tests" "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" + "github.com/cockroachdb/cockroach/pkg/util" "github.com/cockroachdb/cockroach/pkg/util/ctxgroup" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/protoutil" + "github.com/cockroachdb/cockroach/pkg/util/syncutil" "github.com/cockroachdb/errors" "github.com/cockroachdb/errors/errorspb" "github.com/lib/pq" @@ -52,6 +56,127 @@ import ( "golang.org/x/sync/errgroup" ) +// TestConcurrentDeclarativeSchemaChanges tests that concurrent declarative +// schema changes operating on the same descriptors are performed serially. +func TestConcurrentDeclarativeSchemaChanges(t *testing.T) { + defer leaktest.AfterTest(t)() + defer log.Scope(t).Close(t) + + ctx, cancel := context.WithCancel(context.Background()) + + var maxValue = 4000 + if util.RaceEnabled { + // Race builds are a lot slower, so use a smaller number of rows. + maxValue = 200 + } + + // Protects backfillNotification. + var mu syncutil.Mutex + var backfillNotification, continueNotification chan struct{} + // We have to have initBackfillNotification return the new + // channel rather than having later users read the original + // backfillNotification to make the race detector happy. + initBackfillNotification := func() (chan struct{}, chan struct{}) { + mu.Lock() + defer mu.Unlock() + backfillNotification = make(chan struct{}) + continueNotification = make(chan struct{}) + return backfillNotification, continueNotification + } + notifyBackfill := func() { + mu.Lock() + defer mu.Unlock() + if backfillNotification != nil { + close(backfillNotification) + backfillNotification = nil + } + if continueNotification != nil { + <-continueNotification + close(continueNotification) + continueNotification = nil + } + } + var addColumnBlockedCounter atomic.Uint32 + params, _ := tests.CreateTestServerParams() + params.Knobs = base.TestingKnobs{ + SQLDeclarativeSchemaChanger: &scexec.TestingKnobs{ + AfterWaitingForConcurrentSchemaChanges: func(stmts []string, wasBlocked bool) { + for _, stmt := range stmts { + if wasBlocked && strings.Contains(stmt, "ADD COLUMN") { + addColumnBlockedCounter.Add(1) + return + } + } + }, + }, + DistSQL: &execinfra.TestingKnobs{ + RunBeforeBackfillChunk: func(_ roachpb.Span) error { + notifyBackfill() + return nil + }, + }, + // Decrease the adopt loop interval so that retries happen quickly. + JobsTestingKnobs: jobs.NewTestingKnobsWithShortIntervals(), + // Prevent the GC job from running so we ensure that all the keys + // which were written remain. + GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(jobID jobspb.JobID) error { + <-ctx.Done() + return ctx.Err() + }}, + } + s, sqlDB, kvDB := serverutils.StartServer(t, params) + defer s.Stopper().Stop(ctx) + defer cancel() + + if _, err := sqlDB.Exec(`CREATE DATABASE t`); err != nil { + t.Fatal(err) + } + + if _, err := sqlDB.Exec(`CREATE TABLE t.test (k INT NOT NULL, v INT)`); err != nil { + t.Fatal(err) + } + if err := sqltestutils.BulkInsertIntoTable(sqlDB, maxValue); err != nil { + t.Fatal(err) + } + + backfillNotif, continueNotif := initBackfillNotification() + var wg sync.WaitGroup + wg.Add(1) + go func() { + if _, err := sqlDB.Exec(`CREATE INDEX i1 ON t.test (v)`); err != nil { + t.Error(err) + } + wg.Done() + }() + + // Wait until the create index schema change job has started + // before kicking off the add column + <-backfillNotif + require.Zero(t, addColumnBlockedCounter.Load()) + wg.Add(1) + go func() { + if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD COLUMN w INT NOT NULL DEFAULT 42`); err != nil { + t.Error(err) + } + wg.Done() + }() + + // Unblock the create index job. + continueNotif <- struct{}{} + wg.Wait() + + // The ADD COLUMN schema change must have been blocked. + require.NotZero(t, addColumnBlockedCounter.Load()) + + // There should be 3 k/v pairs per row: + // * the original primary index keyed on rowid, + // * the secondary index on v with rowid as key suffix, + // * the new primary index, still keyed on rowid, but with w stored. + testutils.SucceedsSoon(t, func() error { + return sqltestutils.CheckTableKeyCount(ctx, kvDB, 3, maxValue) + }) +} + func TestSchemaChangeWaitsForOtherSchemaChanges(t *testing.T) { defer leaktest.AfterTest(t)() diff --git a/pkg/sql/schemachanger/scplan/internal/scstage/build.go b/pkg/sql/schemachanger/scplan/internal/scstage/build.go index 1b99761a608f..715e5f001bf3 100644 --- a/pkg/sql/schemachanger/scplan/internal/scstage/build.go +++ b/pkg/sql/schemachanger/scplan/internal/scstage/build.go @@ -64,7 +64,7 @@ func BuildStages( return m }(), startingPhase: phase, - descIDs: screl.AllTargetDescIDs(init.TargetState), + descIDs: screl.AllTargetStateDescIDs(init.TargetState), withSanityChecks: withSanityChecks, } // Build stages for all remaining phases. diff --git a/pkg/sql/schemachanger/screl/scalars.go b/pkg/sql/schemachanger/screl/scalars.go index e2452e30fd35..bb552c8084c3 100644 --- a/pkg/sql/schemachanger/screl/scalars.go +++ b/pkg/sql/schemachanger/screl/scalars.go @@ -41,33 +41,38 @@ func GetIndexID(e scpb.Element) (catid.IndexID, bool) { return v.(catid.IndexID), true } -// AllTargetDescIDs returns all the descriptor IDs referenced in the -// target state's elements. This is a superset of the IDs of the descriptors -// affected by the schema change. -func AllTargetDescIDs(s scpb.TargetState) (ids catalog.DescriptorIDSet) { +// AllTargetStateDescIDs applies AllTargetDescIDs to the whole target state. +func AllTargetStateDescIDs(s scpb.TargetState) (ids catalog.DescriptorIDSet) { for i := range s.Targets { - e := s.Targets[i].Element() - // Handle special cases to tighten this superset a bit. - switch te := e.(type) { - case *scpb.Namespace: - // Ignore the parent database and schema in the namespace element: - // - the parent schema of an object has no back-references to it, - // - the parent database has back-references to a schema, but these - // will be captured by the scpb.SchemaParent target. - ids.Add(te.DescriptorID) - case *scpb.SchemaChild: - // Ignore the parent schema, it won't have back-references. - ids.Add(te.ChildObjectID) - case *scpb.TableData: - // Ignore the parent database in the table data element, the parent - // database won't have back-references to any tables. - ids.Add(te.TableID) - default: - _ = WalkDescIDs(e, func(id *catid.DescID) error { - ids.Add(*id) - return nil - }) - } + AllTargetDescIDs(s.Targets[i].Element()).ForEach(ids.Add) + } + return ids +} + +// AllTargetDescIDs returns all the descriptor IDs referenced in the element. +// This is a superset of the IDs of the descriptors actually affected by the +// schema change. +func AllTargetDescIDs(e scpb.Element) (ids catalog.DescriptorIDSet) { + // Handle special cases to tighten this superset a bit. + switch te := e.(type) { + case *scpb.Namespace: + // Ignore the parent database and schema in the namespace element: + // - the parent schema of an object has no back-references to it, + // - the parent database has back-references to a schema, but these + // will be captured by the scpb.SchemaParent target. + ids.Add(te.DescriptorID) + case *scpb.SchemaChild: + // Ignore the parent schema, it won't have back-references. + ids.Add(te.ChildObjectID) + case *scpb.TableData: + // Ignore the parent database in the table data element, the parent + // database won't have back-references to any tables. + ids.Add(te.TableID) + default: + _ = WalkDescIDs(e, func(id *catid.DescID) error { + ids.Add(*id) + return nil + }) } return ids } @@ -133,14 +138,12 @@ func MinElementVersion(el scpb.Element) clusterversion.Key { } } -// MaxElementVersion returns the minimum cluster version at which an element may -// be used. -func MaxElementVersion(el scpb.Element) (version *clusterversion.Key) { - var v clusterversion.Key +// MaxElementVersion returns the maximum cluster version at which an element +// may be used. +func MaxElementVersion(el scpb.Element) (version clusterversion.Key, exists bool) { switch el.(type) { case *scpb.SecondaryIndexPartial: - v = clusterversion.V23_1_SchemaChangerDeprecatedIndexPredicates - return &v + return clusterversion.V23_1_SchemaChangerDeprecatedIndexPredicates, true /* exists */ } - return nil + return version, false /* exists */ } diff --git a/pkg/sql/schemachanger/sctest/cumulative.go b/pkg/sql/schemachanger/sctest/cumulative.go index 657e36acfe92..2167cefef907 100644 --- a/pkg/sql/schemachanger/sctest/cumulative.go +++ b/pkg/sql/schemachanger/sctest/cumulative.go @@ -1016,7 +1016,7 @@ func Backup(t *testing.T, path string, newCluster NewClusterFunc) { }, func(db *gosql.DB) { tdb := sqlutils.MakeSQLRunner(db) var ok bool - dbName, ok = maybeGetDatabaseForIDs(t, tdb, screl.AllTargetDescIDs(pl.TargetState)) + dbName, ok = maybeGetDatabaseForIDs(t, tdb, screl.AllTargetStateDescIDs(pl.TargetState)) if ok { tdb.Exec(t, fmt.Sprintf("USE %q", dbName)) } @@ -1717,7 +1717,7 @@ func BackupMixedVersionElements(t *testing.T, path string, newCluster NewMixedCl }, func(db *gosql.DB) { tdb := sqlutils.MakeSQLRunner(db) var ok bool - dbName, ok = maybeGetDatabaseForIDs(t, tdb, screl.AllTargetDescIDs(pl.TargetState)) + dbName, ok = maybeGetDatabaseForIDs(t, tdb, screl.AllTargetStateDescIDs(pl.TargetState)) if ok { tdb.Exec(t, fmt.Sprintf("USE %q", dbName)) }