From 4b3fe803db81c3bca362c41193c2d525fc33ce99 Mon Sep 17 00:00:00 2001 From: Jayant Shrivastava Date: Thu, 19 Nov 2020 17:31:39 -0500 Subject: [PATCH 1/5] sql: implement sequence caching Previously, incrementing sequences at a high throughput would result in many distributed writes to the KV layer due to MVCC. This has caused garbage collection problems in the past. This would occur in situations such as bulk importing data while using the sequence number as an id for each new row being added. This change allows clients to cache sequence numbers in their local session data. When the cache is empty, the sequence will be incremented once by the cache size * increment amount, which are both sequence options. Then, all the intermediate values will be cached locally on a node to be given out whenever the sequence is incremented. To accommodate schema changes, cached sequences values will be invalidated when new descriptor versions are seen by the cache. This invalidation can occur when old versions are seen as well to accommodate schema change rollbacks. Release note (sql change): Using the CACHE sequence option no longer results in an "unimplemented" error. The CACHE option is now fully implemented and will allow nodes to cache sequence numbers. A cache size of 1 means that there is no cache, and cache sizes of less than 1 are not valid. --- pkg/sql/catalog/descpb/structured.go | 16 + pkg/sql/catalog/descpb/structured.pb.go | 696 +++++++++--------- pkg/sql/catalog/descpb/structured.proto | 4 + pkg/sql/catalog/systemschema/system.go | 1 + pkg/sql/exec_util.go | 5 + .../logictest/testdata/logic_test/sequences | 92 ++- pkg/sql/planner.go | 10 + pkg/sql/sequence.go | 60 +- pkg/sql/sequence_test.go | 288 +++++++- pkg/sql/sessiondata/sequence_cache.go | 69 ++ pkg/sql/sessiondata/session_data.go | 4 + 11 files changed, 890 insertions(+), 355 deletions(-) create mode 100644 pkg/sql/sessiondata/sequence_cache.go diff --git a/pkg/sql/catalog/descpb/structured.go b/pkg/sql/catalog/descpb/structured.go index b22c02c97d07..97812b010318 100644 --- a/pkg/sql/catalog/descpb/structured.go +++ b/pkg/sql/catalog/descpb/structured.go @@ -306,6 +306,22 @@ func (opts *TableDescriptor_SequenceOpts) HasOwner() bool { return !opts.SequenceOwner.Equal(TableDescriptor_SequenceOpts_SequenceOwner{}) } +// EffectiveCacheSize returns the CacheSize field of a sequence option with +// the exception that it will return 1 if the CacheSize field is 0. +// A cache size of 1 indicates that there is no caching. The returned value +// will always be greater than or equal to 1. +// +// Prior to #51259, sequence caching was unimplemented and cache sizes were +// left uninitialized (ie. to have a value of 0). If a sequence has a cache +// size of 0, it should be treated in the same was as sequences with cache +// sizes of 1. +func (opts *TableDescriptor_SequenceOpts) EffectiveCacheSize() int64 { + if opts.CacheSize == 0 { + return 1 + } + return opts.CacheSize +} + // SafeValue implements the redact.SafeValue interface. func (ConstraintValidity) SafeValue() {} diff --git a/pkg/sql/catalog/descpb/structured.pb.go b/pkg/sql/catalog/descpb/structured.pb.go index 1c3ac904240e..d4dc92e6a587 100644 --- a/pkg/sql/catalog/descpb/structured.pb.go +++ b/pkg/sql/catalog/descpb/structured.pb.go @@ -76,7 +76,7 @@ func (x *ConstraintValidity) UnmarshalJSON(data []byte) error { return nil } func (ConstraintValidity) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{0} } // SystemColumnKind is an enum representing the different kind of system @@ -121,7 +121,7 @@ func (x *SystemColumnKind) UnmarshalJSON(data []byte) error { return nil } func (SystemColumnKind) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{1} } // State indicates whether a descriptor is public (i.e., normally visible, @@ -173,7 +173,7 @@ func (x *DescriptorState) UnmarshalJSON(data []byte) error { return nil } func (DescriptorState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{2} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{2} } type ForeignKeyReference_Action int32 @@ -218,7 +218,7 @@ func (x *ForeignKeyReference_Action) UnmarshalJSON(data []byte) error { return nil } func (ForeignKeyReference_Action) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{0, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{0, 0} } // Match is the algorithm used to compare composite keys. @@ -258,7 +258,7 @@ func (x *ForeignKeyReference_Match) UnmarshalJSON(data []byte) error { return nil } func (ForeignKeyReference_Match) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{0, 1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{0, 1} } // The direction of a column in the index. @@ -295,7 +295,7 @@ func (x *IndexDescriptor_Direction) UnmarshalJSON(data []byte) error { return nil } func (IndexDescriptor_Direction) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{7, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{7, 0} } // The type of the index. @@ -332,7 +332,7 @@ func (x *IndexDescriptor_Type) UnmarshalJSON(data []byte) error { return nil } func (IndexDescriptor_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{7, 1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{7, 1} } type ConstraintToUpdate_ConstraintType int32 @@ -375,7 +375,7 @@ func (x *ConstraintToUpdate_ConstraintType) UnmarshalJSON(data []byte) error { return nil } func (ConstraintToUpdate_ConstraintType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{8, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{8, 0} } // A descriptor within a mutation is unavailable for reads, writes @@ -440,7 +440,7 @@ func (x *DescriptorMutation_State) UnmarshalJSON(data []byte) error { return nil } func (DescriptorMutation_State) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{12, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{12, 0} } // Direction of mutation. @@ -483,7 +483,7 @@ func (x *DescriptorMutation_Direction) UnmarshalJSON(data []byte) error { return nil } func (DescriptorMutation_Direction) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{12, 1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{12, 1} } // AuditMode indicates which auditing actions to take when this table is used. @@ -520,7 +520,7 @@ func (x *TableDescriptor_AuditMode) UnmarshalJSON(data []byte) error { return nil } func (TableDescriptor_AuditMode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 0} } // Represents the kind of type that this type descriptor represents. @@ -560,7 +560,7 @@ func (x *TypeDescriptor_Kind) UnmarshalJSON(data []byte) error { return nil } func (TypeDescriptor_Kind) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{16, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{16, 0} } // Represents what operations are allowed on this ENUM member. @@ -601,7 +601,7 @@ func (x *TypeDescriptor_EnumMember_Capability) UnmarshalJSON(data []byte) error return nil } func (TypeDescriptor_EnumMember_Capability) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{16, 0, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{16, 0, 0} } // ForeignKeyReference is deprecated, replaced by ForeignKeyConstraint in v19.2 @@ -631,7 +631,7 @@ func (m *ForeignKeyReference) Reset() { *m = ForeignKeyReference{} } func (m *ForeignKeyReference) String() string { return proto.CompactTextString(m) } func (*ForeignKeyReference) ProtoMessage() {} func (*ForeignKeyReference) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{0} } func (m *ForeignKeyReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -679,7 +679,7 @@ func (m *ForeignKeyConstraint) Reset() { *m = ForeignKeyConstraint{} } func (m *ForeignKeyConstraint) String() string { return proto.CompactTextString(m) } func (*ForeignKeyConstraint) ProtoMessage() {} func (*ForeignKeyConstraint) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{1} } func (m *ForeignKeyConstraint) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -744,7 +744,7 @@ func (m *ColumnDescriptor) Reset() { *m = ColumnDescriptor{} } func (m *ColumnDescriptor) String() string { return proto.CompactTextString(m) } func (*ColumnDescriptor) ProtoMessage() {} func (*ColumnDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{2} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{2} } func (m *ColumnDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -800,7 +800,7 @@ func (m *ColumnFamilyDescriptor) Reset() { *m = ColumnFamilyDescriptor{} func (m *ColumnFamilyDescriptor) String() string { return proto.CompactTextString(m) } func (*ColumnFamilyDescriptor) ProtoMessage() {} func (*ColumnFamilyDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{3} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{3} } func (m *ColumnFamilyDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -846,7 +846,7 @@ func (m *InterleaveDescriptor) Reset() { *m = InterleaveDescriptor{} } func (m *InterleaveDescriptor) String() string { return proto.CompactTextString(m) } func (*InterleaveDescriptor) ProtoMessage() {} func (*InterleaveDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{4} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{4} } func (m *InterleaveDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -890,7 +890,7 @@ func (m *InterleaveDescriptor_Ancestor) Reset() { *m = InterleaveDescrip func (m *InterleaveDescriptor_Ancestor) String() string { return proto.CompactTextString(m) } func (*InterleaveDescriptor_Ancestor) ProtoMessage() {} func (*InterleaveDescriptor_Ancestor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{4, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{4, 0} } func (m *InterleaveDescriptor_Ancestor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -945,7 +945,7 @@ func (m *ShardedDescriptor) Reset() { *m = ShardedDescriptor{} } func (m *ShardedDescriptor) String() string { return proto.CompactTextString(m) } func (*ShardedDescriptor) ProtoMessage() {} func (*ShardedDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{5} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{5} } func (m *ShardedDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -990,7 +990,7 @@ func (m *PartitioningDescriptor) Reset() { *m = PartitioningDescriptor{} func (m *PartitioningDescriptor) String() string { return proto.CompactTextString(m) } func (*PartitioningDescriptor) ProtoMessage() {} func (*PartitioningDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{6} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{6} } func (m *PartitioningDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1033,7 +1033,7 @@ func (m *PartitioningDescriptor_List) Reset() { *m = PartitioningDescrip func (m *PartitioningDescriptor_List) String() string { return proto.CompactTextString(m) } func (*PartitioningDescriptor_List) ProtoMessage() {} func (*PartitioningDescriptor_List) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{6, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{6, 0} } func (m *PartitioningDescriptor_List) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1078,7 +1078,7 @@ func (m *PartitioningDescriptor_Range) Reset() { *m = PartitioningDescri func (m *PartitioningDescriptor_Range) String() string { return proto.CompactTextString(m) } func (*PartitioningDescriptor_Range) ProtoMessage() {} func (*PartitioningDescriptor_Range) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{6, 1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{6, 1} } func (m *PartitioningDescriptor_Range) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1242,7 +1242,7 @@ func (m *IndexDescriptor) Reset() { *m = IndexDescriptor{} } func (m *IndexDescriptor) String() string { return proto.CompactTextString(m) } func (*IndexDescriptor) ProtoMessage() {} func (*IndexDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{7} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{7} } func (m *IndexDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1293,7 +1293,7 @@ func (m *ConstraintToUpdate) Reset() { *m = ConstraintToUpdate{} } func (m *ConstraintToUpdate) String() string { return proto.CompactTextString(m) } func (*ConstraintToUpdate) ProtoMessage() {} func (*ConstraintToUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{8} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{8} } func (m *ConstraintToUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1336,7 +1336,7 @@ func (m *PrimaryKeySwap) Reset() { *m = PrimaryKeySwap{} } func (m *PrimaryKeySwap) String() string { return proto.CompactTextString(m) } func (*PrimaryKeySwap) ProtoMessage() {} func (*PrimaryKeySwap) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{9} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{9} } func (m *PrimaryKeySwap) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1376,7 +1376,7 @@ func (m *ComputedColumnSwap) Reset() { *m = ComputedColumnSwap{} } func (m *ComputedColumnSwap) String() string { return proto.CompactTextString(m) } func (*ComputedColumnSwap) ProtoMessage() {} func (*ComputedColumnSwap) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{10} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{10} } func (m *ComputedColumnSwap) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1424,7 +1424,7 @@ func (m *MaterializedViewRefresh) Reset() { *m = MaterializedViewRefresh func (m *MaterializedViewRefresh) String() string { return proto.CompactTextString(m) } func (*MaterializedViewRefresh) ProtoMessage() {} func (*MaterializedViewRefresh) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{11} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{11} } func (m *MaterializedViewRefresh) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1481,7 +1481,7 @@ func (m *DescriptorMutation) Reset() { *m = DescriptorMutation{} } func (m *DescriptorMutation) String() string { return proto.CompactTextString(m) } func (*DescriptorMutation) ProtoMessage() {} func (*DescriptorMutation) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{12} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{12} } func (m *DescriptorMutation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1819,7 +1819,7 @@ func (m *NameInfo) Reset() { *m = NameInfo{} } func (m *NameInfo) String() string { return proto.CompactTextString(m) } func (*NameInfo) ProtoMessage() {} func (*NameInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{13} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{13} } func (m *NameInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2001,7 +2001,7 @@ func (m *TableDescriptor) Reset() { *m = TableDescriptor{} } func (m *TableDescriptor) String() string { return proto.CompactTextString(m) } func (*TableDescriptor) ProtoMessage() {} func (*TableDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14} } func (m *TableDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2308,7 +2308,7 @@ func (m *TableDescriptor_SchemaChangeLease) Reset() { *m = TableDescript func (m *TableDescriptor_SchemaChangeLease) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_SchemaChangeLease) ProtoMessage() {} func (*TableDescriptor_SchemaChangeLease) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 0} } func (m *TableDescriptor_SchemaChangeLease) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2354,7 +2354,7 @@ func (m *TableDescriptor_CheckConstraint) Reset() { *m = TableDescriptor func (m *TableDescriptor_CheckConstraint) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_CheckConstraint) ProtoMessage() {} func (*TableDescriptor_CheckConstraint) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 1} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 1} } func (m *TableDescriptor_CheckConstraint) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2394,7 +2394,7 @@ func (m *TableDescriptor_Reference) Reset() { *m = TableDescriptor_Refer func (m *TableDescriptor_Reference) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_Reference) ProtoMessage() {} func (*TableDescriptor_Reference) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 2} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 2} } func (m *TableDescriptor_Reference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2431,7 +2431,7 @@ func (m *TableDescriptor_MutationJob) Reset() { *m = TableDescriptor_Mut func (m *TableDescriptor_MutationJob) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_MutationJob) ProtoMessage() {} func (*TableDescriptor_MutationJob) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 3} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 3} } func (m *TableDescriptor_MutationJob) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2468,13 +2468,16 @@ type TableDescriptor_SequenceOpts struct { // Whether the sequence is virtual. Virtual bool `protobuf:"varint,5,opt,name=virtual" json:"virtual"` SequenceOwner TableDescriptor_SequenceOpts_SequenceOwner `protobuf:"bytes,6,opt,name=sequence_owner,json=sequenceOwner" json:"sequence_owner"` + // The number of values (which have already been created in KV) + // that a node can cache locally. + CacheSize int64 `protobuf:"varint,7,opt,name=cache_size,json=cacheSize" json:"cache_size"` } func (m *TableDescriptor_SequenceOpts) Reset() { *m = TableDescriptor_SequenceOpts{} } func (m *TableDescriptor_SequenceOpts) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_SequenceOpts) ProtoMessage() {} func (*TableDescriptor_SequenceOpts) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 4} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 4} } func (m *TableDescriptor_SequenceOpts) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2514,7 +2517,7 @@ func (m *TableDescriptor_SequenceOpts_SequenceOwner) String() string { } func (*TableDescriptor_SequenceOpts_SequenceOwner) ProtoMessage() {} func (*TableDescriptor_SequenceOpts_SequenceOwner) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 4, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 4, 0} } func (m *TableDescriptor_SequenceOpts_SequenceOwner) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2554,7 +2557,7 @@ func (m *TableDescriptor_Replacement) Reset() { *m = TableDescriptor_Rep func (m *TableDescriptor_Replacement) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_Replacement) ProtoMessage() {} func (*TableDescriptor_Replacement) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 5} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 5} } func (m *TableDescriptor_Replacement) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2591,7 +2594,7 @@ func (m *TableDescriptor_GCDescriptorMutation) Reset() { *m = TableDescr func (m *TableDescriptor_GCDescriptorMutation) String() string { return proto.CompactTextString(m) } func (*TableDescriptor_GCDescriptorMutation) ProtoMessage() {} func (*TableDescriptor_GCDescriptorMutation) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{14, 6} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{14, 6} } func (m *TableDescriptor_GCDescriptorMutation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2640,7 +2643,7 @@ func (m *DatabaseDescriptor) Reset() { *m = DatabaseDescriptor{} } func (m *DatabaseDescriptor) String() string { return proto.CompactTextString(m) } func (*DatabaseDescriptor) ProtoMessage() {} func (*DatabaseDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{15} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{15} } func (m *DatabaseDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2741,7 +2744,7 @@ func (m *DatabaseDescriptor_SchemaInfo) Reset() { *m = DatabaseDescripto func (m *DatabaseDescriptor_SchemaInfo) String() string { return proto.CompactTextString(m) } func (*DatabaseDescriptor_SchemaInfo) ProtoMessage() {} func (*DatabaseDescriptor_SchemaInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{15, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{15, 0} } func (m *DatabaseDescriptor_SchemaInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2803,7 +2806,7 @@ func (m *TypeDescriptor) Reset() { *m = TypeDescriptor{} } func (m *TypeDescriptor) String() string { return proto.CompactTextString(m) } func (*TypeDescriptor) ProtoMessage() {} func (*TypeDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{16} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{16} } func (m *TypeDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2944,7 +2947,7 @@ func (m *TypeDescriptor_EnumMember) Reset() { *m = TypeDescriptor_EnumMe func (m *TypeDescriptor_EnumMember) String() string { return proto.CompactTextString(m) } func (*TypeDescriptor_EnumMember) ProtoMessage() {} func (*TypeDescriptor_EnumMember) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{16, 0} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{16, 0} } func (m *TypeDescriptor_EnumMember) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2992,7 +2995,7 @@ func (m *SchemaDescriptor) Reset() { *m = SchemaDescriptor{} } func (m *SchemaDescriptor) String() string { return proto.CompactTextString(m) } func (*SchemaDescriptor) ProtoMessage() {} func (*SchemaDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{17} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{17} } func (m *SchemaDescriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3095,7 +3098,7 @@ func (m *Descriptor) Reset() { *m = Descriptor{} } func (m *Descriptor) String() string { return proto.CompactTextString(m) } func (*Descriptor) ProtoMessage() {} func (*Descriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_structured_7058934a8610dc30, []int{18} + return fileDescriptor_structured_4b060b458c5e4b4c, []int{18} } func (m *Descriptor) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4633,6 +4636,9 @@ func (this *TableDescriptor_SequenceOpts) Equal(that interface{}) bool { if !this.SequenceOwner.Equal(&that1.SequenceOwner) { return false } + if this.CacheSize != that1.CacheSize { + return false + } return true } func (this *TableDescriptor_SequenceOpts_SequenceOwner) Equal(that interface{}) bool { @@ -6595,6 +6601,9 @@ func (m *TableDescriptor_SequenceOpts) MarshalTo(dAtA []byte) (int, error) { return 0, err } i += n26 + dAtA[i] = 0x38 + i++ + i = encodeVarintStructured(dAtA, i, uint64(m.CacheSize)) return i, nil } @@ -7758,6 +7767,7 @@ func (m *TableDescriptor_SequenceOpts) Size() (n int) { n += 2 l = m.SequenceOwner.Size() n += 1 + l + sovStructured(uint64(l)) + n += 1 + sovStructured(uint64(m.CacheSize)) return n } @@ -13784,6 +13794,25 @@ func (m *TableDescriptor_SequenceOpts) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CacheSize", wireType) + } + m.CacheSize = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStructured + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CacheSize |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipStructured(dAtA[iNdEx:]) @@ -15733,298 +15762,299 @@ var ( ) func init() { - proto.RegisterFile("sql/catalog/descpb/structured.proto", fileDescriptor_structured_7058934a8610dc30) + proto.RegisterFile("sql/catalog/descpb/structured.proto", fileDescriptor_structured_4b060b458c5e4b4c) } -var fileDescriptor_structured_7058934a8610dc30 = []byte{ - // 4611 bytes of a gzipped FileDescriptorProto +var fileDescriptor_structured_4b060b458c5e4b4c = []byte{ + // 4632 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x4b, 0x6c, 0x1b, 0x67, 0x7a, 0xe2, 0x9b, 0xfc, 0xf8, 0x1a, 0xfd, 0x96, 0x6d, 0x5a, 0x49, 0x24, 0x99, 0x8e, 0x13, 0x25, 0xd9, 0x48, 0x8e, 0xbc, 0xdd, 0xf5, 0x26, 0xcd, 0x22, 0x14, 0x49, 0x59, 0xd4, 0x83, 0x54, 0x46, 0xb2, 0x9d, 0xed, 0xb6, 0x9d, 0x1d, 0x71, 0x7e, 0x52, 0x13, 0x0f, 0x67, 0xe8, 0x99, 0xa1, 0x2d, - 0x16, 0x3d, 0xf5, 0x54, 0x14, 0x45, 0x1f, 0x87, 0x1e, 0x8b, 0x06, 0x45, 0x80, 0xee, 0xad, 0xd8, - 0x4b, 0x7b, 0x2b, 0xd0, 0x4b, 0x91, 0x5b, 0xb7, 0xb7, 0x3d, 0x09, 0xad, 0x72, 0xe9, 0xb5, 0x97, - 0x16, 0xc8, 0xa9, 0xf8, 0x5f, 0xf3, 0xe0, 0x43, 0xa6, 0xa4, 0xb4, 0x07, 0x1b, 0x9c, 0xef, 0xf5, - 0xbf, 0xbe, 0xf7, 0xff, 0x0b, 0xee, 0x39, 0x2f, 0x8c, 0xf5, 0xb6, 0xea, 0xaa, 0x86, 0xd5, 0x5d, - 0xd7, 0xb0, 0xd3, 0xee, 0x1f, 0xaf, 0x3b, 0xae, 0x3d, 0x68, 0xbb, 0x03, 0x1b, 0x6b, 0x6b, 0x7d, - 0xdb, 0x72, 0x2d, 0x74, 0xb3, 0x6d, 0xb5, 0x9f, 0xdb, 0x96, 0xda, 0x3e, 0x59, 0x73, 0x5e, 0x18, - 0xe4, 0xdf, 0xb1, 0xea, 0xe0, 0xc5, 0xd2, 0xc0, 0xd5, 0x8d, 0xf5, 0x13, 0xa3, 0xbd, 0xee, 0xea, - 0x3d, 0xec, 0xb8, 0x6a, 0xaf, 0xcf, 0x18, 0x16, 0xcb, 0x13, 0xa4, 0xf6, 0x6d, 0xfd, 0xa5, 0x6e, - 0xe0, 0x2e, 0xe6, 0x34, 0x37, 0x09, 0x8d, 0x3b, 0xec, 0x63, 0x87, 0xfd, 0xcf, 0xc1, 0x77, 0xba, - 0xd8, 0x5a, 0xef, 0x62, 0x4b, 0x37, 0x35, 0x7c, 0xba, 0xde, 0xb6, 0xcc, 0x8e, 0xde, 0xe5, 0xa8, - 0x85, 0xae, 0xd5, 0xb5, 0xe8, 0xcf, 0x75, 0xf2, 0x8b, 0x41, 0xcb, 0x7f, 0x94, 0x80, 0x1b, 0x5b, - 0x96, 0x8d, 0xf5, 0xae, 0xb9, 0x8b, 0x87, 0x32, 0xee, 0x60, 0x1b, 0x9b, 0x6d, 0x8c, 0x56, 0x20, - 0xe1, 0xaa, 0xc7, 0x06, 0x2e, 0x45, 0x56, 0x22, 0xab, 0xf9, 0x4d, 0xf8, 0xe6, 0x6c, 0x79, 0xee, - 0xbb, 0xb3, 0xe5, 0x68, 0xa3, 0x26, 0x33, 0x04, 0xba, 0x0f, 0x09, 0x3a, 0x4a, 0x29, 0x4a, 0x29, - 0x8a, 0x9c, 0x22, 0xd5, 0x20, 0x40, 0x42, 0x46, 0xb1, 0xa8, 0x04, 0x71, 0x53, 0xed, 0xe1, 0x52, - 0x6c, 0x25, 0xb2, 0x9a, 0xd9, 0x8c, 0x13, 0x2a, 0x99, 0x42, 0xd0, 0x2e, 0xa4, 0x5f, 0xaa, 0x86, - 0xae, 0xe9, 0xee, 0xb0, 0x14, 0x5f, 0x89, 0xac, 0x16, 0x36, 0xde, 0x5b, 0x9b, 0xb8, 0x55, 0x6b, - 0x55, 0xcb, 0x74, 0x5c, 0x5b, 0xd5, 0x4d, 0xf7, 0x29, 0x67, 0xe0, 0x82, 0x3c, 0x01, 0xe8, 0x01, - 0xcc, 0x3b, 0x27, 0xaa, 0x8d, 0x35, 0xa5, 0x6f, 0xe3, 0x8e, 0x7e, 0xaa, 0x18, 0xd8, 0x2c, 0x25, - 0x56, 0x22, 0xab, 0x09, 0x4e, 0x5a, 0x64, 0xe8, 0x03, 0x8a, 0xdd, 0xc3, 0x26, 0x3a, 0x82, 0x8c, - 0x65, 0x2a, 0x1a, 0x36, 0xb0, 0x8b, 0x4b, 0x49, 0x3a, 0xfe, 0x47, 0x53, 0xc6, 0x9f, 0xb0, 0x41, - 0x6b, 0x95, 0xb6, 0xab, 0x5b, 0xa6, 0x98, 0x87, 0x65, 0xd6, 0xa8, 0x20, 0x2e, 0x75, 0xd0, 0xd7, - 0x54, 0x17, 0x97, 0x52, 0xd7, 0x96, 0xfa, 0x84, 0x0a, 0x42, 0x7b, 0x90, 0xe8, 0xa9, 0x6e, 0xfb, - 0xa4, 0x94, 0xa6, 0x12, 0x1f, 0x5c, 0x42, 0xe2, 0x3e, 0xe1, 0xe3, 0x02, 0x99, 0x90, 0xf2, 0x33, - 0x48, 0xb2, 0x71, 0x50, 0x1e, 0x32, 0xcd, 0x96, 0x52, 0xa9, 0x1e, 0x35, 0x5a, 0x4d, 0x69, 0x0e, - 0xe5, 0x20, 0x2d, 0xd7, 0x0f, 0x8f, 0xe4, 0x46, 0xf5, 0x48, 0x8a, 0x90, 0xaf, 0xc3, 0xfa, 0x91, - 0xd2, 0x7c, 0xb2, 0xb7, 0x27, 0x45, 0x51, 0x11, 0xb2, 0xe4, 0xab, 0x56, 0xdf, 0xaa, 0x3c, 0xd9, - 0x3b, 0x92, 0x62, 0x28, 0x0b, 0xa9, 0x6a, 0xe5, 0xb0, 0x5a, 0xa9, 0xd5, 0xa5, 0xf8, 0x62, 0xfc, - 0x97, 0x5f, 0x2f, 0xcd, 0x95, 0x1f, 0x40, 0x82, 0x0e, 0x87, 0x00, 0x92, 0x87, 0x8d, 0xfd, 0x83, - 0xbd, 0xba, 0x34, 0x87, 0xd2, 0x10, 0xdf, 0x22, 0x22, 0x22, 0x84, 0xe3, 0xa0, 0x22, 0x1f, 0x35, - 0x2a, 0x7b, 0x52, 0x94, 0x71, 0x7c, 0x1c, 0xff, 0xcf, 0xaf, 0x96, 0x23, 0xe5, 0x7f, 0x4b, 0xc0, - 0x82, 0x3f, 0x77, 0xff, 0xb4, 0x51, 0x15, 0x8a, 0x96, 0xad, 0x77, 0x75, 0x53, 0xa1, 0x3a, 0xa7, - 0xe8, 0x1a, 0xd7, 0xc7, 0x37, 0xc8, 0x7a, 0xce, 0xcf, 0x96, 0xf3, 0x2d, 0x8a, 0x3e, 0x22, 0xd8, - 0x46, 0x8d, 0x2b, 0x68, 0xde, 0x0a, 0x00, 0x35, 0xb4, 0x0b, 0xf3, 0x5c, 0x48, 0xdb, 0x32, 0x06, - 0x3d, 0x53, 0xd1, 0x35, 0xa7, 0x14, 0x5d, 0x89, 0xad, 0xe6, 0x37, 0x97, 0xcf, 0xcf, 0x96, 0x8b, - 0x4c, 0x44, 0x95, 0xe2, 0x1a, 0x35, 0xe7, 0xbb, 0xb3, 0xe5, 0xb4, 0xf8, 0x90, 0xf9, 0xf0, 0xfc, - 0x5b, 0x73, 0xd0, 0x33, 0xb8, 0x69, 0x8b, 0xbd, 0xd5, 0x82, 0x02, 0x63, 0x54, 0xe0, 0xbd, 0xf3, - 0xb3, 0xe5, 0x1b, 0xde, 0xe6, 0x6b, 0x93, 0x85, 0xde, 0xb0, 0x47, 0x09, 0x34, 0x07, 0xb5, 0x20, - 0x00, 0xf6, 0x97, 0x1b, 0xa7, 0xcb, 0x5d, 0xe6, 0xcb, 0x9d, 0xf7, 0x45, 0x87, 0x97, 0x3c, 0x6f, - 0x8f, 0x20, 0x34, 0xcf, 0xf0, 0x12, 0x17, 0x1a, 0x5e, 0xf2, 0xba, 0x86, 0x17, 0x32, 0xa3, 0xd4, - 0xff, 0x89, 0x19, 0xa5, 0xbf, 0x77, 0x33, 0xca, 0x7c, 0x0f, 0x66, 0xc4, 0x74, 0x77, 0x27, 0x9e, - 0x06, 0x29, 0xbb, 0x13, 0x4f, 0x67, 0xa5, 0xdc, 0x4e, 0x3c, 0x9d, 0x93, 0xf2, 0x3b, 0xf1, 0x74, - 0x5e, 0x2a, 0x94, 0xff, 0x2b, 0x0e, 0x12, 0x3b, 0xdd, 0x1a, 0x76, 0xda, 0xb6, 0xde, 0x77, 0x2d, - 0xdb, 0x3b, 0x93, 0xc8, 0xd8, 0x99, 0xbc, 0x03, 0x51, 0x5d, 0xe3, 0xae, 0xf4, 0x16, 0x3f, 0xed, - 0x28, 0x3d, 0x5e, 0x5f, 0x6f, 0xa2, 0xba, 0x86, 0xd6, 0x20, 0x4e, 0xfc, 0x3d, 0x75, 0xa7, 0xd9, - 0x8d, 0xc5, 0xd1, 0x15, 0xe0, 0xde, 0x1a, 0x0b, 0x07, 0x47, 0x32, 0xa5, 0x43, 0x2b, 0x90, 0x36, - 0x07, 0x86, 0x41, 0x5d, 0x39, 0xd1, 0xa5, 0xb4, 0xd8, 0x14, 0x01, 0x45, 0x77, 0x21, 0xa7, 0xe1, - 0x8e, 0x3a, 0x30, 0x5c, 0x05, 0x9f, 0xf6, 0x6d, 0xa6, 0x2f, 0x72, 0x96, 0xc3, 0xea, 0xa7, 0x7d, - 0x1b, 0xbd, 0x09, 0xc9, 0x13, 0x5d, 0xd3, 0xb0, 0x49, 0xd5, 0x45, 0x88, 0xe0, 0x30, 0xb4, 0x01, - 0xf3, 0x03, 0x07, 0x3b, 0x8a, 0x83, 0x5f, 0x0c, 0xc8, 0x5e, 0x51, 0x73, 0x00, 0x6a, 0x0e, 0x49, - 0xae, 0x9e, 0x45, 0x42, 0x70, 0xc8, 0xf1, 0x44, 0xdb, 0xef, 0x42, 0xae, 0x6d, 0xf5, 0xfa, 0x03, - 0x17, 0xb3, 0x41, 0xb3, 0x6c, 0x50, 0x0e, 0xa3, 0x83, 0x6e, 0xc0, 0xbc, 0xf5, 0xca, 0x1c, 0x11, - 0x9b, 0x0b, 0x8b, 0x25, 0x04, 0x41, 0xb1, 0x9f, 0x81, 0xd4, 0xef, 0x2a, 0xaa, 0xeb, 0xda, 0xfa, - 0x31, 0x91, 0x6d, 0x0e, 0x7a, 0xa5, 0x7c, 0x68, 0x4f, 0x0b, 0x07, 0x8f, 0x2b, 0x02, 0xdd, 0x1c, - 0xf4, 0xe4, 0x42, 0xbf, 0x1b, 0xfc, 0x46, 0x5b, 0xf0, 0x96, 0x6a, 0xb8, 0xd8, 0x16, 0xa6, 0x4d, - 0x36, 0x51, 0xd1, 0x4d, 0xa5, 0x6f, 0x5b, 0x5d, 0x1b, 0x3b, 0x4e, 0xa9, 0x10, 0xd8, 0x81, 0x3b, - 0x94, 0x94, 0x9d, 0xcf, 0xd1, 0xb0, 0x8f, 0x1b, 0xe6, 0x01, 0x27, 0x43, 0x3f, 0x07, 0xe4, 0x0c, - 0x1d, 0x17, 0xf7, 0x84, 0xa0, 0xe7, 0xba, 0xa9, 0x95, 0x8a, 0x54, 0xef, 0xde, 0x9d, 0xa2, 0x77, - 0x87, 0x94, 0x81, 0x89, 0xdb, 0xd5, 0x4d, 0x8d, 0x8f, 0x22, 0x39, 0x23, 0x70, 0x4f, 0xf3, 0xd2, - 0x52, 0x66, 0x27, 0x9e, 0xce, 0x48, 0xb0, 0x13, 0x4f, 0xa7, 0xa4, 0x74, 0xf9, 0xcf, 0xa2, 0x70, - 0x8b, 0x91, 0x6d, 0xa9, 0x3d, 0xdd, 0x18, 0x5e, 0x57, 0xf3, 0x98, 0x14, 0xae, 0x79, 0xf4, 0xc8, - 0xe8, 0x52, 0x08, 0x1b, 0x73, 0x78, 0xf4, 0xc8, 0x08, 0xac, 0x49, 0x40, 0xe8, 0x11, 0x40, 0xc0, - 0x23, 0xc6, 0xe9, 0x59, 0xdd, 0x39, 0x3f, 0x5b, 0xce, 0x4c, 0xf6, 0x83, 0x99, 0x76, 0xc0, 0xfb, - 0xcd, 0x0b, 0x25, 0xf4, 0x24, 0x50, 0x4d, 0xcc, 0x6f, 0xde, 0xe3, 0x73, 0x2a, 0xd6, 0x18, 0x81, - 0x60, 0x0f, 0xfb, 0x69, 0x2d, 0x84, 0xe4, 0x5b, 0x54, 0xfe, 0xc7, 0x28, 0x2c, 0x34, 0x4c, 0x17, - 0xdb, 0x06, 0x56, 0x5f, 0xe2, 0xc0, 0x76, 0x7c, 0x01, 0x19, 0xd5, 0x6c, 0x63, 0xc7, 0xb5, 0x6c, - 0xa7, 0x14, 0x59, 0x89, 0xad, 0x66, 0x37, 0x7e, 0x38, 0xe5, 0x54, 0x26, 0xf1, 0xaf, 0x55, 0x38, - 0x33, 0xdf, 0x49, 0x5f, 0xd8, 0xe2, 0x3f, 0x45, 0x20, 0x2d, 0xb0, 0xe8, 0x01, 0xa4, 0x47, 0x02, - 0xd7, 0x4d, 0xbe, 0x9a, 0x54, 0xd8, 0x7f, 0xa7, 0x5c, 0xee, 0xb5, 0x7f, 0x0b, 0xd2, 0x34, 0x6f, - 0x52, 0xbc, 0x33, 0x59, 0x14, 0x1c, 0x3c, 0xb1, 0x0a, 0xe6, 0x58, 0x29, 0x4a, 0xdb, 0xd0, 0x50, - 0x75, 0x52, 0xfa, 0x13, 0xa3, 0xfc, 0xb7, 0xc5, 0xfe, 0x1d, 0x86, 0x13, 0xa0, 0xb1, 0x8c, 0x88, - 0xed, 0x19, 0xdf, 0xb9, 0x7f, 0x88, 0xc0, 0x3c, 0x61, 0xd0, 0xb0, 0x16, 0xd8, 0xb6, 0x7b, 0x00, - 0xba, 0xa3, 0x38, 0x0c, 0x4e, 0x57, 0x24, 0x4c, 0x21, 0xa3, 0x3b, 0x9c, 0xdc, 0x53, 0xb5, 0xe8, - 0x98, 0xaa, 0xfd, 0x04, 0xf2, 0x94, 0x57, 0x39, 0x1e, 0xb4, 0x9f, 0x63, 0xd7, 0xa1, 0x33, 0x4c, - 0x6c, 0x2e, 0xf0, 0x19, 0xe6, 0xa8, 0x84, 0x4d, 0x86, 0x93, 0x73, 0x4e, 0xe0, 0x6b, 0x4c, 0xfb, - 0xe2, 0x63, 0xda, 0xc7, 0x27, 0xfe, 0x3f, 0x31, 0xb8, 0x75, 0xa0, 0xda, 0xae, 0x4e, 0x22, 0x80, - 0x6e, 0x76, 0x03, 0xb3, 0xbf, 0x0f, 0x59, 0x73, 0x20, 0x0c, 0xd2, 0xe1, 0x07, 0xc2, 0xe6, 0x07, - 0xe6, 0x80, 0x1b, 0x98, 0x83, 0xf6, 0x20, 0x6e, 0xe8, 0x8e, 0x4b, 0x53, 0x84, 0xec, 0xc6, 0xc6, - 0x14, 0xb5, 0x98, 0x3c, 0xc6, 0xda, 0x9e, 0xee, 0xb8, 0x62, 0xcd, 0x44, 0x0a, 0x6a, 0x41, 0xc2, - 0x56, 0xcd, 0x2e, 0xa6, 0xf6, 0x92, 0xdd, 0x78, 0x78, 0x39, 0x71, 0x32, 0x61, 0x15, 0x61, 0x87, - 0xca, 0x59, 0xfc, 0xeb, 0x08, 0xc4, 0xc9, 0x28, 0x17, 0x98, 0xf4, 0x2d, 0x48, 0xbe, 0x54, 0x8d, - 0x01, 0x66, 0x69, 0x4e, 0x4e, 0xe6, 0x5f, 0xe8, 0xf7, 0xa0, 0xe8, 0x0c, 0x8e, 0xfb, 0x81, 0xa1, - 0x78, 0x1c, 0xf9, 0xf0, 0x52, 0xb3, 0xf2, 0x32, 0xea, 0xb0, 0x2c, 0x76, 0x00, 0x8b, 0x2f, 0x20, - 0x41, 0x67, 0x7d, 0xc1, 0xfc, 0xee, 0x42, 0xce, 0xb5, 0x14, 0x7c, 0xda, 0x36, 0x06, 0x8e, 0xfe, - 0x92, 0x69, 0x4a, 0x4e, 0xce, 0xba, 0x56, 0x5d, 0x80, 0xd0, 0x7d, 0x28, 0x74, 0x6c, 0xab, 0xa7, - 0xe8, 0xa6, 0x20, 0x8a, 0x51, 0xa2, 0x3c, 0x81, 0x36, 0x04, 0x30, 0xa4, 0xb2, 0x7f, 0x95, 0x83, - 0x22, 0x35, 0x8c, 0x99, 0xdc, 0xde, 0xfd, 0x80, 0xdb, 0xbb, 0x19, 0x72, 0x7b, 0x9e, 0x75, 0x11, - 0xaf, 0xf7, 0x26, 0x24, 0x07, 0xa6, 0xfe, 0x62, 0xc0, 0xc6, 0xf7, 0x42, 0x1f, 0x83, 0xcd, 0xa0, - 0x95, 0xe8, 0x07, 0x80, 0x88, 0x2b, 0xc0, 0x4a, 0x88, 0x30, 0x41, 0x09, 0x25, 0x8a, 0xa9, 0x4e, - 0xf5, 0xa0, 0xc9, 0x4b, 0x78, 0xd0, 0x6d, 0x90, 0xf0, 0xa9, 0x6b, 0xab, 0xc1, 0x9c, 0x34, 0x45, - 0xf9, 0x97, 0x48, 0xd8, 0xab, 0x13, 0xdc, 0x64, 0x21, 0x05, 0x1c, 0xc0, 0x69, 0x44, 0x4b, 0xe6, - 0xb9, 0x0c, 0x4d, 0xb7, 0x31, 0xcd, 0xa4, 0x9c, 0x52, 0x7a, 0x25, 0x76, 0x41, 0xc6, 0x34, 0xb2, - 0xed, 0x6b, 0x35, 0xc1, 0x28, 0x4b, 0x4c, 0x94, 0x07, 0x70, 0xd0, 0x21, 0x64, 0x3b, 0x2c, 0xc1, - 0x52, 0x9e, 0xe3, 0x21, 0x4d, 0xc5, 0xb2, 0x1b, 0xef, 0xcf, 0x9e, 0x8a, 0x6d, 0x26, 0xc9, 0x11, - 0x94, 0x22, 0x32, 0x74, 0x3c, 0x24, 0x7a, 0x06, 0xf9, 0x40, 0xf6, 0x7c, 0x3c, 0xa4, 0xf9, 0xc7, - 0xd5, 0xc4, 0xe6, 0x7c, 0x41, 0x9b, 0x43, 0xf4, 0x39, 0x80, 0xee, 0x05, 0x00, 0x9a, 0xa6, 0x64, - 0x37, 0x3e, 0xb8, 0x44, 0xa4, 0x10, 0xfe, 0xc5, 0x17, 0x82, 0x9e, 0x41, 0xc1, 0xff, 0xa2, 0x93, - 0xcd, 0x5d, 0x7a, 0xb2, 0x4c, 0x6a, 0x3e, 0x20, 0x67, 0x93, 0xa4, 0xe2, 0x0b, 0x24, 0x81, 0xb2, - 0x1c, 0xdd, 0xc5, 0x41, 0x35, 0xc8, 0x53, 0x35, 0x28, 0x9f, 0x9f, 0x2d, 0xa3, 0xaa, 0xc0, 0x4f, - 0x56, 0x05, 0xd4, 0x1e, 0xc1, 0x33, 0xc5, 0x0a, 0x29, 0x30, 0x91, 0x58, 0xf0, 0x15, 0xeb, 0xd0, - 0x57, 0xe1, 0x31, 0xc5, 0x0a, 0xa8, 0x37, 0xab, 0x9d, 0x72, 0x21, 0xdf, 0x53, 0xbc, 0xba, 0xef, - 0x09, 0x09, 0x42, 0x75, 0x9e, 0x14, 0x4b, 0x34, 0xbd, 0xfa, 0x60, 0x46, 0x25, 0x25, 0x19, 0x9b, - 0x70, 0x09, 0x34, 0x57, 0x7e, 0x08, 0xa8, 0x6d, 0x63, 0xd5, 0xc5, 0x1a, 0x49, 0x4a, 0x0d, 0xbd, - 0xad, 0xbb, 0xc6, 0xb0, 0x34, 0x1f, 0xb0, 0xfb, 0x79, 0x8e, 0xaf, 0x7b, 0x68, 0xf4, 0x08, 0x52, - 0x2f, 0xb1, 0xed, 0xe8, 0x96, 0x59, 0x42, 0xd4, 0x99, 0x2c, 0xf1, 0x46, 0xc8, 0xad, 0x91, 0xf1, - 0x9e, 0x32, 0x2a, 0x59, 0x90, 0xa3, 0x6d, 0xc8, 0x63, 0xb3, 0x6d, 0x69, 0xba, 0xd9, 0xa5, 0x69, - 0x66, 0xe9, 0x86, 0x9f, 0xef, 0x7c, 0x77, 0xb6, 0xfc, 0xc6, 0x08, 0x7f, 0x9d, 0xd3, 0x92, 0x69, - 0xcb, 0x39, 0x1c, 0xf8, 0x42, 0xdb, 0x90, 0x12, 0x31, 0x79, 0x81, 0xee, 0xe9, 0xea, 0xb4, 0x0c, - 0x73, 0x34, 0xa2, 0xf3, 0x75, 0x09, 0x76, 0x52, 0x2e, 0x68, 0xba, 0x43, 0x72, 0x11, 0xad, 0x74, - 0x33, 0x58, 0x2e, 0x08, 0x28, 0xaa, 0x02, 0x74, 0xb1, 0xa5, 0xb0, 0xd6, 0x52, 0xe9, 0x16, 0x1d, - 0x6e, 0x29, 0x30, 0x5c, 0x17, 0x5b, 0x6b, 0xa2, 0x01, 0x45, 0xea, 0xc7, 0x8e, 0xde, 0x15, 0x29, - 0x42, 0x17, 0x5b, 0x0c, 0x80, 0xca, 0x90, 0xe9, 0xdb, 0x58, 0xd3, 0xdb, 0xa4, 0xbc, 0xbb, 0x1d, - 0xf0, 0xcd, 0x3e, 0xb8, 0xbc, 0x04, 0x19, 0xcf, 0x6b, 0xa0, 0x14, 0xc4, 0x2a, 0x87, 0x55, 0xd6, - 0x4d, 0xa8, 0xd5, 0x0f, 0xab, 0x52, 0xa4, 0x7c, 0x17, 0xe2, 0x74, 0xf1, 0x59, 0x48, 0x6d, 0xb5, - 0xe4, 0x67, 0x15, 0xb9, 0xc6, 0x3a, 0x18, 0x8d, 0xe6, 0xd3, 0xba, 0x7c, 0x54, 0xaf, 0x49, 0x22, - 0x2e, 0xfc, 0x73, 0x0c, 0x90, 0x5f, 0xc8, 0x1e, 0x59, 0xbc, 0x18, 0xec, 0x42, 0xb1, 0xed, 0x41, - 0xd9, 0x01, 0x44, 0x56, 0xa2, 0xab, 0x85, 0x8d, 0x47, 0xaf, 0x2d, 0x86, 0x85, 0x8c, 0x20, 0xc8, - 0x57, 0xa6, 0x42, 0x3b, 0x04, 0x0d, 0xe4, 0x43, 0xd1, 0x91, 0x18, 0x24, 0x43, 0xa2, 0x7d, 0x82, - 0xdb, 0xcf, 0x79, 0x14, 0xfe, 0xd1, 0x94, 0x81, 0x69, 0xaa, 0x18, 0x50, 0xdc, 0x2a, 0xe1, 0xf1, - 0x87, 0x16, 0xe9, 0x01, 0x15, 0x85, 0xe4, 0xb0, 0x7b, 0x8d, 0x5f, 0xe8, 0xb1, 0x26, 0x35, 0x5d, - 0x84, 0xc7, 0x0a, 0x78, 0xd7, 0x47, 0x50, 0x34, 0x2d, 0x57, 0x21, 0x25, 0x23, 0xf7, 0x02, 0xb4, - 0x10, 0xcc, 0x6f, 0x4a, 0x5c, 0x57, 0x7d, 0x9b, 0xcf, 0x9b, 0x96, 0xdb, 0x1c, 0x18, 0x06, 0x03, - 0x94, 0x3f, 0x86, 0x42, 0x78, 0x8f, 0x50, 0x06, 0x12, 0xd5, 0xed, 0x7a, 0x75, 0x57, 0x9a, 0x43, - 0x45, 0xc8, 0x6e, 0xb5, 0xe4, 0x7a, 0xe3, 0x71, 0x53, 0xd9, 0xad, 0xff, 0x8c, 0x75, 0x9c, 0x9a, - 0x2d, 0xd1, 0x71, 0xf2, 0xaa, 0x9c, 0x84, 0x94, 0x2c, 0xff, 0x77, 0x04, 0x0a, 0x07, 0xb6, 0xde, - 0x53, 0xed, 0xe1, 0x2e, 0x1e, 0x1e, 0xbe, 0x52, 0xfb, 0xe8, 0x33, 0x58, 0x30, 0xf1, 0x2b, 0xa5, - 0xcf, 0xa0, 0x8a, 0x97, 0x35, 0x47, 0x26, 0xb7, 0x23, 0xe7, 0x4d, 0xfc, 0x8a, 0x4b, 0x68, 0xf0, - 0xa4, 0xf9, 0x07, 0x90, 0xb5, 0x0c, 0x8d, 0x71, 0x62, 0xd1, 0x12, 0xca, 0x06, 0x99, 0xc0, 0x32, - 0xb4, 0x06, 0x43, 0x13, 0x6a, 0x32, 0x9e, 0xa0, 0x8e, 0x4d, 0xa0, 0x36, 0xf1, 0x2b, 0x41, 0xfd, - 0x19, 0x2c, 0x10, 0xd9, 0x63, 0xb3, 0x8b, 0x4f, 0x99, 0x9d, 0x65, 0x68, 0xe1, 0xd9, 0x71, 0xe5, - 0xfd, 0xfb, 0x08, 0x50, 0xa7, 0x3d, 0x70, 0x45, 0xb3, 0x88, 0x2e, 0xfe, 0x87, 0x90, 0x27, 0x93, - 0xf1, 0x6b, 0xa5, 0xc8, 0x94, 0xf3, 0x20, 0x73, 0x16, 0x1e, 0x98, 0x70, 0x91, 0x49, 0xf9, 0x5c, - 0xd1, 0x69, 0x5c, 0x96, 0xe1, 0xb5, 0xa6, 0xd0, 0xbb, 0x90, 0xd3, 0x4d, 0xe2, 0xb4, 0x78, 0xad, - 0x1e, 0xec, 0xe4, 0x66, 0x39, 0x86, 0x54, 0xec, 0x7c, 0xc6, 0xbf, 0x8a, 0xc2, 0xed, 0x7d, 0xd5, - 0xc5, 0xb6, 0xae, 0x1a, 0xfa, 0x1f, 0x60, 0xed, 0xa9, 0x8e, 0x5f, 0xc9, 0xb8, 0x63, 0x63, 0xe7, - 0x04, 0x7d, 0x01, 0xf3, 0x63, 0x67, 0x46, 0xa7, 0x9e, 0xdd, 0x78, 0x67, 0x36, 0xaf, 0x2d, 0x72, - 0xcf, 0x91, 0xd3, 0x44, 0xfb, 0xe1, 0xd3, 0x61, 0xb9, 0xfb, 0xe5, 0x64, 0x06, 0x8f, 0xef, 0x11, - 0x24, 0x54, 0x47, 0xb1, 0x3a, 0xdc, 0x32, 0xdf, 0x0a, 0x08, 0x1a, 0xb8, 0xba, 0xb1, 0x76, 0x62, - 0xb4, 0xd7, 0x8e, 0x44, 0xdb, 0x5e, 0xd8, 0xb4, 0xea, 0xb4, 0x3a, 0xe8, 0x43, 0x28, 0x3a, 0x27, - 0xd6, 0xc0, 0xd0, 0x94, 0x63, 0xb5, 0xfd, 0xbc, 0xa3, 0x1b, 0x46, 0xa8, 0xef, 0x52, 0x60, 0xc8, - 0x4d, 0x8e, 0xe3, 0x7b, 0xf6, 0xe7, 0x29, 0x40, 0xfe, 0x7c, 0xf6, 0x07, 0xae, 0x4a, 0xbd, 0x5e, - 0x05, 0x92, 0xdc, 0xdc, 0xd8, 0x1e, 0xbd, 0x3b, 0xd5, 0x33, 0x85, 0xfb, 0x4c, 0xdb, 0x73, 0x32, - 0x67, 0x44, 0x3f, 0x0d, 0x76, 0xe9, 0x67, 0xde, 0x91, 0xed, 0x39, 0xd1, 0xbe, 0xdf, 0x85, 0x84, - 0xe3, 0x12, 0x2f, 0x1d, 0xa3, 0xb1, 0x75, 0x7d, 0x0a, 0xff, 0xf8, 0xe4, 0xd7, 0x0e, 0x09, 0x9b, - 0xf0, 0x4d, 0x54, 0x06, 0x7a, 0x06, 0x19, 0x2f, 0xa5, 0xe4, 0x2d, 0xff, 0x87, 0xb3, 0x0b, 0xf4, - 0xa2, 0x81, 0x88, 0x15, 0x9e, 0x2c, 0x54, 0x81, 0x6c, 0x8f, 0x93, 0xf9, 0x8d, 0x83, 0x15, 0x9e, - 0xd5, 0x83, 0x90, 0x40, 0xb3, 0xfb, 0xc0, 0x97, 0x0c, 0x82, 0xa9, 0x41, 0x23, 0x9f, 0x6d, 0x19, - 0x06, 0x39, 0x34, 0xda, 0xc6, 0xf4, 0x22, 0x9f, 0x80, 0xa2, 0x5d, 0x92, 0x9b, 0x0b, 0x5f, 0x46, - 0x9b, 0x92, 0xd9, 0x19, 0x1a, 0xa7, 0x22, 0x56, 0x6c, 0xcf, 0xc9, 0x01, 0x76, 0xd4, 0x82, 0x42, - 0x3f, 0xe4, 0xcf, 0x78, 0x22, 0x7c, 0x7f, 0x5a, 0x36, 0x14, 0x22, 0xde, 0x9e, 0x93, 0x47, 0xd8, - 0xd1, 0xcf, 0x01, 0xb5, 0xc7, 0xfc, 0x44, 0x09, 0x5e, 0x33, 0xcb, 0x51, 0x86, 0xed, 0x39, 0x79, - 0x82, 0x18, 0xf4, 0x25, 0xdc, 0xee, 0x4d, 0x36, 0x69, 0x9e, 0x12, 0xaf, 0x4d, 0x19, 0x61, 0x8a, - 0x23, 0xd8, 0x9e, 0x93, 0xa7, 0x09, 0x2c, 0x7f, 0x06, 0x09, 0xaa, 0x3a, 0x24, 0xb0, 0x3f, 0x69, - 0xee, 0x36, 0x5b, 0xcf, 0x9a, 0x2c, 0x56, 0xd4, 0xea, 0x7b, 0xf5, 0xa3, 0xba, 0xd2, 0x6a, 0xee, - 0x91, 0x58, 0x71, 0x07, 0x6e, 0x72, 0x40, 0xa5, 0x59, 0x53, 0x9e, 0xc9, 0x0d, 0x81, 0x8a, 0x96, - 0x57, 0x83, 0x99, 0x43, 0x1a, 0xe2, 0xcd, 0x56, 0xb3, 0x2e, 0xcd, 0xd1, 0x1c, 0xa2, 0x56, 0x93, - 0x22, 0x34, 0x87, 0x90, 0x5b, 0x07, 0x22, 0xc4, 0x6c, 0xe6, 0x00, 0x34, 0x4f, 0xdd, 0x76, 0xe2, - 0xe9, 0xa4, 0x94, 0x2a, 0xff, 0x5d, 0x04, 0xd2, 0xa4, 0x24, 0x6b, 0x98, 0x1d, 0x0b, 0x3d, 0x84, - 0x4c, 0x5f, 0xb5, 0xb1, 0xe9, 0xfa, 0x9e, 0x56, 0x74, 0xca, 0xd2, 0x07, 0x14, 0xe1, 0x35, 0x72, - 0xd2, 0x8c, 0xb0, 0x71, 0x51, 0x1b, 0x64, 0x0b, 0x24, 0x2e, 0xce, 0x69, 0x9f, 0xe0, 0x9e, 0x4a, - 0xa4, 0xb2, 0x5e, 0xcd, 0x9b, 0x5e, 0x97, 0x92, 0xe2, 0x0f, 0x29, 0xda, 0x93, 0x5d, 0xe8, 0x07, - 0xa1, 0x22, 0x42, 0xfc, 0xcb, 0x5d, 0x28, 0x8e, 0x64, 0x08, 0x17, 0x94, 0xbd, 0x2b, 0xb4, 0xec, - 0x8d, 0xf9, 0x7e, 0xdf, 0x2b, 0x7b, 0xa3, 0xbc, 0xe2, 0x0d, 0x2d, 0x36, 0x3e, 0xe3, 0x62, 0x1f, - 0xfa, 0x59, 0x30, 0x33, 0xbe, 0x3b, 0x3c, 0xa6, 0xcc, 0x5f, 0x90, 0x00, 0x1f, 0xc0, 0x7c, 0xcf, - 0xd2, 0xf4, 0x0e, 0xc9, 0xf7, 0x88, 0xe5, 0xba, 0x7a, 0x8f, 0x5d, 0x21, 0xcc, 0xe8, 0x70, 0xa5, - 0x20, 0x37, 0x41, 0xa2, 0xc7, 0x90, 0x12, 0xdd, 0x9d, 0x34, 0x8d, 0x00, 0xb3, 0x7a, 0x4c, 0x91, - 0x07, 0x73, 0x6e, 0xb4, 0x05, 0x05, 0x13, 0x9f, 0x06, 0x9b, 0x91, 0x99, 0x90, 0x4f, 0xc9, 0x35, - 0xf1, 0xe9, 0xe4, 0x4e, 0x64, 0xce, 0xf4, 0x31, 0x1a, 0xfa, 0x1c, 0xf2, 0xe1, 0x60, 0x07, 0x57, - 0x08, 0x76, 0xb9, 0x7e, 0x30, 0xd2, 0x6d, 0x41, 0x4a, 0x44, 0xb9, 0xec, 0x15, 0xa2, 0x9c, 0x60, - 0x46, 0x9b, 0x24, 0x85, 0x38, 0x75, 0xfd, 0xd4, 0x24, 0xe7, 0x97, 0x2f, 0xe7, 0x67, 0xcb, 0x59, - 0xb2, 0xc2, 0x09, 0x2d, 0xc7, 0xac, 0xe9, 0xc1, 0x35, 0xb4, 0x03, 0xe0, 0x5d, 0x4c, 0x3b, 0xb4, - 0xd3, 0x3e, 0xbd, 0x8c, 0x3d, 0x10, 0x84, 0xfe, 0x94, 0xe4, 0x00, 0x37, 0xda, 0x87, 0x8c, 0x70, - 0xc7, 0xac, 0xc0, 0x9c, 0xee, 0xb7, 0xc6, 0x83, 0x83, 0x08, 0x09, 0x9e, 0x04, 0x92, 0x5b, 0x1b, - 0x58, 0x75, 0x30, 0xaf, 0x32, 0x1f, 0xcd, 0x98, 0x5b, 0x33, 0xe3, 0xaa, 0x9e, 0xa8, 0x66, 0x17, - 0xef, 0x11, 0xfe, 0xcd, 0x68, 0x29, 0x22, 0x33, 0x51, 0xa8, 0x09, 0x12, 0xdd, 0xb2, 0x60, 0xac, - 0x91, 0xe8, 0xae, 0xbd, 0x2d, 0x0c, 0x97, 0xec, 0xda, 0xd4, 0x78, 0x43, 0x75, 0x6a, 0xdf, 0x8f, - 0x39, 0xbf, 0x0d, 0x85, 0x8e, 0x65, 0xf7, 0x54, 0x57, 0x11, 0xc6, 0x33, 0xef, 0xf7, 0xa3, 0xbe, - 0x3b, 0x5b, 0xce, 0x6f, 0x51, 0xac, 0x30, 0x9c, 0x7c, 0x27, 0xf8, 0x89, 0x36, 0x45, 0x68, 0xbe, - 0x41, 0x23, 0xe9, 0x3b, 0xaf, 0xdd, 0xac, 0x09, 0x11, 0xb9, 0x09, 0x49, 0x5a, 0x36, 0x38, 0xa5, - 0x05, 0xba, 0xe3, 0x57, 0x2c, 0x41, 0x64, 0x2e, 0x05, 0xed, 0x41, 0x41, 0x23, 0x10, 0x52, 0xd3, - 0xb2, 0x4e, 0xd7, 0x4d, 0x2a, 0x77, 0x79, 0x8a, 0x5c, 0xe1, 0x62, 0x45, 0x43, 0x43, 0x30, 0xb3, - 0x6e, 0x58, 0x0b, 0xd2, 0x1d, 0xb5, 0xa7, 0x1b, 0x3a, 0x76, 0x4a, 0xb7, 0xa8, 0x9c, 0x0f, 0x2f, - 0xb4, 0xe7, 0xd1, 0x5b, 0x0f, 0x11, 0xc2, 0x85, 0x10, 0xcf, 0xac, 0x29, 0x60, 0x48, 0x8e, 0xef, - 0xf6, 0xb8, 0x59, 0x8b, 0x5b, 0x8f, 0xd0, 0x0d, 0x08, 0x35, 0x6b, 0xfe, 0xa5, 0xa1, 0x7b, 0x00, - 0x2f, 0x75, 0xfc, 0x4a, 0x79, 0x31, 0xc0, 0xf6, 0xb0, 0x54, 0x0a, 0x16, 0xb0, 0x04, 0xfe, 0x39, - 0x01, 0xa3, 0x8f, 0x20, 0xa3, 0xe1, 0x3e, 0x36, 0x35, 0xa7, 0x65, 0x96, 0xee, 0xd0, 0x72, 0xe1, - 0xc6, 0xf9, 0xd9, 0x72, 0xa6, 0x26, 0x80, 0xdc, 0x8b, 0xfa, 0x54, 0xe8, 0x4b, 0xc8, 0xb1, 0x0f, - 0xac, 0xb5, 0xcc, 0xcd, 0x61, 0x69, 0x91, 0x2e, 0xfa, 0xc1, 0x8c, 0x87, 0xe2, 0xb7, 0x87, 0xbc, - 0x8e, 0x7a, 0x2d, 0x20, 0x4d, 0x0e, 0xc9, 0x46, 0xbf, 0x0b, 0x39, 0xa1, 0xc7, 0x3b, 0xd6, 0xb1, - 0x53, 0x7a, 0xe3, 0xc2, 0x76, 0xf7, 0xe8, 0x58, 0xfb, 0x3e, 0xab, 0xf0, 0x52, 0x41, 0x69, 0xe8, - 0x0b, 0xc8, 0x7b, 0x17, 0x77, 0x56, 0xdf, 0x75, 0x4a, 0x6f, 0x52, 0x33, 0x7c, 0x38, 0xab, 0x19, - 0x72, 0xde, 0x56, 0x9f, 0xde, 0x04, 0x04, 0xbe, 0xd0, 0x5d, 0xc8, 0x68, 0xb6, 0xd5, 0x67, 0xd1, - 0xe2, 0xad, 0x95, 0xc8, 0x6a, 0xcc, 0xeb, 0x51, 0xd8, 0x56, 0x9f, 0x86, 0x01, 0x05, 0x0a, 0x36, - 0xee, 0x1b, 0x6a, 0x1b, 0xf7, 0x48, 0x1c, 0xb3, 0x3a, 0xa5, 0x25, 0x3a, 0xfa, 0xc6, 0xcc, 0x1b, - 0xe9, 0x31, 0x0b, 0xc5, 0x0c, 0xc8, 0x6b, 0x75, 0xd0, 0x13, 0x00, 0x75, 0xa0, 0xe9, 0xae, 0xd2, - 0xb3, 0x34, 0x5c, 0x5a, 0xbe, 0xf0, 0x36, 0x79, 0x54, 0x78, 0x85, 0x30, 0xee, 0x5b, 0x1a, 0xf6, - 0xee, 0x8e, 0x04, 0x00, 0x7d, 0x04, 0x59, 0xba, 0xb4, 0x2f, 0xad, 0x63, 0xa2, 0x9b, 0x2b, 0x74, - 0x71, 0xf3, 0xfc, 0x2c, 0x33, 0x35, 0xdb, 0xea, 0xef, 0x58, 0xc7, 0x54, 0x63, 0xf8, 0x4f, 0x0d, - 0x39, 0x90, 0xeb, 0xb6, 0x15, 0xdf, 0x71, 0xde, 0xa5, 0xa7, 0xf8, 0xc9, 0x8c, 0x73, 0x79, 0x5c, - 0x9d, 0xe0, 0x4a, 0x6f, 0x88, 0x08, 0xf0, 0xb8, 0x2a, 0x60, 0x8e, 0x9c, 0xed, 0xb6, 0xbd, 0x0f, - 0x52, 0x11, 0xb2, 0x46, 0x18, 0x37, 0x80, 0x72, 0xb0, 0x22, 0x64, 0x18, 0x66, 0x02, 0x4d, 0xe0, - 0x1d, 0x33, 0x85, 0x56, 0x53, 0xec, 0xcc, 0xee, 0xcd, 0x1e, 0xe1, 0x0b, 0x8c, 0xbb, 0xe2, 0xb4, - 0x3a, 0xf4, 0x60, 0xdb, 0x90, 0xb3, 0x06, 0xee, 0xb1, 0x35, 0x30, 0x35, 0xa5, 0xf3, 0xdc, 0x29, - 0xbd, 0x4d, 0x57, 0x7b, 0xa9, 0xee, 0x86, 0xb7, 0xba, 0x16, 0x17, 0xb4, 0xb5, 0xeb, 0xc8, 0x59, - 0x21, 0x75, 0xeb, 0xb9, 0x83, 0x7e, 0x01, 0x59, 0xdd, 0xf4, 0xc7, 0xb8, 0x7f, 0xf9, 0x31, 0x90, - 0xa8, 0x3c, 0x1a, 0xa6, 0x37, 0x04, 0x70, 0x99, 0x64, 0x84, 0x0f, 0xa0, 0x60, 0x75, 0x3a, 0x86, - 0x6e, 0x62, 0xc5, 0xc6, 0xaa, 0x63, 0x99, 0xa5, 0x77, 0x02, 0x3b, 0x98, 0xe7, 0x38, 0x99, 0xa2, - 0x50, 0x19, 0x32, 0x2e, 0xee, 0xf5, 0x2d, 0x5b, 0xb5, 0x87, 0xa5, 0x77, 0x83, 0x57, 0x6e, 0x1e, - 0x18, 0x1d, 0xc3, 0xe2, 0xc0, 0xc4, 0xa7, 0x7d, 0xcb, 0xc1, 0x9a, 0x32, 0x96, 0x5b, 0xae, 0x52, - 0x1f, 0x77, 0x9f, 0x4f, 0xea, 0xf6, 0x13, 0x41, 0x39, 0x31, 0xc9, 0xbc, 0x3d, 0x98, 0x88, 0xd6, - 0xd0, 0x8f, 0x60, 0x41, 0x77, 0x94, 0x60, 0xd6, 0xae, 0x10, 0x5f, 0x57, 0x7a, 0x2f, 0x30, 0x25, - 0xa4, 0x3b, 0xa3, 0x19, 0xff, 0xe2, 0x2f, 0x23, 0x30, 0x3f, 0x16, 0x55, 0xd1, 0xef, 0x43, 0xca, - 0xb4, 0xb4, 0xc0, 0xc5, 0x68, 0x9d, 0x4f, 0x2f, 0xd9, 0xb4, 0x34, 0x76, 0x2f, 0xfa, 0xb0, 0xab, - 0xbb, 0x27, 0x83, 0xe3, 0xb5, 0xb6, 0xd5, 0x5b, 0xf7, 0x36, 0x5f, 0x3b, 0xf6, 0x7f, 0xaf, 0xf7, - 0x9f, 0x77, 0xd7, 0xe9, 0xaf, 0xfe, 0xf1, 0x1a, 0x63, 0x93, 0x93, 0x44, 0x6a, 0x43, 0x23, 0x65, - 0x38, 0x3e, 0xed, 0xeb, 0x76, 0x20, 0xb3, 0x8c, 0x06, 0x7c, 0x45, 0xc1, 0x47, 0x12, 0xc5, 0xe2, - 0x57, 0x57, 0xbf, 0x8a, 0x42, 0x71, 0x24, 0xb2, 0x91, 0x54, 0x9a, 0x76, 0x3d, 0x42, 0xa9, 0x34, - 0x81, 0x5c, 0x90, 0xe0, 0x07, 0x1f, 0xd8, 0xc4, 0xae, 0xfb, 0xc0, 0x26, 0x7c, 0x25, 0x94, 0xb8, - 0xc4, 0x95, 0xd0, 0x4f, 0xe0, 0x96, 0xee, 0x28, 0xa6, 0x65, 0x8a, 0xce, 0x9d, 0x57, 0xbc, 0x06, - 0x9f, 0x71, 0xdc, 0xd0, 0x9d, 0xa6, 0x65, 0xb2, 0x9e, 0x9d, 0xb7, 0x6a, 0xff, 0xc5, 0x47, 0x6a, - 0xfc, 0xc5, 0x87, 0xd7, 0x99, 0x8b, 0x4b, 0x89, 0xc5, 0xaf, 0x23, 0x90, 0x09, 0x3e, 0x1b, 0x8c, - 0x86, 0x9b, 0x51, 0x63, 0xe5, 0xc5, 0x15, 0x2f, 0xb8, 0xc3, 0xbb, 0x10, 0x9b, 0x7d, 0x17, 0xf8, - 0xd1, 0xfe, 0x21, 0x64, 0x03, 0x21, 0x6b, 0xb4, 0x61, 0x10, 0xb9, 0x42, 0xc3, 0xe0, 0x6d, 0x48, - 0x72, 0x3f, 0xcd, 0x14, 0x2b, 0xcf, 0xb9, 0x13, 0xcc, 0x47, 0x27, 0xbe, 0x24, 0xfe, 0x99, 0x8f, - 0xfe, 0xaf, 0x31, 0xc8, 0x05, 0x43, 0x1a, 0x31, 0x6a, 0xdd, 0x6c, 0xdb, 0x34, 0x9e, 0xd0, 0xd1, - 0x63, 0xde, 0x3d, 0xba, 0x00, 0x93, 0x40, 0xd7, 0xd3, 0x4d, 0x85, 0xde, 0xdd, 0x86, 0x94, 0x37, - 0xdd, 0xd3, 0xcd, 0xa7, 0x04, 0x4a, 0x49, 0xd4, 0x53, 0x4e, 0x12, 0x0b, 0x91, 0xa8, 0xa7, 0x8c, - 0x64, 0x91, 0x66, 0x89, 0xb6, 0x4b, 0x4b, 0xb9, 0x58, 0x20, 0xfb, 0xb3, 0x5d, 0xb4, 0x04, 0xa9, - 0x97, 0xba, 0xed, 0x0e, 0x54, 0x83, 0x56, 0x6d, 0xe2, 0x98, 0x05, 0x10, 0x99, 0x50, 0xf0, 0x83, - 0xf8, 0x2b, 0x13, 0xdb, 0x54, 0x71, 0xb2, 0x1b, 0x95, 0x2b, 0x44, 0x71, 0xff, 0x83, 0x08, 0x12, - 0xae, 0xce, 0x09, 0x02, 0x17, 0xff, 0x36, 0x02, 0xf9, 0x10, 0x19, 0x6a, 0x40, 0x91, 0x0e, 0x3c, - 0xd6, 0xe9, 0xbc, 0xeb, 0x3d, 0x00, 0x24, 0xe8, 0x89, 0x95, 0x58, 0xde, 0x0a, 0xa0, 0x34, 0xf4, - 0x19, 0x14, 0x98, 0x28, 0xef, 0x45, 0x46, 0x58, 0xfd, 0x72, 0x54, 0x52, 0xf8, 0x59, 0x46, 0xce, - 0xf2, 0x61, 0x5a, 0xf0, 0xb2, 0x79, 0xd1, 0x84, 0x6c, 0x20, 0x4b, 0x98, 0x41, 0xef, 0x7f, 0x0c, - 0x71, 0xcf, 0x0b, 0xcd, 0xda, 0x50, 0x74, 0x7d, 0xd7, 0xf4, 0x55, 0x04, 0x16, 0x26, 0x45, 0xeb, - 0x90, 0x3d, 0x31, 0x45, 0x9a, 0xc9, 0x9e, 0xee, 0x05, 0xb3, 0x28, 0xa6, 0x5c, 0xe2, 0x02, 0xd4, - 0xcf, 0xa3, 0xde, 0xf1, 0x54, 0x9c, 0xe9, 0x56, 0x31, 0xa4, 0xe2, 0xa4, 0x2e, 0x0a, 0x28, 0x79, - 0x79, 0x15, 0x32, 0x5e, 0x6e, 0x83, 0x72, 0x90, 0xae, 0x35, 0x0e, 0x2b, 0x9b, 0x7b, 0xf5, 0x9a, - 0x34, 0x87, 0xf2, 0x90, 0x91, 0xeb, 0x95, 0x1a, 0xed, 0xd2, 0x48, 0x91, 0x8f, 0xd3, 0x7f, 0xfc, - 0xd5, 0x72, 0x84, 0xfb, 0x90, 0xa4, 0x94, 0xda, 0x89, 0xa7, 0x91, 0x74, 0xa3, 0xfc, 0xa7, 0x49, - 0x40, 0x35, 0xd5, 0x55, 0x89, 0x2a, 0x5d, 0xa2, 0x97, 0x11, 0xbd, 0x60, 0xd3, 0xc3, 0xf5, 0x69, - 0xec, 0x5a, 0xf5, 0xe9, 0xc4, 0x6e, 0x45, 0xfc, 0x3a, 0xdd, 0x8a, 0x2b, 0x35, 0x4d, 0xc6, 0x2b, - 0xac, 0xe4, 0x35, 0x2a, 0xac, 0xa7, 0x90, 0x62, 0x79, 0x02, 0x7b, 0x2c, 0x30, 0xbd, 0x00, 0x1c, - 0x3f, 0x18, 0x5e, 0x2a, 0x3b, 0x75, 0xd3, 0xb5, 0x87, 0xde, 0x3d, 0x22, 0x83, 0xf9, 0xb5, 0x69, - 0xfa, 0xea, 0xb5, 0xe9, 0x78, 0x96, 0x94, 0x99, 0x9a, 0x25, 0x2d, 0x1e, 0x01, 0xf0, 0x4c, 0xc5, - 0xec, 0x58, 0x33, 0x98, 0xe3, 0x12, 0xa4, 0x88, 0x9a, 0xf7, 0x31, 0x53, 0x20, 0xcf, 0xf5, 0x71, - 0x20, 0xb7, 0xba, 0x3e, 0xe4, 0x82, 0xab, 0x44, 0x12, 0xc4, 0x9e, 0xe3, 0x21, 0x53, 0x45, 0x99, - 0xfc, 0x44, 0x3b, 0x90, 0xf0, 0x1d, 0xf4, 0xf4, 0x47, 0x64, 0x53, 0xb7, 0x8f, 0x4c, 0x57, 0x66, - 0x22, 0x3e, 0x8e, 0x3e, 0x0a, 0x98, 0x46, 0xf9, 0x4f, 0x00, 0x0a, 0x47, 0xc3, 0x7e, 0xd0, 0x14, - 0xae, 0xd4, 0x87, 0x9c, 0xd4, 0x6d, 0x8c, 0x5e, 0xbe, 0xdb, 0x78, 0xc1, 0x43, 0x7e, 0xb6, 0xdb, - 0xf1, 0x0b, 0x76, 0xbb, 0x06, 0x71, 0xfa, 0xfe, 0x31, 0x41, 0xb5, 0x61, 0x9a, 0x05, 0x86, 0x57, - 0xbb, 0x16, 0x78, 0x02, 0x49, 0xb9, 0xd1, 0xcf, 0x20, 0x87, 0xcd, 0x41, 0x4f, 0xe9, 0xe1, 0xde, - 0x31, 0xb6, 0x85, 0xe2, 0x3f, 0x98, 0x4d, 0x5a, 0xdd, 0x1c, 0xf4, 0xf6, 0x29, 0xa3, 0x28, 0x54, - 0xb0, 0x07, 0x71, 0xd0, 0x03, 0x48, 0xa8, 0x86, 0x4e, 0xad, 0xe0, 0x75, 0xef, 0x6a, 0x19, 0x21, - 0xfa, 0x14, 0xf2, 0xaa, 0x6d, 0xab, 0x43, 0xfe, 0x42, 0x54, 0xa3, 0x9a, 0xce, 0x4d, 0x98, 0x94, - 0x17, 0x15, 0x82, 0xa4, 0x8f, 0x42, 0xc5, 0x46, 0x64, 0x55, 0x0f, 0x14, 0x6a, 0x98, 0x66, 0xae, - 0xd7, 0x30, 0x85, 0xeb, 0xb8, 0xa0, 0x71, 0x6f, 0x92, 0xbd, 0x86, 0x37, 0xf9, 0x05, 0x2c, 0x8a, - 0xc7, 0x33, 0x44, 0xa0, 0xdf, 0x54, 0x0f, 0xbc, 0xdd, 0x2d, 0x9f, 0x9f, 0x2d, 0x97, 0x64, 0x9f, - 0xca, 0x5f, 0x2e, 0xcb, 0xe1, 0xc8, 0x4e, 0x95, 0xec, 0x89, 0x78, 0x2d, 0xe0, 0x57, 0xf2, 0x57, - 0xf7, 0x2b, 0xe1, 0xa0, 0x50, 0xb8, 0x56, 0x50, 0x18, 0xf7, 0x51, 0xc5, 0xe9, 0x3e, 0xea, 0x2f, - 0xa3, 0x00, 0xbe, 0x1a, 0xa2, 0x1f, 0xc3, 0xed, 0xfe, 0xc9, 0xd0, 0xd1, 0xdb, 0xaa, 0xa1, 0xd8, - 0xb8, 0x6f, 0x63, 0x07, 0x9b, 0x2c, 0xa8, 0x53, 0xdb, 0xce, 0xc9, 0xb7, 0x04, 0x5a, 0x0e, 0x61, - 0xd1, 0x27, 0x70, 0xcb, 0xb0, 0xba, 0x93, 0xf8, 0x82, 0xa5, 0xc8, 0x4d, 0x4e, 0x33, 0xc2, 0xac, - 0x02, 0xb4, 0xd5, 0xbe, 0x7a, 0xac, 0x1b, 0x7e, 0x75, 0xf2, 0xc9, 0x65, 0x4d, 0x68, 0xad, 0xea, - 0x89, 0x10, 0x97, 0xa7, 0xbe, 0xd0, 0xf2, 0xdb, 0x00, 0x3e, 0x9e, 0x5e, 0xbb, 0xec, 0xed, 0xf9, - 0x49, 0x00, 0xbf, 0xc0, 0xe1, 0x49, 0xc3, 0x1b, 0x10, 0x27, 0x76, 0x8e, 0xd2, 0x10, 0xaf, 0x37, - 0x9f, 0xec, 0x4b, 0x73, 0x28, 0x03, 0x89, 0xca, 0x5e, 0xa3, 0x72, 0x18, 0xcc, 0x13, 0xca, 0x7f, - 0x13, 0x07, 0x89, 0x79, 0xa2, 0xeb, 0xba, 0xc3, 0xe9, 0x55, 0xdb, 0xeb, 0xaf, 0x46, 0xc2, 0x9a, - 0x13, 0xff, 0xfe, 0xd3, 0x89, 0xc4, 0xf7, 0x94, 0x4e, 0x24, 0xaf, 0x91, 0x4e, 0xa4, 0xae, 0xe1, - 0x00, 0xfe, 0xbf, 0xc3, 0x7e, 0x40, 0x43, 0xbe, 0x8e, 0x02, 0x04, 0x74, 0xe3, 0xa7, 0xc1, 0xbf, - 0x5f, 0x9b, 0x7e, 0x47, 0x32, 0x52, 0xb1, 0x6c, 0xcf, 0x89, 0xbf, 0x6e, 0x7b, 0x0c, 0x69, 0x8d, - 0xc7, 0x6c, 0x1e, 0xda, 0xdf, 0x9b, 0x39, 0xb4, 0x6f, 0xcf, 0xc9, 0x1e, 0x33, 0xfa, 0x24, 0xf4, - 0x07, 0x1b, 0xf7, 0x67, 0xb2, 0xb4, 0x6d, 0xf1, 0x22, 0xad, 0x02, 0x49, 0x16, 0xb4, 0xb9, 0xb2, - 0x4d, 0xfd, 0xcb, 0x81, 0x11, 0xd3, 0xd8, 0x9e, 0x93, 0x39, 0x23, 0xbf, 0xe2, 0x4c, 0x41, 0x62, - 0x60, 0xea, 0x96, 0xf9, 0xbe, 0x1c, 0x7c, 0x0b, 0x25, 0x7a, 0x0e, 0xc4, 0x34, 0xe9, 0x6f, 0xd5, - 0xc5, 0x1a, 0xbb, 0x6c, 0x7d, 0x62, 0xbe, 0xf4, 0x00, 0x11, 0x54, 0x00, 0xe0, 0x78, 0xdd, 0xec, - 0x4a, 0x51, 0x9a, 0xdd, 0x93, 0x44, 0x89, 0x7c, 0xc5, 0xde, 0xff, 0x14, 0xa4, 0xd1, 0x3f, 0x5d, - 0x08, 0x5c, 0xbb, 0xce, 0x43, 0x7e, 0xff, 0x69, 0xb5, 0x7a, 0xd4, 0xd8, 0xaf, 0x1f, 0x1e, 0x55, - 0xf6, 0x0f, 0xd8, 0x3b, 0x9f, 0x23, 0x52, 0x1a, 0xb4, 0x1a, 0x35, 0x29, 0xfa, 0xfe, 0xa7, 0x50, - 0x1c, 0x51, 0x08, 0x04, 0x90, 0x3c, 0x78, 0xb2, 0xb9, 0xd7, 0xa8, 0x4e, 0xbc, 0xb6, 0x45, 0x59, - 0x48, 0xb5, 0xb6, 0xb6, 0xf6, 0x1a, 0xcd, 0xba, 0x14, 0xdb, 0x5c, 0xfd, 0xe6, 0x3f, 0x96, 0xe6, - 0xbe, 0x39, 0x5f, 0x8a, 0xfc, 0xfa, 0x7c, 0x29, 0xf2, 0x9b, 0xf3, 0xa5, 0xc8, 0xbf, 0x9f, 0x2f, - 0x45, 0xfe, 0xe2, 0xdb, 0xa5, 0xb9, 0x5f, 0x7f, 0xbb, 0x34, 0xf7, 0x9b, 0x6f, 0x97, 0xe6, 0x7e, - 0x27, 0xc9, 0xfe, 0x86, 0xf2, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xa9, 0xe0, 0xe6, 0xae, - 0x39, 0x00, 0x00, + 0x06, 0x3d, 0xf5, 0x54, 0x14, 0x45, 0x1f, 0x87, 0x1e, 0x8b, 0x06, 0x45, 0x80, 0xee, 0xad, 0xd8, + 0x4b, 0x7b, 0x2b, 0xd0, 0x5b, 0x8e, 0xdb, 0xdb, 0x9e, 0x84, 0x56, 0xb9, 0x14, 0xe8, 0xa9, 0x40, + 0xd1, 0x02, 0x39, 0x15, 0xff, 0x6b, 0x1e, 0x7c, 0x28, 0x94, 0x94, 0xee, 0xc1, 0x06, 0xe7, 0x7b, + 0xfd, 0xaf, 0xef, 0xfd, 0xff, 0x82, 0x7b, 0xce, 0x0b, 0x63, 0xbd, 0xad, 0xba, 0xaa, 0x61, 0x75, + 0xd7, 0x35, 0xec, 0xb4, 0xfb, 0xc7, 0xeb, 0x8e, 0x6b, 0x0f, 0xda, 0xee, 0xc0, 0xc6, 0xda, 0x5a, + 0xdf, 0xb6, 0x5c, 0x0b, 0xdd, 0x6c, 0x5b, 0xed, 0xe7, 0xb6, 0xa5, 0xb6, 0x4f, 0xd6, 0x9c, 0x17, + 0x06, 0xf9, 0x77, 0xac, 0x3a, 0x78, 0xb1, 0x34, 0x70, 0x75, 0x63, 0xfd, 0xc4, 0x68, 0xaf, 0xbb, + 0x7a, 0x0f, 0x3b, 0xae, 0xda, 0xeb, 0x33, 0x86, 0xc5, 0xf2, 0x04, 0xa9, 0x7d, 0x5b, 0x7f, 0xa9, + 0x1b, 0xb8, 0x8b, 0x39, 0xcd, 0x4d, 0x42, 0xe3, 0x0e, 0xfb, 0xd8, 0x61, 0xff, 0x73, 0xf0, 0x9d, + 0x2e, 0xb6, 0xd6, 0xbb, 0xd8, 0xd2, 0x4d, 0x0d, 0x9f, 0xae, 0xb7, 0x2d, 0xb3, 0xa3, 0x77, 0x39, + 0x6a, 0xa1, 0x6b, 0x75, 0x2d, 0xfa, 0x73, 0x9d, 0xfc, 0x62, 0xd0, 0xf2, 0x1f, 0x27, 0xe0, 0xc6, + 0x96, 0x65, 0x63, 0xbd, 0x6b, 0xee, 0xe2, 0xa1, 0x8c, 0x3b, 0xd8, 0xc6, 0x66, 0x1b, 0xa3, 0x15, + 0x48, 0xb8, 0xea, 0xb1, 0x81, 0x4b, 0x91, 0x95, 0xc8, 0x6a, 0x7e, 0x13, 0xbe, 0x3e, 0x5b, 0x9e, + 0xfb, 0xf6, 0x6c, 0x39, 0xda, 0xa8, 0xc9, 0x0c, 0x81, 0xee, 0x43, 0x82, 0x8e, 0x52, 0x8a, 0x52, + 0x8a, 0x22, 0xa7, 0x48, 0x35, 0x08, 0x90, 0x90, 0x51, 0x2c, 0x2a, 0x41, 0xdc, 0x54, 0x7b, 0xb8, + 0x14, 0x5b, 0x89, 0xac, 0x66, 0x36, 0xe3, 0x84, 0x4a, 0xa6, 0x10, 0xb4, 0x0b, 0xe9, 0x97, 0xaa, + 0xa1, 0x6b, 0xba, 0x3b, 0x2c, 0xc5, 0x57, 0x22, 0xab, 0x85, 0x8d, 0x77, 0xd6, 0x26, 0x6e, 0xd5, + 0x5a, 0xd5, 0x32, 0x1d, 0xd7, 0x56, 0x75, 0xd3, 0x7d, 0xca, 0x19, 0xb8, 0x20, 0x4f, 0x00, 0x7a, + 0x00, 0xf3, 0xce, 0x89, 0x6a, 0x63, 0x4d, 0xe9, 0xdb, 0xb8, 0xa3, 0x9f, 0x2a, 0x06, 0x36, 0x4b, + 0x89, 0x95, 0xc8, 0x6a, 0x82, 0x93, 0x16, 0x19, 0xfa, 0x80, 0x62, 0xf7, 0xb0, 0x89, 0x8e, 0x20, + 0x63, 0x99, 0x8a, 0x86, 0x0d, 0xec, 0xe2, 0x52, 0x92, 0x8e, 0xff, 0xc1, 0x94, 0xf1, 0x27, 0x6c, + 0xd0, 0x5a, 0xa5, 0xed, 0xea, 0x96, 0x29, 0xe6, 0x61, 0x99, 0x35, 0x2a, 0x88, 0x4b, 0x1d, 0xf4, + 0x35, 0xd5, 0xc5, 0xa5, 0xd4, 0xb5, 0xa5, 0x3e, 0xa1, 0x82, 0xd0, 0x1e, 0x24, 0x7a, 0xaa, 0xdb, + 0x3e, 0x29, 0xa5, 0xa9, 0xc4, 0x07, 0x97, 0x90, 0xb8, 0x4f, 0xf8, 0xb8, 0x40, 0x26, 0xa4, 0xfc, + 0x0c, 0x92, 0x6c, 0x1c, 0x94, 0x87, 0x4c, 0xb3, 0xa5, 0x54, 0xaa, 0x47, 0x8d, 0x56, 0x53, 0x9a, + 0x43, 0x39, 0x48, 0xcb, 0xf5, 0xc3, 0x23, 0xb9, 0x51, 0x3d, 0x92, 0x22, 0xe4, 0xeb, 0xb0, 0x7e, + 0xa4, 0x34, 0x9f, 0xec, 0xed, 0x49, 0x51, 0x54, 0x84, 0x2c, 0xf9, 0xaa, 0xd5, 0xb7, 0x2a, 0x4f, + 0xf6, 0x8e, 0xa4, 0x18, 0xca, 0x42, 0xaa, 0x5a, 0x39, 0xac, 0x56, 0x6a, 0x75, 0x29, 0xbe, 0x18, + 0xff, 0xe5, 0x57, 0x4b, 0x73, 0xe5, 0x07, 0x90, 0xa0, 0xc3, 0x21, 0x80, 0xe4, 0x61, 0x63, 0xff, + 0x60, 0xaf, 0x2e, 0xcd, 0xa1, 0x34, 0xc4, 0xb7, 0x88, 0x88, 0x08, 0xe1, 0x38, 0xa8, 0xc8, 0x47, + 0x8d, 0xca, 0x9e, 0x14, 0x65, 0x1c, 0x1f, 0xc6, 0xff, 0xe3, 0xcb, 0xe5, 0x48, 0xf9, 0x5f, 0x13, + 0xb0, 0xe0, 0xcf, 0xdd, 0x3f, 0x6d, 0x54, 0x85, 0xa2, 0x65, 0xeb, 0x5d, 0xdd, 0x54, 0xa8, 0xce, + 0x29, 0xba, 0xc6, 0xf5, 0xf1, 0x35, 0xb2, 0x9e, 0xf3, 0xb3, 0xe5, 0x7c, 0x8b, 0xa2, 0x8f, 0x08, + 0xb6, 0x51, 0xe3, 0x0a, 0x9a, 0xb7, 0x02, 0x40, 0x0d, 0xed, 0xc2, 0x3c, 0x17, 0xd2, 0xb6, 0x8c, + 0x41, 0xcf, 0x54, 0x74, 0xcd, 0x29, 0x45, 0x57, 0x62, 0xab, 0xf9, 0xcd, 0xe5, 0xf3, 0xb3, 0xe5, + 0x22, 0x13, 0x51, 0xa5, 0xb8, 0x46, 0xcd, 0xf9, 0xf6, 0x6c, 0x39, 0x2d, 0x3e, 0x64, 0x3e, 0x3c, + 0xff, 0xd6, 0x1c, 0xf4, 0x0c, 0x6e, 0xda, 0x62, 0x6f, 0xb5, 0xa0, 0xc0, 0x18, 0x15, 0x78, 0xef, + 0xfc, 0x6c, 0xf9, 0x86, 0xb7, 0xf9, 0xda, 0x64, 0xa1, 0x37, 0xec, 0x51, 0x02, 0xcd, 0x41, 0x2d, + 0x08, 0x80, 0xfd, 0xe5, 0xc6, 0xe9, 0x72, 0x97, 0xf9, 0x72, 0xe7, 0x7d, 0xd1, 0xe1, 0x25, 0xcf, + 0xdb, 0x23, 0x08, 0xcd, 0x33, 0xbc, 0xc4, 0x85, 0x86, 0x97, 0xbc, 0xae, 0xe1, 0x85, 0xcc, 0x28, + 0xf5, 0xff, 0x62, 0x46, 0xe9, 0xef, 0xdd, 0x8c, 0x32, 0xdf, 0x83, 0x19, 0x31, 0xdd, 0xdd, 0x89, + 0xa7, 0x41, 0xca, 0xee, 0xc4, 0xd3, 0x59, 0x29, 0xb7, 0x13, 0x4f, 0xe7, 0xa4, 0xfc, 0x4e, 0x3c, + 0x9d, 0x97, 0x0a, 0xe5, 0xff, 0x8a, 0x83, 0xc4, 0x4e, 0xb7, 0x86, 0x9d, 0xb6, 0xad, 0xf7, 0x5d, + 0xcb, 0xf6, 0xce, 0x24, 0x32, 0x76, 0x26, 0x6f, 0x41, 0x54, 0xd7, 0xb8, 0x2b, 0xbd, 0xc5, 0x4f, + 0x3b, 0x4a, 0x8f, 0xd7, 0xd7, 0x9b, 0xa8, 0xae, 0xa1, 0x35, 0x88, 0x13, 0x7f, 0x4f, 0xdd, 0x69, + 0x76, 0x63, 0x71, 0x74, 0x05, 0xb8, 0xb7, 0xc6, 0xc2, 0xc1, 0x91, 0x4c, 0xe9, 0xd0, 0x0a, 0xa4, + 0xcd, 0x81, 0x61, 0x50, 0x57, 0x4e, 0x74, 0x29, 0x2d, 0x36, 0x45, 0x40, 0xd1, 0x5d, 0xc8, 0x69, + 0xb8, 0xa3, 0x0e, 0x0c, 0x57, 0xc1, 0xa7, 0x7d, 0x9b, 0xe9, 0x8b, 0x9c, 0xe5, 0xb0, 0xfa, 0x69, + 0xdf, 0x46, 0xaf, 0x43, 0xf2, 0x44, 0xd7, 0x34, 0x6c, 0x52, 0x75, 0x11, 0x22, 0x38, 0x0c, 0x6d, + 0xc0, 0xfc, 0xc0, 0xc1, 0x8e, 0xe2, 0xe0, 0x17, 0x03, 0xb2, 0x57, 0xd4, 0x1c, 0x80, 0x9a, 0x43, + 0x92, 0xab, 0x67, 0x91, 0x10, 0x1c, 0x72, 0x3c, 0xd1, 0xf6, 0xbb, 0x90, 0x6b, 0x5b, 0xbd, 0xfe, + 0xc0, 0xc5, 0x6c, 0xd0, 0x2c, 0x1b, 0x94, 0xc3, 0xe8, 0xa0, 0x1b, 0x30, 0x6f, 0xbd, 0x32, 0x47, + 0xc4, 0xe6, 0xc2, 0x62, 0x09, 0x41, 0x50, 0xec, 0x27, 0x20, 0xf5, 0xbb, 0x8a, 0xea, 0xba, 0xb6, + 0x7e, 0x4c, 0x64, 0x9b, 0x83, 0x5e, 0x29, 0x1f, 0xda, 0xd3, 0xc2, 0xc1, 0xe3, 0x8a, 0x40, 0x37, + 0x07, 0x3d, 0xb9, 0xd0, 0xef, 0x06, 0xbf, 0xd1, 0x16, 0xbc, 0xa1, 0x1a, 0x2e, 0xb6, 0x85, 0x69, + 0x93, 0x4d, 0x54, 0x74, 0x53, 0xe9, 0xdb, 0x56, 0xd7, 0xc6, 0x8e, 0x53, 0x2a, 0x04, 0x76, 0xe0, + 0x0e, 0x25, 0x65, 0xe7, 0x73, 0x34, 0xec, 0xe3, 0x86, 0x79, 0xc0, 0xc9, 0xd0, 0xcf, 0x01, 0x39, + 0x43, 0xc7, 0xc5, 0x3d, 0x21, 0xe8, 0xb9, 0x6e, 0x6a, 0xa5, 0x22, 0xd5, 0xbb, 0xb7, 0xa7, 0xe8, + 0xdd, 0x21, 0x65, 0x60, 0xe2, 0x76, 0x75, 0x53, 0xe3, 0xa3, 0x48, 0xce, 0x08, 0xdc, 0xd3, 0xbc, + 0xb4, 0x94, 0xd9, 0x89, 0xa7, 0x33, 0x12, 0xec, 0xc4, 0xd3, 0x29, 0x29, 0x5d, 0xfe, 0xf3, 0x28, + 0xdc, 0x62, 0x64, 0x5b, 0x6a, 0x4f, 0x37, 0x86, 0xd7, 0xd5, 0x3c, 0x26, 0x85, 0x6b, 0x1e, 0x3d, + 0x32, 0xba, 0x14, 0xc2, 0xc6, 0x1c, 0x1e, 0x3d, 0x32, 0x02, 0x6b, 0x12, 0x10, 0x7a, 0x04, 0x10, + 0xf0, 0x88, 0x71, 0x7a, 0x56, 0x77, 0xce, 0xcf, 0x96, 0x33, 0x93, 0xfd, 0x60, 0xa6, 0x1d, 0xf0, + 0x7e, 0xf3, 0x42, 0x09, 0x3d, 0x09, 0x54, 0x13, 0xf3, 0x9b, 0xf7, 0xf8, 0x9c, 0x8a, 0x35, 0x46, + 0x20, 0xd8, 0xc3, 0x7e, 0x5a, 0x0b, 0x21, 0xf9, 0x16, 0x95, 0xff, 0x29, 0x0a, 0x0b, 0x0d, 0xd3, + 0xc5, 0xb6, 0x81, 0xd5, 0x97, 0x38, 0xb0, 0x1d, 0x9f, 0x41, 0x46, 0x35, 0xdb, 0xd8, 0x71, 0x2d, + 0xdb, 0x29, 0x45, 0x56, 0x62, 0xab, 0xd9, 0x8d, 0x1f, 0x4e, 0x39, 0x95, 0x49, 0xfc, 0x6b, 0x15, + 0xce, 0xcc, 0x77, 0xd2, 0x17, 0xb6, 0xf8, 0xcf, 0x11, 0x48, 0x0b, 0x2c, 0x7a, 0x00, 0xe9, 0x91, + 0xc0, 0x75, 0x93, 0xaf, 0x26, 0x15, 0xf6, 0xdf, 0x29, 0x97, 0x7b, 0xed, 0xdf, 0x81, 0x34, 0xcd, + 0x9b, 0x14, 0xef, 0x4c, 0x16, 0x05, 0x07, 0x4f, 0xac, 0x82, 0x39, 0x56, 0x8a, 0xd2, 0x36, 0x34, + 0x54, 0x9d, 0x94, 0xfe, 0xc4, 0x28, 0xff, 0x6d, 0xb1, 0x7f, 0x87, 0xe1, 0x04, 0x68, 0x2c, 0x23, + 0x62, 0x7b, 0xc6, 0x77, 0xee, 0x1f, 0x23, 0x30, 0x4f, 0x18, 0x34, 0xac, 0x05, 0xb6, 0xed, 0x1e, + 0x80, 0xee, 0x28, 0x0e, 0x83, 0xd3, 0x15, 0x09, 0x53, 0xc8, 0xe8, 0x0e, 0x27, 0xf7, 0x54, 0x2d, + 0x3a, 0xa6, 0x6a, 0x3f, 0x81, 0x3c, 0xe5, 0x55, 0x8e, 0x07, 0xed, 0xe7, 0xd8, 0x75, 0xe8, 0x0c, + 0x13, 0x9b, 0x0b, 0x7c, 0x86, 0x39, 0x2a, 0x61, 0x93, 0xe1, 0xe4, 0x9c, 0x13, 0xf8, 0x1a, 0xd3, + 0xbe, 0xf8, 0x98, 0xf6, 0xf1, 0x89, 0xff, 0x6f, 0x0c, 0x6e, 0x1d, 0xa8, 0xb6, 0xab, 0x93, 0x08, + 0xa0, 0x9b, 0xdd, 0xc0, 0xec, 0xef, 0x43, 0xd6, 0x1c, 0x08, 0x83, 0x74, 0xf8, 0x81, 0xb0, 0xf9, + 0x81, 0x39, 0xe0, 0x06, 0xe6, 0xa0, 0x3d, 0x88, 0x1b, 0xba, 0xe3, 0xd2, 0x14, 0x21, 0xbb, 0xb1, + 0x31, 0x45, 0x2d, 0x26, 0x8f, 0xb1, 0xb6, 0xa7, 0x3b, 0xae, 0x58, 0x33, 0x91, 0x82, 0x5a, 0x90, + 0xb0, 0x55, 0xb3, 0x8b, 0xa9, 0xbd, 0x64, 0x37, 0x1e, 0x5e, 0x4e, 0x9c, 0x4c, 0x58, 0x45, 0xd8, + 0xa1, 0x72, 0x16, 0xff, 0x26, 0x02, 0x71, 0x32, 0xca, 0x05, 0x26, 0x7d, 0x0b, 0x92, 0x2f, 0x55, + 0x63, 0x80, 0x59, 0x9a, 0x93, 0x93, 0xf9, 0x17, 0xfa, 0x03, 0x28, 0x3a, 0x83, 0xe3, 0x7e, 0x60, + 0x28, 0x1e, 0x47, 0xde, 0xbf, 0xd4, 0xac, 0xbc, 0x8c, 0x3a, 0x2c, 0x8b, 0x1d, 0xc0, 0xe2, 0x0b, + 0x48, 0xd0, 0x59, 0x5f, 0x30, 0xbf, 0xbb, 0x90, 0x73, 0x2d, 0x05, 0x9f, 0xb6, 0x8d, 0x81, 0xa3, + 0xbf, 0x64, 0x9a, 0x92, 0x93, 0xb3, 0xae, 0x55, 0x17, 0x20, 0x74, 0x1f, 0x0a, 0x1d, 0xdb, 0xea, + 0x29, 0xba, 0x29, 0x88, 0x62, 0x94, 0x28, 0x4f, 0xa0, 0x0d, 0x01, 0x0c, 0xa9, 0xec, 0x5f, 0xe7, + 0xa0, 0x48, 0x0d, 0x63, 0x26, 0xb7, 0x77, 0x3f, 0xe0, 0xf6, 0x6e, 0x86, 0xdc, 0x9e, 0x67, 0x5d, + 0xc4, 0xeb, 0xbd, 0x0e, 0xc9, 0x81, 0xa9, 0xbf, 0x18, 0xb0, 0xf1, 0xbd, 0xd0, 0xc7, 0x60, 0x33, + 0x68, 0x25, 0xfa, 0x01, 0x20, 0xe2, 0x0a, 0xb0, 0x12, 0x22, 0x4c, 0x50, 0x42, 0x89, 0x62, 0xaa, + 0x53, 0x3d, 0x68, 0xf2, 0x12, 0x1e, 0x74, 0x1b, 0x24, 0x7c, 0xea, 0xda, 0x6a, 0x30, 0x27, 0x4d, + 0x51, 0xfe, 0x25, 0x12, 0xf6, 0xea, 0x04, 0x37, 0x59, 0x48, 0x01, 0x07, 0x70, 0x1a, 0xd1, 0x92, + 0x79, 0x2e, 0x43, 0xd3, 0x6d, 0x4c, 0x33, 0x29, 0xa7, 0x94, 0x5e, 0x89, 0x5d, 0x90, 0x31, 0x8d, + 0x6c, 0xfb, 0x5a, 0x4d, 0x30, 0xca, 0x12, 0x13, 0xe5, 0x01, 0x1c, 0x74, 0x08, 0xd9, 0x0e, 0x4b, + 0xb0, 0x94, 0xe7, 0x78, 0x48, 0x53, 0xb1, 0xec, 0xc6, 0xbb, 0xb3, 0xa7, 0x62, 0x9b, 0x49, 0x72, + 0x04, 0xa5, 0x88, 0x0c, 0x1d, 0x0f, 0x89, 0x9e, 0x41, 0x3e, 0x90, 0x3d, 0x1f, 0x0f, 0x69, 0xfe, + 0x71, 0x35, 0xb1, 0x39, 0x5f, 0xd0, 0xe6, 0x10, 0x7d, 0x0a, 0xa0, 0x7b, 0x01, 0x80, 0xa6, 0x29, + 0xd9, 0x8d, 0xf7, 0x2e, 0x11, 0x29, 0x84, 0x7f, 0xf1, 0x85, 0xa0, 0x67, 0x50, 0xf0, 0xbf, 0xe8, + 0x64, 0x73, 0x97, 0x9e, 0x2c, 0x93, 0x9a, 0x0f, 0xc8, 0xd9, 0x24, 0xa9, 0xf8, 0x02, 0x49, 0xa0, + 0x2c, 0x47, 0x77, 0x71, 0x50, 0x0d, 0xf2, 0x54, 0x0d, 0xca, 0xe7, 0x67, 0xcb, 0xa8, 0x2a, 0xf0, + 0x93, 0x55, 0x01, 0xb5, 0x47, 0xf0, 0x4c, 0xb1, 0x42, 0x0a, 0x4c, 0x24, 0x16, 0x7c, 0xc5, 0x3a, + 0xf4, 0x55, 0x78, 0x4c, 0xb1, 0x02, 0xea, 0xcd, 0x6a, 0xa7, 0x5c, 0xc8, 0xf7, 0x14, 0xaf, 0xee, + 0x7b, 0x42, 0x82, 0x50, 0x9d, 0x27, 0xc5, 0x12, 0x4d, 0xaf, 0xde, 0x9b, 0x51, 0x49, 0x49, 0xc6, + 0x26, 0x5c, 0x02, 0xcd, 0x95, 0x1f, 0x02, 0x6a, 0xdb, 0x58, 0x75, 0xb1, 0x46, 0x92, 0x52, 0x43, + 0x6f, 0xeb, 0xae, 0x31, 0x2c, 0xcd, 0x07, 0xec, 0x7e, 0x9e, 0xe3, 0xeb, 0x1e, 0x1a, 0x3d, 0x82, + 0xd4, 0x4b, 0x6c, 0x3b, 0xba, 0x65, 0x96, 0x10, 0x75, 0x26, 0x4b, 0xbc, 0x11, 0x72, 0x6b, 0x64, + 0xbc, 0xa7, 0x8c, 0x4a, 0x16, 0xe4, 0x68, 0x1b, 0xf2, 0xd8, 0x6c, 0x5b, 0x9a, 0x6e, 0x76, 0x69, + 0x9a, 0x59, 0xba, 0xe1, 0xe7, 0x3b, 0xdf, 0x9e, 0x2d, 0xbf, 0x36, 0xc2, 0x5f, 0xe7, 0xb4, 0x64, + 0xda, 0x72, 0x0e, 0x07, 0xbe, 0xd0, 0x36, 0xa4, 0x44, 0x4c, 0x5e, 0xa0, 0x7b, 0xba, 0x3a, 0x2d, + 0xc3, 0x1c, 0x8d, 0xe8, 0x7c, 0x5d, 0x82, 0x9d, 0x94, 0x0b, 0x9a, 0xee, 0x90, 0x5c, 0x44, 0x2b, + 0xdd, 0x0c, 0x96, 0x0b, 0x02, 0x8a, 0xaa, 0x00, 0x5d, 0x6c, 0x29, 0xac, 0xb5, 0x54, 0xba, 0x45, + 0x87, 0x5b, 0x0a, 0x0c, 0xd7, 0xc5, 0xd6, 0x9a, 0x68, 0x40, 0x91, 0xfa, 0xb1, 0xa3, 0x77, 0x45, + 0x8a, 0xd0, 0xc5, 0x16, 0x03, 0xa0, 0x32, 0x64, 0xfa, 0x36, 0xd6, 0xf4, 0x36, 0x29, 0xef, 0x6e, + 0x07, 0x7c, 0xb3, 0x0f, 0x2e, 0x2f, 0x41, 0xc6, 0xf3, 0x1a, 0x28, 0x05, 0xb1, 0xca, 0x61, 0x95, + 0x75, 0x13, 0x6a, 0xf5, 0xc3, 0xaa, 0x14, 0x29, 0xdf, 0x85, 0x38, 0x5d, 0x7c, 0x16, 0x52, 0x5b, + 0x2d, 0xf9, 0x59, 0x45, 0xae, 0xb1, 0x0e, 0x46, 0xa3, 0xf9, 0xb4, 0x2e, 0x1f, 0xd5, 0x6b, 0x92, + 0x88, 0x0b, 0xff, 0x12, 0x03, 0xe4, 0x17, 0xb2, 0x47, 0x16, 0x2f, 0x06, 0xbb, 0x50, 0x6c, 0x7b, + 0x50, 0x76, 0x00, 0x91, 0x95, 0xe8, 0x6a, 0x61, 0xe3, 0xd1, 0x77, 0x16, 0xc3, 0x42, 0x46, 0x10, + 0xe4, 0x2b, 0x53, 0xa1, 0x1d, 0x82, 0x06, 0xf2, 0xa1, 0xe8, 0x48, 0x0c, 0x92, 0x21, 0xd1, 0x3e, + 0xc1, 0xed, 0xe7, 0x3c, 0x0a, 0xff, 0x68, 0xca, 0xc0, 0x34, 0x55, 0x0c, 0x28, 0x6e, 0x95, 0xf0, + 0xf8, 0x43, 0x8b, 0xf4, 0x80, 0x8a, 0x42, 0x72, 0xd8, 0xbd, 0xc6, 0x2f, 0xf4, 0x58, 0x93, 0x9a, + 0x2e, 0xc2, 0x63, 0x05, 0xbc, 0xeb, 0x23, 0x28, 0x9a, 0x96, 0xab, 0x90, 0x92, 0x91, 0x7b, 0x01, + 0x5a, 0x08, 0xe6, 0x37, 0x25, 0xae, 0xab, 0xbe, 0xcd, 0xe7, 0x4d, 0xcb, 0x6d, 0x0e, 0x0c, 0x83, + 0x01, 0xca, 0x1f, 0x42, 0x21, 0xbc, 0x47, 0x28, 0x03, 0x89, 0xea, 0x76, 0xbd, 0xba, 0x2b, 0xcd, + 0xa1, 0x22, 0x64, 0xb7, 0x5a, 0x72, 0xbd, 0xf1, 0xb8, 0xa9, 0xec, 0xd6, 0x7f, 0xc6, 0x3a, 0x4e, + 0xcd, 0x96, 0xe8, 0x38, 0x79, 0x55, 0x4e, 0x42, 0x4a, 0x96, 0xff, 0x27, 0x02, 0x85, 0x03, 0x5b, + 0xef, 0xa9, 0xf6, 0x70, 0x17, 0x0f, 0x0f, 0x5f, 0xa9, 0x7d, 0xf4, 0x09, 0x2c, 0x98, 0xf8, 0x95, + 0xd2, 0x67, 0x50, 0xc5, 0xcb, 0x9a, 0x23, 0x93, 0xdb, 0x91, 0xf3, 0x26, 0x7e, 0xc5, 0x25, 0x34, + 0x78, 0xd2, 0xfc, 0x03, 0xc8, 0x5a, 0x86, 0xc6, 0x38, 0xb1, 0x68, 0x09, 0x65, 0x83, 0x4c, 0x60, + 0x19, 0x5a, 0x83, 0xa1, 0x09, 0x35, 0x19, 0x4f, 0x50, 0xc7, 0x26, 0x50, 0x9b, 0xf8, 0x95, 0xa0, + 0xfe, 0x04, 0x16, 0x88, 0xec, 0xb1, 0xd9, 0xc5, 0xa7, 0xcc, 0xce, 0x32, 0xb4, 0xf0, 0xec, 0xb8, + 0xf2, 0xfe, 0x43, 0x04, 0xa8, 0xd3, 0x1e, 0xb8, 0xa2, 0x59, 0x44, 0x17, 0xff, 0x43, 0xc8, 0x93, + 0xc9, 0xf8, 0xb5, 0x52, 0x64, 0xca, 0x79, 0x90, 0x39, 0x0b, 0x0f, 0x4c, 0xb8, 0xc8, 0xa4, 0x7c, + 0xae, 0xe8, 0x34, 0x2e, 0xcb, 0xf0, 0x5a, 0x53, 0xe8, 0x6d, 0xc8, 0xe9, 0x26, 0x71, 0x5a, 0xbc, + 0x56, 0x0f, 0x76, 0x72, 0xb3, 0x1c, 0x43, 0x2a, 0x76, 0x3e, 0xe3, 0x5f, 0x45, 0xe1, 0xf6, 0xbe, + 0xea, 0x62, 0x5b, 0x57, 0x0d, 0xfd, 0x0b, 0xac, 0x3d, 0xd5, 0xf1, 0x2b, 0x19, 0x77, 0x6c, 0xec, + 0x9c, 0xa0, 0xcf, 0x60, 0x7e, 0xec, 0xcc, 0xe8, 0xd4, 0xb3, 0x1b, 0x6f, 0xcd, 0xe6, 0xb5, 0x45, + 0xee, 0x39, 0x72, 0x9a, 0x68, 0x3f, 0x7c, 0x3a, 0x2c, 0x77, 0xbf, 0x9c, 0xcc, 0xe0, 0xf1, 0x3d, + 0x82, 0x84, 0xea, 0x28, 0x56, 0x87, 0x5b, 0xe6, 0x1b, 0x01, 0x41, 0x03, 0x57, 0x37, 0xd6, 0x4e, + 0x8c, 0xf6, 0xda, 0x91, 0x68, 0xdb, 0x0b, 0x9b, 0x56, 0x9d, 0x56, 0x07, 0xbd, 0x0f, 0x45, 0xe7, + 0xc4, 0x1a, 0x18, 0x9a, 0x72, 0xac, 0xb6, 0x9f, 0x77, 0x74, 0xc3, 0x08, 0xf5, 0x5d, 0x0a, 0x0c, + 0xb9, 0xc9, 0x71, 0x7c, 0xcf, 0xfe, 0x22, 0x05, 0xc8, 0x9f, 0xcf, 0xfe, 0xc0, 0x55, 0xa9, 0xd7, + 0xab, 0x40, 0x92, 0x9b, 0x1b, 0xdb, 0xa3, 0xb7, 0xa7, 0x7a, 0xa6, 0x70, 0x9f, 0x69, 0x7b, 0x4e, + 0xe6, 0x8c, 0xe8, 0xa7, 0xc1, 0x2e, 0xfd, 0xcc, 0x3b, 0xb2, 0x3d, 0x27, 0xda, 0xf7, 0xbb, 0x90, + 0x70, 0x5c, 0xe2, 0xa5, 0x63, 0x34, 0xb6, 0xae, 0x4f, 0xe1, 0x1f, 0x9f, 0xfc, 0xda, 0x21, 0x61, + 0x13, 0xbe, 0x89, 0xca, 0x40, 0xcf, 0x20, 0xe3, 0xa5, 0x94, 0xbc, 0xe5, 0xff, 0x70, 0x76, 0x81, + 0x5e, 0x34, 0x10, 0xb1, 0xc2, 0x93, 0x85, 0x2a, 0x90, 0xed, 0x71, 0x32, 0xbf, 0x71, 0xb0, 0xc2, + 0xb3, 0x7a, 0x10, 0x12, 0x68, 0x76, 0x1f, 0xf8, 0x92, 0x41, 0x30, 0x35, 0x68, 0xe4, 0xb3, 0x2d, + 0xc3, 0x20, 0x87, 0x46, 0xdb, 0x98, 0x5e, 0xe4, 0x13, 0x50, 0xb4, 0x4b, 0x72, 0x73, 0xe1, 0xcb, + 0x68, 0x53, 0x32, 0x3b, 0x43, 0xe3, 0x54, 0xc4, 0x8a, 0xed, 0x39, 0x39, 0xc0, 0x8e, 0x5a, 0x50, + 0xe8, 0x87, 0xfc, 0x19, 0x4f, 0x84, 0xef, 0x4f, 0xcb, 0x86, 0x42, 0xc4, 0xdb, 0x73, 0xf2, 0x08, + 0x3b, 0xfa, 0x39, 0xa0, 0xf6, 0x98, 0x9f, 0x28, 0xc1, 0x77, 0xcc, 0x72, 0x94, 0x61, 0x7b, 0x4e, + 0x9e, 0x20, 0x06, 0x7d, 0x0e, 0xb7, 0x7b, 0x93, 0x4d, 0x9a, 0xa7, 0xc4, 0x6b, 0x53, 0x46, 0x98, + 0xe2, 0x08, 0xb6, 0xe7, 0xe4, 0x69, 0x02, 0xcb, 0x9f, 0x40, 0x82, 0xaa, 0x0e, 0x09, 0xec, 0x4f, + 0x9a, 0xbb, 0xcd, 0xd6, 0xb3, 0x26, 0x8b, 0x15, 0xb5, 0xfa, 0x5e, 0xfd, 0xa8, 0xae, 0xb4, 0x9a, + 0x7b, 0x24, 0x56, 0xdc, 0x81, 0x9b, 0x1c, 0x50, 0x69, 0xd6, 0x94, 0x67, 0x72, 0x43, 0xa0, 0xa2, + 0xe5, 0xd5, 0x60, 0xe6, 0x90, 0x86, 0x78, 0xb3, 0xd5, 0xac, 0x4b, 0x73, 0x34, 0x87, 0xa8, 0xd5, + 0xa4, 0x08, 0xcd, 0x21, 0xe4, 0xd6, 0x81, 0x08, 0x31, 0x9b, 0x39, 0x00, 0xcd, 0x53, 0xb7, 0x9d, + 0x78, 0x3a, 0x29, 0xa5, 0xca, 0x7f, 0x1f, 0x81, 0x34, 0x29, 0xc9, 0x1a, 0x66, 0xc7, 0x42, 0x0f, + 0x21, 0xd3, 0x57, 0x6d, 0x6c, 0xba, 0xbe, 0xa7, 0x15, 0x9d, 0xb2, 0xf4, 0x01, 0x45, 0x78, 0x8d, + 0x9c, 0x34, 0x23, 0x6c, 0x5c, 0xd4, 0x06, 0xd9, 0x02, 0x89, 0x8b, 0x73, 0xda, 0x27, 0xb8, 0xa7, + 0x12, 0xa9, 0xac, 0x57, 0xf3, 0xba, 0xd7, 0xa5, 0xa4, 0xf8, 0x43, 0x8a, 0xf6, 0x64, 0x17, 0xfa, + 0x41, 0xa8, 0x88, 0x10, 0xff, 0x79, 0x17, 0x8a, 0x23, 0x19, 0xc2, 0x05, 0x65, 0xef, 0x0a, 0x2d, + 0x7b, 0x63, 0xbe, 0xdf, 0xf7, 0xca, 0xde, 0x28, 0xaf, 0x78, 0x43, 0x8b, 0x8d, 0xcf, 0xb8, 0xd8, + 0x87, 0x7e, 0x16, 0xcc, 0x8c, 0xef, 0x0e, 0x8f, 0x29, 0xf3, 0x17, 0x24, 0xc0, 0x07, 0x30, 0xdf, + 0xb3, 0x34, 0xbd, 0x43, 0xf2, 0x3d, 0x62, 0xb9, 0xae, 0xde, 0x63, 0x57, 0x08, 0x33, 0x3a, 0x5c, + 0x29, 0xc8, 0x4d, 0x90, 0xe8, 0x31, 0xa4, 0x44, 0x77, 0x27, 0x4d, 0x23, 0xc0, 0xac, 0x1e, 0x53, + 0xe4, 0xc1, 0x9c, 0x1b, 0x6d, 0x41, 0xc1, 0xc4, 0xa7, 0xc1, 0x66, 0x64, 0x26, 0xe4, 0x53, 0x72, + 0x4d, 0x7c, 0x3a, 0xb9, 0x13, 0x99, 0x33, 0x7d, 0x8c, 0x86, 0x3e, 0x85, 0x7c, 0x38, 0xd8, 0xc1, + 0x15, 0x82, 0x5d, 0xae, 0x1f, 0x8c, 0x74, 0x5b, 0x90, 0x12, 0x51, 0x2e, 0x7b, 0x85, 0x28, 0x27, + 0x98, 0xd1, 0x26, 0x49, 0x21, 0x4e, 0x5d, 0x3f, 0x35, 0xc9, 0xf9, 0xe5, 0xcb, 0xf9, 0xd9, 0x72, + 0x96, 0xac, 0x70, 0x42, 0xcb, 0x31, 0x6b, 0x7a, 0x70, 0x0d, 0xed, 0x00, 0x78, 0x17, 0xd3, 0x0e, + 0xed, 0xb4, 0x4f, 0x2f, 0x63, 0x0f, 0x04, 0xa1, 0x3f, 0x25, 0x39, 0xc0, 0x8d, 0xf6, 0x21, 0x23, + 0xdc, 0x31, 0x2b, 0x30, 0xa7, 0xfb, 0xad, 0xf1, 0xe0, 0x20, 0x42, 0x82, 0x27, 0x81, 0xe4, 0xd6, + 0x06, 0x56, 0x1d, 0xcc, 0xab, 0xcc, 0x47, 0x33, 0xe6, 0xd6, 0xcc, 0xb8, 0xaa, 0x27, 0xaa, 0xd9, + 0xc5, 0x7b, 0x84, 0x7f, 0x33, 0x5a, 0x8a, 0xc8, 0x4c, 0x14, 0x6a, 0x82, 0x44, 0xb7, 0x2c, 0x18, + 0x6b, 0x24, 0xba, 0x6b, 0x6f, 0x0a, 0xc3, 0x25, 0xbb, 0x36, 0x35, 0xde, 0x50, 0x9d, 0xda, 0xf7, + 0x63, 0xce, 0xef, 0x42, 0xa1, 0x63, 0xd9, 0x3d, 0xd5, 0x55, 0x84, 0xf1, 0xcc, 0xfb, 0xfd, 0xa8, + 0x6f, 0xcf, 0x96, 0xf3, 0x5b, 0x14, 0x2b, 0x0c, 0x27, 0xdf, 0x09, 0x7e, 0xa2, 0x4d, 0x11, 0x9a, + 0x6f, 0xd0, 0x48, 0xfa, 0xd6, 0x77, 0x6e, 0xd6, 0x84, 0x88, 0xdc, 0x84, 0x24, 0x2d, 0x1b, 0x9c, + 0xd2, 0x02, 0xdd, 0xf1, 0x2b, 0x96, 0x20, 0x32, 0x97, 0x82, 0xf6, 0xa0, 0xa0, 0x11, 0x08, 0xa9, + 0x69, 0x59, 0xa7, 0xeb, 0x26, 0x95, 0xbb, 0x3c, 0x45, 0xae, 0x70, 0xb1, 0xa2, 0xa1, 0x21, 0x98, + 0x59, 0x37, 0xac, 0x05, 0xe9, 0x8e, 0xda, 0xd3, 0x0d, 0x1d, 0x3b, 0xa5, 0x5b, 0x54, 0xce, 0xfb, + 0x17, 0xda, 0xf3, 0xe8, 0xad, 0x87, 0x08, 0xe1, 0x42, 0x88, 0x67, 0xd6, 0x14, 0x30, 0x24, 0xc7, + 0x77, 0x7b, 0xdc, 0xac, 0xc5, 0xad, 0x47, 0xe8, 0x06, 0x84, 0x9a, 0x35, 0xff, 0xd2, 0xd0, 0x3d, + 0x80, 0x97, 0x3a, 0x7e, 0xa5, 0xbc, 0x18, 0x60, 0x7b, 0x58, 0x2a, 0x05, 0x0b, 0x58, 0x02, 0xff, + 0x94, 0x80, 0xd1, 0x07, 0x90, 0xd1, 0x70, 0x1f, 0x9b, 0x9a, 0xd3, 0x32, 0x4b, 0x77, 0x68, 0xb9, + 0x70, 0xe3, 0xfc, 0x6c, 0x39, 0x53, 0x13, 0x40, 0xee, 0x45, 0x7d, 0x2a, 0xf4, 0x39, 0xe4, 0xd8, + 0x07, 0xd6, 0x5a, 0xe6, 0xe6, 0xb0, 0xb4, 0x48, 0x17, 0xfd, 0x60, 0xc6, 0x43, 0xf1, 0xdb, 0x43, + 0x5e, 0x47, 0xbd, 0x16, 0x90, 0x26, 0x87, 0x64, 0xa3, 0xdf, 0x87, 0x9c, 0xd0, 0xe3, 0x1d, 0xeb, + 0xd8, 0x29, 0xbd, 0x76, 0x61, 0xbb, 0x7b, 0x74, 0xac, 0x7d, 0x9f, 0x55, 0x78, 0xa9, 0xa0, 0x34, + 0xf4, 0x19, 0xe4, 0xbd, 0x8b, 0x3b, 0xab, 0xef, 0x3a, 0xa5, 0xd7, 0xa9, 0x19, 0x3e, 0x9c, 0xd5, + 0x0c, 0x39, 0x6f, 0xab, 0x4f, 0x6f, 0x02, 0x02, 0x5f, 0xe8, 0x2e, 0x64, 0x34, 0xdb, 0xea, 0xb3, + 0x68, 0xf1, 0xc6, 0x4a, 0x64, 0x35, 0xe6, 0xf5, 0x28, 0x6c, 0xab, 0x4f, 0xc3, 0x80, 0x02, 0x05, + 0x1b, 0xf7, 0x0d, 0xb5, 0x8d, 0x7b, 0x24, 0x8e, 0x59, 0x9d, 0xd2, 0x12, 0x1d, 0x7d, 0x63, 0xe6, + 0x8d, 0xf4, 0x98, 0x85, 0x62, 0x06, 0xe4, 0xb5, 0x3a, 0xe8, 0x09, 0x80, 0x3a, 0xd0, 0x74, 0x57, + 0xe9, 0x59, 0x1a, 0x2e, 0x2d, 0x5f, 0x78, 0x9b, 0x3c, 0x2a, 0xbc, 0x42, 0x18, 0xf7, 0x2d, 0x0d, + 0x7b, 0x77, 0x47, 0x02, 0x80, 0x3e, 0x80, 0x2c, 0x5d, 0xda, 0xe7, 0xd6, 0x31, 0xd1, 0xcd, 0x15, + 0xba, 0xb8, 0x79, 0x7e, 0x96, 0x99, 0x9a, 0x6d, 0xf5, 0x77, 0xac, 0x63, 0xaa, 0x31, 0xfc, 0xa7, + 0x86, 0x1c, 0xc8, 0x75, 0xdb, 0x8a, 0xef, 0x38, 0xef, 0xd2, 0x53, 0xfc, 0x68, 0xc6, 0xb9, 0x3c, + 0xae, 0x4e, 0x70, 0xa5, 0x37, 0x44, 0x04, 0x78, 0x5c, 0x15, 0x30, 0x47, 0xce, 0x76, 0xdb, 0xde, + 0x07, 0xa9, 0x08, 0x59, 0x23, 0x8c, 0x1b, 0x40, 0x39, 0x58, 0x11, 0x32, 0x0c, 0x33, 0x81, 0x26, + 0xf0, 0x8e, 0x99, 0x42, 0xab, 0x29, 0x76, 0x66, 0xf7, 0x66, 0x8f, 0xf0, 0x05, 0xc6, 0x5d, 0x71, + 0x5a, 0x1d, 0x7a, 0xb0, 0x6d, 0xc8, 0x59, 0x03, 0xf7, 0xd8, 0x1a, 0x98, 0x9a, 0xd2, 0x79, 0xee, + 0x94, 0xde, 0xa4, 0xab, 0xbd, 0x54, 0x77, 0xc3, 0x5b, 0x5d, 0x8b, 0x0b, 0xda, 0xda, 0x75, 0xe4, + 0xac, 0x90, 0xba, 0xf5, 0xdc, 0x41, 0xbf, 0x80, 0xac, 0x6e, 0xfa, 0x63, 0xdc, 0xbf, 0xfc, 0x18, + 0x48, 0x54, 0x1e, 0x0d, 0xd3, 0x1b, 0x02, 0xb8, 0x4c, 0x32, 0xc2, 0x7b, 0x50, 0xb0, 0x3a, 0x1d, + 0x43, 0x37, 0xb1, 0x62, 0x63, 0xd5, 0xb1, 0xcc, 0xd2, 0x5b, 0x81, 0x1d, 0xcc, 0x73, 0x9c, 0x4c, + 0x51, 0xa8, 0x0c, 0x19, 0x17, 0xf7, 0xfa, 0x96, 0xad, 0xda, 0xc3, 0xd2, 0xdb, 0xc1, 0x2b, 0x37, + 0x0f, 0x8c, 0x8e, 0x61, 0x71, 0x60, 0xe2, 0xd3, 0xbe, 0xe5, 0x60, 0x4d, 0x19, 0xcb, 0x2d, 0x57, + 0xa9, 0x8f, 0xbb, 0xcf, 0x27, 0x75, 0xfb, 0x89, 0xa0, 0x9c, 0x98, 0x64, 0xde, 0x1e, 0x4c, 0x44, + 0x6b, 0xe8, 0x47, 0xb0, 0xa0, 0x3b, 0x4a, 0x30, 0x6b, 0x57, 0x88, 0xaf, 0x2b, 0xbd, 0x13, 0x98, + 0x12, 0xd2, 0x9d, 0xd1, 0x8c, 0x7f, 0xf1, 0x97, 0x11, 0x98, 0x1f, 0x8b, 0xaa, 0xe8, 0x0f, 0x21, + 0x65, 0x5a, 0x5a, 0xe0, 0x62, 0xb4, 0xce, 0xa7, 0x97, 0x6c, 0x5a, 0x1a, 0xbb, 0x17, 0x7d, 0xd8, + 0xd5, 0xdd, 0x93, 0xc1, 0xf1, 0x5a, 0xdb, 0xea, 0xad, 0x7b, 0x9b, 0xaf, 0x1d, 0xfb, 0xbf, 0xd7, + 0xfb, 0xcf, 0xbb, 0xeb, 0xf4, 0x57, 0xff, 0x78, 0x8d, 0xb1, 0xc9, 0x49, 0x22, 0xb5, 0xa1, 0x91, + 0x32, 0x1c, 0x9f, 0xf6, 0x75, 0x3b, 0x90, 0x59, 0x46, 0x03, 0xbe, 0xa2, 0xe0, 0x23, 0x89, 0x62, + 0xf1, 0xab, 0xab, 0x5f, 0x45, 0xa1, 0x38, 0x12, 0xd9, 0x48, 0x2a, 0x4d, 0xbb, 0x1e, 0xa1, 0x54, + 0x9a, 0x40, 0x2e, 0x48, 0xf0, 0x83, 0x0f, 0x6c, 0x62, 0xd7, 0x7d, 0x60, 0x13, 0xbe, 0x12, 0x4a, + 0x5c, 0xe2, 0x4a, 0xe8, 0x27, 0x70, 0x4b, 0x77, 0x14, 0xd3, 0x32, 0x45, 0xe7, 0xce, 0x2b, 0x5e, + 0x83, 0xcf, 0x38, 0x6e, 0xe8, 0x4e, 0xd3, 0x32, 0x59, 0xcf, 0xce, 0x5b, 0xb5, 0xff, 0xe2, 0x23, + 0x35, 0xfe, 0xe2, 0xc3, 0xeb, 0xcc, 0xc5, 0xa5, 0xc4, 0xe2, 0x57, 0x11, 0xc8, 0x04, 0x9f, 0x0d, + 0x46, 0xc3, 0xcd, 0xa8, 0xb1, 0xf2, 0xe2, 0x8a, 0x17, 0xdc, 0xe1, 0x5d, 0x88, 0xcd, 0xbe, 0x0b, + 0xfc, 0x68, 0xff, 0x08, 0xb2, 0x81, 0x90, 0x35, 0xda, 0x30, 0x88, 0x5c, 0xa1, 0x61, 0xf0, 0x26, + 0x24, 0xb9, 0x9f, 0x66, 0x8a, 0x95, 0xe7, 0xdc, 0x09, 0xe6, 0xa3, 0x13, 0x9f, 0x13, 0xff, 0xcc, + 0x47, 0xff, 0xef, 0x18, 0xe4, 0x82, 0x21, 0x8d, 0x18, 0xb5, 0x6e, 0xb6, 0x6d, 0x1a, 0x4f, 0xe8, + 0xe8, 0x31, 0xef, 0x1e, 0x5d, 0x80, 0x49, 0xa0, 0xeb, 0xe9, 0xa6, 0x42, 0xef, 0x6e, 0x43, 0xca, + 0x9b, 0xee, 0xe9, 0xe6, 0x53, 0x02, 0xa5, 0x24, 0xea, 0x29, 0x27, 0x89, 0x85, 0x48, 0xd4, 0x53, + 0x46, 0xb2, 0x48, 0xb3, 0x44, 0xdb, 0xa5, 0xa5, 0x5c, 0x2c, 0x90, 0xfd, 0xd9, 0x2e, 0x5a, 0x82, + 0xd4, 0x4b, 0xdd, 0x76, 0x07, 0xaa, 0x41, 0xab, 0x36, 0x71, 0xcc, 0x02, 0x88, 0x4c, 0x28, 0xf8, + 0x41, 0xfc, 0x95, 0x89, 0x6d, 0xaa, 0x38, 0xd9, 0x8d, 0xca, 0x15, 0xa2, 0xb8, 0xff, 0x41, 0x04, + 0x09, 0x57, 0xe7, 0x04, 0x81, 0x24, 0xad, 0x6a, 0xab, 0xed, 0x13, 0xac, 0x38, 0xfa, 0x17, 0xac, + 0x12, 0xf4, 0xb6, 0x85, 0xc2, 0x0f, 0xf5, 0x2f, 0xf0, 0xe2, 0xdf, 0x45, 0x20, 0x1f, 0x92, 0x85, + 0x1a, 0x50, 0xa4, 0xb3, 0x1b, 0x6b, 0x87, 0xde, 0xf5, 0x5e, 0x09, 0x12, 0xf4, 0xc4, 0x72, 0x2d, + 0x6f, 0x05, 0x50, 0x1a, 0xfa, 0x04, 0x0a, 0x4c, 0x94, 0xf7, 0x6c, 0x23, 0xac, 0xa3, 0x39, 0x2a, + 0x29, 0xfc, 0x76, 0x23, 0x67, 0xf9, 0x30, 0x2d, 0x78, 0x23, 0xbd, 0x68, 0x42, 0x36, 0x90, 0x4a, + 0xcc, 0x60, 0x1c, 0x3f, 0x86, 0xb8, 0xe7, 0xaa, 0x66, 0xed, 0x3a, 0xba, 0xbe, 0xff, 0xfa, 0x32, + 0x02, 0x0b, 0x93, 0x42, 0x7a, 0xc8, 0xe8, 0x98, 0xb6, 0xcd, 0x64, 0x74, 0xf7, 0x82, 0xa9, 0x16, + 0xd3, 0x40, 0x71, 0x4b, 0xea, 0x27, 0x5b, 0x6f, 0x79, 0x76, 0xc0, 0x14, 0xb0, 0x18, 0xb2, 0x03, + 0x52, 0x3c, 0x05, 0x2c, 0xa1, 0xbc, 0x0a, 0x19, 0x2f, 0x01, 0x42, 0x39, 0x48, 0xd7, 0x1a, 0x87, + 0x95, 0xcd, 0xbd, 0x7a, 0x4d, 0x9a, 0x43, 0x79, 0xc8, 0xc8, 0xf5, 0x4a, 0x8d, 0xb6, 0x72, 0xa4, + 0xc8, 0x87, 0xe9, 0x3f, 0xf9, 0x72, 0x39, 0xc2, 0x1d, 0x4d, 0x52, 0x4a, 0xed, 0xc4, 0xd3, 0x48, + 0xba, 0x51, 0xfe, 0xb3, 0x24, 0xa0, 0x9a, 0xea, 0xaa, 0x44, 0xdf, 0x2e, 0xd1, 0xf0, 0x88, 0x5e, + 0xb0, 0xe9, 0xe1, 0x22, 0x36, 0x76, 0xad, 0x22, 0x76, 0x62, 0x4b, 0x23, 0x7e, 0x9d, 0x96, 0xc6, + 0x95, 0x3a, 0x2b, 0xe3, 0x65, 0x58, 0xf2, 0x1a, 0x65, 0xd8, 0x53, 0x48, 0xb1, 0x64, 0x82, 0xbd, + 0x28, 0x98, 0x5e, 0x25, 0x8e, 0x1f, 0x0c, 0xaf, 0xa7, 0x9d, 0xba, 0xe9, 0xda, 0x43, 0xef, 0xb2, + 0x91, 0xc1, 0xfc, 0x02, 0x36, 0x7d, 0xf5, 0x02, 0x76, 0x3c, 0x95, 0xca, 0x4c, 0x4d, 0xa5, 0x16, + 0x8f, 0x00, 0x78, 0x3a, 0x63, 0x76, 0xac, 0x19, 0xcc, 0x71, 0x09, 0x52, 0x44, 0xcd, 0xfb, 0x98, + 0x29, 0x90, 0xe7, 0x1f, 0x39, 0x90, 0x5b, 0x5d, 0x1f, 0x72, 0xc1, 0x55, 0x22, 0x09, 0x62, 0xcf, + 0xf1, 0x90, 0xa9, 0xa2, 0x4c, 0x7e, 0xa2, 0x1d, 0x48, 0xf8, 0x5e, 0x7c, 0xfa, 0x4b, 0xb3, 0xa9, + 0xdb, 0x47, 0xa6, 0x2b, 0x33, 0x11, 0x1f, 0x46, 0x1f, 0x05, 0x4c, 0xa3, 0xfc, 0xa7, 0x00, 0x85, + 0xa3, 0x61, 0x3f, 0x68, 0x0a, 0x57, 0x6a, 0x56, 0x4e, 0x6a, 0x49, 0x46, 0x2f, 0xdf, 0x92, 0xbc, + 0xe0, 0xb5, 0x3f, 0xdb, 0xed, 0xf8, 0x05, 0xbb, 0x5d, 0x83, 0x38, 0x7d, 0x24, 0x99, 0xa0, 0xda, + 0x30, 0xcd, 0x02, 0xc3, 0xab, 0x5d, 0x0b, 0xbc, 0x93, 0xa4, 0xdc, 0xe8, 0x67, 0x90, 0xc3, 0xe6, + 0xa0, 0xa7, 0xf4, 0x70, 0xef, 0x18, 0xdb, 0x42, 0xf1, 0x1f, 0xcc, 0x26, 0xad, 0x6e, 0x0e, 0x7a, + 0xfb, 0x94, 0x51, 0x54, 0x33, 0xd8, 0x83, 0x38, 0xe8, 0x01, 0x24, 0x54, 0x43, 0xa7, 0x56, 0xf0, + 0x5d, 0x8f, 0x6f, 0x19, 0x21, 0xfa, 0x18, 0xf2, 0xaa, 0x6d, 0xab, 0x43, 0xfe, 0x8c, 0x54, 0xa3, + 0x9a, 0xce, 0x4d, 0x98, 0xd4, 0x20, 0x15, 0x82, 0xa4, 0x2f, 0x47, 0xc5, 0x46, 0x64, 0x55, 0x0f, + 0x14, 0xea, 0xaa, 0x66, 0xae, 0xd7, 0x55, 0x85, 0xeb, 0xb8, 0xa0, 0x71, 0x6f, 0x92, 0xbd, 0x86, + 0x37, 0xf9, 0x05, 0x2c, 0x8a, 0x17, 0x36, 0x44, 0xa0, 0xdf, 0x79, 0x0f, 0x3c, 0xf0, 0x2d, 0x9f, + 0x9f, 0x2d, 0x97, 0x64, 0x9f, 0xca, 0x5f, 0x2e, 0x4b, 0xf4, 0xc8, 0x4e, 0x95, 0xec, 0x89, 0x78, + 0x2d, 0xe0, 0x57, 0xf2, 0x57, 0xf7, 0x2b, 0xe1, 0xa0, 0x50, 0xb8, 0x56, 0x50, 0x18, 0xf7, 0x51, + 0xc5, 0xe9, 0x3e, 0xea, 0xaf, 0xa2, 0x00, 0xbe, 0x1a, 0xa2, 0x1f, 0xc3, 0xed, 0xfe, 0xc9, 0xd0, + 0xd1, 0xdb, 0xaa, 0xa1, 0xd8, 0xb8, 0x6f, 0x63, 0x07, 0x9b, 0x2c, 0xa8, 0x53, 0xdb, 0xce, 0xc9, + 0xb7, 0x04, 0x5a, 0x0e, 0x61, 0xd1, 0x47, 0x70, 0xcb, 0xb0, 0xba, 0x93, 0xf8, 0x82, 0xf5, 0xca, + 0x4d, 0x4e, 0x33, 0xc2, 0xac, 0x92, 0x44, 0xac, 0xaf, 0x1e, 0xeb, 0x86, 0x5f, 0xc2, 0x7c, 0x74, + 0x59, 0x13, 0x5a, 0xab, 0x7a, 0x22, 0xc4, 0x0d, 0xab, 0x2f, 0xb4, 0xfc, 0x26, 0x80, 0x8f, 0xa7, + 0x77, 0x33, 0x7b, 0x7b, 0x7e, 0x12, 0xc0, 0x6f, 0x79, 0x78, 0xd2, 0xf0, 0x1a, 0xc4, 0x89, 0x9d, + 0xa3, 0x34, 0xc4, 0xeb, 0xcd, 0x27, 0xfb, 0xd2, 0x1c, 0xca, 0x40, 0xa2, 0xb2, 0xd7, 0xa8, 0x1c, + 0x06, 0xf3, 0x84, 0xf2, 0xdf, 0xc6, 0x41, 0x62, 0x9e, 0xe8, 0xba, 0xee, 0x70, 0x7a, 0x69, 0xf7, + 0xdd, 0xf7, 0x27, 0x61, 0xcd, 0x89, 0x7f, 0xff, 0xe9, 0x44, 0xe2, 0x7b, 0x4a, 0x27, 0x92, 0xd7, + 0x48, 0x27, 0x52, 0xd7, 0x70, 0x00, 0xbf, 0xed, 0xb0, 0x1f, 0xd0, 0x90, 0xaf, 0xa2, 0x00, 0x01, + 0xdd, 0xf8, 0x69, 0xf0, 0x8f, 0xdc, 0xa6, 0x5f, 0xa4, 0x8c, 0x94, 0x35, 0xdb, 0x73, 0xe2, 0x4f, + 0xe0, 0x1e, 0x43, 0x5a, 0xe3, 0x31, 0x9b, 0x87, 0xf6, 0x77, 0x66, 0x0e, 0xed, 0xdb, 0x73, 0xb2, + 0xc7, 0x8c, 0x3e, 0x0a, 0xfd, 0x55, 0xc7, 0xfd, 0x99, 0x2c, 0x6d, 0x5b, 0x3c, 0x5b, 0xab, 0x40, + 0x92, 0x05, 0x6d, 0xae, 0x6c, 0x53, 0xff, 0xbc, 0x60, 0xc4, 0x34, 0xb6, 0xe7, 0x64, 0xce, 0xc8, + 0xef, 0x41, 0x53, 0x90, 0x18, 0x98, 0xba, 0x65, 0xbe, 0x2b, 0x07, 0x1f, 0x4c, 0x89, 0xc6, 0x04, + 0x31, 0x4d, 0xfa, 0x5b, 0x75, 0xb1, 0xc6, 0x6e, 0x64, 0x9f, 0x98, 0x2f, 0x3d, 0x40, 0x04, 0x15, + 0x00, 0x38, 0x5e, 0x37, 0xbb, 0x52, 0x94, 0x66, 0xf7, 0x24, 0x51, 0x22, 0x5f, 0xb1, 0x77, 0x3f, + 0x06, 0x69, 0xf4, 0xef, 0x1b, 0x02, 0x77, 0xb3, 0xf3, 0x90, 0xdf, 0x7f, 0x5a, 0xad, 0x1e, 0x35, + 0xf6, 0xeb, 0x87, 0x47, 0x95, 0xfd, 0x03, 0xf6, 0x18, 0xe8, 0x88, 0x94, 0x06, 0xad, 0x46, 0x4d, + 0x8a, 0xbe, 0xfb, 0x31, 0x14, 0x47, 0x14, 0x02, 0x01, 0x24, 0x0f, 0x9e, 0x6c, 0xee, 0x35, 0xaa, + 0x13, 0xef, 0x76, 0x51, 0x16, 0x52, 0xad, 0xad, 0xad, 0xbd, 0x46, 0xb3, 0x2e, 0xc5, 0x36, 0x57, + 0xbf, 0xfe, 0xf7, 0xa5, 0xb9, 0xaf, 0xcf, 0x97, 0x22, 0xbf, 0x3e, 0x5f, 0x8a, 0xfc, 0xe6, 0x7c, + 0x29, 0xf2, 0x6f, 0xe7, 0x4b, 0x91, 0xbf, 0xfc, 0x66, 0x69, 0xee, 0xd7, 0xdf, 0x2c, 0xcd, 0xfd, + 0xe6, 0x9b, 0xa5, 0xb9, 0xdf, 0x4b, 0xb2, 0x3f, 0xb4, 0xfc, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x1f, 0x29, 0x10, 0x52, 0xd3, 0x39, 0x00, 0x00, } diff --git a/pkg/sql/catalog/descpb/structured.proto b/pkg/sql/catalog/descpb/structured.proto index f9f7ffe63ece..abb7b451ae6c 100644 --- a/pkg/sql/catalog/descpb/structured.proto +++ b/pkg/sql/catalog/descpb/structured.proto @@ -955,6 +955,10 @@ message TableDescriptor { } optional SequenceOwner sequence_owner = 6 [(gogoproto.nullable) = false]; + + // The number of values (which have already been created in KV) + // that a node can cache locally. + optional int64 cache_size = 7 [(gogoproto.nullable) = false]; } // The presence of sequence_opts indicates that this descriptor is for a sequence. diff --git a/pkg/sql/catalog/systemschema/system.go b/pkg/sql/catalog/systemschema/system.go index ddb13b047e3e..19a6aa32e925 100644 --- a/pkg/sql/catalog/systemschema/system.go +++ b/pkg/sql/catalog/systemschema/system.go @@ -628,6 +628,7 @@ var ( MinValue: 1, MaxValue: math.MaxInt64, Start: 1, + CacheSize: 1, }, Privileges: descpb.NewCustomSuperuserPrivilegeDescriptor( descpb.SystemAllowedPrivileges[keys.DescIDSequenceID], security.NodeUser), diff --git a/pkg/sql/exec_util.go b/pkg/sql/exec_util.go index c5af209f1e15..304d6fa7af43 100644 --- a/pkg/sql/exec_util.go +++ b/pkg/sql/exec_util.go @@ -2278,6 +2278,11 @@ func (m *sessionDataMutator) SetNoticeDisplaySeverity(severity pgnotice.DisplayS m.data.NoticeDisplaySeverity = severity } +// initSequenceCache creates an empty sequence cache instance for the session. +func (m *sessionDataMutator) initSequenceCache() { + m.data.SequenceCache = sessiondata.SequenceCache{} +} + type sqlStatsCollector struct { // sqlStats tracks per-application statistics for all applications on each // node. diff --git a/pkg/sql/logictest/testdata/logic_test/sequences b/pkg/sql/logictest/testdata/logic_test/sequences index d09f2e28d079..93214fbadbd6 100644 --- a/pkg/sql/logictest/testdata/logic_test/sequences +++ b/pkg/sql/logictest/testdata/logic_test/sequences @@ -96,20 +96,11 @@ CREATE SEQUENCE limit_test MAXVALUE 10 START WITH 11 statement error pgcode 22023 START value \(5\) cannot be less than MINVALUE \(10\) CREATE SEQUENCE limit_test MINVALUE 10 START WITH 5 -statement error pgcode 22023 CACHE \(-1\) must be greater than zero -CREATE SEQUENCE cache_test CACHE -1 - -statement error pgcode 22023 CACHE \(0\) must be greater than zero -CREATE SEQUENCE cache_test CACHE 0 - -statement error pgcode 0A000 CACHE values larger than 1 are not supported, found 5 -CREATE SEQUENCE cache_test CACHE 5 - statement error pgcode 0A000 CYCLE option is not supported CREATE SEQUENCE cycle_test CYCLE statement ok -CREATE SEQUENCE ignored_options_test CACHE 1 NO CYCLE +CREATE SEQUENCE ignored_options_test NO CYCLE # Verify presence in crdb_internal.create_statements. @@ -120,7 +111,7 @@ query ITTITTTTTTTB colnames SELECT * FROM crdb_internal.create_statements WHERE descriptor_name = 'show_create_test' ---- database_id database_name schema_name descriptor_id descriptor_type descriptor_name create_statement state create_nofks alter_statements validate_statements has_partitions -52 test public 66 sequence show_create_test CREATE SEQUENCE public.show_create_test MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 PUBLIC CREATE SEQUENCE public.show_create_test MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 {} {} false +52 test public 63 sequence show_create_test CREATE SEQUENCE public.show_create_test MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 PUBLIC CREATE SEQUENCE public.show_create_test MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 {} {} false query TT colnames SHOW CREATE SEQUENCE show_create_test @@ -1279,7 +1270,13 @@ ALTER SEQUENCE db2.seq OWNED BY db1.t.a statement ok CREATE SEQUENCE db2.seq2 OWNED BY db1.t.a +statement error relation "" does not exist +ALTER SEQUENCE db2.seq2 OWNED BY doesntexist + # Unit test for #60737 +# Test that passing a descriptor other than a sequence +# returns an appropriate error. +subtest invalid_ids statement ok CREATE SEQUENCE s1 MINVALUE -4 START WITH -2 CACHE 1 INCREMENT BY -2; @@ -1329,3 +1326,76 @@ DROP SEQUENCE s1 statement ok DROP TABLE s2 +statement error does not exist +SELECT currval(12345::regclass) # Bogus ID + +subtest cached_sequences + +statement error pgcode 22023 CACHE \(-1\) must be greater than zero +CREATE SEQUENCE cache_test CACHE -1 + +statement error pgcode 22023 CACHE \(0\) must be greater than zero +CREATE SEQUENCE cache_test CACHE 0 + +statement ok +CREATE SEQUENCE cache_test CACHE 10 INCREMENT 1 + +# Verify cache invalidation with schema changes. + +# 10 values (1,2,...,10) are cached, and the underlying sequence is incremented to 10. +query I +SELECT nextval('cache_test') +---- +1 + +# sanity checks +query I +SELECT lastval() +---- +1 + +query I +SELECT currval('cache_test') +---- +1 + +query I +SELECT last_value FROM cache_test +---- +10 + +statement ok +BEGIN + +statement ok +ALTER SEQUENCE cache_test INCREMENT 5 + +# The cache is invalidated due to the above schema change, and 10 new values (15,20,...,60) are cached. +query I +SELECT nextval('cache_test') +---- +15 + +# Rollback the schema change to use the old INCREMENT amount. +statement ok +ABORT + +# The underlying sequence was still incremented despite the txn being aborted. +query I +SELECT last_value FROM cache_test +---- +60 + +# 10 new values (61,62,...,70) are cached. +query I +SELECT nextval('cache_test') +---- +61 + +query I +SELECT last_value FROM cache_test +---- +70 + +statement ok +DROP SEQUENCE cache_test diff --git a/pkg/sql/planner.go b/pkg/sql/planner.go index b3613a55114f..93313fc43b8b 100644 --- a/pkg/sql/planner.go +++ b/pkg/sql/planner.go @@ -448,6 +448,16 @@ func (p *planner) ExecCfg() *ExecutorConfig { return p.extendedEvalCtx.ExecCfg } +// GetOrInitSequenceCache returns the sequence cache for the session. +// If the sequence cache has not been used yet, it initializes the cache +// inside the session data. +func (p *planner) GetOrInitSequenceCache() sessiondata.SequenceCache { + if p.SessionData().SequenceCache == nil { + p.sessionDataMutator.initSequenceCache() + } + return p.SessionData().SequenceCache +} + func (p *planner) LeaseMgr() *lease.Manager { return p.Descriptors().LeaseManager() } diff --git a/pkg/sql/sequence.go b/pkg/sql/sequence.go index b1e428d5a349..3ffc2dbbec6a 100644 --- a/pkg/sql/sequence.go +++ b/pkg/sql/sequence.go @@ -87,27 +87,66 @@ func (p *planner) IncrementSequence(ctx context.Context, seqName *tree.TableName } seqOpts := descriptor.SequenceOpts + var val int64 if seqOpts.Virtual { rowid := builtins.GenerateUniqueInt(p.EvalContext().NodeID.SQLInstanceID()) val = int64(rowid) } else { + val, err = p.incrementSequenceUsingCache(ctx, descriptor) + } + if err != nil { + return 0, err + } + + p.ExtendedEvalContext().SessionMutator.RecordLatestSequenceVal(uint32(descriptor.ID), val) + + return val, nil +} + +// incrementSequenceUsingCache fetches the next value of the sequence +// represented by the passed catalog.TableDescriptor. If the sequence has a +// cache size of greater than 1, then this function will read cached values +// from the session data and repopulate these values when the cache is empty. +func (p *planner) incrementSequenceUsingCache( + ctx context.Context, descriptor catalog.TableDescriptor, +) (int64, error) { + seqOpts := descriptor.GetSequenceOpts() + + cacheSize := seqOpts.EffectiveCacheSize() + + fetchNextValues := func() (currentValue int64, incrementAmount int64, sizeOfCache int64, err error) { seqValueKey := p.ExecCfg().Codec.SequenceKey(uint32(descriptor.ID)) - val, err = kv.IncrementValRetryable( - ctx, p.txn.DB(), seqValueKey, seqOpts.Increment) + + endValue, err := kv.IncrementValRetryable( + ctx, p.txn.DB(), seqValueKey, seqOpts.Increment*cacheSize) + if err != nil { if errors.HasType(err, (*roachpb.IntegerOverflowError)(nil)) { - return 0, boundsExceededError(descriptor) + return 0, 0, 0, boundsExceededError(descriptor) } - return 0, err + return 0, 0, 0, err } - if val > seqOpts.MaxValue || val < seqOpts.MinValue { - return 0, boundsExceededError(descriptor) + if endValue > seqOpts.MaxValue || endValue < seqOpts.MinValue { + return 0, 0, 0, boundsExceededError(descriptor) } - } - p.ExtendedEvalContext().SessionMutator.RecordLatestSequenceVal(uint32(descriptor.ID), val) + return endValue - seqOpts.Increment*(cacheSize-1), seqOpts.Increment, cacheSize, nil + } + var val int64 + var err error + if cacheSize == 1 { + val, _, _, err = fetchNextValues() + if err != nil { + return 0, err + } + } else { + val, err = p.GetOrInitSequenceCache().NextValue(uint32(descriptor.GetID()), uint32(descriptor.GetVersion()), fetchNextValues) + if err != nil { + return 0, err + } + } return val, nil } @@ -262,6 +301,8 @@ func assignSequenceOptions( opts.MaxValue = -1 opts.Start = opts.MaxValue } + // No Caching + opts.CacheSize = 1 } // Fill in all other options. @@ -289,8 +330,7 @@ func assignSequenceOptions( case v == 1: // Do nothing; this is the default. case v > 1: - return unimplemented.NewWithIssuef(32567, - "CACHE values larger than 1 are not supported, found %d", v) + opts.CacheSize = *option.IntVal } case tree.SeqOptIncrement: // Do nothing; this has already been set. diff --git a/pkg/sql/sequence_test.go b/pkg/sql/sequence_test.go index 8f523ccba7a9..ba36f371ae72 100644 --- a/pkg/sql/sequence_test.go +++ b/pkg/sql/sequence_test.go @@ -8,11 +8,14 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -package sql +package sql_test import ( "context" + "fmt" "math" + "math/rand" + "sync" "testing" "github.com/cockroachdb/cockroach/pkg/base" @@ -23,6 +26,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc" "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" + "github.com/cockroachdb/cockroach/pkg/testutils/testcluster" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/stretchr/testify/require" ) @@ -353,6 +357,288 @@ CREATE SEQUENCE t.valid_seq OWNED BY t.test.a`) } } +// TestCachedSequences tests the behavior of cached sequences. +func TestCachedSequences(t *testing.T) { + defer leaktest.AfterTest(t)() + + // Start test cluster. + ctx := context.Background() + tc := testcluster.StartTestCluster(t, 3, base.TestClusterArgs{}) + defer tc.Stopper().Stop(ctx) + + sqlSessions := []*sqlutils.SQLRunner{} + for i := 0; i < 3; i++ { + newConn, err := tc.ServerConn(0).Conn(ctx) + if err != nil { + t.Fatal(err) + } + sqlSessions = append(sqlSessions, sqlutils.MakeSQLRunner(newConn)) + } + + anySession := func() int { + return rand.Intn(3) + } + + execStmt := func(t *testing.T, statement string) { + sqlSessions[anySession()].Exec(t, statement) + } + + checkIntValue := func(t *testing.T, session int, statement string, value int) { + sqlSessions[session].CheckQueryResults(t, statement, [][]string{ + {fmt.Sprintf("%d", value)}, + }) + } + + testCases := []struct { + name string + test func(*testing.T) + }{ + // Test a cached sequences in a single session. + { + name: "Single Session Cache Test", + test: func(t *testing.T) { + execStmt(t, ` + CREATE SEQUENCE s + CACHE 5 + INCREMENT BY 2 + START WITH 2 + `) + + // The cache starts out empty. When the cache is empty, the underlying sequence in the database + // should be incremented by the cache size * increment amount, so it should increase by 10 each time. + + // Session 0 caches 5 values (2,4,6,8,10) and uses the first value (2). + // + // caches: + // session 0: 4,6,8,10 + // db: + // s: 10 + checkIntValue(t, 0, "SELECT nextval('s')", 2) + checkIntValue(t, anySession(), "SELECT last_value FROM s", 10) + + // caches: + // session 0: - + // db: + // s: 10 + for sequenceNumber := 4; sequenceNumber <= 10; sequenceNumber += 2 { + checkIntValue(t, 0, "SELECT nextval('s')", sequenceNumber) + } + checkIntValue(t, anySession(), "SELECT last_value FROM s", 10) + + // Session 0 caches 5 values (12,14,16,18,20) and uses the first value (12). + // caches: + // session 0: 14,16,18,20 + // db: + // s: 20 + checkIntValue(t, 0, "SELECT nextval('s')", 12) + checkIntValue(t, anySession(), "SELECT last_value FROM s", 20) + + // caches: + // node 0: - + // db: + // s: 20 + for sequenceNumber := 14; sequenceNumber <= 20; sequenceNumber += 2 { + checkIntValue(t, 0, "SELECT nextval('s')", sequenceNumber) + } + checkIntValue(t, anySession(), "SELECT last_value FROM s", 20) + + execStmt(t, "DROP SEQUENCE s") + }, + }, + // Test multiple cached sequences using multiple sessions. + { + name: "Multi-Session, Multi-Sequence Cache Test", + test: func(t *testing.T) { + execStmt(t, ` + CREATE SEQUENCE s1 + CACHE 5 + INCREMENT BY 2 + START WITH 2 + `) + + execStmt(t, ` + CREATE SEQUENCE s2 + CACHE 4 + INCREMENT BY 3 + START WITH 3 + `) + + // The caches all start out empty. When a cache is empty, the underlying sequence in the database + // should be incremented by the cache size * increment amount. + // + // s1 increases by 10 each time, and s2 increases by 12 each time. + + // caches: + // session 0: + // s1: 4,6,8,10 + // session 1: - + // session 2: - + // db: + // s1: 10 + checkIntValue(t, 0, "SELECT nextval('s1')", 2) + checkIntValue(t, anySession(), "SELECT last_value FROM s1", 10) + + // caches: + // session 0: + // s1: 4,6,8,10 + // s2: 6,9,12 + // session 1: - + // session 2: - + // db: + // s1: 10 + // s2: 12 + checkIntValue(t, 0, "SELECT nextval('s2')", 3) + checkIntValue(t, anySession(), "SELECT last_value FROM s2", 12) + + // caches: + // session 0: + // s1: 4,6,8,10 + // s2: 6,9,12 + // session 1: + // s1: 14,16,18,20 + // session 2: - + // db: + // s1: 20 + // s2: 12 + checkIntValue(t, 1, "SELECT nextval('s1')", 12) + checkIntValue(t, anySession(), "SELECT last_value FROM s1", 20) + + // caches: + // session 0: + // s1: 4,6,8,10 + // s2: 6,9,12 + // session 1: + // s1: 14,16,18,20 + // s2: 18,21,24 + // session 2: - + // db: + // s1: 20 + // s2: 24 + checkIntValue(t, 1, "SELECT nextval('s2')", 15) + checkIntValue(t, anySession(), "SELECT last_value FROM s2", 24) + + // caches: + // session 0: + // s1: 4,6,8,10 + // s2: 6,9,12 + // session 1: + // s1: 14,16,18,20 + // s2: 18,21,24 + // session 2: + // s1: 24,26,28,30 + // db: + // s1: 30 + // s2: 24 + checkIntValue(t, 2, "SELECT nextval('s1')", 22) + checkIntValue(t, anySession(), "SELECT last_value FROM s1", 30) + + // caches: + // session 0: + // s1: 4,6,8,10 + // s2: 6,9,12 + // session 1: + // s1: 14,16,18,20 + // s2: 18,21,24 + // session 2: + // s1: 24,26,28,30 + // s2: 30,33,36 + // db: + // s1: 30 + // s2: 36 + checkIntValue(t, 2, "SELECT nextval('s2')", 27) + checkIntValue(t, anySession(), "SELECT last_value FROM s2", 36) + + // caches: + // session 0: + // s1: 4,6,8,10 + // s2: 6,9,12 + // session 1: + // s1: 14,16,18,20 + // s2: 18,21,24 + // session 2: + // s1: 24,26,28,30 + // s2: 30,33,36 + // db: + // s1: 30 + // s2: 36 + wg := sync.WaitGroup{} + emptyCache := func(session, start, finish, inc int, seq string) { + for sequenceNumber := start; sequenceNumber <= finish; sequenceNumber += inc { + checkIntValue(t, session, fmt.Sprintf("SELECT nextval('%s')", seq), sequenceNumber) + } + wg.Done() + } + wg.Add(3) + go emptyCache(0, 4, 10, 2, "s1") + go emptyCache(1, 14, 20, 2, "s1") + go emptyCache(2, 24, 30, 2, "s1") + wg.Wait() + + wg.Add(3) + go emptyCache(0, 6, 12, 3, "s2") + go emptyCache(1, 18, 24, 3, "s2") + go emptyCache(2, 30, 36, 3, "s2") + wg.Wait() + + // caches: + // session 0: - + // session 1: - + // session 2: - + // db: + // s1: 30 + // s2: 36 + checkIntValue(t, anySession(), "SELECT last_value FROM s1", 30) + checkIntValue(t, anySession(), "SELECT last_value FROM s2", 36) + + execStmt(t, "DROP SEQUENCE s1") + execStmt(t, "DROP SEQUENCE s2") + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tc.test(t) + }) + } +} + +// TestSequencesZeroCacheSize is a regression test for #51259, sequence caching. +// Prior sequences will have cache sizes of 0, and sequences made after will have +// a cache size of at least 1 where 1 means no caching. This test verifies that sequences +// cache sizes of 0 function in the same way as sequences with a cache size of 1. +func TestSequencesZeroCacheSize(t *testing.T) { + defer leaktest.AfterTest(t)() + + ctx := context.Background() + params := base.TestServerArgs{} + s, sqlConn, kvDB := serverutils.StartServer(t, params) + defer s.Stopper().Stop(ctx) + + sqlDB := sqlutils.MakeSQLRunner(sqlConn) + + sqlDB.Exec(t, ` + CREATE DATABASE test; + CREATE SEQUENCE test.seq INCREMENT BY 1 START WITH 1; + `) + + // Alter the descriptor to have a cache size of 0. + seqDesc := catalogkv.TestingGetMutableExistingTableDescriptor(kvDB, keys.SystemSQLCodec, "test", "seq") + seqDesc.SequenceOpts.CacheSize = 0 + err := kvDB.Put( + context.Background(), + catalogkeys.MakeDescMetadataKey(keys.SystemSQLCodec, seqDesc.GetID()), + seqDesc.DescriptorProto(), + ) + require.NoError(t, err) + + // Verify the sequences increases by 1. + sqlDB.CheckQueryResults(t, `SELECT nextval('test.seq')`, [][]string{{"1"}}) + sqlDB.CheckQueryResults(t, `SELECT last_value from test.seq`, [][]string{{"1"}}) + sqlDB.CheckQueryResults(t, `SELECT nextval('test.seq')`, [][]string{{"2"}}) + sqlDB.CheckQueryResults(t, `SELECT last_value from test.seq`, [][]string{{"2"}}) +} + // addOwnedSequence adds the sequence referenced by seqName to the // ownsSequenceIDs of the column referenced by (dbName, tableName, colIdx). func addOwnedSequence( diff --git a/pkg/sql/sessiondata/sequence_cache.go b/pkg/sql/sessiondata/sequence_cache.go new file mode 100644 index 000000000000..d3503b937b60 --- /dev/null +++ b/pkg/sql/sessiondata/sequence_cache.go @@ -0,0 +1,69 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package sessiondata + +// SequenceCache stores sequence values that have already been created in KV +// and are available to be given out as sequence numbers. Values for sequences +// are keyed by the descpb.ID of each sequence. These IDs are represented as +// uint32 to prevent an import cycle with the descpb package. The cache should +// only be accessed using the provided API. +// +// The cache ensures that values are invalidated when new descriptor versions are seen. Note that +// new descriptor versions may not monotonically increase. For example, the sequence schema +// may be altered in a txn, so the cache sees a new version V and invalidates/repopulates itself. Then, +// the txn may get rolled back, so the cache will see version V-1 and invalidate/repopulate itself again. +type SequenceCache map[uint32]*sequenceCacheEntry + +type sequenceCacheEntry struct { + // cachedVersion stores the descpb.DescriptorVersion that cached values are associated with. + // The version is checked to determine if cache needs to be invalidated. The version is stored as + // a uint32 to prevent an import cycle with the descpb package. + cachedVersion uint32 + // currentValue stores the present value of the sequence to be given out. + currentValue int64 + // increment stores the amount to increment the currentVal by each time the + // currentVal is used. This value corresponds to descpb.TableDescriptor_SequenceOpts.Increment. + increment int64 + // numValues represents the number of values to cache. The cache is considered + // to be empty when numValues is 0. + numValues int64 +} + +// NextValue fetches the next value in the sequence cache. If the values in the cache have all been +// given out or if the descriptor version has changed, then fetchNextValues() is used to repopulate the cache. +func (sc SequenceCache) NextValue( + seqID uint32, clientVersion uint32, fetchNextValues func() (int64, int64, int64, error), +) (int64, error) { + // Create entry for this sequence ID if there are no existing entries. + if _, found := sc[seqID]; !found { + sc[seqID] = &sequenceCacheEntry{} + } + cacheEntry := sc[seqID] + + if cacheEntry.numValues > 0 && cacheEntry.cachedVersion == clientVersion { + cacheEntry.currentValue += cacheEntry.increment + cacheEntry.numValues-- + return cacheEntry.currentValue - cacheEntry.increment, nil + } + + currentValue, increment, numValues, err := fetchNextValues() + if err != nil { + return 0, err + } + + // One value must be returned, and the rest of the values are stored. + val := currentValue + cacheEntry.currentValue = currentValue + increment + cacheEntry.increment = increment + cacheEntry.numValues = numValues - 1 + cacheEntry.cachedVersion = clientVersion + return val, nil +} diff --git a/pkg/sql/sessiondata/session_data.go b/pkg/sql/sessiondata/session_data.go index 58c4fd630618..08e453a2e588 100644 --- a/pkg/sql/sessiondata/session_data.go +++ b/pkg/sql/sessiondata/session_data.go @@ -152,6 +152,10 @@ type SessionData struct { SynchronousCommit bool // EnableSeqScan is a dummy setting for the enable_seqscan var. EnableSeqScan bool + + // SequenceCache stores sequence values which have been cached using the + // CACHE sequence option. + SequenceCache SequenceCache } // IsTemporarySchemaID returns true if the given ID refers to any of the temp From 69dbd62dfb742b3e5217caf30a134897dd5320e1 Mon Sep 17 00:00:00 2001 From: Jayant Shrivastava Date: Mon, 7 Dec 2020 11:47:50 -0500 Subject: [PATCH 2/5] sql: create benchmark for concurrent sequence increments Previously, there was no benchmark that tested the performance of concurrent increments to sequences. There was also no benchmark which compared sequence performance based on different cache sizes. This change adds a benchmark to measure performance based on the above criteria. Release note: None --- pkg/sql/sequence_test.go | 57 ++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/pkg/sql/sequence_test.go b/pkg/sql/sequence_test.go index ba36f371ae72..6f7d55071d8f 100644 --- a/pkg/sql/sequence_test.go +++ b/pkg/sql/sequence_test.go @@ -32,30 +32,49 @@ import ( ) func BenchmarkSequenceIncrement(b *testing.B) { - cluster := serverutils.StartNewTestCluster(b, 3, base.TestClusterArgs{}) - defer cluster.Stopper().Stop(context.Background()) - - sqlDB := cluster.ServerConn(0) + runSubBenchMark := func(b *testing.B, cacheSize int, parallelism int) { + subBenchMark := func(b *testing.B) { + cluster := serverutils.StartNewTestCluster(b, 3, base.TestClusterArgs{}) + defer cluster.Stopper().Stop(context.Background()) + + sqlDB := cluster.ServerConn(0) + if _, err := sqlDB.Exec(fmt.Sprintf(` + CREATE SEQUENCE seq CACHE %d; + CREATE TABLE tbl ( + id INT PRIMARY KEY DEFAULT nextval('seq'), + foo text + ); + `, cacheSize)); err != nil { + b.Fatal(err) + } - if _, err := sqlDB.Exec(` - CREATE DATABASE test; - USE test; - CREATE SEQUENCE seq; - CREATE TABLE tbl ( - id INT PRIMARY KEY DEFAULT nextval('seq'), - foo text - ); - `); err != nil { - b.Fatal(err) + b.SetParallelism(parallelism) + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + session, err := sqlDB.Conn(context.Background()) + if err != nil { + b.Fatal(err) + } + conn := sqlutils.MakeSQLRunner(session) + for pb.Next() { + conn.Exec(b, "INSERT INTO tbl (foo) VALUES ('foo')") + } + if err = session.Close(); err != nil { + b.Fatal(err) + } + }) + } + b.Run(fmt.Sprintf("Cache-%d-P-%d", cacheSize, parallelism), subBenchMark) } - b.ResetTimer() - for n := 0; n < b.N; n++ { - if _, err := sqlDB.Exec("INSERT INTO tbl (foo) VALUES ('foo')"); err != nil { - b.Fatal(err) + cacheSizes := []int{1, 32, 64, 128, 256, 512} + parallelism := []int{1, 2, 4, 8} + + for _, cacheSize := range cacheSizes { + for _, p := range parallelism { + runSubBenchMark(b, cacheSize, p) } } - b.StopTimer() } func BenchmarkUniqueRowID(b *testing.B) { From 5c7b9997a0b012c45cb1132d34e7358d413c0925 Mon Sep 17 00:00:00 2001 From: Jayant Shrivastava Date: Sun, 22 Nov 2020 00:09:20 -0500 Subject: [PATCH 3/5] sql: add serial normalization setting for cached sequences Closes: https://github.com/cockroachdb/cockroach/issues/51259 Release note (sql change): The `serial_normalization` session variable can now be set to the value `sql_sequence_cached`. If this value is set, the cluster setting `sql.defaults.serial_sequences_cache_size` can be used to control the number of values to cache in a user's session with a default of 256. When the cache is empty, the the underlying sequence will only be incremened once to populate it. Using `sql_sequence_cached` will result in better performance than `sql_sequence` because the former will perform fewer distributed calls to increment sequences. However, cached seqences may result in large gaps between serial sequence numbers if a session terminates before using all the values in its cache. --- docs/generated/settings/settings.html | 2 +- pkg/sql/exec_util.go | 7 +- pkg/sql/logictest/testdata/logic_test/serial | 70 ++++++++++++++++++++ pkg/sql/sequence.go | 8 +-- pkg/sql/serial.go | 19 +++++- pkg/sql/sessiondata/session_data.go | 16 ++++- 6 files changed, 112 insertions(+), 10 deletions(-) diff --git a/docs/generated/settings/settings.html b/docs/generated/settings/settings.html index 04a4fd915926..c3916a9f9f2b 100644 --- a/docs/generated/settings/settings.html +++ b/docs/generated/settings/settings.html @@ -64,7 +64,7 @@ sql.defaults.idle_in_session_timeoutduration0sdefault value for the idle_in_session_timeout; default value for the idle_in_session_timeout session setting; controls the duration a session is permitted to idle before the session is terminated; if set to 0, there is no timeout sql.defaults.idle_in_transaction_session_timeoutduration0sdefault value for the idle_in_transaction_session_timeout; controls the duration a session is permitted to idle in a transaction before the session is terminated; if set to 0, there is no timeout sql.defaults.results_buffer.sizebyte size16 KiBdefault size of the buffer that accumulates results for a statement or a batch of statements before they are sent to the client. This can be overridden on an individual connection with the 'results_buffer_size' parameter. Note that auto-retries generally only happen while no results have been delivered to the client, so reducing this size can increase the number of retriable errors a client receives. On the other hand, increasing the buffer size can increase the delay until the client receives the first result row. Updating the setting only affects new connections. Setting to 0 disables any buffering. -sql.defaults.serial_normalizationenumerationrowiddefault handling of SERIAL in table definitions [rowid = 0, virtual_sequence = 1, sql_sequence = 2] +sql.defaults.serial_normalizationenumerationrowiddefault handling of SERIAL in table definitions [rowid = 0, virtual_sequence = 1, sql_sequence = 2, sql_sequence_cached = 3] sql.defaults.statement_timeoutduration0sdefault value for the statement_timeout; default value for the statement_timeout session setting; controls the duration a query is permitted to run before it is canceled; if set to 0, there is no timeout sql.distsql.max_running_flowsinteger500maximum number of concurrent flows that can be run on a node sql.log.slow_query.experimental_full_table_scans.enabledbooleanfalsewhen set to true, statements that perform a full table/index scan will be logged to the slow query log even if they do not meet the latency threshold. Must have the slow query log enabled for this setting to have any effect. diff --git a/pkg/sql/exec_util.go b/pkg/sql/exec_util.go index 304d6fa7af43..7b262ad61818 100644 --- a/pkg/sql/exec_util.go +++ b/pkg/sql/exec_util.go @@ -369,9 +369,10 @@ var SerialNormalizationMode = settings.RegisterPublicEnumSetting( "default handling of SERIAL in table definitions", "rowid", map[int64]string{ - int64(sessiondata.SerialUsesRowID): "rowid", - int64(sessiondata.SerialUsesVirtualSequences): "virtual_sequence", - int64(sessiondata.SerialUsesSQLSequences): "sql_sequence", + int64(sessiondata.SerialUsesRowID): "rowid", + int64(sessiondata.SerialUsesVirtualSequences): "virtual_sequence", + int64(sessiondata.SerialUsesSQLSequences): "sql_sequence", + int64(sessiondata.SerialUsesCachedSQLSequences): "sql_sequence_cached", }, ) diff --git a/pkg/sql/logictest/testdata/logic_test/serial b/pkg/sql/logictest/testdata/logic_test/serial index 2776d40b668b..9fd1f48dd1cc 100644 --- a/pkg/sql/logictest/testdata/logic_test/serial +++ b/pkg/sql/logictest/testdata/logic_test/serial @@ -335,3 +335,73 @@ SELECT count(DISTINCT a), count(DISTINCT b), count(DISTINCT c) FROM serials statement ok DROP TABLE serials, smallbig, serial + +# Verify that the sequence gets incremented to the default cache +# size of 256 and that serial values increase by 1 each time. +subtest serial_cached_sequence + +statement ok +SET serial_normalization = sql_sequence_cached + +statement ok +CREATE TABLE serial ( + cached SERIAL +); + +statement ok +INSERT INTO serial (cached) VALUES (DEFAULT); + +query I +SELECT cached from serial; +---- +1 + +query T +SELECT pg_get_serial_sequence('serial', 'cached') +---- +public.serial_cached_seq + +query I +SELECT last_value from public.serial_cached_seq; +---- +256 + +statement ok +INSERT INTO serial (cached) VALUES (DEFAULT); + +query I +SELECT cached from serial ORDER BY cached; +---- +1 +2 + +query I +SELECT last_value from public.serial_cached_seq; +---- +256 + +statement ok +DROP TABLE serial; + +# Verify that the cache size for serial sequences can be changed +# from 256, the default, to 512. +subtest serial_cached_sequence_cluster_settings + +statement ok +SET CLUSTER SETTING sql.defaults.serial_sequences_cache_size = 512; + +statement ok +CREATE TABLE serial ( + cached512 SERIAL +); + +statement ok +INSERT INTO serial (cached512) VALUES (DEFAULT); + +query I +SELECT last_value from public.serial_cached512_seq; +---- +512 + +statement ok +DROP TABLE serial; diff --git a/pkg/sql/sequence.go b/pkg/sql/sequence.go index 3ffc2dbbec6a..9f3145a07d8b 100644 --- a/pkg/sql/sequence.go +++ b/pkg/sql/sequence.go @@ -109,14 +109,14 @@ func (p *planner) IncrementSequence(ctx context.Context, seqName *tree.TableName // cache size of greater than 1, then this function will read cached values // from the session data and repopulate these values when the cache is empty. func (p *planner) incrementSequenceUsingCache( - ctx context.Context, descriptor catalog.TableDescriptor, + ctx context.Context, descriptor *tabledesc.Immutable, ) (int64, error) { seqOpts := descriptor.GetSequenceOpts() cacheSize := seqOpts.EffectiveCacheSize() fetchNextValues := func() (currentValue int64, incrementAmount int64, sizeOfCache int64, err error) { - seqValueKey := p.ExecCfg().Codec.SequenceKey(uint32(descriptor.ID)) + seqValueKey := p.ExecCfg().Codec.SequenceKey(uint32(descriptor.GetID())) endValue, err := kv.IncrementValRetryable( ctx, p.txn.DB(), seqValueKey, seqOpts.Increment*cacheSize) @@ -179,7 +179,7 @@ func (p *planner) GetLatestValueInSessionForSequence( return 0, err } - val, ok := p.SessionData().SequenceState.GetLastValueByID(uint32(descriptor.ID)) + val, ok := p.SessionData().SequenceState.GetLastValueByID(uint32(descriptor.GetID())) if !ok { return 0, pgerror.Newf( pgcode.ObjectNotInPrerequisiteState, @@ -255,7 +255,7 @@ func (p *planner) GetSequenceValue( if desc.SequenceOpts == nil { return 0, errors.New("descriptor is not a sequence") } - keyValue, err := p.txn.Get(ctx, codec.SequenceKey(uint32(desc.ID))) + keyValue, err := p.txn.Get(ctx, codec.SequenceKey(uint32(desc.GetID()))) if err != nil { return 0, err } diff --git a/pkg/sql/serial.go b/pkg/sql/serial.go index 638467375c62..5207e04fc95f 100644 --- a/pkg/sql/serial.go +++ b/pkg/sql/serial.go @@ -15,6 +15,7 @@ import ( "fmt" "github.com/cockroachdb/cockroach/pkg/server/telemetry" + "github.com/cockroachdb/cockroach/pkg/settings" "github.com/cockroachdb/cockroach/pkg/sql/catalog" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" @@ -40,6 +41,15 @@ var virtualSequenceOpts = tree.SequenceOptions{ tree.SequenceOption{Name: tree.SeqOptVirtual}, } +// cachedSequencesCacheSize is the default cache size used when +// SessionNormalizationMode is SerialUsesCachedSQLSequences. +var cachedSequencesCacheSizeSetting = settings.RegisterIntSetting( + "sql.defaults.serial_sequences_cache_size", + "the default cache size when the session's serial normalization mode is set to cached sequences"+ + "A cache size of 1 means no caching. Any cache size less than 1 is invalid.", + 256, +) + // processSerialInColumnDef analyzes a column definition and determines // whether to use a sequence if the requested type is SERIAL-like. // If a sequence must be created, it returns an TableName to use @@ -84,7 +94,7 @@ func (p *planner) processSerialInColumnDef( // switch this behavior around. newSpec.Type = types.Int - case sessiondata.SerialUsesSQLSequences: + case sessiondata.SerialUsesSQLSequences, sessiondata.SerialUsesCachedSQLSequences: // With real sequences we can use the requested type as-is. default: @@ -154,6 +164,13 @@ func (p *planner) processSerialInColumnDef( if serialNormalizationMode == sessiondata.SerialUsesVirtualSequences { seqType = "virtual " seqOpts = virtualSequenceOpts + } else if serialNormalizationMode == sessiondata.SerialUsesCachedSQLSequences { + seqType = "cached " + + value := cachedSequencesCacheSizeSetting.Get(&p.ExecCfg().Settings.SV) + seqOpts = tree.SequenceOptions{ + tree.SequenceOption{Name: tree.SeqOptCache, IntVal: &value}, + } } log.VEventf(ctx, 2, "new column %q of %q will have %s sequence name %q and default %q", d, tableName, seqType, seqName, defaultExpr) diff --git a/pkg/sql/sessiondata/session_data.go b/pkg/sql/sessiondata/session_data.go index 08e453a2e588..e7814f7c1c9c 100644 --- a/pkg/sql/sessiondata/session_data.go +++ b/pkg/sql/sessiondata/session_data.go @@ -394,8 +394,18 @@ const ( // use INT NOT NULL DEFAULT nextval(...). SerialUsesVirtualSequences // SerialUsesSQLSequences means create a regular SQL sequence and - // use INT NOT NULL DEFAULT nextval(...). + // use INT NOT NULL DEFAULT nextval(...). Each call to nextval() + // is a distributed call to kv. This minimizes the size of gaps + // between successive sequence numbers (which occur due to + // node failures or errors), but the multiple kv calls + // can impact performance negatively. SerialUsesSQLSequences + // SerialUsesCachedSQLSequences is identical to SerialUsesSQLSequences with + // the exception that nodes can cache sequence values. This significantly + // reduces contention and distributed calls to kv, which results in better + // performance. Gaps between sequences may be larger as a result of cached + // values being lost to errors and/or node failures. + SerialUsesCachedSQLSequences ) func (m SerialNormalizationMode) String() string { @@ -406,6 +416,8 @@ func (m SerialNormalizationMode) String() string { return "virtual_sequence" case SerialUsesSQLSequences: return "sql_sequence" + case SerialUsesCachedSQLSequences: + return "sql_sequence_cached" default: return fmt.Sprintf("invalid (%d)", m) } @@ -420,6 +432,8 @@ func SerialNormalizationModeFromString(val string) (_ SerialNormalizationMode, o return SerialUsesVirtualSequences, true case "SQL_SEQUENCE": return SerialUsesSQLSequences, true + case "SQL_SEQUENCE_CACHED": + return SerialUsesCachedSQLSequences, true default: return 0, false } From 42db57cf782f27a008276ffae6c12b442a5d3c5d Mon Sep 17 00:00:00 2001 From: Jayant Shrivastava Date: Wed, 10 Feb 2021 22:15:25 -0500 Subject: [PATCH 4/5] sql: make cached sequences bounds-related semantics match pg semantics Previously, cached sequences did not obey pg semantics with respect to exceeding bounds. For example, if there were a sequence with a cache size of 5 and max value of 2, calling nextval(...) would immediately cause an error due to exceeded bounds. According to postgres, nextval(...) should return 1, then 2, then finally return an error due to the max value of 2 being reached. This change alters sequence caching behavior to match the above semantics. Additionally, this change now makes it possible for sequences to exceed the bounds set by MAXVALUE and MINVALUE. This is because calling nextval(...) should be as fast as possible, and the fastest way to do this is to let nextval(...) always succeed on incrementing a sequence. Despite this, a user will never see any values that exceed a sequence's bounds. To make a sequence incrementable again after exceeding its bounds, there are two options: 1. The user changes the sequence's value by calling setval(...). 2. The user performs a schema change to alter the sequences MinValue or MaxValue. If the value of a sequence exceeds its bounds, it must be restored to the original MinValue or MaxValue in the same transaction as the schema change. This change adds code to handle case 2 above. Release note: None --- pkg/sql/alter_sequence.go | 53 +++++ .../logictest/testdata/logic_test/sequences | 199 ++++++++++++++++++ pkg/sql/sequence.go | 25 ++- 3 files changed, 275 insertions(+), 2 deletions(-) diff --git a/pkg/sql/alter_sequence.go b/pkg/sql/alter_sequence.go index c37b859be6f4..a330da746fc1 100644 --- a/pkg/sql/alter_sequence.go +++ b/pkg/sql/alter_sequence.go @@ -54,12 +54,65 @@ func (n *alterSequenceNode) startExec(params runParams) error { telemetry.Inc(sqltelemetry.SchemaChangeAlterCounter("sequence")) desc := n.seqDesc + oldMinValue := desc.SequenceOpts.MinValue + oldMaxValue := desc.SequenceOpts.MaxValue + err := assignSequenceOptions( desc.SequenceOpts, n.n.Options, false /* setDefaults */, ¶ms, desc.GetID(), desc.ParentID, ) if err != nil { return err } + opts := desc.SequenceOpts + seqValueKey := params.p.ExecCfg().Codec.SequenceKey(uint32(desc.ID)) + if err != nil { + return err + } + + getSequenceValue := func() (int64, error) { + kv, err := params.p.txn.Get(params.ctx, seqValueKey) + if err != nil { + return 0, err + } + return kv.ValueInt(), nil + } + + // Due to the semantics of sequence caching (see sql.planner.incrementSequenceUsingCache()), + // it is possible for a sequence to have a value that exceeds its MinValue or MaxValue. Users + // do no see values extending the sequence's bounds, and instead see "bounds exceeded" errors. + // To make a usable again after exceeding its bounds, there are two options: + // 1. The user changes the sequence's value by calling setval(...) + // 2. The user performs a schema change to alter the sequences MinValue or MaxValue. In this case, the + // value of the sequence must be restored to the original MinValue or MaxValue transactionally. + // The code below handles the second case. + + // The sequence is decreasing and the minvalue is being decreased. + if opts.Increment < 0 && desc.SequenceOpts.MinValue < oldMinValue { + sequenceVal, err := getSequenceValue() + if err != nil { + return err + } + + // If the sequence exceeded the old MinValue, it must be changed to start at the old MinValue. + if sequenceVal < oldMinValue { + err := params.p.txn.Put(params.ctx, seqValueKey, oldMinValue) + if err != nil { + return err + } + } + } else if opts.Increment > 0 && desc.SequenceOpts.MaxValue > oldMaxValue { + sequenceVal, err := getSequenceValue() + if err != nil { + return err + } + + if sequenceVal > oldMaxValue { + err := params.p.txn.Put(params.ctx, seqValueKey, oldMaxValue) + if err != nil { + return err + } + } + } if err := params.p.writeSchemaChange( params.ctx, n.seqDesc, descpb.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann()), diff --git a/pkg/sql/logictest/testdata/logic_test/sequences b/pkg/sql/logictest/testdata/logic_test/sequences index 93214fbadbd6..068868930ab5 100644 --- a/pkg/sql/logictest/testdata/logic_test/sequences +++ b/pkg/sql/logictest/testdata/logic_test/sequences @@ -1399,3 +1399,202 @@ SELECT last_value FROM cache_test statement ok DROP SEQUENCE cache_test + +subtest cached_sequences_with_bounds_increasing + +statement ok +CREATE SEQUENCE cached_upper_bound_test MAXVALUE 4 START WITH 2 CACHE 5 INCREMENT BY 2; + +# Without this MAXVALUE CONSTRAINT, the values 2,4,6,8,10 would be cached +# and the underlying sequence would be set to 10. Given the constraint, only +# 2 and 4 are cached, but the underlying sequence is still set to 10. + +query I +SELECT nextval('cached_upper_bound_test'); +---- +2 + +query I +SELECT nextval('cached_upper_bound_test'); +---- +4 + +query I +SELECT last_value FROM cached_upper_bound_test; +---- +10 + +# nextval() should return errors while still incrementing the underlying sequence +# by 10 each time (cache size of 5 * increment of 2). Despite the underlying sequence changing, +# currval() and lastval() should not change. + +statement error pgcode 2200H pq: nextval\(\): reached maximum value of sequence "cached_upper_bound_test" \(4\) +SELECT nextval('cached_upper_bound_test'); + +statement error pgcode 2200H pq: nextval\(\): reached maximum value of sequence "cached_upper_bound_test" \(4\) +SELECT nextval('cached_upper_bound_test'); + +query I +SELECT lastval(); +---- +4 + +query I +SELECT currval('cached_upper_bound_test'); +---- +4 + +query I +SELECT last_value FROM cached_upper_bound_test; +---- +30 + +# Performing a schema change on the sequence to increase the bounds should reset the underlying +# sequence to its original MAXVALUE. + +statement ok +ALTER SEQUENCE cached_upper_bound_test MAXVALUE 100; + +query I +SELECT last_value FROM cached_upper_bound_test; +---- +4 + +# Calling nextval() should cache the values 6,8,10,12,14 while incrementing +# the underlying sequence to 14. + +query I +SELECT nextval('cached_upper_bound_test'); +---- +6 + +query I +SELECT last_value FROM cached_upper_bound_test; +---- +14 + +query I +SELECT lastval(); +---- +6 + +query I +SELECT currval('cached_upper_bound_test'); +---- +6 + +statement ok +drop sequence cached_upper_bound_test; + +# This test is the same as cached_sequences_with_bounds_increasing, except it uses negative values. +subtest cached_sequences_with_bounds_decreasing + +statement ok +CREATE SEQUENCE cached_lower_bound_test MINVALUE -4 START WITH -2 CACHE 5 INCREMENT BY -2; + +query I +SELECT nextval('cached_lower_bound_test'); +---- +-2 + + +query I +SELECT nextval('cached_lower_bound_test'); +---- +-4 + +query I +SELECT last_value FROM cached_lower_bound_test; +---- +-10 + +statement error pgcode 2200H pq: nextval\(\): reached minimum value of sequence "cached_lower_bound_test" \(-4\) +SELECT nextval('cached_lower_bound_test'); + +statement error pgcode 2200H pq: nextval\(\): reached minimum value of sequence "cached_lower_bound_test" \(-4\) +SELECT nextval('cached_lower_bound_test'); + +query I +SELECT last_value FROM cached_lower_bound_test; +---- +-30 + +statement ok +ALTER SEQUENCE cached_lower_bound_test MINVALUE -100; + +query I +SELECT last_value FROM cached_lower_bound_test; +---- +-4 + +query I +SELECT nextval('cached_lower_bound_test'); +---- +-6 + +query I +SELECT last_value FROM cached_lower_bound_test; +---- +-14 + +statement ok +DROP SEQUENCE cached_lower_bound_test; + +# This test is the same as cached_sequences_with_bounds_decreasing, except it uses both positive and negative values. +subtest cached_sequences_with_bounds_middle + +statement ok +CREATE SEQUENCE cached_lower_bound_test_2 MINVALUE -2 MAXVALUE 2 START WITH 2 CACHE 5 INCREMENT BY -2; + +query I +SELECT nextval('cached_lower_bound_test_2'); +---- +2 + + +query I +SELECT nextval('cached_lower_bound_test_2'); +---- +0 + +query I +SELECT nextval('cached_lower_bound_test_2'); +---- +-2 + +query I +SELECT last_value FROM cached_lower_bound_test_2; +---- +-6 + +statement error pgcode 2200H pq: nextval\(\): reached minimum value of sequence "cached_lower_bound_test_2" \(-2\) +SELECT nextval('cached_lower_bound_test_2'); + +statement error pgcode 2200H pq: nextval\(\): reached minimum value of sequence "cached_lower_bound_test_2" \(-2\) +SELECT nextval('cached_lower_bound_test_2'); + +query I +SELECT last_value FROM cached_lower_bound_test_2; +---- +-26 + +statement ok +ALTER SEQUENCE cached_lower_bound_test_2 MINVALUE -100; + +query I +SELECT last_value FROM cached_lower_bound_test_2; +---- +-2 + +query I +SELECT nextval('cached_lower_bound_test_2'); +---- +-4 + +query I +SELECT last_value FROM cached_lower_bound_test_2; +---- +-12 + +statement ok +DROP SEQUENCE cached_lower_bound_test_2; diff --git a/pkg/sql/sequence.go b/pkg/sql/sequence.go index 9f3145a07d8b..ce0235bae3d8 100644 --- a/pkg/sql/sequence.go +++ b/pkg/sql/sequence.go @@ -115,7 +115,7 @@ func (p *planner) incrementSequenceUsingCache( cacheSize := seqOpts.EffectiveCacheSize() - fetchNextValues := func() (currentValue int64, incrementAmount int64, sizeOfCache int64, err error) { + fetchNextValues := func() (currentValue, incrementAmount, sizeOfCache int64, err error) { seqValueKey := p.ExecCfg().Codec.SequenceKey(uint32(descriptor.GetID())) endValue, err := kv.IncrementValRetryable( @@ -127,8 +127,29 @@ func (p *planner) incrementSequenceUsingCache( } return 0, 0, 0, err } + + // This sequence has exceeded its bounds after performing this increment. if endValue > seqOpts.MaxValue || endValue < seqOpts.MinValue { - return 0, 0, 0, boundsExceededError(descriptor) + // If the sequence exceeded its bounds prior to the increment, then return an error. + if (seqOpts.Increment > 0 && endValue-seqOpts.Increment*cacheSize >= seqOpts.MaxValue) || + (seqOpts.Increment < 0 && endValue-seqOpts.Increment*cacheSize <= seqOpts.MinValue) { + return 0, 0, 0, boundsExceededError(descriptor) + } + // Otherwise, values between the limit and the value prior to incrementing can be cached. + limit := seqOpts.MaxValue + if seqOpts.Increment < 0 { + limit = seqOpts.MinValue + } + abs := func(i int64) int64 { + if i < 0 { + return -i + } + return i + } + currentValue = endValue - seqOpts.Increment*(cacheSize-1) + incrementAmount = seqOpts.Increment + sizeOfCache = abs(limit-(endValue-seqOpts.Increment*cacheSize)) / abs(seqOpts.Increment) + return currentValue, incrementAmount, sizeOfCache, nil } return endValue - seqOpts.Increment*(cacheSize-1), seqOpts.Increment, cacheSize, nil From 039b8ca4838d4950f3ea930064547339459f46ad Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Tue, 13 Apr 2021 09:25:18 -0400 Subject: [PATCH 5/5] sql: add `CACHE` clause to `SHOW CREATE SEQUENCE` when relevant In 21.1 we added support for `CACHE` to sequences but we didn't add the logic to render that clause. Release note (bug fix): Render `CACHE` clause for sequences which use a cache. --- pkg/sql/logictest/testdata/logic_test/sequences | 5 +++++ pkg/sql/show_create_clauses.go | 3 +++ pkg/sql/show_test.go | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/pkg/sql/logictest/testdata/logic_test/sequences b/pkg/sql/logictest/testdata/logic_test/sequences index 068868930ab5..e86f49e5998c 100644 --- a/pkg/sql/logictest/testdata/logic_test/sequences +++ b/pkg/sql/logictest/testdata/logic_test/sequences @@ -1340,6 +1340,11 @@ CREATE SEQUENCE cache_test CACHE 0 statement ok CREATE SEQUENCE cache_test CACHE 10 INCREMENT 1 +query TT +SHOW CREATE SEQUENCE cache_test +---- +cache_test CREATE SEQUENCE public.cache_test MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 CACHE 10 + # Verify cache invalidation with schema changes. # 10 values (1,2,...,10) are cached, and the underlying sequence is incremented to 10. diff --git a/pkg/sql/show_create_clauses.go b/pkg/sql/show_create_clauses.go index 72d4c3c86b7c..f22295e9fcf1 100644 --- a/pkg/sql/show_create_clauses.go +++ b/pkg/sql/show_create_clauses.go @@ -237,6 +237,9 @@ func ShowCreateSequence( if opts.Virtual { f.Printf(" VIRTUAL") } + if opts.CacheSize > 1 { + f.Printf(" CACHE %d", opts.CacheSize) + } return f.CloseAndGetString(), nil } diff --git a/pkg/sql/show_test.go b/pkg/sql/show_test.go index 6d731133f665..398509222b98 100644 --- a/pkg/sql/show_test.go +++ b/pkg/sql/show_test.go @@ -461,6 +461,14 @@ func TestShowCreateSequence(t *testing.T) { `CREATE SEQUENCE %s INCREMENT 5 MAXVALUE 10000 START 10 MINVALUE 0`, `CREATE SEQUENCE public.%s MINVALUE 0 MAXVALUE 10000 INCREMENT 5 START 10`, }, + { + `CREATE SEQUENCE %s INCREMENT 5 MAXVALUE 10000 START 10 MINVALUE 0 CACHE 1`, + `CREATE SEQUENCE public.%s MINVALUE 0 MAXVALUE 10000 INCREMENT 5 START 10`, + }, + { + `CREATE SEQUENCE %s INCREMENT 5 MAXVALUE 10000 START 10 MINVALUE 0 CACHE 10`, + `CREATE SEQUENCE public.%s MINVALUE 0 MAXVALUE 10000 INCREMENT 5 START 10 CACHE 10`, + }, } for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) {