From 149416b13e5d39bf0f4c306fd2a9b313e293a595 Mon Sep 17 00:00:00 2001 From: Lucy Zhang Date: Tue, 24 Nov 2020 12:20:46 -0500 Subject: [PATCH 1/2] sql: allow for pre-19.2 foreign keys in table validation We introduced a bug in v20.2 where we failed to upgrade referenced descriptors' FK representations from pre-19.2 descriptors when validating cross-references for tables, leading to validation failures that would make the table unusable. This PR gets rid of the validation errors by having `Validate()` account for pre-19.2-style foreign keys on referenced table descriptors. Release note (bug fix): Fixes a bug where tables and metadata were unavailable due to spurious `missing fk back reference` validation errors. --- pkg/sql/catalog/tabledesc/structured.go | 127 ++++++++++++++++++- pkg/sql/catalog/tabledesc/structured_test.go | 116 ++++++++++++++--- 2 files changed, 224 insertions(+), 19 deletions(-) diff --git a/pkg/sql/catalog/tabledesc/structured.go b/pkg/sql/catalog/tabledesc/structured.go index 81c1c5eaa504..63e59c01833a 100644 --- a/pkg/sql/catalog/tabledesc/structured.go +++ b/pkg/sql/catalog/tabledesc/structured.go @@ -1532,10 +1532,72 @@ func (desc *Immutable) validateCrossReferences(ctx context.Context, dg catalog.D } return nil }) - if !found { - return errors.AssertionFailedf("missing fk back reference %q to %q from %q", + if found { + continue + } + // In 20.2 we introduced a bug where we fail to upgrade the FK references + // on the referenced descriptors from their pre-19.2 format when reading + // them during validation (#57032). So we account for the possibility of + // un-upgraded foreign key references on the other table. This logic + // somewhat parallels the logic in maybeUpgradeForeignKeyRepOnIndex. + unupgradedFKsPresent := false + if err := referencedTable.ForeachIndex(catalog.IndexOpts{}, func( + referencedIdx *descpb.IndexDescriptor, isPrimary bool, + ) error { + if found { + // TODO (lucy): If we ever revisit the tabledesc.Immutable methods, add + // a way to break out of the index loop. + return nil + } + if len(referencedIdx.ReferencedBy) > 0 { + unupgradedFKsPresent = true + } else { + return nil + } + // Determine whether the index on the other table is a unique index that + // could support this FK constraint. + if !referencedIdx.IsValidReferencedIndex(fk.ReferencedColumnIDs) { + return nil + } + // Now check the backreferences. Backreferences in ReferencedBy only had + // Index and Table populated. + for i := range referencedIdx.ReferencedBy { + backref := &referencedIdx.ReferencedBy[i] + if backref.Table != desc.ID { + continue + } + // Look up the index that the un-upgraded reference refers to and + // see if that index could support the foreign key reference. (Note + // that it shouldn't be possible for this index to not exist. See + // planner.MaybeUpgradeDependentOldForeignKeyVersionTables, which is + // called from the drop index implementation.) + originalOriginIndex, err := desc.FindIndexByID(backref.Index) + if err != nil { + return errors.AssertionFailedf( + "missing index %d on %q from pre-19.2 foreign key "+ + "backreference %q on %q", + backref.Index, desc.Name, fk.Name, referencedTable.GetName(), + ) + } + if originalOriginIndex.IsValidOriginIndex(fk.OriginColumnIDs) { + found = true + break + } + } + return nil + }); err != nil { + return err + } + if found { + continue + } + if unupgradedFKsPresent { + return errors.AssertionFailedf("missing fk back reference %q to %q "+ + "from %q (un-upgraded foreign key references present)", fk.Name, desc.Name, referencedTable.GetName()) } + return errors.AssertionFailedf("missing fk back reference %q to %q from %q", + fk.Name, desc.Name, referencedTable.GetName()) } for i := range desc.InboundFKs { backref := &desc.InboundFKs[i] @@ -1551,10 +1613,67 @@ func (desc *Immutable) validateCrossReferences(ctx context.Context, dg catalog.D } return nil }) - if !found { - return errors.AssertionFailedf("missing fk forward reference %q to %q from %q", + if found { + continue + } + // In 20.2 we introduced a bug where we fail to upgrade the FK references + // on the referenced descriptors from their pre-19.2 format when reading + // them during validation (#57032). So we account for the possibility of + // un-upgraded foreign key references on the other table. This logic + // somewhat parallels the logic in maybeUpgradeForeignKeyRepOnIndex. + unupgradedFKsPresent := false + if err := originTable.ForeachIndex(catalog.IndexOpts{}, func( + originIdx *descpb.IndexDescriptor, isPrimary bool, + ) error { + if found { + // TODO (lucy): If we ever revisit the tabledesc.Immutable methods, add + // a way to break out of the index loop. + return nil + } + fk := originIdx.ForeignKey + if fk.IsSet() { + unupgradedFKsPresent = true + } else { + return nil + } + // Determine whether the index on the other table is a index that could + // support this FK constraint on the referencing side. Such an index would + // have been required in earlier versions. + if !originIdx.IsValidOriginIndex(backref.OriginColumnIDs) { + return nil + } + if fk.Table != desc.ID { + return nil + } + // Look up the index that the un-upgraded reference refers to and + // see if that index could support the foreign key reference. (Note + // that it shouldn't be possible for this index to not exist. See + // planner.MaybeUpgradeDependentOldForeignKeyVersionTables, which is + // called from the drop index implementation.) + originalReferencedIndex, err := desc.FindIndexByID(fk.Index) + if err != nil { + return errors.AssertionFailedf( + "missing index %d on %q from pre-19.2 foreign key forward reference %q on %q", + fk.Index, desc.Name, backref.Name, originTable.GetName(), + ) + } + if originalReferencedIndex.IsValidReferencedIndex(backref.OriginColumnIDs) { + found = true + } + return nil + }); err != nil { + return err + } + if found { + continue + } + if unupgradedFKsPresent { + return errors.AssertionFailedf("missing fk forward reference %q to %q from %q "+ + "(un-upgraded foreign key references present)", backref.Name, desc.Name, originTable.GetName()) } + return errors.AssertionFailedf("missing fk forward reference %q to %q from %q", + backref.Name, desc.Name, originTable.GetName()) } for _, index := range desc.AllNonDropIndexes() { diff --git a/pkg/sql/catalog/tabledesc/structured_test.go b/pkg/sql/catalog/tabledesc/structured_test.go index f18fa9cd528c..47d8110f4002 100644 --- a/pkg/sql/catalog/tabledesc/structured_test.go +++ b/pkg/sql/catalog/tabledesc/structured_test.go @@ -672,7 +672,7 @@ func TestValidateCrossTableReferences(t *testing.T) { otherDescs []descpb.TableDescriptor }{ // Foreign keys - { + { // 0 err: `invalid foreign key: missing table=52: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -692,7 +692,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, otherDescs: nil, }, - { + { // 1 err: `missing fk back reference "fk" to "foo" from "baz"`, desc: descpb.TableDescriptor{ ID: 51, @@ -718,7 +718,7 @@ func TestValidateCrossTableReferences(t *testing.T) { FormatVersion: descpb.InterleavedFormatVersion, }}, }, - { + { // 2 err: `invalid foreign key backreference: missing table=52: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -737,7 +737,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }, }, - { + { // 3 err: `missing fk forward reference "fk" to "foo" from "baz"`, desc: descpb.TableDescriptor{ ID: 51, @@ -767,9 +767,93 @@ func TestValidateCrossTableReferences(t *testing.T) { FormatVersion: descpb.InterleavedFormatVersion, }}, }, + { // 4 + // Regression test for #57066: We can handle one of the referenced tables + // having a pre-19.2 foreign key reference. + err: "", + desc: descpb.TableDescriptor{ + ID: 51, + Name: "foo", + ParentID: 1, + UnexposedParentSchemaID: keys.PublicSchemaID, + FormatVersion: descpb.InterleavedFormatVersion, + Indexes: []descpb.IndexDescriptor{ + { + ID: 2, + ColumnIDs: []descpb.ColumnID{1, 2}, + }, + }, + OutboundFKs: []descpb.ForeignKeyConstraint{ + { + Name: "fk", + ReferencedTableID: 52, + ReferencedColumnIDs: []descpb.ColumnID{1}, + OriginTableID: 51, + OriginColumnIDs: []descpb.ColumnID{1}, + }, + }, + }, + otherDescs: []descpb.TableDescriptor{{ + ID: 52, + Name: "baz", + ParentID: 1, + UnexposedParentSchemaID: keys.PublicSchemaID, + FormatVersion: descpb.InterleavedFormatVersion, + Indexes: []descpb.IndexDescriptor{ + { + Unique: true, + ColumnIDs: []descpb.ColumnID{1}, + ReferencedBy: []descpb.ForeignKeyReference{{Table: 51, Index: 2}}, + }, + }, + }}, + }, + { // 5 + // Regression test for #57066: We can handle one of the referenced tables + // having a pre-19.2 foreign key reference. + err: "", + desc: descpb.TableDescriptor{ + ID: 51, + Name: "foo", + ParentID: 1, + UnexposedParentSchemaID: keys.PublicSchemaID, + FormatVersion: descpb.InterleavedFormatVersion, + Indexes: []descpb.IndexDescriptor{ + { + ID: 2, + ColumnIDs: []descpb.ColumnID{1}, + Unique: true, + }, + }, + InboundFKs: []descpb.ForeignKeyConstraint{ + { + Name: "fk", + ReferencedTableID: 51, + ReferencedColumnIDs: []descpb.ColumnID{1}, + OriginTableID: 52, + OriginColumnIDs: []descpb.ColumnID{1}, + }, + }, + }, + otherDescs: []descpb.TableDescriptor{{ + ID: 52, + Name: "baz", + ParentID: 1, + UnexposedParentSchemaID: keys.PublicSchemaID, + FormatVersion: descpb.InterleavedFormatVersion, + Indexes: []descpb.IndexDescriptor{ + { + ID: 2, + Unique: true, + ColumnIDs: []descpb.ColumnID{1}, + ForeignKey: descpb.ForeignKeyReference{Table: 51, Index: 2}, + }, + }, + }}, + }, // Interleaves - { + { // 6 err: `invalid interleave: missing table=52 index=2: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -786,7 +870,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, otherDescs: nil, }, - { + { // 7 err: `invalid interleave: missing table=baz index=2: index-id "2" does not exist`, desc: descpb.TableDescriptor{ Name: "foo", @@ -808,7 +892,7 @@ func TestValidateCrossTableReferences(t *testing.T) { UnexposedParentSchemaID: keys.PublicSchemaID, }}, }, - { + { // 8 err: `missing interleave back reference to "foo"@"bar" from "baz"@"qux"`, desc: descpb.TableDescriptor{ Name: "foo", @@ -834,7 +918,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }}, }, - { + { // 9 err: `invalid interleave backreference table=52 index=2: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -847,7 +931,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }, }, - { + { // 10 err: `invalid interleave backreference table=baz index=2: index-id "2" does not exist`, desc: descpb.TableDescriptor{ Name: "foo", @@ -866,7 +950,7 @@ func TestValidateCrossTableReferences(t *testing.T) { UnexposedParentSchemaID: keys.PublicSchemaID, }}, }, - { + { // 11 err: `broken interleave backward reference from "foo"@"bar" to "baz"@"qux"`, desc: descpb.TableDescriptor{ Name: "foo", @@ -890,7 +974,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }}, }, - { + { // 12 err: `type ID 500 in descriptor not found: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -913,7 +997,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }, // Add some expressions with invalid type references. - { + { // 13 err: `type ID 500 in descriptor not found: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -936,7 +1020,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }, }, - { + { // 14 err: `type ID 500 in descriptor not found: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -959,7 +1043,7 @@ func TestValidateCrossTableReferences(t *testing.T) { }, }, }, - { + { // 15 err: `type ID 500 in descriptor not found: descriptor not found`, desc: descpb.TableDescriptor{ Name: "foo", @@ -984,7 +1068,9 @@ func TestValidateCrossTableReferences(t *testing.T) { } desc := NewImmutable(test.desc) if err := desc.ValidateCrossReferences(ctx, descs); err == nil { - t.Errorf("%d: expected \"%s\", but found success: %+v", i, test.err, test.desc) + if test.err != "" { + t.Errorf("%d: expected \"%s\", but found success: %+v", i, test.err, test.desc) + } } else if test.err != err.Error() && "internal error: "+test.err != err.Error() { t.Errorf("%d: expected \"%s\", but found \"%s\"", i, test.err, err.Error()) } From bb95a38d12490c7f58b71ffd9f7e56c50d7176a2 Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Tue, 24 Nov 2020 13:27:29 -0500 Subject: [PATCH 2/2] catalogkv: add testing of descriptor unwrapping and validation This commit adds a framework to test that descriptors validate properly. It also adds testdata and a bash script to generate that test data. This test is to exercise a problematic path whereby tables constructed in v19.1 would fail to validate in v20.2. Release note: None --- pkg/sql/catalog/catalogkv/BUILD.bazel | 19 ++- .../fkupgrade/descriptors.csv | 45 +++++++ .../unwrap_validation/fkupgrade/generate.sh | 100 ++++++++++++++ .../catalogkv/unwrap_validation_test.go | 127 ++++++++++++++++++ 4 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/descriptors.csv create mode 100755 pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/generate.sh create mode 100644 pkg/sql/catalog/catalogkv/unwrap_validation_test.go diff --git a/pkg/sql/catalog/catalogkv/BUILD.bazel b/pkg/sql/catalog/catalogkv/BUILD.bazel index d17d88857172..4368446a4aa4 100644 --- a/pkg/sql/catalog/catalogkv/BUILD.bazel +++ b/pkg/sql/catalog/catalogkv/BUILD.bazel @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "catalogkv", @@ -32,3 +32,20 @@ go_library( "//vendor/github.com/cockroachdb/errors", ], ) + +go_test( + name = "catalogkv_test", + srcs = ["unwrap_validation_test.go"], + data = glob(["testdata/**"]), + embed = [":catalogkv"], + deps = [ + "//pkg/sql/catalog", + "//pkg/sql/catalog/descpb", + "//pkg/testutils", + "//pkg/util/encoding/csv", + "//pkg/util/hlc", + "//pkg/util/protoutil", + "//vendor/github.com/cockroachdb/errors", + "//vendor/github.com/stretchr/testify/require", + ], +) diff --git a/pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/descriptors.csv b/pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/descriptors.csv new file mode 100644 index 000000000000..71d820f714ca --- /dev/null +++ b/pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/descriptors.csv @@ -0,0 +1,45 @@ +id,descriptor +1,12210a0673797374656d10011a150a090a0561646d696e10300a080a04726f6f741030 +2,0ad8020a096e616d6573706163651802200128013a0a08c0dcd5b4e4baa2a516421e0a08706172656e74494410011a0c08011040180030005014600020003000421a0a046e616d6510021a0c0807100018003000501960002000300042180a02696410031a0c08011040180030005014600020013000480452550a077072696d617279100118012208706172656e74494422046e616d6530013002400040004a10080010001a00200028003000380040005a007a020800800100880100900100980100a20106080012001800a8010060026a150a090a0561646d696e10300a080a04726f6f741030800101880103980100b201210a077072696d61727910001a08706172656e7449441a046e616d65200120022800b201140a0866616d5f335f696410031a02696420032803b80104c20100e80100f2010408001200f801008002009202009a020a08c0dcd5b4e4baa2a516b20200b80200c00200 +3,0af1010a0a64657363726970746f721803200128013a0042140a02696410011a08080110401800300320003000421c0a0a64657363726970746f7210021a08080810001800300020013000480352300a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a02080080010060026a150a090a0561646d696e10300a080a04726f6f741030800101880103980100b201130a077072696d61727910001a02696420012800b201240a1066616d5f325f64657363726970746f7210021a0a64657363726970746f7220022802b80103c20100e80100f2010408001200f80100800200 +4,0acc020a0575736572731804200128013a00421a0a08757365726e616d6510011a0808071000180030002000300042200a0e68617368656450617373776f726410021a08080810001800300020013000421f0a066973526f6c6510031a08080010001800300020002a0566616c73653000480452360a077072696d617279100118012208757365726e616d65300140004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201190a077072696d61727910001a08757365726e616d6520012800b2012c0a1466616d5f325f68617368656450617373776f726410021a0e68617368656450617373776f726420022802b2011c0a0c66616d5f335f6973526f6c6510031a066973526f6c6520032803b80104c20100e80100f2010408001200f80100800200 +5,0ae2010a057a6f6e65731805200128013a0042140a02696410011a0808011040180030032000300042180a06636f6e66696710021a08080810001800300020013000480352300a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201130a077072696d61727910001a02696420012800b2011c0a0c66616d5f325f636f6e66696710021a06636f6e66696720022802b80103c20100e80100f2010408001200f80100800200 +6,0ade020a0873657474696e67731806200128013a0042160a046e616d6510011a0808071000180030002000300042170a0576616c756510021a0808071000180030002000300042300a0b6c6173745570646174656410031a08080510001800300020002a116e6f7728293a3a3a54494d455354414d503000421b0a0976616c75655479706510041a08080710001800300020013000480552320a077072696d6172791001180122046e616d65300140004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201590a2666616d5f305f6e616d655f76616c75655f6c617374557064617465645f76616c75655479706510001a046e616d651a0576616c75651a0b6c617374557064617465641a0976616c75655479706520012002200320042800b80101c20100e80100f2010408001200f80100800200 +8,0ac6020a0774656e616e74731808200128013a00421e0a02696410011a0c0801104018003000501460002000300068007000780042280a0661637469766510021a0c08001000180030005010600020002a0474727565300068007000780042200a04696e666f10031a0c080810001800300050116000200130006800700078004804524b0a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a80100b20100ba010060026a1d0a090a0561646d696e10300a080a04726f6f74103012046e6f64651801800101880103980100b201250a077072696d61727910001a0269641a066163746976651a04696e666f2001200220032800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200 +11,0ad4020a056c65617365180b200128013a0042180a0664657363494410011a0808011040180030032000300042190a0776657273696f6e10021a0808011040180030032000300042180a066e6f6465494410031a08080110401800300320003000421c0a0a65787069726174696f6e10041a080805100018003000200030004805525d0a077072696d617279100118012206646573634944220776657273696f6e220a65787069726174696f6e22066e6f64654944300130023004300340004000400040004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2013a0a077072696d61727910001a066465736349441a0776657273696f6e1a066e6f646549441a0a65787069726174696f6e20012002200320042800b80101c20100e80100f2010408001200f80100800200 +12,0afe030a086576656e746c6f67180c200128013a00421b0a0974696d657374616d7010011a08080510001800300020003000421b0a096576656e745479706510021a08080710001800300020003000421a0a08746172676574494410031a08080110401800300320003000421d0a0b7265706f7274696e67494410041a0808011040180030032000300042160a04696e666f10051a0808071000180030002001300042250a08756e69717565494410061a08080810001800300020002a09757569645f763428293000480752450a077072696d61727910011801220974696d657374616d702208756e69717565494430013006400040004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201260a077072696d61727910001a0974696d657374616d701a08756e697175654944200120062800b201220a0f66616d5f325f6576656e745479706510021a096576656e745479706520022802b201200a0e66616d5f335f746172676574494410031a08746172676574494420032803b201260a1166616d5f345f7265706f7274696e67494410041a0b7265706f7274696e67494420042804b201180a0a66616d5f355f696e666f10051a04696e666f20052805b80106c20100e80100f2010408001200f80100800200 +13,0abf040a0872616e67656c6f67180d200128013a00421b0a0974696d657374616d7010011a0808051000180030002000300042190a0772616e6765494410021a0808011040180030032000300042190a0773746f7265494410031a08080110401800300320003000421b0a096576656e745479706510041a08080710001800300020003000421e0a0c6f7468657252616e6765494410051a0808011040180030032001300042160a04696e666f10061a08080710001800300020013000422a0a08756e69717565494410071a08080110401800300320002a0e756e697175655f726f77696428293000480852450a077072696d61727910011801220974696d657374616d702208756e69717565494430013007400040004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201260a077072696d61727910001a0974696d657374616d701a08756e697175654944200120072800b2011e0a0d66616d5f325f72616e6765494410021a0772616e6765494420022802b2011e0a0d66616d5f335f73746f7265494410031a0773746f7265494420032803b201220a0f66616d5f345f6576656e745479706510041a096576656e745479706520042804b201280a1266616d5f355f6f7468657252616e6765494410051a0c6f7468657252616e6765494420052805b201180a0a66616d5f365f696e666f10061a04696e666f20062806b80107c20100e80100f2010408001200f80100800200 +14,0aa7020a027569180e200128013a0042150a036b657910011a0808071000180030002000300042170a0576616c756510021a08080810001800300020013000421d0a0b6c6173745570646174656410031a08080510001800300020003000480452310a077072696d6172791001180122036b6579300140004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201140a077072696d61727910001a036b657920012800b2011a0a0b66616d5f325f76616c756510021a0576616c756520022802b201260a1166616d5f335f6c6173745570646174656410031a0b6c6173745570646174656420032803b80104c20100e80100f2010408001200f80100800200 +15,0a93080a046a6f6273180f2001280a3a00422e0a02696410011a0c08011040180030005014600020002a0e756e697175655f726f7769642829300068007000780042220a0673746174757310021a0c0807100018003000501960002000300068007000780042370a076372656174656410031a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780042230a077061796c6f616410041a0c0808100018003000501160002000300068007000780042240a0870726f677265737310051a0c08081000180030005011600020013000680070007800422b0a0f637265617465645f62795f7479706510061a0c0807100018003000501960002001300068007000780042290a0d637265617465645f62795f696410071a0c08011040180030005014600020013000680070007800422c0a10636c61696d5f73657373696f6e5f696410081a0c08081000180030005011600020013000680070007800422d0a11636c61696d5f696e7374616e63655f696410091a0c08011040180030005014600020013000680070007800480a524b0a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a020800800100880100900100980100a20106080012001800a80100b20100ba01005a6e0a176a6f62735f7374617475735f637265617465645f696478100218002206737461747573220763726561746564300230033801400040004a10080010001a00200028003000380040005a007a020800800100880100900100980100a20106080012001800a80100b20100ba01005a96010a266a6f62735f637265617465645f62795f747970655f637265617465645f62795f69645f69647810031800220f637265617465645f62795f74797065220d637265617465645f62795f69642a06737461747573300630073801400040004a10080010001a00200028003000380040005a0070027a020800800100880101900101980100a20106080012001800a80100b20100ba010060046a1b0a0a0a0561646d696e10f0030a090a04726f6f7410f00312001800800104880103980100b2016f0a1f66616d5f305f69645f7374617475735f637265617465645f7061796c6f616410001a0269641a067374617475731a07637265617465641a077061796c6f61641a0f637265617465645f62795f747970651a0d637265617465645f62795f69642001200220032004200620072800b2011a0a0870726f677265737310011a0870726f677265737320052805b201340a05636c61696d10021a10636c61696d5f73657373696f6e5f69641a11636c61696d5f696e7374616e63655f6964200820092808b80103c20100e80100f2010408001200f801008002009202009a020a088080aeeee4baa2a516b20200b80200c00200c80200 +19,0af9050a0c7765625f73657373696f6e731813200128013a0042240a02696410011a08080110401800300320002a0e756e697175655f726f77696428293000421e0a0c68617368656453656372657410021a08080810001800300020003000421a0a08757365726e616d6510031a08080710001800300020003000422e0a0963726561746564417410041a08080510001800300020002a116e6f7728293a3a3a54494d455354414d503000421b0a0965787069726573417410051a08080510001800300020003000421b0a097265766f6b6564417410061a08080510001800300020013000422f0a0a6c61737455736564417410071a08080510001800300020002a116e6f7728293a3a3a54494d455354414d503000421b0a096175646974496e666f10081a08080710001800300020013000480952300a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a0208008001005a4c0a1a7765625f73657373696f6e735f6578706972657341745f6964781002180022096578706972657341743005380140004a10080010001a00200028003000380040005a007a0208008001005a4c0a1a7765625f73657373696f6e735f6372656174656441745f6964781003180022096372656174656441743004380140004a10080010001a00200028003000380040005a007a02080080010060046a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201bb010a5166616d5f305f69645f6861736865645365637265745f757365726e616d655f6372656174656441745f6578706972657341745f7265766f6b656441745f6c6173745573656441745f6175646974496e666f10001a0269641a0c6861736865645365637265741a08757365726e616d651a096372656174656441741a096578706972657341741a097265766f6b656441741a0a6c6173745573656441741a096175646974496e666f200120022003200420052006200720082800b80101c20100e80100f2010408001200f80100800200 +20,0aab050a107461626c655f737461746973746963731814200128013a0042190a077461626c65494410011a08080110401800300320003000422d0a0b737461746973746963494410021a08080110401800300320002a0e756e697175655f726f7769642829300042160a046e616d6510031a0808071000180030002001300042280a09636f6c756d6e49447310041a15080f1040180020ffffffffffffffffff013003380120003000422e0a0963726561746564417410051a08080510001800300020002a116e6f7728293a3a3a54494d455354414d503000421a0a08726f77436f756e7410061a08080110401800300320003000421f0a0d64697374696e6374436f756e7410071a08080110401800300320003000421b0a096e756c6c436f756e7410081a08080110401800300320003000421b0a09686973746f6772616d10091a08080810001800300020013000480a52460a077072696d6172791001180122077461626c654944220b737461746973746963494430013002400040004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201d6010a5d66616d5f305f7461626c6549445f73746174697374696349445f6e616d655f636f6c756d6e4944735f6372656174656441745f726f77436f756e745f64697374696e6374436f756e745f6e756c6c436f756e745f686973746f6772616d10001a077461626c6549441a0b73746174697374696349441a046e616d651a09636f6c756d6e4944731a096372656174656441741a08726f77436f756e741a0d64697374696e6374436f756e741a096e756c6c436f756e741a09686973746f6772616d2001200220032004200520062007200820092800b80101c20100e80100f2010408001200f80100800200 +21,0a8a030a096c6f636174696f6e731815200128013a00421d0a0b6c6f63616c6974794b657910011a08080710001800300020003000421f0a0d6c6f63616c69747956616c756510021a08080710001800300020003000421a0a086c6174697475646510031a080803100f1812300020003000421b0a096c6f6e67697475646510041a080803100f18123000200030004805524c0a077072696d61727910011801220b6c6f63616c6974794b6579220d6c6f63616c69747956616c756530013002400040004a10080010001a00200028003000380040005a007a02080080010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201710a3266616d5f305f6c6f63616c6974794b65795f6c6f63616c69747956616c75655f6c617469747564655f6c6f6e67697475646510001a0b6c6f63616c6974794b65791a0d6c6f63616c69747956616c75651a086c617469747564651a096c6f6e67697475646520012002200320042800b80101c20100e80100f2010408001200f80100800200 +23,0aae030a0c726f6c655f6d656d626572731817200128013a0042160a04726f6c6510011a0808071000180030002000300042180a066d656d62657210021a0808071000180030002000300042190a07697341646d696e10031a080800100018003000200030004804523e0a077072696d617279100118012204726f6c6522066d656d62657230013002400040004a10080010001a00200028003000380040005a007a0208008001005a420a15726f6c655f6d656d626572735f726f6c655f696478100218002204726f6c653001380240004a10080010001a00200028003000380040005a007a0208008001005a460a17726f6c655f6d656d626572735f6d656d6265725f6964781003180022066d656d6265723002380140004a10080010001a00200028003000380040005a007a02080080010060046a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2011f0a077072696d61727910001a04726f6c651a066d656d626572200120022800b2011e0a0d66616d5f335f697341646d696e10031a07697341646d696e20032803b80104c20100e80100f2010408001200f80100800200 +24,0a8b030a08636f6d6d656e74731818200128053a0a08b0c1bcc8fabaa2a51642180a047479706510011a0a0801104018003000501420003000421d0a096f626a6563745f696410021a0a0801104018003000501420003000421a0a067375625f696410031a0a0801104018003000501420003000421b0a07636f6d6d656e7410041a0a0807100018003000501920003000480552500a077072696d6172791001180122047479706522096f626a6563745f696422067375625f69643001300230034000400040004a10080010001a00200028003000380040005a007a02080080010088010060026a230a0a0a0561646d696e10f0030a0a0a067075626c696310200a090a04726f6f7410f003800101880103980100b2012c0a077072696d61727910001a04747970651a096f626a6563745f69641a067375625f69642001200220032800b2011e0a0d66616d5f345f636f6d6d656e7410041a07636f6d6d656e7420042804b80105c20100e80100f2010408001200f801008002009202009a020a08c0dcd5b4e4baa2a516b20200 +25,0aac040a1c7265706c69636174696f6e5f636f6e73747261696e745f73746174731819200128023a0a08f8d197c2fabaa2a516421b0a077a6f6e655f696410011a0a0801104018003000501420003000421e0a0a7375627a6f6e655f696410021a0a080110401800300050142000300042180a047479706510031a0a0807100018003000501920003000421a0a06636f6e66696710041a0a0807100018003000501920003000421d0a097265706f72745f696410051a0a080110401800300050142000300042240a0f76696f6c6174696f6e5f737461727410061a0b080910001800300050a0092001300042240a1076696f6c6174696e675f72616e67657310071a0a08011040180030005014200030004808525e0a077072696d6172791001180122077a6f6e655f6964220a7375627a6f6e655f69642204747970652206636f6e666967300130023003300440004000400040004a10080010001a00200028003000380040005a007a02080080010088010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2016c0a077072696d61727910001a077a6f6e655f69641a0a7375627a6f6e655f69641a04747970651a06636f6e6669671a097265706f72745f69641a0f76696f6c6174696f6e5f73746172741a1076696f6c6174696e675f72616e67657320012002200320042005200620072800b80101c20100e80100f2010408001200f801008002009202009a020a089091ceb6fabaa2a516b20200 +26,0ab8030a1f7265706c69636174696f6e5f637269746963616c5f6c6f63616c6974696573181a200128013a00421b0a077a6f6e655f696410011a0a0801104018003000501420003000421e0a0a7375627a6f6e655f696410021a0a0801104018003000501420003000421c0a086c6f63616c69747910031a0a0807100018003000501920003000421d0a097265706f72745f696410041a0a080110401800300050142000300042220a0e61745f7269736b5f72616e67657310051a0a0801104018003000501420003000480652560a077072696d6172791001180122077a6f6e655f6964220a7375627a6f6e655f696422086c6f63616c6974793001300230034000400040004a10080010001a00200028003000380040005a007a02080080010088010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201510a077072696d61727910001a077a6f6e655f69641a0a7375627a6f6e655f69641a086c6f63616c6974791a097265706f72745f69641a0e61745f7269736b5f72616e676573200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200 +27,0abb040a117265706c69636174696f6e5f7374617473181b200128013a00421b0a077a6f6e655f696410011a0a0801104018003000501420003000421e0a0a7375627a6f6e655f696410021a0a0801104018003000501420003000421d0a097265706f72745f696410031a0a080110401800300050142000300042200a0c746f74616c5f72616e67657310041a0a080110401800300050142000300042260a12756e617661696c61626c655f72616e67657310051a0a0801104018003000501420003000422b0a17756e6465725f7265706c6963617465645f72616e67657310061a0a0801104018003000501420003000422a0a166f7665725f7265706c6963617465645f72616e67657310071a0a0801104018003000501420003000480852480a077072696d6172791001180122077a6f6e655f6964220a7375627a6f6e655f696430013002400040004a10080010001a00200028003000380040005a007a02080080010088010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2018e010a077072696d61727910001a077a6f6e655f69641a0a7375627a6f6e655f69641a097265706f72745f69641a0c746f74616c5f72616e6765731a12756e617661696c61626c655f72616e6765731a17756e6465725f7265706c6963617465645f72616e6765731a166f7665725f7265706c6963617465645f72616e67657320012002200320042005200620072800b80102c20100e80100f2010408001200f801008002009202009a0200b20200 +28,0aff010a0c7265706f7274735f6d657461181c200128023a0a08a0dd87c0fabaa2a51642160a02696410011a0a0801104018003000501420003000421e0a0967656e65726174656410021a0b080910001800300050a00920003000480352330a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a02080080010088010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201200a077072696d61727910001a0269641a0967656e657261746564200120022802b80101c20100e80100f2010408001200f801008002009202009a020a08c8f2d3bafabaa2a516b20200 +30,0a91030a0a6e616d65737061636532181e200128013a00421e0a08706172656e74494410011a0c0801104018003000501460002000300042240a0e706172656e74536368656d61494410021a0c08011040180030005014600020003000421a0a046e616d6510031a0c0807100018003000501960002000300042180a02696410041a0c08011040180030005014600020013000480552690a077072696d617279100118012208706172656e744944220e706172656e74536368656d61494422046e616d653001300230034000400040004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a8010060026a150a090a0561646d696e10300a080a04726f6f741030800101880103980100b201330a077072696d61727910001a08706172656e7449441a0e706172656e74536368656d6149441a046e616d652001200220032800b201140a0866616d5f345f696410041a02696420042804b80105c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +31,0adb030a1170726f7465637465645f74735f6d657461181f200128013a0042250a0973696e676c65746f6e10011a0c08001000180030005010600020002a04747275653000421d0a0776657273696f6e10021a0c0801104018003000501460002000300042210a0b6e756d5f7265636f72647310031a0c08011040180030005014600020003000421f0a096e756d5f7370616e7310041a0c0801104018003000501460002000300042210a0b746f74616c5f627974657310051a0c080110401800300050146000200030004806524c0a077072696d61727910011801220973696e676c65746f6e300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a8010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100a201240a0973696e676c65746f6e120f636865636b5f73696e676c65746f6e1800280130003800b201500a077072696d61727910001a0973696e676c65746f6e1a0776657273696f6e1a0b6e756d5f7265636f7264731a096e756d5f7370616e731a0b746f74616c5f6279746573200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +32,0ad9030a1470726f7465637465645f74735f7265636f7264731820200128013a0042190a02696410011a0d080e10001800300050861760002000300042190a02747310021a0d080310001800300050a40d600020003000421f0a096d6574615f7479706510031a0c08071000180030005019600020003000421a0a046d65746110041a0c08081000180030005011600020013000421f0a096e756d5f7370616e7310051a0c08011040180030005014600020003000421b0a057370616e7310061a0c0808100018003000501160002000300042250a08766572696669656410071a0c08001000180030005010600020002a0566616c73653000480852450a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a8010060026a150a090a0561646d696e10300a080a04726f6f741030800101880103980100b201500a077072696d61727910001a0269641a0274731a096d6574615f747970651a046d6574611a096e756d5f7370616e731a057370616e731a08766572696669656420012002200320042005200620072800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +33,0ac4020a0c726f6c655f6f7074696f6e731821200128013a00421e0a08757365726e616d6510011a0c08071000180030005019600020003000421c0a066f7074696f6e10021a0c08071000180030005019600020003000421b0a0576616c756510031a0c08071000180030005019600020013000480452570a077072696d617279100118012208757365726e616d6522066f7074696f6e30013002400040004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a8010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2012c0a077072696d61727910001a08757365726e616d651a066f7074696f6e1a0576616c75652001200220032803b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +34,0ac9020a1773746174656d656e745f62756e646c655f6368756e6b731822200128013a0042280a02696410011a0c08011040180030005014600020002a0e756e697175655f726f7769642829300042210a0b6465736372697074696f6e10021a0c08071000180030005019600020013000421a0a046461746110031a0c08081000180030005011600020003000480452450a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a8010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2012a0a077072696d61727910001a0269641a0b6465736372697074696f6e1a04646174612001200220032800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +35,0aeb040a1e73746174656d656e745f646961676e6f73746963735f72657175657374731823200128013a0042280a02696410011a0c08011040180030005014600020002a0e756e697175655f726f7769642829300042260a09636f6d706c6574656410021a0c08001000180030005010600020002a0566616c73653000422b0a1573746174656d656e745f66696e6765727072696e7410031a0c08071000180030005019600020003000422e0a1873746174656d656e745f646961676e6f73746963735f696410041a0c0801104018003000501460002001300042230a0c7265717565737465645f617410051a0d080910001800300050a009600020003000480652450a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a801005a730a0d636f6d706c657465645f696478100218002209636f6d706c65746564220269642a1573746174656d656e745f66696e6765727072696e7430023001400040004a10080010001a00200028003000380040005a0070037a020800800100880100900101980100a20106080012001800a8010060036a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b201650a077072696d61727910001a0269641a09636f6d706c657465641a1573746174656d656e745f66696e6765727072696e741a1873746174656d656e745f646961676e6f73746963735f69641a0c7265717565737465645f6174200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +36,0aae040a1573746174656d656e745f646961676e6f73746963731824200128013a0042280a02696410011a0c08011040180030005014600020002a0e756e697175655f726f77696428293000422b0a1573746174656d656e745f66696e6765727072696e7410021a0c08071000180030005019600020003000421f0a0973746174656d656e7410031a0c0807100018003000501960002000300042230a0c636f6c6c65637465645f617410041a0d080910001800300050a009600020003000421c0a05747261636510051a0d081210001800300050da1d60002001300042340a0d62756e646c655f6368756e6b7310061a1d080f104018003000380150f8075a0c080110401800300050146000600020013000421b0a056572726f7210071a0c08071000180030005019600020013000480852450a077072696d6172791001180122026964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a8010060026a170a0a0a0561646d696e10f0030a090a04726f6f7410f003800101880103980100b2016c0a077072696d61727910001a0269641a1573746174656d656e745f66696e6765727072696e741a0973746174656d656e741a0c636f6c6c65637465645f61741a0574726163651a0d62756e646c655f6368756e6b731a056572726f7220012002200320042005200620072800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021d +37,0aa3070a0e7363686564756c65645f6a6f62731825200128023a0042370a0b7363686564756c655f696410011a0c08011040180030005014600020002a0e756e697175655f726f7769642829300068007000780042290a0d7363686564756c655f6e616d6510021a0c0807100018003000501960002000300068007000780042390a076372656174656410031a0d080910001800300050a009600020002a136e6f7728293a3a3a54494d455354414d50545a300068007000780042210a056f776e657210041a0c0807100018003000501960002000300068007000780042250a086e6578745f72756e10051a0d080910001800300050a009600020013000680070007800422a0a0e7363686564756c655f737461746510061a0c0808100018003000501160002001300068007000780042290a0d7363686564756c655f6578707210071a0c08071000180030005019600020013000680070007800422c0a107363686564756c655f64657461696c7310081a0c0808100018003000501160002001300068007000780042290a0d6578656375746f725f7479706510091a0c08071000180030005019600020003000680070007800422a0a0e657865637574696f6e5f61726773100a1a0c08081000180030005011600020003000680070007800480b52540a077072696d61727910011801220b7363686564756c655f6964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a80100b20100ba01005a580a0c6e6578745f72756e5f6964781002180022086e6578745f72756e3005380140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a80100b20100ba010060036a1f0a0a0a0561646d696e10f0030a090a04726f6f7410f00312046e6f64651801800101880103980100b201380a05736368656410001a0b7363686564756c655f69641a086e6578745f72756e1a0e7363686564756c655f73746174652001200520062800b201780a056f7468657210011a0d7363686564756c655f6e616d651a07637265617465641a056f776e65721a0d7363686564756c655f657870721a107363686564756c655f64657461696c731a0d6578656375746f725f747970651a0e657865637574696f6e5f61726773200220032004200720082009200a2800b80102c20100e80100f2010408001200f801008002009202009a020a08a8fb8ada9bbba2a516b20200b80200c0021dc80200 +39,0ad0020a0b73716c6c6976656e6573731827200128013a0042260a0a73657373696f6e5f696410011a0c0808100018003000501160002000300068007000780042270a0a65787069726174696f6e10021a0d080310001800300050a40d600020003000680070007800480352530a077072696d61727910011801220a73657373696f6e5f6964300140004a10080010001a00200028003000380040005a007a020800800100880100900101980100a20106080012001800a80100b20100ba010060026a1f0a0a0a0561646d696e10f0030a090a04726f6f7410f00312046e6f64651801800101880103980100b2013c0a1a66616d305f73657373696f6e5f69645f65787069726174696f6e10001a0a73657373696f6e5f69641a0a65787069726174696f6e200120022802b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200 +50,12240a0964656661756c74646210321a150a090a0561646d696e10020a080a04726f6f741002 +51,12230a08706f73746772657310331a150a090a0561646d696e10020a080a04726f6f741002 +52,121e0a0364623110341a150a090a0561646d696e10020a080a04726f6f741002 +53,0ac7020a01611835203428033a0042150a016910011a0a080110401800300050142000300042150a016b10021a0a0801104018003000501420013000480352320a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001008801005a340a07615f6a5f6b65791002180122016b3002380140004a10080010001a00200028003000380040005a007a02080080010088010060036a150a090a0561646d696e10020a080a04726f6f741002800101880103980100b201170a077072696d61727910001a01691a016b200120022802b80101c20100e80100f2010408001200f801008002009202009a0200aa024408361002180220352a0a666b5f6a5f7265665f613000380040004800500258026210080010001a00200028003000380040006a10083610021a0020002800300038004000b20200 +54,0a93020a01621836203428033a0a08b0cdd6e5edbaa2a51642130a016910011a0808011040180030032000300042130a016a10021a080801104018003003200130004803522f0a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001005a4d0a07625f6a5f6b65791002180122016a3002380140004a1a083510021a0a666b5f6a5f7265665f61200028013000380040005210083710021a00200028003000380040005a007a02080080010060036a150a090a0561646d696e10020a080a04726f6f741002800101880103980100b201170a077072696d61727910001a01691a016a200120022802b80101c20100e80100f2010408001200f80100800200 +55,0ae1020a01631837203428033a0042150a016910011a0a080110401800300050142000300042150a016b10021a0a0801104018003000501420013000480352320a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001008801005a440a17635f6175746f5f696e6465785f666b5f6a5f7265665f621002180022016b3002380140004a10080010001a00200028003000380040005a007a02080080010088010060036a150a090a0561646d696e10020a080a04726f6f741002800101880103980100b201170a077072696d61727910001a01691a016b200120022802b80101c20100e80100f2010408001200f801008002009202009a0200a2024e08371002180220362a0a666b5f6a5f7265665f62300038004000480050025802621a083610021a0a666b5f6a5f7265665f62200028013000380040006a10080010001a0020002800300038004000b20200 +56,121e0a0364623210381a150a090a0561646d696e10020a080a04726f6f741002 +57,0ac3020a01611839203828023a0a08f880afeaedbaa2a51642130a016910011a0808011040180030032000300042130a016a10021a080801104018003003200130004803522f0a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001005a430a07615f6a5f6b65791002180122016a3002380140004a10080010001a00200028003000380040005210083a10021a00200028003000380040005a007a0208008001005a380a09615f6a5f695f6964781003180022016a22016930023001400040004a10080010001a00200028003000380040005a007a02080080010060046a150a090a0561646d696e10020a080a04726f6f741002800101880103980100b201170a077072696d61727910001a01691a016a200120022802b80101c20100e80100f2010408001200f80100800200 +58,0a93020a0162183a203828033a0a08f8e8adededbaa2a51642130a016910011a0808011040180030032000300042130a016a10021a080801104018003003200130004803522f0a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001005a4d0a07625f6a5f6b65791002180122016a3002380140004a1a083910021a0a666b5f6a5f7265665f61200028013000380040005210083b10031a00200028003000380040005a007a02080080010060036a150a090a0561646d696e10020a080a04726f6f741002800101880103980100b201170a077072696d61727910001a01691a016a200120022802b80101c20100e80100f2010408001200f80100800200 +59,0a9b040a0163183b2038280b3a0a0898f3e7acfdbaa2a51642150a016910011a0a080110401800300050142000300042150a016a10021a0a080110401800300050142001300042150a016b10031a0a0801104018003000501420013000480452320a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001008801005a440a17635f6175746f5f696e6465785f666b5f6a5f7265665f621003180022016a3002380140004a10080010001a00200028003000380040005a007a0208008001008801005a380a0b65787472615f6964785f311004180022016a3002380140004a10080010001a00200028003000380040005a007a0208008001008801005a3f0a0b65787472615f6964785f321005180022016a22016b300230033801400040004a10080010001a00200028003000380040005a007a02080080010088010060066a150a090a0561646d696e10020a080a04726f6f741002800104880103980100b2011c0a077072696d61727910001a01691a016a1a016b2001200220032800b80101c20100e80100f2010408001200f801008002008a0216080210e8d1a4acfdbaa2a516188180fea1a5fad8bb089202009a0200a2024e083b10021802203a2a0a666b5f6a5f7265665f62300038004000480050035802621a083a10021a0a666b5f6a5f7265665f62200028013000380040006a10080010001a0020002800300038004000b20200 +60,121e0a03646233103c1a150a090a0561646d696e10020a080a04726f6f741002 +61,0af4020a0161183d203c28073a0042170a016910011a0c0801104018003000501460002000300042170a016a10021a0c08011040180030005014600020013000480352440a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a020800800100880100900100980100a20106080012001800a801005a460a07615f6964785f6a1002180122016a3002380140004a10080010001a00200028003000380040005a007a020800800100880100900100980100a20106080012001800a8010060036a150a090a0561646d696e10020a080a04726f6f741002800102880103980100b201170a077072696d61727910001a01691a016a200120022802b80101c20100e80100f2010408001200f801008002009202009a0200aa0220083e10021802203d2a0a666b5f6a5f7265665f61300138004000480050025802aa0220083f10021802203d2a0a666b5f6a5f7265665f61300138004000480050025802b20200b80200c00200 +62,0a83030a0162183e203c280b3a0042170a016910011a0c0801104018003000501460002000300042170a016a10021a0c0801104018003000501460002001300042170a016b10031a0c08011040180030005014600020013000480452440a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a020800800100880100900100980100a20106080012001800a801005a510a0b625f6964785f6a5f6e65771003180022016a22016b300230033801400040004a10080010001a00200028003000380040005a007a020800800100880101900101980100a20106080012001800a8010060046a150a090a0561646d696e10020a080a04726f6f741002800104880103980100b2011c0a077072696d61727910001a01691a016a1a016b2001200220032800b80101c20100e80100f2010408001200f801008002008a02060802100018009202009a0200a20220083e10021802203d2a0a666b5f6a5f7265665f61300138004000480050025802b20200b80200c00200 +63,0a9b020a0163183f203c28053a0a08b0b1ed95efbaa2a51642130a016910011a0808011040180030032000300042130a016a10021a0808011040180030032001300042130a016b10031a080801104018003003200130004804522f0a077072696d61727910011801220169300140004a10080010001a00200028003000380040005a007a0208008001005a3b0a07635f6964785f6a1002180022016a3002380140004a1a083d10021a0a666b5f6a5f7265665f61200128013000380040005a007a02080080010060036a150a090a0561646d696e10020a080a04726f6f741002800102880103980100b2011c0a077072696d61727910001a01691a016a1a016b2001200220032800b80101c20100e80100f2010408001200f80100800200 diff --git a/pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/generate.sh b/pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/generate.sh new file mode 100755 index 000000000000..2f81aa0a11f0 --- /dev/null +++ b/pkg/sql/catalog/catalogkv/testdata/unwrap_validation/fkupgrade/generate.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +set -e + +declare -a VERSIONS=( v19.1.11 v19.2.11 v20.1.8 v20.2.1 ) + +declare -A VERSION_STATEMENTS=( + [v19.1.11]=" +CREATE DATABASE db1; +USE db1; +CREATE TABLE a (i INT PRIMARY KEY, j INT UNIQUE); +CREATE TABLE b (i INT PRIMARY KEY, j INT UNIQUE REFERENCES a (j)); +-- c.j will get an auto-created index. +CREATE TABLE c (i INT PRIMARY KEY, j INT REFERENCES b (j)); + +CREATE DATABASE db2; +USE db2; +CREATE TABLE a (i INT PRIMARY KEY, j INT UNIQUE, INDEX(j, i)); +CREATE TABLE b (i INT PRIMARY KEY, j INT UNIQUE REFERENCES a (j)); +-- c.j will get an auto-created index. +CREATE TABLE c (i INT PRIMARY KEY, j INT REFERENCES b (j), k INT, INDEX idx_k (k)); +-- Create some extra indexes. +CREATE INDEX extra_idx_1 ON c(j); +CREATE INDEX extra_idx_2 ON c(j, k); + +CREATE DATABASE db3; +USE db3; +CREATE TABLE a (i INT PRIMARY KEY, j INT); +CREATE UNIQUE INDEX a_idx_j ON a(j); +CREATE TABLE b (i INT PRIMARY KEY, j INT, k INT); +CREATE INDEX b_idx_j ON b(j); +ALTER TABLE b ADD FOREIGN KEY (j) REFERENCES a(j); +CREATE TABLE c (i INT PRIMARY KEY, j INT, k INT); +CREATE INDEX c_idx_j ON c(j); +ALTER TABLE c ADD FOREIGN KEY (j) REFERENCES a(j); +" + [v19.2.11]=" +-- These schema changes will upgrade the FKs on the respective descriptors. +-- Keep db1.b unupgraded, but upgrade the other tables in its reference graph. +ALTER TABLE db1.a RENAME COLUMN j TO k; +ALTER TABLE db1.c RENAME COLUMN j TO k; + +-- Unrelated DROP INDEX. +DROP INDEX db2.c@idx_k; +" + [v20.1.8]=" +-- Swap out a referencing-side index. This should upgrade db3.a, but we leave db3.c alone. +USE db3; +CREATE INDEX b_idx_j_new ON b(j, k); +DROP INDEX b_idx_j; +" + [v20.2.1]='' +) + + +main() { + check_local_does_not_exist + install_cockroach_versions + run_version_statements + dump_descriptors +} + +check_local_does_not_exist() { + out="$( { roachprod run local true 2>&1 || true ; } | head )" + if [[ "${out}" =~ "unknown cluster: local" ]]; then + return 0 + fi + echo >&2 "make sure the local cluster does not exist" + exit 1 +} + +install_cockroach_versions() { + roachprod create local -n 1 + for v in "${VERSIONS[@]}"; do + roachprod stage local release "${v}" + roachprod run local cp ./cockroach "./cockroach-${v}" + done +} + +run_version_statements() { + for v in "${VERSIONS[@]}"; do + roachprod stop local + roachprod start local --binary cockroach-$v + sleep 1 # wait for the upgrade to happen + stmts="${VERSION_STATEMENTS[$v]}" + if [[ -z "${stmts}" ]]; then + continue + fi + roachprod sql local -- -e "${stmts}" + done +} + +dump_descriptors() { + roachprod sql local -- \ + --format csv \ + -e "SELECT id, encode(descriptor, 'hex') AS descriptor FROM system.descriptor" \ + > descriptors.csv +} + +main diff --git a/pkg/sql/catalog/catalogkv/unwrap_validation_test.go b/pkg/sql/catalog/catalogkv/unwrap_validation_test.go new file mode 100644 index 000000000000..4f4a53d9adea --- /dev/null +++ b/pkg/sql/catalog/catalogkv/unwrap_validation_test.go @@ -0,0 +1,127 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package catalogkv + +import ( + "context" + "encoding/hex" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "testing" + + "github.com/cockroachdb/cockroach/pkg/sql/catalog" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" + "github.com/cockroachdb/cockroach/pkg/testutils" + "github.com/cockroachdb/cockroach/pkg/util/encoding/csv" + "github.com/cockroachdb/cockroach/pkg/util/hlc" + "github.com/cockroachdb/cockroach/pkg/util/protoutil" + "github.com/cockroachdb/errors" + "github.com/stretchr/testify/require" +) + +// TestUnwrapValidation uses testdata to find issues validating descriptors. +// The test is driven by serialized testdata. The expected testdata directories +// will hold a file "descriptors.csv" which is a csv of id,descriptor where +// descriptor is hex encoded. +func TestUnwrapValidation(t *testing.T) { + testdata := testutils.TestDataPath("testdata", "unwrap_validation") + const descriptorsCSVFilename = "descriptors.csv" + dirs, err := ioutil.ReadDir(testdata) + require.NoError(t, err) + for _, dir := range dirs { + if !dir.IsDir() { + continue + } + dp := filepath.Join(testdata, dir.Name(), descriptorsCSVFilename) + if _, err := os.Stat(dp); errors.Is(err, os.ErrNotExist) { + continue + } + t.Run(dir.Name(), func(t *testing.T) { + unwrapValidationTest(t, dp) + }) + } +} + +func unwrapValidationTest(t *testing.T, descriptorCSVPath string) { + m := decodeDescriptorDSV(t, descriptorCSVPath) + for id, data := range m { + var desc descpb.Descriptor + require.NoError(t, protoutil.Unmarshal(data, &desc)) + ts := descpb.GetDescriptorModificationTime(&desc) + if ts == (hlc.Timestamp{}) { + ts = hlc.Timestamp{WallTime: 1} + } + _, err := unwrapDescriptor(context.Background(), m, ts, &desc, true) + require.NoErrorf(t, err, "id: %d", id) + } +} + +// oneLevelMapDescGetter exists to mirror the behavior of the +// oneLevelTxnDescGetter but instead of reading from the key-value store, it +// reads from the map. +type oneLevelMapDescGetter map[descpb.ID][]byte + +var _ catalog.DescGetter = (oneLevelMapDescGetter)(nil) + +func (o oneLevelMapDescGetter) GetDesc( + ctx context.Context, id descpb.ID, +) (catalog.Descriptor, error) { + var desc descpb.Descriptor + if err := protoutil.Unmarshal(o[id], &desc); err != nil { + return nil, err + } + mt := descpb.GetDescriptorModificationTime(&desc) + if mt == (hlc.Timestamp{}) { + mt = hlc.Timestamp{WallTime: 1} + } + return unwrapDescriptorMutable(ctx, nil, mt, &desc) +} + +func (o oneLevelMapDescGetter) GetDescs( + ctx context.Context, reqs []descpb.ID, +) ([]catalog.Descriptor, error) { + resps := make([]catalog.Descriptor, len(reqs)) + for i, r := range reqs { + var err error + resps[i], err = o.GetDesc(ctx, r) + if err != nil { + return nil, err + } + } + return resps, nil +} + +func decodeDescriptorDSV(t *testing.T, descriptorCSVPath string) oneLevelMapDescGetter { + f, err := os.Open(descriptorCSVPath) + require.NoError(t, err) + defer f.Close() + r := csv.NewReader(f) + records, err := r.ReadAll() + require.NoError(t, err) + require.Equal(t, records[0], []string{"id", "descriptor"}) + records = records[1:] + m := decodeCSVRecordsToDescGetter(t, records) + return m +} + +func decodeCSVRecordsToDescGetter(t *testing.T, records [][]string) oneLevelMapDescGetter { + m := oneLevelMapDescGetter{} + for _, rec := range records { + id, err := strconv.Atoi(rec[0]) + require.NoError(t, err) + decoded, err := hex.DecodeString(rec[1]) + require.NoError(t, err) + m[descpb.ID(id)] = decoded + } + return m +}