diff --git a/pkg/pb/plan/plan.pb.go b/pkg/pb/plan/plan.pb.go index a870fc9fed007..95cd6e21ad33f 100644 --- a/pkg/pb/plan/plan.pb.go +++ b/pkg/pb/plan/plan.pb.go @@ -5980,6 +5980,7 @@ type UpdateCtx struct { SkipInsertOnNullPk bool `protobuf:"varint,10,opt,name=skip_insert_on_null_pk,json=skipInsertOnNullPk,proto3" json:"skip_insert_on_null_pk,omitempty"` InsertPkColIdx int32 `protobuf:"varint,11,opt,name=insert_pk_col_idx,json=insertPkColIdx,proto3" json:"insert_pk_col_idx,omitempty"` CountDeleteAffectRows bool `protobuf:"varint,12,opt,name=count_delete_affect_rows,json=countDeleteAffectRows,proto3" json:"count_delete_affect_rows,omitempty"` + IgnoreAffectedRows bool `protobuf:"varint,13,opt,name=ignore_affected_rows,json=ignoreAffectedRows,proto3" json:"ignore_affected_rows,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6074,6 +6075,13 @@ func (m *UpdateCtx) GetCountDeleteAffectRows() bool { return false } +func (m *UpdateCtx) GetIgnoreAffectedRows() bool { + if m != nil { + return m.IgnoreAffectedRows + } + return false +} + type InsertCtx struct { Ref *ObjectRef `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` AddAffectedRows bool `protobuf:"varint,2,opt,name=add_affected_rows,json=addAffectedRows,proto3" json:"add_affected_rows,omitempty"` @@ -14604,14 +14612,14 @@ func init() { func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) } var fileDescriptor_2d655ab2f7683c23 = []byte{ - // 14485 bytes of a gzipped FileDescriptorProto + // 14498 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x6d, 0x8c, 0x23, 0xd9, 0xb2, 0x20, 0x54, 0x2e, 0xdb, 0x65, 0x3b, 0xfc, 0x51, 0x59, 0xa7, 0xab, 0xbb, 0xdd, 0x3d, 0xfd, 0x51, 0x9d, 0xdd, 0xd3, 0xd3, 0xd3, 0x33, 0xd3, 0x33, 0xd3, 0x3d, 0x1f, 0x3d, 0xf7, 0xdd, 0xb7, 0xf7, 0xba, 0x6c, 0x57, 0x95, 0xa7, 0x5d, 0x76, 0xdd, 0xb4, 0xab, 0x7b, 0xe6, 0x2e, 0x4f, 0xa9, 0x2c, 0x67, 0xda, 0x95, 0x53, 0xe9, 0x4c, 0x4f, 0x66, 0xba, 0xab, 0xea, 0x4a, 0x2b, 0xae, 0xf8, - 0xf1, 0x96, 0x45, 0xfc, 0x40, 0x42, 0xc0, 0xaf, 0x15, 0x0f, 0x24, 0x84, 0x84, 0x40, 0x08, 0xf4, - 0xc4, 0x63, 0x85, 0xc4, 0xf2, 0xc4, 0x9f, 0x45, 0x7c, 0x08, 0xb1, 0x02, 0x04, 0x48, 0x0b, 0x3c, + 0xf1, 0x96, 0x45, 0xfc, 0x40, 0x42, 0xc0, 0xaf, 0x95, 0x1e, 0x48, 0x08, 0x09, 0x81, 0x10, 0xe8, + 0x89, 0xc7, 0x0a, 0x89, 0xe5, 0x89, 0x3f, 0x8b, 0xf8, 0x10, 0xb0, 0x02, 0x04, 0x48, 0x0b, 0x3c, 0xfe, 0xb2, 0x02, 0x09, 0x24, 0x24, 0xfe, 0x80, 0x22, 0xce, 0xc9, 0xcc, 0x93, 0xb6, 0x7b, 0x7a, 0xe6, 0xde, 0xfb, 0xa4, 0xfd, 0x53, 0xe5, 0x13, 0x11, 0xe7, 0x3b, 0x4e, 0x9c, 0x88, 0x38, 0x71, 0x4e, 0x02, 0xcc, 0x1c, 0xc3, 0x7d, 0x32, 0xf3, 0xbd, 0xd0, 0x63, 0x39, 0xfc, 0x7d, 0xf3, 0xa3, @@ -14699,7 +14707,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x66, 0x6e, 0x32, 0xd1, 0x47, 0x9e, 0x3b, 0xb6, 0x27, 0xd4, 0xa3, 0x8a, 0x56, 0x32, 0x26, 0x93, 0x26, 0x01, 0x58, 0x03, 0x36, 0x13, 0x34, 0x57, 0xd4, 0x72, 0x24, 0x98, 0x6e, 0xf0, 0x92, 0x1a, 0x93, 0x89, 0x6f, 0x4d, 0x8c, 0xd0, 0xe2, 0xf4, 0x24, 0x9b, 0xaa, 0x71, 0x76, 0x92, 0x6f, 0xff, - 0x61, 0x86, 0xb7, 0x79, 0xcf, 0x31, 0x26, 0xac, 0x08, 0xb9, 0x5e, 0xbf, 0xd7, 0x56, 0xd6, 0x58, + 0x41, 0x86, 0xb7, 0x79, 0xcf, 0x31, 0x26, 0xac, 0x08, 0xb9, 0x5e, 0xbf, 0xd7, 0x56, 0xd6, 0x58, 0x05, 0x8a, 0x9d, 0xde, 0xb0, 0xad, 0xf5, 0x1a, 0x5d, 0x25, 0x43, 0xc2, 0x65, 0xd8, 0xd8, 0xed, 0xb6, 0x95, 0x75, 0xc4, 0xbc, 0xec, 0x77, 0x1b, 0xc3, 0x4e, 0xb7, 0xad, 0xe4, 0x38, 0x46, 0xeb, 0x34, 0x87, 0x4a, 0x91, 0x29, 0x50, 0x39, 0xd2, 0xfa, 0xad, 0xe3, 0x66, 0x5b, 0xef, 0x1d, 0x77, @@ -14772,7 +14780,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x58, 0x4c, 0x49, 0x3d, 0x22, 0x83, 0xf6, 0x31, 0x6c, 0x49, 0x59, 0x66, 0xa8, 0x89, 0x05, 0x24, 0x1e, 0x4b, 0xda, 0x66, 0x4c, 0x4e, 0x0a, 0x5a, 0xc0, 0xde, 0xc7, 0x71, 0x1a, 0x39, 0x73, 0x93, 0x0b, 0x9b, 0xf9, 0xd4, 0x0d, 0xea, 0x55, 0x1a, 0xe0, 0xcd, 0x08, 0xde, 0xe4, 0x60, 0xf5, 0x3f, - 0x5b, 0x87, 0xea, 0x9e, 0xe7, 0x5b, 0xf6, 0xc4, 0x4d, 0x18, 0x74, 0xc9, 0x62, 0x8a, 0x98, 0x76, + 0x5d, 0x87, 0xea, 0x9e, 0xe7, 0x5b, 0xf6, 0xc4, 0x4d, 0x18, 0x74, 0xc9, 0x62, 0x8a, 0x98, 0x76, 0x5d, 0x62, 0xda, 0xbb, 0x50, 0x1e, 0xf3, 0x8c, 0x7a, 0x78, 0xc2, 0x1d, 0x33, 0x39, 0x0d, 0x04, 0x68, 0x78, 0xe2, 0xa0, 0xa8, 0x89, 0x08, 0x28, 0x73, 0x8e, 0x32, 0x47, 0x99, 0x70, 0x07, 0x65, 0x3f, 0xa3, 0xbd, 0xc4, 0xb4, 0x1c, 0x2b, 0xe4, 0x33, 0x59, 0x7b, 0x7a, 0x3b, 0xd2, 0x5f, 0xa4, @@ -14824,7 +14832,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x24, 0xde, 0xc1, 0x9a, 0x2c, 0xcf, 0x76, 0xf3, 0x24, 0xf1, 0x6f, 0xfe, 0x12, 0xd8, 0x32, 0x6f, 0xbc, 0x4d, 0xaa, 0xe6, 0x85, 0x54, 0xfd, 0xd9, 0xfa, 0xf3, 0x8c, 0xfa, 0x12, 0xaa, 0x29, 0xa1, 0xb1, 0x72, 0x77, 0xe0, 0x4a, 0x9e, 0x31, 0x15, 0xf6, 0x3b, 0x4f, 0x44, 0x0a, 0xbc, 0xed, 0x4e, - 0x84, 0x73, 0x92, 0x2b, 0xf0, 0x94, 0x56, 0xff, 0xab, 0x2c, 0x54, 0x0e, 0x8c, 0xe0, 0xf4, 0xd0, + 0x84, 0x73, 0x92, 0x2b, 0xf0, 0x94, 0x56, 0xff, 0xcb, 0x2c, 0x54, 0x0e, 0x8c, 0xe0, 0xf4, 0xd0, 0x98, 0x0d, 0x42, 0x23, 0x0c, 0x90, 0x95, 0x4e, 0x8d, 0xe0, 0x74, 0x6a, 0xcc, 0xb8, 0xba, 0x9d, 0xe1, 0x7e, 0x09, 0x01, 0x43, 0x5d, 0x1b, 0x99, 0x18, 0x93, 0x7d, 0xf7, 0xe8, 0x85, 0x70, 0x3a, 0xc4, 0x69, 0x14, 0x61, 0xc1, 0xe9, 0x7c, 0x3c, 0x8e, 0xab, 0x8a, 0x92, 0xec, 0x01, 0x54, 0xc5, @@ -14835,7 +14843,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0xa7, 0xa9, 0x8c, 0x0b, 0x5c, 0xd8, 0x02, 0x70, 0x68, 0x85, 0xa7, 0x9e, 0x49, 0x5a, 0x6d, 0xbc, 0xb0, 0x07, 0x32, 0x4a, 0x4b, 0x53, 0xe2, 0x70, 0xa2, 0xc5, 0x38, 0x72, 0x43, 0xd2, 0x6d, 0xb3, 0x5a, 0x94, 0xc4, 0x2d, 0xcd, 0x37, 0xdc, 0x89, 0x15, 0xd4, 0xcb, 0x3b, 0xd9, 0x47, 0x19, 0x4d, - 0xa4, 0xd4, 0x7f, 0x63, 0x1d, 0xf2, 0x7c, 0x26, 0xdf, 0x81, 0xd2, 0x09, 0x9d, 0x0d, 0xa0, 0xe9, + 0xa4, 0xd4, 0x7f, 0x7d, 0x1d, 0xf2, 0x7c, 0x26, 0xdf, 0x81, 0xd2, 0x09, 0x9d, 0x0d, 0xa0, 0xe9, 0x2f, 0x7c, 0xf8, 0x04, 0xe8, 0xcd, 0xa7, 0x5c, 0xd1, 0x14, 0x4e, 0xa3, 0x8c, 0x46, 0xbf, 0xb1, 0x48, 0x6f, 0x1e, 0x62, 0x5d, 0x59, 0x82, 0x8a, 0x14, 0x36, 0xc2, 0xf7, 0xce, 0x89, 0x1b, 0x72, 0x84, 0x88, 0x92, 0x74, 0x4c, 0x40, 0xbb, 0x23, 0x66, 0xca, 0x13, 0xae, 0x48, 0x80, 0xa6, 0x1b, @@ -14861,7 +14869,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x2c, 0xa5, 0xf3, 0x89, 0x94, 0x56, 0x7f, 0x0d, 0xb5, 0x81, 0x31, 0x9d, 0x71, 0x59, 0x4e, 0x1d, 0x63, 0x90, 0x43, 0x9e, 0x10, 0xac, 0x47, 0xbf, 0x71, 0xd1, 0x1d, 0x59, 0xfe, 0xc8, 0x72, 0xa3, 0x35, 0x1a, 0x25, 0x51, 0xfc, 0x1e, 0xa3, 0x34, 0xd7, 0xbc, 0xf3, 0x48, 0x9c, 0x47, 0x69, 0xf5, - 0xdf, 0xce, 0x40, 0x59, 0x6a, 0x06, 0xfb, 0x18, 0x72, 0xa4, 0xb8, 0x66, 0x64, 0x41, 0x28, 0x11, + 0xdf, 0xca, 0x40, 0x59, 0x6a, 0x06, 0xfb, 0x18, 0x72, 0xa4, 0xb8, 0x66, 0x64, 0x41, 0x28, 0x11, 0xf0, 0xdf, 0x5c, 0xd5, 0x41, 0x42, 0xf6, 0x10, 0xf2, 0x41, 0x68, 0xf8, 0xd1, 0x81, 0x85, 0x22, 0xe5, 0xd8, 0xf5, 0xe6, 0xae, 0xa9, 0x71, 0x34, 0x53, 0x21, 0x6b, 0xb9, 0xa6, 0x70, 0x93, 0x2c, 0x53, 0x21, 0x52, 0xdd, 0x81, 0x52, 0x5c, 0x3c, 0xb2, 0x80, 0xd6, 0x7f, 0x35, 0x50, 0xd6, 0x58, @@ -14874,7 +14882,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x9b, 0xc6, 0x0c, 0x35, 0x13, 0xf6, 0x0b, 0xd8, 0x3a, 0x99, 0xa3, 0x76, 0x3c, 0x73, 0x8c, 0x91, 0x75, 0xea, 0x39, 0xa6, 0x15, 0x2d, 0xc2, 0xd4, 0x91, 0x8c, 0xf0, 0x1e, 0x2b, 0x44, 0x7c, 0x94, 0xd0, 0xb2, 0xcf, 0xa1, 0x32, 0xf3, 0xbd, 0x13, 0x4b, 0x0f, 0xbc, 0xb9, 0x3f, 0xb2, 0x96, 0xcc, - 0xba, 0x24, 0x6f, 0x99, 0xe8, 0x06, 0x44, 0xa6, 0xfe, 0xbb, 0xeb, 0x50, 0x69, 0x59, 0xe6, 0x7c, + 0xba, 0x24, 0x6f, 0x99, 0xe8, 0x06, 0x44, 0xa6, 0xfe, 0x3b, 0xeb, 0x50, 0x69, 0x59, 0xe6, 0x7c, 0xf6, 0xb5, 0x67, 0xbb, 0xcd, 0xf0, 0x82, 0x7d, 0x06, 0x15, 0xcf, 0x21, 0x67, 0x84, 0x2e, 0x85, 0x23, 0xac, 0x2a, 0x07, 0x3c, 0xea, 0x01, 0x05, 0x2f, 0x7c, 0x04, 0x57, 0xb8, 0x7d, 0x2f, 0x3c, 0x63, 0x17, 0x3c, 0x33, 0xae, 0x99, 0xbc, 0xa6, 0x70, 0x14, 0xdf, 0xa0, 0x89, 0xfc, 0x8f, 0x60, @@ -14882,7 +14890,7 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x0d, 0xdb, 0x51, 0x0b, 0x47, 0x7c, 0xf4, 0x78, 0xe6, 0x9c, 0x6c, 0x86, 0xa4, 0x46, 0x57, 0x34, 0x78, 0xcb, 0x93, 0x81, 0x54, 0xd6, 0xa7, 0x70, 0xd5, 0xc4, 0xde, 0xeb, 0x7c, 0xf0, 0xcf, 0x2c, 0x6b, 0xa6, 0x3b, 0x46, 0x10, 0x8a, 0xb3, 0x54, 0x46, 0xc8, 0x5d, 0xc4, 0xbd, 0xb0, 0xac, 0x59, - 0xd7, 0x08, 0x42, 0xf5, 0x5f, 0xcd, 0x42, 0x89, 0x3b, 0x27, 0x70, 0xb8, 0x1e, 0x41, 0xc1, 0x3b, + 0xd7, 0x08, 0x42, 0xf5, 0xbf, 0xce, 0x42, 0x89, 0x3b, 0x27, 0x70, 0xb8, 0x1e, 0x41, 0xc1, 0x3b, 0xf9, 0x4e, 0xf7, 0x63, 0xab, 0x7c, 0xe9, 0xbc, 0x74, 0xc3, 0x3b, 0xf9, 0x4e, 0xb3, 0xc6, 0xec, 0x83, 0x68, 0xab, 0x43, 0x0b, 0x7e, 0x5d, 0xf6, 0xc6, 0x47, 0xea, 0xbf, 0xd8, 0xfa, 0xd0, 0x34, 0x7d, 0x06, 0x65, 0xdb, 0x0d, 0x2c, 0x3f, 0xe4, 0x0e, 0x99, 0xc2, 0x9b, 0x27, 0x81, 0x93, 0x91, @@ -14892,625 +14900,626 @@ var fileDescriptor_2d655ab2f7683c23 = []byte{ 0x88, 0xed, 0x10, 0xb2, 0xef, 0xf6, 0xe6, 0x8e, 0x73, 0x74, 0xc6, 0xde, 0x87, 0x2d, 0x41, 0x3e, 0x3b, 0x8b, 0x78, 0x85, 0x8c, 0xd2, 0xbc, 0x56, 0xe3, 0x88, 0xa3, 0x33, 0xa1, 0xc9, 0x7d, 0x09, 0x75, 0x7e, 0x84, 0x2f, 0x3a, 0x65, 0x8c, 0xc7, 0xd6, 0x28, 0xd4, 0x51, 0x75, 0x10, 0xa7, 0x0d, - 0x57, 0x09, 0xcf, 0xbd, 0x4c, 0x0d, 0xc2, 0xa2, 0xe4, 0x53, 0xff, 0xbd, 0x0c, 0x94, 0x78, 0xb5, - 0x38, 0x43, 0xf7, 0x20, 0xfb, 0x03, 0xb3, 0x83, 0x38, 0xf6, 0x18, 0xb6, 0x0c, 0xd3, 0x14, 0x15, - 0x58, 0x26, 0xaf, 0x82, 0x8b, 0x83, 0x4d, 0xc3, 0x34, 0x1b, 0x02, 0x4e, 0x62, 0xf5, 0x11, 0x28, - 0x76, 0xa0, 0x47, 0xf6, 0x67, 0x72, 0x60, 0x5f, 0xd4, 0x6a, 0x76, 0x20, 0xcc, 0x4f, 0xee, 0x9c, - 0x4e, 0x4d, 0x78, 0xee, 0x87, 0x27, 0x5c, 0x65, 0x00, 0x9a, 0x45, 0x6b, 0xbf, 0x19, 0x5e, 0x7c, - 0x9d, 0x2b, 0x66, 0x14, 0x50, 0xff, 0xf3, 0x32, 0x94, 0x1b, 0xae, 0xe1, 0x5c, 0xfe, 0xc6, 0xa2, - 0x68, 0x03, 0x72, 0x55, 0xce, 0xe6, 0x62, 0x08, 0xf8, 0x41, 0x59, 0x89, 0x20, 0xd4, 0xb2, 0xbb, - 0x50, 0xf6, 0xe6, 0x61, 0x8c, 0xe7, 0x47, 0x67, 0xc0, 0x41, 0x44, 0x10, 0xe7, 0x8f, 0xdd, 0xe0, - 0x51, 0x7e, 0xd2, 0xca, 0x93, 0xfc, 0xb1, 0xa6, 0x16, 0xe7, 0x27, 0x82, 0xfb, 0x50, 0x0d, 0xed, - 0xa9, 0x45, 0xa7, 0x85, 0xf3, 0xa9, 0x65, 0xf2, 0x90, 0x46, 0x1e, 0x25, 0xd7, 0x14, 0x30, 0x2c, - 0x65, 0x6a, 0x4d, 0x3d, 0xff, 0x92, 0x97, 0xb2, 0xc1, 0x4b, 0xe1, 0x20, 0x2a, 0xe5, 0x43, 0x60, - 0xe7, 0x86, 0x1d, 0xea, 0xe9, 0xa2, 0xb8, 0x76, 0xac, 0x20, 0x66, 0x28, 0x17, 0x77, 0x0d, 0x36, - 0x4c, 0x3b, 0x38, 0xeb, 0xf4, 0x85, 0x66, 0x2c, 0x52, 0xd8, 0x97, 0x60, 0x64, 0xe0, 0xc6, 0x1c, - 0x5a, 0x5c, 0x8b, 0xcb, 0x6a, 0x25, 0x84, 0xec, 0x22, 0x00, 0x05, 0xbb, 0x6b, 0x85, 0xe7, 0x9e, - 0x8f, 0x39, 0xb9, 0xe2, 0x9b, 0x00, 0x70, 0x03, 0x44, 0x52, 0xac, 0x88, 0x78, 0x2f, 0xab, 0xc5, - 0x69, 0x54, 0x29, 0x39, 0x1f, 0x12, 0xb6, 0xc2, 0x9b, 0x9f, 0x40, 0xd8, 0x03, 0xa8, 0x51, 0xf3, - 0x49, 0x31, 0xc6, 0x3e, 0xd0, 0xe9, 0x56, 0x56, 0xab, 0x20, 0x94, 0xec, 0x69, 0xa4, 0xfa, 0x0a, - 0x6e, 0xa4, 0xfa, 0xa7, 0x1b, 0xbe, 0x6f, 0x5c, 0xea, 0x53, 0xe3, 0x3b, 0xcf, 0x27, 0xdf, 0x47, - 0x56, 0xbb, 0x26, 0x0f, 0x5b, 0x03, 0xd1, 0x87, 0x88, 0x7d, 0x63, 0x56, 0xdb, 0xf5, 0x7c, 0x72, - 0x8c, 0xac, 0xcc, 0x8a, 0x58, 0xb2, 0xe2, 0x69, 0x82, 0x49, 0x4b, 0x0f, 0x78, 0x74, 0xa5, 0x56, - 0x26, 0xd8, 0x2e, 0x81, 0x50, 0x4f, 0x0d, 0x9e, 0x71, 0x79, 0xb9, 0x25, 0x42, 0x9d, 0x9e, 0x91, - 0x24, 0xe4, 0x88, 0x53, 0xcb, 0x30, 0xe9, 0xc4, 0x8c, 0x10, 0x07, 0x96, 0x41, 0xe7, 0xd1, 0xc1, - 0x33, 0x7d, 0x36, 0x0f, 0x79, 0x58, 0xa4, 0x96, 0x0f, 0x9e, 0x1d, 0xcd, 0x43, 0x01, 0x9e, 0x58, - 0x21, 0x1d, 0x90, 0x11, 0x78, 0xdf, 0x0a, 0x51, 0xd9, 0x0c, 0x9e, 0x45, 0x7e, 0xe2, 0xab, 0x62, - 0x6c, 0x9f, 0x09, 0x47, 0xb0, 0x0a, 0xd5, 0x18, 0xa9, 0x4f, 0xe7, 0x3c, 0x0e, 0x32, 0xab, 0x95, - 0x23, 0x82, 0xc3, 0xb9, 0x83, 0x13, 0x3b, 0x32, 0x46, 0xa7, 0x96, 0xee, 0x63, 0x53, 0xae, 0xf3, - 0xa9, 0x23, 0x88, 0x86, 0xad, 0x79, 0x07, 0x78, 0x42, 0x3f, 0xb5, 0x43, 0x72, 0xd0, 0x64, 0xb5, - 0x22, 0x01, 0x0e, 0xec, 0x10, 0xd7, 0x31, 0x47, 0x0a, 0x0e, 0xa4, 0x22, 0x6e, 0x10, 0xd1, 0x26, - 0x21, 0x0e, 0x09, 0x4e, 0x05, 0x3d, 0x02, 0x25, 0x45, 0x8b, 0xe5, 0xdd, 0x24, 0xd2, 0x9a, 0x44, - 0x8a, 0xa5, 0x3e, 0x04, 0x9e, 0x59, 0x47, 0xd6, 0xe3, 0x65, 0xbe, 0xc3, 0xad, 0x34, 0x02, 0xb7, - 0xec, 0xe0, 0x8c, 0x4a, 0x7c, 0x00, 0x35, 0x89, 0x0e, 0xcb, 0xbb, 0xc5, 0x39, 0x23, 0x26, 0x4b, - 0xb5, 0xd1, 0xb7, 0xa6, 0x5e, 0x28, 0xba, 0x79, 0x5b, 0x6a, 0xa3, 0x46, 0xf0, 0x74, 0x1b, 0x05, - 0x2d, 0x96, 0x79, 0x47, 0x6a, 0x23, 0x27, 0xc5, 0x52, 0xef, 0x41, 0xe5, 0xdc, 0xb7, 0xc3, 0xd0, - 0x72, 0xf9, 0xe2, 0xbf, 0xcb, 0x07, 0x56, 0xc0, 0x68, 0xf5, 0xdf, 0x83, 0x0a, 0x1f, 0x79, 0x21, - 0xdf, 0x76, 0x38, 0x89, 0x80, 0x45, 0x02, 0x42, 0x8c, 0xc6, 0xd4, 0x76, 0xc9, 0x0b, 0x93, 0xd5, - 0x4a, 0x1c, 0x82, 0xc6, 0xaa, 0x84, 0x36, 0x2e, 0xc8, 0x17, 0x93, 0xa0, 0x8d, 0x0b, 0x5a, 0x92, - 0x33, 0xdb, 0x71, 0xf8, 0xc2, 0xbf, 0x2f, 0x96, 0x24, 0x42, 0x68, 0xdd, 0xc7, 0x68, 0xaa, 0xfd, - 0x81, 0x84, 0xa6, 0xba, 0x91, 0x71, 0x08, 0x8d, 0x55, 0xbf, 0x2b, 0x18, 0x07, 0x01, 0x58, 0x73, - 0x82, 0x34, 0x2e, 0xc8, 0xd3, 0x12, 0x23, 0x8d, 0x0b, 0x21, 0xb7, 0xb0, 0x54, 0xca, 0xfb, 0x5e, - 0x2c, 0xb7, 0x10, 0x84, 0xb9, 0x65, 0x02, 0xe3, 0xa2, 0xfe, 0x28, 0x4d, 0x60, 0x5c, 0x90, 0x85, - 0x64, 0x19, 0x26, 0x6f, 0xf8, 0xfb, 0xbc, 0x78, 0x04, 0x50, 0xbb, 0x77, 0xa0, 0x12, 0x3c, 0xd3, - 0x13, 0xfc, 0x63, 0x9e, 0x3d, 0x78, 0xa6, 0x45, 0x14, 0x0f, 0xa0, 0x16, 0xb3, 0x06, 0xa7, 0xf9, - 0x80, 0x4f, 0xbc, 0x29, 0x58, 0x83, 0x0e, 0x18, 0x7f, 0x9b, 0x81, 0x9b, 0x7d, 0x72, 0x22, 0x91, - 0xf8, 0x3f, 0xb4, 0x82, 0xc0, 0x98, 0x58, 0x7b, 0x9e, 0xbf, 0x37, 0xff, 0xcd, 0x6f, 0x2e, 0xd9, - 0x23, 0xd8, 0x3c, 0x32, 0x7c, 0xcb, 0x0d, 0xe3, 0xa3, 0x31, 0xe1, 0x99, 0x59, 0x04, 0xb3, 0xe7, - 0xa0, 0x70, 0x10, 0x0f, 0xf3, 0x6a, 0x46, 0xc7, 0x3d, 0x8b, 0xfe, 0xe7, 0x25, 0x2a, 0x34, 0xf6, - 0x4a, 0x2d, 0x3b, 0x08, 0x35, 0xb4, 0xf4, 0xd9, 0x57, 0xa0, 0x38, 0xde, 0x39, 0x5a, 0x2c, 0xa8, - 0xc6, 0xea, 0x92, 0xe2, 0x2c, 0x76, 0xc9, 0x44, 0x5b, 0xae, 0x11, 0x61, 0xa2, 0xee, 0x7e, 0x05, - 0xca, 0x7c, 0x36, 0x4b, 0x67, 0x5d, 0x7f, 0x43, 0x56, 0x22, 0x4c, 0xb2, 0x7e, 0x00, 0x65, 0xa9, - 0xd6, 0x15, 0xca, 0x35, 0x24, 0x75, 0x21, 0xb1, 0x54, 0xcf, 0x8a, 0x30, 0x53, 0x48, 0x4a, 0x57, - 0xff, 0xf9, 0x75, 0x50, 0xc8, 0x39, 0xa6, 0x51, 0x78, 0x00, 0x9d, 0xb0, 0xa5, 0xcc, 0xb2, 0xcc, - 0x5b, 0xcd, 0xb2, 0x1d, 0xc8, 0x3b, 0xf6, 0x34, 0x8e, 0xb6, 0x4a, 0x9d, 0xfb, 0x10, 0x02, 0xe7, - 0xda, 0xf3, 0xed, 0x09, 0x19, 0x90, 0x72, 0xe4, 0x21, 0xf9, 0x07, 0xd1, 0x1e, 0xa3, 0x29, 0x7a, - 0x02, 0x60, 0xda, 0x41, 0xa8, 0x93, 0x4b, 0x45, 0x34, 0x5b, 0x8c, 0x4c, 0x3c, 0xfe, 0x5a, 0xc9, - 0x8c, 0xa7, 0xe2, 0x11, 0x28, 0x92, 0x12, 0xe6, 0xc6, 0xde, 0x90, 0xbc, 0x96, 0x28, 0x67, 0x4d, - 0xb7, 0xe9, 0x86, 0x4b, 0x94, 0xa8, 0x3e, 0x6d, 0x2c, 0x51, 0x76, 0xcc, 0x0b, 0xf5, 0xef, 0xbd, - 0x0b, 0xb9, 0x9e, 0x67, 0x5a, 0xec, 0x13, 0x28, 0x51, 0x38, 0xaf, 0x34, 0xc1, 0x42, 0x49, 0x46, - 0x34, 0xfd, 0xa1, 0x99, 0x2a, 0xba, 0xe2, 0xd7, 0x9b, 0x03, 0x80, 0xef, 0x91, 0x71, 0x47, 0x87, - 0xc0, 0xd8, 0xa5, 0xb2, 0x70, 0x40, 0x91, 0xbf, 0x84, 0x63, 0x70, 0x6f, 0x25, 0x37, 0xbf, 0x6f, - 0xb9, 0xa4, 0x91, 0xe7, 0xb5, 0x38, 0x4d, 0x26, 0xb5, 0xef, 0xa1, 0xea, 0xc5, 0x77, 0xa0, 0xfc, - 0x0a, 0x93, 0x9a, 0xe3, 0x69, 0x4b, 0xfa, 0x04, 0x4a, 0xdf, 0x79, 0xb6, 0xcb, 0x1b, 0xbe, 0xb1, - 0xd4, 0x70, 0xb4, 0x58, 0x78, 0xc3, 0xbf, 0x13, 0xbf, 0xd8, 0x7d, 0x28, 0x78, 0x2e, 0x2f, 0xbb, - 0xb0, 0x54, 0xf6, 0x86, 0xe7, 0x76, 0x79, 0x3c, 0x57, 0xd5, 0x0e, 0x74, 0xdf, 0x9e, 0x9c, 0x86, - 0x3a, 0xe6, 0x14, 0x87, 0xc7, 0x65, 0x3b, 0xd0, 0x10, 0x86, 0xc5, 0x22, 0xe3, 0x8d, 0x6d, 0x07, - 0x35, 0x3c, 0x2a, 0xac, 0xb4, 0x54, 0x18, 0x70, 0x34, 0x15, 0xf8, 0x2e, 0x14, 0x27, 0xbe, 0x87, - 0x46, 0xc4, 0x65, 0x1d, 0x96, 0x28, 0x0b, 0x84, 0xdb, 0xbd, 0x44, 0xf5, 0x89, 0x7e, 0xda, 0xee, - 0x44, 0x27, 0x2f, 0x49, 0x79, 0x27, 0xfb, 0xa8, 0xa8, 0x55, 0x22, 0x20, 0xf9, 0x3f, 0xde, 0x85, - 0xa2, 0x31, 0x99, 0xe8, 0x22, 0x2c, 0x6d, 0xa9, 0x2c, 0x63, 0x32, 0xa1, 0x2a, 0x9f, 0x40, 0xf5, - 0xdc, 0x76, 0xf5, 0x60, 0x66, 0x8d, 0x38, 0x6d, 0x75, 0x79, 0x28, 0xcf, 0x6d, 0x17, 0xb9, 0x9b, - 0xe8, 0xe5, 0x65, 0x50, 0xfb, 0xf1, 0xcb, 0x60, 0xf3, 0x4d, 0xcb, 0x40, 0x85, 0x0d, 0x71, 0x04, - 0xa0, 0x2c, 0x91, 0x08, 0x0c, 0xfb, 0x14, 0xca, 0xbe, 0xe1, 0x9e, 0xe9, 0xe2, 0x24, 0xfe, 0x5b, - 0xd9, 0xd2, 0xd7, 0x0c, 0xf7, 0x4c, 0x1c, 0xc4, 0x83, 0x1f, 0xff, 0x4e, 0xab, 0xcc, 0x5b, 0x6f, - 0xb1, 0x91, 0x24, 0xd3, 0x8b, 0xfd, 0xb0, 0xe9, 0xf5, 0x39, 0xd9, 0x38, 0x96, 0x1b, 0xea, 0x51, - 0x86, 0x2b, 0xab, 0x33, 0x54, 0x38, 0x59, 0x9f, 0x67, 0xc3, 0x0e, 0x90, 0xa7, 0x4d, 0x27, 0xb7, - 0xdc, 0x76, 0xaa, 0x03, 0xb1, 0x0b, 0x4e, 0x03, 0x3f, 0x71, 0xc7, 0x35, 0x60, 0x33, 0x89, 0x06, - 0xe6, 0x21, 0xd8, 0x57, 0x65, 0x57, 0x7f, 0x2a, 0x7c, 0x38, 0xb2, 0xaa, 0xec, 0x54, 0x4c, 0xf1, - 0x7d, 0xa8, 0xf2, 0xd0, 0x17, 0x3e, 0x6e, 0x01, 0x29, 0x49, 0x25, 0xad, 0x42, 0x40, 0x3e, 0x4e, - 0x01, 0x09, 0x18, 0x61, 0xea, 0x85, 0x17, 0xa4, 0x25, 0x25, 0x02, 0x86, 0xdb, 0x76, 0xe1, 0x85, - 0x56, 0x32, 0xa3, 0x9f, 0xb8, 0xf9, 0x9f, 0xd8, 0xae, 0x89, 0xac, 0x17, 0x1a, 0x93, 0xa0, 0x5e, - 0xa7, 0x95, 0x59, 0x16, 0xb0, 0xa1, 0x31, 0x09, 0xd0, 0xf0, 0x37, 0xb8, 0xb1, 0xc1, 0xdb, 0x7d, - 0x43, 0xf6, 0x4c, 0x49, 0x66, 0x88, 0x56, 0x36, 0x24, 0x9b, 0xe4, 0x4b, 0x60, 0xd1, 0x09, 0xa5, - 0x64, 0xc7, 0xdf, 0x5c, 0xe2, 0xc6, 0x4d, 0x71, 0x44, 0x19, 0x5b, 0xf1, 0x77, 0xa1, 0xcc, 0x3d, - 0x15, 0x7a, 0x10, 0x5a, 0xb3, 0xfa, 0x3b, 0xd4, 0x20, 0xe0, 0xa0, 0x41, 0x68, 0xcd, 0xd8, 0x97, - 0x50, 0x4d, 0x5b, 0x59, 0xb7, 0x56, 0x1c, 0xf4, 0x11, 0x5b, 0x68, 0x95, 0x91, 0x6c, 0x77, 0xdd, - 0xe7, 0x51, 0xed, 0xa4, 0x21, 0x51, 0x46, 0x7e, 0x98, 0x55, 0x71, 0xbd, 0xb0, 0x19, 0xc1, 0x70, - 0x00, 0x23, 0x03, 0x3b, 0xbc, 0x20, 0xa5, 0x2a, 0x1e, 0xc0, 0xd8, 0x74, 0x44, 0xe3, 0x28, 0xb2, - 0x22, 0x5b, 0xc0, 0x43, 0x3d, 0x68, 0x93, 0xb7, 0x7c, 0x1e, 0xd6, 0x41, 0x3a, 0x54, 0x7c, 0xf6, - 0xb7, 0xb8, 0xf7, 0x68, 0x3c, 0x04, 0x46, 0xde, 0x8d, 0x9e, 0x43, 0x6d, 0xe6, 0x5b, 0xba, 0x54, - 0xb3, 0x2a, 0x77, 0xea, 0xc8, 0xb7, 0x92, 0xca, 0x2b, 0x33, 0x29, 0xc5, 0x7e, 0x01, 0x5b, 0x52, - 0xce, 0xf9, 0x19, 0x65, 0xbe, 0x4f, 0x99, 0xb7, 0x17, 0x32, 0x1f, 0x9f, 0x61, 0xf6, 0xda, 0x2c, - 0x95, 0x66, 0xdb, 0x90, 0xef, 0x04, 0x6d, 0xd7, 0x24, 0xdd, 0xaa, 0xa8, 0xf1, 0x04, 0x7b, 0x06, - 0x15, 0x6e, 0xc8, 0x50, 0x64, 0x6c, 0x50, 0x7f, 0x28, 0xbb, 0x9e, 0xc9, 0x9a, 0x21, 0x84, 0x56, - 0x76, 0xe2, 0xdf, 0x01, 0xfb, 0x02, 0xb6, 0xf8, 0xb9, 0x80, 0x2c, 0x22, 0xdf, 0x5b, 0x9e, 0x72, - 0x22, 0xda, 0x4b, 0xe4, 0xa4, 0x06, 0x37, 0xfc, 0xb9, 0x4b, 0xc6, 0x8d, 0xc8, 0xc9, 0x3d, 0x56, - 0x94, 0xff, 0x11, 0xe5, 0xbf, 0x2e, 0x56, 0x17, 0x27, 0xe3, 0x79, 0x49, 0x36, 0x5d, 0xf3, 0x65, - 0xd0, 0x11, 0xe6, 0x7b, 0x43, 0x99, 0xdc, 0x93, 0x43, 0x65, 0xbe, 0xff, 0x53, 0xca, 0x24, 0x2f, - 0x0f, 0x95, 0xc9, 0x20, 0x37, 0x9f, 0xdb, 0x26, 0x69, 0x7a, 0x15, 0x8d, 0x7e, 0xb3, 0x77, 0xa1, - 0xe6, 0x5b, 0xa3, 0xb9, 0x1f, 0xd8, 0xaf, 0x2d, 0x3d, 0xb0, 0xdd, 0x33, 0xd2, 0xf1, 0x8a, 0x5a, - 0x35, 0x86, 0x0e, 0x6c, 0xf7, 0x0c, 0x45, 0x86, 0x75, 0x11, 0x5a, 0xbe, 0xcb, 0xaf, 0x03, 0x7c, - 0x28, 0x8b, 0x8c, 0x36, 0x21, 0x70, 0x9d, 0x6b, 0x60, 0xc5, 0xbf, 0x17, 0x66, 0x36, 0xe0, 0x33, - 0xfb, 0xe4, 0x47, 0xcd, 0xec, 0x80, 0x66, 0xf6, 0x21, 0x14, 0x6d, 0x37, 0xb4, 0xfc, 0xd7, 0x86, - 0x53, 0xff, 0x78, 0x49, 0x1a, 0xc7, 0x38, 0xf6, 0x00, 0x0a, 0x81, 0x63, 0xe3, 0x7a, 0xaf, 0x7f, - 0xb2, 0x44, 0x16, 0xa1, 0xd8, 0x23, 0x28, 0xc5, 0xb7, 0xde, 0xea, 0x9f, 0x2e, 0xd1, 0x25, 0x48, - 0x76, 0x07, 0x72, 0xe7, 0xc8, 0x50, 0x4f, 0x97, 0x8f, 0x0a, 0x10, 0x8e, 0xdb, 0xf7, 0x18, 0x75, - 0x76, 0xda, 0xbe, 0x9f, 0x2d, 0x6d, 0xdf, 0x7b, 0xb6, 0xe3, 0xf0, 0xed, 0x7b, 0x2c, 0x7e, 0xe1, - 0xe6, 0x47, 0x39, 0xb0, 0x27, 0x9f, 0x2d, 0x6f, 0x7e, 0x88, 0x7b, 0x49, 0xf7, 0x03, 0xcb, 0x01, - 0xf9, 0xbf, 0xb9, 0x1b, 0xff, 0x73, 0x79, 0xac, 0xd2, 0x8e, 0x71, 0x0d, 0x82, 0x38, 0x8d, 0x06, - 0x88, 0xf0, 0xfe, 0xa3, 0xd2, 0xf4, 0x05, 0xbf, 0x4c, 0xc2, 0x21, 0x1d, 0xf3, 0x82, 0x7d, 0x02, - 0xd5, 0x28, 0xea, 0x08, 0xab, 0x0b, 0xea, 0x5f, 0x2e, 0xb5, 0x20, 0x4d, 0xc0, 0x5a, 0x50, 0x19, - 0xa3, 0xee, 0x3e, 0xe5, 0xaa, 0x7c, 0xfd, 0x39, 0x35, 0x64, 0x27, 0xda, 0x58, 0xdf, 0xa4, 0xea, - 0x6b, 0xa9, 0x5c, 0xec, 0x09, 0x30, 0x7b, 0xcc, 0xe7, 0x73, 0xcf, 0xf7, 0xa6, 0x5c, 0x5d, 0xaf, - 0x7f, 0xc5, 0x3d, 0x68, 0xcb, 0x18, 0x3a, 0x0c, 0xb4, 0x5c, 0x53, 0x9f, 0x06, 0x42, 0x4d, 0xf8, - 0x19, 0xb5, 0x53, 0x08, 0xaf, 0xf8, 0x76, 0x6c, 0xe4, 0xec, 0x45, 0xda, 0xc3, 0x80, 0x6b, 0x0d, - 0x5f, 0x01, 0xb2, 0xeb, 0xeb, 0x24, 0xeb, 0x1f, 0xfd, 0x60, 0x56, 0xa4, 0x8d, 0xb2, 0x3e, 0x87, - 0x1a, 0x77, 0x94, 0x92, 0x46, 0x86, 0x2c, 0xfa, 0x73, 0x59, 0x72, 0xc9, 0x2e, 0x64, 0xad, 0x62, - 0xca, 0x0e, 0xe5, 0x2f, 0x61, 0x33, 0xf2, 0xf5, 0x86, 0xc2, 0x2d, 0xfc, 0xc7, 0x72, 0xb5, 0xb1, - 0x2f, 0x55, 0xab, 0xce, 0xa3, 0x9f, 0x54, 0xe5, 0x33, 0xa8, 0xd2, 0x2e, 0x1a, 0x5f, 0x3f, 0xfa, - 0x1b, 0x2b, 0xaf, 0x1f, 0x55, 0x90, 0x28, 0x4a, 0xa1, 0xf0, 0x4f, 0xd6, 0xe9, 0x28, 0xb4, 0xea, - 0xbf, 0xe0, 0xc2, 0x3f, 0x06, 0x36, 0x43, 0x8b, 0x3d, 0x03, 0x30, 0x66, 0x33, 0xe7, 0x92, 0xb3, - 0xe6, 0x2f, 0x89, 0x35, 0xb7, 0x25, 0xd6, 0x6c, 0x20, 0x92, 0x78, 0xb3, 0x64, 0x44, 0x3f, 0xd9, - 0x53, 0xa8, 0xcc, 0xbc, 0x20, 0xd4, 0xcd, 0xa9, 0x43, 0xfd, 0x6f, 0xc8, 0x6b, 0xfb, 0xc8, 0x0b, - 0xc2, 0xd6, 0xd4, 0xc1, 0x5e, 0xc0, 0x2c, 0xfe, 0xcd, 0xba, 0x70, 0xc5, 0x73, 0x75, 0x73, 0x3e, - 0x73, 0xec, 0x11, 0x8e, 0x80, 0x41, 0x47, 0xef, 0xf5, 0x5d, 0xaa, 0xf1, 0x96, 0x54, 0x63, 0xdf, - 0x6d, 0x45, 0x44, 0x22, 0x04, 0x6e, 0xcb, 0x5b, 0x04, 0x91, 0x9d, 0x49, 0x73, 0x10, 0x87, 0x8c, - 0x36, 0xb9, 0x6a, 0x40, 0xd0, 0x28, 0x66, 0xf4, 0x39, 0x6c, 0x26, 0x54, 0xd8, 0xc1, 0xa0, 0xde, - 0x92, 0x39, 0x59, 0x8a, 0x41, 0xaf, 0x46, 0x19, 0x11, 0x16, 0xd0, 0xd8, 0x79, 0x8e, 0x33, 0x9f, - 0x09, 0x51, 0x5a, 0x6f, 0x8b, 0xb1, 0x23, 0x20, 0x97, 0x92, 0x92, 0x29, 0x6e, 0x4d, 0xeb, 0x7b, - 0xb2, 0x29, 0x6e, 0x4d, 0x51, 0xcd, 0x10, 0x51, 0x71, 0xaf, 0x6d, 0xeb, 0x3c, 0xa8, 0xef, 0x53, - 0x28, 0xa3, 0x88, 0xb8, 0x7e, 0x89, 0x20, 0xdc, 0xf7, 0x4d, 0xdb, 0x47, 0x13, 0x80, 0x82, 0xb3, - 0x0e, 0x78, 0xc8, 0x2e, 0x07, 0x21, 0x05, 0x6b, 0x42, 0x9d, 0xc4, 0xb9, 0x58, 0xab, 0xa9, 0x33, - 0xb8, 0xce, 0xd2, 0x92, 0xbc, 0x8a, 0xb4, 0xfc, 0x88, 0xef, 0x48, 0x3a, 0x8d, 0xfb, 0x25, 0xdc, - 0x5e, 0x5d, 0x48, 0x74, 0x3b, 0xf3, 0x6b, 0xd2, 0x37, 0x6e, 0xac, 0xc8, 0xdd, 0xe4, 0x17, 0x36, - 0x7f, 0x06, 0xd5, 0x89, 0x41, 0x23, 0xe1, 0xe8, 0x53, 0xcf, 0xb4, 0xea, 0x2f, 0xe4, 0x8b, 0x93, - 0x34, 0x69, 0xfb, 0x06, 0x0e, 0x8a, 0x73, 0xe8, 0x99, 0x96, 0x56, 0x9e, 0x24, 0x09, 0xf6, 0x1c, - 0xea, 0x09, 0x13, 0xce, 0x5d, 0xac, 0x17, 0x6d, 0x3d, 0xdb, 0x1d, 0x85, 0xf5, 0x2e, 0x8d, 0xe9, - 0xb5, 0x18, 0x7f, 0x8c, 0xe8, 0x96, 0xc0, 0xb2, 0x26, 0x28, 0x24, 0x1c, 0xc4, 0x2e, 0x16, 0xd8, - 0xa6, 0x55, 0x3f, 0x94, 0x2f, 0x46, 0x71, 0xd1, 0x89, 0x24, 0xb4, 0x5f, 0x0d, 0x6c, 0xd3, 0xd2, - 0x6a, 0xe3, 0x54, 0x5a, 0xfd, 0x0f, 0xf2, 0x50, 0x8c, 0xac, 0x3a, 0x56, 0x86, 0xc2, 0x71, 0xef, - 0x45, 0xaf, 0xff, 0xaa, 0xc7, 0xef, 0x57, 0x36, 0x06, 0x83, 0xb6, 0x36, 0x54, 0x4c, 0x56, 0x03, - 0xa0, 0x3b, 0x4b, 0xfa, 0xa0, 0xd9, 0xe8, 0xf1, 0xfb, 0x96, 0x74, 0x53, 0x8a, 0xa7, 0xd7, 0xd9, - 0x16, 0x54, 0xf7, 0x8e, 0x7b, 0x14, 0x31, 0xc9, 0x41, 0x59, 0x04, 0xb5, 0xbf, 0xe1, 0x87, 0xb3, - 0x1c, 0x94, 0x43, 0xd0, 0x61, 0x63, 0xd8, 0xd6, 0x3a, 0x11, 0x28, 0xcf, 0xae, 0xc2, 0x56, 0x4c, - 0x15, 0x95, 0xa0, 0x14, 0xb0, 0x21, 0x47, 0x5a, 0xff, 0xeb, 0x76, 0x73, 0xa8, 0x00, 0x1d, 0xec, - 0xee, 0xef, 0x2b, 0x65, 0x56, 0x81, 0x62, 0xab, 0x33, 0x18, 0x76, 0x7a, 0xcd, 0xa1, 0x52, 0xc1, - 0xf6, 0xed, 0x75, 0xba, 0xc3, 0xb6, 0xa6, 0x54, 0x59, 0x11, 0x72, 0x5f, 0xf7, 0x3b, 0x3d, 0xa5, - 0x46, 0x57, 0xb5, 0x1a, 0x87, 0x47, 0xdd, 0xb6, 0xb2, 0x89, 0xd0, 0x41, 0x5f, 0x1b, 0x2a, 0x0a, - 0x42, 0x5f, 0x75, 0x7a, 0xad, 0xfe, 0x2b, 0x65, 0x8b, 0x95, 0x20, 0x7f, 0xdc, 0xc3, 0x6a, 0x18, - 0xab, 0x42, 0x89, 0x7e, 0xea, 0x8d, 0x6e, 0x57, 0xb9, 0x22, 0x9d, 0x06, 0x6f, 0x23, 0x8a, 0xce, - 0x96, 0x07, 0xd8, 0x86, 0xab, 0xd8, 0xf4, 0x38, 0x49, 0xd4, 0xd7, 0xb0, 0x9c, 0xc3, 0x4e, 0xef, - 0x78, 0xa0, 0x5c, 0x47, 0x62, 0xfa, 0x49, 0x98, 0x3a, 0x96, 0xd3, 0xe9, 0xd1, 0xc8, 0xdd, 0xc1, - 0xdf, 0xad, 0x76, 0xb7, 0x3d, 0x6c, 0x2b, 0x77, 0xb1, 0x57, 0xdd, 0x7e, 0xf3, 0x85, 0xde, 0x3f, - 0x52, 0xee, 0xe1, 0x10, 0x1e, 0x69, 0x6d, 0x5d, 0x10, 0xde, 0x67, 0x0a, 0x54, 0xf6, 0x8e, 0x7f, - 0xfd, 0xeb, 0x6f, 0x75, 0xd1, 0xa9, 0x77, 0xb1, 0xce, 0x84, 0x42, 0x3f, 0x7e, 0xa1, 0x3c, 0x5c, - 0x00, 0x0d, 0x5e, 0x28, 0xef, 0xe1, 0xa0, 0x44, 0x83, 0xaa, 0x3c, 0x42, 0x02, 0xad, 0xdd, 0x3c, - 0xd6, 0x06, 0x9d, 0x97, 0x6d, 0xbd, 0x39, 0x6c, 0x2b, 0xef, 0xd3, 0x28, 0x74, 0x7a, 0x2f, 0x94, - 0xc7, 0xd8, 0x4c, 0xfc, 0xc5, 0xc7, 0xfe, 0x03, 0xc6, 0xa0, 0x96, 0xd0, 0x12, 0xec, 0x43, 0x24, - 0xd9, 0xd5, 0xfa, 0x8d, 0x56, 0xb3, 0x31, 0x18, 0x2a, 0x1f, 0x61, 0x1f, 0x07, 0x47, 0xdd, 0xce, - 0x50, 0x79, 0x82, 0x1d, 0xd9, 0x6f, 0x0c, 0x0f, 0xda, 0x9a, 0xf2, 0x31, 0xdb, 0x84, 0xf2, 0xb0, - 0x73, 0xd8, 0xd6, 0xc5, 0x98, 0x3e, 0xc5, 0x3a, 0xf6, 0x3a, 0xdd, 0xae, 0xf2, 0x8c, 0x4e, 0x33, - 0x1b, 0xda, 0xb0, 0x43, 0x13, 0xf9, 0x19, 0x16, 0xd0, 0x38, 0x3a, 0xea, 0x7e, 0xab, 0x7c, 0x8e, - 0x1d, 0x3c, 0x3c, 0xee, 0x0e, 0x3b, 0xfa, 0xf1, 0x51, 0xab, 0x31, 0x6c, 0x2b, 0x5f, 0xd0, 0x2c, - 0xf7, 0x07, 0xc3, 0xd6, 0x61, 0x57, 0xf9, 0x92, 0xca, 0x24, 0x96, 0x6a, 0x76, 0xfb, 0xbd, 0xb6, - 0xf2, 0x5c, 0xcd, 0x15, 0x37, 0x94, 0x0d, 0x35, 0x57, 0xdc, 0x51, 0x76, 0xd4, 0x5c, 0x51, 0x55, - 0xd4, 0xc7, 0xe5, 0x41, 0xff, 0x58, 0x6b, 0xf2, 0xb6, 0xaa, 0x7f, 0x0b, 0x8a, 0x91, 0x51, 0x8f, - 0xb5, 0x74, 0x7a, 0xbd, 0xb6, 0xa6, 0xac, 0x61, 0x4b, 0xba, 0xed, 0xbd, 0xa1, 0x92, 0xa1, 0x93, - 0xdf, 0xce, 0xfe, 0xc1, 0x50, 0x59, 0xc7, 0x9f, 0xfd, 0x63, 0x1c, 0xd4, 0x2c, 0x8d, 0x46, 0xfb, - 0xb0, 0xa3, 0xe4, 0xf0, 0x57, 0xa3, 0x37, 0xec, 0x28, 0x79, 0xe2, 0x99, 0x4e, 0x6f, 0xbf, 0xdb, - 0x56, 0x36, 0x10, 0x7a, 0xd8, 0xd0, 0x5e, 0x28, 0x05, 0x5e, 0x68, 0xab, 0xfd, 0x8d, 0x52, 0x64, - 0x1b, 0xb0, 0xde, 0x7d, 0xaa, 0x94, 0x10, 0xd4, 0x6a, 0xb7, 0x8e, 0x8f, 0x14, 0x50, 0x1f, 0x41, - 0xa1, 0x31, 0x99, 0xd0, 0x0a, 0xc6, 0xce, 0x1f, 0x77, 0xbb, 0x7c, 0xc9, 0xec, 0xf6, 0x87, 0xc3, - 0xfe, 0xa1, 0x92, 0x41, 0xae, 0x1d, 0xf6, 0x8f, 0x94, 0x75, 0xb5, 0x03, 0xc5, 0x48, 0x7d, 0x91, - 0xae, 0x1e, 0x16, 0x21, 0x77, 0xa4, 0xb5, 0x5f, 0xf2, 0x70, 0x85, 0x5e, 0xfb, 0x1b, 0x6c, 0x26, - 0xfe, 0xc2, 0x82, 0xb2, 0x58, 0x11, 0xbf, 0x23, 0x48, 0x77, 0x0f, 0xbb, 0x9d, 0x5e, 0xbb, 0xa1, - 0x29, 0x79, 0xf5, 0x39, 0x94, 0x25, 0x39, 0x82, 0x93, 0xbd, 0xdf, 0x38, 0x42, 0x86, 0xe9, 0xea, - 0xa2, 0xd8, 0x6b, 0xc0, 0x62, 0x50, 0x32, 0x0f, 0x19, 0xf5, 0x73, 0xd8, 0x5a, 0xda, 0x36, 0xa8, - 0xe1, 0x8d, 0x8e, 0x68, 0x78, 0x67, 0xbf, 0xd7, 0xd7, 0xda, 0xfc, 0x1a, 0xa4, 0x98, 0xa1, 0x75, - 0xf5, 0x03, 0x28, 0xc5, 0xfb, 0x1b, 0x72, 0x6c, 0x53, 0xeb, 0x0f, 0x06, 0x7c, 0x42, 0xd7, 0x30, - 0x4d, 0xa3, 0xca, 0xd3, 0x19, 0xd5, 0x86, 0x5a, 0x5a, 0xd8, 0xb0, 0x1d, 0xb8, 0xc5, 0x79, 0x7a, - 0xf7, 0xb8, 0xd3, 0x6d, 0xe9, 0x83, 0x4e, 0xab, 0xad, 0x1f, 0xf7, 0x06, 0x47, 0xed, 0x66, 0x67, - 0xaf, 0xd3, 0x6e, 0x29, 0x6b, 0xec, 0x26, 0x5c, 0x5b, 0xa2, 0xe0, 0x77, 0x30, 0x33, 0xec, 0x06, - 0x5c, 0x5d, 0xc2, 0x11, 0x27, 0xaf, 0x7f, 0x9d, 0x2b, 0xde, 0x55, 0x76, 0xbe, 0xce, 0x15, 0x1f, - 0x28, 0xef, 0xaa, 0x03, 0xd8, 0x8a, 0x76, 0x74, 0xba, 0xed, 0x41, 0xa6, 0xe6, 0x36, 0xe4, 0xbb, - 0xd6, 0x6b, 0xcb, 0x89, 0xae, 0x2d, 0x50, 0x02, 0xa1, 0xfd, 0x93, 0xef, 0x3a, 0xf1, 0x75, 0x7d, - 0x4a, 0xa0, 0x0a, 0xdf, 0x93, 0x5e, 0x0c, 0xa0, 0x4b, 0xae, 0xff, 0x52, 0x06, 0x8a, 0xb1, 0x9e, - 0xf0, 0x00, 0xd6, 0x87, 0x03, 0x71, 0x28, 0xb8, 0xfd, 0x24, 0x79, 0x20, 0x65, 0x18, 0xfd, 0xd2, - 0xd6, 0x87, 0x03, 0xf6, 0x21, 0x6c, 0xf0, 0x4b, 0xcb, 0xc2, 0x21, 0xb8, 0x9d, 0xd6, 0x3d, 0x86, - 0x84, 0xd3, 0x04, 0x0d, 0xfb, 0x1c, 0x4a, 0x71, 0x6b, 0x85, 0x87, 0xec, 0x7a, 0x3a, 0x43, 0x8c, - 0xd6, 0x12, 0x4a, 0xb5, 0x0b, 0xb5, 0x74, 0x81, 0xec, 0x0e, 0x00, 0x2f, 0x52, 0x72, 0x03, 0x4b, - 0x10, 0x76, 0x13, 0xa2, 0xbb, 0xd4, 0x2d, 0x6a, 0x58, 0x35, 0xbe, 0x5b, 0xdd, 0x52, 0xff, 0x34, - 0x07, 0x90, 0x58, 0x1a, 0x38, 0x10, 0xb1, 0xdf, 0x2f, 0x2f, 0xa2, 0x1e, 0xde, 0x81, 0x92, 0xe3, - 0x19, 0xa6, 0xfc, 0x3e, 0x4a, 0x11, 0x01, 0xc4, 0x11, 0xf2, 0xad, 0xbf, 0x12, 0x0f, 0x39, 0x62, - 0xd7, 0x60, 0x63, 0xec, 0xf9, 0x53, 0x23, 0x14, 0x77, 0x54, 0x44, 0x0a, 0x15, 0x06, 0x7b, 0xe2, - 0x7a, 0xbe, 0x85, 0xf6, 0x96, 0x4b, 0xd7, 0x54, 0x70, 0x0e, 0x2a, 0x02, 0xd8, 0x45, 0x18, 0x6e, - 0xf8, 0x96, 0x3b, 0x72, 0xbc, 0xc0, 0x32, 0x71, 0x0b, 0xdf, 0x20, 0xa3, 0x0a, 0x22, 0xd0, 0xee, - 0x25, 0xef, 0xad, 0x3f, 0xb5, 0x5d, 0x23, 0x14, 0x07, 0x81, 0xd4, 0xdb, 0x08, 0x82, 0xcd, 0xfd, - 0x2e, 0xf0, 0x84, 0x1b, 0x90, 0x5f, 0x71, 0x2b, 0x22, 0x80, 0x9a, 0x7b, 0x1b, 0xc0, 0x0a, 0x46, - 0xc6, 0x8c, 0x17, 0x5e, 0xe2, 0xf7, 0x8c, 0x05, 0x64, 0xf7, 0x92, 0x75, 0xa1, 0x36, 0x3c, 0x41, - 0x05, 0xc7, 0x6b, 0x19, 0xa1, 0xd1, 0xf4, 0x1c, 0xe1, 0xa0, 0x7b, 0xb0, 0x68, 0x92, 0x3d, 0x49, - 0x93, 0xf1, 0xd8, 0xdb, 0x85, 0xbc, 0xec, 0x33, 0xa8, 0xd8, 0x23, 0xeb, 0xc4, 0xf2, 0x27, 0xdc, - 0xbc, 0x2b, 0xa7, 0x2e, 0x97, 0x70, 0x0c, 0xd9, 0x77, 0x65, 0x3b, 0x49, 0xa0, 0xe2, 0x38, 0xf5, - 0xdc, 0x89, 0x67, 0x9e, 0xf0, 0x5c, 0x15, 0xd9, 0xd9, 0x70, 0x88, 0x18, 0x9e, 0x47, 0x10, 0x61, - 0xe2, 0x66, 0x03, 0xae, 0xac, 0x68, 0xd0, 0x4f, 0x0a, 0xf8, 0xfc, 0x2f, 0xd6, 0xa1, 0x2c, 0xb5, - 0x89, 0x4e, 0x6f, 0x8c, 0x19, 0x79, 0x1f, 0xe3, 0x88, 0xf7, 0x92, 0x80, 0xf0, 0xeb, 0x3f, 0x23, - 0x23, 0x34, 0x1c, 0x6f, 0x22, 0x5d, 0x6c, 0x12, 0x90, 0x8e, 0x49, 0x07, 0xaa, 0xc6, 0xd4, 0x0a, - 0x66, 0xc6, 0x28, 0x5a, 0x55, 0x09, 0x20, 0x79, 0xcc, 0x27, 0x27, 0x3f, 0xe6, 0xa3, 0xf0, 0x93, - 0x77, 0x1e, 0xba, 0x44, 0x07, 0xed, 0x77, 0xa1, 0x1c, 0x69, 0xf3, 0x58, 0x8b, 0x38, 0x1c, 0x8e, - 0x40, 0x1d, 0x93, 0x3d, 0x84, 0xe4, 0xb1, 0x22, 0xdd, 0x08, 0x74, 0x6f, 0x1c, 0xc5, 0x4d, 0xc6, - 0xe0, 0x46, 0xd0, 0x1f, 0xc7, 0x27, 0x36, 0xa4, 0x99, 0x09, 0x9e, 0x40, 0x00, 0xc9, 0xd0, 0x27, - 0x70, 0x45, 0xb8, 0x91, 0x2d, 0x53, 0x1f, 0xdb, 0x96, 0x63, 0xea, 0xb6, 0xc9, 0xe3, 0x1a, 0xf2, - 0xda, 0x56, 0x8c, 0xda, 0x43, 0x4c, 0xc7, 0x24, 0xbd, 0x57, 0xf8, 0x0e, 0x4c, 0x7b, 0x62, 0x05, - 0xa1, 0x88, 0xf2, 0xab, 0x70, 0x60, 0x8b, 0x60, 0xea, 0x3f, 0xce, 0x41, 0x29, 0x9e, 0xac, 0xb7, - 0x0d, 0xe6, 0x7d, 0xa8, 0x8e, 0x3c, 0xd7, 0xb5, 0x48, 0x26, 0x27, 0xe3, 0x59, 0x49, 0x80, 0x14, - 0xd9, 0xcc, 0x24, 0xa2, 0x28, 0x6e, 0x9f, 0xdf, 0xce, 0xd9, 0x4a, 0x30, 0x2f, 0x45, 0x04, 0xff, - 0x4d, 0x28, 0xe2, 0x62, 0x3c, 0x31, 0x82, 0x68, 0x98, 0xe3, 0x34, 0x2e, 0xa1, 0x91, 0xe7, 0x38, - 0x3c, 0x43, 0xf4, 0x28, 0x45, 0x02, 0x61, 0x4f, 0xe9, 0x59, 0x12, 0xba, 0x5d, 0xb4, 0x41, 0xfc, - 0x5f, 0x97, 0xb8, 0x8f, 0x5f, 0x30, 0x3a, 0xe4, 0x8d, 0xd7, 0x22, 0x42, 0xf6, 0x0b, 0x50, 0x66, - 0xf3, 0xe0, 0xd4, 0x32, 0xf5, 0x99, 0x6f, 0x99, 0xb4, 0xc7, 0x88, 0x3b, 0x08, 0xdb, 0x52, 0xe6, - 0xa3, 0x08, 0xa7, 0x6d, 0x72, 0xea, 0x18, 0xc0, 0xde, 0x83, 0xcd, 0x64, 0x1a, 0x66, 0x46, 0x78, - 0xca, 0x43, 0x52, 0x4a, 0x5a, 0x2d, 0x06, 0x1f, 0x21, 0x94, 0x7d, 0x06, 0xd7, 0x7c, 0x2b, 0xb0, - 0xcd, 0xb9, 0xe1, 0xe8, 0xe9, 0x89, 0xe0, 0x4f, 0x5c, 0x6c, 0x47, 0xd8, 0x3d, 0x69, 0x42, 0xb0, - 0xf8, 0xa9, 0x71, 0x41, 0x8e, 0x38, 0xc7, 0xb1, 0x1c, 0x3b, 0x98, 0xd2, 0xbc, 0xe5, 0xb5, 0xda, - 0xd4, 0xb8, 0x38, 0x4a, 0xa0, 0x14, 0x91, 0x36, 0x73, 0xec, 0x85, 0xbb, 0xe0, 0x7c, 0x2e, 0x11, - 0xae, 0x71, 0x34, 0x53, 0xa1, 0x8a, 0x05, 0x92, 0xcd, 0x19, 0x07, 0x99, 0x64, 0xb5, 0xf2, 0xd4, - 0x20, 0xe7, 0x2c, 0x9d, 0x52, 0x3e, 0x80, 0x5a, 0x4c, 0xc3, 0x43, 0x0f, 0xc4, 0xe9, 0xbf, 0x20, - 0xe2, 0xd1, 0x07, 0xd4, 0x34, 0xce, 0x1d, 0xd1, 0xb4, 0xd6, 0x78, 0xa4, 0xbc, 0x00, 0x47, 0x73, - 0x7a, 0x03, 0xb8, 0x3b, 0x1b, 0x59, 0x64, 0x93, 0x28, 0x0a, 0x94, 0xee, 0x98, 0xea, 0xbf, 0x90, - 0x01, 0xb6, 0x3c, 0x3d, 0x6f, 0xba, 0xf3, 0x85, 0xc3, 0x1b, 0x5d, 0x58, 0xc1, 0xdf, 0xec, 0x7d, - 0x28, 0x4c, 0x3d, 0x2e, 0x32, 0xb3, 0x6f, 0xb8, 0x81, 0xbc, 0x31, 0xf5, 0x48, 0x84, 0xbe, 0x07, - 0x9b, 0x23, 0xcf, 0x15, 0x0d, 0xe5, 0x2b, 0x8a, 0xf3, 0x57, 0x2d, 0x01, 0xe3, 0xba, 0x52, 0xff, - 0xe3, 0x0c, 0xd4, 0xd2, 0x93, 0xce, 0x1e, 0xd2, 0x8b, 0x30, 0xa9, 0x37, 0x65, 0xd2, 0x14, 0xfd, - 0x19, 0xbd, 0x14, 0xb3, 0xaa, 0x89, 0xb7, 0x01, 0x48, 0x5a, 0xe9, 0x27, 0x81, 0xe0, 0xfb, 0x8a, - 0x56, 0x22, 0xc8, 0x6e, 0xe0, 0xd1, 0xa9, 0x2d, 0x7f, 0xf4, 0x8b, 0xe3, 0x73, 0x3b, 0x59, 0xdc, - 0x37, 0x38, 0x88, 0x08, 0x3e, 0x91, 0x4e, 0x9a, 0xf8, 0x49, 0xd2, 0x6a, 0xc6, 0x8c, 0xa9, 0xd4, - 0xbf, 0xc8, 0x00, 0x24, 0xf3, 0x8e, 0xa3, 0x7f, 0x66, 0x5d, 0x12, 0x6b, 0x8a, 0xf1, 0x2c, 0x9c, - 0x59, 0x97, 0x47, 0xa2, 0x6d, 0xe2, 0x94, 0x32, 0x10, 0x71, 0xae, 0x15, 0xad, 0xc4, 0x0f, 0x26, - 0x03, 0x7e, 0x69, 0x50, 0x9c, 0x4b, 0x4a, 0x4d, 0xe7, 0x47, 0x91, 0x01, 0x5d, 0xb6, 0xd9, 0xe4, - 0xb9, 0xe9, 0x0e, 0x1f, 0x5a, 0x79, 0xe2, 0x7a, 0x24, 0x3f, 0x47, 0xed, 0x44, 0x50, 0x24, 0xe4, - 0xe5, 0x24, 0x84, 0x3c, 0xf0, 0x8c, 0x9f, 0x9a, 0xc6, 0x84, 0xaa, 0x13, 0x6d, 0xea, 0x8d, 0x30, - 0xa4, 0x8b, 0xcf, 0xb1, 0x0b, 0x20, 0x13, 0xdd, 0x89, 0xe4, 0xd6, 0xff, 0x3b, 0x14, 0x9f, 0x2b, - 0x2e, 0x99, 0x88, 0xbd, 0x3d, 0xbe, 0x3c, 0xf2, 0x10, 0x67, 0xda, 0x89, 0x44, 0x22, 0x91, 0xf0, - 0xcb, 0xb0, 0xd5, 0x91, 0xe7, 0x70, 0x71, 0x88, 0x40, 0xf5, 0x5f, 0xc9, 0x03, 0x24, 0xce, 0xdf, - 0x14, 0x97, 0x66, 0x52, 0x5c, 0xca, 0x9e, 0xc2, 0x35, 0x71, 0xab, 0x3b, 0x0e, 0xfc, 0xb3, 0x5d, - 0xfd, 0xc4, 0x88, 0x02, 0x8d, 0x99, 0xc0, 0xf2, 0x90, 0xae, 0x8e, 0xbb, 0x6b, 0x84, 0xec, 0x39, - 0xca, 0x85, 0x24, 0x4f, 0x78, 0x39, 0x7b, 0x23, 0x8b, 0x56, 0x93, 0xec, 0xc3, 0xcb, 0x19, 0xfb, - 0x04, 0xae, 0xfa, 0xd6, 0xd8, 0xb7, 0x82, 0x53, 0x3d, 0x0c, 0xe4, 0xca, 0xf8, 0x4d, 0x80, 0x2d, - 0x81, 0x1c, 0x06, 0x71, 0x5d, 0x9f, 0xc0, 0x55, 0x21, 0x51, 0x16, 0x9a, 0xc7, 0x4f, 0x57, 0xb7, - 0x38, 0x52, 0x6e, 0x1d, 0xcd, 0x3c, 0x79, 0xc4, 0xa3, 0xc7, 0xe9, 0x8a, 0x38, 0xf3, 0x38, 0x18, - 0xe2, 0x19, 0x16, 0x72, 0x6b, 0x93, 0x68, 0x2a, 0x6a, 0x3c, 0xc1, 0x54, 0xc8, 0xe1, 0x0a, 0x21, - 0x01, 0x54, 0x7b, 0x5a, 0x7b, 0x42, 0x8f, 0xef, 0xd1, 0x13, 0x3a, 0x9e, 0x69, 0x69, 0x84, 0x63, - 0x1f, 0xe1, 0xae, 0x94, 0x74, 0x3b, 0x7a, 0x3f, 0x8a, 0xc7, 0xbe, 0x29, 0x49, 0x47, 0x35, 0xfe, - 0x92, 0xd4, 0x07, 0xc0, 0xa4, 0x96, 0x47, 0xd4, 0x15, 0xa2, 0xde, 0x8c, 0x9b, 0x2d, 0x88, 0xdf, - 0x03, 0x6a, 0x22, 0x17, 0x5b, 0xd5, 0x65, 0x1f, 0x30, 0x22, 0x49, 0x7e, 0x7d, 0x02, 0x57, 0x93, - 0xde, 0xe9, 0x46, 0xa8, 0x87, 0xa7, 0x96, 0x6e, 0xb9, 0x26, 0xc9, 0xa7, 0xa2, 0xb6, 0x15, 0x77, - 0xb4, 0x11, 0x0e, 0x4f, 0xad, 0xb6, 0x6b, 0xca, 0xa7, 0x6c, 0x9b, 0x3f, 0x7c, 0xca, 0xf6, 0x05, - 0xd4, 0xd3, 0x7e, 0x16, 0x69, 0xb8, 0xf9, 0x53, 0x16, 0xdb, 0x72, 0xfc, 0x60, 0x3c, 0xe2, 0x8f, - 0x61, 0xeb, 0xd4, 0x08, 0xd2, 0x3e, 0x1a, 0x3a, 0xfc, 0x2b, 0x6a, 0x9b, 0xa7, 0x46, 0x20, 0x3b, - 0x66, 0xd4, 0xbf, 0x9b, 0x81, 0x5a, 0xda, 0x1d, 0xce, 0xef, 0x07, 0xf3, 0xbd, 0x2d, 0x43, 0x3b, - 0x7c, 0xbc, 0x83, 0xbd, 0x03, 0x25, 0x1e, 0x64, 0x38, 0x9f, 0xba, 0xd1, 0x5a, 0x98, 0x9d, 0x71, - 0x79, 0x8a, 0x02, 0x72, 0x76, 0xf6, 0x16, 0x01, 0x39, 0xe3, 0x97, 0xa3, 0xde, 0x87, 0xc2, 0xfc, - 0x2c, 0x79, 0xa4, 0x66, 0x25, 0xe9, 0x9c, 0x48, 0xd5, 0xff, 0x72, 0x1d, 0x2a, 0xf2, 0x29, 0xce, - 0x8f, 0x89, 0x3e, 0xfc, 0x49, 0x81, 0xa1, 0x3b, 0x74, 0x7f, 0x41, 0xa7, 0xdb, 0x47, 0x38, 0x4e, - 0x3c, 0xf4, 0x10, 0x4e, 0x8d, 0xa0, 0x31, 0x0f, 0x71, 0xaf, 0x20, 0x45, 0xce, 0x73, 0xa2, 0x1b, - 0x5a, 0x7c, 0x65, 0xa0, 0x4c, 0x10, 0x97, 0xb3, 0x3e, 0x11, 0x17, 0x40, 0xe9, 0xf2, 0x38, 0x85, - 0xfa, 0xe7, 0x97, 0xf8, 0xa5, 0x12, 0xdd, 0x1d, 0xa7, 0xab, 0x0d, 0x4f, 0x61, 0x33, 0xb9, 0x6e, - 0xc7, 0xb3, 0x6c, 0x2c, 0x65, 0xa9, 0xc6, 0x77, 0xed, 0xc4, 0xc3, 0x36, 0x55, 0x3b, 0xd0, 0x3d, - 0xc7, 0x8c, 0xae, 0xfd, 0x16, 0xa2, 0x33, 0xf6, 0xbe, 0x63, 0x8a, 0x17, 0x0b, 0x38, 0x8d, 0x6b, - 0x9d, 0x47, 0x34, 0xf1, 0x39, 0x7c, 0xcf, 0x3a, 0x17, 0xd7, 0x7f, 0xff, 0x7e, 0x16, 0xb6, 0x96, - 0x0e, 0x6e, 0x50, 0xb1, 0x4c, 0x1e, 0x7d, 0xc4, 0x9f, 0xec, 0x1e, 0x54, 0xa6, 0x46, 0x38, 0x3a, - 0x45, 0x5d, 0x65, 0x6c, 0x5f, 0x44, 0x2f, 0x57, 0x12, 0xec, 0x88, 0x40, 0xb8, 0x9f, 0x70, 0x59, - 0xcb, 0x8f, 0xb6, 0xb9, 0xe0, 0xe3, 0x62, 0xbc, 0x4b, 0x67, 0xda, 0xd1, 0xd5, 0x87, 0xdc, 0x1b, - 0xae, 0x3e, 0xdc, 0x84, 0x92, 0xeb, 0x51, 0x98, 0xeb, 0xec, 0x4c, 0x88, 0xe9, 0x82, 0xeb, 0x85, - 0x7d, 0xf7, 0xe8, 0x8c, 0x3d, 0x85, 0xab, 0xf3, 0x80, 0x62, 0xc9, 0x4e, 0x2c, 0x3f, 0x38, 0xb5, - 0x63, 0x17, 0x2a, 0x17, 0x20, 0x57, 0xe6, 0x81, 0x75, 0x18, 0xe3, 0x84, 0x27, 0xb5, 0x01, 0x15, - 0x9a, 0x03, 0x77, 0xe4, 0xd1, 0xa1, 0x4c, 0x81, 0x84, 0xc7, 0x9d, 0x15, 0xa7, 0x55, 0x2f, 0xac, - 0xcb, 0xb6, 0xa0, 0xd2, 0xca, 0x67, 0x49, 0x82, 0xbd, 0x4f, 0x97, 0xca, 0x4e, 0xac, 0xc4, 0x36, - 0x4a, 0x31, 0xa7, 0x56, 0x22, 0x2c, 0x31, 0xf1, 0x0b, 0xb8, 0xc1, 0x6f, 0xfc, 0x4e, 0x67, 0x9e, - 0x6b, 0xb9, 0xa1, 0x9e, 0x64, 0x0c, 0xd2, 0xf1, 0x0d, 0x12, 0x5b, 0x5f, 0xa3, 0x1b, 0xc0, 0x22, - 0xc7, 0x51, 0x54, 0x56, 0x80, 0xf5, 0x72, 0x07, 0x25, 0x0d, 0x18, 0x2c, 0x9f, 0x12, 0x11, 0x16, - 0x7f, 0xaa, 0xb7, 0x60, 0xa3, 0x13, 0x1f, 0xab, 0xc5, 0x11, 0xe5, 0x59, 0xf1, 0xa8, 0x9d, 0x07, - 0x25, 0xee, 0x6f, 0x3d, 0x34, 0x66, 0xec, 0x31, 0x64, 0xa7, 0xc6, 0x4c, 0x84, 0xe9, 0xd4, 0xe3, - 0x58, 0x26, 0x8e, 0x7d, 0x72, 0x68, 0xcc, 0xb8, 0x55, 0x86, 0x44, 0x37, 0xbf, 0x80, 0x62, 0x04, - 0xf8, 0x49, 0x56, 0xd1, 0x7f, 0xb7, 0x0e, 0xa5, 0x96, 0x7c, 0x2c, 0x8e, 0x9a, 0x5c, 0xe8, 0xcf, - 0x5d, 0xd2, 0x6f, 0xc5, 0xf3, 0x5d, 0x23, 0xc3, 0x1d, 0x0a, 0x50, 0xb4, 0x80, 0xd7, 0x7f, 0x60, - 0x01, 0xdf, 0x02, 0xf0, 0xe9, 0x54, 0x89, 0x0e, 0x96, 0xb2, 0xf1, 0x0d, 0x9b, 0x8e, 0xd9, 0x31, - 0x2f, 0x56, 0x07, 0x17, 0xe7, 0x7e, 0x7c, 0x70, 0x71, 0x7e, 0x65, 0x70, 0xf1, 0xc3, 0x64, 0x13, - 0xc5, 0x69, 0xc5, 0x8a, 0x4b, 0x7c, 0x2b, 0x9f, 0xc5, 0x97, 0x7a, 0xb1, 0xf6, 0x9f, 0x41, 0x2d, - 0xea, 0x9d, 0x28, 0x0f, 0x52, 0xf7, 0x88, 0x05, 0x8e, 0x9f, 0xa3, 0x57, 0x43, 0x39, 0x99, 0x16, - 0x4c, 0xe5, 0xb7, 0x04, 0x30, 0xff, 0x6b, 0x19, 0x60, 0xe2, 0x14, 0x64, 0x6f, 0xee, 0x38, 0x43, - 0xeb, 0x82, 0xe4, 0xdf, 0x63, 0xd8, 0x12, 0xc7, 0xfc, 0xd2, 0x4b, 0x10, 0x22, 0xb0, 0x8d, 0x23, - 0x92, 0xc0, 0xb6, 0x55, 0x8f, 0x46, 0xac, 0xaf, 0x7c, 0x34, 0x62, 0xf5, 0x63, 0x14, 0x77, 0xa1, - 0x2c, 0x3f, 0xb9, 0xc0, 0x95, 0x58, 0x30, 0xe2, 0xd7, 0x16, 0xd4, 0xff, 0x61, 0x1d, 0x20, 0x39, - 0xa9, 0xf9, 0x43, 0x47, 0x86, 0xaf, 0x98, 0x92, 0xec, 0xaa, 0x29, 0x79, 0x04, 0x8a, 0x4c, 0x27, - 0xbd, 0xfd, 0x51, 0x4b, 0x08, 0x23, 0x65, 0xce, 0x0e, 0xe4, 0x47, 0x17, 0xe8, 0xe2, 0xa5, 0x08, - 0xa6, 0xe5, 0x48, 0x7e, 0x6c, 0x2c, 0xc4, 0x4c, 0xd1, 0x0e, 0xf8, 0xce, 0xc3, 0xbe, 0x82, 0x1b, - 0x71, 0x4e, 0xfd, 0xdc, 0x0e, 0x4f, 0xbd, 0x79, 0x28, 0x44, 0x52, 0x20, 0x64, 0xf1, 0xb5, 0xa8, - 0xa4, 0x57, 0x1c, 0xcd, 0x45, 0x4d, 0xc0, 0x3e, 0x87, 0xd2, 0x78, 0xee, 0x38, 0x7a, 0x68, 0x5d, - 0x84, 0x42, 0xa4, 0xd4, 0x53, 0x87, 0x5c, 0xd2, 0xf4, 0x6a, 0xc5, 0xb1, 0x48, 0xa8, 0x7f, 0x3f, - 0x07, 0xf9, 0x5f, 0xcd, 0x2d, 0xff, 0x92, 0x7d, 0x01, 0xa5, 0x20, 0x9c, 0x86, 0x72, 0xbc, 0x99, - 0x38, 0xbc, 0x20, 0x3c, 0x85, 0x8b, 0x59, 0x53, 0xcb, 0x0d, 0xf9, 0xe9, 0x2f, 0xd2, 0x92, 0x84, - 0xda, 0x86, 0x7c, 0x10, 0x5a, 0xb3, 0x40, 0xdc, 0x1a, 0xe1, 0x09, 0xb6, 0x03, 0x79, 0xd7, 0x33, - 0xad, 0x20, 0x7d, 0x37, 0xa4, 0x87, 0x7a, 0x15, 0x47, 0x30, 0x15, 0x36, 0xe2, 0x19, 0x5f, 0x8a, - 0xf9, 0xe2, 0x18, 0xba, 0x71, 0x6a, 0x19, 0x28, 0x33, 0xa3, 0xb7, 0x54, 0xe2, 0x34, 0x2a, 0x10, - 0xe4, 0xfd, 0x32, 0x26, 0xd1, 0x1b, 0x4c, 0x22, 0xc9, 0x76, 0xa0, 0x8c, 0x3f, 0x5f, 0xf9, 0x76, - 0x68, 0x0d, 0x9e, 0x45, 0x7b, 0x98, 0x04, 0x42, 0xc3, 0xdb, 0xb4, 0x42, 0x6b, 0x14, 0x0e, 0xbe, - 0x77, 0x22, 0xf3, 0x56, 0x82, 0xb0, 0x9f, 0x01, 0x3b, 0x31, 0x46, 0x67, 0x13, 0x9f, 0xe2, 0x24, - 0xbf, 0x9f, 0x5b, 0xbe, 0x1d, 0x8b, 0xdb, 0xb2, 0x34, 0x28, 0xda, 0x56, 0x42, 0xf6, 0x2b, 0x4e, - 0xc5, 0xae, 0xc1, 0xc6, 0xd4, 0xb8, 0x68, 0x79, 0x33, 0x11, 0xc0, 0x2e, 0x52, 0xec, 0x19, 0x5c, - 0x43, 0x15, 0x20, 0x7a, 0xb1, 0x03, 0x79, 0x48, 0x9c, 0x2b, 0xf2, 0xe7, 0x1b, 0xaf, 0x9c, 0x1a, - 0x41, 0x72, 0x0b, 0x5f, 0xf8, 0x85, 0x77, 0x61, 0x3b, 0x72, 0xef, 0x98, 0xd6, 0xcc, 0x72, 0x4d, - 0xcb, 0x1d, 0xd9, 0xf1, 0x1d, 0xff, 0x25, 0xe6, 0xbf, 0x22, 0x88, 0x5b, 0x12, 0xad, 0xfa, 0x27, - 0x50, 0x4d, 0xcd, 0xdd, 0xd2, 0xd9, 0xd2, 0xa0, 0xdd, 0x6d, 0x37, 0x87, 0xdc, 0xdf, 0x2c, 0x0e, - 0x41, 0xd6, 0xa5, 0xd3, 0x92, 0x9c, 0xe4, 0x87, 0xce, 0xd3, 0x59, 0x4b, 0x5b, 0xdb, 0x6f, 0xd3, - 0x81, 0x40, 0x56, 0xc9, 0xaa, 0xff, 0xfa, 0x3a, 0x6c, 0x0d, 0x7d, 0xc3, 0x0d, 0x0c, 0xae, 0xed, - 0xb9, 0xa1, 0xef, 0x39, 0xec, 0x67, 0x50, 0x0c, 0x47, 0x8e, 0xcc, 0x4c, 0x77, 0x23, 0xd1, 0xb5, - 0x40, 0xfa, 0x64, 0x38, 0xe2, 0x01, 0x05, 0x85, 0x90, 0xff, 0x60, 0x1f, 0x41, 0xfe, 0xc4, 0x9a, - 0xd8, 0xae, 0x90, 0xde, 0x57, 0x17, 0x33, 0xee, 0x22, 0xf2, 0x60, 0x4d, 0xe3, 0x54, 0xec, 0x13, - 0xd8, 0x18, 0x79, 0xd3, 0x48, 0x39, 0x48, 0xee, 0xf4, 0x4b, 0x15, 0x21, 0xf6, 0x60, 0x4d, 0x13, - 0x74, 0xec, 0x0b, 0x28, 0xfa, 0x9e, 0xe3, 0xe0, 0xdc, 0x09, 0xb5, 0xa1, 0xbe, 0x98, 0x47, 0x13, - 0xf8, 0x83, 0x35, 0x2d, 0xa6, 0x55, 0x9f, 0x40, 0x41, 0x34, 0x16, 0x87, 0x61, 0xb7, 0xbd, 0xdf, - 0x11, 0x23, 0xd8, 0xec, 0x1f, 0x1e, 0x76, 0x86, 0xfc, 0x3d, 0x13, 0xad, 0xdf, 0xed, 0xee, 0x36, - 0x9a, 0x2f, 0x94, 0xf5, 0xdd, 0x22, 0x6c, 0xf0, 0x29, 0x56, 0xff, 0x34, 0x03, 0x9b, 0x0b, 0x1d, - 0x60, 0xcf, 0x21, 0x47, 0x56, 0x3b, 0x1f, 0x9e, 0x07, 0x2b, 0x7b, 0x29, 0xa5, 0xb9, 0x4d, 0x82, - 0x39, 0xd4, 0xaf, 0xa0, 0x96, 0x86, 0x4b, 0xa7, 0x19, 0x55, 0x28, 0x69, 0xed, 0x46, 0x4b, 0xef, - 0xf7, 0xba, 0xdf, 0xf2, 0xe3, 0x41, 0x4a, 0xbe, 0xd2, 0x3a, 0x74, 0x8c, 0xf0, 0x37, 0x41, 0x59, - 0x1c, 0x18, 0xb6, 0x8f, 0xf6, 0xe5, 0x74, 0xe6, 0x58, 0xa4, 0xc6, 0x4b, 0x53, 0x76, 0x67, 0xc5, - 0x48, 0x0a, 0x32, 0x1e, 0x24, 0x3c, 0x4a, 0xa5, 0xd5, 0x3f, 0x01, 0xb6, 0x3c, 0x82, 0x7f, 0xb8, - 0xe2, 0xff, 0xef, 0x0c, 0xe4, 0x8e, 0x1c, 0xc3, 0x65, 0xf7, 0x21, 0x4f, 0xaf, 0x0b, 0x8a, 0x3d, - 0x40, 0x5e, 0x91, 0xc8, 0x16, 0x84, 0x63, 0x1f, 0x40, 0x36, 0x1c, 0x45, 0xef, 0xa4, 0x5c, 0x7f, - 0x03, 0xf3, 0x1d, 0xac, 0x69, 0x48, 0xc5, 0x1e, 0x41, 0xd6, 0x34, 0xa3, 0x3b, 0x83, 0xc2, 0x1f, - 0xd1, 0x32, 0x42, 0xa3, 0x65, 0x8d, 0x6d, 0xd7, 0x16, 0xaf, 0x21, 0x22, 0x09, 0x7b, 0x17, 0xb2, - 0xe6, 0xc8, 0x49, 0x5f, 0x00, 0xe5, 0xce, 0xde, 0xb8, 0x40, 0x73, 0xe4, 0xa0, 0x96, 0x1c, 0xfa, - 0x97, 0xba, 0x3f, 0x77, 0xe9, 0xb6, 0x49, 0x20, 0x2c, 0xd7, 0x32, 0x6a, 0x42, 0x73, 0xba, 0xb2, - 0x12, 0x88, 0x07, 0x17, 0x66, 0xbe, 0x35, 0x33, 0xfc, 0xd8, 0x66, 0xb5, 0x83, 0x23, 0x0e, 0xd8, - 0xdd, 0x00, 0x7a, 0x42, 0x5e, 0xfd, 0x90, 0x9e, 0xbe, 0x43, 0xe3, 0x47, 0x8d, 0x7e, 0xad, 0x78, - 0x6d, 0x58, 0x60, 0xd4, 0x7f, 0x94, 0x85, 0xb2, 0xd4, 0x1e, 0xf6, 0x19, 0x14, 0xcd, 0xf4, 0x42, - 0xbc, 0xb1, 0xd4, 0xe8, 0x27, 0xad, 0x68, 0x09, 0x9a, 0x82, 0xbd, 0x29, 0x5a, 0x25, 0xd4, 0x5f, - 0x1b, 0xbe, 0xcd, 0x9f, 0x54, 0x5d, 0x97, 0xc3, 0x46, 0x06, 0x56, 0xf8, 0x32, 0xc2, 0x1c, 0xac, - 0x69, 0x95, 0x40, 0x4a, 0x93, 0x85, 0x26, 0xba, 0x94, 0x4d, 0x3d, 0x63, 0xcb, 0x81, 0x07, 0x6b, - 0x5a, 0x84, 0x47, 0x52, 0xeb, 0xc2, 0x1a, 0xcd, 0xc3, 0xc8, 0x42, 0xab, 0x46, 0x1d, 0x22, 0x20, - 0xbd, 0xa5, 0xcd, 0x7f, 0xb2, 0xa7, 0x28, 0xb1, 0x0d, 0xc7, 0xf1, 0x48, 0xe1, 0xcb, 0xcb, 0x2e, - 0xc1, 0x56, 0x0c, 0xe7, 0x6f, 0x77, 0x47, 0x29, 0xf6, 0x10, 0xf2, 0x5e, 0x78, 0x6a, 0x45, 0x76, - 0x4f, 0xf4, 0x88, 0x1e, 0x82, 0x5a, 0xcd, 0x2e, 0x72, 0x0a, 0xa1, 0xd5, 0x3f, 0xcb, 0x40, 0x41, - 0x8c, 0x00, 0xdb, 0x82, 0xea, 0xa0, 0x3d, 0xd4, 0x5f, 0x36, 0xb4, 0x4e, 0x63, 0xb7, 0xdb, 0x16, - 0xf7, 0x56, 0xf7, 0xb5, 0x46, 0x4f, 0x08, 0x48, 0xad, 0xfd, 0xb2, 0xff, 0xa2, 0xcd, 0x8f, 0x08, - 0x5b, 0xed, 0xde, 0xb7, 0x4a, 0x96, 0x1f, 0x91, 0xb7, 0x8f, 0x1a, 0x1a, 0xca, 0xca, 0x32, 0x14, - 0xda, 0xdf, 0xb4, 0x9b, 0xc7, 0x24, 0x2c, 0x6b, 0x00, 0xad, 0x76, 0xa3, 0xdb, 0xed, 0x37, 0x51, - 0x78, 0x6e, 0x30, 0x06, 0xb5, 0xa6, 0xd6, 0x6e, 0x0c, 0xdb, 0x7a, 0xa3, 0xd9, 0xec, 0x1f, 0xf7, - 0x86, 0x4a, 0x01, 0x6b, 0x6c, 0x74, 0x87, 0x6d, 0x2d, 0x06, 0xd1, 0xc3, 0xa6, 0x2d, 0xad, 0x7f, - 0x14, 0x43, 0x4a, 0xbb, 0x25, 0xb4, 0x96, 0x69, 0xae, 0xd4, 0xff, 0x68, 0x0b, 0x6a, 0x69, 0xd6, - 0x64, 0x5f, 0x42, 0xd1, 0x34, 0x53, 0x73, 0x7c, 0x6b, 0x15, 0x0b, 0x3f, 0x69, 0x99, 0xd1, 0x34, - 0xf3, 0x1f, 0xec, 0x5e, 0xb4, 0x90, 0xd6, 0x97, 0x16, 0x52, 0xb4, 0x8c, 0x7e, 0x01, 0x9b, 0xe2, - 0x65, 0xb7, 0xd8, 0x8d, 0x9d, 0x5a, 0x25, 0x4d, 0x42, 0xb6, 0x04, 0xee, 0x60, 0x4d, 0xab, 0x8d, - 0x52, 0x10, 0xf6, 0x73, 0xa8, 0x19, 0xdc, 0x39, 0x2c, 0xbb, 0xc1, 0x63, 0x55, 0xb6, 0x41, 0xbe, - 0xe1, 0x24, 0x7b, 0xd5, 0x90, 0x01, 0xc8, 0x88, 0xa6, 0xef, 0xcd, 0x92, 0xcc, 0xf9, 0x54, 0xfc, - 0x92, 0xef, 0xcd, 0xa4, 0xbc, 0x15, 0x53, 0x4a, 0xb3, 0x2f, 0xa0, 0x22, 0x5a, 0x9e, 0x38, 0x85, - 0xe2, 0x25, 0xcb, 0x9b, 0x4d, 0xaa, 0xe9, 0xc1, 0x9a, 0x56, 0x1e, 0x25, 0x49, 0xf6, 0x0c, 0xf5, - 0xd1, 0x44, 0x91, 0x2f, 0xc8, 0xbc, 0x46, 0xad, 0x8d, 0x72, 0x81, 0x11, 0xa7, 0xd8, 0x27, 0x00, - 0xd4, 0x4e, 0x9e, 0xa7, 0x98, 0x8a, 0xec, 0xf5, 0xbd, 0x59, 0x94, 0xa5, 0x64, 0x46, 0x09, 0xa9, - 0x79, 0xdc, 0xa5, 0x57, 0x5a, 0x6e, 0x1e, 0xb9, 0xf5, 0x92, 0xe6, 0x71, 0x6f, 0x60, 0xdc, 0x3c, - 0x9e, 0x0d, 0x96, 0x9a, 0x17, 0xe5, 0xe2, 0xcd, 0xe3, 0x99, 0xa2, 0xe6, 0xf1, 0x3c, 0xe5, 0xc5, - 0xe6, 0x45, 0x59, 0xa8, 0x79, 0x3c, 0xc7, 0xcf, 0x97, 0x2c, 0x90, 0xca, 0x1b, 0x2d, 0x10, 0x9c, - 0xb6, 0xb4, 0x0d, 0xf2, 0x73, 0xa8, 0x05, 0xa7, 0xde, 0xb9, 0x24, 0x40, 0xaa, 0x72, 0xee, 0xc1, - 0xa9, 0x77, 0x2e, 0x4b, 0x90, 0x6a, 0x20, 0x03, 0xb0, 0xb5, 0xbc, 0x8b, 0x14, 0x6b, 0x54, 0x93, - 0x5b, 0x4b, 0x3d, 0x7c, 0x69, 0x5b, 0xe7, 0xd8, 0x5a, 0x23, 0x4a, 0xe0, 0xa0, 0x24, 0x0e, 0xb2, - 0x40, 0xb8, 0xbc, 0x52, 0xf1, 0xb0, 0xa2, 0x26, 0x88, 0x5d, 0x65, 0x01, 0xf2, 0xd6, 0xdc, 0x95, - 0xb3, 0x29, 0x32, 0x6f, 0x1d, 0xbb, 0xa9, 0x8c, 0x15, 0x4e, 0x2a, 0xb2, 0x26, 0xab, 0x22, 0xb0, - 0xbe, 0x9f, 0x5b, 0xee, 0xc8, 0x12, 0x71, 0xef, 0xa9, 0x55, 0x31, 0x10, 0xb8, 0x64, 0x55, 0x44, - 0x90, 0x98, 0xaf, 0xe3, 0xec, 0x6c, 0x91, 0xaf, 0xa5, 0xcc, 0xc4, 0xd7, 0x71, 0xd6, 0x78, 0x41, - 0xc5, 0x79, 0xaf, 0x2c, 0x2d, 0x28, 0x29, 0x33, 0x5f, 0x50, 0x71, 0xee, 0x67, 0x20, 0xb8, 0x89, - 0x0f, 0x6e, 0x2a, 0x3a, 0x9e, 0xb7, 0x5a, 0x8c, 0x2e, 0x8c, 0xe2, 0x14, 0xf2, 0xaa, 0x6f, 0xa1, - 0xc5, 0x23, 0x58, 0xe1, 0xaa, 0xcc, 0xab, 0x1a, 0x61, 0xe2, 0xa5, 0xe4, 0x27, 0x49, 0xa9, 0xb2, - 0x99, 0x1d, 0xfa, 0x75, 0x73, 0xb9, 0xb2, 0x23, 0x3b, 0xf4, 0x93, 0xca, 0x30, 0xc5, 0x3e, 0x02, - 0x62, 0x43, 0x9e, 0xc5, 0x92, 0x45, 0x37, 0x0e, 0x8b, 0xc8, 0x50, 0x34, 0xc5, 0x6f, 0x64, 0x16, - 0x51, 0xc7, 0xc8, 0x1c, 0xd5, 0xc7, 0x32, 0xb3, 0xf0, 0x2a, 0x9a, 0xad, 0x26, 0x32, 0x0b, 0x27, - 0x6a, 0x9a, 0x23, 0xf6, 0x18, 0x28, 0x37, 0xd1, 0x4f, 0x52, 0x8f, 0xb4, 0xfa, 0xde, 0x8c, 0x53, - 0x17, 0x90, 0x00, 0x69, 0xb1, 0x07, 0x8e, 0xe7, 0x46, 0x1d, 0x3f, 0x4d, 0xf5, 0x00, 0x11, 0xb1, - 0x30, 0x18, 0xc5, 0x29, 0xf5, 0x9f, 0xdb, 0x80, 0x82, 0x90, 0xb5, 0xec, 0x0a, 0x6c, 0x0a, 0x91, - 0xdf, 0x6a, 0x0c, 0x1b, 0xbb, 0x8d, 0x01, 0x2a, 0x69, 0x0c, 0x6a, 0x5c, 0xe6, 0xc7, 0xb0, 0x0c, - 0xee, 0x03, 0x24, 0xf4, 0x63, 0xd0, 0x3a, 0xee, 0x03, 0x22, 0x2f, 0x0f, 0xc4, 0xc8, 0xb2, 0x4d, - 0x28, 0xf3, 0x8c, 0x1c, 0x40, 0xcf, 0x68, 0x50, 0x2e, 0x9e, 0xce, 0x4b, 0x59, 0x78, 0xc4, 0xcc, - 0x46, 0x92, 0x85, 0x03, 0x0a, 0x71, 0x96, 0x28, 0xa4, 0x86, 0x41, 0x6d, 0xa8, 0x1d, 0xf7, 0x9a, - 0x49, 0x3d, 0x25, 0x7a, 0xfa, 0x80, 0x17, 0xf3, 0xb2, 0xd3, 0x7e, 0xa5, 0x00, 0x66, 0xe2, 0xa5, - 0x50, 0xba, 0x8c, 0x6a, 0x26, 0x15, 0x42, 0xc9, 0x0a, 0xbb, 0x0e, 0x57, 0x06, 0x07, 0xfd, 0x57, - 0x3a, 0xcf, 0x14, 0x77, 0xa1, 0xca, 0xb6, 0x41, 0x91, 0x10, 0xbc, 0xf8, 0x1a, 0x56, 0x49, 0xd0, - 0x88, 0x70, 0xa0, 0x6c, 0xd2, 0xe3, 0x7f, 0x08, 0x1b, 0xf2, 0x7d, 0x57, 0xc1, 0xae, 0xf0, 0xac, - 0xfd, 0xee, 0xf1, 0x61, 0x6f, 0xa0, 0x6c, 0x61, 0x23, 0x08, 0xc2, 0x5b, 0xce, 0xe2, 0x62, 0x92, - 0xdd, 0xfa, 0x0a, 0x6d, 0xe0, 0x08, 0x7b, 0xd5, 0xd0, 0x7a, 0x9d, 0xde, 0xfe, 0x40, 0xd9, 0x8e, - 0x4b, 0x6e, 0x6b, 0x5a, 0x5f, 0x1b, 0x28, 0x57, 0x63, 0xc0, 0x60, 0xd8, 0x18, 0x1e, 0x0f, 0x94, - 0x6b, 0x71, 0x2b, 0x8f, 0xb4, 0x7e, 0xb3, 0x3d, 0x18, 0x74, 0x3b, 0x83, 0xa1, 0x72, 0x9d, 0x5d, - 0x85, 0xad, 0xa4, 0x45, 0x11, 0x71, 0x5d, 0x6a, 0xa8, 0xb6, 0xdf, 0x1e, 0x2a, 0x37, 0xe2, 0x66, - 0x34, 0xfb, 0xdd, 0x6e, 0x83, 0xa2, 0x7c, 0x6e, 0x22, 0x11, 0x05, 0x98, 0x89, 0xde, 0xbc, 0x83, - 0xed, 0x3a, 0xee, 0xc9, 0xa0, 0x5b, 0x12, 0x6b, 0x0c, 0xda, 0xbf, 0x3a, 0x6e, 0xf7, 0x9a, 0x6d, - 0xe5, 0x76, 0xc2, 0x1a, 0x31, 0xec, 0x4e, 0xcc, 0x1a, 0x31, 0xe8, 0x6e, 0x5c, 0x67, 0x04, 0x1a, - 0x28, 0x3b, 0xf1, 0x80, 0x1d, 0x1f, 0xed, 0x6b, 0x8d, 0x56, 0x5b, 0x51, 0x11, 0xa2, 0xb5, 0x7b, - 0x8d, 0xc3, 0x68, 0x62, 0xef, 0x4b, 0x13, 0x7b, 0xd4, 0x19, 0x6a, 0xca, 0x83, 0x78, 0x22, 0x29, - 0xf9, 0x2e, 0x7b, 0x07, 0xae, 0xcb, 0x2c, 0xa7, 0xbf, 0xea, 0x0c, 0x0f, 0x44, 0x1c, 0xd8, 0x43, - 0x1e, 0x76, 0x44, 0xc8, 0x66, 0xab, 0xc9, 0x03, 0xde, 0x28, 0x2f, 0xa6, 0x1e, 0xa9, 0xb9, 0xe2, - 0x3d, 0xe5, 0xde, 0xe3, 0x4d, 0x31, 0x14, 0xbd, 0x5e, 0xbb, 0x39, 0xec, 0x6b, 0x83, 0xdd, 0x0a, - 0x7d, 0x63, 0x45, 0xa8, 0x20, 0xea, 0xd7, 0xc0, 0xe4, 0x4f, 0x08, 0x88, 0x0b, 0x44, 0x0c, 0x72, - 0x63, 0xdf, 0x9b, 0x46, 0xc7, 0xa3, 0xf8, 0x1b, 0xad, 0xf8, 0xd9, 0xfc, 0x84, 0xa2, 0xa4, 0x92, - 0x47, 0x6b, 0x64, 0x90, 0xfa, 0xef, 0x64, 0xa0, 0x96, 0x56, 0x3f, 0xc8, 0x39, 0x3d, 0xd6, 0x5d, - 0x2f, 0xe4, 0xef, 0x92, 0x06, 0xf1, 0xcb, 0xfe, 0xe3, 0x9e, 0x17, 0xd2, 0xc3, 0xa4, 0x41, 0xea, - 0x44, 0x7e, 0x7d, 0xe1, 0x44, 0xbe, 0x03, 0x57, 0x52, 0x5f, 0x6c, 0x48, 0xbd, 0x0a, 0x5b, 0x8f, - 0xdf, 0x36, 0x5f, 0x68, 0xbf, 0xc6, 0x82, 0xe5, 0x3e, 0x89, 0xa7, 0x87, 0x72, 0xc9, 0xd3, 0x43, - 0x07, 0x50, 0x4d, 0x69, 0x3b, 0xe4, 0x0b, 0x1a, 0xa7, 0x5b, 0x5a, 0xb4, 0xc7, 0x6f, 0x6f, 0xa6, - 0xfa, 0x6f, 0x65, 0xa0, 0x22, 0xeb, 0x3e, 0xbf, 0x73, 0x49, 0x14, 0xd7, 0x2b, 0x7e, 0xeb, 0xb6, - 0x19, 0x3d, 0x32, 0x1a, 0x81, 0x3a, 0xf4, 0x6d, 0x29, 0xee, 0xe7, 0xdf, 0x3b, 0x1b, 0xc4, 0xdd, - 0x91, 0x41, 0x14, 0xc5, 0x70, 0x6a, 0x8d, 0xce, 0xf6, 0x5e, 0x20, 0x41, 0x14, 0xc5, 0x10, 0x43, - 0xd4, 0xbb, 0x50, 0xda, 0x3b, 0x8b, 0xc2, 0x9c, 0xe5, 0xd7, 0x79, 0x4b, 0xfc, 0xa5, 0x23, 0xf5, - 0x2f, 0x32, 0x50, 0x4b, 0x3c, 0x1f, 0x14, 0x34, 0xc6, 0xbf, 0xf4, 0xc1, 0xd9, 0x61, 0xdd, 0x3c, - 0x49, 0x22, 0x55, 0xd6, 0xe5, 0x48, 0x95, 0xfb, 0xa2, 0xb0, 0xac, 0x2c, 0xf4, 0xe3, 0xba, 0xc4, - 0x3b, 0x4a, 0xcf, 0xa0, 0x82, 0xff, 0x35, 0x6b, 0x6c, 0xf9, 0xbe, 0x65, 0xa6, 0xaf, 0x75, 0x26, - 0xc4, 0x29, 0x22, 0xb2, 0xf2, 0x44, 0x0c, 0xcc, 0x1b, 0x9e, 0x48, 0xa4, 0xa7, 0x3b, 0xff, 0xcf, - 0x2c, 0x94, 0x25, 0x4d, 0xf2, 0x47, 0xb1, 0xdf, 0x2d, 0x28, 0x25, 0x0f, 0xf6, 0x89, 0xc7, 0x6b, - 0x62, 0x40, 0x6a, 0xae, 0xb2, 0x0b, 0x73, 0x55, 0x87, 0x82, 0xcf, 0x1f, 0x9b, 0x10, 0x8e, 0xe8, - 0x28, 0x99, 0x76, 0xf9, 0xe6, 0xdf, 0x72, 0x16, 0xf5, 0x29, 0x54, 0x24, 0x7f, 0x6d, 0x14, 0x5a, - 0xb2, 0x48, 0x5f, 0x4e, 0x7c, 0xb7, 0x01, 0xbb, 0x0a, 0x1b, 0xe3, 0x33, 0xdd, 0x3c, 0xe1, 0x4f, - 0x9a, 0x94, 0xb4, 0xfc, 0xf8, 0xac, 0x75, 0x42, 0x27, 0x75, 0xe3, 0x58, 0x79, 0xe2, 0x5e, 0xb4, - 0xe2, 0x38, 0x52, 0x91, 0x1e, 0x41, 0x61, 0x7c, 0x26, 0x3f, 0x4d, 0xb2, 0x34, 0xe4, 0x1b, 0xe3, - 0x33, 0x7a, 0x90, 0xe4, 0x63, 0xd8, 0x16, 0x3b, 0xb8, 0x11, 0xe8, 0xfc, 0x9d, 0x30, 0x7a, 0xc8, - 0x91, 0xbf, 0xd5, 0xbb, 0xc5, 0x71, 0x8d, 0x60, 0x40, 0x18, 0xe4, 0x38, 0x15, 0x2a, 0x12, 0x03, - 0x72, 0x6f, 0x58, 0x49, 0x4b, 0xc1, 0xd8, 0x73, 0xa8, 0x8c, 0xcf, 0xf8, 0x84, 0x0e, 0xbd, 0x43, - 0x4b, 0xdc, 0xb4, 0xdc, 0x5e, 0x9c, 0x4a, 0x8a, 0xea, 0x4b, 0x51, 0xb2, 0x6b, 0xb0, 0xa1, 0x19, - 0xe7, 0x83, 0x5f, 0x75, 0x49, 0x8d, 0x2c, 0x69, 0x22, 0xf5, 0x75, 0xae, 0x58, 0x53, 0x36, 0xd5, - 0xff, 0x34, 0x03, 0xb5, 0xc4, 0x0a, 0xc0, 0x45, 0xc8, 0x1e, 0xcb, 0x9f, 0xe8, 0xa9, 0x2f, 0x1a, - 0x0a, 0x48, 0xf2, 0x64, 0x78, 0x39, 0xe3, 0x4f, 0xc7, 0xaf, 0x7a, 0xa5, 0x74, 0x95, 0x03, 0x3d, - 0xbb, 0xf2, 0x83, 0x1f, 0xfb, 0x90, 0x1d, 0x5e, 0xce, 0xb8, 0xc7, 0x09, 0x37, 0x45, 0x6e, 0x9d, - 0xf2, 0xed, 0x90, 0xe2, 0x5c, 0x5f, 0xb4, 0xbf, 0xe5, 0x8f, 0x6d, 0x1d, 0x69, 0x9d, 0xc3, 0x86, - 0xf6, 0xad, 0x8e, 0x00, 0x52, 0x1b, 0xf6, 0xfa, 0x5a, 0xbb, 0xb3, 0xdf, 0x23, 0x40, 0x8e, 0xfc, - 0x51, 0x49, 0x13, 0x1b, 0xa6, 0xb9, 0x77, 0x26, 0x3f, 0xf0, 0x98, 0x49, 0x3d, 0xf0, 0x18, 0xbf, - 0x85, 0x2a, 0x3f, 0x31, 0x1d, 0xc6, 0x5e, 0x7d, 0x16, 0xaf, 0xc2, 0x78, 0x49, 0xb3, 0xf7, 0x20, - 0x37, 0x3e, 0xb3, 0x2e, 0xd3, 0xa6, 0x5e, 0x7a, 0x01, 0x11, 0x81, 0xfa, 0x57, 0x19, 0x60, 0xa9, - 0x86, 0x70, 0xeb, 0xe3, 0x77, 0x6d, 0xcb, 0x97, 0x50, 0x17, 0x37, 0x19, 0x38, 0x95, 0xe4, 0xb1, - 0x17, 0x43, 0x7a, 0xd5, 0x4b, 0x6e, 0xf8, 0x24, 0x0f, 0xa9, 0xb2, 0x8f, 0x81, 0xbf, 0x1e, 0x4d, - 0x41, 0xa0, 0xb9, 0x37, 0x58, 0x8a, 0x5a, 0x42, 0x93, 0x3c, 0x17, 0x2d, 0x3f, 0x83, 0xcd, 0x9d, - 0xfd, 0x9b, 0xc9, 0xac, 0xd1, 0x9a, 0x57, 0xff, 0xe5, 0x0c, 0x5c, 0x49, 0x33, 0xc4, 0xef, 0xd7, - 0xcb, 0xf4, 0x9b, 0xdf, 0xd9, 0xc5, 0x37, 0xbf, 0x57, 0xf1, 0x53, 0x6e, 0x25, 0x3f, 0xfd, 0xed, - 0x0c, 0x6c, 0x4b, 0xa3, 0x9f, 0xd8, 0x8b, 0x7f, 0x4d, 0x2d, 0x93, 0x9e, 0xfe, 0xce, 0xa5, 0x9e, - 0xfe, 0x56, 0xff, 0x32, 0x03, 0xd7, 0x16, 0x5a, 0xa2, 0x59, 0x7f, 0xad, 0x6d, 0x49, 0x3f, 0x11, - 0x4e, 0x07, 0x0e, 0xd1, 0x83, 0x54, 0x99, 0x47, 0x59, 0xe9, 0x89, 0x70, 0x3a, 0x85, 0xa2, 0xa3, - 0xd0, 0xdb, 0xe2, 0xdd, 0x42, 0x3d, 0xb8, 0x74, 0x47, 0x62, 0xb2, 0x4b, 0x04, 0x19, 0x5c, 0xba, - 0x23, 0xf5, 0xef, 0x65, 0xe0, 0xc6, 0x42, 0x1f, 0x1a, 0xf3, 0xd0, 0x13, 0xe7, 0xe6, 0x7f, 0x4d, - 0xdd, 0xb8, 0x0b, 0x65, 0x8a, 0x2a, 0x10, 0x87, 0xf1, 0x7c, 0x58, 0xc1, 0x48, 0xea, 0x55, 0x20, - 0x6b, 0x1a, 0x97, 0xe2, 0xd1, 0x1f, 0xfc, 0x89, 0x0b, 0xf6, 0xd4, 0x9b, 0xfb, 0x22, 0x8e, 0x93, - 0x7e, 0xab, 0x9f, 0xc1, 0x56, 0xd2, 0xf4, 0xa6, 0x78, 0xa9, 0xfd, 0x2e, 0x94, 0x5d, 0xeb, 0x5c, - 0x8f, 0xde, 0x71, 0x17, 0x11, 0xcd, 0xae, 0x75, 0x2e, 0x08, 0xd4, 0x3d, 0x59, 0x16, 0xc6, 0x5f, - 0xc3, 0x72, 0xcc, 0x54, 0x8c, 0x93, 0xe7, 0x98, 0x11, 0x0a, 0x4b, 0x93, 0x7a, 0x59, 0x70, 0xad, - 0x73, 0xe2, 0xc3, 0x73, 0x51, 0x4e, 0xc3, 0x14, 0xef, 0xa6, 0xaf, 0x0c, 0x98, 0xbb, 0x01, 0xc5, - 0x99, 0x9f, 0x1a, 0xa6, 0xc2, 0xcc, 0xe7, 0xd5, 0x3e, 0x10, 0xf1, 0xd2, 0x6f, 0x8a, 0x09, 0xe1, - 0x11, 0xd4, 0xe2, 0x6b, 0x79, 0xb9, 0xe4, 0x6b, 0x79, 0x9f, 0x0b, 0x31, 0x48, 0x96, 0x1f, 0xaf, - 0x59, 0x81, 0xac, 0x6d, 0x5e, 0x50, 0xc5, 0x55, 0x0d, 0x7f, 0x92, 0x26, 0x67, 0x7d, 0x2f, 0x42, - 0xb6, 0xf1, 0xa7, 0xba, 0x0b, 0x65, 0x2d, 0x65, 0xe6, 0x56, 0x24, 0x8f, 0x51, 0x90, 0x7e, 0x09, - 0x32, 0x19, 0x20, 0xad, 0x9c, 0x38, 0x8c, 0x02, 0x35, 0x10, 0x82, 0xef, 0xa5, 0xe1, 0x8f, 0x4e, - 0x0d, 0xbf, 0x6b, 0xb9, 0x93, 0xf0, 0x14, 0x87, 0x9c, 0x3b, 0x72, 0xe5, 0x21, 0x04, 0x0e, 0x8a, - 0xd8, 0x01, 0x47, 0xd1, 0x21, 0xf2, 0xe8, 0xdb, 0x5a, 0xae, 0x75, 0x2e, 0xf2, 0xdf, 0x06, 0xc0, - 0xf1, 0x17, 0x68, 0x7e, 0x90, 0x59, 0xf2, 0x1c, 0x93, 0xa3, 0xd5, 0x2d, 0xd1, 0x5f, 0xf1, 0x68, - 0x55, 0xcb, 0x1a, 0xab, 0x8e, 0x98, 0x79, 0xde, 0x21, 0x31, 0x08, 0xbf, 0xd3, 0x34, 0xb2, 0x7b, - 0x50, 0x89, 0x7c, 0x12, 0xf4, 0xf8, 0x28, 0xaf, 0xbe, 0x1c, 0xc1, 0x7a, 0xf3, 0xa9, 0xfa, 0x77, - 0xb3, 0x50, 0x69, 0xf0, 0x28, 0xa8, 0xd9, 0x65, 0x7f, 0x16, 0xb2, 0x3f, 0x81, 0xab, 0xf4, 0x1a, - 0x19, 0xff, 0x02, 0x01, 0x05, 0x1f, 0xd1, 0xf5, 0x36, 0x31, 0x88, 0x8f, 0xa5, 0x41, 0x14, 0x59, - 0x9e, 0x0c, 0xce, 0xec, 0x19, 0xbf, 0x55, 0xd9, 0x31, 0x2f, 0xe8, 0x0a, 0x23, 0x8f, 0x30, 0xa0, - 0x87, 0xcb, 0xd2, 0x08, 0x7a, 0xbb, 0x08, 0x8b, 0x9f, 0x9d, 0x89, 0x62, 0x45, 0x88, 0x09, 0x02, - 0x8f, 0xce, 0x38, 0xcd, 0x63, 0xd8, 0xe2, 0x17, 0xa9, 0x97, 0x37, 0xe0, 0x4d, 0x8e, 0x48, 0xf8, - 0x7b, 0x00, 0x5b, 0xe2, 0xf1, 0x34, 0x7a, 0x4d, 0x5b, 0x1f, 0x79, 0xb3, 0x4b, 0x71, 0x80, 0xf9, - 0xde, 0x1b, 0x9a, 0xda, 0xe1, 0xa4, 0x08, 0xe2, 0xed, 0xdc, 0x0c, 0xd2, 0xd0, 0x9b, 0x6d, 0xb8, - 0xfe, 0x86, 0x3e, 0xbd, 0x2d, 0x48, 0xa2, 0x28, 0x05, 0x49, 0xdc, 0xdc, 0x85, 0xed, 0x55, 0xf5, - 0xfd, 0x94, 0x32, 0xd4, 0x3f, 0xaf, 0x02, 0x24, 0x1c, 0x9b, 0x52, 0x47, 0x33, 0x0b, 0xea, 0xe8, - 0x4f, 0x0a, 0x80, 0xfa, 0x0c, 0x6a, 0x38, 0x54, 0x7a, 0x92, 0x23, 0xbb, 0x32, 0x47, 0x05, 0xa9, - 0x86, 0xc9, 0x5b, 0x11, 0xcb, 0x81, 0x15, 0xb9, 0x95, 0x81, 0x15, 0x9f, 0x42, 0x81, 0x1f, 0xb5, - 0x05, 0x22, 0xa8, 0xf4, 0xfa, 0xe2, 0xea, 0x7b, 0x22, 0x6e, 0x68, 0x46, 0x74, 0xac, 0x0d, 0x35, - 0x14, 0xfd, 0xbe, 0x1d, 0x9e, 0x4e, 0xe5, 0xc7, 0x4a, 0xee, 0x2c, 0xe7, 0x8c, 0xc8, 0xc4, 0x07, - 0xcd, 0xe4, 0xa4, 0xa4, 0xbd, 0x86, 0x53, 0xe1, 0xff, 0x25, 0xed, 0xb5, 0x20, 0x6b, 0xaf, 0xc3, - 0x29, 0xf7, 0xfa, 0xa2, 0xf6, 0xfa, 0x11, 0x5c, 0x11, 0xb7, 0xc6, 0x31, 0x03, 0x0e, 0x27, 0xd1, - 0xf3, 0x70, 0x78, 0x45, 0xbc, 0x59, 0x36, 0x25, 0xdb, 0x0e, 0xc9, 0xbf, 0x81, 0xed, 0xd1, 0xa9, - 0xe1, 0x4e, 0x2c, 0x3d, 0x3c, 0x71, 0x74, 0xfa, 0xec, 0x91, 0x3e, 0x35, 0x66, 0x42, 0xa9, 0x7e, - 0x6f, 0xa9, 0xb1, 0x4d, 0x22, 0x1e, 0x9e, 0x38, 0x14, 0xac, 0x17, 0x87, 0xdf, 0x6c, 0x8d, 0x16, - 0xe1, 0x0b, 0xa7, 0xe0, 0xb0, 0x74, 0x0a, 0xbe, 0xa8, 0x66, 0x97, 0x57, 0xa8, 0xd9, 0x89, 0xb2, - 0x5c, 0x91, 0x95, 0x65, 0xf6, 0x21, 0x14, 0xc4, 0xa3, 0x17, 0xc2, 0xf3, 0xcb, 0x96, 0x57, 0x87, - 0x16, 0x91, 0x60, 0x4d, 0x51, 0x4c, 0x06, 0xbd, 0x8b, 0x54, 0xe3, 0x35, 0xc9, 0x30, 0xb6, 0x2b, - 0xdc, 0x9e, 0x71, 0x60, 0xa1, 0xf0, 0xf2, 0xde, 0x94, 0x0a, 0x8e, 0x71, 0xc2, 0x2e, 0x5f, 0xc8, - 0x71, 0xf3, 0x3f, 0xd9, 0x80, 0x0d, 0x71, 0xb2, 0xfe, 0x18, 0x72, 0xa6, 0xef, 0xcd, 0xe2, 0xbb, - 0x44, 0x2b, 0xb4, 0x76, 0xfa, 0xee, 0x2e, 0x2a, 0xf8, 0x4f, 0x60, 0xc3, 0x30, 0x4d, 0x7d, 0x7c, - 0x96, 0x3e, 0x91, 0x5e, 0x50, 0xa0, 0x0f, 0xd6, 0xb4, 0xbc, 0x41, 0x9a, 0xf4, 0x97, 0x50, 0x42, - 0xfa, 0x24, 0x54, 0xb7, 0xbc, 0x6c, 0x16, 0x44, 0xaa, 0xee, 0xc1, 0x9a, 0x56, 0x34, 0x22, 0xb5, - 0xf7, 0x8f, 0xd3, 0xbe, 0xfd, 0xdc, 0x52, 0x07, 0x17, 0xf4, 0xb4, 0x05, 0x2f, 0xff, 0xdf, 0x00, - 0xee, 0xec, 0x8d, 0x77, 0xec, 0xbc, 0x7c, 0xf8, 0xb9, 0xb4, 0xbf, 0x1f, 0xac, 0x69, 0x7c, 0xdf, - 0x8a, 0xf6, 0xfb, 0xcf, 0x23, 0xbf, 0x7b, 0xfc, 0xcd, 0xc1, 0x15, 0x23, 0x83, 0x62, 0x30, 0x76, - 0xbe, 0x93, 0x4c, 0xc4, 0x6c, 0x66, 0xf4, 0x21, 0x94, 0xf4, 0x65, 0x83, 0xf4, 0xae, 0x4e, 0xd9, - 0xe2, 0x2d, 0xfe, 0x39, 0x94, 0xb9, 0x1b, 0x96, 0xe7, 0x2b, 0x2e, 0x0d, 0x6d, 0xb2, 0x29, 0xd3, - 0xc1, 0x5e, 0xb2, 0x45, 0x37, 0xa3, 0x7e, 0xfa, 0x96, 0x7c, 0x76, 0x72, 0x6b, 0xe5, 0x40, 0x69, - 0xf1, 0x31, 0x0a, 0xef, 0xac, 0xc6, 0xf3, 0xb0, 0x2e, 0x6c, 0x8b, 0x43, 0x06, 0xbe, 0x01, 0x47, - 0x7b, 0x26, 0x2c, 0xcd, 0x57, 0x6a, 0x87, 0x3e, 0x58, 0xd3, 0x98, 0xb1, 0xbc, 0x6f, 0x37, 0x61, - 0x2b, 0x6a, 0x12, 0xed, 0xac, 0x52, 0xf0, 0x95, 0xdc, 0xa5, 0x64, 0xdf, 0x3d, 0x58, 0xd3, 0x36, - 0x8d, 0x34, 0x88, 0x75, 0xe0, 0x4a, 0x54, 0x08, 0x39, 0xdb, 0xc5, 0xc8, 0x54, 0x96, 0x66, 0x51, - 0xde, 0xab, 0x0f, 0xd6, 0xb4, 0x2d, 0x63, 0x69, 0x03, 0x3f, 0x8c, 0xda, 0x23, 0x2b, 0x87, 0x7c, - 0x25, 0xde, 0x5d, 0x39, 0x4c, 0x89, 0xa6, 0x1a, 0xb7, 0x2c, 0x01, 0x25, 0x91, 0x0c, 0x37, 0x35, - 0xb8, 0xb6, 0x5a, 0xc2, 0xc8, 0xdb, 0x4c, 0x8e, 0x6f, 0x33, 0xaa, 0xbc, 0xcd, 0x2c, 0xbe, 0x73, - 0x26, 0x6d, 0x3a, 0xbf, 0x84, 0x6a, 0x4a, 0xc4, 0xb2, 0x32, 0x14, 0xa2, 0x8f, 0xc0, 0xd0, 0xfd, - 0xcc, 0x66, 0xff, 0xe8, 0x5b, 0x25, 0x83, 0xe0, 0x4e, 0x6f, 0x30, 0x6c, 0xf4, 0x86, 0xca, 0x3a, - 0x4f, 0x1c, 0x75, 0x1b, 0xcd, 0xb6, 0x92, 0x55, 0xff, 0x32, 0x0b, 0xa5, 0xf8, 0x9c, 0xed, 0x77, - 0xf7, 0x86, 0xc5, 0x6e, 0xa6, 0xac, 0xec, 0x66, 0x5a, 0x30, 0xf5, 0xf8, 0xa7, 0x9d, 0x72, 0xd1, - 0xe7, 0x7e, 0x64, 0x83, 0x2a, 0x58, 0x7e, 0xfe, 0x26, 0xff, 0x23, 0x9f, 0xbf, 0x91, 0xa3, 0xf5, - 0x37, 0xd2, 0xd1, 0xfa, 0x0b, 0x1f, 0x02, 0x2a, 0xd0, 0x37, 0x38, 0xe4, 0x0f, 0x01, 0xd1, 0x17, - 0xd1, 0x5f, 0xda, 0xd6, 0xb9, 0x08, 0x6f, 0x17, 0xa9, 0xf4, 0x0e, 0x0d, 0x6f, 0xd9, 0xa1, 0x7f, - 0x8c, 0xb4, 0x7f, 0x0a, 0xdb, 0xe3, 0xb3, 0xf8, 0xcb, 0x1f, 0x89, 0x73, 0xa5, 0x42, 0x4d, 0x5a, - 0x89, 0x63, 0xef, 0xc5, 0x9f, 0x65, 0xad, 0xca, 0x6e, 0xa0, 0x78, 0xb6, 0xe2, 0xef, 0xb4, 0xfe, - 0x8b, 0x19, 0x80, 0xe4, 0x04, 0xea, 0xf7, 0x76, 0xe5, 0x4a, 0xde, 0xb2, 0xec, 0x0f, 0x78, 0xcb, - 0xde, 0xf6, 0xc2, 0xeb, 0xf7, 0x50, 0x8a, 0xcf, 0x1c, 0x7f, 0x77, 0xc6, 0xfa, 0x49, 0x55, 0xfe, - 0xad, 0xc8, 0xad, 0x1d, 0x1f, 0xda, 0xfd, 0xbe, 0x63, 0x91, 0xaa, 0x3e, 0xfb, 0x96, 0xea, 0x2f, - 0xb8, 0x6f, 0x39, 0xae, 0xfc, 0x0f, 0xbc, 0x9a, 0x64, 0x46, 0xcf, 0xa5, 0x2f, 0x4f, 0xcd, 0x85, - 0x83, 0xfc, 0xf7, 0xaf, 0xfa, 0x27, 0x75, 0xf8, 0xff, 0xc8, 0x44, 0x5e, 0xdc, 0xf8, 0x63, 0x2d, - 0x6f, 0x54, 0x7a, 0x57, 0x3b, 0xa2, 0x7f, 0x4a, 0x75, 0x3f, 0xe8, 0xa3, 0xca, 0xfd, 0x90, 0x8f, - 0xea, 0x3d, 0xc8, 0xf3, 0xed, 0x2e, 0xff, 0x26, 0xff, 0x14, 0xc7, 0xbf, 0xf5, 0xe3, 0x6c, 0xaa, - 0x2a, 0x94, 0x7c, 0xde, 0xdf, 0xed, 0xa8, 0xdc, 0xe8, 0xc3, 0x72, 0x74, 0x9b, 0xe8, 0x9f, 0xe2, - 0x12, 0xf5, 0x77, 0x1d, 0x92, 0x1f, 0x76, 0x5b, 0xa8, 0xff, 0x5f, 0x06, 0xaa, 0xa9, 0x18, 0x82, - 0xdf, 0xa1, 0x8a, 0x95, 0x72, 0x39, 0xfb, 0x4f, 0x90, 0x5c, 0x4e, 0x05, 0x02, 0x17, 0xd3, 0x81, - 0xc0, 0x28, 0xee, 0x2a, 0x29, 0x13, 0x66, 0x95, 0xb1, 0x93, 0x59, 0x69, 0xec, 0xdc, 0x89, 0xbf, - 0xaf, 0xdd, 0x69, 0xf1, 0xb8, 0xdb, 0xaa, 0x26, 0x41, 0xd8, 0x57, 0x70, 0x43, 0x38, 0x11, 0xf8, - 0xf8, 0x78, 0x63, 0x3d, 0xfe, 0xfa, 0xb6, 0x30, 0xca, 0xaf, 0x71, 0x02, 0xfe, 0x69, 0xbd, 0x71, - 0x23, 0xc2, 0xaa, 0x1d, 0xa8, 0xa6, 0x82, 0x33, 0x70, 0x6f, 0x99, 0x38, 0xde, 0x89, 0xe1, 0x88, - 0xb6, 0x88, 0x14, 0xdb, 0x81, 0xfc, 0xf9, 0xa9, 0xe5, 0x5b, 0x2b, 0x3e, 0xb0, 0xc0, 0x11, 0xea, - 0xcf, 0xa1, 0x22, 0x07, 0x8a, 0xb1, 0x0f, 0x21, 0x6f, 0x87, 0xd6, 0x34, 0x72, 0x8f, 0x5c, 0x5b, - 0x8e, 0x25, 0xeb, 0x84, 0xd6, 0x54, 0xe3, 0x44, 0xea, 0x9f, 0x65, 0x40, 0x59, 0xc4, 0xd1, 0x27, - 0x4d, 0x2f, 0x83, 0xd0, 0x9a, 0x46, 0x8d, 0xe1, 0x29, 0xa9, 0x91, 0xeb, 0xa9, 0x46, 0x46, 0x5e, - 0xa4, 0x6c, 0xfa, 0x23, 0x71, 0x5c, 0x29, 0x59, 0xf1, 0xf5, 0x7b, 0x42, 0xb0, 0x87, 0x50, 0xf4, - 0x2d, 0xfa, 0x36, 0xbc, 0xb9, 0xe2, 0x96, 0x4d, 0x8c, 0x53, 0xff, 0x4e, 0x06, 0x0a, 0x22, 0xaa, - 0x6d, 0xa5, 0xbf, 0xea, 0x7d, 0x28, 0xf0, 0xef, 0xc4, 0x47, 0x0f, 0xbd, 0x2e, 0xc5, 0xeb, 0x46, - 0x78, 0x76, 0x87, 0xc7, 0xfa, 0xa5, 0xfd, 0x57, 0x47, 0x8e, 0xe1, 0x6a, 0x04, 0x17, 0x5f, 0xcc, - 0x34, 0xa6, 0xe2, 0xe2, 0x07, 0x7f, 0xa1, 0x13, 0x08, 0x44, 0x57, 0x3b, 0xd4, 0x3f, 0x86, 0x82, - 0x88, 0x9a, 0x5b, 0xd9, 0x94, 0xb7, 0x7c, 0xf7, 0x5b, 0xdd, 0x01, 0x48, 0xc2, 0xe8, 0x56, 0x95, - 0xa0, 0x3e, 0x86, 0x62, 0x14, 0x39, 0x87, 0xfc, 0x97, 0x54, 0x2d, 0xae, 0x6f, 0xc9, 0x8d, 0x71, - 0xc4, 0x47, 0x8b, 0xba, 0xde, 0xe8, 0x8c, 0x9c, 0xe5, 0x1f, 0x03, 0xdd, 0x65, 0x1b, 0x2e, 0x3d, - 0x65, 0x9a, 0xfe, 0xba, 0x55, 0x4c, 0xc4, 0x1e, 0x43, 0x2c, 0x2f, 0xdf, 0xe6, 0x5a, 0x50, 0x1b, - 0xd1, 0xad, 0x47, 0xe2, 0xb2, 0x67, 0xc2, 0x9b, 0xda, 0xa5, 0xa7, 0xb4, 0x33, 0xf2, 0xc7, 0x05, - 0x52, 0x6d, 0xd2, 0x24, 0x32, 0xb5, 0x06, 0x15, 0x39, 0xdc, 0x47, 0x6d, 0xc0, 0xd6, 0xa1, 0x15, - 0x1a, 0x28, 0x7f, 0xa2, 0x07, 0x1e, 0x39, 0xff, 0xe2, 0x8f, 0x34, 0xff, 0x2e, 0xd2, 0x69, 0x9c, - 0x48, 0xfd, 0xcb, 0x1c, 0x28, 0x8b, 0xb8, 0x1f, 0xba, 0x01, 0x7a, 0x17, 0xca, 0x1e, 0xf1, 0x45, - 0xea, 0x9b, 0xa8, 0x1c, 0x24, 0xdd, 0x2a, 0x48, 0x7d, 0xce, 0xae, 0x68, 0x07, 0x07, 0xfc, 0x83, - 0x76, 0xd7, 0xf9, 0x75, 0x3f, 0xc7, 0x1b, 0x11, 0x5b, 0x57, 0xe8, 0x76, 0x5f, 0xd7, 0x1b, 0xd1, - 0xc5, 0x52, 0xe1, 0x9d, 0xe0, 0x31, 0xa8, 0x15, 0xad, 0x28, 0x5c, 0x12, 0x74, 0x7e, 0x27, 0xee, - 0x1a, 0x84, 0x81, 0x78, 0xe1, 0xa1, 0xc8, 0x01, 0xc3, 0x20, 0xfa, 0x34, 0xce, 0x48, 0x7c, 0xc0, - 0x33, 0x4b, 0x9f, 0xc6, 0x69, 0xba, 0x74, 0xaf, 0x94, 0x3e, 0x18, 0x30, 0x12, 0x9f, 0x2e, 0x16, - 0x1f, 0x27, 0x42, 0xd4, 0x7d, 0xfe, 0x89, 0x53, 0xdf, 0x0a, 0x02, 0xfe, 0xa2, 0x72, 0x49, 0x3c, - 0xa5, 0x2d, 0x80, 0xf1, 0x83, 0xf5, 0xe2, 0x1b, 0x8c, 0x48, 0x02, 0xe2, 0x5d, 0x67, 0xfe, 0x11, - 0x46, 0x24, 0xb8, 0x01, 0xc5, 0xdf, 0x78, 0xae, 0x45, 0x5e, 0x8e, 0x32, 0xb5, 0xaa, 0x80, 0xe9, - 0x43, 0x63, 0x86, 0x1b, 0x81, 0x43, 0x8f, 0x89, 0xf0, 0x1b, 0x95, 0x3c, 0xa1, 0xfe, 0xb7, 0x19, - 0xd8, 0x5e, 0x1c, 0x6b, 0x62, 0xa3, 0x0a, 0x14, 0x9b, 0xfd, 0xae, 0xde, 0x6b, 0x1c, 0xb6, 0x95, - 0x35, 0xb6, 0x09, 0xe5, 0xfe, 0xee, 0xd7, 0xed, 0xe6, 0x90, 0x03, 0x32, 0xf4, 0xb2, 0xd0, 0x40, - 0x3f, 0xe8, 0xb4, 0x5a, 0xed, 0x1e, 0xb7, 0x28, 0xfa, 0xbb, 0x5f, 0xeb, 0xdd, 0x7e, 0x93, 0x7f, - 0x7a, 0x32, 0x0a, 0x84, 0x18, 0x28, 0x39, 0x0a, 0x93, 0xa0, 0x70, 0x78, 0x4c, 0xe6, 0x79, 0x9c, - 0xf7, 0xab, 0x81, 0xde, 0xec, 0x0d, 0x95, 0x0d, 0x4c, 0xf5, 0x8e, 0xbb, 0x5d, 0x4a, 0x51, 0x40, - 0x67, 0xb3, 0x7f, 0x78, 0xa4, 0xb5, 0x07, 0x03, 0x7d, 0xd0, 0xf9, 0x75, 0x5b, 0x29, 0x52, 0xcd, - 0x5a, 0x67, 0xbf, 0xd3, 0xe3, 0x80, 0x12, 0x2b, 0x40, 0xf6, 0xb0, 0xd3, 0xe3, 0x2f, 0x2a, 0x1d, - 0x36, 0xbe, 0x51, 0xca, 0xf8, 0x63, 0x70, 0x7c, 0xa8, 0x54, 0x58, 0x09, 0xf2, 0xdd, 0xf6, 0xcb, - 0x76, 0x57, 0xa9, 0xaa, 0xff, 0x73, 0x36, 0xd2, 0x88, 0x29, 0xd2, 0xe9, 0xc7, 0x68, 0x81, 0xab, - 0xce, 0x17, 0xe3, 0x41, 0xcb, 0x4a, 0x83, 0xc6, 0xee, 0x41, 0x45, 0x6c, 0x0a, 0xa9, 0xef, 0xd8, - 0x0a, 0x18, 0xb1, 0xdc, 0x7d, 0xa8, 0xc6, 0xc1, 0x01, 0xd2, 0xe7, 0x6c, 0x2a, 0x11, 0x70, 0xc5, - 0xf1, 0xc5, 0xc6, 0x8a, 0xe3, 0x8b, 0x99, 0x1d, 0xa2, 0x95, 0x8d, 0x32, 0x97, 0x73, 0x52, 0x09, - 0x21, 0xf4, 0x21, 0x76, 0xba, 0xec, 0x89, 0xe8, 0xb9, 0x6b, 0x47, 0x1f, 0xc2, 0x2e, 0x22, 0xe0, - 0xd8, 0xb5, 0xc3, 0xc5, 0xe0, 0x84, 0xd2, 0x52, 0x70, 0x82, 0xbc, 0x39, 0x43, 0x7a, 0x73, 0xbe, - 0x1d, 0xef, 0x91, 0x88, 0xe4, 0x5f, 0xc0, 0x2e, 0xc5, 0xbb, 0x20, 0x7d, 0xb0, 0x78, 0xee, 0xd3, - 0xe3, 0xb2, 0x12, 0x59, 0x85, 0xc8, 0x14, 0x81, 0x89, 0x77, 0x45, 0xba, 0x6b, 0x9f, 0xa6, 0x26, - 0x5b, 0xba, 0xa4, 0xd5, 0xd2, 0xa4, 0xec, 0x09, 0x5c, 0x11, 0xbc, 0x9d, 0x1a, 0x5b, 0x71, 0x4d, - 0x97, 0xa3, 0x1a, 0xc9, 0x08, 0xab, 0x7f, 0x04, 0xc5, 0x28, 0xa8, 0xed, 0x87, 0x95, 0xdd, 0x15, - 0xf3, 0xaa, 0xfe, 0xfb, 0xeb, 0x50, 0x8a, 0x43, 0xdc, 0x7e, 0x14, 0x77, 0xd0, 0x77, 0xbb, 0x82, - 0x33, 0x59, 0xc4, 0x14, 0x11, 0x10, 0xcd, 0x94, 0xb8, 0xf3, 0x35, 0xf7, 0xed, 0x48, 0x63, 0xe3, - 0x90, 0x63, 0xdf, 0xa6, 0x17, 0xe4, 0x6c, 0x57, 0xba, 0x50, 0x5b, 0xd2, 0x8a, 0x08, 0xa0, 0x85, - 0x76, 0x03, 0xe8, 0x37, 0xe5, 0xe4, 0x4c, 0x52, 0xc0, 0x34, 0xe6, 0xbb, 0x16, 0xdb, 0x7f, 0x9c, - 0x37, 0x44, 0x8a, 0xbe, 0x3a, 0xc6, 0xa3, 0x6b, 0x78, 0x4c, 0x41, 0xf4, 0x65, 0xdf, 0x77, 0xa0, - 0x34, 0x8f, 0x3f, 0x0d, 0x2d, 0x38, 0x62, 0x1e, 0x7d, 0x18, 0x3a, 0x3d, 0xab, 0xa5, 0xc5, 0x59, - 0x5d, 0xe4, 0x69, 0x58, 0xe2, 0x69, 0x35, 0x84, 0x82, 0x08, 0xf3, 0xfb, 0xe1, 0x01, 0xff, 0xc1, - 0xa1, 0x52, 0x20, 0x6b, 0x38, 0xd1, 0x2d, 0x5e, 0xfc, 0xb9, 0xd0, 0xb0, 0xdc, 0x42, 0xc3, 0xd4, - 0x7f, 0x73, 0x1d, 0x20, 0x09, 0x17, 0x64, 0x1f, 0x2d, 0x84, 0x26, 0x67, 0x96, 0xb6, 0xfd, 0x85, - 0x88, 0xe4, 0x85, 0x27, 0x15, 0xd7, 0x7f, 0xc4, 0x93, 0x8a, 0x4f, 0xa1, 0x1a, 0xf8, 0xa3, 0xb7, - 0x3a, 0xdc, 0xcb, 0x81, 0x3f, 0x8a, 0xfd, 0xed, 0x1f, 0x03, 0x26, 0xe9, 0xb9, 0xe5, 0xc4, 0x50, - 0x5d, 0xd2, 0x5a, 0x4a, 0x81, 0x3f, 0xea, 0x9f, 0x7c, 0xd7, 0xe2, 0x17, 0xed, 0xcc, 0x20, 0xd4, - 0x57, 0x49, 0x89, 0x4d, 0x33, 0x08, 0x5b, 0xb2, 0xa0, 0x78, 0x00, 0x35, 0xa4, 0x5d, 0x12, 0x16, - 0x15, 0x33, 0x48, 0x0e, 0x58, 0xd4, 0x7f, 0x36, 0x3a, 0x92, 0x5e, 0xf0, 0xe5, 0xb2, 0x2f, 0x84, - 0x21, 0x2e, 0x29, 0x11, 0xf5, 0x55, 0xae, 0x5f, 0x7e, 0x83, 0x36, 0x26, 0x5d, 0xfe, 0x8c, 0xef, - 0xfa, 0x8f, 0xfd, 0x8c, 0xef, 0x0e, 0x40, 0xf2, 0xe0, 0x35, 0xae, 0xc0, 0xf8, 0xba, 0x4e, 0x89, - 0x5f, 0xc4, 0x79, 0x7c, 0x08, 0x57, 0x1a, 0x93, 0x89, 0x6f, 0x4d, 0xe8, 0x5b, 0x47, 0xee, 0xd8, - 0x9e, 0x44, 0x31, 0x9f, 0x8d, 0xfd, 0x7d, 0xbd, 0xd9, 0xef, 0xed, 0x75, 0xf6, 0xa3, 0xf7, 0xc0, - 0xee, 0xc1, 0x6d, 0x09, 0xb8, 0xaf, 0xf5, 0x8f, 0x8f, 0x30, 0xd1, 0x6c, 0x0c, 0xf5, 0xbe, 0xd6, - 0x6a, 0x6b, 0x4a, 0xe6, 0xf1, 0x3d, 0xa8, 0x34, 0xc5, 0x4e, 0x19, 0xbf, 0x51, 0xe6, 0xb9, 0x16, - 0xff, 0xa2, 0x5a, 0xf7, 0x37, 0x9f, 0x29, 0x99, 0xc7, 0x2a, 0x94, 0xa5, 0xef, 0x19, 0x22, 0xc5, - 0x81, 0x11, 0x9c, 0x8a, 0xaf, 0x6b, 0x19, 0xee, 0xc4, 0x52, 0x32, 0x8f, 0x1f, 0xa2, 0x0e, 0x2f, - 0x7f, 0x4d, 0x10, 0x60, 0xa3, 0xe7, 0xf9, 0x53, 0xc3, 0x11, 0x74, 0xd6, 0x3c, 0x40, 0xba, 0x8f, - 0xe1, 0xea, 0xca, 0x6f, 0x23, 0xd2, 0x9d, 0x30, 0x7b, 0x3a, 0x73, 0x2c, 0x7e, 0xbb, 0xe9, 0xe0, - 0xf2, 0xc4, 0xb7, 0x4d, 0x25, 0xf3, 0xf8, 0xf9, 0xc2, 0xb7, 0xb3, 0x8e, 0x7b, 0xbb, 0xfd, 0xe3, - 0x5e, 0x8b, 0x9e, 0x0f, 0xa3, 0x57, 0xfa, 0x9a, 0xdd, 0xe3, 0x41, 0xe7, 0xa5, 0xd8, 0x5a, 0xdb, - 0xdf, 0x44, 0xc9, 0xf5, 0xc7, 0xdf, 0x44, 0x0f, 0x61, 0x44, 0xad, 0xee, 0xf6, 0x1b, 0x2d, 0xbe, - 0x25, 0xc7, 0x8f, 0x0e, 0x0e, 0x77, 0xf9, 0x37, 0xb7, 0xb4, 0xf6, 0xe0, 0xb8, 0x3b, 0x8c, 0xde, - 0x33, 0xac, 0x01, 0x74, 0x9a, 0xed, 0xdd, 0xb6, 0xb6, 0x8f, 0x04, 0x59, 0x4c, 0x1f, 0xf6, 0x7b, - 0xfb, 0xfd, 0xd6, 0x2e, 0xa6, 0x73, 0x8f, 0xff, 0x9b, 0x75, 0x50, 0x16, 0xdf, 0x2e, 0x61, 0xef, - 0xc0, 0x75, 0x22, 0xd2, 0x8f, 0xb4, 0x76, 0xab, 0xd3, 0xe4, 0xe1, 0xb0, 0x2f, 0x1b, 0xdd, 0x0e, - 0xd6, 0x79, 0x1d, 0xae, 0x2c, 0x22, 0x1b, 0xbd, 0x16, 0x7f, 0xe5, 0x6c, 0x11, 0xd1, 0xfe, 0xd5, - 0x71, 0xa3, 0xab, 0xac, 0xb3, 0xdb, 0x70, 0x63, 0x11, 0xd5, 0xeb, 0x0f, 0x05, 0x3a, 0xcb, 0xea, - 0xb0, 0xbd, 0x88, 0xee, 0xb6, 0x07, 0xa8, 0x37, 0xdc, 0x81, 0x9b, 0xab, 0x30, 0x22, 0x67, 0x7e, - 0x55, 0x4b, 0xf7, 0x49, 0xed, 0xd0, 0x94, 0x0d, 0x64, 0x99, 0x37, 0x20, 0x45, 0xfe, 0x02, 0xbb, - 0x06, 0x6c, 0xb9, 0xa7, 0x4a, 0x71, 0xe5, 0x08, 0x0c, 0xf8, 0x77, 0xb6, 0x4b, 0xec, 0x2e, 0xbc, - 0xb3, 0x0a, 0xd9, 0x17, 0x1f, 0xe2, 0x86, 0xc7, 0xff, 0x30, 0x03, 0xf5, 0x37, 0x5d, 0x65, 0x67, - 0x2a, 0xdc, 0xd1, 0x8e, 0x7b, 0xf4, 0xea, 0x20, 0x7f, 0x20, 0x51, 0x7f, 0xd1, 0xfe, 0x76, 0xe1, - 0x31, 0xb9, 0xdb, 0x70, 0x63, 0x05, 0x8d, 0xd6, 0x78, 0xa5, 0xbf, 0xfc, 0x54, 0xc9, 0xb0, 0x0f, - 0xe0, 0xbd, 0x15, 0xe8, 0xbd, 0x6e, 0xbf, 0x31, 0xd4, 0x7f, 0xdd, 0xd6, 0xfa, 0x7a, 0xb3, 0xdb, - 0x1f, 0xb4, 0x5b, 0x48, 0xbc, 0xce, 0x76, 0xe0, 0xd6, 0x0a, 0xe2, 0x01, 0x7f, 0xbc, 0xf2, 0xe5, - 0xa7, 0x4a, 0x96, 0xbd, 0x0b, 0xf7, 0xde, 0x4c, 0xb1, 0x87, 0x9a, 0xd9, 0xcb, 0x4f, 0x95, 0xdc, - 0xe3, 0x5f, 0x42, 0xfd, 0x4d, 0x77, 0xcd, 0x70, 0x59, 0x34, 0x0f, 0x1a, 0x74, 0x9f, 0x0f, 0xb5, - 0xb9, 0xbe, 0xce, 0x53, 0xe4, 0x73, 0xd6, 0xda, 0xdd, 0x36, 0x05, 0x64, 0x3f, 0xfe, 0x6d, 0x46, - 0xb2, 0x6c, 0xa2, 0xfb, 0x42, 0x31, 0x40, 0xac, 0x55, 0x19, 0xa4, 0x59, 0x86, 0xa9, 0x64, 0x70, - 0x96, 0x52, 0xa0, 0xae, 0x37, 0x32, 0x1c, 0x65, 0x9d, 0x42, 0xaf, 0x23, 0x38, 0xdd, 0x4d, 0x55, - 0xb2, 0x38, 0x74, 0x31, 0xac, 0xeb, 0x9d, 0x1f, 0xf9, 0xb6, 0xe7, 0xdb, 0xe1, 0x25, 0x47, 0xe7, - 0x1e, 0xff, 0xd3, 0x22, 0x6c, 0x20, 0x25, 0xef, 0xb0, 0x82, 0x86, 0x69, 0x26, 0x30, 0xda, 0x62, - 0x39, 0xaf, 0x93, 0x7e, 0xb1, 0x80, 0xc8, 0x20, 0x7f, 0x44, 0xee, 0x97, 0x45, 0xe4, 0x3a, 0x22, - 0x35, 0x8b, 0x82, 0x76, 0x97, 0x90, 0xd9, 0xdd, 0x5f, 0xfc, 0x83, 0xbf, 0xba, 0x93, 0xf9, 0xaf, - 0xff, 0xea, 0x4e, 0xe6, 0x7f, 0xf9, 0xab, 0x3b, 0x6b, 0x7f, 0xf6, 0xbf, 0xdd, 0xc9, 0xfc, 0xfa, - 0xa3, 0x89, 0x1d, 0x9e, 0xce, 0x4f, 0x9e, 0x8c, 0xbc, 0xe9, 0xc7, 0x53, 0x23, 0xf4, 0xed, 0x0b, - 0xae, 0xe8, 0x44, 0x09, 0xd7, 0xfa, 0x78, 0x76, 0x36, 0xf9, 0x78, 0x76, 0xf2, 0x31, 0x8a, 0xdc, - 0x93, 0x8d, 0x99, 0xef, 0x85, 0xde, 0xb3, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x64, 0x21, 0x73, - 0x5c, 0x2d, 0x95, 0x00, 0x00, + 0x57, 0x09, 0xcf, 0xbd, 0x4c, 0x0d, 0xc2, 0x92, 0xe4, 0xfb, 0x04, 0xb6, 0xed, 0x89, 0xeb, 0xf9, + 0x51, 0x16, 0xcb, 0xe4, 0x99, 0xf8, 0x31, 0x04, 0xe3, 0xb8, 0x86, 0x40, 0x61, 0x0e, 0xf5, 0xdf, + 0xcd, 0x40, 0x89, 0x37, 0x14, 0xe7, 0xf4, 0x1e, 0x64, 0x7f, 0x60, 0x3e, 0x11, 0xc7, 0x1e, 0xc3, + 0x96, 0x61, 0x9a, 0x0b, 0xe5, 0x73, 0x01, 0xb2, 0x69, 0x98, 0xa6, 0x5c, 0x38, 0xf9, 0x42, 0x03, + 0x3d, 0xb2, 0x58, 0x93, 0x23, 0xfe, 0xa2, 0x56, 0xb3, 0x03, 0x61, 0xb0, 0x72, 0x77, 0x76, 0x8a, + 0x45, 0x72, 0x3f, 0xcc, 0x22, 0x2a, 0x03, 0xd0, 0x2c, 0x92, 0x16, 0xcd, 0xf0, 0xe2, 0xeb, 0x5c, + 0x31, 0xa3, 0x80, 0xfa, 0x9f, 0x95, 0xa1, 0xdc, 0x70, 0x0d, 0xe7, 0xf2, 0x37, 0x16, 0xc5, 0x27, + 0x90, 0x73, 0x73, 0x36, 0x17, 0x83, 0xc6, 0x8f, 0xd6, 0x4a, 0x04, 0xa1, 0x96, 0xdd, 0x85, 0xb2, + 0x37, 0x0f, 0x63, 0x3c, 0x3f, 0x6c, 0x03, 0x0e, 0x22, 0x82, 0x38, 0x7f, 0xec, 0x38, 0x8f, 0xf2, + 0x93, 0x1e, 0x9f, 0xe4, 0x8f, 0x75, 0xbb, 0x38, 0x3f, 0x11, 0xdc, 0x87, 0x6a, 0x68, 0x4f, 0x2d, + 0x3a, 0x5f, 0x9c, 0x4f, 0x2d, 0x93, 0x07, 0x41, 0xf2, 0xb8, 0xba, 0xa6, 0x80, 0x61, 0x29, 0x53, + 0x6b, 0xea, 0xf9, 0x97, 0xbc, 0x94, 0x0d, 0x5e, 0x0a, 0x07, 0x51, 0x29, 0x1f, 0x02, 0x3b, 0x37, + 0xec, 0x50, 0x4f, 0x17, 0xc5, 0xf5, 0x69, 0x05, 0x31, 0x43, 0xb9, 0xb8, 0x6b, 0xb0, 0x61, 0xda, + 0xc1, 0x59, 0xa7, 0x2f, 0x74, 0x69, 0x91, 0xc2, 0xbe, 0x04, 0x23, 0x03, 0xb7, 0xf2, 0xd0, 0xe2, + 0x7a, 0x5f, 0x56, 0x2b, 0x21, 0x64, 0x17, 0x01, 0xb8, 0x15, 0xb8, 0x56, 0x78, 0xee, 0xf9, 0x98, + 0x93, 0xab, 0xca, 0x09, 0x00, 0xb7, 0x4c, 0x24, 0xc5, 0x8a, 0x88, 0x5b, 0xb3, 0x5a, 0x9c, 0x46, + 0x25, 0x94, 0x73, 0x2e, 0x61, 0x2b, 0xbc, 0xf9, 0x09, 0x84, 0x3d, 0x80, 0x1a, 0x35, 0x9f, 0x54, + 0x69, 0xec, 0x03, 0x31, 0x62, 0x56, 0xab, 0x20, 0x94, 0x2c, 0x70, 0xa4, 0xfa, 0x0a, 0x6e, 0xa4, + 0xfa, 0xa7, 0x1b, 0xbe, 0x6f, 0x5c, 0xea, 0x53, 0xe3, 0x3b, 0xcf, 0x27, 0x6f, 0x49, 0x56, 0xbb, + 0x26, 0x0f, 0x5b, 0x03, 0xd1, 0x87, 0x88, 0x7d, 0x63, 0x56, 0xdb, 0xf5, 0x7c, 0x72, 0xa5, 0xac, + 0xcc, 0x8a, 0x58, 0xb2, 0xfb, 0x69, 0x82, 0x49, 0xaf, 0x0f, 0x78, 0x3c, 0xa6, 0x56, 0x26, 0xd8, + 0x2e, 0x81, 0x50, 0xb3, 0x0d, 0x9e, 0x71, 0x09, 0xbb, 0x25, 0x82, 0xa3, 0x9e, 0x91, 0xec, 0xe4, + 0x88, 0x53, 0xcb, 0x30, 0xe9, 0x8c, 0x8d, 0x10, 0x07, 0x96, 0x41, 0x27, 0xd8, 0xc1, 0x33, 0x7d, + 0x36, 0x0f, 0x79, 0x20, 0xa5, 0x96, 0x0f, 0x9e, 0x1d, 0xcd, 0x43, 0x01, 0x9e, 0x58, 0x21, 0x1d, + 0xa9, 0x11, 0x78, 0xdf, 0x0a, 0x51, 0x3d, 0x0d, 0x9e, 0x45, 0x9e, 0xe5, 0xab, 0x62, 0x6c, 0x9f, + 0x09, 0xd7, 0xb1, 0x0a, 0xd5, 0x18, 0xa9, 0x4f, 0xe7, 0x3c, 0x72, 0x32, 0xab, 0x95, 0x23, 0x82, + 0xc3, 0xb9, 0x83, 0x13, 0x3b, 0x32, 0x46, 0xa7, 0x96, 0xee, 0x63, 0x53, 0xae, 0xf3, 0xa9, 0x23, + 0x88, 0x86, 0xad, 0x79, 0x07, 0x78, 0x42, 0x3f, 0xb5, 0x43, 0x72, 0xe9, 0x64, 0xb5, 0x22, 0x01, + 0x0e, 0xec, 0x10, 0xd7, 0x31, 0x47, 0x0a, 0x0e, 0xa4, 0x22, 0x6e, 0x10, 0xd1, 0x26, 0x21, 0x0e, + 0x09, 0x4e, 0x05, 0x3d, 0x02, 0x25, 0x45, 0x8b, 0xe5, 0xdd, 0x24, 0xd2, 0x9a, 0x44, 0x8a, 0xa5, + 0x3e, 0x04, 0x9e, 0x59, 0x47, 0xd6, 0xe3, 0x65, 0xbe, 0xc3, 0xed, 0x3a, 0x02, 0xb7, 0xec, 0xe0, + 0x8c, 0x4a, 0x7c, 0x00, 0x35, 0x89, 0x0e, 0xcb, 0xbb, 0xc5, 0x39, 0x23, 0x26, 0x4b, 0xb5, 0xd1, + 0xb7, 0xa6, 0x5e, 0x28, 0xba, 0x79, 0x5b, 0x6a, 0xa3, 0x46, 0xf0, 0x74, 0x1b, 0x05, 0x2d, 0x96, + 0x79, 0x47, 0x6a, 0x23, 0x27, 0xc5, 0x52, 0xef, 0x41, 0xe5, 0xdc, 0xb7, 0xc3, 0xd0, 0x72, 0xf9, + 0xe2, 0xbf, 0xcb, 0x07, 0x56, 0xc0, 0x68, 0xf5, 0xdf, 0x83, 0x0a, 0x1f, 0x79, 0x21, 0xdf, 0x76, + 0x38, 0x89, 0x80, 0x45, 0x02, 0x42, 0x8c, 0xc6, 0xd4, 0x76, 0xc9, 0x6f, 0x93, 0xd5, 0x4a, 0x1c, + 0x82, 0xe6, 0xad, 0x84, 0x36, 0x2e, 0xc8, 0x7b, 0x93, 0xa0, 0x8d, 0x0b, 0x5a, 0x92, 0x33, 0xdb, + 0x71, 0xf8, 0xc2, 0xbf, 0x2f, 0x96, 0x24, 0x42, 0x68, 0xdd, 0xc7, 0x68, 0xaa, 0xfd, 0x81, 0x84, + 0xa6, 0xba, 0x91, 0x71, 0x08, 0x8d, 0x55, 0xbf, 0x2b, 0x18, 0x07, 0x01, 0x58, 0x73, 0x82, 0x34, + 0x2e, 0xc8, 0x37, 0x13, 0x23, 0x8d, 0x0b, 0x21, 0xb7, 0xb0, 0x54, 0xca, 0xfb, 0x5e, 0x2c, 0xb7, + 0x10, 0x84, 0xb9, 0x65, 0x02, 0xe3, 0xa2, 0xfe, 0x28, 0x4d, 0x60, 0x5c, 0x90, 0x4d, 0x65, 0x19, + 0x26, 0x6f, 0xf8, 0xfb, 0xbc, 0x78, 0x04, 0x50, 0xbb, 0x77, 0xa0, 0x12, 0x3c, 0xd3, 0x13, 0xfc, + 0x63, 0x9e, 0x3d, 0x78, 0xa6, 0x45, 0x14, 0x0f, 0xa0, 0x16, 0xb3, 0x06, 0xa7, 0xf9, 0x80, 0x4f, + 0xbc, 0x29, 0x58, 0x83, 0x8e, 0x24, 0x7f, 0x9b, 0x81, 0x9b, 0x7d, 0x72, 0x3b, 0x91, 0xf8, 0x3f, + 0xb4, 0x82, 0xc0, 0x98, 0x58, 0x7b, 0x9e, 0xbf, 0x37, 0xff, 0xcd, 0x6f, 0x2e, 0xd9, 0x23, 0xd8, + 0x3c, 0x32, 0x7c, 0xcb, 0x0d, 0xe3, 0xc3, 0x34, 0xe1, 0xcb, 0x59, 0x04, 0xb3, 0xe7, 0xa0, 0x70, + 0x10, 0x0f, 0x0c, 0x6b, 0x46, 0x07, 0x44, 0x8b, 0x1e, 0xeb, 0x25, 0x2a, 0x34, 0x0f, 0x4b, 0x2d, + 0x3b, 0x08, 0x35, 0xc3, 0x9d, 0xa0, 0x8c, 0x52, 0x1c, 0xef, 0x1c, 0x6d, 0x1c, 0x54, 0x7c, 0x75, + 0x49, 0xd5, 0x16, 0xbb, 0x64, 0xa2, 0x5f, 0xd7, 0x88, 0x30, 0x51, 0x90, 0xbf, 0x02, 0x65, 0x3e, + 0x9b, 0xa5, 0xb3, 0xae, 0xbf, 0x21, 0x2b, 0x11, 0x26, 0x59, 0x3f, 0x80, 0xb2, 0x54, 0xeb, 0x0a, + 0x75, 0x1c, 0x92, 0xba, 0x90, 0x58, 0xaa, 0x67, 0x45, 0x60, 0x2a, 0x24, 0xa5, 0xab, 0xff, 0xfc, + 0x3a, 0x28, 0xe4, 0x4e, 0xd3, 0x28, 0xa0, 0x80, 0xce, 0xe4, 0x52, 0x86, 0x5c, 0xe6, 0xad, 0x86, + 0xdc, 0x0e, 0xe4, 0x1d, 0x7b, 0x1a, 0xc7, 0x67, 0xa5, 0x4e, 0x8a, 0x08, 0x81, 0x73, 0xed, 0xf9, + 0xf6, 0x84, 0x4c, 0x4e, 0x39, 0x56, 0x91, 0x3c, 0x8a, 0x68, 0xc1, 0xd1, 0x14, 0x3d, 0x01, 0x30, + 0xed, 0x20, 0xd4, 0xc9, 0x09, 0x23, 0x9a, 0x2d, 0x46, 0x26, 0x1e, 0x7f, 0xad, 0x64, 0xc6, 0x53, + 0xf1, 0x08, 0x14, 0x49, 0x6d, 0x73, 0x63, 0xff, 0x49, 0x5e, 0x4b, 0xd4, 0xb9, 0xa6, 0xdb, 0x74, + 0xc3, 0x25, 0x4a, 0x54, 0xb8, 0x36, 0x96, 0x28, 0x3b, 0xe6, 0x85, 0xfa, 0xf7, 0xde, 0x85, 0x5c, + 0xcf, 0x33, 0x2d, 0xf6, 0x09, 0x94, 0x28, 0x00, 0x58, 0x9a, 0x60, 0xa1, 0x56, 0x23, 0x9a, 0xfe, + 0xd0, 0x4c, 0x15, 0x5d, 0xf1, 0xeb, 0xcd, 0x21, 0xc3, 0xf7, 0xc8, 0x1c, 0xa4, 0x63, 0x63, 0xec, + 0x52, 0x59, 0xb8, 0xac, 0xc8, 0xc3, 0xc2, 0x31, 0xb8, 0xb7, 0xd2, 0xc1, 0x80, 0x6f, 0xb9, 0xa4, + 0xc3, 0xe7, 0xb5, 0x38, 0x4d, 0x46, 0xb8, 0xef, 0xa1, 0xea, 0xc5, 0x77, 0xa0, 0xfc, 0x0a, 0x23, + 0x9c, 0xe3, 0x69, 0x4b, 0xfa, 0x04, 0x4a, 0xdf, 0x79, 0xb6, 0xcb, 0x1b, 0xbe, 0xb1, 0xd4, 0x70, + 0xb4, 0x71, 0x78, 0xc3, 0xbf, 0x13, 0xbf, 0xd8, 0x7d, 0x28, 0x78, 0x2e, 0x2f, 0xbb, 0xb0, 0x54, + 0xf6, 0x86, 0xe7, 0x76, 0x79, 0x04, 0x58, 0xd5, 0x0e, 0x74, 0xdf, 0x9e, 0x9c, 0x86, 0x3a, 0xe6, + 0x14, 0xc7, 0xcd, 0x65, 0x3b, 0xd0, 0x10, 0x86, 0xc5, 0x22, 0xe3, 0x8d, 0x6d, 0x07, 0x35, 0x3c, + 0x2a, 0xac, 0xb4, 0x54, 0x18, 0x70, 0x34, 0x15, 0xf8, 0x2e, 0x14, 0x27, 0xbe, 0x87, 0x66, 0xc7, + 0x65, 0x1d, 0x96, 0x28, 0x0b, 0x84, 0xdb, 0xbd, 0x44, 0xf5, 0x89, 0x7e, 0xda, 0xee, 0x44, 0x27, + 0xbf, 0x4a, 0x79, 0x27, 0xfb, 0xa8, 0xa8, 0x55, 0x22, 0x20, 0x79, 0x4c, 0xde, 0x85, 0xa2, 0x31, + 0x99, 0xe8, 0x22, 0x90, 0x6d, 0xa9, 0x2c, 0x63, 0x32, 0xa1, 0x2a, 0x9f, 0x40, 0xf5, 0xdc, 0x76, + 0xf5, 0x60, 0x66, 0x8d, 0x38, 0x6d, 0x75, 0x79, 0x28, 0xcf, 0x6d, 0x17, 0xb9, 0x9b, 0xe8, 0xe5, + 0x65, 0x50, 0xfb, 0xf1, 0xcb, 0x60, 0xf3, 0x4d, 0xcb, 0x40, 0x85, 0x0d, 0x71, 0x68, 0xa0, 0x2c, + 0x91, 0x08, 0x0c, 0xfb, 0x14, 0xca, 0xbe, 0xe1, 0x9e, 0xe9, 0xe2, 0xec, 0xfe, 0x5b, 0xd9, 0x37, + 0xa0, 0x19, 0xee, 0x99, 0x38, 0xba, 0x07, 0x3f, 0xfe, 0x9d, 0x56, 0x99, 0xb7, 0xde, 0x62, 0x55, + 0x49, 0xc6, 0x1a, 0xfb, 0x61, 0x63, 0xed, 0x73, 0xb2, 0x8a, 0x2c, 0x37, 0xd4, 0xa3, 0x0c, 0x57, + 0x56, 0x67, 0xa8, 0x70, 0xb2, 0x3e, 0xcf, 0x86, 0x1d, 0x20, 0xdf, 0x9c, 0x4e, 0x8e, 0xbc, 0xed, + 0x54, 0x07, 0x62, 0xa7, 0x9d, 0x06, 0x7e, 0xe2, 0xc0, 0x6b, 0xc0, 0x66, 0x12, 0x3f, 0xcc, 0x83, + 0xb6, 0xaf, 0xca, 0x87, 0x03, 0xa9, 0x80, 0xe3, 0xc8, 0x0e, 0xb3, 0x53, 0x51, 0xc8, 0xf7, 0xa1, + 0xca, 0x83, 0x65, 0xf8, 0xb8, 0x05, 0xa4, 0x24, 0x95, 0xb4, 0x0a, 0x01, 0xf9, 0x38, 0x05, 0x24, + 0x60, 0x84, 0x71, 0x18, 0x5e, 0x90, 0x96, 0x94, 0x08, 0x18, 0x6e, 0x0d, 0x86, 0x17, 0x5a, 0xc9, + 0x8c, 0x7e, 0xe2, 0xe6, 0x7f, 0x62, 0xbb, 0x26, 0xb2, 0x5e, 0x68, 0x4c, 0x82, 0x7a, 0x9d, 0x56, + 0x66, 0x59, 0xc0, 0x86, 0xc6, 0x24, 0x60, 0x9f, 0x41, 0xc5, 0xe0, 0xc6, 0x06, 0x6f, 0xf7, 0x0d, + 0xd9, 0x97, 0x25, 0x99, 0x21, 0x5a, 0xd9, 0x90, 0x6c, 0x92, 0x2f, 0x81, 0x45, 0x67, 0x9a, 0x92, + 0xe5, 0x7f, 0x73, 0x89, 0x1b, 0x37, 0xc5, 0xa1, 0x66, 0x6c, 0xf7, 0xdf, 0x85, 0x32, 0xf7, 0x6d, + 0xe8, 0x41, 0x68, 0xcd, 0xea, 0xef, 0x50, 0x83, 0x80, 0x83, 0x06, 0xa1, 0x35, 0x63, 0x5f, 0x42, + 0x35, 0x6d, 0x65, 0xdd, 0x5a, 0x71, 0x34, 0x48, 0x6c, 0xa1, 0x55, 0x46, 0xb2, 0xdd, 0x75, 0x9f, + 0xc7, 0xc1, 0x93, 0x86, 0x44, 0x19, 0xf9, 0xf1, 0x57, 0xc5, 0xf5, 0xc2, 0x66, 0x04, 0xc3, 0x01, + 0x8c, 0x4c, 0xf2, 0xf0, 0x82, 0x94, 0xaa, 0x78, 0x00, 0x63, 0xd3, 0x11, 0x8d, 0xa3, 0xc8, 0x8a, + 0x6c, 0x01, 0x0f, 0x0e, 0xa1, 0x4d, 0xde, 0xf2, 0x79, 0x20, 0x08, 0xe9, 0x50, 0xf1, 0x69, 0xe1, + 0xe2, 0xde, 0xa3, 0xf1, 0xa0, 0x19, 0x79, 0x37, 0x7a, 0x0e, 0xb5, 0x99, 0x6f, 0xe9, 0x52, 0xcd, + 0xaa, 0xdc, 0xa9, 0x23, 0xdf, 0x4a, 0x2a, 0xaf, 0xcc, 0xa4, 0x14, 0xfb, 0x05, 0x6c, 0x49, 0x39, + 0xe7, 0x67, 0x94, 0xf9, 0x3e, 0x65, 0xde, 0x5e, 0xc8, 0x7c, 0x7c, 0x86, 0xd9, 0x6b, 0xb3, 0x54, + 0x9a, 0x6d, 0x43, 0xbe, 0x13, 0xb4, 0x5d, 0x93, 0x74, 0xab, 0xa2, 0xc6, 0x13, 0xec, 0x19, 0x54, + 0xb8, 0x21, 0x43, 0xb1, 0xb4, 0x41, 0xfd, 0xa1, 0xec, 0xac, 0x26, 0x6b, 0x86, 0x10, 0x5a, 0xd9, + 0x89, 0x7f, 0x07, 0xec, 0x0b, 0xd8, 0xe2, 0x27, 0x09, 0xb2, 0x88, 0x7c, 0x6f, 0x79, 0xca, 0x89, + 0x68, 0x2f, 0x91, 0x93, 0x1a, 0xdc, 0xf0, 0xe7, 0x2e, 0x19, 0x37, 0x22, 0x27, 0xf7, 0x71, 0x51, + 0xfe, 0x47, 0x94, 0xff, 0xba, 0x58, 0x5d, 0x9c, 0x8c, 0xe7, 0x25, 0xd9, 0x74, 0xcd, 0x97, 0x41, + 0x47, 0x98, 0xef, 0x0d, 0x65, 0x72, 0xdf, 0x0f, 0x95, 0xf9, 0xfe, 0x4f, 0x29, 0x93, 0xfc, 0x42, + 0x54, 0x26, 0x83, 0xdc, 0x7c, 0x6e, 0x9b, 0xa4, 0xe9, 0x55, 0x34, 0xfa, 0xcd, 0xde, 0x85, 0x9a, + 0x6f, 0x8d, 0xe6, 0x7e, 0x60, 0xbf, 0xb6, 0xf4, 0xc0, 0x76, 0xcf, 0x48, 0xc7, 0x2b, 0x6a, 0xd5, + 0x18, 0x3a, 0xb0, 0xdd, 0x33, 0x14, 0x19, 0xd6, 0x45, 0x68, 0xf9, 0x2e, 0xbf, 0x40, 0xf0, 0xa1, + 0x2c, 0x32, 0xda, 0x84, 0xc0, 0x75, 0xae, 0x81, 0x15, 0xff, 0x5e, 0x98, 0xd9, 0x80, 0xcf, 0xec, + 0x93, 0x1f, 0x35, 0xb3, 0x03, 0x9a, 0xd9, 0x87, 0x50, 0xb4, 0xdd, 0xd0, 0xf2, 0x5f, 0x1b, 0x4e, + 0xfd, 0xe3, 0x25, 0x69, 0x1c, 0xe3, 0xd8, 0x03, 0x28, 0x04, 0x8e, 0x8d, 0xeb, 0xbd, 0xfe, 0xc9, + 0x12, 0x59, 0x84, 0x62, 0x8f, 0xa0, 0x14, 0xdf, 0x93, 0xab, 0x7f, 0xba, 0x44, 0x97, 0x20, 0xd9, + 0x1d, 0xc8, 0x9d, 0x23, 0x43, 0x3d, 0x5d, 0x3e, 0x5c, 0x40, 0x38, 0x6e, 0xdf, 0x63, 0xd4, 0xd9, + 0x69, 0xfb, 0x7e, 0xb6, 0xb4, 0x7d, 0xef, 0xd9, 0x8e, 0xc3, 0xb7, 0xef, 0xb1, 0xf8, 0x85, 0x9b, + 0x1f, 0xe5, 0xc0, 0x9e, 0x7c, 0xb6, 0xbc, 0xf9, 0x21, 0xee, 0x25, 0xdd, 0x28, 0x2c, 0x07, 0xe4, + 0x31, 0xe7, 0x8e, 0xff, 0xcf, 0xe5, 0xb1, 0x4a, 0xbb, 0xd2, 0x35, 0x08, 0xe2, 0x34, 0x1a, 0x20, + 0xe2, 0xbc, 0x00, 0x95, 0xa6, 0x2f, 0xf8, 0xf5, 0x13, 0x0e, 0xe9, 0x98, 0x17, 0xec, 0x13, 0xa8, + 0x46, 0x71, 0x4a, 0x58, 0x5d, 0x50, 0xff, 0x72, 0xa9, 0x05, 0x69, 0x02, 0xd6, 0x82, 0xca, 0x18, + 0x75, 0xf7, 0x29, 0x57, 0xe5, 0xeb, 0xcf, 0xa9, 0x21, 0x3b, 0xd1, 0xc6, 0xfa, 0x26, 0x55, 0x5f, + 0x4b, 0xe5, 0x62, 0x4f, 0x80, 0xd9, 0x63, 0x3e, 0x9f, 0x7b, 0xbe, 0x37, 0xe5, 0xea, 0x7a, 0xfd, + 0x2b, 0xe1, 0xdd, 0x5a, 0xc2, 0xd0, 0xf1, 0xa1, 0xe5, 0x9a, 0xfa, 0x34, 0x10, 0x6a, 0xc2, 0xcf, + 0xa8, 0x9d, 0x42, 0x78, 0xc5, 0xf7, 0x69, 0x23, 0xf7, 0x30, 0xd2, 0x1e, 0x06, 0x5c, 0x6b, 0xf8, + 0x0a, 0x90, 0x5d, 0x5f, 0x27, 0x59, 0xff, 0xe8, 0x07, 0xb3, 0x22, 0x6d, 0x94, 0xf5, 0x39, 0xd4, + 0xb8, 0x6b, 0x95, 0x34, 0x32, 0x64, 0xd1, 0x9f, 0xcb, 0x92, 0x4b, 0x76, 0x3a, 0x6b, 0x15, 0x53, + 0x76, 0x41, 0x7f, 0x09, 0x9b, 0x91, 0x77, 0x38, 0x14, 0x8e, 0xe4, 0x3f, 0x96, 0xab, 0x8d, 0xbd, + 0xaf, 0x5a, 0x75, 0x1e, 0xfd, 0xa4, 0x2a, 0x9f, 0x41, 0x95, 0x76, 0xd1, 0xf8, 0xc2, 0xd2, 0xdf, + 0x58, 0x79, 0x61, 0xa9, 0x82, 0x44, 0x51, 0x0a, 0x85, 0x7f, 0xb2, 0x4e, 0x47, 0xa1, 0x55, 0xff, + 0x05, 0x17, 0xfe, 0x31, 0xb0, 0x19, 0x5a, 0xec, 0x19, 0x80, 0x31, 0x9b, 0x39, 0x97, 0x9c, 0x35, + 0x7f, 0x49, 0xac, 0xb9, 0x2d, 0xb1, 0x66, 0x03, 0x91, 0xc4, 0x9b, 0x25, 0x23, 0xfa, 0xc9, 0x9e, + 0x42, 0x65, 0xe6, 0x05, 0xa1, 0x6e, 0x4e, 0x1d, 0xea, 0x7f, 0x43, 0x5e, 0xdb, 0x47, 0x5e, 0x10, + 0xb6, 0xa6, 0x0e, 0xf6, 0x02, 0x66, 0xf1, 0x6f, 0xd6, 0x85, 0x2b, 0x9e, 0xab, 0x9b, 0xf3, 0x99, + 0x63, 0x8f, 0x70, 0x04, 0x0c, 0x3a, 0xac, 0xaf, 0xef, 0x52, 0x8d, 0xb7, 0xa4, 0x1a, 0xfb, 0x6e, + 0x2b, 0x22, 0x12, 0x41, 0x73, 0x5b, 0xde, 0x22, 0x88, 0xec, 0x4c, 0x9a, 0x83, 0x38, 0xc8, 0xb4, + 0xc9, 0x55, 0x03, 0x82, 0x46, 0x51, 0xa6, 0xcf, 0x61, 0x33, 0xa1, 0xc2, 0x0e, 0x06, 0xf5, 0x96, + 0xcc, 0xc9, 0x52, 0xd4, 0x7a, 0x35, 0xca, 0x88, 0xb0, 0x80, 0xc6, 0xce, 0x73, 0x9c, 0xf9, 0x4c, + 0x88, 0xd2, 0x7a, 0x5b, 0x8c, 0x1d, 0x01, 0xb9, 0x94, 0x94, 0x4c, 0x71, 0x6b, 0x5a, 0xdf, 0x93, + 0x4d, 0x71, 0x6b, 0x8a, 0x6a, 0x86, 0x88, 0xa3, 0x7b, 0x6d, 0x5b, 0xe7, 0x41, 0x7d, 0x9f, 0x82, + 0x1f, 0x45, 0x8c, 0xf6, 0x4b, 0x04, 0xe1, 0xbe, 0x6f, 0xda, 0x3e, 0x9a, 0x00, 0x14, 0xce, 0x75, + 0xc0, 0x83, 0x7c, 0x39, 0x08, 0x29, 0x58, 0x13, 0xea, 0x24, 0xce, 0xc5, 0x5a, 0x4d, 0x9d, 0xda, + 0x75, 0x96, 0x96, 0xe4, 0x55, 0xa4, 0xe5, 0x87, 0x82, 0x47, 0xd2, 0xf9, 0xdd, 0x2f, 0xe1, 0xf6, + 0xea, 0x42, 0xa2, 0xfb, 0x9c, 0x5f, 0x93, 0xbe, 0x71, 0x63, 0x45, 0xee, 0x26, 0xbf, 0xe2, 0xf9, + 0x33, 0xa8, 0x4e, 0x0c, 0x1a, 0x09, 0x47, 0x9f, 0x7a, 0xa6, 0x55, 0x7f, 0x21, 0x5f, 0xb5, 0xa4, + 0x49, 0xdb, 0x37, 0x70, 0x50, 0x9c, 0x43, 0xcf, 0xb4, 0xb4, 0xf2, 0x24, 0x49, 0xb0, 0xe7, 0x50, + 0x4f, 0x98, 0x70, 0xee, 0x62, 0xbd, 0x68, 0xeb, 0xd9, 0xee, 0x28, 0xac, 0x77, 0x69, 0x4c, 0xaf, + 0xc5, 0xf8, 0x63, 0x44, 0xb7, 0x04, 0x96, 0x35, 0x41, 0x21, 0xe1, 0x20, 0x76, 0xb1, 0xc0, 0x36, + 0xad, 0xfa, 0xa1, 0x7c, 0x95, 0x8a, 0x8b, 0x4e, 0x24, 0xa1, 0xfd, 0x6a, 0x60, 0x9b, 0x96, 0x56, + 0x1b, 0xa7, 0xd2, 0xea, 0xbf, 0x9f, 0x87, 0x62, 0x64, 0xd5, 0xb1, 0x32, 0x14, 0x8e, 0x7b, 0x2f, + 0x7a, 0xfd, 0x57, 0x3d, 0x7e, 0x23, 0xb3, 0x31, 0x18, 0xb4, 0xb5, 0xa1, 0x62, 0xb2, 0x1a, 0x00, + 0xdd, 0x72, 0xd2, 0x07, 0xcd, 0x46, 0x8f, 0xdf, 0xd0, 0xa4, 0xbb, 0x55, 0x3c, 0xbd, 0xce, 0xb6, + 0xa0, 0xba, 0x77, 0xdc, 0xa3, 0x18, 0x4b, 0x0e, 0xca, 0x22, 0xa8, 0xfd, 0x0d, 0x3f, 0xce, 0xe5, + 0xa0, 0x1c, 0x82, 0x0e, 0x1b, 0xc3, 0xb6, 0xd6, 0x89, 0x40, 0x79, 0x76, 0x15, 0xb6, 0x62, 0xaa, + 0xa8, 0x04, 0xa5, 0x80, 0x0d, 0x39, 0xd2, 0xfa, 0x5f, 0xb7, 0x9b, 0x43, 0x05, 0xe8, 0x28, 0x78, + 0x7f, 0x5f, 0x29, 0xb3, 0x0a, 0x14, 0x5b, 0x9d, 0xc1, 0xb0, 0xd3, 0x6b, 0x0e, 0x95, 0x0a, 0xb6, + 0x6f, 0xaf, 0xd3, 0x1d, 0xb6, 0x35, 0xa5, 0xca, 0x8a, 0x90, 0xfb, 0xba, 0xdf, 0xe9, 0x29, 0x35, + 0xba, 0xdc, 0xd5, 0x38, 0x3c, 0xea, 0xb6, 0x95, 0x4d, 0x84, 0x0e, 0xfa, 0xda, 0x50, 0x51, 0x10, + 0xfa, 0xaa, 0xd3, 0x6b, 0xf5, 0x5f, 0x29, 0x5b, 0xac, 0x04, 0xf9, 0xe3, 0x1e, 0x56, 0xc3, 0x58, + 0x15, 0x4a, 0xf4, 0x53, 0x6f, 0x74, 0xbb, 0xca, 0x15, 0xe9, 0xfc, 0x78, 0x1b, 0x51, 0x74, 0x1a, + 0x3d, 0xc0, 0x36, 0x5c, 0xc5, 0xa6, 0xc7, 0x49, 0xa2, 0xbe, 0x86, 0xe5, 0x1c, 0x76, 0x7a, 0xc7, + 0x03, 0xe5, 0x3a, 0x12, 0xd3, 0x4f, 0xc2, 0xd4, 0xb1, 0x9c, 0x4e, 0x8f, 0x46, 0xee, 0x0e, 0xfe, + 0x6e, 0xb5, 0xbb, 0xed, 0x61, 0x5b, 0xb9, 0x8b, 0xbd, 0xea, 0xf6, 0x9b, 0x2f, 0xf4, 0xfe, 0x91, + 0x72, 0x0f, 0x87, 0xf0, 0x48, 0x6b, 0xeb, 0x82, 0xf0, 0x3e, 0x53, 0xa0, 0xb2, 0x77, 0xfc, 0xeb, + 0x5f, 0x7f, 0xab, 0x8b, 0x4e, 0xbd, 0x8b, 0x75, 0x26, 0x14, 0xfa, 0xf1, 0x0b, 0xe5, 0xe1, 0x02, + 0x68, 0xf0, 0x42, 0x79, 0x0f, 0x07, 0x25, 0x1a, 0x54, 0xe5, 0x11, 0x12, 0x68, 0xed, 0xe6, 0xb1, + 0x36, 0xe8, 0xbc, 0x6c, 0xeb, 0xcd, 0x61, 0x5b, 0x79, 0x9f, 0x46, 0xa1, 0xd3, 0x7b, 0xa1, 0x3c, + 0xc6, 0x66, 0xe2, 0x2f, 0x3e, 0xf6, 0x1f, 0x30, 0x06, 0xb5, 0x84, 0x96, 0x60, 0x1f, 0x22, 0xc9, + 0xae, 0xd6, 0x6f, 0xb4, 0x9a, 0x8d, 0xc1, 0x50, 0xf9, 0x08, 0xfb, 0x38, 0x38, 0xea, 0x76, 0x86, + 0xca, 0x13, 0xec, 0xc8, 0x7e, 0x63, 0x78, 0xd0, 0xd6, 0x94, 0x8f, 0xd9, 0x26, 0x94, 0x87, 0x9d, + 0xc3, 0xb6, 0x2e, 0xc6, 0xf4, 0x29, 0xd6, 0xb1, 0xd7, 0xe9, 0x76, 0x95, 0x67, 0x74, 0xfe, 0xd9, + 0xd0, 0x86, 0x1d, 0x9a, 0xc8, 0xcf, 0xb0, 0x80, 0xc6, 0xd1, 0x51, 0xf7, 0x5b, 0xe5, 0x73, 0xec, + 0xe0, 0xe1, 0x71, 0x77, 0xd8, 0xd1, 0x8f, 0x8f, 0x5a, 0x8d, 0x61, 0x5b, 0xf9, 0x82, 0x66, 0xb9, + 0x3f, 0x18, 0xb6, 0x0e, 0xbb, 0xca, 0x97, 0x54, 0x26, 0xb1, 0x54, 0xb3, 0xdb, 0xef, 0xb5, 0x95, + 0xe7, 0x6a, 0xae, 0xb8, 0xa1, 0x6c, 0xa8, 0xb9, 0xe2, 0x8e, 0xb2, 0xa3, 0xe6, 0x8a, 0xaa, 0xa2, + 0x3e, 0x2e, 0x0f, 0xfa, 0xc7, 0x5a, 0x93, 0xb7, 0x55, 0xfd, 0x5b, 0x50, 0x8c, 0x8c, 0x7a, 0xac, + 0xa5, 0xd3, 0xeb, 0xb5, 0x35, 0x65, 0x0d, 0x5b, 0xd2, 0x6d, 0xef, 0x0d, 0x95, 0x0c, 0x9d, 0x15, + 0x77, 0xf6, 0x0f, 0x86, 0xca, 0x3a, 0xfe, 0xec, 0x1f, 0xe3, 0xa0, 0x66, 0x69, 0x34, 0xda, 0x87, + 0x1d, 0x25, 0x87, 0xbf, 0x1a, 0xbd, 0x61, 0x47, 0xc9, 0x13, 0xcf, 0x74, 0x7a, 0xfb, 0xdd, 0xb6, + 0xb2, 0x81, 0xd0, 0xc3, 0x86, 0xf6, 0x42, 0x29, 0xf0, 0x42, 0x5b, 0xed, 0x6f, 0x94, 0x22, 0xdb, + 0x80, 0xf5, 0xee, 0x53, 0xa5, 0x84, 0xa0, 0x56, 0xbb, 0x75, 0x7c, 0xa4, 0x80, 0xfa, 0x08, 0x0a, + 0x8d, 0xc9, 0x84, 0x56, 0x30, 0x76, 0xfe, 0xb8, 0xdb, 0xe5, 0x4b, 0x66, 0xb7, 0x3f, 0x1c, 0xf6, + 0x0f, 0x95, 0x0c, 0x72, 0xed, 0xb0, 0x7f, 0xa4, 0xac, 0xab, 0x1d, 0x28, 0x46, 0xea, 0x8b, 0x74, + 0x59, 0xb1, 0x08, 0xb9, 0x23, 0xad, 0xfd, 0x92, 0x07, 0x38, 0xf4, 0xda, 0xdf, 0x60, 0x33, 0xf1, + 0x17, 0x16, 0x94, 0xc5, 0x8a, 0xf8, 0xad, 0x42, 0xba, 0xad, 0xd8, 0xed, 0xf4, 0xda, 0x0d, 0x4d, + 0xc9, 0xab, 0xcf, 0xa1, 0x2c, 0xc9, 0x11, 0x9c, 0xec, 0xfd, 0xc6, 0x11, 0x32, 0x4c, 0x57, 0x17, + 0xc5, 0x5e, 0x03, 0x16, 0x83, 0x92, 0x79, 0xc8, 0xa8, 0x9f, 0xc3, 0xd6, 0xd2, 0xb6, 0x41, 0x0d, + 0x6f, 0x74, 0x44, 0xc3, 0x3b, 0xfb, 0xbd, 0xbe, 0xd6, 0xe6, 0x17, 0x27, 0xc5, 0x0c, 0xad, 0xab, + 0x1f, 0x40, 0x29, 0xde, 0xdf, 0x90, 0x63, 0x9b, 0x5a, 0x7f, 0x30, 0xe0, 0x13, 0xba, 0x86, 0x69, + 0x1a, 0x55, 0x9e, 0xce, 0xa8, 0x36, 0xd4, 0xd2, 0xc2, 0x86, 0xed, 0xc0, 0x2d, 0xce, 0xd3, 0xbb, + 0xc7, 0x9d, 0x6e, 0x4b, 0x1f, 0x74, 0x5a, 0x6d, 0xfd, 0xb8, 0x37, 0x38, 0x6a, 0x37, 0x3b, 0x7b, + 0x9d, 0x76, 0x4b, 0x59, 0x63, 0x37, 0xe1, 0xda, 0x12, 0x05, 0xbf, 0xb5, 0x99, 0x61, 0x37, 0xe0, + 0xea, 0x12, 0x8e, 0x38, 0x79, 0xfd, 0xeb, 0x5c, 0xf1, 0xae, 0xb2, 0xf3, 0x75, 0xae, 0xf8, 0x40, + 0x79, 0x57, 0x1d, 0xc0, 0x56, 0xb4, 0xa3, 0xd3, 0xfd, 0x10, 0x32, 0x35, 0xb7, 0x21, 0xdf, 0xb5, + 0x5e, 0x5b, 0x4e, 0x74, 0xd1, 0x81, 0x12, 0x08, 0xed, 0x9f, 0x7c, 0xd7, 0x89, 0x2f, 0xf8, 0x53, + 0x02, 0x55, 0xf8, 0x9e, 0xf4, 0xc6, 0x00, 0x5d, 0x8b, 0xfd, 0x97, 0x32, 0x50, 0x8c, 0xf5, 0x84, + 0x07, 0xb0, 0x3e, 0x1c, 0x88, 0x43, 0xc1, 0xed, 0x27, 0xc9, 0x93, 0x2a, 0xc3, 0xe8, 0x97, 0xb6, + 0x3e, 0x1c, 0xb0, 0x0f, 0x61, 0x83, 0x5f, 0x73, 0x16, 0x0e, 0xc1, 0xed, 0xb4, 0xee, 0x31, 0x24, + 0x9c, 0x26, 0x68, 0xd8, 0xe7, 0x50, 0x8a, 0x5b, 0x2b, 0x3c, 0x64, 0xd7, 0xd3, 0x19, 0x62, 0xb4, + 0x96, 0x50, 0xaa, 0x5d, 0xa8, 0xa5, 0x0b, 0x64, 0x77, 0x00, 0x78, 0x91, 0x92, 0x1b, 0x58, 0x82, + 0xb0, 0x9b, 0x10, 0xdd, 0xbe, 0x6e, 0x51, 0xc3, 0xaa, 0xf1, 0x6d, 0xec, 0x96, 0xfa, 0xa7, 0x39, + 0x80, 0xc4, 0xd2, 0xc0, 0x81, 0x88, 0xfd, 0x7e, 0x79, 0x11, 0x27, 0xf1, 0x0e, 0x94, 0x1c, 0xcf, + 0x30, 0xe5, 0x17, 0x55, 0x8a, 0x08, 0x20, 0x8e, 0x90, 0xef, 0x09, 0x96, 0x78, 0x90, 0x12, 0xbb, + 0x06, 0x1b, 0x63, 0xcf, 0x9f, 0x1a, 0xa1, 0xb8, 0xd5, 0x22, 0x52, 0xa8, 0x30, 0xf0, 0xe3, 0x57, + 0xb4, 0xb7, 0x5c, 0xba, 0xd8, 0x82, 0x73, 0x50, 0x11, 0xc0, 0x2e, 0xc2, 0x70, 0xc3, 0xb7, 0xdc, + 0x91, 0xe3, 0x05, 0x96, 0x89, 0x5b, 0xf8, 0x06, 0x19, 0x55, 0x10, 0x81, 0x76, 0x2f, 0x79, 0x6f, + 0xfd, 0xa9, 0xed, 0x1a, 0xa1, 0x38, 0x08, 0xa4, 0xde, 0x46, 0x10, 0x6c, 0xee, 0x77, 0x81, 0x27, + 0xdc, 0x80, 0xfc, 0x52, 0x5c, 0x11, 0x01, 0xd4, 0xdc, 0xdb, 0x00, 0x56, 0x30, 0x32, 0x66, 0xbc, + 0xf0, 0x12, 0xbf, 0x99, 0x2c, 0x20, 0xbb, 0x97, 0xac, 0x0b, 0xb5, 0xe1, 0x09, 0x2a, 0x38, 0x5e, + 0xcb, 0x08, 0x8d, 0xa6, 0xe7, 0x08, 0x07, 0xdd, 0x83, 0x45, 0x93, 0xec, 0x49, 0x9a, 0x8c, 0x47, + 0xeb, 0x2e, 0xe4, 0x65, 0x9f, 0x41, 0xc5, 0x1e, 0x59, 0x27, 0x96, 0x3f, 0xe1, 0xe6, 0x5d, 0x39, + 0x75, 0x1d, 0x85, 0x63, 0xc8, 0xbe, 0x2b, 0xdb, 0x49, 0x02, 0x15, 0xc7, 0xa9, 0xe7, 0x4e, 0x3c, + 0xf3, 0x84, 0xe7, 0xaa, 0xc8, 0xce, 0x86, 0x43, 0xc4, 0xf0, 0x3c, 0x82, 0x08, 0x13, 0x37, 0x1b, + 0x70, 0x65, 0x45, 0x83, 0x7e, 0x52, 0x88, 0xe8, 0x7f, 0xbe, 0x0e, 0x65, 0xa9, 0x4d, 0x74, 0x7a, + 0x63, 0xcc, 0xc8, 0xfb, 0x18, 0xc7, 0xc8, 0x97, 0x04, 0x84, 0x5f, 0x18, 0x1a, 0x19, 0xa1, 0xe1, + 0x78, 0x13, 0xe9, 0x2a, 0x94, 0x80, 0x74, 0x4c, 0x3a, 0x50, 0x35, 0xa6, 0x56, 0x30, 0x33, 0x46, + 0xd1, 0xaa, 0x4a, 0x00, 0xc9, 0xf3, 0x3f, 0x39, 0xf9, 0xf9, 0x1f, 0x85, 0x9f, 0xbc, 0xf3, 0x60, + 0x27, 0x3a, 0x68, 0xbf, 0x0b, 0xe5, 0x48, 0x9b, 0xc7, 0x5a, 0xc4, 0xe1, 0x70, 0x04, 0xea, 0x98, + 0xec, 0x21, 0x24, 0xcf, 0x1b, 0xe9, 0x46, 0xa0, 0x7b, 0xe3, 0x28, 0xd2, 0x32, 0x06, 0x37, 0x82, + 0xfe, 0x38, 0x3e, 0xb1, 0x21, 0xcd, 0x4c, 0xf0, 0x04, 0x02, 0x48, 0x86, 0x3e, 0x81, 0x2b, 0xc2, + 0x8d, 0x6c, 0x99, 0xfa, 0xd8, 0xb6, 0x1c, 0x53, 0xb7, 0x4d, 0x1e, 0x09, 0x91, 0xd7, 0xb6, 0x62, + 0xd4, 0x1e, 0x62, 0x3a, 0x26, 0xe9, 0xbd, 0xc2, 0x77, 0x60, 0xda, 0x13, 0x2b, 0x08, 0x45, 0x5c, + 0x60, 0x85, 0x03, 0x5b, 0x04, 0x53, 0xff, 0x71, 0x0e, 0x4a, 0xf1, 0x64, 0xbd, 0x6d, 0x30, 0xef, + 0x43, 0x75, 0xe4, 0xb9, 0xae, 0x45, 0x32, 0x39, 0x19, 0xcf, 0x4a, 0x02, 0xa4, 0x58, 0x68, 0x26, + 0x11, 0x45, 0x91, 0xfe, 0xfc, 0x3e, 0xcf, 0x56, 0x82, 0x79, 0x29, 0x62, 0xfe, 0x6f, 0x42, 0x11, + 0x17, 0xe3, 0x89, 0x11, 0x44, 0xc3, 0x1c, 0xa7, 0x71, 0x09, 0x8d, 0x3c, 0xc7, 0xe1, 0x19, 0xa2, + 0x67, 0x2c, 0x12, 0x08, 0x7b, 0x4a, 0x0f, 0x99, 0xd0, 0x7d, 0xa4, 0x0d, 0xe2, 0xff, 0xba, 0xc4, + 0x7d, 0xfc, 0x4a, 0xd2, 0x21, 0x6f, 0xbc, 0x16, 0x11, 0xb2, 0x5f, 0x80, 0x32, 0x9b, 0x07, 0xa7, + 0x96, 0xa9, 0xcf, 0x7c, 0xcb, 0xa4, 0x3d, 0x46, 0xdc, 0x5a, 0xd8, 0x96, 0x32, 0x1f, 0x45, 0x38, + 0x6d, 0x93, 0x53, 0xc7, 0x00, 0xf6, 0x1e, 0x6c, 0x26, 0xd3, 0x30, 0x33, 0xc2, 0x53, 0x1e, 0xc4, + 0x52, 0xd2, 0x6a, 0x31, 0xf8, 0x08, 0xa1, 0xec, 0x33, 0xb8, 0xe6, 0x5b, 0x81, 0x6d, 0xce, 0x0d, + 0x47, 0x4f, 0x4f, 0x04, 0x7f, 0x14, 0x63, 0x3b, 0xc2, 0xee, 0x49, 0x13, 0x82, 0xc5, 0x4f, 0x8d, + 0x0b, 0x72, 0xc4, 0x39, 0x8e, 0xe5, 0xd8, 0xc1, 0x94, 0xe6, 0x2d, 0xaf, 0xd5, 0xa6, 0xc6, 0xc5, + 0x51, 0x02, 0xa5, 0x18, 0xb6, 0x99, 0x63, 0x2f, 0xdc, 0x1e, 0xe7, 0x73, 0x89, 0x70, 0x8d, 0xa3, + 0x99, 0x0a, 0x55, 0x2c, 0x90, 0x6c, 0xce, 0x38, 0x2c, 0x25, 0xab, 0x95, 0xa7, 0x06, 0x39, 0x67, + 0xe9, 0x94, 0xf2, 0x01, 0xd4, 0x62, 0x1a, 0x1e, 0x7a, 0x20, 0x4e, 0xff, 0x05, 0x11, 0x8f, 0x3e, + 0xa0, 0xa6, 0x71, 0xee, 0x88, 0xa6, 0xb5, 0xc6, 0x63, 0xeb, 0x05, 0x38, 0x9a, 0xd3, 0x1b, 0xc0, + 0xdd, 0xd9, 0xc8, 0x22, 0x9b, 0x44, 0x51, 0xa0, 0x74, 0xc7, 0x54, 0xff, 0x85, 0x0c, 0xb0, 0xe5, + 0xe9, 0x79, 0xd3, 0x2d, 0x31, 0x1c, 0xde, 0xe8, 0x8a, 0x0b, 0xfe, 0x66, 0xef, 0x43, 0x61, 0xea, + 0x71, 0x91, 0x99, 0x7d, 0xc3, 0x9d, 0xe5, 0x8d, 0xa9, 0x47, 0x22, 0xf4, 0x3d, 0xd8, 0x1c, 0x79, + 0xae, 0x68, 0x28, 0x5f, 0x51, 0x9c, 0xbf, 0x6a, 0x09, 0x18, 0xd7, 0x95, 0xfa, 0x1f, 0x65, 0xa0, + 0x96, 0x9e, 0x74, 0xf6, 0x90, 0xde, 0x90, 0x49, 0xbd, 0x42, 0x93, 0xa6, 0xe8, 0xcf, 0xe8, 0x6d, + 0x99, 0x55, 0x4d, 0xbc, 0x0d, 0x40, 0xd2, 0x4a, 0x3f, 0x09, 0x04, 0xdf, 0x57, 0xb4, 0x12, 0x41, + 0x76, 0x03, 0x8f, 0x4e, 0x6d, 0xf9, 0x33, 0x61, 0x1c, 0x9f, 0xdb, 0xc9, 0xe2, 0xbe, 0xc1, 0x41, + 0x44, 0xf0, 0x89, 0x74, 0xd2, 0xc4, 0x4f, 0x92, 0x56, 0x33, 0x66, 0x4c, 0xa5, 0xfe, 0x45, 0x06, + 0x20, 0x99, 0x77, 0x1c, 0xfd, 0x33, 0xeb, 0x92, 0x58, 0x53, 0x8c, 0x67, 0xe1, 0xcc, 0xba, 0x3c, + 0x12, 0x6d, 0x13, 0xa7, 0x94, 0x81, 0x88, 0x8c, 0xad, 0x68, 0x25, 0x7e, 0x30, 0x19, 0xf0, 0x6b, + 0x86, 0xe2, 0x5c, 0x52, 0x6a, 0x3a, 0x3f, 0x8a, 0x0c, 0xe8, 0x7a, 0xce, 0x26, 0xcf, 0x4d, 0xb7, + 0xfe, 0xd0, 0xca, 0x13, 0x17, 0x2a, 0xf9, 0x39, 0x6a, 0x27, 0x82, 0x22, 0x21, 0x2f, 0x27, 0x21, + 0xe4, 0xa1, 0x6a, 0xfc, 0xd4, 0x34, 0x26, 0x54, 0x9d, 0x68, 0x53, 0x6f, 0x84, 0x21, 0x5d, 0x95, + 0x8e, 0x5d, 0x00, 0x99, 0xe8, 0x16, 0x25, 0xb7, 0xfe, 0xdf, 0xa1, 0x88, 0x5e, 0x71, 0x2d, 0x45, + 0xec, 0xed, 0xf1, 0x75, 0x93, 0x87, 0x38, 0xd3, 0x4e, 0x24, 0x12, 0x89, 0x84, 0x5f, 0x9f, 0xad, + 0x8e, 0x3c, 0x87, 0x8b, 0x43, 0x04, 0xaa, 0xff, 0x4a, 0x1e, 0x20, 0x71, 0xfe, 0xa6, 0xb8, 0x34, + 0x93, 0xe2, 0x52, 0xf6, 0x14, 0xae, 0x89, 0x7b, 0xe0, 0x71, 0xa8, 0xa0, 0xed, 0xea, 0x27, 0x46, + 0x14, 0x9a, 0xcc, 0x04, 0x96, 0x07, 0x81, 0x75, 0xdc, 0x5d, 0x23, 0x64, 0xcf, 0x51, 0x2e, 0x24, + 0x79, 0xc2, 0xcb, 0xd9, 0x1b, 0x59, 0xb4, 0x9a, 0x64, 0x1f, 0x5e, 0xce, 0xd8, 0x27, 0x70, 0xd5, + 0xb7, 0xc6, 0xbe, 0x15, 0x9c, 0xea, 0x61, 0x20, 0x57, 0xc6, 0xef, 0x0e, 0x6c, 0x09, 0xe4, 0x30, + 0x88, 0xeb, 0xfa, 0x04, 0xae, 0x0a, 0x89, 0xb2, 0xd0, 0x3c, 0x7e, 0xba, 0xba, 0xc5, 0x91, 0x72, + 0xeb, 0x68, 0xe6, 0xc9, 0x23, 0x1e, 0x3d, 0x67, 0x57, 0xc4, 0x99, 0xc7, 0xc1, 0x10, 0x0f, 0xb7, + 0x90, 0x5b, 0x9b, 0x44, 0x53, 0x51, 0xe3, 0x09, 0xa6, 0x42, 0x0e, 0x57, 0x08, 0x09, 0xa0, 0xda, + 0xd3, 0xda, 0x13, 0x7a, 0xae, 0x8f, 0x1e, 0xdd, 0xf1, 0x4c, 0x4b, 0x23, 0x1c, 0xfb, 0x08, 0x77, + 0xa5, 0xa4, 0xdb, 0xd1, 0x8b, 0x53, 0x3c, 0x5a, 0x4e, 0x49, 0x3a, 0xaa, 0xf1, 0xb7, 0xa7, 0x3e, + 0x00, 0x26, 0xb5, 0x3c, 0xa2, 0xae, 0x10, 0xf5, 0x66, 0xdc, 0x6c, 0x41, 0xfc, 0x1e, 0x50, 0x13, + 0x93, 0xc0, 0xb8, 0x05, 0x1f, 0x30, 0x22, 0x45, 0x30, 0xdd, 0xd5, 0xa4, 0x77, 0xba, 0x11, 0xea, + 0xe1, 0xa9, 0xa5, 0x5b, 0xae, 0x49, 0xf2, 0xa9, 0xa8, 0x6d, 0xc5, 0x1d, 0x6d, 0x84, 0xc3, 0x53, + 0xab, 0xed, 0x9a, 0xf2, 0x29, 0xdb, 0xe6, 0x0f, 0x9f, 0xb2, 0x7d, 0x01, 0xf5, 0xb4, 0x9f, 0x45, + 0x1a, 0x6e, 0xfe, 0xf8, 0xc5, 0xb6, 0x1c, 0x71, 0x18, 0x8f, 0xf8, 0x63, 0xd8, 0x3a, 0x35, 0x82, + 0xb4, 0x8f, 0x86, 0x0e, 0xff, 0x8a, 0xda, 0xe6, 0xa9, 0x11, 0xc8, 0x8e, 0x19, 0xf5, 0xef, 0x66, + 0xa0, 0x96, 0x76, 0x87, 0xf3, 0x1b, 0xc5, 0x7c, 0x6f, 0xcb, 0xd0, 0x0e, 0x1f, 0xef, 0x60, 0xef, + 0x40, 0x89, 0x87, 0x25, 0xce, 0xa7, 0x6e, 0xb4, 0x16, 0x66, 0x67, 0x5c, 0x9e, 0xa2, 0x80, 0x9c, + 0x9d, 0xbd, 0x45, 0x40, 0xce, 0xf8, 0x75, 0xaa, 0xf7, 0xa1, 0x30, 0x3f, 0x4b, 0x9e, 0xb5, 0x59, + 0x49, 0x3a, 0x27, 0x52, 0xf5, 0xbf, 0x58, 0x87, 0x8a, 0x7c, 0x8a, 0xf3, 0x63, 0xa2, 0x0f, 0x7f, + 0x52, 0x28, 0xe9, 0x0e, 0xdd, 0x78, 0xd0, 0xe9, 0xbe, 0x12, 0x8e, 0x13, 0x0f, 0x3d, 0x84, 0x53, + 0x23, 0x68, 0xcc, 0x43, 0xdc, 0x2b, 0x48, 0x91, 0xf3, 0x9c, 0xe8, 0x4e, 0x17, 0x5f, 0x19, 0x28, + 0x13, 0xc4, 0x75, 0xae, 0x4f, 0xc4, 0x95, 0x51, 0xba, 0x6e, 0x4e, 0x97, 0x03, 0xf2, 0x4b, 0xfc, + 0x52, 0x89, 0x6e, 0x9b, 0xd3, 0x65, 0x88, 0xa7, 0xb0, 0x99, 0x5c, 0xd0, 0xe3, 0x59, 0x36, 0x96, + 0xb2, 0x54, 0xe3, 0xdb, 0x79, 0xe2, 0x29, 0x9c, 0xaa, 0x1d, 0xe8, 0x9e, 0x63, 0x46, 0x17, 0x85, + 0x0b, 0xd1, 0x19, 0x7b, 0xdf, 0x31, 0xc5, 0x1b, 0x07, 0x9c, 0xc6, 0xb5, 0xce, 0x23, 0x9a, 0xf8, + 0x1c, 0xbe, 0x67, 0x9d, 0x8b, 0x0b, 0xc3, 0x7f, 0x3f, 0x0b, 0x5b, 0x4b, 0x07, 0x37, 0xa8, 0x58, + 0x26, 0xcf, 0x44, 0xe2, 0x4f, 0x76, 0x0f, 0x2a, 0x53, 0x23, 0x1c, 0x9d, 0xa2, 0xae, 0x32, 0xb6, + 0x2f, 0xa2, 0xb7, 0x2e, 0x09, 0x76, 0x44, 0x20, 0xdc, 0x4f, 0xb8, 0xac, 0xe5, 0x47, 0xdb, 0x5c, + 0xf0, 0x71, 0x31, 0xde, 0xa5, 0x33, 0xed, 0xe8, 0xb2, 0x44, 0xee, 0x0d, 0x97, 0x25, 0x6e, 0x42, + 0xc9, 0xf5, 0x28, 0x30, 0x76, 0x76, 0x26, 0xc4, 0x74, 0xc1, 0xf5, 0xc2, 0xbe, 0x7b, 0x74, 0xc6, + 0x9e, 0xc2, 0xd5, 0x79, 0x40, 0xb1, 0x64, 0x27, 0x96, 0x1f, 0x9c, 0xda, 0xb1, 0x0b, 0x95, 0x0b, + 0x90, 0x2b, 0xf3, 0xc0, 0x3a, 0x8c, 0x71, 0xc2, 0x93, 0xda, 0x80, 0x0a, 0xcd, 0x81, 0x3b, 0xf2, + 0xe8, 0x50, 0xa6, 0x40, 0xc2, 0xe3, 0xce, 0x8a, 0xd3, 0xaa, 0x17, 0xd6, 0x65, 0x5b, 0x50, 0x69, + 0xe5, 0xb3, 0x24, 0xc1, 0xde, 0xa7, 0x6b, 0x68, 0x27, 0x56, 0x62, 0x1b, 0xa5, 0x98, 0x53, 0x2b, + 0x11, 0x96, 0x98, 0xf8, 0x05, 0xdc, 0xe0, 0x77, 0x84, 0xa7, 0x33, 0xcf, 0xb5, 0xdc, 0x50, 0x4f, + 0x32, 0x06, 0xe9, 0xf8, 0x06, 0x89, 0xad, 0xaf, 0xd1, 0x9d, 0x61, 0x91, 0xe3, 0x28, 0x2a, 0x2b, + 0xc0, 0x7a, 0xb9, 0x83, 0x92, 0x06, 0x0c, 0x96, 0x4f, 0x89, 0x08, 0x8b, 0x3f, 0xd5, 0x5b, 0xb0, + 0xd1, 0x89, 0x8f, 0xd5, 0xe2, 0x18, 0xf4, 0xac, 0x78, 0x06, 0xcf, 0x83, 0x12, 0xf7, 0xb7, 0x1e, + 0x1a, 0x33, 0xf6, 0x18, 0xb2, 0x53, 0x63, 0x26, 0xc2, 0x74, 0xea, 0x71, 0x2c, 0x13, 0xc7, 0x3e, + 0x39, 0x34, 0x66, 0xdc, 0x2a, 0x43, 0xa2, 0x9b, 0x5f, 0x40, 0x31, 0x02, 0xfc, 0x24, 0xab, 0xe8, + 0xbf, 0x5b, 0x87, 0x52, 0x4b, 0x3e, 0x16, 0x47, 0x4d, 0x2e, 0xf4, 0xe7, 0x2e, 0xe9, 0xb7, 0xe2, + 0xc1, 0xaf, 0x91, 0xe1, 0x0e, 0x05, 0x28, 0x5a, 0xc0, 0xeb, 0x3f, 0xb0, 0x80, 0x6f, 0x01, 0xf8, + 0x74, 0xaa, 0x44, 0x07, 0x4b, 0xd9, 0xf8, 0x4e, 0x4e, 0xc7, 0xec, 0x98, 0x17, 0xab, 0x83, 0x8b, + 0x73, 0x3f, 0x3e, 0xb8, 0x38, 0xbf, 0x32, 0xb8, 0xf8, 0x61, 0xb2, 0x89, 0xe2, 0xb4, 0x62, 0xc5, + 0x25, 0xbe, 0x95, 0xcf, 0xe2, 0x6b, 0xc0, 0x58, 0xfb, 0xcf, 0xa0, 0x16, 0xf5, 0x4e, 0x94, 0x07, + 0xa9, 0x9b, 0xc7, 0x02, 0xc7, 0xcf, 0xd1, 0xab, 0xa1, 0x9c, 0x4c, 0x0b, 0xa6, 0xf2, 0x5b, 0x02, + 0x98, 0xff, 0xd5, 0x0c, 0x30, 0x71, 0x0a, 0xb2, 0x37, 0x77, 0x9c, 0xa1, 0x75, 0x41, 0xf2, 0xef, + 0x31, 0x6c, 0x89, 0x63, 0x7e, 0xe9, 0xed, 0x08, 0x11, 0xd8, 0xc6, 0x11, 0x49, 0x60, 0xdb, 0xaa, + 0x67, 0x26, 0xd6, 0x57, 0x3e, 0x33, 0xb1, 0xfa, 0xf9, 0x8a, 0xbb, 0x50, 0x96, 0x1f, 0x69, 0xe0, + 0x4a, 0x2c, 0x18, 0xf1, 0xfb, 0x0c, 0xea, 0xff, 0xb0, 0x0e, 0x90, 0x9c, 0xd4, 0xfc, 0xa1, 0x23, + 0xc3, 0x57, 0x4c, 0x49, 0x76, 0xd5, 0x94, 0x3c, 0x02, 0x45, 0xa6, 0x93, 0x5e, 0x0b, 0xa9, 0x25, + 0x84, 0x91, 0x32, 0x67, 0x07, 0xf2, 0x33, 0x0d, 0x74, 0x55, 0x53, 0x04, 0xd3, 0x72, 0x24, 0x3f, + 0x36, 0x16, 0x62, 0xa6, 0x68, 0x07, 0x7c, 0xe7, 0x61, 0x5f, 0xc1, 0x8d, 0x38, 0xa7, 0x7e, 0x6e, + 0x87, 0xa7, 0xde, 0x3c, 0x14, 0x22, 0x29, 0x10, 0xb2, 0xf8, 0x5a, 0x54, 0xd2, 0x2b, 0x8e, 0xe6, + 0xa2, 0x26, 0x60, 0x9f, 0x43, 0x69, 0x3c, 0x77, 0x1c, 0x3d, 0xb4, 0x2e, 0x42, 0x21, 0x52, 0xea, + 0xa9, 0x43, 0x2e, 0x69, 0x7a, 0xb5, 0xe2, 0x58, 0x24, 0xd4, 0xbf, 0x9f, 0x83, 0xfc, 0xaf, 0xe6, + 0x96, 0x7f, 0xc9, 0xbe, 0x80, 0x52, 0x10, 0x4e, 0x43, 0x39, 0xde, 0x4c, 0x1c, 0x5e, 0x10, 0x9e, + 0xc2, 0xc5, 0xac, 0xa9, 0xe5, 0x86, 0xfc, 0xf4, 0x17, 0x69, 0x49, 0x42, 0x6d, 0x43, 0x3e, 0x08, + 0xad, 0x59, 0x20, 0xee, 0x99, 0xf0, 0x04, 0xdb, 0x81, 0xbc, 0xeb, 0x99, 0x56, 0x90, 0xbe, 0x4d, + 0xd2, 0x43, 0xbd, 0x8a, 0x23, 0x98, 0x0a, 0x1b, 0xf1, 0x8c, 0x2f, 0xc5, 0x7c, 0x71, 0x0c, 0xdd, + 0x51, 0xb5, 0x0c, 0x94, 0x99, 0xd1, 0xeb, 0x2b, 0x71, 0x1a, 0x15, 0x08, 0xf2, 0x7e, 0x19, 0x93, + 0xe8, 0xd5, 0x26, 0x91, 0x64, 0x3b, 0x50, 0xc6, 0x9f, 0xaf, 0x7c, 0x3b, 0xb4, 0x06, 0xcf, 0xa2, + 0x3d, 0x4c, 0x02, 0xa1, 0xe1, 0x6d, 0x5a, 0xa1, 0x35, 0x0a, 0x07, 0xdf, 0x3b, 0x91, 0x79, 0x2b, + 0x41, 0xd8, 0xcf, 0x80, 0x9d, 0x18, 0xa3, 0xb3, 0x89, 0x4f, 0x71, 0x92, 0xdf, 0xcf, 0x2d, 0xdf, + 0x8e, 0xc5, 0x6d, 0x59, 0x1a, 0x14, 0x6d, 0x2b, 0x21, 0xfb, 0x15, 0xa7, 0x62, 0xd7, 0x60, 0x63, + 0x6a, 0x5c, 0xb4, 0xbc, 0x99, 0x08, 0x60, 0x17, 0x29, 0xf6, 0x0c, 0xae, 0xa1, 0x0a, 0x10, 0xbd, + 0xf1, 0x81, 0x3c, 0x24, 0xce, 0x15, 0xf9, 0x83, 0x8f, 0x57, 0x4e, 0x8d, 0x20, 0xb9, 0xb7, 0x2f, + 0xfc, 0xc2, 0xbb, 0xb0, 0x1d, 0xb9, 0x77, 0x4c, 0x6b, 0x66, 0xb9, 0xa6, 0xe5, 0x8e, 0xec, 0xf8, + 0x55, 0x80, 0x25, 0xe6, 0xbf, 0x22, 0x88, 0x5b, 0x12, 0xad, 0xfa, 0x27, 0x50, 0x4d, 0xcd, 0xdd, + 0xd2, 0xd9, 0xd2, 0xa0, 0xdd, 0x6d, 0x37, 0x87, 0xdc, 0xdf, 0x2c, 0x0e, 0x41, 0xd6, 0xa5, 0xd3, + 0x92, 0x9c, 0xe4, 0x87, 0xce, 0xd3, 0x59, 0x4b, 0x5b, 0xdb, 0x6f, 0xd3, 0x81, 0x40, 0x56, 0xc9, + 0xaa, 0xff, 0xda, 0x3a, 0x6c, 0x0d, 0x7d, 0xc3, 0x0d, 0x0c, 0xae, 0xed, 0xb9, 0xa1, 0xef, 0x39, + 0xec, 0x67, 0x50, 0x0c, 0x47, 0x8e, 0xcc, 0x4c, 0x77, 0x23, 0xd1, 0xb5, 0x40, 0xfa, 0x64, 0x38, + 0xe2, 0x01, 0x05, 0x85, 0x90, 0xff, 0x60, 0x1f, 0x41, 0xfe, 0xc4, 0x9a, 0xd8, 0xae, 0x90, 0xde, + 0x57, 0x17, 0x33, 0xee, 0x22, 0xf2, 0x60, 0x4d, 0xe3, 0x54, 0xec, 0x13, 0xd8, 0x18, 0x79, 0xd3, + 0x48, 0x39, 0x48, 0x5e, 0x01, 0x90, 0x2a, 0x42, 0xec, 0xc1, 0x9a, 0x26, 0xe8, 0xd8, 0x17, 0x50, + 0xf4, 0x3d, 0xc7, 0xc1, 0xb9, 0x13, 0x6a, 0x43, 0x7d, 0x31, 0x8f, 0x26, 0xf0, 0x07, 0x6b, 0x5a, + 0x4c, 0xab, 0x3e, 0x81, 0x82, 0x68, 0x2c, 0x0e, 0xc3, 0x6e, 0x7b, 0xbf, 0x23, 0x46, 0xb0, 0xd9, + 0x3f, 0x3c, 0xec, 0x0c, 0xf9, 0x0b, 0x28, 0x5a, 0xbf, 0xdb, 0xdd, 0x6d, 0x34, 0x5f, 0x28, 0xeb, + 0xbb, 0x45, 0xd8, 0xe0, 0x53, 0xac, 0xfe, 0x69, 0x06, 0x36, 0x17, 0x3a, 0xc0, 0x9e, 0x43, 0x8e, + 0xac, 0x76, 0x3e, 0x3c, 0x0f, 0x56, 0xf6, 0x52, 0x4a, 0x73, 0x9b, 0x04, 0x73, 0xa8, 0x5f, 0x41, + 0x2d, 0x0d, 0x97, 0x4e, 0x33, 0xaa, 0x50, 0xd2, 0xda, 0x8d, 0x96, 0xde, 0xef, 0x75, 0xbf, 0xe5, + 0xc7, 0x83, 0x94, 0x7c, 0xa5, 0x75, 0xe8, 0x18, 0xe1, 0x6f, 0x82, 0xb2, 0x38, 0x30, 0x6c, 0x1f, + 0xed, 0xcb, 0xe9, 0xcc, 0xb1, 0x48, 0x8d, 0x97, 0xa6, 0xec, 0xce, 0x8a, 0x91, 0x14, 0x64, 0x3c, + 0x48, 0x78, 0x94, 0x4a, 0xab, 0x7f, 0x02, 0x6c, 0x79, 0x04, 0xff, 0x70, 0xc5, 0xff, 0xdf, 0x19, + 0xc8, 0x1d, 0x39, 0x86, 0xcb, 0xee, 0x43, 0x9e, 0xde, 0x23, 0x14, 0x7b, 0x80, 0xbc, 0x22, 0x91, + 0x2d, 0x08, 0xc7, 0x3e, 0x80, 0x6c, 0x38, 0x8a, 0x5e, 0x56, 0xb9, 0xfe, 0x06, 0xe6, 0x3b, 0x58, + 0xd3, 0x90, 0x8a, 0x3d, 0x82, 0xac, 0x69, 0x46, 0xb7, 0x0c, 0x85, 0x3f, 0xa2, 0x65, 0x84, 0x46, + 0xcb, 0x1a, 0xdb, 0xae, 0x2d, 0xde, 0x4f, 0x44, 0x12, 0xf6, 0x2e, 0x64, 0xcd, 0x91, 0x93, 0xbe, + 0x32, 0xca, 0x9d, 0xbd, 0x71, 0x81, 0xe6, 0xc8, 0x41, 0x2d, 0x39, 0xf4, 0x2f, 0x75, 0x7f, 0xee, + 0xd2, 0x6d, 0x93, 0x40, 0x58, 0xae, 0x65, 0xd4, 0x84, 0xe6, 0x74, 0x65, 0x25, 0x10, 0x4f, 0x34, + 0xcc, 0x7c, 0x6b, 0x66, 0xf8, 0xb1, 0xcd, 0x6a, 0x07, 0x47, 0x1c, 0xb0, 0xbb, 0x01, 0xf4, 0xe8, + 0xbc, 0xfa, 0x21, 0x3d, 0x96, 0x87, 0xc6, 0x8f, 0x1a, 0xfd, 0x5a, 0xf1, 0x3e, 0xb1, 0xc0, 0xa8, + 0xff, 0x28, 0x0b, 0x65, 0xa9, 0x3d, 0xec, 0x33, 0x28, 0x9a, 0xe9, 0x85, 0x78, 0x63, 0xa9, 0xd1, + 0x4f, 0x5a, 0xd1, 0x12, 0x34, 0x05, 0x7b, 0x53, 0xb4, 0x4a, 0xa8, 0xbf, 0x36, 0x7c, 0x9b, 0x3f, + 0xc2, 0xba, 0x2e, 0x87, 0x8d, 0x0c, 0xac, 0xf0, 0x65, 0x84, 0x39, 0x58, 0xd3, 0x2a, 0x81, 0x94, + 0x26, 0x0b, 0x4d, 0x74, 0x29, 0x9b, 0x7a, 0xf8, 0x96, 0x03, 0x0f, 0xd6, 0xb4, 0x08, 0x8f, 0xa4, + 0xd6, 0x85, 0x35, 0x9a, 0x87, 0x91, 0x85, 0x56, 0x8d, 0x3a, 0x44, 0x40, 0x7a, 0x7d, 0x9b, 0xff, + 0x64, 0x4f, 0x51, 0x62, 0x1b, 0x8e, 0xe3, 0x91, 0xc2, 0x97, 0x97, 0x5d, 0x82, 0xad, 0x18, 0xce, + 0x5f, 0xfb, 0x8e, 0x52, 0xec, 0x21, 0xe4, 0xbd, 0xf0, 0xd4, 0x8a, 0xec, 0x9e, 0xe8, 0xd9, 0x3d, + 0x04, 0xb5, 0x9a, 0x5d, 0xe4, 0x14, 0x42, 0xab, 0x7f, 0x96, 0x81, 0x82, 0x18, 0x01, 0xb6, 0x05, + 0xd5, 0x41, 0x7b, 0xa8, 0xbf, 0x6c, 0x68, 0x9d, 0xc6, 0x6e, 0xb7, 0x2d, 0x6e, 0xba, 0xee, 0x6b, + 0x8d, 0x9e, 0x10, 0x90, 0x5a, 0xfb, 0x65, 0xff, 0x45, 0x9b, 0x1f, 0x11, 0xb6, 0xda, 0xbd, 0x6f, + 0x95, 0x2c, 0x3f, 0x22, 0x6f, 0x1f, 0x35, 0x34, 0x94, 0x95, 0x65, 0x28, 0xb4, 0xbf, 0x69, 0x37, + 0x8f, 0x49, 0x58, 0xd6, 0x00, 0x5a, 0xed, 0x46, 0xb7, 0xdb, 0x6f, 0xa2, 0xf0, 0xdc, 0x60, 0x0c, + 0x6a, 0x4d, 0xad, 0xdd, 0x18, 0xb6, 0xf5, 0x46, 0xb3, 0xd9, 0x3f, 0xee, 0x0d, 0x95, 0x02, 0xd6, + 0xd8, 0xe8, 0x0e, 0xdb, 0x5a, 0x0c, 0xa2, 0xa7, 0x50, 0x5b, 0x5a, 0xff, 0x28, 0x86, 0x94, 0x76, + 0x4b, 0x68, 0x2d, 0xd3, 0x5c, 0xa9, 0xff, 0xe1, 0x16, 0xd4, 0xd2, 0xac, 0xc9, 0xbe, 0x84, 0xa2, + 0x69, 0xa6, 0xe6, 0xf8, 0xd6, 0x2a, 0x16, 0x7e, 0xd2, 0x32, 0xa3, 0x69, 0xe6, 0x3f, 0xd8, 0xbd, + 0x68, 0x21, 0xad, 0x2f, 0x2d, 0xa4, 0x68, 0x19, 0xfd, 0x02, 0x36, 0xc5, 0x5b, 0x70, 0xb1, 0x1b, + 0x3b, 0xb5, 0x4a, 0x9a, 0x84, 0x6c, 0x09, 0xdc, 0xc1, 0x9a, 0x56, 0x1b, 0xa5, 0x20, 0xec, 0xe7, + 0x50, 0x33, 0xb8, 0x73, 0x58, 0x76, 0x83, 0xc7, 0xaa, 0x6c, 0x83, 0x7c, 0xc3, 0x49, 0xf6, 0xaa, + 0x21, 0x03, 0x90, 0x11, 0x4d, 0xdf, 0x9b, 0x25, 0x99, 0xf3, 0xa9, 0xf8, 0x25, 0xdf, 0x9b, 0x49, + 0x79, 0x2b, 0xa6, 0x94, 0x66, 0x5f, 0x40, 0x45, 0xb4, 0x3c, 0x71, 0x0a, 0xc5, 0x4b, 0x96, 0x37, + 0x9b, 0x54, 0xd3, 0x83, 0x35, 0xad, 0x3c, 0x4a, 0x92, 0xec, 0x19, 0xea, 0xa3, 0x89, 0x22, 0x5f, + 0x90, 0x79, 0x8d, 0x5a, 0x1b, 0xe5, 0x02, 0x23, 0x4e, 0xb1, 0x4f, 0x00, 0xa8, 0x9d, 0x3c, 0x4f, + 0x31, 0x15, 0xd9, 0xeb, 0x7b, 0xb3, 0x28, 0x4b, 0xc9, 0x8c, 0x12, 0x52, 0xf3, 0xb8, 0x4b, 0xaf, + 0xb4, 0xdc, 0x3c, 0x72, 0xeb, 0x25, 0xcd, 0xe3, 0xde, 0xc0, 0xb8, 0x79, 0x3c, 0x1b, 0x2c, 0x35, + 0x2f, 0xca, 0xc5, 0x9b, 0xc7, 0x33, 0x45, 0xcd, 0xe3, 0x79, 0xca, 0x8b, 0xcd, 0x8b, 0xb2, 0x50, + 0xf3, 0x78, 0x8e, 0x9f, 0x2f, 0x59, 0x20, 0x95, 0x37, 0x5a, 0x20, 0x38, 0x6d, 0x69, 0x1b, 0xe4, + 0xe7, 0x50, 0x0b, 0x4e, 0xbd, 0x73, 0x49, 0x80, 0x54, 0xe5, 0xdc, 0x83, 0x53, 0xef, 0x5c, 0x96, + 0x20, 0xd5, 0x40, 0x06, 0x60, 0x6b, 0x79, 0x17, 0x29, 0xd6, 0xa8, 0x26, 0xb7, 0x96, 0x7a, 0xf8, + 0xd2, 0xb6, 0xce, 0xb1, 0xb5, 0x46, 0x94, 0xc0, 0x41, 0x49, 0x1c, 0x64, 0x81, 0x70, 0x79, 0xa5, + 0xe2, 0x61, 0x45, 0x4d, 0x10, 0xbb, 0xca, 0x02, 0xe4, 0xad, 0xb9, 0x2b, 0x67, 0x53, 0x64, 0xde, + 0x3a, 0x76, 0x53, 0x19, 0x2b, 0x9c, 0x54, 0x64, 0x4d, 0x56, 0x45, 0x60, 0x7d, 0x3f, 0xb7, 0xdc, + 0x91, 0x25, 0xe2, 0xde, 0x53, 0xab, 0x62, 0x20, 0x70, 0xc9, 0xaa, 0x88, 0x20, 0x31, 0x5f, 0xc7, + 0xd9, 0xd9, 0x22, 0x5f, 0x4b, 0x99, 0x89, 0xaf, 0xe3, 0xac, 0xf1, 0x82, 0x8a, 0xf3, 0x5e, 0x59, + 0x5a, 0x50, 0x52, 0x66, 0xbe, 0xa0, 0xe2, 0xdc, 0xcf, 0x40, 0x70, 0x13, 0x1f, 0xdc, 0x54, 0x74, + 0x3c, 0x6f, 0xb5, 0x18, 0x5d, 0x18, 0xc5, 0x29, 0xe4, 0x55, 0xdf, 0x42, 0x8b, 0x47, 0xb0, 0xc2, + 0x55, 0x99, 0x57, 0x35, 0xc2, 0xc4, 0x4b, 0xc9, 0x4f, 0x92, 0x52, 0x65, 0x33, 0x3b, 0xf4, 0xeb, + 0xe6, 0x72, 0x65, 0x47, 0x76, 0xe8, 0x27, 0x95, 0x61, 0x8a, 0x7d, 0x04, 0xc4, 0x86, 0x3c, 0x8b, + 0x25, 0x8b, 0x6e, 0x1c, 0x16, 0x91, 0xa1, 0x68, 0x8a, 0xdf, 0xc8, 0x2c, 0xa2, 0x8e, 0x91, 0x39, + 0xaa, 0x8f, 0x65, 0x66, 0xe1, 0x55, 0x34, 0x5b, 0x4d, 0x64, 0x16, 0x4e, 0xd4, 0x34, 0x47, 0xec, + 0x31, 0x50, 0x6e, 0xa2, 0x9f, 0xa4, 0x9e, 0x75, 0xf5, 0xbd, 0x19, 0xa7, 0x2e, 0x20, 0x01, 0xd2, + 0x62, 0x0f, 0x1c, 0xcf, 0x8d, 0x3a, 0x7e, 0x9a, 0xea, 0x01, 0x22, 0x62, 0x61, 0x30, 0x8a, 0x53, + 0xea, 0x3f, 0xb7, 0x01, 0x05, 0x21, 0x6b, 0xd9, 0x15, 0xd8, 0x14, 0x22, 0xbf, 0xd5, 0x18, 0x36, + 0x76, 0x1b, 0x03, 0x54, 0xd2, 0x18, 0xd4, 0xb8, 0xcc, 0x8f, 0x61, 0x19, 0xdc, 0x07, 0x48, 0xe8, + 0xc7, 0xa0, 0x75, 0xdc, 0x07, 0x44, 0x5e, 0x1e, 0x88, 0x91, 0x65, 0x9b, 0x50, 0xe6, 0x19, 0x39, + 0x80, 0x1e, 0xde, 0xa0, 0x5c, 0x3c, 0x9d, 0x97, 0xb2, 0xf0, 0x88, 0x99, 0x8d, 0x24, 0x0b, 0x07, + 0x14, 0xe2, 0x2c, 0x51, 0x48, 0x0d, 0x83, 0xda, 0x50, 0x3b, 0xee, 0x35, 0x93, 0x7a, 0x4a, 0xf4, + 0x58, 0x02, 0x2f, 0xe6, 0x65, 0xa7, 0xfd, 0x4a, 0x01, 0xcc, 0xc4, 0x4b, 0xa1, 0x74, 0x19, 0xd5, + 0x4c, 0x2a, 0x84, 0x92, 0x15, 0x76, 0x1d, 0xae, 0x0c, 0x0e, 0xfa, 0xaf, 0x74, 0x9e, 0x29, 0xee, + 0x42, 0x95, 0x6d, 0x83, 0x22, 0x21, 0x78, 0xf1, 0x35, 0xac, 0x92, 0xa0, 0x11, 0xe1, 0x40, 0xd9, + 0xa4, 0xe7, 0x02, 0x11, 0x36, 0xe4, 0xfb, 0xae, 0x82, 0x5d, 0xe1, 0x59, 0xfb, 0xdd, 0xe3, 0xc3, + 0xde, 0x40, 0xd9, 0xc2, 0x46, 0x10, 0x84, 0xb7, 0x9c, 0xc5, 0xc5, 0x24, 0xbb, 0xf5, 0x15, 0xda, + 0xc0, 0x11, 0xf6, 0xaa, 0xa1, 0xf5, 0x3a, 0xbd, 0xfd, 0x81, 0xb2, 0x1d, 0x97, 0xdc, 0xd6, 0xb4, + 0xbe, 0x36, 0x50, 0xae, 0xc6, 0x80, 0xc1, 0xb0, 0x31, 0x3c, 0x1e, 0x28, 0xd7, 0xe2, 0x56, 0x1e, + 0x69, 0xfd, 0x66, 0x7b, 0x30, 0xe8, 0x76, 0x06, 0x43, 0xe5, 0x3a, 0xbb, 0x0a, 0x5b, 0x49, 0x8b, + 0x22, 0xe2, 0xba, 0xd4, 0x50, 0x6d, 0xbf, 0x3d, 0x54, 0x6e, 0xc4, 0xcd, 0x68, 0xf6, 0xbb, 0xdd, + 0x06, 0x45, 0xf9, 0xdc, 0x44, 0x22, 0x0a, 0x30, 0x13, 0xbd, 0x79, 0x07, 0xdb, 0x75, 0xdc, 0x93, + 0x41, 0xb7, 0x24, 0xd6, 0x18, 0xb4, 0x7f, 0x75, 0xdc, 0xee, 0x35, 0xdb, 0xca, 0xed, 0x84, 0x35, + 0x62, 0xd8, 0x9d, 0x98, 0x35, 0x62, 0xd0, 0xdd, 0xb8, 0xce, 0x08, 0x34, 0x50, 0x76, 0xe2, 0x01, + 0x3b, 0x3e, 0xda, 0xd7, 0x1a, 0xad, 0xb6, 0xa2, 0x22, 0x44, 0x6b, 0xf7, 0x1a, 0x87, 0xd1, 0xc4, + 0xde, 0x97, 0x26, 0xf6, 0xa8, 0x33, 0xd4, 0x94, 0x07, 0xf1, 0x44, 0x52, 0xf2, 0x5d, 0xf6, 0x0e, + 0x5c, 0x97, 0x59, 0x4e, 0x7f, 0xd5, 0x19, 0x1e, 0x88, 0x38, 0xb0, 0x87, 0x3c, 0xec, 0x88, 0x90, + 0xcd, 0x56, 0x93, 0x07, 0xbc, 0x51, 0x5e, 0x4c, 0x3d, 0x52, 0x73, 0xc5, 0x7b, 0xca, 0xbd, 0xc7, + 0x9b, 0x62, 0x28, 0x7a, 0xbd, 0x76, 0x73, 0xd8, 0xd7, 0x06, 0xbb, 0x15, 0xfa, 0x2a, 0x8b, 0x50, + 0x41, 0xd4, 0xaf, 0x81, 0xc9, 0x1f, 0x1d, 0x10, 0x17, 0x88, 0x18, 0xe4, 0xc6, 0xbe, 0x37, 0x8d, + 0x8e, 0x47, 0xf1, 0x37, 0x5a, 0xf1, 0xb3, 0xf9, 0x09, 0x45, 0x49, 0x25, 0xcf, 0xdc, 0xc8, 0x20, + 0xf5, 0xdf, 0xce, 0x40, 0x2d, 0xad, 0x7e, 0x90, 0x73, 0x7a, 0xac, 0xbb, 0x5e, 0xc8, 0x5f, 0x32, + 0x0d, 0xe2, 0x6f, 0x01, 0x8c, 0x7b, 0x5e, 0x48, 0x4f, 0x99, 0x06, 0xa9, 0x13, 0xf9, 0xf5, 0x85, + 0x13, 0xf9, 0x0e, 0x5c, 0x49, 0x7d, 0xe3, 0x21, 0xf5, 0x8e, 0x6c, 0x3d, 0x7e, 0x0d, 0x7d, 0xa1, + 0xfd, 0x1a, 0x0b, 0x96, 0xfb, 0x24, 0x1e, 0x2b, 0xca, 0x25, 0x8f, 0x15, 0x1d, 0x40, 0x35, 0xa5, + 0xed, 0x90, 0x2f, 0x68, 0x9c, 0x6e, 0x69, 0xd1, 0x1e, 0xbf, 0xbd, 0x99, 0xea, 0xbf, 0x99, 0x81, + 0x8a, 0xac, 0xfb, 0xfc, 0xce, 0x25, 0x51, 0x5c, 0xaf, 0xf8, 0xad, 0xdb, 0x66, 0xf4, 0x2c, 0x69, + 0x04, 0xea, 0xd0, 0xd7, 0xa8, 0xb8, 0x9f, 0x7f, 0xef, 0x6c, 0x10, 0x77, 0x47, 0x06, 0x51, 0x14, + 0xc3, 0xa9, 0x35, 0x3a, 0xdb, 0x7b, 0x81, 0x04, 0x51, 0x14, 0x43, 0x0c, 0x51, 0xef, 0x42, 0x69, + 0xef, 0x2c, 0x0a, 0x73, 0x96, 0xdf, 0xf3, 0x2d, 0xf1, 0xb7, 0x91, 0xd4, 0xbf, 0xc8, 0x40, 0x2d, + 0xf1, 0x7c, 0x50, 0xd0, 0x18, 0xff, 0x36, 0x08, 0x67, 0x87, 0x75, 0xf3, 0x24, 0x89, 0x54, 0x59, + 0x97, 0x23, 0x55, 0xee, 0x8b, 0xc2, 0xb2, 0xb2, 0xd0, 0x8f, 0xeb, 0x12, 0x2f, 0x2f, 0x3d, 0x83, + 0x0a, 0xfe, 0xd7, 0xac, 0xb1, 0xe5, 0xfb, 0x96, 0x99, 0xbe, 0xd6, 0x99, 0x10, 0xa7, 0x88, 0xc8, + 0xca, 0x13, 0x31, 0x30, 0x6f, 0x78, 0x54, 0x91, 0x1e, 0xfb, 0xfc, 0x3f, 0xb3, 0x50, 0x96, 0x34, + 0xc9, 0x1f, 0xc5, 0x7e, 0xb7, 0xa0, 0x94, 0x3c, 0xf1, 0x27, 0x9e, 0xbb, 0x89, 0x01, 0xa9, 0xb9, + 0xca, 0x2e, 0xcc, 0x55, 0x1d, 0x0a, 0x3e, 0x7f, 0x6c, 0x42, 0x38, 0xa2, 0xa3, 0x64, 0xda, 0xe5, + 0x9b, 0x7f, 0xcb, 0x59, 0xd4, 0xa7, 0x50, 0x91, 0xfc, 0xb5, 0x51, 0x68, 0xc9, 0x22, 0x7d, 0x39, + 0xf1, 0xdd, 0x06, 0xec, 0x2a, 0x6c, 0x8c, 0xcf, 0x74, 0xf3, 0x84, 0x3f, 0x82, 0x52, 0xd2, 0xf2, + 0xe3, 0xb3, 0xd6, 0x09, 0x9d, 0xd4, 0x8d, 0x63, 0xe5, 0x89, 0x7b, 0xd1, 0x8a, 0xe3, 0x48, 0x45, + 0x7a, 0x04, 0x85, 0xf1, 0x99, 0xfc, 0x98, 0xc9, 0xd2, 0x90, 0x6f, 0x8c, 0xcf, 0xe8, 0x09, 0x93, + 0x8f, 0x61, 0x5b, 0xec, 0xe0, 0x46, 0xa0, 0xf3, 0x97, 0xc5, 0xe8, 0xe9, 0x47, 0xfe, 0xba, 0xef, + 0x16, 0xc7, 0x35, 0x82, 0x01, 0x61, 0x90, 0xe3, 0x54, 0xa8, 0x48, 0x0c, 0xc8, 0xbd, 0x61, 0x25, + 0x2d, 0x05, 0x63, 0xcf, 0xa1, 0x32, 0x3e, 0xe3, 0x13, 0x3a, 0xf4, 0x0e, 0x2d, 0x71, 0xd3, 0x72, + 0x7b, 0x71, 0x2a, 0x29, 0xaa, 0x2f, 0x45, 0xc9, 0xae, 0xc1, 0x86, 0x66, 0x9c, 0x0f, 0x7e, 0xd5, + 0x25, 0x35, 0xb2, 0xa4, 0x89, 0xd4, 0xd7, 0xb9, 0x62, 0x4d, 0xd9, 0x54, 0xff, 0x93, 0x0c, 0xd4, + 0x12, 0x2b, 0x00, 0x17, 0x21, 0x7b, 0x2c, 0x7f, 0xd4, 0xa7, 0xbe, 0x68, 0x28, 0x20, 0xc9, 0x93, + 0xe1, 0xe5, 0x8c, 0x3f, 0x36, 0xbf, 0xea, 0x5d, 0xd3, 0x55, 0x0e, 0xf4, 0xec, 0xca, 0x4f, 0x84, + 0xec, 0x43, 0x76, 0x78, 0x39, 0xe3, 0x1e, 0x27, 0xdc, 0x14, 0xb9, 0x75, 0xca, 0xb7, 0x43, 0x8a, + 0x73, 0x7d, 0xd1, 0xfe, 0x96, 0x3f, 0xcf, 0x75, 0xa4, 0x75, 0x0e, 0x1b, 0xda, 0xb7, 0x3a, 0x02, + 0x48, 0x6d, 0xd8, 0xeb, 0x6b, 0xed, 0xce, 0x7e, 0x8f, 0x00, 0x39, 0xf2, 0x47, 0x25, 0x4d, 0x6c, + 0x98, 0xe6, 0xde, 0x99, 0xfc, 0x24, 0x64, 0x26, 0xf5, 0x24, 0x64, 0xfc, 0x7a, 0xaa, 0xfc, 0x28, + 0x75, 0x18, 0x7b, 0xf5, 0x59, 0xbc, 0x0a, 0xe3, 0x25, 0xcd, 0xde, 0x83, 0xdc, 0xf8, 0xcc, 0xba, + 0x4c, 0x9b, 0x7a, 0xe9, 0x05, 0x44, 0x04, 0xea, 0x5f, 0x65, 0x80, 0xa5, 0x1a, 0xc2, 0xad, 0x8f, + 0xdf, 0xb5, 0x2d, 0x5f, 0x42, 0x5d, 0xdc, 0x64, 0xe0, 0x54, 0x92, 0xc7, 0x5e, 0x0c, 0xe9, 0x55, + 0x2f, 0xb9, 0xe1, 0x93, 0x3c, 0xbd, 0xca, 0x3e, 0x06, 0xfe, 0xde, 0x34, 0x05, 0x81, 0xe6, 0xde, + 0x60, 0x29, 0x6a, 0x09, 0x4d, 0xf2, 0xc0, 0xb4, 0xfc, 0x70, 0x36, 0x77, 0xf6, 0x6f, 0x26, 0xb3, + 0x46, 0x6b, 0x5e, 0xfd, 0x97, 0x33, 0x70, 0x25, 0xcd, 0x10, 0xbf, 0x5f, 0x2f, 0xd3, 0xaf, 0x84, + 0x67, 0x17, 0x5f, 0x09, 0x5f, 0xc5, 0x4f, 0xb9, 0x95, 0xfc, 0xf4, 0xb7, 0x33, 0xb0, 0x2d, 0x8d, + 0x7e, 0x62, 0x2f, 0xfe, 0x35, 0xb5, 0x4c, 0x7a, 0x2c, 0x3c, 0x97, 0x7a, 0x2c, 0x5c, 0xfd, 0xcb, + 0x0c, 0x5c, 0x5b, 0x68, 0x89, 0x66, 0xfd, 0xb5, 0xb6, 0x25, 0xfd, 0xa8, 0x38, 0x1d, 0x38, 0x44, + 0x4f, 0x58, 0x65, 0x1e, 0x65, 0xa5, 0x47, 0xc5, 0xe9, 0x14, 0x8a, 0x8e, 0x42, 0x6f, 0x8b, 0x97, + 0x0e, 0xf5, 0xe0, 0xd2, 0x1d, 0x89, 0xc9, 0x2e, 0x11, 0x64, 0x70, 0xe9, 0x8e, 0xd4, 0xbf, 0x97, + 0x81, 0x1b, 0x0b, 0x7d, 0x68, 0xcc, 0x43, 0x4f, 0x9c, 0x9b, 0xff, 0x35, 0x75, 0xe3, 0x2e, 0x94, + 0x29, 0xaa, 0x40, 0x1c, 0xc6, 0xf3, 0x61, 0x05, 0x23, 0xa9, 0x57, 0x81, 0xac, 0x69, 0x5c, 0x8a, + 0x47, 0x7f, 0xf0, 0x27, 0x2e, 0xd8, 0x53, 0x6f, 0xee, 0x8b, 0x38, 0x4e, 0xfa, 0xad, 0x7e, 0x06, + 0x5b, 0x49, 0xd3, 0x9b, 0xe2, 0x6d, 0xf7, 0xbb, 0x50, 0x76, 0xad, 0x73, 0x3d, 0x7a, 0xf9, 0x5d, + 0x44, 0x34, 0xbb, 0xd6, 0xb9, 0x20, 0x50, 0xf7, 0x64, 0x59, 0x18, 0x7f, 0x3f, 0xcb, 0x31, 0x53, + 0x31, 0x4e, 0x9e, 0x63, 0x46, 0x28, 0x2c, 0x4d, 0xea, 0x65, 0xc1, 0xb5, 0xce, 0x89, 0x0f, 0xcf, + 0x45, 0x39, 0x0d, 0x53, 0xbc, 0xb4, 0xbe, 0x32, 0x60, 0xee, 0x06, 0x14, 0x67, 0x7e, 0x6a, 0x98, + 0x0a, 0x33, 0x9f, 0x57, 0xfb, 0x40, 0xc4, 0x4b, 0xbf, 0x29, 0x26, 0x84, 0x47, 0x50, 0x8b, 0xef, + 0xeb, 0xe5, 0x92, 0xef, 0xeb, 0x7d, 0x2e, 0xc4, 0x20, 0x59, 0x7e, 0xbc, 0x66, 0x05, 0xb2, 0xb6, + 0x79, 0x41, 0x15, 0x57, 0x35, 0xfc, 0x49, 0x9a, 0x9c, 0xf5, 0xbd, 0x08, 0xd9, 0xc6, 0x9f, 0xea, + 0x2e, 0x94, 0xb5, 0x94, 0x99, 0x5b, 0x91, 0x3c, 0x46, 0x41, 0xfa, 0xed, 0xc8, 0x64, 0x80, 0xb4, + 0x72, 0xe2, 0x30, 0x0a, 0xd4, 0x40, 0x08, 0xbe, 0x97, 0x86, 0x3f, 0x3a, 0x35, 0xfc, 0xae, 0xe5, + 0x4e, 0xc2, 0x53, 0x1c, 0x72, 0xee, 0xc8, 0x95, 0x87, 0x10, 0x38, 0x28, 0x62, 0x07, 0x1c, 0x45, + 0x87, 0xc8, 0xa3, 0xaf, 0x71, 0xb9, 0xd6, 0xb9, 0xc8, 0x7f, 0x1b, 0x00, 0xc7, 0x5f, 0xa0, 0xf9, + 0x41, 0x66, 0xc9, 0x73, 0x4c, 0x8e, 0x56, 0xb7, 0x44, 0x7f, 0xc5, 0xa3, 0x55, 0x2d, 0x6b, 0xac, + 0x3a, 0x62, 0xe6, 0x79, 0x87, 0xc4, 0x20, 0xfc, 0x4e, 0xd3, 0xc8, 0xee, 0x41, 0x25, 0xf2, 0x49, + 0xd0, 0x73, 0xa5, 0xbc, 0xfa, 0x72, 0x04, 0xeb, 0xcd, 0xa7, 0xea, 0xdf, 0xcd, 0x42, 0xa5, 0xc1, + 0xa3, 0xa0, 0x66, 0x97, 0xfd, 0x59, 0xc8, 0xfe, 0x04, 0xae, 0xd2, 0xfb, 0x65, 0xfc, 0x9b, 0x05, + 0x14, 0x7c, 0x44, 0xd7, 0xdb, 0xc4, 0x20, 0x3e, 0x96, 0x06, 0x51, 0x64, 0x79, 0x32, 0x38, 0xb3, + 0x67, 0xfc, 0x56, 0x65, 0xc7, 0xbc, 0xa0, 0x2b, 0x8c, 0x3c, 0xc2, 0x80, 0x9e, 0x3a, 0x4b, 0x23, + 0xe8, 0xed, 0x22, 0x2c, 0x7e, 0x76, 0x26, 0x8a, 0x15, 0x21, 0x26, 0x08, 0x3c, 0x3a, 0xe3, 0x34, + 0x8f, 0x61, 0x8b, 0x5f, 0xa4, 0x5e, 0xde, 0x80, 0x37, 0x39, 0x22, 0xe1, 0xef, 0x01, 0x6c, 0x89, + 0xe7, 0xd6, 0xe8, 0xfd, 0x6d, 0x7d, 0xe4, 0xcd, 0x2e, 0xc5, 0x01, 0xe6, 0x7b, 0x6f, 0x68, 0x6a, + 0x87, 0x93, 0x22, 0x88, 0xb7, 0x73, 0x33, 0x48, 0x43, 0x6f, 0xb6, 0xe1, 0xfa, 0x1b, 0xfa, 0xf4, + 0xb6, 0x20, 0x89, 0xa2, 0x14, 0x24, 0x71, 0x73, 0x17, 0xb6, 0x57, 0xd5, 0xf7, 0x53, 0xca, 0x50, + 0xff, 0xbc, 0x0a, 0x90, 0x70, 0x6c, 0x4a, 0x1d, 0xcd, 0x2c, 0xa8, 0xa3, 0x3f, 0x29, 0x00, 0xea, + 0x33, 0xa8, 0xe1, 0x50, 0xe9, 0x49, 0x8e, 0xec, 0xca, 0x1c, 0x15, 0xa4, 0x1a, 0x26, 0x6f, 0x45, + 0x2c, 0x07, 0x56, 0xe4, 0x56, 0x06, 0x56, 0x7c, 0x0a, 0x05, 0x7e, 0xd4, 0x16, 0x88, 0xa0, 0xd2, + 0xeb, 0x8b, 0xab, 0xef, 0x89, 0xb8, 0xa1, 0x19, 0xd1, 0xb1, 0x36, 0xd4, 0x50, 0xf4, 0xfb, 0x76, + 0x78, 0x3a, 0x95, 0x1f, 0x2b, 0xb9, 0xb3, 0x9c, 0x33, 0x22, 0x13, 0x9f, 0x40, 0x93, 0x93, 0x92, + 0xf6, 0x1a, 0x4e, 0x85, 0xff, 0x97, 0xb4, 0xd7, 0x82, 0xac, 0xbd, 0x0e, 0xa7, 0xdc, 0xeb, 0x8b, + 0xda, 0xeb, 0x47, 0x70, 0x45, 0xdc, 0x1a, 0xc7, 0x0c, 0x38, 0x9c, 0x44, 0xcf, 0xc3, 0xe1, 0x15, + 0xf1, 0x66, 0xd9, 0x94, 0x6c, 0x3b, 0x24, 0xff, 0x06, 0xb6, 0x47, 0xa7, 0x86, 0x3b, 0xb1, 0xf4, + 0xf0, 0xc4, 0xd1, 0xe9, 0x43, 0x49, 0xfa, 0xd4, 0x98, 0x09, 0xa5, 0xfa, 0xbd, 0xa5, 0xc6, 0x36, + 0x89, 0x78, 0x78, 0xe2, 0x50, 0xb0, 0x5e, 0x1c, 0x7e, 0xb3, 0x35, 0x5a, 0x84, 0x2f, 0x9c, 0x82, + 0xc3, 0xd2, 0x29, 0xf8, 0xa2, 0x9a, 0x5d, 0x5e, 0xa1, 0x66, 0x27, 0xca, 0x72, 0x45, 0x56, 0x96, + 0xd9, 0x87, 0x50, 0x10, 0x8f, 0x5e, 0x08, 0xcf, 0x2f, 0x5b, 0x5e, 0x1d, 0x5a, 0x44, 0x82, 0x35, + 0x45, 0x31, 0x19, 0xf4, 0x2e, 0x52, 0x8d, 0xd7, 0x24, 0xc3, 0xd8, 0xae, 0x70, 0x7b, 0xc6, 0x81, + 0x85, 0xc2, 0xcb, 0x7b, 0x53, 0x2a, 0x38, 0xc6, 0x09, 0xbb, 0x7c, 0x21, 0xc7, 0xcd, 0xff, 0x78, + 0x03, 0x36, 0xc4, 0xc9, 0xfa, 0x63, 0xc8, 0x99, 0xbe, 0x37, 0x8b, 0xef, 0x12, 0xad, 0xd0, 0xda, + 0xe9, 0x4b, 0xbd, 0xa8, 0xe0, 0x3f, 0x81, 0x0d, 0xc3, 0x34, 0xf5, 0xf1, 0x59, 0xfa, 0x44, 0x7a, + 0x41, 0x81, 0x3e, 0x58, 0xd3, 0xf2, 0x06, 0x69, 0xd2, 0x5f, 0x42, 0x09, 0xe9, 0x93, 0x50, 0xdd, + 0xf2, 0xb2, 0x59, 0x10, 0xa9, 0xba, 0x07, 0x6b, 0x5a, 0xd1, 0x88, 0xd4, 0xde, 0x3f, 0x4e, 0xfb, + 0xf6, 0x73, 0x4b, 0x1d, 0x5c, 0xd0, 0xd3, 0x16, 0xbc, 0xfc, 0x7f, 0x03, 0xb8, 0xb3, 0x37, 0xde, + 0xb1, 0xf3, 0xf2, 0xe1, 0xe7, 0xd2, 0xfe, 0x7e, 0xb0, 0xa6, 0xf1, 0x7d, 0x2b, 0xda, 0xef, 0x3f, + 0x8f, 0xfc, 0xee, 0xf1, 0x57, 0x0a, 0x57, 0x8c, 0x0c, 0x8a, 0xc1, 0xd8, 0xf9, 0x4e, 0x32, 0x11, + 0xb3, 0x99, 0xd1, 0xa7, 0x53, 0xd2, 0x97, 0x0d, 0xd2, 0xbb, 0x3a, 0x65, 0x8b, 0xb7, 0xf8, 0xe7, + 0x50, 0xe6, 0x6e, 0x58, 0x9e, 0xaf, 0xb8, 0x34, 0xb4, 0xc9, 0xa6, 0x4c, 0x07, 0x7b, 0xc9, 0x16, + 0xdd, 0x8c, 0xfa, 0xe9, 0x5b, 0xf2, 0xd9, 0xc9, 0xad, 0x95, 0x03, 0xa5, 0xc5, 0xc7, 0x28, 0xbc, + 0xb3, 0x1a, 0xcf, 0xc3, 0xba, 0xb0, 0x2d, 0x0e, 0x19, 0xf8, 0x06, 0x1c, 0xed, 0x99, 0xb0, 0x34, + 0x5f, 0xa9, 0x1d, 0xfa, 0x60, 0x4d, 0x63, 0xc6, 0xf2, 0xbe, 0xdd, 0x84, 0xad, 0xa8, 0x49, 0xb4, + 0xb3, 0x4a, 0xc1, 0x57, 0x72, 0x97, 0x92, 0x7d, 0xf7, 0x60, 0x4d, 0xdb, 0x34, 0xd2, 0x20, 0xd6, + 0x81, 0x2b, 0x51, 0x21, 0xe4, 0x6c, 0x17, 0x23, 0x53, 0x59, 0x9a, 0x45, 0x79, 0xaf, 0x3e, 0x58, + 0xd3, 0xb6, 0x8c, 0xa5, 0x0d, 0xfc, 0x30, 0x6a, 0x8f, 0xac, 0x1c, 0xf2, 0x95, 0x78, 0x77, 0xe5, + 0x30, 0x25, 0x9a, 0x6a, 0xdc, 0xb2, 0x04, 0x94, 0x44, 0x32, 0xdc, 0xd4, 0xe0, 0xda, 0x6a, 0x09, + 0x23, 0x6f, 0x33, 0x39, 0xbe, 0xcd, 0xa8, 0xf2, 0x36, 0xb3, 0xf8, 0xce, 0x99, 0xb4, 0xe9, 0xfc, + 0x12, 0xaa, 0x29, 0x11, 0xcb, 0xca, 0x50, 0x88, 0x3e, 0x1b, 0x43, 0xf7, 0x33, 0x9b, 0xfd, 0xa3, + 0x6f, 0x95, 0x0c, 0x82, 0x3b, 0xbd, 0xc1, 0xb0, 0xd1, 0x1b, 0x2a, 0xeb, 0x3c, 0x71, 0xd4, 0x6d, + 0x34, 0xdb, 0x4a, 0x56, 0xfd, 0xcb, 0x2c, 0x94, 0xe2, 0x73, 0xb6, 0xdf, 0xdd, 0x1b, 0x16, 0xbb, + 0x99, 0xb2, 0xb2, 0x9b, 0x69, 0xc1, 0xd4, 0xe3, 0x1f, 0x83, 0xca, 0x45, 0x1f, 0x08, 0x92, 0x0d, + 0xaa, 0x60, 0xf9, 0xf9, 0x9b, 0xfc, 0x8f, 0x7c, 0xfe, 0x46, 0x8e, 0xd6, 0xdf, 0x48, 0x47, 0xeb, + 0x2f, 0x7c, 0x3a, 0xa8, 0x40, 0x5f, 0xed, 0x90, 0x3f, 0x1d, 0x44, 0xdf, 0x50, 0x7f, 0x69, 0x5b, + 0xe7, 0x22, 0xbc, 0x5d, 0xa4, 0xd2, 0x3b, 0x34, 0xbc, 0x65, 0x87, 0xfe, 0x31, 0xd2, 0xfe, 0x29, + 0x6c, 0x8f, 0xcf, 0xe2, 0x6f, 0x85, 0x24, 0xce, 0x95, 0x0a, 0x35, 0x69, 0x25, 0x8e, 0xbd, 0x17, + 0x7f, 0xc8, 0xb5, 0x2a, 0xbb, 0x81, 0xe2, 0xd9, 0x8a, 0xbf, 0xec, 0xfa, 0x2f, 0x66, 0x00, 0x92, + 0x13, 0xa8, 0xdf, 0xdb, 0x95, 0x2b, 0x79, 0xcb, 0xb2, 0x3f, 0xe0, 0x2d, 0x7b, 0xdb, 0x0b, 0xaf, + 0xdf, 0x43, 0x29, 0x3e, 0x73, 0xfc, 0xdd, 0x19, 0xeb, 0x27, 0x55, 0xf9, 0xb7, 0x22, 0xb7, 0x76, + 0x7c, 0x68, 0xf7, 0xfb, 0x8e, 0x45, 0xaa, 0xfa, 0xec, 0x5b, 0xaa, 0xbf, 0xe0, 0xbe, 0xe5, 0xb8, + 0xf2, 0x3f, 0xf0, 0x6a, 0x92, 0x19, 0x3d, 0x97, 0xbe, 0x3c, 0x35, 0x17, 0x0e, 0xf2, 0xdf, 0xbf, + 0xea, 0x9f, 0xd4, 0xe1, 0xff, 0x23, 0x13, 0x79, 0x71, 0xe3, 0xcf, 0xbb, 0xbc, 0x51, 0xe9, 0x5d, + 0xed, 0x88, 0xfe, 0x29, 0xd5, 0xfd, 0xa0, 0x8f, 0x2a, 0xf7, 0x43, 0x3e, 0xaa, 0xf7, 0x20, 0xcf, + 0xb7, 0xbb, 0xfc, 0x9b, 0xfc, 0x53, 0x1c, 0xff, 0xd6, 0xcf, 0xb9, 0xa9, 0xaa, 0x50, 0xf2, 0x79, + 0x7f, 0xb7, 0xa3, 0x72, 0xa3, 0x4f, 0xd1, 0xd1, 0x6d, 0xa2, 0x7f, 0x8a, 0x4b, 0xd4, 0xdf, 0x75, + 0x48, 0x7e, 0xd8, 0x6d, 0xa1, 0xfe, 0x7f, 0x19, 0xa8, 0xa6, 0x62, 0x08, 0x7e, 0x87, 0x2a, 0x56, + 0xca, 0xe5, 0xec, 0x3f, 0x41, 0x72, 0x39, 0x15, 0x08, 0x5c, 0x4c, 0x07, 0x02, 0xa3, 0xb8, 0xab, + 0xa4, 0x4c, 0x98, 0x55, 0xc6, 0x4e, 0x66, 0xa5, 0xb1, 0x73, 0x27, 0xfe, 0x22, 0x77, 0xa7, 0xc5, + 0xe3, 0x6e, 0xab, 0x9a, 0x04, 0x61, 0x5f, 0xc1, 0x0d, 0xe1, 0x44, 0xe0, 0xe3, 0xe3, 0x8d, 0xf5, + 0xf8, 0x7b, 0xdd, 0xc2, 0x28, 0xbf, 0xc6, 0x09, 0xf8, 0xc7, 0xf8, 0xc6, 0x8d, 0x08, 0xab, 0x76, + 0xa0, 0x9a, 0x0a, 0xce, 0xc0, 0xbd, 0x65, 0xe2, 0x78, 0x27, 0x86, 0x23, 0xda, 0x22, 0x52, 0x6c, + 0x07, 0xf2, 0xe7, 0xa7, 0x96, 0x6f, 0xad, 0xf8, 0x24, 0x03, 0x47, 0xa8, 0x3f, 0x87, 0x8a, 0x1c, + 0x28, 0xc6, 0x3e, 0x84, 0xbc, 0x1d, 0x5a, 0xd3, 0xc8, 0x3d, 0x72, 0x6d, 0x39, 0x96, 0xac, 0x13, + 0x5a, 0x53, 0x8d, 0x13, 0xa9, 0x7f, 0x96, 0x01, 0x65, 0x11, 0x47, 0x1f, 0x41, 0xbd, 0x0c, 0x42, + 0x6b, 0x1a, 0x35, 0x86, 0xa7, 0xa4, 0x46, 0xae, 0xa7, 0x1a, 0x19, 0x79, 0x91, 0xb2, 0xe9, 0xcf, + 0xca, 0x71, 0xa5, 0x64, 0xc5, 0xf7, 0xf2, 0x09, 0xc1, 0x1e, 0x42, 0xd1, 0xb7, 0xe8, 0x6b, 0xf2, + 0xe6, 0x8a, 0x5b, 0x36, 0x31, 0x4e, 0xfd, 0x3b, 0x19, 0x28, 0x88, 0xa8, 0xb6, 0x95, 0xfe, 0xaa, + 0xf7, 0xa1, 0xc0, 0xbf, 0x2c, 0x1f, 0x3d, 0xf4, 0xba, 0x14, 0xaf, 0x1b, 0xe1, 0xd9, 0x1d, 0x1e, + 0xeb, 0x97, 0xf6, 0x5f, 0x1d, 0x39, 0x86, 0xab, 0x11, 0x5c, 0x7c, 0x63, 0xd3, 0x98, 0x8a, 0x8b, + 0x1f, 0xfc, 0x85, 0x4e, 0x20, 0x10, 0x5d, 0xed, 0x50, 0xff, 0x18, 0x0a, 0x22, 0x6a, 0x6e, 0x65, + 0x53, 0xde, 0xf2, 0xa5, 0x70, 0x75, 0x07, 0x20, 0x09, 0xa3, 0x5b, 0x55, 0x82, 0xfa, 0x18, 0x8a, + 0x51, 0xe4, 0x1c, 0xf2, 0x5f, 0x52, 0xb5, 0xb8, 0xbe, 0x25, 0x37, 0xc6, 0x11, 0x9f, 0x39, 0xea, + 0x7a, 0xa3, 0x33, 0x72, 0x96, 0x7f, 0x0c, 0x74, 0x97, 0x6d, 0xb8, 0xf4, 0x94, 0x69, 0xfa, 0x7b, + 0x58, 0x31, 0x11, 0x7b, 0x0c, 0xb1, 0xbc, 0x7c, 0x9b, 0x6b, 0x41, 0x6d, 0x44, 0xb7, 0x1e, 0x89, + 0xcb, 0x9e, 0x09, 0x6f, 0x6a, 0x97, 0x9e, 0xd2, 0xce, 0xc8, 0x9f, 0x23, 0x48, 0xb5, 0x49, 0x93, + 0xc8, 0xd4, 0x1a, 0x54, 0xe4, 0x70, 0x1f, 0xb5, 0x01, 0x5b, 0x87, 0x56, 0x68, 0xa0, 0xfc, 0x89, + 0x1e, 0x78, 0xe4, 0xfc, 0x8b, 0x3f, 0xd2, 0xfc, 0xbb, 0x48, 0xa7, 0x71, 0x22, 0xf5, 0x2f, 0x73, + 0xa0, 0x2c, 0xe2, 0x7e, 0xe8, 0x06, 0xe8, 0x5d, 0x28, 0x7b, 0xc4, 0x17, 0xa9, 0xaf, 0xa8, 0x72, + 0x90, 0x74, 0xab, 0x20, 0xf5, 0x01, 0xbc, 0xa2, 0x1d, 0x1c, 0xf0, 0x4f, 0xe0, 0x5d, 0xe7, 0xd7, + 0xfd, 0x1c, 0x6f, 0x44, 0x6c, 0x5d, 0xa1, 0xdb, 0x7d, 0x5d, 0x6f, 0x44, 0x17, 0x4b, 0x85, 0x77, + 0x82, 0xc7, 0xa0, 0x56, 0xb4, 0xa2, 0x70, 0x49, 0xd0, 0xf9, 0x9d, 0xb8, 0x6b, 0x10, 0x06, 0xe2, + 0x85, 0x87, 0x22, 0x07, 0x0c, 0x83, 0xe8, 0x63, 0x3a, 0x23, 0xf1, 0xc9, 0xcf, 0x2c, 0x7d, 0x4c, + 0xa7, 0xe9, 0xd2, 0xbd, 0x52, 0xfa, 0xc4, 0xc0, 0x48, 0x7c, 0xec, 0x58, 0x7c, 0xce, 0x08, 0x51, + 0xf7, 0xf9, 0x47, 0x51, 0x7d, 0x2b, 0x08, 0xf8, 0x8b, 0xca, 0x25, 0xf1, 0x94, 0xb6, 0x00, 0xc6, + 0x0f, 0xd6, 0x8b, 0xaf, 0x36, 0x22, 0x09, 0x88, 0x77, 0x9d, 0xf9, 0x67, 0x1b, 0x91, 0xe0, 0x06, + 0x14, 0x7f, 0xe3, 0xb9, 0x16, 0x79, 0x39, 0xca, 0xd4, 0xaa, 0x02, 0xa6, 0x0f, 0x8d, 0x19, 0x6e, + 0x04, 0x0e, 0x3d, 0x26, 0xc2, 0x6f, 0x54, 0xf2, 0x84, 0xfa, 0xdf, 0x66, 0x60, 0x7b, 0x71, 0xac, + 0x89, 0x8d, 0x2a, 0x50, 0x6c, 0xf6, 0xbb, 0x7a, 0xaf, 0x71, 0xd8, 0x56, 0xd6, 0xd8, 0x26, 0x94, + 0xfb, 0xbb, 0x5f, 0xb7, 0x9b, 0x43, 0x0e, 0xc8, 0xd0, 0xcb, 0x42, 0x03, 0xfd, 0xa0, 0xd3, 0x6a, + 0xb5, 0x7b, 0xdc, 0xa2, 0xe8, 0xef, 0x7e, 0xad, 0x77, 0xfb, 0x4d, 0xfe, 0xb1, 0xca, 0x28, 0x10, + 0x62, 0xa0, 0xe4, 0x28, 0x4c, 0x82, 0xc2, 0xe1, 0x31, 0x99, 0xe7, 0x71, 0xde, 0xaf, 0x06, 0x7a, + 0xb3, 0x37, 0x54, 0x36, 0x30, 0xd5, 0x3b, 0xee, 0x76, 0x29, 0x45, 0x01, 0x9d, 0xcd, 0xfe, 0xe1, + 0x91, 0xd6, 0x1e, 0x0c, 0xf4, 0x41, 0xe7, 0xd7, 0x6d, 0xa5, 0x48, 0x35, 0x6b, 0x9d, 0xfd, 0x4e, + 0x8f, 0x03, 0x4a, 0xac, 0x00, 0xd9, 0xc3, 0x4e, 0x8f, 0xbf, 0xa8, 0x74, 0xd8, 0xf8, 0x46, 0x29, + 0xe3, 0x8f, 0xc1, 0xf1, 0xa1, 0x52, 0x61, 0x25, 0xc8, 0x77, 0xdb, 0x2f, 0xdb, 0x5d, 0xa5, 0xaa, + 0xfe, 0xcf, 0xd9, 0x48, 0x23, 0xa6, 0x48, 0xa7, 0x1f, 0xa3, 0x05, 0xae, 0x3a, 0x5f, 0x8c, 0x07, + 0x2d, 0x2b, 0x0d, 0x1a, 0xbb, 0x07, 0x15, 0xb1, 0x29, 0xa4, 0xbe, 0x7c, 0x2b, 0x60, 0xc4, 0x72, + 0xf7, 0xa1, 0x1a, 0x07, 0x07, 0x48, 0x1f, 0xc0, 0xa9, 0x44, 0xc0, 0x15, 0xc7, 0x17, 0x1b, 0x2b, + 0x8e, 0x2f, 0x66, 0x76, 0x88, 0x56, 0x36, 0xca, 0x5c, 0xce, 0x49, 0x25, 0x84, 0xd0, 0xa7, 0xdb, + 0xe9, 0xb2, 0x27, 0xa2, 0xe7, 0xae, 0x1d, 0x7d, 0x3a, 0xbb, 0x88, 0x80, 0x63, 0xd7, 0x0e, 0x17, + 0x83, 0x13, 0x4a, 0x4b, 0xc1, 0x09, 0xf2, 0xe6, 0x0c, 0xe9, 0xcd, 0xf9, 0x76, 0xbc, 0x47, 0x22, + 0x92, 0x7f, 0x33, 0xbb, 0x14, 0xef, 0x82, 0xf4, 0x89, 0xe3, 0xb9, 0x4f, 0x8f, 0xcb, 0x4a, 0x64, + 0x15, 0x22, 0x53, 0x04, 0x26, 0xde, 0x15, 0xe9, 0xae, 0x7d, 0x9a, 0x9a, 0x6c, 0xe9, 0x92, 0x56, + 0x4b, 0x93, 0xb2, 0x27, 0x70, 0x45, 0xf0, 0x76, 0x6a, 0x6c, 0xc5, 0x35, 0x5d, 0x8e, 0x6a, 0x24, + 0x23, 0xac, 0xfe, 0x11, 0x14, 0xa3, 0xa0, 0xb6, 0x1f, 0x56, 0x76, 0x57, 0xcc, 0xab, 0xfa, 0xef, + 0xad, 0x43, 0x29, 0x0e, 0x71, 0xfb, 0x51, 0xdc, 0x41, 0x5f, 0xfa, 0x0a, 0xce, 0x64, 0x11, 0x53, + 0x44, 0x40, 0x34, 0x53, 0xe2, 0xce, 0xd7, 0xdc, 0xb7, 0x23, 0x8d, 0x8d, 0x43, 0x8e, 0x7d, 0x9b, + 0x5e, 0x90, 0xb3, 0x5d, 0xe9, 0x42, 0x6d, 0x49, 0x2b, 0x22, 0x80, 0x16, 0xda, 0x0d, 0xa0, 0xdf, + 0x94, 0x93, 0x33, 0x49, 0x01, 0xd3, 0x98, 0xef, 0x5a, 0x6c, 0xff, 0x71, 0xde, 0x10, 0x29, 0xfa, + 0x4e, 0x19, 0x8f, 0xae, 0xe1, 0x31, 0x05, 0xd1, 0xb7, 0x80, 0xdf, 0x81, 0xd2, 0x3c, 0xfe, 0x98, + 0xb4, 0xe0, 0x88, 0x79, 0xf4, 0x29, 0xe9, 0xf4, 0xac, 0x96, 0x16, 0x67, 0x75, 0x91, 0xa7, 0x61, + 0x89, 0xa7, 0xd5, 0x10, 0x0a, 0x22, 0xcc, 0xef, 0x87, 0x07, 0xfc, 0x07, 0x87, 0x4a, 0x81, 0xac, + 0xe1, 0x44, 0xb7, 0x78, 0xf1, 0xe7, 0x42, 0xc3, 0x72, 0x0b, 0x0d, 0x53, 0xff, 0x8d, 0x75, 0x80, + 0x24, 0x5c, 0x90, 0x7d, 0xb4, 0x10, 0x9a, 0x9c, 0x59, 0xda, 0xf6, 0x17, 0x22, 0x92, 0x17, 0x9e, + 0x54, 0x5c, 0xff, 0x11, 0x4f, 0x2a, 0x3e, 0x85, 0x6a, 0xe0, 0x8f, 0xde, 0xea, 0x70, 0x2f, 0x07, + 0xfe, 0x28, 0xf6, 0xb7, 0x7f, 0x0c, 0x98, 0xa4, 0xe7, 0x96, 0x13, 0x43, 0x75, 0x49, 0x6b, 0x29, + 0x05, 0xfe, 0xa8, 0x7f, 0xf2, 0x5d, 0x8b, 0x5f, 0xb4, 0x33, 0x83, 0x50, 0x5f, 0x25, 0x25, 0x36, + 0xcd, 0x20, 0x6c, 0xc9, 0x82, 0xe2, 0x01, 0xd4, 0x90, 0x76, 0x49, 0x58, 0x54, 0xcc, 0x20, 0x39, + 0x60, 0x51, 0xff, 0xd9, 0xe8, 0x48, 0x7a, 0xc1, 0x97, 0xcb, 0xbe, 0x10, 0x86, 0xb8, 0xa4, 0x44, + 0xd4, 0x57, 0xb9, 0x7e, 0xf9, 0x0d, 0xda, 0x98, 0x74, 0xf9, 0xc3, 0xbf, 0xeb, 0x3f, 0xf6, 0xc3, + 0xbf, 0x3b, 0x00, 0xc9, 0x83, 0xd7, 0xb8, 0x02, 0xe3, 0xeb, 0x3a, 0x25, 0x7e, 0x11, 0xe7, 0xf1, + 0x21, 0x5c, 0x69, 0x4c, 0x26, 0xbe, 0x35, 0xa1, 0xaf, 0x23, 0xb9, 0x63, 0x7b, 0x12, 0xc5, 0x7c, + 0x36, 0xf6, 0xf7, 0xf5, 0x66, 0xbf, 0xb7, 0xd7, 0xd9, 0x8f, 0xde, 0x03, 0xbb, 0x07, 0xb7, 0x25, + 0xe0, 0xbe, 0xd6, 0x3f, 0x3e, 0xc2, 0x44, 0xb3, 0x31, 0xd4, 0xfb, 0x5a, 0xab, 0xad, 0x29, 0x99, + 0xc7, 0xf7, 0xa0, 0xd2, 0x14, 0x3b, 0x65, 0xfc, 0x46, 0x99, 0xe7, 0x5a, 0xfc, 0x1b, 0x6c, 0xdd, + 0xdf, 0x7c, 0xa6, 0x64, 0x1e, 0xab, 0x50, 0x96, 0xbe, 0x80, 0x88, 0x14, 0x07, 0x46, 0x70, 0x2a, + 0xbe, 0xc7, 0x65, 0xb8, 0x13, 0x4b, 0xc9, 0x3c, 0x7e, 0x88, 0x3a, 0xbc, 0xfc, 0xfd, 0x41, 0x80, + 0x8d, 0x9e, 0xe7, 0x4f, 0x0d, 0x47, 0xd0, 0x59, 0xf3, 0x00, 0xe9, 0x3e, 0x86, 0xab, 0x2b, 0xbf, + 0xa6, 0x48, 0x77, 0xc2, 0xec, 0xe9, 0xcc, 0xb1, 0xf8, 0xed, 0xa6, 0x83, 0xcb, 0x13, 0xdf, 0x36, + 0x95, 0xcc, 0xe3, 0xe7, 0x0b, 0x5f, 0xdb, 0x3a, 0xee, 0xed, 0xf6, 0x8f, 0x7b, 0x2d, 0x7a, 0x3e, + 0x8c, 0x5e, 0xe9, 0x6b, 0x76, 0x8f, 0x07, 0x9d, 0x97, 0x62, 0x6b, 0x6d, 0x7f, 0x13, 0x25, 0xd7, + 0x1f, 0x7f, 0x13, 0x3d, 0x84, 0x11, 0xb5, 0xba, 0xdb, 0x6f, 0xb4, 0xf8, 0x96, 0x1c, 0x3f, 0x3a, + 0x38, 0xdc, 0xe5, 0x5f, 0xe9, 0xd2, 0xda, 0x83, 0xe3, 0xee, 0x30, 0x7a, 0xcf, 0xb0, 0x06, 0xd0, + 0x69, 0xb6, 0x77, 0xdb, 0xda, 0x3e, 0x12, 0x64, 0x31, 0x7d, 0xd8, 0xef, 0xed, 0xf7, 0x5b, 0xbb, + 0x98, 0xce, 0x3d, 0xfe, 0x6f, 0xd6, 0x41, 0x59, 0x7c, 0xbb, 0x84, 0xbd, 0x03, 0xd7, 0x89, 0x48, + 0x3f, 0xd2, 0xda, 0xad, 0x4e, 0x93, 0x87, 0xc3, 0xbe, 0x6c, 0x74, 0x3b, 0x58, 0xe7, 0x75, 0xb8, + 0xb2, 0x88, 0x6c, 0xf4, 0x5a, 0xfc, 0x95, 0xb3, 0x45, 0x44, 0xfb, 0x57, 0xc7, 0x8d, 0xae, 0xb2, + 0xce, 0x6e, 0xc3, 0x8d, 0x45, 0x54, 0xaf, 0x3f, 0x14, 0xe8, 0x2c, 0xab, 0xc3, 0xf6, 0x22, 0xba, + 0xdb, 0x1e, 0xa0, 0xde, 0x70, 0x07, 0x6e, 0xae, 0xc2, 0x88, 0x9c, 0xf9, 0x55, 0x2d, 0xdd, 0x27, + 0xb5, 0x43, 0x53, 0x36, 0x90, 0x65, 0xde, 0x80, 0x14, 0xf9, 0x0b, 0xec, 0x1a, 0xb0, 0xe5, 0x9e, + 0x2a, 0xc5, 0x95, 0x23, 0x30, 0xe0, 0x5f, 0xe6, 0x2e, 0xb1, 0xbb, 0xf0, 0xce, 0x2a, 0x64, 0x5f, + 0x7c, 0xba, 0x1b, 0x1e, 0xff, 0xc3, 0x0c, 0xd4, 0xdf, 0x74, 0x95, 0x9d, 0xa9, 0x70, 0x47, 0x3b, + 0xee, 0xd1, 0xab, 0x83, 0xfc, 0x81, 0x44, 0xfd, 0x45, 0xfb, 0xdb, 0x85, 0xc7, 0xe4, 0x6e, 0xc3, + 0x8d, 0x15, 0x34, 0x5a, 0xe3, 0x95, 0xfe, 0xf2, 0x53, 0x25, 0xc3, 0x3e, 0x80, 0xf7, 0x56, 0xa0, + 0xf7, 0xba, 0xfd, 0xc6, 0x50, 0xff, 0x75, 0x5b, 0xeb, 0xeb, 0xcd, 0x6e, 0x7f, 0xd0, 0x6e, 0x21, + 0xf1, 0x3a, 0xdb, 0x81, 0x5b, 0x2b, 0x88, 0x07, 0xfc, 0xf1, 0xca, 0x97, 0x9f, 0x2a, 0x59, 0xf6, + 0x2e, 0xdc, 0x7b, 0x33, 0xc5, 0x1e, 0x6a, 0x66, 0x2f, 0x3f, 0x55, 0x72, 0x8f, 0x7f, 0x09, 0xf5, + 0x37, 0xdd, 0x35, 0xc3, 0x65, 0xd1, 0x3c, 0x68, 0xd0, 0x7d, 0x3e, 0xd4, 0xe6, 0xfa, 0x3a, 0x4f, + 0x91, 0xcf, 0x59, 0x6b, 0x77, 0xdb, 0x14, 0x90, 0xfd, 0xf8, 0xb7, 0x19, 0xc9, 0xb2, 0x89, 0xee, + 0x0b, 0xc5, 0x00, 0xb1, 0x56, 0x65, 0x90, 0x66, 0x19, 0xa6, 0x92, 0xc1, 0x59, 0x4a, 0x81, 0xba, + 0xde, 0xc8, 0x70, 0x94, 0x75, 0x0a, 0xbd, 0x8e, 0xe0, 0x74, 0x37, 0x55, 0xc9, 0xe2, 0xd0, 0xc5, + 0xb0, 0xae, 0x77, 0x7e, 0xe4, 0xdb, 0x9e, 0x6f, 0x87, 0x97, 0x1c, 0x9d, 0x7b, 0xfc, 0x4f, 0x8b, + 0xb0, 0x81, 0x94, 0xbc, 0xc3, 0x0a, 0x1a, 0xa6, 0x99, 0xc0, 0x68, 0x8b, 0xe5, 0xbc, 0x4e, 0xfa, + 0xc5, 0x02, 0x22, 0x83, 0xfc, 0x11, 0xb9, 0x5f, 0x16, 0x91, 0xeb, 0x88, 0xd4, 0x2c, 0x0a, 0xda, + 0x5d, 0x42, 0x66, 0x77, 0x7f, 0xf1, 0x0f, 0xfe, 0xea, 0x4e, 0xe6, 0xbf, 0xfa, 0xab, 0x3b, 0x99, + 0xff, 0xe5, 0xaf, 0xee, 0xac, 0xfd, 0xd9, 0xff, 0x76, 0x27, 0xf3, 0xeb, 0x8f, 0x26, 0x76, 0x78, + 0x3a, 0x3f, 0x79, 0x32, 0xf2, 0xa6, 0x1f, 0x4f, 0x8d, 0xd0, 0xb7, 0x2f, 0xb8, 0xa2, 0x13, 0x25, + 0x5c, 0xeb, 0xe3, 0xd9, 0xd9, 0xe4, 0xe3, 0xd9, 0xc9, 0xc7, 0x28, 0x72, 0x4f, 0x36, 0x66, 0xbe, + 0x17, 0x7a, 0xcf, 0xfe, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xca, 0xf0, 0x7b, 0xf4, 0x5f, 0x95, + 0x00, 0x00, } func (m *Type) Marshal() (dAtA []byte, err error) { @@ -19648,6 +19657,16 @@ func (m *UpdateCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.IgnoreAffectedRows { + i-- + if m.IgnoreAffectedRows { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x68 + } if m.CountDeleteAffectRows { i-- if m.CountDeleteAffectRows { @@ -29823,6 +29842,9 @@ func (m *UpdateCtx) ProtoSize() (n int) { if m.CountDeleteAffectRows { n += 2 } + if m.IgnoreAffectedRows { + n += 2 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -43906,6 +43928,26 @@ func (m *UpdateCtx) Unmarshal(dAtA []byte) error { } } m.CountDeleteAffectRows = bool(v != 0) + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IgnoreAffectedRows", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IgnoreAffectedRows = bool(v != 0) default: iNdEx = preIndex skippy, err := skipPlan(dAtA[iNdEx:]) diff --git a/pkg/sql/colexec/multi_update/affect_rows_test.go b/pkg/sql/colexec/multi_update/affect_rows_test.go index 659ad558fbddd..8f9571677885f 100644 --- a/pkg/sql/colexec/multi_update/affect_rows_test.go +++ b/pkg/sql/colexec/multi_update/affect_rows_test.go @@ -78,6 +78,14 @@ func TestUpsertAffectRowsAccounting(t *testing.T) { require.EqualValues(t, 0, op.GetAffectedRows()) }) + t.Run("foreign key side effects never affect rows", func(t *testing.T) { + op := newAffectRowsTestOp(actionUpdate, true) + op.MultiUpdateCtx = []*MultiUpdateCtx{{IgnoreAffectedRows: true}} + op.addInsertAffectRows(UpdateMainTable, 4) + op.addDeleteAffectRows(UpdateMainTable, 3) + require.EqualValues(t, 0, op.GetAffectedRows()) + }) + t.Run("batch upsert: new + updated rows", func(t *testing.T) { // 2 brand new rows (INSERT only) + 3 conflicting rows (DELETE + INSERT): // inserts cover all 5 rows, deletes cover the 3 conflicts => 5 + 3 = 8. diff --git a/pkg/sql/colexec/multi_update/multi_update_partition.go b/pkg/sql/colexec/multi_update/multi_update_partition.go index 247ee15bfd10f..843c372858f5c 100644 --- a/pkg/sql/colexec/multi_update/multi_update_partition.go +++ b/pkg/sql/colexec/multi_update/multi_update_partition.go @@ -443,6 +443,7 @@ func (ctx *MultiUpdateCtx) clone() *MultiUpdateCtx { PartitionCols: ctx.PartitionCols, SkipInsertOnNullPk: ctx.SkipInsertOnNullPk, InsertPkColIdx: ctx.InsertPkColIdx, + IgnoreAffectedRows: ctx.IgnoreAffectedRows, } objRef := *ctx.ObjRef def := *ctx.TableDef diff --git a/pkg/sql/colexec/multi_update/types.go b/pkg/sql/colexec/multi_update/types.go index b9dcaacb7a48b..9828987e9a784 100644 --- a/pkg/sql/colexec/multi_update/types.go +++ b/pkg/sql/colexec/multi_update/types.go @@ -116,7 +116,8 @@ type MultiUpdateCtx struct { SkipInsertOnNullPk bool // InsertPkColIdx is the PK column's index within InsertCols. It is only // used with SkipInsertOnNullPk for REPLACE delete-only rows. - InsertPkColIdx int + InsertPkColIdx int + IgnoreAffectedRows bool } func (update MultiUpdate) TypeName() string { @@ -230,5 +231,8 @@ func (update *MultiUpdate) addDeleteAffectRows(tableType UpdateTableType, rowCou } func (update *MultiUpdate) doAddAffectedRows(affectedRows uint64) { + if len(update.MultiUpdateCtx) > 0 && update.MultiUpdateCtx[0].IgnoreAffectedRows { + return + } update.ctr.affectedRows += affectedRows } diff --git a/pkg/sql/compile/compile.go b/pkg/sql/compile/compile.go index c134e01fa3986..7cdfd302f7435 100644 --- a/pkg/sql/compile/compile.go +++ b/pkg/sql/compile/compile.go @@ -652,11 +652,13 @@ func (c *Compile) runOnce() (err error) { // REPLACE parent checks and actions run before the main pipeline. query := c.pn.GetQuery() - if query != nil && query.StmtType == plan.Query_INSERT && len(query.GetDetectSqls()) != 0 { - if err = validateReplaceParentTxnMode( + if query != nil && len(query.GetDetectSqls()) != 0 { + if err = validateForeignKeyParentTxnMode( c.proc.Ctx, query, c.proc.GetTxnOperator().Txn().IsPessimistic()); err != nil { return err } + } + if query != nil && query.StmtType == plan.Query_INSERT && len(query.GetDetectSqls()) != 0 { for _, sql := range query.DetectSqls { if strings.HasPrefix(sql, "REPLACE_PARENT_PLAN:") { continue @@ -782,7 +784,8 @@ func (c *Compile) runOnce() (err error) { if strings.HasPrefix(sql, "REPLACE_PARENT_LOCK:") || strings.HasPrefix(sql, "REPLACE_PARENT_PLAN:") || strings.HasPrefix(sql, "REPLACE_PARENT_CHK:") || - strings.HasPrefix(sql, "REPLACE_PARENT_ACTION:") { + strings.HasPrefix(sql, "REPLACE_PARENT_ACTION:") || + strings.HasPrefix(sql, "UPDATE_PARENT_PLAN:") { continue } postCheckSqls = append(postCheckSqls, sql) @@ -799,7 +802,7 @@ func (c *Compile) runOnce() (err error) { return err } -func validateReplaceParentTxnMode(ctx context.Context, query *plan.Query, pessimistic bool) error { +func validateForeignKeyParentTxnMode(ctx context.Context, query *plan.Query, pessimistic bool) error { if pessimistic || query == nil { return nil } @@ -809,6 +812,10 @@ func validateReplaceParentTxnMode(ctx context.Context, query *plan.Query, pessim return moerr.NewNotSupported(ctx, "REPLACE on a referenced parent table in optimistic transaction mode") } + if strings.HasPrefix(sql, "UPDATE_PARENT_PLAN:") { + return moerr.NewNotSupported(ctx, + "UPDATE on a referenced parent table in optimistic transaction mode") + } } return nil } diff --git a/pkg/sql/compile/compile_test.go b/pkg/sql/compile/compile_test.go index 28ed80d2e58df..36cb5f24d6555 100644 --- a/pkg/sql/compile/compile_test.go +++ b/pkg/sql/compile/compile_test.go @@ -328,20 +328,24 @@ func TestConstructLockOpPreservesSharedTableMode(t *testing.T) { } } -func TestValidateReplaceParentTxnMode(t *testing.T) { +func TestValidateForeignKeyParentTxnMode(t *testing.T) { ctx := context.Background() query := &plan.Query{DetectSqls: []string{"REPLACE_PARENT_LOCK:select 1 for update"}} - require.NoError(t, validateReplaceParentTxnMode(ctx, query, true)) - require.ErrorContains(t, validateReplaceParentTxnMode(ctx, query, false), + require.NoError(t, validateForeignKeyParentTxnMode(ctx, query, true)) + require.ErrorContains(t, validateForeignKeyParentTxnMode(ctx, query, false), "optimistic transaction mode") query.DetectSqls = []string{"REPLACE_PARENT_PLAN:"} - require.NoError(t, validateReplaceParentTxnMode(ctx, query, true)) - require.ErrorContains(t, validateReplaceParentTxnMode(ctx, query, false), + require.NoError(t, validateForeignKeyParentTxnMode(ctx, query, true)) + require.ErrorContains(t, validateForeignKeyParentTxnMode(ctx, query, false), "optimistic transaction mode") - require.NoError(t, validateReplaceParentTxnMode(ctx, + query.DetectSqls = []string{"UPDATE_PARENT_PLAN:"} + require.NoError(t, validateForeignKeyParentTxnMode(ctx, query, true)) + require.ErrorContains(t, validateForeignKeyParentTxnMode(ctx, query, false), + "UPDATE on a referenced parent table") + require.NoError(t, validateForeignKeyParentTxnMode(ctx, &plan.Query{DetectSqls: []string{"select true"}}, false)) - require.NoError(t, validateReplaceParentTxnMode(ctx, nil, false)) + require.NoError(t, validateForeignKeyParentTxnMode(ctx, nil, false)) } func TestLockTableLocksAllPrePipelineTargets(t *testing.T) { diff --git a/pkg/sql/compile/operator.go b/pkg/sql/compile/operator.go index 165db85aee2e0..a525df21e6151 100644 --- a/pkg/sql/compile/operator.go +++ b/pkg/sql/compile/operator.go @@ -905,6 +905,7 @@ func constructMultiUpdate( PartitionCols: partitionCols, SkipInsertOnNullPk: updateCtx.SkipInsertOnNullPk, InsertPkColIdx: int(updateCtx.InsertPkColIdx), + IgnoreAffectedRows: updateCtx.IgnoreAffectedRows, } } arg.Action = action diff --git a/pkg/sql/compile/remoterun.go b/pkg/sql/compile/remoterun.go index 5bfe6fd98806d..525a9182bf07e 100644 --- a/pkg/sql/compile/remoterun.go +++ b/pkg/sql/compile/remoterun.go @@ -868,6 +868,7 @@ func convertToPipelineInstruction(op vm.Operator, proc *process.Process, ctx *sc TableDef: muCtx.TableDef, SkipInsertOnNullPk: muCtx.SkipInsertOnNullPk, InsertPkColIdx: int32(muCtx.InsertPkColIdx), + IgnoreAffectedRows: muCtx.IgnoreAffectedRows, CountDeleteAffectRows: t.CountDeleteAffectRows, } @@ -1376,6 +1377,7 @@ func convertToVmOperator(opr *pipeline.Instruction, ctx *scopeContext, eng engin TableDef: muCtx.TableDef, SkipInsertOnNullPk: muCtx.SkipInsertOnNullPk, InsertPkColIdx: int(muCtx.InsertPkColIdx), + IgnoreAffectedRows: muCtx.IgnoreAffectedRows, } arg.MultiUpdateCtx[i].InsertCols = make([]int, len(muCtx.InsertCols)) diff --git a/pkg/sql/compile/remoterun_test.go b/pkg/sql/compile/remoterun_test.go index a87dcdb80a663..37b083730fcc8 100644 --- a/pkg/sql/compile/remoterun_test.go +++ b/pkg/sql/compile/remoterun_test.go @@ -864,8 +864,9 @@ func Test_DMLOperatorSerializationRoundtrip(t *testing.T) { op := &multi_update.MultiUpdate{ MultiUpdateCtx: []*multi_update.MultiUpdateCtx{ { - ObjRef: &plan.ObjectRef{ObjName: "t1"}, - TableDef: &plan.TableDef{Name: "t1"}, + ObjRef: &plan.ObjectRef{ObjName: "t1"}, + TableDef: &plan.TableDef{Name: "t1"}, + IgnoreAffectedRows: true, }, }, Action: multi_update.UpdateWriteTable, @@ -875,12 +876,16 @@ func Test_DMLOperatorSerializationRoundtrip(t *testing.T) { require.NoError(t, err) require.True(t, pipeInstr.MultiUpdate.UpdateCtxList[0].CountDeleteAffectRows, "serialized UpdateCtx must carry CountDeleteAffectRows") + require.True(t, pipeInstr.MultiUpdate.UpdateCtxList[0].IgnoreAffectedRows, + "serialized UpdateCtx must carry IgnoreAffectedRows") restored, err := convertToVmOperator(pipeInstr, ctx, nil) require.NoError(t, err) restoredOp := restored.(*multi_update.MultiUpdate) require.True(t, restoredOp.CountDeleteAffectRows, "CountDeleteAffectRows must survive the remote pipeline round-trip") + require.True(t, restoredOp.MultiUpdateCtx[0].IgnoreAffectedRows, + "IgnoreAffectedRows must survive the remote pipeline round-trip") }) t.Run("MultiUpdate_RejectZeroTemporal", func(t *testing.T) { diff --git a/pkg/sql/plan/bind_insert.go b/pkg/sql/plan/bind_insert.go index 6da4173d13013..e4c77ff3319d9 100644 --- a/pkg/sql/plan/bind_insert.go +++ b/pkg/sql/plan/bind_insert.go @@ -1061,7 +1061,7 @@ func (builder *QueryBuilder) appendModernChildFkMarkOks( selectTag int32, childColPos func(colName string) int32, ) (int32, []*plan.Expr, error) { - selectNode := builder.qry.Nodes[lastNodeID] + selectNode := builder.updateInputProjectNode(lastNodeID) inputTypes := make([]plan.Type, len(selectNode.ProjectList)) for i, expr := range selectNode.ProjectList { inputTypes[i] = expr.Typ @@ -1304,6 +1304,11 @@ func (builder *QueryBuilder) appendModernChildFkMarkOks( PrimaryColTyp: fkLock.typ, Mode: lockpb.LockMode_Shared, LockTable: fkLock.lockTable, }) } + baseTableIDs := make(map[uint64]struct{}, len(nonSelfFks)) + for _, fk := range nonSelfFks { + baseTableIDs[fk.ForeignTbl] = struct{}{} + } + sortForeignKeyLockTargets(lockTargets, baseTableIDs) lockInputID := builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, Children: []int32{lastNodeID}, ProjectList: lockProject, BindingTags: []int32{lockTag}, diff --git a/pkg/sql/plan/bind_update.go b/pkg/sql/plan/bind_update.go index 29e2f5876fe0d..1adf85c3a3b75 100644 --- a/pkg/sql/plan/bind_update.go +++ b/pkg/sql/plan/bind_update.go @@ -377,7 +377,12 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) if err != nil { return 0, err } - if updateMayDependOnForeignKeys(dmlCtx, newColName2Idx) { + mayDependOnForeignKeys, err := builder.updateMayDependOnForeignKeys( + bindCtx, dmlCtx, newColName2Idx) + if err != nil { + return 0, err + } + if mayDependOnForeignKeys { // The plan shape and planner route depend on foreign_key_checks. // Preserve that dependency even while checks are disabled so prepared // and generic plan caches rebuild after either session-state transition. @@ -398,19 +403,6 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } } - lastNodeID, selectNodeTag, selectNode, err = builder.appendUpdateForeignKeyChecks( - bindCtx, - dmlCtx, - lastNodeID, - selectNodeTag, - oldColName2Idx, - newColName2Idx, - fkChecksEnabled, - ) - if err != nil { - return 0, err - } - for i, tableDef := range dmlCtx.tableDefs { if updateAutoIncrCols[i] { lastNodeID = builder.appendNode(&plan.Node{ @@ -427,6 +419,19 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } } + lastNodeID, selectNodeTag, selectNode, err = builder.appendUpdateForeignKeyChecks( + bindCtx, + dmlCtx, + lastNodeID, + selectNodeTag, + selectNode, + oldColName2Idx, + newColName2Idx, + ) + if err != nil { + return 0, err + } + idxScanNodes := make([][]*plan.Node, len(dmlCtx.tableDefs)) pkNeedUpdate := make([]bool, len(dmlCtx.tableDefs)) idxNeedUpdate := make([][]bool, len(dmlCtx.tableDefs)) @@ -1375,6 +1380,19 @@ func (builder *QueryBuilder) appendRowNumberDedupNode( selectNode *plan.Node, selectNodeTag int32, partitionColPositions []int32, +) (int32, *plan.Node, int32, error) { + return builder.appendRowNumberGuardNode( + bindCtx, lastNodeID, selectNode, selectNodeTag, partitionColPositions, "", "") +} + +func (builder *QueryBuilder) appendRowNumberGuardNode( + bindCtx *BindContext, + lastNodeID int32, + selectNode *plan.Node, + selectNodeTag int32, + partitionColPositions []int32, + duplicateErrorMessage string, + duplicateErrorType string, ) (int32, *plan.Node, int32, error) { partitionByExprs := make([]*plan.Expr, 0, len(partitionColPositions)) childColExpr := func(pos int32) *plan.Expr { @@ -1488,10 +1506,25 @@ func (builder *QueryBuilder) appendRowNumberDedupNode( if err != nil { return 0, nil, 0, err } + guardExpr := keepFirstRowExpr + if duplicateErrorType != "" { + guardExpr, err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "assert", + []*plan.Expr{ + keepFirstRowExpr, + makePlan2StringConstExprWithType(duplicateErrorMessage), + makePlan2StringConstExprWithType(duplicateErrorType), + }, + ) + if err != nil { + return 0, nil, 0, err + } + } lastNodeID = builder.appendNode(&plan.Node{ NodeType: plan.Node_FILTER, Children: []int32{lastNodeID}, - FilterList: []*plan.Expr{keepFirstRowExpr}, + FilterList: []*plan.Expr{guardExpr}, }, bindCtx) projectList := make([]*plan.Expr, len(selectNode.ProjectList)) diff --git a/pkg/sql/plan/bind_update_fk.go b/pkg/sql/plan/bind_update_fk.go index d131c0e718852..d955147cc2bc2 100644 --- a/pkg/sql/plan/bind_update_fk.go +++ b/pkg/sql/plan/bind_update_fk.go @@ -15,56 +15,88 @@ package plan import ( + "context" + "fmt" + "sort" + + "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/moerr" + lockpb "github.com/matrixorigin/matrixone/pkg/pb/lock" "github.com/matrixorigin/matrixone/pkg/pb/plan" + planutil "github.com/matrixorigin/matrixone/pkg/sql/util" +) + +const ( + foreignKeyNoReferencedRowAssert = "fk_no_referenced_row" + foreignKeyRowIsReferencedAssert = "fk_row_is_referenced" + foreignKeyAmbiguousMappingAssert = "fk_ambiguous_parent_mapping" ) -const foreignKeyNoReferencedRowAssert = "fk_no_referenced_row" +func (builder *QueryBuilder) updateInputProjectNode(nodeID int32) *plan.Node { + node := builder.qry.Nodes[nodeID] + if node.NodeType == plan.Node_PRE_INSERT && len(node.Children) == 1 { + return builder.qry.Nodes[node.Children[0]] + } + return node +} func (builder *QueryBuilder) appendUpdateForeignKeyChecks( bindCtx *BindContext, dmlCtx *DMLContext, lastNodeID int32, selectNodeTag int32, + selectNode *plan.Node, oldColName2Idx map[string]int32, newColName2Idx map[string]int32, - enabled bool, ) (int32, int32, *plan.Node, error) { + enabled, err := IsForeignKeyChecksEnabled(builder.compCtx) + if err != nil { + return 0, 0, nil, err + } if !enabled { - return lastNodeID, selectNodeTag, builder.qry.Nodes[lastNodeID], nil + return lastNodeID, selectNodeTag, selectNode, nil } - var err error for i, tableDef := range dmlCtx.tableDefs { if len(dmlCtx.updateCol2Expr[i]) == 0 { continue } alias := dmlCtx.aliases[i] - if err = builder.rejectUpdateOfReferencedParentKey( + lastNodeID, selectNodeTag, err = builder.appendUpdateParentForeignKeyChecks( bindCtx, tableDef, alias, + lastNodeID, + selectNodeTag, + oldColName2Idx, newColName2Idx, - ); err != nil { + ) + if err != nil { return 0, 0, nil, err } - affectedFks := affectedUpdateChildFks(tableDef, alias, newColName2Idx) if len(affectedFks) == 0 { continue } + validatedFks := make([]*plan.ForeignKeyDef, 0, len(affectedFks)) + for _, fk := range affectedFks { + if fk.ForeignTbl != 0 { + validatedFks = append(validatedFks, fk) + } + } + if len(validatedFks) == 0 { + continue + } + fkTableDef := *tableDef - fkTableDef.Fkeys = make([]*plan.ForeignKeyDef, len(affectedFks)) - for j, fk := range affectedFks { + fkTableDef.Fkeys = make([]*plan.ForeignKeyDef, len(validatedFks)) + for j, fk := range validatedFks { fkTableDef.Fkeys[j] = DeepCopyFkey(fk) - if fkTableDef.Fkeys[j].ForeignTbl == 0 { - fkTableDef.Fkeys[j].ForeignTbl = tableDef.TblId - } } - sourceNode := builder.qry.Nodes[lastNodeID] + sourceNode := selectNode projLen := len(sourceNode.ProjectList) projectTypes := make([]plan.Type, projLen) for j, expr := range sourceNode.ProjectList { @@ -94,7 +126,7 @@ func (builder *QueryBuilder) appendUpdateForeignKeyChecks( "Cannot add or update a child row: a foreign key constraint fails", ) errTypeExpr := makePlan2StringConstExprWithType(foreignKeyNoReferencedRowAssert) - for j, fk := range affectedFks { + for j, fk := range validatedFks { unchanged, buildErr := builder.buildUpdateFkUnchangedExpr( tableDef, fk, @@ -155,25 +187,66 @@ func (builder *QueryBuilder) appendUpdateForeignKeyChecks( }, bindCtx) selectNodeTag = validatedTag + selectNode = builder.qry.Nodes[lastNodeID] } - return lastNodeID, selectNodeTag, builder.qry.Nodes[lastNodeID], nil + return lastNodeID, selectNodeTag, selectNode, nil } -func updateMayDependOnForeignKeys( +func (builder *QueryBuilder) updateMayDependOnForeignKeys( + bindCtx *BindContext, dmlCtx *DMLContext, newColName2Idx map[string]int32, -) bool { +) (bool, error) { for i, tableDef := range dmlCtx.tableDefs { if len(dmlCtx.updateCol2Expr[i]) == 0 { continue } - if len(affectedUpdateChildFks(tableDef, dmlCtx.aliases[i], newColName2Idx)) > 0 || - len(tableDef.RefChildTbls) > 0 { - return true + alias := dmlCtx.aliases[i] + if len(affectedUpdateChildFks(tableDef, alias, newColName2Idx)) > 0 { + return true, nil + } + if tableDef == nil || len(tableDef.RefChildTbls) == 0 { + continue + } + + parentColIDToName := make(map[uint64]string, len(tableDef.Cols)) + for _, col := range tableDef.Cols { + parentColIDToName[col.ColId] = col.Name + } + visited := make(map[uint64]struct{}, len(tableDef.RefChildTbls)) + for _, childTableID := range tableDef.RefChildTbls { + if childTableID == 0 { + childTableID = tableDef.TblId + } + if _, ok := visited[childTableID]; ok { + continue + } + visited[childTableID] = struct{}{} + + _, childTableDef, err := builder.compCtx.ResolveById(childTableID, bindCtx.snapshot) + if err != nil { + return false, err + } + if childTableDef == nil { + return false, moerr.NewInternalErrorf( + builder.GetContext(), "foreign-key child table %d not found", childTableID) + } + for _, fk := range childTableDef.Fkeys { + referencesCurrentTable := fk.ForeignTbl == tableDef.TblId || + (fk.ForeignTbl == 0 && childTableDef.TblId == tableDef.TblId) + if !referencesCurrentTable { + continue + } + for _, parentColID := range fk.ForeignCols { + if _, ok := newColName2Idx[alias+"."+parentColIDToName[parentColID]]; ok { + return true, nil + } + } + } } } - return false + return false, nil } func affectedUpdateChildFks( @@ -202,14 +275,23 @@ func affectedUpdateChildFks( return affected } -func (builder *QueryBuilder) rejectUpdateOfReferencedParentKey( +type updateParentForeignKey struct { + childObjRef *plan.ObjectRef + childTableDef *plan.TableDef + fk *plan.ForeignKeyDef +} + +func (builder *QueryBuilder) appendUpdateParentForeignKeyChecks( bindCtx *BindContext, tableDef *plan.TableDef, alias string, + lastNodeID int32, + selectNodeTag int32, + oldColName2Idx map[string]int32, newColName2Idx map[string]int32, -) error { +) (int32, int32, error) { if tableDef == nil || len(tableDef.RefChildTbls) == 0 { - return nil + return lastNodeID, selectNodeTag, nil } parentColIDToName := make(map[uint64]string, len(tableDef.Cols)) @@ -217,6 +299,7 @@ func (builder *QueryBuilder) rejectUpdateOfReferencedParentKey( parentColIDToName[col.ColId] = col.Name } + affected := make([]updateParentForeignKey, 0) visited := make(map[uint64]struct{}, len(tableDef.RefChildTbls)) for _, childTableID := range tableDef.RefChildTbls { if childTableID == 0 { @@ -227,12 +310,12 @@ func (builder *QueryBuilder) rejectUpdateOfReferencedParentKey( } visited[childTableID] = struct{}{} - _, childTableDef, err := builder.compCtx.ResolveById(childTableID, bindCtx.snapshot) + childObjRef, childTableDef, err := builder.compCtx.ResolveById(childTableID, bindCtx.snapshot) if err != nil { - return err + return 0, 0, err } if childTableDef == nil { - return moerr.NewInternalErrorf( + return 0, 0, moerr.NewInternalErrorf( builder.GetContext(), "foreign-key child table %d not found", childTableID, @@ -247,12 +330,489 @@ func (builder *QueryBuilder) rejectUpdateOfReferencedParentKey( } for _, parentColID := range fk.ForeignCols { if _, ok := newColName2Idx[alias+"."+parentColIDToName[parentColID]]; ok { - return newLegacyUpdatePlannerRouteError( - updateRouteReasonForeignKey, - moerr.NewUnsupportedDML( - builder.GetContext(), - foreignKeyUnsupportedDMLCause, - ), + affected = append(affected, updateParentForeignKey{ + childObjRef: childObjRef, + childTableDef: childTableDef, + fk: fk, + }) + break + } + } + } + } + sort.SliceStable(affected, func(i, j int) bool { + if affected[i].childTableDef.TblId != affected[j].childTableDef.TblId { + return affected[i].childTableDef.TblId < affected[j].childTableDef.TblId + } + return affected[i].fk.Name < affected[j].fk.Name + }) + if len(affected) == 0 { + return lastNodeID, selectNodeTag, nil + } + // PREPARE may happen before the execution transaction exists. Keep a marker + // in the serialized plan so compile/run can enforce the actual transaction + // mode even when the binder could not observe it. + builder.qry.DetectSqls = append(builder.qry.DetectSqls, "UPDATE_PARENT_PLAN:") + if proc := builder.compCtx.GetProcess(); proc != nil { + if txnOp := proc.GetTxnOperator(); txnOp != nil && !txnOp.Txn().IsPessimistic() { + return 0, 0, newUpdatePlannerRouteError( + updatePlannerRejected, + updateRouteReasonForeignKey, + moerr.NewNotSupported( + builder.GetContext(), + "updating a referenced parent key in an optimistic transaction", + ), + ) + } + } + + lastNodeID, selectNodeTag, err := builder.appendUpdateParentKeyLocks( + bindCtx, + tableDef, + alias, + affected, + lastNodeID, + selectNodeTag, + oldColName2Idx, + newColName2Idx, + ) + if err != nil { + return 0, 0, err + } + + for _, affectedFK := range affected { + if affectedFK.childTableDef.TblId == tableDef.TblId { + switch affectedFK.fk.OnUpdate { + case plan.ForeignKeyDef_RESTRICT, + plan.ForeignKeyDef_NO_ACTION, + plan.ForeignKeyDef_SET_DEFAULT: + case plan.ForeignKeyDef_CASCADE, plan.ForeignKeyDef_SET_NULL: + return 0, 0, newLegacyUpdatePlannerRouteError( + updateRouteReasonForeignKey, + moerr.NewUnsupportedDML( + builder.GetContext(), + "self-referencing parent foreign key action", + ), + ) + } + } + switch affectedFK.fk.OnUpdate { + case plan.ForeignKeyDef_RESTRICT, + plan.ForeignKeyDef_NO_ACTION, + plan.ForeignKeyDef_SET_DEFAULT: + var err error + lastNodeID, selectNodeTag, err = builder.appendUpdateParentRestrictCheck( + bindCtx, + tableDef, + alias, + affectedFK, + lastNodeID, + selectNodeTag, + oldColName2Idx, + newColName2Idx, + ) + if err != nil { + return 0, 0, err + } + case plan.ForeignKeyDef_CASCADE, plan.ForeignKeyDef_SET_NULL: + default: + return 0, 0, moerr.NewInternalErrorf( + builder.GetContext(), + "unsupported foreign key ON UPDATE action %s", + affectedFK.fk.OnUpdate.String(), + ) + } + } + + mutations := make([]updateParentForeignKey, 0, len(affected)) + for _, affectedFK := range affected { + if affectedFK.fk.OnUpdate == plan.ForeignKeyDef_CASCADE || + affectedFK.fk.OnUpdate == plan.ForeignKeyDef_SET_NULL { + mutations = append(mutations, affectedFK) + } + } + if len(mutations) == 0 { + return lastNodeID, selectNodeTag, nil + } + + mutationByChild := make(map[uint64]struct{}, len(mutations)) + for _, mutation := range mutations { + if _, exists := mutationByChild[mutation.childTableDef.TblId]; exists { + return 0, 0, newLegacyUpdatePlannerRouteError( + updateRouteReasonForeignKey, + moerr.NewUnsupportedDML( + builder.GetContext(), + "multiple parent foreign key actions targeting the same child table", + ), + ) + } + mutationByChild[mutation.childTableDef.TblId] = struct{}{} + if err := builder.validateModernUpdateParentMutation(bindCtx, tableDef, mutation); err != nil { + return 0, 0, err + } + } + + sourceSinkID := appendSinkNodeWithTag(builder, bindCtx, lastNodeID, selectNodeTag) + sourceStep := builder.appendStep(sourceSinkID) + for _, mutation := range mutations { + if err := builder.appendUpdateParentMutation( + bindCtx, + tableDef, + alias, + mutation, + sourceStep, + selectNodeTag, + oldColName2Idx, + newColName2Idx, + ); err != nil { + return 0, 0, err + } + } + lastNodeID = builder.appendTaggedSinkScan(bindCtx, sourceStep, selectNodeTag) + return lastNodeID, selectNodeTag, nil +} + +func (builder *QueryBuilder) appendUpdateParentKeyLocks( + bindCtx *BindContext, + parentTableDef *plan.TableDef, + parentAlias string, + affected []updateParentForeignKey, + lastNodeID int32, + selectNodeTag int32, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, +) (int32, int32, error) { + parentObjRef, resolvedParent, err := builder.compCtx.ResolveById(parentTableDef.TblId, bindCtx.snapshot) + if err != nil { + return 0, 0, err + } + if resolvedParent == nil { + return 0, 0, moerr.NewInternalErrorf( + builder.GetContext(), "foreign-key parent table %d not found", parentTableDef.TblId) + } + + rowProject := getProjectionByLastNodeWithTag(builder, lastNodeID, selectNodeTag) + lockTag := builder.genNewBindTag() + lockProject := append([]*plan.Expr(nil), rowProject...) + lockTargets := make([]*plan.LockTarget, 0, len(affected)*2) + tableLocked := false + validIndexes, _ := getValidIndexes(parentTableDef) + + for _, affectedFK := range affected { + referencedNames, buildErr := updateParentColNames( + builder.GetContext(), parentTableDef, affectedFK.fk.ForeignCols) + if buildErr != nil { + return 0, 0, buildErr + } + + lockTableDef := parentTableDef + lockObjRef := parentObjRef + lockTable := false + var matchedIndex *plan.IndexDef + var pkeyNames []string + if parentTableDef.Pkey != nil { + pkeyNames = parentTableDef.Pkey.Names + if len(pkeyNames) == 0 && parentTableDef.Pkey.PkeyColName != "" { + pkeyNames = []string{parentTableDef.Pkey.PkeyColName} + } + } + if !updateForeignKeyPartsEqual(pkeyNames, referencedNames) { + for _, idxDef := range validIndexes { + if idxDef.Unique && updateForeignKeyPartsEqual(idxDef.Parts, referencedNames) { + matchedIndex = idxDef + break + } + } + if matchedIndex == nil { + lockTable = true + } else { + lockObjRef, lockTableDef, buildErr = builder.compCtx.ResolveIndexTableByRef( + parentObjRef, matchedIndex.IndexTableName, bindCtx.snapshot) + if buildErr != nil { + return 0, 0, buildErr + } + } + } + if lockTable && tableLocked { + continue + } + + for _, useNew := range []bool{false, true} { + keyParts := make([]*plan.Expr, len(referencedNames)) + for i, colName := range referencedNames { + pos := oldColName2Idx[parentAlias+"."+colName] + if useNew { + if newPos, ok := newColName2Idx[parentAlias+"."+colName]; ok { + pos = newPos + } + } + keyParts[i] = &plan.Expr{ + Typ: rowProject[pos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, ColPos: pos, + }}, + } + } + + lockExpr := keyParts[0] + if !lockTable { + if matchedIndex != nil { + prefixLengths, prefixErr := catalog.IndexPrefixLengthsFromParamsWithError( + matchedIndex.IndexAlgoParams) + if prefixErr != nil { + return 0, 0, prefixErr + } + for i := range keyParts { + keyParts[i], buildErr = builder.makeIndexPartExprFromInputExpr( + keyParts[i], referencedNames[i], prefixLengths) + if buildErr != nil { + return 0, 0, buildErr + } + } + } + if len(keyParts) > 1 || (matchedIndex != nil && indexTableStoresSerializedKey(matchedIndex)) { + lockExpr, buildErr = BindFuncExprImplByPlanExpr( + builder.GetContext(), "serial", keyParts) + if buildErr != nil { + return 0, 0, buildErr + } + } + } + lockProject = append(lockProject, lockExpr) + _, lockTyp := getPkPos(lockTableDef, false) + lockTargets = append(lockTargets, &plan.LockTarget{ + TableId: lockTableDef.TblId, ObjRef: lockObjRef, + PrimaryColIdxInBat: int32(len(lockProject) - 1), PrimaryColRelPos: lockTag, + PrimaryColTyp: lockTyp, Mode: lockpb.LockMode_Exclusive, LockTable: lockTable, + }) + if lockTable { + tableLocked = true + break + } + } + } + sortForeignKeyLockTargets(lockTargets, map[uint64]struct{}{parentTableDef.TblId: {}}) + + lockInputID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, Children: []int32{lastNodeID}, + ProjectList: lockProject, BindingTags: []int32{lockTag}, + }, bindCtx) + lockOutput := getProjectionByLastNodeWithTag(builder, lockInputID, lockTag) + lockNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_LOCK_OP, Children: []int32{lockInputID}, + TableDef: resolvedParent, LockTargets: lockTargets, + }, bindCtx) + lockedNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, Children: []int32{lockNodeID}, + ProjectList: append([]*plan.Expr(nil), lockOutput[:len(rowProject)]...), + BindingTags: []int32{selectNodeTag}, + }, bindCtx) + lockedSinkID := appendSinkNodeWithTag(builder, bindCtx, lockedNodeID, selectNodeTag) + lockedStep := builder.appendStep(lockedSinkID) + return builder.appendTaggedSinkScan(bindCtx, lockedStep, selectNodeTag), selectNodeTag, nil +} + +func updateParentColNames( + ctx context.Context, + tableDef *plan.TableDef, + colIDs []uint64, +) ([]string, error) { + idToName := make(map[uint64]string, len(tableDef.Cols)) + for _, col := range tableDef.Cols { + idToName[col.ColId] = col.Name + } + names := make([]string, len(colIDs)) + for i, colID := range colIDs { + name, ok := idToName[colID] + if !ok { + return nil, moerr.NewInternalErrorf(ctx, "foreign-key parent column %d not found", colID) + } + names[i] = name + } + return names, nil +} + +func updateForeignKeyPartsEqual(left, right []string) bool { + if len(left) != len(right) { + return false + } + for i := range left { + if catalog.ResolveAlias(left[i]) != catalog.ResolveAlias(right[i]) { + return false + } + } + return true +} + +func sortForeignKeyLockTargets(lockTargets []*plan.LockTarget, baseTableIDs map[uint64]struct{}) { + sort.SliceStable(lockTargets, func(i, j int) bool { + _, leftBase := baseTableIDs[lockTargets[i].TableId] + _, rightBase := baseTableIDs[lockTargets[j].TableId] + if leftBase != rightBase { + return leftBase + } + leftName, rightName := "", "" + if lockTargets[i].ObjRef != nil { + leftName = lockTargets[i].ObjRef.ObjName + } + if lockTargets[j].ObjRef != nil { + rightName = lockTargets[j].ObjRef.ObjName + } + if leftName != rightName { + return leftName < rightName + } + if lockTargets[i].TableId != lockTargets[j].TableId { + return lockTargets[i].TableId < lockTargets[j].TableId + } + if lockTargets[i].LockTable != lockTargets[j].LockTable { + return !lockTargets[i].LockTable + } + if lockTargets[i].PrimaryColIdxInBat != lockTargets[j].PrimaryColIdxInBat { + return lockTargets[i].PrimaryColIdxInBat < lockTargets[j].PrimaryColIdxInBat + } + return lockTargets[i].PrimaryColRelPos < lockTargets[j].PrimaryColRelPos + }) +} + +func updateParentReferenceIsUnique( + ctx context.Context, + parentTableDef *plan.TableDef, + foreignCols []uint64, +) (bool, error) { + referencedNames, err := updateParentColNames(ctx, parentTableDef, foreignCols) + if err != nil { + return false, err + } + if parentTableDef.Pkey != nil { + pkeyNames := parentTableDef.Pkey.Names + if len(pkeyNames) == 0 && parentTableDef.Pkey.PkeyColName != "" { + pkeyNames = []string{parentTableDef.Pkey.PkeyColName} + } + if updateForeignKeyPartsEqual(pkeyNames, referencedNames) { + return true, nil + } + } + validIndexes, _ := getValidIndexes(parentTableDef) + for _, idxDef := range validIndexes { + if idxDef.Unique && updateForeignKeyPartsEqual(idxDef.Parts, referencedNames) { + return true, nil + } + } + return false, nil +} + +func (builder *QueryBuilder) validateModernUpdateParentMutation( + bindCtx *BindContext, + parentTableDef *plan.TableDef, + affectedFK updateParentForeignKey, +) error { + childTableDef := affectedFK.childTableDef + ensureName2ColIndexForReplace(childTableDef) + parentColByID := make(map[uint64]*plan.ColDef, len(parentTableDef.Cols)) + for _, col := range parentTableDef.Cols { + parentColByID[col.ColId] = col + } + for _, parentColID := range affectedFK.fk.ForeignCols { + if col := parentColByID[parentColID]; col != nil && col.Typ.AutoIncr { + return newLegacyUpdatePlannerRouteError( + updateRouteReasonForeignKey, + moerr.NewUnsupportedDML( + builder.GetContext(), + "parent foreign key action changing auto-increment referenced key", + ), + ) + } + } + if err := builder.validateModernUpdateParentRowClosure(parentTableDef, affectedFK); err != nil { + return err + } + if childTableDef.TblId == parentTableDef.TblId { + return newLegacyUpdatePlannerRouteError( + updateRouteReasonForeignKey, + moerr.NewUnsupportedDML(builder.GetContext(), "self-referencing parent foreign key action"), + ) + } + _, hasIrregularIndex := getValidIndexes(childTableDef) + if hasIrregularIndex { + return moerr.NewNotSupported( + builder.GetContext(), + "parent foreign key action on child table with irregular indexes", + ) + } + if childTableDef.Partition != nil { + return moerr.NewNotSupported( + builder.GetContext(), + "parent foreign key action on partitioned child table", + ) + } + + childColIDToName := make(map[uint64]string, len(childTableDef.Cols)) + for _, col := range childTableDef.Cols { + childColIDToName[col.ColId] = col.Name + } + primaryNames := make(map[string]struct{}, len(childTableDef.Pkey.Names)+1) + primaryNames[childTableDef.Pkey.PkeyColName] = struct{}{} + for _, name := range childTableDef.Pkey.Names { + primaryNames[name] = struct{}{} + } + for _, childColID := range affectedFK.fk.Cols { + if _, ok := primaryNames[childColIDToName[childColID]]; ok { + return newLegacyUpdatePlannerRouteError( + updateRouteReasonForeignKey, + moerr.NewUnsupportedDML( + builder.GetContext(), + "parent foreign key action changing child primary key", + ), + ) + } + } + + updatedChildCols := make(map[uint64]struct{}, len(affectedFK.fk.Cols)) + for _, childColID := range affectedFK.fk.Cols { + updatedChildCols[childColID] = struct{}{} + } + for _, col := range childTableDef.Cols { + if col.GeneratedCol != nil { + updatedChildCols[col.ColId] = struct{}{} + } + } + for _, outgoingFK := range childTableDef.Fkeys { + if outgoingFK == affectedFK.fk { + continue + } + for _, childColID := range outgoingFK.Cols { + if _, changed := updatedChildCols[childColID]; changed { + return moerr.NewNotSupported( + builder.GetContext(), + "parent foreign key action changing child column constrained by another foreign key", + ) + } + } + } + visited := make(map[uint64]struct{}, len(childTableDef.RefChildTbls)) + for _, grandchildID := range childTableDef.RefChildTbls { + if grandchildID == 0 { + grandchildID = childTableDef.TblId + } + if _, ok := visited[grandchildID]; ok { + continue + } + visited[grandchildID] = struct{}{} + _, grandchildDef, err := builder.compCtx.ResolveById(grandchildID, bindCtx.snapshot) + if err != nil { + return err + } + for _, fk := range grandchildDef.Fkeys { + referencesChild := fk.ForeignTbl == childTableDef.TblId || + (fk.ForeignTbl == 0 && grandchildDef.TblId == childTableDef.TblId) + if !referencesChild { + continue + } + for _, referencedColID := range fk.ForeignCols { + if _, changed := updatedChildCols[referencedColID]; changed { + return moerr.NewNotSupported( + builder.GetContext(), + "recursive parent foreign key action graph", ) } } @@ -261,6 +821,900 @@ func (builder *QueryBuilder) rejectUpdateOfReferencedParentKey( return nil } +func (builder *QueryBuilder) validateModernUpdateParentRowClosure( + parentTableDef *plan.TableDef, + affectedFK updateParentForeignKey, +) error { + childTableDef := affectedFK.childTableDef + childColByID := make(map[uint64]*plan.ColDef, len(childTableDef.Cols)) + parentColByID := make(map[uint64]*plan.ColDef, len(parentTableDef.Cols)) + updatedChildNames := make(map[string]struct{}, len(affectedFK.fk.Cols)) + for _, col := range childTableDef.Cols { + childColByID[col.ColId] = col + if col.GeneratedCol != nil || col.OnUpdate != nil { + return builder.newUnsupportedUpdateParentRowClosureError() + } + } + for _, col := range parentTableDef.Cols { + parentColByID[col.ColId] = col + } + for i, childColID := range affectedFK.fk.Cols { + childCol := childColByID[childColID] + if childCol == nil || i >= len(affectedFK.fk.ForeignCols) { + return moerr.NewInternalError(builder.GetContext(), "invalid parent foreign key action columns") + } + updatedChildNames[childCol.Name] = struct{}{} + if affectedFK.fk.OnUpdate != plan.ForeignKeyDef_CASCADE { + continue + } + parentCol := parentColByID[affectedFK.fk.ForeignCols[i]] + if parentCol == nil { + return moerr.NewInternalError(builder.GetContext(), "invalid parent foreign key action columns") + } + if parentCol.Typ.Id != childCol.Typ.Id || + parentCol.Typ.Width != childCol.Typ.Width || + parentCol.Typ.Scale != childCol.Typ.Scale || + parentCol.Typ.Enumvalues != childCol.Typ.Enumvalues { + return builder.newUnsupportedUpdateParentRowClosureError() + } + } + for _, idxDef := range childTableDef.Indexes { + if !idxDef.Unique { + continue + } + for _, part := range idxDef.Parts { + if _, changed := updatedChildNames[catalog.ResolveAlias(part)]; changed { + return builder.newUnsupportedUpdateParentRowClosureError() + } + } + } + if childTableDef.ClusterBy != nil && + planutil.JudgeIsCompositeClusterByColumn(childTableDef.ClusterBy.Name) { + for _, colName := range planutil.SplitCompositeClusterByColumnName(childTableDef.ClusterBy.Name) { + if _, changed := updatedChildNames[colName]; changed { + return builder.newUnsupportedUpdateParentRowClosureError() + } + } + } + return nil +} + +func (builder *QueryBuilder) newUnsupportedUpdateParentRowClosureError() error { + return newUpdatePlannerRouteError( + updatePlannerRejected, + updateRouteReasonForeignKey, + moerr.NewNotSupported( + builder.GetContext(), + "parent foreign key action requires complete child update row closure", + ), + ) +} + +func (builder *QueryBuilder) appendUpdateParentMutation( + bindCtx *BindContext, + parentTableDef *plan.TableDef, + parentAlias string, + affectedFK updateParentForeignKey, + sourceStep int32, + sourceTag int32, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, +) error { + parentNodeID := builder.appendTaggedSinkScan(bindCtx, sourceStep, sourceTag) + parentNode := builder.qry.Nodes[parentNodeID] + unchanged, err := builder.buildUpdateReferencedKeyUnchangedExpr( + parentTableDef, + affectedFK.fk, + parentAlias, + sourceTag, + oldColName2Idx, + newColName2Idx, + parentNode, + ) + if err != nil { + return err + } + if unchanged != nil { + changed, bindErr := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "not", + []*plan.Expr{unchanged}, + ) + if bindErr != nil { + return bindErr + } + parentNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_FILTER, + Children: []int32{parentNodeID}, + FilterList: []*plan.Expr{changed}, + }, bindCtx) + } + parentColIDToName := make(map[uint64]string, len(parentTableDef.Cols)) + for _, col := range parentTableDef.Cols { + parentColIDToName[col.ColId] = col.Name + } + + uniqueReference, err := updateParentReferenceIsUnique( + builder.GetContext(), parentTableDef, affectedFK.fk.ForeignCols) + if err != nil { + return err + } + childTableDef := affectedFK.childTableDef + childTag := builder.genNewBindTag() + builder.addNameByColRef(childTag, childTableDef) + childNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_TABLE_SCAN, + TableDef: childTableDef, + ObjRef: affectedFK.childObjRef, + BindingTags: []int32{childTag}, + ScanSnapshot: bindCtx.snapshot, + }, bindCtx) + + childColIDToPos := make(map[uint64]int32, len(childTableDef.Cols)) + for i, col := range childTableDef.Cols { + childColIDToPos[col.ColId] = int32(i) + } + + joinPreds := make([]*plan.Expr, len(affectedFK.fk.Cols)) + newChildExprs := make(map[int32]*plan.Expr, len(affectedFK.fk.Cols)) + for i, childColID := range affectedFK.fk.Cols { + parentColName := parentColIDToName[affectedFK.fk.ForeignCols[i]] + oldParentPos := oldColName2Idx[parentAlias+"."+parentColName] + newParentPos := oldParentPos + if pos, ok := newColName2Idx[parentAlias+"."+parentColName]; ok { + newParentPos = pos + } + childPos := childColIDToPos[childColID] + oldParentExpr := &plan.Expr{ + Typ: parentNode.ProjectList[oldParentPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: sourceTag, + ColPos: oldParentPos, + }}, + } + childExpr := &plan.Expr{ + Typ: childTableDef.Cols[childPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: childTag, + ColPos: childPos, + }}, + } + joinPreds[i], err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "=", + []*plan.Expr{oldParentExpr, childExpr}, + ) + if err != nil { + return err + } + + switch affectedFK.fk.OnUpdate { + case plan.ForeignKeyDef_CASCADE: + newChildExprs[childPos] = &plan.Expr{ + Typ: childTableDef.Cols[childPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: sourceTag, + ColPos: newParentPos, + }}, + } + case plan.ForeignKeyDef_SET_NULL: + col := childTableDef.Cols[childPos] + if col.Default != nil && !col.Default.NullAbility { + return moerr.NewConstraintViolation( + builder.GetContext(), + fmt.Sprintf("Column '%s' cannot be null", col.Name), + ) + } + newChildExprs[childPos] = &plan.Expr{ + Typ: col.Typ, + Expr: &plan.Expr_Lit{Lit: &Const{Isnull: true}}, + } + } + } + + joinNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_JOIN, + Children: []int32{parentNodeID, childNodeID}, + JoinType: plan.Node_INNER, + OnList: joinPreds, + }, bindCtx) + if !uniqueReference { + mappingTag := builder.genNewBindTag() + mappingProjection := make([]*plan.Expr, 0, len(childTableDef.Cols)+len(newChildExprs)) + for i, col := range childTableDef.Cols { + mappingProjection = append(mappingProjection, &plan.Expr{ + Typ: col.Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: childTag, + ColPos: int32(i), + }}, + }) + } + mappingNewChildExprs := make(map[int32]*plan.Expr, len(newChildExprs)) + for _, childColID := range affectedFK.fk.Cols { + childPos := childColIDToPos[childColID] + newPos := int32(len(mappingProjection)) + mappingProjection = append(mappingProjection, newChildExprs[childPos]) + mappingNewChildExprs[childPos] = &plan.Expr{ + Typ: childTableDef.Cols[childPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: mappingTag, + ColPos: newPos, + }}, + } + } + joinNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{joinNodeID}, + ProjectList: mappingProjection, + BindingTags: []int32{mappingTag}, + }, bindCtx) + childTag = mappingTag + newChildExprs = mappingNewChildExprs + + childRowIDPos := childTableDef.Name2ColIndex[catalog.Row_ID] + childRowIDExpr := &plan.Expr{ + Typ: childTableDef.Cols[childRowIDPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: childTag, + ColPos: childRowIDPos, + }}, + } + mappingIdentity := []*plan.Expr{childRowIDExpr} + if affectedFK.fk.OnUpdate == plan.ForeignKeyDef_CASCADE { + for _, childColID := range affectedFK.fk.Cols { + mappingIdentity = append(mappingIdentity, newChildExprs[childColIDToPos[childColID]]) + } + } + joinNodeID, err = builder.appendRowNumberMappingGuardNode( + bindCtx, joinNodeID, mappingIdentity, "", "") + if err != nil { + return err + } + if affectedFK.fk.OnUpdate == plan.ForeignKeyDef_CASCADE { + joinNodeID, err = builder.appendRowNumberMappingGuardNode( + bindCtx, + joinNodeID, + []*plan.Expr{childRowIDExpr}, + "parent foreign key action has an ambiguous non-unique referenced-key mapping", + foreignKeyAmbiguousMappingAssert, + ) + if err != nil { + return err + } + } + } + + type mutationIndex struct { + def *plan.IndexDef + objRef *plan.ObjectRef + tableDef *plan.TableDef + tag int32 + } + validIndexes, _ := getValidIndexes(childTableDef) + indexes := make([]mutationIndex, 0, len(validIndexes)) + for _, idxDef := range validIndexes { + indexAffected := false + for _, part := range idxDef.Parts { + colPos, ok := childTableDef.Name2ColIndex[catalog.ResolveAlias(part)] + if ok { + _, indexAffected = newChildExprs[colPos] + } + if indexAffected { + break + } + } + if !indexAffected { + continue + } + idxObjRef, idxTableDef, resolveErr := builder.compCtx.ResolveIndexTableByRef( + affectedFK.childObjRef, + idxDef.IndexTableName, + bindCtx.snapshot, + ) + if resolveErr != nil { + return resolveErr + } + ensureName2ColIndexForReplace(idxTableDef) + idxTag := builder.genNewBindTag() + builder.addNameByColRef(idxTag, idxTableDef) + idxScanID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_TABLE_SCAN, + TableDef: idxTableDef, + ObjRef: idxObjRef, + BindingTags: []int32{idxTag}, + ScanSnapshot: bindCtx.snapshot, + }, bindCtx) + + oldKeyExpr, buildErr := builder.buildUpdateMutationIndexKey( + childTableDef, + idxDef, + childTag, + nil, + ) + if buildErr != nil { + return buildErr + } + lookupName := indexLookupColumnName(idxDef) + lookupPos := idxTableDef.Name2ColIndex[lookupName] + storedKeyExpr := &plan.Expr{ + Typ: idxTableDef.Cols[lookupPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: idxTag, + ColPos: lookupPos, + }}, + } + indexMatch, buildErr := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "=", + []*plan.Expr{oldKeyExpr, storedKeyExpr}, + ) + if buildErr != nil { + return buildErr + } + joinType := plan.Node_INNER + if idxDef.Unique { + joinType = plan.Node_LEFT + } + joinNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_JOIN, + Children: []int32{joinNodeID, idxScanID}, + JoinType: joinType, + OnList: []*plan.Expr{indexMatch}, + }, bindCtx) + indexes = append(indexes, mutationIndex{ + def: idxDef, + objRef: idxObjRef, + tableDef: idxTableDef, + tag: idxTag, + }) + } + + actionTag := builder.genNewBindTag() + actionProjection := make([]*plan.Expr, len(childTableDef.Cols)) + for i, col := range childTableDef.Cols { + if newExpr, ok := newChildExprs[int32(i)]; ok { + actionProjection[i] = newExpr + continue + } + actionProjection[i] = &plan.Expr{ + Typ: col.Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: childTag, + ColPos: int32(i), + }}, + } + } + finalReplacements := make(map[int32]*plan.Expr, len(newChildExprs)) + for pos, expr := range newChildExprs { + finalReplacements[pos] = expr + } + + type mutationIndexPositions struct { + oldRowID int32 + oldKey int32 + newKey int32 + } + indexPositions := make([]mutationIndexPositions, len(indexes)) + for i, idx := range indexes { + oldRowIDPos := idx.tableDef.Name2ColIndex[catalog.Row_ID] + oldKeyPos := idx.tableDef.Name2ColIndex[indexLookupColumnName(idx.def)] + indexPositions[i].oldRowID = int32(len(actionProjection)) + actionProjection = append(actionProjection, &plan.Expr{ + Typ: idx.tableDef.Cols[oldRowIDPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: idx.tag, + ColPos: oldRowIDPos, + }}, + }) + indexPositions[i].oldKey = int32(len(actionProjection)) + actionProjection = append(actionProjection, &plan.Expr{ + Typ: idx.tableDef.Cols[oldKeyPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: idx.tag, + ColPos: oldKeyPos, + }}, + }) + newKeyExpr, buildErr := builder.buildUpdateMutationIndexKey( + childTableDef, + idx.def, + childTag, + finalReplacements, + ) + if buildErr != nil { + return buildErr + } + indexPositions[i].newKey = int32(len(actionProjection)) + actionProjection = append(actionProjection, newKeyExpr) + } + actionNodeID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{joinNodeID}, + ProjectList: actionProjection, + BindingTags: []int32{actionTag}, + }, bindCtx) + + rowIDPos := childTableDef.Name2ColIndex[catalog.Row_ID] + pkPos := childTableDef.Name2ColIndex[childTableDef.Pkey.PkeyColName] + insertCols := make([]plan.ColRef, 0, len(childTableDef.Cols)-1) + for i, col := range childTableDef.Cols { + if col.Name == catalog.Row_ID { + continue + } + insertCols = append(insertCols, plan.ColRef{RelPos: actionTag, ColPos: int32(i)}) + } + lockTarget := &plan.LockTarget{ + TableId: childTableDef.TblId, + ObjRef: affectedFK.childObjRef, + PrimaryColIdxInBat: pkPos, + PrimaryColRelPos: actionTag, + PrimaryColTyp: actionProjection[pkPos].Typ, + } + lockTargets := []*plan.LockTarget{lockTarget} + updateCtxList := []*plan.UpdateCtx{{ + ObjRef: affectedFK.childObjRef, + TableDef: childTableDef, + InsertCols: insertCols, + IgnoreAffectedRows: true, + DeleteCols: []plan.ColRef{ + {RelPos: actionTag, ColPos: rowIDPos}, + {RelPos: actionTag, ColPos: pkPos}, + }, + }} + for i, idx := range indexes { + positions := indexPositions[i] + updateCtxList = append(updateCtxList, &plan.UpdateCtx{ + ObjRef: idx.objRef, + TableDef: idx.tableDef, + IgnoreAffectedRows: true, + InsertCols: []plan.ColRef{ + {RelPos: actionTag, ColPos: positions.newKey}, + {RelPos: actionTag, ColPos: pkPos}, + }, + DeleteCols: []plan.ColRef{ + {RelPos: actionTag, ColPos: positions.oldRowID}, + {RelPos: actionTag, ColPos: positions.oldKey}, + }, + }) + if idx.def.Unique { + lockTargets = append(lockTargets, + &plan.LockTarget{ + TableId: idx.tableDef.TblId, + ObjRef: idx.objRef, + PrimaryColIdxInBat: positions.oldKey, + PrimaryColRelPos: actionTag, + PrimaryColTyp: actionProjection[positions.oldKey].Typ, + }, + &plan.LockTarget{ + TableId: idx.tableDef.TblId, + ObjRef: idx.objRef, + PrimaryColIdxInBat: positions.newKey, + PrimaryColRelPos: actionTag, + PrimaryColTyp: actionProjection[positions.newKey].Typ, + }, + ) + } + } + sortForeignKeyLockTargets(lockTargets, map[uint64]struct{}{childTableDef.TblId: {}}) + actionNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_LOCK_OP, + Children: []int32{actionNodeID}, + TableDef: childTableDef, + BindingTags: []int32{actionTag}, + LockTargets: lockTargets, + }, bindCtx) + actionNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_MULTI_UPDATE, + Children: []int32{actionNodeID}, + BindingTags: []int32{builder.genNewBindTag()}, + UpdateCtxList: updateCtxList, + }, bindCtx) + builder.appendStep(actionNodeID) + builder.qry.HasForeignKeyAction = true + return nil +} + +func (builder *QueryBuilder) appendRowNumberMappingGuardNode( + bindCtx *BindContext, + lastNodeID int32, + partitionByExprs []*plan.Expr, + duplicateErrorMessage string, + duplicateErrorType string, +) (int32, error) { + if len(partitionByExprs) == 0 { + return lastNodeID, nil + } + + partitionBy := make([]*plan.OrderBySpec, 0, len(partitionByExprs)) + for _, expr := range partitionByExprs { + partitionBy = append(partitionBy, &plan.OrderBySpec{ + Expr: expr, + Flag: plan.OrderBySpec_INTERNAL, + }) + } + lastNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_PARTITION, + Children: []int32{lastNodeID}, + OrderBy: partitionBy, + }, bindCtx) + + rowNumberFunc, err := BindFuncExprImplByPlanExpr(builder.GetContext(), "row_number", nil) + if err != nil { + return 0, err + } + windowTag := builder.genNewBindTag() + lastNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_WINDOW, + Children: []int32{lastNodeID}, + WinSpecList: []*plan.Expr{{ + Typ: rowNumberFunc.Typ, + Expr: &plan.Expr_W{W: &plan.WindowSpec{ + WindowFunc: rowNumberFunc, + Name: "row_number", + PartitionBy: partitionByExprs, + Frame: &plan.FrameClause{ + Type: plan.FrameClause_ROWS, + Start: &plan.FrameBound{ + Type: plan.FrameBound_PRECEDING, + UnBounded: true, + }, + End: &plan.FrameBound{ + Type: plan.FrameBound_FOLLOWING, + UnBounded: true, + }, + }, + }}, + }}, + WindowIdx: 0, + BindingTags: []int32{windowTag}, + }, bindCtx) + + rowNumberCol := &plan.Expr{ + Typ: rowNumberFunc.Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: windowTag, + ColPos: 0, + Name: "__mo_fk_mapping_row_number", + }}, + } + keepFirstRowExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), "=", []*plan.Expr{rowNumberCol, makePlan2Int64ConstExprWithType(1)}) + if err != nil { + return 0, err + } + guardExpr := keepFirstRowExpr + if duplicateErrorType != "" { + guardExpr, err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "assert", + []*plan.Expr{ + keepFirstRowExpr, + makePlan2StringConstExprWithType(duplicateErrorMessage), + makePlan2StringConstExprWithType(duplicateErrorType), + }, + ) + if err != nil { + return 0, err + } + } + return builder.appendNode(&plan.Node{ + NodeType: plan.Node_FILTER, + Children: []int32{lastNodeID}, + FilterList: []*plan.Expr{guardExpr}, + }, bindCtx), nil +} + +func (builder *QueryBuilder) buildUpdateMutationIndexKey( + tableDef *plan.TableDef, + idxDef *plan.IndexDef, + tableTag int32, + replacements map[int32]*plan.Expr, +) (*plan.Expr, error) { + if isSpatialIndexDef(idxDef) { + pkPos := tableDef.Name2ColIndex[tableDef.Pkey.PkeyColName] + if replacement, ok := replacements[pkPos]; ok { + return DeepCopyExpr(replacement), nil + } + return &plan.Expr{ + Typ: tableDef.Cols[pkPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: tableTag, + ColPos: pkPos, + }}, + }, nil + } + + prefixLengths, err := catalog.IndexPrefixLengthsFromParamsWithError(idxDef.IndexAlgoParams) + if err != nil { + return nil, err + } + args := make([]*plan.Expr, len(idxDef.Parts)) + for i, part := range idxDef.Parts { + colName := catalog.ResolveAlias(part) + colPos := tableDef.Name2ColIndex[colName] + inputExpr, ok := replacements[colPos] + if ok { + inputExpr = DeepCopyExpr(inputExpr) + } else { + inputExpr = &plan.Expr{ + Typ: tableDef.Cols[colPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: tableTag, + ColPos: colPos, + }}, + } + } + args[i], err = builder.makeIndexPartExprFromInputExpr( + inputExpr, + colName, + prefixLengths, + ) + if err != nil { + return nil, err + } + } + if !indexTableStoresSerializedKey(idxDef) { + return args[0], nil + } + funcName := "serial" + if !idxDef.Unique { + funcName = "serial_full" + } + return BindFuncExprImplByPlanExpr(builder.GetContext(), funcName, args) +} + +func (builder *QueryBuilder) appendUpdateParentRestrictCheck( + bindCtx *BindContext, + parentTableDef *plan.TableDef, + parentAlias string, + affectedFK updateParentForeignKey, + lastNodeID int32, + selectNodeTag int32, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, +) (int32, int32, error) { + sourceNode := builder.updateInputProjectNode(lastNodeID) + sourceTypes := make([]plan.Type, len(sourceNode.ProjectList)) + for i, expr := range sourceNode.ProjectList { + sourceTypes[i] = expr.Typ + } + + parentColIDToName := make(map[uint64]string, len(parentTableDef.Cols)) + for _, col := range parentTableDef.Cols { + parentColIDToName[col.ColId] = col.Name + } + childColIDToPos := make(map[uint64]int32, len(affectedFK.childTableDef.Cols)) + for i, col := range affectedFK.childTableDef.Cols { + childColIDToPos[col.ColId] = int32(i) + } + + childTag := builder.genNewBindTag() + builder.addNameByColRef(childTag, affectedFK.childTableDef) + childScanID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_TABLE_SCAN, + TableDef: affectedFK.childTableDef, + ObjRef: affectedFK.childObjRef, + BindingTags: []int32{childTag}, + ScanSnapshot: bindCtx.snapshot, + }, bindCtx) + + joinPreds := make([]*plan.Expr, len(affectedFK.fk.Cols)) + for i, childColID := range affectedFK.fk.Cols { + parentColName := parentColIDToName[affectedFK.fk.ForeignCols[i]] + parentPos := oldColName2Idx[parentAlias+"."+parentColName] + childPos := childColIDToPos[childColID] + parentExpr := &plan.Expr{ + Typ: sourceNode.ProjectList[parentPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: parentPos, + }}, + } + childExpr := &plan.Expr{ + Typ: affectedFK.childTableDef.Cols[childPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: childTag, + ColPos: childPos, + }}, + } + var err error + joinPreds[i], err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "=", + []*plan.Expr{parentExpr, childExpr}, + ) + if err != nil { + return 0, 0, err + } + } + + markNodeID, markExpr, err := builder.insertMarkJoin( + lastNodeID, + childScanID, + joinPreds, + nil, + false, + bindCtx, + ) + if err != nil { + return 0, 0, err + } + + unchanged, err := builder.buildUpdateReferencedKeyUnchangedExpr( + parentTableDef, + affectedFK.fk, + parentAlias, + selectNodeTag, + oldColName2Idx, + newColName2Idx, + sourceNode, + ) + if err != nil { + return 0, 0, err + } + noChild, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "not", + []*plan.Expr{markExpr}, + ) + if err != nil { + return 0, 0, err + } + ok := noChild + if unchanged != nil { + ok, err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "or", + []*plan.Expr{unchanged, noChild}, + ) + if err != nil { + return 0, 0, err + } + } + if affectedFK.childTableDef.TblId == parentTableDef.TblId { + var newKeyHasNull *plan.Expr + for _, parentColID := range affectedFK.fk.ForeignCols { + parentColName := parentColIDToName[parentColID] + parentPos := newColName2Idx[parentAlias+"."+parentColName] + newKeyExpr := &plan.Expr{ + Typ: sourceNode.ProjectList[parentPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: parentPos, + }}, + } + isNull, buildErr := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "isnull", + []*plan.Expr{newKeyExpr}, + ) + if buildErr != nil { + return 0, 0, buildErr + } + if newKeyHasNull == nil { + newKeyHasNull = isNull + continue + } + newKeyHasNull, buildErr = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "or", + []*plan.Expr{newKeyHasNull, isNull}, + ) + if buildErr != nil { + return 0, 0, buildErr + } + } + if newKeyHasNull != nil { + ok, err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "or", + []*plan.Expr{ok, newKeyHasNull}, + ) + if err != nil { + return 0, 0, err + } + } + } + assertExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "assert", + []*plan.Expr{ + ok, + makePlan2StringConstExprWithType( + "Cannot delete or update a parent row: a foreign key constraint fails", + ), + makePlan2StringConstExprWithType(foreignKeyRowIsReferencedAssert), + }, + ) + if err != nil { + return 0, 0, err + } + lastNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_FILTER, + Children: []int32{markNodeID}, + FilterList: []*plan.Expr{assertExpr}, + }, bindCtx) + + validatedTag := builder.genNewBindTag() + projectList := make([]*plan.Expr, len(sourceTypes)) + for i, typ := range sourceTypes { + projectList[i] = &plan.Expr{ + Typ: typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: int32(i), + }}, + } + } + lastNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, + ProjectList: projectList, + Children: []int32{lastNodeID}, + BindingTags: []int32{validatedTag}, + }, bindCtx) + return lastNodeID, validatedTag, nil +} + +func (builder *QueryBuilder) buildUpdateReferencedKeyUnchangedExpr( + parentTableDef *plan.TableDef, + fk *plan.ForeignKeyDef, + parentAlias string, + selectNodeTag int32, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, + selectNode *plan.Node, +) (*plan.Expr, error) { + parentColIDToName := make(map[uint64]string, len(parentTableDef.Cols)) + for _, col := range parentTableDef.Cols { + parentColIDToName[col.ColId] = col.Name + } + + var unchanged *plan.Expr + for _, parentColID := range fk.ForeignCols { + qualifiedName := parentAlias + "." + parentColIDToName[parentColID] + newPos, updated := newColName2Idx[qualifiedName] + if !updated { + continue + } + oldPos := oldColName2Idx[qualifiedName] + oldExpr := &plan.Expr{ + Typ: selectNode.ProjectList[oldPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: oldPos, + }}, + } + newExpr := &plan.Expr{ + Typ: selectNode.ProjectList[newPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: newPos, + }}, + } + equal, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "<=>", + []*plan.Expr{oldExpr, newExpr}, + ) + if err != nil { + return nil, err + } + if unchanged == nil { + unchanged = equal + continue + } + unchanged, err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "and", + []*plan.Expr{unchanged, equal}, + ) + if err != nil { + return nil, err + } + } + return unchanged, nil +} + func (builder *QueryBuilder) buildUpdateFkUnchangedExpr( tableDef *plan.TableDef, fk *plan.ForeignKeyDef, diff --git a/pkg/sql/plan/build.go b/pkg/sql/plan/build.go index dc73512b01379..c5d3ee91ed7b2 100644 --- a/pkg/sql/plan/build.go +++ b/pkg/sql/plan/build.go @@ -379,6 +379,42 @@ func bindAndOptimizeUpdateQuery(ctx CompilerContext, stmt *tree.Update, isPrepar if err = builder.finishIrregularIndexMaintenance(query, bindCtx); err != nil { return nil, err } + + enabled, err := IsForeignKeyChecksEnabled(ctx) + if err != nil { + return nil, err + } + if enabled && query.HasForeignKeyAction { + tblInfo, resolveErr := getUpdateTableInfo(ctx, stmt) + if resolveErr != nil { + return nil, resolveErr + } + for i, tableDef := range tblInfo.tableDefs { + if len(tblInfo.updateKeys[i]) == 0 { + continue + } + selfFkeys := make([]*plan.ForeignKeyDef, 0, len(tableDef.Fkeys)) + for _, fk := range tableDef.Fkeys { + if fk.ForeignTbl == 0 { + selfFkeys = append(selfFkeys, fk) + } + } + if len(selfFkeys) == 0 { + continue + } + sqls, genErr := genSqlsForCheckFKSelfRefer( + ctx.GetContext(), + tblInfo.objRef[i].SchemaName, + tableDef.Name, + tableDef.Cols, + selfFkeys, + ) + if genErr != nil { + return nil, genErr + } + query.DetectSqls = append(query.DetectSqls, sqls...) + } + } recordUpdatePlannerRoute(updatePlannerModern, updateRouteReasonNone, "selected") return &Plan{ Plan: &plan.Plan_Query{ diff --git a/pkg/sql/plan/build_constraint_util.go b/pkg/sql/plan/build_constraint_util.go index 24508bd67c4e5..058c6d7b70ddd 100644 --- a/pkg/sql/plan/build_constraint_util.go +++ b/pkg/sql/plan/build_constraint_util.go @@ -1872,6 +1872,7 @@ func appendForeignConstrantPlan( objRef *ObjectRef, sourceStep int32, isFkRecursionCall bool, + isUpdate bool, ) error { enabled, err := IsForeignKeyChecksEnabled(builder.compCtx) if err != nil { @@ -1910,7 +1911,11 @@ func appendForeignConstrantPlan( if err != nil { return err } - filterExpr, err := BindFuncExprImplByPlanExpr(builder.GetContext(), "assert", []*Expr{nullCheckExpr, errExpr}) + assertArgs := []*Expr{nullCheckExpr, errExpr} + if isUpdate { + assertArgs = append(assertArgs, makePlan2StringConstExprWithType(foreignKeyNoReferencedRowAssert)) + } + filterExpr, err := BindFuncExprImplByPlanExpr(builder.GetContext(), "assert", assertArgs) if err != nil { return err } diff --git a/pkg/sql/plan/build_dml_util.go b/pkg/sql/plan/build_dml_util.go index 84c1cff7ff758..e6f6f07c88475 100644 --- a/pkg/sql/plan/build_dml_util.go +++ b/pkg/sql/plan/build_dml_util.go @@ -562,21 +562,7 @@ func appendRecursiveCascadeLockNode( } } - slices.SortStableFunc(lockTargets, func(left, right *plan.LockTarget) int { - if left.TableId < right.TableId { - return -1 - } - if left.TableId > right.TableId { - return 1 - } - if !left.LockTable && right.LockTable { - return -1 - } - if left.LockTable && !right.LockTable { - return 1 - } - return 0 - }) + sortForeignKeyLockTargets(lockTargets, map[uint64]struct{}{delCtx.tableDef.TblId: {}}) if len(lockProject) > len(rowProject) { sourceNodeID = builder.appendNode(&plan.Node{ NodeType: plan.Node_PROJECT, Children: []int32{sourceNodeID}, @@ -2147,7 +2133,9 @@ func makeOneInsertPlan( // if table have fk. then append join node & filter node // sink_scan -> join -> filter - if err = appendForeignConstrantPlan(builder, bindCtx, tableDef, objRef, sourceStep, isFkRecursionCall); err != nil { + if err = appendForeignConstrantPlan( + builder, bindCtx, tableDef, objRef, sourceStep, isFkRecursionCall, updateColLength > 0, + ); err != nil { return err } diff --git a/pkg/sql/plan/build_test.go b/pkg/sql/plan/build_test.go index 897b2b1dc521c..beb5759a074dd 100644 --- a/pkg/sql/plan/build_test.go +++ b/pkg/sql/plan/build_test.go @@ -2763,7 +2763,7 @@ func TestUpdateFallbackGeneratedColumnChainUsesFreshExpr(t *testing.T) { } func TestPreparedForeignKeyActionsMarkQueryUncacheable(t *testing.T) { - t.Run("affected child key marks prepare uncacheable", func(t *testing.T) { + t.Run("ordinary child update marks prepare uncacheable", func(t *testing.T) { mock := NewMockOptimizer(true) setMockEmpDeptForeignKeyAction(t, mock, plan.ForeignKeyDef_SET_NULL, plan.ForeignKeyDef_CASCADE) @@ -2771,11 +2771,11 @@ func TestPreparedForeignKeyActionsMarkQueryUncacheable(t *testing.T) { require.True(t, query.GetHasForeignKeyAction()) }) - t.Run("unrelated child column keeps prepare cacheable", func(t *testing.T) { + t.Run("unrelated child update remains cacheable", func(t *testing.T) { mock := NewMockOptimizer(true) setMockEmpDeptForeignKeyAction(t, mock, plan.ForeignKeyDef_SET_NULL, plan.ForeignKeyDef_CASCADE) - query := buildPreparedQuery(t, mock, "prepare stmt1 from update emp set sal = ? where empno = ?") + query := buildPreparedQuery(t, mock, "prepare stmt1 from update emp set ename = ? where empno = ?") require.False(t, query.GetHasForeignKeyAction()) }) @@ -2787,6 +2787,32 @@ func TestPreparedForeignKeyActionsMarkQueryUncacheable(t *testing.T) { require.True(t, query.GetHasForeignKeyAction()) }) + t.Run("unrelated parent update remains cacheable", func(t *testing.T) { + mock := NewMockOptimizer(true) + setMockEmpDeptForeignKeyAction(t, mock, plan.ForeignKeyDef_RESTRICT, plan.ForeignKeyDef_CASCADE) + + query := buildPreparedQuery(t, mock, "prepare stmt1 from update dept set loc = ? where deptno = ?") + require.False(t, query.GetHasForeignKeyAction()) + }) + + t.Run("child update remains uncacheable with checks disabled", func(t *testing.T) { + mock := NewMockOptimizer(true) + setMockEmpDeptForeignKeyAction(t, mock, plan.ForeignKeyDef_SET_NULL, plan.ForeignKeyDef_CASCADE) + mock.ctxt.ResolveVariableFunc = func(name string, _, _ bool) (interface{}, error) { + switch name { + case "foreign_key_checks": + return int64(0), nil + case "sql_mode": + return "", nil + default: + return nil, moerr.NewInternalError(context.Background(), "unexpected variable") + } + } + + query := buildPreparedQuery(t, mock, "prepare stmt1 from update emp set deptno = ? where empno = ?") + require.True(t, query.GetHasForeignKeyAction()) + }) + t.Run("parent delete set null marks prepare uncacheable", func(t *testing.T) { mock := NewMockOptimizer(true) setMockEmpDeptForeignKeyAction(t, mock, plan.ForeignKeyDef_SET_NULL, plan.ForeignKeyDef_RESTRICT) diff --git a/pkg/sql/plan/deepcopy.go b/pkg/sql/plan/deepcopy.go index a47f34eca3533..666c4ca00a5f7 100644 --- a/pkg/sql/plan/deepcopy.go +++ b/pkg/sql/plan/deepcopy.go @@ -107,6 +107,7 @@ func DeepCopyUpdateCtxList(updateCtxList []*plan.UpdateCtx) []*plan.UpdateCtx { SkipInsertOnNullPk: ctx.SkipInsertOnNullPk, InsertPkColIdx: ctx.InsertPkColIdx, CountDeleteAffectRows: ctx.CountDeleteAffectRows, + IgnoreAffectedRows: ctx.IgnoreAffectedRows, } } diff --git a/pkg/sql/plan/function/list_builtIn.go b/pkg/sql/plan/function/list_builtIn.go index ba7e8be51ede0..3621e30a4ca3d 100644 --- a/pkg/sql/plan/function/list_builtIn.go +++ b/pkg/sql/plan/function/list_builtIn.go @@ -14365,6 +14365,12 @@ var supportedOthersBuiltIns = []FuncNew{ if errType == "fk_no_referenced_row" { return moerr.NewErrFKNoReferencedRow2(proc.Ctx) } + if errType == "fk_row_is_referenced" { + return moerr.NewErrFKRowIsReferenced(proc.Ctx) + } + if errType == "fk_ambiguous_parent_mapping" { + return moerr.NewNotSupported(proc.Ctx, errMsg) + } return moerr.NewInternalError(proc.Ctx, errMsg) } res.AppendMustValue(true) diff --git a/pkg/sql/plan/update_planner_route_test.go b/pkg/sql/plan/update_planner_route_test.go index 20d7c5a66e9c9..4f83cbaf3d41d 100644 --- a/pkg/sql/plan/update_planner_route_test.go +++ b/pkg/sql/plan/update_planner_route_test.go @@ -18,16 +18,19 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/moerr" - "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/defines" + lockpb "github.com/matrixorigin/matrixone/pkg/pb/lock" planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + txnpb "github.com/matrixorigin/matrixone/pkg/pb/txn" "github.com/matrixorigin/matrixone/pkg/sql/parsers" "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + planutil "github.com/matrixorigin/matrixone/pkg/sql/util" ) func TestClassifyUpdatePlannerError(t *testing.T) { @@ -194,42 +197,6 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) { wantRoute: updatePlannerModern, wantReason: updateRouteReasonNone, }, - { - name: "pub primary key", - sql: "UPDATE nation SET n_nationkey = 2", - prepare: func(mock *MockOptimizer) { - mock.ctxt.tables["nation"].Name = catalog.MO_PUBS - }, - wantRoute: updatePlannerModern, - wantReason: updateRouteReasonNone, - }, - { - name: "sub unique key", - sql: "UPDATE nation SET n_name = 'x'", - prepare: func(mock *MockOptimizer) { - tableDef := mock.ctxt.tables["nation"] - tableDef.Name = catalog.MO_SUBS - tableDef.Indexes = []*planpb.IndexDef{{ - IndexName: "uk_name", - Unique: true, - Parts: []string{"n_name"}, - }} - }, - wantRoute: updatePlannerModern, - wantReason: updateRouteReasonNone, - }, - { - name: "set auto increment", - sql: "UPDATE nation SET n_nationkey = 2", - prepare: func(mock *MockOptimizer) { - col := mock.ctxt.tables["nation"].Cols[0] - col.Typ.Id = int32(types.T_uint64) - col.Typ.Enumvalues = "one,two" - col.Typ.AutoIncr = true - }, - wantRoute: updatePlannerModern, - wantReason: updateRouteReasonNone, - }, } for _, test := range tests { @@ -264,32 +231,6 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) { } } -func TestRemainingUpdateSpecialCasesUseModernPlan(t *testing.T) { - t.Run("pub primary key uses multi update", func(t *testing.T) { - mock := NewMockOptimizer(true) - mock.ctxt.tables["nation"].Name = catalog.MO_PUBS - - logicPlan, err := runOneStmt(mock, t, "UPDATE nation SET n_nationkey = 2") - require.NoError(t, err) - require.Equal(t, 1, countUpdateFkPlanNodes(logicPlan.GetQuery(), planpb.Node_MULTI_UPDATE)) - }) - - t.Run("set auto increment keeps type conversion and pre insert", func(t *testing.T) { - mock := NewMockOptimizer(true) - col := mock.ctxt.tables["nation"].Cols[0] - col.Typ.Id = int32(types.T_uint64) - col.Typ.Enumvalues = "one,two" - col.Typ.AutoIncr = true - - logicPlan, err := runOneStmt(mock, t, "UPDATE nation SET n_nationkey = 'two'") - require.NoError(t, err) - query := logicPlan.GetQuery() - require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE)) - require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_PRE_INSERT)) - require.True(t, updateFkPlanContainsFunc(query, moSetCastValueToIndexFun)) - }) -} - func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { prepareEmpDept := func(mock *MockOptimizer) { emp := mock.ctxt.tables["emp"] @@ -302,16 +243,11 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { mock.ctxt.id2name[emp.TblId] = "emp" } disableForeignKeyChecks := func(mock *MockOptimizer) { - mock.ctxt.ResolveVariableFunc = func(name string, _, _ bool) (interface{}, error) { - switch name { - case "foreign_key_checks": - return int64(0), nil - case "sql_mode": - return "", nil - default: - return nil, moerr.NewInternalError(context.Background(), "unexpected variable") - } - } + mock.ctxt.SetContext(context.WithValue( + mock.ctxt.GetContext(), + defines.DisableFkCheck{}, + true, + )) } t.Run("unrelated child column uses multi update without parent probe", func(t *testing.T) { @@ -375,22 +311,31 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { require.True(t, hasParentScan) require.True(t, hasMarkJoin) require.True(t, hasAssert) - require.Equal(t, 3, len(findUpdateFkAssert(logicPlan.GetQuery()).GetF().Args)) + require.True(t, updateFkPlanContainsTypedAssert( + logicPlan.GetQuery(), + foreignKeyNoReferencedRowAssert, + )) }) - t.Run("disabled checks keep affected child plan sensitive without validation", func(t *testing.T) { + t.Run("irregular index child foreign key update keeps typed error", func(t *testing.T) { mock := NewMockOptimizer(true) prepareEmpDept(mock) - disableForeignKeyChecks(mock) + mock.ctxt.tables["emp"].Indexes = []*planpb.IndexDef{{ + IndexName: "idx", + IndexAlgo: catalog.MoIndexIvfFlatAlgo.ToString(), + Parts: []string{"sal"}, + }} - logicPlan, err := runOneStmt(mock, t, "UPDATE emp SET deptno = 2") + logicPlan, err := runOneStmt(mock, t, "UPDATE emp SET deptno = 2, sal = 1") require.NoError(t, err) - query := logicPlan.GetQuery() - require.True(t, query.GetHasForeignKeyAction()) require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE)) - require.Equal(t, 0, countUpdateFkMarkJoins(query)) - require.Nil(t, findUpdateFkAssert(query)) + require.Equal(t, 1, countUpdateFkAsserts(query)) + require.True(t, updateFkPlanScansTable(query, mock.ctxt.tables["dept"].TblId)) + require.True(t, updateFkPlanContainsTypedAssert( + query, + foreignKeyNoReferencedRowAssert, + )) }) t.Run("auto increment child key uses legacy final row validation", func(t *testing.T) { @@ -445,27 +390,140 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { require.Equal(t, 0, countUpdateFkMarkJoins(query)) }) - t.Run("affected referenced parent key keeps typed legacy route", func(t *testing.T) { + t.Run("affected restricted parent key stays modern with child probe", func(t *testing.T) { mock := NewMockOptimizer(true) prepareEmpDept(mock) - stmt, err := parsers.ParseOne( - mock.CurrentContext().GetContext(), - dialect.MYSQL, - "UPDATE dept SET deptno = 2", - 1, - ) + logicPlan, err := runOneStmt(mock, t, "UPDATE dept SET deptno = 2") require.NoError(t, err) - defer stmt.Free() + query := logicPlan.GetQuery() + require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE)) + require.Equal(t, 1, countUpdateFkMarkJoins(query)) + require.Equal(t, 1, countUpdateFkAsserts(query)) + require.True(t, updateFkPlanContainsFunc(query, "<=>")) + require.True(t, updateFkPlanContainsTypedAssert( + query, + foreignKeyRowIsReferencedAssert, + )) + }) - builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) - _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) - require.Error(t, err) - route, reason, _ := classifyUpdatePlannerError(err) - require.Equal(t, updatePlannerLegacy, route) - require.Equal(t, updateRouteReasonForeignKey, reason) + t.Run("set default preserves restrict compatibility on modern path", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + mock.ctxt.tables["emp"].Fkeys[0].OnUpdate = planpb.ForeignKeyDef_SET_DEFAULT + + logicPlan, err := runOneStmt(mock, t, "UPDATE dept SET deptno = 2") + require.NoError(t, err) + query := logicPlan.GetQuery() + require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE)) + require.Equal(t, 1, countUpdateFkMarkJoins(query)) + require.Equal(t, 1, countUpdateFkAsserts(query)) }) + for _, test := range []struct { + name string + action planpb.ForeignKeyDef_RefAction + }{ + {name: "cascade parent key builds child multi update", action: planpb.ForeignKeyDef_CASCADE}, + {name: "set null parent key builds child multi update", action: planpb.ForeignKeyDef_SET_NULL}, + } { + t.Run(test.name, func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + emp := mock.ctxt.tables["emp"] + emp.Fkeys[0].OnUpdate = test.action + + logicPlan, err := runOneStmt(mock, t, "UPDATE dept SET deptno = 2") + require.NoError(t, err) + query := logicPlan.GetQuery() + require.Equal(t, 2, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE)) + require.True(t, query.HasForeignKeyAction) + require.True(t, updateFkPlanContainsFunc(query, "<=>")) + hasIndexedParentUpdate := false + for _, node := range query.Nodes { + if node.NodeType == planpb.Node_MULTI_UPDATE && len(node.UpdateCtxList) > 1 { + hasIndexedParentUpdate = true + } + if node.NodeType != planpb.Node_MULTI_UPDATE { + continue + } + if len(node.UpdateCtxList) > 0 && node.UpdateCtxList[0].ObjRef.ObjName == "emp" { + require.Len(t, node.UpdateCtxList, 1, + "cascade must not rewrite child indexes whose key parts are unchanged") + for _, updateCtx := range node.UpdateCtxList { + require.True(t, updateCtx.IgnoreAffectedRows) + } + } + if len(node.UpdateCtxList) > 0 && node.UpdateCtxList[0].ObjRef.ObjName == "dept" { + for _, updateCtx := range node.UpdateCtxList { + require.False(t, updateCtx.IgnoreAffectedRows) + } + } + } + require.True(t, hasIndexedParentUpdate) + }) + } + + for _, test := range []struct { + name string + prepare func(*MockOptimizer) + }{ + { + name: "generated unique collision requires complete child row closure", + prepare: func(mock *MockOptimizer) { + setMockGeneratedColumn(t, mock, "emp", "sal", "deptno") + mock.ctxt.tables["emp"].Indexes = append(mock.ctxt.tables["emp"].Indexes, &planpb.IndexDef{ + IndexName: "uk_sal", Parts: []string{"sal"}, Unique: true, + }) + }, + }, + { + name: "parent child width mismatch requires assignment cast", + prepare: func(mock *MockOptimizer) { + requireMockColumn(t, mock, "emp", "deptno").Typ.Width = 16 + }, + }, + { + name: "composite cluster by dependency requires recomputation", + prepare: func(mock *MockOptimizer) { + emp := mock.ctxt.tables["emp"] + emp.ClusterBy = &planpb.ClusterByDef{ + Name: planutil.BuildCompositeClusterByColumnName([]string{"deptno", "empno"}), + } + }, + }, + { + name: "on update feeding generated column requires dependency closure", + prepare: func(mock *MockOptimizer) { + setMockOnUpdateExpr(t, mock, "emp", "job", "changed") + setMockGeneratedColumn(t, mock, "emp", "ename", "job") + }, + }, + } { + t.Run(test.name, func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + mock.ctxt.tables["emp"].Fkeys[0].OnUpdate = planpb.ForeignKeyDef_CASCADE + test.prepare(mock) + + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), + dialect.MYSQL, + "UPDATE dept SET deptno = 2", + 1, + ) + require.NoError(t, err) + defer stmt.Free() + + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.ErrorContains(t, err, "complete child update row closure") + route, reason, _ := classifyUpdatePlannerError(err) + require.Equal(t, updatePlannerRejected, route) + require.Equal(t, updateRouteReasonForeignKey, reason) + }) + } + t.Run("disabled checks skip child probe and parent fallback", func(t *testing.T) { mock := NewMockOptimizer(true) prepareEmpDept(mock) @@ -511,8 +569,242 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, countUpdateFkMarkJoins(logicPlan.GetQuery())) require.Equal(t, 1, countUpdateFkAsserts(logicPlan.GetQuery())) + require.True(t, updateFkPlanContainsTypedAssert( + logicPlan.GetQuery(), + foreignKeyNoReferencedRowAssert, + )) require.True(t, updateFkPlanContainsFunc(logicPlan.GetQuery(), "<=>")) }) + + t.Run("parent cascade changing another child foreign key is rejected", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + emp := mock.ctxt.tables["emp"] + emp.Fkeys[0].OnUpdate = planpb.ForeignKeyDef_CASCADE + otherParent := mock.ctxt.tables["nation"] + emp.Fkeys = append(emp.Fkeys, &planpb.ForeignKeyDef{ + Name: "fk_emp_other_parent", + Cols: []uint64{7}, + ForeignTbl: otherParent.TblId, + ForeignCols: []uint64{0}, + }) + + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), + dialect.MYSQL, + "UPDATE dept SET deptno = 2", + 1, + ) + require.NoError(t, err) + defer stmt.Free() + + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.ErrorContains(t, err, "child column constrained by another foreign key") + route, _, _ := classifyUpdatePlannerError(err) + require.Equal(t, updatePlannerRejected, route) + }) +} + +func TestBindUpdateParentForeignKeySafetyGates(t *testing.T) { + prepareEmpDept := func(mock *MockOptimizer, action planpb.ForeignKeyDef_RefAction) { + setMockEmpDeptForeignKeyAction(t, mock, planpb.ForeignKeyDef_RESTRICT, action) + } + + for _, action := range []planpb.ForeignKeyDef_RefAction{ + planpb.ForeignKeyDef_RESTRICT, + planpb.ForeignKeyDef_CASCADE, + planpb.ForeignKeyDef_SET_NULL, + } { + t.Run("optimistic "+action.String(), func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock, action) + setMockTxnMode(mock, txnpb.TxnMode_Optimistic) + + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), dialect.MYSQL, + "UPDATE dept SET deptno = 2", 1) + require.NoError(t, err) + defer stmt.Free() + + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.ErrorContains(t, err, "optimistic transaction") + route, reason, _ := classifyUpdatePlannerError(err) + require.Equal(t, updatePlannerRejected, route) + require.Equal(t, updateRouteReasonForeignKey, reason) + }) + } + + for _, test := range []struct { + name string + action planpb.ForeignKeyDef_RefAction + windowCount int + ambiguous bool + }{ + {name: "cascade guards distinct child outputs", action: planpb.ForeignKeyDef_CASCADE, windowCount: 2, ambiguous: true}, + {name: "set null only deduplicates child identity", action: planpb.ForeignKeyDef_SET_NULL, windowCount: 1}, + } { + t.Run("non unique referenced prefix "+test.name, func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock, test.action) + dept := mock.ctxt.tables["dept"] + dept.Pkey = &planpb.PrimaryKeyDef{ + Names: []string{"deptno", "dname"}, PkeyColName: "deptno", + } + + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), dialect.MYSQL, + "UPDATE dept SET deptno = 2", 1) + require.NoError(t, err) + defer stmt.Free() + + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.NoError(t, err) + require.Equal(t, test.ambiguous, updateFkPlanContainsTypedAssert( + builder.qry, foreignKeyAmbiguousMappingAssert)) + windowCount := 0 + for _, node := range builder.qry.Nodes { + if node.NodeType == planpb.Node_WINDOW { + windowCount++ + } + } + require.Equal(t, test.windowCount, windowCount) + }) + } +} + +func TestBindUpdateForeignKeySensitivityIncludesImplicitFinalRowChanges(t *testing.T) { + for _, checksDisabled := range []bool{false, true} { + t.Run(map[bool]string{false: "checks enabled", true: "checks disabled"}[checksDisabled], func(t *testing.T) { + mock := NewMockOptimizer(true) + setMockEmpDeptForeignKeyAction( + t, mock, planpb.ForeignKeyDef_RESTRICT, planpb.ForeignKeyDef_RESTRICT) + setMockOnUpdateExpr(t, mock, "emp", "deptno", "2") + if checksDisabled { + mock.ctxt.SetContext(context.WithValue( + mock.ctxt.GetContext(), defines.DisableFkCheck{}, true)) + } + + logicPlan, err := runOneStmt(mock, t, "UPDATE emp SET sal = sal + 1") + require.NoError(t, err) + require.True(t, logicPlan.GetQuery().HasForeignKeyAction, + "implicit ON UPDATE FK column must make prepared plans cache-sensitive") + }) + } +} + +func TestSortForeignKeyLockTargetsUsesBaseBeforeHiddenTables(t *testing.T) { + base := &planpb.LockTarget{TableId: 20, ObjRef: &planpb.ObjectRef{ObjName: "z_parent"}} + hidden := &planpb.LockTarget{TableId: 10, ObjRef: &planpb.ObjectRef{ObjName: "__mo_index_a"}} + targets := []*planpb.LockTarget{hidden, base} + + sortForeignKeyLockTargets(targets, map[uint64]struct{}{base.TableId: {}}) + require.Same(t, base, targets[0]) + require.Same(t, hidden, targets[1]) +} + +func TestUpdateParentForeignKeyLocksPrecedeChildConsumers(t *testing.T) { + mock := NewMockOptimizer(true) + setMockEmpDeptForeignKeyAction(t, mock, planpb.ForeignKeyDef_RESTRICT, planpb.ForeignKeyDef_CASCADE) + child := mock.ctxt.tables["emp"] + child.Indexes = append(child.Indexes, &planpb.IndexDef{ + IndexName: "building_idx", IndexTableName: "missing_building_idx", + Parts: []string{"ename"}, TableExist: false, + IndexAlgo: catalog.MoIndexDefaultAlgo.ToString(), + }) + + logicPlan, err := runOneStmt(mock, t, "update dept set deptno = deptno + 10 where deptno = 1") + require.NoError(t, err) + query := logicPlan.GetQuery() + require.Contains(t, query.DetectSqls, "UPDATE_PARENT_PLAN:") + parentID := mock.ctxt.tables["dept"].TblId + childID := child.TblId + + contains := func(root, target int32) bool { + var visit func(int32) bool + visit = func(nodeID int32) bool { + if nodeID == target { + return true + } + for _, childNodeID := range query.Nodes[nodeID].Children { + if visit(childNodeID) { + return true + } + } + return false + } + return visit(root) + } + stepContaining := func(target int32) int { + for step, root := range query.Steps { + if contains(root, target) { + return step + } + } + return -1 + } + var stepDependsOn func(int, int, map[int]bool) bool + stepDependsOn = func(step, dependency int, visited map[int]bool) bool { + if step == dependency { + return true + } + if visited[step] { + return false + } + visited[step] = true + var nodeDependsOn func(int32) bool + nodeDependsOn = func(nodeID int32) bool { + for _, sourceStep := range query.Nodes[nodeID].SourceStep { + if stepDependsOn(int(sourceStep), dependency, visited) { + return true + } + } + for _, childNodeID := range query.Nodes[nodeID].Children { + if nodeDependsOn(childNodeID) { + return true + } + } + return false + } + return nodeDependsOn(query.Steps[step]) + } + + lockNodeID := int32(-1) + for nodeID, node := range query.Nodes { + for _, target := range node.LockTargets { + if target.TableId == parentID && target.Mode == lockpb.LockMode_Exclusive { + lockNodeID = int32(nodeID) + require.Len(t, node.Children, 1) + lockInput := query.Nodes[node.Children[0]] + require.Less(t, int(target.PrimaryColIdxInBat), len(lockInput.ProjectList)) + assert.Equal(t, target.PrimaryColTyp.Id, + lockInput.ProjectList[target.PrimaryColIdxInBat].Typ.Id) + break + } + } + if lockNodeID >= 0 { + break + } + } + require.NotEqual(t, int32(-1), lockNodeID) + lockStep := stepContaining(lockNodeID) + require.GreaterOrEqual(t, lockStep, 0) + assert.Equal(t, planpb.Node_SINK, query.Nodes[query.Steps[lockStep]].NodeType) + + foundChildConsumer := false + for nodeID, node := range query.Nodes { + if node.NodeType != planpb.Node_TABLE_SCAN || node.TableDef == nil || node.TableDef.TblId != childID { + continue + } + foundChildConsumer = true + consumerStep := stepContaining(int32(nodeID)) + require.GreaterOrEqual(t, consumerStep, 0) + assert.True(t, stepDependsOn(consumerStep, lockStep, make(map[int]bool)), + "every child scan must depend on the materialized parent-key lock step") + } + assert.True(t, foundChildConsumer) } func TestBindUpdateSelfReferencingForeignKeyRouting(t *testing.T) { @@ -537,13 +829,28 @@ func TestBindUpdateSelfReferencingForeignKeyRouting(t *testing.T) { logicPlan, err := runOneStmt(mock, t, "UPDATE self_ref SET parent_id = 2") require.NoError(t, err) require.Equal(t, 1, countUpdateFkPlanNodes(logicPlan.GetQuery(), planpb.Node_MULTI_UPDATE)) - require.Equal(t, 1, countUpdateFkMarkJoins(logicPlan.GetQuery())) - require.Equal(t, 1, countUpdateFkAsserts(logicPlan.GetQuery())) + require.Equal(t, 0, countUpdateFkMarkJoins(logicPlan.GetQuery())) + require.Equal(t, 0, countUpdateFkAsserts(logicPlan.GetQuery())) + require.NotEmpty(t, logicPlan.GetQuery().DetectSqls) }) - t.Run("referenced key keeps typed legacy route", func(t *testing.T) { + t.Run("restricted referenced key uses final self validation", func(t *testing.T) { mock := NewMockOptimizer(true) prepareSelfRef(mock) + logicPlan, err := runOneStmt(mock, t, "UPDATE self_ref SET id = 2") + require.NoError(t, err) + query := logicPlan.GetQuery() + require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE)) + require.Equal(t, 1, countUpdateFkMarkJoins(query)) + require.Equal(t, 1, countUpdateFkAsserts(query)) + require.NotEmpty(t, query.DetectSqls) + require.True(t, updateFkPlanContainsFunc(query, "isnull")) + }) + + t.Run("self cascade uses typed legacy validation", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareSelfRef(mock) + mock.ctxt.tables["self_ref"].Fkeys[0].OnUpdate = planpb.ForeignKeyDef_CASCADE stmt, err := parsers.ParseOne( mock.CurrentContext().GetContext(), dialect.MYSQL, @@ -560,6 +867,135 @@ func TestBindUpdateSelfReferencingForeignKeyRouting(t *testing.T) { require.Equal(t, updatePlannerLegacy, route) require.Equal(t, updateRouteReasonForeignKey, reason) }) + + t.Run("disabled checks omit self detect sql", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareSelfRef(mock) + mock.ctxt.SetContext(context.WithValue( + mock.ctxt.GetContext(), + defines.DisableFkCheck{}, + true, + )) + logicPlan, err := runOneStmt(mock, t, "UPDATE self_ref SET parent_id = 99") + require.NoError(t, err) + require.Empty(t, logicPlan.GetQuery().DetectSqls) + require.Equal(t, 0, countUpdateFkMarkJoins(logicPlan.GetQuery())) + require.Equal(t, 0, countUpdateFkAsserts(logicPlan.GetQuery())) + }) +} + +func TestBindUpdateAutoIncrementRunsBeforeForeignKeys(t *testing.T) { + prepareEmpDept := func(mock *MockOptimizer) { + emp := mock.ctxt.tables["emp"] + dept := mock.ctxt.tables["dept"] + emp.TblId = 88887 + emp.Fkeys[0].ForeignTbl = dept.TblId + emp.Fkeys[0].ForeignCols = []uint64{0} + dept.RefChildTbls = []uint64{emp.TblId} + mock.ctxt.id2name[emp.TblId] = "emp" + } + bindDirect := func(t *testing.T, mock *MockOptimizer, sql string) *planpb.Query { + stmt, err := parsers.ParseOne(mock.CurrentContext().GetContext(), dialect.MYSQL, sql, 1) + require.NoError(t, err) + defer stmt.Free() + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.NoError(t, err) + return builder.qry + } + firstNode := func(query *planpb.Query, match func(*planpb.Node) bool) int { + for i, node := range query.Nodes { + if match(node) { + return i + } + } + return -1 + } + + t.Run("child generated key uses legacy final row validation", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + mock.ctxt.tables["emp"].Cols[7].Typ.AutoIncr = true + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), + dialect.MYSQL, + "UPDATE emp SET deptno = DEFAULT", + 1, + ) + require.NoError(t, err) + defer stmt.Free() + + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.ErrorContains(t, err, "auto_increment foreign key update") + route, reason, _ := classifyUpdatePlannerError(err) + require.Equal(t, updatePlannerLegacy, route) + require.Equal(t, updateRouteReasonAutoIncrementFK, reason) + }) + + t.Run("parent action on generated key uses legacy planner", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + mock.ctxt.tables["dept"].Cols[0].Typ.AutoIncr = true + mock.ctxt.tables["emp"].Fkeys[0].OnUpdate = planpb.ForeignKeyDef_CASCADE + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), + dialect.MYSQL, + "UPDATE dept SET deptno = DEFAULT", + 1, + ) + require.NoError(t, err) + defer stmt.Free() + + builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) + _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) + require.ErrorContains(t, err, "auto-increment referenced key") + route, reason, _ := classifyUpdatePlannerError(err) + require.Equal(t, updatePlannerLegacy, route) + require.Equal(t, updateRouteReasonForeignKey, reason) + }) + + t.Run("disabled checks preserve pre-insert input schema", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + mock.ctxt.tables["emp"].Cols[0].Typ.AutoIncr = true + mock.ctxt.SetContext(context.WithValue( + mock.ctxt.GetContext(), + defines.DisableFkCheck{}, + true, + )) + + query := bindDirect(t, mock, "UPDATE emp SET empno = DEFAULT") + require.NotNil(t, query) + require.NotEqual(t, -1, firstNode(query, func(node *planpb.Node) bool { + return node.NodeType == planpb.Node_PRE_INSERT + })) + }) +} + +func TestLegacyInsertForeignKeyKeepsGenericAssert(t *testing.T) { + mock := NewMockOptimizer(true) + emp := mock.ctxt.tables["emp"] + dept := mock.ctxt.tables["dept"] + emp.TblId = 88887 + emp.Fkeys[0].ForeignTbl = dept.TblId + emp.Fkeys[0].ForeignCols = []uint64{0} + mock.ctxt.id2name[emp.TblId] = "emp" + + stmt, err := parsers.ParseOne( + mock.CurrentContext().GetContext(), + dialect.MYSQL, + "INSERT INTO emp (empno, deptno) VALUES (1, 10)", + 1, + ) + require.NoError(t, err) + defer stmt.Free() + + logicPlan, err := buildInsert(stmt.(*tree.Insert), mock.CurrentContext(), false, false) + require.NoError(t, err) + query := logicPlan.GetQuery() + require.True(t, updateFkPlanContainsAssertWithArity(query, 2)) + require.False(t, updateFkPlanContainsTypedAssert(query, foreignKeyNoReferencedRowAssert)) } func TestResolveSingleTablePreservesForeignKeyPolicy(t *testing.T) { @@ -629,15 +1065,40 @@ func countUpdateFkAsserts(query *planpb.Query) int { return count } -func findUpdateFkAssert(query *planpb.Query) *planpb.Expr { +func updateFkPlanContainsTypedAssert(query *planpb.Query, errType string) bool { for _, node := range query.Nodes { for _, filter := range node.FilterList { - if filter.GetF() != nil && filter.GetF().Func.ObjName == "assert" { - return filter + fn := filter.GetF() + if fn == nil || fn.Func.ObjName != "assert" || len(fn.Args) != 3 { + continue + } + if lit := fn.Args[2].GetLit(); lit != nil && lit.GetSval() == errType { + return true } } } - return nil + return false +} + +func updateFkPlanContainsAssertWithArity(query *planpb.Query, arity int) bool { + for _, node := range query.Nodes { + for _, filter := range node.FilterList { + fn := filter.GetF() + if fn != nil && fn.Func.ObjName == "assert" && len(fn.Args) == arity { + return true + } + } + } + return false +} + +func updateFkPlanScansTable(query *planpb.Query, tableID uint64) bool { + for _, node := range query.Nodes { + if node.NodeType == planpb.Node_TABLE_SCAN && node.TableDef != nil && node.TableDef.TblId == tableID { + return true + } + } + return false } func updateFkPlanContainsFunc(query *planpb.Query, name string) bool { diff --git a/pkg/tests/issues/issue_26339_test.go b/pkg/tests/issues/issue_26339_test.go new file mode 100644 index 0000000000000..8fedf902ac7d9 --- /dev/null +++ b/pkg/tests/issues/issue_26339_test.go @@ -0,0 +1,261 @@ +// Copyright 2026 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package issues + +import ( + "context" + "database/sql" + "fmt" + "strings" + "testing" + "time" + + "github.com/go-sql-driver/mysql" + moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" + "github.com/matrixorigin/matrixone/pkg/embed" + pbtxn "github.com/matrixorigin/matrixone/pkg/pb/txn" + "github.com/stretchr/testify/require" +) + +func TestIssue26339ForeignKeyExecutionRegressions(t *testing.T) { + runAuthenticatedClusterTest(t, func(c embed.Cluster) { + ctx, cancel := context.WithTimeout(context.Background(), 240*time.Second) + defer cancel() + + cn, err := c.GetCNService(0) + require.NoError(t, err) + port := cn.GetServiceConfig().CN.Frontend.Port + db, err := sql.Open("mysql", fmt.Sprintf("dump:111@tcp(127.0.0.1:%d)/", port)) + require.NoError(t, err) + defer db.Close() + db.SetMaxOpenConns(3) + + const database = "issue_26339_fk_execution" + defer func() { + cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cleanupCancel() + execSQLMaybe(t, cleanupCtx, db, "drop database if exists "+database) + }() + execSQLRequire(t, ctx, db, "drop database if exists "+database) + execSQLRequire(t, ctx, db, "create database "+database) + + t.Run("optimistic parent update is rejected before concurrent child write", func(t *testing.T) { + execSQLRequire(t, ctx, db, "create table "+database+".optimistic_parent (id int primary key)") + execSQLRequire(t, ctx, db, "create table "+database+".optimistic_child ("+ + "id int primary key, parent_id int, foreign key (parent_id) "+ + "references "+database+".optimistic_parent(id) on update cascade)") + execSQLRequire(t, ctx, db, "insert into "+database+".optimistic_parent values (1)") + + rt := moruntime.ServiceRuntime(cn.ServiceID()) + oldMode, hadMode := rt.GetGlobalVariables(moruntime.TxnMode) + oldIsolation, hadIsolation := rt.GetGlobalVariables(moruntime.TxnIsolation) + rt.SetGlobalVariables(moruntime.TxnMode, pbtxn.TxnMode_Optimistic) + rt.SetGlobalVariables(moruntime.TxnIsolation, pbtxn.TxnIsolation_SI) + defer func() { + if hadMode { + rt.SetGlobalVariables(moruntime.TxnMode, oldMode) + } else { + rt.SetGlobalVariables(moruntime.TxnMode, pbtxn.TxnMode_Pessimistic) + } + if hadIsolation { + rt.SetGlobalVariables(moruntime.TxnIsolation, oldIsolation) + } else { + rt.SetGlobalVariables(moruntime.TxnIsolation, pbtxn.TxnIsolation_RC) + } + }() + + parentConn, err := db.Conn(ctx) + require.NoError(t, err) + defer parentConn.Close() + childConn, err := db.Conn(ctx) + require.NoError(t, err) + defer childConn.Close() + + _, err = parentConn.ExecContext(ctx, "begin") + require.NoError(t, err) + defer func() { + rollbackCtx, rollbackCancel := context.WithTimeout(context.Background(), 10*time.Second) + defer rollbackCancel() + _, _ = parentConn.ExecContext(rollbackCtx, "rollback") + }() + _, err = childConn.ExecContext(ctx, "begin") + require.NoError(t, err) + defer func() { + rollbackCtx, rollbackCancel := context.WithTimeout(context.Background(), 10*time.Second) + defer rollbackCancel() + _, _ = childConn.ExecContext(rollbackCtx, "rollback") + }() + + _, err = parentConn.ExecContext(ctx, + "update "+database+".optimistic_parent set id = 2 where id = 1") + require.Error(t, err) + var mysqlErr *mysql.MySQLError + require.ErrorAs(t, err, &mysqlErr) + require.Equal(t, uint16(20105), mysqlErr.Number) + require.Contains(t, err.Error(), "optimistic transaction") + + _, err = childConn.ExecContext(ctx, + "insert into "+database+".optimistic_child values (10, 1)") + require.NoError(t, err) + _, err = childConn.ExecContext(ctx, "commit") + require.NoError(t, err) + _, err = parentConn.ExecContext(ctx, "rollback") + require.NoError(t, err) + + var parentID, childParentID, orphanCount int + require.NoError(t, db.QueryRowContext(ctx, + "select id from "+database+".optimistic_parent").Scan(&parentID)) + require.NoError(t, db.QueryRowContext(ctx, + "select parent_id from "+database+".optimistic_child where id = 10").Scan(&childParentID)) + require.NoError(t, db.QueryRowContext(ctx, + "select count(*) from "+database+".optimistic_child c left join "+ + database+".optimistic_parent p on c.parent_id = p.id where p.id is null").Scan(&orphanCount)) + require.Equal(t, 1, parentID) + require.Equal(t, 1, childParentID) + require.Zero(t, orphanCount) + }) + + t.Run("non unique referenced prefix validates actual child mappings", func(t *testing.T) { + execSQLRequire(t, ctx, db, "create table "+database+".mapping_parent ("+ + "a int, b int, primary key (a, b))") + execSQLRequire(t, ctx, db, "create table "+database+".mapping_child ("+ + "id int primary key, parent_a int, foreign key (parent_a) "+ + "references "+database+".mapping_parent(a) on update cascade)") + + // No child row means there is no referential-action target to make + // ambiguous, even when changed parents share the same old prefix. + execSQLRequire(t, ctx, db, + "insert into "+database+".mapping_parent values (1, 1), (1, 2)") + execSQLRequire(t, ctx, db, + "update "+database+".mapping_parent set a = b + 1 where a = 1") + var parentCount int + require.NoError(t, db.QueryRowContext(ctx, + "select count(*) from "+database+".mapping_parent where (a, b) in ((2, 1), (3, 2))"). + Scan(&parentCount)) + require.Equal(t, 2, parentCount) + + execSQLRequire(t, ctx, db, "delete from "+database+".mapping_parent") + execSQLRequire(t, ctx, db, + "insert into "+database+".mapping_parent values (1, 1), (1, 2)") + execSQLRequire(t, ctx, db, + "insert into "+database+".mapping_child values (10, 1)") + + // Duplicate parent matches are safe when they produce one identical + // new tuple for the child row. + execSQLRequire(t, ctx, db, + "update "+database+".mapping_parent set a = 2 where a = 1") + var childParent int + require.NoError(t, db.QueryRowContext(ctx, + "select parent_a from "+database+".mapping_child where id = 10").Scan(&childParent)) + require.Equal(t, 2, childParent) + + execSQLRequire(t, ctx, db, "delete from "+database+".mapping_child") + execSQLRequire(t, ctx, db, "delete from "+database+".mapping_parent") + execSQLRequire(t, ctx, db, + "insert into "+database+".mapping_parent values (1, 1), (1, 2)") + execSQLRequire(t, ctx, db, + "insert into "+database+".mapping_child values (10, 1)") + + // Distinct outputs for the same child remain ambiguous and the whole + // statement must roll back. + _, updateErr := db.ExecContext(ctx, + "update "+database+".mapping_parent set a = b + 1 where a = 1") + require.Error(t, updateErr) + var mysqlErr *mysql.MySQLError + require.ErrorAs(t, updateErr, &mysqlErr) + require.Equal(t, uint16(20105), mysqlErr.Number) + require.Contains(t, updateErr.Error(), "ambiguous non-unique referenced-key mapping") + + var originalParentCount, orphanCount int + require.NoError(t, db.QueryRowContext(ctx, + "select count(*) from "+database+".mapping_parent where a = 1").Scan(&originalParentCount)) + require.NoError(t, db.QueryRowContext(ctx, + "select count(*) from "+database+".mapping_child c left join "+ + database+".mapping_parent p on c.parent_a = p.a where p.a is null").Scan(&orphanCount)) + require.Equal(t, 2, originalParentCount) + require.Zero(t, orphanCount) + + execSQLRequire(t, ctx, db, "create table "+database+".set_null_parent ("+ + "a int, b int, primary key (a, b))") + execSQLRequire(t, ctx, db, "create table "+database+".set_null_child ("+ + "id int primary key, parent_a int, foreign key (parent_a) "+ + "references "+database+".set_null_parent(a) on update set null)") + execSQLRequire(t, ctx, db, + "insert into "+database+".set_null_parent values (1, 1), (1, 2)") + execSQLRequire(t, ctx, db, + "insert into "+database+".set_null_child values (10, 1)") + execSQLRequire(t, ctx, db, + "update "+database+".set_null_parent set a = b + 1 where a = 1") + var nullChildCount int + require.NoError(t, db.QueryRowContext(ctx, + "select count(*) from "+database+".set_null_child where id = 10 and parent_a is null"). + Scan(&nullChildCount)) + require.Equal(t, 1, nullChildCount) + }) + + t.Run("prepared implicit on update observes enabled foreign key checks", func(t *testing.T) { + conn, err := db.Conn(ctx) + require.NoError(t, err) + defer conn.Close() + + execConn := func(statement string) error { + _, execErr := conn.ExecContext(ctx, statement) + return execErr + } + require.NoError(t, execConn("create table "+database+".prepared_parent (id datetime primary key)")) + require.NoError(t, execConn("create table "+database+".prepared_child ("+ + "id int primary key, parent_id datetime on update current_timestamp, note int, "+ + "foreign key (parent_id) references "+database+".prepared_parent(id))")) + require.NoError(t, execConn( + "insert into "+database+".prepared_parent values ('2000-01-01 00:00:00')")) + require.NoError(t, execConn( + "insert into "+database+".prepared_child values (10, '2000-01-01 00:00:00', 1)")) + + require.NoError(t, execConn("set foreign_key_checks = 0")) + require.NoError(t, execConn("prepare stmt_26339 from 'update "+database+ + ".prepared_child set note = 2 where id = 10'")) + defer func() { + deallocateCtx, deallocateCancel := context.WithTimeout(context.Background(), 10*time.Second) + defer deallocateCancel() + _, _ = conn.ExecContext(deallocateCtx, "deallocate prepare stmt_26339") + }() + require.NoError(t, execConn("set foreign_key_checks = 1")) + executeErr := execConn("execute stmt_26339") + require.Error(t, executeErr) + var mysqlErr *mysql.MySQLError + require.ErrorAs(t, executeErr, &mysqlErr) + require.Equal(t, uint16(1452), mysqlErr.Number) + require.True(t, + strings.Contains(executeErr.Error(), "Cannot add or update a child row") || + strings.Contains(executeErr.Error(), "foreign key constraint fails"), + "expected a foreign-key violation, got %v", executeErr) + + var parentID, childParentID string + var note, orphanCount int + require.NoError(t, conn.QueryRowContext(ctx, + "select cast(id as char) from "+database+".prepared_parent").Scan(&parentID)) + require.NoError(t, conn.QueryRowContext(ctx, + "select cast(parent_id as char), note from "+database+".prepared_child where id = 10"). + Scan(&childParentID, ¬e)) + require.NoError(t, conn.QueryRowContext(ctx, + "select count(*) from "+database+".prepared_child c left join "+ + database+".prepared_parent p on c.parent_id = p.id where p.id is null").Scan(&orphanCount)) + require.Equal(t, "2000-01-01 00:00:00", parentID) + require.Equal(t, parentID, childParentID) + require.Equal(t, 1, note) + require.Zero(t, orphanCount) + }) + }) +} diff --git a/proto/plan.proto b/proto/plan.proto index a959a227d6708..745ad7d0c1443 100644 --- a/proto/plan.proto +++ b/proto/plan.proto @@ -634,6 +634,7 @@ message UpdateCtx { bool skip_insert_on_null_pk = 10; int32 insert_pk_col_idx = 11; bool count_delete_affect_rows = 12; + bool ignore_affected_rows = 13; } message InsertCtx { diff --git a/test/distributed/cases/ddl/alter_table_rename_column.result b/test/distributed/cases/ddl/alter_table_rename_column.result index 931218ed291c7..ed91770031001 100644 --- a/test/distributed/cases/ddl/alter_table_rename_column.result +++ b/test/distributed/cases/ddl/alter_table_rename_column.result @@ -242,7 +242,7 @@ delete from foreign02 where col2New = 2; update foreign01 set col2 = 'database ewueh ' where col1 = 1; internal error: column 'col2' not found in table update foreign01 set col1new = 9283923 where col1new = 1; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails select * from foreign01; col1new col2new col3 col4 1 sfhuwe 1 1 diff --git a/test/distributed/cases/foreign_key/fk_base.result b/test/distributed/cases/foreign_key/fk_base.result index f72503faecbb7..c7c4b0b2b6b88 100644 --- a/test/distributed/cases/foreign_key/fk_base.result +++ b/test/distributed/cases/foreign_key/fk_base.result @@ -51,7 +51,7 @@ create table c1 (a int, b int, foreign key f_a(a) references f1(a)); insert into f1 values (1,1), (2,2), (3,3); insert into c1 values (1,1), (2,2), (3,3); update f1 set a = 11 where b = 1; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update c1 set a = 11 where b = 1; Cannot add or update a child row: a foreign key constraint fails update c1 set a = null where b = 1; @@ -120,7 +120,7 @@ INSERT INTO t_emp VALUES (7698,'BLAKE',30,2850.00); INSERT INTO t_emp VALUES (7782,'CLARK',10,2950.00); INSERT INTO t_emp VALUES (7788,'SCOTT',20,3500.00); update t_dept set id = 50 where name = 'ACCOUNTING'; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails delete from t_dept where name = 'ACCOUNTING'; internal error: Cannot delete or update a parent row: a foreign key constraint fails update t_emp set deptId = 50 where salary < 1500; @@ -329,7 +329,7 @@ update f1 set a=a; update f1 set a=1; update f1 set a=a, b=2; update f1 set a=2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails drop table c1; drop table f1; create table f1(a int, b int, primary key (a,b)); @@ -340,7 +340,7 @@ update f1 set a=a; update f1 set a=a, b=1; update f1 set b=1, a=a; update f1 set a=a, b=2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails drop table c1; drop table f1; drop database if exists db1; diff --git a/test/distributed/cases/foreign_key/fk_self_refer2.result b/test/distributed/cases/foreign_key/fk_self_refer2.result index 00347e527c3dc..0532ac764c153 100644 --- a/test/distributed/cases/foreign_key/fk_self_refer2.result +++ b/test/distributed/cases/foreign_key/fk_self_refer2.result @@ -35,7 +35,7 @@ internal error: Cannot delete or update a parent row: a foreign key constraint f delete from t1 where a = 3; delete from t1 where a = 8; update t1 set a = 3 where a = 2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update t1 set b = NULL where a = 2; delete from t1 where a= 2; update t1 set b = NULL where a = 1; @@ -85,7 +85,7 @@ internal error: Cannot delete or update a parent row: a foreign key constraint f delete from t1 where a = 3; delete from t1 where a = 8; update t1 set a = 3 where a = 2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update t1 set b = NULL where a = 2; update t1 set a = 3 where a = 2; delete from t1 where a = 2; @@ -145,7 +145,7 @@ internal error: Cannot delete or update a parent row: a foreign key constraint f update t1 set b = NULL where a = 1; Cannot add or update a child row: a foreign key constraint fails update t1 set b = 2 where a = 1; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update t1 set c = NULL where a = 1; update t1 set b = 2 where a = 1; delete from t1 where a = 1; diff --git a/test/distributed/cases/foreign_key/fk_self_refer3.result b/test/distributed/cases/foreign_key/fk_self_refer3.result index 7369f60f7b940..00df469fe3c87 100644 --- a/test/distributed/cases/foreign_key/fk_self_refer3.result +++ b/test/distributed/cases/foreign_key/fk_self_refer3.result @@ -22,13 +22,13 @@ insert into t1 values (1,4,3,1,4,1,4); Cannot add or update a child row: a foreign key constraint fails insert into t1 values (1,4,3,1,4,1,3); update t1 set b = 5 where b = 4; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update t1 set e = 5 where b = 4; Cannot add or update a child row: a foreign key constraint fails update t1 set e = NULL where b = 4; update t1 set b = 5 where b = 4; update t1 set c = 4 where b = 5; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update t1 set g = 4 where b = 5; Cannot add or update a child row: a foreign key constraint fails update t1 set g = 2 where b = 5; diff --git a/test/distributed/cases/foreign_key/foreign_key.result b/test/distributed/cases/foreign_key/foreign_key.result index 5e33e550f155a..8de680e2665fd 100644 --- a/test/distributed/cases/foreign_key/foreign_key.result +++ b/test/distributed/cases/foreign_key/foreign_key.result @@ -21,7 +21,7 @@ internal error: Cannot add or update a child row: a foreign key constraint fails update fk_02 set col2='80' where col2='90'; Cannot add or update a child row: a foreign key constraint fails update fk_01 set col1=5 where col2=734; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails delete from fk_01 where col1='90'; internal error: Cannot delete or update a parent row: a foreign key constraint fails delete from fk_01 where col1='190'; @@ -143,9 +143,9 @@ Cannot add or update a child row: a foreign key constraint fails delete from fk_01 where col1=2 and col2='apple'; internal error: Cannot delete or update a parent row: a foreign key constraint fails update fk_01 set col1=3 where col1=2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update fk_01 set col1=1 where col1=2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails select * from fk_01; col1 col2 col3 2 yellow 20 @@ -278,7 +278,7 @@ select * from fk_02; col1 col2 col3 col4 1 aa bb 2 update fk_01 set col1=8 where col1=2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails select * from fk_01; col1 col2 col3 2 safer prow @@ -327,7 +327,7 @@ col1 col2 col3 3 ultra strong 4 aaa bbb update fk_01 set col1=8 where col1=2; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update fk_02 set col4=5 where col3='ff'; select * from fk_01; col1 col2 col3 diff --git a/test/distributed/cases/foreign_key/foreign_key_multilayer.result b/test/distributed/cases/foreign_key/foreign_key_multilayer.result index 4d8c0569d3d49..61639dab04804 100644 --- a/test/distributed/cases/foreign_key/foreign_key_multilayer.result +++ b/test/distributed/cases/foreign_key/foreign_key_multilayer.result @@ -90,21 +90,21 @@ L_COMMENT VARCHAR(44) NOT NULL, PRIMARY KEY (L_ORDERKEY, L_LINENUMBER),constraint fk_l1 foreign key(L_ORDERKEY) REFERENCES ORDERS_fk(o_orderkey),constraint fk_l2 foreign key(L_PARTKEY) REFERENCES PART_fk(P_PARTKEY),constraint fk_l3 foreign key(L_SUPPKEY) REFERENCES SUPPLIER_fk(S_SUPPKEY)); insert into lineitem_fk values(5999968,199,9991,2,46,63179.16,0.08,0.06,"R","F","1993-09-16","1993-09-21","1993-10-02","COLLECT COD","RAIL","dolites wake"); update nation_fk set n_nationkey=10 where n_nationkey=13; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update lineitem_fk set l_partkey=2 where l_suppkey=9991; Cannot add or update a child row: a foreign key constraint fails update PARTSUPP_fk set PS_PARTKEY=40; Cannot add or update a child row: a foreign key constraint fails update orders_fk set O_ORDERKEY=1 where O_CUSTKEY=12; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update supplier_fk set s_suppkey=11 where s_nationkey=13; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update customer_fk set c_nationkey=6; Cannot add or update a child row: a foreign key constraint fails update part_fk set p_partkey=200 where P_RETAILPRICE=2097.99; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails update region_fk set r_regionkey=5 where r_name="ASIA"; -internal error: Cannot delete or update a parent row: a foreign key constraint fails +Cannot delete or update a parent row: a foreign key constraint fails delete from nation_fk where n_nationkey=13; internal error: Cannot delete or update a parent row: a foreign key constraint fails select * from SUPPLIER_fk; @@ -318,7 +318,7 @@ select * from PARTSUPP_fk; ps_partkey ps_suppkey ps_availqty ps_supplycost ps_comment 199 9991 7872 606.64 according to the final pinto beans: carefully silent requests sleep final update PARTSUPP_fk set PS_PARTKEY=40; -internal error: Cannot add or update a child row: a foreign key constraint fails +Cannot add or update a child row: a foreign key constraint fails select * from lineitem_fk; l_orderkey l_partkey l_suppkey l_linenumber l_quantity l_extendedprice l_discount l_tax l_returnflag l_linestatus l_shipdate l_commitdate l_receiptdate l_shipinstruct l_shipmode l_comment 5999968 199 9991 2 46.00 63179.16 0.08 0.06 R F 1993-09-16 1993-09-21 1993-10-02 COLLECT COD RAIL dolites wake diff --git a/test/distributed/cases/foreign_key/update_modern_fk.result b/test/distributed/cases/foreign_key/update_modern_fk.result index 8e5c8ead1446d..410bf2f27a654 100644 --- a/test/distributed/cases/foreign_key/update_modern_fk.result +++ b/test/distributed/cases/foreign_key/update_modern_fk.result @@ -18,15 +18,15 @@ insert into child_single values (30, 1, 'a'); delete from child_single where id = 30; update child_single set parent_id = 3 where id = 10; select * from child_single order by id; -id parent_id note -10 3 b -20 2 NULL +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 3 ¦ b 𝄀 +20 ¦ 2 ¦ null update child_single set parent_id = 99 where id = 10; Cannot add or update a child row: a foreign key constraint fails select * from child_single order by id; -id parent_id note -10 3 b -20 2 NULL +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 3 ¦ b 𝄀 +20 ¦ 2 ¦ null set foreign_key_checks = 0; update child_single set parent_id = 99 where id = 10; set foreign_key_checks = 1; @@ -35,38 +35,16 @@ update child_single set note = 'orphan' where id = 10; insert into child_single values (30, 1, 'orphan'); Duplicate entry 'orphan' for key 'note' select * from child_single order by id; -id parent_id note -10 99 orphan -20 2 NULL -update child_single set parent_id = 1 where id = 10; -set foreign_key_checks = 0; -prepare fk_enable_checks from -'update child_single set parent_id = ? where id = ?'; -set @fk_parent_id = 98; -set @fk_child_id = 10; -set foreign_key_checks = 1; -execute fk_enable_checks using @fk_parent_id, @fk_child_id; -Cannot add or update a child row: a foreign key constraint fails -select * from child_single where id = 10; -id parent_id note -10 1 orphan -deallocate prepare fk_enable_checks; -prepare fk_disable_checks from -'update child_single set parent_id = ? where id = ?'; -set foreign_key_checks = 0; -execute fk_disable_checks using @fk_parent_id, @fk_child_id; -set foreign_key_checks = 1; -select * from child_single where id = 10; -id parent_id note -10 98 orphan -deallocate prepare fk_disable_checks; +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 99 ¦ orphan 𝄀 +20 ¦ 2 ¦ null update child_single set parent_id = 1 where id = 10; update child_single set parent_id = case id when 10 then 2 else 98 end; Cannot add or update a child row: a foreign key constraint fails select * from child_single order by id; -id parent_id note -10 1 orphan -20 2 NULL +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 1 ¦ orphan 𝄀 +20 ¦ 2 ¦ null create table parent_composite ( a int, b int, @@ -84,32 +62,17 @@ update child_composite set a = null, b = 99 where id = 1; update child_composite set a = 99, b = null where id = 2; update child_composite set a = 1, b = 1 where id = 3; select * from child_composite order by id; -id a b -1 NULL 99 -2 99 NULL -3 1 1 +➤ id[4,32,0] ¦ a[4,32,0] ¦ b[4,32,0] 𝄀 +1 ¦ null ¦ 99 𝄀 +2 ¦ 99 ¦ null 𝄀 +3 ¦ 1 ¦ 1 update child_composite set a = 98, b = 98 where id = 3; Cannot add or update a child row: a foreign key constraint fails select * from child_composite order by id; -id a b -1 NULL 99 -2 99 NULL -3 1 1 -create table parent_auto_fk ( -id int primary key -); -create table child_auto_fk ( -parent_id int auto_increment unique, -constraint fk_auto foreign key (parent_id) references parent_auto_fk(id) -); -insert into parent_auto_fk values (1); -insert into child_auto_fk values (0); -update child_auto_fk -set parent_id = if(parent_id = 1, null, parent_id); -internal error: Cannot add or update a child row: a foreign key constraint fails -select * from child_auto_fk; -parent_id -1 +➤ id[4,32,0] ¦ a[4,32,0] ¦ b[4,32,0] 𝄀 +1 ¦ null ¦ 99 𝄀 +2 ¦ 99 ¦ null 𝄀 +3 ¦ 1 ¦ 1 create table self_ref ( id int primary key, parent_id int, @@ -119,15 +82,285 @@ constraint fk_self foreign key (parent_id) references self_ref(id) insert into self_ref values (1, 1, 'root'), (2, 1, 'child'); update self_ref set name = 'changed' where id = 2; update self_ref set parent_id = 2 where id = 2; +set foreign_key_checks = 0; +update self_ref set parent_id = 99 where id = 2; +update self_ref set parent_id = 2 where id = 2; +set foreign_key_checks = 1; update self_ref set parent_id = 99 where id = 2; Cannot add or update a child row: a foreign key constraint fails select * from self_ref order by id; -id parent_id name -1 1 root -2 2 changed +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ name[12,-1,0] 𝄀 +1 ¦ 1 ¦ root 𝄀 +2 ¦ 2 ¦ changed +create table parent_restrict ( +id int primary key +); +create table child_restrict ( +id int primary key, +parent_id int, +constraint fk_parent_restrict foreign key (parent_id) +references parent_restrict(id) on update restrict +); +insert into parent_restrict values (1), (2); +insert into child_restrict values (10, 1); +update parent_restrict set id = id where id = 1; +update parent_restrict set id = 11 where id = 1; +Cannot delete or update a parent row: a foreign key constraint fails +select * from parent_restrict order by id; +➤ id[4,32,0] 𝄀 +1 𝄀 +2 +select * from child_restrict order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] 𝄀 +10 ¦ 1 +create table parent_cascade ( +id int primary key +); +create table child_cascade ( +id int primary key, +parent_id int, +note varchar(32), +unique key uk_cascade_note(note), +key idx_cascade_parent(parent_id), +constraint fk_parent_cascade foreign key (parent_id) +references parent_cascade(id) on update cascade +); +insert into parent_cascade values (1), (2); +insert into child_cascade values (10, 1, 'a'), (20, 1, 'b'), (30, 2, 'c'); +update parent_cascade set id = 11 where id = 1; +select row_count(); +➤ row_count()[-5,64,0] 𝄀 +1 +select * from parent_cascade order by id; +➤ id[4,32,0] 𝄀 +2 𝄀 +11 +select * from child_cascade order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 11 ¦ a 𝄀 +20 ¦ 11 ¦ b 𝄀 +30 ¦ 2 ¦ c +update child_cascade set note = 'd' where id = 10; +insert into child_cascade values (40, 11, 'a'); +select * from child_cascade order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 11 ¦ d 𝄀 +20 ¦ 11 ¦ b 𝄀 +30 ¦ 2 ¦ c 𝄀 +40 ¦ 11 ¦ a +create table parent_set_null ( +id int primary key +); +create table child_set_null ( +id int primary key, +parent_id int, +key idx_set_null_parent(parent_id), +constraint fk_parent_set_null foreign key (parent_id) +references parent_set_null(id) on update set null +); +insert into parent_set_null values (1), (2); +insert into child_set_null values (10, 1), (20, 1), (30, 2); +update parent_set_null set id = 11 where id = 1; +select * from parent_set_null order by id; +➤ id[4,32,0] 𝄀 +2 𝄀 +11 +select * from child_set_null order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] 𝄀 +10 ¦ null 𝄀 +20 ¦ null 𝄀 +30 ¦ 2 +create table parent_composite_action ( +a int, +b int, +primary key (a, b) +); +create table child_composite_action ( +id int primary key, +a int, +b int, +generated_sum int as (a + b), +key idx_composite_action(a, b), +key idx_generated_sum(generated_sum), +constraint fk_composite_action foreign key (a, b) +references parent_composite_action(a, b) on update cascade +); +insert into parent_composite_action values (1, 2), (3, 4); +insert into child_composite_action(id, a, b) values (10, 1, 2), (20, 3, 4); +update parent_composite_action set a = 11, b = 12 where a = 1 and b = 2; +not supported: parent foreign key action requires complete child update row closure +select row_count(); +➤ row_count()[-5,64,0] 𝄀 +0 +select * from parent_composite_action order by a, b; +➤ a[4,32,0] ¦ b[4,32,0] 𝄀 +1 ¦ 2 𝄀 +3 ¦ 4 +select * from child_composite_action order by id; +➤ id[4,32,0] ¦ a[4,32,0] ¦ b[4,32,0] ¦ generated_sum[4,32,0] 𝄀 +10 ¦ 1 ¦ 2 ¦ 3 𝄀 +20 ¦ 3 ¦ 4 ¦ 7 +create table child_second_cascade ( +id int primary key, +parent_id int, +constraint fk_second_cascade foreign key (parent_id) +references parent_cascade(id) on update cascade +); +insert into child_second_cascade values (1, 11), (2, 2); +update parent_cascade set id = 111 where id = 11; +select row_count(); +➤ row_count()[-5,64,0] 𝄀 +1 +select * from child_cascade order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 111 ¦ d 𝄀 +20 ¦ 111 ¦ b 𝄀 +30 ¦ 2 ¦ c 𝄀 +40 ¦ 111 ¦ a +select * from child_second_cascade order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] 𝄀 +1 ¦ 111 𝄀 +2 ¦ 2 +set foreign_key_checks = 0; +update parent_cascade set id = 22 where id = 2; +set foreign_key_checks = 1; +select * from parent_cascade order by id; +➤ id[4,32,0] 𝄀 +22 𝄀 +111 +select * from child_cascade order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ note[12,-1,0] 𝄀 +10 ¦ 111 ¦ d 𝄀 +20 ¦ 111 ¦ b 𝄀 +30 ¦ 2 ¦ c 𝄀 +40 ¦ 111 ¦ a +create table parent_dual_a ( +id int primary key +); +create table parent_dual_b ( +id int primary key +); +create table child_dual_fk ( +x int, +constraint fk_dual_a foreign key (x) +references parent_dual_a(id) on update cascade, +constraint fk_dual_b foreign key (x) +references parent_dual_b(id) +); +insert into parent_dual_a values (1); +insert into parent_dual_b values (1); +insert into child_dual_fk values (1); +update parent_dual_a set id = 2 where id = 1; +not supported: parent foreign key action changing child column constrained by another foreign key +select * from parent_dual_a order by id; +➤ id[4,32,0] 𝄀 +1 +select * from child_dual_fk; +➤ x[4,32,0] 𝄀 +1 +create table parent_generated_unique ( +id int primary key +); +create table child_generated_unique ( +id int primary key, +parent_id int, +u int generated always as (parent_id % 10) stored, +unique key uk_generated_unique(u), +constraint fk_generated_unique foreign key (parent_id) +references parent_generated_unique(id) on update cascade +); +insert into parent_generated_unique values (1), (12); +insert into child_generated_unique(id, parent_id) values (10, 1), (20, 12); +update parent_generated_unique set id = 2 where id = 1; +not supported: parent foreign key action requires complete child update row closure +select * from parent_generated_unique order by id; +➤ id[4,32,0] 𝄀 +1 𝄀 +12 +select * from child_generated_unique order by id; +➤ id[4,32,0] ¦ parent_id[4,32,0] ¦ u[4,32,0] 𝄀 +10 ¦ 1 ¦ 1 𝄀 +20 ¦ 12 ¦ 2 +set foreign_key_checks = 0; +create table update_preinsert_index ( +a int not null auto_increment primary key, +b varchar(25) not null, +c datetime, +key idx_b(b), +key idx_c(c) +); +insert into update_preinsert_index(b, c) +values ('a', '2020-09-08'), ('b', '2020-09-09'); +update update_preinsert_index set a = 90; +Duplicate entry '90' for key 'a' +set foreign_key_checks = 1; +drop table update_preinsert_index; +create table parent_lock_order ( +id int primary key +); +create table child_lock_order ( +id int primary key, +parent_id int, +constraint fk_lock_order foreign key (parent_id) +references parent_lock_order(id) on update cascade +); +insert into parent_lock_order values (1); +begin; +update parent_lock_order set id = 2 where id = 1; +use update_modern_fk; +set session lock_wait_timeout = 1; +begin; +insert into child_lock_order values (10, 1); +-- @regex("(?s)Lock wait timeout exceeded; try restarting transaction", true) +Lock wait timeout exceeded; try restarting transaction +rollback; +commit; +select * from parent_lock_order; +➤ id[4,32,0] 𝄀 +2 +select * from child_lock_order; +➤ id[4,32,0] ¦ parent_id[4,32,0] +drop table child_lock_order; +drop table parent_lock_order; +create table parent_nonunique_prefix ( +a int, +b int, +primary key (a, b) +); +create table child_nonunique_prefix ( +id int primary key, +parent_a int, +constraint fk_nonunique_prefix foreign key (parent_a) +references parent_nonunique_prefix(a) on update cascade +); +insert into parent_nonunique_prefix values (1, 1), (1, 2); +insert into child_nonunique_prefix values (10, 1); +update parent_nonunique_prefix set a = b + 1 where a = 1; +not supported: parent foreign key action has an ambiguous non-unique referenced-key mapping +select * from parent_nonunique_prefix order by a, b; +➤ a[4,32,0] ¦ b[4,32,0] 𝄀 +1 ¦ 1 𝄀 +1 ¦ 2 +select * from child_nonunique_prefix order by id; +➤ id[4,32,0] ¦ parent_a[4,32,0] 𝄀 +10 ¦ 1 +drop table child_nonunique_prefix; +drop table parent_nonunique_prefix; +drop table child_generated_unique; +drop table parent_generated_unique; +drop table child_dual_fk; +drop table parent_dual_b; +drop table parent_dual_a; +drop table child_second_cascade; +drop table child_composite_action; +drop table parent_composite_action; +drop table child_set_null; +drop table parent_set_null; +drop table child_cascade; +drop table parent_cascade; +drop table child_restrict; +drop table parent_restrict; drop table self_ref; -drop table child_auto_fk; -drop table parent_auto_fk; drop table child_composite; drop table parent_composite; drop table child_single; diff --git a/test/distributed/cases/foreign_key/update_modern_fk.sql b/test/distributed/cases/foreign_key/update_modern_fk.sql index 9261265946170..20c62363523c6 100644 --- a/test/distributed/cases/foreign_key/update_modern_fk.sql +++ b/test/distributed/cases/foreign_key/update_modern_fk.sql @@ -35,26 +35,6 @@ insert into child_single values (30, 1, 'orphan'); select * from child_single order by id; update child_single set parent_id = 1 where id = 10; - -set foreign_key_checks = 0; -prepare fk_enable_checks from - 'update child_single set parent_id = ? where id = ?'; -set @fk_parent_id = 98; -set @fk_child_id = 10; -set foreign_key_checks = 1; -execute fk_enable_checks using @fk_parent_id, @fk_child_id; -select * from child_single where id = 10; -deallocate prepare fk_enable_checks; - -prepare fk_disable_checks from - 'update child_single set parent_id = ? where id = ?'; -set foreign_key_checks = 0; -execute fk_disable_checks using @fk_parent_id, @fk_child_id; -set foreign_key_checks = 1; -select * from child_single where id = 10; -deallocate prepare fk_disable_checks; -update child_single set parent_id = 1 where id = 10; - update child_single set parent_id = case id when 10 then 2 else 98 end; select * from child_single order by id; @@ -82,21 +62,6 @@ select * from child_composite order by id; update child_composite set a = 98, b = 98 where id = 3; select * from child_composite order by id; -create table parent_auto_fk ( - id int primary key -); - -create table child_auto_fk ( - parent_id int auto_increment unique, - constraint fk_auto foreign key (parent_id) references parent_auto_fk(id) -); - -insert into parent_auto_fk values (1); -insert into child_auto_fk values (0); -update child_auto_fk -set parent_id = if(parent_id = 1, null, parent_id); -select * from child_auto_fk; - create table self_ref ( id int primary key, parent_id int, @@ -107,12 +72,228 @@ create table self_ref ( insert into self_ref values (1, 1, 'root'), (2, 1, 'child'); update self_ref set name = 'changed' where id = 2; update self_ref set parent_id = 2 where id = 2; +set foreign_key_checks = 0; +update self_ref set parent_id = 99 where id = 2; +update self_ref set parent_id = 2 where id = 2; +set foreign_key_checks = 1; update self_ref set parent_id = 99 where id = 2; select * from self_ref order by id; +create table parent_restrict ( + id int primary key +); + +create table child_restrict ( + id int primary key, + parent_id int, + constraint fk_parent_restrict foreign key (parent_id) + references parent_restrict(id) on update restrict +); + +insert into parent_restrict values (1), (2); +insert into child_restrict values (10, 1); +update parent_restrict set id = id where id = 1; +update parent_restrict set id = 11 where id = 1; +select * from parent_restrict order by id; +select * from child_restrict order by id; + +create table parent_cascade ( + id int primary key +); + +create table child_cascade ( + id int primary key, + parent_id int, + note varchar(32), + unique key uk_cascade_note(note), + key idx_cascade_parent(parent_id), + constraint fk_parent_cascade foreign key (parent_id) + references parent_cascade(id) on update cascade +); + +insert into parent_cascade values (1), (2); +insert into child_cascade values (10, 1, 'a'), (20, 1, 'b'), (30, 2, 'c'); +update parent_cascade set id = 11 where id = 1; +select row_count(); +select * from parent_cascade order by id; +select * from child_cascade order by id; +update child_cascade set note = 'd' where id = 10; +insert into child_cascade values (40, 11, 'a'); +select * from child_cascade order by id; + +create table parent_set_null ( + id int primary key +); + +create table child_set_null ( + id int primary key, + parent_id int, + key idx_set_null_parent(parent_id), + constraint fk_parent_set_null foreign key (parent_id) + references parent_set_null(id) on update set null +); + +insert into parent_set_null values (1), (2); +insert into child_set_null values (10, 1), (20, 1), (30, 2); +update parent_set_null set id = 11 where id = 1; +select * from parent_set_null order by id; +select * from child_set_null order by id; + +create table parent_composite_action ( + a int, + b int, + primary key (a, b) +); + +create table child_composite_action ( + id int primary key, + a int, + b int, + generated_sum int as (a + b), + key idx_composite_action(a, b), + key idx_generated_sum(generated_sum), + constraint fk_composite_action foreign key (a, b) + references parent_composite_action(a, b) on update cascade +); + +insert into parent_composite_action values (1, 2), (3, 4); +insert into child_composite_action(id, a, b) values (10, 1, 2), (20, 3, 4); +update parent_composite_action set a = 11, b = 12 where a = 1 and b = 2; +select row_count(); +select * from parent_composite_action order by a, b; +select * from child_composite_action order by id; + +create table child_second_cascade ( + id int primary key, + parent_id int, + constraint fk_second_cascade foreign key (parent_id) + references parent_cascade(id) on update cascade +); + +insert into child_second_cascade values (1, 11), (2, 2); +update parent_cascade set id = 111 where id = 11; +select row_count(); +select * from child_cascade order by id; +select * from child_second_cascade order by id; + +set foreign_key_checks = 0; +update parent_cascade set id = 22 where id = 2; +set foreign_key_checks = 1; +select * from parent_cascade order by id; +select * from child_cascade order by id; + +create table parent_dual_a ( + id int primary key +); +create table parent_dual_b ( + id int primary key +); +create table child_dual_fk ( + x int, + constraint fk_dual_a foreign key (x) + references parent_dual_a(id) on update cascade, + constraint fk_dual_b foreign key (x) + references parent_dual_b(id) +); + +insert into parent_dual_a values (1); +insert into parent_dual_b values (1); +insert into child_dual_fk values (1); +update parent_dual_a set id = 2 where id = 1; +select * from parent_dual_a order by id; +select * from child_dual_fk; + +create table parent_generated_unique ( + id int primary key +); +create table child_generated_unique ( + id int primary key, + parent_id int, + u int generated always as (parent_id % 10) stored, + unique key uk_generated_unique(u), + constraint fk_generated_unique foreign key (parent_id) + references parent_generated_unique(id) on update cascade +); +insert into parent_generated_unique values (1), (12); +insert into child_generated_unique(id, parent_id) values (10, 1), (20, 12); +update parent_generated_unique set id = 2 where id = 1; +select * from parent_generated_unique order by id; +select * from child_generated_unique order by id; + +set foreign_key_checks = 0; +create table update_preinsert_index ( + a int not null auto_increment primary key, + b varchar(25) not null, + c datetime, + key idx_b(b), + key idx_c(c) +); +insert into update_preinsert_index(b, c) +values ('a', '2020-09-08'), ('b', '2020-09-09'); +update update_preinsert_index set a = 90; +set foreign_key_checks = 1; +drop table update_preinsert_index; + +create table parent_lock_order ( + id int primary key +); +create table child_lock_order ( + id int primary key, + parent_id int, + constraint fk_lock_order foreign key (parent_id) + references parent_lock_order(id) on update cascade +); +insert into parent_lock_order values (1); +begin; +update parent_lock_order set id = 2 where id = 1; +-- @session:id=1{ +use update_modern_fk; +set session lock_wait_timeout = 1; +begin; +-- @regex("(?s)Lock wait timeout exceeded; try restarting transaction",true) +insert into child_lock_order values (10, 1); +rollback; +-- @session} +commit; +select * from parent_lock_order; +select * from child_lock_order; +drop table child_lock_order; +drop table parent_lock_order; + +create table parent_nonunique_prefix ( + a int, + b int, + primary key (a, b) +); +create table child_nonunique_prefix ( + id int primary key, + parent_a int, + constraint fk_nonunique_prefix foreign key (parent_a) + references parent_nonunique_prefix(a) on update cascade +); +insert into parent_nonunique_prefix values (1, 1), (1, 2); +insert into child_nonunique_prefix values (10, 1); +update parent_nonunique_prefix set a = b + 1 where a = 1; +select * from parent_nonunique_prefix order by a, b; +select * from child_nonunique_prefix order by id; +drop table child_nonunique_prefix; +drop table parent_nonunique_prefix; + +drop table child_generated_unique; +drop table parent_generated_unique; +drop table child_dual_fk; +drop table parent_dual_b; +drop table parent_dual_a; +drop table child_second_cascade; +drop table child_composite_action; +drop table parent_composite_action; +drop table child_set_null; +drop table parent_set_null; +drop table child_cascade; +drop table parent_cascade; +drop table child_restrict; +drop table parent_restrict; drop table self_ref; -drop table child_auto_fk; -drop table parent_auto_fk; drop table child_composite; drop table parent_composite; drop table child_single; diff --git a/test/distributed/cases/prepare/prepare_fk_action_cache.result b/test/distributed/cases/prepare/prepare_fk_action_cache.result index c2896d8d572ec..df9c314bf6399 100644 --- a/test/distributed/cases/prepare/prepare_fk_action_cache.result +++ b/test/distributed/cases/prepare/prepare_fk_action_cache.result @@ -35,4 +35,22 @@ select id, parent_id from child_delete order by id; id parent_id 10 NULL 20 NULL +create table parent_toggle(id int primary key); +create table child_toggle( +id int primary key, +parent_id int, +foreign key(parent_id) references parent_toggle(id) +); +insert into parent_toggle values (1); +insert into child_toggle values (10, 1); +set foreign_key_checks = 0; +prepare stmt_toggle_fk from 'update child_toggle set parent_id = ? where id = 10'; +set foreign_key_checks = 1; +set @missing_parent_id = 2; +execute stmt_toggle_fk using @missing_parent_id; +Cannot add or update a child row: a foreign key constraint fails +deallocate prepare stmt_toggle_fk; +select id, parent_id from child_toggle; +id parent_id +10 1 drop database prepare_fk_action_cache; diff --git a/test/distributed/cases/prepare/prepare_fk_action_cache.sql b/test/distributed/cases/prepare/prepare_fk_action_cache.sql index b6705e84704d1..7556f870a042c 100644 --- a/test/distributed/cases/prepare/prepare_fk_action_cache.sql +++ b/test/distributed/cases/prepare/prepare_fk_action_cache.sql @@ -33,4 +33,20 @@ deallocate prepare stmt_delete_fk; select id, v from parent_delete order by id; select id, parent_id from child_delete order by id; +create table parent_toggle(id int primary key); +create table child_toggle( + id int primary key, + parent_id int, + foreign key(parent_id) references parent_toggle(id) +); +insert into parent_toggle values (1); +insert into child_toggle values (10, 1); +set foreign_key_checks = 0; +prepare stmt_toggle_fk from 'update child_toggle set parent_id = ? where id = 10'; +set foreign_key_checks = 1; +set @missing_parent_id = 2; +execute stmt_toggle_fk using @missing_parent_id; +deallocate prepare stmt_toggle_fk; +select id, parent_id from child_toggle; + drop database prepare_fk_action_cache;