Like a UnionNode, an UnpivotNode materializes tuples by evaluating expressions. Unlike a UnionNode, for each input tuple, an UnpivotNode might produce multiple output tuples.
| 136 | // Unlike a UnionNode, for each input tuple, an UnpivotNode might produce multiple |
| 137 | // output tuples. |
| 138 | Status UnpivotNode::GetNext(RuntimeState* state, RowBatch* row_batch, bool* eos) { |
| 139 | SCOPED_TIMER(runtime_profile_->total_time_counter()); |
| 140 | RETURN_IF_CANCELLED(state); |
| 141 | RETURN_IF_ERROR(QueryMaintenance(state)); |
| 142 | const auto& plan_node = static_cast<const UnpivotPlanNode&>(plan_node_); |
| 143 | int64_t tuple_buf_size = -1; |
| 144 | uint8_t* tuple_buf = nullptr; |
| 145 | RETURN_IF_ERROR( |
| 146 | row_batch->ResizeAndAllocateTupleBuffer(state, &tuple_buf_size, &tuple_buf)); |
| 147 | memset(tuple_buf, 0, tuple_buf_size); |
| 148 | auto output_tuple = tuple_buf; |
| 149 | DCHECK_GT(plan_node.num_unpivot_columns_, 0); |
| 150 | // Materializes one row in each iteration if *eos is false. |
| 151 | do { |
| 152 | if (unpivot_slot_idx_ == plan_node.num_unpivot_columns_) { |
| 153 | ++child_row_idx_; |
| 154 | unpivot_slot_idx_ = 0; |
| 155 | } |
| 156 | if (child_row_batch_ == nullptr || child_row_idx_ == child_row_batch_->num_rows()) { |
| 157 | if (child_row_batch_ == nullptr) { |
| 158 | child_row_batch_ = make_unique<RowBatch>( |
| 159 | child(0)->row_desc(), state->batch_size(), mem_tracker()); |
| 160 | } else { |
| 161 | child_row_batch_->Reset(); |
| 162 | } |
| 163 | if (!child_eos_) { |
| 164 | RETURN_IF_ERROR(child(0)->GetNext(state, child_row_batch_.get(), &child_eos_)); |
| 165 | } |
| 166 | child_row_idx_ = 0; |
| 167 | } |
| 168 | *eos = ReachedLimit() |
| 169 | || (child_eos_ && (child_row_idx_ == child_row_batch_->num_rows())); |
| 170 | if (*eos) { |
| 171 | return Status::OK(); |
| 172 | } |
| 173 | if (child_row_batch_->num_rows() == 0) { |
| 174 | continue; |
| 175 | } |
| 176 | MaterializeOutputTuple(reinterpret_cast<Tuple*>(output_tuple), row_batch); |
| 177 | ++unpivot_slot_idx_; |
| 178 | auto output_row = row_batch->GetRow(row_batch->AddRow()); |
| 179 | output_row->SetTuple(0, reinterpret_cast<Tuple*>(output_tuple)); |
| 180 | if (EvalConjuncts(conjunct_evals_.data(), conjunct_evals_.size(), output_row)) { |
| 181 | row_batch->CommitLastRow(); |
| 182 | IncrementNumRowsReturned(1); |
| 183 | output_tuple += plan_node.tuple_desc_->byte_size(); |
| 184 | } |
| 185 | } while (!*eos && !row_batch->AtCapacity()); |
| 186 | return Status::OK(); |
| 187 | } |
| 188 | |
| 189 | Status UnpivotNode::Reset(RuntimeState* state, RowBatch* row_batch) { |
| 190 | if (child_row_batch_ != nullptr) { |
nothing calls this directly
no test coverage detected