| 208 | } |
| 209 | |
| 210 | Status UnionNode::GetNextMaterialized(RuntimeState* state, RowBatch* row_batch) { |
| 211 | // Fetch from children, evaluate corresponding exprs and materialize. |
| 212 | DCHECK(!ReachedLimit()); |
| 213 | DCHECK_LT(child_idx_, children_.size()); |
| 214 | int64_t tuple_buf_size; |
| 215 | uint8_t* tuple_buf; |
| 216 | RETURN_IF_ERROR( |
| 217 | row_batch->ResizeAndAllocateTupleBuffer(state, &tuple_buf_size, &tuple_buf)); |
| 218 | memset(tuple_buf, 0, tuple_buf_size); |
| 219 | |
| 220 | while (HasMoreMaterialized() && !row_batch->AtCapacity()) { |
| 221 | // The loop runs until we are either done iterating over the children that require |
| 222 | // materialization, or the row batch is at capacity. |
| 223 | DCHECK(!IsChildPassthrough(child_idx_)); |
| 224 | // Child row batch was either never set or we're moving on to a different child. |
| 225 | if (child_batch_.get() == nullptr) { |
| 226 | DCHECK_LT(child_idx_, children_.size()); |
| 227 | child_batch_.reset(new RowBatch( |
| 228 | child(child_idx_)->row_desc(), state->batch_size(), mem_tracker())); |
| 229 | child_row_idx_ = 0; |
| 230 | // Open the current child unless it's the first child, which was already opened in |
| 231 | // UnionNode::Open(). |
| 232 | if (child_eos_) RETURN_IF_ERROR(child(child_idx_)->Open(state)); |
| 233 | // The first batch from each child is always fetched here. |
| 234 | RETURN_IF_ERROR(child(child_idx_)->GetNext( |
| 235 | state, child_batch_.get(), &child_eos_)); |
| 236 | } |
| 237 | |
| 238 | while (!row_batch->AtCapacity()) { |
| 239 | DCHECK(child_batch_.get() != nullptr); |
| 240 | DCHECK_LE(child_row_idx_, child_batch_->num_rows()); |
| 241 | if (child_row_idx_ == child_batch_->num_rows()) { |
| 242 | // Move on to the next child if it is at eos. |
| 243 | if (child_eos_) break; |
| 244 | // Fetch more rows from the child. |
| 245 | child_batch_->Reset(); |
| 246 | child_row_idx_ = 0; |
| 247 | // All batches except the first batch from each child are fetched here. |
| 248 | RETURN_IF_ERROR(child(child_idx_)->GetNext( |
| 249 | state, child_batch_.get(), &child_eos_)); |
| 250 | // If we fetched an empty batch, go back to the beginning of this while loop, and |
| 251 | // try again. |
| 252 | if (child_batch_->num_rows() == 0) continue; |
| 253 | } |
| 254 | DCHECK_EQ(codegend_union_materialize_batch_fns_.size(), children_.size()); |
| 255 | UnionPlanNode::UnionMaterializeBatchFn fn = |
| 256 | codegend_union_materialize_batch_fns_[child_idx_].load(); |
| 257 | if (fn == nullptr) { |
| 258 | MaterializeBatch(row_batch, &tuple_buf); |
| 259 | } else { |
| 260 | fn(this, row_batch, &tuple_buf); |
| 261 | } |
| 262 | } |
| 263 | // It shouldn't be the case that we reached the limit because we shouldn't have |
| 264 | // incremented 'num_rows_returned_' yet. |
| 265 | DCHECK(!ReachedLimit()); |
| 266 | |
| 267 | if (child_eos_ && child_row_idx_ == child_batch_->num_rows()) { |
nothing calls this directly
no test coverage detected