/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved. miniob is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ // // Created by Wangyunlai on 2022/12/14. // #include "sql/optimizer/physical_plan_generator.h" #include "sql/operator/table_get_logical_operator.h" #include "sql/operator/table_scan_physical_operator.h" #include "sql/operator/index_scan_physical_operator.h" #include "sql/operator/predicate_logical_operator.h" #include "sql/operator/predicate_physical_operator.h" #include "sql/operator/project_logical_operator.h" #include "sql/operator/project_physical_operator.h" #include "sql/operator/delete_logical_operator.h" #include "sql/operator/delete_physical_operator.h" #include "sql/operator/explain_logical_operator.h" #include "sql/operator/explain_physical_operator.h" #include "sql/operator/join_logical_operator.h" #include "sql/operator/join_physical_operator.h" #include "sql/expr/expression.h" #include "common/log/log.h" using namespace std; RC PhysicalPlanGenerator::create(LogicalOperator &logical_operator, std::unique_ptr &oper) { RC rc = RC::SUCCESS; switch (logical_operator.type()) { case LogicalOperatorType::TABLE_GET: { return create_plan(static_cast(logical_operator), oper); } break; case LogicalOperatorType::PREDICATE: { return create_plan(static_cast(logical_operator), oper); } break; case LogicalOperatorType::PROJECTION: { return create_plan(static_cast(logical_operator), oper); } break; case LogicalOperatorType::DELETE: { return create_plan(static_cast(logical_operator), oper); } break; case LogicalOperatorType::EXPLAIN: { return create_plan(static_cast(logical_operator), oper); } break; case LogicalOperatorType::JOIN: { return create_plan(static_cast(logical_operator), oper); } break; default: { return RC::INVALID_ARGUMENT; } } return rc; } RC PhysicalPlanGenerator::create_plan(TableGetLogicalOperator &table_get_oper, std::unique_ptr &oper) { std::vector> &predicates = table_get_oper.predicates(); // 看看是否有可以用于索引查找的表达式 Table *table = table_get_oper.table(); Index *index = nullptr; ValueExpr *value_expr = nullptr; for (auto &expr : predicates) { if (expr->type() == ExprType::COMPARISON) { auto comparison_expr = static_cast(expr.get()); // 简单处理,就找等值查询 if (comparison_expr->comp() != EQUAL_TO) { continue; } std::unique_ptr &left_expr = comparison_expr->left(); std::unique_ptr &right_expr = comparison_expr->right(); // 左右比较的一边最少是一个值 if (left_expr->type() != ExprType::VALUE && right_expr->type() != ExprType::VALUE) { continue; } FieldExpr *field_expr = nullptr; if (left_expr->type() == ExprType::FIELD) { ASSERT(right_expr->type() == ExprType::VALUE, "right expr should be a value expr while left is field expr"); field_expr = static_cast(left_expr.get()); value_expr = static_cast(right_expr.get()); } else if (right_expr->type() == ExprType::FIELD) { ASSERT(left_expr->type() == ExprType::VALUE, "left expr should be a value expr while right is a field expr"); field_expr = static_cast(right_expr.get()); value_expr = static_cast(left_expr.get()); } if (field_expr == nullptr) { continue; } const Field &field = field_expr->field(); index = table->find_index_by_field(field.field_name()); if (nullptr != index) { break; } } } if (index != nullptr) { ASSERT(value_expr != nullptr, "got an index but value expr is null ?"); const TupleCell &tuple_cell = value_expr->get_tuple_cell(); IndexScanPhysicalOperator *index_scan_oper = new IndexScanPhysicalOperator( table, index, &tuple_cell, true /*left_inclusive*/, &tuple_cell, true /*right_inclusive*/); index_scan_oper->set_predicates(std::move(predicates)); oper = std::unique_ptr(index_scan_oper); LOG_TRACE("use index scan"); } else { auto table_scan_oper = new TableScanPhysicalOperator(table); table_scan_oper->set_predicates(std::move(predicates)); oper = std::unique_ptr(table_scan_oper); LOG_TRACE("use table scan"); } return RC::SUCCESS; } RC PhysicalPlanGenerator::create_plan(PredicateLogicalOperator &pred_oper, std::unique_ptr &oper) { std::vector> &children_opers = pred_oper.children(); ASSERT(children_opers.size() == 1, "predicate logical operator's sub oper number should be 1"); LogicalOperator &child_oper = *children_opers.front(); std::unique_ptr child_phy_oper; RC rc = create(child_oper, child_phy_oper); if (rc != RC::SUCCESS) { LOG_WARN("failed to create child operator of predicate operator. rc=%s", strrc(rc)); return rc; } std::vector> &expressions = pred_oper.expressions(); ASSERT(expressions.size() == 1, "predicate logical operator's children should be 1"); std::unique_ptr expression = std::move(expressions.front()); oper = std::unique_ptr(new PredicatePhysicalOperator(std::move(expression))); oper->add_child(std::move(child_phy_oper)); return rc; } RC PhysicalPlanGenerator::create_plan(ProjectLogicalOperator &project_oper, std::unique_ptr &oper) { std::vector> &child_opers = project_oper.children(); std::unique_ptr child_phy_oper; RC rc = RC::SUCCESS; if (!child_opers.empty()) { LogicalOperator *child_oper = child_opers.front().get(); rc = create(*child_oper, child_phy_oper); if (rc != RC::SUCCESS) { LOG_WARN("failed to create project logical operator's child physical operator. rc=%s", strrc(rc)); return rc; } } ProjectPhysicalOperator *project_operator = new ProjectPhysicalOperator; const std::vector &project_fields = project_oper.fields(); for (const Field &field : project_fields) { project_operator->add_projection(field.table(), field.meta()); } if (child_phy_oper) { project_operator->add_child(std::move(child_phy_oper)); } oper = std::unique_ptr(project_operator); LOG_TRACE("create a project physical operator"); return rc; } RC PhysicalPlanGenerator::create_plan(DeleteLogicalOperator &delete_oper, std::unique_ptr &oper) { std::vector> &child_opers = delete_oper.children(); std::unique_ptr child_physical_oper; RC rc = RC::SUCCESS; if (!child_opers.empty()) { LogicalOperator *child_oper = child_opers.front().get(); rc = create(*child_oper, child_physical_oper); if (rc != RC::SUCCESS) { LOG_WARN("failed to create physical operator. rc=%s", strrc(rc)); return rc; } } oper = std::unique_ptr(new DeletePhysicalOperator(delete_oper.table(), nullptr)); if (child_physical_oper) { oper->add_child(move(child_physical_oper)); } return rc; } RC PhysicalPlanGenerator::create_plan(ExplainLogicalOperator &explain_oper, std::unique_ptr &oper) { std::vector> &child_opers = explain_oper.children(); RC rc = RC::SUCCESS; std::unique_ptr explain_physical_oper(new ExplainPhysicalOperator); for (std::unique_ptr &child_oper : child_opers) { std::unique_ptr child_physical_oper; rc = create(*child_oper, child_physical_oper); if (rc != RC::SUCCESS) { LOG_WARN("failed to create child physical operator. rc=%s", strrc(rc)); return rc; } explain_physical_oper->add_child(std::move(child_physical_oper)); } oper = std::move(explain_physical_oper); return rc; } RC PhysicalPlanGenerator::create_plan(JoinLogicalOperator &join_oper, std::unique_ptr &oper) { RC rc = RC::SUCCESS; std::vector> &child_opers = join_oper.children(); if (child_opers.size() != 2) { LOG_WARN("join operator should have 2 children, but have %d", child_opers.size()); return RC::INTERNAL; } std::unique_ptr join_physical_oper(new NestedLoopJoinPhysicalOperator); for (auto &child_oper : child_opers) { std::unique_ptr child_physical_oper; rc = create(*child_oper, child_physical_oper); if (rc != RC::SUCCESS) { LOG_WARN("failed to create physical child oper. rc=%s", strrc(rc)); return rc; } join_physical_oper->add_child(std::move(child_physical_oper)); } oper = std::move(join_physical_oper); return rc; }