be/src/exec/common/join_op_utils.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | // Lightweight join-op level types split out of join_utils.h so that |
21 | | // exec/pipeline/dependency.h (which holds JoinOpVariants / AsofIndexVariant |
22 | | // members by value) does not have to see the hash-table machinery. |
23 | | // Everything here depends only on thrift enums and std containers. |
24 | | |
25 | | #include <gen_cpp/PlanNodes_types.h> |
26 | | #include <pdqsort.h> |
27 | | |
28 | | #include <cstdint> |
29 | | #include <variant> |
30 | | #include <vector> |
31 | | |
32 | | #include "common/compiler_util.h" |
33 | | |
34 | | namespace doris { |
35 | | |
36 | | using JoinOpVariants = |
37 | | std::variant<std::integral_constant<TJoinOp::type, TJoinOp::INNER_JOIN>, |
38 | | std::integral_constant<TJoinOp::type, TJoinOp::LEFT_SEMI_JOIN>, |
39 | | std::integral_constant<TJoinOp::type, TJoinOp::LEFT_ANTI_JOIN>, |
40 | | std::integral_constant<TJoinOp::type, TJoinOp::LEFT_OUTER_JOIN>, |
41 | | std::integral_constant<TJoinOp::type, TJoinOp::FULL_OUTER_JOIN>, |
42 | | std::integral_constant<TJoinOp::type, TJoinOp::RIGHT_OUTER_JOIN>, |
43 | | std::integral_constant<TJoinOp::type, TJoinOp::CROSS_JOIN>, |
44 | | std::integral_constant<TJoinOp::type, TJoinOp::RIGHT_SEMI_JOIN>, |
45 | | std::integral_constant<TJoinOp::type, TJoinOp::RIGHT_ANTI_JOIN>, |
46 | | std::integral_constant<TJoinOp::type, TJoinOp::NULL_AWARE_LEFT_ANTI_JOIN>, |
47 | | std::integral_constant<TJoinOp::type, TJoinOp::NULL_AWARE_LEFT_SEMI_JOIN>, |
48 | | std::integral_constant<TJoinOp::type, TJoinOp::ASOF_LEFT_INNER_JOIN>, |
49 | | std::integral_constant<TJoinOp::type, TJoinOp::ASOF_LEFT_OUTER_JOIN>>; |
50 | | |
51 | 509k | inline bool is_asof_join(TJoinOp::type join_op) { |
52 | 509k | return join_op == TJoinOp::ASOF_LEFT_INNER_JOIN || join_op == TJoinOp::ASOF_LEFT_OUTER_JOIN; |
53 | 509k | } |
54 | | |
55 | | template <int JoinOpType> |
56 | | inline constexpr bool is_asof_join_op_v = |
57 | | JoinOpType == TJoinOp::ASOF_LEFT_INNER_JOIN || JoinOpType == TJoinOp::ASOF_LEFT_OUTER_JOIN; |
58 | | |
59 | | template <int JoinOpType> |
60 | | inline constexpr bool is_asof_outer_join_op_v = JoinOpType == TJoinOp::ASOF_LEFT_OUTER_JOIN; |
61 | | |
62 | | // ASOF JOIN index with inline values for cache-friendly branchless binary search. |
63 | | // IntType is the integer representation of the ASOF column value: |
64 | | // uint32_t for DateV2, uint64_t for DateTimeV2 and TimestampTZ, |
65 | | // int64_t for TimestampNs, and AsofMixedDateTimeKey for exact mixed |
66 | | // TimestampNs/DateTimeV2 comparisons. |
67 | | // Rows are sorted by asof_value during build, then materialized into SoA arrays |
68 | | // so probe-side binary search only touches the ASOF values hot path. |
69 | | template <typename IntType> |
70 | | struct AsofIndexGroup { |
71 | | using int_type = IntType; |
72 | | |
73 | | struct Entry { |
74 | | IntType asof_value; |
75 | | uint32_t row_index; // 1-based, 0 = invalid/padding |
76 | | }; |
77 | | |
78 | | std::vector<Entry> entries; |
79 | | std::vector<IntType> asof_values; |
80 | | std::vector<uint32_t> row_indexes; |
81 | | |
82 | 9.63k | void add_row(IntType value, uint32_t row_idx) { entries.push_back({value, row_idx}); }_ZN5doris14AsofIndexGroupIoE7add_rowEoj Line | Count | Source | 82 | 5 | void add_row(IntType value, uint32_t row_idx) { entries.push_back({value, row_idx}); } |
_ZN5doris14AsofIndexGroupIjE7add_rowEjj Line | Count | Source | 82 | 1.12k | void add_row(IntType value, uint32_t row_idx) { entries.push_back({value, row_idx}); } |
_ZN5doris14AsofIndexGroupImE7add_rowEmj Line | Count | Source | 82 | 8.40k | void add_row(IntType value, uint32_t row_idx) { entries.push_back({value, row_idx}); } |
_ZN5doris14AsofIndexGroupIlE7add_rowElj Line | Count | Source | 82 | 107 | void add_row(IntType value, uint32_t row_idx) { entries.push_back({value, row_idx}); } |
|
83 | | |
84 | 2.67k | void sort_and_finalize() { |
85 | 2.67k | if (entries.empty()) { |
86 | 4 | return; |
87 | 4 | } |
88 | 2.67k | if (entries.size() > 1) { |
89 | 2.09k | pdqsort(entries.begin(), entries.end(), |
90 | 24.0k | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; });_ZZN5doris14AsofIndexGroupIoE17sort_and_finalizeEvENKUlRKNS1_5EntryES4_E_clES4_S4_ Line | Count | Source | 90 | 1 | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); |
_ZZN5doris14AsofIndexGroupIjE17sort_and_finalizeEvENKUlRKNS1_5EntryES4_E_clES4_S4_ Line | Count | Source | 90 | 2.10k | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); |
_ZZN5doris14AsofIndexGroupImE17sort_and_finalizeEvENKUlRKNS1_5EntryES4_E_clES4_S4_ Line | Count | Source | 90 | 21.7k | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); |
_ZZN5doris14AsofIndexGroupIlE17sort_and_finalizeEvENKUlRKNS1_5EntryES4_E_clES4_S4_ Line | Count | Source | 90 | 201 | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); |
|
91 | 2.09k | } |
92 | | |
93 | 2.67k | asof_values.resize(entries.size()); |
94 | 2.67k | row_indexes.resize(entries.size()); |
95 | 12.3k | for (size_t i = 0; i < entries.size(); ++i) { |
96 | 9.66k | asof_values[i] = entries[i].asof_value; |
97 | 9.66k | row_indexes[i] = entries[i].row_index; |
98 | 9.66k | } |
99 | | |
100 | 2.67k | std::vector<Entry>().swap(entries); |
101 | 2.67k | } _ZN5doris14AsofIndexGroupIoE17sort_and_finalizeEv Line | Count | Source | 84 | 4 | void sort_and_finalize() { | 85 | 4 | if (entries.empty()) { | 86 | 0 | return; | 87 | 0 | } | 88 | 4 | if (entries.size() > 1) { | 89 | 1 | pdqsort(entries.begin(), entries.end(), | 90 | 1 | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); | 91 | 1 | } | 92 | | | 93 | 4 | asof_values.resize(entries.size()); | 94 | 4 | row_indexes.resize(entries.size()); | 95 | 9 | for (size_t i = 0; i < entries.size(); ++i) { | 96 | 5 | asof_values[i] = entries[i].asof_value; | 97 | 5 | row_indexes[i] = entries[i].row_index; | 98 | 5 | } | 99 | | | 100 | 4 | std::vector<Entry>().swap(entries); | 101 | 4 | } |
_ZN5doris14AsofIndexGroupIjE17sort_and_finalizeEv Line | Count | Source | 84 | 52 | void sort_and_finalize() { | 85 | 52 | if (entries.empty()) { | 86 | 4 | return; | 87 | 4 | } | 88 | 48 | if (entries.size() > 1) { | 89 | 29 | pdqsort(entries.begin(), entries.end(), | 90 | 29 | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); | 91 | 29 | } | 92 | | | 93 | 48 | asof_values.resize(entries.size()); | 94 | 48 | row_indexes.resize(entries.size()); | 95 | 1.16k | for (size_t i = 0; i < entries.size(); ++i) { | 96 | 1.12k | asof_values[i] = entries[i].asof_value; | 97 | 1.12k | row_indexes[i] = entries[i].row_index; | 98 | 1.12k | } | 99 | | | 100 | 48 | std::vector<Entry>().swap(entries); | 101 | 48 | } |
_ZN5doris14AsofIndexGroupImE17sort_and_finalizeEv Line | Count | Source | 84 | 2.59k | void sort_and_finalize() { | 85 | 2.59k | if (entries.empty()) { | 86 | 0 | return; | 87 | 0 | } | 88 | 2.59k | if (entries.size() > 1) { | 89 | 2.03k | pdqsort(entries.begin(), entries.end(), | 90 | 2.03k | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); | 91 | 2.03k | } | 92 | | | 93 | 2.59k | asof_values.resize(entries.size()); | 94 | 2.59k | row_indexes.resize(entries.size()); | 95 | 11.0k | for (size_t i = 0; i < entries.size(); ++i) { | 96 | 8.43k | asof_values[i] = entries[i].asof_value; | 97 | 8.43k | row_indexes[i] = entries[i].row_index; | 98 | 8.43k | } | 99 | | | 100 | 2.59k | std::vector<Entry>().swap(entries); | 101 | 2.59k | } |
_ZN5doris14AsofIndexGroupIlE17sort_and_finalizeEv Line | Count | Source | 84 | 26 | void sort_and_finalize() { | 85 | 26 | if (entries.empty()) { | 86 | 0 | return; | 87 | 0 | } | 88 | 26 | if (entries.size() > 1) { | 89 | 21 | pdqsort(entries.begin(), entries.end(), | 90 | 21 | [](const Entry& a, const Entry& b) { return a.asof_value < b.asof_value; }); | 91 | 21 | } | 92 | | | 93 | 26 | asof_values.resize(entries.size()); | 94 | 26 | row_indexes.resize(entries.size()); | 95 | 133 | for (size_t i = 0; i < entries.size(); ++i) { | 96 | 107 | asof_values[i] = entries[i].asof_value; | 97 | 107 | row_indexes[i] = entries[i].row_index; | 98 | 107 | } | 99 | | | 100 | 26 | std::vector<Entry>().swap(entries); | 101 | 26 | } |
|
102 | | |
103 | 821 | const IntType* values_data() const { return asof_values.data(); }_ZNK5doris14AsofIndexGroupIjE11values_dataEv Line | Count | Source | 103 | 1 | const IntType* values_data() const { return asof_values.data(); } |
_ZNK5doris14AsofIndexGroupImE11values_dataEv Line | Count | Source | 103 | 816 | const IntType* values_data() const { return asof_values.data(); } |
_ZNK5doris14AsofIndexGroupIlE11values_dataEv Line | Count | Source | 103 | 4 | const IntType* values_data() const { return asof_values.data(); } |
Unexecuted instantiation: _ZNK5doris14AsofIndexGroupIoE11values_dataEv |
104 | | |
105 | | // Branchless lower_bound: first i where asof_values[i] >= target |
106 | 466 | ALWAYS_INLINE size_t lower_bound(IntType target) const { |
107 | 466 | size_t lo = 0, n = asof_values.size(); |
108 | 2.34k | while (n > 1) { |
109 | 1.88k | size_t half = n / 2; |
110 | 1.88k | lo += half * (asof_values[lo + half] < target); |
111 | 1.88k | n -= half; |
112 | 1.88k | } |
113 | 466 | if (lo < asof_values.size()) { |
114 | 465 | lo += (asof_values[lo] < target); |
115 | 465 | } |
116 | 466 | return lo; |
117 | 466 | } _ZNK5doris14AsofIndexGroupIjE11lower_boundEj Line | Count | Source | 106 | 33 | ALWAYS_INLINE size_t lower_bound(IntType target) const { | 107 | 33 | size_t lo = 0, n = asof_values.size(); | 108 | 163 | while (n > 1) { | 109 | 130 | size_t half = n / 2; | 110 | 130 | lo += half * (asof_values[lo + half] < target); | 111 | 130 | n -= half; | 112 | 130 | } | 113 | 33 | if (lo < asof_values.size()) { | 114 | 32 | lo += (asof_values[lo] < target); | 115 | 32 | } | 116 | 33 | return lo; | 117 | 33 | } |
_ZNK5doris14AsofIndexGroupImE11lower_boundEm Line | Count | Source | 106 | 421 | ALWAYS_INLINE size_t lower_bound(IntType target) const { | 107 | 421 | size_t lo = 0, n = asof_values.size(); | 108 | 2.14k | while (n > 1) { | 109 | 1.72k | size_t half = n / 2; | 110 | 1.72k | lo += half * (asof_values[lo + half] < target); | 111 | 1.72k | n -= half; | 112 | 1.72k | } | 113 | 421 | if (lo < asof_values.size()) { | 114 | 421 | lo += (asof_values[lo] < target); | 115 | 421 | } | 116 | 421 | return lo; | 117 | 421 | } |
_ZNK5doris14AsofIndexGroupIlE11lower_boundEl Line | Count | Source | 106 | 10 | ALWAYS_INLINE size_t lower_bound(IntType target) const { | 107 | 10 | size_t lo = 0, n = asof_values.size(); | 108 | 40 | while (n > 1) { | 109 | 30 | size_t half = n / 2; | 110 | 30 | lo += half * (asof_values[lo + half] < target); | 111 | 30 | n -= half; | 112 | 30 | } | 113 | 10 | if (lo < asof_values.size()) { | 114 | 10 | lo += (asof_values[lo] < target); | 115 | 10 | } | 116 | 10 | return lo; | 117 | 10 | } |
_ZNK5doris14AsofIndexGroupIoE11lower_boundEo Line | Count | Source | 106 | 2 | ALWAYS_INLINE size_t lower_bound(IntType target) const { | 107 | 2 | size_t lo = 0, n = asof_values.size(); | 108 | 4 | while (n > 1) { | 109 | 2 | size_t half = n / 2; | 110 | 2 | lo += half * (asof_values[lo + half] < target); | 111 | 2 | n -= half; | 112 | 2 | } | 113 | 2 | if (lo < asof_values.size()) { | 114 | 2 | lo += (asof_values[lo] < target); | 115 | 2 | } | 116 | 2 | return lo; | 117 | 2 | } |
|
118 | | |
119 | | // Branchless upper_bound: first i where asof_values[i] > target |
120 | 961 | ALWAYS_INLINE size_t upper_bound(IntType target) const { |
121 | 961 | size_t lo = 0, n = asof_values.size(); |
122 | 4.11k | while (n > 1) { |
123 | 3.15k | size_t half = n / 2; |
124 | 3.15k | lo += half * (asof_values[lo + half] <= target); |
125 | 3.15k | n -= half; |
126 | 3.15k | } |
127 | 961 | if (lo < asof_values.size()) { |
128 | 960 | lo += (asof_values[lo] <= target); |
129 | 960 | } |
130 | 961 | return lo; |
131 | 961 | } _ZNK5doris14AsofIndexGroupIjE11upper_boundEj Line | Count | Source | 120 | 41 | ALWAYS_INLINE size_t upper_bound(IntType target) const { | 121 | 41 | size_t lo = 0, n = asof_values.size(); | 122 | 215 | while (n > 1) { | 123 | 174 | size_t half = n / 2; | 124 | 174 | lo += half * (asof_values[lo + half] <= target); | 125 | 174 | n -= half; | 126 | 174 | } | 127 | 41 | if (lo < asof_values.size()) { | 128 | 40 | lo += (asof_values[lo] <= target); | 129 | 40 | } | 130 | 41 | return lo; | 131 | 41 | } |
_ZNK5doris14AsofIndexGroupImE11upper_boundEm Line | Count | Source | 120 | 906 | ALWAYS_INLINE size_t upper_bound(IntType target) const { | 121 | 906 | size_t lo = 0, n = asof_values.size(); | 122 | 3.85k | while (n > 1) { | 123 | 2.94k | size_t half = n / 2; | 124 | 2.94k | lo += half * (asof_values[lo + half] <= target); | 125 | 2.94k | n -= half; | 126 | 2.94k | } | 127 | 906 | if (lo < asof_values.size()) { | 128 | 906 | lo += (asof_values[lo] <= target); | 129 | 906 | } | 130 | 906 | return lo; | 131 | 906 | } |
_ZNK5doris14AsofIndexGroupIlE11upper_boundEl Line | Count | Source | 120 | 11 | ALWAYS_INLINE size_t upper_bound(IntType target) const { | 121 | 11 | size_t lo = 0, n = asof_values.size(); | 122 | 41 | while (n > 1) { | 123 | 30 | size_t half = n / 2; | 124 | 30 | lo += half * (asof_values[lo + half] <= target); | 125 | 30 | n -= half; | 126 | 30 | } | 127 | 11 | if (lo < asof_values.size()) { | 128 | 11 | lo += (asof_values[lo] <= target); | 129 | 11 | } | 130 | 11 | return lo; | 131 | 11 | } |
_ZNK5doris14AsofIndexGroupIoE11upper_boundEo Line | Count | Source | 120 | 3 | ALWAYS_INLINE size_t upper_bound(IntType target) const { | 121 | 3 | size_t lo = 0, n = asof_values.size(); | 122 | 4 | while (n > 1) { | 123 | 1 | size_t half = n / 2; | 124 | 1 | lo += half * (asof_values[lo + half] <= target); | 125 | 1 | n -= half; | 126 | 1 | } | 127 | 3 | if (lo < asof_values.size()) { | 128 | 3 | lo += (asof_values[lo] <= target); | 129 | 3 | } | 130 | 3 | return lo; | 131 | 3 | } |
|
132 | | |
133 | | // Semantics by (is_greater, is_strict): |
134 | | // (true, false): probe >= build -> find largest build value <= probe |
135 | | // (true, true): probe > build -> find largest build value < probe |
136 | | // (false, false): probe <= build -> find smallest build value >= probe |
137 | | // (false, true): probe < build -> find smallest build value > probe |
138 | | // Returns the build row index of the best match, or 0 if no match. |
139 | | template <bool IsGreater, bool IsStrict> |
140 | 1.41k | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { |
141 | 1.41k | if (asof_values.empty()) { |
142 | 4 | return 0; |
143 | 4 | } |
144 | 1.40k | if constexpr (IsGreater) { |
145 | 959 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); |
146 | 959 | return pos > 0 ? row_indexes[pos - 1] : 0; |
147 | 959 | } else { |
148 | 450 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); |
149 | 450 | return pos < asof_values.size() ? row_indexes[pos] : 0; |
150 | 450 | } |
151 | 1.40k | } _ZNK5doris14AsofIndexGroupIjE15find_best_matchILb1ELb1EEEjj Line | Count | Source | 140 | 15 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 15 | if (asof_values.empty()) { | 142 | 1 | return 0; | 143 | 1 | } | 144 | 14 | if constexpr (IsGreater) { | 145 | 14 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 14 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 14 | } |
_ZNK5doris14AsofIndexGroupIjE15find_best_matchILb1ELb0EEEjj Line | Count | Source | 140 | 22 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 22 | if (asof_values.empty()) { | 142 | 1 | return 0; | 143 | 1 | } | 144 | 21 | if constexpr (IsGreater) { | 145 | 21 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 21 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 21 | } |
_ZNK5doris14AsofIndexGroupIjE15find_best_matchILb0ELb1EEEjj Line | Count | Source | 140 | 16 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 16 | if (asof_values.empty()) { | 142 | 1 | return 0; | 143 | 1 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 15 | } else { | 148 | 15 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 15 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 15 | } | 151 | 15 | } |
_ZNK5doris14AsofIndexGroupIjE15find_best_matchILb0ELb0EEEjj Line | Count | Source | 140 | 15 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 15 | if (asof_values.empty()) { | 142 | 1 | return 0; | 143 | 1 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 14 | } else { | 148 | 14 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 14 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 14 | } | 151 | 14 | } |
_ZNK5doris14AsofIndexGroupImE15find_best_matchILb1ELb1EEEjm Line | Count | Source | 140 | 205 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 205 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | 205 | if constexpr (IsGreater) { | 145 | 205 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 205 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 205 | } |
_ZNK5doris14AsofIndexGroupImE15find_best_matchILb1ELb0EEEjm Line | Count | Source | 140 | 704 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 704 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | 704 | if constexpr (IsGreater) { | 145 | 704 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 704 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 704 | } |
_ZNK5doris14AsofIndexGroupImE15find_best_matchILb0ELb1EEEjm Line | Count | Source | 140 | 198 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 198 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 198 | } else { | 148 | 198 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 198 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 198 | } | 151 | 198 | } |
_ZNK5doris14AsofIndexGroupImE15find_best_matchILb0ELb0EEEjm Line | Count | Source | 140 | 212 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 212 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 212 | } else { | 148 | 212 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 212 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 212 | } | 151 | 212 | } |
_ZNK5doris14AsofIndexGroupIlE15find_best_matchILb1ELb1EEEjl Line | Count | Source | 140 | 5 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 5 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | 5 | if constexpr (IsGreater) { | 145 | 5 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 5 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 5 | } |
_ZNK5doris14AsofIndexGroupIlE15find_best_matchILb1ELb0EEEjl Line | Count | Source | 140 | 6 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 6 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | 6 | if constexpr (IsGreater) { | 145 | 6 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 6 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 6 | } |
_ZNK5doris14AsofIndexGroupIlE15find_best_matchILb0ELb1EEEjl Line | Count | Source | 140 | 5 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 5 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 5 | } else { | 148 | 5 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 5 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 5 | } | 151 | 5 | } |
_ZNK5doris14AsofIndexGroupIlE15find_best_matchILb0ELb0EEEjl Line | Count | Source | 140 | 5 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 5 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 5 | } else { | 148 | 5 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 5 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 5 | } | 151 | 5 | } |
_ZNK5doris14AsofIndexGroupIoE15find_best_matchILb1ELb1EEEjo Line | Count | Source | 140 | 1 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 1 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | 1 | if constexpr (IsGreater) { | 145 | 1 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 1 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 1 | } |
_ZNK5doris14AsofIndexGroupIoE15find_best_matchILb1ELb0EEEjo Line | Count | Source | 140 | 3 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 3 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | 3 | if constexpr (IsGreater) { | 145 | 3 | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | 3 | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | | } else { | 148 | | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | | } | 151 | 3 | } |
Unexecuted instantiation: _ZNK5doris14AsofIndexGroupIoE15find_best_matchILb0ELb1EEEjo _ZNK5doris14AsofIndexGroupIoE15find_best_matchILb0ELb0EEEjo Line | Count | Source | 140 | 1 | ALWAYS_INLINE uint32_t find_best_match(IntType probe_value) const { | 141 | 1 | if (asof_values.empty()) { | 142 | 0 | return 0; | 143 | 0 | } | 144 | | if constexpr (IsGreater) { | 145 | | size_t pos = IsStrict ? lower_bound(probe_value) : upper_bound(probe_value); | 146 | | return pos > 0 ? row_indexes[pos - 1] : 0; | 147 | 1 | } else { | 148 | 1 | size_t pos = IsStrict ? upper_bound(probe_value) : lower_bound(probe_value); | 149 | 1 | return pos < asof_values.size() ? row_indexes[pos] : 0; | 150 | 1 | } | 151 | 1 | } |
|
152 | | }; |
153 | | |
154 | | using AsofMixedDateTimeKey = unsigned __int128; |
155 | | |
156 | | // Type-erased container for all ASOF index groups. |
157 | | // DateV2 -> uint32_t, DateTimeV2/TimestampTZ -> uint64_t, TimestampNs -> int64_t. |
158 | | // Mixed TimestampNs/DateTimeV2 uses a wider packed civil key with three extra |
159 | | // nanosecond digits, so neither side is narrowed to the other's physical type. |
160 | | using AsofIndexVariant = |
161 | | std::variant<std::monostate, std::vector<AsofIndexGroup<uint32_t>>, |
162 | | std::vector<AsofIndexGroup<uint64_t>>, std::vector<AsofIndexGroup<int64_t>>, |
163 | | std::vector<AsofIndexGroup<AsofMixedDateTimeKey>>>; |
164 | | |
165 | | } // namespace doris |