diff --git a/pkg/ccl/changefeedccl/changefeed_test.go b/pkg/ccl/changefeedccl/changefeed_test.go index be4249e7b2ad..51851699472d 100644 --- a/pkg/ccl/changefeedccl/changefeed_test.go +++ b/pkg/ccl/changefeedccl/changefeed_test.go @@ -1321,13 +1321,13 @@ func TestChangefeedTruncateRenameDrop(t *testing.T) { assertPayloads(t, truncate, []string{`truncate: [1]->{"after": {"a": 1}}`}) assertPayloads(t, truncateCascade, []string{`truncate_cascade: [1]->{"after": {"b": 1}}`}) sqlDB.Exec(t, `TRUNCATE TABLE truncate CASCADE`) - if _, err := truncate.Next(); !testutils.IsError(err, `"truncate" was dropped or truncated`) { - t.Errorf(`expected ""truncate" was dropped or truncated" error got: %+v`, err) + if _, err := truncate.Next(); !testutils.IsError(err, `"truncate" was truncated`) { + t.Fatalf(`expected ""truncate" was truncated" error got: %+v`, err) } if _, err := truncateCascade.Next(); !testutils.IsError( - err, `"truncate_cascade" was dropped or truncated`, + err, `"truncate_cascade" was truncated`, ) { - t.Errorf(`expected ""truncate_cascade" was dropped or truncated" error got: %+v`, err) + t.Fatalf(`expected ""truncate_cascade" was truncated" error got: %+v`, err) } sqlDB.Exec(t, `CREATE TABLE rename (a INT PRIMARY KEY)`) diff --git a/pkg/ccl/changefeedccl/schemafeed/table_event_filter.go b/pkg/ccl/changefeedccl/schemafeed/table_event_filter.go index cbc5a7f4e1e0..18a56d88bd1c 100644 --- a/pkg/ccl/changefeedccl/schemafeed/table_event_filter.go +++ b/pkg/ccl/changefeedccl/schemafeed/table_event_filter.go @@ -24,6 +24,7 @@ const ( tableEventTypeAddColumnNoBackfill tableEventTypeAddColumnWithBackfill tableEventTypeDropColumn + tableEventTruncate ) var ( @@ -55,6 +56,8 @@ func classifyTableEvent(e TableEvent) tableEventType { return tableEventTypeAddColumnNoBackfill case hasNewColumnDropBackfillMutation(e): return tableEventTypeDropColumn + case tableTruncated(e): + return tableEventTruncate default: return tableEventTypeUnknown } @@ -66,6 +69,10 @@ type tableEventFilter map[tableEventType]bool func (b tableEventFilter) shouldFilter(ctx context.Context, e TableEvent) (bool, error) { et := classifyTableEvent(e) + // Truncation events are not ignored and return an error. + if et == tableEventTruncate { + return false, errors.Errorf(`"%s" was truncated`, e.Before.Name) + } shouldFilter, ok := b[et] if !ok { return false, errors.AssertionFailedf("policy does not specify how to handle event type %v", et) @@ -100,3 +107,19 @@ func newColumnNoBackfill(e TableEvent) (res bool) { return len(e.Before.Columns) < len(e.After.Columns) && !e.Before.HasColumnBackfillMutation() } + +func pkChangeMutationExists(desc *sqlbase.ImmutableTableDescriptor) bool { + for _, m := range desc.Mutations { + if m.Direction == descpb.DescriptorMutation_ADD && m.GetPrimaryKeySwap() != nil { + return true + } + } + return false +} + +func tableTruncated(e TableEvent) bool { + // A table was truncated if the primary index has changed, but an ALTER + // PRIMARY KEY statement was not performed. TRUNCATE operates by creating + // a new set of indexes for the table, including a new primary index. + return e.Before.PrimaryIndex.ID != e.After.PrimaryIndex.ID && !pkChangeMutationExists(e.Before) +} diff --git a/pkg/jobs/jobspb/jobs.pb.go b/pkg/jobs/jobspb/jobs.pb.go index 324be881752e..4c2e6b0d2cfe 100644 --- a/pkg/jobs/jobspb/jobs.pb.go +++ b/pkg/jobs/jobspb/jobs.pb.go @@ -54,7 +54,7 @@ func (x EncryptionMode) String() string { return proto.EnumName(EncryptionMode_name, int32(x)) } func (EncryptionMode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{0} } type Status int32 @@ -83,7 +83,7 @@ func (x Status) String() string { return proto.EnumName(Status_name, int32(x)) } func (Status) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{1} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{1} } type Type int32 @@ -129,7 +129,7 @@ var Type_value = map[string]int32{ } func (Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{2} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{2} } type SchemaChangeGCProgress_Status int32 @@ -159,7 +159,7 @@ func (x SchemaChangeGCProgress_Status) String() string { return proto.EnumName(SchemaChangeGCProgress_Status_name, int32(x)) } func (SchemaChangeGCProgress_Status) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{15, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{15, 0} } type Lease struct { @@ -173,7 +173,7 @@ func (m *Lease) Reset() { *m = Lease{} } func (m *Lease) String() string { return proto.CompactTextString(m) } func (*Lease) ProtoMessage() {} func (*Lease) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{0} } func (m *Lease) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -214,7 +214,7 @@ func (m *BackupEncryptionOptions) Reset() { *m = BackupEncryptionOptions func (m *BackupEncryptionOptions) String() string { return proto.CompactTextString(m) } func (*BackupEncryptionOptions) ProtoMessage() {} func (*BackupEncryptionOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{1} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{1} } func (m *BackupEncryptionOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -248,7 +248,7 @@ func (m *BackupEncryptionOptions_KMSInfo) Reset() { *m = BackupEncryptio func (m *BackupEncryptionOptions_KMSInfo) String() string { return proto.CompactTextString(m) } func (*BackupEncryptionOptions_KMSInfo) ProtoMessage() {} func (*BackupEncryptionOptions_KMSInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{1, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{1, 0} } func (m *BackupEncryptionOptions_KMSInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -302,7 +302,7 @@ func (m *BackupDetails) Reset() { *m = BackupDetails{} } func (m *BackupDetails) String() string { return proto.CompactTextString(m) } func (*BackupDetails) ProtoMessage() {} func (*BackupDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{2} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{2} } func (m *BackupDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -334,7 +334,7 @@ func (m *BackupProgress) Reset() { *m = BackupProgress{} } func (m *BackupProgress) String() string { return proto.CompactTextString(m) } func (*BackupProgress) ProtoMessage() {} func (*BackupProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{3} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{3} } func (m *BackupProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -389,7 +389,7 @@ func (m *RestoreDetails) Reset() { *m = RestoreDetails{} } func (m *RestoreDetails) String() string { return proto.CompactTextString(m) } func (*RestoreDetails) ProtoMessage() {} func (*RestoreDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{4} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{4} } func (m *RestoreDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -426,7 +426,7 @@ func (m *RestoreDetails_DescriptorRewrite) Reset() { *m = RestoreDetails func (m *RestoreDetails_DescriptorRewrite) String() string { return proto.CompactTextString(m) } func (*RestoreDetails_DescriptorRewrite) ProtoMessage() {} func (*RestoreDetails_DescriptorRewrite) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{4, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{4, 0} } func (m *RestoreDetails_DescriptorRewrite) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -459,7 +459,7 @@ func (m *RestoreDetails_BackupLocalityInfo) Reset() { *m = RestoreDetail func (m *RestoreDetails_BackupLocalityInfo) String() string { return proto.CompactTextString(m) } func (*RestoreDetails_BackupLocalityInfo) ProtoMessage() {} func (*RestoreDetails_BackupLocalityInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{4, 1} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{4, 1} } func (m *RestoreDetails_BackupLocalityInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -493,7 +493,7 @@ func (m *RestoreDetails_Tenant) Reset() { *m = RestoreDetails_Tenant{} } func (m *RestoreDetails_Tenant) String() string { return proto.CompactTextString(m) } func (*RestoreDetails_Tenant) ProtoMessage() {} func (*RestoreDetails_Tenant) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{4, 3} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{4, 3} } func (m *RestoreDetails_Tenant) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -526,7 +526,7 @@ func (m *RestoreProgress) Reset() { *m = RestoreProgress{} } func (m *RestoreProgress) String() string { return proto.CompactTextString(m) } func (*RestoreProgress) ProtoMessage() {} func (*RestoreProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{5} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{5} } func (m *RestoreProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -585,7 +585,7 @@ func (m *ImportDetails) Reset() { *m = ImportDetails{} } func (m *ImportDetails) String() string { return proto.CompactTextString(m) } func (*ImportDetails) ProtoMessage() {} func (*ImportDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{6} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{6} } func (m *ImportDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -622,7 +622,7 @@ func (m *ImportDetails_Table) Reset() { *m = ImportDetails_Table{} } func (m *ImportDetails_Table) String() string { return proto.CompactTextString(m) } func (*ImportDetails_Table) ProtoMessage() {} func (*ImportDetails_Table) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{6, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{6, 0} } func (m *ImportDetails_Table) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -665,7 +665,7 @@ func (m *ImportProgress) Reset() { *m = ImportProgress{} } func (m *ImportProgress) String() string { return proto.CompactTextString(m) } func (*ImportProgress) ProtoMessage() {} func (*ImportProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{7} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{7} } func (m *ImportProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -699,7 +699,7 @@ func (m *TypeSchemaChangeDetails) Reset() { *m = TypeSchemaChangeDetails func (m *TypeSchemaChangeDetails) String() string { return proto.CompactTextString(m) } func (*TypeSchemaChangeDetails) ProtoMessage() {} func (*TypeSchemaChangeDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{8} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{8} } func (m *TypeSchemaChangeDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -732,7 +732,7 @@ func (m *TypeSchemaChangeProgress) Reset() { *m = TypeSchemaChangeProgre func (m *TypeSchemaChangeProgress) String() string { return proto.CompactTextString(m) } func (*TypeSchemaChangeProgress) ProtoMessage() {} func (*TypeSchemaChangeProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{9} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{9} } func (m *TypeSchemaChangeProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -765,7 +765,7 @@ func (m *ResumeSpanList) Reset() { *m = ResumeSpanList{} } func (m *ResumeSpanList) String() string { return proto.CompactTextString(m) } func (*ResumeSpanList) ProtoMessage() {} func (*ResumeSpanList) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{10} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{10} } func (m *ResumeSpanList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -800,7 +800,7 @@ func (m *DroppedTableDetails) Reset() { *m = DroppedTableDetails{} } func (m *DroppedTableDetails) String() string { return proto.CompactTextString(m) } func (*DroppedTableDetails) ProtoMessage() {} func (*DroppedTableDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{11} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{11} } func (m *DroppedTableDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -842,6 +842,11 @@ var xxx_messageInfo_DroppedTableDetails proto.InternalMessageInfo type SchemaChangeGCDetails struct { // Indexes to GC. Indexes []SchemaChangeGCDetails_DroppedIndex `protobuf:"bytes,1,rep,name=indexes,proto3" json:"indexes"` + // InterleavedTable is the table being truncated. In particular, it is the + // TableDescriptor before any of the truncate modifications have been applied. + InterleavedTable *descpb.TableDescriptor `protobuf:"bytes,4,opt,name=interleaved_table,json=interleavedTable,proto3" json:"interleaved_table,omitempty"` + // InterleavedIndexes is the set of interleaved indexes to truncate. + InterleavedIndexes []descpb.IndexDescriptor `protobuf:"bytes,5,rep,name=interleaved_indexes,json=interleavedIndexes,proto3" json:"interleaved_indexes"` // Entire tables to GC. Tables []SchemaChangeGCDetails_DroppedID `protobuf:"bytes,2,rep,name=tables,proto3" json:"tables"` // If dropping indexes, the table ID which has those indexes. If dropping a @@ -853,7 +858,7 @@ func (m *SchemaChangeGCDetails) Reset() { *m = SchemaChangeGCDetails{} } func (m *SchemaChangeGCDetails) String() string { return proto.CompactTextString(m) } func (*SchemaChangeGCDetails) ProtoMessage() {} func (*SchemaChangeGCDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{12} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{12} } func (m *SchemaChangeGCDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -887,7 +892,7 @@ func (m *SchemaChangeGCDetails_DroppedIndex) Reset() { *m = SchemaChange func (m *SchemaChangeGCDetails_DroppedIndex) String() string { return proto.CompactTextString(m) } func (*SchemaChangeGCDetails_DroppedIndex) ProtoMessage() {} func (*SchemaChangeGCDetails_DroppedIndex) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{12, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{12, 0} } func (m *SchemaChangeGCDetails_DroppedIndex) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -921,7 +926,7 @@ func (m *SchemaChangeGCDetails_DroppedID) Reset() { *m = SchemaChangeGCD func (m *SchemaChangeGCDetails_DroppedID) String() string { return proto.CompactTextString(m) } func (*SchemaChangeGCDetails_DroppedID) ProtoMessage() {} func (*SchemaChangeGCDetails_DroppedID) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{12, 1} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{12, 1} } func (m *SchemaChangeGCDetails_DroppedID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -982,7 +987,7 @@ func (m *SchemaChangeDetails) Reset() { *m = SchemaChangeDetails{} } func (m *SchemaChangeDetails) String() string { return proto.CompactTextString(m) } func (*SchemaChangeDetails) ProtoMessage() {} func (*SchemaChangeDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{13} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{13} } func (m *SchemaChangeDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1014,7 +1019,7 @@ func (m *SchemaChangeProgress) Reset() { *m = SchemaChangeProgress{} } func (m *SchemaChangeProgress) String() string { return proto.CompactTextString(m) } func (*SchemaChangeProgress) ProtoMessage() {} func (*SchemaChangeProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{14} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{14} } func (m *SchemaChangeProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1050,7 +1055,7 @@ func (m *SchemaChangeGCProgress) Reset() { *m = SchemaChangeGCProgress{} func (m *SchemaChangeGCProgress) String() string { return proto.CompactTextString(m) } func (*SchemaChangeGCProgress) ProtoMessage() {} func (*SchemaChangeGCProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{15} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{15} } func (m *SchemaChangeGCProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1084,7 +1089,7 @@ func (m *SchemaChangeGCProgress_IndexProgress) Reset() { *m = SchemaChan func (m *SchemaChangeGCProgress_IndexProgress) String() string { return proto.CompactTextString(m) } func (*SchemaChangeGCProgress_IndexProgress) ProtoMessage() {} func (*SchemaChangeGCProgress_IndexProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{15, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{15, 0} } func (m *SchemaChangeGCProgress_IndexProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1118,7 +1123,7 @@ func (m *SchemaChangeGCProgress_TableProgress) Reset() { *m = SchemaChan func (m *SchemaChangeGCProgress_TableProgress) String() string { return proto.CompactTextString(m) } func (*SchemaChangeGCProgress_TableProgress) ProtoMessage() {} func (*SchemaChangeGCProgress_TableProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{15, 1} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{15, 1} } func (m *SchemaChangeGCProgress_TableProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1151,7 +1156,7 @@ func (m *ChangefeedTarget) Reset() { *m = ChangefeedTarget{} } func (m *ChangefeedTarget) String() string { return proto.CompactTextString(m) } func (*ChangefeedTarget) ProtoMessage() {} func (*ChangefeedTarget) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{16} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{16} } func (m *ChangefeedTarget) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1204,7 +1209,7 @@ func (m *ChangefeedDetails) Reset() { *m = ChangefeedDetails{} } func (m *ChangefeedDetails) String() string { return proto.CompactTextString(m) } func (*ChangefeedDetails) ProtoMessage() {} func (*ChangefeedDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{17} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{17} } func (m *ChangefeedDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1239,7 +1244,7 @@ func (m *ResolvedSpan) Reset() { *m = ResolvedSpan{} } func (m *ResolvedSpan) String() string { return proto.CompactTextString(m) } func (*ResolvedSpan) ProtoMessage() {} func (*ResolvedSpan) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{18} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{18} } func (m *ResolvedSpan) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1282,7 +1287,7 @@ func (m *ChangefeedProgress) Reset() { *m = ChangefeedProgress{} } func (m *ChangefeedProgress) String() string { return proto.CompactTextString(m) } func (*ChangefeedProgress) ProtoMessage() {} func (*ChangefeedProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{19} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{19} } func (m *ChangefeedProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1326,7 +1331,7 @@ func (m *CreateStatsDetails) Reset() { *m = CreateStatsDetails{} } func (m *CreateStatsDetails) String() string { return proto.CompactTextString(m) } func (*CreateStatsDetails) ProtoMessage() {} func (*CreateStatsDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{20} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{20} } func (m *CreateStatsDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1363,7 +1368,7 @@ func (m *CreateStatsDetails_ColStat) Reset() { *m = CreateStatsDetails_C func (m *CreateStatsDetails_ColStat) String() string { return proto.CompactTextString(m) } func (*CreateStatsDetails_ColStat) ProtoMessage() {} func (*CreateStatsDetails_ColStat) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{20, 0} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{20, 0} } func (m *CreateStatsDetails_ColStat) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1395,7 +1400,7 @@ func (m *CreateStatsProgress) Reset() { *m = CreateStatsProgress{} } func (m *CreateStatsProgress) String() string { return proto.CompactTextString(m) } func (*CreateStatsProgress) ProtoMessage() {} func (*CreateStatsProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{21} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{21} } func (m *CreateStatsProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1462,7 +1467,7 @@ func (m *Payload) Reset() { *m = Payload{} } func (m *Payload) String() string { return proto.CompactTextString(m) } func (*Payload) ProtoMessage() {} func (*Payload) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{22} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{22} } func (m *Payload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1801,7 +1806,7 @@ func (m *Progress) Reset() { *m = Progress{} } func (m *Progress) String() string { return proto.CompactTextString(m) } func (*Progress) ProtoMessage() {} func (*Progress) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{23} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{23} } func (m *Progress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2207,7 +2212,7 @@ func (m *Job) Reset() { *m = Job{} } func (m *Job) String() string { return proto.CompactTextString(m) } func (*Job) ProtoMessage() {} func (*Job) Descriptor() ([]byte, []int) { - return fileDescriptor_jobs_6f3c1209a096a8fe, []int{24} + return fileDescriptor_jobs_f1c41cd546fbc9b1, []int{24} } func (m *Job) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3324,6 +3329,28 @@ func (m *SchemaChangeGCDetails) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintJobs(dAtA, i, uint64(m.ParentID)) } + if m.InterleavedTable != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintJobs(dAtA, i, uint64(m.InterleavedTable.Size())) + n17, err := m.InterleavedTable.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n17 + } + if len(m.InterleavedIndexes) > 0 { + for _, msg := range m.InterleavedIndexes { + dAtA[i] = 0x2a + i++ + i = encodeVarintJobs(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -3443,21 +3470,21 @@ func (m *SchemaChangeDetails) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintJobs(dAtA, i, uint64(m.FormatVersion)) } if len(m.DroppedTypes) > 0 { - dAtA18 := make([]byte, len(m.DroppedTypes)*10) - var j17 int + dAtA19 := make([]byte, len(m.DroppedTypes)*10) + var j18 int for _, num := range m.DroppedTypes { for num >= 1<<7 { - dAtA18[j17] = uint8(uint64(num)&0x7f | 0x80) + dAtA19[j18] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j17++ + j18++ } - dAtA18[j17] = uint8(num) - j17++ + dAtA19[j18] = uint8(num) + j18++ } dAtA[i] = 0x42 i++ - i = encodeVarintJobs(dAtA, i, uint64(j17)) - i += copy(dAtA[i:], dAtA18[:j17]) + i = encodeVarintJobs(dAtA, i, uint64(j18)) + i += copy(dAtA[i:], dAtA19[:j18]) } return i, nil } @@ -3668,21 +3695,21 @@ func (m *ChangefeedDetails) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintJobs(dAtA, i, uint64((&v).Size())) - n19, err := (&v).MarshalTo(dAtA[i:]) + n20, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n19 + i += n20 } } dAtA[i] = 0x3a i++ i = encodeVarintJobs(dAtA, i, uint64(m.StatementTime.Size())) - n20, err := m.StatementTime.MarshalTo(dAtA[i:]) + n21, err := m.StatementTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n20 + i += n21 return i, nil } @@ -3704,19 +3731,19 @@ func (m *ResolvedSpan) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintJobs(dAtA, i, uint64(m.Span.Size())) - n21, err := m.Span.MarshalTo(dAtA[i:]) + n22, err := m.Span.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n21 + i += n22 dAtA[i] = 0x12 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Timestamp.Size())) - n22, err := m.Timestamp.MarshalTo(dAtA[i:]) + n23, err := m.Timestamp.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n22 + i += n23 if m.BoundaryReached { dAtA[i] = 0x18 i++ @@ -3760,11 +3787,11 @@ func (m *ChangefeedProgress) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintJobs(dAtA, i, uint64(m.ProtectedTimestampRecord.Size())) - n23, err := m.ProtectedTimestampRecord.MarshalTo(dAtA[i:]) + n24, err := m.ProtectedTimestampRecord.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n23 + i += n24 return i, nil } @@ -3792,11 +3819,11 @@ func (m *CreateStatsDetails) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Table.Size())) - n24, err := m.Table.MarshalTo(dAtA[i:]) + n25, err := m.Table.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n24 + i += n25 if len(m.ColumnStats) > 0 { for _, msg := range m.ColumnStats { dAtA[i] = 0x1a @@ -3819,11 +3846,11 @@ func (m *CreateStatsDetails) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintJobs(dAtA, i, uint64(m.AsOf.Size())) - n25, err := m.AsOf.MarshalTo(dAtA[i:]) + n26, err := m.AsOf.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n26 } if len(m.FQTableName) > 0 { dAtA[i] = 0x32 @@ -3856,21 +3883,21 @@ func (m *CreateStatsDetails_ColStat) MarshalTo(dAtA []byte) (int, error) { var l int _ = l if len(m.ColumnIDs) > 0 { - dAtA27 := make([]byte, len(m.ColumnIDs)*10) - var j26 int + dAtA28 := make([]byte, len(m.ColumnIDs)*10) + var j27 int for _, num := range m.ColumnIDs { for num >= 1<<7 { - dAtA27[j26] = uint8(uint64(num)&0x7f | 0x80) + dAtA28[j27] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j26++ + j27++ } - dAtA27[j26] = uint8(num) - j26++ + dAtA28[j27] = uint8(num) + j27++ } dAtA[i] = 0xa i++ - i = encodeVarintJobs(dAtA, i, uint64(j26)) - i += copy(dAtA[i:], dAtA27[:j26]) + i = encodeVarintJobs(dAtA, i, uint64(j27)) + i += copy(dAtA[i:], dAtA28[:j27]) } if m.HasHistogram { dAtA[i] = 0x10 @@ -3951,21 +3978,21 @@ func (m *Payload) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintJobs(dAtA, i, uint64(m.FinishedMicros)) } if len(m.DescriptorIDs) > 0 { - dAtA29 := make([]byte, len(m.DescriptorIDs)*10) - var j28 int + dAtA30 := make([]byte, len(m.DescriptorIDs)*10) + var j29 int for _, num := range m.DescriptorIDs { for num >= 1<<7 { - dAtA29[j28] = uint8(uint64(num)&0x7f | 0x80) + dAtA30[j29] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j28++ + j29++ } - dAtA29[j28] = uint8(num) - j28++ + dAtA30[j29] = uint8(num) + j29++ } dAtA[i] = 0x32 i++ - i = encodeVarintJobs(dAtA, i, uint64(j28)) - i += copy(dAtA[i:], dAtA29[:j28]) + i = encodeVarintJobs(dAtA, i, uint64(j29)) + i += copy(dAtA[i:], dAtA30[:j29]) } if len(m.Error) > 0 { dAtA[i] = 0x42 @@ -3977,18 +4004,18 @@ func (m *Payload) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x4a i++ i = encodeVarintJobs(dAtA, i, uint64(m.Lease.Size())) - n30, err := m.Lease.MarshalTo(dAtA[i:]) + n31, err := m.Lease.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n31 } if m.Details != nil { - nn31, err := m.Details.MarshalTo(dAtA[i:]) + nn32, err := m.Details.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn31 + i += nn32 } if len(m.Statement) > 0 { dAtA[i] = 0x82 @@ -4032,11 +4059,11 @@ func (m *Payload) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintJobs(dAtA, i, uint64(m.FinalResumeError.Size())) - n32, err := m.FinalResumeError.MarshalTo(dAtA[i:]) + n33, err := m.FinalResumeError.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n33 } if m.Noncancelable { dAtA[i] = 0xa0 @@ -4059,11 +4086,11 @@ func (m *Payload_Backup) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Backup.Size())) - n33, err := m.Backup.MarshalTo(dAtA[i:]) + n34, err := m.Backup.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n34 } return i, nil } @@ -4073,11 +4100,11 @@ func (m *Payload_Restore) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x5a i++ i = encodeVarintJobs(dAtA, i, uint64(m.Restore.Size())) - n34, err := m.Restore.MarshalTo(dAtA[i:]) + n35, err := m.Restore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n35 } return i, nil } @@ -4087,11 +4114,11 @@ func (m *Payload_SchemaChange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x62 i++ i = encodeVarintJobs(dAtA, i, uint64(m.SchemaChange.Size())) - n35, err := m.SchemaChange.MarshalTo(dAtA[i:]) + n36, err := m.SchemaChange.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n36 } return i, nil } @@ -4101,11 +4128,11 @@ func (m *Payload_Import) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x6a i++ i = encodeVarintJobs(dAtA, i, uint64(m.Import.Size())) - n36, err := m.Import.MarshalTo(dAtA[i:]) + n37, err := m.Import.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n37 } return i, nil } @@ -4115,11 +4142,11 @@ func (m *Payload_Changefeed) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Changefeed.Size())) - n37, err := m.Changefeed.MarshalTo(dAtA[i:]) + n38, err := m.Changefeed.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n38 } return i, nil } @@ -4129,11 +4156,11 @@ func (m *Payload_CreateStats) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintJobs(dAtA, i, uint64(m.CreateStats.Size())) - n38, err := m.CreateStats.MarshalTo(dAtA[i:]) + n39, err := m.CreateStats.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n39 } return i, nil } @@ -4145,11 +4172,11 @@ func (m *Payload_SchemaChangeGC) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintJobs(dAtA, i, uint64(m.SchemaChangeGC.Size())) - n39, err := m.SchemaChangeGC.MarshalTo(dAtA[i:]) + n40, err := m.SchemaChangeGC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n40 } return i, nil } @@ -4161,11 +4188,11 @@ func (m *Payload_TypeSchemaChange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintJobs(dAtA, i, uint64(m.TypeSchemaChange.Size())) - n40, err := m.TypeSchemaChange.MarshalTo(dAtA[i:]) + n41, err := m.TypeSchemaChange.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n41 } return i, nil } @@ -4185,11 +4212,11 @@ func (m *Progress) MarshalTo(dAtA []byte) (int, error) { var l int _ = l if m.Progress != nil { - nn41, err := m.Progress.MarshalTo(dAtA[i:]) + nn42, err := m.Progress.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn41 + i += nn42 } if m.ModifiedMicros != 0 { dAtA[i] = 0x10 @@ -4203,11 +4230,11 @@ func (m *Progress) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.RunningStatus) } if m.Details != nil { - nn42, err := m.Details.MarshalTo(dAtA[i:]) + nn43, err := m.Details.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn42 + i += nn43 } return i, nil } @@ -4226,11 +4253,11 @@ func (m *Progress_HighWater) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintJobs(dAtA, i, uint64(m.HighWater.Size())) - n43, err := m.HighWater.MarshalTo(dAtA[i:]) + n44, err := m.HighWater.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n44 } return i, nil } @@ -4240,11 +4267,11 @@ func (m *Progress_Backup) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Backup.Size())) - n44, err := m.Backup.MarshalTo(dAtA[i:]) + n45, err := m.Backup.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n45 } return i, nil } @@ -4254,11 +4281,11 @@ func (m *Progress_Restore) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x5a i++ i = encodeVarintJobs(dAtA, i, uint64(m.Restore.Size())) - n45, err := m.Restore.MarshalTo(dAtA[i:]) + n46, err := m.Restore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n46 } return i, nil } @@ -4268,11 +4295,11 @@ func (m *Progress_SchemaChange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x62 i++ i = encodeVarintJobs(dAtA, i, uint64(m.SchemaChange.Size())) - n46, err := m.SchemaChange.MarshalTo(dAtA[i:]) + n47, err := m.SchemaChange.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n47 } return i, nil } @@ -4282,11 +4309,11 @@ func (m *Progress_Import) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x6a i++ i = encodeVarintJobs(dAtA, i, uint64(m.Import.Size())) - n47, err := m.Import.MarshalTo(dAtA[i:]) + n48, err := m.Import.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n47 + i += n48 } return i, nil } @@ -4296,11 +4323,11 @@ func (m *Progress_Changefeed) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Changefeed.Size())) - n48, err := m.Changefeed.MarshalTo(dAtA[i:]) + n49, err := m.Changefeed.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n48 + i += n49 } return i, nil } @@ -4310,11 +4337,11 @@ func (m *Progress_CreateStats) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintJobs(dAtA, i, uint64(m.CreateStats.Size())) - n49, err := m.CreateStats.MarshalTo(dAtA[i:]) + n50, err := m.CreateStats.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n49 + i += n50 } return i, nil } @@ -4326,11 +4353,11 @@ func (m *Progress_SchemaChangeGC) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintJobs(dAtA, i, uint64(m.SchemaChangeGC.Size())) - n50, err := m.SchemaChangeGC.MarshalTo(dAtA[i:]) + n51, err := m.SchemaChangeGC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n51 } return i, nil } @@ -4342,11 +4369,11 @@ func (m *Progress_TypeSchemaChange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintJobs(dAtA, i, uint64(m.TypeSchemaChange.Size())) - n51, err := m.TypeSchemaChange.MarshalTo(dAtA[i:]) + n52, err := m.TypeSchemaChange.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n52 } return i, nil } @@ -4374,21 +4401,21 @@ func (m *Job) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintJobs(dAtA, i, uint64(m.Progress.Size())) - n52, err := m.Progress.MarshalTo(dAtA[i:]) + n53, err := m.Progress.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n52 + i += n53 } if m.Payload != nil { dAtA[i] = 0x1a i++ i = encodeVarintJobs(dAtA, i, uint64(m.Payload.Size())) - n53, err := m.Payload.MarshalTo(dAtA[i:]) + n54, err := m.Payload.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n53 + i += n54 } return i, nil } @@ -4845,6 +4872,16 @@ func (m *SchemaChangeGCDetails) Size() (n int) { if m.ParentID != 0 { n += 1 + sovJobs(uint64(m.ParentID)) } + if m.InterleavedTable != nil { + l = m.InterleavedTable.Size() + n += 1 + l + sovJobs(uint64(l)) + } + if len(m.InterleavedIndexes) > 0 { + for _, e := range m.InterleavedIndexes { + l = e.Size() + n += 1 + l + sovJobs(uint64(l)) + } + } return n } @@ -8492,6 +8529,70 @@ func (m *SchemaChangeGCDetails) Unmarshal(dAtA []byte) error { break } } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InterleavedTable", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowJobs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthJobs + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.InterleavedTable == nil { + m.InterleavedTable = &descpb.TableDescriptor{} + } + if err := m.InterleavedTable.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InterleavedIndexes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowJobs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthJobs + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InterleavedIndexes = append(m.InterleavedIndexes, descpb.IndexDescriptor{}) + if err := m.InterleavedIndexes[len(m.InterleavedIndexes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipJobs(dAtA[iNdEx:]) @@ -11720,250 +11821,253 @@ var ( ErrIntOverflowJobs = fmt.Errorf("proto: integer overflow") ) -func init() { proto.RegisterFile("jobs/jobspb/jobs.proto", fileDescriptor_jobs_6f3c1209a096a8fe) } +func init() { proto.RegisterFile("jobs/jobspb/jobs.proto", fileDescriptor_jobs_f1c41cd546fbc9b1) } -var fileDescriptor_jobs_6f3c1209a096a8fe = []byte{ - // 3869 bytes of a gzipped FileDescriptorProto +var fileDescriptor_jobs_f1c41cd546fbc9b1 = []byte{ + // 3915 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5a, 0x4d, 0x6c, 0x23, 0x47, - 0x76, 0x56, 0x93, 0x4d, 0xb2, 0xf9, 0x28, 0x52, 0xad, 0x1a, 0xcd, 0x0c, 0x97, 0xb1, 0x45, 0x85, + 0x76, 0x56, 0x93, 0x4d, 0xb2, 0xf9, 0x28, 0x52, 0xad, 0x92, 0x66, 0x86, 0xcb, 0x8c, 0x45, 0x85, 0xb6, 0x77, 0x7e, 0x6c, 0x53, 0x5e, 0x79, 0xb3, 0xeb, 0x9d, 0xac, 0xc7, 0x2b, 0xfe, 0x68, 0x44, - 0xce, 0xe8, 0xc7, 0x4d, 0x69, 0xbc, 0xf6, 0x62, 0xd3, 0x69, 0xb2, 0x4b, 0x54, 0x47, 0x64, 0x77, - 0x4f, 0x57, 0x73, 0xc6, 0x5a, 0x04, 0x09, 0xb0, 0x41, 0x00, 0x63, 0x4e, 0x09, 0xb0, 0xc9, 0x21, - 0xc9, 0x04, 0x01, 0x92, 0x00, 0x39, 0x04, 0x08, 0x10, 0x04, 0x49, 0x0e, 0x41, 0x4e, 0x39, 0xf8, - 0x90, 0xc3, 0x22, 0xa7, 0x45, 0x0e, 0x4c, 0x42, 0x5f, 0x72, 0xc8, 0x21, 0x40, 0x80, 0x1c, 0xe6, - 0x14, 0xd4, 0x4f, 0x37, 0x9b, 0x94, 0x46, 0xa2, 0x46, 0xf6, 0xe6, 0x32, 0xc3, 0x7e, 0x55, 0xf5, - 0x55, 0xd5, 0xab, 0xf7, 0xbe, 0xf7, 0xea, 0x95, 0xe0, 0xda, 0xaf, 0x39, 0x6d, 0xb2, 0x4a, 0xff, - 0x71, 0xdb, 0xec, 0xbf, 0xb2, 0xeb, 0x39, 0xbe, 0x83, 0xbe, 0xd6, 0x71, 0x3a, 0x47, 0x9e, 0x63, - 0x74, 0x0e, 0xcb, 0xe4, 0x51, 0xaf, 0xcc, 0x5a, 0x78, 0xaf, 0xc2, 0x55, 0xec, 0x79, 0x8e, 0x47, - 0xfb, 0xf3, 0x1f, 0x7c, 0x44, 0x61, 0xa9, 0xeb, 0x74, 0x1d, 0xf6, 0x73, 0x95, 0xfe, 0x12, 0x52, - 0xc4, 0x30, 0xdc, 0xf6, 0xaa, 0x69, 0xf8, 0x86, 0x90, 0xe5, 0x03, 0x99, 0xe5, 0xbc, 0x7d, 0xe0, - 0x78, 0x7d, 0xc3, 0x0f, 0x30, 0x5e, 0x23, 0x8f, 0x7a, 0xab, 0x1d, 0xc3, 0x37, 0x7a, 0x4e, 0x77, - 0xd5, 0xc4, 0xa4, 0xe3, 0xb6, 0x57, 0x89, 0xef, 0x0d, 0x3a, 0xfe, 0xc0, 0xc3, 0x66, 0x30, 0x7c, - 0xe0, 0x5b, 0xbd, 0xd5, 0xc3, 0x5e, 0x67, 0xd5, 0xb7, 0xfa, 0x98, 0xf8, 0x46, 0xdf, 0xe5, 0x2d, - 0xa5, 0xdf, 0x84, 0xc4, 0x03, 0x6c, 0x10, 0x8c, 0x3e, 0x81, 0x94, 0xed, 0x98, 0x58, 0xb7, 0xcc, - 0xbc, 0xb4, 0x22, 0xdd, 0xcc, 0x56, 0xd6, 0x47, 0xc3, 0x62, 0x72, 0xdb, 0x31, 0x71, 0xa3, 0xf6, - 0x7c, 0x58, 0x7c, 0xb7, 0x6b, 0xf9, 0x87, 0x83, 0x76, 0xb9, 0xe3, 0xf4, 0x57, 0xc3, 0x7d, 0x9a, - 0xed, 0xf1, 0xef, 0x55, 0xf7, 0xa8, 0xbb, 0x2a, 0x56, 0x59, 0xe6, 0xc3, 0xb4, 0x24, 0x45, 0x6c, - 0x98, 0x68, 0x09, 0x12, 0xd8, 0x75, 0x3a, 0x87, 0xf9, 0xd8, 0x8a, 0x74, 0x33, 0xae, 0xf1, 0x8f, - 0x3b, 0xf2, 0x7f, 0xfe, 0x49, 0x51, 0x2a, 0xfd, 0x79, 0x0c, 0xae, 0x57, 0x8c, 0xce, 0xd1, 0xc0, - 0xad, 0xdb, 0x1d, 0xef, 0xd8, 0xf5, 0x2d, 0xc7, 0xde, 0x61, 0xff, 0x12, 0xa4, 0x42, 0xfc, 0x08, - 0x1f, 0xb3, 0xf5, 0xcc, 0x6b, 0xf4, 0x27, 0x7a, 0x1f, 0xe4, 0xbe, 0x63, 0x62, 0x06, 0x94, 0x5b, - 0xbb, 0x55, 0x7e, 0xa1, 0xca, 0xcb, 0x63, 0xb4, 0x2d, 0xc7, 0xc4, 0x1a, 0x1b, 0x86, 0xda, 0xa0, - 0x1c, 0xf5, 0x89, 0x6e, 0xd9, 0x07, 0x4e, 0x3e, 0xbe, 0x22, 0xdd, 0xcc, 0xac, 0xdd, 0x39, 0x03, - 0xe2, 0x05, 0xcb, 0x2a, 0xdf, 0xdf, 0x6a, 0x35, 0xec, 0x03, 0xa7, 0x92, 0x19, 0x0d, 0x8b, 0x29, - 0xf1, 0xa1, 0xa5, 0x8e, 0xfa, 0x84, 0xfe, 0x28, 0xec, 0x40, 0x20, 0xa3, 0xeb, 0x1f, 0x78, 0x16, - 0x5b, 0x7f, 0x5a, 0xa3, 0x3f, 0xd1, 0x5b, 0x80, 0x30, 0xc7, 0xc3, 0xa6, 0x4e, 0xcf, 0x57, 0xa7, - 0x1b, 0x8c, 0xb1, 0x0d, 0xaa, 0x61, 0x4b, 0xcd, 0xf0, 0x8d, 0xfb, 0xf8, 0x98, 0x6b, 0x48, 0xe8, - 0xe9, 0x9f, 0x12, 0x90, 0xe5, 0x0b, 0xaa, 0x61, 0xdf, 0xb0, 0x7a, 0x04, 0x55, 0x00, 0x88, 0x6f, - 0x78, 0xbe, 0x4e, 0xcf, 0x94, 0x4d, 0x92, 0x59, 0x7b, 0x35, 0xb2, 0x1d, 0x7a, 0xe6, 0xe5, 0xc3, - 0x5e, 0xa7, 0xbc, 0x17, 0x9c, 0x79, 0x45, 0xfe, 0x7c, 0x58, 0x9c, 0xd3, 0xd2, 0x6c, 0x18, 0x95, - 0xa2, 0xbb, 0xa0, 0x60, 0xdb, 0xe4, 0x08, 0xb1, 0xd9, 0x11, 0x52, 0xd8, 0x36, 0xd9, 0xf8, 0xaf, - 0xf1, 0x1d, 0x52, 0x5d, 0xa6, 0x2b, 0xa9, 0xd1, 0xb0, 0x18, 0xdf, 0xd7, 0x1a, 0x7c, 0xab, 0x37, - 0x60, 0xa1, 0xcd, 0xd6, 0xab, 0xf7, 0x0d, 0xdb, 0x3a, 0xc0, 0xc4, 0xcf, 0xcb, 0x6c, 0x9f, 0x39, - 0x2e, 0xde, 0x12, 0x52, 0xf4, 0x5b, 0x12, 0x5c, 0x19, 0x78, 0x16, 0xd1, 0xdb, 0xc7, 0x7a, 0xcf, - 0xe9, 0x18, 0x3d, 0xcb, 0x3f, 0xd6, 0x8f, 0x1e, 0xe7, 0x13, 0x2b, 0xf1, 0x9b, 0x99, 0xb5, 0xbb, - 0xe7, 0x1e, 0x90, 0xd0, 0x47, 0x79, 0xdf, 0xb3, 0x48, 0xe5, 0xf8, 0x81, 0x40, 0xb8, 0xff, 0xb8, - 0x6e, 0xfb, 0xde, 0x71, 0x65, 0x69, 0x34, 0x2c, 0xaa, 0xfb, 0x5a, 0x23, 0xda, 0xf4, 0x50, 0x53, - 0x07, 0x53, 0x9d, 0x91, 0x06, 0x80, 0xc3, 0x93, 0xce, 0x27, 0x99, 0x2e, 0xd6, 0x2e, 0x6e, 0x1c, - 0x5a, 0x04, 0x05, 0xfd, 0xae, 0x04, 0x05, 0xea, 0x66, 0xb8, 0x43, 0x8f, 0x3b, 0x74, 0x3d, 0xdd, - 0xc3, 0x1d, 0xc7, 0x33, 0xf3, 0x29, 0xaa, 0x8e, 0x4a, 0xeb, 0x5f, 0x67, 0xf5, 0x2e, 0xe6, 0xc4, - 0x83, 0x81, 0x65, 0x96, 0xf7, 0xf7, 0x1b, 0xb5, 0xd1, 0xb0, 0x98, 0xdf, 0x0d, 0xc0, 0xc3, 0x03, - 0xd2, 0x18, 0xb4, 0x96, 0x77, 0x5f, 0xd0, 0x82, 0xde, 0x83, 0x5c, 0xc7, 0xe9, 0xf5, 0x70, 0x87, - 0xae, 0x50, 0xdf, 0xd7, 0x1a, 0x79, 0x85, 0x1d, 0xde, 0xe2, 0x68, 0x58, 0xcc, 0x56, 0xc3, 0x16, - 0x7a, 0x8c, 0xd9, 0x4e, 0xf4, 0xb3, 0x50, 0x85, 0xab, 0xa7, 0xaa, 0x38, 0xea, 0xa6, 0x69, 0xee, - 0xa6, 0x4b, 0x90, 0x78, 0x6c, 0xf4, 0x06, 0xdc, 0xa6, 0xd2, 0x1a, 0xff, 0xb8, 0x13, 0x7b, 0x4f, - 0x2a, 0xa9, 0x90, 0xe3, 0x9a, 0xdb, 0xf5, 0x9c, 0xae, 0x87, 0x09, 0x29, 0xfd, 0x61, 0x0e, 0x72, - 0x1a, 0x26, 0xbe, 0xe3, 0xe1, 0xc0, 0xb2, 0xff, 0x5a, 0x82, 0x2b, 0x94, 0xca, 0x3c, 0xcb, 0xf5, - 0x1d, 0x4f, 0xf7, 0xf0, 0x13, 0xcf, 0xf2, 0x31, 0xc9, 0xc7, 0x98, 0x45, 0xac, 0x9f, 0x71, 0x2a, - 0x93, 0x40, 0xe5, 0x5a, 0x08, 0xa2, 0x09, 0x0c, 0x6e, 0x14, 0x77, 0x7f, 0xfc, 0x6f, 0xc5, 0x3b, - 0x33, 0xe9, 0xfc, 0x24, 0xbb, 0x96, 0x1b, 0x35, 0x0d, 0x99, 0x27, 0x80, 0xd1, 0x2b, 0x20, 0x53, - 0xa3, 0xca, 0xc7, 0x57, 0xe2, 0x37, 0xd3, 0x15, 0x65, 0x34, 0x2c, 0xca, 0xd4, 0xec, 0x34, 0x26, - 0x9d, 0x70, 0x34, 0xf9, 0x25, 0x1c, 0xed, 0x1e, 0x64, 0x7c, 0xa3, 0xdd, 0xc3, 0x3a, 0x9d, 0x99, - 0x08, 0xdf, 0xf8, 0xfa, 0x94, 0x26, 0xc8, 0xa3, 0x5e, 0xdb, 0x20, 0xb8, 0xbc, 0x47, 0x7b, 0x46, - 0xf6, 0x0e, 0x7e, 0x20, 0x20, 0x68, 0x15, 0x32, 0xce, 0x63, 0xec, 0x79, 0x96, 0x89, 0x75, 0xb3, - 0xcd, 0x0c, 0x3d, 0x5d, 0xc9, 0x8d, 0x86, 0x45, 0xd8, 0x11, 0xe2, 0x5a, 0x45, 0x83, 0xa0, 0x4b, - 0xad, 0x8d, 0x7c, 0x58, 0x12, 0x7e, 0x1c, 0x3a, 0x27, 0xe3, 0xcf, 0x14, 0x5b, 0xc2, 0x77, 0x67, - 0x3f, 0x0c, 0x7e, 0xee, 0x81, 0xf1, 0x30, 0x06, 0xe5, 0x9b, 0x44, 0xed, 0x13, 0x2d, 0xe8, 0x4d, - 0x58, 0x74, 0x3d, 0xec, 0x1a, 0x1e, 0xd6, 0x3b, 0x4e, 0xdf, 0xed, 0x61, 0x1f, 0x9b, 0xcc, 0x52, - 0x15, 0x4d, 0x15, 0x0d, 0xd5, 0x40, 0x8e, 0xde, 0x80, 0x1c, 0xf1, 0x0d, 0x9f, 0x12, 0x3b, 0xc1, - 0x1e, 0xed, 0x99, 0x66, 0x3d, 0xb3, 0x4c, 0xda, 0x10, 0x42, 0x74, 0x0b, 0x54, 0xa6, 0x08, 0xa2, - 0xbb, 0x83, 0x76, 0xcf, 0x22, 0x87, 0xd8, 0xcc, 0x03, 0xeb, 0xb8, 0xc0, 0xe5, 0xbb, 0x81, 0x18, - 0x1d, 0x4f, 0x18, 0x60, 0x87, 0xaa, 0xc3, 0xe8, 0xe2, 0x7c, 0x66, 0x45, 0xba, 0x99, 0xa8, 0x6c, - 0x3e, 0x1f, 0x16, 0x6b, 0x33, 0x5b, 0x0f, 0xc1, 0xfd, 0x55, 0xdf, 0xc3, 0x38, 0x62, 0x8c, 0x55, - 0x81, 0x17, 0xb5, 0xa3, 0x40, 0x36, 0x45, 0x44, 0xf3, 0x5f, 0x0a, 0x11, 0xed, 0x42, 0xca, 0xc7, - 0xb6, 0x61, 0xfb, 0x24, 0x9f, 0x65, 0xc7, 0xf6, 0xce, 0xec, 0xc7, 0xb6, 0xc7, 0x06, 0x06, 0xf6, - 0x28, 0x60, 0x50, 0x0d, 0xc0, 0x3f, 0x76, 0x03, 0x73, 0xcc, 0x31, 0xd0, 0x37, 0x5e, 0x64, 0x8e, - 0xc7, 0x6e, 0xd4, 0x1a, 0xd3, 0xbe, 0xf8, 0x26, 0xa8, 0x09, 0xf3, 0xa4, 0x73, 0x88, 0xfb, 0x86, - 0xc0, 0x59, 0x60, 0x38, 0x37, 0x5e, 0x80, 0xd3, 0x62, 0x5d, 0x23, 0x48, 0x19, 0x12, 0x4a, 0x48, - 0xe1, 0x7f, 0x24, 0x58, 0x3c, 0xe1, 0xef, 0x68, 0x0f, 0x62, 0x61, 0x46, 0x43, 0x29, 0x33, 0xc6, - 0xb2, 0x99, 0xcb, 0xf8, 0x7e, 0xcc, 0x32, 0x51, 0x17, 0xd2, 0xd4, 0x02, 0x6d, 0x9f, 0xa6, 0x4b, - 0x31, 0x06, 0xde, 0x1c, 0x0d, 0x8b, 0xca, 0x2e, 0x13, 0x5e, 0x7a, 0x0a, 0x85, 0x83, 0x37, 0x4c, - 0x54, 0x84, 0x8c, 0xef, 0xe8, 0xf8, 0x53, 0x8b, 0xf8, 0x96, 0xdd, 0x65, 0x71, 0x56, 0xd1, 0xc0, - 0x77, 0xea, 0x42, 0x52, 0xf8, 0xa3, 0x18, 0xa0, 0x93, 0x8e, 0x85, 0xfe, 0x5e, 0x82, 0x57, 0x82, - 0x98, 0xea, 0x78, 0x56, 0xd7, 0xb2, 0x8d, 0xde, 0x44, 0x70, 0x95, 0x98, 0xa6, 0x3f, 0xb9, 0x8c, - 0xf7, 0x8a, 0x80, 0xbb, 0x23, 0xe0, 0xa7, 0x03, 0xef, 0x2b, 0x34, 0x40, 0xf1, 0xc0, 0x7b, 0xa2, - 0xcb, 0x43, 0x2d, 0x3f, 0x78, 0xc1, 0xe0, 0xc2, 0x7d, 0x78, 0xf5, 0x4c, 0xe0, 0x8b, 0x84, 0x9b, - 0xc2, 0x8f, 0x25, 0xb8, 0xfe, 0x82, 0x20, 0x10, 0xc5, 0xc9, 0x72, 0x9c, 0x0f, 0xa3, 0x38, 0x99, - 0xb5, 0x5f, 0xbe, 0x44, 0xa0, 0x89, 0x2e, 0xe2, 0x9b, 0x90, 0xe4, 0x4e, 0x84, 0xae, 0x85, 0xd6, - 0x28, 0x57, 0x92, 0xdc, 0x1a, 0x99, 0x3d, 0x21, 0x90, 0x19, 0xa7, 0xf2, 0x44, 0x90, 0xfd, 0x6e, - 0xca, 0x8a, 0xa4, 0xc6, 0x4a, 0xef, 0xc0, 0x82, 0x98, 0x2a, 0x08, 0x98, 0xe8, 0x55, 0x80, 0x43, - 0xab, 0x7b, 0xa8, 0x3f, 0x31, 0x7c, 0xec, 0x89, 0xe4, 0x38, 0x4d, 0x25, 0x1f, 0x51, 0x41, 0xe9, - 0x33, 0x05, 0xb2, 0x8d, 0xbe, 0xeb, 0x78, 0x7e, 0x10, 0x4e, 0x1f, 0x40, 0x92, 0xf3, 0x9b, 0x38, - 0xf5, 0xf2, 0x19, 0xfb, 0x9a, 0x18, 0xc9, 0x03, 0x89, 0x70, 0x7d, 0x81, 0x11, 0xc6, 0xb9, 0xd8, - 0xa9, 0x71, 0xee, 0x7d, 0x48, 0xf2, 0xfb, 0x89, 0xc8, 0xaf, 0x8b, 0x91, 0xb9, 0x82, 0xdb, 0x41, - 0x63, 0x67, 0xc3, 0xea, 0xe1, 0x0d, 0xd6, 0x2d, 0x00, 0xe7, 0x83, 0xd0, 0xd7, 0x41, 0x21, 0xc4, - 0xd7, 0x89, 0xf5, 0x23, 0x1e, 0x26, 0xe3, 0x3c, 0xc9, 0x6e, 0xb5, 0xf6, 0x5a, 0xd6, 0x8f, 0xb0, - 0x96, 0x22, 0xc4, 0xa7, 0x3f, 0x50, 0x01, 0x94, 0x27, 0x46, 0xaf, 0xc7, 0xc2, 0x69, 0x82, 0x5d, - 0x2a, 0xc2, 0xef, 0x49, 0xe7, 0x4c, 0x7e, 0xb5, 0xce, 0x29, 0x22, 0xa3, 0x6b, 0xf8, 0x87, 0x2c, - 0x9d, 0x4b, 0x6b, 0xc0, 0x45, 0xbb, 0x86, 0x7f, 0x88, 0xf2, 0x90, 0x22, 0x06, 0x0d, 0x52, 0x24, - 0xaf, 0xac, 0xc4, 0x6f, 0xce, 0x6b, 0xc1, 0x27, 0x5a, 0x06, 0x16, 0x62, 0xf9, 0x27, 0x8b, 0x56, - 0x71, 0x2d, 0x22, 0x61, 0x7a, 0x38, 0xb2, 0x5c, 0xfd, 0xe0, 0x88, 0xf0, 0x10, 0x25, 0xf4, 0x70, - 0x64, 0xb9, 0x1b, 0xf7, 0x89, 0x96, 0xa2, 0x8d, 0x1b, 0x47, 0x84, 0x26, 0xd9, 0x96, 0xdd, 0xc5, - 0xc4, 0xd7, 0x4d, 0xcb, 0xc3, 0x1d, 0xbf, 0x77, 0xcc, 0x62, 0x94, 0xa2, 0xe5, 0xb8, 0xb8, 0x26, - 0xa4, 0x34, 0xf6, 0x4d, 0xc7, 0x53, 0x16, 0x5b, 0x14, 0x6d, 0x61, 0x2a, 0x9c, 0x9e, 0x1a, 0x26, - 0xb3, 0xa7, 0x87, 0xc9, 0x73, 0x12, 0xdc, 0x6b, 0xff, 0x0f, 0x09, 0x6e, 0xe1, 0xb3, 0x18, 0x24, - 0x98, 0xdd, 0xa2, 0x3b, 0x20, 0xd3, 0x63, 0x13, 0x57, 0xa3, 0x59, 0x93, 0x25, 0x36, 0x86, 0x7a, - 0xa4, 0x6d, 0xf4, 0x71, 0x1e, 0xb1, 0x43, 0x65, 0xbf, 0xd1, 0x75, 0x48, 0x11, 0xfc, 0x48, 0x7f, - 0x6c, 0xf4, 0xf2, 0x57, 0xd8, 0x89, 0x25, 0x09, 0x7e, 0xf4, 0xd0, 0xe8, 0xa1, 0xab, 0x90, 0xb4, - 0x88, 0x6e, 0xe3, 0x27, 0xf9, 0x25, 0xa6, 0xa7, 0x84, 0x45, 0xb6, 0xf1, 0x13, 0x46, 0xde, 0x86, - 0xd7, 0xc5, 0xbe, 0xde, 0x71, 0x7a, 0x24, 0x7f, 0x95, 0x3a, 0x0c, 0xcd, 0xc5, 0xa8, 0xa8, 0xea, - 0xf4, 0x48, 0x53, 0x56, 0x62, 0x6a, 0xbc, 0x29, 0x2b, 0x71, 0x55, 0x6e, 0xca, 0x8a, 0xac, 0x26, - 0x9a, 0xb2, 0x92, 0x50, 0x93, 0x4d, 0x59, 0x49, 0xaa, 0xa9, 0xa6, 0xac, 0xa4, 0x54, 0xa5, 0x29, - 0x2b, 0x8a, 0x9a, 0x6e, 0xca, 0x4a, 0x5a, 0x85, 0xa6, 0xac, 0x80, 0x9a, 0x69, 0xca, 0x4a, 0x46, - 0x9d, 0x6f, 0xca, 0xca, 0xbc, 0x9a, 0x6d, 0xca, 0x4a, 0x56, 0xcd, 0x35, 0x65, 0x25, 0xa7, 0x2e, - 0x34, 0x65, 0x65, 0x41, 0x55, 0x9b, 0xb2, 0xa2, 0xaa, 0x8b, 0x4d, 0x59, 0x59, 0x54, 0x51, 0xe9, - 0xbf, 0x24, 0xc8, 0x71, 0x87, 0x0e, 0xc9, 0xe3, 0x4d, 0x58, 0x64, 0x26, 0x66, 0xd9, 0x5d, 0xdd, - 0x15, 0x42, 0x46, 0x0b, 0x31, 0x4d, 0x0d, 0x1a, 0xc2, 0xce, 0xaf, 0x41, 0xd6, 0xc3, 0x86, 0x39, - 0xee, 0x18, 0x63, 0x1d, 0xe7, 0xa9, 0x30, 0xec, 0xf4, 0x06, 0xe4, 0x18, 0xe3, 0x8d, 0x7b, 0xc5, - 0x59, 0xaf, 0x2c, 0x93, 0x86, 0xdd, 0x2a, 0x90, 0x25, 0xae, 0x61, 0x8f, 0x7b, 0xc9, 0x8c, 0x8b, - 0xae, 0x9f, 0xc2, 0x0f, 0x2d, 0xd7, 0xb0, 0x05, 0x2f, 0xcc, 0xd3, 0x31, 0x51, 0xe6, 0xf3, 0x30, - 0x19, 0xf4, 0xb1, 0xee, 0x3a, 0x3c, 0x07, 0x8e, 0x6b, 0x69, 0x2e, 0xd9, 0x75, 0x48, 0xe9, 0xd7, - 0xe1, 0x3a, 0x4d, 0x35, 0x78, 0x9a, 0x50, 0x3d, 0x34, 0xec, 0x6e, 0x78, 0xa3, 0x30, 0x20, 0xc5, - 0xd2, 0x95, 0x30, 0x17, 0xd8, 0x1c, 0x0d, 0x8b, 0x49, 0xda, 0xfb, 0xd2, 0x7c, 0x90, 0xa4, 0xc0, - 0x0d, 0xb3, 0x54, 0x80, 0xfc, 0xf4, 0xec, 0xe1, 0x1d, 0x47, 0x63, 0x57, 0x9c, 0x41, 0x1f, 0xd3, - 0xad, 0x3d, 0xb0, 0x88, 0x8f, 0xbe, 0x07, 0xf3, 0x62, 0x2b, 0x74, 0x87, 0x01, 0x33, 0x9f, 0xa3, - 0x8d, 0x8c, 0x17, 0x82, 0x90, 0xd2, 0xdf, 0x48, 0x70, 0xa5, 0xe6, 0x39, 0xae, 0x8b, 0x4d, 0x61, - 0xc2, 0x7c, 0xab, 0x81, 0xe5, 0x4a, 0x11, 0xcb, 0xdd, 0x86, 0x58, 0xa3, 0x26, 0x12, 0x95, 0xbb, - 0x97, 0xcd, 0x7f, 0x1a, 0x35, 0xf4, 0x1d, 0x48, 0xd2, 0xd4, 0x7a, 0x40, 0x18, 0xcb, 0xe7, 0xd6, - 0x7e, 0xf1, 0x8c, 0x88, 0xd2, 0x62, 0x1d, 0x35, 0x31, 0xa0, 0xf4, 0x2f, 0x32, 0x5c, 0x8d, 0xea, - 0xe8, 0x5e, 0x35, 0x58, 0xf8, 0x0f, 0x21, 0x65, 0xd9, 0x26, 0xfe, 0x34, 0x8c, 0x53, 0xef, 0x9f, - 0x85, 0x7a, 0x1a, 0x44, 0x59, 0xe8, 0xa3, 0x41, 0x61, 0x82, 0x8c, 0x55, 0x60, 0xa2, 0xef, 0x87, - 0x51, 0x90, 0x5f, 0x23, 0xef, 0xbc, 0x34, 0x7a, 0x6d, 0x2a, 0x22, 0x4e, 0x04, 0x9c, 0x38, 0x8b, - 0x5a, 0x5f, 0x49, 0xc0, 0x29, 0xfc, 0xbe, 0x04, 0xf3, 0xd1, 0x2d, 0x22, 0x0b, 0x14, 0xb6, 0xbd, - 0xc0, 0xae, 0xe3, 0x95, 0x6d, 0x1a, 0x26, 0x58, 0x23, 0x9b, 0xf7, 0x83, 0x97, 0x9e, 0x97, 0x43, - 0x08, 0xf5, 0x35, 0x4c, 0xf4, 0x0b, 0x90, 0x36, 0x3d, 0xc7, 0x1d, 0x97, 0x8a, 0xe2, 0x9a, 0x42, - 0x05, 0x94, 0x7e, 0x0b, 0xbf, 0x01, 0xe9, 0x50, 0x39, 0x91, 0x94, 0x3b, 0xfe, 0x25, 0xa6, 0xdc, - 0x67, 0xcd, 0x5f, 0xfa, 0xdf, 0x04, 0x5c, 0x39, 0xcd, 0xed, 0x3f, 0x06, 0x35, 0xe2, 0x65, 0x7a, - 0xcf, 0x22, 0xbe, 0x38, 0xfd, 0x5b, 0x67, 0xe7, 0x76, 0x11, 0x57, 0x15, 0x87, 0x9d, 0xf3, 0x26, - 0x1d, 0xf8, 0x07, 0x90, 0x33, 0xf9, 0x96, 0x75, 0x61, 0x56, 0xf1, 0x73, 0x93, 0xab, 0x53, 0xdc, - 0x55, 0xa0, 0x67, 0xcd, 0x48, 0x13, 0x61, 0x25, 0xb1, 0x00, 0xdd, 0x34, 0x7c, 0x83, 0x06, 0x2a, - 0x7a, 0xc6, 0x32, 0xf3, 0xe0, 0xd6, 0x68, 0x58, 0x5c, 0x14, 0x58, 0x35, 0xd1, 0x7a, 0x69, 0x1d, - 0x2f, 0x9a, 0x53, 0x80, 0x26, 0x25, 0x4d, 0xda, 0x4e, 0x27, 0x4e, 0x8c, 0x49, 0x93, 0x86, 0xca, - 0xcb, 0x93, 0x26, 0xfd, 0xd9, 0x30, 0xd1, 0x6f, 0x4b, 0xb0, 0xc8, 0xeb, 0x1a, 0xfd, 0x81, 0x6f, - 0xb0, 0x92, 0x54, 0x98, 0xb4, 0x7d, 0x3c, 0x1a, 0x16, 0x17, 0x98, 0x42, 0xb6, 0x44, 0x1b, 0x9b, - 0xb6, 0xf2, 0xb2, 0xd3, 0x8e, 0x51, 0x44, 0x22, 0x13, 0x0a, 0x4c, 0x74, 0x1f, 0x72, 0x3c, 0x03, - 0xd5, 0x69, 0x0e, 0x46, 0x2f, 0xde, 0x29, 0xb6, 0x86, 0xd7, 0x9f, 0x0f, 0x8b, 0x2b, 0xa7, 0x58, - 0x16, 0x4f, 0x5e, 0x1f, 0xf2, 0xbe, 0x5a, 0xf6, 0x20, 0xfa, 0x89, 0x3a, 0x90, 0x0d, 0x4d, 0xe3, - 0xd8, 0x15, 0xc9, 0xdf, 0xe5, 0x89, 0x77, 0x3e, 0xb0, 0x11, 0x8a, 0x29, 0xae, 0x07, 0xd7, 0x60, - 0xe9, 0xd4, 0x80, 0xf3, 0x07, 0x09, 0xb8, 0x36, 0x49, 0x62, 0x61, 0x10, 0xd5, 0xa7, 0x69, 0xf6, - 0x83, 0x99, 0x89, 0x30, 0xc0, 0xe0, 0xec, 0x10, 0x7c, 0x4d, 0x13, 0xed, 0x0f, 0xa7, 0x88, 0xf6, - 0x25, 0xf0, 0xd9, 0xa9, 0x4f, 0xe1, 0x0b, 0xd0, 0xc2, 0x3f, 0x4b, 0x90, 0x9d, 0x98, 0xff, 0xe7, - 0xc9, 0x82, 0xbb, 0x61, 0xe0, 0xe3, 0x2f, 0x10, 0xef, 0x5d, 0x7c, 0x6f, 0x93, 0xf1, 0xb0, 0xf0, - 0x77, 0x12, 0x64, 0x27, 0xb6, 0xfb, 0x15, 0xf1, 0xe7, 0x97, 0xbe, 0xf2, 0xd2, 0xb7, 0x21, 0xc9, - 0x25, 0x08, 0x41, 0xee, 0xa3, 0xf5, 0xc6, 0x5e, 0x63, 0xfb, 0x9e, 0xbe, 0xb1, 0xa3, 0xe9, 0xf7, - 0xaa, 0xea, 0x1c, 0x9a, 0x07, 0xa5, 0x56, 0x7f, 0x50, 0xa7, 0x42, 0x55, 0x42, 0x19, 0x48, 0xb1, - 0xaf, 0x7a, 0x4d, 0x8d, 0x95, 0x2a, 0xa0, 0x72, 0xec, 0x03, 0x4c, 0x19, 0x8f, 0xa6, 0xc3, 0xa8, - 0x0c, 0x57, 0x28, 0x2c, 0xee, 0xd3, 0x30, 0x4a, 0x39, 0x5e, 0x8f, 0x24, 0x31, 0x8b, 0x61, 0x13, - 0x65, 0xfb, 0x6d, 0xa3, 0x8f, 0x4b, 0x7f, 0x2b, 0xc3, 0xe2, 0x18, 0x24, 0xe0, 0x7b, 0x7a, 0x6d, - 0xb2, 0xec, 0x23, 0x7d, 0xfc, 0x26, 0xc1, 0xaf, 0x4d, 0x96, 0x7d, 0xb4, 0xaf, 0x35, 0xb4, 0x14, - 0x6d, 0xdc, 0xf7, 0x2c, 0xd4, 0x04, 0xd9, 0x71, 0xfd, 0x20, 0x07, 0xfd, 0xd6, 0x19, 0xaa, 0x38, - 0x31, 0x47, 0x79, 0xc7, 0xf5, 0x79, 0x01, 0x41, 0x63, 0x18, 0xe8, 0x2f, 0x25, 0x48, 0xf1, 0x9c, - 0x9e, 0xe4, 0x93, 0x0c, 0xef, 0x3b, 0x17, 0xc2, 0xe3, 0x0a, 0x10, 0x85, 0xe9, 0x8f, 0xa8, 0xa9, - 0x3f, 0x1f, 0x16, 0x17, 0xa7, 0x15, 0x44, 0x2e, 0x59, 0xb1, 0x0e, 0x96, 0x88, 0x9a, 0xbc, 0x56, - 0x3a, 0x56, 0x34, 0x63, 0xba, 0x19, 0xcb, 0xd1, 0xd9, 0x89, 0x83, 0x28, 0x74, 0x61, 0x3e, 0xba, - 0xfa, 0x53, 0x2a, 0x2a, 0xeb, 0x93, 0x15, 0x95, 0x37, 0x67, 0xd2, 0x0c, 0xc7, 0x8c, 0x56, 0x50, - 0xbe, 0x0d, 0xe9, 0x50, 0xed, 0x17, 0xa9, 0xff, 0x70, 0x96, 0x0c, 0xef, 0x59, 0x09, 0x35, 0x59, - 0xfa, 0x2b, 0x09, 0xe6, 0x35, 0x4c, 0x9c, 0xde, 0x63, 0x6c, 0xd2, 0x60, 0x8e, 0xbe, 0x01, 0x32, - 0x4d, 0x0e, 0xc4, 0x2d, 0xf1, 0x9c, 0x0c, 0x9c, 0x75, 0x45, 0xeb, 0x90, 0x0e, 0xef, 0xba, 0x17, - 0x79, 0x36, 0x1b, 0x8f, 0xa2, 0x97, 0xec, 0xb6, 0x33, 0xb0, 0x4d, 0xc3, 0x3b, 0xd6, 0x3d, 0x6c, - 0x74, 0xe8, 0x25, 0x9b, 0x57, 0xf7, 0x16, 0x02, 0xb9, 0xc6, 0xc5, 0xa5, 0xcf, 0x62, 0x80, 0xc6, - 0xca, 0x89, 0xd0, 0x04, 0x4d, 0x49, 0xd8, 0x3e, 0xc4, 0x1d, 0x22, 0x76, 0x6a, 0xf5, 0x74, 0x2a, - 0xb3, 0x09, 0x37, 0x1e, 0x1c, 0xa9, 0x17, 0x91, 0x11, 0xf4, 0x7b, 0x67, 0xdf, 0xe8, 0xe3, 0xec, - 0x46, 0xcf, 0xac, 0xf4, 0xe7, 0x7a, 0xab, 0x17, 0xe1, 0xee, 0x1f, 0x65, 0x40, 0x55, 0x0f, 0x1b, - 0x3e, 0xa6, 0xcc, 0x43, 0xce, 0xba, 0xf2, 0x54, 0x20, 0xc1, 0x02, 0x86, 0x38, 0x9f, 0x19, 0x6f, - 0xff, 0x42, 0x29, 0x7c, 0x28, 0xfa, 0x15, 0x98, 0xef, 0x38, 0xbd, 0x41, 0xdf, 0xd6, 0xd9, 0x43, - 0x82, 0xc8, 0xf0, 0x7e, 0xe9, 0x2c, 0x23, 0x3e, 0xb1, 0xb8, 0x72, 0xd5, 0xe9, 0xd1, 0xef, 0xe0, - 0x0a, 0xc7, 0x01, 0x59, 0x0f, 0xf4, 0x0a, 0xa4, 0x43, 0x87, 0x62, 0xb9, 0x5d, 0x5a, 0x1b, 0x0b, - 0xd0, 0x1a, 0x24, 0x0c, 0xa2, 0x3b, 0x07, 0x2c, 0xf9, 0x3a, 0xcf, 0xc2, 0x34, 0xd9, 0x20, 0x3b, - 0x07, 0xe8, 0x5d, 0xc8, 0x1e, 0x3c, 0xe2, 0x09, 0x29, 0x27, 0x50, 0xfe, 0xbe, 0xb3, 0x30, 0x1a, - 0x16, 0x33, 0x1b, 0x1f, 0xb2, 0xcd, 0x52, 0xfa, 0xd4, 0x32, 0x07, 0x8f, 0xc2, 0x0f, 0x74, 0x1b, - 0x16, 0xfb, 0xc6, 0xa7, 0xfa, 0x81, 0x67, 0x74, 0x44, 0x06, 0xd6, 0xe3, 0xac, 0x20, 0x69, 0x0b, - 0x7d, 0xe3, 0xd3, 0x0d, 0x21, 0x6f, 0x98, 0x3d, 0x5c, 0xf8, 0x07, 0x09, 0x52, 0x62, 0x47, 0xc8, - 0x05, 0x10, 0xea, 0xb1, 0x4c, 0x9e, 0x4c, 0x64, 0x2b, 0x1f, 0x8e, 0x86, 0xc5, 0x74, 0x95, 0x49, - 0x1b, 0x35, 0xf2, 0x7c, 0x58, 0xfc, 0xde, 0xcb, 0x92, 0x56, 0x00, 0xa2, 0xa5, 0xf9, 0x24, 0x0d, - 0x93, 0x15, 0x24, 0x0e, 0x0d, 0xa2, 0x1f, 0x5a, 0xc4, 0x77, 0xba, 0x9e, 0xd1, 0x67, 0x87, 0xab, - 0x68, 0xf3, 0x87, 0x06, 0xd9, 0x0c, 0x64, 0xa8, 0x40, 0xd3, 0x81, 0xc7, 0xfc, 0x1d, 0x88, 0xbb, - 0x54, 0xf8, 0x5d, 0xba, 0x0a, 0x57, 0x22, 0x47, 0x14, 0xa6, 0x4b, 0x7f, 0x0c, 0x90, 0xda, 0x35, - 0x8e, 0x7b, 0x8e, 0x61, 0xa2, 0x15, 0xc8, 0x04, 0xaf, 0x32, 0x34, 0x0f, 0xe4, 0x36, 0x15, 0x15, - 0xd1, 0x09, 0x06, 0x04, 0x7b, 0x4c, 0xbf, 0x9c, 0x71, 0xc2, 0x6f, 0xf1, 0x14, 0x45, 0xe7, 0xd2, - 0xfb, 0x56, 0xc7, 0x73, 0xf8, 0x0d, 0x39, 0xce, 0x98, 0x93, 0x4a, 0xb7, 0x98, 0x10, 0xdd, 0x80, - 0x85, 0x03, 0xcb, 0x66, 0x45, 0xb4, 0xa0, 0x1f, 0x2b, 0x77, 0x6a, 0xb9, 0x40, 0x2c, 0x3a, 0x3e, - 0x86, 0x5c, 0xe4, 0x21, 0x8a, 0xea, 0x39, 0xc9, 0xf4, 0xbc, 0x33, 0x1a, 0x16, 0xb3, 0x63, 0xbb, - 0xe5, 0xba, 0xbe, 0x4c, 0x80, 0xc8, 0x8e, 0xa7, 0xa1, 0x9a, 0x5e, 0x82, 0x04, 0xfb, 0x53, 0x15, - 0xfe, 0x3a, 0xac, 0xf1, 0x0f, 0xf4, 0x2d, 0x48, 0xf4, 0xb0, 0x41, 0x78, 0xc5, 0x32, 0xb3, 0xb6, - 0x72, 0x86, 0x27, 0xb0, 0xbf, 0x2a, 0xd1, 0x78, 0x77, 0x54, 0x81, 0x24, 0x2f, 0x8b, 0xb2, 0x62, - 0x66, 0x66, 0xed, 0xe6, 0xac, 0x8f, 0xfa, 0x9b, 0x73, 0x9a, 0x18, 0x89, 0xea, 0x90, 0xf2, 0x78, - 0x25, 0x9c, 0x95, 0x38, 0xcf, 0xbd, 0xc2, 0x45, 0xca, 0xf3, 0x9b, 0x73, 0x5a, 0x30, 0x16, 0xed, - 0x05, 0x4f, 0x4e, 0x9c, 0x52, 0xc5, 0x03, 0x5b, 0x79, 0xc6, 0x6c, 0x68, 0x0c, 0x38, 0x81, 0x42, - 0x37, 0x68, 0xb1, 0x42, 0x1b, 0xab, 0x94, 0x9e, 0xbd, 0xc1, 0x89, 0x12, 0x3b, 0xdd, 0x20, 0x1f, - 0x89, 0xb6, 0x01, 0x3a, 0x21, 0xcd, 0xe7, 0x73, 0x0c, 0xe7, 0xad, 0x8b, 0xa4, 0x12, 0x9b, 0x73, - 0x5a, 0x04, 0x01, 0x7d, 0x08, 0x99, 0xce, 0xd8, 0xd6, 0xf3, 0x0b, 0x0c, 0xf0, 0xed, 0x0b, 0x91, - 0xd7, 0x26, 0x25, 0xac, 0xb1, 0x74, 0x92, 0xb0, 0xd4, 0x69, 0xc2, 0xaa, 0x43, 0x56, 0xdc, 0xb6, - 0xf9, 0x5f, 0x39, 0xe5, 0x17, 0x19, 0x5f, 0x46, 0xad, 0x24, 0xf8, 0x3b, 0xa8, 0x72, 0xdd, 0xee, - 0x38, 0x26, 0x36, 0xeb, 0xf4, 0x5b, 0x13, 0xa5, 0x30, 0xf6, 0x41, 0xd0, 0x3d, 0xc8, 0x75, 0x7a, - 0xd8, 0xb0, 0x07, 0x6e, 0x80, 0x83, 0x66, 0xc4, 0xc9, 0x8a, 0x71, 0x02, 0x68, 0x1b, 0xd0, 0x01, - 0x7b, 0xf8, 0x8a, 0xae, 0x8a, 0x95, 0x6e, 0x67, 0x01, 0x53, 0xd9, 0x58, 0x6d, 0xbc, 0x32, 0xf4, - 0x3a, 0x64, 0x6d, 0xc7, 0xee, 0x18, 0x76, 0x07, 0xf7, 0x58, 0x68, 0xe1, 0xd5, 0xde, 0x49, 0x21, - 0xfa, 0x04, 0x72, 0x64, 0x22, 0x7f, 0xce, 0x5f, 0x65, 0x33, 0xbe, 0x73, 0xd1, 0x7a, 0xd3, 0xe6, - 0x9c, 0x36, 0x85, 0x84, 0x7e, 0x15, 0x54, 0x7f, 0xaa, 0xc6, 0xc8, 0x8a, 0xec, 0x67, 0xbf, 0x10, - 0xbf, 0xa0, 0x28, 0xba, 0x39, 0xa7, 0x9d, 0x40, 0xab, 0xa4, 0xe9, 0x9d, 0x9f, 0x35, 0x87, 0xb5, - 0xe8, 0x94, 0xaa, 0x94, 0xfe, 0x3b, 0x09, 0x4a, 0x98, 0x79, 0xac, 0x02, 0x0a, 0x63, 0xc5, 0xf8, - 0x71, 0x9e, 0x12, 0x65, 0x6c, 0x73, 0x4e, 0x5b, 0x0c, 0xda, 0xc6, 0xef, 0xf3, 0x37, 0x60, 0xa1, - 0xef, 0x98, 0xd6, 0x81, 0x35, 0x66, 0x3b, 0x5e, 0xc1, 0xc9, 0x05, 0x62, 0xc1, 0x76, 0x77, 0x27, - 0x9e, 0xb6, 0xe2, 0x33, 0xc4, 0xbd, 0xcd, 0xb9, 0xc8, 0xdb, 0x17, 0x65, 0x5f, 0x6f, 0x60, 0xdb, - 0x96, 0xdd, 0xd5, 0xc5, 0x65, 0x87, 0x47, 0xd5, 0xac, 0x90, 0x8a, 0xfb, 0x4a, 0x75, 0x8a, 0x8e, - 0x6e, 0x9d, 0x4b, 0x47, 0xc1, 0xde, 0x37, 0xa5, 0x90, 0x8f, 0x36, 0xa6, 0xf9, 0xe8, 0xf6, 0xf9, - 0x7c, 0x14, 0x81, 0x09, 0x09, 0x69, 0xff, 0x54, 0x42, 0x5a, 0x9d, 0xd1, 0x5a, 0x22, 0x88, 0x93, - 0x8c, 0x54, 0x9d, 0x62, 0xa4, 0x5b, 0xe7, 0x32, 0x52, 0x74, 0x8f, 0x82, 0x92, 0x76, 0x4e, 0xa1, - 0xa4, 0xb7, 0x67, 0xa2, 0xa4, 0x08, 0x58, 0x94, 0x93, 0xb4, 0xd3, 0x38, 0xa9, 0x3c, 0x1b, 0x27, - 0x45, 0x20, 0x27, 0x48, 0xe9, 0x07, 0x27, 0x1c, 0x4e, 0x65, 0xb0, 0xdf, 0xb8, 0xf0, 0x0d, 0x77, - 0x53, 0x3a, 0xe1, 0x71, 0xc6, 0x29, 0x1e, 0xb7, 0xc8, 0xe0, 0xdf, 0xbd, 0x80, 0xc7, 0x45, 0x26, - 0x38, 0xe9, 0x72, 0x00, 0x4a, 0xf0, 0x28, 0x12, 0x71, 0xbf, 0xd2, 0x4f, 0x24, 0x88, 0x37, 0x9d, - 0x36, 0xca, 0x8d, 0xcb, 0x01, 0xec, 0x22, 0xff, 0xc1, 0xb8, 0xbb, 0xc8, 0x6d, 0x5f, 0x3b, 0x63, - 0x25, 0xc1, 0xcc, 0x5a, 0x38, 0x08, 0x7d, 0x17, 0x52, 0x2e, 0xcf, 0x75, 0x84, 0x87, 0x95, 0xce, - 0x1a, 0xcf, 0x7b, 0x6a, 0xc1, 0x90, 0xdb, 0xb7, 0x20, 0x37, 0xf9, 0xa7, 0x95, 0x28, 0x07, 0xb0, - 0x6b, 0x10, 0xe2, 0x1e, 0x7a, 0x06, 0xc1, 0xea, 0x1c, 0x4a, 0x41, 0xfc, 0xfe, 0x56, 0x4b, 0x95, - 0x6e, 0x7f, 0x3f, 0x5a, 0x20, 0xa8, 0x69, 0xeb, 0x8d, 0xed, 0xc6, 0xf6, 0x3d, 0x7d, 0x7b, 0x7d, - 0xab, 0xde, 0x52, 0xe7, 0x50, 0x1e, 0x96, 0x3e, 0x5a, 0x6f, 0xec, 0x89, 0x8a, 0x81, 0xde, 0xd8, - 0xde, 0xab, 0x6b, 0x0f, 0xd7, 0x1f, 0xa8, 0x12, 0xba, 0x06, 0x48, 0xdb, 0xa9, 0xde, 0x6f, 0xd5, - 0x2a, 0x7a, 0x75, 0x67, 0x6b, 0x77, 0xbd, 0xba, 0xd7, 0xd8, 0xd9, 0x56, 0x63, 0x48, 0x01, 0xb9, - 0xb6, 0xb3, 0x5d, 0x57, 0xe1, 0xf6, 0x4f, 0xe2, 0x20, 0x53, 0x1d, 0xa3, 0xd7, 0x21, 0xb3, 0xbf, - 0xdd, 0xda, 0xad, 0x57, 0x1b, 0x1b, 0x8d, 0x7a, 0x4d, 0x9d, 0x2b, 0x5c, 0x79, 0xfa, 0x6c, 0x65, - 0x81, 0x36, 0xed, 0xdb, 0xc4, 0xc5, 0x1d, 0x46, 0x2e, 0xa8, 0x00, 0xc9, 0xca, 0x7a, 0xf5, 0xfe, - 0xfe, 0xae, 0x2a, 0x15, 0x72, 0x4f, 0x9f, 0xad, 0x00, 0xed, 0xc0, 0x1d, 0x1b, 0xbd, 0x02, 0x29, - 0xad, 0xde, 0xda, 0xdb, 0xd1, 0xea, 0x6a, 0xac, 0xb0, 0xf0, 0xf4, 0xd9, 0x4a, 0x86, 0x36, 0x0a, - 0x7f, 0x45, 0x37, 0x20, 0xdb, 0xaa, 0x6e, 0xd6, 0xb7, 0xd6, 0xf5, 0xea, 0xe6, 0xfa, 0xf6, 0xbd, - 0xba, 0x1a, 0x2f, 0x2c, 0x3d, 0x7d, 0xb6, 0xa2, 0x4e, 0x1f, 0x30, 0x9d, 0xa2, 0xb1, 0xb5, 0xbb, - 0xa3, 0xed, 0xa9, 0xf2, 0x78, 0x0a, 0xee, 0x57, 0xa8, 0x04, 0xc0, 0x47, 0x6f, 0xd4, 0xeb, 0x35, - 0x35, 0x51, 0x40, 0x4f, 0x9f, 0xad, 0xe4, 0x68, 0xfb, 0xd8, 0x5d, 0xd0, 0x1b, 0x30, 0x5f, 0xd5, - 0xea, 0xeb, 0x7b, 0x75, 0xbd, 0xb5, 0xb7, 0xbe, 0xd7, 0x52, 0x93, 0xe3, 0x9d, 0x44, 0x5c, 0x00, - 0x95, 0x61, 0x71, 0x7d, 0x7f, 0x6f, 0x47, 0x9f, 0xe8, 0x9b, 0x2a, 0x5c, 0x7f, 0xfa, 0x6c, 0xe5, - 0x0a, 0xed, 0xbb, 0x3e, 0xf0, 0x9d, 0x68, 0xff, 0xb7, 0x40, 0x9d, 0x58, 0xbf, 0x7e, 0xaf, 0xaa, - 0x2a, 0x85, 0x6b, 0x4f, 0x9f, 0xad, 0xa0, 0xe9, 0x2d, 0xdc, 0xab, 0xa2, 0x6f, 0xc2, 0xb5, 0xbd, - 0x8f, 0x77, 0xeb, 0xb5, 0x7a, 0xab, 0xaa, 0x4f, 0x6e, 0x3b, 0x5d, 0xc8, 0x3f, 0x7d, 0xb6, 0xb2, - 0x44, 0xc7, 0x4c, 0x8f, 0x2b, 0x28, 0x9f, 0xfd, 0xe9, 0xf2, 0xdc, 0x5f, 0xfc, 0xd9, 0xf2, 0x5c, - 0xe5, 0xe6, 0xe7, 0xff, 0xb1, 0x3c, 0xf7, 0xf9, 0x68, 0x59, 0xfa, 0xe9, 0x68, 0x59, 0xfa, 0xd9, - 0x68, 0x59, 0xfa, 0xf7, 0xd1, 0xb2, 0xf4, 0x3b, 0x5f, 0x2c, 0xcf, 0xfd, 0xf4, 0x8b, 0xe5, 0xb9, - 0x9f, 0x7d, 0xb1, 0x3c, 0xf7, 0x49, 0x92, 0x9b, 0x55, 0x3b, 0xc9, 0xfe, 0xfa, 0xf8, 0xdd, 0xff, - 0x0b, 0x00, 0x00, 0xff, 0xff, 0x6d, 0xf7, 0x2a, 0xef, 0x4c, 0x2d, 0x00, 0x00, + 0xce, 0xe8, 0xc7, 0x4d, 0x69, 0xbc, 0xf6, 0xc2, 0xe9, 0xb4, 0xd8, 0x25, 0xa9, 0x23, 0xb2, 0xbb, + 0xa7, 0xab, 0x39, 0x63, 0x2d, 0x82, 0x04, 0xd8, 0x20, 0x81, 0x31, 0xa7, 0x04, 0xd8, 0xe4, 0x90, + 0x64, 0x82, 0x00, 0x49, 0x80, 0x1c, 0x02, 0x04, 0x08, 0x82, 0x24, 0x87, 0x20, 0xa7, 0x1c, 0x7c, + 0xc8, 0x61, 0x8f, 0x8b, 0x1c, 0x98, 0x84, 0xbe, 0xe4, 0x90, 0x43, 0x80, 0x00, 0x39, 0xcc, 0x29, + 0xa8, 0x9f, 0x6e, 0x36, 0x29, 0x0d, 0x45, 0x8d, 0x6c, 0xe7, 0x22, 0x75, 0xbf, 0xaa, 0xfa, 0xaa, + 0xeb, 0xd5, 0x7b, 0xdf, 0x7b, 0xf5, 0x8a, 0x70, 0xf5, 0xd7, 0x9c, 0x7d, 0xb2, 0x42, 0xff, 0xb8, + 0xfb, 0xec, 0x5f, 0xd9, 0xf5, 0x1c, 0xdf, 0x41, 0xdf, 0x68, 0x3b, 0xed, 0x63, 0xcf, 0x31, 0xda, + 0x47, 0x65, 0xf2, 0xa8, 0x53, 0x66, 0x2d, 0xbc, 0x57, 0xe1, 0x0a, 0xf6, 0x3c, 0xc7, 0xa3, 0xfd, + 0xf9, 0x03, 0x1f, 0x51, 0x58, 0x3c, 0x74, 0x0e, 0x1d, 0xf6, 0xb8, 0x42, 0x9f, 0x84, 0x14, 0x31, + 0x0c, 0x77, 0x7f, 0xc5, 0x34, 0x7c, 0x43, 0xc8, 0xf2, 0x81, 0xcc, 0x72, 0xde, 0x3a, 0x70, 0xbc, + 0xae, 0xe1, 0x07, 0x18, 0xaf, 0x92, 0x47, 0x9d, 0x95, 0xb6, 0xe1, 0x1b, 0x1d, 0xe7, 0x70, 0xc5, + 0xc4, 0xa4, 0xed, 0xee, 0xaf, 0x10, 0xdf, 0xeb, 0xb5, 0xfd, 0x9e, 0x87, 0xcd, 0x60, 0x78, 0xcf, + 0xb7, 0x3a, 0x2b, 0x47, 0x9d, 0xf6, 0x8a, 0x6f, 0x75, 0x31, 0xf1, 0x8d, 0xae, 0xcb, 0x5b, 0x4a, + 0xbf, 0x09, 0x89, 0x07, 0xd8, 0x20, 0x18, 0x7d, 0x0c, 0x29, 0xdb, 0x31, 0xb1, 0x6e, 0x99, 0x79, + 0x69, 0x59, 0xba, 0x99, 0xad, 0xac, 0x0d, 0xfa, 0xc5, 0xe4, 0x96, 0x63, 0xe2, 0x46, 0xed, 0x79, + 0xbf, 0xf8, 0xce, 0xa1, 0xe5, 0x1f, 0xf5, 0xf6, 0xcb, 0x6d, 0xa7, 0xbb, 0x12, 0xae, 0xd3, 0xdc, + 0x1f, 0x3e, 0xaf, 0xb8, 0xc7, 0x87, 0x2b, 0xe2, 0x2b, 0xcb, 0x7c, 0x98, 0x96, 0xa4, 0x88, 0x0d, + 0x13, 0x2d, 0x42, 0x02, 0xbb, 0x4e, 0xfb, 0x28, 0x1f, 0x5b, 0x96, 0x6e, 0xc6, 0x35, 0xfe, 0x72, + 0x47, 0xfe, 0xcf, 0x3f, 0x2d, 0x4a, 0xa5, 0xbf, 0x88, 0xc1, 0xb5, 0x8a, 0xd1, 0x3e, 0xee, 0xb9, + 0x75, 0xbb, 0xed, 0x9d, 0xb8, 0xbe, 0xe5, 0xd8, 0xdb, 0xec, 0x2f, 0x41, 0x2a, 0xc4, 0x8f, 0xf1, + 0x09, 0xfb, 0x9e, 0x59, 0x8d, 0x3e, 0xa2, 0xf7, 0x40, 0xee, 0x3a, 0x26, 0x66, 0x40, 0xb9, 0xd5, + 0x5b, 0xe5, 0x17, 0xaa, 0xbc, 0x3c, 0x44, 0xdb, 0x74, 0x4c, 0xac, 0xb1, 0x61, 0x68, 0x1f, 0x94, + 0xe3, 0x2e, 0xd1, 0x2d, 0xfb, 0xc0, 0xc9, 0xc7, 0x97, 0xa5, 0x9b, 0x99, 0xd5, 0x3b, 0x13, 0x20, + 0x5e, 0xf0, 0x59, 0xe5, 0xfb, 0x9b, 0xad, 0x86, 0x7d, 0xe0, 0x54, 0x32, 0x83, 0x7e, 0x31, 0x25, + 0x5e, 0xb4, 0xd4, 0x71, 0x97, 0xd0, 0x87, 0xc2, 0x36, 0x04, 0x32, 0xfa, 0xfd, 0x3d, 0xcf, 0x62, + 0xdf, 0x9f, 0xd6, 0xe8, 0x23, 0x7a, 0x13, 0x10, 0xe6, 0x78, 0xd8, 0xd4, 0xe9, 0xfe, 0xea, 0x74, + 0x81, 0x31, 0xb6, 0x40, 0x35, 0x6c, 0xa9, 0x19, 0xbe, 0x71, 0x1f, 0x9f, 0x70, 0x0d, 0x09, 0x3d, + 0xfd, 0x73, 0x02, 0xb2, 0xfc, 0x83, 0x6a, 0xd8, 0x37, 0xac, 0x0e, 0x41, 0x15, 0x00, 0xe2, 0x1b, + 0x9e, 0xaf, 0xd3, 0x3d, 0x65, 0x93, 0x64, 0x56, 0x5f, 0x89, 0x2c, 0x87, 0xee, 0x79, 0xf9, 0xa8, + 0xd3, 0x2e, 0xef, 0x06, 0x7b, 0x5e, 0x91, 0x3f, 0xef, 0x17, 0x67, 0xb4, 0x34, 0x1b, 0x46, 0xa5, + 0xe8, 0x2e, 0x28, 0xd8, 0x36, 0x39, 0x42, 0x6c, 0x7a, 0x84, 0x14, 0xb6, 0x4d, 0x36, 0xfe, 0x1b, + 0x7c, 0x85, 0x54, 0x97, 0xe9, 0x4a, 0x6a, 0xd0, 0x2f, 0xc6, 0xf7, 0xb4, 0x06, 0x5f, 0xea, 0x0d, + 0x98, 0xdb, 0x67, 0xdf, 0xab, 0x77, 0x0d, 0xdb, 0x3a, 0xc0, 0xc4, 0xcf, 0xcb, 0x6c, 0x9d, 0x39, + 0x2e, 0xde, 0x14, 0x52, 0xf4, 0x5b, 0x12, 0x2c, 0xf4, 0x3c, 0x8b, 0xe8, 0xfb, 0x27, 0x7a, 0xc7, + 0x69, 0x1b, 0x1d, 0xcb, 0x3f, 0xd1, 0x8f, 0x1f, 0xe7, 0x13, 0xcb, 0xf1, 0x9b, 0x99, 0xd5, 0xbb, + 0xe7, 0x6e, 0x90, 0xd0, 0x47, 0x79, 0xcf, 0xb3, 0x48, 0xe5, 0xe4, 0x81, 0x40, 0xb8, 0xff, 0xb8, + 0x6e, 0xfb, 0xde, 0x49, 0x65, 0x71, 0xd0, 0x2f, 0xaa, 0x7b, 0x5a, 0x23, 0xda, 0xf4, 0x50, 0x53, + 0x7b, 0x63, 0x9d, 0x91, 0x06, 0x80, 0xc3, 0x9d, 0xce, 0x27, 0x99, 0x2e, 0x56, 0x2f, 0x6e, 0x1c, + 0x5a, 0x04, 0x05, 0xfd, 0x9e, 0x04, 0x05, 0xea, 0x66, 0xb8, 0x4d, 0xb7, 0x3b, 0x74, 0x3d, 0xdd, + 0xc3, 0x6d, 0xc7, 0x33, 0xf3, 0x29, 0xaa, 0x8e, 0x4a, 0xeb, 0x5f, 0xa7, 0xf5, 0x2e, 0xe6, 0xc4, + 0xbd, 0x9e, 0x65, 0x96, 0xf7, 0xf6, 0x1a, 0xb5, 0x41, 0xbf, 0x98, 0xdf, 0x09, 0xc0, 0xc3, 0x0d, + 0xd2, 0x18, 0xb4, 0x96, 0x77, 0x5f, 0xd0, 0x82, 0xde, 0x85, 0x5c, 0xdb, 0xe9, 0x74, 0x70, 0x9b, + 0x7e, 0xa1, 0xbe, 0xa7, 0x35, 0xf2, 0x0a, 0xdb, 0xbc, 0xf9, 0x41, 0xbf, 0x98, 0xad, 0x86, 0x2d, + 0x74, 0x1b, 0xb3, 0xed, 0xe8, 0x6b, 0xa1, 0x0a, 0x57, 0xce, 0x54, 0x71, 0xd4, 0x4d, 0xd3, 0xdc, + 0x4d, 0x17, 0x21, 0xf1, 0xd8, 0xe8, 0xf4, 0xb8, 0x4d, 0xa5, 0x35, 0xfe, 0x72, 0x27, 0xf6, 0xae, + 0x54, 0x52, 0x21, 0xc7, 0x35, 0xb7, 0xe3, 0x39, 0x87, 0x1e, 0x26, 0xa4, 0xf4, 0x47, 0x39, 0xc8, + 0x69, 0x98, 0xf8, 0x8e, 0x87, 0x03, 0xcb, 0xfe, 0x1b, 0x09, 0x16, 0x28, 0x95, 0x79, 0x96, 0xeb, + 0x3b, 0x9e, 0xee, 0xe1, 0x27, 0x9e, 0xe5, 0x63, 0x92, 0x8f, 0x31, 0x8b, 0x58, 0x9b, 0xb0, 0x2b, + 0xa3, 0x40, 0xe5, 0x5a, 0x08, 0xa2, 0x09, 0x0c, 0x6e, 0x14, 0x77, 0x7f, 0xf2, 0x6f, 0xc5, 0x3b, + 0x53, 0xe9, 0xfc, 0x34, 0xbb, 0x96, 0x1b, 0x35, 0x0d, 0x99, 0xa7, 0x80, 0xd1, 0x75, 0x90, 0xa9, + 0x51, 0xe5, 0xe3, 0xcb, 0xf1, 0x9b, 0xe9, 0x8a, 0x32, 0xe8, 0x17, 0x65, 0x6a, 0x76, 0x1a, 0x93, + 0x8e, 0x38, 0x9a, 0xfc, 0x12, 0x8e, 0x76, 0x0f, 0x32, 0xbe, 0xb1, 0xdf, 0xc1, 0x3a, 0x9d, 0x99, + 0x08, 0xdf, 0xf8, 0xe6, 0x98, 0x26, 0xc8, 0xa3, 0xce, 0xbe, 0x41, 0x70, 0x79, 0x97, 0xf6, 0x8c, + 0xac, 0x1d, 0xfc, 0x40, 0x40, 0xd0, 0x0a, 0x64, 0x9c, 0xc7, 0xd8, 0xf3, 0x2c, 0x13, 0xeb, 0xe6, + 0x3e, 0x33, 0xf4, 0x74, 0x25, 0x37, 0xe8, 0x17, 0x61, 0x5b, 0x88, 0x6b, 0x15, 0x0d, 0x82, 0x2e, + 0xb5, 0x7d, 0xe4, 0xc3, 0xa2, 0xf0, 0xe3, 0xd0, 0x39, 0x19, 0x7f, 0xa6, 0xd8, 0x27, 0x7c, 0x7f, + 0xfa, 0xcd, 0xe0, 0xfb, 0x1e, 0x18, 0x0f, 0x63, 0x50, 0xbe, 0x48, 0xb4, 0x7f, 0xaa, 0x05, 0xbd, + 0x01, 0xf3, 0xae, 0x87, 0x5d, 0xc3, 0xc3, 0x7a, 0xdb, 0xe9, 0xba, 0x1d, 0xec, 0x63, 0x93, 0x59, + 0xaa, 0xa2, 0xa9, 0xa2, 0xa1, 0x1a, 0xc8, 0xd1, 0xeb, 0x90, 0x23, 0xbe, 0xe1, 0x53, 0x62, 0x27, + 0xd8, 0xa3, 0x3d, 0xd3, 0xac, 0x67, 0x96, 0x49, 0x1b, 0x42, 0x88, 0x6e, 0x81, 0xca, 0x14, 0x41, + 0x74, 0xb7, 0xb7, 0xdf, 0xb1, 0xc8, 0x11, 0x36, 0xf3, 0xc0, 0x3a, 0xce, 0x71, 0xf9, 0x4e, 0x20, + 0x46, 0x27, 0x23, 0x06, 0xd8, 0xa6, 0xea, 0x30, 0x0e, 0x71, 0x3e, 0xb3, 0x2c, 0xdd, 0x4c, 0x54, + 0x36, 0x9e, 0xf7, 0x8b, 0xb5, 0xa9, 0xad, 0x87, 0xe0, 0xee, 0x8a, 0xef, 0x61, 0x1c, 0x31, 0xc6, + 0xaa, 0xc0, 0x8b, 0xda, 0x51, 0x20, 0x1b, 0x23, 0xa2, 0xd9, 0x2f, 0x85, 0x88, 0x76, 0x20, 0xe5, + 0x63, 0xdb, 0xb0, 0x7d, 0x92, 0xcf, 0xb2, 0x6d, 0x7b, 0x7b, 0xfa, 0x6d, 0xdb, 0x65, 0x03, 0x03, + 0x7b, 0x14, 0x30, 0xa8, 0x06, 0xe0, 0x9f, 0xb8, 0x81, 0x39, 0xe6, 0x18, 0xe8, 0xeb, 0x2f, 0x32, + 0xc7, 0x13, 0x37, 0x6a, 0x8d, 0x69, 0x5f, 0xbc, 0x13, 0xd4, 0x84, 0x59, 0xd2, 0x3e, 0xc2, 0x5d, + 0x43, 0xe0, 0xcc, 0x31, 0x9c, 0x1b, 0x2f, 0xc0, 0x69, 0xb1, 0xae, 0x11, 0xa4, 0x0c, 0x09, 0x25, + 0xa4, 0xf0, 0x3f, 0x12, 0xcc, 0x9f, 0xf2, 0x77, 0xb4, 0x0b, 0xb1, 0x30, 0xa3, 0xa1, 0x94, 0x19, + 0x63, 0xd9, 0xcc, 0x65, 0x7c, 0x3f, 0x66, 0x99, 0xe8, 0x10, 0xd2, 0xd4, 0x02, 0x6d, 0x9f, 0xa6, + 0x4b, 0x31, 0x06, 0xde, 0x1c, 0xf4, 0x8b, 0xca, 0x0e, 0x13, 0x5e, 0x7a, 0x0a, 0x85, 0x83, 0x37, + 0x4c, 0x54, 0x84, 0x8c, 0xef, 0xe8, 0xf8, 0x53, 0x8b, 0xf8, 0x96, 0x7d, 0xc8, 0xe2, 0xac, 0xa2, + 0x81, 0xef, 0xd4, 0x85, 0xa4, 0xf0, 0xc7, 0x31, 0x40, 0xa7, 0x1d, 0x0b, 0xfd, 0x83, 0x04, 0xd7, + 0x83, 0x98, 0xea, 0x78, 0xd6, 0xa1, 0x65, 0x1b, 0x9d, 0x91, 0xe0, 0x2a, 0x31, 0x4d, 0x7f, 0x7c, + 0x19, 0xef, 0x15, 0x01, 0x77, 0x5b, 0xc0, 0x8f, 0x07, 0xde, 0xeb, 0x34, 0x40, 0xf1, 0xc0, 0x7b, + 0xaa, 0xcb, 0x43, 0x2d, 0xdf, 0x7b, 0xc1, 0xe0, 0xc2, 0x7d, 0x78, 0x65, 0x22, 0xf0, 0x45, 0xc2, + 0x4d, 0xe1, 0x27, 0x12, 0x5c, 0x7b, 0x41, 0x10, 0x88, 0xe2, 0x64, 0x39, 0xce, 0x07, 0x51, 0x9c, + 0xcc, 0xea, 0x2f, 0x5f, 0x22, 0xd0, 0x44, 0x3f, 0xe2, 0xdb, 0x90, 0xe4, 0x4e, 0x84, 0xae, 0x86, + 0xd6, 0x28, 0x57, 0x92, 0xdc, 0x1a, 0x99, 0x3d, 0x21, 0x90, 0x19, 0xa7, 0xf2, 0x44, 0x90, 0x3d, + 0x37, 0x65, 0x45, 0x52, 0x63, 0xa5, 0xb7, 0x61, 0x4e, 0x4c, 0x15, 0x04, 0x4c, 0xf4, 0x0a, 0xc0, + 0x91, 0x75, 0x78, 0xa4, 0x3f, 0x31, 0x7c, 0xec, 0x89, 0xe4, 0x38, 0x4d, 0x25, 0x1f, 0x52, 0x41, + 0xe9, 0x33, 0x05, 0xb2, 0x8d, 0xae, 0xeb, 0x78, 0x7e, 0x10, 0x4e, 0x1f, 0x40, 0x92, 0xf3, 0x9b, + 0xd8, 0xf5, 0xf2, 0x84, 0x75, 0x8d, 0x8c, 0xe4, 0x81, 0x44, 0xb8, 0xbe, 0xc0, 0x08, 0xe3, 0x5c, + 0xec, 0xcc, 0x38, 0xf7, 0x1e, 0x24, 0xf9, 0xf9, 0x44, 0xe4, 0xd7, 0xc5, 0xc8, 0x5c, 0xc1, 0xe9, + 0xa0, 0xb1, 0xbd, 0x6e, 0x75, 0xf0, 0x3a, 0xeb, 0x16, 0x80, 0xf3, 0x41, 0xe8, 0x9b, 0xa0, 0x10, + 0xe2, 0xeb, 0xc4, 0xfa, 0x31, 0x0f, 0x93, 0x71, 0x9e, 0x64, 0xb7, 0x5a, 0xbb, 0x2d, 0xeb, 0xc7, + 0x58, 0x4b, 0x11, 0xe2, 0xd3, 0x07, 0x54, 0x00, 0xe5, 0x89, 0xd1, 0xe9, 0xb0, 0x70, 0x9a, 0x60, + 0x87, 0x8a, 0xf0, 0x7d, 0xd4, 0x39, 0x93, 0x5f, 0xad, 0x73, 0x8a, 0xc8, 0xe8, 0x1a, 0xfe, 0x11, + 0x4b, 0xe7, 0xd2, 0x1a, 0x70, 0xd1, 0x8e, 0xe1, 0x1f, 0xa1, 0x3c, 0xa4, 0x88, 0x41, 0x83, 0x14, + 0xc9, 0x2b, 0xcb, 0xf1, 0x9b, 0xb3, 0x5a, 0xf0, 0x8a, 0x96, 0x80, 0x85, 0x58, 0xfe, 0xca, 0xa2, + 0x55, 0x5c, 0x8b, 0x48, 0x98, 0x1e, 0x8e, 0x2d, 0x57, 0x3f, 0x38, 0x26, 0x3c, 0x44, 0x09, 0x3d, + 0x1c, 0x5b, 0xee, 0xfa, 0x7d, 0xa2, 0xa5, 0x68, 0xe3, 0xfa, 0x31, 0xa1, 0x49, 0xb6, 0x65, 0x1f, + 0x62, 0xe2, 0xeb, 0xa6, 0xe5, 0xe1, 0xb6, 0xdf, 0x39, 0x61, 0x31, 0x4a, 0xd1, 0x72, 0x5c, 0x5c, + 0x13, 0x52, 0x1a, 0xfb, 0xc6, 0xe3, 0x29, 0x8b, 0x2d, 0x8a, 0x36, 0x37, 0x16, 0x4e, 0xcf, 0x0c, + 0x93, 0xd9, 0xb3, 0xc3, 0xe4, 0x39, 0x09, 0xee, 0xd5, 0xff, 0x87, 0x04, 0xb7, 0xf0, 0x59, 0x0c, + 0x12, 0xcc, 0x6e, 0xd1, 0x1d, 0x90, 0xe9, 0xb6, 0x89, 0xa3, 0xd1, 0xb4, 0xc9, 0x12, 0x1b, 0x43, + 0x3d, 0xd2, 0x36, 0xba, 0x38, 0x8f, 0xd8, 0xa6, 0xb2, 0x67, 0x74, 0x0d, 0x52, 0x04, 0x3f, 0xd2, + 0x1f, 0x1b, 0x9d, 0xfc, 0x02, 0xdb, 0xb1, 0x24, 0xc1, 0x8f, 0x1e, 0x1a, 0x1d, 0x74, 0x05, 0x92, + 0x16, 0xd1, 0x6d, 0xfc, 0x24, 0xbf, 0xc8, 0xf4, 0x94, 0xb0, 0xc8, 0x16, 0x7e, 0xc2, 0xc8, 0xdb, + 0xf0, 0x0e, 0xb1, 0xaf, 0xb7, 0x9d, 0x0e, 0xc9, 0x5f, 0xa1, 0x0e, 0x43, 0x73, 0x31, 0x2a, 0xaa, + 0x3a, 0x1d, 0xd2, 0x94, 0x95, 0x98, 0x1a, 0x6f, 0xca, 0x4a, 0x5c, 0x95, 0x9b, 0xb2, 0x22, 0xab, + 0x89, 0xa6, 0xac, 0x24, 0xd4, 0x64, 0x53, 0x56, 0x92, 0x6a, 0xaa, 0x29, 0x2b, 0x29, 0x55, 0x69, + 0xca, 0x8a, 0xa2, 0xa6, 0x9b, 0xb2, 0x92, 0x56, 0xa1, 0x29, 0x2b, 0xa0, 0x66, 0x9a, 0xb2, 0x92, + 0x51, 0x67, 0x9b, 0xb2, 0x32, 0xab, 0x66, 0x9b, 0xb2, 0x92, 0x55, 0x73, 0x4d, 0x59, 0xc9, 0xa9, + 0x73, 0x4d, 0x59, 0x99, 0x53, 0xd5, 0xa6, 0xac, 0xa8, 0xea, 0x7c, 0x53, 0x56, 0xe6, 0x55, 0x54, + 0xfa, 0x2f, 0x09, 0x72, 0xdc, 0xa1, 0x43, 0xf2, 0x78, 0x03, 0xe6, 0x99, 0x89, 0x59, 0xf6, 0xa1, + 0xee, 0x0a, 0x21, 0xa3, 0x85, 0x98, 0xa6, 0x06, 0x0d, 0x61, 0xe7, 0x57, 0x21, 0xeb, 0x61, 0xc3, + 0x1c, 0x76, 0x8c, 0xb1, 0x8e, 0xb3, 0x54, 0x18, 0x76, 0x7a, 0x1d, 0x72, 0x8c, 0xf1, 0x86, 0xbd, + 0xe2, 0xac, 0x57, 0x96, 0x49, 0xc3, 0x6e, 0x15, 0xc8, 0x12, 0xd7, 0xb0, 0x87, 0xbd, 0x64, 0xc6, + 0x45, 0xd7, 0xce, 0xe0, 0x87, 0x96, 0x6b, 0xd8, 0x82, 0x17, 0x66, 0xe9, 0x98, 0x28, 0xf3, 0x79, + 0x98, 0xf4, 0xba, 0x58, 0x77, 0x1d, 0x9e, 0x03, 0xc7, 0xb5, 0x34, 0x97, 0xec, 0x38, 0xa4, 0xf4, + 0xeb, 0x70, 0x8d, 0xa6, 0x1a, 0x3c, 0x4d, 0xa8, 0x1e, 0x19, 0xf6, 0x61, 0x78, 0xa2, 0x30, 0x20, + 0xc5, 0xd2, 0x95, 0x30, 0x17, 0xd8, 0x18, 0xf4, 0x8b, 0x49, 0xda, 0xfb, 0xd2, 0x7c, 0x90, 0xa4, + 0xc0, 0x0d, 0xb3, 0x54, 0x80, 0xfc, 0xf8, 0xec, 0xe1, 0x19, 0x47, 0x63, 0x47, 0x9c, 0x5e, 0x17, + 0xd3, 0xa5, 0x3d, 0xb0, 0x88, 0x8f, 0x7e, 0x00, 0xb3, 0x62, 0x29, 0x74, 0x85, 0x01, 0x33, 0x9f, + 0xa3, 0x8d, 0x8c, 0x17, 0x82, 0x90, 0xd2, 0xdf, 0x4a, 0xb0, 0x50, 0xf3, 0x1c, 0xd7, 0xc5, 0xa6, + 0x30, 0x61, 0xbe, 0xd4, 0xc0, 0x72, 0xa5, 0x88, 0xe5, 0x6e, 0x41, 0xac, 0x51, 0x13, 0x89, 0xca, + 0xdd, 0xcb, 0xe6, 0x3f, 0x8d, 0x1a, 0xfa, 0x1e, 0x24, 0x69, 0x6a, 0xdd, 0x23, 0x8c, 0xe5, 0x73, + 0xab, 0xbf, 0x38, 0x21, 0xa2, 0xb4, 0x58, 0x47, 0x4d, 0x0c, 0x28, 0xfd, 0x4e, 0x12, 0xae, 0x44, + 0x75, 0x74, 0xaf, 0x1a, 0x7c, 0xf8, 0x27, 0x90, 0xb2, 0x6c, 0x13, 0x7f, 0x1a, 0xc6, 0xa9, 0xf7, + 0x26, 0xa1, 0x9e, 0x05, 0x51, 0x16, 0xfa, 0x68, 0x50, 0x98, 0x20, 0x63, 0x15, 0x98, 0xe8, 0x87, + 0x61, 0x14, 0xe4, 0xc7, 0xc8, 0x3b, 0x2f, 0x8d, 0x5e, 0x1b, 0x8b, 0x88, 0x23, 0x01, 0x27, 0xce, + 0xa2, 0xd6, 0x57, 0x13, 0x70, 0x5a, 0x30, 0x6f, 0xd9, 0x3e, 0xf6, 0x3a, 0xd8, 0x78, 0x4c, 0xf9, + 0x96, 0x4e, 0x2f, 0x4e, 0x93, 0xd3, 0xb2, 0x9b, 0x1a, 0x01, 0xe0, 0x2c, 0xf9, 0x09, 0x2c, 0x44, + 0x41, 0x83, 0x2d, 0x98, 0x7c, 0xc2, 0x64, 0x1a, 0x1e, 0xc2, 0x06, 0x07, 0xb9, 0x08, 0x50, 0x83, + 0xe3, 0x14, 0xfe, 0x40, 0x82, 0xd9, 0xe8, 0xb6, 0x20, 0x0b, 0x14, 0x36, 0x47, 0xe0, 0x8b, 0xf1, + 0xca, 0x16, 0x0d, 0x6d, 0xac, 0x91, 0xe9, 0xea, 0xfd, 0x97, 0xd6, 0x15, 0x87, 0x10, 0x5b, 0xde, + 0x30, 0xd1, 0x2f, 0x40, 0xda, 0xf4, 0x1c, 0x77, 0x58, 0xde, 0x8a, 0x6b, 0x0a, 0x15, 0xd0, 0x90, + 0x51, 0xf8, 0x0d, 0x48, 0x87, 0x1b, 0x1a, 0x39, 0x26, 0xc4, 0xbf, 0xc4, 0x63, 0xc2, 0xa4, 0xf9, + 0x4b, 0xff, 0x9b, 0x80, 0x85, 0xb3, 0xa8, 0xea, 0x23, 0x50, 0x23, 0xcc, 0xa0, 0x77, 0x2c, 0xe2, + 0x0b, 0x8b, 0xbd, 0x35, 0x39, 0x1f, 0x8d, 0xd0, 0x8b, 0xd8, 0x8f, 0x9c, 0x37, 0x4a, 0x3a, 0x3f, + 0x82, 0x9c, 0xc9, 0x97, 0xac, 0x0b, 0x57, 0x88, 0x9f, 0x9b, 0x10, 0x9e, 0x41, 0x31, 0x02, 0x3d, + 0x6b, 0x46, 0x9a, 0x08, 0x2b, 0xe3, 0x05, 0xe8, 0xa6, 0xe1, 0x1b, 0xd4, 0x4e, 0xe8, 0x1e, 0xcb, + 0x8c, 0x75, 0x5a, 0x83, 0x7e, 0x71, 0x5e, 0x60, 0xd5, 0x44, 0xeb, 0xa5, 0x75, 0x3c, 0x6f, 0x8e, + 0x01, 0x9a, 0x94, 0xe8, 0x69, 0x3b, 0x9d, 0x38, 0x31, 0x24, 0x7a, 0x6a, 0xa9, 0x97, 0x27, 0x7a, + 0xfa, 0xd8, 0x30, 0xd1, 0x6f, 0x4b, 0x30, 0xcf, 0x6b, 0x31, 0xdd, 0x9e, 0x6f, 0xb0, 0x32, 0x5a, + 0x98, 0x68, 0x7e, 0x34, 0xe8, 0x17, 0xe7, 0x98, 0x42, 0x36, 0x45, 0x1b, 0x9b, 0xb6, 0xf2, 0xb2, + 0xd3, 0x0e, 0x51, 0x44, 0xf2, 0x15, 0x0a, 0x4c, 0x74, 0x1f, 0x72, 0x3c, 0x6b, 0xd6, 0x69, 0xde, + 0x68, 0x39, 0x36, 0xcb, 0x40, 0xb3, 0x95, 0xd7, 0x9e, 0xf7, 0x8b, 0xcb, 0x67, 0x58, 0x16, 0x4f, + 0xb8, 0x1f, 0xf2, 0xbe, 0x5a, 0xf6, 0x20, 0xfa, 0x8a, 0xda, 0x90, 0x0d, 0x4d, 0xe3, 0xc4, 0x15, + 0x09, 0xeb, 0xe5, 0x83, 0xc5, 0x6c, 0x60, 0x23, 0x14, 0x53, 0x1c, 0x69, 0xae, 0xc2, 0xe2, 0x99, + 0x41, 0xf2, 0x0f, 0x13, 0x70, 0x75, 0x94, 0x78, 0xc3, 0xc0, 0xaf, 0x8f, 0x87, 0x86, 0xf7, 0xa7, + 0x26, 0xef, 0x00, 0x83, 0xb3, 0x43, 0xf0, 0x36, 0x1e, 0x1c, 0x3e, 0x19, 0x0b, 0x0e, 0x2f, 0x81, + 0xcf, 0x76, 0x7d, 0x0c, 0x5f, 0x80, 0x16, 0xfe, 0x45, 0x82, 0xec, 0xc8, 0xfc, 0x5f, 0x27, 0x0b, + 0xee, 0x84, 0xc1, 0x9a, 0xdf, 0x9a, 0xbc, 0x7b, 0xf1, 0xb5, 0x8d, 0xc6, 0xf0, 0xc2, 0xdf, 0x4b, + 0x90, 0x1d, 0x59, 0xee, 0x57, 0xc4, 0x9f, 0x5f, 0xfa, 0x97, 0x97, 0xbe, 0x0b, 0x49, 0x2e, 0x41, + 0x08, 0x72, 0x1f, 0xae, 0x35, 0x76, 0x1b, 0x5b, 0xf7, 0xf4, 0xf5, 0x6d, 0x4d, 0xbf, 0x57, 0x55, + 0x67, 0xd0, 0x2c, 0x28, 0xb5, 0xfa, 0x83, 0x3a, 0x15, 0xaa, 0x12, 0xca, 0x40, 0x8a, 0xbd, 0xd5, + 0x6b, 0x6a, 0xac, 0x54, 0x01, 0x95, 0x63, 0x1f, 0x60, 0xca, 0x78, 0x34, 0x85, 0x47, 0x65, 0x58, + 0xa0, 0xb0, 0xb8, 0x4b, 0x43, 0x3f, 0xe5, 0x78, 0x3d, 0x92, 0x78, 0xcd, 0x87, 0x4d, 0x94, 0xed, + 0xb7, 0x8c, 0x2e, 0x2e, 0xfd, 0x9d, 0x0c, 0xf3, 0x43, 0x90, 0x80, 0xef, 0xe9, 0x51, 0xcf, 0xb2, + 0x8f, 0xf5, 0xe1, 0x3d, 0x0a, 0x3f, 0xea, 0x59, 0xf6, 0xf1, 0x9e, 0xd6, 0xd0, 0x52, 0xb4, 0x71, + 0xcf, 0xb3, 0x50, 0x13, 0x64, 0xc7, 0xf5, 0x83, 0xbc, 0xf9, 0x3b, 0x13, 0x54, 0x71, 0x6a, 0x8e, + 0xf2, 0xb6, 0xeb, 0xf3, 0xa2, 0x87, 0xc6, 0x30, 0xd0, 0x5f, 0x49, 0x90, 0xe2, 0xe7, 0x10, 0x92, + 0x4f, 0x32, 0xbc, 0xef, 0x5d, 0x08, 0x8f, 0x2b, 0x40, 0x14, 0xd3, 0x3f, 0xa4, 0xa6, 0xfe, 0xbc, + 0x5f, 0x9c, 0x1f, 0x57, 0x10, 0xb9, 0x64, 0x95, 0x3d, 0xf8, 0x44, 0xd4, 0xe4, 0xf5, 0xdd, 0xa1, + 0xa2, 0x19, 0xd3, 0x4d, 0x59, 0x42, 0xcf, 0x8e, 0x6c, 0x44, 0xe1, 0x10, 0x66, 0xa3, 0x5f, 0x7f, + 0x46, 0x15, 0x68, 0x6d, 0xb4, 0x0a, 0xf4, 0xc6, 0x54, 0x9a, 0xe1, 0x98, 0xd1, 0xaa, 0xcf, 0x77, + 0x21, 0x1d, 0xaa, 0xfd, 0x22, 0x35, 0x2b, 0xce, 0x92, 0xe1, 0xd9, 0x30, 0xa1, 0x26, 0x4b, 0x7f, + 0x2d, 0xc1, 0xac, 0x86, 0x89, 0xd3, 0x79, 0x8c, 0x4d, 0x1a, 0xcc, 0xd1, 0xb7, 0x40, 0xa6, 0xc9, + 0x81, 0x38, 0xd9, 0x9e, 0x73, 0x6a, 0x60, 0x5d, 0xd1, 0x1a, 0xa4, 0xc3, 0xf3, 0xf9, 0x45, 0xae, + 0xfa, 0x86, 0xa3, 0xd0, 0x2d, 0x50, 0xf7, 0x9d, 0x9e, 0x6d, 0x1a, 0xde, 0x89, 0xee, 0x61, 0xa3, + 0x7d, 0x84, 0x4d, 0x51, 0x91, 0x9c, 0x0b, 0xe4, 0x1a, 0x17, 0x97, 0x3e, 0x8b, 0x01, 0x1a, 0x2a, + 0x27, 0x42, 0x13, 0x34, 0x25, 0x61, 0xeb, 0x10, 0xe7, 0x9e, 0xd8, 0x99, 0x15, 0xdf, 0xb1, 0xcc, + 0x26, 0x5c, 0x78, 0xb0, 0xa5, 0x5e, 0x44, 0x46, 0xd0, 0xef, 0x4f, 0xae, 0x42, 0xc4, 0x59, 0x15, + 0x82, 0x59, 0xe9, 0xd7, 0x5a, 0x89, 0x10, 0xe1, 0xee, 0x9f, 0x64, 0x40, 0x55, 0x0f, 0x1b, 0x3e, + 0xa6, 0xcc, 0x43, 0x26, 0x1d, 0xd3, 0x2a, 0x90, 0xe0, 0x39, 0x7d, 0xec, 0x22, 0x39, 0xbd, 0x50, + 0x0a, 0x1f, 0x8a, 0x7e, 0x05, 0x66, 0xdb, 0x4e, 0xa7, 0xd7, 0xb5, 0x75, 0x76, 0xf9, 0x21, 0x32, + 0xbc, 0x5f, 0x9a, 0x64, 0xc4, 0xa7, 0x3e, 0xae, 0x5c, 0x75, 0x3a, 0xf4, 0x3d, 0x38, 0x76, 0x72, + 0x40, 0xd6, 0x03, 0x5d, 0x87, 0x74, 0xe8, 0x50, 0x2c, 0xb7, 0x4b, 0x6b, 0x43, 0x01, 0x5a, 0x85, + 0x84, 0x41, 0x74, 0xe7, 0x80, 0x25, 0x5f, 0xe7, 0x59, 0x98, 0x26, 0x1b, 0x64, 0xfb, 0x00, 0xbd, + 0x03, 0xd9, 0x83, 0x47, 0x3c, 0x21, 0xe5, 0x04, 0xca, 0xef, 0xa4, 0xe6, 0x06, 0xfd, 0x62, 0x66, + 0xfd, 0x03, 0xb6, 0x58, 0x4a, 0x9f, 0x5a, 0xe6, 0xe0, 0x51, 0xf8, 0x82, 0x6e, 0xc3, 0x7c, 0xd7, + 0xf8, 0x54, 0x3f, 0xf0, 0x8c, 0xb6, 0xc8, 0xc0, 0x3a, 0x9c, 0x15, 0x24, 0x6d, 0xae, 0x6b, 0x7c, + 0xba, 0x2e, 0xe4, 0x0d, 0xb3, 0x83, 0x0b, 0xff, 0x28, 0x41, 0x4a, 0xac, 0x08, 0xb9, 0x00, 0x42, + 0x3d, 0x96, 0xc9, 0x93, 0x89, 0x6c, 0xe5, 0x83, 0x41, 0xbf, 0x98, 0xae, 0x32, 0x69, 0xa3, 0x46, + 0x9e, 0xf7, 0x8b, 0x3f, 0x78, 0x59, 0xd2, 0x0a, 0x40, 0xb4, 0x34, 0x9f, 0xa4, 0x61, 0xb2, 0x22, + 0xca, 0x91, 0x41, 0xf4, 0x23, 0x8b, 0xf8, 0xce, 0xa1, 0x67, 0x74, 0xd9, 0xe6, 0x2a, 0xda, 0xec, + 0x91, 0x41, 0x36, 0x02, 0x19, 0x2a, 0xd0, 0x74, 0xe0, 0x31, 0xbf, 0xbb, 0xe2, 0x2e, 0x15, 0xbe, + 0x97, 0xae, 0xc0, 0x42, 0x64, 0x8b, 0xc2, 0x74, 0xe9, 0x4f, 0x00, 0x52, 0x3b, 0xc6, 0x49, 0xc7, + 0x31, 0x4c, 0xb4, 0x0c, 0x99, 0xe0, 0x26, 0x89, 0xe6, 0x81, 0xdc, 0xa6, 0xa2, 0x22, 0x3a, 0x41, + 0x8f, 0x60, 0x8f, 0xe9, 0x97, 0x33, 0x4e, 0xf8, 0x2e, 0xae, 0xcf, 0xe8, 0x5c, 0x7a, 0xd7, 0x6a, + 0x7b, 0x0e, 0x3f, 0xd5, 0xc7, 0x19, 0x73, 0x52, 0xe9, 0x26, 0x13, 0xa2, 0x1b, 0x30, 0x77, 0x60, + 0xd9, 0xac, 0xf0, 0x17, 0xf4, 0x63, 0x25, 0x5a, 0x2d, 0x17, 0x88, 0x45, 0xc7, 0xc7, 0x90, 0x8b, + 0x5c, 0x9e, 0x51, 0x3d, 0x27, 0x99, 0x9e, 0xb7, 0x07, 0xfd, 0x62, 0x76, 0x68, 0xb7, 0x5c, 0xd7, + 0x97, 0x09, 0x10, 0xd9, 0xe1, 0x34, 0x54, 0xd3, 0x8b, 0x90, 0x60, 0x3f, 0xaf, 0xe1, 0x37, 0xda, + 0x1a, 0x7f, 0x41, 0xdf, 0x81, 0x44, 0x07, 0x1b, 0x84, 0x57, 0x59, 0x33, 0xab, 0xcb, 0x13, 0x3c, + 0x81, 0xfd, 0x12, 0x46, 0xe3, 0xdd, 0x51, 0x05, 0x92, 0xbc, 0x94, 0xcb, 0x0a, 0xb0, 0x99, 0xd5, + 0x9b, 0xd3, 0xfe, 0x10, 0x61, 0x63, 0x46, 0x13, 0x23, 0x51, 0x1d, 0x52, 0x1e, 0xaf, 0xde, 0xb3, + 0xb2, 0xec, 0xb9, 0x47, 0xb8, 0xc8, 0x95, 0xc2, 0xc6, 0x8c, 0x16, 0x8c, 0x45, 0xbb, 0xc1, 0x35, + 0x19, 0xa7, 0x54, 0x71, 0x29, 0x58, 0x9e, 0x32, 0x1b, 0x1a, 0x02, 0x8e, 0xa0, 0xd0, 0x05, 0x5a, + 0xac, 0x38, 0xc8, 0xaa, 0xbb, 0x93, 0x17, 0x38, 0x72, 0x2d, 0x40, 0x17, 0xc8, 0x47, 0xa2, 0x2d, + 0x80, 0x76, 0x48, 0xf3, 0xf9, 0x1c, 0xc3, 0x79, 0xf3, 0x22, 0xa9, 0xc4, 0xc6, 0x8c, 0x16, 0x41, + 0x40, 0x1f, 0x40, 0xa6, 0x3d, 0xb4, 0xf5, 0xfc, 0x1c, 0x03, 0x7c, 0xeb, 0x42, 0xe4, 0xb5, 0x41, + 0x09, 0x6b, 0x28, 0x1d, 0x25, 0x2c, 0x75, 0x9c, 0xb0, 0xea, 0x90, 0x15, 0xa7, 0x6d, 0xfe, 0xcb, + 0xac, 0xfc, 0x3c, 0xe3, 0xcb, 0xa8, 0x95, 0x04, 0xbf, 0xdd, 0x2a, 0xd7, 0xed, 0xb6, 0x63, 0x62, + 0xb3, 0x4e, 0xdf, 0x35, 0x51, 0xbe, 0x63, 0x2f, 0x04, 0xdd, 0x83, 0x5c, 0xbb, 0x83, 0x0d, 0xbb, + 0xe7, 0x06, 0x38, 0x68, 0x4a, 0x9c, 0xac, 0x18, 0x27, 0x80, 0xb6, 0x00, 0x1d, 0xb0, 0xcb, 0xba, + 0xe8, 0x57, 0xb1, 0x72, 0xf3, 0x34, 0x60, 0x2a, 0x1b, 0xab, 0x0d, 0xbf, 0x0c, 0xbd, 0x06, 0x59, + 0xdb, 0xb1, 0xdb, 0x86, 0xdd, 0xc6, 0x1d, 0x16, 0x5a, 0x78, 0x85, 0x7a, 0x54, 0x88, 0x3e, 0x86, + 0x1c, 0x19, 0xc9, 0x9f, 0xf3, 0x57, 0xd8, 0x8c, 0x6f, 0x5f, 0xb4, 0x46, 0xb6, 0x31, 0xa3, 0x8d, + 0x21, 0xa1, 0x5f, 0x05, 0xd5, 0x1f, 0xab, 0x8b, 0xb2, 0x8b, 0x81, 0xc9, 0xb7, 0xda, 0x2f, 0x28, + 0xe4, 0x6e, 0xcc, 0x68, 0xa7, 0xd0, 0x2a, 0x69, 0x7a, 0xe6, 0x67, 0xcd, 0x61, 0xfd, 0x3c, 0xa5, + 0x2a, 0xa5, 0xff, 0x4e, 0x82, 0x12, 0x66, 0x1e, 0x2b, 0x80, 0xc2, 0x58, 0x31, 0xfc, 0x41, 0x01, + 0x25, 0xca, 0xd8, 0xc6, 0x8c, 0x36, 0x1f, 0xb4, 0x0d, 0x7f, 0x53, 0x70, 0x03, 0xe6, 0xba, 0x8e, + 0x69, 0x1d, 0x58, 0x43, 0xb6, 0xe3, 0x15, 0x9c, 0x5c, 0x20, 0x16, 0x6c, 0x77, 0x77, 0xe4, 0x3a, + 0x2e, 0x3e, 0x45, 0xdc, 0xdb, 0x98, 0x89, 0xdc, 0xd7, 0x51, 0xf6, 0xf5, 0x7a, 0xb6, 0x6d, 0xd9, + 0x87, 0xba, 0x38, 0xec, 0xf0, 0xa8, 0x9a, 0x15, 0x52, 0x71, 0x5e, 0xa9, 0x8e, 0xd1, 0xd1, 0xad, + 0x73, 0xe9, 0x28, 0x58, 0xfb, 0x86, 0x14, 0xf2, 0xd1, 0xfa, 0x38, 0x1f, 0xdd, 0x3e, 0x9f, 0x8f, + 0x22, 0x30, 0x21, 0x21, 0xed, 0x9d, 0x49, 0x48, 0x2b, 0x53, 0x5a, 0x4b, 0x04, 0x71, 0x94, 0x91, + 0xaa, 0x63, 0x8c, 0x74, 0xeb, 0x5c, 0x46, 0x8a, 0xae, 0x51, 0x50, 0xd2, 0xf6, 0x19, 0x94, 0xf4, + 0xd6, 0x54, 0x94, 0x14, 0x01, 0x8b, 0x72, 0x92, 0x76, 0x16, 0x27, 0x95, 0xa7, 0xe3, 0xa4, 0x08, + 0xe4, 0x08, 0x29, 0xfd, 0xe8, 0x94, 0xc3, 0xa9, 0x0c, 0xf6, 0x5b, 0x17, 0x3e, 0xe1, 0x6e, 0x48, + 0xa7, 0x3c, 0xce, 0x38, 0xc3, 0xe3, 0xe6, 0x19, 0xfc, 0x3b, 0x17, 0xf0, 0xb8, 0xc8, 0x04, 0xa7, + 0x5d, 0x0e, 0x40, 0x09, 0x2e, 0x72, 0x22, 0xee, 0x57, 0xfa, 0xa9, 0x04, 0xf1, 0xa6, 0xb3, 0x8f, + 0x72, 0xc3, 0x72, 0x00, 0x3b, 0xc8, 0xbf, 0x3f, 0xec, 0x2e, 0x72, 0xdb, 0x57, 0x27, 0x7c, 0x49, + 0x30, 0xb3, 0x16, 0x0e, 0x42, 0xdf, 0x87, 0x94, 0xcb, 0x73, 0x1d, 0xe1, 0x61, 0xa5, 0x49, 0xe3, + 0x79, 0x4f, 0x2d, 0x18, 0x72, 0xfb, 0x16, 0xe4, 0x46, 0x7f, 0x0e, 0x8a, 0x72, 0x00, 0x3b, 0x06, + 0x21, 0xee, 0x91, 0x67, 0x10, 0xac, 0xce, 0xa0, 0x14, 0xc4, 0xef, 0x6f, 0xb6, 0x54, 0xe9, 0xf6, + 0x0f, 0xa3, 0x05, 0x82, 0x9a, 0xb6, 0xd6, 0xd8, 0x6a, 0x6c, 0xdd, 0xd3, 0xb7, 0xd6, 0x36, 0xeb, + 0x2d, 0x75, 0x06, 0xe5, 0x61, 0xf1, 0xc3, 0xb5, 0xc6, 0xae, 0xa8, 0x18, 0xe8, 0x8d, 0xad, 0xdd, + 0xba, 0xf6, 0x70, 0xed, 0x81, 0x2a, 0xa1, 0xab, 0x80, 0xb4, 0xed, 0xea, 0xfd, 0x56, 0xad, 0xa2, + 0x57, 0xb7, 0x37, 0x77, 0xd6, 0xaa, 0xbb, 0x8d, 0xed, 0x2d, 0x35, 0x86, 0x14, 0x90, 0x6b, 0xdb, + 0x5b, 0x75, 0x15, 0x6e, 0xff, 0x34, 0x0e, 0x32, 0xd5, 0x31, 0x7a, 0x0d, 0x32, 0x7b, 0x5b, 0xad, + 0x9d, 0x7a, 0xb5, 0xb1, 0xde, 0xa8, 0xd7, 0xd4, 0x99, 0xc2, 0xc2, 0xd3, 0x67, 0xcb, 0x73, 0xb4, + 0x69, 0xcf, 0x26, 0x2e, 0x6e, 0x33, 0x72, 0x41, 0x05, 0x48, 0x56, 0xd6, 0xaa, 0xf7, 0xf7, 0x76, + 0x54, 0xa9, 0x90, 0x7b, 0xfa, 0x6c, 0x19, 0x68, 0x07, 0xee, 0xd8, 0xe8, 0x3a, 0xa4, 0xb4, 0x7a, + 0x6b, 0x77, 0x5b, 0xab, 0xab, 0xb1, 0xc2, 0xdc, 0xd3, 0x67, 0xcb, 0x19, 0xda, 0x28, 0xfc, 0x15, + 0xdd, 0x80, 0x6c, 0xab, 0xba, 0x51, 0xdf, 0x5c, 0xd3, 0xab, 0x1b, 0x6b, 0x5b, 0xf7, 0xea, 0x6a, + 0xbc, 0xb0, 0xf8, 0xf4, 0xd9, 0xb2, 0x3a, 0xbe, 0xc1, 0x74, 0x8a, 0xc6, 0xe6, 0xce, 0xb6, 0xb6, + 0xab, 0xca, 0xc3, 0x29, 0xb8, 0x5f, 0xa1, 0x12, 0x00, 0x1f, 0xbd, 0x5e, 0xaf, 0xd7, 0xd4, 0x44, + 0x01, 0x3d, 0x7d, 0xb6, 0x9c, 0xa3, 0xed, 0x43, 0x77, 0x41, 0xaf, 0xc3, 0x6c, 0x55, 0xab, 0xaf, + 0xed, 0xd6, 0xf5, 0xd6, 0xee, 0xda, 0x6e, 0x4b, 0x4d, 0x0e, 0x57, 0x12, 0x71, 0x01, 0x54, 0x86, + 0xf9, 0xb5, 0xbd, 0xdd, 0x6d, 0x7d, 0xa4, 0x6f, 0xaa, 0x70, 0xed, 0xe9, 0xb3, 0xe5, 0x05, 0xda, + 0x77, 0xad, 0xe7, 0x3b, 0xd1, 0xfe, 0x6f, 0x82, 0x3a, 0xf2, 0xfd, 0xfa, 0xbd, 0xaa, 0xaa, 0x14, + 0xae, 0x3e, 0x7d, 0xb6, 0x8c, 0xc6, 0x97, 0x70, 0xaf, 0x8a, 0xbe, 0x0d, 0x57, 0x77, 0x3f, 0xda, + 0xa9, 0xd7, 0xea, 0xad, 0xaa, 0x3e, 0xba, 0xec, 0x74, 0x21, 0xff, 0xf4, 0xd9, 0xf2, 0x22, 0x1d, + 0x33, 0x3e, 0xae, 0xa0, 0x7c, 0xf6, 0x67, 0x4b, 0x33, 0x7f, 0xf9, 0xe7, 0x4b, 0x33, 0x95, 0x9b, + 0x9f, 0xff, 0xc7, 0xd2, 0xcc, 0xe7, 0x83, 0x25, 0xe9, 0x67, 0x83, 0x25, 0xe9, 0xe7, 0x83, 0x25, + 0xe9, 0xdf, 0x07, 0x4b, 0xd2, 0xef, 0x7e, 0xb1, 0x34, 0xf3, 0xb3, 0x2f, 0x96, 0x66, 0x7e, 0xfe, + 0xc5, 0xd2, 0xcc, 0xc7, 0x49, 0x6e, 0x56, 0xfb, 0x49, 0xf6, 0x8b, 0xe9, 0x77, 0xfe, 0x2f, 0x00, + 0x00, 0xff, 0xff, 0xf9, 0x1b, 0xc5, 0x37, 0x00, 0x2e, 0x00, 0x00, } diff --git a/pkg/jobs/jobspb/jobs.proto b/pkg/jobs/jobspb/jobs.proto index e45f4ad51bf0..5110aaa8ddf3 100644 --- a/pkg/jobs/jobspb/jobs.proto +++ b/pkg/jobs/jobspb/jobs.proto @@ -271,6 +271,15 @@ message SchemaChangeGCDetails { // Indexes to GC. repeated DroppedIndex indexes = 1 [(gogoproto.nullable) = false]; + // The below two fields are used only in the case of TRUNCATE operating on + // tables with interleaved indexes. They are only set together. + + // InterleavedTable is the table being truncated. In particular, it is the + // TableDescriptor before any of the truncate modifications have been applied. + sqlbase.TableDescriptor interleaved_table = 4; + // InterleavedIndexes is the set of interleaved indexes to truncate. + repeated sqlbase.IndexDescriptor interleaved_indexes = 5 [(gogoproto.nullable) = false]; + // Entire tables to GC. repeated DroppedID tables = 2 [(gogoproto.nullable) = false]; diff --git a/pkg/sql/backfill.go b/pkg/sql/backfill.go index d66a7d310b9c..1382396edeaf 100644 --- a/pkg/sql/backfill.go +++ b/pkg/sql/backfill.go @@ -620,6 +620,59 @@ func (sc *SchemaChanger) getTableVersion( return tableDesc, nil } +// TruncateInterleavedIndexes truncates the input set of indexes from the given +// table. It is used in the schema change GC job to delete interleaved index +// data as part of a TRUNCATE statement. Note that we cannot use +// SchemaChanger.truncateIndexes instead because that accesses the most recent +// version of the table when deleting. In this case, we need to use the version +// of the table before truncation, which is passed in. +func TruncateInterleavedIndexes( + ctx context.Context, + execCfg *ExecutorConfig, + table *sqlbase.ImmutableTableDescriptor, + indexes []descpb.IndexDescriptor, +) error { + log.Infof(ctx, "truncating %d interleaved indexes", len(indexes)) + chunkSize := int64(indexTruncateChunkSize) + alloc := &sqlbase.DatumAlloc{} + codec, db := execCfg.Codec, execCfg.DB + for _, desc := range indexes { + var resume roachpb.Span + for rowIdx, done := int64(0), false; !done; rowIdx += chunkSize { + log.VEventf(ctx, 2, "truncate interleaved index (%d) at row: %d, span: %s", table.ID, rowIdx, resume) + resumeAt := resume + // Make a new txn just to drop this chunk. + if err := db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { + rd := row.MakeDeleter(codec, table, nil) + td := tableDeleter{rd: rd, alloc: alloc} + if err := td.init(ctx, txn, nil /* *tree.EvalContext */); err != nil { + return err + } + resume, err := td.deleteIndex( + ctx, + &desc, + resumeAt, + chunkSize, + false, /* traceKV */ + ) + done = resume.Key == nil + return err + }); err != nil { + return err + } + } + // All the data chunks have been removed. Now also removed the + // zone configs for the dropped indexes, if any. + if err := db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { + return RemoveIndexZoneConfigs(ctx, txn, execCfg, table.ParentID, indexes) + }); err != nil { + return err + } + } + log.Infof(ctx, "finished truncating interleaved indexes") + return nil +} + // truncateIndexes truncate the KV ranges corresponding to dropped indexes. // // The indexes are dropped chunk by chunk, each chunk being deleted in @@ -661,17 +714,7 @@ func (sc *SchemaChanger) truncateIndexes( if err != nil { return err } - rd, err := row.MakeDeleter( - ctx, - txn, - sc.execCfg.Codec, - tableDesc, - nil, - alloc, - ) - if err != nil { - return err - } + rd := row.MakeDeleter(sc.execCfg.Codec, tableDesc, nil) td := tableDeleter{rd: rd, alloc: alloc} if err := td.init(ctx, txn, nil /* *tree.EvalContext */); err != nil { return err @@ -1817,16 +1860,12 @@ func indexTruncateInTxn( alloc := &sqlbase.DatumAlloc{} var sp roachpb.Span for done := false; !done; done = sp.Key == nil { - rd, err := row.MakeDeleter( - ctx, txn, execCfg.Codec, tableDesc, nil, alloc, - ) - if err != nil { - return err - } + rd := row.MakeDeleter(execCfg.Codec, tableDesc, nil) td := tableDeleter{rd: rd, alloc: alloc} if err := td.init(ctx, txn, evalCtx); err != nil { return err } + var err error sp, err = td.deleteIndex( ctx, idx, sp, indexTruncateChunkSize, traceKV, ) diff --git a/pkg/sql/descriptor_mutation_test.go b/pkg/sql/descriptor_mutation_test.go index c46bb8293a3d..401b56234920 100644 --- a/pkg/sql/descriptor_mutation_test.go +++ b/pkg/sql/descriptor_mutation_test.go @@ -259,7 +259,14 @@ CREATE INDEX allidx ON t.test (k, v); func(t *testing.T) { // Init table to start state. - mTest.Exec(t, `TRUNCATE TABLE t.test`) + if _, err := sqlDB.Exec(` +DROP TABLE t.test; +CREATE TABLE t.test (k VARCHAR PRIMARY KEY DEFAULT 'default', v VARCHAR, i VARCHAR DEFAULT 'i', FAMILY (k), FAMILY (v), FAMILY (i)); +CREATE INDEX allidx ON t.test (k, v); +`); err != nil { + t.Fatal(err) + } + // read table descriptor mTest.tableDesc = catalogkv.TestingGetMutableExistingTableDescriptor( kvDB, keys.SystemSQLCodec, "t", "test") @@ -524,6 +531,12 @@ CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, INDEX foo (v)); if _, err := sqlDB.Exec(`TRUNCATE TABLE t.test`); err != nil { t.Fatal(err) } + if _, err := sqlDB.Exec(` +DROP TABLE t.test; +CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, INDEX foo (v)); +`); err != nil { + t.Fatal(err) + } // read table descriptor mTest.tableDesc = catalogkv.TestingGetMutableExistingTableDescriptor( kvDB, keys.SystemSQLCodec, "t", "test") @@ -687,6 +700,13 @@ CREATE INDEX allidx ON t.test (k, v); continue } // Init table to start state. + if _, err := sqlDB.Exec(` +DROP TABLE t.test; +CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, i CHAR, INDEX foo (i, v), FAMILY (k), FAMILY (v), FAMILY (i)); +CREATE INDEX allidx ON t.test (k, v); +`); err != nil { + t.Fatal(err) + } if _, err := sqlDB.Exec(`TRUNCATE TABLE t.test`); err != nil { t.Fatal(err) } diff --git a/pkg/sql/drop_table.go b/pkg/sql/drop_table.go index 57f0cec4a7da..a846b5e8b046 100644 --- a/pkg/sql/drop_table.go +++ b/pkg/sql/drop_table.go @@ -341,6 +341,37 @@ func (p *planner) dropTableImpl( return droppedViews, err } +// unsplitRangesForTable unsplit any manually split ranges within the table span. +func (p *planner) unsplitRangesForTable( + ctx context.Context, tableDesc *sqlbase.MutableTableDescriptor, +) error { + // Gate this on being the system tenant because secondary tenants aren't + // allowed to scan the meta ranges directly. + if p.ExecCfg().Codec.ForSystemTenant() { + span := tableDesc.TableSpan(p.ExecCfg().Codec) + ranges, err := ScanMetaKVs(ctx, p.txn, span) + if err != nil { + return err + } + for _, r := range ranges { + var desc roachpb.RangeDescriptor + if err := r.ValueProto(&desc); err != nil { + return err + } + if (desc.GetStickyBit() != hlc.Timestamp{}) { + // Swallow "key is not the start of a range" errors because it would mean + // that the sticky bit was removed and merged concurrently. DROP TABLE + // should not fail because of this. + if err := p.ExecCfg().DB.AdminUnsplit(ctx, desc.StartKey); err != nil && + !strings.Contains(err.Error(), "is not the start of a range") { + return err + } + } + } + } + return nil +} + // drainName when set implies that the name needs to go through the draining // names process. This parameter is always passed in as true except from // TRUNCATE which directly deletes the old name to id map and doesn't need @@ -369,29 +400,9 @@ func (p *planner) initiateDropTable( } // Unsplit all manually split ranges in the table so they can be - // automatically merged by the merge queue. Gate this on being the - // system tenant because secondary tenants aren't allowed to scan - // the meta ranges directly. - if p.ExecCfg().Codec.ForSystemTenant() { - span := tableDesc.TableSpan(p.ExecCfg().Codec) - ranges, err := ScanMetaKVs(ctx, p.txn, span) - if err != nil { - return err - } - for _, r := range ranges { - var desc roachpb.RangeDescriptor - if err := r.ValueProto(&desc); err != nil { - return err - } - if (desc.GetStickyBit() != hlc.Timestamp{}) { - // Swallow "key is not the start of a range" errors because it would mean - // that the sticky bit was removed and merged concurrently. DROP TABLE - // should not fail because of this. - if err := p.ExecCfg().DB.AdminUnsplit(ctx, desc.StartKey); err != nil && !strings.Contains(err.Error(), "is not the start of a range") { - return err - } - } - } + // automatically merged by the merge queue. + if err := p.unsplitRangesForTable(ctx, tableDesc); err != nil { + return err } tableDesc.State = descpb.TableDescriptor_DROP diff --git a/pkg/sql/gcjob/gc_job.go b/pkg/sql/gcjob/gc_job.go index 15982eb67a2f..816d61573738 100644 --- a/pkg/sql/gcjob/gc_job.go +++ b/pkg/sql/gcjob/gc_job.go @@ -21,6 +21,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/errors" @@ -96,6 +97,25 @@ func (r schemaChangeGCResumer) Resume( if err != nil { return err } + + // If there are any interleaved indexes to drop as part of a table TRUNCATE + // operation, then drop the indexes before waiting on the GC timer. + if len(details.InterleavedIndexes) > 0 { + // Before deleting any indexes, ensure that old versions of the table + // descriptor are no longer in use. + if err := sql.WaitToUpdateLeases(ctx, execCfg.LeaseManager, details.InterleavedTable.ID); err != nil { + return err + } + if err := sql.TruncateInterleavedIndexes( + ctx, + execCfg, + sqlbase.NewImmutableTableDescriptor(*details.InterleavedTable), + details.InterleavedIndexes, + ); err != nil { + return err + } + } + zoneCfgFilter, gossipUpdateC := setupConfigWatcher(execCfg) tableDropTimes, indexDropTimes := getDropTimes(details) diff --git a/pkg/sql/gcjob/index_garbage_collection.go b/pkg/sql/gcjob/index_garbage_collection.go index e16d48abc8cd..af00aa1b1a26 100644 --- a/pkg/sql/gcjob/index_garbage_collection.go +++ b/pkg/sql/gcjob/index_garbage_collection.go @@ -39,6 +39,13 @@ func gcIndexes( log.Infof(ctx, "GC is being considered on table %d for indexes indexes: %+v", parentID, droppedIndexes) } + // Before deleting any indexes, ensure that old versions of the table descriptor + // are no longer in use. This is necessary in the case of truncate, where we + // schedule a GC Job in the transaction that commits the truncation. + if err := sql.WaitToUpdateLeases(ctx, execCfg.LeaseManager, parentID); err != nil { + return false, err + } + var parentTable *sqlbase.ImmutableTableDescriptor if err := execCfg.DB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) (err error) { parentTable, err = catalogkv.MustGetTableDescByID(ctx, txn, execCfg.Codec, parentID) diff --git a/pkg/sql/logictest/testdata/logic_test/crdb_internal b/pkg/sql/logictest/testdata/logic_test/crdb_internal index 9e99bfa15c75..2ad365067f90 100644 --- a/pkg/sql/logictest/testdata/logic_test/crdb_internal +++ b/pkg/sql/logictest/testdata/logic_test/crdb_internal @@ -537,12 +537,12 @@ query TT colnames SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL ---- start_pretty end_pretty -/Table/58/1/1 /Table/58/1/2 -/Table/58/1/2 /Table/58/1/3 -/Table/58/1/3 /Table/58/2/1 -/Table/58/2/1 /Table/58/2/2 -/Table/58/2/2 /Table/58/2/3 -/Table/58/2/3 /Max +/Table/56/3/1 /Table/56/3/2 +/Table/56/3/2 /Table/56/3/3 +/Table/56/3/3 /Table/56/4/1 +/Table/56/4/1 /Table/56/4/2 +/Table/56/4/2 /Table/56/4/3 +/Table/56/4/3 /Max statement ok DROP TABLE foo @@ -565,12 +565,12 @@ query TT colnames SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL ---- start_pretty end_pretty -/Table/59/1/1 /Table/59/1/2 -/Table/59/1/2 /Table/59/1/3 -/Table/59/1/3 /Table/59/2/1 -/Table/59/2/1 /Table/59/2/2 -/Table/59/2/2 /Table/59/2/3 -/Table/59/2/3 /Max +/Table/58/1/1 /Table/58/1/2 +/Table/58/1/2 /Table/58/1/3 +/Table/58/1/3 /Table/58/2/1 +/Table/58/2/1 /Table/58/2/2 +/Table/58/2/2 /Table/58/2/3 +/Table/58/2/3 /Max statement ok DROP INDEX foo@idx @@ -581,9 +581,9 @@ query T colnames SELECT start_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL ---- start_pretty -/Table/59/1/1 -/Table/59/1/2 -/Table/59/1/3 +/Table/58/1/1 +/Table/58/1/2 +/Table/58/1/3 query T SELECT crdb_internal.cluster_name() @@ -633,7 +633,7 @@ CREATE TYPE enum2 AS ENUM () query ITTITTT SELECT * FROM crdb_internal.create_type_statements ---- -52 test public 61 enum1 CREATE TYPE public.enum1 AS ENUM ('hello', 'hi') {hello,hi} -52 test public 63 enum2 CREATE TYPE public.enum2 AS ENUM () {} +52 test public 60 enum1 CREATE TYPE public.enum1 AS ENUM ('hello', 'hi') {hello,hi} +52 test public 62 enum2 CREATE TYPE public.enum2 AS ENUM () {} # Test the virtual index as well. diff --git a/pkg/sql/logictest/testdata/logic_test/privileges_table b/pkg/sql/logictest/testdata/logic_test/privileges_table index dbd323ccf878..ed1b6b19b166 100644 --- a/pkg/sql/logictest/testdata/logic_test/privileges_table +++ b/pkg/sql/logictest/testdata/logic_test/privileges_table @@ -72,7 +72,7 @@ statement error pq: user testuser does not have SELECT privilege on relation t SELECT r FROM t statement error pq: user testuser does not have SELECT privilege on relation t -SELECT * from [56 as num_ref] +SELECT * from [55 as num_ref] statement error user testuser does not have GRANT privilege on relation t GRANT ALL ON t TO bar diff --git a/pkg/sql/logictest/testdata/logic_test/schema_change_in_txn b/pkg/sql/logictest/testdata/logic_test/schema_change_in_txn index 4b0ae91afc3a..85b97abdb326 100644 --- a/pkg/sql/logictest/testdata/logic_test/schema_change_in_txn +++ b/pkg/sql/logictest/testdata/logic_test/schema_change_in_txn @@ -658,11 +658,8 @@ TRUNCATE want statement ok INSERT INTO want (k,v) VALUES ('a', 'b') -statement ok -CREATE INDEX foo on want (v) - query TT -SELECT * FROM want@foo +SELECT * FROM want ---- a b @@ -680,8 +677,7 @@ BEGIN statement ok TRUNCATE orders -# table orders is not visible to the transaction #17949 -statement error pgcode 42P01 relation "orders" does not exist +statement ok INSERT INTO orders (k,v) VALUES ('a', 'b') statement ok @@ -693,8 +689,7 @@ BEGIN statement ok TRUNCATE customers CASCADE -# table customers is not visible to the transaction #17949 -statement error pgcode 42P01 relation "customers" does not exist +statement ok INSERT INTO customers (k) VALUES ('b') statement ok diff --git a/pkg/sql/logictest/testdata/logic_test/temp_table b/pkg/sql/logictest/testdata/logic_test/temp_table index ef41622bd8ea..ff3b63e13b55 100644 --- a/pkg/sql/logictest/testdata/logic_test/temp_table +++ b/pkg/sql/logictest/testdata/logic_test/temp_table @@ -246,7 +246,7 @@ ALTER TABLE regression_48233 RENAME TO reg_48233 query IITI rowsort SELECT * FROM system.namespace WHERE name LIKE '%48233' ---- -50 65 reg_48233 79 +50 65 reg_48233 78 statement error pq: cannot change schema of table with RENAME ALTER TABLE reg_48233 RENAME TO public.reg_48233 diff --git a/pkg/sql/logictest/testdata/logic_test/truncate b/pkg/sql/logictest/testdata/logic_test/truncate index baa7a6ca98e6..7012c8465953 100644 --- a/pkg/sql/logictest/testdata/logic_test/truncate +++ b/pkg/sql/logictest/testdata/logic_test/truncate @@ -48,18 +48,6 @@ query II SELECT * FROM kview ---- -# The "updating privileges" clause in the SELECT statement is for excluding jobs -# run by an unrelated startup migration. -# TODO (lucy): Update this if/when we decide to change how these jobs queued by -# the startup migration are handled. -query T -SELECT status FROM [SHOW JOBS] WHERE job_type = 'SCHEMA CHANGE' AND description != 'updating privileges' ----- -succeeded -succeeded -succeeded -succeeded - query T SELECT status FROM [SHOW JOBS] WHERE job_type = 'SCHEMA CHANGE GC' ---- diff --git a/pkg/sql/opt_exec_factory.go b/pkg/sql/opt_exec_factory.go index 1fb6e27a23c1..a82c0d8fcb4e 100644 --- a/pkg/sql/opt_exec_factory.go +++ b/pkg/sql/opt_exec_factory.go @@ -1551,8 +1551,6 @@ func (ef *execFactory) ConstructDelete( returnColOrdSet exec.TableColumnOrdinalSet, autoCommit bool, ) (exec.Node, error) { - ctx := ef.planner.extendedEvalCtx.Context - // Derive table and column descriptors. rowsNeeded := !returnColOrdSet.Empty() tabDesc := table.(*optTable).desc @@ -1566,17 +1564,7 @@ func (ef *execFactory) ConstructDelete( // the deleter derives the columns that need to be fetched. By contrast, the // CBO will have already determined the set of fetch columns, and passes // those sets into the deleter (which will basically be a no-op). - rd, err := row.MakeDeleter( - ctx, - ef.planner.txn, - ef.planner.ExecCfg().Codec, - tabDesc, - fetchColDescs, - ef.planner.alloc, - ) - if err != nil { - return nil, err - } + rd := row.MakeDeleter(ef.planner.ExecCfg().Codec, tabDesc, fetchColDescs) // Truncate any FetchCols added by MakeUpdater. The optimizer has already // computed a correct set that can sometimes be smaller. diff --git a/pkg/sql/row/deleter.go b/pkg/sql/row/deleter.go index 41e432923f04..f45ee4089e62 100644 --- a/pkg/sql/row/deleter.go +++ b/pkg/sql/row/deleter.go @@ -37,13 +37,10 @@ type Deleter struct { // expectation of which values are passed as values to DeleteRow. Any column // passed in requestedCols will be included in FetchCols. func MakeDeleter( - ctx context.Context, - txn *kv.Txn, codec keys.SQLCodec, tableDesc *sqlbase.ImmutableTableDescriptor, requestedCols []descpb.ColumnDescriptor, - alloc *sqlbase.DatumAlloc, -) (Deleter, error) { +) Deleter { indexes := tableDesc.DeletableIndexes() fetchCols := requestedCols[:len(requestedCols):len(requestedCols)] @@ -62,19 +59,19 @@ func MakeDeleter( } for _, colID := range tableDesc.PrimaryIndex.ColumnIDs { if err := maybeAddCol(colID); err != nil { - return Deleter{}, err + return Deleter{} } } for _, index := range indexes { for _, colID := range index.ColumnIDs { if err := maybeAddCol(colID); err != nil { - return Deleter{}, err + return Deleter{} } } // The extra columns are needed to fix #14601. for _, colID := range index.ExtraColumnIDs { if err := maybeAddCol(colID); err != nil { - return Deleter{}, err + return Deleter{} } } } @@ -85,7 +82,7 @@ func MakeDeleter( FetchColIDtoRowIndex: fetchColIDtoRowIndex, } - return rd, nil + return rd } // DeleteRow adds to the batch the kv operations necessary to delete a table row diff --git a/pkg/sql/row/updater.go b/pkg/sql/row/updater.go index 746bb840186b..6ae894898b7f 100644 --- a/pkg/sql/row/updater.go +++ b/pkg/sql/row/updater.go @@ -174,11 +174,7 @@ func MakeUpdater( // When changing the primary key, we delete the old values and reinsert // them, so request them all. var err error - if ru.rd, err = MakeDeleter( - ctx, txn, codec, tableDesc, tableCols, alloc, - ); err != nil { - return Updater{}, err - } + ru.rd = MakeDeleter(codec, tableDesc, tableCols) ru.FetchCols = ru.rd.FetchCols ru.FetchColIDtoRowIndex = ColIDtoRowIndexFromCols(ru.FetchCols) if ru.ri, err = MakeInserter( diff --git a/pkg/sql/schema_changer.go b/pkg/sql/schema_changer.go index b8fe9e851ca7..d897c87f53f8 100644 --- a/pkg/sql/schema_changer.go +++ b/pkg/sql/schema_changer.go @@ -974,7 +974,7 @@ func (sc *SchemaChanger) done(ctx context.Context) error { // index swap occurs. The logic that generates spans for subzone // configurations removes spans for indexes in the dropping state, // which we don't want. So, set up the zone configs before we swap. - if err := sc.maybeUpdateZoneConfigsForPKChange( + if err := maybeUpdateZoneConfigsForPKChange( ctx, txn, sc.execCfg, scTable, pkSwap); err != nil { return err } @@ -1126,7 +1126,7 @@ func (sc *SchemaChanger) done(ctx context.Context) error { // maybeUpdateZoneConfigsForPKChange moves zone configs for any rewritten // indexes from the old index over to the new index. -func (sc *SchemaChanger) maybeUpdateZoneConfigsForPKChange( +func maybeUpdateZoneConfigsForPKChange( ctx context.Context, txn *kv.Txn, execCfg *ExecutorConfig, diff --git a/pkg/sql/schema_changer_test.go b/pkg/sql/schema_changer_test.go index 1dd151734e3e..97e3278904ed 100644 --- a/pkg/sql/schema_changer_test.go +++ b/pkg/sql/schema_changer_test.go @@ -3920,15 +3920,16 @@ CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14 } // Check that SQL thinks the table is empty. - if err := checkTableKeyCount(ctx, kvDB, 0, 0); err != nil { - t.Fatal(err) - } + row := sqlDB.QueryRow("SELECT count(*) FROM t.test") + var count int + require.NoError(t, row.Scan(&count)) + require.Equal(t, 0, count) - newTableDesc := catalogkv.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") - if newTableDesc.Adding() { - t.Fatalf("bad state = %s", newTableDesc.State) + tableDesc = catalogkv.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") + if tableDesc.Adding() { + t.Fatalf("bad state = %s", tableDesc.State) } - if err := zoneExists(sqlDB, &cfg, newTableDesc.ID); err != nil { + if err := zoneExists(sqlDB, &cfg, tableDesc.ID); err != nil { t.Fatal(err) } @@ -3940,22 +3941,6 @@ CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14 } else if e := maxValue + 1; len(kvs) != e { t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) } - // Check that the table descriptor exists so we know the data will - // eventually be deleted. - var droppedDesc *sqlbase.ImmutableTableDescriptor - if err := kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { - var err error - droppedDesc, err = catalogkv.MustGetTableDescByID(ctx, txn, keys.SystemSQLCodec, tableDesc.ID) - return err - }); err != nil { - t.Fatal(err) - } - if droppedDesc == nil { - t.Fatalf("table descriptor doesn't exist after table is truncated: %d", tableDesc.ID) - } - if !droppedDesc.Dropped() { - t.Fatalf("bad state = %s", droppedDesc.State) - } close(blockGC) @@ -4030,18 +4015,20 @@ CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL REFERENCES t.pi (d) DE } // Check that SQL thinks the table is empty. - if err := checkTableKeyCount(ctx, kvDB, 0, 0); err != nil { - t.Fatal(err) - } + row := sqlDB.QueryRow("SELECT count(*) FROM t.test") + var count int + require.NoError(t, row.Scan(&count)) + require.Equal(t, 0, count) // Bulk insert. if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { t.Fatal(err) } - if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { - t.Fatal(err) - } + row = sqlDB.QueryRow("SELECT count(*) FROM t.test") + require.NoError(t, row.Scan(&count)) + require.Equal(t, maxValue+1, count) + if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { t.Fatal(err) } @@ -4053,6 +4040,7 @@ CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL REFERENCES t.pi (d) DE t.Fatalf("err = %v", err) } + // Get the table descriptor after the truncation. newTableDesc := catalogkv.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") if newTableDesc.Adding() { t.Fatalf("bad state = %s", newTableDesc.State) @@ -4061,27 +4049,8 @@ CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL REFERENCES t.pi (d) DE t.Fatal(err) } - // Wait until the older descriptor has been deleted. - testutils.SucceedsSoon(t, func() error { - if err := kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { - var err error - _, err = catalogkv.MustGetTableDescByID(ctx, txn, keys.SystemSQLCodec, tableDesc.ID) - return err - }); err != nil { - if errors.Is(err, sqlbase.ErrDescriptorNotFound) { - return nil - } - return err - } - return errors.Errorf("table descriptor exists after table is truncated: %d", tableDesc.ID) - }) - - if err := zoneExists(sqlDB, nil, tableDesc.ID); err != nil { - t.Fatal(err) - } - // Ensure that the table data has been deleted. - tablePrefix := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) + tablePrefix := keys.SystemSQLCodec.IndexPrefix(uint32(tableDesc.ID), uint32(tableDesc.PrimaryIndex.ID)) tableEnd := tablePrefix.PrefixEnd() if kvs, err := kvDB.Scan(ctx, tablePrefix, tableEnd, 0); err != nil { t.Fatal(err) @@ -4115,6 +4084,64 @@ CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL REFERENCES t.pi (d) DE } } +func TestTruncateInterleavedTables(t *testing.T) { + defer leaktest.AfterTest(t)() + defer log.Scope(t).Close(t) + + defer setTestJobsAdoptInterval()() + defer gcjob.SetSmallMaxGCIntervalForTest()() + + params, _ := tests.CreateTestServerParams() + + s, sqlDBRaw, kvDB := serverutils.StartServer(t, params) + ctx := context.Background() + defer s.Stopper().Stop(ctx) + sqlDB := sqlutils.SQLRunner{DB: sqlDBRaw} + + // Disable strict GC TTL enforcement because we're going to shove a zero-value + // TTL into the system with AddImmediateGCZoneConfig. + defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDBRaw)() + + sqlDB.Exec(t, ` +CREATE DATABASE t; +CREATE TABLE t.parent (x INT PRIMARY KEY); +CREATE TABLE t.child (x INT, y INT, PRIMARY KEY (x, y)) INTERLEAVE IN PARENT t.parent (x); +INSERT INTO t.parent VALUES (1), (2), (3); +INSERT INTO t.child VALUES (1, 2), (2, 3), (3, 4); +`) + + // Get the table descriptors before truncation. + parent := catalogkv.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "parent") + child := catalogkv.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "child") + + // Add zone configs for the parent and child tables. + _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDBRaw, parent.ID) + require.NoError(t, err) + _, err = sqltestutils.AddImmediateGCZoneConfig(sqlDBRaw, child.ID) + require.NoError(t, err) + + // Truncate the parent now, which should cascade truncate the child. + sqlDB.Exec(t, `TRUNCATE TABLE t.parent CASCADE`) + + // SQL should think that both the parent and child tables are empty. + sqlDB.CheckQueryResults(t, `SELECT count(*) FROM t.parent`, [][]string{{"0"}}) + sqlDB.CheckQueryResults(t, `SELECT count(*) FROM t.child`, [][]string{{"0"}}) + + // The GC should kick in and actually delete all of the data in each table. + testutils.SucceedsSoon(t, func() error { + // We only need to scan the parent's table span to verify that + // the index data is deleted, since child is interleaved in it. + start := keys.SystemSQLCodec.TablePrefix(uint32(parent.ID)) + end := start.PrefixEnd() + kvs, err := kvDB.Scan(ctx, start, end, 0) + require.NoError(t, err) + if len(kvs) != 0 { + return errors.Newf("expected 0 kvs, found %d", len(kvs)) + } + return nil + }) +} + // Test TRUNCATE during a column backfill. func TestTruncateWhileColumnBackfill(t *testing.T) { defer leaktest.AfterTest(t)() diff --git a/pkg/sql/sqlbase/table.go b/pkg/sql/sqlbase/table.go index d017f6db932c..11b308e917c9 100644 --- a/pkg/sql/sqlbase/table.go +++ b/pkg/sql/sqlbase/table.go @@ -576,24 +576,3 @@ func InitTableDescriptor( }, } } - -// NewMutableTableDescriptorAsReplacement creates a new MutableTableDescriptor -// as a replacement of an existing table. This is utilized with truncate. -// -// The passed readTimestamp is serialized into the descriptor's ReplacementOf -// field for debugging purposes. The passed id will be the ID of the newly -// returned replacement. -// -// TODO(ajwerner): Decide whether we need to clone here. -func NewMutableTableDescriptorAsReplacement( - id descpb.ID, replacementOf *MutableTableDescriptor, readTimestamp hlc.Timestamp, -) *MutableTableDescriptor { - replacement := &MutableTableDescriptor{ImmutableTableDescriptor: replacementOf.ImmutableTableDescriptor} - replacement.ID = id - replacement.Version = 1 - replacement.ReplacementOf = descpb.TableDescriptor_Replacement{ - ID: replacementOf.ID, - Time: readTimestamp, - } - return replacement -} diff --git a/pkg/sql/sqlbase/table_desc.go b/pkg/sql/sqlbase/table_desc.go index 0c395c6b7857..0699835df0a1 100644 --- a/pkg/sql/sqlbase/table_desc.go +++ b/pkg/sql/sqlbase/table_desc.go @@ -41,6 +41,7 @@ type TableDescriptor interface { GetIndexes() []descpb.IndexDescriptor ForeachNonDropIndex(f func(idxDesc *descpb.IndexDescriptor) error) error IndexSpan(codec keys.SQLCodec, id descpb.IndexID) roachpb.Span + IsInterleaved() bool FindIndexByID(id descpb.IndexID) (*descpb.IndexDescriptor, error) FindIndexByName(name string) (_ *descpb.IndexDescriptor, dropped bool, _ error) FindIndexesWithPartition(name string) []*descpb.IndexDescriptor diff --git a/pkg/sql/truncate.go b/pkg/sql/truncate.go index 141f8300e4d6..82622bb9d988 100644 --- a/pkg/sql/truncate.go +++ b/pkg/sql/truncate.go @@ -12,21 +12,20 @@ package sql import ( "context" - "fmt" - "github.com/cockroachdb/cockroach/pkg/config" + "github.com/cockroachdb/cockroach/pkg/jobs/jobspb" "github.com/cockroachdb/cockroach/pkg/keys" "github.com/cockroachdb/cockroach/pkg/kv" "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/security" - "github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkv" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/privilege" "github.com/cockroachdb/cockroach/pkg/sql/row" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" - "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/log" + "github.com/cockroachdb/cockroach/pkg/util/protoutil" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/errors" ) @@ -54,6 +53,24 @@ func (t *truncateNode) startExec(params runParams) error { // while constructing the list of tables that should be truncated. toTraverse := make([]sqlbase.MutableTableDescriptor, 0, len(n.Tables)) + // Collect copies of each interleaved descriptor being truncated before any + // modification has been done to them. We need this in order to truncate + // the interleaved indexes in the GC job. We have to collect these descriptors + // before the truncate modifications to know what are the correct index spans + // to delete. Once changes have been made, the index spans where k/v data for + // the table reside are no longer accessible from the table. + interleaveCopies := make(map[descpb.ID]*descpb.TableDescriptor) + maybeAddInterleave := func(desc sqlbase.TableDescriptor) { + if !desc.IsInterleaved() { + return + } + _, ok := interleaveCopies[desc.GetID()] + if ok { + return + } + interleaveCopies[desc.GetID()] = protoutil.Clone(desc.TableDesc()).(*descpb.TableDescriptor) + } + for i := range n.Tables { tn := &n.Tables[i] tableDesc, err := p.ResolveMutableTableDescriptor( @@ -68,6 +85,7 @@ func (t *truncateNode) startExec(params runParams) error { toTruncate[tableDesc.ID] = tn.FQString() toTraverse = append(toTraverse, *tableDesc) + maybeAddInterleave(tableDesc) } // Check that any referencing tables are contained in the set, or, if CASCADE @@ -100,6 +118,7 @@ func (t *truncateNode) startExec(params runParams) error { } toTruncate[other.ID] = otherName.FQString() toTraverse = append(toTraverse, *other) + maybeAddInterleave(other) return nil } @@ -123,9 +142,8 @@ func (t *truncateNode) startExec(params runParams) error { return err } - traceKV := p.extendedEvalCtx.Tracing.KVTracingEnabled() for id, name := range toTruncate { - if err := p.truncateTable(ctx, id, tree.AsStringWithFQNames(t.n, params.Ann()), traceKV); err != nil { + if err := p.truncateTable(ctx, id, interleaveCopies, tree.AsStringWithFQNames(t.n, params.Ann())); err != nil { return err } @@ -153,11 +171,17 @@ func (t *truncateNode) Next(runParams) (bool, error) { return false, nil } func (t *truncateNode) Values() tree.Datums { return tree.Datums{} } func (t *truncateNode) Close(context.Context) {} -// truncateTable truncates the data of a table in a single transaction. It -// drops the table and recreates it with a new ID. The dropped table is -// GC-ed later through an asynchronous schema change. +// truncateTable truncates the data of a table in a single transaction. It does +// so by dropping all existing indexes on the table and creating new ones without +// backfilling any data into the new indexes. The old indexes are cleaned up +// asynchronously by the SchemaChangeGCJob. interleaveDescs is a set of +// interleaved TableDescriptors being truncated before any of the truncate +// mutations have been applied. func (p *planner) truncateTable( - ctx context.Context, id descpb.ID, jobDesc string, traceKV bool, + ctx context.Context, + id descpb.ID, + interleaveDescs map[descpb.ID]*descpb.TableDescriptor, + jobDesc string, ) error { // Read the table descriptor because it might have changed // while another table in the truncation list was truncated. @@ -166,140 +190,168 @@ func (p *planner) truncateTable( return err } - newID, err := catalogkv.GenerateUniqueDescID(ctx, p.ExecCfg().DB, p.ExecCfg().Codec) + // Get all tables that might reference this one. + allRefs, err := p.findAllReferencingInterleaves(ctx, tableDesc) if err != nil { return err } - // tableDesc.DropJobID = dropJobID - newTableDesc := sqlbase.NewMutableTableDescriptorAsReplacement( - newID, tableDesc, p.txn.ReadTimestamp()) - - // Remove old name -> id map. - // This is a violation of consistency because once the TRUNCATE commits - // some nodes in the cluster can have cached the old name to id map - // for the table and applying operations using the old table id. - // This violation is needed because it is not uncommon for TRUNCATE - // to be used along with other CRUD commands that follow it in the - // same transaction. Commands that follow the TRUNCATE in the same - // transaction will use the correct descriptor (through uncommittedTables) - // See the comment about problem 3 related to draining names in - // structured.proto - // - // TODO(vivek): Fix properly along with #12123. - key := catalogkv.MakeObjectNameKey( - ctx, p.ExecCfg().Settings, - newTableDesc.ParentID, - newTableDesc.GetParentSchemaID(), - newTableDesc.Name, - ).Key(p.ExecCfg().Codec) - - // Remove the old namespace entry. - if err := catalogkv.RemoveObjectNamespaceEntry( - ctx, p.txn, p.execCfg.Codec, - tableDesc.ParentID, tableDesc.GetParentSchemaID(), tableDesc.GetName(), - traceKV); err != nil { - return err - } - // Drop table. - if err := p.initiateDropTable(ctx, tableDesc, true /* queueJob */, jobDesc, false /* drainName */); err != nil { - return err + // Collect all of the old indexes. + oldIndexes := make([]descpb.IndexDescriptor, len(tableDesc.Indexes)+1) + oldIndexes[0] = *protoutil.Clone(&tableDesc.PrimaryIndex).(*descpb.IndexDescriptor) + for i := range tableDesc.Indexes { + oldIndexes[i+1] = *protoutil.Clone(&tableDesc.Indexes[i]).(*descpb.IndexDescriptor) } - // update all the references to this table. - tables, err := p.findAllReferences(ctx, *tableDesc) - if err != nil { - return err + // Reset all of the index IDs. + tableDesc.PrimaryIndex.ID = descpb.IndexID(0) + for i := range tableDesc.Indexes { + tableDesc.Indexes[i].ID = descpb.IndexID(0) } - if changed, err := reassignReferencedTables(tables, tableDesc.ID, newID); err != nil { + // Create new ID's for all of the indexes in the table. + if err := tableDesc.AllocateIDs(); err != nil { return err - } else if changed { - newTableDesc.State = descpb.TableDescriptor_ADD - } - - for _, table := range tables { - if err := p.writeSchemaChange( - ctx, table, descpb.InvalidMutationID, "updating reference for truncated table", - ); err != nil { - return err - } } - // Reassign all self references. - if changed, err := reassignReferencedTables( - []*sqlbase.MutableTableDescriptor{newTableDesc}, tableDesc.ID, newID, - ); err != nil { - return err - } else if changed { - newTableDesc.State = descpb.TableDescriptor_ADD + // Construct a mapping from old index ID's to new index ID's. + indexIDMapping := make(map[descpb.IndexID]descpb.IndexID, len(oldIndexes)) + indexIDMapping[oldIndexes[0].ID] = tableDesc.PrimaryIndex.ID + for i := range tableDesc.Indexes { + indexIDMapping[oldIndexes[i+1].ID] = tableDesc.Indexes[i].ID } // Resolve all outstanding mutations. Make all new schema elements // public because the table is empty and doesn't need to be backfilled. - for _, m := range newTableDesc.Mutations { - if err := newTableDesc.MakeMutationComplete(m); err != nil { + for _, m := range tableDesc.Mutations { + if err := tableDesc.MakeMutationComplete(m); err != nil { return err } } - newTableDesc.Mutations = nil - newTableDesc.GCMutations = nil - // NB: Set the modification time to a zero value so that it is interpreted - // as the commit timestamp for the new descriptor. See the comment on - // descpb.Descriptor.Table(). - newTableDesc.ModificationTime = hlc.Timestamp{} - if err := p.createDescriptorWithID( - ctx, key, newID, newTableDesc, p.ExtendedEvalContext().Settings, - fmt.Sprintf("creating new descriptor %d for truncated table %s with id %d", - newID, newTableDesc.Name, id), - ); err != nil { + tableDesc.Mutations = nil + tableDesc.GCMutations = nil + + // Create schema change GC jobs for all of the indexes. + dropTime := timeutil.Now().UnixNano() + droppedIndexes := make([]jobspb.SchemaChangeGCDetails_DroppedIndex, 0, len(oldIndexes)) + var droppedInterleaves []descpb.IndexDescriptor + for i := range oldIndexes { + idx := oldIndexes[i] + if idx.IsInterleaved() { + droppedInterleaves = append(droppedInterleaves, idx) + } else { + droppedIndexes = append(droppedIndexes, jobspb.SchemaChangeGCDetails_DroppedIndex{ + IndexID: idx.ID, + DropTime: dropTime, + }) + } + } + + details := jobspb.SchemaChangeGCDetails{ + Indexes: droppedIndexes, + ParentID: tableDesc.ID, + } + // If we have any interleaved indexes, add that information to the job record. + if len(droppedInterleaves) > 0 { + details.InterleavedTable = interleaveDescs[tableDesc.ID] + details.InterleavedIndexes = droppedInterleaves + } + record := CreateGCJobRecord(jobDesc, p.User(), details) + if _, err := p.ExecCfg().JobRegistry.CreateAdoptableJobWithTxn(ctx, record, p.txn); err != nil { return err } - // Reassign comments on the table, columns and indexes. - if err := reassignComments(ctx, p, tableDesc, newTableDesc); err != nil { + // Unsplit all manually split ranges in the table so they can be + // automatically merged by the merge queue. + if err := p.unsplitRangesForTable(ctx, tableDesc); err != nil { return err } - // Remove back references from types to the original table descriptor. - if err := p.removeBackRefsFromAllTypesInTable(ctx, tableDesc); err != nil { + // Reassign any referenced index ID's from other tables. + if err := p.reassignInterleaveIndexReferences(ctx, allRefs, tableDesc.ID, indexIDMapping); err != nil { + return err + } + // Reassign any self references. + if err := p.reassignInterleaveIndexReferences( + ctx, + []*sqlbase.MutableTableDescriptor{tableDesc}, + tableDesc.ID, + indexIDMapping, + ); err != nil { return err } - // Add all of the references to the new table descriptor. - if err := p.addBackRefsFromAllTypesInTable(ctx, newTableDesc); err != nil { + // Move any zone configs on indexes over to the new set of indexes. + oldIndexIDs := make([]descpb.IndexID, len(oldIndexes)-1) + for i := range oldIndexIDs { + oldIndexIDs[i] = oldIndexes[i+1].ID + } + newIndexIDs := make([]descpb.IndexID, len(tableDesc.Indexes)) + for i := range newIndexIDs { + newIndexIDs[i] = tableDesc.Indexes[i].ID + } + swapInfo := &descpb.PrimaryKeySwap{ + OldPrimaryIndexId: oldIndexes[0].ID, + OldIndexes: oldIndexIDs, + NewPrimaryIndexId: tableDesc.PrimaryIndex.ID, + NewIndexes: newIndexIDs, + } + if err := maybeUpdateZoneConfigsForPKChange(ctx, p.txn, p.ExecCfg(), tableDesc, swapInfo); err != nil { return err } - // Copy the zone config, if this is for the system tenant. Secondary tenants - // do not have zone configs for individual objects. - if p.ExecCfg().Codec.ForSystemTenant() { - zoneKey := config.MakeZoneKey(config.SystemTenantObjectID(tableDesc.ID)) - b := &kv.Batch{} - b.Get(zoneKey) - if err := p.txn.Run(ctx, b); err != nil { - return err - } - val := b.Results[0].Rows[0].Value - if val == nil { - return nil + // Reassign any index comments. + if err := p.reassignIndexComments(ctx, tableDesc, indexIDMapping); err != nil { + return err + } + + return p.writeSchemaChange(ctx, tableDesc, descpb.InvalidMutationID, jobDesc) +} + +// ClearTableDataInChunks truncates the data of a table in chunks. It deletes a +// range of data for the table, which includes the PK and all indexes. +// The table has already been marked for deletion and has been purged from the +// descriptor cache on all nodes. +// +// TODO(vivek): No node is reading/writing data on the table at this stage, +// therefore the entire table can be deleted with no concern for conflicts (we +// can even eliminate the need to use a transaction for each chunk at a later +// stage if it proves inefficient). +func ClearTableDataInChunks( + ctx context.Context, + db *kv.DB, + codec keys.SQLCodec, + tableDesc *sqlbase.ImmutableTableDescriptor, + traceKV bool, +) error { + const chunkSize = row.TableTruncateChunkSize + var resume roachpb.Span + alloc := &sqlbase.DatumAlloc{} + for rowIdx, done := 0, false; !done; rowIdx += chunkSize { + resumeAt := resume + if traceKV { + log.VEventf(ctx, 2, "table %s truncate at row: %d, span: %s", tableDesc.Name, rowIdx, resume) } - zoneCfg, err := val.GetBytes() - if err != nil { + if err := db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { + rd := row.MakeDeleter(codec, tableDesc, nil) + td := tableDeleter{rd: rd, alloc: alloc} + if err := td.init(ctx, txn, nil /* *tree.EvalContext */); err != nil { + return err + } + var err error + resume, err = td.deleteAllRows(ctx, resumeAt, chunkSize, traceKV) return err - } - const insertZoneCfg = `INSERT INTO system.zones (id, config) VALUES ($1, $2)` - if _, err = p.ExtendedEvalContext().ExecCfg.InternalExecutor.Exec( - ctx, "insert-zone", p.txn, insertZoneCfg, newID, zoneCfg, - ); err != nil { + }); err != nil { return err } + done = resume.Key == nil } return nil } -// For all the references from a table -func (p *planner) findAllReferences( - ctx context.Context, table sqlbase.MutableTableDescriptor, +// findAllReferencingInterleaves finds all tables that might interleave or +// be interleaved by the input table. +func (p *planner) findAllReferencingInterleaves( + ctx context.Context, table *sqlbase.MutableTableDescriptor, ) ([]*sqlbase.MutableTableDescriptor, error) { refs, err := table.FindAllReferences() if err != nil { @@ -320,125 +372,76 @@ func (p *planner) findAllReferences( return tables, nil } -// reassign all the references from oldID to newID. -func reassignReferencedTables( - tables []*sqlbase.MutableTableDescriptor, oldID, newID descpb.ID, -) (bool, error) { - changed := false +// reassignInterleaveIndexReferences reassigns all index ID's present in +// interleave descriptor references according to indexIDMapping. +func (p *planner) reassignInterleaveIndexReferences( + ctx context.Context, + tables []*sqlbase.MutableTableDescriptor, + truncatedID descpb.ID, + indexIDMapping map[descpb.IndexID]descpb.IndexID, +) error { for _, table := range tables { + changed := false if err := table.ForeachNonDropIndex(func(index *descpb.IndexDescriptor) error { for j, a := range index.Interleave.Ancestors { - if a.TableID == oldID { - index.Interleave.Ancestors[j].TableID = newID + if a.TableID == truncatedID { + index.Interleave.Ancestors[j].IndexID = indexIDMapping[index.Interleave.Ancestors[j].IndexID] changed = true } } for j, c := range index.InterleavedBy { - if c.Table == oldID { - index.InterleavedBy[j].Table = newID + if c.Table == truncatedID { + index.InterleavedBy[j].Index = indexIDMapping[index.InterleavedBy[j].Index] changed = true } } return nil }); err != nil { - return false, err - } - for i := range table.OutboundFKs { - fk := &table.OutboundFKs[i] - if fk.ReferencedTableID == oldID { - fk.ReferencedTableID = newID - changed = true - } - } - for i := range table.InboundFKs { - fk := &table.InboundFKs[i] - if fk.OriginTableID == oldID { - fk.OriginTableID = newID - changed = true - } - } - - for i, dest := range table.DependsOn { - if dest == oldID { - table.DependsOn[i] = newID - changed = true - } + return err } - origRefs := table.DependedOnBy - table.DependedOnBy = nil - for _, ref := range origRefs { - if ref.ID == oldID { - ref.ID = newID - changed = true + if changed { + if err := p.writeSchemaChange(ctx, table, descpb.InvalidMutationID, "updating reference for truncated table"); err != nil { + return err } - table.DependedOnBy = append(table.DependedOnBy, ref) } } - return changed, nil + return nil } -// reassignComments reassign all comments on the table, indexes and columns. -func reassignComments( - ctx context.Context, p *planner, oldTableDesc, newTableDesc *sqlbase.MutableTableDescriptor, +func (p *planner) reassignIndexComments( + ctx context.Context, + table *sqlbase.MutableTableDescriptor, + indexIDMapping map[descpb.IndexID]descpb.IndexID, ) error { - _, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.ExecEx( + // Check if there are any index comments that need to be updated. + row, err := p.extendedEvalCtx.ExecCfg.InternalExecutor.QueryRowEx( ctx, "update-table-comments", p.txn, sqlbase.InternalExecutorSessionDataOverride{User: security.RootUser}, - `UPDATE system.comments SET object_id=$1 WHERE object_id=$2`, - newTableDesc.ID, - oldTableDesc.ID, + `SELECT count(*) FROM system.comments WHERE object_id = $1 AND type = $2`, + table.ID, + keys.IndexCommentType, ) - return err -} - -// ClearTableDataInChunks truncates the data of a table in chunks. It deletes a -// range of data for the table, which includes the PK and all indexes. -// The table has already been marked for deletion and has been purged from the -// descriptor cache on all nodes. -// -// TODO(vivek): No node is reading/writing data on the table at this stage, -// therefore the entire table can be deleted with no concern for conflicts (we -// can even eliminate the need to use a transaction for each chunk at a later -// stage if it proves inefficient). -func ClearTableDataInChunks( - ctx context.Context, - db *kv.DB, - codec keys.SQLCodec, - tableDesc *sqlbase.ImmutableTableDescriptor, - traceKV bool, -) error { - const chunkSize = row.TableTruncateChunkSize - var resume roachpb.Span - alloc := &sqlbase.DatumAlloc{} - for rowIdx, done := 0, false; !done; rowIdx += chunkSize { - resumeAt := resume - if traceKV { - log.VEventf(ctx, 2, "table %s truncate at row: %d, span: %s", tableDesc.Name, rowIdx, resume) - } - if err := db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { - rd, err := row.MakeDeleter( + if err != nil { + return err + } + if int(tree.MustBeDInt(row[0])) > 0 { + for old, new := range indexIDMapping { + if _, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.ExecEx( ctx, - txn, - codec, - tableDesc, - nil, - alloc, - ) - if err != nil { + "update-table-comments", + p.txn, + sqlbase.InternalExecutorSessionDataOverride{User: security.RootUser}, + `UPDATE system.comments SET sub_id=$1 WHERE sub_id=$2 AND object_id=$3 AND type=$4`, + new, + old, + table.ID, + keys.IndexCommentType, + ); err != nil { return err } - td := tableDeleter{rd: rd, alloc: alloc} - if err := td.init(ctx, txn, nil /* *tree.EvalContext */); err != nil { - return err - } - resume, err = td.deleteAllRows(ctx, resumeAt, chunkSize, traceKV) - return err - }); err != nil { - return err } - done = resume.Key == nil } return nil }