From f105beadcc24153a80107aa99666790ea1a0d54e Mon Sep 17 00:00:00 2001 From: sumeerbhola Date: Fri, 18 Sep 2020 23:00:59 -0400 Subject: [PATCH] [WIP] rowexec: paired joiners to accomplish left joins The paired joiners are used to accomplish left {outer,semi,anti} joins when the first joiner will produce false positives (as known to the optimizer). Currently, only the invertedJoiner can function as this first joiner but there is wording in the spec describing how this could also be useful for join expressions that can't be fully evaluated on one non-inverted index. The first joiner outputs an additional bool column representing a continuation value. This is used to demarcate groups of consecutive rows output by the first joiner that represent the same original left row. The first joiner needs to preserve input row order (the invertedJoiner always does this). The second joiner is a lookup join and handles these groups in a special manner. The second join does not need to be order preserving. Informs #53576 Prior to this, the way to do: - a left outer join with an inverted join is to do an inner join with the same ON condition, which is a pair of inverted join and lookup join, and then wrap the expression in another left join with the original left side. - a left anti join with an inverted join is to map it to a left outer join (previous bullet). - a left semi join is to map it to an inner join with the same ON condition, which is a pair of inverted join and lookup join, and then project, sort (or make the lookup join order preserving) and dedup. We expect that the alternative outlined in this PR (it excludes the optimizer changes) will be more efficient since it is simply a pairing of inverted joiner and lookup join (and the latter does not need to be order preserving). Release note: None --- pkg/sql/execinfrapb/processors_sql.pb.go | 540 ++++++++++++++--------- pkg/sql/execinfrapb/processors_sql.proto | 74 ++++ pkg/sql/rowexec/inverted_joiner.go | 30 +- pkg/sql/rowexec/joinreader.go | 176 +++++++- pkg/sql/rowexec/joinreader_strategies.go | 45 +- 5 files changed, 643 insertions(+), 222 deletions(-) diff --git a/pkg/sql/execinfrapb/processors_sql.pb.go b/pkg/sql/execinfrapb/processors_sql.pb.go index 1010ec149b37..2883d4ea8d5f 100644 --- a/pkg/sql/execinfrapb/processors_sql.pb.go +++ b/pkg/sql/execinfrapb/processors_sql.pb.go @@ -64,7 +64,7 @@ func (x *ScanVisibility) UnmarshalJSON(data []byte) error { return nil } func (ScanVisibility) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{0} } // These mirror the aggregate functions supported by sql/parser. See @@ -199,7 +199,7 @@ func (x *AggregatorSpec_Func) UnmarshalJSON(data []byte) error { return nil } func (AggregatorSpec_Func) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{12, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{12, 0} } type AggregatorSpec_Type int32 @@ -245,7 +245,7 @@ func (x *AggregatorSpec_Type) UnmarshalJSON(data []byte) error { return nil } func (AggregatorSpec_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{12, 1} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{12, 1} } type WindowerSpec_WindowFunc int32 @@ -309,7 +309,7 @@ func (x *WindowerSpec_WindowFunc) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_WindowFunc) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 0} } // Mode indicates which mode of framing is used. @@ -353,7 +353,7 @@ func (x *WindowerSpec_Frame_Mode) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_Frame_Mode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 1, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 1, 0} } // BoundType indicates which type of boundary is used. @@ -400,7 +400,7 @@ func (x *WindowerSpec_Frame_BoundType) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_Frame_BoundType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 1, 1} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 1, 1} } // Exclusion specifies the type of frame exclusion. @@ -443,7 +443,7 @@ func (x *WindowerSpec_Frame_Exclusion) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_Frame_Exclusion) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 1, 2} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 1, 2} } // ValuesCoreSpec is the core of a processor that has no inputs and generates @@ -463,7 +463,7 @@ func (m *ValuesCoreSpec) Reset() { *m = ValuesCoreSpec{} } func (m *ValuesCoreSpec) String() string { return proto.CompactTextString(m) } func (*ValuesCoreSpec) ProtoMessage() {} func (*ValuesCoreSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{0} } func (m *ValuesCoreSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -570,7 +570,7 @@ func (m *TableReaderSpec) Reset() { *m = TableReaderSpec{} } func (m *TableReaderSpec) String() string { return proto.CompactTextString(m) } func (*TableReaderSpec) ProtoMessage() {} func (*TableReaderSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{1} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{1} } func (m *TableReaderSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -625,7 +625,7 @@ func (m *IndexSkipTableReaderSpec) Reset() { *m = IndexSkipTableReaderSp func (m *IndexSkipTableReaderSpec) String() string { return proto.CompactTextString(m) } func (*IndexSkipTableReaderSpec) ProtoMessage() {} func (*IndexSkipTableReaderSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{2} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{2} } func (m *IndexSkipTableReaderSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -672,6 +672,57 @@ var xxx_messageInfo_IndexSkipTableReaderSpec proto.InternalMessageInfo // // If performing an index join (where a = c and b = d) (lookup columns is []): // Internal columns: | c | d | e | +// +// There is a special case when a "join reader" is used as the second join in +// a pair of joins to accomplish a LEFT_OUTER, LEFT_SEMI or LEFT_ANTI join. +// The first join in this pair of joins is unable to precisely evaluate the +// join condition and produces false positives. This is typical when the first +// join is a inverted join (see InvertedJoinerSpec), but can also be the case +// when the first join is being evaluated over an index that does not have all +// the columns needed to evaluate the join condition. The first join outputs +// rows in sorted order of the original left columns. The input stream columns +// for the second join are a combination of the original left columns and the +// lookup columns. The first join additionally adds a continuation column that +// demarcates a group of successive rows that correspond to an original left +// row. The first row in a group contains false (since it is not a +// continuation of the group) and successive rows contain true. +// +// The mapping from original join to the pair of joins is: +// LEFT_OUTER => LEFT_OUTER, LEFT_OUTER +// LEFT_SEMI => INNER, LEFT_SEMI (better than doing INNER, INNER, SORT, DISTINCT) +// LEFT_ANTI => LEFT_OUTER, LEFT_ANTI. +// where the first join always preserves order. +// +// More specifically, consider a lookup join example where the input stream +// columns are: | a | b | c | d | cont |. +// The lookup column is | d |. And the table columns are | e | f | with +// d = e. +// This join reader can see input of the form +// a1, b1, c1, d1, false +// a1, b1, c1, d2, true +// a1, b2, c1, null, false // when the first join is LEFT_OUTER +// a2, b1, c1, d3, false +// a2, b2, c1, d4, true +// +// Say both the results for (a1, b1, c1) are false positives, and the first +// of the (a2, b1, c1) result is a false positive. +// The output for LEFT_OUTER: +// a1, b1, c1, d1, null, null +// a1, b2, c1, null, null, null +// a2, b2, c1, d4, d4, f1 +// The d column is not part of the original left row, so will be projected +// away after the join. +// +// The output for LEFT_ANTI: +// a1, b1, c1, d1 +// a1, b2, c1, null +// Again, the d column will be projected away after the join. +// +// The output for LEFT_SEMI: +// a1, b1, c1, d3 +// Again, the d column will be projected away after the join. +// +// This special case is type JoinReaderSpec struct { Table descpb.TableDescriptor `protobuf:"bytes,1,opt,name=table" json:"table"` // If 0, we use the primary index; each row in the input stream has a value @@ -726,13 +777,16 @@ type JoinReaderSpec struct { // result of the secondary index joined against the primary index is // expected to contain the materialized system columns. HasSystemColumns bool `protobuf:"varint,13,opt,name=has_system_columns,json=hasSystemColumns" json:"has_system_columns"` + // LeftJoinWithPairedJoiner is used when a left {outer,anti,semi} join is + // being achieved by pairing two joins. See the comment above. + LeftJoinWithPairedJoiner bool `protobuf:"varint,14,opt,name=left_join_with_paired_joiner,json=leftJoinWithPairedJoiner" json:"left_join_with_paired_joiner"` } func (m *JoinReaderSpec) Reset() { *m = JoinReaderSpec{} } func (m *JoinReaderSpec) String() string { return proto.CompactTextString(m) } func (*JoinReaderSpec) ProtoMessage() {} func (*JoinReaderSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{3} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{3} } func (m *JoinReaderSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -776,7 +830,7 @@ func (m *SorterSpec) Reset() { *m = SorterSpec{} } func (m *SorterSpec) String() string { return proto.CompactTextString(m) } func (*SorterSpec) ProtoMessage() {} func (*SorterSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{4} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{4} } func (m *SorterSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -838,7 +892,7 @@ func (m *DistinctSpec) Reset() { *m = DistinctSpec{} } func (m *DistinctSpec) String() string { return proto.CompactTextString(m) } func (*DistinctSpec) ProtoMessage() {} func (*DistinctSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{5} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{5} } func (m *DistinctSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -873,7 +927,7 @@ func (m *OrdinalitySpec) Reset() { *m = OrdinalitySpec{} } func (m *OrdinalitySpec) String() string { return proto.CompactTextString(m) } func (*OrdinalitySpec) ProtoMessage() {} func (*OrdinalitySpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{6} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{6} } func (m *OrdinalitySpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -931,7 +985,7 @@ func (m *ZigzagJoinerSpec) Reset() { *m = ZigzagJoinerSpec{} } func (m *ZigzagJoinerSpec) String() string { return proto.CompactTextString(m) } func (*ZigzagJoinerSpec) ProtoMessage() {} func (*ZigzagJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{7} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{7} } func (m *ZigzagJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1007,7 +1061,7 @@ func (m *MergeJoinerSpec) Reset() { *m = MergeJoinerSpec{} } func (m *MergeJoinerSpec) String() string { return proto.CompactTextString(m) } func (*MergeJoinerSpec) ProtoMessage() {} func (*MergeJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{8} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{8} } func (m *MergeJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1094,7 +1148,7 @@ func (m *HashJoinerSpec) Reset() { *m = HashJoinerSpec{} } func (m *HashJoinerSpec) String() string { return proto.CompactTextString(m) } func (*HashJoinerSpec) ProtoMessage() {} func (*HashJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{9} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{9} } func (m *HashJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1133,6 +1187,17 @@ var xxx_messageInfo_HashJoinerSpec proto.InternalMessageInfo // that was indexed). For LEFT_SEMI and LEFT_ANTI, the "internal columns" are // the columns of the left input. // +// In many cases, the inverted join will contain false positives wrt the +// original join condition. This is handled by pairing it with a lookup join. +// This pairing works naturally when the user query specified INNER, by +// running an INNER inverted join followed by INNER lookup join. For a user +// query with LEFT_OUTER/LEFT_ANTI, the inverted join is run as a LEFT_OUTER +// with a special mode that outputs an additional bool column that represents +// whether this row is a continuation of a group. This is paired with a lookup +// join that also knows about the semantics of this bool column. For a user +// query with LEFT_SEMI, the inverted join is run as an INNER join with the +// same special mode. See the JoinReaderSpec for an example. +// // Example: // Input stream columns: | a | b | // Table columns: | c | d | e | @@ -1147,6 +1212,9 @@ var xxx_messageInfo_HashJoinerSpec proto.InternalMessageInfo // Internal columns for INNER and LEFT_OUTER: | a | b | c | d | e | // where d, e are not populated. // Internal columns for LEFT_SEMI and LEFT_ANTI: | a | b | +// +// For a LEFT_OUTER with OutputGroupCountForLeftJoin = true, the internal +// columns including an additional bool column as the last column. type InvertedJoinerSpec struct { Table descpb.TableDescriptor `protobuf:"bytes,1,opt,name=table" json:"table"` // The ID of the inverted index. The first column in the index is the @@ -1185,13 +1253,17 @@ type InvertedJoinerSpec struct { // Indicates that the inverted joiner should maintain the ordering of the // input stream. MaintainOrdering bool `protobuf:"varint,7,opt,name=maintain_ordering,json=maintainOrdering" json:"maintain_ordering"` + // Indicates that the join should output a continuation column that + // indicates whether a row is a continuation of a group corresponding to a + // left row. + OutputContinuationForLeftJoin bool `protobuf:"varint,8,opt,name=output_continuation_for_left_join,json=outputContinuationForLeftJoin" json:"output_continuation_for_left_join"` } func (m *InvertedJoinerSpec) Reset() { *m = InvertedJoinerSpec{} } func (m *InvertedJoinerSpec) String() string { return proto.CompactTextString(m) } func (*InvertedJoinerSpec) ProtoMessage() {} func (*InvertedJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{10} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{10} } func (m *InvertedJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1252,7 +1324,7 @@ func (m *InvertedFiltererSpec) Reset() { *m = InvertedFiltererSpec{} } func (m *InvertedFiltererSpec) String() string { return proto.CompactTextString(m) } func (*InvertedFiltererSpec) ProtoMessage() {} func (*InvertedFiltererSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{11} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{11} } func (m *InvertedFiltererSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1290,7 +1362,7 @@ func (m *InvertedFiltererSpec_PreFiltererSpec) Reset() { *m = InvertedFi func (m *InvertedFiltererSpec_PreFiltererSpec) String() string { return proto.CompactTextString(m) } func (*InvertedFiltererSpec_PreFiltererSpec) ProtoMessage() {} func (*InvertedFiltererSpec_PreFiltererSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{11, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{11, 0} } func (m *InvertedFiltererSpec_PreFiltererSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1336,7 +1408,7 @@ func (m *AggregatorSpec) Reset() { *m = AggregatorSpec{} } func (m *AggregatorSpec) String() string { return proto.CompactTextString(m) } func (*AggregatorSpec) ProtoMessage() {} func (*AggregatorSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{12} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{12} } func (m *AggregatorSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1387,7 +1459,7 @@ func (m *AggregatorSpec_Aggregation) Reset() { *m = AggregatorSpec_Aggre func (m *AggregatorSpec_Aggregation) String() string { return proto.CompactTextString(m) } func (*AggregatorSpec_Aggregation) ProtoMessage() {} func (*AggregatorSpec_Aggregation) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{12, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{12, 0} } func (m *AggregatorSpec_Aggregation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1427,7 +1499,7 @@ func (m *ProjectSetSpec) Reset() { *m = ProjectSetSpec{} } func (m *ProjectSetSpec) String() string { return proto.CompactTextString(m) } func (*ProjectSetSpec) ProtoMessage() {} func (*ProjectSetSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{13} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{13} } func (m *ProjectSetSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1469,7 +1541,7 @@ func (m *WindowerSpec) Reset() { *m = WindowerSpec{} } func (m *WindowerSpec) String() string { return proto.CompactTextString(m) } func (*WindowerSpec) ProtoMessage() {} func (*WindowerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14} } func (m *WindowerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1505,7 +1577,7 @@ func (m *WindowerSpec_Func) Reset() { *m = WindowerSpec_Func{} } func (m *WindowerSpec_Func) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Func) ProtoMessage() {} func (*WindowerSpec_Func) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 0} } func (m *WindowerSpec_Func) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1541,7 +1613,7 @@ func (m *WindowerSpec_Frame) Reset() { *m = WindowerSpec_Frame{} } func (m *WindowerSpec_Frame) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Frame) ProtoMessage() {} func (*WindowerSpec_Frame) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 1} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 1} } func (m *WindowerSpec_Frame) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1582,7 +1654,7 @@ func (m *WindowerSpec_Frame_Bound) Reset() { *m = WindowerSpec_Frame_Bou func (m *WindowerSpec_Frame_Bound) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Frame_Bound) ProtoMessage() {} func (*WindowerSpec_Frame_Bound) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 1, 0} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 1, 0} } func (m *WindowerSpec_Frame_Bound) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1618,7 +1690,7 @@ func (m *WindowerSpec_Frame_Bounds) Reset() { *m = WindowerSpec_Frame_Bo func (m *WindowerSpec_Frame_Bounds) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Frame_Bounds) ProtoMessage() {} func (*WindowerSpec_Frame_Bounds) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 1, 1} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 1, 1} } func (m *WindowerSpec_Frame_Bounds) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1668,7 +1740,7 @@ func (m *WindowerSpec_WindowFn) Reset() { *m = WindowerSpec_WindowFn{} } func (m *WindowerSpec_WindowFn) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_WindowFn) ProtoMessage() {} func (*WindowerSpec_WindowFn) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_07823ff4d8e0340a, []int{14, 2} + return fileDescriptor_processors_sql_3a604963f9a66bbd, []int{14, 2} } func (m *WindowerSpec_WindowFn) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1998,6 +2070,14 @@ func (m *JoinReaderSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0 } i++ + dAtA[i] = 0x70 + i++ + if m.LeftJoinWithPairedJoiner { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -2383,6 +2463,14 @@ func (m *InvertedJoinerSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0 } i++ + dAtA[i] = 0x40 + i++ + if m.OutputContinuationForLeftJoin { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -2963,6 +3051,7 @@ func (m *JoinReaderSpec) Size() (n int) { n += 1 + sovProcessorsSql(uint64(m.LockingWaitPolicy)) n += 2 n += 2 + n += 2 return n } @@ -3109,6 +3198,7 @@ func (m *InvertedJoinerSpec) Size() (n int) { n += 1 + l + sovProcessorsSql(uint64(l)) n += 1 + sovProcessorsSql(uint64(m.Type)) n += 2 + n += 2 return n } @@ -4320,6 +4410,26 @@ func (m *JoinReaderSpec) Unmarshal(dAtA []byte) error { } } m.HasSystemColumns = bool(v != 0) + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LeftJoinWithPairedJoiner", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProcessorsSql + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.LeftJoinWithPairedJoiner = bool(v != 0) default: iNdEx = preIndex skippy, err := skipProcessorsSql(dAtA[iNdEx:]) @@ -5701,6 +5811,26 @@ func (m *InvertedJoinerSpec) Unmarshal(dAtA []byte) error { } } m.MaintainOrdering = bool(v != 0) + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OutputContinuationForLeftJoin", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProcessorsSql + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.OutputContinuationForLeftJoin = bool(v != 0) default: iNdEx = preIndex skippy, err := skipProcessorsSql(dAtA[iNdEx:]) @@ -7595,178 +7725,182 @@ var ( ) func init() { - proto.RegisterFile("sql/execinfrapb/processors_sql.proto", fileDescriptor_processors_sql_07823ff4d8e0340a) -} - -var fileDescriptor_processors_sql_07823ff4d8e0340a = []byte{ - // 2693 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x6f, 0x1b, 0xc7, - 0x15, 0xd7, 0xf2, 0x43, 0x22, 0x1f, 0x3f, 0x34, 0x1e, 0x3b, 0x31, 0xc3, 0xb4, 0xb2, 0x4c, 0xa7, - 0x89, 0xec, 0x38, 0x52, 0xa3, 0x16, 0x29, 0x92, 0x16, 0x45, 0x57, 0xe4, 0x52, 0xa6, 0x4c, 0xed, - 0xca, 0xcb, 0xa5, 0xec, 0x24, 0x40, 0x06, 0x2b, 0x72, 0x44, 0x6d, 0xbc, 0xdc, 0xa5, 0x76, 0x97, - 0x96, 0x94, 0x63, 0x81, 0xa2, 0xa7, 0x02, 0x2d, 0x7a, 0xe9, 0xa9, 0x08, 0x0a, 0xf4, 0x3f, 0xe8, - 0xb9, 0xa7, 0x1e, 0x0c, 0xf4, 0x92, 0x53, 0x1b, 0xa0, 0x40, 0xd1, 0x38, 0x7f, 0x44, 0xd1, 0x5b, - 0x31, 0xb3, 0xb3, 0xab, 0x25, 0x21, 0x3a, 0x61, 0xec, 0xc4, 0x17, 0x81, 0xf3, 0x3e, 0x7e, 0xf3, - 0xbe, 0xe6, 0xcd, 0x9b, 0x15, 0xbc, 0xe6, 0x1f, 0xdb, 0x1b, 0xf4, 0x94, 0xf6, 0x2c, 0xe7, 0xd0, - 0x33, 0x47, 0x07, 0x1b, 0x23, 0xcf, 0xed, 0x51, 0xdf, 0x77, 0x3d, 0x9f, 0xf8, 0xc7, 0xf6, 0xfa, - 0xc8, 0x73, 0x03, 0x17, 0x57, 0x7a, 0x6e, 0xef, 0xa1, 0xe7, 0x9a, 0xbd, 0xa3, 0x75, 0x46, 0xec, - 0x5b, 0x7e, 0xe0, 0x1f, 0xdb, 0xde, 0xd8, 0xa9, 0xde, 0x60, 0xfa, 0x3d, 0x33, 0x30, 0x6d, 0x77, - 0xb0, 0xd1, 0xa7, 0x7e, 0x6f, 0x74, 0xb0, 0xe1, 0x07, 0xde, 0xb8, 0x17, 0x8c, 0x3d, 0xda, 0x0f, - 0xd5, 0xab, 0xb5, 0x0b, 0x84, 0x3e, 0x76, 0x2d, 0x87, 0x04, 0x67, 0x23, 0x2a, 0x64, 0x56, 0x2f, - 0x90, 0xb1, 0xdd, 0xde, 0x43, 0xcb, 0x19, 0x08, 0x89, 0x97, 0x98, 0x04, 0xd3, 0xf0, 0xc3, 0xbf, - 0x82, 0x5c, 0x9d, 0xf6, 0xa0, 0x6f, 0x06, 0xa6, 0xe0, 0xfd, 0xe0, 0x29, 0xde, 0x1d, 0x98, 0x7e, - 0xb4, 0xf7, 0x2d, 0x26, 0xe6, 0x8e, 0x82, 0x0d, 0xcb, 0x79, 0x44, 0xbd, 0x80, 0xf6, 0xe9, 0xe9, - 0xc8, 0xdb, 0xf0, 0x47, 0xa6, 0x43, 0xd8, 0x2f, 0xea, 0xfb, 0x96, 0xeb, 0x08, 0xd9, 0x2b, 0x03, - 0x77, 0xe0, 0xf2, 0x9f, 0x1b, 0xec, 0x57, 0x48, 0xad, 0xfd, 0x5e, 0x82, 0xf2, 0xbe, 0x69, 0x8f, - 0xa9, 0x5f, 0x77, 0x3d, 0xda, 0x19, 0xd1, 0x1e, 0xae, 0xc3, 0x52, 0xcf, 0xb5, 0xc7, 0x43, 0xc7, - 0xaf, 0x48, 0xab, 0xe9, 0xb5, 0xc2, 0xe6, 0x8d, 0xf5, 0x59, 0x51, 0x5c, 0x6f, 0x98, 0xc1, 0x78, - 0xd8, 0x72, 0x0e, 0xdd, 0xad, 0xcc, 0xe3, 0x7f, 0x5f, 0x5b, 0xd0, 0x23, 0x4d, 0xfc, 0x2a, 0xe4, - 0x3d, 0xf3, 0x84, 0x1c, 0x9c, 0x05, 0xd4, 0xaf, 0xa4, 0x56, 0xd3, 0x6b, 0x45, 0x3d, 0xe7, 0x99, - 0x27, 0x5b, 0x6c, 0x8d, 0xaf, 0x41, 0xce, 0x19, 0x0f, 0x89, 0xe7, 0x9e, 0xf8, 0x95, 0xf4, 0xaa, - 0xb4, 0x96, 0x89, 0xb4, 0x9d, 0xf1, 0x50, 0x77, 0x4f, 0xfc, 0xda, 0xbf, 0xb2, 0xb0, 0x6c, 0x98, - 0x07, 0x36, 0xd5, 0xa9, 0xd9, 0xa7, 0x1e, 0x37, 0x6b, 0x0b, 0xb2, 0x01, 0x23, 0x55, 0xa4, 0x55, - 0x69, 0xad, 0xb0, 0xf9, 0xfa, 0x94, 0x51, 0xfe, 0xb1, 0xcd, 0x03, 0xc3, 0xd5, 0x1a, 0xd4, 0xef, - 0x79, 0xd6, 0x28, 0x70, 0x3d, 0x81, 0x1c, 0xaa, 0xe2, 0xeb, 0x90, 0xb7, 0x9c, 0x3e, 0x3d, 0x25, - 0x56, 0xff, 0xb4, 0x92, 0x5a, 0x95, 0xd6, 0x4a, 0x82, 0x9f, 0xe3, 0xe4, 0x56, 0xff, 0x14, 0xaf, - 0xc0, 0x92, 0x47, 0x1f, 0x51, 0xcf, 0xa7, 0xdc, 0xb4, 0x5c, 0x64, 0x9a, 0x20, 0x62, 0x05, 0xb2, - 0x2c, 0xbe, 0x7e, 0x25, 0xc3, 0x63, 0x73, 0x73, 0x76, 0x6c, 0x26, 0x1c, 0x30, 0x9d, 0xc8, 0x12, - 0xae, 0x8d, 0x6f, 0x00, 0xd8, 0xd6, 0xd0, 0x0a, 0xc8, 0x91, 0xe5, 0x04, 0x95, 0xec, 0xaa, 0xb4, - 0x96, 0x16, 0x02, 0x79, 0x4e, 0xbf, 0x63, 0x39, 0x01, 0x8b, 0x93, 0xe5, 0x93, 0xde, 0x11, 0xed, - 0x3d, 0xac, 0x2c, 0x26, 0x8d, 0xb1, 0xfc, 0x3a, 0x23, 0x62, 0x15, 0xe0, 0x91, 0xe5, 0x5b, 0x07, - 0x96, 0x6d, 0x05, 0x67, 0x95, 0xa5, 0x55, 0x69, 0xad, 0xbc, 0xb9, 0x36, 0xdb, 0xa2, 0x4e, 0xcf, - 0x74, 0xf6, 0x63, 0x79, 0x01, 0x96, 0x40, 0xc0, 0x3f, 0x85, 0xab, 0x43, 0xf3, 0x94, 0x04, 0xd6, - 0x90, 0xfa, 0x81, 0x39, 0x1c, 0x11, 0x73, 0x40, 0x89, 0x63, 0x3a, 0xae, 0x5f, 0xc9, 0x27, 0xf2, - 0x74, 0x65, 0x68, 0x9e, 0x1a, 0x91, 0x8c, 0x3c, 0xa0, 0x2a, 0x93, 0xc0, 0x1f, 0x02, 0x12, 0x75, - 0x4f, 0xfc, 0xc0, 0xa3, 0xce, 0x20, 0x38, 0xaa, 0x00, 0x37, 0xe9, 0xd6, 0x8c, 0x5c, 0x31, 0x7b, - 0xda, 0xa1, 0x4a, 0x47, 0x68, 0x88, 0x1d, 0x96, 0xed, 0x49, 0x32, 0x3e, 0x80, 0xcb, 0x11, 0xf8, - 0x89, 0x69, 0x05, 0x64, 0xe4, 0xda, 0x56, 0xef, 0xac, 0x52, 0xe0, 0xf8, 0xb7, 0xbf, 0x1a, 0xff, - 0xbe, 0x69, 0x05, 0x7b, 0x5c, 0x47, 0xec, 0x70, 0xc9, 0x9e, 0x66, 0xe0, 0xd7, 0xa1, 0x30, 0x32, - 0x3d, 0xd3, 0xb6, 0xa9, 0x6d, 0x7d, 0x42, 0x2b, 0xc5, 0x44, 0xc4, 0x93, 0x0c, 0xbc, 0x09, 0xf8, - 0xc8, 0xf4, 0x89, 0x7f, 0xe6, 0x07, 0x74, 0x48, 0xa2, 0xb3, 0x52, 0x4e, 0x88, 0xa3, 0x23, 0xd3, - 0xef, 0x70, 0x76, 0x3d, 0xe4, 0xee, 0x64, 0x72, 0x39, 0x94, 0xdf, 0xc9, 0xe4, 0x4a, 0xa8, 0x5c, - 0xfb, 0x5f, 0x1a, 0x2a, 0x2d, 0x56, 0x6f, 0x9d, 0x87, 0xd6, 0xe8, 0x05, 0x95, 0x79, 0x5c, 0xc6, - 0xe9, 0x67, 0x2a, 0xe3, 0xc9, 0x02, 0xcc, 0x3c, 0x73, 0x01, 0x26, 0x4e, 0x5f, 0xf6, 0xa2, 0xd3, - 0x77, 0x51, 0x8d, 0x2d, 0x7e, 0xcb, 0x35, 0xb6, 0xf4, 0x1c, 0x6b, 0xac, 0xf6, 0x45, 0x16, 0xca, - 0x3b, 0xae, 0xe5, 0x7c, 0xf7, 0x19, 0xbf, 0x09, 0x65, 0xdb, 0x75, 0x1f, 0x8e, 0x47, 0x71, 0xc5, - 0xb2, 0xd4, 0x97, 0xb6, 0x52, 0x48, 0xd2, 0x4b, 0x21, 0x47, 0x14, 0x2b, 0xbb, 0x01, 0xdc, 0xf0, - 0x06, 0xe1, 0x29, 0x2d, 0x6c, 0xbe, 0x36, 0x3b, 0xa5, 0x4a, 0x7c, 0xcf, 0x88, 0x1d, 0x17, 0x5d, - 0x87, 0xd1, 0xf0, 0xbb, 0x90, 0x61, 0xb7, 0x9d, 0x48, 0xcf, 0xb5, 0x19, 0x5e, 0xb1, 0x58, 0x18, - 0x67, 0x23, 0x2a, 0x94, 0xb9, 0xca, 0x73, 0x6f, 0x6b, 0xef, 0xc2, 0xcb, 0x93, 0xae, 0x13, 0xd3, - 0xa3, 0xe4, 0x21, 0x3d, 0xab, 0xe4, 0x12, 0x45, 0x76, 0x79, 0x22, 0x08, 0xb2, 0x47, 0xef, 0xd2, - 0xb3, 0x0b, 0x0b, 0x2e, 0xff, 0x2d, 0x17, 0x1c, 0x3c, 0xcf, 0xa6, 0xf6, 0x36, 0x5c, 0x1a, 0x9a, - 0x96, 0x13, 0x98, 0x96, 0x43, 0x5c, 0xaf, 0x4f, 0x3d, 0xcb, 0x19, 0xf0, 0xb6, 0x19, 0xf7, 0xaa, - 0x88, 0xad, 0x09, 0xee, 0x8c, 0xfe, 0x56, 0xfa, 0x8a, 0xfe, 0x96, 0x45, 0x8b, 0x3b, 0x99, 0x5c, - 0x11, 0x95, 0xd8, 0x4c, 0x01, 0x1d, 0xd7, 0x0b, 0x44, 0x7d, 0xdf, 0x83, 0x65, 0x77, 0x1c, 0x8c, - 0xc6, 0xc1, 0xf9, 0xfe, 0x61, 0xa5, 0xd7, 0x66, 0xa7, 0x34, 0xb2, 0x45, 0xec, 0x57, 0x0e, 0x01, - 0x92, 0x16, 0x46, 0x58, 0x64, 0x68, 0x06, 0xbd, 0x23, 0x62, 0x53, 0x67, 0xa2, 0xee, 0x51, 0xc4, - 0xdf, 0x65, 0xec, 0x36, 0x75, 0x6a, 0x7f, 0x95, 0xa0, 0xd8, 0xb0, 0xfc, 0xc0, 0x72, 0x7a, 0x01, - 0xb7, 0xeb, 0x0d, 0x58, 0xe6, 0x42, 0xb4, 0x4f, 0x92, 0xf3, 0x4e, 0x49, 0x2f, 0x0b, 0x72, 0x74, - 0x1c, 0x6e, 0x02, 0xea, 0x0b, 0xc5, 0x58, 0x32, 0xc5, 0x25, 0x97, 0x23, 0x7a, 0x24, 0xba, 0x09, - 0xd8, 0x19, 0xdb, 0x76, 0x58, 0x60, 0x11, 0x73, 0x62, 0x90, 0x40, 0x9c, 0x2f, 0x7b, 0x34, 0xb2, - 0x05, 0xbf, 0x0e, 0x45, 0xea, 0x79, 0xae, 0x47, 0x5c, 0x87, 0xf4, 0xc7, 0x23, 0x7e, 0xe4, 0xf2, - 0x51, 0x15, 0x73, 0x8e, 0xe6, 0x34, 0xc6, 0xa3, 0x1a, 0x82, 0xb2, 0xe6, 0xf5, 0x2d, 0xc7, 0x64, - 0x35, 0xcd, 0x3c, 0xa8, 0xfd, 0x21, 0x0d, 0xe8, 0x03, 0x6b, 0xf0, 0x89, 0x39, 0x60, 0xc7, 0x48, - 0x84, 0xbb, 0x01, 0x8b, 0xbc, 0x27, 0x44, 0xd3, 0xdb, 0x7c, 0xfd, 0x44, 0xe8, 0xe2, 0x26, 0x00, - 0x3d, 0x9e, 0xf0, 0xb6, 0xb0, 0x79, 0x7d, 0x76, 0xbe, 0x84, 0xff, 0xd1, 0x08, 0x43, 0x8f, 0xcf, - 0x63, 0x57, 0x0e, 0x1b, 0x93, 0x1b, 0x9a, 0x3e, 0xd1, 0x75, 0x38, 0x47, 0xf8, 0xf4, 0x9c, 0xba, - 0xce, 0x5d, 0x28, 0x1e, 0x5a, 0xa7, 0xb4, 0x4f, 0x1e, 0xf1, 0xa1, 0xb6, 0x92, 0xe5, 0x96, 0x3f, - 0xa5, 0x79, 0x4c, 0x0e, 0xbf, 0x7a, 0x81, 0x6b, 0x87, 0xc4, 0x67, 0x68, 0x61, 0xb5, 0x7f, 0xa4, - 0x61, 0x79, 0x97, 0x7a, 0x03, 0x9a, 0xc8, 0xcc, 0x2e, 0x94, 0x6c, 0x7a, 0xf8, 0x0c, 0xc7, 0xa0, - 0xc8, 0xd4, 0xe3, 0x43, 0xa0, 0x41, 0xd9, 0xb3, 0x06, 0x47, 0x09, 0xbc, 0xd4, 0x9c, 0x78, 0x25, - 0xae, 0x1f, 0x03, 0x26, 0x12, 0x90, 0x7d, 0x11, 0x6d, 0xff, 0x26, 0x94, 0xd8, 0xe1, 0x20, 0xf4, - 0x78, 0x6c, 0xc6, 0x9d, 0x3f, 0x3a, 0x37, 0x45, 0xc6, 0x52, 0x04, 0x07, 0xbf, 0x07, 0x57, 0x79, - 0x28, 0xcf, 0x6b, 0x74, 0x46, 0x4b, 0xa7, 0x87, 0x81, 0x72, 0x3c, 0xd9, 0xd2, 0x7f, 0x06, 0x95, - 0x30, 0x6e, 0x17, 0x28, 0xe7, 0x13, 0xca, 0x57, 0xb8, 0xd4, 0x94, 0x76, 0xed, 0x77, 0x69, 0x28, - 0xdf, 0x31, 0xfd, 0xa3, 0x44, 0x5e, 0x6f, 0xc1, 0xf2, 0x94, 0x31, 0x61, 0x23, 0x11, 0x57, 0x6b, - 0xd2, 0x04, 0x7c, 0x1b, 0xd0, 0xf4, 0xe6, 0x61, 0x2f, 0xe1, 0xc2, 0xe5, 0xc9, 0x2d, 0x5f, 0x78, - 0x46, 0xde, 0x84, 0xf2, 0x90, 0x15, 0xf1, 0x79, 0x87, 0x4c, 0xa6, 0xa4, 0x14, 0xf2, 0x22, 0x63, - 0x5f, 0x5c, 0x4e, 0x7e, 0x95, 0x06, 0xdc, 0x12, 0x2f, 0xe0, 0x44, 0x5e, 0xbe, 0xa3, 0xc1, 0x4a, - 0x83, 0x52, 0xf4, 0xfc, 0xfe, 0xa6, 0xdd, 0xab, 0x18, 0x01, 0xf0, 0x84, 0xbd, 0xe8, 0xac, 0x5f, - 0x38, 0x32, 0x2c, 0x3d, 0x6d, 0x64, 0xd8, 0xc9, 0xe4, 0xd2, 0x28, 0x53, 0xfb, 0x53, 0x1a, 0xae, - 0x44, 0x79, 0x68, 0x5a, 0x76, 0x40, 0x3d, 0x91, 0x89, 0x75, 0x40, 0x71, 0x88, 0x7a, 0xae, 0xcd, - 0x83, 0x29, 0x25, 0x82, 0x59, 0x8e, 0xb8, 0x75, 0xd7, 0x66, 0x21, 0xfd, 0x68, 0x3a, 0xa4, 0x61, - 0x67, 0xfb, 0xd1, 0x94, 0x17, 0xee, 0x28, 0x58, 0x4f, 0x7e, 0xf9, 0x58, 0x67, 0x0f, 0x94, 0xf3, - 0x88, 0xec, 0x79, 0x6e, 0xe0, 0x5e, 0x18, 0xe1, 0x8f, 0xe1, 0xd2, 0xc8, 0xa3, 0xe4, 0x50, 0xd8, - 0x48, 0xfc, 0x11, 0xed, 0xf1, 0x48, 0x15, 0x36, 0x7f, 0x3e, 0x3b, 0xd6, 0x17, 0xb9, 0xb6, 0xbe, - 0xe7, 0xd1, 0xe4, 0x5a, 0x5f, 0x1e, 0x4d, 0x12, 0xaa, 0xbf, 0x91, 0x60, 0x79, 0x4a, 0x08, 0xef, - 0x00, 0x9c, 0x7f, 0x9f, 0x11, 0xe5, 0x39, 0x4f, 0x92, 0x13, 0xda, 0x78, 0x5d, 0x24, 0x3a, 0x0c, - 0x51, 0x75, 0x3a, 0xd1, 0x74, 0xb8, 0x1e, 0x7e, 0x74, 0x32, 0xc4, 0xcd, 0xf4, 0xf7, 0x1c, 0x94, - 0xe5, 0xc1, 0xc0, 0xa3, 0x03, 0x33, 0x70, 0x43, 0x73, 0xae, 0x03, 0x0c, 0x3c, 0x37, 0x1c, 0x8f, - 0x93, 0xed, 0x28, 0xcf, 0xa9, 0x75, 0xd7, 0xf6, 0xf1, 0x47, 0x50, 0x34, 0x85, 0x92, 0xe5, 0xc6, - 0xcf, 0xc6, 0x1f, 0xcf, 0xb6, 0x79, 0x72, 0x8b, 0x78, 0x99, 0xa8, 0xf9, 0x24, 0x1e, 0xfe, 0xa1, - 0x98, 0xe8, 0x68, 0x9f, 0x24, 0x4c, 0xc9, 0xc4, 0xa6, 0x20, 0xc1, 0xdd, 0x8e, 0x2d, 0xda, 0x16, - 0x7e, 0x67, 0x79, 0x81, 0xbf, 0xf5, 0xb5, 0x2d, 0x99, 0x2e, 0xf7, 0xea, 0xaf, 0x53, 0x50, 0x48, - 0x98, 0xc7, 0x80, 0x0f, 0xc7, 0x4e, 0x8f, 0xa7, 0x65, 0x1e, 0xe0, 0xe6, 0xd8, 0xe9, 0x45, 0xc0, - 0x0c, 0x00, 0xaf, 0x42, 0x2e, 0x1e, 0x01, 0x53, 0x89, 0xe3, 0x13, 0x53, 0xf1, 0x6b, 0x50, 0x0e, - 0x6b, 0x30, 0x3e, 0x15, 0xac, 0x77, 0x94, 0xf4, 0x62, 0x48, 0x15, 0xa7, 0xe1, 0x2a, 0xff, 0x20, - 0xc7, 0xd9, 0x59, 0x3e, 0x76, 0x2e, 0xf6, 0x42, 0xc6, 0x1d, 0xc8, 0x9b, 0xde, 0x60, 0x3c, 0xa4, - 0x4e, 0xe0, 0x57, 0x16, 0x79, 0x46, 0xe6, 0xa9, 0xa2, 0x73, 0x65, 0x71, 0x7e, 0x7f, 0x99, 0x81, - 0x0c, 0xf3, 0x02, 0x23, 0x28, 0xca, 0xea, 0xfb, 0x44, 0xd5, 0x0c, 0xa2, 0x76, 0xdb, 0x6d, 0xb4, - 0x80, 0x97, 0x20, 0x2d, 0xef, 0x6f, 0x23, 0x09, 0x17, 0x21, 0xb7, 0xa5, 0x69, 0x6d, 0x22, 0xab, - 0x0d, 0x94, 0xc2, 0x05, 0x58, 0xe2, 0x2b, 0x4d, 0x47, 0x69, 0x5c, 0x06, 0xa8, 0x6b, 0x6a, 0x5d, - 0x36, 0x88, 0xbc, 0xbd, 0x8d, 0x32, 0x38, 0x0f, 0xd9, 0xba, 0xd6, 0x55, 0x0d, 0x94, 0x65, 0xea, - 0xbb, 0xf2, 0x03, 0xb4, 0xc4, 0x7f, 0xb4, 0x54, 0x94, 0xc3, 0x00, 0x8b, 0x1d, 0xa3, 0xd1, 0x50, - 0xf6, 0x51, 0x9e, 0x11, 0x3b, 0xdd, 0x5d, 0x04, 0x0c, 0xae, 0xd3, 0xdd, 0x25, 0x2d, 0xd5, 0x40, - 0x05, 0xb6, 0xd3, 0xbe, 0xac, 0xb7, 0x64, 0xb5, 0xae, 0xa0, 0x22, 0x63, 0x3d, 0xd0, 0x74, 0x8e, - 0x5c, 0x0a, 0x77, 0xea, 0xaa, 0x06, 0xd1, 0xb5, 0xfb, 0x1d, 0x54, 0xe6, 0x7a, 0xf7, 0xf4, 0x46, - 0xab, 0xd9, 0x44, 0xcb, 0x18, 0x43, 0xb9, 0xd9, 0x52, 0xe5, 0x36, 0x89, 0xb5, 0x11, 0x73, 0x28, - 0xa4, 0x89, 0x3d, 0x2f, 0xe1, 0x12, 0xe4, 0x65, 0x5d, 0x97, 0xdf, 0xe7, 0x88, 0x98, 0x6d, 0xb6, - 0xd3, 0xd1, 0x54, 0xbe, 0xba, 0xcc, 0x98, 0x6c, 0xb5, 0xc5, 0x97, 0x57, 0xd8, 0x76, 0x1d, 0x43, - 0x6f, 0xa9, 0xdb, 0x7c, 0xfd, 0x12, 0xf7, 0xba, 0x65, 0xf0, 0x10, 0xbc, 0xcc, 0x1c, 0x61, 0x0b, - 0x4d, 0x47, 0x57, 0x71, 0x0e, 0x32, 0x75, 0x4d, 0xd7, 0x51, 0x05, 0x57, 0xe0, 0xca, 0x9e, 0xa2, - 0xd7, 0x15, 0xd5, 0x68, 0xb5, 0x15, 0xd2, 0x68, 0x75, 0xea, 0xa4, 0xb5, 0xbb, 0xd7, 0x46, 0xaf, - 0x4c, 0x71, 0xea, 0x9a, 0x6a, 0x84, 0x9c, 0x2a, 0xbe, 0x0c, 0xcb, 0xdc, 0x06, 0x6d, 0x6b, 0x47, - 0xa9, 0x87, 0x41, 0x7c, 0x15, 0x5f, 0x01, 0x14, 0x9a, 0x92, 0xa0, 0x7e, 0x8f, 0x59, 0xb0, 0x2f, - 0xeb, 0x64, 0x4f, 0xdb, 0x43, 0xdf, 0x0f, 0xcd, 0x63, 0x6e, 0xf1, 0xf5, 0x0a, 0x5e, 0x86, 0x42, - 0xc7, 0x20, 0xbb, 0xf2, 0x5d, 0xa5, 0xdd, 0x52, 0x15, 0x74, 0x8d, 0xb9, 0xd3, 0x31, 0x88, 0xf2, - 0xc0, 0x50, 0x54, 0x03, 0xad, 0x32, 0x5f, 0x3b, 0x06, 0xe9, 0xaa, 0x2d, 0x4d, 0x45, 0xd7, 0x43, - 0x6d, 0x52, 0xd7, 0xda, 0x6d, 0xa5, 0x6e, 0xa0, 0x5a, 0xed, 0x36, 0x64, 0xd8, 0x11, 0x61, 0xbe, - 0xc8, 0x5d, 0x43, 0x43, 0x0b, 0x3c, 0x55, 0x75, 0xb9, 0x2d, 0xeb, 0x48, 0x62, 0xd2, 0xaa, 0xa6, - 0x12, 0xb1, 0x4e, 0xd5, 0xfe, 0x26, 0x41, 0x79, 0xcf, 0x73, 0x3f, 0xa6, 0xbd, 0xa0, 0x43, 0xc3, - 0x77, 0xd5, 0x2f, 0x20, 0xcb, 0xda, 0x53, 0xf4, 0xfe, 0x98, 0xa7, 0x22, 0x43, 0x45, 0xbc, 0x0d, - 0x97, 0x06, 0xd4, 0xa1, 0x9e, 0x19, 0x24, 0x26, 0x8f, 0xf0, 0x0d, 0xf2, 0xb4, 0xfe, 0x86, 0x62, - 0xa5, 0x68, 0x24, 0x79, 0x03, 0x90, 0x33, 0xe6, 0x4f, 0x58, 0x9f, 0x8c, 0xa8, 0x47, 0x06, 0xd4, - 0x09, 0xdf, 0x1f, 0x7a, 0xc9, 0x19, 0xb3, 0xb7, 0xab, 0xbf, 0x47, 0xbd, 0x6d, 0xea, 0xd4, 0xbe, - 0x28, 0x41, 0xf1, 0xbe, 0xe5, 0xf4, 0xdd, 0x13, 0xd1, 0xa1, 0x57, 0xf9, 0xb7, 0xc0, 0xc0, 0xe2, - 0x0d, 0xeb, 0x4c, 0x3c, 0x0c, 0x93, 0x24, 0xdc, 0x81, 0xfc, 0x09, 0xd7, 0x68, 0xc6, 0xc6, 0x6d, - 0xcc, 0x76, 0x35, 0x09, 0x2e, 0x16, 0xcd, 0xf8, 0x1c, 0xc6, 0x38, 0xd5, 0xbf, 0x48, 0xe2, 0x04, - 0x76, 0xa0, 0x14, 0xf5, 0x47, 0xda, 0xfc, 0xa6, 0xdd, 0x48, 0x9f, 0xc4, 0xc0, 0xf7, 0x00, 0xc4, - 0x56, 0x0c, 0x31, 0xc5, 0x11, 0xdf, 0x9e, 0xcf, 0x66, 0x86, 0x9a, 0x00, 0x79, 0x2f, 0xf3, 0xf8, - 0xd3, 0x6b, 0x52, 0xf5, 0xd3, 0x25, 0xc8, 0x36, 0x3d, 0x73, 0x48, 0xf1, 0x5d, 0xc8, 0x0c, 0xdd, - 0x3e, 0x15, 0xe6, 0x7e, 0x5d, 0x70, 0xae, 0xbb, 0xbe, 0xeb, 0xf6, 0xe3, 0xce, 0xcc, 0x40, 0xf0, - 0x3d, 0x58, 0x3c, 0x70, 0xc7, 0x4e, 0xdf, 0x9f, 0x71, 0xff, 0x3f, 0x1d, 0x6e, 0x8b, 0xab, 0x46, - 0x63, 0x51, 0x08, 0x84, 0x3f, 0x80, 0x3c, 0x3d, 0xed, 0xd9, 0x63, 0x7e, 0xf1, 0xa6, 0xb9, 0x91, - 0xef, 0xcc, 0x85, 0xaa, 0x44, 0xda, 0xf1, 0x5b, 0x37, 0x22, 0x54, 0xff, 0x2b, 0x41, 0x96, 0x6f, - 0xca, 0x76, 0xe1, 0xfb, 0xb1, 0x83, 0x24, 0x42, 0xf1, 0xce, 0xfc, 0xb6, 0x27, 0x6e, 0xaa, 0x73, - 0x38, 0x7c, 0x03, 0xc0, 0x72, 0x02, 0xe2, 0x1e, 0x1e, 0xfa, 0x34, 0xbc, 0x57, 0xa2, 0xcf, 0xf2, - 0x79, 0xcb, 0x09, 0x34, 0x4e, 0xc6, 0xd7, 0xa1, 0xc8, 0x4e, 0x45, 0x3f, 0x12, 0x63, 0x9e, 0x16, - 0xf5, 0x02, 0xa7, 0x09, 0x91, 0x1d, 0x28, 0x84, 0x4c, 0xfe, 0xcf, 0x2c, 0x31, 0xb4, 0xce, 0xf1, - 0xaf, 0x1e, 0x08, 0xb5, 0x99, 0x4d, 0xd5, 0x3f, 0x4a, 0xb0, 0x18, 0x86, 0x1b, 0xab, 0x90, 0xf5, - 0x03, 0xd3, 0x0b, 0xc4, 0x54, 0xb3, 0x39, 0xbf, 0xdb, 0xf1, 0x17, 0x66, 0x06, 0x83, 0x1b, 0x90, - 0xa6, 0x4e, 0x5f, 0x14, 0xc0, 0x37, 0x40, 0xd3, 0x99, 0x7a, 0xed, 0x0d, 0xc8, 0xb0, 0xea, 0x62, - 0x57, 0x92, 0x2e, 0xab, 0xdb, 0x0a, 0x5a, 0x60, 0xfd, 0x8d, 0xdf, 0x1e, 0x12, 0xeb, 0x6f, 0xdb, - 0xba, 0xd6, 0xdd, 0xeb, 0xa0, 0x54, 0xed, 0x13, 0xc8, 0xc7, 0xb1, 0xc7, 0x57, 0xe1, 0x72, 0x57, - 0xdd, 0xd2, 0xba, 0x6a, 0x43, 0x69, 0x90, 0x3d, 0x5d, 0xa9, 0x2b, 0x8d, 0x96, 0xba, 0x8d, 0x16, - 0x26, 0x19, 0x4d, 0xad, 0xdd, 0xd6, 0xee, 0x33, 0x86, 0xc4, 0xba, 0xb5, 0xd6, 0x6c, 0x76, 0x14, - 0x23, 0x21, 0x9e, 0x4a, 0x50, 0xcf, 0x65, 0xd3, 0xac, 0x4d, 0xd7, 0xbb, 0xba, 0xae, 0x84, 0xd7, - 0x18, 0xca, 0xd4, 0x3e, 0x84, 0x7c, 0x5c, 0x5d, 0xec, 0xc6, 0x52, 0x35, 0xa2, 0x3c, 0xa8, 0xb7, - 0xbb, 0x1d, 0xd6, 0xa8, 0xf9, 0xa6, 0x7c, 0xd9, 0x50, 0x48, 0x52, 0x4f, 0xc2, 0x97, 0xa0, 0x14, - 0x31, 0xb8, 0x1f, 0x28, 0xc5, 0xb4, 0x23, 0x92, 0xd1, 0x52, 0x3a, 0x28, 0x5d, 0xfd, 0x67, 0x0a, - 0x72, 0x51, 0xdf, 0xc1, 0x4a, 0x62, 0xc4, 0x29, 0x6c, 0xbe, 0xf9, 0x75, 0xa3, 0x3a, 0x3d, 0xe0, - 0x34, 0x20, 0x17, 0xbf, 0x0f, 0x32, 0x73, 0x7e, 0x7b, 0x88, 0x35, 0xd9, 0x33, 0xed, 0x90, 0xe5, - 0x4b, 0x3c, 0x76, 0x6e, 0xcf, 0x93, 0x63, 0x3d, 0x54, 0xc5, 0x6b, 0x30, 0x31, 0x32, 0xf1, 0x59, - 0x3e, 0x1b, 0x0d, 0x9a, 0x13, 0xc3, 0x54, 0x15, 0x72, 0xa6, 0x37, 0xf0, 0x5b, 0xfd, 0x53, 0xf6, - 0x98, 0x65, 0x5d, 0x3d, 0x5e, 0x33, 0x94, 0xf0, 0x43, 0xa3, 0x40, 0xc9, 0x25, 0x9e, 0x28, 0x13, - 0x9c, 0x9d, 0x4c, 0x2e, 0x85, 0xd2, 0x62, 0x6a, 0xfa, 0xb3, 0x04, 0x70, 0xde, 0x1d, 0xd9, 0x0d, - 0xa9, 0x6b, 0xf7, 0x89, 0xda, 0xdd, 0xdd, 0x52, 0x74, 0x51, 0x67, 0xb2, 0x7a, 0x37, 0xbc, 0x3b, - 0x1b, 0x8a, 0xda, 0x51, 0x08, 0x5f, 0xf3, 0x24, 0x89, 0x49, 0x20, 0xa4, 0xa4, 0xd9, 0x45, 0x5d, - 0xef, 0xee, 0xf2, 0x79, 0xc1, 0x08, 0x07, 0x28, 0x3e, 0x25, 0x84, 0x03, 0x54, 0x5b, 0xde, 0x46, - 0x8b, 0x0c, 0xae, 0xad, 0xc8, 0x0d, 0xb4, 0xc4, 0xea, 0xa7, 0xd9, 0xd2, 0x3b, 0x06, 0xd9, 0x97, - 0xdb, 0x5d, 0x05, 0xe5, 0x18, 0x7e, 0x5b, 0x8e, 0xd7, 0x79, 0x86, 0xa6, 0x1a, 0x77, 0xc4, 0x12, - 0x6e, 0xfd, 0x04, 0xca, 0x93, 0x5f, 0xca, 0x59, 0xe1, 0xef, 0x75, 0xb7, 0xda, 0xad, 0x3a, 0x5a, - 0xc0, 0xaf, 0xc0, 0x4b, 0xe1, 0x6f, 0x36, 0xd6, 0xf0, 0xc9, 0x4f, 0xb0, 0xa4, 0xad, 0xb7, 0x1e, - 0x7f, 0xb1, 0xb2, 0xf0, 0xf8, 0xc9, 0x8a, 0xf4, 0xd9, 0x93, 0x15, 0xe9, 0xf3, 0x27, 0x2b, 0xd2, - 0x7f, 0x9e, 0xac, 0x48, 0xbf, 0xfd, 0x72, 0x65, 0xe1, 0xb3, 0x2f, 0x57, 0x16, 0x3e, 0xff, 0x72, - 0x65, 0xe1, 0x83, 0x42, 0xe2, 0x5f, 0xd5, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x28, 0xfe, 0x1f, - 0x92, 0x9a, 0x1f, 0x00, 0x00, + proto.RegisterFile("sql/execinfrapb/processors_sql.proto", fileDescriptor_processors_sql_3a604963f9a66bbd) +} + +var fileDescriptor_processors_sql_3a604963f9a66bbd = []byte{ + // 2766 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x19, 0xcf, 0x6f, 0xdb, 0xd6, + 0xd9, 0xd4, 0x0f, 0x5b, 0xfa, 0xf4, 0xc3, 0x2f, 0x2f, 0x6e, 0xa3, 0xba, 0xad, 0xe3, 0x28, 0x5d, + 0xeb, 0xa4, 0xa9, 0xbd, 0x7a, 0x43, 0x87, 0x76, 0xc3, 0x30, 0x5a, 0xa2, 0x1c, 0x39, 0x32, 0xe9, + 0x50, 0x94, 0x93, 0xb6, 0x40, 0x1f, 0x68, 0xea, 0x59, 0x66, 0x43, 0x91, 0x32, 0x49, 0xc5, 0x76, + 0x8f, 0xbb, 0xec, 0x34, 0x60, 0xc3, 0x2e, 0x3b, 0x0d, 0xc5, 0x80, 0x61, 0xff, 0xc0, 0xce, 0x3b, + 0xed, 0x10, 0x60, 0x97, 0x5e, 0xb6, 0x15, 0x18, 0x30, 0xac, 0xe9, 0x1f, 0x31, 0xec, 0x36, 0xbc, + 0xc7, 0x47, 0x9a, 0x32, 0xac, 0xac, 0x4e, 0xd2, 0xe6, 0x62, 0xe8, 0x7d, 0xbf, 0xde, 0xf7, 0xfb, + 0xfb, 0x1e, 0x0d, 0x6f, 0x04, 0x87, 0xce, 0x1a, 0x3d, 0xa6, 0x96, 0xed, 0xee, 0xfb, 0xe6, 0x68, + 0x6f, 0x6d, 0xe4, 0x7b, 0x16, 0x0d, 0x02, 0xcf, 0x0f, 0x48, 0x70, 0xe8, 0xac, 0x8e, 0x7c, 0x2f, + 0xf4, 0x70, 0xcd, 0xf2, 0xac, 0x07, 0xbe, 0x67, 0x5a, 0x07, 0xab, 0x0c, 0xd8, 0xb7, 0x83, 0x30, + 0x38, 0x74, 0xfc, 0xb1, 0xbb, 0x78, 0x9d, 0xf1, 0x5b, 0x66, 0x68, 0x3a, 0xde, 0x60, 0xad, 0x4f, + 0x03, 0x6b, 0xb4, 0xb7, 0x16, 0x84, 0xfe, 0xd8, 0x0a, 0xc7, 0x3e, 0xed, 0x47, 0xec, 0x8b, 0xf5, + 0x73, 0x88, 0x3e, 0xf5, 0x6c, 0x97, 0x84, 0x27, 0x23, 0x2a, 0x68, 0x96, 0xcf, 0xa1, 0x71, 0x3c, + 0xeb, 0x81, 0xed, 0x0e, 0x04, 0xc5, 0x4b, 0x8c, 0x82, 0x71, 0x04, 0xd1, 0x5f, 0x01, 0x5e, 0x3c, + 0x6b, 0x41, 0xdf, 0x0c, 0x4d, 0x81, 0xfb, 0xde, 0x13, 0xac, 0xdb, 0x33, 0x83, 0xf8, 0xee, 0x9b, + 0x8c, 0xcc, 0x1b, 0x85, 0x6b, 0xb6, 0xfb, 0x90, 0xfa, 0x21, 0xed, 0xd3, 0xe3, 0x91, 0xbf, 0x16, + 0x8c, 0x4c, 0x97, 0xb0, 0x5f, 0x34, 0x08, 0x6c, 0xcf, 0x15, 0xb4, 0x0b, 0x03, 0x6f, 0xe0, 0xf1, + 0x9f, 0x6b, 0xec, 0x57, 0x04, 0xad, 0xff, 0x46, 0x82, 0xea, 0xae, 0xe9, 0x8c, 0x69, 0xd0, 0xf0, + 0x7c, 0xda, 0x1d, 0x51, 0x0b, 0x37, 0x60, 0xce, 0xf2, 0x9c, 0xf1, 0xd0, 0x0d, 0x6a, 0xd2, 0x72, + 0x76, 0xa5, 0xb4, 0x7e, 0x7d, 0x75, 0x9a, 0x17, 0x57, 0x9b, 0x66, 0x38, 0x1e, 0xb6, 0xdd, 0x7d, + 0x6f, 0x23, 0xf7, 0xe8, 0x5f, 0x57, 0x67, 0xf4, 0x98, 0x13, 0xbf, 0x0a, 0x45, 0xdf, 0x3c, 0x22, + 0x7b, 0x27, 0x21, 0x0d, 0x6a, 0x99, 0xe5, 0xec, 0x4a, 0x59, 0x2f, 0xf8, 0xe6, 0xd1, 0x06, 0x3b, + 0xe3, 0xab, 0x50, 0x70, 0xc7, 0x43, 0xe2, 0x7b, 0x47, 0x41, 0x2d, 0xbb, 0x2c, 0xad, 0xe4, 0x62, + 0x6e, 0x77, 0x3c, 0xd4, 0xbd, 0xa3, 0xa0, 0xfe, 0xcf, 0x3c, 0xcc, 0x1b, 0xe6, 0x9e, 0x43, 0x75, + 0x6a, 0xf6, 0xa9, 0xcf, 0xd5, 0xda, 0x80, 0x7c, 0xc8, 0x40, 0x35, 0x69, 0x59, 0x5a, 0x29, 0xad, + 0xbf, 0x79, 0x46, 0xa9, 0xe0, 0xd0, 0xe1, 0x8e, 0xe1, 0x6c, 0x4d, 0x1a, 0x58, 0xbe, 0x3d, 0x0a, + 0x3d, 0x5f, 0x48, 0x8e, 0x58, 0xf1, 0x35, 0x28, 0xda, 0x6e, 0x9f, 0x1e, 0x13, 0xbb, 0x7f, 0x5c, + 0xcb, 0x2c, 0x4b, 0x2b, 0x15, 0x81, 0x2f, 0x70, 0x70, 0xbb, 0x7f, 0x8c, 0x97, 0x60, 0xce, 0xa7, + 0x0f, 0xa9, 0x1f, 0x50, 0xae, 0x5a, 0x21, 0x56, 0x4d, 0x00, 0xb1, 0x02, 0x79, 0xe6, 0xdf, 0xa0, + 0x96, 0xe3, 0xbe, 0xb9, 0x31, 0xdd, 0x37, 0x13, 0x06, 0x98, 0x6e, 0xac, 0x09, 0xe7, 0xc6, 0xd7, + 0x01, 0x1c, 0x7b, 0x68, 0x87, 0xe4, 0xc0, 0x76, 0xc3, 0x5a, 0x7e, 0x59, 0x5a, 0xc9, 0x0a, 0x82, + 0x22, 0x87, 0xdf, 0xb6, 0xdd, 0x90, 0xf9, 0xc9, 0x0e, 0x88, 0x75, 0x40, 0xad, 0x07, 0xb5, 0xd9, + 0xb4, 0x32, 0x76, 0xd0, 0x60, 0x40, 0xac, 0x02, 0x3c, 0xb4, 0x03, 0x7b, 0xcf, 0x76, 0xec, 0xf0, + 0xa4, 0x36, 0xb7, 0x2c, 0xad, 0x54, 0xd7, 0x57, 0xa6, 0x6b, 0xd4, 0xb5, 0x4c, 0x77, 0x37, 0xa1, + 0x17, 0xc2, 0x52, 0x12, 0xf0, 0x8f, 0xe1, 0xca, 0xd0, 0x3c, 0x26, 0xa1, 0x3d, 0xa4, 0x41, 0x68, + 0x0e, 0x47, 0xc4, 0x1c, 0x50, 0xe2, 0x9a, 0xae, 0x17, 0xd4, 0x8a, 0xa9, 0x38, 0x2d, 0x0c, 0xcd, + 0x63, 0x23, 0xa6, 0x91, 0x07, 0x54, 0x65, 0x14, 0xf8, 0x63, 0x40, 0x22, 0xef, 0x49, 0x10, 0xfa, + 0xd4, 0x1d, 0x84, 0x07, 0x35, 0xe0, 0x2a, 0xdd, 0x9c, 0x12, 0x2b, 0xa6, 0x4f, 0x27, 0x62, 0xe9, + 0x0a, 0x0e, 0x71, 0xc3, 0xbc, 0x33, 0x09, 0xc6, 0x7b, 0x70, 0x39, 0x16, 0x7e, 0x64, 0xda, 0x21, + 0x19, 0x79, 0x8e, 0x6d, 0x9d, 0xd4, 0x4a, 0x5c, 0xfe, 0xad, 0xff, 0x2f, 0xff, 0x9e, 0x69, 0x87, + 0x3b, 0x9c, 0x47, 0xdc, 0x70, 0xc9, 0x39, 0x8b, 0xc0, 0x6f, 0x42, 0x69, 0x64, 0xfa, 0xa6, 0xe3, + 0x50, 0xc7, 0xfe, 0x8c, 0xd6, 0xca, 0x29, 0x8f, 0xa7, 0x11, 0x78, 0x1d, 0xf0, 0x81, 0x19, 0x90, + 0xe0, 0x24, 0x08, 0xe9, 0x90, 0xc4, 0xb5, 0x52, 0x4d, 0x91, 0xa3, 0x03, 0x33, 0xe8, 0x72, 0x74, + 0x23, 0xc2, 0x6e, 0xe5, 0x0a, 0x05, 0x54, 0xdc, 0xca, 0x15, 0x2a, 0xa8, 0x5a, 0xff, 0x6f, 0x16, + 0x6a, 0x6d, 0x96, 0x6f, 0xdd, 0x07, 0xf6, 0xe8, 0x05, 0xa5, 0x79, 0x92, 0xc6, 0xd9, 0x67, 0x4a, + 0xe3, 0xc9, 0x04, 0xcc, 0x3d, 0x73, 0x02, 0xa6, 0xaa, 0x2f, 0x7f, 0x5e, 0xf5, 0x9d, 0x97, 0x63, + 0xb3, 0xdf, 0x72, 0x8e, 0xcd, 0x3d, 0xc7, 0x1c, 0xab, 0xff, 0x71, 0x16, 0xaa, 0x5b, 0x9e, 0xed, + 0x7e, 0xf7, 0x11, 0xbf, 0x01, 0x55, 0xc7, 0xf3, 0x1e, 0x8c, 0x47, 0x49, 0xc6, 0xb2, 0xd0, 0x57, + 0x36, 0x32, 0x48, 0xd2, 0x2b, 0x11, 0x46, 0x24, 0x2b, 0x9b, 0x00, 0x5e, 0x34, 0x41, 0x78, 0x48, + 0x4b, 0xeb, 0x6f, 0x4c, 0x0f, 0xa9, 0x92, 0xcc, 0x19, 0x71, 0xe3, 0xac, 0xe7, 0x32, 0x18, 0x7e, + 0x1f, 0x72, 0x6c, 0xda, 0x89, 0xf0, 0x5c, 0x9d, 0x62, 0x15, 0xf3, 0x85, 0x71, 0x32, 0xa2, 0x82, + 0x99, 0xb3, 0x3c, 0xf7, 0xb6, 0xf6, 0x3e, 0xbc, 0x3c, 0x69, 0x3a, 0x31, 0x7d, 0x4a, 0x1e, 0xd0, + 0x93, 0x5a, 0x21, 0x95, 0x64, 0x97, 0x27, 0x9c, 0x20, 0xfb, 0xf4, 0x0e, 0x3d, 0x39, 0x37, 0xe1, + 0x8a, 0xdf, 0x72, 0xc2, 0xc1, 0xf3, 0x6c, 0x6a, 0xef, 0xc2, 0xa5, 0xa1, 0x69, 0xbb, 0xa1, 0x69, + 0xbb, 0xc4, 0xf3, 0xfb, 0xd4, 0xb7, 0xdd, 0x01, 0x6f, 0x9b, 0x49, 0xaf, 0x8a, 0xd1, 0x9a, 0xc0, + 0x4e, 0xe9, 0x6f, 0x95, 0x27, 0xf5, 0x37, 0xdc, 0x84, 0xd7, 0x1c, 0xba, 0x1f, 0x12, 0xbe, 0x1d, + 0x1d, 0xd9, 0xe1, 0x01, 0x19, 0x99, 0xb6, 0x4f, 0xfb, 0x1c, 0x40, 0xfd, 0x89, 0xee, 0x58, 0x63, + 0x94, 0x2c, 0xf0, 0xf7, 0xec, 0xf0, 0x60, 0x87, 0x93, 0x6d, 0x71, 0xaa, 0xad, 0x5c, 0x21, 0x8f, + 0x66, 0xb7, 0x72, 0x85, 0x32, 0xaa, 0xb0, 0xcd, 0x04, 0xba, 0x9e, 0x1f, 0x8a, 0x2a, 0xb9, 0x0b, + 0xf3, 0xde, 0x38, 0x1c, 0x8d, 0xc3, 0x53, 0x2b, 0xa2, 0x7a, 0xa9, 0x4f, 0x4f, 0x8c, 0xd8, 0x22, + 0x71, 0x6f, 0x35, 0x12, 0x90, 0xb6, 0x33, 0x96, 0x45, 0x86, 0x66, 0x68, 0x1d, 0x10, 0x87, 0xba, + 0x13, 0xd5, 0x83, 0x62, 0xfc, 0x36, 0x43, 0x77, 0xa8, 0x5b, 0xff, 0xb3, 0x04, 0xe5, 0xa6, 0x1d, + 0x84, 0xb6, 0x6b, 0x85, 0x5c, 0xaf, 0xb7, 0x60, 0x9e, 0x13, 0xd1, 0x3e, 0x49, 0x6f, 0x4d, 0x15, + 0xbd, 0x2a, 0xc0, 0xb1, 0x87, 0x6e, 0x00, 0xea, 0x0b, 0xc6, 0x84, 0x32, 0xc3, 0x29, 0xe7, 0x63, + 0x78, 0x4c, 0xba, 0x0e, 0xd8, 0x1d, 0x3b, 0x4e, 0x94, 0xa6, 0x31, 0x72, 0x62, 0x1d, 0x41, 0x1c, + 0x2f, 0xfb, 0x34, 0xd6, 0x05, 0xbf, 0x09, 0x65, 0xea, 0xfb, 0x9e, 0x4f, 0x3c, 0x97, 0xf4, 0xc7, + 0x23, 0x5e, 0xb8, 0xc5, 0xb8, 0x16, 0x38, 0x46, 0x73, 0x9b, 0xe3, 0x51, 0x1d, 0x41, 0x55, 0xf3, + 0xfb, 0xb6, 0x6b, 0xb2, 0xca, 0x60, 0x16, 0xd4, 0x7f, 0x9b, 0x05, 0xf4, 0x91, 0x3d, 0xf8, 0xcc, + 0x1c, 0x44, 0x51, 0xe0, 0x66, 0x35, 0x61, 0x96, 0x77, 0x96, 0x78, 0x07, 0xbc, 0x58, 0x57, 0x12, + 0xbc, 0xb8, 0x05, 0x40, 0x0f, 0x27, 0xac, 0x2d, 0xad, 0x5f, 0x9b, 0x1e, 0x2f, 0x61, 0x7f, 0xbc, + 0x08, 0xd1, 0xc3, 0x53, 0xdf, 0x55, 0xa3, 0xf6, 0xe6, 0x45, 0xaa, 0x4f, 0xf4, 0x2e, 0x8e, 0x11, + 0x36, 0x3d, 0xa7, 0xde, 0x75, 0x07, 0xca, 0xfb, 0xf6, 0x31, 0xed, 0x93, 0x87, 0x7c, 0x35, 0xae, + 0xe5, 0xb9, 0xe6, 0x4f, 0x68, 0x41, 0x93, 0x2b, 0xb4, 0x5e, 0xe2, 0xdc, 0x11, 0xf0, 0x19, 0x1a, + 0x61, 0xfd, 0xef, 0x59, 0x98, 0xdf, 0xa6, 0xfe, 0x80, 0xa6, 0x22, 0xb3, 0x0d, 0x15, 0x5e, 0x69, + 0x4f, 0x5d, 0x06, 0x65, 0xc6, 0x9e, 0x14, 0x81, 0x06, 0x55, 0xdf, 0x1e, 0x1c, 0xa4, 0xe4, 0x65, + 0x2e, 0x28, 0xaf, 0xc2, 0xf9, 0x13, 0x81, 0xa9, 0x00, 0xe4, 0x5f, 0xc4, 0xf0, 0xb8, 0x01, 0x15, + 0x56, 0x1c, 0x84, 0x1e, 0x8e, 0xcd, 0x64, 0x7e, 0xc4, 0x75, 0x53, 0x66, 0x28, 0x45, 0x60, 0xf0, + 0x07, 0x70, 0x85, 0xbb, 0xf2, 0x34, 0x47, 0xa7, 0x0c, 0x06, 0xba, 0x1f, 0x2a, 0x87, 0x93, 0x83, + 0xe1, 0x27, 0x50, 0x8b, 0xfc, 0x76, 0x0e, 0x73, 0x31, 0xc5, 0xbc, 0xc0, 0xa9, 0xce, 0x70, 0xd7, + 0x7f, 0x9d, 0x85, 0xea, 0x6d, 0x33, 0x38, 0x48, 0xc5, 0xf5, 0x26, 0xcc, 0x9f, 0x51, 0x26, 0x6a, + 0x24, 0x62, 0x40, 0xa7, 0x55, 0xc0, 0xb7, 0x00, 0x9d, 0xbd, 0x3c, 0xea, 0x25, 0x9c, 0xb8, 0x3a, + 0x79, 0xe5, 0x0b, 0x8f, 0xc8, 0xdb, 0x50, 0x1d, 0xb2, 0x24, 0x3e, 0xed, 0x90, 0xe9, 0x90, 0x54, + 0x22, 0x5c, 0xac, 0xec, 0x8b, 0x8b, 0xc9, 0xdf, 0xb2, 0x80, 0xdb, 0xe2, 0x1d, 0x9d, 0x8a, 0xcb, + 0x77, 0xb4, 0x9e, 0x69, 0x50, 0x89, 0x1f, 0xf1, 0x4f, 0xdb, 0xbd, 0xca, 0xb1, 0x00, 0x1e, 0xb0, + 0x17, 0x1d, 0xf5, 0x73, 0x17, 0x8f, 0xb9, 0x27, 0x2e, 0x1e, 0x2a, 0x5c, 0x13, 0x33, 0xde, 0xf2, + 0xdc, 0xd0, 0x76, 0xc7, 0x66, 0x68, 0x7b, 0x2e, 0xd9, 0xf7, 0x7c, 0x92, 0x2c, 0x17, 0x13, 0x59, + 0xf0, 0x7a, 0x44, 0xde, 0x48, 0x51, 0xb7, 0x3c, 0xbf, 0x23, 0xd6, 0x8b, 0xad, 0x5c, 0x21, 0x8b, + 0x72, 0xf5, 0xdf, 0x67, 0x61, 0x21, 0x8e, 0x6b, 0xcb, 0x76, 0x42, 0xea, 0x8b, 0xc8, 0xae, 0x02, + 0x4a, 0x5c, 0x6e, 0x79, 0x0e, 0x0f, 0x8e, 0x94, 0x0a, 0x4e, 0x35, 0xc6, 0x36, 0x3c, 0x87, 0x85, + 0xe8, 0x93, 0xb3, 0x21, 0x8a, 0x3a, 0xe5, 0x0f, 0xce, 0x78, 0xc5, 0x1b, 0x85, 0xab, 0xe9, 0xef, + 0x31, 0xab, 0xec, 0xd9, 0x74, 0xea, 0xe1, 0x1d, 0xdf, 0x0b, 0xbd, 0x73, 0x23, 0xf6, 0x29, 0x5c, + 0x1a, 0xf9, 0x94, 0xec, 0x0b, 0x1d, 0x49, 0x30, 0xa2, 0x16, 0xf7, 0x7c, 0x69, 0xfd, 0xa7, 0xd3, + 0x63, 0x77, 0x9e, 0x69, 0xab, 0x3b, 0x3e, 0x4d, 0x9f, 0xf5, 0xf9, 0xd1, 0x24, 0x60, 0xf1, 0x97, + 0x12, 0xcc, 0x9f, 0x21, 0xc2, 0x5b, 0x00, 0xa7, 0x5f, 0x8d, 0x44, 0xba, 0x5f, 0x24, 0x69, 0x52, + 0xdc, 0x78, 0x55, 0x24, 0x4e, 0xe4, 0xa2, 0xc5, 0xb3, 0x89, 0x43, 0x87, 0xab, 0xd1, 0xa7, 0x30, + 0x43, 0x4c, 0xba, 0xbf, 0x16, 0xa0, 0x2a, 0x0f, 0x06, 0x3e, 0x1d, 0x98, 0xa1, 0x17, 0xa9, 0x73, + 0x0d, 0x60, 0xe0, 0x7b, 0xd1, 0xd2, 0x9e, 0x6e, 0x6f, 0x45, 0x0e, 0x6d, 0x78, 0x4e, 0x80, 0x3f, + 0x81, 0xb2, 0x29, 0x98, 0x6c, 0x2f, 0x79, 0xcc, 0xfe, 0x70, 0xba, 0xce, 0x93, 0x57, 0x24, 0xc7, + 0x54, 0x0d, 0xa5, 0xe5, 0xe1, 0xef, 0x8b, 0x0d, 0x91, 0xf6, 0x49, 0x4a, 0x95, 0x5c, 0xa2, 0x0a, + 0x12, 0xd8, 0xcd, 0x44, 0xa3, 0x4d, 0x61, 0x77, 0x9e, 0x17, 0xcc, 0x3b, 0xdf, 0x58, 0x93, 0xb3, + 0xe5, 0xb3, 0xf8, 0x8b, 0x0c, 0x94, 0x52, 0xea, 0x31, 0xc1, 0xfb, 0x63, 0xd7, 0xe2, 0x61, 0xb9, + 0x88, 0xe0, 0xd6, 0xd8, 0xb5, 0x62, 0xc1, 0x4c, 0x00, 0x5e, 0x86, 0x42, 0xb2, 0x52, 0x66, 0x52, + 0xb5, 0x94, 0x40, 0xf1, 0x1b, 0x50, 0x8d, 0x72, 0x30, 0xa9, 0x0a, 0xd6, 0x8b, 0x2a, 0x7a, 0x39, + 0x82, 0x8a, 0x6a, 0xb8, 0xc2, 0x3f, 0x13, 0x72, 0x74, 0x9e, 0xaf, 0xb1, 0xb3, 0x56, 0x84, 0xb8, + 0x0d, 0x45, 0xd3, 0x1f, 0x8c, 0x87, 0xd4, 0x0d, 0x83, 0xda, 0x2c, 0x8f, 0xc8, 0x45, 0xb2, 0xe8, + 0x94, 0x59, 0xd4, 0xef, 0xcf, 0x73, 0x90, 0x63, 0x56, 0x60, 0x04, 0x65, 0x59, 0xfd, 0x90, 0xa8, + 0x9a, 0x41, 0xd4, 0x5e, 0xa7, 0x83, 0x66, 0xf0, 0x1c, 0x64, 0xe5, 0xdd, 0x4d, 0x24, 0xe1, 0x32, + 0x14, 0x36, 0x34, 0xad, 0x43, 0x64, 0xb5, 0x89, 0x32, 0xb8, 0x04, 0x73, 0xfc, 0xa4, 0xe9, 0x28, + 0x8b, 0xab, 0x00, 0x0d, 0x4d, 0x6d, 0xc8, 0x06, 0x91, 0x37, 0x37, 0x51, 0x0e, 0x17, 0x21, 0xdf, + 0xd0, 0x7a, 0xaa, 0x81, 0xf2, 0x8c, 0x7d, 0x5b, 0xbe, 0x8f, 0xe6, 0xf8, 0x8f, 0xb6, 0x8a, 0x0a, + 0x18, 0x60, 0xb6, 0x6b, 0x34, 0x9b, 0xca, 0x2e, 0x2a, 0x32, 0x60, 0xb7, 0xb7, 0x8d, 0x80, 0x89, + 0xeb, 0xf6, 0xb6, 0x49, 0x5b, 0x35, 0x50, 0x89, 0xdd, 0xb4, 0x2b, 0xeb, 0x6d, 0x59, 0x6d, 0x28, + 0xa8, 0xcc, 0x50, 0xf7, 0x35, 0x9d, 0x4b, 0xae, 0x44, 0x37, 0xf5, 0x54, 0x83, 0xe8, 0xda, 0xbd, + 0x2e, 0xaa, 0x72, 0xbe, 0xbb, 0x7a, 0xb3, 0xdd, 0x6a, 0xa1, 0x79, 0x8c, 0xa1, 0xda, 0x6a, 0xab, + 0x72, 0x87, 0x24, 0xdc, 0x88, 0x19, 0x14, 0xc1, 0xc4, 0x9d, 0x97, 0x70, 0x05, 0x8a, 0xb2, 0xae, + 0xcb, 0x1f, 0x72, 0x89, 0x98, 0x5d, 0xb6, 0xd5, 0xd5, 0x54, 0x7e, 0xba, 0xcc, 0x90, 0xec, 0xb4, + 0xc1, 0x8f, 0x0b, 0xec, 0xba, 0xae, 0xa1, 0xb7, 0xd5, 0x4d, 0x7e, 0x7e, 0x89, 0x5b, 0xdd, 0x36, + 0xb8, 0x0b, 0x5e, 0x66, 0x86, 0xb0, 0x83, 0xa6, 0xa3, 0x2b, 0xb8, 0x00, 0xb9, 0x86, 0xa6, 0xeb, + 0xa8, 0x86, 0x6b, 0xb0, 0xb0, 0xa3, 0xe8, 0x0d, 0x45, 0x35, 0xda, 0x1d, 0x85, 0x34, 0xdb, 0xdd, + 0x06, 0x69, 0x6f, 0xef, 0x74, 0xd0, 0x2b, 0x67, 0x30, 0x0d, 0x4d, 0x35, 0x22, 0xcc, 0x22, 0xbe, + 0x0c, 0xf3, 0x5c, 0x07, 0x6d, 0x63, 0x4b, 0x69, 0x44, 0x4e, 0x7c, 0x15, 0x2f, 0x00, 0x8a, 0x54, + 0x49, 0x41, 0x5f, 0x63, 0x1a, 0xec, 0xca, 0x3a, 0xd9, 0xd1, 0x76, 0xd0, 0xeb, 0x91, 0x7a, 0xcc, + 0x2c, 0x7e, 0x5e, 0xc2, 0xf3, 0x50, 0xea, 0x1a, 0x64, 0x5b, 0xbe, 0xa3, 0x74, 0xda, 0xaa, 0x82, + 0xae, 0x32, 0x73, 0xba, 0x06, 0x51, 0xee, 0x1b, 0x8a, 0x6a, 0xa0, 0x65, 0x66, 0x6b, 0xd7, 0x20, + 0x3d, 0xb5, 0xad, 0xa9, 0xe8, 0x5a, 0xc4, 0x4d, 0x1a, 0x5a, 0xa7, 0xa3, 0x34, 0x0c, 0x54, 0xaf, + 0xdf, 0x82, 0x1c, 0x2b, 0x11, 0x66, 0x8b, 0xdc, 0x33, 0x34, 0x34, 0xc3, 0x43, 0xd5, 0x90, 0x3b, + 0xb2, 0x8e, 0x24, 0x46, 0xad, 0x6a, 0x2a, 0x11, 0xe7, 0x4c, 0xfd, 0x2f, 0x12, 0x54, 0x77, 0x7c, + 0xef, 0x53, 0x6a, 0x85, 0x5d, 0x1a, 0xbd, 0xd3, 0x7e, 0x06, 0x79, 0xd6, 0x9e, 0xe2, 0xf7, 0xcc, + 0x45, 0x32, 0x32, 0x62, 0xc4, 0x9b, 0x70, 0x69, 0x40, 0x5d, 0xea, 0x9b, 0x61, 0x6a, 0x93, 0x89, + 0xde, 0x34, 0x4f, 0xea, 0x6f, 0x28, 0x61, 0x8a, 0x57, 0x9c, 0xb7, 0x00, 0xb9, 0x63, 0xfe, 0xb0, + 0x0e, 0xc8, 0x88, 0xfa, 0x64, 0x40, 0xdd, 0xe8, 0x3d, 0xa3, 0x57, 0xdc, 0x31, 0x7b, 0x51, 0x07, + 0x3b, 0xd4, 0xdf, 0xa4, 0x6e, 0xfd, 0xab, 0x0a, 0x94, 0xef, 0xd9, 0x6e, 0xdf, 0x3b, 0x12, 0x1d, + 0x7a, 0x99, 0x7f, 0xa1, 0x0c, 0x6d, 0xde, 0xb0, 0x4e, 0xc4, 0x43, 0x33, 0x0d, 0xc2, 0x5d, 0x28, + 0x1e, 0x71, 0x8e, 0x56, 0xa2, 0xdc, 0xda, 0x74, 0x53, 0xd3, 0xc2, 0xc5, 0xa1, 0x95, 0xd4, 0x61, + 0x22, 0x67, 0xf1, 0x4f, 0x92, 0xa8, 0xc0, 0x2e, 0x54, 0xe2, 0xfe, 0x48, 0x5b, 0x4f, 0xdb, 0x8d, + 0xf4, 0x49, 0x19, 0xf8, 0x2e, 0x80, 0xb8, 0x8a, 0x49, 0xcc, 0x70, 0x89, 0xef, 0x5e, 0x4c, 0x67, + 0x26, 0x35, 0x25, 0xe4, 0x83, 0xdc, 0xa3, 0xcf, 0xaf, 0x4a, 0x8b, 0x9f, 0xcf, 0x41, 0xbe, 0xe5, + 0x9b, 0x43, 0x8a, 0xef, 0x40, 0x6e, 0xe8, 0xf5, 0xa9, 0x50, 0xf7, 0x9b, 0x0a, 0xe7, 0xbc, 0xab, + 0xdb, 0x5e, 0x3f, 0xe9, 0xcc, 0x4c, 0x08, 0xbe, 0x0b, 0xb3, 0x7b, 0xde, 0xd8, 0xed, 0x07, 0x53, + 0xe6, 0xff, 0x93, 0xc5, 0x6d, 0x70, 0xd6, 0x78, 0xcd, 0x8a, 0x04, 0xe1, 0x8f, 0xa0, 0x48, 0x8f, + 0x2d, 0x67, 0xcc, 0x07, 0x6f, 0x96, 0x2b, 0xf9, 0xde, 0x85, 0xa4, 0x2a, 0x31, 0x77, 0xf2, 0x76, + 0x8e, 0x01, 0x8b, 0xff, 0x91, 0x20, 0xcf, 0x2f, 0x65, 0xb7, 0xf0, 0xfb, 0x58, 0x21, 0x09, 0x57, + 0xbc, 0x77, 0x71, 0xdd, 0x53, 0x93, 0xea, 0x54, 0x1c, 0xbe, 0x0e, 0x60, 0xbb, 0x21, 0xf1, 0xf6, + 0xf7, 0x03, 0x1a, 0xcd, 0x95, 0xf8, 0x9f, 0x05, 0x45, 0xdb, 0x0d, 0x35, 0x0e, 0xc6, 0xd7, 0xa0, + 0xcc, 0xaa, 0xa2, 0x1f, 0x93, 0x31, 0x4b, 0xcb, 0x7a, 0x89, 0xc3, 0x04, 0xc9, 0x16, 0x94, 0x22, + 0x24, 0xff, 0x17, 0x9b, 0x58, 0x82, 0x2f, 0xf0, 0x0f, 0x28, 0x88, 0xb8, 0x99, 0x4e, 0x8b, 0xbf, + 0x93, 0x60, 0x36, 0x72, 0x37, 0x56, 0x21, 0x1f, 0x84, 0xa6, 0x1f, 0x8a, 0xad, 0x66, 0xfd, 0xe2, + 0x66, 0x27, 0xdf, 0xbd, 0x99, 0x18, 0xdc, 0x84, 0x2c, 0x75, 0xfb, 0x22, 0x01, 0x9e, 0x42, 0x9a, + 0xce, 0xd8, 0xeb, 0x6f, 0x41, 0x8e, 0x65, 0x17, 0x1b, 0x49, 0xba, 0xac, 0x6e, 0x2a, 0x68, 0x86, + 0xf5, 0x37, 0x3e, 0x3d, 0x24, 0xd6, 0xdf, 0x36, 0x75, 0xad, 0xb7, 0xd3, 0x45, 0x99, 0xfa, 0x67, + 0x50, 0x4c, 0x7c, 0x8f, 0xaf, 0xc0, 0xe5, 0x9e, 0xba, 0xa1, 0xf5, 0xd4, 0xa6, 0xd2, 0x24, 0x3b, + 0xba, 0xd2, 0x50, 0x9a, 0x6d, 0x75, 0x13, 0xcd, 0x4c, 0x22, 0x5a, 0x5a, 0xa7, 0xa3, 0xdd, 0x63, + 0x08, 0x89, 0x75, 0x6b, 0xad, 0xd5, 0xea, 0x2a, 0x46, 0x8a, 0x3c, 0x93, 0x82, 0x9e, 0xd2, 0x66, + 0x59, 0x9b, 0x6e, 0xf4, 0x74, 0x5d, 0x89, 0xc6, 0x18, 0xca, 0xd5, 0x3f, 0x86, 0x62, 0x92, 0x5d, + 0x6c, 0x62, 0xa9, 0x1a, 0x51, 0xee, 0x37, 0x3a, 0xbd, 0x2e, 0x6b, 0xd4, 0xfc, 0x52, 0x7e, 0x6c, + 0x2a, 0x24, 0xcd, 0x27, 0xe1, 0x4b, 0x50, 0x89, 0x11, 0xdc, 0x0e, 0x94, 0x61, 0xdc, 0x31, 0xc8, + 0x68, 0x2b, 0x5d, 0x94, 0x5d, 0xfc, 0x47, 0x06, 0x0a, 0x71, 0xdf, 0xc1, 0x4a, 0x6a, 0xc5, 0x29, + 0xad, 0xbf, 0xfd, 0x4d, 0xbd, 0x7a, 0x76, 0xc1, 0x69, 0x42, 0x21, 0x79, 0x6f, 0xe4, 0x2e, 0xf8, + 0x2d, 0x23, 0xe1, 0x64, 0xcf, 0xbe, 0x7d, 0x16, 0x2f, 0xf1, 0x78, 0xba, 0x75, 0x91, 0x18, 0xeb, + 0x11, 0x2b, 0x5e, 0x81, 0x89, 0x95, 0x89, 0xef, 0xf2, 0xf9, 0x78, 0xd1, 0x9c, 0x58, 0xa6, 0x16, + 0xa1, 0x60, 0xfa, 0x83, 0xa0, 0xdd, 0x3f, 0x66, 0x8f, 0x63, 0xd6, 0xd5, 0x93, 0x33, 0x93, 0x12, + 0x3f, 0x73, 0xb8, 0x94, 0x42, 0xea, 0x89, 0x32, 0x81, 0xd9, 0xca, 0x15, 0x32, 0x28, 0x2b, 0xb6, + 0xa6, 0x3f, 0x48, 0x00, 0xa7, 0xdd, 0x91, 0x4d, 0x48, 0x5d, 0xbb, 0x47, 0xd4, 0xde, 0xf6, 0x86, + 0xa2, 0x8b, 0x3c, 0x93, 0xd5, 0x3b, 0xd1, 0xec, 0x6c, 0x2a, 0x6a, 0x57, 0x21, 0xfc, 0xcc, 0x83, + 0x24, 0x36, 0x81, 0x08, 0x92, 0x65, 0x83, 0xba, 0xd1, 0xdb, 0xe6, 0xfb, 0x82, 0x11, 0x2d, 0x50, + 0x7c, 0x4b, 0x88, 0x16, 0xa8, 0x8e, 0xbc, 0x89, 0x66, 0x99, 0xb8, 0x8e, 0x22, 0x37, 0xd1, 0x1c, + 0xcb, 0x9f, 0x56, 0x5b, 0xef, 0x1a, 0x64, 0x57, 0xee, 0xf4, 0x14, 0x54, 0x60, 0xf2, 0x3b, 0x72, + 0x72, 0x2e, 0x32, 0x69, 0xaa, 0x71, 0x5b, 0x1c, 0xe1, 0xe6, 0x8f, 0xa0, 0x3a, 0xf9, 0xfd, 0x9e, + 0x25, 0xfe, 0x4e, 0x6f, 0xa3, 0xd3, 0x6e, 0xa0, 0x19, 0xfc, 0x0a, 0xbc, 0x14, 0xfd, 0x66, 0x6b, + 0x0d, 0xdf, 0xfc, 0x04, 0x4a, 0xda, 0x78, 0xe7, 0xd1, 0x57, 0x4b, 0x33, 0x8f, 0x1e, 0x2f, 0x49, + 0x5f, 0x3c, 0x5e, 0x92, 0xbe, 0x7c, 0xbc, 0x24, 0xfd, 0xfb, 0xf1, 0x92, 0xf4, 0xab, 0xaf, 0x97, + 0x66, 0xbe, 0xf8, 0x7a, 0x69, 0xe6, 0xcb, 0xaf, 0x97, 0x66, 0x3e, 0x2a, 0xa5, 0xfe, 0x81, 0xfe, + 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x4c, 0x93, 0x55, 0x30, 0x20, 0x00, 0x00, } diff --git a/pkg/sql/execinfrapb/processors_sql.proto b/pkg/sql/execinfrapb/processors_sql.proto index 57b78e5ec5e0..856fc42bb4a0 100644 --- a/pkg/sql/execinfrapb/processors_sql.proto +++ b/pkg/sql/execinfrapb/processors_sql.proto @@ -194,6 +194,57 @@ message IndexSkipTableReaderSpec { // // If performing an index join (where a = c and b = d) (lookup columns is []): // Internal columns: | c | d | e | +// +// There is a special case when a "join reader" is used as the second join in +// a pair of joins to accomplish a LEFT_OUTER, LEFT_SEMI or LEFT_ANTI join. +// The first join in this pair of joins is unable to precisely evaluate the +// join condition and produces false positives. This is typical when the first +// join is a inverted join (see InvertedJoinerSpec), but can also be the case +// when the first join is being evaluated over an index that does not have all +// the columns needed to evaluate the join condition. The first join outputs +// rows in sorted order of the original left columns. The input stream columns +// for the second join are a combination of the original left columns and the +// lookup columns. The first join additionally adds a continuation column that +// demarcates a group of successive rows that correspond to an original left +// row. The first row in a group contains false (since it is not a +// continuation of the group) and successive rows contain true. +// +// The mapping from original join to the pair of joins is: +// LEFT_OUTER => LEFT_OUTER, LEFT_OUTER +// LEFT_SEMI => INNER, LEFT_SEMI (better than doing INNER, INNER, SORT, DISTINCT) +// LEFT_ANTI => LEFT_OUTER, LEFT_ANTI. +// where the first join always preserves order. +// +// More specifically, consider a lookup join example where the input stream +// columns are: | a | b | c | d | cont |. +// The lookup column is | d |. And the table columns are | e | f | with +// d = e. +// This join reader can see input of the form +// a1, b1, c1, d1, false +// a1, b1, c1, d2, true +// a1, b2, c1, null, false // when the first join is LEFT_OUTER +// a2, b1, c1, d3, false +// a2, b2, c1, d4, true +// +// Say both the results for (a1, b1, c1) are false positives, and the first +// of the (a2, b1, c1) result is a false positive. +// The output for LEFT_OUTER: +// a1, b1, c1, d1, null, null +// a1, b2, c1, null, null, null +// a2, b2, c1, d4, d4, f1 +// The d column is not part of the original left row, so will be projected +// away after the join. +// +// The output for LEFT_ANTI: +// a1, b1, c1, d1 +// a1, b2, c1, null +// Again, the d column will be projected away after the join. +// +// The output for LEFT_SEMI: +// a1, b1, c1, d3 +// Again, the d column will be projected away after the join. +// +// This special case is message JoinReaderSpec { optional sqlbase.TableDescriptor table = 1 [(gogoproto.nullable) = false]; @@ -263,6 +314,10 @@ message JoinReaderSpec { // result of the secondary index joined against the primary index is // expected to contain the materialized system columns. optional bool has_system_columns = 13 [(gogoproto.nullable) = false]; + + // LeftJoinWithPairedJoiner is used when a left {outer,anti,semi} join is + // being achieved by pairing two joins. See the comment above. + optional bool left_join_with_paired_joiner = 14 [(gogoproto.nullable) = false]; } // SorterSpec is the specification for a "sorting aggregator". A sorting @@ -484,6 +539,17 @@ message HashJoinerSpec { // that was indexed). For LEFT_SEMI and LEFT_ANTI, the "internal columns" are // the columns of the left input. // +// In many cases, the inverted join will contain false positives wrt the +// original join condition. This is handled by pairing it with a lookup join. +// This pairing works naturally when the user query specified INNER, by +// running an INNER inverted join followed by INNER lookup join. For a user +// query with LEFT_OUTER/LEFT_ANTI, the inverted join is run as a LEFT_OUTER +// with a special mode that outputs an additional bool column that represents +// whether this row is a continuation of a group. This is paired with a lookup +// join that also knows about the semantics of this bool column. For a user +// query with LEFT_SEMI, the inverted join is run as an INNER join with the +// same special mode. See the JoinReaderSpec for an example. +// // Example: // Input stream columns: | a | b | // Table columns: | c | d | e | @@ -498,6 +564,9 @@ message HashJoinerSpec { // Internal columns for INNER and LEFT_OUTER: | a | b | c | d | e | // where d, e are not populated. // Internal columns for LEFT_SEMI and LEFT_ANTI: | a | b | +// +// For a LEFT_OUTER with OutputGroupCountForLeftJoin = true, the internal +// columns including an additional bool column as the last column. message InvertedJoinerSpec { optional sqlbase.TableDescriptor table = 1 [(gogoproto.nullable) = false]; @@ -545,6 +614,11 @@ message InvertedJoinerSpec { // Indicates that the inverted joiner should maintain the ordering of the // input stream. optional bool maintain_ordering = 7 [(gogoproto.nullable) = false]; + + // Indicates that the join should output a continuation column that + // indicates whether a row is a continuation of a group corresponding to a + // left row. + optional bool output_continuation_for_left_join = 8 [(gogoproto.nullable) = false]; } // InvertedFiltererSpec is the specification of a processor that does filtering diff --git a/pkg/sql/rowexec/inverted_joiner.go b/pkg/sql/rowexec/inverted_joiner.go index 65f1a60267c4..211284be691a 100644 --- a/pkg/sql/rowexec/inverted_joiner.go +++ b/pkg/sql/rowexec/inverted_joiner.go @@ -140,6 +140,10 @@ type invertedJoiner struct { // A row with one element, corresponding to an encoded inverted column // value. Used to construct the span of the index for that value. invertedColRow rowenc.EncDatumRow + + outputContinuationCol bool + trueEncDatum rowenc.EncDatum + falseEncDatum rowenc.EncDatum } var _ execinfra.Processor = &invertedJoiner{} @@ -298,6 +302,11 @@ func newInvertedJoiner( ij.diskMonitor, ) + if spec.OutputContinuationForLeftJoin { + ij.outputContinuationCol = true + ij.trueEncDatum = rowenc.DatumToEncDatum(types.Bool, tree.DBoolTrue) + ij.falseEncDatum = rowenc.DatumToEncDatum(types.Bool, tree.DBoolFalse) + } return ij, nil } @@ -532,7 +541,11 @@ func (ij *invertedJoiner) emitRow() ( if !seenMatch { switch ij.joinType { case descpb.LeftOuterJoin: - return ijEmittingRows, ij.renderUnmatchedRow(ij.inputRows[inputRowIdx]), nil + ij.renderUnmatchedRow(ij.inputRows[inputRowIdx]) + if ij.outputContinuationCol { + ij.combinedRow = append(ij.combinedRow, ij.falseEncDatum) + } + return ijEmittingRows, ij.combinedRow, nil case descpb.LeftAntiJoin: return ijEmittingRows, ij.inputRows[inputRowIdx], nil } @@ -564,9 +577,18 @@ func (ij *invertedJoiner) emitRow() ( return nil } if renderedRow != nil { + firstRowForInputIdx := ij.emitCursor.seenMatch ij.emitCursor.seenMatch = true switch ij.joinType { case descpb.InnerJoin, descpb.LeftOuterJoin: + if ij.outputContinuationCol { + if firstRowForInputIdx { + ij.combinedRow = append(ij.combinedRow, ij.falseEncDatum) + } else { + ij.combinedRow = append(ij.combinedRow, ij.trueEncDatum) + } + renderedRow = ij.combinedRow + } return ijEmittingRows, renderedRow, nil case descpb.LeftSemiJoin: // Skip the rest of the joined rows. @@ -588,7 +610,8 @@ func (ij *invertedJoiner) emitRow() ( } // render constructs a row with columns from both sides. The ON condition is -// evaluated; if it fails, returns nil. +// evaluated; if it fails, returns nil. When it returns a non-nil row, it is +// identical to ij.combinedRow. func (ij *invertedJoiner) render(lrow, rrow rowenc.EncDatumRow) (rowenc.EncDatumRow, error) { ij.combinedRow = append(ij.combinedRow[:0], lrow...) ij.combinedRow = append(ij.combinedRow, rrow...) @@ -602,13 +625,12 @@ func (ij *invertedJoiner) render(lrow, rrow rowenc.EncDatumRow) (rowenc.EncDatum } // renderUnmatchedRow creates a result row given an unmatched row. -func (ij *invertedJoiner) renderUnmatchedRow(row rowenc.EncDatumRow) rowenc.EncDatumRow { +func (ij *invertedJoiner) renderUnmatchedRow(row rowenc.EncDatumRow) { ij.combinedRow = append(ij.combinedRow[:0], row...) ij.combinedRow = ij.combinedRow[:cap(ij.combinedRow)] for i := len(row); i < len(ij.combinedRow); i++ { ij.combinedRow[i].Datum = tree.DNull } - return ij.combinedRow } func (ij *invertedJoiner) transformToKeyRow(row rowenc.EncDatumRow) { diff --git a/pkg/sql/rowexec/joinreader.go b/pkg/sql/rowexec/joinreader.go index f134a301b252..316885b8ae27 100644 --- a/pkg/sql/rowexec/joinreader.go +++ b/pkg/sql/rowexec/joinreader.go @@ -24,6 +24,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/rowcontainer" "github.com/cockroachdb/cockroach/pkg/sql/rowenc" "github.com/cockroachdb/cockroach/pkg/sql/scrub" + "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/span" "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/cockroach/pkg/util" @@ -46,6 +47,8 @@ const ( jrPerformingLookup // jrEmittingRows means we are emitting the results of the index lookup. jrEmittingRows + // jrReadyToDrain means we are done but have not yet started draining + jrReadyToDrain ) // joinReaderType represents the type of join being used. @@ -101,6 +104,31 @@ type joinReader struct { // State variables for each batch of input rows. scratchInputRows rowenc.EncDatumRows + + // Fields used when this is the second join in a pair of joins that + // are together implementing left {outer,semi,anti} joins where the + // first join produces false positives because it cannot evaluate + // the whole expression (or evaluate it accurately, as in sometimes + // the case with inverted indexes). The first join is running a + // left outer join, and each group of rows seen by the second join + // correspond to one left row. + // + // TODO(sumeer): add support for joinReader to also be the first + // join in this pair, say when the index can evaluate most of the + // join condition (the part with low selectivity), but not all. + // Currently only the invertedJoiner can serve as the first join + // in the pair. + + // The current batch of input rows belong to groups which are + // tracked in groupingState. The last row from the last batch + // is in lastInputRowFromLastBatch -- it is tracked because we + // don't know if it was the last row in a group until we get + // to the next batch. + groupingState *inputBatchGroupingState + lastInputRowFromLastBatch rowenc.EncDatumRow + lastGroupFromLastBatchMatched bool + lastGroupContinued bool + groupStateReset bool } var _ execinfra.Processor = &joinReader{} @@ -145,6 +173,9 @@ func newJoinReader( inputTypes: input.OutputTypes(), lookupCols: lookupCols, } + if spec.LeftJoinWithPairedJoiner { + jr.groupingState = &inputBatchGroupingState{} + } var err error var isSecondary bool @@ -300,6 +331,7 @@ func (jr *joinReader) initJoinReaderStrategy( joinerBase: &jr.joinerBase, defaultSpanGenerator: spanGenerator, isPartialJoin: jr.joinType == descpb.LeftSemiJoin || jr.joinType == descpb.LeftAntiJoin, + groupingState: jr.groupingState, } return } @@ -332,6 +364,7 @@ func (jr *joinReader) initJoinReaderStrategy( defaultSpanGenerator: spanGenerator, isPartialJoin: jr.joinType == descpb.LeftSemiJoin || jr.joinType == descpb.LeftAntiJoin, lookedUpRows: drc, + groupingState: jr.groupingState, } } @@ -400,11 +433,15 @@ func (jr *joinReader) Next() (rowenc.EncDatumRow, *execinfrapb.ProducerMetadata) var meta *execinfrapb.ProducerMetadata switch jr.runningState { case jrReadingInput: - jr.runningState, meta = jr.readInput() + jr.runningState, row, meta = jr.readInput() case jrPerformingLookup: jr.runningState, meta = jr.performLookup() case jrEmittingRows: jr.runningState, row, meta = jr.emitRow() + case jrReadyToDrain: + jr.MoveToDraining(nil) + meta = jr.DrainHelper() + jr.runningState = jrStateUnknown default: log.Fatalf(jr.Ctx, "unsupported state: %d", jr.runningState) } @@ -422,42 +459,104 @@ func (jr *joinReader) Next() (rowenc.EncDatumRow, *execinfrapb.ProducerMetadata) } // readInput reads the next batch of input rows and starts an index scan. -func (jr *joinReader) readInput() (joinReaderState, *execinfrapb.ProducerMetadata) { +// It can sometimes emit a single row on behalf of the previous batch. +func (jr *joinReader) readInput() ( + joinReaderState, + rowenc.EncDatumRow, + *execinfrapb.ProducerMetadata, +) { + if jr.groupingState != nil { + if !jr.groupStateReset { + jr.lastGroupFromLastBatchMatched = jr.groupingState.lastGroupMatched() + jr.groupingState.reset() + jr.lastGroupContinued = false + jr.groupStateReset = true + } + // Else, returning meta interrupted reading the input batch, so already + // did the if-block work for this batch. + } // Read the next batch of input rows. for jr.curBatchSizeBytes < jr.batchSizeBytes { row, meta := jr.input.Next() if meta != nil { if meta.Err != nil { jr.MoveToDraining(nil /* err */) - return jrStateUnknown, meta + return jrStateUnknown, nil, meta } - return jrReadingInput, meta + return jrReadingInput, nil, meta } if row == nil { break } jr.curBatchSizeBytes += int64(row.Size()) + if jr.groupingState != nil { + continuationEncDatum := row[len(row)-1] + if err := continuationEncDatum.EnsureDecoded(types.Bool, &jr.alloc); err != nil { + jr.MoveToDraining(err) + return jrStateUnknown, nil, jr.DrainHelper() + } + continuationVal := bool(*continuationEncDatum.Datum.(*tree.DBool)) + jr.groupingState.addContinuationValForRow(continuationVal) + if len(jr.scratchInputRows) == 0 && continuationVal { + // First row in batch is a continuation of last group + jr.lastGroupContinued = true + } + row = row[:len(row)-1] + } jr.scratchInputRows = append(jr.scratchInputRows, jr.rowAlloc.CopyRow(row)) } + var outRow rowenc.EncDatumRow + // Finished reading the input batch. + if jr.groupingState != nil { + jr.groupStateReset = false + if jr.lastInputRowFromLastBatch != nil && !jr.lastGroupContinued { + // Group ended in previous batch. + if !jr.lastGroupFromLastBatchMatched { + // Handle the cases where we need to emit the left row when there is no + // match. + switch jr.joinType { + case descpb.LeftOuterJoin: + outRow = jr.renderUnmatchedRow(jr.lastInputRowFromLastBatch, leftSide) + case descpb.LeftAntiJoin: + outRow = jr.lastInputRowFromLastBatch + } + jr.lastInputRowFromLastBatch = nil + } + // Else the last group matched, so already emitted 1+ row for left outer + // join, 1 row for semi join. + } + // Last group continued, or this is the first ever batch. Either way, + // we don't need to do anything special for the last batch. + } if len(jr.scratchInputRows) == 0 { log.VEventf(jr.Ctx, 1, "no more input rows") + if outRow != nil { + return jrReadyToDrain, outRow, nil + } // We're done. jr.MoveToDraining(nil) - return jrStateUnknown, jr.DrainHelper() + return jrStateUnknown, nil, jr.DrainHelper() } log.VEventf(jr.Ctx, 1, "read %d input rows", len(jr.scratchInputRows)) + if jr.groupingState != nil && len(jr.scratchInputRows) > 0 { + jr.lastInputRowFromLastBatch = jr.scratchInputRows[len(jr.scratchInputRows)-1] + if jr.lastGroupFromLastBatchMatched && jr.lastGroupContinued { + jr.groupingState.setFirstGroupMatched() + } + } + spans, err := jr.strategy.processLookupRows(jr.scratchInputRows) if err != nil { jr.MoveToDraining(err) - return jrStateUnknown, jr.DrainHelper() + return jrStateUnknown, nil, jr.DrainHelper() } jr.scratchInputRows = jr.scratchInputRows[:0] jr.curBatchSizeBytes = 0 if len(spans) == 0 { // All of the input rows were filtered out. Skip the index lookup. - return jrEmittingRows, nil + return jrEmittingRows, outRow, nil } // Sort the spans for the following cases: @@ -480,10 +579,10 @@ func (jr *joinReader) readInput() (joinReaderState, *execinfrapb.ProducerMetadat jr.Ctx, jr.FlowCtx.Txn, spans, jr.shouldLimitBatches, 0, /* limitHint */ jr.FlowCtx.TraceKV); err != nil { jr.MoveToDraining(err) - return jrStateUnknown, jr.DrainHelper() + return jrStateUnknown, nil, jr.DrainHelper() } - return jrPerformingLookup, nil + return jrPerformingLookup, outRow, nil } // performLookup reads the next batch of index rows. @@ -667,3 +766,62 @@ func (jr *joinReader) Child(nth int, verbose bool) execinfra.OpNode { } panic(errors.AssertionFailedf("invalid index %d", nth)) } + +// inputBatchGroupingState encapsulates the state needed for all the +// groups in an input batch. +// Ideally, we would unify this with the per-row match tracking logic, +// but that is handled differently in joinReaderOrderingStrategy and +// joinReaderNoOrderingStrategy. TOOD(sumeer): look more carefully +// at what can be done. +type inputBatchGroupingState struct { + // Row num in batch to the group num. + batchRowToGroupNum []int + // For each group num, whether it matched. + groupMatched []bool + // For each group num, the first row num in the group. + groupToFirstRow []int +} + +func (ib *inputBatchGroupingState) reset() { + ib.batchRowToGroupNum = ib.batchRowToGroupNum[:0] + ib.groupMatched = ib.groupMatched[:0] + ib.groupToFirstRow = ib.groupToFirstRow[:0] +} + +func (ib *inputBatchGroupingState) addContinuationValForRow(cont bool) { + if len(ib.groupMatched) == 0 || !cont { + // First row in input batch or the start of a new group. + ib.groupMatched = append(ib.groupMatched, false) + ib.groupToFirstRow = append(ib.groupToFirstRow, len(ib.batchRowToGroupNum)) + } + ib.batchRowToGroupNum = append(ib.batchRowToGroupNum, len(ib.groupMatched)-1) +} + +func (ib *inputBatchGroupingState) setFirstGroupMatched() { + ib.groupMatched[0] = true +} + +func (ib *inputBatchGroupingState) setMatched(rowIndex int) { + ib.groupMatched[ib.batchRowToGroupNum[rowIndex]] = true +} + +func (ib *inputBatchGroupingState) getMatched(rowIndex int) bool { + return ib.groupMatched[ib.batchRowToGroupNum[rowIndex]] +} + +func (ib *inputBatchGroupingState) lastGroupMatched() bool { + if len(ib.groupMatched) == 0 { + return false + } + return ib.groupMatched[len(ib.groupMatched)-1] +} + +func (ib *inputBatchGroupingState) isUnmatched(rowIndex int) bool { + // Return true for the first row index in a group that is complete and group is not matched. + lastGroup := len(ib.groupMatched) - 1 + groupNum := ib.batchRowToGroupNum[rowIndex] + if lastGroup == groupNum { + return false + } + return ib.groupMatched[groupNum] && ib.groupToFirstRow[groupNum] == rowIndex +} diff --git a/pkg/sql/rowexec/joinreader_strategies.go b/pkg/sql/rowexec/joinreader_strategies.go index 5b7599eacf81..ec8536f54ebc 100644 --- a/pkg/sql/rowexec/joinreader_strategies.go +++ b/pkg/sql/rowexec/joinreader_strategies.go @@ -160,6 +160,8 @@ type joinReaderNoOrderingStrategy struct { matchingInputRowIndices []int lookedUpRow rowenc.EncDatumRow } + + groupingState *inputBatchGroupingState } // getLookupRowsBatchSizeHint returns the batch size for the join reader no @@ -196,7 +198,8 @@ func (s *joinReaderNoOrderingStrategy) processLookedUpRow( // overwriting the caller's slice. s.scratchMatchingInputRowIndices = s.scratchMatchingInputRowIndices[:0] for _, inputRowIdx := range matchingInputRowIndices { - if !s.matched[inputRowIdx] { + if (s.groupingState == nil && !s.matched[inputRowIdx]) || + !s.groupingState.getMatched(inputRowIdx) { s.scratchMatchingInputRowIndices = append(s.scratchMatchingInputRowIndices, inputRowIdx) } } @@ -226,7 +229,7 @@ func (s *joinReaderNoOrderingStrategy) nextRowToEmit( if len(s.matched) != 0 { s.emitState.unmatchedInputRowIndices = s.emitState.unmatchedInputRowIndices[:0] for inputRowIdx, m := range s.matched { - if !m { + if (s.groupingState == nil && !m) || s.groupingState.isUnmatched(inputRowIdx) { s.emitState.unmatchedInputRowIndices = append(s.emitState.unmatchedInputRowIndices, inputRowIdx) } } @@ -240,6 +243,10 @@ func (s *joinReaderNoOrderingStrategy) nextRowToEmit( } inputRow := s.inputRows[s.emitState.unmatchedInputRowIndices[s.emitState.unmatchedInputRowIndicesCursor]] s.emitState.unmatchedInputRowIndicesCursor++ + // When s.groupingState != nil, for either a left outer join or left anti + // join, this will emit a row that includes a possibly non-nil value in + // the lookup columns, which will differ for different rows in a group. + // These will need to be projected away. if !s.joinType.ShouldIncludeRightColsInOutput() { return inputRow, jrEmittingRows, nil } @@ -250,6 +257,9 @@ func (s *joinReaderNoOrderingStrategy) nextRowToEmit( inputRowIdx := s.emitState.matchingInputRowIndices[s.emitState.matchingInputRowIndicesCursor] s.emitState.matchingInputRowIndicesCursor++ inputRow := s.inputRows[inputRowIdx] + if s.groupingState != nil && s.joinType == descpb.LeftSemiJoin && s.groupingState.getMatched(inputRowIdx) { + continue + } // Render the output row, this also evaluates the ON condition. outputRow, err := s.render(inputRow, s.emitState.lookedUpRow) @@ -262,11 +272,18 @@ func (s *joinReaderNoOrderingStrategy) nextRowToEmit( } s.matched[inputRowIdx] = true + if s.groupingState != nil { + s.groupingState.setMatched(inputRowIdx) + } if !s.joinType.ShouldIncludeRightColsInOutput() { if s.joinType == descpb.LeftAntiJoin { // Skip emitting row. continue } + // When s.groupingState != nil, for a left semi join, this will emit a + // row that includes a possibly non-nil value in the lookup columns, + // which will differ for different rows in a group. These will need to + // be projected away. return inputRow, jrEmittingRows, nil } return outputRow, jrEmittingRows, nil @@ -385,6 +402,8 @@ type joinReaderOrderingStrategy struct { // match means that there's no need to output an outer or anti join row. seenMatch bool } + + groupingState *inputBatchGroupingState } func (s *joinReaderOrderingStrategy) getLookupRowsBatchSizeHint() int64 { @@ -441,7 +460,8 @@ func (s *joinReaderOrderingStrategy) processLookedUpRow( // for this input row yet. Additionally, since we don't have to render // anything to output a Semi or Anti join match, we can evaluate our // on condition now and only buffer if we pass it. - if len(s.inputRowIdxToLookedUpRowIndices[inputRowIdx]) == 0 { + if (s.groupingState == nil && len(s.inputRowIdxToLookedUpRowIndices[inputRowIdx]) == 0) || + !s.groupingState.getMatched(inputRowIdx) { renderedRow, err := s.render(s.inputRows[inputRowIdx], row) if err != nil { return jrStateUnknown, err @@ -450,6 +470,9 @@ func (s *joinReaderOrderingStrategy) processLookedUpRow( // We failed our on-condition - don't buffer anything. continue } + if s.groupingState != nil { + s.groupingState.setMatched(inputRowIdx) + } s.inputRowIdxToLookedUpRowIndices[inputRowIdx] = partialJoinSentinel } } @@ -485,11 +508,16 @@ func (s *joinReaderOrderingStrategy) nextRowToEmit( if s.emitCursor.outputRowIdx >= len(lookedUpRows) { // We have no more rows for the current input row. Emit an outer or anti // row if we didn't see a match, and bump to the next input row. + inputRowIdx := s.emitCursor.inputRowIdx s.emitCursor.inputRowIdx++ s.emitCursor.outputRowIdx = 0 seenMatch := s.emitCursor.seenMatch s.emitCursor.seenMatch = false - if !seenMatch { + // When s.groupingState != nil, for either a left outer join or left anti + // join, this will emit a row that includes a possibly non-nil value in + // the lookup columns, which will differ for different rows in a group. + // These will need to be projected away. + if (s.groupingState == nil && !seenMatch) || s.groupingState.isUnmatched(inputRowIdx) { switch s.joinType { case descpb.LeftOuterJoin: // An outer-join non-match means we emit the input row with NULLs for @@ -509,11 +537,13 @@ func (s *joinReaderOrderingStrategy) nextRowToEmit( s.emitCursor.outputRowIdx++ switch s.joinType { case descpb.LeftSemiJoin: - // A semi-join match means we emit our input row. + // A semi-join match means we emit our input row. This is the case where + // we used the partialJoinSentinel. s.emitCursor.seenMatch = true return inputRow, jrEmittingRows, nil case descpb.LeftAntiJoin: - // An anti-join match means we emit nothing. + // An anti-join match means we emit nothing. This is the case where + // we used the partialJoinSentinel. s.emitCursor.seenMatch = true return nil, jrEmittingRows, nil } @@ -528,6 +558,9 @@ func (s *joinReaderOrderingStrategy) nextRowToEmit( } if outputRow != nil { s.emitCursor.seenMatch = true + if s.groupingState != nil { + s.groupingState.setMatched(s.emitCursor.inputRowIdx) + } } return outputRow, jrEmittingRows, nil }