P::PhysicalPtr ReduceGroupByAttributes::applyInternal(const P::PhysicalPtr &input) { std::vector<P::PhysicalPtr> new_children; for (const P::PhysicalPtr &child : input->children()) { new_children.push_back(applyInternal(child)); } if (new_children != input->children()) { return applyToNode(input->copyWithNewChildren(new_children)); } else { return applyToNode(input); } }
P::PhysicalPtr InjectJoinFilters::transformHashJoinToFilters( const P::PhysicalPtr &input) const { std::vector<P::PhysicalPtr> new_children; for (const P::PhysicalPtr &child : input->children()) { new_children.emplace_back(transformHashJoinToFilters(child)); } P::HashJoinPtr hash_join; if (P::SomeHashJoin::MatchesWithConditionalCast(input, &hash_join) && isTransformable(hash_join)) { const bool is_anti_join = hash_join->join_type() == P::HashJoin::JoinType::kLeftAntiJoin; DCHECK_EQ(2u, new_children.size()); P::PhysicalPtr build_child = new_children[1]; E::PredicatePtr build_side_filter_predicate = nullptr; P::SelectionPtr selection; if (hash_join->build_predicate() == nullptr) { if (P::SomeSelection::MatchesWithConditionalCast(build_child, &selection) && E::SubsetOfExpressions(hash_join->right_join_attributes(), selection->input()->getOutputAttributes())) { build_child = selection->input(); build_side_filter_predicate = selection->filter_predicate(); } } else { build_child = hash_join->right(); build_side_filter_predicate = hash_join->build_predicate(); } return P::FilterJoin::Create(new_children[0], build_child, hash_join->left_join_attributes(), hash_join->right_join_attributes(), hash_join->project_expressions(), build_side_filter_predicate, is_anti_join, hash_join->hasRepartition(), hash_join->cloneOutputPartitionSchemeHeader()); } if (input->children() != new_children) { return input->copyWithNewChildren(new_children); } else { return input; } }
void InjectJoinFilters::concretizeAsLIPFilters( const P::PhysicalPtr &input, const P::PhysicalPtr &anchor_node) const { switch (input->getPhysicalType()) { case P::PhysicalType::kAggregate: { const P::AggregatePtr &aggregate = std::static_pointer_cast<const P::Aggregate>(input); concretizeAsLIPFilters(aggregate->input(), aggregate); break; } case P::PhysicalType::kSelection: { const P::SelectionPtr &selection = std::static_pointer_cast<const P::Selection>(input); concretizeAsLIPFilters(selection->input(), selection); break; } // Currently we disable the attachment of filters to HashJoin nodes. See the // comments in InjectJoinFilters::addFilterAnchors(). /* case P::PhysicalType::kHashJoin: { const P::HashJoinPtr &hash_join = std::static_pointer_cast<const P::HashJoin>(input); concretizeAsLIPFilters(hash_join->left(), hash_join); concretizeAsLIPFilters(hash_join->right(), nullptr); break; } */ case P::PhysicalType::kFilterJoin: { const P::FilterJoinPtr &filter_join = std::static_pointer_cast<const P::FilterJoin>(input); DCHECK_EQ(1u, filter_join->build_attributes().size()); const E::AttributeReferencePtr &build_attr = filter_join->build_attributes().front(); std::int64_t min_cpp_value; std::int64_t max_cpp_value; const bool has_exact_min_max_stats = findExactMinMaxValuesForAttributeHelper(filter_join, build_attr, &min_cpp_value, &max_cpp_value); DCHECK(has_exact_min_max_stats); DCHECK_GE(max_cpp_value, min_cpp_value); DCHECK_LE(max_cpp_value - min_cpp_value, kMaxFilterSize); CHECK(anchor_node != nullptr); lip_filter_configuration_->addBuildInfo( P::BitVectorExactFilterBuildInfo::Create(build_attr, min_cpp_value, max_cpp_value, filter_join->is_anti_join()), filter_join); lip_filter_configuration_->addProbeInfo( P::LIPFilterProbeInfo::Create(filter_join->probe_attributes().front(), build_attr, filter_join), anchor_node); concretizeAsLIPFilters(filter_join->left(), anchor_node); concretizeAsLIPFilters(filter_join->right(), filter_join); break; } default: { for (const P::PhysicalPtr &child : input->children()) { concretizeAsLIPFilters(child, nullptr); } } } }
void PlanVisualizer::visit(const P::PhysicalPtr &input) { int node_id = ++id_counter_; node_id_map_.emplace(input, node_id); std::set<E::ExprId> referenced_ids; for (const auto &attr : input->getReferencedAttributes()) { referenced_ids.emplace(attr->id()); } for (const auto &child : input->children()) { visit(child); int child_id = node_id_map_[child]; edges_.emplace_back(EdgeInfo()); EdgeInfo &edge_info = edges_.back(); edge_info.src_node_id = child_id; edge_info.dst_node_id = node_id; edge_info.dashed = false; if ((input->getPhysicalType() == P::PhysicalType::kHashJoin || input->getPhysicalType() == P::PhysicalType::kFilterJoin) && child == input->children()[1]) { edge_info.dashed = true; } for (const auto &attr : child->getOutputAttributes()) { if (referenced_ids.find(attr->id()) != referenced_ids.end()) { edge_info.labels.emplace_back(attr->attribute_alias()); } } } nodes_.emplace_back(NodeInfo()); NodeInfo &node_info = nodes_.back(); node_info.id = node_id; if (color_map_.find(input->getName()) != color_map_.end()) { node_info.color = color_map_[input->getName()]; } switch (input->getPhysicalType()) { case P::PhysicalType::kTableReference: { const P::TableReferencePtr table_reference = std::static_pointer_cast<const P::TableReference>(input); node_info.labels.emplace_back(table_reference->relation()->getName()); break; } case P::PhysicalType::kHashJoin: { const P::HashJoinPtr hash_join = std::static_pointer_cast<const P::HashJoin>(input); node_info.labels.emplace_back(input->getName()); const auto &left_attributes = hash_join->left_join_attributes(); const auto &right_attributes = hash_join->right_join_attributes(); for (std::size_t i = 0; i < left_attributes.size(); ++i) { node_info.labels.emplace_back( left_attributes[i]->attribute_alias() + " = " + right_attributes[i]->attribute_alias()); } break; } case P::PhysicalType::kFilterJoin: { const P::FilterJoinPtr filter_join = std::static_pointer_cast<const P::FilterJoin>(input); node_info.labels.emplace_back(input->getName()); const auto &probe_attributes = filter_join->probe_attributes(); const auto &build_attributes = filter_join->build_attributes(); for (std::size_t i = 0; i < probe_attributes.size(); ++i) { node_info.labels.emplace_back( probe_attributes[i]->attribute_alias() + " = " + build_attributes[i]->attribute_alias()); } break; } default: { node_info.labels.emplace_back(input->getName()); break; } } const P::PartitionSchemeHeader *partition_scheme_header = input->getOutputPartitionSchemeHeader(); if (partition_scheme_header) { node_info.labels.emplace_back(partition_scheme_header->toString()); } if (lip_filter_conf_ != nullptr) { const auto &build_filters = lip_filter_conf_->getBuildInfoMap(); const auto build_it = build_filters.find(input); if (build_it != build_filters.end()) { for (const auto &build_info : build_it->second) { node_info.labels.emplace_back( std::string("[LIP build] ") + build_info->build_attribute()->attribute_alias()); } } const auto &probe_filters = lip_filter_conf_->getProbeInfoMap(); const auto probe_it = probe_filters.find(input); if (probe_it != probe_filters.end()) { for (const auto &probe_info : probe_it->second) { node_info.labels.emplace_back( std::string("[LIP probe] ") + probe_info->probe_attribute()->attribute_alias()); } } } try { const std::size_t estimated_cardinality = cost_model_->estimateCardinality(input); const double estimated_selectivity = cost_model_->estimateSelectivity(input); node_info.labels.emplace_back( "est. # = " + std::to_string(estimated_cardinality)); node_info.labels.emplace_back( "est. Selectivity = " + std::to_string(estimated_selectivity)); } catch (const std::exception &e) { // NOTE(jianqiao): CostModel::estimateCardinality() may throw UnsupportedPhysicalPlan // exception for some type of physical nodes such as CreateTable. // In this case, we omit the node's cardinality/selectivity information. } }