xref: /aosp_15_r20/external/perfetto/src/trace_processor/db/query_executor_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/db/query_executor.h"
18 
19 #include <algorithm>
20 #include <cstdint>
21 #include <memory>
22 #include <numeric>
23 #include <string>
24 #include <vector>
25 
26 #include "perfetto/ext/base/string_view.h"
27 #include "perfetto/trace_processor/basic_types.h"
28 #include "src/trace_processor/containers/bit_vector.h"
29 #include "src/trace_processor/containers/row_map.h"
30 #include "src/trace_processor/containers/string_pool.h"
31 #include "src/trace_processor/db/column/arrangement_overlay.h"
32 #include "src/trace_processor/db/column/data_layer.h"
33 #include "src/trace_processor/db/column/fake_storage.h"
34 #include "src/trace_processor/db/column/id_storage.h"
35 #include "src/trace_processor/db/column/null_overlay.h"
36 #include "src/trace_processor/db/column/numeric_storage.h"
37 #include "src/trace_processor/db/column/selector_overlay.h"
38 #include "src/trace_processor/db/column/set_id_storage.h"
39 #include "src/trace_processor/db/column/string_storage.h"
40 #include "src/trace_processor/db/column/types.h"
41 #include "test/gtest_and_gmock.h"
42 
43 namespace perfetto::trace_processor {
44 namespace {
45 
46 using testing::ElementsAre;
47 
48 using IdStorage = column::IdStorage;
49 using SetIdStorage = column::SetIdStorage;
50 using StringStorage = column::StringStorage;
51 using NullOverlay = column::NullOverlay;
52 using ArrangementOverlay = column::ArrangementOverlay;
53 using SelectorOverlay = column::SelectorOverlay;
54 
55 using Indices = column::DataLayerChain::Indices;
56 
TEST(QueryExecutor,OnlyStorageRange)57 TEST(QueryExecutor, OnlyStorageRange) {
58   std::vector<int64_t> storage_data{1, 2, 3, 4, 5};
59   column::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64,
60                                           false);
61   auto chain = storage.MakeChain();
62 
63   Constraint c{0, FilterOp::kGe, SqlValue::Long(3)};
64   RowMap rm(0, chain->size());
65   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
66 
67   ASSERT_EQ(rm.size(), 3u);
68   ASSERT_EQ(rm.Get(0), 2u);
69 }
70 
TEST(QueryExecutor,OnlyStorageRangeIsNull)71 TEST(QueryExecutor, OnlyStorageRangeIsNull) {
72   std::vector<int64_t> storage_data{1, 2, 3, 4, 5};
73   column::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64,
74                                           false);
75   auto chain = storage.MakeChain();
76 
77   Constraint c{0, FilterOp::kIsNull, SqlValue()};
78   RowMap rm(0, 5);
79   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
80 
81   ASSERT_EQ(rm.size(), 0u);
82 }
83 
TEST(QueryExecutor,OnlyStorageIndex)84 TEST(QueryExecutor, OnlyStorageIndex) {
85   // Setup storage
86   std::vector<int64_t> storage_data(10);
87   std::iota(storage_data.begin(), storage_data.end(), 0);
88   std::transform(storage_data.begin(), storage_data.end(), storage_data.begin(),
89                  [](int64_t n) { return n % 5; });
90   column::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64,
91                                           false);
92   auto chain = storage.MakeChain();
93 
94   Constraint c{0, FilterOp::kLt, SqlValue::Long(2)};
95   RowMap rm(0, 10);
96   QueryExecutor::IndexedColumnFilterForTesting(c, *chain, &rm);
97 
98   ASSERT_EQ(rm.size(), 4u);
99   ASSERT_EQ(rm.Get(0), 0u);
100   ASSERT_EQ(rm.Get(1), 1u);
101   ASSERT_EQ(rm.Get(2), 5u);
102   ASSERT_EQ(rm.Get(3), 6u);
103 }
104 
TEST(QueryExecutor,OnlyStorageIndexIsNull)105 TEST(QueryExecutor, OnlyStorageIndexIsNull) {
106   std::vector<int64_t> storage_data{1, 2, 3, 4, 5};
107   column::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64,
108                                           false);
109   auto chain = storage.MakeChain();
110 
111   Constraint c{0, FilterOp::kIsNull, SqlValue()};
112   RowMap rm(0, 5);
113   QueryExecutor::IndexedColumnFilterForTesting(c, *chain, &rm);
114 
115   ASSERT_EQ(rm.size(), 0u);
116 }
117 
TEST(QueryExecutor,NullBounds)118 TEST(QueryExecutor, NullBounds) {
119   std::vector<int64_t> storage_data(5);
120   std::iota(storage_data.begin(), storage_data.end(), 0);
121   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
122       &storage_data, ColumnType::kInt64, false);
123   BitVector bv{1, 1, 0, 1, 1, 0, 0, 0, 1, 0};
124   column::NullOverlay storage(&bv);
125   auto chain = storage.MakeChain(numeric->MakeChain());
126 
127   Constraint c{0, FilterOp::kGe, SqlValue::Long(3)};
128   RowMap rm(0, 10);
129   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
130 
131   ASSERT_EQ(rm.size(), 2u);
132   ASSERT_EQ(rm.Get(0), 4u);
133   ASSERT_EQ(rm.Get(1), 8u);
134 }
135 
TEST(QueryExecutor,NullRangeIsNull)136 TEST(QueryExecutor, NullRangeIsNull) {
137   std::vector<int64_t> storage_data(5);
138   std::iota(storage_data.begin(), storage_data.end(), 0);
139   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
140       &storage_data, ColumnType::kInt64, false);
141 
142   BitVector bv{1, 1, 0, 1, 1, 0, 0, 0, 1, 0};
143   column::NullOverlay storage(&bv);
144   auto chain = storage.MakeChain(numeric->MakeChain());
145 
146   Constraint c{0, FilterOp::kIsNull, SqlValue()};
147   RowMap rm(0, chain->size());
148   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
149 
150   ASSERT_EQ(rm.size(), 5u);
151   ASSERT_EQ(rm.Get(0), 2u);
152   ASSERT_EQ(rm.Get(1), 5u);
153   ASSERT_EQ(rm.Get(2), 6u);
154   ASSERT_EQ(rm.Get(3), 7u);
155   ASSERT_EQ(rm.Get(4), 9u);
156 }
157 
TEST(QueryExecutor,NullIndex)158 TEST(QueryExecutor, NullIndex) {
159   std::vector<int64_t> storage_data(6);
160   std::iota(storage_data.begin(), storage_data.end(), 0);
161   std::transform(storage_data.begin(), storage_data.end(), storage_data.begin(),
162                  [](int64_t n) { return n % 3; });
163   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
164       &storage_data, ColumnType::kInt64, false);
165 
166   BitVector bv{1, 1, 0, 1, 1, 0, 1, 0, 0, 1};
167   column::NullOverlay storage(&bv);
168   auto chain = storage.MakeChain(numeric->MakeChain());
169 
170   Constraint c{0, FilterOp::kGe, SqlValue::Long(1)};
171   RowMap rm(0, 10);
172   QueryExecutor::IndexedColumnFilterForTesting(c, *chain, &rm);
173 
174   ASSERT_EQ(rm.size(), 4u);
175   ASSERT_EQ(rm.Get(0), 1u);
176   ASSERT_EQ(rm.Get(1), 3u);
177   ASSERT_EQ(rm.Get(2), 6u);
178   ASSERT_EQ(rm.Get(3), 9u);
179 }
180 
TEST(QueryExecutor,NullIndexIsNull)181 TEST(QueryExecutor, NullIndexIsNull) {
182   std::vector<int64_t> storage_data(5);
183   std::iota(storage_data.begin(), storage_data.end(), 0);
184   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
185       &storage_data, ColumnType::kInt64, false);
186 
187   BitVector bv{1, 1, 0, 1, 1, 0, 0, 0, 1, 0};
188   column::NullOverlay storage(&bv);
189   auto chain = storage.MakeChain(numeric->MakeChain());
190 
191   Constraint c{0, FilterOp::kIsNull, SqlValue()};
192   RowMap rm(0, 10);
193   QueryExecutor::IndexedColumnFilterForTesting(c, *chain, &rm);
194 
195   ASSERT_EQ(rm.size(), 5u);
196   ASSERT_EQ(rm.Get(0), 2u);
197   ASSERT_EQ(rm.Get(1), 5u);
198   ASSERT_EQ(rm.Get(2), 6u);
199   ASSERT_EQ(rm.Get(3), 7u);
200   ASSERT_EQ(rm.Get(4), 9u);
201 }
202 
TEST(QueryExecutor,SelectorOverlayBounds)203 TEST(QueryExecutor, SelectorOverlayBounds) {
204   std::vector<int64_t> storage_data(5);
205   std::iota(storage_data.begin(), storage_data.end(), 0);
206   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
207       &storage_data, ColumnType::kInt64, false);
208 
209   BitVector bv{1, 1, 0, 0, 1};
210   SelectorOverlay storage(&bv);
211   auto chain = storage.MakeChain(numeric->MakeChain());
212 
213   Constraint c{0, FilterOp::kGt, SqlValue::Long(1)};
214   RowMap rm(0, 3);
215   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
216 
217   ASSERT_THAT(rm.GetAllIndices(), ElementsAre(2u));
218 }
219 
TEST(QueryExecutor,SelectorOverlayIndex)220 TEST(QueryExecutor, SelectorOverlayIndex) {
221   std::vector<int64_t> storage_data(10);
222   std::iota(storage_data.begin(), storage_data.end(), 0);
223   std::transform(storage_data.begin(), storage_data.end(), storage_data.begin(),
224                  [](int64_t n) { return n % 5; });
225   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
226       &storage_data, ColumnType::kInt64, false);
227 
228   BitVector bv{1, 1, 0, 1, 1, 0, 1, 0, 0, 1};
229   SelectorOverlay storage(&bv);
230   auto chain = storage.MakeChain(numeric->MakeChain());
231 
232   Constraint c{0, FilterOp::kGe, SqlValue::Long(2)};
233   RowMap rm(0, 6);
234   QueryExecutor::IndexedColumnFilterForTesting(c, *chain, &rm);
235 
236   ASSERT_THAT(rm.GetAllIndices(), ElementsAre(2u, 3u, 5u));
237 }
238 
TEST(QueryExecutor,ArrangementOverlayBounds)239 TEST(QueryExecutor, ArrangementOverlayBounds) {
240   std::vector<int64_t> storage_data(5);
241   std::iota(storage_data.begin(), storage_data.end(), 0);
242   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
243       &storage_data, ColumnType::kInt64, false);
244 
245   std::vector<uint32_t> arrangement{4, 1, 2, 2, 3};
246   ArrangementOverlay storage(&arrangement, Indices::State::kNonmonotonic);
247   auto chain = storage.MakeChain(numeric->MakeChain());
248 
249   Constraint c{0, FilterOp::kGe, SqlValue::Long(3)};
250   RowMap rm(0, 5);
251   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
252 
253   ASSERT_THAT(rm.GetAllIndices(), ElementsAre(0u, 4u));
254 }
255 
TEST(QueryExecutor,ArrangementOverlaySubsetInputRange)256 TEST(QueryExecutor, ArrangementOverlaySubsetInputRange) {
257   auto fake = column::FakeStorageChain::SearchSubset(5u, RowMap::Range(2u, 4u));
258 
259   std::vector<uint32_t> arrangement{4, 1, 2, 2, 3};
260   ArrangementOverlay storage(&arrangement, Indices::State::kNonmonotonic);
261   auto chain = storage.MakeChain(std::move(fake));
262 
263   Constraint c{0, FilterOp::kGe, SqlValue::Long(0u)};
264   RowMap rm(1, 3);
265   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
266 
267   ASSERT_THAT(rm.GetAllIndices(), ElementsAre(2u));
268 }
269 
TEST(QueryExecutor,ArrangementOverlaySubsetInputBitvector)270 TEST(QueryExecutor, ArrangementOverlaySubsetInputBitvector) {
271   auto fake =
272       column::FakeStorageChain::SearchSubset(5u, BitVector({0, 0, 1, 1, 0}));
273 
274   std::vector<uint32_t> arrangement{4, 1, 2, 2, 3};
275   ArrangementOverlay storage(&arrangement, Indices::State::kNonmonotonic);
276   auto chain = storage.MakeChain(std::move(fake));
277 
278   Constraint c{0, FilterOp::kGe, SqlValue::Long(0u)};
279   RowMap rm(1, 3);
280   QueryExecutor::BoundedColumnFilterForTesting(c, *chain, &rm);
281 
282   ASSERT_THAT(rm.GetAllIndices(), ElementsAre(2u));
283 }
284 
TEST(QueryExecutor,ArrangementOverlayIndex)285 TEST(QueryExecutor, ArrangementOverlayIndex) {
286   std::vector<int64_t> storage_data(5);
287   std::iota(storage_data.begin(), storage_data.end(), 0);
288   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
289       &storage_data, ColumnType::kInt64, false);
290 
291   std::vector<uint32_t> arrangement{4, 1, 2, 2, 3};
292   ArrangementOverlay storage(&arrangement, Indices::State::kNonmonotonic);
293   auto chain = storage.MakeChain(numeric->MakeChain());
294 
295   Constraint c{0, FilterOp::kGe, SqlValue::Long(3)};
296   RowMap rm(0, 5);
297   QueryExecutor::IndexedColumnFilterForTesting(c, *chain, &rm);
298 
299   ASSERT_THAT(rm.GetAllIndices(), ElementsAre(0u, 4u));
300 }
301 
TEST(QueryExecutor,MismatchedTypeNullWithOtherOperations)302 TEST(QueryExecutor, MismatchedTypeNullWithOtherOperations) {
303   std::vector<int64_t> storage_data{0, 1, 2, 3, 0, 1, 2, 3};
304   column::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64,
305                                           false);
306   auto chain = storage.MakeChain();
307 
308   // Filter.
309   Constraint c{0, FilterOp::kGe, SqlValue()};
310   QueryExecutor exec({chain.get()}, 6);
311   RowMap res = exec.Filter({c});
312 
313   ASSERT_TRUE(res.empty());
314 }
315 
TEST(QueryExecutor,SingleConstraintWithNullAndSelector)316 TEST(QueryExecutor, SingleConstraintWithNullAndSelector) {
317   std::vector<int64_t> storage_data{0, 1, 2, 3, 0, 1, 2, 3};
318   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
319       &storage_data, ColumnType::kInt64, false);
320 
321   // Current vector
322   // 0, 1, NULL, 2, 3, 0, NULL, NULL, 1, 2, 3, NULL
323   BitVector null_bv{1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0};
324   auto null = std::make_unique<column::NullOverlay>(&null_bv);
325 
326   // Final vector
327   // 0, NULL, 3, NULL, 1, 3
328   BitVector selector_bv{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
329   SelectorOverlay storage(&selector_bv);
330   auto chain = storage.MakeChain(null->MakeChain(numeric->MakeChain()));
331 
332   // Filter.
333   Constraint c{0, FilterOp::kGe, SqlValue::Long(2)};
334   QueryExecutor exec({chain.get()}, 6);
335   RowMap res = exec.Filter({c});
336 
337   ASSERT_EQ(res.size(), 2u);
338   ASSERT_EQ(res.Get(0), 2u);
339   ASSERT_EQ(res.Get(1), 5u);
340 }
341 
TEST(QueryExecutor,SingleConstraintWithNullAndArrangement)342 TEST(QueryExecutor, SingleConstraintWithNullAndArrangement) {
343   std::vector<int64_t> storage_data{0, 1, 2, 3, 0, 1, 2, 3};
344   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
345       &storage_data, ColumnType::kInt64, false);
346 
347   // Current vector
348   // 0, 1, NULL, 2, 3, 0, NULL, NULL, 1, 2, 3, NULL
349   BitVector null_bv{1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0};
350   auto null = std::make_unique<column::NullOverlay>(&null_bv);
351 
352   // Final vector
353   // NULL, 3, NULL, NULL, 3, NULL
354   std::vector<uint32_t> arrangement{2, 4, 6, 2, 4, 6};
355   ArrangementOverlay storage(&arrangement, Indices::State::kNonmonotonic);
356   auto chain = storage.MakeChain(null->MakeChain(numeric->MakeChain()));
357 
358   // Filter.
359   Constraint c{0, FilterOp::kGe, SqlValue::Long(1)};
360   QueryExecutor exec({chain.get()}, 6);
361   RowMap res = exec.Filter({c});
362 
363   ASSERT_EQ(res.size(), 2u);
364   ASSERT_EQ(res.Get(0), 1u);
365   ASSERT_EQ(res.Get(1), 4u);
366 }
367 
TEST(QueryExecutor,IsNullWithSelector)368 TEST(QueryExecutor, IsNullWithSelector) {
369   std::vector<int64_t> storage_data{0, 1, 2, 3, 0, 1, 2, 3};
370   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
371       &storage_data, ColumnType::kInt64, false);
372 
373   // Current vector
374   // 0, 1, NULL, 2, 3, 0, NULL, NULL, 1, 2, 3, NULL
375   BitVector null_bv{1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0};
376   auto null = std::make_unique<column::NullOverlay>(&null_bv);
377 
378   // Final vector
379   // 0, NULL, 3, NULL, 1, 3
380   BitVector selector_bv{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
381   SelectorOverlay storage(&selector_bv);
382   auto chain = storage.MakeChain(null->MakeChain(numeric->MakeChain()));
383 
384   // Filter.
385   Constraint c{0, FilterOp::kIsNull, SqlValue()};
386   QueryExecutor exec({chain.get()}, 6);
387   RowMap res = exec.Filter({c});
388 
389   ASSERT_EQ(res.size(), 2u);
390   ASSERT_EQ(res.Get(0), 1u);
391   ASSERT_EQ(res.Get(1), 3u);
392 }
393 
TEST(QueryExecutor,BinarySearch)394 TEST(QueryExecutor, BinarySearch) {
395   std::vector<int64_t> storage_data{0, 1, 2, 3, 4, 5, 6};
396   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
397       &storage_data, ColumnType::kInt64, true);
398 
399   // Add nulls - {0, 1, NULL, NULL, 2, 3, NULL, NULL, 4, 5, 6, NULL}
400   BitVector null_bv{1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0};
401   auto null = std::make_unique<column::NullOverlay>(&null_bv);
402 
403   // Final vector {1, NULL, 3, NULL, 5, NULL}.
404   BitVector selector_bv{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
405   SelectorOverlay storage(&selector_bv);
406 
407   auto chain = storage.MakeChain(null->MakeChain(numeric->MakeChain()));
408 
409   // Filter.
410   Constraint c{0, FilterOp::kGe, SqlValue::Long(3)};
411   QueryExecutor exec({chain.get()}, 6);
412   RowMap res = exec.Filter({c});
413 
414   ASSERT_EQ(res.size(), 2u);
415   ASSERT_EQ(res.Get(0), 2u);
416   ASSERT_EQ(res.Get(1), 4u);
417 }
418 
TEST(QueryExecutor,BinarySearchIsNull)419 TEST(QueryExecutor, BinarySearchIsNull) {
420   std::vector<int64_t> storage_data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
421   auto numeric = std::make_unique<column::NumericStorage<int64_t>>(
422       &storage_data, ColumnType::kInt64, true);
423 
424   // Select 6 elements from storage, resulting in a vector {0, 1, 3, 4, 6, 7}.
425   BitVector selector_bv{1, 1, 0, 1, 1, 0, 1, 1, 0, 0};
426   auto selector = std::make_unique<SelectorOverlay>(&selector_bv);
427 
428   // Add nulls, final vector {NULL, NULL, NULL 0, 1, 3, 4, 6, 7}.
429   BitVector null_bv{0, 0, 0, 1, 1, 1, 1, 1, 1};
430   column::NullOverlay storage(&null_bv);
431 
432   auto chain = storage.MakeChain(selector->MakeChain(numeric->MakeChain()));
433 
434   // Filter.
435   Constraint c{0, FilterOp::kIsNull, SqlValue()};
436   QueryExecutor exec({chain.get()}, 9);
437   RowMap res = exec.Filter({c});
438 
439   ASSERT_EQ(res.size(), 3u);
440   ASSERT_EQ(res.Get(0), 0u);
441   ASSERT_EQ(res.Get(1), 1u);
442   ASSERT_EQ(res.Get(2), 2u);
443 }
444 
TEST(QueryExecutor,SetIdStorage)445 TEST(QueryExecutor, SetIdStorage) {
446   std::vector<uint32_t> storage_data{0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9};
447   auto numeric = std::make_unique<column::SetIdStorage>(&storage_data);
448 
449   // Select 6 elements from storage, resulting in a vector {0, 3, 3, 6, 9, 9}.
450   BitVector selector_bv{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
451   auto selector = std::make_unique<SelectorOverlay>(&selector_bv);
452 
453   // Add nulls - vector (size 10) {NULL, 0, 3, NULL, 3, 6, NULL, 9, 9, NULL}.
454   BitVector null_bv{0, 1, 1, 0, 1, 1, 0, 1, 1, 0};
455   column::NullOverlay storage(&null_bv);
456 
457   auto chain = storage.MakeChain(selector->MakeChain(numeric->MakeChain()));
458 
459   // Filter.
460   Constraint c{0, FilterOp::kIsNull, SqlValue()};
461   QueryExecutor exec({chain.get()}, 10);
462   RowMap res = exec.Filter({c});
463 
464   ASSERT_EQ(res.size(), 4u);
465   ASSERT_EQ(res.Get(0), 0u);
466   ASSERT_EQ(res.Get(1), 3u);
467   ASSERT_EQ(res.Get(2), 6u);
468   ASSERT_EQ(res.Get(3), 9u);
469 }
470 
TEST(QueryExecutor,BinarySearchNotEq)471 TEST(QueryExecutor, BinarySearchNotEq) {
472   std::vector<int64_t> storage_data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
473   column::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64,
474                                           true);
475   auto chain = storage.MakeChain();
476 
477   // Filter.
478   Constraint c{0, FilterOp::kNe, SqlValue::Long(5)};
479   QueryExecutor exec({chain.get()}, 10);
480   RowMap res = exec.Filter({c});
481 
482   ASSERT_EQ(res.size(), 9u);
483 }
484 
TEST(QueryExecutor,IdSearchIsNull)485 TEST(QueryExecutor, IdSearchIsNull) {
486   IdStorage storage;
487   auto chain = storage.MakeChain();
488 
489   // Filter.
490   Constraint c{0, FilterOp::kIsNull, SqlValue()};
491   QueryExecutor exec({chain.get()}, 5);
492   RowMap res = exec.Filter({c});
493 
494   ASSERT_EQ(res.size(), 0u);
495 }
496 
TEST(QueryExecutor,IdSearchIsNotNull)497 TEST(QueryExecutor, IdSearchIsNotNull) {
498   IdStorage storage;
499   auto chain = storage.MakeChain();
500 
501   // Filter.
502   Constraint c{0, FilterOp::kIsNotNull, SqlValue()};
503   QueryExecutor exec({chain.get()}, 5);
504   RowMap res = exec.Filter({c});
505 
506   ASSERT_EQ(res.size(), 5u);
507 }
508 
TEST(QueryExecutor,IdSearchNotEq)509 TEST(QueryExecutor, IdSearchNotEq) {
510   IdStorage storage;
511   auto chain = storage.MakeChain();
512 
513   // Filter.
514   Constraint c{0, FilterOp::kNe, SqlValue::Long(3)};
515   QueryExecutor exec({chain.get()}, 5);
516   RowMap res = exec.Filter({c});
517 
518   ASSERT_EQ(res.size(), 4u);
519 }
520 
TEST(QueryExecutor,StringSearchIsNull)521 TEST(QueryExecutor, StringSearchIsNull) {
522   StringPool pool;
523   std::vector<std::string> strings{"cheese",  "pasta", "pizza",
524                                    "pierogi", "onion", "fries"};
525   std::vector<StringPool::Id> ids;
526   for (const auto& string : strings) {
527     ids.push_back(pool.InternString(base::StringView(string)));
528   }
529   ids.insert(ids.begin() + 3, StringPool::Id::Null());
530   auto string = std::make_unique<StringStorage>(&pool, &ids);
531 
532   // Final vec {"cheese", "pasta", "NULL", "pierogi", "fries"}.
533   BitVector selector_bv{1, 1, 0, 1, 1, 0, 1};
534   SelectorOverlay storage(&selector_bv);
535   auto chain = storage.MakeChain(string->MakeChain());
536 
537   // Filter.
538   Constraint c{0, FilterOp::kIsNull, SqlValue()};
539   QueryExecutor exec({chain.get()}, 5);
540   RowMap res = exec.Filter({c});
541 
542   ASSERT_EQ(res.size(), 1u);
543   ASSERT_EQ(res.Get(0), 2u);
544 }
545 
TEST(QueryExecutor,StringSearchGtSorted)546 TEST(QueryExecutor, StringSearchGtSorted) {
547   StringPool pool;
548   std::vector<std::string> strings{"apple",    "burger",   "cheese",
549                                    "doughnut", "eggplant", "fries"};
550   std::vector<StringPool::Id> ids;
551   for (const auto& string : strings) {
552     ids.push_back(pool.InternString(base::StringView(string)));
553   }
554   auto string = std::make_unique<StringStorage>(&pool, &ids, true);
555 
556   // Final vec {"apple", "burger", "doughnut", "eggplant"}.
557   BitVector selector_bv{1, 1, 0, 1, 1, 0};
558   SelectorOverlay storage(&selector_bv);
559   auto chain = storage.MakeChain(string->MakeChain());
560 
561   // Filter.
562   Constraint c{0, FilterOp::kGe, SqlValue::String("camembert")};
563   QueryExecutor exec({chain.get()}, 4);
564   RowMap res = exec.Filter({c});
565 
566   ASSERT_EQ(res.size(), 2u);
567   ASSERT_EQ(res.Get(0), 2u);
568 }
569 
TEST(QueryExecutor,StringSearchNeSorted)570 TEST(QueryExecutor, StringSearchNeSorted) {
571   StringPool pool;
572   std::vector<std::string> strings{"apple",    "burger",   "cheese",
573                                    "doughnut", "eggplant", "fries"};
574   std::vector<StringPool::Id> ids;
575   for (const auto& string : strings) {
576     ids.push_back(pool.InternString(base::StringView(string)));
577   }
578   auto string = std::make_unique<StringStorage>(&pool, &ids, true);
579 
580   // Final vec {"apple", "burger", "doughnut", "eggplant"}.
581   BitVector selector_bv{1, 1, 0, 1, 1, 0};
582   SelectorOverlay storage(&selector_bv);
583   auto chain = storage.MakeChain(string->MakeChain());
584 
585   // Filter.
586   Constraint c{0, FilterOp::kNe, SqlValue::String("doughnut")};
587   QueryExecutor exec({chain.get()}, 4);
588   RowMap res = exec.Filter({c});
589 
590   ASSERT_EQ(res.size(), 3u);
591   ASSERT_EQ(res.Get(0), 0u);
592 }
593 
TEST(QueryExecutor,MismatchedTypeIdWithString)594 TEST(QueryExecutor, MismatchedTypeIdWithString) {
595   IdStorage storage;
596   auto chain = storage.MakeChain();
597 
598   // Filter.
599   Constraint c{0, FilterOp::kGe, SqlValue::String("cheese")};
600   QueryExecutor exec({chain.get()}, 5);
601   RowMap res = exec.Filter({c});
602 
603   ASSERT_EQ(res.size(), 0u);
604 }
605 
TEST(QueryExecutor,MismatchedTypeIdWithDouble)606 TEST(QueryExecutor, MismatchedTypeIdWithDouble) {
607   IdStorage storage;
608   auto chain = storage.MakeChain();
609 
610   // Filter.
611   Constraint c{0, FilterOp::kGe, SqlValue::Double(1.5)};
612   QueryExecutor exec({chain.get()}, 5);
613   RowMap res = exec.Filter({c});
614 
615   ASSERT_EQ(res.size(), 3u);
616 }
617 
TEST(QueryExecutor,MismatchedTypeSetIdWithDouble)618 TEST(QueryExecutor, MismatchedTypeSetIdWithDouble) {
619   std::vector<uint32_t> storage_data{0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9};
620   SetIdStorage storage(&storage_data);
621   auto chain = storage.MakeChain();
622 
623   // Filter.
624   Constraint c{0, FilterOp::kGe, SqlValue::Double(1.5)};
625   QueryExecutor exec({chain.get()}, chain->size());
626   RowMap res = exec.Filter({c});
627 
628   ASSERT_EQ(res.size(), 9u);
629 }
630 
631 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
TEST(QueryExecutor,StringBinarySearchRegex)632 TEST(QueryExecutor, StringBinarySearchRegex) {
633   StringPool pool;
634   std::vector<std::string> strings{"cheese",  "pasta", "pizza",
635                                    "pierogi", "onion", "fries"};
636   std::vector<StringPool::Id> ids;
637   for (const auto& string : strings) {
638     ids.push_back(pool.InternString(base::StringView(string)));
639   }
640   ids.insert(ids.begin() + 3, StringPool::Id::Null());
641   auto string = std::make_unique<StringStorage>(&pool, &ids);
642 
643   // Final vec {"cheese", "pasta", "NULL", "pierogi", "fries"}.
644   BitVector selector_bv{1, 1, 0, 1, 1, 0, 1};
645   SelectorOverlay storage(&selector_bv);
646   auto chain = storage.MakeChain(string->MakeChain());
647 
648   // Filter.
649   Constraint c{0, FilterOp::kRegex, SqlValue::String("p.*")};
650   QueryExecutor exec({chain.get()}, 5);
651   RowMap res = exec.Filter({c});
652 
653   ASSERT_EQ(res.size(), 2u);
654   ASSERT_EQ(res.Get(0), 1u);
655   ASSERT_EQ(res.Get(1), 3u);
656 }
657 
TEST(QueryExecutor,StringBinarySearchRegexWithNum)658 TEST(QueryExecutor, StringBinarySearchRegexWithNum) {
659   StringPool pool;
660   std::vector<std::string> strings{"cheese",  "pasta", "pizza",
661                                    "pierogi", "onion", "fries"};
662   std::vector<StringPool::Id> ids;
663   for (const auto& string : strings) {
664     ids.push_back(pool.InternString(base::StringView(string)));
665   }
666   ids.insert(ids.begin() + 3, StringPool::Id::Null());
667   auto string = std::make_unique<StringStorage>(&pool, &ids);
668 
669   // Final vec {"cheese", "pasta", "NULL", "pierogi", "fries"}.
670   BitVector selector_bv{1, 1, 0, 1, 1, 0, 1};
671   SelectorOverlay storage(&selector_bv);
672   auto chain = storage.MakeChain(string->MakeChain());
673 
674   // Filter.
675   Constraint c{0, FilterOp::kRegex, SqlValue::Long(4)};
676   QueryExecutor exec({chain.get()}, 5);
677   RowMap res = exec.Filter({c});
678 
679   ASSERT_EQ(res.size(), 0u);
680 }
681 #endif
682 
683 }  // namespace
684 }  // namespace perfetto::trace_processor
685