| 346 | } |
| 347 | |
| 348 | inline Status AnalyticEvalNode::AddRow(int64_t stream_idx, TupleRow* row) { |
| 349 | if (fn_scope_ != ROWS || !window_.__isset.window_start || |
| 350 | stream_idx - rows_start_offset_ >= curr_partition_idx_) { |
| 351 | VLOG_ROW << id() << " Update idx=" << stream_idx; |
| 352 | AggFnEvaluator::Add(analytic_fn_evals_, row, curr_tuple_); |
| 353 | if (window_.__isset.window_start) { |
| 354 | VLOG_ROW << id() << " Adding tuple to window at idx=" << stream_idx; |
| 355 | Tuple* tuple = row->GetTuple(0)->DeepCopy( |
| 356 | *child(0)->row_desc()->tuple_descriptors()[0], curr_tuple_pool_.get()); |
| 357 | window_tuples_.emplace_back(stream_idx, tuple); |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | Status status; |
| 362 | // Buffer the entire input row to be returned later with the analytic eval results. |
| 363 | if (UNLIKELY(!input_stream_->AddRow(row, &status))) { |
| 364 | // AddRow returns false if an error occurs (available via status()) or there is |
| 365 | // not enough memory (status() is OK). If there isn't enough memory, we unpin |
| 366 | // the stream and continue writing/reading in unpinned mode. |
| 367 | // TODO: Consider re-pinning later if the output stream is fully consumed. |
| 368 | RETURN_IF_ERROR(status); |
| 369 | RETURN_IF_ERROR(state_->StartSpilling(mem_tracker())); |
| 370 | RETURN_IF_ERROR( |
| 371 | input_stream_->UnpinStream(BufferedTupleStream::UNPIN_ALL_EXCEPT_CURRENT)); |
| 372 | VLOG_FILE << id() << " Unpin input stream while adding row idx=" << stream_idx; |
| 373 | if (!input_stream_->AddRow(row, &status)) { |
| 374 | // Rows should be added in unpinned mode unless an error occurs. |
| 375 | RETURN_IF_ERROR(status); |
| 376 | DCHECK(false); |
| 377 | } |
| 378 | } |
| 379 | DCHECK(status.ok()); |
| 380 | return Status::OK(); |
| 381 | } |
| 382 | |
| 383 | Status AnalyticEvalNode::AddResultTuple(int64_t stream_idx) { |
| 384 | VLOG_ROW << id() << " AddResultTuple idx=" << stream_idx; |