Project
Loading...
Searching...
No Matches
test_ASoA.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <cstdio>
13#include "Framework/ASoA.h"
18#include "gandiva/tree_expr_builder.h"
19#include "arrow/status.h"
20#include "gandiva/filter.h"
21#include <catch_amalgamated.hpp>
22#include <arrow/util/key_value_metadata.h>
23
24using namespace o2::framework;
25using namespace arrow;
26using namespace o2::soa;
27
28namespace o2::aod
29{
30namespace test
31{
36DECLARE_SOA_DYNAMIC_COLUMN(Sum, sum, [](int x, int y) { return x + y; });
37DECLARE_SOA_EXPRESSION_COLUMN(ESum, esum, int, test::x + test::y);
38} // namespace test
39
40DECLARE_SOA_TABLE(Points, "TEST", "POINTS", test::X, test::Y);
41DECLARE_SOA_TABLE(Points3Ds, "TEST", "PTS3D", o2::soa::Index<>, test::X, test::Y, test::Z);
42
43DECLARE_SOA_TABLE_VERSIONED(Points3DMk1s, "TEST", "PTS3D", 1, o2::soa::Index<>, o2::soa::Marker<1>, test::X, test::Y, test::Z);
44DECLARE_SOA_TABLE_VERSIONED(Points3DMk2s, "TEST", "PTS3D", 2, o2::soa::Index<>, o2::soa::Marker<2>, test::X, test::Y, test::Z);
45DECLARE_SOA_TABLE_VERSIONED(Points3DMk3s, "TEST", "PTS3D", 3, o2::soa::Index<>, o2::soa::Marker<3>, test::X, test::Y, test::Z);
46
47namespace test
48{
49DECLARE_SOA_COLUMN_FULL(SomeBool, someBool, bool, "someBool");
50DECLARE_SOA_COLUMN_FULL(Color, color, int32_t, "color");
51} // namespace test
52
53DECLARE_SOA_TABLE(Infos, "TEST", "INFOS", test::Color, test::SomeBool);
54
55namespace test
56{
59DECLARE_SOA_INDEX_COLUMN_FULL(PointA, pointA, int, Points, "_A");
60DECLARE_SOA_INDEX_COLUMN_FULL(PointB, pointB, int, Points, "_B");
61DECLARE_SOA_COLUMN_FULL(Thickness, thickness, int, "thickness");
62} // namespace test
63
64DECLARE_SOA_TABLE(Segments, "TEST", "SEGMENTS", test::N, test::PointAId, test::PointBId, test::InfoId);
65DECLARE_SOA_TABLE(SegmentsExtras, "TEST", "SEGMENTSPLUS", test::Thickness);
66
67namespace test
68{
69DECLARE_SOA_COLUMN(L1, l1, std::vector<float>);
70DECLARE_SOA_COLUMN(L2, l2, std::vector<int>);
71} // namespace test
72
73DECLARE_SOA_TABLE(Lists, "TEST", "LISTS", o2::soa::Index<>, test::L1, test::L2);
74} // namespace o2::aod
75
76TEST_CASE("TestMarkers")
77{
78 TableBuilder b1;
79 auto pwriter = b1.cursor<o2::aod::Points3Ds>();
80 for (auto i = 0; i < 20; ++i) {
81 pwriter(0, -1 * i, (int)(i / 2), 2 * i);
82 }
83 auto t1 = b1.finalize();
84
85 auto pt = o2::aod::Points3Ds{t1};
86 auto pt1 = o2::aod::Points3DMk1s{t1};
87 auto pt2 = o2::aod::Points3DMk2s{t1};
88 auto pt3 = o2::aod::Points3DMk3s{t1};
89 REQUIRE(pt1.begin().mark() == (size_t)1);
90 REQUIRE(pt2.begin().mark() == (size_t)2);
91 REQUIRE(pt3.begin().mark() == (size_t)3);
92}
93
94TEST_CASE("TestTableIteration")
95{
96 TableBuilder builder;
97 auto rowWriter = builder.persist<int32_t, int32_t>({"fX", "fY"});
98 rowWriter(0, 0, 0);
99 rowWriter(0, 0, 1);
100 rowWriter(0, 0, 2);
101 rowWriter(0, 0, 3);
102 rowWriter(0, 1, 4);
103 rowWriter(0, 1, 5);
104 rowWriter(0, 1, 6);
105 rowWriter(0, 1, 7);
106 auto table = builder.finalize();
107
108 auto i = ColumnIterator<int32_t>(table->column(0).get());
109 int64_t pos = 0;
110 uint64_t offset = 0;
111 i.mCurrentPos = &pos;
112 i.mGlobalOffset = &offset;
113 REQUIRE(*i == 0);
114 pos++;
115 REQUIRE(*i == 0);
116 pos++;
117 REQUIRE(*i == 0);
118 pos++;
119 REQUIRE(*i == 0);
120 pos++;
121 REQUIRE(*i == 1);
122 pos++;
123 REQUIRE(*i == 1);
124 pos++;
125 REQUIRE(*i == 1);
126 pos++;
127 REQUIRE(*i == 1);
128
129 arrow::ChunkedArray* chunks[2] = {
130 table->column(0).get(),
131 table->column(1).get()};
132 o2::aod::Points::iterator tests(chunks, {table->num_rows(), 0});
133 REQUIRE(tests.x() == 0);
134 REQUIRE(tests.y() == 0);
135 ++tests;
136 REQUIRE(tests.x() == 0);
137 REQUIRE(tests.y() == 1);
138 using Test = InPlaceTable<"T/0"_h, o2::aod::test::X, o2::aod::test::Y>;
139 Test tests2{table};
140 size_t value = 0;
141 auto b = tests2.begin();
142 auto e = tests2.end();
143 REQUIRE(b != e);
144 ++b;
145 ++b;
146 ++b;
147 ++b;
148 ++b;
149 ++b;
150 ++b;
151 ++b;
152 REQUIRE(b == e);
153
154 b = tests2.begin();
155 REQUIRE(b != e);
156 REQUIRE(((b + 1) == (b + 1)));
157 REQUIRE(((b + 7) != b));
158 REQUIRE(((b + 7) != e));
159 REQUIRE(((b + 8) == e));
160
161 for (auto& t : tests2) {
162 REQUIRE(t.x() == value / 4);
163 REQUIRE((size_t)t.y() == value);
164 REQUIRE(value < 8);
165 value++;
166 }
167
168 for (auto t1 = tests2.begin(); t1 != tests2.end(); ++t1) {
169 for (auto t2 = t1 + 1; t2 != tests2.end(); ++t2) {
170 }
171 }
172}
173
174TEST_CASE("TestDynamicColumns")
175{
176 TableBuilder builder;
177 auto rowWriter = builder.persist<int32_t, int32_t>({"fX", "fY"});
178 rowWriter(0, 0, 0);
179 rowWriter(0, 0, 1);
180 rowWriter(0, 0, 2);
181 rowWriter(0, 0, 3);
182 rowWriter(0, 1, 4);
183 rowWriter(0, 1, 5);
184 rowWriter(0, 1, 6);
185 rowWriter(0, 1, 7);
186 auto table = builder.finalize();
187
188 using Test1 = InPlaceTable<"A"_h, o2::aod::test::X, o2::aod::test::Y, o2::aod::test::Sum<o2::aod::test::X, o2::aod::test::Y>>;
189
190 Test1 tests1{table};
191 for (auto& test : tests1) {
192 REQUIRE(test.sum() == (test.x() + test.y()));
193 }
194
195 using Test2 = InPlaceTable<"B"_h, o2::aod::test::X, o2::aod::test::Y, o2::aod::test::Sum<o2::aod::test::Y, o2::aod::test::Y>>;
196
197 Test2 tests2{table};
198 for (auto& test : tests2) {
199 CHECK(test.sum() == (test.y() + test.y()));
200 }
201}
202
203TEST_CASE("TestColumnIterators")
204{
205 TableBuilder builder;
206 auto rowWriter = builder.persist<int32_t, int32_t>({"fX", "fY"});
207 rowWriter(0, 0, 0);
208 rowWriter(0, 0, 1);
209 rowWriter(0, 0, 2);
210 rowWriter(0, 0, 3);
211 rowWriter(0, 1, 4);
212 rowWriter(0, 1, 5);
213 rowWriter(0, 1, 6);
214 rowWriter(0, 1, 7);
215 auto table = builder.finalize();
216
217 int64_t index1 = 0;
218 int64_t index2 = 0;
219 ColumnIterator<int32_t> foo{table->column(1).get()};
220 foo.mCurrentPos = &index1;
221 auto bar{foo};
222 bar.mCurrentPos = &index2;
223 REQUIRE(foo.mCurrent == bar.mCurrent);
224 REQUIRE(foo.mLast == bar.mLast);
225 REQUIRE(foo.mColumn == bar.mColumn);
226 REQUIRE(foo.mFirstIndex == bar.mFirstIndex);
227 REQUIRE(foo.mCurrentChunk == bar.mCurrentChunk);
228
229 auto foobar = std::move(foo);
230 REQUIRE(foobar.mCurrent == bar.mCurrent);
231 REQUIRE(foobar.mLast == bar.mLast);
232 REQUIRE(foobar.mColumn == bar.mColumn);
233 REQUIRE(foobar.mFirstIndex == bar.mFirstIndex);
234 REQUIRE(foobar.mCurrentChunk == bar.mCurrentChunk);
235}
236
237TEST_CASE("TestJoinedTables")
238{
239 TableBuilder builderX;
240 auto rowWriterX = builderX.persist<int32_t>({"fX"});
241 rowWriterX(0, 0);
242 rowWriterX(0, 1);
243 rowWriterX(0, 2);
244 rowWriterX(0, 3);
245 rowWriterX(0, 4);
246 rowWriterX(0, 5);
247 rowWriterX(0, 6);
248 rowWriterX(0, 7);
249 auto tableX = builderX.finalize();
250
251 TableBuilder builderY;
252 auto rowWriterY = builderY.persist<int32_t>({"fY"});
253 rowWriterY(0, 7);
254 rowWriterY(0, 6);
255 rowWriterY(0, 5);
256 rowWriterY(0, 4);
257 rowWriterY(0, 3);
258 rowWriterY(0, 2);
259 rowWriterY(0, 1);
260 rowWriterY(0, 0);
261 auto tableY = builderY.finalize();
262
263 TableBuilder builderZ;
264 auto rowWriterZ = builderZ.persist<int32_t>({"fZ"});
265 rowWriterZ(0, 8);
266 rowWriterZ(0, 8);
267 rowWriterZ(0, 8);
268 rowWriterZ(0, 8);
269 rowWriterZ(0, 8);
270 rowWriterZ(0, 8);
271 rowWriterZ(0, 8);
272 rowWriterZ(0, 8);
273 auto tableZ = builderZ.finalize();
274
275 TableBuilder builderW;
276 auto rowWriterW = builderW.persist<int32_t>({"fW"});
277 rowWriterW(0, 8);
278 rowWriterW(0, 8);
279 rowWriterW(0, 8);
280 auto tableW = builderW.finalize();
281
282 using TestX = InPlaceTable<"A0"_h, o2::aod::test::X>;
283 using TestY = InPlaceTable<"A1"_h, o2::aod::test::Y>;
284 using TestZ = InPlaceTable<"A2"_h, o2::aod::test::Z>;
285 using TestW = InPlaceTable<"A3"_h, o2::aod::test::W>;
286 using Test = Join<TestX, TestY>;
287
288 REQUIRE(Test::contains<TestX>());
289 REQUIRE(Test::contains<TestY>());
290 REQUIRE(!Test::contains<TestZ>());
291
292 Test tests{{tableX, tableY}};
293
294 REQUIRE(tests.contains<TestX>());
295 REQUIRE(tests.contains<TestY>());
296 REQUIRE(!tests.contains<TestZ>());
297
298 for (auto& test : tests) {
299 REQUIRE(7 == test.x() + test.y());
300 }
301
302 auto tests2 = join(TestX{tableX}, TestY{tableY});
303 static_assert(std::same_as<Test::self_t, decltype(tests2)>, "Joined tables should have the same type, regardless how we construct them");
304 for (auto& test : tests2) {
305 REQUIRE(7 == test.x() + test.y());
306 }
307
308 auto tests3 = join(TestX{tableX}, TestY{tableY}, TestZ{tableZ});
309
310 for (auto& test : tests3) {
311 REQUIRE(15 == test.x() + test.y() + test.z());
312 }
313 using TestMoreThanTwo = Join<TestX, TestY, TestZ>;
314 TestMoreThanTwo tests4{{tableX, tableY, tableZ}};
315 for (auto& test : tests4) {
316 REQUIRE(15 == test.x() + test.y() + test.z());
317 }
318
319 // a table of different size must be detected in any position of the join
320 auto joinError = [](auto&& makeJoin) -> std::string {
321 try {
322 makeJoin();
323 } catch (RuntimeErrorRef ref) {
324 return error_from_ref(ref).what;
325 }
326 return "";
327 };
328 REQUIRE(joinError([&] { join(TestZ{tableZ}, TestW{tableW}); }) == "Tables TEST and TEST have different sizes (8 vs 3) and cannot be joined!");
329 REQUIRE(joinError([&] { join(TestW{tableW}, TestY{tableY}, TestZ{tableZ}); }) == "Tables TEST and TEST have different sizes (3 vs 8) and cannot be joined!");
330 REQUIRE(joinError([&] { join(TestX{tableX}, TestW{tableW}, TestZ{tableZ}); }) == "Tables TEST and TEST have different sizes (8 vs 3) and cannot be joined!");
331 REQUIRE(joinError([&] { join(TestX{tableX}, TestY{tableY}, TestW{tableW}); }) == "Tables TEST and TEST have different sizes (8 vs 3) and cannot be joined!");
332 REQUIRE(joinError([&] { Join<TestX, TestY, TestW>{{tableX, tableY, tableW}}; }) == "Tables at positions 1 and 2 have different sizes (8 vs 3) and cannot be joined!");
333}
334
335TEST_CASE("TestConcatTables")
336{
337 TableBuilder builderA;
338 auto rowWriterA = builderA.persist<int32_t, int32_t>({"fX", "fY"});
339 rowWriterA(0, 0, 0);
340 rowWriterA(0, 1, 0);
341 rowWriterA(0, 2, 0);
342 rowWriterA(0, 3, 0);
343 rowWriterA(0, 4, 0);
344 rowWriterA(0, 5, 0);
345 rowWriterA(0, 6, 0);
346 rowWriterA(0, 7, 0);
347 auto tableA = builderA.finalize();
348 REQUIRE(tableA->num_rows() == 8);
349
350 TableBuilder builderB;
351 auto rowWriterB = builderB.persist<int32_t>({"fX"});
352 rowWriterB(0, 8);
353 rowWriterB(0, 9);
354 rowWriterB(0, 10);
355 rowWriterB(0, 11);
356 rowWriterB(0, 12);
357 rowWriterB(0, 13);
358 rowWriterB(0, 14);
359 rowWriterB(0, 15);
360 auto tableB = builderB.finalize();
361
362 TableBuilder builderC;
363 auto rowWriterC = builderC.persist<int32_t>({"fZ"});
364 rowWriterC(0, 8);
365 rowWriterC(0, 9);
366 rowWriterC(0, 10);
367 rowWriterC(0, 11);
368 rowWriterC(0, 12);
369 rowWriterC(0, 13);
370 rowWriterC(0, 14);
371 rowWriterC(0, 15);
372 auto tableC = builderC.finalize();
373
374 TableBuilder builderD;
375 auto rowWriterD = builderD.persist<int32_t, int32_t>({"fX", "fZ"});
376 rowWriterD(0, 16, 8);
377 rowWriterD(0, 17, 9);
378 rowWriterD(0, 18, 10);
379 rowWriterD(0, 19, 11);
380 rowWriterD(0, 20, 12);
381 rowWriterD(0, 21, 13);
382 rowWriterD(0, 22, 14);
383 rowWriterD(0, 23, 15);
384 auto tableD = builderD.finalize();
385
386 using TestA = InPlaceTable<0, o2::soa::Index<>, o2::aod::test::X, o2::aod::test::Y>; // o2::aod::TestA;
387 using TestB = InPlaceTable<0, o2::soa::Index<>, o2::aod::test::X>; // o2::aod::TestB;
388 using TestC = InPlaceTable<0, o2::aod::test::Z>; // o2::aod::TestC;
389 using TestD = InPlaceTable<0, o2::aod::test::X, o2::aod::test::Z>; // o2::aod::TestD;
390 using ConcatTest = Concat<TestA, TestB>;
391 using JoinedTest = Join<TestA, TestC>;
392 using NestedJoinTest = Join<JoinedTest, TestD>;
393 using NestedConcatTest = Concat<Join<TestA, TestB>, TestD>;
394
395 static_assert(std::same_as<NestedJoinTest::columns_t, o2::framework::pack<o2::soa::Index<>, o2::aod::test::Y, o2::aod::test::X, o2::aod::test::Z>>, "Bad nested join");
396
397 static_assert(std::same_as<ConcatTest::columns_t, o2::framework::pack<o2::soa::Index<>, o2::aod::test::X>>, "Bad intersection of columns");
398 ConcatTest tests{{tableA, tableB}};
399 REQUIRE(16 == tests.size());
400 for (auto& test : tests) {
401 REQUIRE(test.index() == test.x());
402 }
403
404 static_assert(std::same_as<NestedConcatTest::columns_t, o2::framework::pack<o2::aod::test::X>>, "Bad nested concat");
405
406 // Hardcode a selection for the first 5 odd numbers
407 using FilteredTest = Filtered<TestA>;
408 using namespace o2::framework;
409 expressions::Filter testf = (o2::aod::test::x == 1) || (o2::aod::test::x == 3);
410 gandiva::Selection selection;
411 auto status = gandiva::SelectionVector::MakeInt64(tests.size(), arrow::default_memory_pool(), &selection);
412 REQUIRE(status.ok());
413
414 auto fptr = tableA->schema()->GetFieldByName("fX");
415 REQUIRE(fptr != nullptr);
416 REQUIRE(fptr->name() == "fX");
417 REQUIRE(fptr->type()->id() == arrow::Type::INT32);
418
419 auto node_x = gandiva::TreeExprBuilder::MakeField(fptr);
420 auto literal_1 = gandiva::TreeExprBuilder::MakeLiteral(static_cast<int32_t>(1));
421 auto literal_3 = gandiva::TreeExprBuilder::MakeLiteral(static_cast<int32_t>(3));
422 auto equals_to_1 = gandiva::TreeExprBuilder::MakeFunction("equal", {node_x, literal_1}, arrow::boolean());
423 auto equals_to_3 = gandiva::TreeExprBuilder::MakeFunction("equal", {node_x, literal_3}, arrow::boolean());
424 auto node_or = gandiva::TreeExprBuilder::MakeOr({equals_to_1, equals_to_3});
425 auto condition = gandiva::TreeExprBuilder::MakeCondition(node_or);
426 REQUIRE(condition->ToString() == "bool equal((int32) fX, (const int32) 1) || bool equal((int32) fX, (const int32) 3)");
427 std::shared_ptr<gandiva::Filter> filter;
428 status = gandiva::Filter::Make(tableA->schema(), condition, &filter);
429 REQUIRE(status.ToString() == "OK");
430
431 arrow::TableBatchReader reader(*tableA);
432 std::shared_ptr<RecordBatch> batch;
433 auto s = reader.ReadNext(&batch);
434 REQUIRE(s.ok());
435 REQUIRE(batch != nullptr);
436 REQUIRE(batch->num_rows() == 8);
437 auto st = filter->Evaluate(*batch, selection);
438 REQUIRE(st.ToString() == "OK");
439
440 gandiva::Selection selection_f = expressions::createSelection(tableA, testf);
441
442 TestA testA{tableA};
443 FilteredTest filtered{{testA.asArrowTableRef()}, selection_f};
444 REQUIRE(2 == filtered.size());
445
446 auto i = 0;
447 REQUIRE(filtered.begin() != filtered.end());
448 for (auto& f : filtered) {
449 REQUIRE(i * 2 + 1 == f.x());
450 REQUIRE(i * 2 + 1 == f.index());
451 i++;
452 }
453 REQUIRE(i == 2);
454
455 // Hardcode a selection for the first 5 odd numbers
456 using FilteredConcatTest = Filtered<ConcatTest::table_t>;
457 using namespace o2::framework;
458 gandiva::Selection selectionConcat;
459 status = gandiva::SelectionVector::MakeInt64(tests.size(), arrow::default_memory_pool(), &selectionConcat);
460 REQUIRE(status.ok() == true);
461 selectionConcat->SetIndex(0, 0);
462 selectionConcat->SetIndex(1, 5);
463 selectionConcat->SetIndex(2, 10);
464 selectionConcat->SetNumSlots(3);
465 ConcatTest concatTest{tableA, tableB};
466 FilteredConcatTest concatTestTable{{concatTest.asArrowTableRef()}, selectionConcat};
467 REQUIRE(3 == concatTestTable.size());
468
469 i = 0;
470 auto b = concatTestTable.begin();
471 auto e = concatTestTable.end();
472
473 REQUIRE(b.mRowIndex == 0);
474 REQUIRE(b.getSelectionRow() == 0);
475 REQUIRE(e.index == 3);
476
477 REQUIRE(concatTestTable.begin() != concatTestTable.end());
478 for (auto& f : concatTestTable) {
479 REQUIRE(i * 5 == f.x());
480 REQUIRE(i * 5 == f.index());
481 REQUIRE(i == f.filteredIndex());
482 i++;
483 }
484 REQUIRE(i == 3);
485
486 // Test with a Joined table
487 using FilteredJoinTest = Filtered<JoinedTest::table_t>;
488 gandiva::Selection selectionJoin;
489 status = gandiva::SelectionVector::MakeInt64(tests.size(), arrow::default_memory_pool(), &selectionJoin);
490 REQUIRE(status.ok() == true);
491 selectionJoin->SetIndex(0, 0);
492 selectionJoin->SetIndex(1, 2);
493 selectionJoin->SetIndex(2, 4);
494 selectionJoin->SetNumSlots(3);
495 JoinedTest testJoin{{tableA, tableC}};
496 FilteredJoinTest filteredJoin{{testJoin.asArrowTableRef()}, selectionJoin};
497
498 i = 0;
499 REQUIRE(filteredJoin.begin() != filteredJoin.end());
500 for (auto& f : filteredJoin) {
501 REQUIRE(i * 2 == f.x());
502 REQUIRE(i * 2 == f.index());
503 i++;
504 }
505 REQUIRE(i == 3);
506}
507
508TEST_CASE("TestDereference")
509{
510 TableBuilder builderA;
511 auto pointsWriter = builderA.cursor<o2::aod::Points>();
512 pointsWriter(0, 0, 0);
513 pointsWriter(0, 3, 4);
514 auto pointsT = builderA.finalize();
515 o2::aod::Points points{pointsT};
516 REQUIRE(pointsT->num_rows() == 2);
517
518 TableBuilder builderA2;
519 auto infoWriter = builderA2.cursor<o2::aod::Infos>();
520 infoWriter(0, 0, true);
521 infoWriter(0, 1, false);
522 infoWriter(0, 4, true);
523 auto infosT = builderA2.finalize();
524 o2::aod::Infos infos{infosT};
525 REQUIRE(infos.begin().someBool() == true);
526 REQUIRE((infos.begin() + 1).someBool() == false);
527 REQUIRE((infos.begin() + 2).someBool() == true);
528 REQUIRE((infos.begin() + 2).color() == 4);
529 REQUIRE(infosT->num_rows() == 3);
530
531 TableBuilder builderB;
532 auto segmentsWriter = builderB.cursor<o2::aod::Segments>();
533 segmentsWriter(0, 10, 0, 1, 2);
534 auto segmentsT = builderB.finalize();
535 o2::aod::Segments segments{segmentsT};
536 REQUIRE(segmentsT->num_rows() == 1);
537
538 TableBuilder builderC;
539 auto segmentsExtraWriter = builderC.cursor<o2::aod::SegmentsExtras>();
540 segmentsExtraWriter(0, 1);
541 auto segmentsExtraT = builderC.finalize();
542 o2::aod::SegmentsExtras segmentsExtras{segmentsExtraT};
543 REQUIRE(segmentsExtraT->num_rows() == 1);
544
545 REQUIRE(segments.begin().pointAId() == 0);
546 REQUIRE(segments.begin().pointBId() == 1);
547 static_assert(std::same_as<decltype(segments.begin().pointA()), o2::aod::Points::iterator>);
548 auto i = segments.begin();
549 using namespace o2::framework;
550 i.bindExternalIndices(&points, &infos);
551 REQUIRE(i.n() == 10);
552 REQUIRE(i.info().color() == 4);
553 REQUIRE(i.info().someBool() == true);
554 REQUIRE(i.pointA().x() == 0);
555 REQUIRE(i.pointA().y() == 0);
556 REQUIRE(i.pointB().x() == 3);
557 REQUIRE(i.pointB().y() == 4);
558
559 segments.bindExternalIndices(&points, &infos);
560 auto j = segments.begin();
561 REQUIRE(j.n() == 10);
562 REQUIRE(j.info().color() == 4);
563 REQUIRE(j.info().someBool() == true);
564 REQUIRE(j.pointA().x() == 0);
565 REQUIRE(j.pointA().y() == 0);
566 REQUIRE(j.pointB().x() == 3);
567 REQUIRE(j.pointB().y() == 4);
568
569 auto joined = join(segments, segmentsExtras);
570 joined.bindExternalIndices(&points, &infos);
571 auto se = joined.begin();
572 REQUIRE(se.n() == 10);
573 REQUIRE(se.info().color() == 4);
574 REQUIRE(se.pointA().x() == 0);
575 REQUIRE(se.pointA().y() == 0);
576 REQUIRE(se.pointB().x() == 3);
577 REQUIRE(se.pointB().y() == 4);
578 REQUIRE(se.thickness() == 1);
579}
580
581TEST_CASE("TestSchemaCreation")
582{
583 auto schema = std::make_shared<arrow::Schema>(createFieldsFromColumns(o2::aod::Points::persistent_columns_t{}));
584 REQUIRE(schema->num_fields() == 2);
585 REQUIRE(schema->field(0)->name() == "fX");
586 REQUIRE(schema->field(1)->name() == "fY");
587}
588
589TEST_CASE("TestFilteredOperators")
590{
591 TableBuilder builderA;
592 auto rowWriterA = builderA.persist<int32_t, int32_t>({"fX", "fY"});
593 rowWriterA(0, 0, 8);
594 rowWriterA(0, 1, 9);
595 rowWriterA(0, 2, 10);
596 rowWriterA(0, 3, 11);
597 rowWriterA(0, 4, 12);
598 rowWriterA(0, 5, 13);
599 rowWriterA(0, 6, 14);
600 rowWriterA(0, 7, 15);
601 auto tableA = builderA.finalize();
602 REQUIRE(tableA->num_rows() == 8);
603
604 using TestA = InPlaceTable<0, o2::soa::Index<>, o2::aod::test::X, o2::aod::test::Y>; // o2::soa::Table<OriginEnc{"AOD"}, o2::soa::Index<>, o2::aod::test::X, o2::aod::test::Y>;
605 using FilteredTest = Filtered<TestA>;
606 using namespace o2::framework;
607
608 expressions::Filter f1 = o2::aod::test::x < 4;
609 expressions::Filter f2 = o2::aod::test::y > 13;
610
611 TestA testA{tableA};
612 auto s1 = expressions::createSelection(testA.asArrowTable(), f1);
613 FilteredTest filtered1{{testA.asArrowTableRef()}, s1};
614 REQUIRE(4 == filtered1.size());
615 REQUIRE(filtered1.begin() != filtered1.end());
616
617 auto s2 = expressions::createSelection(testA.asArrowTable(), f2);
618 FilteredTest filtered2{{testA.asArrowTableRef()}, s2};
619 REQUIRE(2 == filtered2.size());
620 REQUIRE(filtered2.begin() != filtered2.end());
621
622 FilteredTest filteredUnion = filtered1 + filtered2;
623 REQUIRE(6 == filteredUnion.size());
624
625 std::vector<std::tuple<int32_t, int32_t>> expectedUnion{{0, 8}, {1, 9}, {2, 10}, {3, 11}, {6, 14}, {7, 15}};
626 auto i = 0;
627 for (auto& f : filteredUnion) {
628 REQUIRE(std::get<0>(expectedUnion[i]) == f.x());
629 REQUIRE(std::get<1>(expectedUnion[i]) == f.y());
630 REQUIRE(std::get<0>(expectedUnion[i]) == f.index());
631 i++;
632 }
633 REQUIRE(i == 6);
634
635 FilteredTest filteredIntersection = filtered1 * filtered2;
636 REQUIRE(0 == filteredIntersection.size());
637
638 REQUIRE(filteredIntersection.size() == 0);
639
640 expressions::Filter f3 = o2::aod::test::x < 3;
641 auto s3 = expressions::createSelection(testA.asArrowTable(), f3);
642 FilteredTest filtered3{{testA.asArrowTableRef()}, s3};
643 REQUIRE(3 == filtered3.size());
644 REQUIRE(filtered3.begin() != filtered3.end());
645
646 FilteredTest unionIntersection = (filtered1 + filtered2) * filtered3;
647 REQUIRE(3 == unionIntersection.size());
648
649 i = 0;
650 for (auto& f : unionIntersection) {
651 REQUIRE(i == f.x());
652 REQUIRE(i + 8 == f.y());
653 REQUIRE(i == f.index());
654 i++;
655 }
656 REQUIRE(i == 3);
657}
658
659TEST_CASE("TestNestedFiltering")
660{
661 TableBuilder builderA;
662 auto rowWriterA = builderA.persist<int32_t, int32_t>({"fX", "fY"});
663 rowWriterA(0, 0, 8);
664 rowWriterA(0, 1, 9);
665 rowWriterA(0, 2, 10);
666 rowWriterA(0, 3, 11);
667 rowWriterA(0, 4, 12);
668 rowWriterA(0, 5, 13);
669 rowWriterA(0, 6, 14);
670 rowWriterA(0, 7, 15);
671 auto tableA = builderA.finalize();
672 REQUIRE(tableA->num_rows() == 8);
673
674 using TestA = InPlaceTable<0, o2::soa::Index<>, o2::aod::test::X, o2::aod::test::Y>;
675 using FilteredTest = Filtered<TestA>;
676 using NestedFilteredTest = Filtered<Filtered<TestA>>;
677 using TripleNestedFilteredTest = Filtered<Filtered<Filtered<TestA>>>;
678 using namespace o2::framework;
679
680 expressions::Filter f1 = o2::aod::test::x < 4;
681 expressions::Filter f2 = o2::aod::test::y > 9;
682 expressions::Filter f3 = o2::aod::test::x < 3;
683
684 TestA testA{tableA};
685 auto s1 = expressions::createSelection(testA.asArrowTable(), f1);
686 FilteredTest filtered{{testA.asArrowTableRef()}, s1};
687 REQUIRE(4 == filtered.size());
688 REQUIRE(filtered.begin() != filtered.end());
689
690 auto s2 = expressions::createSelection(filtered.asArrowTable(), f2);
691 NestedFilteredTest nestedFiltered{{filtered}, s2};
692 REQUIRE(2 == nestedFiltered.size());
693 auto i = 0;
694 for (auto& f : nestedFiltered) {
695 REQUIRE(i + 2 == f.x());
696 REQUIRE(i + 10 == f.y());
697 REQUIRE(i + 2 == f.index());
698 i++;
699 }
700 REQUIRE(i == 2);
701
702 auto s3 = expressions::createSelection(nestedFiltered.asArrowTable(), f3);
703 TripleNestedFilteredTest tripleFiltered{{nestedFiltered}, s3};
704 REQUIRE(1 == tripleFiltered.size());
705 i = 0;
706 for (auto& f : tripleFiltered) {
707 REQUIRE(i + 2 == f.x());
708 REQUIRE(i + 10 == f.y());
709 REQUIRE(i + 2 == f.index());
710 i++;
711 }
712 REQUIRE(i == 1);
713}
714
715TEST_CASE("TestEmptyTables")
716{
717 TableBuilder bPoints;
718 [[maybe_unused]] auto pwriter = bPoints.cursor<o2::aod::Points>();
719 auto pempty = bPoints.finalize();
720
721 TableBuilder bInfos;
722 [[maybe_unused]] auto iwriter = bInfos.cursor<o2::aod::Infos>();
723 auto iempty = bInfos.finalize();
724
725 o2::aod::Points p{pempty};
726 o2::aod::Infos i{iempty};
727
729 PI pi{{pempty, iempty}};
730 REQUIRE(pi.size() == 0);
731 auto spawned = Extend<o2::aod::Points, o2::aod::test::ESum>(p);
732 REQUIRE(spawned.size() == 0);
733}
734
735namespace o2::aod
736{
737DECLARE_SOA_TABLE(Origints, "TEST", "ORIG", o2::soa::Index<>, test::X, test::SomeBool);
738namespace test
739{
740DECLARE_SOA_INDEX_COLUMN(Origint, origint);
741DECLARE_SOA_INDEX_COLUMN_FULL(AltOrigint, altOrigint, int, Origints, "_alt");
743} // namespace test
744
745DECLARE_SOA_TABLE(References, "TEST", "REFS", o2::soa::Index<>, test::OrigintId);
746DECLARE_SOA_TABLE(OtherReferences, "TEST", "OREFS", o2::soa::Index<>, test::AltOrigintId);
747DECLARE_SOA_TABLE(ManyReferences, "TEST", "MREFS", o2::soa::Index<>, test::OrigintIds);
748} // namespace o2::aod
749
750TEST_CASE("TestIndexToFiltered")
751{
753 auto writer = b.cursor<o2::aod::Origints>();
754 for (auto i = 0; i < 20; ++i) {
755 writer(0, i, i % 3 == 0);
756 }
757 auto origins = b.finalize();
758 o2::aod::Origints o{origins};
759
761 auto writer_z = z.cursor<o2::aod::ManyReferences>();
762 std::vector<int> ids;
763 for (auto i = 0; i < 5; ++i) {
764 ids.clear();
765 for (auto j = 0; j < 20; ++j) {
766 ids.push_back(j);
767 }
768 writer_z(0, ids);
769 }
770 auto mrefs = z.finalize();
771 o2::aod::ManyReferences m{mrefs};
772
774 auto writer_w = w.cursor<o2::aod::References>();
775 for (auto i = 0; i < 5 * 20; ++i) {
776 writer_w(0, i % 20);
777 }
778 auto refs = w.finalize();
779 o2::aod::References r{refs};
780 expressions::Filter flt = o2::aod::test::someBool == true;
782 auto selection = expressions::createSelection(o.asArrowTable(), flt);
783 Flt f{{o.asArrowTableRef()}, selection};
784 r.bindExternalIndices(&f);
785 auto it = r.begin();
786 it.moveByIndex(23);
787 REQUIRE(it.origint_as<Flt>().globalIndex() == 3);
788 it++;
789 REQUIRE(it.origint_as<Flt>().globalIndex() == 4);
790 it++;
791 REQUIRE(it.origint_as<Flt>().globalIndex() == 5);
792
793 m.bindExternalIndices(&f);
794 for (auto const& row : m) {
795 auto os = row.origints_as<Flt>();
796 auto fos = row.filtered_origints_as<Flt>();
797 REQUIRE(os.size() == 20);
798 REQUIRE(fos.size() == 6);
799 }
800}
801namespace o2::aod
802{
803namespace test
804{
805DECLARE_SOA_INDEX_COLUMN_FULL(SinglePoint, singlePoint, int32_t, Points3Ds, "");
806DECLARE_SOA_ARRAY_INDEX_COLUMN(Points3D, pointGroup);
807DECLARE_SOA_SLICE_INDEX_COLUMN(Points3D, pointSlice);
808DECLARE_SOA_SELF_INDEX_COLUMN(OtherPoint, otherPoint);
811} // namespace test
812
813DECLARE_SOA_TABLE(PointsRef, "TEST", "PTSREF", test::Points3DIdSlice, test::Points3DIds);
814DECLARE_SOA_TABLE(PointsRefF, "TEST", "PTSREFF", test::SinglePointId, test::Points3DIdSlice, test::Points3DIds);
815DECLARE_SOA_TABLE(PointsSelfIndex, "TEST", "PTSSLF", o2::soa::Index<>, test::X, test::Y, test::Z, test::OtherPointId,
816 test::PointSeqIdSlice, test::PointSetIds);
817} // namespace o2::aod
818
819TEST_CASE("TestAdvancedIndices")
820{
821 TableBuilder b1;
822 auto pwriter = b1.persist<int, int, int>({"fX", "fY", "fZ"});
823 for (auto i = 0; i < 20; ++i) {
824 pwriter(0, -1 * i, (int)(i / 2), 2 * i);
825 }
826 auto tpts1 = b1.finalize();
827
828 TableBuilder b2;
829 auto prwriter = b2.cursor<o2::aod::PointsRef>();
830 auto a = std::array{0, 1};
831 auto aa = std::vector{2, 3, 4};
832 prwriter(0, &a[0], aa);
833 a = {4, 10};
834 aa = {12, 2, 19};
835 prwriter(0, &a[0], aa);
836 auto t2 = b2.finalize();
837
838 auto pt = o2::aod::Points3Ds{tpts1};
839 auto prt = o2::aod::PointsRef{t2};
840 prt.bindExternalIndices(&pt);
841
842 auto it = prt.begin();
843 auto s1 = it.pointSlice();
844 auto g1 = it.pointGroup();
845 auto bb = std::same_as<decltype(s1), o2::aod::Points3Ds>;
846 REQUIRE(bb);
847 REQUIRE(s1.size() == 2);
848 aa = {2, 3, 4};
849 for (int i = 0; i < 3; ++i) {
850 REQUIRE(g1[i].globalIndex() == aa[i]);
851 }
852
853 // Check the X coordinate of the points in the pointGroup
854 // for the first point.
855 for (auto& p : it.pointGroup_as<o2::aod::Points3Ds>()) {
856 REQUIRE(p.x() == -1 * p.globalIndex());
857 }
858
859 ++it;
860 auto s2 = it.pointSlice();
861 auto g2 = it.pointGroup();
862 REQUIRE(s2.size() == 7);
863 aa = {12, 2, 19};
864 for (int i = 0; i < 3; ++i) {
865 REQUIRE(g2[i].globalIndex() == aa[i]);
866 }
867
869 expressions::Filter fltx = (o2::aod::test::x <= -6);
870 Flt f{{tpts1}, expressions::createSelection(tpts1, fltx)};
871 prt.bindExternalIndices(&f);
872
873 auto it2 = prt.begin();
874 auto s1f = it2.pointSlice_as<Flt>();
875 auto g1f = it2.pointGroup_as<Flt>();
876 REQUIRE(s1f.size() == 2);
877 aa = {2, 3, 4};
878 for (int i = 0; i < 3; ++i) {
879 REQUIRE(g1f[i].globalIndex() == aa[i]);
880 }
881
882 ++it2;
883 auto s2f = it2.pointSlice_as<Flt>();
884 auto g2f = it2.pointGroup_as<Flt>();
885 REQUIRE(s2f.size() == 7);
886 aa = {12, 2, 19};
887 for (int i = 0; i < 3; ++i) {
888 REQUIRE(g2f[i].globalIndex() == aa[i]);
889 }
890
891 TableBuilder b3;
892 auto pswriter = b3.cursor<o2::aod::PointsSelfIndex>();
893 int references[] = {19, 2, 0, 13, 4, 6, 5, 5, 11, 9, 3, 8, 16, 14, 1, 18, 12, 18, 2, 7};
894 int slice[2] = {-1, -1};
895 std::vector<int> pset;
896 std::array<int, 4> withSlices = {3, 6, 13, 19};
897 std::array<std::pair<int, int>, 4> bounds = {std::pair{1, 5}, std::pair{3, 3}, std::pair{11, 11}, std::pair{10, 18}};
898 std::array<int, 4> withSets = {0, 1, 13, 14};
899 unsigned const int sizes[] = {3, 1, 5, 4};
900 unsigned int c1 = 0;
901 unsigned int c2 = 0;
902 for (auto i = 0; i < 20; ++i) {
903 pset.clear();
904 slice[0] = -1;
905 slice[1] = -1;
906 if (c1 < withSlices.size() && i == withSlices[c1]) {
907 slice[0] = bounds[c1].first;
908 slice[1] = bounds[c1].second;
909 ++c1;
910 }
911 if (c2 < withSets.size() && i == withSets[c2]) {
912 for (auto z = 0U; z < sizes[c2]; ++z) {
913 pset.push_back(i + 1 + z);
914 }
915 ++c2;
916 }
917 pswriter(0, -1 * i, 0.5 * i, 2 * i, references[i], slice, pset);
918 }
919 auto t3 = b3.finalize();
920 auto pst = o2::aod::PointsSelfIndex{t3};
921 pst.bindInternalIndicesTo(&pst);
922 auto i = 0;
923 c1 = 0;
924 c2 = 0;
925 for (auto& p : pst) {
926 auto op = p.otherPoint_as<o2::aod::PointsSelfIndex>();
927 auto bbb = std::same_as<decltype(op), o2::aod::PointsSelfIndex::iterator>;
928 REQUIRE(bbb);
929 REQUIRE(op.globalIndex() == references[i]);
930
931 auto ops = p.pointSeq_as<o2::aod::PointsSelfIndex>();
932 auto bbbs = std::same_as<decltype(ops), o2::aod::PointsSelfIndex>;
933 REQUIRE(bbbs);
934
935 if (i == withSlices[c1]) {
936 auto lit = ops.begin();
937 REQUIRE(ops.size() == bounds[c1].second - bounds[c1].first + 1);
938 REQUIRE(lit.globalIndex() == bounds[c1].first);
939 lit.moveByIndex(ops.size() - 1);
940 REQUIRE(lit.globalIndex() == bounds[c1].second);
941 ++c1;
942 } else {
943 REQUIRE(ops.size() == 0);
944 }
945
946 auto opss = p.pointSet_as<o2::aod::PointsSelfIndex>();
947 auto bbba = std::same_as<decltype(opss), std::vector<o2::aod::PointsSelfIndex::iterator>>;
948 REQUIRE(bbba);
949
950 auto opss_ids = p.pointSetIds();
951 if (c2 < withSets.size() && i == withSets[c2]) {
952 REQUIRE(opss.size() == sizes[c2]);
953 REQUIRE(opss.begin()->globalIndex() == i + 1);
954 REQUIRE(opss.back().globalIndex() == i + sizes[c2]);
955 int c3 = 0;
956 for (auto const& id : opss_ids) {
957 REQUIRE(id == i + 1 + c3);
958 ++c3;
959 }
960 ++c2;
961 } else {
962 REQUIRE(opss.size() == 0);
963 }
964 ++i;
965 }
966}
967
968namespace o2::aod
969{
970DECLARE_SOA_TABLE(PointsSelfRef, "TEST", "PTSSR", test::OtherPointId, test::PointSeqIdSlice, test::PointSetIds);
971} // namespace o2::aod
972
973TEST_CASE("TestSelfIndexRecursion")
974{
975 TableBuilder b3;
976 auto pswriter = b3.cursor<o2::aod::PointsSelfIndex>();
977 int references[] = {19, 2, 0, 13, 4, 6, 5, 5, 11, 9, 3, 8, 16, 14, 1, 18, 12, 18, 2, 7};
978 int slice[2] = {-1, -1};
979 std::vector<int> pset;
980 std::array<int, 4> withSlices = {3, 6, 13, 19};
981 std::array<std::pair<int, int>, 4> bounds = {std::pair{1, 5}, std::pair{3, 3}, std::pair{11, 11}, std::pair{10, 18}};
982 std::array<int, 4> withSets = {0, 1, 13, 14};
983 unsigned const int sizes[] = {3, 1, 5, 4};
984 unsigned int c1 = 0;
985 unsigned int c2 = 0;
986 for (auto i = 0; i < 20; ++i) {
987 pset.clear();
988 slice[0] = -1;
989 slice[1] = -1;
990 if (c1 < withSlices.size() && i == withSlices[c1]) {
991 slice[0] = bounds[c1].first;
992 slice[1] = bounds[c1].second;
993 ++c1;
994 }
995 if (c2 < withSets.size() && i == withSets[c2]) {
996 for (auto z = 0U; z < sizes[c2]; ++z) {
997 pset.push_back(i + 1 + z);
998 }
999 ++c2;
1000 }
1001 pswriter(0, -1 * i, 0.5 * i, 2 * i, references[i], slice, pset);
1002 }
1003 auto t3 = b3.finalize();
1004 auto pst = o2::aod::PointsSelfIndex{t3};
1005 pst.bindInternalIndicesTo(&pst);
1006
1007 // FIXME: only 4 levels of recursive self-index dereference are tested
1008 for (auto& p : pst) {
1009 auto ops = p.pointSeq_as<o2::aod::PointsSelfIndex>();
1010 for (auto& pp : ops) {
1011 auto bpp = std::same_as<std::decay_t<decltype(pp)>, o2::aod::PointsSelfIndex::iterator>;
1012 REQUIRE(bpp);
1013 auto opps = pp.pointSeq_as<o2::aod::PointsSelfIndex>();
1014 for (auto& ppp : opps) {
1015 auto bppp = std::same_as<std::decay_t<decltype(ppp)>, o2::aod::PointsSelfIndex::iterator>;
1016 REQUIRE(bppp);
1017 auto oppps = ppp.pointSeq_as<o2::aod::PointsSelfIndex>();
1018 for (auto& pppp : oppps) {
1019 auto bpppp = std::same_as<std::decay_t<decltype(pppp)>, o2::aod::PointsSelfIndex::iterator>;
1020 REQUIRE(bpppp);
1021 auto opppps = pppp.pointSeq_as<o2::aod::PointsSelfIndex>();
1022 }
1023 }
1024 }
1025 }
1026
1029 auto corewriter = b.cursor<o2::aod::Points3Ds>();
1030 for (auto i = 0; i < 20; ++i) {
1031 corewriter(0, -1 * i, 0.5 * i, 2 * i);
1032 }
1033 auto t1 = b.finalize();
1034
1035 c1 = 0;
1036 c2 = 0;
1037 TableBuilder be;
1038 auto extwriter = be.cursor<o2::aod::PointsSelfRef>();
1039 for (auto i = 0; i < 20; ++i) {
1040 pset.clear();
1041 slice[0] = -1;
1042 slice[1] = -1;
1043 if (c1 < withSlices.size() && i == withSlices[c1]) {
1044 slice[0] = bounds[c1].first;
1045 slice[1] = bounds[c1].second;
1046 ++c1;
1047 }
1048 if (c2 < withSets.size() && i == withSets[c2]) {
1049 for (auto z = 0U; z < sizes[c2]; ++z) {
1050 pset.push_back(i + 1 + z);
1051 }
1052 ++c2;
1053 }
1054 extwriter(0, references[i], slice, pset);
1055 }
1056 auto t2 = be.finalize();
1057
1058 FullPoints fp({t1, t2});
1059 fp.bindInternalIndicesTo(&fp);
1060
1061 // FIXME: only 4 levels of recursive self-index dereference are tested
1062 // self-index binding should stay the same for recursive dereferences
1063 for (auto& p : fp) {
1064 REQUIRE(std::same_as<std::decay_t<decltype(p)>, FullPoints::iterator>);
1065 auto ops = p.pointSeq_as<FullPoints>();
1066 for (auto& pp : ops) {
1067 REQUIRE(std::same_as<std::decay_t<decltype(pp)>, FullPoints::iterator>);
1068 auto opps = pp.pointSeq_as<FullPoints>();
1069 for (auto& ppp : opps) {
1070 REQUIRE(std::same_as<std::decay_t<decltype(ppp)>, FullPoints::iterator>);
1071 auto oppps = ppp.pointSeq_as<FullPoints>();
1072 for (auto& pppp : oppps) {
1073 REQUIRE(std::same_as<std::decay_t<decltype(pppp)>, FullPoints::iterator>);
1074 auto opppps = pppp.pointSeq_as<FullPoints>();
1075 }
1076 }
1077 }
1078 }
1079
1080 auto const& fpa = fp;
1081
1082 // iterators acquired through different means should have consistent types
1083 for (auto const& it1 : fpa) {
1084 [[maybe_unused]] auto it2 = fpa.rawIteratorAt(0);
1085 [[maybe_unused]] auto it3 = fpa.iteratorAt(0);
1086 auto bit1 = std::same_as<std::decay_t<decltype(it1)>, std::decay_t<decltype(it2)>>;
1087 REQUIRE(bit1);
1088 auto bit2 = std::same_as<std::decay_t<decltype(it1)>, std::decay_t<decltype(it3)>>;
1089 REQUIRE(bit2);
1090 }
1091
1092 using FilteredPoints = o2::soa::Filtered<FullPoints>;
1093 FilteredPoints ffp({t1, t2}, SelectionVector{1, 2, 3});
1094 ffp.bindInternalIndicesTo(&ffp);
1095
1096 // Filter should not interfere with self-index and the binding should stay the same
1097 for (auto& p : ffp) {
1098 REQUIRE(std::same_as<std::decay_t<decltype(p)>, FilteredPoints::iterator>);
1099 REQUIRE(std::same_as<std::decay_t<decltype(p)>::parent_t, FilteredPoints>);
1100 auto ops = p.pointSeq_as<typename std::decay_t<decltype(p)>::parent_t>();
1101 for (auto& pp : ops) {
1102 REQUIRE(std::same_as<std::decay_t<decltype(pp)>::parent_t, FilteredPoints>);
1103 auto opps = pp.pointSeq_as<FilteredPoints>();
1104 for (auto& ppp : opps) {
1105 REQUIRE(std::same_as<std::decay_t<decltype(ppp)>, FilteredPoints::iterator>);
1106 auto oppps = ppp.pointSeq_as<FilteredPoints>();
1107 for (auto& pppp : oppps) {
1108 REQUIRE(std::same_as<std::decay_t<decltype(pppp)>, FilteredPoints::iterator>);
1109 auto opppps = pppp.pointSeq_as<FilteredPoints>();
1110 }
1111 }
1112 }
1113 }
1114
1115 auto const& ffpa = ffp;
1116
1117 // rawIteratorAt() should create an unfiltered iterator, unlike begin() and iteratorAt()
1118 for (auto const& it1 : ffpa) {
1119 [[maybe_unused]] auto it2 = ffpa.rawIteratorAt(0);
1120 [[maybe_unused]] auto it3 = ffpa.iteratorAt(0);
1121 using T1 = std::decay_t<decltype(it1)>;
1122 using T2 = std::decay_t<decltype(it2)>;
1123 using T3 = std::decay_t<decltype(it3)>;
1124 auto bit1 = !std::same_as<T1, T2>;
1125 REQUIRE(bit1);
1126 auto bit2 = !std::same_as<T1, T3>;
1127 REQUIRE(bit2);
1128 auto bit3 = std::same_as<typename T1::policy_t, typename T3::policy_t>;
1129 REQUIRE(bit3);
1130 auto bit4 = std::same_as<typename T1::policy_t, o2::soa::FilteredIndexPolicy>;
1131 REQUIRE(bit4);
1132 auto bit5 = std::same_as<typename T2::policy_t, o2::soa::DefaultIndexPolicy>;
1133 REQUIRE(bit5);
1134 }
1135}
1136
1137TEST_CASE("TestListColumns")
1138{
1140 auto writer = b.cursor<o2::aod::Lists>();
1141 std::vector<float> floats;
1142 std::vector<int> ints;
1143 for (auto i = 1; i < 11; ++i) {
1144 floats.clear();
1145 ints.clear();
1146 for (auto j = 0; j < i; ++j) {
1147 floats.push_back(0.1231233f * (float)j + 0.1982798f);
1148 ints.push_back(j + 10);
1149 }
1150
1151 writer(0, floats, ints);
1152 }
1153 auto lt = b.finalize();
1154 o2::aod::Lists tbl{lt};
1155 auto s = 1U;
1156 for (auto& row : tbl) {
1157 auto f = row.l1();
1158 auto i = row.l2();
1159 auto constexpr bf = std::same_as<decltype(f), gsl::span<const float, (size_t)-1>>;
1160 auto constexpr bi = std::same_as<decltype(i), gsl::span<const int, (size_t)-1>>;
1161 REQUIRE(bf);
1162 REQUIRE(bi);
1163 REQUIRE(f.size() == s);
1164 REQUIRE(i.size() == s);
1165
1166 for (auto j = 0u; j < f.size(); ++j) {
1167 REQUIRE(f[j] == 0.1231233f * (float)j + 0.1982798f);
1168 REQUIRE(i[j] == (int)j + 10);
1169 }
1170 ++s;
1171 }
1172}
1173
1174TEST_CASE("TestSliceByCached")
1175{
1177 auto writer = b.cursor<o2::aod::Origints>();
1178 for (auto i = 0; i < 20; ++i) {
1179 writer(0, i, i % 3 == 0);
1180 }
1181 auto origins = b.finalize();
1182 o2::aod::Origints o{origins};
1183
1185 auto writer_w = w.cursor<o2::aod::References>();
1186 auto step = -1;
1187 for (auto i = 0; i < 5 * 20; ++i) {
1188 if (i % 5 == 0) {
1189 ++step;
1190 }
1191 writer_w(0, step);
1192 }
1193 auto refs = w.finalize();
1194 o2::aod::References r{refs};
1195
1196 std::string key = "fIndex" + o2::framework::cutString(o2::soa::getLabelFromType<o2::aod::Origints>());
1197 ArrowTableSlicingCache atscache({{o2::soa::getLabelFromType<o2::aod::References>(), o2::soa::getMatcherFromTypeForKey<o2::aod::References>(key), key}});
1198 auto s = atscache.updateCacheEntry(0, refs);
1199 SliceCache cache{&atscache};
1200
1201 for (auto& oi : o) {
1202 auto cachedSlice = r.sliceByCached(o2::aod::test::origintId, oi.globalIndex(), cache);
1203 REQUIRE(cachedSlice.size() == 5);
1204 for (auto& ri : cachedSlice) {
1205 REQUIRE(ri.origintId() == oi.globalIndex());
1206 }
1207 }
1208}
1209
1210TEST_CASE("TestSliceByCachedMismatched")
1211{
1213 auto writer = b.cursor<o2::aod::Origints>();
1214 for (auto i = 0; i < 20; ++i) {
1215 writer(0, i, i % 3 == 0);
1216 }
1217 auto origins = b.finalize();
1218 o2::aod::Origints o{origins};
1219
1221 auto writer_w = w.cursor<o2::aod::References>();
1222 auto step = -1;
1223 for (auto i = 0; i < 5 * 20; ++i) {
1224 if (i % 5 == 0) {
1225 ++step;
1226 }
1227 writer_w(0, step);
1228 }
1229 auto refs = w.finalize();
1230 o2::aod::References r{refs};
1231
1232 TableBuilder w2;
1233 auto writer_w2 = w2.cursor<o2::aod::OtherReferences>();
1234 step = -1;
1235 for (auto i = 0; i < 5 * 20; ++i) {
1236 if (i % 3 == 0) {
1237 ++step;
1238 }
1239 writer_w2(0, step);
1240 }
1241 auto refs2 = w2.finalize();
1242 o2::aod::OtherReferences r2{refs2};
1243
1245 J rr{{refs, refs2}};
1246
1247 auto key = "fIndex" + o2::framework::cutString(o2::soa::getLabelFromType<o2::aod::Origints>()) + "_alt";
1248 ArrowTableSlicingCache atscache({{o2::soa::getLabelFromTypeForKey<J>(key), o2::soa::getMatcherFromTypeForKey<J>(key), key}});
1249 auto s = atscache.updateCacheEntry(0, refs2);
1250 SliceCache cache{&atscache};
1251
1252 for (auto& oi : o) {
1253 auto cachedSlice = rr.sliceByCached(o2::aod::test::altOrigintId, oi.globalIndex(), cache);
1254 REQUIRE(cachedSlice.size() == 3);
1255 for (auto& ri : cachedSlice) {
1256 REQUIRE(ri.altOrigintId() == oi.globalIndex());
1257 }
1258 }
1259}
1260
1261TEST_CASE("TestSliceByCachedFiltered")
1262{
1264 auto writer = b.cursor<o2::aod::Origints>();
1265 for (auto i = 0; i < 20; ++i) {
1266 writer(0, i, i % 3 == 0);
1267 }
1268 auto origins = b.finalize();
1269 o2::aod::Origints o{origins};
1270
1272 auto writer_w = w.cursor<o2::aod::References>();
1273 auto step = -1;
1274 for (auto i = 0; i < 5 * 20; ++i) {
1275 if (i % 5 == 0) {
1276 ++step;
1277 }
1278 writer_w(0, step);
1279 }
1280 auto refs = w.finalize();
1281 o2::aod::References r{refs};
1282
1283 TableBuilder w2;
1284 auto writer_w2 = w2.cursor<o2::aod::OtherReferences>();
1285 step = -1;
1286 for (auto i = 0; i < 5 * 20; ++i) {
1287 if (i % 3 == 0) {
1288 ++step;
1289 }
1290 writer_w2(0, step);
1291 }
1292 auto refs2 = w2.finalize();
1293 o2::aod::OtherReferences r2{refs2};
1294
1296 J rr{{refs, refs2}};
1297
1298 auto rrf = rr.select(o2::aod::test::altOrigintId > 2 && o2::aod::test::altOrigintId < 15);
1299
1300 auto key = "fIndex" + o2::framework::cutString(o2::soa::getLabelFromType<o2::aod::Origints>()) + "_alt";
1301 ArrowTableSlicingCache atscache({{o2::soa::getLabelFromTypeForKey<J>(key), o2::soa::getMatcherFromTypeForKey<J>(key), key}});
1302 auto s = atscache.updateCacheEntry(0, refs2);
1303 SliceCache cache{&atscache};
1304
1305 for (auto& oi : o) {
1306 auto cachedSlice = rrf.sliceByCached(o2::aod::test::altOrigintId, oi.globalIndex(), cache);
1307 if (oi.globalIndex() <= 2 || oi.globalIndex() >= 15) {
1308 CHECK(cachedSlice.size() == 0);
1309 } else {
1310 CHECK(cachedSlice.size() == 3);
1311 }
1312 for (auto& ri : cachedSlice) {
1313 REQUIRE(ri.altOrigintId() == oi.globalIndex());
1314 }
1315 }
1316}
1317
1318TEST_CASE("TestIndexUnboundExceptions")
1319{
1321 auto prwriter = b.cursor<o2::aod::PointsRefF>();
1322 auto a = std::array{0, 1};
1323 auto aa = std::vector{2, 3, 4};
1324 prwriter(0, 0, &a[0], aa);
1325 a = {4, 10};
1326 aa = {12, 2, 19};
1327 prwriter(0, 1, &a[0], aa);
1328 auto t = b.finalize();
1329 auto prt = o2::aod::PointsRefF{t};
1330
1331 for (auto& row : prt) {
1332 try {
1333 [[maybe_unused]] auto sp = row.singlePoint();
1334 } catch (RuntimeErrorRef ref) {
1335 REQUIRE(std::string{error_from_ref(ref).what} == "Index pointing to Points3Ds is not bound! Did you subscribe to the table?");
1336 }
1337 try {
1338 auto ps = row.pointSlice();
1339 } catch (RuntimeErrorRef ref) {
1340 REQUIRE(std::string{error_from_ref(ref).what} == "Index pointing to Points3Ds is not bound! Did you subscribe to the table?");
1341 }
1342 try {
1343 auto pg = row.pointGroup();
1344 } catch (RuntimeErrorRef ref) {
1345 REQUIRE(std::string{error_from_ref(ref).what} == "Index pointing to Points3Ds is not bound! Did you subscribe to the table?");
1346 }
1347 }
1348}
1349
1350namespace o2::aod
1351{
1352namespace test
1353{
1354DECLARE_SOA_COLUMN(SmallIntArray, smallIntArray, int8_t[32]);
1355DECLARE_SOA_BITMAP_COLUMN(BoolArray, boolArray, 32);
1356} // namespace test
1357
1358DECLARE_SOA_TABLE(BILists, "TEST", "BILISTS", o2::soa::Index<>, test::SmallIntArray, test::BoolArray);
1359} // namespace o2::aod
1360
1361TEST_CASE("TestArrayColumns")
1362{
1364 auto writer = b.cursor<o2::aod::BILists>();
1365 int8_t ii[32];
1366 for (auto i = 0; i < 20; ++i) {
1367 uint32_t bb = 0;
1368 for (auto j = 0; j < 32; ++j) {
1369 ii[j] = j;
1370 if (j % 2 == 0) {
1371 bb |= 1 << j;
1372 }
1373 }
1374 writer(0, ii, bb);
1375 }
1376 auto t = b.finalize();
1377
1378 o2::aod::BILists li{t};
1379 for (auto const& row : li) {
1380 auto iir = row.smallIntArray();
1381 [[maybe_unused]] auto bbrr = row.boolArray_raw();
1382 REQUIRE(std::same_as<std::decay_t<decltype(iir)>, int8_t const*>);
1383 for (auto i = 0; i < 32; ++i) {
1384 REQUIRE(iir[i] == i);
1385 REQUIRE(row.boolArray_bit(i) == (i % 2 == 0));
1386 }
1387 }
1388}
1389
1390namespace o2::aod
1391{
1392namespace table
1393{
1395DECLARE_SOA_COLUMN(Two, two, float);
1396DECLARE_SOA_COLUMN(Three, three, double);
1397DECLARE_SOA_COLUMN(Four, four, int[2]);
1398DECLARE_SOA_DYNAMIC_COLUMN(Five, five, [](const int in[2]) -> float { return (float)in[0] / (float)in[1]; });
1399} // namespace table
1400
1401DECLARE_SOA_TABLE(MixTest, "AOD", "MIXTST",
1402 table::One, table::Two, table::Three, table::Four,
1403 table::Five<table::Four>);
1404} // namespace o2::aod
1405
1406TEST_CASE("TestCombinedGetter")
1407{
1409 auto writer = b.cursor<o2::aod::MixTest>();
1410 int f[2];
1411 for (auto i = 0; i < 20; ++i) {
1412 f[0] = i;
1413 f[1] = i + 1;
1414 writer(0, i, o2::constants::math::PI * i, o2::constants::math::Almost0 * i, f);
1415 }
1416 auto t = b.finalize();
1417 o2::aod::MixTest mt{t};
1418 auto count = 0;
1419 for (auto const& row : mt) {
1420 auto features1 = row.getValues<float, o2::aod::table::One, o2::aod::table::Three>();
1421 auto features2 = row.getValues<double, o2::aod::table::One, o2::aod::table::Two, o2::aod::table::Three>();
1422 auto features3 = row.getValues<float, o2::aod::table::Two, o2::aod::table::Five<o2::aod::table::Four>>();
1423 auto b1 = std::same_as<std::array<float, 2>, decltype(features1)>;
1424 REQUIRE(b1);
1425 auto b2 = std::same_as<std::array<double, 3>, decltype(features2)>;
1426 REQUIRE(b2);
1427 auto b3 = std::same_as<std::array<float, 2>, decltype(features3)>;
1428 REQUIRE(b3);
1429 REQUIRE(features1[0] == (float)count);
1430 REQUIRE(features1[1] == (float)(o2::constants::math::Almost0 * count));
1431
1432 REQUIRE(features2[0] == (double)count);
1433 REQUIRE(features2[1] == (double)(o2::constants::math::PI * count));
1434 REQUIRE(features2[2] == (double)(o2::constants::math::Almost0 * count));
1435
1436 REQUIRE(features3[0] == (float)(o2::constants::math::PI * count));
1437 REQUIRE(features3[1] == (float)((float)count / (float)(count + 1)));
1438 ++count;
1439 }
1440}
1441
1442TEST_CASE("TestWritingCursorLastIndexAndReserve")
1443{
1444 // Nails down the WritingCursor semantics the AOD-producer reserves depend on:
1445 // lastIndex() returns the *last index* (rows - 1), not the row count, and
1446 // reserve(newRows + lastIndex() + 1) reserves exactly the post-batch total so a
1447 // fully-filled, no-skip batch neither overruns (the fwdTrkCls crash) nor trips
1448 // the release() / per-row UnsafeAppend guard.
1449 Produces<o2::aod::Points> cursor; // Points has two persistent columns: X, Y
1450 auto* builder = new TableBuilder();
1452
1453 // Empty cursor: no row written, so the last index is -1 and rows == lastIndex()+1 == 0.
1454 REQUIRE(cursor.lastIndex() == -1);
1455
1456 // operator() increments before the append, but only to the index of the row it
1457 // writes: after N writes lastIndex() == N - 1, NOT N.
1458 cursor(10, 20);
1459 REQUIRE(cursor.lastIndex() == 0);
1460 cursor(11, 21);
1461 REQUIRE(cursor.lastIndex() == 1);
1462 cursor(12, 22);
1463 REQUIRE(cursor.lastIndex() == 2);
1464 REQUIRE(cursor.lastIndex() + 1 == 3); // rows-so-far == last index + 1
1465
1466 // Reserve a second batch the correct way: total = newRows + rowsSoFar
1467 // = newRows + (lastIndex() + 1).
1468 // The (buggy) newRows + lastIndex() would reserve 4 here and under-reserve the
1469 // 5th row; the + 1 makes it exactly 5.
1470 int64_t const newRows = 2;
1471 int64_t const reserved = newRows + cursor.lastIndex() + 1; // correct total -> reserve(5)
1472 cursor.reserve(reserved);
1473 cursor(13, 23); // row index 3
1474 cursor(14, 24); // row index 4 — fills the batch exactly (5 rows total)
1475 REQUIRE(cursor.lastIndex() == 4);
1476
1477 // The contract release() enforces: rows filled (lastIndex()+1) must not exceed
1478 // what was reserved. Correct (+1) gives reserved == 5 -> 5 <= 5 (green); the buggy
1479 // newRows + lastIndex() reserves only 4 -> 5 <= 4 fails (red).
1480 REQUIRE(cursor.lastIndex() + 1 <= reserved);
1481
1482 auto table = builder->finalize();
1483 REQUIRE(table->num_rows() == 5);
1484 REQUIRE(table->num_columns() == 2);
1485 cursor.release();
1486}
1487
1488namespace o2::aod
1489{
1490namespace test
1491{
1492DECLARE_SOA_COLUMN(UInt8, guint8, uint8_t);
1493DECLARE_SOA_COLUMN(UInt16, guint16, uint16_t);
1494DECLARE_SOA_COLUMN(UInt32, guint32, uint32_t);
1495DECLARE_SOA_COLUMN(UInt64, guint64, uint64_t);
1496} // namespace test
1497
1498DECLARE_SOA_TABLE(UnsignedIntTest8, "TEST", "TSHI8", test::UInt8);
1499DECLARE_SOA_TABLE(UnsignedIntTest16, "TEST", "TSHI16", test::UInt16);
1500DECLARE_SOA_TABLE(UnsignedIntTest32, "TEST", "TSHI32", test::UInt32);
1501DECLARE_SOA_TABLE(UnsignedIntTest64, "TEST", "TSHI64", test::UInt64);
1502} // namespace o2::aod
1503
1504TEST_CASE("TestUnsignedIntExpressions")
1505{
1506 auto max8 = std::numeric_limits<uint8_t>::max();
1507 auto max16 = std::numeric_limits<uint8_t>::max();
1508 auto max32 = std::numeric_limits<uint8_t>::max();
1509 auto max64 = std::numeric_limits<uint8_t>::max();
1510
1511 TableBuilder b8;
1512 auto writer8 = b8.cursor<o2::aod::UnsignedIntTest8>();
1513 for (uint64_t i = 0; i < max8; i += (max8 / 100)) {
1514 writer8(0, i);
1515 }
1516 auto t8 = b8.finalize();
1517 o2::aod::UnsignedIntTest8 at8{{t8}};
1518
1519 uint8_t limit8 = max8 / 2 + 1;
1520 o2::framework::expressions::Filter test8 = o2::aod::test::guint8 < limit8;
1522
1524
1525 REQUIRE(at8.size() == 128);
1526 REQUIRE(fat8.size() == 64);
1527
1528 TableBuilder b16;
1529 auto writer16 = b16.cursor<o2::aod::UnsignedIntTest16>();
1530 for (uint64_t i = 0; i < max16; i += (max16 / 100)) {
1531 writer16(0, i);
1532 }
1533 auto t16 = b16.finalize();
1534 o2::aod::UnsignedIntTest16 at16{{t16}};
1535
1536 uint16_t limit16 = max16 / 2 + 1;
1537 o2::framework::expressions::Filter test16 = o2::aod::test::guint16 < limit16;
1538 auto s16 = o2::framework::expressions::createSelection(t16, test16);
1539
1541
1542 REQUIRE(at16.size() == 128);
1543 REQUIRE(fat16.size() == 64);
1544
1545 TableBuilder b32;
1546 auto writer32 = b32.cursor<o2::aod::UnsignedIntTest32>();
1547 for (uint64_t i = 0; i < max32; i += (max32 / 100)) {
1548 writer32(0, i);
1549 }
1550 auto t32 = b32.finalize();
1551 o2::aod::UnsignedIntTest32 at32{{t32}};
1552
1553 uint32_t limit32 = max32 / 2 + 1;
1554 o2::framework::expressions::Filter test32 = o2::aod::test::guint32 < limit32;
1555 auto s32 = o2::framework::expressions::createSelection(t32, test32);
1556
1558
1559 REQUIRE(at32.size() == 128);
1560 REQUIRE(fat32.size() == 64);
1561
1562 TableBuilder b64;
1563 auto writer64 = b64.cursor<o2::aod::UnsignedIntTest64>();
1564 for (uint64_t i = 0; i < max64; i += (max64 / 100)) {
1565 writer64(0, i);
1566 }
1567 auto t64 = b64.finalize();
1568 o2::aod::UnsignedIntTest64 at64{{t64}};
1569
1570 uint64_t limit64 = max64 / 2 + 1;
1571 o2::framework::expressions::Filter test64 = o2::aod::test::guint64 < limit64;
1572 auto s64 = o2::framework::expressions::createSelection(t64, test64);
1573
1575
1576 REQUIRE(at64.size() == 128);
1577 REQUIRE(fat64.size() == 64);
1578}
#define DECLARE_SOA_ARRAY_INDEX_COLUMN(_Name_, _Getter_)
Definition ASoA.h:2800
#define DECLARE_SOA_SLICE_INDEX_COLUMN(_Name_, _Getter_)
Definition ASoA.h:2659
#define DECLARE_SOA_DYNAMIC_COLUMN(_Name_, _Getter_,...)
Definition ASoA.h:3108
#define DECLARE_SOA_SELF_INDEX_COLUMN(_Name_, _Getter_)
Definition ASoA.h:2943
#define DECLARE_SOA_TABLE(_Name_, _Origin_, _Desc_,...)
Definition ASoA.h:3196
#define DECLARE_SOA_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Expression_)
Definition ASoA.h:2514
#define DECLARE_SOA_COLUMN(_Name_, _Getter_, _Type_)
Definition ASoA.h:2440
#define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_)
Definition ASoA.h:2881
#define DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(_Name_, _Getter_)
Definition ASoA.h:3007
#define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_)
Definition ASoA.h:2334
#define DECLARE_SOA_TABLE_VERSIONED(_Name_, _Origin_, _Desc_, _Version_,...)
Definition ASoA.h:3199
#define DECLARE_SOA_INDEX_COLUMN(_Name_, _Getter_)
Definition ASoA.h:2882
#define DECLARE_SOA_BITMAP_COLUMN(_Name_, _Getter_, _Size_)
Definition ASoA.h:2475
#define DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(_Name_, _Getter_)
Definition ASoA.h:3078
std::shared_ptr< arrow::Schema > schema
std::vector< double > sum
int32_t i
uint32_t op
const int16_t bb
Test
Definition Utils.h:55
useful math constants
uint16_t pos
Definition RawData.h:3
uint32_t one
Definition RawData.h:4
uint32_t j
Definition RawData.h:0
benchmark::State & st
StringRef key
std::shared_ptr< T > get(const HistName &histName)
auto persist(std::array< char const *, sizeof...(ARGS)+1 > const &columnNames)
std::shared_ptr< arrow::Table > finalize()
void bindInternalIndicesTo(I const *ptr)
Definition ASoA.h:3690
unfiltered_iterator begin()
Definition ASoA.h:2029
auto select(framework::expressions::Filter const &f) const
Definition ASoA.h:2154
#define CHECK
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLint GLsizei count
Definition glcorearb.h:399
GLuint color
Definition glcorearb.h:1272
GLuint * ids
Definition glcorearb.h:647
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
Definition glcorearb.h:2595
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition glcorearb.h:5034
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLintptr offset
Definition glcorearb.h:660
GLuint segments
Definition glcorearb.h:4946
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
GLboolean r
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLint ref
Definition glcorearb.h:291
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
std::shared_ptr< gandiva::SelectionVector > Selection
Definition Expressions.h:45
gandiva::Selection createSelection(std::shared_ptr< arrow::Table > const &table, Filter const &expression)
Function for creating gandiva selection from our internal filter tree.
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
RuntimeError & error_from_ref(RuntimeErrorRef)
std::string cutString(std::string &&str)
Definition ASoA.cxx:322
auto createFieldsFromColumns(framework::pack< C... >)
Definition ASoA.h:77
constexpr auto join(Ts const &... t)
Definition ASoA.h:3506
std::vector< int64_t > SelectionVector
Definition ASoA.h:444
FIXME: do not use data model tables.
char what[MAX_RUNTIME_ERROR_SIZE]
int64_t lastIndex()
Last index inserted in the table.
bool resetCursor(LifetimeHolder< TableBuilder > builder)
A struct, containing the root of the expression tree.
TEST_CASE("TestMarkers")
Definition test_ASoA.cxx:76
HistogramRegistry foo()
std::vector< int > row