MCPcopy Create free account
hub / github.com/apache/arrow / Finalize

Method Finalize

python/pyarrow/src/arrow/python/udf.cc:166–217  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

164 }
165
166 Status Finalize(compute::KernelContext* ctx, Datum* out) override {
167 auto state =
168 arrow::internal::checked_cast<PythonUdfScalarAggregatorImpl*>(ctx->state());
169 const int num_args = input_schema->num_fields();
170
171 // Note: The way that batches are concatenated together
172 // would result in using double amount of the memory.
173 // This is OK for now because non decomposable aggregate
174 // UDF is supposed to be used with segmented aggregation
175 // where the size of the segment is more or less constant
176 // so doubling that is not a big deal. This can be also
177 // improved in the future to use more efficient way to
178 // concatenate.
179 ARROW_ASSIGN_OR_RAISE(auto table,
180 arrow::Table::FromRecordBatches(input_schema, values));
181 ARROW_ASSIGN_OR_RAISE(table, table->CombineChunks(ctx->memory_pool()));
182 UdfContext udf_context{ctx->memory_pool(), table->num_rows()};
183
184 if (table->num_rows() == 0) {
185 return Status::Invalid("Finalized is called with empty inputs");
186 }
187
188 RETURN_NOT_OK(SafeCallIntoPython([&] {
189 std::unique_ptr<OwnedRef> result;
190 OwnedRef arg_tuple(PyTuple_New(num_args));
191 RETURN_NOT_OK(CheckPyError());
192
193 for (int arg_id = 0; arg_id < num_args; arg_id++) {
194 // Since we combined chunks there is only one chunk
195 std::shared_ptr<Array> c_data = table->column(arg_id)->chunk(0);
196 PyObject* data = wrap_array(c_data);
197 PyTuple_SetItem(arg_tuple.obj(), arg_id, data);
198 }
199 result =
200 std::make_unique<OwnedRef>(cb(function->obj(), udf_context, arg_tuple.obj()));
201 RETURN_NOT_OK(CheckPyError());
202 // unwrapping the output for expected output type
203 if (is_scalar(result->obj())) {
204 ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> val, unwrap_scalar(result->obj()));
205 if (*output_type != *val->type) {
206 return Status::TypeError("Expected output datatype ", output_type->ToString(),
207 ", but function returned datatype ",
208 val->type->ToString());
209 }
210 out->value = std::move(val);
211 return Status::OK();
212 }
213 return Status::TypeError("Unexpected output type: ",
214 Py_TYPE(result->obj())->tp_name, " (expected Scalar)");
215 }));
216 return Status::OK();
217 }
218
219 std::shared_ptr<OwnedRefNoGIL> function;
220 UdfWrapperCallback cb;

Callers

nothing calls this directly

Calls 14

SafeCallIntoPythonFunction · 0.85
CheckPyErrorFunction · 0.85
is_scalarFunction · 0.85
CombineChunksMethod · 0.80
ARROW_ASSIGN_OR_RAISEFunction · 0.50
InvalidFunction · 0.50
TypeErrorFunction · 0.50
OKFunction · 0.50
stateMethod · 0.45
num_fieldsMethod · 0.45
memory_poolMethod · 0.45
num_rowsMethod · 0.45

Tested by

no test coverage detected