Может быть, я упускаю что-то очевидное, но, судя по всему, я не могу понять, как я могу получить доступ к элементам массива после операции фильтра Gandiva.
Я привел минимальный пример, который я собираю следующим образом:
$ /usr/lib64/ccache/g++ -g -Wall -m64 -std=c++17 -pthread -fPIC \
-I/opt/data-an/include mwe.cc -o mwe \
-L/opt/data-an/lib64 -lgandiva -larrow
и тогда я запускаю бинарный файл так:
$ LD_LIBRARY_PATH=/opt/data-an/lib64 ./mwe
В общих чертах это то, что я пытался (сопровождаемые выдержками из MWE):
создать 5-элементный вектор: 1, 3, 2, 4, 5
int num_records = 5;
arrow::Int64Builder i64builder;
ArrayPtr array0;
EXPECT_OK(i64builder.AppendValues({1, 3, 2, 4, 5}));
EXPECT_OK(i64builder.Finish(&array0));
используйте Gandiva, чтобы получить четные элементы, индексы: 2, 3
// schema for input fields
auto field0 = field("f0", arrow::int64());
auto schema = arrow::schema({field0});
// even: f0 % 2 == 0
auto field0_node = TreeExprBuilder::MakeField(field0);
auto lit_2 = TreeExprBuilder::MakeLiteral(int64_t(2));
auto remainder = TreeExprBuilder::MakeFunction("mod", {field0_node, lit_2}, int64());
auto lit_0 = TreeExprBuilder::MakeLiteral(int64_t(0));
auto even = TreeExprBuilder::MakeFunction("equal", {remainder, lit_0}, boolean());
auto condition = TreeExprBuilder::MakeCondition(even);
// input record batch
auto in_batch = arrow::RecordBatch::Make(schema, num_records, {array0});
// filter
std::shared_ptr<Filter> filter;
EXPECT_OK(Filter::Make(schema, condition, &filter));
std::shared_ptr<SelectionVector> selected;
EXPECT_OK(SelectionVector::MakeInt16(num_records, pool_, &selected));
EXPECT_OK(filter->Evaluate(*in_batch, selected));
получить доступ к четным элементам в исходном массиве, используя вектор выбора из фильтра Gandiva в качестве индексного массива
// std::cout << "array0[0]: " << array0->Value(0); // doesn't compile
// error: ‘using element_type = class arrow::Array’ {aka ‘class
// arrow::Array’} has no member named ‘Value’
// downcast it to the correct derived class
auto array0_cast = std::dynamic_pointer_cast<NumericArray<Int64Type>>(array0);
std::cout << "array0[0]: " << array0_cast->Value(0) << std::endl;
Но я не могу получить доступ к элементам вектор выбора. Так как это было объявлено как std::shared_ptr<arrow::Array>
, Value(..)
метод не найден. Так как я заполнил его SelectionVector::MakeInt16(..)
Я пытался унизить arrow::NumericArray<Int16Type>
, но это не удается! Я не уверен, где я иду не так.
auto idx_arr_cast = std::dynamic_pointer_cast<NumericArray<Int16Type>>(idx_arr);
if (idx_arr_cast) {
std::cout << "idx_arr[0]: " << idx_arr_cast->Value(0) << std::endl;
} else {
std::cerr << "idx_arr_cast is a nullptr!" << std::endl;
}
У меня также есть связанный, но более общий вопрос. Учитывая массив, я не могу найти способ доступа к элементам (или перебрать их), если я не знаю точный тип. Если я знаю тип, я могу опускать руки, и использовать подобные Value(..)
, GetValue(..)
, GetString(..)
и т. д. Это кажется довольно круглым только для доступа к элементам. Что мне не хватает?
Замечания: Полный MWE вместе с Makefile может быть клонирован из этот смысл.
SelectionVector
хранит индексы, поэтому тип unsigned
, следующие работы:
auto arr = std::dynamic_pointer_cast<NumericArray<UInt16Type>>(selected->ToArray());
Благодаря Равиндре в списке разработчиков Arrow для ответ.
Других решений пока нет …