| 49 | } |
| 50 | |
| 51 | Status UnnestPlanNode::InitCollExprs(FragmentState* state) { |
| 52 | DCHECK(containing_subplan_ != nullptr) |
| 53 | << "set_containing_subplan() must have been called"; |
| 54 | const RowDescriptor& row_desc = *containing_subplan_->children_[0]->row_descriptor_; |
| 55 | RETURN_IF_ERROR(ScalarExpr::Create( |
| 56 | tnode_->unnest_node.collection_exprs, row_desc, state, &collection_exprs_)); |
| 57 | DCHECK_GT(collection_exprs_.size(), 0); |
| 58 | |
| 59 | for (ScalarExpr* coll_expr : collection_exprs_) { |
| 60 | DCHECK(coll_expr->IsSlotRef()); |
| 61 | const SlotRef* slot_ref = static_cast<SlotRef*>(coll_expr); |
| 62 | SlotDescriptor* slot_desc = state->desc_tbl().GetSlotDescriptor(slot_ref->slot_id()); |
| 63 | DCHECK(slot_desc != nullptr); |
| 64 | coll_slot_descs_.push_back(slot_desc); |
| 65 | |
| 66 | // If the collection is in a struct we don't use the itemTupleDesc of the struct but |
| 67 | // the tuple in which the top level struct is placed. |
| 68 | const TupleDescriptor* parent_tuple = slot_desc->parent(); |
| 69 | const TupleDescriptor* master_tuple = parent_tuple->getMasterTuple(); |
| 70 | const TupleDescriptor* top_level_tuple = master_tuple == nullptr ? |
| 71 | parent_tuple : master_tuple; |
| 72 | coll_tuple_idxs_.push_back(row_desc.GetTupleIdx(top_level_tuple->id())); |
| 73 | } |
| 74 | return Status::OK(); |
| 75 | } |
| 76 | |
| 77 | Status UnnestPlanNode::CreateExecNode(RuntimeState* state, ExecNode** node) const { |
| 78 | ObjectPool* pool = state->obj_pool(); |
no test coverage detected