示例#1
0
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.
  }
}