From 67a49675cde66dff86fc9bd1b8e542f762cfbf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Mon, 24 Nov 2025 16:35:26 +0800 Subject: [PATCH 01/12] refactor(rewriter): Adjust rewrite files position --- src/observer/sql/optimizer/optimize_stage.h | 2 +- .../{ => rewrite}/comparison_simplification_rule.cpp | 2 +- .../{ => rewrite}/comparison_simplification_rule.h | 2 +- .../{ => rewrite}/conjunction_simplification_rule.cpp | 2 +- .../{ => rewrite}/conjunction_simplification_rule.h | 2 +- .../sql/optimizer/{ => rewrite}/expression_rewriter.cpp | 6 +++--- .../sql/optimizer/{ => rewrite}/expression_rewriter.h | 2 +- .../{ => rewrite}/predicate_pushdown_rewriter.cpp | 2 +- .../optimizer/{ => rewrite}/predicate_pushdown_rewriter.h | 2 +- .../sql/optimizer/{ => rewrite}/predicate_rewrite.cpp | 2 +- .../sql/optimizer/{ => rewrite}/predicate_rewrite.h | 2 +- .../optimizer/{ => rewrite}/predicate_to_join_rule.cpp | 2 +- .../sql/optimizer/{ => rewrite}/predicate_to_join_rule.h | 2 +- src/observer/sql/optimizer/{ => rewrite}/rewrite_rule.h | 0 src/observer/sql/optimizer/{ => rewrite}/rewriter.cpp | 8 ++++---- src/observer/sql/optimizer/{ => rewrite}/rewriter.h | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) rename src/observer/sql/optimizer/{ => rewrite}/comparison_simplification_rule.cpp (94%) rename src/observer/sql/optimizer/{ => rewrite}/comparison_simplification_rule.h (96%) rename src/observer/sql/optimizer/{ => rewrite}/conjunction_simplification_rule.cpp (97%) rename src/observer/sql/optimizer/{ => rewrite}/conjunction_simplification_rule.h (95%) rename src/observer/sql/optimizer/{ => rewrite}/expression_rewriter.cpp (95%) rename src/observer/sql/optimizer/{ => rewrite}/expression_rewriter.h (95%) rename src/observer/sql/optimizer/{ => rewrite}/predicate_pushdown_rewriter.cpp (98%) rename src/observer/sql/optimizer/{ => rewrite}/predicate_pushdown_rewriter.h (96%) rename src/observer/sql/optimizer/{ => rewrite}/predicate_rewrite.cpp (97%) rename src/observer/sql/optimizer/{ => rewrite}/predicate_rewrite.h (95%) rename src/observer/sql/optimizer/{ => rewrite}/predicate_to_join_rule.cpp (90%) rename src/observer/sql/optimizer/{ => rewrite}/predicate_to_join_rule.h (93%) rename src/observer/sql/optimizer/{ => rewrite}/rewrite_rule.h (100%) rename src/observer/sql/optimizer/{ => rewrite}/rewriter.cpp (89%) rename src/observer/sql/optimizer/{ => rewrite}/rewriter.h (96%) diff --git a/src/observer/sql/optimizer/optimize_stage.h b/src/observer/sql/optimizer/optimize_stage.h index 83c0f9739..b1be2ec28 100644 --- a/src/observer/sql/optimizer/optimize_stage.h +++ b/src/observer/sql/optimizer/optimize_stage.h @@ -20,7 +20,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/physical_operator.h" #include "sql/optimizer/logical_plan_generator.h" #include "sql/optimizer/physical_plan_generator.h" -#include "sql/optimizer/rewriter.h" +#include "sql/optimizer/rewrite/rewriter.h" class SQLStageEvent; class LogicalOperator; diff --git a/src/observer/sql/optimizer/comparison_simplification_rule.cpp b/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp similarity index 94% rename from src/observer/sql/optimizer/comparison_simplification_rule.cpp rename to src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp index 99a7655ce..4fad78560 100644 --- a/src/observer/sql/optimizer/comparison_simplification_rule.cpp +++ b/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/13. // -#include "sql/optimizer/comparison_simplification_rule.h" +#include "sql/optimizer/rewrite/comparison_simplification_rule.h" #include "common/log/log.h" #include "sql/expr/expression.h" diff --git a/src/observer/sql/optimizer/comparison_simplification_rule.h b/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h similarity index 96% rename from src/observer/sql/optimizer/comparison_simplification_rule.h rename to src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h index f46e70d6e..6032e38cc 100644 --- a/src/observer/sql/optimizer/comparison_simplification_rule.h +++ b/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h @@ -15,7 +15,7 @@ See the Mulan PSL v2 for more details. */ #pragma once #include "common/sys/rc.h" -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" class LogicalOperator; diff --git a/src/observer/sql/optimizer/conjunction_simplification_rule.cpp b/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp similarity index 97% rename from src/observer/sql/optimizer/conjunction_simplification_rule.cpp rename to src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp index 5ba4e4148..14467fe22 100644 --- a/src/observer/sql/optimizer/conjunction_simplification_rule.cpp +++ b/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/26. // -#include "sql/optimizer/conjunction_simplification_rule.h" +#include "sql/optimizer/rewrite/conjunction_simplification_rule.h" #include "common/log/log.h" #include "sql/expr/expression.h" diff --git a/src/observer/sql/optimizer/conjunction_simplification_rule.h b/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h similarity index 95% rename from src/observer/sql/optimizer/conjunction_simplification_rule.h rename to src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h index c855f0141..952f60c35 100644 --- a/src/observer/sql/optimizer/conjunction_simplification_rule.h +++ b/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h @@ -14,7 +14,7 @@ See the Mulan PSL v2 for more details. */ #pragma once -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" class LogicalOperator; diff --git a/src/observer/sql/optimizer/expression_rewriter.cpp b/src/observer/sql/optimizer/rewrite/expression_rewriter.cpp similarity index 95% rename from src/observer/sql/optimizer/expression_rewriter.cpp rename to src/observer/sql/optimizer/rewrite/expression_rewriter.cpp index b0c6d2455..7aa5829bb 100644 --- a/src/observer/sql/optimizer/expression_rewriter.cpp +++ b/src/observer/sql/optimizer/rewrite/expression_rewriter.cpp @@ -12,10 +12,10 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/13. // -#include "sql/optimizer/expression_rewriter.h" +#include "sql/optimizer/rewrite/expression_rewriter.h" #include "common/log/log.h" -#include "sql/optimizer/comparison_simplification_rule.h" -#include "sql/optimizer/conjunction_simplification_rule.h" +#include "sql/optimizer/rewrite/comparison_simplification_rule.h" +#include "sql/optimizer/rewrite/conjunction_simplification_rule.h" using namespace std; diff --git a/src/observer/sql/optimizer/expression_rewriter.h b/src/observer/sql/optimizer/rewrite/expression_rewriter.h similarity index 95% rename from src/observer/sql/optimizer/expression_rewriter.h rename to src/observer/sql/optimizer/rewrite/expression_rewriter.h index 3376b1db8..023d2531d 100644 --- a/src/observer/sql/optimizer/expression_rewriter.h +++ b/src/observer/sql/optimizer/rewrite/expression_rewriter.h @@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */ #include "common/sys/rc.h" #include "sql/expr/expression.h" #include "sql/operator/logical_operator.h" -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" class ExpressionRewriter : public RewriteRule { diff --git a/src/observer/sql/optimizer/predicate_pushdown_rewriter.cpp b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp similarity index 98% rename from src/observer/sql/optimizer/predicate_pushdown_rewriter.cpp rename to src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp index f67cc551d..2e68feb29 100644 --- a/src/observer/sql/optimizer/predicate_pushdown_rewriter.cpp +++ b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/30. // -#include "sql/optimizer/predicate_pushdown_rewriter.h" +#include "sql/optimizer/rewrite/predicate_pushdown_rewriter.h" #include "common/log/log.h" #include "sql/expr/expression.h" #include "sql/operator/logical_operator.h" diff --git a/src/observer/sql/optimizer/predicate_pushdown_rewriter.h b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h similarity index 96% rename from src/observer/sql/optimizer/predicate_pushdown_rewriter.h rename to src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h index 5fbc4510a..36097482a 100644 --- a/src/observer/sql/optimizer/predicate_pushdown_rewriter.h +++ b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h @@ -15,7 +15,7 @@ See the Mulan PSL v2 for more details. */ #pragma once #include "common/lang/vector.h" -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" /** * @brief 将一些谓词表达式下推到表数据扫描中 diff --git a/src/observer/sql/optimizer/predicate_rewrite.cpp b/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp similarity index 97% rename from src/observer/sql/optimizer/predicate_rewrite.cpp rename to src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp index 7444efd68..a6ac0a3dc 100644 --- a/src/observer/sql/optimizer/predicate_rewrite.cpp +++ b/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/29. // -#include "sql/optimizer/predicate_rewrite.h" +#include "sql/optimizer/rewrite/predicate_rewrite.h" #include "sql/operator/logical_operator.h" RC PredicateRewriteRule::rewrite(unique_ptr &oper, bool &change_made) diff --git a/src/observer/sql/optimizer/predicate_rewrite.h b/src/observer/sql/optimizer/rewrite/predicate_rewrite.h similarity index 95% rename from src/observer/sql/optimizer/predicate_rewrite.h rename to src/observer/sql/optimizer/rewrite/predicate_rewrite.h index 193742dfa..349a712d1 100644 --- a/src/observer/sql/optimizer/predicate_rewrite.h +++ b/src/observer/sql/optimizer/rewrite/predicate_rewrite.h @@ -14,7 +14,7 @@ See the Mulan PSL v2 for more details. */ #pragma once -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" /** * @brief 谓词重写规则 diff --git a/src/observer/sql/optimizer/predicate_to_join_rule.cpp b/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp similarity index 90% rename from src/observer/sql/optimizer/predicate_to_join_rule.cpp rename to src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp index 1dc87abd4..6a8bfca47 100644 --- a/src/observer/sql/optimizer/predicate_to_join_rule.cpp +++ b/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp @@ -8,4 +8,4 @@ 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. */ -#include "sql/optimizer/predicate_to_join_rule.h" +#include "sql/optimizer/rewrite/predicate_to_join_rule.h" diff --git a/src/observer/sql/optimizer/predicate_to_join_rule.h b/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h similarity index 93% rename from src/observer/sql/optimizer/predicate_to_join_rule.h rename to src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h index 4a91f3eb9..a70313657 100644 --- a/src/observer/sql/optimizer/predicate_to_join_rule.h +++ b/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h @@ -11,7 +11,7 @@ See the Mulan PSL v2 for more details. */ #pragma once #include "common/lang/vector.h" -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" /** * @brief 将一些谓词表达式下推到join中 diff --git a/src/observer/sql/optimizer/rewrite_rule.h b/src/observer/sql/optimizer/rewrite/rewrite_rule.h similarity index 100% rename from src/observer/sql/optimizer/rewrite_rule.h rename to src/observer/sql/optimizer/rewrite/rewrite_rule.h diff --git a/src/observer/sql/optimizer/rewriter.cpp b/src/observer/sql/optimizer/rewrite/rewriter.cpp similarity index 89% rename from src/observer/sql/optimizer/rewriter.cpp rename to src/observer/sql/optimizer/rewrite/rewriter.cpp index fcb189b1b..e067f484e 100644 --- a/src/observer/sql/optimizer/rewriter.cpp +++ b/src/observer/sql/optimizer/rewrite/rewriter.cpp @@ -12,12 +12,12 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/29. // -#include "sql/optimizer/rewriter.h" +#include "sql/optimizer/rewrite/rewriter.h" #include "common/log/log.h" #include "sql/operator/logical_operator.h" -#include "sql/optimizer/expression_rewriter.h" -#include "sql/optimizer/predicate_pushdown_rewriter.h" -#include "sql/optimizer/predicate_rewrite.h" +#include "sql/optimizer/rewrite/expression_rewriter.h" +#include "sql/optimizer/rewrite/predicate_pushdown_rewriter.h" +#include "sql/optimizer/rewrite/predicate_rewrite.h" Rewriter::Rewriter() { diff --git a/src/observer/sql/optimizer/rewriter.h b/src/observer/sql/optimizer/rewrite/rewriter.h similarity index 96% rename from src/observer/sql/optimizer/rewriter.h rename to src/observer/sql/optimizer/rewrite/rewriter.h index b54fc71f6..5df11bcb6 100644 --- a/src/observer/sql/optimizer/rewriter.h +++ b/src/observer/sql/optimizer/rewrite/rewriter.h @@ -14,7 +14,7 @@ See the Mulan PSL v2 for more details. */ #pragma once -#include "sql/optimizer/rewrite_rule.h" +#include "sql/optimizer/rewrite/rewrite_rule.h" #include "common/lang/memory.h" #include "common/lang/vector.h" From d668b76e91a2d2d09861c7ae4751d17a2ae387bd Mon Sep 17 00:00:00 2001 From: evtrouble Date: Fri, 22 Aug 2025 10:20:18 +0800 Subject: [PATCH 02/12] refactor(operator): Unify OpType of logical and physical operator --- .../aggregate_vec_physical_operator.h | 2 +- .../sql/operator/calc_logical_operator.h | 1 - .../sql/operator/calc_physical_operator.h | 1 - .../sql/operator/delete_logical_operator.h | 1 - .../sql/operator/delete_physical_operator.h | 2 - .../sql/operator/explain_logical_operator.h | 2 - .../sql/operator/explain_physical_operator.h | 2 - .../sql/operator/expr_vec_physical_operator.h | 2 +- .../sql/operator/group_by_logical_operator.h | 1 - .../operator/group_by_vec_physical_operator.h | 2 +- .../hash_group_by_physical_operator.h | 1 - .../operator/index_scan_physical_operator.h | 2 +- .../sql/operator/insert_logical_operator.h | 2 - .../sql/operator/insert_physical_operator.h | 2 - .../sql/operator/join_logical_operator.h | 1 - .../sql/operator/join_physical_operator.h | 2 +- .../sql/operator/logical_operator.cpp | 8 ++-- src/observer/sql/operator/logical_operator.h | 21 +--------- .../nested_loop_join_physical_operator.h | 2 - src/observer/sql/operator/operator_node.h | 11 ++++-- .../sql/operator/physical_operator.cpp | 38 +++++++++---------- src/observer/sql/operator/physical_operator.h | 29 -------------- .../sql/operator/predicate_logical_operator.h | 2 - .../operator/predicate_physical_operator.h | 1 - .../sql/operator/project_logical_operator.h | 1 - .../sql/operator/project_physical_operator.h | 1 - .../operator/project_vec_physical_operator.h | 2 +- .../scalar_group_by_physical_operator.h | 1 - .../operator/string_list_physical_operator.h | 2 +- .../sql/operator/table_get_logical_operator.h | 2 - .../operator/table_scan_physical_operator.h | 1 - .../table_scan_vec_physical_operator.h | 2 +- .../sql/optimizer/cascade/optimizer.cpp | 4 +- src/observer/sql/optimizer/optimize_stage.cpp | 2 +- .../sql/optimizer/physical_plan_generator.cpp | 32 ++++++++-------- .../rewrite/predicate_pushdown_rewriter.cpp | 4 +- .../optimizer/rewrite/predicate_rewrite.cpp | 2 +- 37 files changed, 61 insertions(+), 133 deletions(-) diff --git a/src/observer/sql/operator/aggregate_vec_physical_operator.h b/src/observer/sql/operator/aggregate_vec_physical_operator.h index 1afab13f2..5ed7b73a8 100644 --- a/src/observer/sql/operator/aggregate_vec_physical_operator.h +++ b/src/observer/sql/operator/aggregate_vec_physical_operator.h @@ -23,7 +23,7 @@ class AggregateVecPhysicalOperator : public PhysicalOperator virtual ~AggregateVecPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::AGGREGATE_VEC; } + OpType get_op_type() const override { return OpType::AGGREGATE_VEC; } RC open(Trx *trx) override; RC next(Chunk &chunk) override; diff --git a/src/observer/sql/operator/calc_logical_operator.h b/src/observer/sql/operator/calc_logical_operator.h index 985dd388d..ab01dd913 100644 --- a/src/observer/sql/operator/calc_logical_operator.h +++ b/src/observer/sql/operator/calc_logical_operator.h @@ -26,6 +26,5 @@ class CalcLogicalOperator : public LogicalOperator CalcLogicalOperator(vector> &&expressions) { expressions_.swap(expressions); } virtual ~CalcLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::CALC; } OpType get_op_type() const override { return OpType::LOGICALCALCULATE; } }; diff --git a/src/observer/sql/operator/calc_physical_operator.h b/src/observer/sql/operator/calc_physical_operator.h index 4b704af80..13ed43ac2 100644 --- a/src/observer/sql/operator/calc_physical_operator.h +++ b/src/observer/sql/operator/calc_physical_operator.h @@ -26,7 +26,6 @@ class CalcPhysicalOperator : public PhysicalOperator virtual ~CalcPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::CALC; } OpType get_op_type() const override { return OpType::CALCULATE; } string name() const override { return "CALC"; } diff --git a/src/observer/sql/operator/delete_logical_operator.h b/src/observer/sql/operator/delete_logical_operator.h index effc305c9..929f19e18 100644 --- a/src/observer/sql/operator/delete_logical_operator.h +++ b/src/observer/sql/operator/delete_logical_operator.h @@ -26,7 +26,6 @@ class DeleteLogicalOperator : public LogicalOperator DeleteLogicalOperator(Table *table); virtual ~DeleteLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::DELETE; } OpType get_op_type() const override { return OpType::LOGICALDELETE; } Table *table() const { return table_; } diff --git a/src/observer/sql/operator/delete_physical_operator.h b/src/observer/sql/operator/delete_physical_operator.h index 241447985..2168ab353 100644 --- a/src/observer/sql/operator/delete_physical_operator.h +++ b/src/observer/sql/operator/delete_physical_operator.h @@ -30,8 +30,6 @@ class DeletePhysicalOperator : public PhysicalOperator virtual ~DeletePhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::DELETE; } - OpType get_op_type() const override { return OpType::DELETE; } RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/explain_logical_operator.h b/src/observer/sql/operator/explain_logical_operator.h index c226f0f9b..3c0b9ce18 100644 --- a/src/observer/sql/operator/explain_logical_operator.h +++ b/src/observer/sql/operator/explain_logical_operator.h @@ -26,7 +26,5 @@ class ExplainLogicalOperator : public LogicalOperator ExplainLogicalOperator() = default; virtual ~ExplainLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::EXPLAIN; } - OpType get_op_type() const override { return OpType::LOGICALEXPLAIN; } }; diff --git a/src/observer/sql/operator/explain_physical_operator.h b/src/observer/sql/operator/explain_physical_operator.h index 10c1b6d7a..0354509ff 100644 --- a/src/observer/sql/operator/explain_physical_operator.h +++ b/src/observer/sql/operator/explain_physical_operator.h @@ -26,8 +26,6 @@ class ExplainPhysicalOperator : public PhysicalOperator ExplainPhysicalOperator() = default; virtual ~ExplainPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::EXPLAIN; } - OpType get_op_type() const override { return OpType::EXPLAIN; } double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override diff --git a/src/observer/sql/operator/expr_vec_physical_operator.h b/src/observer/sql/operator/expr_vec_physical_operator.h index bbd5a9a91..a6a2f6fb6 100644 --- a/src/observer/sql/operator/expr_vec_physical_operator.h +++ b/src/observer/sql/operator/expr_vec_physical_operator.h @@ -23,7 +23,7 @@ class ExprVecPhysicalOperator : public PhysicalOperator virtual ~ExprVecPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::EXPR_VEC; } + OpType get_op_type() const override { return OpType::EXPR_VEC; } RC open(Trx *trx) override; RC next(Chunk &chunk) override; diff --git a/src/observer/sql/operator/group_by_logical_operator.h b/src/observer/sql/operator/group_by_logical_operator.h index 6e533e906..a7cf11c12 100644 --- a/src/observer/sql/operator/group_by_logical_operator.h +++ b/src/observer/sql/operator/group_by_logical_operator.h @@ -23,7 +23,6 @@ class GroupByLogicalOperator : public LogicalOperator virtual ~GroupByLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::GROUP_BY; } OpType get_op_type() const override { return OpType::LOGICALGROUPBY; } auto &group_by_expressions() { return group_by_expressions_; } diff --git a/src/observer/sql/operator/group_by_vec_physical_operator.h b/src/observer/sql/operator/group_by_vec_physical_operator.h index fe00deec7..afcf19ecc 100644 --- a/src/observer/sql/operator/group_by_vec_physical_operator.h +++ b/src/observer/sql/operator/group_by_vec_physical_operator.h @@ -24,7 +24,7 @@ class GroupByVecPhysicalOperator : public PhysicalOperator virtual ~GroupByVecPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::GROUP_BY_VEC; } + OpType get_op_type() const override { return OpType::GROUPBY_VEC; } RC open(Trx *trx) override { return RC::UNIMPLEMENTED; } RC next(Chunk &chunk) override { return RC::UNIMPLEMENTED; } diff --git a/src/observer/sql/operator/hash_group_by_physical_operator.h b/src/observer/sql/operator/hash_group_by_physical_operator.h index 36431d5a9..0c4962da3 100644 --- a/src/observer/sql/operator/hash_group_by_physical_operator.h +++ b/src/observer/sql/operator/hash_group_by_physical_operator.h @@ -31,7 +31,6 @@ class HashGroupByPhysicalOperator : public GroupByPhysicalOperator virtual ~HashGroupByPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::HASH_GROUP_BY; } OpType get_op_type() const override { return OpType::HASHGROUPBY; } RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/index_scan_physical_operator.h b/src/observer/sql/operator/index_scan_physical_operator.h index 405e74716..13e2797ca 100644 --- a/src/observer/sql/operator/index_scan_physical_operator.h +++ b/src/observer/sql/operator/index_scan_physical_operator.h @@ -30,7 +30,7 @@ class IndexScanPhysicalOperator : public PhysicalOperator virtual ~IndexScanPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::INDEX_SCAN; } + OpType get_op_type() const override { return OpType::INDEXSCAN; } string param() const override; diff --git a/src/observer/sql/operator/insert_logical_operator.h b/src/observer/sql/operator/insert_logical_operator.h index 72df40ac5..c9a624e62 100644 --- a/src/observer/sql/operator/insert_logical_operator.h +++ b/src/observer/sql/operator/insert_logical_operator.h @@ -27,8 +27,6 @@ class InsertLogicalOperator : public LogicalOperator InsertLogicalOperator(Table *table, vector values); virtual ~InsertLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::INSERT; } - OpType get_op_type() const override { return OpType::LOGICALINSERT; } Table *table() const { return table_; } diff --git a/src/observer/sql/operator/insert_physical_operator.h b/src/observer/sql/operator/insert_physical_operator.h index 85aedc6e5..f803f0332 100644 --- a/src/observer/sql/operator/insert_physical_operator.h +++ b/src/observer/sql/operator/insert_physical_operator.h @@ -30,8 +30,6 @@ class InsertPhysicalOperator : public PhysicalOperator virtual ~InsertPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::INSERT; } - OpType get_op_type() const override { return OpType::INSERT; } RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/join_logical_operator.h b/src/observer/sql/operator/join_logical_operator.h index deec7bcd8..2da7dd351 100644 --- a/src/observer/sql/operator/join_logical_operator.h +++ b/src/observer/sql/operator/join_logical_operator.h @@ -27,7 +27,6 @@ class JoinLogicalOperator : public LogicalOperator JoinLogicalOperator() = default; virtual ~JoinLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::JOIN; } void add_predicate_op(LogicalOperator *predicate_op) { predicate_op_ = predicate_op; } auto predicates() -> Expression * { diff --git a/src/observer/sql/operator/join_physical_operator.h b/src/observer/sql/operator/join_physical_operator.h index 930d5f194..f3dae560c 100644 --- a/src/observer/sql/operator/join_physical_operator.h +++ b/src/observer/sql/operator/join_physical_operator.h @@ -28,7 +28,7 @@ class NestedLoopJoinPhysicalOperator : public PhysicalOperator NestedLoopJoinPhysicalOperator(); virtual ~NestedLoopJoinPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::NESTED_LOOP_JOIN; } + OpType get_op_type() const override { return OpType::INNERNLJOIN; } RC open(Trx *trx) override; RC next() override; diff --git a/src/observer/sql/operator/logical_operator.cpp b/src/observer/sql/operator/logical_operator.cpp index a2fb251db..4f6c4bc6c 100644 --- a/src/observer/sql/operator/logical_operator.cpp +++ b/src/observer/sql/operator/logical_operator.cpp @@ -20,14 +20,14 @@ void LogicalOperator::add_child(unique_ptr oper) { children_.emplace_back(std::move(oper)); } void LogicalOperator::add_expressions(unique_ptr expr) { expressions_.emplace_back(std::move(expr)); } -bool LogicalOperator::can_generate_vectorized_operator(const LogicalOperatorType &type) +bool LogicalOperator::can_generate_vectorized_operator(const OpType &type) { bool bool_ret = false; switch (type) { - case LogicalOperatorType::CALC: - case LogicalOperatorType::DELETE: - case LogicalOperatorType::INSERT: + case OpType::LOGICALCALCULATE: + case OpType::LOGICALDELETE: + case OpType::LOGICALINSERT: bool_ret = false; break; diff --git a/src/observer/sql/operator/logical_operator.h b/src/observer/sql/operator/logical_operator.h index d212dbcc2..cd3afed88 100644 --- a/src/observer/sql/operator/logical_operator.h +++ b/src/observer/sql/operator/logical_operator.h @@ -25,23 +25,6 @@ See the Mulan PSL v2 for more details. */ * 物理算子会描述怎么做某件事情,这是与其不同的地方。 */ -/** - * @brief 逻辑算子类型 - * - */ -enum class LogicalOperatorType -{ - CALC, - TABLE_GET, ///< 从表中获取数据 - PREDICATE, ///< 过滤,就是谓词 - PROJECTION, ///< 投影,就是select - JOIN, ///< 连接 - INSERT, ///< 插入 - DELETE, ///< 删除,删除可能会有子查询 - EXPLAIN, ///< 查看执行计划 - GROUP_BY, ///< 分组 -}; - /** * @brief 逻辑算子描述当前执行计划要做什么 * @details 可以看OptimizeStage中相关的代码 @@ -52,8 +35,6 @@ class LogicalOperator : public OperatorNode LogicalOperator() = default; virtual ~LogicalOperator(); - virtual LogicalOperatorType type() const = 0; - bool is_physical() const override { return false; } bool is_logical() const override { return true; } @@ -61,7 +42,7 @@ class LogicalOperator : public OperatorNode void add_expressions(unique_ptr expr); auto children() -> vector> &{ return children_; } auto expressions() -> vector> &{ return expressions_; } - static bool can_generate_vectorized_operator(const LogicalOperatorType &type); + static bool can_generate_vectorized_operator(const OpType &type); // TODO: used by cascade optimizer, tmp function, need to be remove void generate_general_child(); diff --git a/src/observer/sql/operator/nested_loop_join_physical_operator.h b/src/observer/sql/operator/nested_loop_join_physical_operator.h index 80b455975..9b4d1b257 100644 --- a/src/observer/sql/operator/nested_loop_join_physical_operator.h +++ b/src/observer/sql/operator/nested_loop_join_physical_operator.h @@ -28,8 +28,6 @@ class NestedLoopJoinPhysicalOperator : public PhysicalOperator NestedLoopJoinPhysicalOperator(); virtual ~NestedLoopJoinPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::NESTED_LOOP_JOIN; } - OpType get_op_type() const override { return OpType::INNERNLJOIN; } virtual double calculate_cost( diff --git a/src/observer/sql/operator/operator_node.h b/src/observer/sql/operator/operator_node.h index f349f4b00..68c5e8e00 100644 --- a/src/observer/sql/operator/operator_node.h +++ b/src/observer/sql/operator/operator_node.h @@ -59,7 +59,13 @@ enum class OpType HASHGROUPBY, ANALYZE, FILTER, - SCALARGROUPBY + SCALARGROUPBY, + STRINGLIST, + AGGREGATE_VEC, + EXPR_VEC, + GROUPBY_VEC, + PROJECTION_VEC, + SEQSCAN_VEC }; // TODO: OperatorNode is the abstrace class of logical/physical operator @@ -74,9 +80,6 @@ class OperatorNode */ // virtual std::string get_name() const = 0; - /** - * TODO: unify logical and physical OpType - */ virtual OpType get_op_type() const { return OpType::UNDEFINED; } /** diff --git a/src/observer/sql/operator/physical_operator.cpp b/src/observer/sql/operator/physical_operator.cpp index 7ff99d67c..1aad0044c 100644 --- a/src/observer/sql/operator/physical_operator.cpp +++ b/src/observer/sql/operator/physical_operator.cpp @@ -14,30 +14,30 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/physical_operator.h" -string physical_operator_type_name(PhysicalOperatorType type) +string physical_operator_type_name(OpType type) { switch (type) { - case PhysicalOperatorType::TABLE_SCAN: return "TABLE_SCAN"; - case PhysicalOperatorType::INDEX_SCAN: return "INDEX_SCAN"; - case PhysicalOperatorType::NESTED_LOOP_JOIN: return "NESTED_LOOP_JOIN"; - case PhysicalOperatorType::HASH_JOIN: return "HASH_JOIN"; - case PhysicalOperatorType::EXPLAIN: return "EXPLAIN"; - case PhysicalOperatorType::PREDICATE: return "PREDICATE"; - case PhysicalOperatorType::INSERT: return "INSERT"; - case PhysicalOperatorType::DELETE: return "DELETE"; - case PhysicalOperatorType::PROJECT: return "PROJECT"; - case PhysicalOperatorType::STRING_LIST: return "STRING_LIST"; - case PhysicalOperatorType::HASH_GROUP_BY: return "HASH_GROUP_BY"; - case PhysicalOperatorType::SCALAR_GROUP_BY: return "SCALAR_GROUP_BY"; - case PhysicalOperatorType::AGGREGATE_VEC: return "AGGREGATE_VEC"; - case PhysicalOperatorType::GROUP_BY_VEC: return "GROUP_BY_VEC"; - case PhysicalOperatorType::PROJECT_VEC: return "PROJECT_VEC"; - case PhysicalOperatorType::TABLE_SCAN_VEC: return "TABLE_SCAN_VEC"; - case PhysicalOperatorType::EXPR_VEC: return "EXPR_VEC"; + case OpType::SEQSCAN: return "TABLE_SCAN"; + case OpType::INDEXSCAN: return "INDEX_SCAN"; + case OpType::INNERNLJOIN: return "NESTED_LOOP_JOIN"; + case OpType::INNERHASHJOIN: return "HASH_JOIN"; + case OpType::EXPLAIN: return "EXPLAIN"; + case OpType::FILTER: return "PREDICATE"; + case OpType::INSERT: return "INSERT"; + case OpType::DELETE: return "DELETE"; + case OpType::PROJECTION: return "PROJECT"; + case OpType::STRINGLIST: return "STRING_LIST"; + case OpType::HASHGROUPBY: return "HASH_GROUP_BY"; + case OpType::SCALARGROUPBY: return "SCALAR_GROUP_BY"; + case OpType::AGGREGATE_VEC: return "AGGREGATE_VEC"; + case OpType::GROUPBY_VEC: return "GROUP_BY_VEC"; + case OpType::PROJECTION_VEC: return "PROJECT_VEC"; + case OpType::SEQSCAN_VEC: return "TABLE_SCAN_VEC"; + case OpType::EXPR_VEC: return "EXPR_VEC"; default: return "UNKNOWN"; } } -string PhysicalOperator::name() const { return physical_operator_type_name(type()); } +string PhysicalOperator::name() const { return physical_operator_type_name(get_op_type()); } string PhysicalOperator::param() const { return ""; } diff --git a/src/observer/sql/operator/physical_operator.h b/src/observer/sql/operator/physical_operator.h index 8f2b67ba1..8e5756836 100644 --- a/src/observer/sql/operator/physical_operator.h +++ b/src/observer/sql/operator/physical_operator.h @@ -28,33 +28,6 @@ class Trx; * @details 物理算子描述执行计划将如何执行,比如从表中怎么获取数据,如何做投影,怎么做连接等 */ -/** - * @brief 物理算子类型 - * @ingroup PhysicalOperator - */ -enum class PhysicalOperatorType -{ - TABLE_SCAN, - TABLE_SCAN_VEC, - INDEX_SCAN, - NESTED_LOOP_JOIN, - HASH_JOIN, - EXPLAIN, - PREDICATE, - PREDICATE_VEC, - PROJECT, - PROJECT_VEC, - CALC, - STRING_LIST, - DELETE, - INSERT, - SCALAR_GROUP_BY, - HASH_GROUP_BY, - GROUP_BY_VEC, - AGGREGATE_VEC, - EXPR_VEC, -}; - /** * @brief 与LogicalOperator对应,物理算子描述执行计划将如何执行 * @ingroup PhysicalOperator @@ -75,8 +48,6 @@ class PhysicalOperator : public OperatorNode bool is_physical() const override { return true; } bool is_logical() const override { return false; } - virtual PhysicalOperatorType type() const = 0; - virtual RC open(Trx *trx) = 0; virtual RC next() { return RC::UNIMPLEMENTED; } virtual RC next(Chunk &chunk) { return RC::UNIMPLEMENTED; } diff --git a/src/observer/sql/operator/predicate_logical_operator.h b/src/observer/sql/operator/predicate_logical_operator.h index 115121ff9..13b94f61e 100644 --- a/src/observer/sql/operator/predicate_logical_operator.h +++ b/src/observer/sql/operator/predicate_logical_operator.h @@ -27,7 +27,5 @@ class PredicateLogicalOperator : public LogicalOperator PredicateLogicalOperator(unique_ptr expression); virtual ~PredicateLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::PREDICATE; } - OpType get_op_type() const override { return OpType::LOGICALFILTER; } }; diff --git a/src/observer/sql/operator/predicate_physical_operator.h b/src/observer/sql/operator/predicate_physical_operator.h index 49bbcbfbd..9ad0fe061 100644 --- a/src/observer/sql/operator/predicate_physical_operator.h +++ b/src/observer/sql/operator/predicate_physical_operator.h @@ -30,7 +30,6 @@ class PredicatePhysicalOperator : public PhysicalOperator virtual ~PredicatePhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::PREDICATE; } OpType get_op_type() const override { return OpType::FILTER; } RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/project_logical_operator.h b/src/observer/sql/operator/project_logical_operator.h index 6522ac3c1..da3a9de6d 100644 --- a/src/observer/sql/operator/project_logical_operator.h +++ b/src/observer/sql/operator/project_logical_operator.h @@ -29,7 +29,6 @@ class ProjectLogicalOperator : public LogicalOperator ProjectLogicalOperator(vector> &&expressions); virtual ~ProjectLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::PROJECTION; } OpType get_op_type() const override { return OpType::LOGICALPROJECTION; } unique_ptr find_log_prop(const vector &log_props) override; diff --git a/src/observer/sql/operator/project_physical_operator.h b/src/observer/sql/operator/project_physical_operator.h index 781e4ee11..a2ad906e8 100644 --- a/src/observer/sql/operator/project_physical_operator.h +++ b/src/observer/sql/operator/project_physical_operator.h @@ -28,7 +28,6 @@ class ProjectPhysicalOperator : public PhysicalOperator virtual ~ProjectPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::PROJECT; } OpType get_op_type() const override { return OpType::PROJECTION; } virtual double calculate_cost( diff --git a/src/observer/sql/operator/project_vec_physical_operator.h b/src/observer/sql/operator/project_vec_physical_operator.h index de3f716f6..2d68b7901 100644 --- a/src/observer/sql/operator/project_vec_physical_operator.h +++ b/src/observer/sql/operator/project_vec_physical_operator.h @@ -25,7 +25,7 @@ class ProjectVecPhysicalOperator : public PhysicalOperator virtual ~ProjectVecPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::PROJECT_VEC; } + OpType get_op_type() const override { return OpType::PROJECTION_VEC; } RC open(Trx *trx) override; RC next(Chunk &chunk) override; diff --git a/src/observer/sql/operator/scalar_group_by_physical_operator.h b/src/observer/sql/operator/scalar_group_by_physical_operator.h index d55d3c507..8ad543b58 100644 --- a/src/observer/sql/operator/scalar_group_by_physical_operator.h +++ b/src/observer/sql/operator/scalar_group_by_physical_operator.h @@ -26,7 +26,6 @@ class ScalarGroupByPhysicalOperator : public GroupByPhysicalOperator ScalarGroupByPhysicalOperator(vector &&expressions); virtual ~ScalarGroupByPhysicalOperator() = default; - PhysicalOperatorType type() const override { return PhysicalOperatorType::SCALAR_GROUP_BY; } OpType get_op_type() const override { return OpType::SCALARGROUPBY; } RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/string_list_physical_operator.h b/src/observer/sql/operator/string_list_physical_operator.h index 038aa0bea..09466be1e 100644 --- a/src/observer/sql/operator/string_list_physical_operator.h +++ b/src/observer/sql/operator/string_list_physical_operator.h @@ -43,7 +43,7 @@ class StringListPhysicalOperator : public PhysicalOperator strings_.emplace_back(1, v); } - PhysicalOperatorType type() const override { return PhysicalOperatorType::STRING_LIST; } + OpType get_op_type() const override { return OpType::STRINGLIST; } RC open(Trx *) override { return RC::SUCCESS; } diff --git a/src/observer/sql/operator/table_get_logical_operator.h b/src/observer/sql/operator/table_get_logical_operator.h index a95c25337..3dca6f69b 100644 --- a/src/observer/sql/operator/table_get_logical_operator.h +++ b/src/observer/sql/operator/table_get_logical_operator.h @@ -28,8 +28,6 @@ class TableGetLogicalOperator : public LogicalOperator TableGetLogicalOperator(Table *table, ReadWriteMode mode); virtual ~TableGetLogicalOperator() = default; - LogicalOperatorType type() const override { return LogicalOperatorType::TABLE_GET; } - OpType get_op_type() const override { return OpType::LOGICALGET; } virtual uint64_t hash() const override diff --git a/src/observer/sql/operator/table_scan_physical_operator.h b/src/observer/sql/operator/table_scan_physical_operator.h index d62e8e483..5211e2d24 100644 --- a/src/observer/sql/operator/table_scan_physical_operator.h +++ b/src/observer/sql/operator/table_scan_physical_operator.h @@ -35,7 +35,6 @@ class TableScanPhysicalOperator : public PhysicalOperator string param() const override; - PhysicalOperatorType type() const override { return PhysicalOperatorType::TABLE_SCAN; } OpType get_op_type() const override { return OpType::SEQSCAN; } virtual uint64_t hash() const override { diff --git a/src/observer/sql/operator/table_scan_vec_physical_operator.h b/src/observer/sql/operator/table_scan_vec_physical_operator.h index 8982055dd..14cc15063 100644 --- a/src/observer/sql/operator/table_scan_vec_physical_operator.h +++ b/src/observer/sql/operator/table_scan_vec_physical_operator.h @@ -30,7 +30,7 @@ class TableScanVecPhysicalOperator : public PhysicalOperator string param() const override; - PhysicalOperatorType type() const override { return PhysicalOperatorType::TABLE_SCAN_VEC; } + OpType get_op_type() const override { return OpType::SEQSCAN_VEC; } RC open(Trx *trx) override; RC next(Chunk &chunk) override; diff --git a/src/observer/sql/optimizer/cascade/optimizer.cpp b/src/observer/sql/optimizer/cascade/optimizer.cpp index dd6b26a68..26dca33ac 100644 --- a/src/observer/sql/optimizer/cascade/optimizer.cpp +++ b/src/observer/sql/optimizer/cascade/optimizer.cpp @@ -42,8 +42,8 @@ std::unique_ptr Optimizer::choose_best_plan(int root_group_id) } auto winner_contents = winner->get_op(); context_->get_memo().release_operator(winner_contents); - PhysicalOperator* winner_phys = dynamic_cast(winner_contents); - LOG_TRACE("winner: %d", winner_phys->type()); + PhysicalOperator* winner_phys = static_cast(winner_contents); + LOG_TRACE("winner: %d", winner_phys->get_op_type()); for (const auto& child : winner->get_child_group_ids()) { winner_phys->add_child(choose_best_plan(child)); } diff --git a/src/observer/sql/optimizer/optimize_stage.cpp b/src/observer/sql/optimizer/optimize_stage.cpp index a0560541f..e838a9ad6 100644 --- a/src/observer/sql/optimizer/optimize_stage.cpp +++ b/src/observer/sql/optimizer/optimize_stage.cpp @@ -89,7 +89,7 @@ RC OptimizeStage::generate_physical_plan( unique_ptr &logical_operator, unique_ptr &physical_operator, Session *session) { RC rc = RC::SUCCESS; - if (session->get_execution_mode() == ExecutionMode::CHUNK_ITERATOR && LogicalOperator::can_generate_vectorized_operator(logical_operator->type())) { + if (session->get_execution_mode() == ExecutionMode::CHUNK_ITERATOR && LogicalOperator::can_generate_vectorized_operator(logical_operator->get_op_type())) { LOG_TRACE("use chunk iterator"); session->set_used_chunk_mode(true); rc = physical_plan_generator_.create_vec(*logical_operator, physical_operator, session); diff --git a/src/observer/sql/optimizer/physical_plan_generator.cpp b/src/observer/sql/optimizer/physical_plan_generator.cpp index 4ce64a24b..02f0a4c9e 100644 --- a/src/observer/sql/optimizer/physical_plan_generator.cpp +++ b/src/observer/sql/optimizer/physical_plan_generator.cpp @@ -50,40 +50,40 @@ RC PhysicalPlanGenerator::create(LogicalOperator &logical_operator, unique_ptr

(logical_operator), oper, session); } break; - case LogicalOperatorType::TABLE_GET: { + case OpType::LOGICALGET: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::PREDICATE: { + case OpType::LOGICALFILTER: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::PROJECTION: { + case OpType::LOGICALPROJECTION: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::INSERT: { + case OpType::LOGICALINSERT: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::DELETE: { + case OpType::LOGICALDELETE: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::EXPLAIN: { + case OpType::LOGICALEXPLAIN: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::JOIN: { + case OpType::LOGICALINNERJOIN: { return create_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::GROUP_BY: { + case OpType::LOGICALGROUPBY: { return create_plan(static_cast(logical_operator), oper, session); } break; @@ -99,21 +99,21 @@ RC PhysicalPlanGenerator::create_vec(LogicalOperator &logical_operator, unique_p { RC rc = RC::SUCCESS; - switch (logical_operator.type()) { - case LogicalOperatorType::TABLE_GET: { + switch (logical_operator.get_op_type()) { + case OpType::LOGICALGET: { return create_vec_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::PROJECTION: { + case OpType::LOGICALPROJECTION: { return create_vec_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::GROUP_BY: { + case OpType::LOGICALGROUPBY: { return create_vec_plan(static_cast(logical_operator), oper, session); } break; - case LogicalOperatorType::EXPLAIN: { + case OpType::LOGICALEXPLAIN: { return create_vec_plan(static_cast(logical_operator), oper, session); } break; default: { - LOG_WARN("unknown logical operator type: %d", logical_operator.type()); + LOG_WARN("unknown logical operator type: %d", logical_operator.get_op_type()); return RC::INVALID_ARGUMENT; } } diff --git a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp index 2e68feb29..eee834acb 100644 --- a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp +++ b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp @@ -21,7 +21,7 @@ See the Mulan PSL v2 for more details. */ RC PredicatePushdownRewriter::rewrite(unique_ptr &oper, bool &change_made) { RC rc = RC::SUCCESS; - if (oper->type() != LogicalOperatorType::PREDICATE) { + if (oper->get_op_type() != OpType::LOGICALFILTER) { return rc; } @@ -30,7 +30,7 @@ RC PredicatePushdownRewriter::rewrite(unique_ptr &oper, bool &c } unique_ptr &child_oper = oper->children().front(); - if (child_oper->type() != LogicalOperatorType::TABLE_GET) { + if (child_oper->get_op_type() != OpType::LOGICALGET) { return rc; } diff --git a/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp b/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp index a6ac0a3dc..987eaa0b2 100644 --- a/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp +++ b/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp @@ -23,7 +23,7 @@ RC PredicateRewriteRule::rewrite(unique_ptr &oper, bool &change } auto &child_oper = child_opers.front(); - if (child_oper->type() != LogicalOperatorType::PREDICATE) { + if (child_oper->get_op_type() != OpType::LOGICALFILTER) { return RC::SUCCESS; } From b56ac16fa651e3b42cb66007165a04bc6d2257e2 Mon Sep 17 00:00:00 2001 From: evtrouble Date: Fri, 22 Aug 2025 17:06:30 +0800 Subject: [PATCH 03/12] refactor(operator): Adjust operator files position --- src/observer/net/mysql_communicator.cpp | 2 +- .../sql/executor/desc_table_executor.cpp | 2 +- src/observer/sql/executor/execute_stage.cpp | 2 +- src/observer/sql/executor/help_executor.h | 2 +- .../sql/executor/show_tables_executor.h | 2 +- .../{ => logical}/calc_logical_operator.h | 0 .../{ => logical}/delete_logical_operator.cpp | 2 +- .../{ => logical}/delete_logical_operator.h | 0 .../{ => logical}/explain_logical_operator.h | 0 .../group_by_logical_operator.cpp | 2 +- .../{ => logical}/group_by_logical_operator.h | 0 .../{ => logical}/insert_logical_operator.cpp | 2 +- .../{ => logical}/insert_logical_operator.h | 0 .../{ => logical}/join_logical_operator.h | 0 .../predicate_logical_operator.cpp | 2 +- .../predicate_logical_operator.h | 0 .../project_logical_operator.cpp | 2 +- .../{ => logical}/project_logical_operator.h | 0 .../table_get_logical_operator.cpp | 2 +- .../table_get_logical_operator.h | 0 .../aggregate_vec_physical_operator.cpp | 2 +- .../aggregate_vec_physical_operator.h | 0 .../{ => physical}/calc_physical_operator.h | 0 .../delete_physical_operator.cpp | 2 +- .../{ => physical}/delete_physical_operator.h | 0 .../explain_physical_operator.cpp | 2 +- .../explain_physical_operator.h | 0 .../expr_vec_physical_operator.cpp | 2 +- .../expr_vec_physical_operator.h | 0 .../group_by_physical_operator.cpp | 2 +- .../group_by_physical_operator.h | 0 .../group_by_vec_physical_operator.cpp | 2 +- .../group_by_vec_physical_operator.h | 0 .../hash_group_by_physical_operator.cpp | 2 +- .../hash_group_by_physical_operator.h | 2 +- .../hash_join_physical_operator.cpp | 2 +- .../hash_join_physical_operator.h | 0 .../index_scan_physical_operator.cpp | 2 +- .../index_scan_physical_operator.h | 0 .../insert_physical_operator.cpp | 2 +- .../{ => physical}/insert_physical_operator.h | 0 .../{ => physical}/join_physical_operator.cpp | 2 +- .../{ => physical}/join_physical_operator.h | 0 .../nested_loop_join_physical_operator.cpp | 2 +- .../nested_loop_join_physical_operator.h | 0 .../predicate_physical_operator.cpp | 2 +- .../predicate_physical_operator.h | 0 .../project_physical_operator.cpp | 2 +- .../project_physical_operator.h | 0 .../project_vec_physical_operator.cpp | 2 +- .../project_vec_physical_operator.h | 0 .../scalar_group_by_physical_operator.cpp | 2 +- .../scalar_group_by_physical_operator.h | 2 +- .../string_list_physical_operator.h | 0 .../table_scan_physical_operator.cpp | 2 +- .../table_scan_physical_operator.h | 0 .../table_scan_vec_physical_operator.cpp | 2 +- .../table_scan_vec_physical_operator.h | 0 .../cascade/implementation_rules.cpp | 34 ++++++------ .../sql/optimizer/logical_plan_generator.cpp | 18 +++---- .../sql/optimizer/physical_plan_generator.cpp | 54 +++++++++---------- .../rewrite/predicate_pushdown_rewriter.cpp | 2 +- 62 files changed, 85 insertions(+), 85 deletions(-) rename src/observer/sql/operator/{ => logical}/calc_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/delete_logical_operator.cpp (91%) rename src/observer/sql/operator/{ => logical}/delete_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/explain_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/group_by_logical_operator.cpp (94%) rename src/observer/sql/operator/{ => logical}/group_by_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/insert_logical_operator.cpp (92%) rename src/observer/sql/operator/{ => logical}/insert_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/join_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/predicate_logical_operator.cpp (92%) rename src/observer/sql/operator/{ => logical}/predicate_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/project_logical_operator.cpp (94%) rename src/observer/sql/operator/{ => logical}/project_logical_operator.h (100%) rename src/observer/sql/operator/{ => logical}/table_get_logical_operator.cpp (95%) rename src/observer/sql/operator/{ => logical}/table_get_logical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/aggregate_vec_physical_operator.cpp (98%) rename src/observer/sql/operator/{ => physical}/aggregate_vec_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/calc_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/delete_physical_operator.cpp (96%) rename src/observer/sql/operator/{ => physical}/delete_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/explain_physical_operator.cpp (96%) rename src/observer/sql/operator/{ => physical}/explain_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/expr_vec_physical_operator.cpp (96%) rename src/observer/sql/operator/{ => physical}/expr_vec_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/group_by_physical_operator.cpp (98%) rename src/observer/sql/operator/{ => physical}/group_by_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/group_by_vec_physical_operator.cpp (89%) rename src/observer/sql/operator/{ => physical}/group_by_vec_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/hash_group_by_physical_operator.cpp (98%) rename src/observer/sql/operator/{ => physical}/hash_group_by_physical_operator.h (97%) rename src/observer/sql/operator/{ => physical}/hash_join_physical_operator.cpp (89%) rename src/observer/sql/operator/{ => physical}/hash_join_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/index_scan_physical_operator.cpp (98%) rename src/observer/sql/operator/{ => physical}/index_scan_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/insert_physical_operator.cpp (95%) rename src/observer/sql/operator/{ => physical}/insert_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/join_physical_operator.cpp (98%) rename src/observer/sql/operator/{ => physical}/join_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/nested_loop_join_physical_operator.cpp (97%) rename src/observer/sql/operator/{ => physical}/nested_loop_join_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/predicate_physical_operator.cpp (96%) rename src/observer/sql/operator/{ => physical}/predicate_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/project_physical_operator.cpp (96%) rename src/observer/sql/operator/{ => physical}/project_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/project_vec_physical_operator.cpp (96%) rename src/observer/sql/operator/{ => physical}/project_vec_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/scalar_group_by_physical_operator.cpp (97%) rename src/observer/sql/operator/{ => physical}/scalar_group_by_physical_operator.h (95%) rename src/observer/sql/operator/{ => physical}/string_list_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/table_scan_physical_operator.cpp (97%) rename src/observer/sql/operator/{ => physical}/table_scan_physical_operator.h (100%) rename src/observer/sql/operator/{ => physical}/table_scan_vec_physical_operator.cpp (97%) rename src/observer/sql/operator/{ => physical}/table_scan_vec_physical_operator.h (100%) diff --git a/src/observer/net/mysql_communicator.cpp b/src/observer/net/mysql_communicator.cpp index d543f3a52..4e1f77c55 100644 --- a/src/observer/net/mysql_communicator.cpp +++ b/src/observer/net/mysql_communicator.cpp @@ -20,7 +20,7 @@ See the Mulan PSL v2 for more details. */ #include "session/session.h" #include "net/buffered_writer.h" #include "net/mysql_communicator.h" -#include "sql/operator/string_list_physical_operator.h" +#include "sql/operator/physical/string_list_physical_operator.h" /** * @brief MySQL协议相关实现 diff --git a/src/observer/sql/executor/desc_table_executor.cpp b/src/observer/sql/executor/desc_table_executor.cpp index ea993fa51..783c9a59e 100644 --- a/src/observer/sql/executor/desc_table_executor.cpp +++ b/src/observer/sql/executor/desc_table_executor.cpp @@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */ #include "event/session_event.h" #include "event/sql_event.h" #include "session/session.h" -#include "sql/operator/string_list_physical_operator.h" +#include "sql/operator/physical/string_list_physical_operator.h" #include "sql/stmt/desc_table_stmt.h" #include "storage/db/db.h" #include "storage/table/table.h" diff --git a/src/observer/sql/executor/execute_stage.cpp b/src/observer/sql/executor/execute_stage.cpp index f4354b32f..e9ee2d28c 100644 --- a/src/observer/sql/executor/execute_stage.cpp +++ b/src/observer/sql/executor/execute_stage.cpp @@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */ #include "event/session_event.h" #include "event/sql_event.h" #include "sql/executor/command_executor.h" -#include "sql/operator/calc_physical_operator.h" +#include "sql/operator/physical/calc_physical_operator.h" #include "sql/stmt/select_stmt.h" #include "sql/stmt/stmt.h" #include "storage/default/default_handler.h" diff --git a/src/observer/sql/executor/help_executor.h b/src/observer/sql/executor/help_executor.h index c5946aa9b..bcd50e42a 100644 --- a/src/observer/sql/executor/help_executor.h +++ b/src/observer/sql/executor/help_executor.h @@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */ #include "event/session_event.h" #include "event/sql_event.h" #include "sql/executor/sql_result.h" -#include "sql/operator/string_list_physical_operator.h" +#include "sql/operator/physical/string_list_physical_operator.h" /** * @brief Help语句执行器 diff --git a/src/observer/sql/executor/show_tables_executor.h b/src/observer/sql/executor/show_tables_executor.h index 0b6acf6ca..d476aa4c3 100644 --- a/src/observer/sql/executor/show_tables_executor.h +++ b/src/observer/sql/executor/show_tables_executor.h @@ -19,7 +19,7 @@ See the Mulan PSL v2 for more details. */ #include "event/sql_event.h" #include "session/session.h" #include "sql/executor/sql_result.h" -#include "sql/operator/string_list_physical_operator.h" +#include "sql/operator/physical/string_list_physical_operator.h" #include "storage/db/db.h" /** diff --git a/src/observer/sql/operator/calc_logical_operator.h b/src/observer/sql/operator/logical/calc_logical_operator.h similarity index 100% rename from src/observer/sql/operator/calc_logical_operator.h rename to src/observer/sql/operator/logical/calc_logical_operator.h diff --git a/src/observer/sql/operator/delete_logical_operator.cpp b/src/observer/sql/operator/logical/delete_logical_operator.cpp similarity index 91% rename from src/observer/sql/operator/delete_logical_operator.cpp rename to src/observer/sql/operator/logical/delete_logical_operator.cpp index 5fc03f34e..3ade9bdbc 100644 --- a/src/observer/sql/operator/delete_logical_operator.cpp +++ b/src/observer/sql/operator/logical/delete_logical_operator.cpp @@ -12,6 +12,6 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/12/26. // -#include "sql/operator/delete_logical_operator.h" +#include "sql/operator/logical/delete_logical_operator.h" DeleteLogicalOperator::DeleteLogicalOperator(Table *table) : table_(table) {} diff --git a/src/observer/sql/operator/delete_logical_operator.h b/src/observer/sql/operator/logical/delete_logical_operator.h similarity index 100% rename from src/observer/sql/operator/delete_logical_operator.h rename to src/observer/sql/operator/logical/delete_logical_operator.h diff --git a/src/observer/sql/operator/explain_logical_operator.h b/src/observer/sql/operator/logical/explain_logical_operator.h similarity index 100% rename from src/observer/sql/operator/explain_logical_operator.h rename to src/observer/sql/operator/logical/explain_logical_operator.h diff --git a/src/observer/sql/operator/group_by_logical_operator.cpp b/src/observer/sql/operator/logical/group_by_logical_operator.cpp similarity index 94% rename from src/observer/sql/operator/group_by_logical_operator.cpp rename to src/observer/sql/operator/logical/group_by_logical_operator.cpp index 5d86d847c..725853b69 100644 --- a/src/observer/sql/operator/group_by_logical_operator.cpp +++ b/src/observer/sql/operator/logical/group_by_logical_operator.cpp @@ -13,7 +13,7 @@ See the Mulan PSL v2 for more details. */ // #include "common/log/log.h" -#include "sql/operator/group_by_logical_operator.h" +#include "sql/operator/logical/group_by_logical_operator.h" #include "sql/expr/expression.h" using namespace std; diff --git a/src/observer/sql/operator/group_by_logical_operator.h b/src/observer/sql/operator/logical/group_by_logical_operator.h similarity index 100% rename from src/observer/sql/operator/group_by_logical_operator.h rename to src/observer/sql/operator/logical/group_by_logical_operator.h diff --git a/src/observer/sql/operator/insert_logical_operator.cpp b/src/observer/sql/operator/logical/insert_logical_operator.cpp similarity index 92% rename from src/observer/sql/operator/insert_logical_operator.cpp rename to src/observer/sql/operator/logical/insert_logical_operator.cpp index 51ad27a2e..10ca981cc 100644 --- a/src/observer/sql/operator/insert_logical_operator.cpp +++ b/src/observer/sql/operator/logical/insert_logical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2023/4/25. // -#include "sql/operator/insert_logical_operator.h" +#include "sql/operator/logical/insert_logical_operator.h" InsertLogicalOperator::InsertLogicalOperator(Table *table, vector values) : table_(table), values_(values) {} diff --git a/src/observer/sql/operator/insert_logical_operator.h b/src/observer/sql/operator/logical/insert_logical_operator.h similarity index 100% rename from src/observer/sql/operator/insert_logical_operator.h rename to src/observer/sql/operator/logical/insert_logical_operator.h diff --git a/src/observer/sql/operator/join_logical_operator.h b/src/observer/sql/operator/logical/join_logical_operator.h similarity index 100% rename from src/observer/sql/operator/join_logical_operator.h rename to src/observer/sql/operator/logical/join_logical_operator.h diff --git a/src/observer/sql/operator/predicate_logical_operator.cpp b/src/observer/sql/operator/logical/predicate_logical_operator.cpp similarity index 92% rename from src/observer/sql/operator/predicate_logical_operator.cpp rename to src/observer/sql/operator/logical/predicate_logical_operator.cpp index e7db87c77..e8ab44062 100644 --- a/src/observer/sql/operator/predicate_logical_operator.cpp +++ b/src/observer/sql/operator/logical/predicate_logical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/13. // -#include "sql/operator/predicate_logical_operator.h" +#include "sql/operator/logical/predicate_logical_operator.h" PredicateLogicalOperator::PredicateLogicalOperator(unique_ptr expression) { diff --git a/src/observer/sql/operator/predicate_logical_operator.h b/src/observer/sql/operator/logical/predicate_logical_operator.h similarity index 100% rename from src/observer/sql/operator/predicate_logical_operator.h rename to src/observer/sql/operator/logical/predicate_logical_operator.h diff --git a/src/observer/sql/operator/project_logical_operator.cpp b/src/observer/sql/operator/logical/project_logical_operator.cpp similarity index 94% rename from src/observer/sql/operator/project_logical_operator.cpp rename to src/observer/sql/operator/logical/project_logical_operator.cpp index bbd06d1be..91803dcc9 100644 --- a/src/observer/sql/operator/project_logical_operator.cpp +++ b/src/observer/sql/operator/logical/project_logical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/15 // -#include "sql/operator/project_logical_operator.h" +#include "sql/operator/logical/project_logical_operator.h" using namespace std; diff --git a/src/observer/sql/operator/project_logical_operator.h b/src/observer/sql/operator/logical/project_logical_operator.h similarity index 100% rename from src/observer/sql/operator/project_logical_operator.h rename to src/observer/sql/operator/logical/project_logical_operator.h diff --git a/src/observer/sql/operator/table_get_logical_operator.cpp b/src/observer/sql/operator/logical/table_get_logical_operator.cpp similarity index 95% rename from src/observer/sql/operator/table_get_logical_operator.cpp rename to src/observer/sql/operator/logical/table_get_logical_operator.cpp index 9917062b0..508ef822b 100644 --- a/src/observer/sql/operator/table_get_logical_operator.cpp +++ b/src/observer/sql/operator/logical/table_get_logical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/12/15 // -#include "sql/operator/table_get_logical_operator.h" +#include "sql/operator/logical/table_get_logical_operator.h" #include "sql/optimizer/cascade/property.h" #include "catalog/catalog.h" diff --git a/src/observer/sql/operator/table_get_logical_operator.h b/src/observer/sql/operator/logical/table_get_logical_operator.h similarity index 100% rename from src/observer/sql/operator/table_get_logical_operator.h rename to src/observer/sql/operator/logical/table_get_logical_operator.h diff --git a/src/observer/sql/operator/aggregate_vec_physical_operator.cpp b/src/observer/sql/operator/physical/aggregate_vec_physical_operator.cpp similarity index 98% rename from src/observer/sql/operator/aggregate_vec_physical_operator.cpp rename to src/observer/sql/operator/physical/aggregate_vec_physical_operator.cpp index cace563a4..c861b470c 100644 --- a/src/observer/sql/operator/aggregate_vec_physical_operator.cpp +++ b/src/observer/sql/operator/physical/aggregate_vec_physical_operator.cpp @@ -10,7 +10,7 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include "common/lang/ranges.h" -#include "sql/operator/aggregate_vec_physical_operator.h" +#include "sql/operator/physical/aggregate_vec_physical_operator.h" #include "sql/expr/aggregate_state.h" #include "sql/expr/expression_tuple.h" #include "sql/expr/composite_tuple.h" diff --git a/src/observer/sql/operator/aggregate_vec_physical_operator.h b/src/observer/sql/operator/physical/aggregate_vec_physical_operator.h similarity index 100% rename from src/observer/sql/operator/aggregate_vec_physical_operator.h rename to src/observer/sql/operator/physical/aggregate_vec_physical_operator.h diff --git a/src/observer/sql/operator/calc_physical_operator.h b/src/observer/sql/operator/physical/calc_physical_operator.h similarity index 100% rename from src/observer/sql/operator/calc_physical_operator.h rename to src/observer/sql/operator/physical/calc_physical_operator.h diff --git a/src/observer/sql/operator/delete_physical_operator.cpp b/src/observer/sql/operator/physical/delete_physical_operator.cpp similarity index 96% rename from src/observer/sql/operator/delete_physical_operator.cpp rename to src/observer/sql/operator/physical/delete_physical_operator.cpp index ea239a9b0..cd0d5ed47 100644 --- a/src/observer/sql/operator/delete_physical_operator.cpp +++ b/src/observer/sql/operator/physical/delete_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/6/27. // -#include "sql/operator/delete_physical_operator.h" +#include "sql/operator/physical/delete_physical_operator.h" #include "common/log/log.h" #include "storage/table/table.h" #include "storage/trx/trx.h" diff --git a/src/observer/sql/operator/delete_physical_operator.h b/src/observer/sql/operator/physical/delete_physical_operator.h similarity index 100% rename from src/observer/sql/operator/delete_physical_operator.h rename to src/observer/sql/operator/physical/delete_physical_operator.h diff --git a/src/observer/sql/operator/explain_physical_operator.cpp b/src/observer/sql/operator/physical/explain_physical_operator.cpp similarity index 96% rename from src/observer/sql/operator/explain_physical_operator.cpp rename to src/observer/sql/operator/physical/explain_physical_operator.cpp index 1ff2933a3..a7171d980 100644 --- a/src/observer/sql/operator/explain_physical_operator.cpp +++ b/src/observer/sql/operator/physical/explain_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/12/27. // -#include "sql/operator/explain_physical_operator.h" +#include "sql/operator/physical/explain_physical_operator.h" #include "sql/optimizer/optimizer_utils.h" #include "common/log/log.h" diff --git a/src/observer/sql/operator/explain_physical_operator.h b/src/observer/sql/operator/physical/explain_physical_operator.h similarity index 100% rename from src/observer/sql/operator/explain_physical_operator.h rename to src/observer/sql/operator/physical/explain_physical_operator.h diff --git a/src/observer/sql/operator/expr_vec_physical_operator.cpp b/src/observer/sql/operator/physical/expr_vec_physical_operator.cpp similarity index 96% rename from src/observer/sql/operator/expr_vec_physical_operator.cpp rename to src/observer/sql/operator/physical/expr_vec_physical_operator.cpp index 64a3a99bb..ed9e29040 100644 --- a/src/observer/sql/operator/expr_vec_physical_operator.cpp +++ b/src/observer/sql/operator/physical/expr_vec_physical_operator.cpp @@ -9,7 +9,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ #include "common/log/log.h" -#include "sql/operator/expr_vec_physical_operator.h" +#include "sql/operator/physical/expr_vec_physical_operator.h" #include "sql/expr/expression_tuple.h" #include "sql/expr/composite_tuple.h" diff --git a/src/observer/sql/operator/expr_vec_physical_operator.h b/src/observer/sql/operator/physical/expr_vec_physical_operator.h similarity index 100% rename from src/observer/sql/operator/expr_vec_physical_operator.h rename to src/observer/sql/operator/physical/expr_vec_physical_operator.h diff --git a/src/observer/sql/operator/group_by_physical_operator.cpp b/src/observer/sql/operator/physical/group_by_physical_operator.cpp similarity index 98% rename from src/observer/sql/operator/group_by_physical_operator.cpp rename to src/observer/sql/operator/physical/group_by_physical_operator.cpp index 75301f2b6..fc1d85ab2 100644 --- a/src/observer/sql/operator/group_by_physical_operator.cpp +++ b/src/observer/sql/operator/physical/group_by_physical_operator.cpp @@ -14,7 +14,7 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include "common/lang/ranges.h" -#include "sql/operator/group_by_physical_operator.h" +#include "sql/operator/physical/group_by_physical_operator.h" #include "sql/expr/expression_tuple.h" #include "sql/expr/composite_tuple.h" diff --git a/src/observer/sql/operator/group_by_physical_operator.h b/src/observer/sql/operator/physical/group_by_physical_operator.h similarity index 100% rename from src/observer/sql/operator/group_by_physical_operator.h rename to src/observer/sql/operator/physical/group_by_physical_operator.h diff --git a/src/observer/sql/operator/group_by_vec_physical_operator.cpp b/src/observer/sql/operator/physical/group_by_vec_physical_operator.cpp similarity index 89% rename from src/observer/sql/operator/group_by_vec_physical_operator.cpp rename to src/observer/sql/operator/physical/group_by_vec_physical_operator.cpp index 726035899..a5da4dd79 100644 --- a/src/observer/sql/operator/group_by_vec_physical_operator.cpp +++ b/src/observer/sql/operator/physical/group_by_vec_physical_operator.cpp @@ -8,4 +8,4 @@ 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. */ -#include "sql/operator/group_by_vec_physical_operator.h" \ No newline at end of file +#include "sql/operator/physical/group_by_vec_physical_operator.h" \ No newline at end of file diff --git a/src/observer/sql/operator/group_by_vec_physical_operator.h b/src/observer/sql/operator/physical/group_by_vec_physical_operator.h similarity index 100% rename from src/observer/sql/operator/group_by_vec_physical_operator.h rename to src/observer/sql/operator/physical/group_by_vec_physical_operator.h diff --git a/src/observer/sql/operator/hash_group_by_physical_operator.cpp b/src/observer/sql/operator/physical/hash_group_by_physical_operator.cpp similarity index 98% rename from src/observer/sql/operator/hash_group_by_physical_operator.cpp rename to src/observer/sql/operator/physical/hash_group_by_physical_operator.cpp index f408c0ec9..1a9521abb 100644 --- a/src/observer/sql/operator/hash_group_by_physical_operator.cpp +++ b/src/observer/sql/operator/physical/hash_group_by_physical_operator.cpp @@ -13,7 +13,7 @@ See the Mulan PSL v2 for more details. */ // #include "common/log/log.h" -#include "sql/operator/hash_group_by_physical_operator.h" +#include "sql/operator/physical/hash_group_by_physical_operator.h" #include "sql/expr/expression_tuple.h" #include "sql/expr/composite_tuple.h" diff --git a/src/observer/sql/operator/hash_group_by_physical_operator.h b/src/observer/sql/operator/physical/hash_group_by_physical_operator.h similarity index 97% rename from src/observer/sql/operator/hash_group_by_physical_operator.h rename to src/observer/sql/operator/physical/hash_group_by_physical_operator.h index 0c4962da3..eefd55d82 100644 --- a/src/observer/sql/operator/hash_group_by_physical_operator.h +++ b/src/observer/sql/operator/physical/hash_group_by_physical_operator.h @@ -14,7 +14,7 @@ See the Mulan PSL v2 for more details. */ #pragma once -#include "sql/operator/group_by_physical_operator.h" +#include "sql/operator/physical/group_by_physical_operator.h" #include "sql/expr/composite_tuple.h" /** diff --git a/src/observer/sql/operator/hash_join_physical_operator.cpp b/src/observer/sql/operator/physical/hash_join_physical_operator.cpp similarity index 89% rename from src/observer/sql/operator/hash_join_physical_operator.cpp rename to src/observer/sql/operator/physical/hash_join_physical_operator.cpp index f80d09c37..52cdace15 100644 --- a/src/observer/sql/operator/hash_join_physical_operator.cpp +++ b/src/observer/sql/operator/physical/hash_join_physical_operator.cpp @@ -8,4 +8,4 @@ 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. */ -#include "sql/operator/hash_join_physical_operator.h" +#include "sql/operator/physical/hash_join_physical_operator.h" diff --git a/src/observer/sql/operator/hash_join_physical_operator.h b/src/observer/sql/operator/physical/hash_join_physical_operator.h similarity index 100% rename from src/observer/sql/operator/hash_join_physical_operator.h rename to src/observer/sql/operator/physical/hash_join_physical_operator.h diff --git a/src/observer/sql/operator/index_scan_physical_operator.cpp b/src/observer/sql/operator/physical/index_scan_physical_operator.cpp similarity index 98% rename from src/observer/sql/operator/index_scan_physical_operator.cpp rename to src/observer/sql/operator/physical/index_scan_physical_operator.cpp index 01cf7eb79..61d581f13 100644 --- a/src/observer/sql/operator/index_scan_physical_operator.cpp +++ b/src/observer/sql/operator/physical/index_scan_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/07/08. // -#include "sql/operator/index_scan_physical_operator.h" +#include "sql/operator/physical/index_scan_physical_operator.h" #include "storage/index/index.h" #include "storage/trx/trx.h" diff --git a/src/observer/sql/operator/index_scan_physical_operator.h b/src/observer/sql/operator/physical/index_scan_physical_operator.h similarity index 100% rename from src/observer/sql/operator/index_scan_physical_operator.h rename to src/observer/sql/operator/physical/index_scan_physical_operator.h diff --git a/src/observer/sql/operator/insert_physical_operator.cpp b/src/observer/sql/operator/physical/insert_physical_operator.cpp similarity index 95% rename from src/observer/sql/operator/insert_physical_operator.cpp rename to src/observer/sql/operator/physical/insert_physical_operator.cpp index fd1bc9085..50fe29d43 100644 --- a/src/observer/sql/operator/insert_physical_operator.cpp +++ b/src/observer/sql/operator/physical/insert_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2021/6/9. // -#include "sql/operator/insert_physical_operator.h" +#include "sql/operator/physical/insert_physical_operator.h" #include "sql/stmt/insert_stmt.h" #include "storage/table/table.h" #include "storage/trx/trx.h" diff --git a/src/observer/sql/operator/insert_physical_operator.h b/src/observer/sql/operator/physical/insert_physical_operator.h similarity index 100% rename from src/observer/sql/operator/insert_physical_operator.h rename to src/observer/sql/operator/physical/insert_physical_operator.h diff --git a/src/observer/sql/operator/join_physical_operator.cpp b/src/observer/sql/operator/physical/join_physical_operator.cpp similarity index 98% rename from src/observer/sql/operator/join_physical_operator.cpp rename to src/observer/sql/operator/physical/join_physical_operator.cpp index 0de387301..7c274528c 100644 --- a/src/observer/sql/operator/join_physical_operator.cpp +++ b/src/observer/sql/operator/physical/join_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/12/30. // -#include "sql/operator/join_physical_operator.h" +#include "sql/operator/physical/join_physical_operator.h" NestedLoopJoinPhysicalOperator::NestedLoopJoinPhysicalOperator() {} diff --git a/src/observer/sql/operator/join_physical_operator.h b/src/observer/sql/operator/physical/join_physical_operator.h similarity index 100% rename from src/observer/sql/operator/join_physical_operator.h rename to src/observer/sql/operator/physical/join_physical_operator.h diff --git a/src/observer/sql/operator/nested_loop_join_physical_operator.cpp b/src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp similarity index 97% rename from src/observer/sql/operator/nested_loop_join_physical_operator.cpp rename to src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp index 5228d23fd..836a185a5 100644 --- a/src/observer/sql/operator/nested_loop_join_physical_operator.cpp +++ b/src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/12/30. // -#include "sql/operator/nested_loop_join_physical_operator.h" +#include "sql/operator/physical/nested_loop_join_physical_operator.h" NestedLoopJoinPhysicalOperator::NestedLoopJoinPhysicalOperator() {} diff --git a/src/observer/sql/operator/nested_loop_join_physical_operator.h b/src/observer/sql/operator/physical/nested_loop_join_physical_operator.h similarity index 100% rename from src/observer/sql/operator/nested_loop_join_physical_operator.h rename to src/observer/sql/operator/physical/nested_loop_join_physical_operator.h diff --git a/src/observer/sql/operator/predicate_physical_operator.cpp b/src/observer/sql/operator/physical/predicate_physical_operator.cpp similarity index 96% rename from src/observer/sql/operator/predicate_physical_operator.cpp rename to src/observer/sql/operator/physical/predicate_physical_operator.cpp index 61b564451..a6f9bacdd 100644 --- a/src/observer/sql/operator/predicate_physical_operator.cpp +++ b/src/observer/sql/operator/physical/predicate_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/6/27. // -#include "sql/operator/predicate_physical_operator.h" +#include "sql/operator/physical/predicate_physical_operator.h" #include "common/log/log.h" #include "sql/stmt/filter_stmt.h" #include "storage/field/field.h" diff --git a/src/observer/sql/operator/predicate_physical_operator.h b/src/observer/sql/operator/physical/predicate_physical_operator.h similarity index 100% rename from src/observer/sql/operator/predicate_physical_operator.h rename to src/observer/sql/operator/physical/predicate_physical_operator.h diff --git a/src/observer/sql/operator/project_physical_operator.cpp b/src/observer/sql/operator/physical/project_physical_operator.cpp similarity index 96% rename from src/observer/sql/operator/project_physical_operator.cpp rename to src/observer/sql/operator/physical/project_physical_operator.cpp index 9c06125b6..a5bb86d20 100644 --- a/src/observer/sql/operator/project_physical_operator.cpp +++ b/src/observer/sql/operator/physical/project_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2022/07/01. // -#include "sql/operator/project_physical_operator.h" +#include "sql/operator/physical/project_physical_operator.h" #include "common/log/log.h" #include "storage/record/record.h" #include "storage/table/table.h" diff --git a/src/observer/sql/operator/project_physical_operator.h b/src/observer/sql/operator/physical/project_physical_operator.h similarity index 100% rename from src/observer/sql/operator/project_physical_operator.h rename to src/observer/sql/operator/physical/project_physical_operator.h diff --git a/src/observer/sql/operator/project_vec_physical_operator.cpp b/src/observer/sql/operator/physical/project_vec_physical_operator.cpp similarity index 96% rename from src/observer/sql/operator/project_vec_physical_operator.cpp rename to src/observer/sql/operator/physical/project_vec_physical_operator.cpp index 06a487cfb..dc8a23b3d 100644 --- a/src/observer/sql/operator/project_vec_physical_operator.cpp +++ b/src/observer/sql/operator/physical/project_vec_physical_operator.cpp @@ -8,7 +8,7 @@ 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. */ -#include "sql/operator/project_vec_physical_operator.h" +#include "sql/operator/physical/project_vec_physical_operator.h" #include "common/log/log.h" #include "storage/record/record.h" #include "storage/table/table.h" diff --git a/src/observer/sql/operator/project_vec_physical_operator.h b/src/observer/sql/operator/physical/project_vec_physical_operator.h similarity index 100% rename from src/observer/sql/operator/project_vec_physical_operator.h rename to src/observer/sql/operator/physical/project_vec_physical_operator.h diff --git a/src/observer/sql/operator/scalar_group_by_physical_operator.cpp b/src/observer/sql/operator/physical/scalar_group_by_physical_operator.cpp similarity index 97% rename from src/observer/sql/operator/scalar_group_by_physical_operator.cpp rename to src/observer/sql/operator/physical/scalar_group_by_physical_operator.cpp index d07546dbe..48a7f9f54 100644 --- a/src/observer/sql/operator/scalar_group_by_physical_operator.cpp +++ b/src/observer/sql/operator/physical/scalar_group_by_physical_operator.cpp @@ -13,7 +13,7 @@ See the Mulan PSL v2 for more details. */ // #include "common/log/log.h" -#include "sql/operator/scalar_group_by_physical_operator.h" +#include "sql/operator/physical/scalar_group_by_physical_operator.h" #include "sql/expr/expression_tuple.h" #include "sql/expr/composite_tuple.h" diff --git a/src/observer/sql/operator/scalar_group_by_physical_operator.h b/src/observer/sql/operator/physical/scalar_group_by_physical_operator.h similarity index 95% rename from src/observer/sql/operator/scalar_group_by_physical_operator.h rename to src/observer/sql/operator/physical/scalar_group_by_physical_operator.h index 8ad543b58..6b5ab323a 100644 --- a/src/observer/sql/operator/scalar_group_by_physical_operator.h +++ b/src/observer/sql/operator/physical/scalar_group_by_physical_operator.h @@ -14,7 +14,7 @@ See the Mulan PSL v2 for more details. */ #pragma once -#include "sql/operator/group_by_physical_operator.h" +#include "sql/operator/physical/group_by_physical_operator.h" /** * @brief 没有 group by 表达式的 group by 物理算子 diff --git a/src/observer/sql/operator/string_list_physical_operator.h b/src/observer/sql/operator/physical/string_list_physical_operator.h similarity index 100% rename from src/observer/sql/operator/string_list_physical_operator.h rename to src/observer/sql/operator/physical/string_list_physical_operator.h diff --git a/src/observer/sql/operator/table_scan_physical_operator.cpp b/src/observer/sql/operator/physical/table_scan_physical_operator.cpp similarity index 97% rename from src/observer/sql/operator/table_scan_physical_operator.cpp rename to src/observer/sql/operator/physical/table_scan_physical_operator.cpp index 895966e23..a09b4ede1 100644 --- a/src/observer/sql/operator/table_scan_physical_operator.cpp +++ b/src/observer/sql/operator/physical/table_scan_physical_operator.cpp @@ -12,7 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by WangYunlai on 2021/6/9. // -#include "sql/operator/table_scan_physical_operator.h" +#include "sql/operator/physical/table_scan_physical_operator.h" #include "event/sql_debug.h" #include "storage/table/table.h" diff --git a/src/observer/sql/operator/table_scan_physical_operator.h b/src/observer/sql/operator/physical/table_scan_physical_operator.h similarity index 100% rename from src/observer/sql/operator/table_scan_physical_operator.h rename to src/observer/sql/operator/physical/table_scan_physical_operator.h diff --git a/src/observer/sql/operator/table_scan_vec_physical_operator.cpp b/src/observer/sql/operator/physical/table_scan_vec_physical_operator.cpp similarity index 97% rename from src/observer/sql/operator/table_scan_vec_physical_operator.cpp rename to src/observer/sql/operator/physical/table_scan_vec_physical_operator.cpp index 9744776cd..5427ef4a7 100644 --- a/src/observer/sql/operator/table_scan_vec_physical_operator.cpp +++ b/src/observer/sql/operator/physical/table_scan_vec_physical_operator.cpp @@ -8,7 +8,7 @@ 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. */ -#include "sql/operator/table_scan_vec_physical_operator.h" +#include "sql/operator/physical/table_scan_vec_physical_operator.h" #include "event/sql_debug.h" #include "storage/table/table.h" diff --git a/src/observer/sql/operator/table_scan_vec_physical_operator.h b/src/observer/sql/operator/physical/table_scan_vec_physical_operator.h similarity index 100% rename from src/observer/sql/operator/table_scan_vec_physical_operator.h rename to src/observer/sql/operator/physical/table_scan_vec_physical_operator.h diff --git a/src/observer/sql/optimizer/cascade/implementation_rules.cpp b/src/observer/sql/optimizer/cascade/implementation_rules.cpp index 740f44381..c74fe3058 100644 --- a/src/observer/sql/optimizer/cascade/implementation_rules.cpp +++ b/src/observer/sql/optimizer/cascade/implementation_rules.cpp @@ -10,23 +10,23 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include "sql/optimizer/cascade/implementation_rules.h" -#include "sql/operator/table_get_logical_operator.h" -#include "sql/operator/table_scan_physical_operator.h" -#include "sql/operator/project_logical_operator.h" -#include "sql/operator/project_physical_operator.h" -#include "sql/operator/insert_logical_operator.h" -#include "sql/operator/insert_physical_operator.h" -#include "sql/operator/explain_logical_operator.h" -#include "sql/operator/explain_physical_operator.h" -#include "sql/operator/calc_logical_operator.h" -#include "sql/operator/calc_physical_operator.h" -#include "sql/operator/delete_logical_operator.h" -#include "sql/operator/delete_physical_operator.h" -#include "sql/operator/predicate_logical_operator.h" -#include "sql/operator/predicate_physical_operator.h" -#include "sql/operator/group_by_logical_operator.h" -#include "sql/operator/scalar_group_by_physical_operator.h" -#include "sql/operator/hash_group_by_physical_operator.h" +#include "sql/operator/logical/table_get_logical_operator.h" +#include "sql/operator/physical/table_scan_physical_operator.h" +#include "sql/operator/logical/project_logical_operator.h" +#include "sql/operator/physical/project_physical_operator.h" +#include "sql/operator/logical/insert_logical_operator.h" +#include "sql/operator/physical/insert_physical_operator.h" +#include "sql/operator/logical/explain_logical_operator.h" +#include "sql/operator/physical/explain_physical_operator.h" +#include "sql/operator/logical/calc_logical_operator.h" +#include "sql/operator/physical/calc_physical_operator.h" +#include "sql/operator/logical/delete_logical_operator.h" +#include "sql/operator/physical/delete_physical_operator.h" +#include "sql/operator/logical/predicate_logical_operator.h" +#include "sql/operator/physical/predicate_physical_operator.h" +#include "sql/operator/logical/group_by_logical_operator.h" +#include "sql/operator/physical/scalar_group_by_physical_operator.h" +#include "sql/operator/physical/hash_group_by_physical_operator.h" // ------------------------------------------------------------------------------------------------- // PhysicalSeqScan diff --git a/src/observer/sql/optimizer/logical_plan_generator.cpp b/src/observer/sql/optimizer/logical_plan_generator.cpp index f9da53f3a..a6b11b146 100644 --- a/src/observer/sql/optimizer/logical_plan_generator.cpp +++ b/src/observer/sql/optimizer/logical_plan_generator.cpp @@ -16,16 +16,16 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" -#include "sql/operator/calc_logical_operator.h" -#include "sql/operator/delete_logical_operator.h" -#include "sql/operator/explain_logical_operator.h" -#include "sql/operator/insert_logical_operator.h" -#include "sql/operator/join_logical_operator.h" +#include "sql/operator/logical/calc_logical_operator.h" +#include "sql/operator/logical/delete_logical_operator.h" +#include "sql/operator/logical/explain_logical_operator.h" +#include "sql/operator/logical/insert_logical_operator.h" +#include "sql/operator/logical/join_logical_operator.h" #include "sql/operator/logical_operator.h" -#include "sql/operator/predicate_logical_operator.h" -#include "sql/operator/project_logical_operator.h" -#include "sql/operator/table_get_logical_operator.h" -#include "sql/operator/group_by_logical_operator.h" +#include "sql/operator/logical/predicate_logical_operator.h" +#include "sql/operator/logical/project_logical_operator.h" +#include "sql/operator/logical/table_get_logical_operator.h" +#include "sql/operator/logical/group_by_logical_operator.h" #include "sql/stmt/calc_stmt.h" #include "sql/stmt/delete_stmt.h" diff --git a/src/observer/sql/optimizer/physical_plan_generator.cpp b/src/observer/sql/optimizer/physical_plan_generator.cpp index 02f0a4c9e..33622e95d 100644 --- a/src/observer/sql/optimizer/physical_plan_generator.cpp +++ b/src/observer/sql/optimizer/physical_plan_generator.cpp @@ -15,33 +15,33 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include "sql/expr/expression.h" #include "session/session.h" -#include "sql/operator/aggregate_vec_physical_operator.h" -#include "sql/operator/calc_logical_operator.h" -#include "sql/operator/calc_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/expr_vec_physical_operator.h" -#include "sql/operator/group_by_vec_physical_operator.h" -#include "sql/operator/hash_join_physical_operator.h" -#include "sql/operator/index_scan_physical_operator.h" -#include "sql/operator/insert_logical_operator.h" -#include "sql/operator/insert_physical_operator.h" -#include "sql/operator/join_logical_operator.h" -#include "sql/operator/nested_loop_join_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/project_vec_physical_operator.h" -#include "sql/operator/table_get_logical_operator.h" -#include "sql/operator/table_scan_physical_operator.h" -#include "sql/operator/group_by_logical_operator.h" -#include "sql/operator/group_by_physical_operator.h" -#include "sql/operator/hash_group_by_physical_operator.h" -#include "sql/operator/scalar_group_by_physical_operator.h" -#include "sql/operator/table_scan_vec_physical_operator.h" +#include "sql/operator/physical/aggregate_vec_physical_operator.h" +#include "sql/operator/logical/calc_logical_operator.h" +#include "sql/operator/physical/calc_physical_operator.h" +#include "sql/operator/logical/delete_logical_operator.h" +#include "sql/operator/physical/delete_physical_operator.h" +#include "sql/operator/logical/explain_logical_operator.h" +#include "sql/operator/physical/explain_physical_operator.h" +#include "sql/operator/physical/expr_vec_physical_operator.h" +#include "sql/operator/physical/group_by_vec_physical_operator.h" +#include "sql/operator/physical/hash_join_physical_operator.h" +#include "sql/operator/physical/index_scan_physical_operator.h" +#include "sql/operator/logical/insert_logical_operator.h" +#include "sql/operator/physical/insert_physical_operator.h" +#include "sql/operator/logical/join_logical_operator.h" +#include "sql/operator/physical/nested_loop_join_physical_operator.h" +#include "sql/operator/logical/predicate_logical_operator.h" +#include "sql/operator/physical/predicate_physical_operator.h" +#include "sql/operator/logical/project_logical_operator.h" +#include "sql/operator/physical/project_physical_operator.h" +#include "sql/operator/physical/project_vec_physical_operator.h" +#include "sql/operator/logical/table_get_logical_operator.h" +#include "sql/operator/physical/table_scan_physical_operator.h" +#include "sql/operator/logical/group_by_logical_operator.h" +#include "sql/operator/physical/group_by_physical_operator.h" +#include "sql/operator/physical/hash_group_by_physical_operator.h" +#include "sql/operator/physical/scalar_group_by_physical_operator.h" +#include "sql/operator/physical/table_scan_vec_physical_operator.h" #include "sql/optimizer/physical_plan_generator.h" using namespace std; diff --git a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp index eee834acb..a2261652d 100644 --- a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp +++ b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp @@ -16,7 +16,7 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include "sql/expr/expression.h" #include "sql/operator/logical_operator.h" -#include "sql/operator/table_get_logical_operator.h" +#include "sql/operator/logical/table_get_logical_operator.h" RC PredicatePushdownRewriter::rewrite(unique_ptr &oper, bool &change_made) { From aa6ffae62a631b1ef3432f567069fd41b2bd47f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Tue, 25 Nov 2025 10:56:50 +0800 Subject: [PATCH 04/12] refactor: Remove duplicate code in MiniOB --- .vscode/tasks.json | 5 - src/observer/net/sql_task_handler.cpp | 14 +- src/observer/session/session_stage.cpp | 71 +--------- src/observer/session/session_stage.h | 17 +-- .../physical/join_physical_operator.cpp | 133 ------------------ .../physical/join_physical_operator.h | 53 ------- .../nested_loop_join_physical_operator.cpp | 32 ++--- 7 files changed, 30 insertions(+), 295 deletions(-) delete mode 100644 src/observer/sql/operator/physical/join_physical_operator.cpp delete mode 100644 src/observer/sql/operator/physical/join_physical_operator.h diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c64205fa5..fe5dc73f5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -22,11 +22,6 @@ "label": "build_release", "type": "shell", "command": "bash build.sh release" - }, - { - "label": "gen_parser", - "type": "shell", - "command": "cd ${workspaceFolder}/src/observer/sql/parser && bash gen_parser.sh" } ] } diff --git a/src/observer/net/sql_task_handler.cpp b/src/observer/net/sql_task_handler.cpp index 90f0609b4..148b87edf 100644 --- a/src/observer/net/sql_task_handler.cpp +++ b/src/observer/net/sql_task_handler.cpp @@ -21,7 +21,7 @@ See the Mulan PSL v2 for more details. */ RC SqlTaskHandler::handle_event(Communicator *communicator) { SessionEvent *event = nullptr; - RC rc = communicator->read_event(event); + RC rc = communicator->read_event(event); if (OB_FAIL(rc)) { return rc; } @@ -30,7 +30,7 @@ RC SqlTaskHandler::handle_event(Communicator *communicator) return RC::SUCCESS; } - session_stage_.handle_request2(event); + session_stage_.handle_request(event); SQLStageEvent sql_event(event, event->query()); @@ -55,6 +55,16 @@ RC SqlTaskHandler::handle_event(Communicator *communicator) return RC::SUCCESS; } +/** + * 处理一个SQL语句经历这几个阶段。 + * 虽然看起来流程比较多,但是对于大多数SQL来说,更多的可以关注parse和executor阶段。 + * 通常只有select、delete等带有查询条件的语句才需要进入optimize。 + * 对于DDL语句,比如create table、create index等,没有对应的查询计划,可以直接搜索 + * create_table_executor、create_index_executor来看具体的执行代码。 + * select、delete等DML语句,会产生一些执行计划,如果感觉繁琐,可以跳过optimize直接看 + * execute_stage中的执行,通过explain语句看需要哪些operator,然后找对应的operator来 + * 调试或者看代码执行过程即可。 + */ RC SqlTaskHandler::handle_sql(SQLStageEvent *sql_event) { RC rc = query_cache_stage_.handle_request(sql_event); diff --git a/src/observer/session/session_stage.cpp b/src/observer/session/session_stage.cpp index eed271357..92bda77c7 100644 --- a/src/observer/session/session_stage.cpp +++ b/src/observer/session/session_stage.cpp @@ -31,31 +31,7 @@ using namespace common; // Destructor SessionStage::~SessionStage() {} -// TODO remove me -void SessionStage::handle_request(SessionEvent *sev) -{ - string sql = sev->query(); - if (common::is_blank(sql.c_str())) { - return; - } - - Session::set_current_session(sev->session()); - sev->session()->set_current_request(sev); - SQLStageEvent sql_event(sev, sql); - (void)handle_sql(&sql_event); - - Communicator *communicator = sev->get_communicator(); - bool need_disconnect = false; - RC rc = communicator->write_result(sev, need_disconnect); - LOG_INFO("write result return %s", strrc(rc)); - if (need_disconnect) { - // do nothing - } - sev->session()->set_current_request(nullptr); - Session::set_current_session(nullptr); -} - -void SessionStage::handle_request2(SessionEvent *event) +void SessionStage::handle_request(SessionEvent *event) { const string &sql = event->query(); if (common::is_blank(sql.c_str())) { @@ -66,48 +42,3 @@ void SessionStage::handle_request2(SessionEvent *event) event->session()->set_current_request(event); SQLStageEvent sql_event(event, sql); } - -/** - * 处理一个SQL语句经历这几个阶段。 - * 虽然看起来流程比较多,但是对于大多数SQL来说,更多的可以关注parse和executor阶段。 - * 通常只有select、delete等带有查询条件的语句才需要进入optimize。 - * 对于DDL语句,比如create table、create index等,没有对应的查询计划,可以直接搜索 - * create_table_executor、create_index_executor来看具体的执行代码。 - * select、delete等DML语句,会产生一些执行计划,如果感觉繁琐,可以跳过optimize直接看 - * execute_stage中的执行,通过explain语句看需要哪些operator,然后找对应的operator来 - * 调试或者看代码执行过程即可。 - */ -RC SessionStage::handle_sql(SQLStageEvent *sql_event) -{ - RC rc = query_cache_stage_.handle_request(sql_event); - if (OB_FAIL(rc)) { - LOG_TRACE("failed to do query cache. rc=%s", strrc(rc)); - return rc; - } - - rc = parse_stage_.handle_request(sql_event); - if (OB_FAIL(rc)) { - LOG_TRACE("failed to do parse. rc=%s", strrc(rc)); - return rc; - } - - rc = resolve_stage_.handle_request(sql_event); - if (OB_FAIL(rc)) { - LOG_TRACE("failed to do resolve. rc=%s", strrc(rc)); - return rc; - } - - rc = optimize_stage_.handle_request(sql_event); - if (rc != RC::UNIMPLEMENTED && rc != RC::SUCCESS) { - LOG_TRACE("failed to do optimize. rc=%s", strrc(rc)); - return rc; - } - - rc = execute_stage_.handle_request(sql_event); - if (OB_FAIL(rc)) { - LOG_TRACE("failed to do execute. rc=%s", strrc(rc)); - return rc; - } - - return rc; -} diff --git a/src/observer/session/session_stage.h b/src/observer/session/session_stage.h index 2762c66ca..3575eddeb 100644 --- a/src/observer/session/session_stage.h +++ b/src/observer/session/session_stage.h @@ -14,11 +14,7 @@ See the Mulan PSL v2 for more details. */ #pragma once -#include "sql/executor/execute_stage.h" -#include "sql/optimizer/optimize_stage.h" -#include "sql/parser/parse_stage.h" -#include "sql/parser/resolve_stage.h" -#include "sql/query_cache/query_cache_stage.h" +class SessionEvent; /** * @brief SEDA处理的stage @@ -42,17 +38,6 @@ class SessionStage SessionStage() = default; virtual ~SessionStage(); -public: - void handle_request2(SessionEvent *event); - public: void handle_request(SessionEvent *event); - RC handle_sql(SQLStageEvent *sql_event); - -private: - QueryCacheStage query_cache_stage_; - ParseStage parse_stage_; - ResolveStage resolve_stage_; - OptimizeStage optimize_stage_; - ExecuteStage execute_stage_; }; diff --git a/src/observer/sql/operator/physical/join_physical_operator.cpp b/src/observer/sql/operator/physical/join_physical_operator.cpp deleted file mode 100644 index 7c274528c..000000000 --- a/src/observer/sql/operator/physical/join_physical_operator.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2021 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/30. -// - -#include "sql/operator/physical/join_physical_operator.h" - -NestedLoopJoinPhysicalOperator::NestedLoopJoinPhysicalOperator() {} - -RC NestedLoopJoinPhysicalOperator::open(Trx *trx) -{ - if (children_.size() != 2) { - LOG_WARN("nlj operator should have 2 children"); - return RC::INTERNAL; - } - - RC rc = RC::SUCCESS; - left_ = children_[0].get(); - right_ = children_[1].get(); - right_closed_ = true; - round_done_ = true; - - rc = left_->open(trx); - trx_ = trx; - return rc; -} - -RC NestedLoopJoinPhysicalOperator::next() -{ - bool left_need_step = (left_tuple_ == nullptr); - RC rc = RC::SUCCESS; - if (round_done_) { - left_need_step = true; - } else { - rc = right_next(); - if (rc != RC::SUCCESS) { - if (rc == RC::RECORD_EOF) { - left_need_step = true; - } else { - return rc; - } - } else { - return rc; // got one tuple from right - } - } - - if (left_need_step) { - rc = left_next(); - if (rc != RC::SUCCESS) { - return rc; - } - } - - rc = right_next(); - return rc; -} - -RC NestedLoopJoinPhysicalOperator::close() -{ - RC rc = left_->close(); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to close left oper. rc=%s", strrc(rc)); - } - - if (!right_closed_) { - rc = right_->close(); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to close right oper. rc=%s", strrc(rc)); - } else { - right_closed_ = true; - } - } - return rc; -} - -Tuple *NestedLoopJoinPhysicalOperator::current_tuple() { return &joined_tuple_; } - -RC NestedLoopJoinPhysicalOperator::left_next() -{ - RC rc = RC::SUCCESS; - rc = left_->next(); - if (rc != RC::SUCCESS) { - return rc; - } - - left_tuple_ = left_->current_tuple(); - joined_tuple_.set_left(left_tuple_); - return rc; -} - -RC NestedLoopJoinPhysicalOperator::right_next() -{ - RC rc = RC::SUCCESS; - if (round_done_) { - if (!right_closed_) { - rc = right_->close(); - - right_closed_ = true; - if (rc != RC::SUCCESS) { - return rc; - } - } - - rc = right_->open(trx_); - if (rc != RC::SUCCESS) { - return rc; - } - right_closed_ = false; - - round_done_ = false; - } - - rc = right_->next(); - if (rc != RC::SUCCESS) { - if (rc == RC::RECORD_EOF) { - round_done_ = true; - } - return rc; - } - - right_tuple_ = right_->current_tuple(); - joined_tuple_.set_right(right_tuple_); - return rc; -} diff --git a/src/observer/sql/operator/physical/join_physical_operator.h b/src/observer/sql/operator/physical/join_physical_operator.h deleted file mode 100644 index f3dae560c..000000000 --- a/src/observer/sql/operator/physical/join_physical_operator.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2021 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 2021/6/10. -// - -#pragma once - -#include "sql/operator/physical_operator.h" -#include "sql/parser/parse.h" - -/** - * @brief 最简单的两表(称为左表、右表)join算子 - * @details 依次遍历左表的每一行,然后关联右表的每一行 - * @ingroup PhysicalOperator - */ -class NestedLoopJoinPhysicalOperator : public PhysicalOperator -{ -public: - NestedLoopJoinPhysicalOperator(); - virtual ~NestedLoopJoinPhysicalOperator() = default; - - OpType get_op_type() const override { return OpType::INNERNLJOIN; } - - RC open(Trx *trx) override; - RC next() override; - RC close() override; - Tuple *current_tuple() override; - -private: - RC left_next(); //! 左表遍历下一条数据 - RC right_next(); //! 右表遍历下一条数据,如果上一轮结束了就重新开始新的一轮 - -private: - Trx *trx_ = nullptr; - - //! 左表右表的真实对象是在PhysicalOperator::children_中,这里是为了写的时候更简单 - PhysicalOperator *left_ = nullptr; - PhysicalOperator *right_ = nullptr; - Tuple *left_tuple_ = nullptr; - Tuple *right_tuple_ = nullptr; - JoinedTuple joined_tuple_; //! 当前关联的左右两个tuple - bool round_done_ = true; //! 右表遍历的一轮是否结束 - bool right_closed_ = true; //! 右表算子是否已经关闭 -}; diff --git a/src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp b/src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp index 836a185a5..bfc9b6a8c 100644 --- a/src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp +++ b/src/observer/sql/operator/physical/nested_loop_join_physical_operator.cpp @@ -36,31 +36,31 @@ RC NestedLoopJoinPhysicalOperator::open(Trx *trx) RC NestedLoopJoinPhysicalOperator::next() { + bool left_need_step = (left_tuple_ == nullptr); RC rc = RC::SUCCESS; - while (RC::SUCCESS == rc) { - bool left_need_step = (left_tuple_ == nullptr); - if (round_done_) { - left_need_step = true; - } - - if (left_need_step) { - rc = left_next(); - if (rc != RC::SUCCESS) { - return rc; - } - } - + if (round_done_) { + left_need_step = true; + } else { rc = right_next(); if (rc != RC::SUCCESS) { if (rc == RC::RECORD_EOF) { - rc = RC::SUCCESS; - round_done_ = true; - continue; + left_need_step = true; } else { return rc; } + } else { + return rc; // got one tuple from right } } + + if (left_need_step) { + rc = left_next(); + if (rc != RC::SUCCESS) { + return rc; + } + } + + rc = right_next(); return rc; } From 2a771956da7ba3f696b143536eec0ba136b4e4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Tue, 25 Nov 2025 14:41:12 +0800 Subject: [PATCH 05/12] docs: Update the display of some documents on github.io --- .../design/miniob-how-to-add-new-datatype.md | 281 ++++++++++++++++-- .../design/miniob-sql-execution-process.md | 22 +- docs/docs/how_to_build.md | 66 ++-- docs/mkdocs.yml | 3 + 4 files changed, 323 insertions(+), 49 deletions(-) diff --git a/docs/docs/design/miniob-how-to-add-new-datatype.md b/docs/docs/design/miniob-how-to-add-new-datatype.md index 4ad9bb0ff..60dbc4752 100644 --- a/docs/docs/design/miniob-how-to-add-new-datatype.md +++ b/docs/docs/design/miniob-how-to-add-new-datatype.md @@ -2,31 +2,258 @@ title: 如何新增一种数据类型 --- -> 本文介绍如何新增一种数据类型。 -MiniOB 的数据类型系统采用分层设计,实现集中在[path](../../../src/observer/common)文件夹下,核心组件包括: -1. Value 类:统一数据操作接口 -路径:src/observer/common/value.h -作用:封装实际数据值,提供类型无关的操作方法 -2. Type 工具类:特定类型的操作实现 -路径:src/observer/common/type/ -作用:每种数据类型对应一个工具类,实现具体运算逻辑 - -以下示例展示 MiniOB 如何处理整数类型数据: -```cpp -// 假设解析器识别到整数 "1" -int val = 1; -Value value(val); // 封装为 Value 对象 -// 执行加法运算 +# 概述 + +本文详细介绍如何在 MiniOB 中新增一种数据类型。MiniOB 采用分层架构设计,数据类型系统实现集中在 `src/observer/common` 目录下,通过统一的接口提供类型无关的数据操作。 + +# 核心架构 + +## 1. 数据类型系统架构 + +MiniOB 的数据类型系统采用分层设计,主要包含以下核心组件: + +### Value 类 - 统一数据操作接口 +- **路径**: `src/observer/common/value.h` +- **作用**: 封装实际数据值,提供类型无关的操作方法 +- **特点**: 支持多种数据类型的统一操作接口 + +### DataType 基类 - 类型操作抽象 +- **路径**: `src/observer/common/type/data_type.h` +- **作用**: 定义数据类型操作的抽象接口 +- **功能**: 提供比较、算术运算、类型转换等操作的虚函数 + +### 具体类型实现类 - 特定类型操作 +- **路径**: `src/observer/common/type/` +- **作用**: 每种数据类型对应一个实现类,实现具体的运算逻辑 +- **示例**: `IntegerType`、`FloatType`、`CharType` 等 + +## 2. 现有数据类型 + +当前 MiniOB 支持以下数据类型: + +```cpp +enum class AttrType +{ + UNDEFINED, + CHARS, ///< 字符串类型 + INTS, ///< 整数类型(4字节) + FLOATS, ///< 浮点数类型(4字节) + VECTORS, ///< 向量类型 + BOOLEANS, ///< boolean类型 + MAXTYPE, ///< 请在 UNDEFINED 与 MAXTYPE 之间增加新类型 +}; +``` + +# 数据类型操作流程 + +## 示例:整数类型操作 + +以下代码展示了 MiniOB 如何处理整数类型数据: + +```cpp +// 1. 创建整数 Value 对象 +int val = 42; +Value value(val); // 自动识别为 AttrType::INTS + +// 2. 执行算术运算 +Value left(10); +Value right(32); Value result; -Value::add(value, value, result); // 调用加法接口 -// Value::add 方法内部会根据类型调用对应工具类 -// 对于 INT 类型,实际调用代码位于: -// src/observer/common/type/integer_type.cpp -``` - -# 若要新增一种数据类型(如 DATE),建议按以下步骤开发: -1. 在 src/observer/common/type/attr_type.h 中添加新的类型枚举以及对应类型名 -2. 在 src/observer/common/type/data_type.cpp 中添加新的类型实例 -3. 在 src/observer/common/type/ 文件夹下,参照现有工具类,实现 DateType 工具类 -4. 在 Value 类中增加类型处理逻辑,支持date类型的分发,储存date类型值 -5. 必要情况下还需要增加新的词法规则(lex_sql.l)以及语法规则(yacc_sql.y),支持新类型关键字 \ No newline at end of file +result.set_type(AttrType::INTS); // 设置结果类型 + +// 3. 调用统一接口进行加法运算 +RC rc = Value::add(left, right, result); +// 内部会调用 IntegerType::add() 方法 +``` +## 类型分发机制 +`Value::add()` 方法通过以下机制实现类型分发: +```cpp +static RC add(const Value &left, const Value &right, Value &result) +{ + return DataType::type_instance(result.attr_type())->add(left, right, result); +} +``` + +# 新增数据类型步骤 + +## 以新增 DATE 类型为例 + +### 步骤 1: 添加类型枚举 + +在 `src/observer/common/type/attr_type.h` 中添加新类型: + +```cpp +enum class AttrType +{ + UNDEFINED, + CHARS, + INTS, + FLOATS, + VECTORS, + BOOLEANS, + DATES, ///< 新增:日期类型 + MAXTYPE, ///< 请在 UNDEFINED 与 MAXTYPE 之间增加新类型 +}; +``` + +### 步骤 2: 注册类型实例 + +在 `src/observer/common/type/data_type.cpp` 中注册新类型: + +```cpp +array, static_cast(AttrType::MAXTYPE)> DataType::type_instances_ = { + make_unique(AttrType::UNDEFINED), + make_unique(), + make_unique(), + make_unique(), + make_unique(), + make_unique(AttrType::BOOLEANS), + make_unique(), // 新增:注册 DateType 实例 +}; +``` + +### 步骤 3: 实现具体类型类 + +创建 `src/observer/common/type/date_type.h`: + +```cpp +#pragma once +#include "common/type/data_type.h" + +class DateType : public DataType +{ +public: + DateType() : DataType(AttrType::DATES) {} + virtual ~DateType() {} + + int compare(const Value &left, const Value &right) const override; + RC add(const Value &left, const Value &right, Value &result) const override; + RC subtract(const Value &left, const Value &right, Value &result) const override; + RC cast_to(const Value &val, AttrType type, Value &result) const override; + RC to_string(const Value &val, string &result) const override; + RC set_value_from_str(Value &val, const string &data) const override; + + int cast_cost(const AttrType type) override; +}; +``` + +### 步骤 4: 实现类型操作逻辑 + +创建 `src/observer/common/type/date_type.cpp`: + +```cpp +#include "common/type/date_type.h" +#include "common/value.h" + +int DateType::compare(const Value &left, const Value &right) const +{ + // 实现日期比较逻辑 + // 返回 -1 (left < right), 0 (left == right), 1 (left > right) +} + +RC DateType::add(const Value &left, const Value &right, Value &result) const +{ + // 实现日期加法运算(如加天数) + // 设置 result 的值和类型 + return RC::SUCCESS; +} + +RC DateType::to_string(const Value &val, string &result) const +{ + // 将日期值转换为字符串格式 + return RC::SUCCESS; +} + +RC DateType::set_value_from_str(Value &val, const string &data) const +{ + // 从字符串解析日期值 + return RC::SUCCESS; +} +``` +### 步骤 5: 扩展 Value 类支持 +在 `src/observer/common/value.h` 中添加日期类型的构造函数: +```cpp +class Value final +{ +public: + // 现有构造函数... + explicit Value(const Date &date); // 新增:日期构造函数 + + // 现有方法... + Date get_date() const; // 新增:获取日期值 + void set_date(const Date &date); // 新增:设置日期值 +}; +``` + +### 步骤 6: 更新词法和语法规则(可选) + +如果需要支持 SQL 中的 DATE 关键字,需要修改: + +- **词法规则**: `src/observer/sql/parser/lex_sql.l` +- **语法规则**: `src/observer/sql/parser/yacc_sql.y` + +# 实现要点 + +## 1. 类型兼容性 + +实现 `cast_cost()` 方法定义类型转换成本: + +```cpp +int DateType::cast_cost(const AttrType type) override +{ + if (type == AttrType::DATES) { + return 0; // 相同类型,无转换成本 + } else if (type == AttrType::CHARS) { + return 1; // 可转换为字符串,成本为1 + } + return INT32_MAX; // 不支持转换 +} +``` +## 2. 错误处理 +所有操作都应返回适当的 `RC` 状态码: +```cpp +RC DateType::add(const Value &left, const Value &right, Value &result) const +{ + if (left.attr_type() != AttrType::DATES || right.attr_type() != AttrType::INTS) { + return RC::SCHEMA_FIELD_TYPE_MISMATCH; + } + // 执行加法操作... + return RC::SUCCESS; +} +``` + +## 3. 内存管理 + +对于复杂数据类型,注意内存管理: + +```cpp +void Value::set_date(const Date &date) +{ + reset(); // 清理之前的数据 + attr_type_ = AttrType::DATES; + // 设置日期值... +} +``` +# 测试验证 +新增数据类型后,建议编写单元测试验证功能: +```cpp +TEST(DateTypeTest, BasicOperations) +{ + Value date1("2023-01-01"); + Value date2("2023-01-02"); + Value result; + result.set_type(AttrType::DATES); + + // 测试比较操作 + EXPECT_EQ(DateType().compare(date1, date2), -1); + + // 测试字符串转换 + string str; + EXPECT_EQ(DateType().to_string(date1, str), RC::SUCCESS); + EXPECT_EQ(str, "2023-01-01"); +} +``` + +# 总结 + +新增数据类型需要按照上述步骤系统性地修改多个文件,确保类型系统的一致性和完整性。建议在实现过程中参考现有的 `IntegerType` 和 `FloatType` 实现,保持代码风格的一致性。 \ No newline at end of file diff --git a/docs/docs/design/miniob-sql-execution-process.md b/docs/docs/design/miniob-sql-execution-process.md index b80a83b4d..d0ffc40b0 100644 --- a/docs/docs/design/miniob-sql-execution-process.md +++ b/docs/docs/design/miniob-sql-execution-process.md @@ -1,9 +1,21 @@ -如图[image](images/miniob-sql-execution-process.png) +--- +title: SQL 执行流程 +--- -PlantUML时序图使用 https://www.plantuml.com/plantuml 生成 -代码如下: -```cpp -@startuml +### SQL 执行流程时序图 + +![SQL 执行流程图](images/miniob-sql-execution-process.png) + +*图:MiniOB SQL 执行流程时序图(可通过 PlantUML 源码重新生成)* + +> 💡 提示:本图由 [PlantUML](https://www.plantuml.com/plantuml) 在线工具生成,可用于调试或更新图表。 +--- + +#### PlantUML 源码 + +建议保存此代码以便后续修改图像内容: + +```plantuml title SQL 执行流程时序图\n skinparam sequence { diff --git a/docs/docs/how_to_build.md b/docs/docs/how_to_build.md index c6823f522..03f7730f7 100644 --- a/docs/docs/how_to_build.md +++ b/docs/docs/how_to_build.md @@ -162,30 +162,62 @@ git config --global core.autocrlf false 也可以将cmake所在路径添加到sudo的PATH变量中来解决上述问题,请参考[sudo命令下环境变量实效的解决方法](https://www.cnblogs.com/xiao-xiaoyang/p/17444600.html)。 -### 3. Could not find a package configuration file provided by "Libevent" -在执行build.sh脚本时,遇到下面的错误 -![cmake error](images/miniob-build-libevent.png) +### 3. 构建错误:找不到 Libevent 或 jsoncpp +在执行 `build.sh init` 时可能出现以下错误: +![CMake Error - Libevent Not Found](images/miniob-build-libevent.png) +![CMake Error - jsoncpp Not Found](images/miniob-build-jsoncpp.png) -通常是因为cmake版本原因(版本太高?)导致libevent在init阶段没有编译成功。 +### 🔍 原因 -***解决方法:*** +项目使用的第三方库 `libevent` 和 `jsoncpp` 依赖较老的 CMake 语法,与高版本 CMake(3.10+)不兼容,导致构建失败。 + +--- +### ✅ 解决方案(二选一) -在[text](../../deps/3rd/libevent/CMakeLists.txt) 中将cmake的最低版本设置 -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -改为 -cmake_minimum_required(VERSION 3.1...3.8 FATAL_ERROR) -之后重新执行 +#### 方案一:快速修复(本地临时使用) + +修改子模块中的 CMake 配置,放宽版本限制。 + +1. 修改 `libevent`: +```bash +sed -i 's|cmake_minimum_required(VERSION 3.1 FATAL_ERROR)|cmake_minimum_required(VERSION 3.1...3.8 FATAL_ERROR)|' deps/3rd/libevent/CMakeLists.txt +``` +2. 修改 jsoncpp: +```bash +sed -i 's|cmake_policy(VERSION 3.0)|cmake_policy(VERSION 3.0...3.8)|' deps/3rd/jsoncpp/jsoncppConfig.cmake.in +``` +重新初始化: ```bash sudo bash build.sh init ``` +⚠️ 注意:此修改仅为本地临时适配,请勿提交到 Git。 + +#### 方案二:根本解决(推荐,长期使用) + +升级 libevent 和 jsoncpp 到支持现代 CMake 的新版。 +```bash +# 更新 libevent +cd deps/3rd/libevent +git checkout main && git pull origin main +cd ../../.. -如果你成功解决libevent的问题,你大概率会遇到另一个错误: -![cmake error](images/miniob-build-jsoncpp.png) -需要在[text](../../deps/3rd/jsoncpp/jsoncppConfig.cmake.in)中将cmake策略 -cmake_policy(VERSION 3.0) -改为 -cmake_policy(VERSION 3.0...3.8) -之后重新执行 +# 更新 jsoncpp +```bash +cd deps/3rd/jsoncpp +git checkout master && git pull origin master +cd ../../.. +``` +推荐切换到稳定版本: +libevent: release-2.1.12-stable +jsoncpp: 1.9.5 或更高 +提交更新: +```bash +git add deps/3rd/libevent deps/3rd/jsoncpp +git commit -m "chore: upgrade libevent and jsoncpp for CMake compatibility" +git push origin main +``` +然后重新构建: ```bash +rm -rf build/ # 清理缓存 sudo bash build.sh init ``` \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index df4e09e1a..21914edac 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -34,6 +34,7 @@ nav: - design/miniob-durability.md - design/miniob-sql-parser.md - design/miniob-how-to-add-new-sql.md + - design/miniob-how-to-add-new-datatype.md - design/miniob-sql-expression.md - design/miniob-bplus-tree.md - design/miniob-bplus-tree-concurrency.md @@ -42,6 +43,8 @@ nav: - design/miniob-pax-storage.md - design/miniob-aggregation-and-group-by.md - design/miniob-lsm-tree.md + - design/miniob-realtime-analytic.md + - design/miniob-sql-execution-process.md - Doxy 代码文档: design/doxy/html/index.html - OceanBase 数据库大赛: - game/introduction.md From dd17e0b1a1450e56b4b95763504623e368f2f309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Tue, 25 Nov 2025 19:06:29 +0800 Subject: [PATCH 06/12] feat(optimizer): Merge rewrite into cascade --- .../cascade/transformation_rules.cpp | 256 ++++++++++++++++++ .../optimizer/cascade/transformation_rules.h | 59 ++++ .../comparison_simplification_rule.cpp | 38 --- .../rewrite/comparison_simplification_rule.h | 37 --- .../conjunction_simplification_rule.cpp | 85 ------ .../rewrite/conjunction_simplification_rule.h | 35 --- .../optimizer/rewrite/expression_rewriter.cpp | 147 ---------- .../optimizer/rewrite/expression_rewriter.h | 36 --- .../rewrite/predicate_pushdown_rewriter.cpp | 126 --------- .../rewrite/predicate_pushdown_rewriter.h | 36 --- .../optimizer/rewrite/predicate_rewrite.cpp | 58 ---- .../sql/optimizer/rewrite/predicate_rewrite.h | 31 --- .../rewrite/predicate_to_join_rule.cpp | 11 - .../rewrite/predicate_to_join_rule.h | 21 -- .../sql/optimizer/rewrite/rewrite_rule.h | 46 ---- .../sql/optimizer/rewrite/rewriter.cpp | 66 ----- src/observer/sql/optimizer/rewrite/rewriter.h | 52 ---- 17 files changed, 315 insertions(+), 825 deletions(-) create mode 100644 src/observer/sql/optimizer/cascade/transformation_rules.cpp create mode 100644 src/observer/sql/optimizer/cascade/transformation_rules.h delete mode 100644 src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h delete mode 100644 src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h delete mode 100644 src/observer/sql/optimizer/rewrite/expression_rewriter.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/expression_rewriter.h delete mode 100644 src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h delete mode 100644 src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/predicate_rewrite.h delete mode 100644 src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h delete mode 100644 src/observer/sql/optimizer/rewrite/rewrite_rule.h delete mode 100644 src/observer/sql/optimizer/rewrite/rewriter.cpp delete mode 100644 src/observer/sql/optimizer/rewrite/rewriter.h diff --git a/src/observer/sql/optimizer/cascade/transformation_rules.cpp b/src/observer/sql/optimizer/cascade/transformation_rules.cpp new file mode 100644 index 000000000..f725bfea3 --- /dev/null +++ b/src/observer/sql/optimizer/cascade/transformation_rules.cpp @@ -0,0 +1,256 @@ +/* Copyright (c) 2021 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. */ + +#include "sql/optimizer/cascade/transformation_rules.h" +#include "common/log/log.h" +#include "sql/optimizer/cascade/group_expr.h" +#include "sql/optimizer/cascade/memo.h" +#include "sql/operator/logical/predicate_logical_operator.h" +#include "sql/operator/logical/table_get_logical_operator.h" +#include "sql/expr/expression.h" + +// ------------------------------------------------------------------------------------------------- +// PredicatePushdownRule +// ------------------------------------------------------------------------------------------------- +PredicatePushdownRule::PredicatePushdownRule() +{ + type_ = RuleType::PREDICATE_PUSHDOWN; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALFILTER)); + auto child = new Pattern(OpType::LOGICALGET); + match_pattern_->add_child(child); +} + +void PredicatePushdownRule::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + ASSERT(input->get_children_groups_size() == 1, "Filter should have 1 child"); + + auto predicate_oper = static_cast(input->get_op()); + vector> &expressions = predicate_oper->expressions(); + if (expressions.size() != 1) { + return; + } + + // 获取子 GroupExpr + Memo &memo = context->get_memo(); + Group *child_group = memo.get_group_by_id(input->get_child_group_ids()[0]); + GroupExpr *child_gexpr = child_group->get_logical_expression(); + if (!child_gexpr || child_gexpr->get_op()->get_op_type() != OpType::LOGICALGET) { + return; + } + + auto table_get_oper = static_cast(child_gexpr->get_op()); + + unique_ptr &predicate_expr = expressions.front(); + vector> pushdown_exprs; + + // 提取可以下推的表达式 + if (predicate_expr->type() == ExprType::CONJUNCTION) { + ConjunctionExpr *conjunction_expr = static_cast(predicate_expr.get()); + if (conjunction_expr->conjunction_type() == ConjunctionExpr::Type::OR) { + // OR 操作太复杂,暂不支持 + return; + } + + vector> &child_exprs = conjunction_expr->children(); + for (auto &child_expr : child_exprs) { + if (child_expr->type() == ExprType::COMPARISON) { + pushdown_exprs.push_back(child_expr->copy()); + } + } + } else if (predicate_expr->type() == ExprType::COMPARISON) { + pushdown_exprs.push_back(predicate_expr->copy()); + } + + if (pushdown_exprs.empty()) { + return; + } + + // 创建新的 TableGetLogicalOperator,包含下推的谓词 + // 合并原有的 predicates 和下推的 predicates + vector> existing_predicates; + for (auto &expr : table_get_oper->predicates()) { + existing_predicates.push_back(expr->copy()); + } + for (auto &expr : pushdown_exprs) { + existing_predicates.push_back(std::move(expr)); + } + + auto new_table_get = make_unique( + table_get_oper->table(), table_get_oper->read_write_mode()); + new_table_get->set_predicates(std::move(existing_predicates)); + + // 返回新的 TableGet,直接替换 Filter(TableGet 是叶子节点,没有子节点) + transformed->emplace_back(std::move(new_table_get)); +} + +// ------------------------------------------------------------------------------------------------- +// PredicateRewriteRule +// ------------------------------------------------------------------------------------------------- +PredicateRewriteRule::PredicateRewriteRule() +{ + type_ = RuleType::PREDICATE_REWRITE; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALFILTER)); + auto child = new Pattern(OpType::LEAF); + match_pattern_->add_child(child); +} + +void PredicateRewriteRule::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + ASSERT(input->get_children_groups_size() == 1, "Filter should have 1 child"); + + auto predicate_oper = static_cast(input->get_op()); + vector> &expressions = predicate_oper->expressions(); + if (expressions.size() != 1) { + return; + } + + unique_ptr &expr = expressions.front(); + if (expr->type() != ExprType::VALUE) { + return; + } + + // 检查是否为恒真或恒假 + auto value_expr = static_cast(expr.get()); + bool bool_value = value_expr->get_value().get_boolean(); + + if (bool_value == true) { + // 恒真:删除 Filter,直接返回子节点 + Memo &memo = context->get_memo(); + Group *child_group = memo.get_group_by_id(input->get_child_group_ids()[0]); + GroupExpr *child_gexpr = child_group->get_logical_expression(); + if (child_gexpr) { + // 返回子节点的逻辑表达式 + // 注意:这里我们需要创建一个新的 GroupExpr,但实际上应该直接使用子节点 + // 由于 Cascade 架构,我们返回一个空的 transformed,让优化器继续处理子节点 + // 或者我们可以返回子节点的 operator + auto child_op = child_gexpr->get_op(); + if (child_op->is_logical()) { + // 创建新的逻辑算子(复制) + // 这里简化处理:如果恒真,我们返回子节点,但需要保持 GroupExpr 结构 + // 实际上,这个规则应该通过 Memo 来处理,而不是直接返回 + // 暂时不生成新的表达式,让优化器继续处理 + return; + } + } + } else { + // 恒假:删除整个子树 + // 在 Cascade 中,这应该返回一个空的 GroupExpr 或者特殊的算子 + // 暂时不处理 + return; + } +} + +// ------------------------------------------------------------------------------------------------- +// ExpressionSimplifyRule +// ------------------------------------------------------------------------------------------------- +ExpressionSimplifyRule::ExpressionSimplifyRule() +{ + type_ = RuleType::EXPRESSION_SIMPLIFY; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALFILTER)); + auto child = new Pattern(OpType::LEAF); + match_pattern_->add_child(child); +} + +void ExpressionSimplifyRule::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + auto predicate_oper = static_cast(input->get_op()); + vector> &expressions = predicate_oper->expressions(); + + bool changed = false; + vector> new_expressions; + + for (auto &expr : expressions) { + unique_ptr new_expr = expr->copy(); + if (simplify_expression(new_expr)) { + changed = true; + } + new_expressions.push_back(std::move(new_expr)); + } + + if (changed && !new_expressions.empty()) { + auto new_predicate = make_unique(std::move(new_expressions.front())); + transformed->emplace_back(std::move(new_predicate), input->get_child_group_ids()); + } +} + +bool ExpressionSimplifyRule::simplify_expression(unique_ptr &expr) const +{ + bool changed = false; + + // 简化比较表达式 + if (expr->type() == ExprType::COMPARISON) { + Value value; + ComparisonExpr *cmp_expr = static_cast(expr.get()); + if (cmp_expr->try_get_value(value) == RC::SUCCESS) { + expr = make_unique(value); + changed = true; + } + } + + // 简化联结表达式 + if (expr->type() == ExprType::CONJUNCTION) { + auto conjunction_expr = static_cast(expr.get()); + vector> &child_exprs = conjunction_expr->children(); + + // 先简化子表达式 + for (auto &child_expr : child_exprs) { + if (simplify_expression(child_expr)) { + changed = true; + } + } + + // 检查是否有可以删除的常量表达式 + for (auto iter = child_exprs.begin(); iter != child_exprs.end();) { + bool constant_value = false; + if ((*iter)->type() == ExprType::VALUE && (*iter)->value_type() == AttrType::BOOLEANS) { + auto value_expr = static_cast(iter->get()); + constant_value = value_expr->get_value().get_boolean(); + + if (conjunction_expr->conjunction_type() == ConjunctionExpr::Type::AND) { + if (constant_value == true) { + iter = child_exprs.erase(iter); + changed = true; + continue; + } else { + // always be false + expr = make_unique(Value((bool)false)); + changed = true; + return changed; + } + } else { + // OR + if (constant_value == true) { + // always be true + expr = make_unique(Value((bool)true)); + changed = true; + return changed; + } else { + iter = child_exprs.erase(iter); + changed = true; + continue; + } + } + } + ++iter; + } + + // 如果只有一个子表达式,直接替换 + if (child_exprs.size() == 1) { + expr = std::move(child_exprs.front()); + changed = true; + } + } + + return changed; +} + diff --git a/src/observer/sql/optimizer/cascade/transformation_rules.h b/src/observer/sql/optimizer/cascade/transformation_rules.h new file mode 100644 index 000000000..ae982e9a2 --- /dev/null +++ b/src/observer/sql/optimizer/cascade/transformation_rules.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2021 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. */ + +#pragma once + +#include "sql/optimizer/cascade/rules.h" + +class Expression; + +/** + * Rule transforms Filter(TableGet) -> TableGet with predicates + * 谓词下推:将 Filter 中的谓词下推到 TableGet 算子中 + */ +class PredicatePushdownRule : public Rule +{ +public: + PredicatePushdownRule(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; + +/** + * Rule transforms Filter(Filter(...)) -> Filter(...) or removes Filter + * 谓词重写:删除恒真/恒假的谓词 + */ +class PredicateRewriteRule : public Rule +{ +public: + PredicateRewriteRule(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; + +/** + * Rule simplifies expressions in logical operators + * 表达式简化:简化比较表达式和联结表达式 + */ +class ExpressionSimplifyRule : public Rule +{ +public: + ExpressionSimplifyRule(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; + +private: + // 简化表达式,返回是否发生变化 + bool simplify_expression(unique_ptr &expr) const; +}; + diff --git a/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp b/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp deleted file mode 100644 index 4fad78560..000000000 --- a/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2021 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/13. -// - -#include "sql/optimizer/rewrite/comparison_simplification_rule.h" -#include "common/log/log.h" -#include "sql/expr/expression.h" - -RC ComparisonSimplificationRule::rewrite(unique_ptr &expr, bool &change_made) -{ - RC rc = RC::SUCCESS; - - change_made = false; - if (expr->type() == ExprType::COMPARISON) { - Value value; - - ComparisonExpr *cmp_expr = static_cast(expr.get()); - - RC sub_rc = cmp_expr->try_get_value(value); - if (sub_rc == RC::SUCCESS) { - unique_ptr new_expr(new ValueExpr(value)); - expr.swap(new_expr); - change_made = true; - LOG_TRACE("comparison expression is simplified"); - } - } - return rc; -} diff --git a/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h b/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h deleted file mode 100644 index 6032e38cc..000000000 --- a/src/observer/sql/optimizer/rewrite/comparison_simplification_rule.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2021 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/13. -// - -#pragma once - -#include "common/sys/rc.h" -#include "sql/optimizer/rewrite/rewrite_rule.h" - -class LogicalOperator; - -/** - * @brief 简单比较的重写规则 - * @ingroup Rewriter - * @details 如果有简单的比较运算,比如比较的两边都是常量,那我们就可以在运行执行计划之前就知道结果, - * 进而直接将表达式改成结果,这样就可以减少运行时的计算量。 - */ -class ComparisonSimplificationRule : public ExpressionRewriteRule -{ -public: - ComparisonSimplificationRule() = default; - virtual ~ComparisonSimplificationRule() = default; - - RC rewrite(unique_ptr &expr, bool &change_made) override; - -private: -}; diff --git a/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp b/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp deleted file mode 100644 index 14467fe22..000000000 --- a/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (c) 2021 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/26. -// - -#include "sql/optimizer/rewrite/conjunction_simplification_rule.h" -#include "common/log/log.h" -#include "sql/expr/expression.h" - -RC try_to_get_bool_constant(unique_ptr &expr, bool &constant_value) -{ - if (expr->type() == ExprType::VALUE && expr->value_type() == AttrType::BOOLEANS) { - auto value_expr = static_cast(expr.get()); - constant_value = value_expr->get_value().get_boolean(); - return RC::SUCCESS; - } - return RC::INTERNAL; -} -RC ConjunctionSimplificationRule::rewrite(unique_ptr &expr, bool &change_made) -{ - RC rc = RC::SUCCESS; - if (expr->type() != ExprType::CONJUNCTION) { - return rc; - } - - change_made = false; - auto conjunction_expr = static_cast(expr.get()); - - vector> &child_exprs = conjunction_expr->children(); - - // 先看看有没有能够直接去掉的表达式。比如AND时恒为true的表达式可以删除 - // 或者是否可以直接计算出当前表达式的值。比如AND时,如果有一个表达式为false,那么整个表达式就是false - for (auto iter = child_exprs.begin(); iter != child_exprs.end();) { - bool constant_value = false; - - rc = try_to_get_bool_constant(*iter, constant_value); - if (rc != RC::SUCCESS) { - rc = RC::SUCCESS; - ++iter; - continue; - } - - if (conjunction_expr->conjunction_type() == ConjunctionExpr::Type::AND) { - if (constant_value == true) { - child_exprs.erase(iter); - } else { - // always be false - unique_ptr child_expr = std::move(child_exprs.front()); - child_exprs.clear(); - expr = std::move(child_expr); - return rc; - } - } else { - // conjunction_type == OR - if (constant_value == true) { - // always be true - unique_ptr child_expr = std::move(child_exprs.front()); - child_exprs.clear(); - expr = std::move(child_expr); - return rc; - } else { - child_exprs.erase(iter); - } - } - } - if (child_exprs.size() == 1) { - LOG_TRACE("conjunction expression has only 1 child"); - unique_ptr child_expr = std::move(child_exprs.front()); - child_exprs.clear(); - expr = std::move(child_expr); - - change_made = true; - } - - return rc; -} diff --git a/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h b/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h deleted file mode 100644 index 952f60c35..000000000 --- a/src/observer/sql/optimizer/rewrite/conjunction_simplification_rule.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2021 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/26. -// - -#pragma once - -#include "sql/optimizer/rewrite/rewrite_rule.h" - -class LogicalOperator; - -/** - * @brief 简化多个表达式联结的运算 - * @ingroup Rewriter - * @details 比如只有一个表达式,或者表达式可以直接出来 - */ -class ConjunctionSimplificationRule : public ExpressionRewriteRule -{ -public: - ConjunctionSimplificationRule() = default; - virtual ~ConjunctionSimplificationRule() = default; - - RC rewrite(unique_ptr &expr, bool &change_made) override; - -private: -}; diff --git a/src/observer/sql/optimizer/rewrite/expression_rewriter.cpp b/src/observer/sql/optimizer/rewrite/expression_rewriter.cpp deleted file mode 100644 index 7aa5829bb..000000000 --- a/src/observer/sql/optimizer/rewrite/expression_rewriter.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* Copyright (c) 2021 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/13. -// - -#include "sql/optimizer/rewrite/expression_rewriter.h" -#include "common/log/log.h" -#include "sql/optimizer/rewrite/comparison_simplification_rule.h" -#include "sql/optimizer/rewrite/conjunction_simplification_rule.h" - -using namespace std; - -ExpressionRewriter::ExpressionRewriter() -{ - expr_rewrite_rules_.emplace_back(new ComparisonSimplificationRule); - expr_rewrite_rules_.emplace_back(new ConjunctionSimplificationRule); -} - -RC ExpressionRewriter::rewrite(unique_ptr &oper, bool &change_made) -{ - RC rc = RC::SUCCESS; - - bool sub_change_made = false; - - vector> &expressions = oper->expressions(); - for (unique_ptr &expr : expressions) { - rc = rewrite_expression(expr, sub_change_made); - if (rc != RC::SUCCESS) { - break; - } - - if (sub_change_made && !change_made) { - change_made = true; - } - } - - if (rc != RC::SUCCESS) { - return rc; - } - - vector> &child_opers = oper->children(); - for (unique_ptr &child_oper : child_opers) { - bool sub_change_made = false; - rc = rewrite(child_oper, sub_change_made); - if (sub_change_made && !change_made) { - change_made = true; - } - if (rc != RC::SUCCESS) { - break; - } - } - return rc; -} - -RC ExpressionRewriter::rewrite_expression(unique_ptr &expr, bool &change_made) -{ - RC rc = RC::SUCCESS; - - change_made = false; - for (unique_ptr &rule : expr_rewrite_rules_) { - bool sub_change_made = false; - - rc = rule->rewrite(expr, sub_change_made); - if (sub_change_made && !change_made) { - change_made = true; - } - if (rc != RC::SUCCESS) { - break; - } - } - - if (change_made || rc != RC::SUCCESS) { - return rc; - } - - switch (expr->type()) { - case ExprType::FIELD: - case ExprType::VALUE: { - // do nothing - } break; - - case ExprType::CAST: { - unique_ptr &child_expr = (static_cast(expr.get()))->child(); - - rc = rewrite_expression(child_expr, change_made); - } break; - - case ExprType::COMPARISON: { - auto comparison_expr = static_cast(expr.get()); - - unique_ptr &left_expr = comparison_expr->left(); - unique_ptr &right_expr = comparison_expr->right(); - - bool left_change_made = false; - - rc = rewrite_expression(left_expr, left_change_made); - if (rc != RC::SUCCESS) { - return rc; - } - - bool right_change_made = false; - - rc = rewrite_expression(right_expr, right_change_made); - if (rc != RC::SUCCESS) { - return rc; - } - - if (left_change_made || right_change_made) { - change_made = true; - } - } break; - - case ExprType::CONJUNCTION: { - auto conjunction_expr = static_cast(expr.get()); - - vector> &children = conjunction_expr->children(); - for (unique_ptr &child_expr : children) { - bool sub_change_made = false; - - rc = rewrite_expression(child_expr, sub_change_made); - if (rc != RC::SUCCESS) { - - LOG_WARN("failed to rewriter conjunction sub expression. rc=%s", strrc(rc)); - return rc; - } - - if (sub_change_made && !change_made) { - change_made = true; - } - } - } break; - - default: { - // do nothing - } break; - } - return rc; -} diff --git a/src/observer/sql/optimizer/rewrite/expression_rewriter.h b/src/observer/sql/optimizer/rewrite/expression_rewriter.h deleted file mode 100644 index 023d2531d..000000000 --- a/src/observer/sql/optimizer/rewrite/expression_rewriter.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2021 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/13. -// - -#pragma once - -#include "common/lang/memory.h" -#include "common/sys/rc.h" -#include "sql/expr/expression.h" -#include "sql/operator/logical_operator.h" -#include "sql/optimizer/rewrite/rewrite_rule.h" - -class ExpressionRewriter : public RewriteRule -{ -public: - ExpressionRewriter(); - virtual ~ExpressionRewriter() = default; - - RC rewrite(unique_ptr &oper, bool &change_made) override; - -private: - RC rewrite_expression(unique_ptr &expr, bool &change_made); - -private: - vector> expr_rewrite_rules_; -}; diff --git a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp deleted file mode 100644 index a2261652d..000000000 --- a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (c) 2021 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/30. -// - -#include "sql/optimizer/rewrite/predicate_pushdown_rewriter.h" -#include "common/log/log.h" -#include "sql/expr/expression.h" -#include "sql/operator/logical_operator.h" -#include "sql/operator/logical/table_get_logical_operator.h" - -RC PredicatePushdownRewriter::rewrite(unique_ptr &oper, bool &change_made) -{ - RC rc = RC::SUCCESS; - if (oper->get_op_type() != OpType::LOGICALFILTER) { - return rc; - } - - if (oper->children().size() != 1) { - return rc; - } - - unique_ptr &child_oper = oper->children().front(); - if (child_oper->get_op_type() != OpType::LOGICALGET) { - return rc; - } - - auto table_get_oper = static_cast(child_oper.get()); - - vector> &predicate_oper_exprs = oper->expressions(); - if (predicate_oper_exprs.size() != 1) { - return rc; - } - - unique_ptr &predicate_expr = predicate_oper_exprs.front(); - vector> pushdown_exprs; - rc = get_exprs_can_pushdown(predicate_expr, pushdown_exprs); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to get exprs can pushdown. rc=%s", strrc(rc)); - return rc; - } - - if (!predicate_expr || is_empty_predicate(predicate_expr)) { - // 所有的表达式都下推到了下层算子 - // 这个predicate operator其实就可以不要了。但是这里没办法删除,弄一个空的表达式吧 - LOG_TRACE("all expressions of predicate operator were pushdown to table get operator, then make a fake one"); - - Value value((bool)true); - predicate_expr = unique_ptr(new ValueExpr(value)); - } - - if (!pushdown_exprs.empty()) { - change_made = true; - table_get_oper->set_predicates(std::move(pushdown_exprs)); - } - return rc; -} - -bool PredicatePushdownRewriter::is_empty_predicate(unique_ptr &expr) -{ - bool bool_ret = false; - if (!expr) { - return true; - } - - if (expr->type() == ExprType::CONJUNCTION) { - ConjunctionExpr *conjunction_expr = static_cast(expr.get()); - if (conjunction_expr->children().empty()) { - bool_ret = true; - } - } - - return bool_ret; -} - -/** - * 查看表达式是否可以直接下放到table get算子的filter - * @param expr 是当前的表达式。如果可以下放给table get 算子,执行完成后expr就失效了 - * @param pushdown_exprs 当前所有要下放给table get 算子的filter。此函数执行多次, - * pushdown_exprs 只会增加,不要做清理操作 - */ -RC PredicatePushdownRewriter::get_exprs_can_pushdown( - unique_ptr &expr, vector> &pushdown_exprs) -{ - RC rc = RC::SUCCESS; - if (expr->type() == ExprType::CONJUNCTION) { - ConjunctionExpr *conjunction_expr = static_cast(expr.get()); - // 或 操作的比较,太复杂,现在不考虑 - if (conjunction_expr->conjunction_type() == ConjunctionExpr::Type::OR) { - LOG_WARN("unsupported or operation"); - rc = RC::UNIMPLEMENTED; - return rc; - } - - vector> &child_exprs = conjunction_expr->children(); - for (auto iter = child_exprs.begin(); iter != child_exprs.end();) { - // 对每个子表达式,判断是否可以下放到table get 算子 - // 如果可以的话,就从当前孩子节点中删除他 - rc = get_exprs_can_pushdown(*iter, pushdown_exprs); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to get pushdown expressions. rc=%s", strrc(rc)); - return rc; - } - - if (!*iter) { - iter = child_exprs.erase(iter); - } else { - ++iter; - } - } - } else if (expr->type() == ExprType::COMPARISON) { - // 如果是比较操作,并且比较的左边或右边是表某个列值,那么就下推下去 - - pushdown_exprs.emplace_back(std::move(expr)); - } - return rc; -} diff --git a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h b/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h deleted file mode 100644 index 36097482a..000000000 --- a/src/observer/sql/optimizer/rewrite/predicate_pushdown_rewriter.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2021 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/30. -// - -#pragma once - -#include "common/lang/vector.h" -#include "sql/optimizer/rewrite/rewrite_rule.h" - -/** - * @brief 将一些谓词表达式下推到表数据扫描中 - * @ingroup Rewriter - * @details 这样可以提前过滤一些数据 - */ -class PredicatePushdownRewriter : public RewriteRule -{ -public: - PredicatePushdownRewriter() = default; - virtual ~PredicatePushdownRewriter() = default; - - RC rewrite(unique_ptr &oper, bool &change_made) override; - -private: - RC get_exprs_can_pushdown(unique_ptr &expr, vector> &pushdown_exprs); - bool is_empty_predicate(unique_ptr &expr); -}; diff --git a/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp b/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp deleted file mode 100644 index 987eaa0b2..000000000 --- a/src/observer/sql/optimizer/rewrite/predicate_rewrite.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2021 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/29. -// - -#include "sql/optimizer/rewrite/predicate_rewrite.h" -#include "sql/operator/logical_operator.h" - -RC PredicateRewriteRule::rewrite(unique_ptr &oper, bool &change_made) -{ - vector> &child_opers = oper->children(); - if (child_opers.size() != 1) { - return RC::SUCCESS; - } - - auto &child_oper = child_opers.front(); - if (child_oper->get_op_type() != OpType::LOGICALFILTER) { - return RC::SUCCESS; - } - - vector> &expressions = child_oper->expressions(); - if (expressions.size() != 1) { - return RC::SUCCESS; - } - - unique_ptr &expr = expressions.front(); - if (expr->type() != ExprType::VALUE) { - return RC::SUCCESS; - } - - // 如果仅有的一个子节点是predicate - // 并且这个子节点可以判断为恒为TRUE,那么可以省略这个子节点,并把他的子节点们(就是孙子节点)接管过来 - // 如果可以判断恒为false,那么就可以删除子节点 - auto value_expr = static_cast(expr.get()); - bool bool_value = value_expr->get_value().get_boolean(); - if (true == bool_value) { - vector> grand_child_opers; - grand_child_opers.swap(child_oper->children()); - child_opers.clear(); - for (auto &grand_child_oper : grand_child_opers) { - oper->add_child(std::move(grand_child_oper)); - } - } else { - child_opers.clear(); - } - - change_made = true; - return RC::SUCCESS; -} diff --git a/src/observer/sql/optimizer/rewrite/predicate_rewrite.h b/src/observer/sql/optimizer/rewrite/predicate_rewrite.h deleted file mode 100644 index 349a712d1..000000000 --- a/src/observer/sql/optimizer/rewrite/predicate_rewrite.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (c) 2021 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/29. -// - -#pragma once - -#include "sql/optimizer/rewrite/rewrite_rule.h" - -/** - * @brief 谓词重写规则 - * @ingroup Rewriter - * @details 有些谓词可以在真正运行之前就知道结果,那么就可以提前运算出来,比如1=1,1=0。 - */ -class PredicateRewriteRule : public RewriteRule -{ -public: - PredicateRewriteRule() = default; - virtual ~PredicateRewriteRule() = default; - - RC rewrite(unique_ptr &oper, bool &change_made) override; -}; diff --git a/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp b/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp deleted file mode 100644 index 6a8bfca47..000000000 --- a/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) 2021 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. */ - -#include "sql/optimizer/rewrite/predicate_to_join_rule.h" diff --git a/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h b/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h deleted file mode 100644 index a70313657..000000000 --- a/src/observer/sql/optimizer/rewrite/predicate_to_join_rule.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (c) 2021 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. */ - -#pragma once - -#include "common/lang/vector.h" -#include "sql/optimizer/rewrite/rewrite_rule.h" - -/** - * @brief 将一些谓词表达式下推到join中 - * @ingroup Rewriter - */ -class PredicateToJoinRewriter -{}; diff --git a/src/observer/sql/optimizer/rewrite/rewrite_rule.h b/src/observer/sql/optimizer/rewrite/rewrite_rule.h deleted file mode 100644 index 894273d4a..000000000 --- a/src/observer/sql/optimizer/rewrite/rewrite_rule.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2021 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/13. -// - -#pragma once - -#include "common/sys/rc.h" -#include "common/lang/memory.h" - -class LogicalOperator; -class Expression; - -/** - * @brief 逻辑计划的重写规则 - * @ingroup Rewriter - * TODO: 重构下当前的查询改写规则,放到 cascade optimizer 中。 - */ -class RewriteRule -{ -public: - virtual ~RewriteRule() = default; - - virtual RC rewrite(unique_ptr &oper, bool &change_made) = 0; -}; - -/** - * @brief 表达式的重写规则 - * @ingroup Rewriter - */ -class ExpressionRewriteRule -{ -public: - virtual ~ExpressionRewriteRule() = default; - - virtual RC rewrite(unique_ptr &expr, bool &change_made) = 0; -}; diff --git a/src/observer/sql/optimizer/rewrite/rewriter.cpp b/src/observer/sql/optimizer/rewrite/rewriter.cpp deleted file mode 100644 index e067f484e..000000000 --- a/src/observer/sql/optimizer/rewrite/rewriter.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2021 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/29. -// - -#include "sql/optimizer/rewrite/rewriter.h" -#include "common/log/log.h" -#include "sql/operator/logical_operator.h" -#include "sql/optimizer/rewrite/expression_rewriter.h" -#include "sql/optimizer/rewrite/predicate_pushdown_rewriter.h" -#include "sql/optimizer/rewrite/predicate_rewrite.h" - -Rewriter::Rewriter() -{ - rewrite_rules_.emplace_back(new ExpressionRewriter); - rewrite_rules_.emplace_back(new PredicateRewriteRule); - rewrite_rules_.emplace_back(new PredicatePushdownRewriter); -} - -RC Rewriter::rewrite(unique_ptr &oper, bool &change_made) -{ - RC rc = RC::SUCCESS; - - change_made = false; - for (unique_ptr &rule : rewrite_rules_) { - bool sub_change_made = false; - - rc = rule->rewrite(oper, sub_change_made); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to rewrite logical operator. rc=%s", strrc(rc)); - return rc; - } - - if (sub_change_made && !change_made) { - change_made = true; - } - } - - if (rc != RC::SUCCESS) { - return rc; - } - - vector> &child_opers = oper->children(); - for (auto &child_oper : child_opers) { - bool sub_change_made = false; - rc = this->rewrite(child_oper, sub_change_made); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to rewrite child oper. rc=%s", strrc(rc)); - return rc; - } - - if (sub_change_made && !change_made) { - change_made = true; - } - } - return rc; -} diff --git a/src/observer/sql/optimizer/rewrite/rewriter.h b/src/observer/sql/optimizer/rewrite/rewriter.h deleted file mode 100644 index 5df11bcb6..000000000 --- a/src/observer/sql/optimizer/rewrite/rewriter.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (c) 2021 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/29. -// - -#pragma once - -#include "sql/optimizer/rewrite/rewrite_rule.h" -#include "common/lang/memory.h" -#include "common/lang/vector.h" - -class LogicalOperator; - -/** - * @defgroup Rewriter - * @brief 根据规则对逻辑计划进行重写 - * TODO: refactor with cascade optimizer - */ - -/** - * @brief 根据一些规则对逻辑计划进行重写 - * @ingroup Rewriter - * @details 当前仅实现了一两个非常简单的规则。 - * 重写包括对逻辑计划和计划中包含的表达式。 - */ -class Rewriter -{ -public: - Rewriter(); - virtual ~Rewriter() = default; - - /** - * @brief 对逻辑计划进行重写 - * @details 如果重写发生,change_made为true,否则为false。 - * 通常情况下如果改写发生改变,就会继续重写,直到没有改变为止。 - * @param oper 逻辑计划 - * @param change_made 当前是否有重写发生 - */ - RC rewrite(unique_ptr &oper, bool &change_made); - -private: - vector> rewrite_rules_; -}; From ed855ccedb7334cb686910c2ec45c471d9f1e423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Wed, 26 Nov 2025 10:55:12 +0800 Subject: [PATCH 07/12] refactor(operator): Improve the comparison between operators --- .../logical/delete_logical_operator.h | 16 ++++++++ .../logical/group_by_logical_operator.h | 39 +++++++++++++++++- .../logical/insert_logical_operator.h | 25 +++++++++++ .../operator/logical/join_logical_operator.h | 26 +++++++++++- .../logical/project_logical_operator.h | 3 -- .../logical/table_get_logical_operator.h | 17 +++++++- .../sql/operator/logical_operator.cpp | 16 ++------ src/observer/sql/operator/logical_operator.h | 33 +++++++++++---- .../physical/calc_physical_operator.h | 24 +++++++++++ .../physical/delete_physical_operator.h | 15 +++++++ .../physical/group_by_physical_operator.h | 41 +++++++++++++++++++ .../hash_group_by_physical_operator.h | 26 ++++++++++++ .../physical/index_scan_physical_operator.h | 38 +++++++++++++++++ .../physical/insert_physical_operator.h | 26 ++++++++++++ .../physical/predicate_physical_operator.h | 21 ++++++++++ .../physical/project_physical_operator.h | 24 +++++++++++ .../physical/table_scan_physical_operator.h | 4 +- 17 files changed, 365 insertions(+), 29 deletions(-) diff --git a/src/observer/sql/operator/logical/delete_logical_operator.h b/src/observer/sql/operator/logical/delete_logical_operator.h index 929f19e18..575faee47 100644 --- a/src/observer/sql/operator/logical/delete_logical_operator.h +++ b/src/observer/sql/operator/logical/delete_logical_operator.h @@ -27,6 +27,22 @@ class DeleteLogicalOperator : public LogicalOperator virtual ~DeleteLogicalOperator() = default; OpType get_op_type() const override { return OpType::LOGICALDELETE; } + + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(table_->table_id()); + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_delete = static_cast(other); + return table_->table_id() == other_delete.table()->table_id(); + } + Table *table() const { return table_; } private: diff --git a/src/observer/sql/operator/logical/group_by_logical_operator.h b/src/observer/sql/operator/logical/group_by_logical_operator.h index a7cf11c12..610dc7a34 100644 --- a/src/observer/sql/operator/logical/group_by_logical_operator.h +++ b/src/observer/sql/operator/logical/group_by_logical_operator.h @@ -25,10 +25,47 @@ class GroupByLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALGROUPBY; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(group_by_expressions_.size()); + hash ^= std::hash()(aggregate_expressions_.size()); + for (const auto &expr : group_by_expressions_) { + hash ^= std::hash()(static_cast(expr->type())); + } + for (const auto &expr : aggregate_expressions_) { + hash ^= std::hash()(static_cast(expr->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_gb = static_cast(other); + if (group_by_expressions_.size() != other_gb.group_by_expressions_.size()) + return false; + if (aggregate_expressions_.size() != other_gb.aggregate_expressions_.size()) + return false; + for (size_t i = 0; i < group_by_expressions_.size(); i++) { + if (!group_by_expressions_[i]->equal(*(other_gb.group_by_expressions_[i]))) + return false; + } + for (size_t i = 0; i < aggregate_expressions_.size(); i++) { + if (aggregate_expressions_[i] != other_gb.aggregate_expressions_[i]) { + // 对于 Expression*,比较指针是否相同 + // 如果需要深度比较,可以使用 equal,但这里 Expression* 可能指向同一个对象 + return false; + } + } + return true; + } + auto &group_by_expressions() { return group_by_expressions_; } auto &aggregate_expressions() { return aggregate_expressions_; } private: - vector> group_by_expressions_; + vector> &group_by_expressions_ = expressions_; vector aggregate_expressions_; ///< 输出的表达式,可能包含聚合函数 }; diff --git a/src/observer/sql/operator/logical/insert_logical_operator.h b/src/observer/sql/operator/logical/insert_logical_operator.h index c9a624e62..886228f3d 100644 --- a/src/observer/sql/operator/logical/insert_logical_operator.h +++ b/src/observer/sql/operator/logical/insert_logical_operator.h @@ -29,6 +29,31 @@ class InsertLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALINSERT; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(table_->table_id()); + hash ^= std::hash()(values_.size()); + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_insert = static_cast(other); + if (table_->table_id() != other_insert.table()->table_id()) + return false; + if (values_.size() != other_insert.values().size()) + return false; + // 比较 values(Value 使用 compare 方法) + for (size_t i = 0; i < values_.size(); i++) { + if (values_[i].compare(other_insert.values()[i]) != 0) + return false; + } + return true; + } + Table *table() const { return table_; } const vector &values() const { return values_; } vector &values() { return values_; } diff --git a/src/observer/sql/operator/logical/join_logical_operator.h b/src/observer/sql/operator/logical/join_logical_operator.h index 2da7dd351..e3946cad0 100644 --- a/src/observer/sql/operator/logical/join_logical_operator.h +++ b/src/observer/sql/operator/logical/join_logical_operator.h @@ -38,6 +38,30 @@ class JoinLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALINNERJOIN; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(join_predicates_.size()); + for (const auto &pred : join_predicates_) { + hash ^= std::hash()(static_cast(pred->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_join = static_cast(other); + if (join_predicates_.size() != other_join.join_predicates_.size()) + return false; + for (size_t i = 0; i < join_predicates_.size(); i++) { + if (!join_predicates_[i]->equal(*(other_join.join_predicates_[i]))) + return false; + } + return true; + } + vector> &get_join_predicates() { return join_predicates_; } void clear_join_predicates() { join_predicates_.clear(); } @@ -70,5 +94,5 @@ class JoinLogicalOperator : public LogicalOperator private: LogicalOperator *predicate_op_ = nullptr; - std::vector> join_predicates_; + std::vector> &join_predicates_ = expressions_; }; diff --git a/src/observer/sql/operator/logical/project_logical_operator.h b/src/observer/sql/operator/logical/project_logical_operator.h index da3a9de6d..45850aa41 100644 --- a/src/observer/sql/operator/logical/project_logical_operator.h +++ b/src/observer/sql/operator/logical/project_logical_operator.h @@ -31,7 +31,4 @@ class ProjectLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALPROJECTION; } unique_ptr find_log_prop(const vector &log_props) override; - - vector> &expressions() { return expressions_; } - const vector> &expressions() const { return expressions_; } }; diff --git a/src/observer/sql/operator/logical/table_get_logical_operator.h b/src/observer/sql/operator/logical/table_get_logical_operator.h index 3dca6f69b..6ec549648 100644 --- a/src/observer/sql/operator/logical/table_get_logical_operator.h +++ b/src/observer/sql/operator/logical/table_get_logical_operator.h @@ -34,6 +34,12 @@ class TableGetLogicalOperator : public LogicalOperator { uint64_t hash = std::hash()(static_cast(get_op_type())); hash ^= std::hash()(table_->table_id()); + // 将 predicates 也加入 hash 计算 + hash ^= std::hash()(predicates_.size()); + for (const auto &pred : predicates_) { + // 使用 Expression 的类型和基本特征来生成 hash + hash ^= std::hash()(static_cast(pred->type())); + } return hash; } @@ -41,9 +47,16 @@ class TableGetLogicalOperator : public LogicalOperator { if (get_op_type() != other.get_op_type()) return false; - const auto &other_get = dynamic_cast(&other); - if (table_->table_id() != other_get->table()->table_id()) + const auto &other_get = static_cast(other); + if (table_->table_id() != other_get.table()->table_id()) return false; + // 比较 predicates:数量必须相同,且每个 predicate 必须相等 + if (predicates_.size() != other_get.predicates_.size()) + return false; + for (size_t i = 0; i < predicates_.size(); i++) { + if (!predicates_[i]->equal(*(other_get.predicates_[i]))) + return false; + } return true; } diff --git a/src/observer/sql/operator/logical_operator.cpp b/src/observer/sql/operator/logical_operator.cpp index 4f6c4bc6c..5fb4d00b4 100644 --- a/src/observer/sql/operator/logical_operator.cpp +++ b/src/observer/sql/operator/logical_operator.cpp @@ -16,11 +16,10 @@ See the Mulan PSL v2 for more details. */ LogicalOperator::~LogicalOperator() {} -void LogicalOperator::add_child(unique_ptr oper) { - children_.emplace_back(std::move(oper)); +void LogicalOperator::add_expressions(unique_ptr expr) { + expressions_.emplace_back(std::move(expr)); } -void LogicalOperator::add_expressions(unique_ptr expr) { expressions_.emplace_back(std::move(expr)); } -bool LogicalOperator::can_generate_vectorized_operator(const OpType &type) +bool LogicalOperator::can_generate_vectorized_operator(OpType type) { bool bool_ret = false; switch (type) @@ -37,12 +36,3 @@ bool LogicalOperator::can_generate_vectorized_operator(const OpType &type) } return bool_ret; } - -void LogicalOperator::generate_general_child() -{ - for (auto &child : children_) { - general_children_.push_back(child.get()); - child->generate_general_child(); - } -} - diff --git a/src/observer/sql/operator/logical_operator.h b/src/observer/sql/operator/logical_operator.h index cd3afed88..6f548dc2d 100644 --- a/src/observer/sql/operator/logical_operator.h +++ b/src/observer/sql/operator/logical_operator.h @@ -38,17 +38,36 @@ class LogicalOperator : public OperatorNode bool is_physical() const override { return false; } bool is_logical() const override { return true; } - void add_child(unique_ptr oper); void add_expressions(unique_ptr expr); - auto children() -> vector> &{ return children_; } auto expressions() -> vector> &{ return expressions_; } - static bool can_generate_vectorized_operator(const OpType &type); - // TODO: used by cascade optimizer, tmp function, need to be remove - void generate_general_child(); + const vector> &expressions() const { return expressions_; } + static bool can_generate_vectorized_operator(OpType type); -protected: - vector> children_; ///< 子算子 + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(expressions_.size()); + for (const auto &expr : expressions_) { + hash ^= std::hash()(static_cast(expr->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_logi = static_cast(other); + if (expressions_.size() != other_logi.expressions_.size()) + return false; + for (size_t i = 0; i < expressions_.size(); i++) { + if (!expressions_[i]->equal(*(other_logi.expressions_[i]))) + return false; + } + return true; + } +protected: ///< 表达式,比如select中的列,where中的谓词等等,都可以使用表达式来表示 ///< 表达式能是一个常量,也可以是一个函数,也可以是一个列,也可以是一个子查询等等 vector> expressions_; diff --git a/src/observer/sql/operator/physical/calc_physical_operator.h b/src/observer/sql/operator/physical/calc_physical_operator.h index 13ed43ac2..70a0b0aa7 100644 --- a/src/observer/sql/operator/physical/calc_physical_operator.h +++ b/src/observer/sql/operator/physical/calc_physical_operator.h @@ -28,6 +28,30 @@ class CalcPhysicalOperator : public PhysicalOperator OpType get_op_type() const override { return OpType::CALCULATE; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(expressions_.size()); + for (const auto &expr : expressions_) { + hash ^= std::hash()(static_cast(expr->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_calc = static_cast(other); + if (expressions_.size() != other_calc.expressions_.size()) + return false; + for (size_t i = 0; i < expressions_.size(); i++) { + if (!expressions_[i]->equal(*(other_calc.expressions_[i]))) + return false; + } + return true; + } + string name() const override { return "CALC"; } string param() const override { return ""; } diff --git a/src/observer/sql/operator/physical/delete_physical_operator.h b/src/observer/sql/operator/physical/delete_physical_operator.h index 2168ab353..41322da7e 100644 --- a/src/observer/sql/operator/physical/delete_physical_operator.h +++ b/src/observer/sql/operator/physical/delete_physical_operator.h @@ -32,6 +32,21 @@ class DeletePhysicalOperator : public PhysicalOperator OpType get_op_type() const override { return OpType::DELETE; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(table_->table_id()); + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_delete = static_cast(other); + return table_->table_id() == other_delete.table_->table_id(); + } + RC open(Trx *trx) override; RC next() override; RC close() override; diff --git a/src/observer/sql/operator/physical/group_by_physical_operator.h b/src/observer/sql/operator/physical/group_by_physical_operator.h index 5c7a8f3ef..d7af27af6 100644 --- a/src/observer/sql/operator/physical/group_by_physical_operator.h +++ b/src/observer/sql/operator/physical/group_by_physical_operator.h @@ -28,6 +28,47 @@ class GroupByPhysicalOperator : public PhysicalOperator GroupByPhysicalOperator(vector &&expressions); virtual ~GroupByPhysicalOperator() = default; + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(aggregate_expressions_.size()); + hash ^= std::hash()(value_expressions_.size()); + for (const auto &expr : aggregate_expressions_) { + if (expr) { + hash ^= std::hash()(static_cast(expr->type())); + } + } + for (const auto &expr : value_expressions_) { + if (expr) { + hash ^= std::hash()(static_cast(expr->type())); + } + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_gb = static_cast(other); + if (aggregate_expressions_.size() != other_gb.aggregate_expressions_.size()) + return false; + if (value_expressions_.size() != other_gb.value_expressions_.size()) + return false; + for (size_t i = 0; i < aggregate_expressions_.size(); i++) { + if (aggregate_expressions_[i] != other_gb.aggregate_expressions_[i]) { + // 对于 Expression*,比较指针是否相同 + return false; + } + } + for (size_t i = 0; i < value_expressions_.size(); i++) { + if (value_expressions_[i] != other_gb.value_expressions_[i]) { + return false; + } + } + return true; + } + protected: using AggregatorList = vector>; /** diff --git a/src/observer/sql/operator/physical/hash_group_by_physical_operator.h b/src/observer/sql/operator/physical/hash_group_by_physical_operator.h index eefd55d82..cfc81af48 100644 --- a/src/observer/sql/operator/physical/hash_group_by_physical_operator.h +++ b/src/observer/sql/operator/physical/hash_group_by_physical_operator.h @@ -33,6 +33,32 @@ class HashGroupByPhysicalOperator : public GroupByPhysicalOperator OpType get_op_type() const override { return OpType::HASHGROUPBY; } + virtual uint64_t hash() const override + { + uint64_t hash = GroupByPhysicalOperator::hash(); + hash ^= std::hash()(group_by_exprs_.size()); + for (const auto &expr : group_by_exprs_) { + hash ^= std::hash()(static_cast(expr->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + if (!GroupByPhysicalOperator::operator==(other)) + return false; + const auto &other_hash_gb = static_cast(other); + if (group_by_exprs_.size() != other_hash_gb.group_by_exprs_.size()) + return false; + for (size_t i = 0; i < group_by_exprs_.size(); i++) { + if (!group_by_exprs_[i]->equal(*(other_hash_gb.group_by_exprs_[i]))) + return false; + } + return true; + } + RC open(Trx *trx) override; RC next() override; RC close() override; diff --git a/src/observer/sql/operator/physical/index_scan_physical_operator.h b/src/observer/sql/operator/physical/index_scan_physical_operator.h index 13e2797ca..5bc14f2a5 100644 --- a/src/observer/sql/operator/physical/index_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/index_scan_physical_operator.h @@ -32,6 +32,44 @@ class IndexScanPhysicalOperator : public PhysicalOperator OpType get_op_type() const override { return OpType::INDEXSCAN; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(table_->table_id()); + if (index_) { + hash ^= std::hash()(index_); + } + hash ^= std::hash()(predicates_.size()); + hash ^= std::hash()(left_inclusive_); + hash ^= std::hash()(right_inclusive_); + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_scan = static_cast(other); + if (table_->table_id() != other_scan.table_->table_id()) + return false; + if (index_ != other_scan.index_) + return false; + if (left_inclusive_ != other_scan.left_inclusive_ || right_inclusive_ != other_scan.right_inclusive_) + return false; + if (predicates_.size() != other_scan.predicates_.size()) + return false; + for (size_t i = 0; i < predicates_.size(); i++) { + if (!predicates_[i]->equal(*(other_scan.predicates_[i]))) + return false; + } + // 比较 left_value_ 和 right_value_ + if (left_value_.compare(other_scan.left_value_) != 0) + return false; + if (right_value_.compare(other_scan.right_value_) != 0) + return false; + return true; + } + string param() const override; RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/physical/insert_physical_operator.h b/src/observer/sql/operator/physical/insert_physical_operator.h index f803f0332..fb3875e88 100644 --- a/src/observer/sql/operator/physical/insert_physical_operator.h +++ b/src/observer/sql/operator/physical/insert_physical_operator.h @@ -32,10 +32,36 @@ class InsertPhysicalOperator : public PhysicalOperator OpType get_op_type() const override { return OpType::INSERT; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(table_->table_id()); + hash ^= std::hash()(values_.size()); + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_insert = static_cast(other); + if (table_->table_id() != other_insert.table()->table_id()) + return false; + if (values_.size() != other_insert.values_.size()) + return false; + for (size_t i = 0; i < values_.size(); i++) { + if (values_[i].compare(other_insert.values_[i]) != 0) + return false; + } + return true; + } + RC open(Trx *trx) override; RC next() override; RC close() override; + Table *table() const { return table_; } + Tuple *current_tuple() override { return nullptr; } private: diff --git a/src/observer/sql/operator/physical/predicate_physical_operator.h b/src/observer/sql/operator/physical/predicate_physical_operator.h index 9ad0fe061..81cce7cd7 100644 --- a/src/observer/sql/operator/physical/predicate_physical_operator.h +++ b/src/observer/sql/operator/physical/predicate_physical_operator.h @@ -32,6 +32,27 @@ class PredicatePhysicalOperator : public PhysicalOperator OpType get_op_type() const override { return OpType::FILTER; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + if (expression_) { + hash ^= std::hash()(static_cast(expression_->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_pred = static_cast(other); + if (expression_ == nullptr && other_pred.expression_ == nullptr) + return true; + if (expression_ == nullptr || other_pred.expression_ == nullptr) + return false; + return expression_->equal(*(other_pred.expression_)); + } + RC open(Trx *trx) override; RC next() override; RC close() override; diff --git a/src/observer/sql/operator/physical/project_physical_operator.h b/src/observer/sql/operator/physical/project_physical_operator.h index a2ad906e8..cb88ae143 100644 --- a/src/observer/sql/operator/physical/project_physical_operator.h +++ b/src/observer/sql/operator/physical/project_physical_operator.h @@ -30,6 +30,30 @@ class ProjectPhysicalOperator : public PhysicalOperator OpType get_op_type() const override { return OpType::PROJECTION; } + virtual uint64_t hash() const override + { + uint64_t hash = std::hash()(static_cast(get_op_type())); + hash ^= std::hash()(expressions_.size()); + for (const auto &expr : expressions_) { + hash ^= std::hash()(static_cast(expr->type())); + } + return hash; + } + + virtual bool operator==(const OperatorNode &other) const override + { + if (get_op_type() != other.get_op_type()) + return false; + const auto &other_proj = static_cast(other); + if (expressions_.size() != other_proj.expressions_.size()) + return false; + for (size_t i = 0; i < expressions_.size(); i++) { + if (!expressions_[i]->equal(*(other_proj.expressions_[i]))) + return false; + } + return true; + } + virtual double calculate_cost( LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override { diff --git a/src/observer/sql/operator/physical/table_scan_physical_operator.h b/src/observer/sql/operator/physical/table_scan_physical_operator.h index 5211e2d24..c15f39169 100644 --- a/src/observer/sql/operator/physical/table_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/table_scan_physical_operator.h @@ -47,8 +47,8 @@ class TableScanPhysicalOperator : public PhysicalOperator { if (get_op_type() != other.get_op_type()) return false; - const auto &other_get = dynamic_cast(&other); - if (table_->table_id() != other_get->table_id()) + const auto &other_get = static_cast(other); + if (table_->table_id() != other_get.table_id()) return false; return true; } From 96551cbee296004b1d4e20dedc49de1aebbe3d08 Mon Sep 17 00:00:00 2001 From: evtrouble Date: Mon, 25 Aug 2025 10:43:03 +0800 Subject: [PATCH 08/12] refactor(cascade): Add cascade error handling --- src/common/sys/rc.h | 1 + .../sql/optimizer/cascade/optimizer.cpp | 48 +++++++++++++------ .../sql/optimizer/cascade/optimizer.h | 8 ++-- .../cascade/tasks/apply_rule_task.cpp | 6 ++- .../optimizer/cascade/tasks/apply_rule_task.h | 2 +- .../optimizer/cascade/tasks/cascade_task.h | 3 +- .../optimizer/cascade/tasks/e_group_task.cpp | 5 +- .../optimizer/cascade/tasks/e_group_task.h | 2 +- .../optimizer/cascade/tasks/o_expr_task.cpp | 3 +- .../sql/optimizer/cascade/tasks/o_expr_task.h | 2 +- .../optimizer/cascade/tasks/o_group_task.cpp | 7 +-- .../optimizer/cascade/tasks/o_group_task.h | 2 +- .../optimizer/cascade/tasks/o_input_task.cpp | 15 +++--- .../optimizer/cascade/tasks/o_input_task.h | 2 +- src/observer/sql/optimizer/optimize_stage.cpp | 10 ++-- 15 files changed, 69 insertions(+), 47 deletions(-) diff --git a/src/common/sys/rc.h b/src/common/sys/rc.h index 767be1e5f..0330c7db5 100644 --- a/src/common/sys/rc.h +++ b/src/common/sys/rc.h @@ -84,6 +84,7 @@ See the Mulan PSL v2 for more details. */ DEFINE_RC(INVALID_TOKEN) \ DEFINE_RC(UNEXPECTED_END_OF_STRING) \ DEFINE_RC(SYNTAX_ERROR) \ + DEFINE_RC(CASCADE_FAIL) \ DEFINE_RC(UNSUPPORTED) enum class RC diff --git a/src/observer/sql/optimizer/cascade/optimizer.cpp b/src/observer/sql/optimizer/cascade/optimizer.cpp index 26dca33ac..12973aeec 100644 --- a/src/observer/sql/optimizer/cascade/optimizer.cpp +++ b/src/observer/sql/optimizer/cascade/optimizer.cpp @@ -12,46 +12,60 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/tasks/o_group_task.h" #include "sql/optimizer/cascade/memo.h" -std::unique_ptr Optimizer::optimize(OperatorNode* op_tree) +RC Optimizer::optimize(unique_ptr op_tree, std::unique_ptr &physical_operator) { // Generate initial operator tree from query tree GroupExpr *gexpr = nullptr; - bool insert = context_->record_node_into_group(op_tree, &gexpr); - ASSERT(insert && gexpr, "Logical expression tree should insert"); + bool insert = context_->record_node_into_group(op_tree.get(), &gexpr); + if(!insert || gexpr == nullptr) { + LOG_ERROR("Logical expression tree should insert"); + return RC::CASCADE_FAIL; + } context_->get_memo().dump(); int root_id = gexpr->get_group_id(); - optimize_loop(root_id); + RC rc = optimize_loop(root_id); + if(OB_FAIL(rc)) { + return rc; + } LOG_TRACE("after optimize, memo dump:"); context_->get_memo().dump(); - return choose_best_plan(root_id); + return choose_best_plan(root_id, physical_operator); } -std::unique_ptr Optimizer::choose_best_plan(int root_group_id) +RC Optimizer::choose_best_plan(int root_group_id, std::unique_ptr &physical_operator) { auto &memo = context_->get_memo(); Group *root_group = memo.get_group_by_id(root_group_id); - ASSERT(root_group != nullptr, "Root group should not be null"); + if(root_group == nullptr) { + LOG_ERROR("Root group should not be null"); + return RC::CASCADE_FAIL; + } // Choose the best physical plan auto winner = root_group->get_winner(); if (winner == nullptr) { LOG_WARN("No winner found in group %d", root_group_id); - return nullptr; + return RC::CASCADE_FAIL; } auto winner_contents = winner->get_op(); context_->get_memo().release_operator(winner_contents); PhysicalOperator* winner_phys = static_cast(winner_contents); LOG_TRACE("winner: %d", winner_phys->get_op_type()); for (const auto& child : winner->get_child_group_ids()) { - winner_phys->add_child(choose_best_plan(child)); + std::unique_ptr child_operator; + RC rc = choose_best_plan(child, child_operator); + if(OB_FAIL(rc)) { + return rc; + } + winner_phys->add_child(std::move(child_operator)); } - - return std::unique_ptr(winner_phys); + physical_operator.reset(winner_phys); + return RC::SUCCESS; } -void Optimizer::optimize_loop(int root_group_id) +RC Optimizer::optimize_loop(int root_group_id) { auto task_stack = new PendingTasks(); context_->set_task_pool(task_stack); @@ -59,14 +73,18 @@ void Optimizer::optimize_loop(int root_group_id) Memo &memo = context_->get_memo(); task_stack->push(new OptimizeGroup(memo.get_group_by_id(root_group_id), context_.get())); - execute_task_stack(task_stack, root_group_id, context_.get()); + return execute_task_stack(task_stack, root_group_id, context_.get()); } -void Optimizer::execute_task_stack(PendingTasks *task_stack, int root_group_id, OptimizerContext *root_context) +RC Optimizer::execute_task_stack(PendingTasks *task_stack, int root_group_id, OptimizerContext *root_context) { + RC rc = RC::SUCCESS; while (!task_stack->empty()) { auto task = task_stack->pop(); - task->perform(); + if(OB_SUCC(rc)) { + rc = task->perform(); + } delete task; } + return rc; } diff --git a/src/observer/sql/optimizer/cascade/optimizer.h b/src/observer/sql/optimizer/cascade/optimizer.h index 724d4a9de..8982fb26f 100644 --- a/src/observer/sql/optimizer/cascade/optimizer.h +++ b/src/observer/sql/optimizer/cascade/optimizer.h @@ -24,14 +24,14 @@ class Optimizer public: Optimizer() : context_(std::make_unique()) {} - std::unique_ptr optimize(OperatorNode *op_tree); + RC optimize(unique_ptr op_tree, std::unique_ptr &physical_operator); - std::unique_ptr choose_best_plan(int root_id); + RC choose_best_plan(int root_id, std::unique_ptr &physical_operator); private: - void optimize_loop(int root_group_id); + RC optimize_loop(int root_group_id); - void execute_task_stack(PendingTasks *task_stack, int root_group_id, OptimizerContext *root_context); + RC execute_task_stack(PendingTasks *task_stack, int root_group_id, OptimizerContext *root_context); CostModel cost_model_; std::unique_ptr context_; diff --git a/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp b/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp index d40c0e570..80fb34054 100644 --- a/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp @@ -15,11 +15,11 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/rules.h" #include "common/log/log.h" -void ApplyRule::perform() +RC ApplyRule::perform() { LOG_TRACE("ApplyRule::perform() for rule: {%d}", rule_->get_rule_idx()); if (group_expr_->rule_explored(rule_)) { - return; + return RC::SUCCESS; } // TODO: expr binding, currently group_expr_->get_op() is enough OperatorNode* before = group_expr_->get_op(); @@ -42,6 +42,7 @@ void ApplyRule::perform() } else { LOG_INFO("record_operator_node_into_group not insert new expr"); new_gexpr->dump(); + return RC::CASCADE_FAIL; } } @@ -51,4 +52,5 @@ void ApplyRule::perform() } group_expr_->set_rule_explored(rule_); + return RC::SUCCESS; } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.h b/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.h index 124bf2974..acc37464a 100644 --- a/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.h @@ -23,7 +23,7 @@ class ApplyRule : public CascadeTask : CascadeTask(context, CascadeTaskType::APPLY_RULE), group_expr_(group_expr), rule_(rule) {} - void perform() override; + RC perform() override; private: GroupExpr *group_expr_; diff --git a/src/observer/sql/optimizer/cascade/tasks/cascade_task.h b/src/observer/sql/optimizer/cascade/tasks/cascade_task.h index da7987f5b..4d4f174fa 100644 --- a/src/observer/sql/optimizer/cascade/tasks/cascade_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/cascade_task.h @@ -11,6 +11,7 @@ See the Mulan PSL v2 for more details. */ #pragma once #include "common/lang/vector.h" +#include "common/sys/rc.h" class Rule; class GroupExpr; @@ -33,7 +34,7 @@ class CascadeTask public: CascadeTask(OptimizerContext *context, CascadeTaskType type) : type_(type), context_(context) {} - virtual void perform() = 0; + virtual RC perform() = 0; Memo &get_memo() const; diff --git a/src/observer/sql/optimizer/cascade/tasks/e_group_task.cpp b/src/observer/sql/optimizer/cascade/tasks/e_group_task.cpp index 426f2e904..c12c6357c 100644 --- a/src/observer/sql/optimizer/cascade/tasks/e_group_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/e_group_task.cpp @@ -12,11 +12,11 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/tasks/o_expr_task.h" #include "common/log/log.h" -void ExploreGroup::perform() +RC ExploreGroup::perform() { LOG_TRACE("ExploreGroup::perform() "); if (group_->has_explored()) { - return; + return RC::SUCCESS; } for (auto &logical_expr : group_->get_logical_expressions()) { @@ -24,4 +24,5 @@ void ExploreGroup::perform() } group_->set_explored(); + return RC::SUCCESS; } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/tasks/e_group_task.h b/src/observer/sql/optimizer/cascade/tasks/e_group_task.h index f1534127f..6938aff26 100644 --- a/src/observer/sql/optimizer/cascade/tasks/e_group_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/e_group_task.h @@ -23,7 +23,7 @@ class ExploreGroup : public CascadeTask : CascadeTask(context, CascadeTaskType::EXPLORE_GROUP), group_(group) {} - void perform() override; + RC perform() override; private: Group *group_; diff --git a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp index 8e45af9e2..bdee74d6e 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp @@ -16,7 +16,7 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include -void OptimizeExpression::perform() +RC OptimizeExpression::perform() { std::vector valid_rules; @@ -58,4 +58,5 @@ void OptimizeExpression::perform() child_group_idx++; } } + return RC::SUCCESS; } diff --git a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.h b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.h index afd71029b..9806dccf2 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.h @@ -22,7 +22,7 @@ class OptimizeExpression : public CascadeTask : CascadeTask(context, CascadeTaskType::OPTIMIZE_EXPR), group_expr_(group_expr) {} - void perform() override; + RC perform() override; private: GroupExpr *group_expr_; diff --git a/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp index 47f06bdcc..dfa660b36 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp @@ -13,15 +13,15 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/tasks/o_expr_task.h" #include "sql/optimizer/cascade/optimizer_context.h" -void OptimizeGroup::perform() +RC OptimizeGroup::perform() { LOG_TRACE("OptimizeGroup::perform() group %d", group_->get_id()); // TODO: currently the cost upper bound is not used if (group_->get_cost_lb() > context_->get_cost_upper_bound()) { - return; + return RC::SUCCESS; } if (group_->get_winner() != nullptr) { - return; + return RC::SUCCESS; } if (!group_->has_explored()) { @@ -35,4 +35,5 @@ void OptimizeGroup::perform() } group_->set_explored(); + return RC::SUCCESS; } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/tasks/o_group_task.h b/src/observer/sql/optimizer/cascade/tasks/o_group_task.h index afad210e0..8e9641ced 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_group_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/o_group_task.h @@ -23,7 +23,7 @@ class OptimizeGroup : public CascadeTask : CascadeTask(context, CascadeTaskType::OPTIMIZE_GROUP), group_(group) {} - void perform() override; + RC perform() override; private: Group *group_; diff --git a/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp index 9ad9b7c7e..d194eba7b 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp @@ -15,7 +15,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/memo.h" #include "common/log/log.h" -void OptimizeInputs::perform() +RC OptimizeInputs::perform() { LOG_TRACE("OptimizeInputs::perform()"); if (cur_child_idx_ == -1) { @@ -40,14 +40,15 @@ void OptimizeInputs::perform() prev_child_idx_ = cur_child_idx_; push_task(new OptimizeInputs(this)); push_task(new OptimizeGroup(child_group, context_)); - return; + return RC::SUCCESS; } } - if (cur_child_idx_ == static_cast(group_expr_->get_children_groups_size())) { - group_expr_->set_local_cost(cur_total_cost_); + if (cur_child_idx_ == static_cast(group_expr_->get_children_groups_size())) { + group_expr_->set_local_cost(cur_total_cost_); - auto cur_group = get_memo().get_group_by_id(group_expr_->get_group_id()); - cur_group->set_expr_cost(group_expr_, cur_total_cost_); - } + auto cur_group = get_memo().get_group_by_id(group_expr_->get_group_id()); + cur_group->set_expr_cost(group_expr_, cur_total_cost_); + } + return RC::SUCCESS; } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/tasks/o_input_task.h b/src/observer/sql/optimizer/cascade/tasks/o_input_task.h index 0c3100bad..439419b3a 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_input_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/o_input_task.h @@ -30,7 +30,7 @@ class OptimizeInputs : public CascadeTask cur_child_idx_(task->cur_child_idx_) {} - void perform() override; + RC perform() override; ~OptimizeInputs() override {} diff --git a/src/observer/sql/optimizer/optimize_stage.cpp b/src/observer/sql/optimizer/optimize_stage.cpp index e838a9ad6..ec8080ccc 100644 --- a/src/observer/sql/optimizer/optimize_stage.cpp +++ b/src/observer/sql/optimizer/optimize_stage.cpp @@ -51,15 +51,11 @@ RC OptimizeStage::handle_request(SQLStageEvent *sql_event) return rc; } - // TODO: better way - logical_operator->generate_general_child(); - Optimizer optimizer; - // TODO: error handle unique_ptr physical_operator; if (sql_event->session_event()->session()->use_cascade()) { - physical_operator = optimizer.optimize(logical_operator.get()); - if (!physical_operator) { - rc = RC::INTERNAL; + Optimizer optimizer; + rc = optimizer.optimize(std::move(logical_operator), physical_operator); + if (OB_FAIL(rc)) { LOG_WARN("failed to optimize logical plan. rc=%s", strrc(rc)); return rc; } From 3fedf654499334a3a3535b9e57e715b45807a0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Thu, 27 Nov 2025 18:51:06 +0800 Subject: [PATCH 09/12] feat(optimizer): Initial implementation of PredicatePushdownRule --- src/common/sys/rc.h | 8 +- src/observer/sql/expr/expression.h | 14 +- .../logical/predicate_logical_operator.cpp | 21 + .../logical/predicate_logical_operator.h | 3 + .../logical/table_get_logical_operator.cpp | 15 +- src/observer/sql/operator/operator_node.h | 51 +- .../physical/index_scan_physical_operator.cpp | 13 +- .../physical/predicate_physical_operator.cpp | 9 + .../physical/predicate_physical_operator.h | 23 + .../physical/project_physical_operator.h | 16 +- .../physical/table_scan_physical_operator.cpp | 16 +- .../physical/table_scan_physical_operator.h | 18 +- .../sql/optimizer/cascade/cost_model.cpp | 102 +++- .../sql/optimizer/cascade/cost_model.h | 8 + src/observer/sql/optimizer/cascade/group.cpp | 19 +- .../sql/optimizer/cascade/group_expr.h | 9 +- .../cascade/implementation_rules.cpp | 360 ++++++++----- .../optimizer/cascade/implementation_rules.h | 98 ++-- src/observer/sql/optimizer/cascade/memo.h | 15 - .../sql/optimizer/cascade/optimizer.cpp | 20 +- .../sql/optimizer/cascade/optimizer.h | 7 +- .../optimizer/cascade/optimizer_context.cpp | 56 +-- .../sql/optimizer/cascade/optimizer_context.h | 9 +- src/observer/sql/optimizer/cascade/rules.cpp | 13 + src/observer/sql/optimizer/cascade/rules.h | 37 +- .../cascade/tasks/apply_rule_task.cpp | 16 +- .../optimizer/cascade/tasks/o_expr_task.cpp | 29 +- .../optimizer/cascade/tasks/o_group_task.cpp | 15 +- .../optimizer/cascade/tasks/o_input_task.cpp | 11 +- .../optimizer/cascade/tasks/o_input_task.h | 5 - .../sql/optimizer/logical_plan_generator.cpp | 302 +++++------ .../sql/optimizer/logical_plan_generator.h | 19 +- src/observer/sql/optimizer/optimize_stage.cpp | 102 +--- src/observer/sql/optimizer/optimize_stage.h | 48 +- .../sql/optimizer/optimizer_utils.cpp | 90 ++++ src/observer/sql/optimizer/optimizer_utils.h | 3 + .../sql/optimizer/physical_plan_generator.cpp | 471 ------------------ .../sql/optimizer/physical_plan_generator.h | 64 --- src/observer/sql/stmt/filter_stmt.cpp | 1 + src/observer/storage/common/column.cpp | 2 +- 40 files changed, 984 insertions(+), 1154 deletions(-) delete mode 100644 src/observer/sql/optimizer/physical_plan_generator.cpp delete mode 100644 src/observer/sql/optimizer/physical_plan_generator.h diff --git a/src/common/sys/rc.h b/src/common/sys/rc.h index 0330c7db5..53a60debb 100644 --- a/src/common/sys/rc.h +++ b/src/common/sys/rc.h @@ -84,8 +84,12 @@ See the Mulan PSL v2 for more details. */ DEFINE_RC(INVALID_TOKEN) \ DEFINE_RC(UNEXPECTED_END_OF_STRING) \ DEFINE_RC(SYNTAX_ERROR) \ - DEFINE_RC(CASCADE_FAIL) \ - DEFINE_RC(UNSUPPORTED) + DEFINE_RC(UNSUPPORTED) \ + DEFINE_RC(OPTIMIZER_GROUP_EXPR_CREATE_FAILED) \ + DEFINE_RC(OPTIMIZER_MEMO_INSERT_FAILED) \ + DEFINE_RC(OPTIMIZER_EXPRESSION_COPY_FAILED) \ + DEFINE_RC(OPTIMIZER_INVALID_GROUP_ID) \ + DEFINE_RC(OPTIMIZER_CASCADE_FAIL) enum class RC { diff --git a/src/observer/sql/expr/expression.h b/src/observer/sql/expr/expression.h index 02dc27c2f..8cd4b21a7 100644 --- a/src/observer/sql/expr/expression.h +++ b/src/observer/sql/expr/expression.h @@ -200,7 +200,12 @@ class FieldExpr : public Expression bool equal(const Expression &other) const override; - unique_ptr copy() const override { return make_unique(field_); } + unique_ptr copy() const override + { + auto copied = make_unique(field_); + copied->set_name(name()); + return copied; + } ExprType type() const override { return ExprType::FIELD; } AttrType value_type() const override { return field_.attr_type(); } @@ -278,6 +283,7 @@ class CastExpr : public Expression AttrType value_type() const override { return cast_type_; } unique_ptr &child() { return child_; } + const unique_ptr &child() const { return child_; } private: RC cast(const Value &value, Value &cast_value) const; @@ -314,7 +320,9 @@ class ComparisonExpr : public Expression RC eval(Chunk &chunk, vector &select) override; unique_ptr &left() { return left_; } + const unique_ptr &left() const { return left_; } unique_ptr &right() { return right_; } + const unique_ptr &right() const { return right_; } /** * 尝试在没有tuple的情况下获取当前表达式的值 @@ -372,6 +380,7 @@ class ConjunctionExpr : public Expression Type conjunction_type() const { return conjunction_type_; } vector> &children() { return children_; } + const vector> &children() const { return children_; } private: Type conjunction_type_; @@ -423,7 +432,9 @@ class ArithmeticExpr : public Expression Type arithmetic_type() const { return arithmetic_type_; } unique_ptr &left() { return left_; } + const unique_ptr &left() const { return left_; } unique_ptr &right() { return right_; } + const unique_ptr &right() const { return right_; } private: RC calc_value(const Value &left_value, const Value &right_value, Value &value) const; @@ -456,6 +467,7 @@ class UnboundAggregateExpr : public Expression const char *aggregate_name() const { return aggregate_name_.c_str(); } unique_ptr &child() { return child_; } + const unique_ptr &child() const { return child_; } RC get_value(const Tuple &tuple, Value &value) const override { return RC::INTERNAL; } AttrType value_type() const override { return child_->value_type(); } diff --git a/src/observer/sql/operator/logical/predicate_logical_operator.cpp b/src/observer/sql/operator/logical/predicate_logical_operator.cpp index e8ab44062..bceaa708e 100644 --- a/src/observer/sql/operator/logical/predicate_logical_operator.cpp +++ b/src/observer/sql/operator/logical/predicate_logical_operator.cpp @@ -13,8 +13,29 @@ See the Mulan PSL v2 for more details. */ // #include "sql/operator/logical/predicate_logical_operator.h" +#include "sql/optimizer/cascade/property.h" PredicateLogicalOperator::PredicateLogicalOperator(unique_ptr expression) { expressions_.emplace_back(std::move(expression)); } + +unique_ptr PredicateLogicalOperator::find_log_prop(const vector &log_props) +{ + if (log_props.empty() || log_props[0] == nullptr) { + // 如果没有输入属性,返回默认值 + return make_unique(1000); + } + + // 获取输入 cardinality + int input_card = log_props[0]->get_card(); + + // 简单估计:谓词过滤会减少约 10% 的行数(实际应该根据谓词类型和选择性来估计) + // TODO: 根据谓词类型和选择性来更准确地估计 cardinality + int output_card = input_card / 10; // 假设过滤后保留 10% 的数据 + if (output_card < 1) { + output_card = 1; // 至少保留 1 行 + } + + return make_unique(output_card); +} diff --git a/src/observer/sql/operator/logical/predicate_logical_operator.h b/src/observer/sql/operator/logical/predicate_logical_operator.h index 13b94f61e..953ad247f 100644 --- a/src/observer/sql/operator/logical/predicate_logical_operator.h +++ b/src/observer/sql/operator/logical/predicate_logical_operator.h @@ -16,6 +16,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/expr/expression.h" #include "sql/operator/logical_operator.h" +#include "sql/optimizer/cascade/property.h" /** * @brief 谓词/过滤逻辑算子 @@ -28,4 +29,6 @@ class PredicateLogicalOperator : public LogicalOperator virtual ~PredicateLogicalOperator() = default; OpType get_op_type() const override { return OpType::LOGICALFILTER; } + + unique_ptr find_log_prop(const vector &log_props) override; }; diff --git a/src/observer/sql/operator/logical/table_get_logical_operator.cpp b/src/observer/sql/operator/logical/table_get_logical_operator.cpp index 508ef822b..803e4d4aa 100644 --- a/src/observer/sql/operator/logical/table_get_logical_operator.cpp +++ b/src/observer/sql/operator/logical/table_get_logical_operator.cpp @@ -28,6 +28,19 @@ void TableGetLogicalOperator::set_predicates(vector> &&ex unique_ptr TableGetLogicalOperator::find_log_prop(const vector &log_props) { int card = Catalog::get_instance().get_table_stats(table_->table_id()).row_nums; - // TODO: think about predicates. + + // 如果有 predicates,降低 cardinality + // 简单估计:每个谓词会减少约 10% 的行数 + // TODO: 根据谓词类型和选择性来更准确地估计 cardinality + if (!predicates_.empty()) { + // 假设每个谓词过滤掉 90% 的数据,保留 10% + for (size_t i = 0; i < predicates_.size(); i++) { + card = card / 10; + if (card < 1) { + card = 1; // 至少保留 1 行 + } + } + } + return make_unique(card); } \ No newline at end of file diff --git a/src/observer/sql/operator/operator_node.h b/src/observer/sql/operator/operator_node.h index 68c5e8e00..24fe7748e 100644 --- a/src/observer/sql/operator/operator_node.h +++ b/src/observer/sql/operator/operator_node.h @@ -68,9 +68,9 @@ enum class OpType SEQSCAN_VEC }; -// TODO: OperatorNode is the abstrace class of logical/physical operator -// in cascade there is EXPR to include OperatorNode and OperatorNode children -// so here remove genral_children. +// OperatorNode is the abstract class of logical/physical operator +// In cascade optimizer, children are managed by GroupExpr through child_group_ids, +// not by OperatorNode itself. class OperatorNode { public: @@ -98,19 +98,8 @@ class OperatorNode virtual uint64_t hash() const { return std::hash()(static_cast(get_op_type())); } virtual bool operator==(const OperatorNode &other) const { - if (get_op_type() != other.get_op_type()) - return false; - if (general_children_.size() != other.general_children_.size()) - return false; - - for (size_t idx = 0; idx < general_children_.size(); idx++) { - auto &child = general_children_[idx]; - auto &other_child = other.general_children_[idx]; - - if (*child != *other_child) - return false; - } - return true; + // 有额外成员的算子需要重写此方法来比较成员 + return get_op_type() == other.get_op_type(); } /** * @brief Generate the logical property of the operator node using the input logical properties. @@ -130,18 +119,28 @@ class OperatorNode * @param child_log_props A vector containing pointers to child logical properties. * @param cm A pointer to the cost model used for calculating the cost. * @return The calculated cost as a double. + * + * @note Default implementation: uses CPU operation cost based on input cardinality. + * If there are child operators, uses the first child's cardinality. + * Otherwise, uses the current operator's cardinality. */ virtual double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) { - return 0.0; + // Default cost: CPU operation cost based on input cardinality + // For operators with children, use the first child's cardinality (input size) + // For leaf operators, use the current operator's cardinality + int card = 0; + if (!child_log_props.empty() && child_log_props[0] != nullptr) { + card = child_log_props[0]->get_card(); + } else if (prop != nullptr) { + card = prop->get_card(); + } + // If cardinality is 0, use a minimum cost to avoid zero cost + // This ensures that even empty tables/operators have some cost + if (card == 0) { + card = 1; // Use minimum cardinality of 1 for cost calculation + } + // Use CPU operation cost as default, similar to ProjectPhysicalOperator + return cm->cpu_op() * card; } - - void add_general_child(OperatorNode *child) { general_children_.push_back(child); } - - vector &get_general_children() { return general_children_; } - -protected: - // TODO: refactor - // cascade optimizer 中使用,为了logical/physical operator 可以统一在 cascade 中迭代 - vector general_children_; }; \ No newline at end of file diff --git a/src/observer/sql/operator/physical/index_scan_physical_operator.cpp b/src/observer/sql/operator/physical/index_scan_physical_operator.cpp index 61d581f13..8f03c699c 100644 --- a/src/observer/sql/operator/physical/index_scan_physical_operator.cpp +++ b/src/observer/sql/operator/physical/index_scan_physical_operator.cpp @@ -15,6 +15,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/physical/index_scan_physical_operator.h" #include "storage/index/index.h" #include "storage/trx/trx.h" +#include "sql/optimizer/optimizer_utils.h" IndexScanPhysicalOperator::IndexScanPhysicalOperator(Table *table, Index *index, ReadWriteMode mode, const Value *left_value, bool left_inclusive, const Value *right_value, bool right_inclusive) @@ -137,5 +138,15 @@ RC IndexScanPhysicalOperator::filter(RowTuple &tuple, bool &result) string IndexScanPhysicalOperator::param() const { - return string(index_->index_meta().name()) + " ON " + table_->name(); + string result = string(index_->index_meta().name()) + " ON " + table_->name(); + if (!predicates_.empty()) { + result += ", filter="; + for (size_t i = 0; i < predicates_.size(); i++) { + if (i > 0) { + result += " AND "; + } + result += OptimizerUtils::expression_to_string(predicates_[i].get()); + } + } + return result; } diff --git a/src/observer/sql/operator/physical/predicate_physical_operator.cpp b/src/observer/sql/operator/physical/predicate_physical_operator.cpp index a6f9bacdd..79b31fce6 100644 --- a/src/observer/sql/operator/physical/predicate_physical_operator.cpp +++ b/src/observer/sql/operator/physical/predicate_physical_operator.cpp @@ -17,6 +17,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/stmt/filter_stmt.h" #include "storage/field/field.h" #include "storage/record/record.h" +#include "sql/optimizer/optimizer_utils.h" PredicatePhysicalOperator::PredicatePhysicalOperator(std::unique_ptr expr) : expression_(std::move(expr)) { @@ -71,3 +72,11 @@ RC PredicatePhysicalOperator::tuple_schema(TupleSchema &schema) const { return children_[0]->tuple_schema(schema); } + +string PredicatePhysicalOperator::param() const +{ + if (expression_ == nullptr) { + return ""; + } + return OptimizerUtils::expression_to_string(expression_.get()); +} diff --git a/src/observer/sql/operator/physical/predicate_physical_operator.h b/src/observer/sql/operator/physical/predicate_physical_operator.h index 81cce7cd7..31d6176e0 100644 --- a/src/observer/sql/operator/physical/predicate_physical_operator.h +++ b/src/observer/sql/operator/physical/predicate_physical_operator.h @@ -53,6 +53,27 @@ class PredicatePhysicalOperator : public PhysicalOperator return expression_->equal(*(other_pred.expression_)); } + double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override + { + // Predicate 需要处理所有输入行,代价与输入 cardinality 成正比 + // 这比在 TableScan 中直接过滤要昂贵,因为需要额外的 CPU 开销 + if (child_log_props.empty() || !child_log_props[0]) { + return cm->cpu_op() * 1; // Minimum cost even if no child + } + int card = child_log_props[0]->get_card(); + if (card == 0) { + card = 1; // Use minimum cardinality of 1 for cost calculation + } + // Calculate expression complexity to adjust cost + double expr_complexity = cm->calculate_expression_complexity(expression_.get()); + if (expr_complexity < 1.0) { + expr_complexity = 1.0; // Minimum complexity multiplier + } + // Predicate 的代价:需要扫描所有输入行并评估表达式 + // 表达式复杂度越高,代价越高 + return cm->cpu_op() * card * expr_complexity; + } + RC open(Trx *trx) override; RC next() override; RC close() override; @@ -61,6 +82,8 @@ class PredicatePhysicalOperator : public PhysicalOperator RC tuple_schema(TupleSchema &schema) const override; + string param() const override; + private: unique_ptr expression_; }; diff --git a/src/observer/sql/operator/physical/project_physical_operator.h b/src/observer/sql/operator/physical/project_physical_operator.h index cb88ae143..29d8cc0de 100644 --- a/src/observer/sql/operator/physical/project_physical_operator.h +++ b/src/observer/sql/operator/physical/project_physical_operator.h @@ -57,7 +57,21 @@ class ProjectPhysicalOperator : public PhysicalOperator virtual double calculate_cost( LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override { - return (cm->cpu_op()) * prop->get_card(); + int card = prop ? prop->get_card() : 0; + if (card == 0) { + card = 1; // Use minimum cardinality of 1 for cost calculation + } + // Calculate total expression complexity for all expressions in projection + double total_expr_complexity = 0.0; + for (const auto &expr : expressions_) { + total_expr_complexity += cm->calculate_expression_complexity(expr.get()); + } + if (total_expr_complexity < static_cast(expressions_.size())) { + total_expr_complexity = static_cast(expressions_.size()); // Minimum: 1.0 per expression + } + // Projection cost: CPU operation cost * cardinality * average expression complexity + double avg_expr_complexity = total_expr_complexity / static_cast(expressions_.size()); + return cm->cpu_op() * card * avg_expr_complexity; } RC open(Trx *trx) override; diff --git a/src/observer/sql/operator/physical/table_scan_physical_operator.cpp b/src/observer/sql/operator/physical/table_scan_physical_operator.cpp index a09b4ede1..cdcf5a6db 100644 --- a/src/observer/sql/operator/physical/table_scan_physical_operator.cpp +++ b/src/observer/sql/operator/physical/table_scan_physical_operator.cpp @@ -15,6 +15,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/physical/table_scan_physical_operator.h" #include "event/sql_debug.h" #include "storage/table/table.h" +#include "sql/optimizer/optimizer_utils.h" using namespace std; @@ -73,7 +74,20 @@ Tuple *TableScanPhysicalOperator::current_tuple() return &tuple_; } -string TableScanPhysicalOperator::param() const { return table_->name(); } +string TableScanPhysicalOperator::param() const +{ + string result = table_->name(); + if (!predicates_.empty()) { + result += ", filter="; + for (size_t i = 0; i < predicates_.size(); i++) { + if (i > 0) { + result += " AND "; + } + result += OptimizerUtils::expression_to_string(predicates_[i].get()); + } + } + return result; +} void TableScanPhysicalOperator::set_predicates(vector> &&exprs) { diff --git a/src/observer/sql/operator/physical/table_scan_physical_operator.h b/src/observer/sql/operator/physical/table_scan_physical_operator.h index c15f39169..89fb75b5c 100644 --- a/src/observer/sql/operator/physical/table_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/table_scan_physical_operator.h @@ -40,6 +40,12 @@ class TableScanPhysicalOperator : public PhysicalOperator { uint64_t hash = std::hash()(static_cast(get_op_type())); hash ^= std::hash()(table_->table_id()); + hash ^= std::hash()(predicates_.size()); + for (const auto &pred : predicates_) { + if (pred) { + hash ^= std::hash()(static_cast(pred->type())); + } + } return hash; } @@ -50,12 +56,22 @@ class TableScanPhysicalOperator : public PhysicalOperator const auto &other_get = static_cast(other); if (table_->table_id() != other_get.table_id()) return false; + if (predicates_.size() != other_get.predicates_.size()) + return false; + for (size_t i = 0; i < predicates_.size(); i++) { + if (!predicates_[i]->equal(*(other_get.predicates_[i]))) + return false; + } return true; } double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override { - return (cm->io() + cm->cpu_op()) * prop->get_card(); + int card = prop ? prop->get_card() : 0; + if (card == 0) { + card = 1; // Use minimum cardinality of 1 for cost calculation + } + return (cm->io() + cm->cpu_op()) * card; } RC open(Trx *trx) override; diff --git a/src/observer/sql/optimizer/cascade/cost_model.cpp b/src/observer/sql/optimizer/cascade/cost_model.cpp index 16f43ec7f..8c035ef46 100644 --- a/src/observer/sql/optimizer/cascade/cost_model.cpp +++ b/src/observer/sql/optimizer/cascade/cost_model.cpp @@ -12,19 +12,117 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/memo.h" #include "catalog/catalog.h" #include "sql/optimizer/cascade/group_expr.h" +#include "common/log/log.h" +#include "sql/expr/expression.h" double CostModel::calculate_cost(Memo *memo, GroupExpr *gexpr) { auto op = gexpr->get_op(); auto log_prop = memo->get_group_by_id(gexpr->get_group_id())->get_logical_prop(); + + // 如果 log_prop 为 nullptr,使用默认值 + if (log_prop == nullptr) { + static LogicalProperty default_prop(0); + log_prop = &default_prop; + } + int arity = gexpr->get_children_groups_size(); vector child_log_props; for (int i = 0; i < arity; ++i) { auto child_group_id = gexpr->get_child_group_id(i); auto child_gexpr = memo->get_group_by_id(child_group_id); - child_log_props.push_back(child_gexpr->get_logical_prop()); + auto child_prop = child_gexpr->get_logical_prop(); + // 如果 child_prop 为 nullptr,使用默认值 + if (child_prop == nullptr) { + static LogicalProperty default_child_prop(0); + child_prop = &default_child_prop; + } + child_log_props.push_back(child_prop); + } + double cost = op->calculate_cost(log_prop, child_log_props, this); + LOG_INFO("CostModel: op_type=%d, group_id=%d, prop_card=%d, arity=%d, cost=%.6f", + static_cast(op->get_op_type()), + gexpr->get_group_id(), + log_prop ? log_prop->get_card() : 0, + arity, + cost); + if (arity > 0 && !child_log_props.empty() && child_log_props[0]) { + LOG_INFO("CostModel: first_child_card=%d", child_log_props[0]->get_card()); + } + return cost; + +} + +double CostModel::calculate_expression_complexity(const Expression *expr) const +{ + if (expr == nullptr) { + return 1.0; // Default complexity + } + + double complexity = 0.0; + ExprType expr_type = expr->type(); + + switch (expr_type) { + case ExprType::VALUE: + // Constant value, no computation needed + complexity = 0.0; + break; + + case ExprType::FIELD: + // Field access, very cheap + complexity = 1.0; + break; + + case ExprType::CAST: { + // Type conversion, moderate cost + const CastExpr *cast_expr = static_cast(expr); + complexity = 2.0 + calculate_expression_complexity(cast_expr->child().get()); + break; + } + + case ExprType::COMPARISON: { + // Comparison operation, moderate cost + const ComparisonExpr *cmp_expr = static_cast(expr); + complexity = 2.0 + calculate_expression_complexity(cmp_expr->left().get()) + + calculate_expression_complexity(cmp_expr->right().get()); + break; + } + + case ExprType::ARITHMETIC: { + // Arithmetic operation, higher cost + const ArithmeticExpr *arith_expr = static_cast(expr); + complexity = 3.0 + calculate_expression_complexity(arith_expr->left().get()) + + calculate_expression_complexity(arith_expr->right().get()); + break; + } + + case ExprType::CONJUNCTION: { + // Conjunction (AND/OR), cost depends on number of children + const ConjunctionExpr *conj_expr = static_cast(expr); + complexity = 1.0; // Base cost for conjunction + for (const auto &child : conj_expr->children()) { + complexity += calculate_expression_complexity(child.get()); + } + break; + } + + case ExprType::AGGREGATION: { + // Aggregation function, high cost + const AggregateExpr *agg_expr = static_cast(expr); + complexity = 5.0 + calculate_expression_complexity(agg_expr->child().get()); + break; + } + + case ExprType::STAR: + case ExprType::UNBOUND_FIELD: + case ExprType::UNBOUND_AGGREGATION: + case ExprType::NONE: + default: + // Unknown or unsupported types, use default + complexity = 1.0; + break; } - return op->calculate_cost(log_prop, child_log_props, this); + return complexity; } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/cost_model.h b/src/observer/sql/optimizer/cascade/cost_model.h index e64284ec8..581685cb2 100644 --- a/src/observer/sql/optimizer/cascade/cost_model.h +++ b/src/observer/sql/optimizer/cascade/cost_model.h @@ -12,6 +12,7 @@ See the Mulan PSL v2 for more details. */ class Memo; class GroupExpr; +class Expression; /** * @brief cost model in cost-based optimization(CBO) */ @@ -44,4 +45,11 @@ class CostModel inline double io() { return IO; } double calculate_cost(Memo *memo, GroupExpr *gexpr); + + /** + * @brief Calculate the complexity cost of an expression + * @param expr The expression to evaluate + * @return The complexity cost multiplier (1.0 = base cost, higher = more expensive) + */ + double calculate_expression_complexity(const Expression *expr) const; }; \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/group.cpp b/src/observer/sql/optimizer/cascade/group.cpp index fab245d1a..b0c4ee561 100644 --- a/src/observer/sql/optimizer/cascade/group.cpp +++ b/src/observer/sql/optimizer/cascade/group.cpp @@ -28,6 +28,11 @@ Group::Group(int id, GroupExpr* expr, Memo *memo) logical_prop_ = (expr->get_op())->find_log_prop(input_prop); } + + // 如果 find_log_prop 返回 nullptr,创建一个默认的 LogicalProperty + if (logical_prop_ == nullptr) { + logical_prop_ = make_unique(1000); + } } Group::~Group() { for (auto expr : logical_expressions_) { @@ -49,8 +54,6 @@ void Group::add_expr(GroupExpr *expr) } bool Group::set_expr_cost(GroupExpr *expr, double cost) { - - if (std::get<0>(winner_) > cost) { // this is lower cost winner_ = std::make_tuple(cost, expr); @@ -65,7 +68,7 @@ GroupExpr *Group::get_winner() { GroupExpr *Group::get_logical_expression() { ASSERT(logical_expressions_.size() == 1, "There should exist only 1 logical expression"); - ASSERT(physical_expressions_.empty(), "No physical expressions should be present"); + ASSERT(!logical_expressions_.empty(), "No logical expressions should be present"); return logical_expressions_[0]; } @@ -73,4 +76,14 @@ void Group::dump() const { LOG_TRACE("Group %d has %lu logical expressions and %lu physical expressions", id_, logical_expressions_.size(), physical_expressions_.size(), physical_expressions_.size()); + + for (size_t i = 0; i < logical_expressions_.size(); i++) { + LOG_TRACE(" Logical[%lu]: op_type=%d", i, static_cast(logical_expressions_[i]->get_op()->get_op_type())); + } + for (size_t i = 0; i < physical_expressions_.size(); i++) { + LOG_TRACE(" Physical[%lu]: op_type=%d, cost=%.6f", + i, + static_cast(physical_expressions_[i]->get_op()->get_op_type()), + physical_expressions_[i]->get_cost()); + } } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/group_expr.h b/src/observer/sql/optimizer/cascade/group_expr.h index c3d752dfb..1c81f71ca 100644 --- a/src/observer/sql/optimizer/cascade/group_expr.h +++ b/src/observer/sql/optimizer/cascade/group_expr.h @@ -28,8 +28,8 @@ class GroupExpr * @param contents optimizer node contents * @param child_groups Vector of children groups */ - GroupExpr(OperatorNode *contents, std::vector &&child_groups) - : group_id_(-1), contents_(contents), child_groups_(child_groups) + GroupExpr(unique_ptr contents, std::vector &&child_groups) + : group_id_(-1), contents_(std::move(contents)), child_groups_(child_groups) {} ~GroupExpr() {} @@ -47,7 +47,8 @@ class GroupExpr return child_groups_[child_idx]; } - OperatorNode *get_op() { return contents_; } + OperatorNode *get_op() { return contents_.get(); } + OperatorNode *release_op() { return contents_.release(); } double get_cost() const { return lowest_cost_; } @@ -77,7 +78,7 @@ class GroupExpr private: int group_id_{}; - OperatorNode *contents_{}; + unique_ptr contents_{}; std::vector child_groups_; diff --git a/src/observer/sql/optimizer/cascade/implementation_rules.cpp b/src/observer/sql/optimizer/cascade/implementation_rules.cpp index c74fe3058..ae9de5f90 100644 --- a/src/observer/sql/optimizer/cascade/implementation_rules.cpp +++ b/src/observer/sql/optimizer/cascade/implementation_rules.cpp @@ -9,6 +9,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ #include "common/log/log.h" +#include "sql/optimizer/cascade/group_expr.h" #include "sql/optimizer/cascade/implementation_rules.h" #include "sql/operator/logical/table_get_logical_operator.h" #include "sql/operator/physical/table_scan_physical_operator.h" @@ -27,78 +28,158 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/logical/group_by_logical_operator.h" #include "sql/operator/physical/scalar_group_by_physical_operator.h" #include "sql/operator/physical/hash_group_by_physical_operator.h" +#include "sql/operator/physical/index_scan_physical_operator.h" +#include "sql/operator/logical/join_logical_operator.h" +#include "sql/operator/physical/nested_loop_join_physical_operator.h" +#include "sql/operator/physical/hash_join_physical_operator.h" +#include "sql/expr/expression.h" // ------------------------------------------------------------------------------------------------- // PhysicalSeqScan // ------------------------------------------------------------------------------------------------- -LogicalGetToPhysicalSeqScan::LogicalGetToPhysicalSeqScan() { - type_ = RuleType::GET_TO_SEQ_SCAN; +LogicalGetToPhysicalSeqScan::LogicalGetToPhysicalSeqScan() +{ + type_ = RuleType::GET_TO_SEQ_SCAN; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALGET)); } -void LogicalGetToPhysicalSeqScan::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const { - TableGetLogicalOperator* table_get_oper = dynamic_cast(input); +void LogicalGetToPhysicalSeqScan::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + TableGetLogicalOperator *table_get_oper = static_cast(input->get_op()); vector> &log_preds = table_get_oper->predicates(); - vector> phys_preds; + vector> phys_preds; for (auto &pred : log_preds) { phys_preds.push_back(pred->copy()); } - Table *table = table_get_oper->table(); - auto table_scan_oper = new TableScanPhysicalOperator(table, table_get_oper->read_write_mode()); + Table *table = table_get_oper->table(); + auto table_scan_oper = new TableScanPhysicalOperator(table, table_get_oper->read_write_mode()); table_scan_oper->set_predicates(std::move(phys_preds)); auto oper = unique_ptr(table_scan_oper); transformed->emplace_back(std::move(oper)); } +// ------------------------------------------------------------------------------------------------- +// PhysicalIndexScan +// ------------------------------------------------------------------------------------------------- +LogicalGetToPhysicalIndexScan::LogicalGetToPhysicalIndexScan() +{ + type_ = RuleType::GET_TO_INDEX_SCAN; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALGET)); +} + +void LogicalGetToPhysicalIndexScan::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + TableGetLogicalOperator *table_get_oper = static_cast(input->get_op()); + + 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 && comparison_expr->comp() != NOT_EQUAL) { + continue; + } + + unique_ptr &left_expr = comparison_expr->left(); + 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 && right_expr->type() == ExprType::VALUE) { + field_expr = static_cast(left_expr.get()); + value_expr = static_cast(right_expr.get()); + } else if (right_expr->type() == ExprType::FIELD && left_expr->type() == ExprType::VALUE) { + field_expr = static_cast(right_expr.get()); + value_expr = static_cast(left_expr.get()); + } + + if (field_expr == nullptr || value_expr == nullptr) { + continue; + } + + const Field &field = field_expr->field(); + // 检查字段是否属于当前表 + if (field.table() != table) { + continue; + } + index = table->find_index_by_field(field.field_name()); + if (nullptr != index) { + break; + } + } + } + + // 只有在找到索引时才生成 IndexScan + if (index != nullptr && value_expr != nullptr) { + vector> phys_preds; + for (auto &pred : predicates) { + phys_preds.push_back(pred->copy()); + } + + const Value &value = value_expr->get_value(); + auto index_scan_oper = new IndexScanPhysicalOperator(table, index, table_get_oper->read_write_mode(), + &value, true /*left_inclusive*/, &value, true /*right_inclusive*/); + index_scan_oper->set_predicates(std::move(phys_preds)); + auto oper = unique_ptr(index_scan_oper); + + transformed->emplace_back(std::move(oper)); + } +} + // ------------------------------------------------------------------------------------------------- // LogicalProjectionToProjection // ------------------------------------------------------------------------------------------------- -LogicalProjectionToProjection::LogicalProjectionToProjection() { - type_ = RuleType::PROJECTION_TO_PHYSOCAL; +LogicalProjectionToProjection::LogicalProjectionToProjection() +{ + type_ = RuleType::PROJECTION_TO_PHYSOCAL; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALPROJECTION)); - auto child = new Pattern(OpType::LEAF); + auto child = new Pattern(OpType::LEAF); match_pattern_->add_child(child); } -void LogicalProjectionToProjection::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const { - auto project_oper = dynamic_cast(input); - vector> &child_opers = project_oper->children(); - ASSERT(child_opers.size() == 1, "only one child is supported for now"); +void LogicalProjectionToProjection::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + auto project_oper = static_cast(input->get_op()); + ASSERT(input->get_children_groups_size() == 1, "only one child is supported for now"); unique_ptr child_phy_oper; auto project_operator = make_unique(std::move(project_oper->expressions())); - if (project_operator) { - project_operator->add_general_child(child_opers.front().get()); - } - transformed->emplace_back(std::move(project_operator)); + transformed->emplace_back(std::move(project_operator), input->get_child_group_ids()); } // ------------------------------------------------------------------------------------------------- // PhysicalInsert // ------------------------------------------------------------------------------------------------- -LogicalInsertToInsert::LogicalInsertToInsert() { - type_ = RuleType::INSERT_TO_PHYSICAL; +LogicalInsertToInsert::LogicalInsertToInsert() +{ + type_ = RuleType::INSERT_TO_PHYSICAL; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALINSERT)); } +void LogicalInsertToInsert::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + InsertLogicalOperator *insert_oper = static_cast(input->get_op()); -void LogicalInsertToInsert::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const { - InsertLogicalOperator* insert_oper = dynamic_cast(input); - - Table *table = insert_oper->table(); - vector &values = insert_oper->values(); - auto insert_phy_oper = make_unique(table, std::move(values)); + Table *table = insert_oper->table(); + vector &values = insert_oper->values(); + auto insert_phy_oper = make_unique(table, std::move(values)); transformed->emplace_back(std::move(insert_phy_oper)); } @@ -108,23 +189,18 @@ void LogicalInsertToInsert::transform(OperatorNode* input, // ------------------------------------------------------------------------------------------------- LogicalExplainToExplain::LogicalExplainToExplain() { - type_ = RuleType::EXPLAIN_TO_PHYSICAL; + type_ = RuleType::EXPLAIN_TO_PHYSICAL; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALEXPLAIN)); - auto child = new Pattern(OpType::LEAF); + auto child = new Pattern(OpType::LEAF); match_pattern_->add_child(child); } -void LogicalExplainToExplain::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const +void LogicalExplainToExplain::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const { - auto explain_oper = dynamic_cast(input); unique_ptr explain_physical_oper(new ExplainPhysicalOperator()); - for (auto &child : explain_oper->children()) { - explain_physical_oper->add_general_child(child.get()); - } - transformed->emplace_back(std::move(explain_physical_oper)); + transformed->emplace_back(std::move(explain_physical_oper), input->get_child_group_ids()); } // ------------------------------------------------------------------------------------------------- @@ -132,15 +208,14 @@ void LogicalExplainToExplain::transform(OperatorNode* input, // ------------------------------------------------------------------------------------------------- LogicalCalcToCalc::LogicalCalcToCalc() { - type_ = RuleType::CALC_TO_PHYSICAL; + type_ = RuleType::CALC_TO_PHYSICAL; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALCALCULATE)); } -void LogicalCalcToCalc::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const +void LogicalCalcToCalc::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const { - auto calc_oper = dynamic_cast(input); + auto calc_oper = static_cast(input->get_op()); unique_ptr calc_phys_oper(new CalcPhysicalOperator(std::move(calc_oper->expressions()))); transformed->emplace_back(std::move(calc_phys_oper)); @@ -151,24 +226,20 @@ void LogicalCalcToCalc::transform(OperatorNode* input, // ------------------------------------------------------------------------------------------------- LogicalDeleteToDelete::LogicalDeleteToDelete() { - type_ = RuleType::DELETE_TO_PHYSICAL; + type_ = RuleType::DELETE_TO_PHYSICAL; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALDELETE)); - auto child = new Pattern(OpType::LEAF); + auto child = new Pattern(OpType::LEAF); match_pattern_->add_child(child); } -void LogicalDeleteToDelete::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const +void LogicalDeleteToDelete::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const { - auto delete_oper = dynamic_cast(input); + auto delete_oper = static_cast(input->get_op()); auto delete_phys_oper = unique_ptr(new DeletePhysicalOperator(delete_oper->table())); - for (auto &child : delete_oper->children()) { - delete_phys_oper->add_general_child(child.get()); - } - transformed->emplace_back(std::move(delete_phys_oper)); + transformed->emplace_back(std::move(delete_phys_oper), input->get_child_group_ids()); } // ------------------------------------------------------------------------------------------------- @@ -176,89 +247,128 @@ void LogicalDeleteToDelete::transform(OperatorNode* input, // ------------------------------------------------------------------------------------------------- LogicalPredicateToPredicate::LogicalPredicateToPredicate() { - type_ = RuleType::PREDICATE_TO_PHYSICAL; + type_ = RuleType::PREDICATE_TO_PHYSICAL; match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALFILTER)); - auto child = new Pattern(OpType::LEAF); + auto child = new Pattern(OpType::LEAF); match_pattern_->add_child(child); } -void LogicalPredicateToPredicate::transform(OperatorNode* input, - std::vector> *transformed, - OptimizerContext *context) const +void LogicalPredicateToPredicate::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const { - auto predicate_oper = dynamic_cast(input); + auto predicate_oper = static_cast(input->get_op()); vector> &expressions = predicate_oper->expressions(); ASSERT(expressions.size() == 1, "predicate logical operator's children should be 1"); - unique_ptr expression = std::move(expressions.front()); - unique_ptr oper = unique_ptr(new PredicatePhysicalOperator(std::move(expression))); - for (auto &child : predicate_oper->children()) { - oper->add_general_child(child.get()); - } - transformed->emplace_back(std::move(oper)); + unique_ptr expression = std::move(expressions.front()); + unique_ptr oper = + unique_ptr(new PredicatePhysicalOperator(std::move(expression))); + transformed->emplace_back(std::move(oper), input->get_child_group_ids()); } // ------------------------------------------------------------------------------------------------- -// Physical Aggregation +// Physical Nested Loop Join // ------------------------------------------------------------------------------------------------- -// LogicalGroupByToAggregation::LogicalGroupByToAggregation() -// { -// type_ = RuleType::GROUP_BY_TO_PHYSICAL_AGGREGATION; -// match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALGROUPBY)); -// auto child = new Pattern(OpType::LEAF); -// match_pattern_->add_child(child); -// } - - -// void LogicalGroupByToAggregation::transform(OperatorNode* input, -// std::vector> *transformed, -// OptimizerContext *context) const -// { -// auto groupby_oper = dynamic_cast(input); -// vector> &group_by_expressions = groupby_oper->group_by_expressions(); -// unique_ptr groupby_phys_oper; -// if (group_by_expressions.empty()) { -// groupby_phys_oper = make_unique(std::move(groupby_oper->aggregate_expressions())); -// } else { -// return; -// } -// for (auto &child : groupby_oper->children()) { -// groupby_phys_oper->add_general_child(child.get()); -// } - -// transformed->emplace_back(std::move(groupby_phys_oper)); -// } +LogicalInnerJoinToNestedLoopJoin::LogicalInnerJoinToNestedLoopJoin() +{ + type_ = RuleType::INNER_JOIN_TO_NL_JOIN; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALINNERJOIN)); + auto left = new Pattern(OpType::LEAF); + auto right = new Pattern(OpType::LEAF); + match_pattern_->add_child(left); + match_pattern_->add_child(right); +} + +void LogicalInnerJoinToNestedLoopJoin::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + ASSERT(input->get_children_groups_size() == 2, "join should have 2 children"); + + auto nl_join_oper = make_unique(); + transformed->emplace_back(std::move(nl_join_oper), input->get_child_group_ids()); +} + +// ------------------------------------------------------------------------------------------------- +// Physical Hash Join +// ------------------------------------------------------------------------------------------------- +LogicalInnerJoinToHashJoin::LogicalInnerJoinToHashJoin() +{ + type_ = RuleType::INNER_JOIN_TO_HASH_JOIN; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALINNERJOIN)); + auto left = new Pattern(OpType::LEAF); + auto right = new Pattern(OpType::LEAF); + match_pattern_->add_child(left); + match_pattern_->add_child(right); +} + +void LogicalInnerJoinToHashJoin::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + ASSERT(input->get_children_groups_size() == 2, "join should have 2 children"); + + // TODO: HashJoinPhysicalOperator 目前是空的,需要实现 + // 暂时不生成 HashJoin,等实现后再启用 + // auto hash_join_oper = make_unique(); + // transformed->emplace_back(std::move(hash_join_oper), input->get_child_group_ids()); +} +// ------------------------------------------------------------------------------------------------- +// Physical Aggregation (Scalar GroupBy) +// ------------------------------------------------------------------------------------------------- +LogicalGroupByToAggregation::LogicalGroupByToAggregation() +{ + type_ = RuleType::GROUP_BY_TO_PHYSICAL_AGGREGATION; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALGROUPBY)); + auto child = new Pattern(OpType::LEAF); + match_pattern_->add_child(child); +} + +void LogicalGroupByToAggregation::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + auto groupby_oper = static_cast(input->get_op()); + vector> &group_by_expressions = groupby_oper->group_by_expressions(); + + // 只有 group_by_expressions 为空时才生成 ScalarGroupBy + if (group_by_expressions.empty()) { + vector aggregate_exprs; + for (auto expr : groupby_oper->aggregate_expressions()) { + aggregate_exprs.push_back(expr); + } + auto groupby_phys_oper = make_unique(std::move(aggregate_exprs)); + transformed->emplace_back(std::move(groupby_phys_oper), input->get_child_group_ids()); + } +} // ------------------------------------------------------------------------------------------------- // Physical Hash Group By // ------------------------------------------------------------------------------------------------- -// LogicalGroupByToHashGroupBy::LogicalGroupByToHashGroupBy() -// { -// type_ = RuleType::GROUP_BY_TO_PHYSICL_HASH_GROUP_BY; -// match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALGROUPBY)); -// auto child = new Pattern(OpType::LEAF); -// match_pattern_->add_child(child); -// } - - -// void LogicalGroupByToHashGroupBy::transform(OperatorNode* input, -// std::vector> *transformed, -// OptimizerContext *context) const -// { -// auto groupby_oper = dynamic_cast(input); -// vector> &group_by_expressions = groupby_oper->group_by_expressions(); -// unique_ptr groupby_phys_oper; -// if (group_by_expressions.empty()) { -// return; -// } else { -// groupby_phys_oper = make_unique(std::move(groupby_oper->group_by_expressions()), -// std::move(groupby_oper->aggregate_expressions())); -// } -// for (auto &child : groupby_oper->children()) { -// groupby_phys_oper->add_general_child(child.get()); -// } - -// transformed->emplace_back(std::move(groupby_phys_oper)); -// } \ No newline at end of file +LogicalGroupByToHashGroupBy::LogicalGroupByToHashGroupBy() +{ + type_ = RuleType::GROUP_BY_TO_PHYSICL_HASH_GROUP_BY; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALGROUPBY)); + auto child = new Pattern(OpType::LEAF); + match_pattern_->add_child(child); +} + +void LogicalGroupByToHashGroupBy::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + auto groupby_oper = static_cast(input->get_op()); + vector> &group_by_expressions = groupby_oper->group_by_expressions(); + + // 只有 group_by_expressions 不为空时才生成 HashGroupBy + if (!group_by_expressions.empty()) { + vector> group_by_exprs; + for (auto &expr : group_by_expressions) { + group_by_exprs.push_back(expr->copy()); + } + vector aggregate_exprs; + for (auto expr : groupby_oper->aggregate_expressions()) { + aggregate_exprs.push_back(expr); + } + auto groupby_phys_oper = make_unique(std::move(group_by_exprs), std::move(aggregate_exprs)); + transformed->emplace_back(std::move(groupby_phys_oper), input->get_child_group_ids()); + } +} \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/implementation_rules.h b/src/observer/sql/optimizer/cascade/implementation_rules.h index d82182ce6..ed07c6908 100644 --- a/src/observer/sql/optimizer/cascade/implementation_rules.h +++ b/src/observer/sql/optimizer/cascade/implementation_rules.h @@ -20,13 +20,21 @@ class LogicalGetToPhysicalSeqScan : public Rule public: LogicalGetToPhysicalSeqScan(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; -// TODO: support index scan -// class LogicalGetToPhysicalIndexScan : public Rule { -// }; +/** + * Rule transforms Logical Get -> Physical Index Scan + */ +class LogicalGetToPhysicalIndexScan : public Rule +{ +public: + LogicalGetToPhysicalIndexScan(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; /** * Rule transforms Logical Projection -> Physical Projection @@ -36,8 +44,8 @@ class LogicalProjectionToProjection : public Rule public: LogicalProjectionToProjection(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; /** @@ -48,8 +56,8 @@ class LogicalInsertToInsert : public Rule public: LogicalInsertToInsert(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; /** @@ -60,8 +68,8 @@ class LogicalExplainToExplain : public Rule public: LogicalExplainToExplain(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; /** @@ -72,8 +80,8 @@ class LogicalCalcToCalc : public Rule public: LogicalCalcToCalc(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; /** @@ -84,8 +92,8 @@ class LogicalDeleteToDelete : public Rule public: LogicalDeleteToDelete(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; /** @@ -97,32 +105,54 @@ class LogicalPredicateToPredicate : public Rule public: LogicalPredicateToPredicate(); - void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const override; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; + +/** + * Rule transforms Logical Inner Join -> Physical Nested Loop Join + */ +class LogicalInnerJoinToNestedLoopJoin : public Rule +{ +public: + LogicalInnerJoinToNestedLoopJoin(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; + +/** + * Rule transforms Logical Inner Join -> Physical Hash Join + */ +class LogicalInnerJoinToHashJoin : public Rule +{ +public: + LogicalInnerJoinToHashJoin(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; /** * Rule transforms Logical Groupby -> Physical Aggregation(Scalar Groupby) - * TODO: currently group by is competition problem, so we don't implement this rule */ -// class LogicalGroupByToAggregation : public Rule { -// public: -// LogicalGroupByToAggregation(); +class LogicalGroupByToAggregation : public Rule +{ +public: + LogicalGroupByToAggregation(); -// void transform(OperatorNode* input, -// std::vector> *transformed, -// OptimizerContext *context) const override; -// }; + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; /** * Rule transforms Logical GroupBy -> Physical GroupBy(Hash GroupBy) - * TODO: currently group by is competition problem, so we don't implement this rule */ -// class LogicalGroupByToHashGroupBy : public Rule { -// public: -// LogicalGroupByToHashGroupBy(); - -// void transform(OperatorNode* input, -// std::vector> *transformed, -// OptimizerContext *context) const override; -// }; \ No newline at end of file +class LogicalGroupByToHashGroupBy : public Rule +{ +public: + LogicalGroupByToHashGroupBy(); + + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/memo.h b/src/observer/sql/optimizer/cascade/memo.h index cef553795..6ee090b34 100644 --- a/src/observer/sql/optimizer/cascade/memo.h +++ b/src/observer/sql/optimizer/cascade/memo.h @@ -45,16 +45,6 @@ class Memo void dump() const; - void record_operator(unique_ptr &&node) { operator_nodes_.emplace(node.get(), std::move(node)); } - - void release_operator(OperatorNode *node) - { - auto it = operator_nodes_.find(node); - if (it != operator_nodes_.end()) { - it->second.release(); - } - } - private: int add_new_group(GroupExpr *gexpr); @@ -85,9 +75,4 @@ class Memo std::unordered_set group_expressions_; vector> groups_; - - // TODO: 这是用来存储在 optimize - // 过程中生成的临时物理算子节点的,有些物理算子节点的所有权会转移到外面,有些物理算子的所有权还在memo,需要删除。 用 - // shared_ptr 更加合适,但是改动比较大,先暂时不改了。 - std::unordered_map> operator_nodes_; }; \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/optimizer.cpp b/src/observer/sql/optimizer/cascade/optimizer.cpp index 12973aeec..ef42b7f8e 100644 --- a/src/observer/sql/optimizer/cascade/optimizer.cpp +++ b/src/observer/sql/optimizer/cascade/optimizer.cpp @@ -12,18 +12,13 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/tasks/o_group_task.h" #include "sql/optimizer/cascade/memo.h" -RC Optimizer::optimize(unique_ptr op_tree, std::unique_ptr &physical_operator) +RC Optimizer::optimize(GroupExpr *root_gexpr, std::unique_ptr &physical_operator) { - // Generate initial operator tree from query tree - GroupExpr *gexpr = nullptr; - bool insert = context_->record_node_into_group(op_tree.get(), &gexpr); - if(!insert || gexpr == nullptr) { - LOG_ERROR("Logical expression tree should insert"); - return RC::CASCADE_FAIL; - } + ASSERT(root_gexpr != nullptr, "Root group expression should not be null"); + context_->get_memo().dump(); - int root_id = gexpr->get_group_id(); + int root_id = root_gexpr->get_group_id(); RC rc = optimize_loop(root_id); if(OB_FAIL(rc)) { @@ -40,17 +35,16 @@ RC Optimizer::choose_best_plan(int root_group_id, std::unique_ptrget_winner(); if (winner == nullptr) { LOG_WARN("No winner found in group %d", root_group_id); - return RC::CASCADE_FAIL; + return RC::OPTIMIZER_MEMO_INSERT_FAILED; } - auto winner_contents = winner->get_op(); - context_->get_memo().release_operator(winner_contents); + auto winner_contents = winner->release_op(); PhysicalOperator* winner_phys = static_cast(winner_contents); LOG_TRACE("winner: %d", winner_phys->get_op_type()); for (const auto& child : winner->get_child_group_ids()) { diff --git a/src/observer/sql/optimizer/cascade/optimizer.h b/src/observer/sql/optimizer/cascade/optimizer.h index 8982fb26f..1bef9ae1d 100644 --- a/src/observer/sql/optimizer/cascade/optimizer.h +++ b/src/observer/sql/optimizer/cascade/optimizer.h @@ -15,19 +15,22 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/physical_operator.h" #include "sql/optimizer/cascade/property_set.h" +class GroupExpr; + /** * @brief cascade optimizer - * TODO: currently, Optimizer is used for CBO optimization. need to unify the optimizer in miniob */ class Optimizer { public: Optimizer() : context_(std::make_unique()) {} - RC optimize(unique_ptr op_tree, std::unique_ptr &physical_operator); + RC optimize(GroupExpr *root_gexpr, std::unique_ptr &physical_operator); RC choose_best_plan(int root_id, std::unique_ptr &physical_operator); + OptimizerContext *context() { return context_.get(); } + private: RC optimize_loop(int root_group_id); diff --git a/src/observer/sql/optimizer/cascade/optimizer_context.cpp b/src/observer/sql/optimizer/cascade/optimizer_context.cpp index 4dce30d85..1ec184308 100644 --- a/src/observer/sql/optimizer/cascade/optimizer_context.cpp +++ b/src/observer/sql/optimizer/cascade/optimizer_context.cpp @@ -31,40 +31,32 @@ OptimizerContext::~OptimizerContext() { } } -GroupExpr *OptimizerContext::make_group_expression(OperatorNode* node) -{ - std::vector child_groups; - for (auto &child : node->get_general_children()) { - auto gexpr = make_group_expression(child); - - // Insert into the memo (this allows for duplicate detection) - auto mexpr = memo_->insert_expression(gexpr); - if (mexpr == nullptr) { - // Delete if need to (see InsertExpression spec) - child_groups.push_back(gexpr->get_group_id()); - delete gexpr; - } else { - child_groups.push_back(mexpr->get_group_id()); - } - } - return new GroupExpr(node, std::move(child_groups)); +bool OptimizerContext::record_node_into_group(unique_ptr node, GroupExpr **gexpr, + int target_group) { + // 此方法仅用于没有子节点的叶子节点(如TableGet, Calc, Insert等) + // 对于有子节点的情况,应该使用record_node_into_group(CandidateExpression &candidate, ...) + // 注意:node的所有权会被转移到GroupExpr中 + // 如果节点已存在,memo_->insert_expression会删除new_gexpr,从而释放node + std::vector empty_child_groups; + auto new_gexpr = new GroupExpr(std::move(node), std::move(empty_child_groups)); + auto ptr = memo_->insert_expression(new_gexpr, target_group); + ASSERT(ptr, "Root of expr should not fail insertion"); + + (*gexpr) = ptr; + // 如果返回的ptr不是new_gexpr,说明节点已存在,new_gexpr会被删除,node也会被释放 + // 如果返回的ptr是new_gexpr,说明是新插入的,node的所有权已转移到GroupExpr + return (ptr == new_gexpr); } - bool OptimizerContext::record_node_into_group(OperatorNode* node, GroupExpr **gexpr, - int target_group) { - auto new_gexpr = make_group_expression(node); - auto ptr = memo_->insert_expression(new_gexpr, target_group); - ASSERT(ptr, "Root of expr should not fail insertion"); +bool OptimizerContext::record_node_into_group(CandidateExpression &candidate, GroupExpr **gexpr, int target_group) { + auto new_gexpr = new GroupExpr(std::move(candidate.op), std::move(candidate.child_group_ids)); + auto ptr = memo_->insert_expression(new_gexpr, target_group); + ASSERT(ptr, "Root of expr should not fail insertion"); - (*gexpr) = ptr; - return (ptr == new_gexpr); - } - - Memo &OptimizerContext::get_memo() { return *memo_; } + (*gexpr) = ptr; + return (ptr == new_gexpr); +} - RuleSet &OptimizerContext::get_rule_set() { return *rule_set_; } +Memo &OptimizerContext::get_memo() { return *memo_; } - void OptimizerContext::record_operator_node_in_memo(unique_ptr&& node) - { - memo_->record_operator(std::move(node)); - } \ No newline at end of file +RuleSet &OptimizerContext::get_rule_set() { return *rule_set_; } diff --git a/src/observer/sql/optimizer/cascade/optimizer_context.h b/src/observer/sql/optimizer/cascade/optimizer_context.h index a77fc8162..c56a54bb0 100644 --- a/src/observer/sql/optimizer/cascade/optimizer_context.h +++ b/src/observer/sql/optimizer/cascade/optimizer_context.h @@ -19,6 +19,7 @@ See the Mulan PSL v2 for more details. */ class Memo; class RuleSet; +class CandidateExpression; /** * OptimizerContext is a class containing pointers to various objects * that are required during the entire query optimization process. @@ -48,11 +49,11 @@ class OptimizerContext void record_operator_node_in_memo(unique_ptr &&node); - GroupExpr *make_group_expression(OperatorNode *node); + // 记录没有子节点的OperatorNode到memo中(用于叶子节点,如TableGet, Calc, Insert等) + bool record_node_into_group(unique_ptr node, GroupExpr **gexpr, int target_group = -1); - bool record_node_into_group(OperatorNode *node, GroupExpr **gexpr) { return record_node_into_group(node, gexpr, -1); } - - bool record_node_into_group(OperatorNode *node, GroupExpr **gexpr, int target_group); + // 记录有子节点的CandidateExpression到memo中(子节点通过child_group_ids指定) + bool record_node_into_group(CandidateExpression &candidate, GroupExpr **gexpr, int target_group = -1); double get_cost_upper_bound() const { return cost_upper_bound_; } diff --git a/src/observer/sql/optimizer/cascade/rules.cpp b/src/observer/sql/optimizer/cascade/rules.cpp index c78fbf596..58f78665e 100644 --- a/src/observer/sql/optimizer/cascade/rules.cpp +++ b/src/observer/sql/optimizer/cascade/rules.cpp @@ -10,15 +10,28 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/rules.h" #include "sql/optimizer/cascade/implementation_rules.h" +#include "sql/optimizer/cascade/transformation_rules.h" #include "sql/optimizer/cascade/group_expr.h" RuleSet::RuleSet() { + // Transformation rules (logical -> logical) + add_rule(RuleSetName::LOGICAL_TRANSFORMATION, new PredicatePushdownRule()); + add_rule(RuleSetName::LOGICAL_TRANSFORMATION, new PredicateRewriteRule()); + add_rule(RuleSetName::LOGICAL_TRANSFORMATION, new ExpressionSimplifyRule()); + + // Implementation rules (logical -> physical) add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalProjectionToProjection()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalGetToPhysicalSeqScan()); + add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalGetToPhysicalIndexScan()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalInsertToInsert()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalExplainToExplain()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalCalcToCalc()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalDeleteToDelete()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalPredicateToPredicate()); + add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalInnerJoinToNestedLoopJoin()); + // TODO: 等 HashJoinPhysicalOperator 实现后再启用 + // add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalInnerJoinToHashJoin()); + add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalGroupByToAggregation()); + add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalGroupByToHashGroupBy()); } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/rules.h b/src/observer/sql/optimizer/cascade/rules.h index b60547a31..da75084cb 100644 --- a/src/observer/sql/optimizer/cascade/rules.h +++ b/src/observer/sql/optimizer/cascade/rules.h @@ -20,7 +20,9 @@ See the Mulan PSL v2 for more details. */ enum class RuleType : uint32_t { // Transformation rules (logical -> logical) - // TODO: currently, we don't have transformation rules + PREDICATE_PUSHDOWN, // 谓词下推 + PREDICATE_REWRITE, // 谓词重写(删除恒真/恒假谓词) + EXPRESSION_SIMPLIFY, // 表达式简化 // Don't move this one LogicalPhysicalDelimiter, @@ -51,26 +53,41 @@ enum class RuleType : uint32_t */ enum class RuleSetName : uint32_t { - // TODO: add more rule sets - PHYSICAL_IMPLEMENTATION + LOGICAL_TRANSFORMATION, // 逻辑转换规则(logical -> logical) + PHYSICAL_IMPLEMENTATION // 物理实现规则(logical -> physical) }; /** * Enum defining rule promises - * LogicalPromise should be used for logical rules + * Higher promise means the rule should be applied sooner. + * Since we use a stack (LIFO), rules with higher promise are pushed later and executed first. + * We want TRANSFORMATION rules (logical -> logical) to execute before IMPLEMENTATION rules (logical -> physical), + * so TRANSFORMATION rules should have higher promise. */ enum class RulePromise : uint32_t { /** - * Logical rule/low priority unnest + * Physical rule (implementation rules) + * Lower promise, will be pushed first, executed later */ - LOGICAL_PROMISE = 0, + PHYSICAL_PROMISE = 0, /** - * Physical rule + * Logical rule (transformation rules) + * Higher promise, will be pushed later, executed first */ - PHYSICAL_PROMISE = 1 + LOGICAL_PROMISE = 1 +}; + +struct CandidateExpression +{ + std::unique_ptr op; + std::vector child_group_ids; + + CandidateExpression(std::unique_ptr node, std::vector children = std::vector()) + : op(std::move(node)), child_group_ids(std::move(children)) + {} }; /** @@ -126,8 +143,8 @@ class Rule * @param transformed Vector of "after" operator trees * @param context The current optimization context */ - virtual void transform(OperatorNode *input, std::vector> *transformed, - OptimizerContext *context) const = 0; + virtual void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const = 0; protected: RuleType type_; diff --git a/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp b/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp index 80fb34054..91c61321f 100644 --- a/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/apply_rule_task.cpp @@ -22,16 +22,14 @@ RC ApplyRule::perform() return RC::SUCCESS; } // TODO: expr binding, currently group_expr_->get_op() is enough - OperatorNode* before = group_expr_->get_op(); - // TODO: check condition - std::vector> after; - rule_->transform(before, &after, context_); - for (const auto &new_expr : after) { + std::vector after; + rule_->transform(group_expr_, &after, context_); + for (auto &candidate : after) { GroupExpr *new_gexpr = nullptr; auto g_id = group_expr_->get_group_id(); - if (context_->record_node_into_group(new_expr.get(), &new_gexpr, g_id)) { + if(context_->record_node_into_group(candidate, &new_gexpr, g_id)) { if (new_gexpr->get_op()->is_logical()) { // further optimize new expr push_task(new OptimizeExpression(new_gexpr, context_)); @@ -42,14 +40,8 @@ RC ApplyRule::perform() } else { LOG_INFO("record_operator_node_into_group not insert new expr"); new_gexpr->dump(); - return RC::CASCADE_FAIL; } } - - // TODO: FIXME, better way for record memory allocation - for (size_t i = 0; i < after.size(); i++) { - context_->record_operator_node_in_memo(std::move(after[i])); - } group_expr_->set_rule_explored(rule_); return RC::SUCCESS; diff --git a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp index bdee74d6e..e5711eebd 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp @@ -20,8 +20,28 @@ RC OptimizeExpression::perform() { std::vector valid_rules; - // Construct valid transformation rules from rule set - // TODO: add transformation rules + // First, collect transformation rules (logical -> logical) + auto trans_rules = get_rule_set().get_rules_by_name(RuleSetName::LOGICAL_TRANSFORMATION); + for (auto &rule : trans_rules) { + // check if we can apply the rule + bool already_explored = group_expr_->rule_explored(rule); + if (already_explored) { + continue; + } + bool root_pattern_mismatch = group_expr_->get_op()->get_op_type() != rule->get_match_pattern()->type(); + + bool child_pattern_mismatch = + group_expr_->get_children_groups_size() != rule->get_match_pattern()->get_child_patterns_size(); + + if (root_pattern_mismatch || child_pattern_mismatch) { + continue; + } + + auto promise = rule->promise(group_expr_); + valid_rules.emplace_back(rule, promise); + } + + // Then, collect implementation rules (logical -> physical) auto phys_rules = get_rule_set().get_rules_by_name(RuleSetName::PHYSICAL_IMPLEMENTATION); for (auto &rule : phys_rules) { // check if we can apply the rule @@ -42,6 +62,11 @@ RC OptimizeExpression::perform() valid_rules.emplace_back(rule, promise); } + if(valid_rules.size() == 0 && group_expr_->get_op()->is_logical()) { + LOG_ERROR("Missing physical implementation rule for logical operator type: %d", static_cast(group_expr_->get_op()->get_op_type())); + return RC::OPTIMIZER_GROUP_EXPR_CREATE_FAILED; + } + std::sort(valid_rules.begin(), valid_rules.end()); LOG_TRACE("OptimizeExpression::perform() op {%d}, valid rules : {%d}", static_cast(group_expr_->get_op()->get_op_type()), valid_rules.size()); diff --git a/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp index dfa660b36..677bfda2c 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_group_task.cpp @@ -17,23 +17,18 @@ RC OptimizeGroup::perform() { LOG_TRACE("OptimizeGroup::perform() group %d", group_->get_id()); // TODO: currently the cost upper bound is not used - if (group_->get_cost_lb() > context_->get_cost_upper_bound()) { + if (group_->get_cost_lb() > context_->get_cost_upper_bound() || group_->has_explored()) { return RC::SUCCESS; } - if (group_->get_winner() != nullptr) { - return RC::SUCCESS; - } - - if (!group_->has_explored()) { - for (auto &logical_expr : group_->get_logical_expressions()) { - push_task(new OptimizeExpression(logical_expr, context_)); - } - } for (auto &physical_expr : group_->get_physical_expressions()) { push_task(new OptimizeInputs(physical_expr, context_)); } + for (auto &logical_expr : group_->get_logical_expressions()) { + push_task(new OptimizeExpression(logical_expr, context_)); + } + group_->set_explored(); return RC::SUCCESS; } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp index d194eba7b..a50b5a9ff 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_input_task.cpp @@ -23,8 +23,14 @@ RC OptimizeInputs::perform() cur_child_idx_ = 0; // only calculate once for current group expr - cur_total_cost_ += context_->get_cost_model()->calculate_cost( + double local_cost = context_->get_cost_model()->calculate_cost( &context_->get_memo(), group_expr_); + cur_total_cost_ += local_cost; + LOG_INFO("OptimizeInputs: group_expr op_type=%d, group_id=%d, local_cost=%.6f, cur_total_cost=%.6f", + static_cast(group_expr_->get_op()->get_op_type()), + group_expr_->get_group_id(), + local_cost, + cur_total_cost_); } for (; cur_child_idx_ < static_cast(group_expr_->get_children_groups_size()); cur_child_idx_++) { auto child_group = @@ -36,8 +42,7 @@ RC OptimizeInputs::perform() cur_total_cost_ += child_best_expr->get_cost(); LOG_INFO("cur_total_cost_ = %f", cur_total_cost_); if (cur_total_cost_ > context_->get_cost_upper_bound()) break; - } else if (prev_child_idx_ != cur_child_idx_) { // we haven't optimized child group - prev_child_idx_ = cur_child_idx_; + } else { // we haven't optimized child group push_task(new OptimizeInputs(this)); push_task(new OptimizeGroup(child_group, context_)); return RC::SUCCESS; diff --git a/src/observer/sql/optimizer/cascade/tasks/o_input_task.h b/src/observer/sql/optimizer/cascade/tasks/o_input_task.h index 439419b3a..713edf291 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_input_task.h +++ b/src/observer/sql/optimizer/cascade/tasks/o_input_task.h @@ -43,9 +43,4 @@ class OptimizeInputs : public CascadeTask * input currently being or about to be optimized */ int cur_child_idx_ = -1; - - /** - * keep track of the previous optimized input idx - */ - int prev_child_idx_ = -1; }; \ No newline at end of file diff --git a/src/observer/sql/optimizer/logical_plan_generator.cpp b/src/observer/sql/optimizer/logical_plan_generator.cpp index a6b11b146..fc667c83c 100644 --- a/src/observer/sql/optimizer/logical_plan_generator.cpp +++ b/src/observer/sql/optimizer/logical_plan_generator.cpp @@ -36,42 +36,40 @@ See the Mulan PSL v2 for more details. */ #include "sql/stmt/stmt.h" #include "sql/expr/expression_iterator.h" +#include "sql/optimizer/cascade/optimizer_context.h" +#include "sql/optimizer/cascade/group_expr.h" +#include "sql/optimizer/cascade/memo.h" using namespace std; using namespace common; -RC LogicalPlanGenerator::create(Stmt *stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create(Stmt *stmt, GroupExpr *&root_gexpr, OptimizerContext *context) { RC rc = RC::SUCCESS; switch (stmt->type()) { case StmtType::CALC: { CalcStmt *calc_stmt = static_cast(stmt); - - rc = create_plan(calc_stmt, logical_operator); + rc = create_plan(calc_stmt, root_gexpr, context); } break; case StmtType::SELECT: { SelectStmt *select_stmt = static_cast(stmt); - - rc = create_plan(select_stmt, logical_operator); + rc = create_plan(select_stmt, root_gexpr, context); } break; case StmtType::INSERT: { InsertStmt *insert_stmt = static_cast(stmt); - - rc = create_plan(insert_stmt, logical_operator); + rc = create_plan(insert_stmt, root_gexpr, context); } break; case StmtType::DELETE: { DeleteStmt *delete_stmt = static_cast(stmt); - - rc = create_plan(delete_stmt, logical_operator); + rc = create_plan(delete_stmt, root_gexpr, context); } break; case StmtType::EXPLAIN: { ExplainStmt *explain_stmt = static_cast(stmt); - - rc = create_plan(explain_stmt, logical_operator); + rc = create_plan(explain_stmt, root_gexpr, context); } break; default: { rc = RC::UNIMPLEMENTED; @@ -80,76 +78,101 @@ RC LogicalPlanGenerator::create(Stmt *stmt, unique_ptr &logical return rc; } -RC LogicalPlanGenerator::create_plan(CalcStmt *calc_stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create_plan(CalcStmt *calc_stmt, GroupExpr *&root_gexpr, OptimizerContext *context) { - logical_operator.reset(new CalcLogicalOperator(std::move(calc_stmt->expressions()))); + unique_ptr calc_op(new CalcLogicalOperator(std::move(calc_stmt->expressions()))); + context->record_node_into_group(std::move(calc_op), &root_gexpr); return RC::SUCCESS; } -RC LogicalPlanGenerator::create_plan(SelectStmt *select_stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create_plan(SelectStmt *select_stmt, GroupExpr *&root_gexpr, OptimizerContext *context) { - unique_ptr *last_oper = nullptr; - - unique_ptr table_oper(nullptr); - last_oper = &table_oper; - unique_ptr predicate_oper; - - RC rc = create_plan(select_stmt->filter_stmt(), predicate_oper); - if (OB_FAIL(rc)) { - LOG_WARN("failed to create predicate logical plan. rc=%s", strrc(rc)); - return rc; - } + GroupExpr *last_gexpr = nullptr; + // GroupExpr *group_by_gexpr = nullptr; + // 1. 创建table get和join const vector &tables = select_stmt->tables(); for (Table *table : tables) { + unique_ptr table_get_op(new TableGetLogicalOperator(table, ReadWriteMode::READ_ONLY)); + GroupExpr *table_get_gexpr = nullptr; + context->record_node_into_group(std::move(table_get_op), &table_get_gexpr); - unique_ptr table_get_oper(new TableGetLogicalOperator(table, ReadWriteMode::READ_ONLY)); - if (table_oper == nullptr) { - table_oper = std::move(table_get_oper); + if (last_gexpr == nullptr) { + last_gexpr = table_get_gexpr; } else { - JoinLogicalOperator *join_oper = new JoinLogicalOperator; - join_oper->add_child(std::move(table_oper)); - join_oper->add_child(std::move(table_get_oper)); - table_oper = unique_ptr(join_oper); + // 创建join + unique_ptr join_op(new JoinLogicalOperator); + std::vector child_groups = {last_gexpr->get_group_id(), table_get_gexpr->get_group_id()}; + CandidateExpression candidate(std::move(join_op), std::move(child_groups)); + context->record_node_into_group(candidate, &last_gexpr); } } - - if (predicate_oper) { - if (*last_oper) { - predicate_oper->add_child(std::move(*last_oper)); + // 2. 创建filter/predicate 0x606000001820 + if (select_stmt->filter_stmt()) { + // 先创建predicate的expressions + RC rc = create_plan(select_stmt->filter_stmt(), last_gexpr, context, last_gexpr->get_group_id()); + if (OB_FAIL(rc)) { + LOG_WARN("failed to create predicate logical plan. rc=%s", strrc(rc)); + return rc; } - - last_oper = &predicate_oper; } - unique_ptr group_by_oper; - rc = create_group_by_plan(select_stmt, group_by_oper); - if (OB_FAIL(rc)) { - LOG_WARN("failed to create group by logical plan. rc=%s", strrc(rc)); - return rc; - } - - if (group_by_oper) { - if (*last_oper) { - group_by_oper->add_child(std::move(*last_oper)); - } - - last_oper = &group_by_oper; - } - - unique_ptr project_oper = make_unique(std::move(select_stmt->query_expressions())); - if (*last_oper) { - project_oper->add_child(std::move(*last_oper)); - } - - last_oper = &project_oper; - - logical_operator = std::move(*last_oper); + // // 3. 创建group by(检查是否有group by或聚合函数) + // bool has_aggregation = false; + // function&)> check_aggregation = [&](unique_ptr &expr) -> RC { + // if (expr->type() == ExprType::AGGREGATION) { + // has_aggregation = true; + // } + // return ExpressionIterator::iterate_child_expr(*expr, check_aggregation); + // }; + // for (auto &expr : select_stmt->query_expressions()) { + // check_aggregation(expr); + // } + + // if (select_stmt->group_by().size() > 0 || has_aggregation) { + // // 创建group by expressions和aggregate expressions + // vector> group_by_exprs; + // for (auto &expr : select_stmt->group_by()) { + // group_by_exprs.push_back(expr->copy()); + // } + + // vector aggregate_expressions; + // function&)> collector = [&](unique_ptr &expr) -> RC { + // RC rc = RC::SUCCESS; + // if (expr->type() == ExprType::AGGREGATION) { + // aggregate_expressions.push_back(expr.get()); + // } + // rc = ExpressionIterator::iterate_child_expr(*expr, collector); + // return rc; + // }; + + // for (auto &expr : select_stmt->query_expressions()) { + // collector(expr); + // } + + // if (last_gexpr) { + // unique_ptr group_by_op(new GroupByLogicalOperator(std::move(group_by_exprs), std::move(aggregate_expressions))); + // std::vector child_groups = {last_gexpr->get_group_id()}; + // CandidateExpression candidate(std::move(group_by_op), std::move(child_groups)); + // bool inserted = context->record_node_into_group(candidate, &group_by_gexpr); + // if (!inserted) { + // Memo &memo = context->get_memo(); + // auto group = memo.get_group_by_id(group_by_gexpr->get_group_id()); + // group_by_gexpr = group->get_logical_expression(); + // } + // last_gexpr = group_by_gexpr; + // } + // } + + // 4. 创建projection + unique_ptr project_op(new ProjectLogicalOperator(std::move(select_stmt->query_expressions()))); + CandidateExpression candidate(std::move(project_op), {last_gexpr->get_group_id()}); + context->record_node_into_group(candidate, &root_gexpr); return RC::SUCCESS; } -RC LogicalPlanGenerator::create_plan(FilterStmt *filter_stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create_plan(FilterStmt *filter_stmt, GroupExpr *&root_gexpr, OptimizerContext *context, int gid) { RC rc = RC::SUCCESS; vector> cmp_exprs; @@ -209,13 +232,11 @@ RC LogicalPlanGenerator::create_plan(FilterStmt *filter_stmt, unique_ptr predicate_oper; - if (!cmp_exprs.empty()) { - unique_ptr conjunction_expr(new ConjunctionExpr(ConjunctionExpr::Type::AND, cmp_exprs)); - predicate_oper = unique_ptr(new PredicateLogicalOperator(std::move(conjunction_expr))); - } + unique_ptr conjunction_expr(new ConjunctionExpr(ConjunctionExpr::Type::AND, cmp_exprs)); + unique_ptr predicate_op(new PredicateLogicalOperator(std::move(conjunction_expr))); + CandidateExpression candidate(std::move(predicate_op), {gid}); + context->record_node_into_group(candidate, &root_gexpr); - logical_operator = std::move(predicate_oper); return rc; } @@ -227,133 +248,70 @@ int LogicalPlanGenerator::implicit_cast_cost(AttrType from, AttrType to) return DataType::type_instance(from)->cast_cost(to); } -RC LogicalPlanGenerator::create_plan(InsertStmt *insert_stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create_plan(InsertStmt *insert_stmt, GroupExpr *&root_gexpr, OptimizerContext *context) { Table *table = insert_stmt->table(); vector values(insert_stmt->values(), insert_stmt->values() + insert_stmt->value_amount()); - - InsertLogicalOperator *insert_operator = new InsertLogicalOperator(table, values); - logical_operator.reset(insert_operator); + unique_ptr insert_op(new InsertLogicalOperator(table, values)); + context->record_node_into_group(std::move(insert_op), &root_gexpr); return RC::SUCCESS; } -RC LogicalPlanGenerator::create_plan(DeleteStmt *delete_stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create_plan(DeleteStmt *delete_stmt, GroupExpr *&root_gexpr, OptimizerContext *context) { - Table *table = delete_stmt->table(); - FilterStmt *filter_stmt = delete_stmt->filter_stmt(); - unique_ptr table_get_oper(new TableGetLogicalOperator(table, ReadWriteMode::READ_WRITE)); + Table *table = delete_stmt->table(); + FilterStmt *filter_stmt = delete_stmt->filter_stmt(); - unique_ptr predicate_oper; + // 1. 创建table get + unique_ptr table_get_op(new TableGetLogicalOperator(table, ReadWriteMode::READ_WRITE)); + GroupExpr *table_get_gexpr = nullptr; + context->record_node_into_group(std::move(table_get_op), &table_get_gexpr); - RC rc = create_plan(filter_stmt, predicate_oper); - if (rc != RC::SUCCESS) { - return rc; + // 2. 创建predicate(如果有) + GroupExpr *predicate_gexpr = nullptr; + GroupExpr *last_gexpr = table_get_gexpr; + + if (filter_stmt) { + RC rc = create_plan(filter_stmt, predicate_gexpr, context, last_gexpr->get_group_id()); + if (OB_FAIL(rc)) { + return rc; + } + last_gexpr = predicate_gexpr; } - unique_ptr delete_oper(new DeleteLogicalOperator(table)); - - if (predicate_oper) { - predicate_oper->add_child(std::move(table_get_oper)); - delete_oper->add_child(std::move(predicate_oper)); - } else { - delete_oper->add_child(std::move(table_get_oper)); - } + // 3. 创建delete + unique_ptr delete_op(new DeleteLogicalOperator(table)); + std::vector child_groups = {last_gexpr->get_group_id()}; + CandidateExpression candidate(std::move(delete_op), std::move(child_groups)); + context->record_node_into_group(candidate, &root_gexpr); - logical_operator = std::move(delete_oper); - return rc; + return RC::SUCCESS; } -RC LogicalPlanGenerator::create_plan(ExplainStmt *explain_stmt, unique_ptr &logical_operator) +RC LogicalPlanGenerator::create_plan(ExplainStmt *explain_stmt, GroupExpr *&root_gexpr, OptimizerContext *context) { - unique_ptr child_oper; - Stmt *child_stmt = explain_stmt->child(); + GroupExpr *child_gexpr = nullptr; - RC rc = create(child_stmt, child_oper); + RC rc = create(child_stmt, child_gexpr, context); if (rc != RC::SUCCESS) { LOG_WARN("failed to create explain's child operator. rc=%s", strrc(rc)); return rc; } - logical_operator = unique_ptr(new ExplainLogicalOperator); - logical_operator->add_child(std::move(child_oper)); - return rc; -} - -RC LogicalPlanGenerator::create_group_by_plan(SelectStmt *select_stmt, unique_ptr &logical_operator) -{ - vector> &group_by_expressions = select_stmt->group_by(); - vector aggregate_expressions; - vector> &query_expressions = select_stmt->query_expressions(); - function&)> collector = [&](unique_ptr &expr) -> RC { - RC rc = RC::SUCCESS; - if (expr->type() == ExprType::AGGREGATION) { - expr->set_pos(aggregate_expressions.size() + group_by_expressions.size()); - aggregate_expressions.push_back(expr.get()); + unique_ptr explain_op(new ExplainLogicalOperator); + if (child_gexpr) { + std::vector child_groups = {child_gexpr->get_group_id()}; + CandidateExpression candidate(std::move(explain_op), std::move(child_groups)); + bool inserted = context->record_node_into_group(candidate, &root_gexpr); + if (!inserted) { + Memo &memo = context->get_memo(); + auto group = memo.get_group_by_id(root_gexpr->get_group_id()); + root_gexpr = group->get_logical_expression(); } - rc = ExpressionIterator::iterate_child_expr(*expr, collector); - return rc; - }; - - function&)> bind_group_by_expr = [&](unique_ptr &expr) -> RC { - RC rc = RC::SUCCESS; - for (size_t i = 0; i < group_by_expressions.size(); i++) { - auto &group_by = group_by_expressions[i]; - if (expr->type() == ExprType::AGGREGATION) { - break; - } else if (expr->equal(*group_by)) { - expr->set_pos(i); - continue; - } else { - rc = ExpressionIterator::iterate_child_expr(*expr, bind_group_by_expr); - } - } - return rc; - }; - - bool found_unbound_column = false; - function&)> find_unbound_column = [&](unique_ptr &expr) -> RC { - RC rc = RC::SUCCESS; - if (expr->type() == ExprType::AGGREGATION) { - // do nothing - } else if (expr->pos() != -1) { - // do nothing - } else if (expr->type() == ExprType::FIELD) { - found_unbound_column = true; - }else { - rc = ExpressionIterator::iterate_child_expr(*expr, find_unbound_column); - } - return rc; - }; - - - for (unique_ptr &expression : query_expressions) { - bind_group_by_expr(expression); - } - - for (unique_ptr &expression : query_expressions) { - find_unbound_column(expression); - } - - // collect all aggregate expressions - for (unique_ptr &expression : query_expressions) { - collector(expression); - } - - if (group_by_expressions.empty() && aggregate_expressions.empty()) { - // 既没有group by也没有聚合函数,不需要group by - return RC::SUCCESS; - } - - if (found_unbound_column) { - LOG_WARN("column must appear in the GROUP BY clause or must be part of an aggregate function"); - return RC::INVALID_ARGUMENT; + } else { + context->record_node_into_group(std::move(explain_op), &root_gexpr); } - // 如果只需要聚合,但是没有group by 语句,需要生成一个空的group by 语句 - - auto group_by_oper = make_unique(std::move(group_by_expressions), - std::move(aggregate_expressions)); - logical_operator = std::move(group_by_oper); - return RC::SUCCESS; + return rc; } diff --git a/src/observer/sql/optimizer/logical_plan_generator.h b/src/observer/sql/optimizer/logical_plan_generator.h index e0707deff..71a50cf9d 100644 --- a/src/observer/sql/optimizer/logical_plan_generator.h +++ b/src/observer/sql/optimizer/logical_plan_generator.h @@ -25,7 +25,8 @@ class FilterStmt; class InsertStmt; class DeleteStmt; class ExplainStmt; -class LogicalOperator; +class GroupExpr; +class OptimizerContext; class LogicalPlanGenerator { @@ -33,17 +34,15 @@ class LogicalPlanGenerator LogicalPlanGenerator() = default; virtual ~LogicalPlanGenerator() = default; - RC create(Stmt *stmt, unique_ptr &logical_operator); + RC create(Stmt *stmt, GroupExpr *&root_gexpr, OptimizerContext *context); private: - RC create_plan(CalcStmt *calc_stmt, unique_ptr &logical_operator); - RC create_plan(SelectStmt *select_stmt, unique_ptr &logical_operator); - RC create_plan(FilterStmt *filter_stmt, unique_ptr &logical_operator); - RC create_plan(InsertStmt *insert_stmt, unique_ptr &logical_operator); - RC create_plan(DeleteStmt *delete_stmt, unique_ptr &logical_operator); - RC create_plan(ExplainStmt *explain_stmt, unique_ptr &logical_operator); - - RC create_group_by_plan(SelectStmt *select_stmt, unique_ptr &logical_operator); + RC create_plan(CalcStmt *calc_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); + RC create_plan(SelectStmt *select_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); + RC create_plan(FilterStmt *filter_stmt, GroupExpr *&root_gexpr, OptimizerContext *context, int gid); + RC create_plan(InsertStmt *insert_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); + RC create_plan(DeleteStmt *delete_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); + RC create_plan(ExplainStmt *explain_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); int implicit_cast_cost(AttrType from, AttrType to); }; diff --git a/src/observer/sql/optimizer/optimize_stage.cpp b/src/observer/sql/optimizer/optimize_stage.cpp index ec8080ccc..a83af467d 100644 --- a/src/observer/sql/optimizer/optimize_stage.cpp +++ b/src/observer/sql/optimizer/optimize_stage.cpp @@ -22,9 +22,9 @@ See the Mulan PSL v2 for more details. */ #include "common/log/log.h" #include "event/session_event.h" #include "event/sql_event.h" -#include "sql/operator/logical_operator.h" #include "sql/stmt/stmt.h" #include "sql/optimizer/cascade/optimizer.h" +#include "sql/optimizer/cascade/group_expr.h" #include "sql/optimizer/optimizer_utils.h" using namespace std; @@ -32,97 +32,39 @@ using namespace common; RC OptimizeStage::handle_request(SQLStageEvent *sql_event) { - unique_ptr logical_operator; + Stmt *stmt = sql_event->stmt(); + if (nullptr == stmt) { + return RC::UNIMPLEMENTED; + } - RC rc = create_logical_plan(sql_event, logical_operator); + Optimizer optimizer; + GroupExpr *root_gexpr = nullptr; + + // 直接生成GroupExpr结构 + RC rc = logical_plan_generator_.create(stmt, root_gexpr, optimizer.context()); if (rc != RC::SUCCESS) { if (rc != RC::UNIMPLEMENTED) { - LOG_WARN("failed to create logical plan. rc=%s", strrc(rc)); + LOG_WARN("failed to create group expression. rc=%s", strrc(rc)); } return rc; } - ASSERT(logical_operator, "logical operator is null"); - - // TODO: unify the RBO and CBO - rc = rewrite(logical_operator); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to rewrite plan. rc=%s", strrc(rc)); - return rc; + if (!root_gexpr) { + LOG_WARN("root group expression is null"); + return RC::INTERNAL; } + // 使用Cascade优化器 unique_ptr physical_operator; - if (sql_event->session_event()->session()->use_cascade()) { - Optimizer optimizer; - rc = optimizer.optimize(std::move(logical_operator), physical_operator); - if (OB_FAIL(rc)) { - LOG_WARN("failed to optimize logical plan. rc=%s", strrc(rc)); - return rc; - } - string phys_plan_str = OptimizerUtils::dump_physical_plan(physical_operator); - - LOG_INFO("cascade physical plan:\n%s", phys_plan_str.c_str()); - } else { - rc = generate_physical_plan(logical_operator, physical_operator, sql_event->session_event()->session()); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to generate physical plan. rc=%s", strrc(rc)); - return rc; - } + // if (sql_event->session_event()->session()->use_cascade()) { + rc = optimizer.optimize(root_gexpr, physical_operator); + if (OB_FAIL(rc)) { + LOG_WARN("failed to optimize logical plan. rc=%s", strrc(rc)); + return rc; } + string phys_plan_str = OptimizerUtils::dump_physical_plan(physical_operator); + LOG_INFO("cascade physical plan:\n%s", phys_plan_str.c_str()); sql_event->set_operator(std::move(physical_operator)); - return rc; } - -RC OptimizeStage::optimize(unique_ptr &oper) -{ - // do nothing - return RC::SUCCESS; -} - -RC OptimizeStage::generate_physical_plan( - unique_ptr &logical_operator, unique_ptr &physical_operator, Session *session) -{ - RC rc = RC::SUCCESS; - if (session->get_execution_mode() == ExecutionMode::CHUNK_ITERATOR && LogicalOperator::can_generate_vectorized_operator(logical_operator->get_op_type())) { - LOG_TRACE("use chunk iterator"); - session->set_used_chunk_mode(true); - rc = physical_plan_generator_.create_vec(*logical_operator, physical_operator, session); - } else { - LOG_TRACE("use tuple iterator"); - session->set_used_chunk_mode(false); - rc = physical_plan_generator_.create(*logical_operator, physical_operator, session); - } - if (rc != RC::SUCCESS) { - LOG_WARN("failed to create physical operator. rc=%s", strrc(rc)); - } - return rc; -} - -RC OptimizeStage::rewrite(unique_ptr &logical_operator) -{ - RC rc = RC::SUCCESS; - - bool change_made = false; - do { - change_made = false; - rc = rewriter_.rewrite(logical_operator, change_made); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to do expression rewrite on logical plan. rc=%s", strrc(rc)); - return rc; - } - } while (change_made); - - return rc; -} - -RC OptimizeStage::create_logical_plan(SQLStageEvent *sql_event, unique_ptr &logical_operator) -{ - Stmt *stmt = sql_event->stmt(); - if (nullptr == stmt) { - return RC::UNIMPLEMENTED; - } - - return logical_plan_generator_.create(stmt, logical_operator); -} diff --git a/src/observer/sql/optimizer/optimize_stage.h b/src/observer/sql/optimizer/optimize_stage.h index b1be2ec28..ea62af751 100644 --- a/src/observer/sql/optimizer/optimize_stage.h +++ b/src/observer/sql/optimizer/optimize_stage.h @@ -15,22 +15,15 @@ See the Mulan PSL v2 for more details. */ #pragma once #include "common/sys/rc.h" -#include "session/session.h" -#include "sql/operator/logical_operator.h" -#include "sql/operator/physical_operator.h" #include "sql/optimizer/logical_plan_generator.h" -#include "sql/optimizer/physical_plan_generator.h" -#include "sql/optimizer/rewrite/rewriter.h" class SQLStageEvent; -class LogicalOperator; class Stmt; /** * @brief 将解析后的Statement转换成执行计划,并进行优化 * @ingroup SQLStage - * @details 优化分为两种,一个是根据规则重写,一个是根据代价模型优化。 - * 在这里,先将Statement转换成逻辑计划,然后进行重写(rewrite),最后生成物理计划。 + * @details 使用Cascade优化器,直接从Statement生成GroupExpr结构,然后进行优化。 * 不过并不是所有的语句都需要生成计划,有些可以直接执行,比如create table、create index等。 * 这些语句可以参考 @class CommandExecutor。 */ @@ -40,42 +33,5 @@ class OptimizeStage RC handle_request(SQLStageEvent *event); private: - /** - * @brief 根据SQL生成逻辑计划 - * @details - * 由于SQL语句种类比较多,并且SQL语句可能会有嵌套的情况,比如带有SQL子查询的语句,那就需要递归的创建逻辑计划。 - * @param sql_event 包含SQL信息的事件 - * @param logical_operator 生成的逻辑计划 - */ - RC create_logical_plan(SQLStageEvent *sql_event, unique_ptr &logical_operator); - - /** - * @brief 重写逻辑计划 - * @details 根据各种规则,对逻辑计划进行重写,比如消除多余的比较(1!=0)等。 - * 规则改写也是一个递归的过程。 - * @param logical_operator 要改写的逻辑计划 - */ - RC rewrite(unique_ptr &logical_operator); - - /** - * @brief 优化逻辑计划 - * @details 当前什么都没做。可以增加每个逻辑计划的代价模型,然后根据代价模型进行优化。 - * @param logical_operator 需要优化的逻辑计划 - */ - RC optimize(unique_ptr &logical_operator); - - /** - * @brief 根据逻辑计划生成物理计划 - * @details 生成的物理计划就可以直接让后面的执行器完全按照物理计划执行了。 - * 物理计划与逻辑计划有些不同,逻辑计划描述要干什么,比如从某张表根据什么条件获取什么数据。 - * 而物理计划描述怎么做,比如如何从某张表按照什么条件获取什么数据,是否使用索引,使用哪个索引等。 - * @param physical_operator 生成的物理计划。通常是一个多叉树的形状,这里就拿着根节点就可以了。 - */ - RC generate_physical_plan( - unique_ptr &logical_operator, unique_ptr &physical_operator, Session *session); - -private: - LogicalPlanGenerator logical_plan_generator_; ///< 根据SQL生成逻辑计划 - PhysicalPlanGenerator physical_plan_generator_; ///< 根据逻辑计划生成物理计划 - Rewriter rewriter_; ///< 逻辑计划改写 + LogicalPlanGenerator logical_plan_generator_; ///< 根据SQL生成GroupExpr结构 }; diff --git a/src/observer/sql/optimizer/optimizer_utils.cpp b/src/observer/sql/optimizer/optimizer_utils.cpp index 37fd1064e..bb1edc2b9 100644 --- a/src/observer/sql/optimizer/optimizer_utils.cpp +++ b/src/observer/sql/optimizer/optimizer_utils.cpp @@ -9,6 +9,96 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ #include "sql/optimizer/optimizer_utils.h" +#include "sql/expr/expression.h" +#include "sql/parser/parse_defs.h" + +using namespace std; + +static string comp_op_to_string(CompOp op) +{ + switch (op) { + case CompOp::EQUAL_TO: return "="; + case CompOp::LESS_EQUAL: return "<="; + case CompOp::NOT_EQUAL: return "<>"; + case CompOp::LESS_THAN: return "<"; + case CompOp::GREAT_EQUAL: return ">="; + case CompOp::GREAT_THAN: return ">"; + case CompOp::NO_OP: return ""; + default: return "?"; + } +} + +string OptimizerUtils::expression_to_string(const Expression *expr) +{ + if (expr == nullptr) { + return ""; + } + + switch (expr->type()) { + case ExprType::FIELD: { + const auto *field_expr = static_cast(expr); + string result; + if (field_expr->table_name() && strlen(field_expr->table_name()) > 0) { + result = string(field_expr->table_name()) + "."; + } + result += field_expr->field_name(); + return result; + } + case ExprType::VALUE: { + const auto *value_expr = static_cast(expr); + Value value = value_expr->get_value(); + return value.to_string(); + } + case ExprType::COMPARISON: { + const auto *comp_expr = static_cast(expr); + string left_str = OptimizerUtils::expression_to_string(comp_expr->left().get()); + string right_str = OptimizerUtils::expression_to_string(comp_expr->right().get()); + string op_str = comp_op_to_string(comp_expr->comp()); + return left_str + " " + op_str + " " + right_str; + } + case ExprType::CONJUNCTION: { + const auto *conj_expr = static_cast(expr); + string op_str = (conj_expr->conjunction_type() == ConjunctionExpr::Type::AND) ? "AND" : "OR"; + string result; + const auto &children = conj_expr->children(); + for (size_t i = 0; i < children.size(); i++) { + if (i > 0) { + result += " " + op_str + " "; + } + result += "(" + OptimizerUtils::expression_to_string(children[i].get()) + ")"; + } + return result; + } + case ExprType::ARITHMETIC: { + const auto *arith_expr = static_cast(expr); + string left_str = OptimizerUtils::expression_to_string(arith_expr->left().get()); + string op_str; + switch (arith_expr->arithmetic_type()) { + case ArithmeticExpr::Type::ADD: op_str = "+"; break; + case ArithmeticExpr::Type::SUB: op_str = "-"; break; + case ArithmeticExpr::Type::MUL: op_str = "*"; break; + case ArithmeticExpr::Type::DIV: op_str = "/"; break; + case ArithmeticExpr::Type::NEGATIVE: return "-" + left_str; + default: op_str = "?"; break; + } + if (arith_expr->right()) { + string right_str = OptimizerUtils::expression_to_string(arith_expr->right().get()); + return "(" + left_str + " " + op_str + " " + right_str + ")"; + } else { + return op_str + "(" + left_str + ")"; + } + } + case ExprType::CAST: { + const auto *cast_expr = static_cast(expr); + string child_str = OptimizerUtils::expression_to_string(cast_expr->child().get()); + return "CAST(" + child_str + ")"; + } + default: { + const char *name = expr->name(); + return name ? string(name) : "?"; + } + } +} string OptimizerUtils::dump_physical_plan(const unique_ptr& children) { diff --git a/src/observer/sql/optimizer/optimizer_utils.h b/src/observer/sql/optimizer/optimizer_utils.h index 6cb2c6529..366578bbf 100644 --- a/src/observer/sql/optimizer/optimizer_utils.h +++ b/src/observer/sql/optimizer/optimizer_utils.h @@ -14,8 +14,11 @@ See the Mulan PSL v2 for more details. */ #include "common/lang/memory.h" #include "sql/operator/physical_operator.h" +class Expression; + class OptimizerUtils { public: static string dump_physical_plan(const unique_ptr &root); + static string expression_to_string(const Expression *expr); }; \ No newline at end of file diff --git a/src/observer/sql/optimizer/physical_plan_generator.cpp b/src/observer/sql/optimizer/physical_plan_generator.cpp deleted file mode 100644 index 33622e95d..000000000 --- a/src/observer/sql/optimizer/physical_plan_generator.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/* Copyright (c) 2021 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 "common/log/log.h" -#include "sql/expr/expression.h" -#include "session/session.h" -#include "sql/operator/physical/aggregate_vec_physical_operator.h" -#include "sql/operator/logical/calc_logical_operator.h" -#include "sql/operator/physical/calc_physical_operator.h" -#include "sql/operator/logical/delete_logical_operator.h" -#include "sql/operator/physical/delete_physical_operator.h" -#include "sql/operator/logical/explain_logical_operator.h" -#include "sql/operator/physical/explain_physical_operator.h" -#include "sql/operator/physical/expr_vec_physical_operator.h" -#include "sql/operator/physical/group_by_vec_physical_operator.h" -#include "sql/operator/physical/hash_join_physical_operator.h" -#include "sql/operator/physical/index_scan_physical_operator.h" -#include "sql/operator/logical/insert_logical_operator.h" -#include "sql/operator/physical/insert_physical_operator.h" -#include "sql/operator/logical/join_logical_operator.h" -#include "sql/operator/physical/nested_loop_join_physical_operator.h" -#include "sql/operator/logical/predicate_logical_operator.h" -#include "sql/operator/physical/predicate_physical_operator.h" -#include "sql/operator/logical/project_logical_operator.h" -#include "sql/operator/physical/project_physical_operator.h" -#include "sql/operator/physical/project_vec_physical_operator.h" -#include "sql/operator/logical/table_get_logical_operator.h" -#include "sql/operator/physical/table_scan_physical_operator.h" -#include "sql/operator/logical/group_by_logical_operator.h" -#include "sql/operator/physical/group_by_physical_operator.h" -#include "sql/operator/physical/hash_group_by_physical_operator.h" -#include "sql/operator/physical/scalar_group_by_physical_operator.h" -#include "sql/operator/physical/table_scan_vec_physical_operator.h" -#include "sql/optimizer/physical_plan_generator.h" - -using namespace std; - -RC PhysicalPlanGenerator::create(LogicalOperator &logical_operator, unique_ptr &oper, Session* session) -{ - RC rc = RC::SUCCESS; - - switch (logical_operator.get_op_type()) { - case OpType::LOGICALCALCULATE: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALGET: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALFILTER: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALPROJECTION: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALINSERT: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALDELETE: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALEXPLAIN: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALINNERJOIN: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - case OpType::LOGICALGROUPBY: { - return create_plan(static_cast(logical_operator), oper, session); - } break; - - default: { - ASSERT(false, "unknown logical operator type"); - return RC::INVALID_ARGUMENT; - } - } - return rc; -} - -RC PhysicalPlanGenerator::create_vec(LogicalOperator &logical_operator, unique_ptr &oper, Session* session) -{ - RC rc = RC::SUCCESS; - - switch (logical_operator.get_op_type()) { - case OpType::LOGICALGET: { - return create_vec_plan(static_cast(logical_operator), oper, session); - } break; - case OpType::LOGICALPROJECTION: { - return create_vec_plan(static_cast(logical_operator), oper, session); - } break; - case OpType::LOGICALGROUPBY: { - return create_vec_plan(static_cast(logical_operator), oper, session); - } break; - case OpType::LOGICALEXPLAIN: { - return create_vec_plan(static_cast(logical_operator), oper, session); - } break; - default: { - LOG_WARN("unknown logical operator type: %d", logical_operator.get_op_type()); - return RC::INVALID_ARGUMENT; - } - } - return rc; -} - -RC PhysicalPlanGenerator::create_plan(TableGetLogicalOperator &table_get_oper, unique_ptr &oper, Session* session) -{ - 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 && comparison_expr->comp() != NOT_EQUAL) { - continue; - } - - unique_ptr &left_expr = comparison_expr->left(); - 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 Value &value = value_expr->get_value(); - IndexScanPhysicalOperator *index_scan_oper = new IndexScanPhysicalOperator(table, - index, - table_get_oper.read_write_mode(), - &value, - true /*left_inclusive*/, - &value, - true /*right_inclusive*/); - - index_scan_oper->set_predicates(std::move(predicates)); - oper = unique_ptr(index_scan_oper); - LOG_TRACE("use index scan"); - } else { - auto table_scan_oper = new TableScanPhysicalOperator(table, table_get_oper.read_write_mode()); - table_scan_oper->set_predicates(std::move(predicates)); - oper = unique_ptr(table_scan_oper); - LOG_TRACE("use table scan"); - } - - return RC::SUCCESS; -} - -RC PhysicalPlanGenerator::create_plan(PredicateLogicalOperator &pred_oper, unique_ptr &oper, Session* session) -{ - 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(); - - unique_ptr child_phy_oper; - RC rc = create(child_oper, child_phy_oper, session); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to create child operator of predicate operator. rc=%s", strrc(rc)); - return rc; - } - - vector> &expressions = pred_oper.expressions(); - ASSERT(expressions.size() == 1, "predicate logical operator's children should be 1"); - - unique_ptr expression = std::move(expressions.front()); - oper = unique_ptr(new PredicatePhysicalOperator(std::move(expression))); - oper->add_child(std::move(child_phy_oper)); - return rc; -} - -RC PhysicalPlanGenerator::create_plan(ProjectLogicalOperator &project_oper, unique_ptr &oper, Session* session) -{ - vector> &child_opers = project_oper.children(); - - 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, session); - if (OB_FAIL(rc)) { - LOG_WARN("failed to create project logical operator's child physical operator. rc=%s", strrc(rc)); - return rc; - } - } - - auto project_operator = make_unique(std::move(project_oper.expressions())); - if (child_phy_oper) { - project_operator->add_child(std::move(child_phy_oper)); - } - - oper = std::move(project_operator); - - LOG_TRACE("create a project physical operator"); - return rc; -} - -RC PhysicalPlanGenerator::create_plan(InsertLogicalOperator &insert_oper, unique_ptr &oper, Session* session) -{ - Table *table = insert_oper.table(); - vector &values = insert_oper.values(); - InsertPhysicalOperator *insert_phy_oper = new InsertPhysicalOperator(table, std::move(values)); - oper.reset(insert_phy_oper); - return RC::SUCCESS; -} - -RC PhysicalPlanGenerator::create_plan(DeleteLogicalOperator &delete_oper, unique_ptr &oper, Session* session) -{ - vector> &child_opers = delete_oper.children(); - - 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, session); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to create physical operator. rc=%s", strrc(rc)); - return rc; - } - } - - oper = unique_ptr(new DeletePhysicalOperator(delete_oper.table())); - - if (child_physical_oper) { - oper->add_child(std::move(child_physical_oper)); - } - return rc; -} - -RC PhysicalPlanGenerator::create_plan(ExplainLogicalOperator &explain_oper, unique_ptr &oper, Session* session) -{ - vector> &child_opers = explain_oper.children(); - - RC rc = RC::SUCCESS; - - unique_ptr explain_physical_oper(new ExplainPhysicalOperator); - for (unique_ptr &child_oper : child_opers) { - unique_ptr child_physical_oper; - rc = create(*child_oper, child_physical_oper, session); - 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, unique_ptr &oper, Session* session) -{ - RC rc = RC::SUCCESS; - - 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; - } - if (session->hash_join_on() && can_use_hash_join(join_oper)) { - // your code here - } else { - unique_ptr join_physical_oper(new NestedLoopJoinPhysicalOperator()); - for (auto &child_oper : child_opers) { - unique_ptr child_physical_oper; - rc = create(*child_oper, child_physical_oper, session); - 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; -} - -bool PhysicalPlanGenerator::can_use_hash_join(JoinLogicalOperator &join_oper) -{ - // your code here - return false; -} - -RC PhysicalPlanGenerator::create_plan(CalcLogicalOperator &logical_oper, unique_ptr &oper, Session* session) -{ - RC rc = RC::SUCCESS; - - CalcPhysicalOperator *calc_oper = new CalcPhysicalOperator(std::move(logical_oper.expressions())); - oper.reset(calc_oper); - return rc; -} - -RC PhysicalPlanGenerator::create_plan(GroupByLogicalOperator &logical_oper, unique_ptr &oper, Session* session) -{ - RC rc = RC::SUCCESS; - - vector> &group_by_expressions = logical_oper.group_by_expressions(); - unique_ptr group_by_oper; - if (group_by_expressions.empty()) { - group_by_oper = make_unique(std::move(logical_oper.aggregate_expressions())); - } else { - group_by_oper = make_unique(std::move(logical_oper.group_by_expressions()), - std::move(logical_oper.aggregate_expressions())); - } - - ASSERT(logical_oper.children().size() == 1, "group by operator should have 1 child"); - - LogicalOperator &child_oper = *logical_oper.children().front(); - unique_ptr child_physical_oper; - rc = create(child_oper, child_physical_oper, session); - if (OB_FAIL(rc)) { - LOG_WARN("failed to create child physical operator of group by operator. rc=%s", strrc(rc)); - return rc; - } - - group_by_oper->add_child(std::move(child_physical_oper)); - - oper = std::move(group_by_oper); - return rc; -} - -RC PhysicalPlanGenerator::create_vec_plan(TableGetLogicalOperator &table_get_oper, unique_ptr &oper, Session* session) -{ - vector> &predicates = table_get_oper.predicates(); - Table *table = table_get_oper.table(); - TableScanVecPhysicalOperator *table_scan_oper = new TableScanVecPhysicalOperator(table, table_get_oper.read_write_mode()); - table_scan_oper->set_predicates(std::move(predicates)); - oper = unique_ptr(table_scan_oper); - LOG_TRACE("use vectorized table scan"); - - return RC::SUCCESS; -} - -RC PhysicalPlanGenerator::create_vec_plan(GroupByLogicalOperator &logical_oper, unique_ptr &oper, Session* session) -{ - RC rc = RC::SUCCESS; - unique_ptr physical_oper = nullptr; - if (logical_oper.group_by_expressions().empty()) { - physical_oper = make_unique(std::move(logical_oper.aggregate_expressions())); - } else { - physical_oper = make_unique( - std::move(logical_oper.group_by_expressions()), std::move(logical_oper.aggregate_expressions())); - - } - - ASSERT(logical_oper.children().size() == 1, "group by operator should have 1 child"); - - LogicalOperator &child_oper = *logical_oper.children().front(); - unique_ptr child_physical_oper; - rc = create_vec(child_oper, child_physical_oper, session); - if (OB_FAIL(rc)) { - LOG_WARN("failed to create child physical operator of group by(vec) operator. rc=%s", strrc(rc)); - return rc; - } - - physical_oper->add_child(std::move(child_physical_oper)); - - oper = std::move(physical_oper); - return rc; - - return RC::SUCCESS; -} - -RC PhysicalPlanGenerator::create_vec_plan(ProjectLogicalOperator &project_oper, unique_ptr &oper, Session* session) -{ - vector> &child_opers = project_oper.children(); - - unique_ptr child_phy_oper; - - RC rc = RC::SUCCESS; - if (!child_opers.empty()) { - LogicalOperator *child_oper = child_opers.front().get(); - rc = create_vec(*child_oper, child_phy_oper, session); - if (rc != RC::SUCCESS) { - LOG_WARN("failed to create project logical operator's child physical operator. rc=%s", strrc(rc)); - return rc; - } - } - - auto project_operator = make_unique(std::move(project_oper.expressions())); - - if (child_phy_oper != nullptr) { - vector expressions; - for (auto &expr : project_operator->expressions()) { - expressions.push_back(expr.get()); - } - auto expr_operator = make_unique(std::move(expressions)); - expr_operator->add_child(std::move(child_phy_oper)); - project_operator->add_child(std::move(expr_operator)); - } - - oper = std::move(project_operator); - - LOG_TRACE("create a project physical operator"); - return rc; -} - - -RC PhysicalPlanGenerator::create_vec_plan(ExplainLogicalOperator &explain_oper, unique_ptr &oper, Session* session) -{ - vector> &child_opers = explain_oper.children(); - - RC rc = RC::SUCCESS; - // reuse `ExplainPhysicalOperator` in explain vectorized physical plan - unique_ptr explain_physical_oper(new ExplainPhysicalOperator); - for (unique_ptr &child_oper : child_opers) { - unique_ptr child_physical_oper; - rc = create_vec(*child_oper, child_physical_oper, session); - 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; -} diff --git a/src/observer/sql/optimizer/physical_plan_generator.h b/src/observer/sql/optimizer/physical_plan_generator.h deleted file mode 100644 index 85f2e27d2..000000000 --- a/src/observer/sql/optimizer/physical_plan_generator.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2021 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. -// - -#pragma once - -#include "common/sys/rc.h" -#include "sql/operator/logical_operator.h" -#include "sql/operator/physical_operator.h" - -class Session; -class TableGetLogicalOperator; -class PredicateLogicalOperator; -class ProjectLogicalOperator; -class InsertLogicalOperator; -class DeleteLogicalOperator; -class ExplainLogicalOperator; -class JoinLogicalOperator; -class CalcLogicalOperator; -class GroupByLogicalOperator; - -/** - * @brief 物理计划生成器 - * @ingroup PhysicalOperator - * @details 根据逻辑计划生成物理计划。 - * 不会做任何优化,完全根据本意生成物理计划。 - */ -class PhysicalPlanGenerator -{ -public: - PhysicalPlanGenerator() = default; - virtual ~PhysicalPlanGenerator() = default; - - RC create(LogicalOperator &logical_operator, unique_ptr &oper, Session *session); - RC create_vec(LogicalOperator &logical_operator, unique_ptr &oper, Session *session); - -private: - RC create_plan(TableGetLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(PredicateLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(ProjectLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(InsertLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(DeleteLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(ExplainLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(JoinLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(CalcLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_plan(GroupByLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_vec_plan(ProjectLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_vec_plan(TableGetLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_vec_plan(GroupByLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - RC create_vec_plan(ExplainLogicalOperator &logical_oper, unique_ptr &oper, Session *session); - - // TODO: remove this and add CBO rules - bool can_use_hash_join(JoinLogicalOperator &logical_oper); -}; diff --git a/src/observer/sql/stmt/filter_stmt.cpp b/src/observer/sql/stmt/filter_stmt.cpp index aa078bcbb..65186f9d5 100644 --- a/src/observer/sql/stmt/filter_stmt.cpp +++ b/src/observer/sql/stmt/filter_stmt.cpp @@ -32,6 +32,7 @@ RC FilterStmt::create(Db *db, Table *default_table, unordered_map Date: Fri, 28 Nov 2025 11:40:24 +0800 Subject: [PATCH 10/12] feat(optimizer): Add ExpressionSimplifyRule and PredicateRewriteRule --- src/common/sys/rc.h | 4 +- .../operator/logical/calc_logical_operator.h | 9 ++ .../logical/delete_logical_operator.h | 5 + .../operator/logical/empty_logical_operator.h | 31 ++++ .../logical/explain_logical_operator.h | 5 + .../logical/group_by_logical_operator.cpp | 14 ++ .../logical/group_by_logical_operator.h | 2 + .../logical/insert_logical_operator.h | 5 + .../operator/logical/join_logical_operator.h | 10 ++ .../logical/predicate_logical_operator.cpp | 8 + .../logical/predicate_logical_operator.h | 2 + .../logical/project_logical_operator.cpp | 9 ++ .../logical/project_logical_operator.h | 2 + .../logical/table_get_logical_operator.cpp | 14 ++ .../logical/table_get_logical_operator.h | 2 + .../sql/operator/logical_operator.cpp | 23 +++ src/observer/sql/operator/logical_operator.h | 12 ++ src/observer/sql/operator/operator_node.h | 2 + .../physical/empty_physical_operator.h | 45 ++++++ .../sql/operator/physical_operator.cpp | 1 + src/observer/sql/optimizer/cascade/group.h | 9 ++ .../sql/optimizer/cascade/group_expr.cpp | 3 +- .../cascade/implementation_rules.cpp | 18 +++ .../optimizer/cascade/implementation_rules.h | 12 ++ src/observer/sql/optimizer/cascade/memo.h | 13 +- src/observer/sql/optimizer/cascade/rules.cpp | 1 + src/observer/sql/optimizer/cascade/rules.h | 25 ++- .../optimizer/cascade/tasks/o_expr_task.cpp | 5 +- .../cascade/transformation_rules.cpp | 36 +---- .../sql/optimizer/logical_plan_generator.cpp | 145 ++++++++++++------ .../sql/optimizer/logical_plan_generator.h | 1 + 31 files changed, 384 insertions(+), 89 deletions(-) create mode 100644 src/observer/sql/operator/logical/empty_logical_operator.h create mode 100644 src/observer/sql/operator/physical/empty_physical_operator.h diff --git a/src/common/sys/rc.h b/src/common/sys/rc.h index 53a60debb..97369a033 100644 --- a/src/common/sys/rc.h +++ b/src/common/sys/rc.h @@ -87,9 +87,7 @@ See the Mulan PSL v2 for more details. */ DEFINE_RC(UNSUPPORTED) \ DEFINE_RC(OPTIMIZER_GROUP_EXPR_CREATE_FAILED) \ DEFINE_RC(OPTIMIZER_MEMO_INSERT_FAILED) \ - DEFINE_RC(OPTIMIZER_EXPRESSION_COPY_FAILED) \ - DEFINE_RC(OPTIMIZER_INVALID_GROUP_ID) \ - DEFINE_RC(OPTIMIZER_CASCADE_FAIL) + DEFINE_RC(OPTIMIZER_INVALID_GROUP_ID) enum class RC { diff --git a/src/observer/sql/operator/logical/calc_logical_operator.h b/src/observer/sql/operator/logical/calc_logical_operator.h index ab01dd913..d361534cb 100644 --- a/src/observer/sql/operator/logical/calc_logical_operator.h +++ b/src/observer/sql/operator/logical/calc_logical_operator.h @@ -27,4 +27,13 @@ class CalcLogicalOperator : public LogicalOperator virtual ~CalcLogicalOperator() = default; OpType get_op_type() const override { return OpType::LOGICALCALCULATE; } + + unique_ptr clone() const override + { + vector> exprs; + for (auto &expr : expressions_) { + exprs.push_back(expr->copy()); + } + return make_unique(std::move(exprs)); + } }; diff --git a/src/observer/sql/operator/logical/delete_logical_operator.h b/src/observer/sql/operator/logical/delete_logical_operator.h index 575faee47..38125c098 100644 --- a/src/observer/sql/operator/logical/delete_logical_operator.h +++ b/src/observer/sql/operator/logical/delete_logical_operator.h @@ -45,6 +45,11 @@ class DeleteLogicalOperator : public LogicalOperator Table *table() const { return table_; } + unique_ptr clone() const override + { + return make_unique(table_); + } + private: Table *table_ = nullptr; }; diff --git a/src/observer/sql/operator/logical/empty_logical_operator.h b/src/observer/sql/operator/logical/empty_logical_operator.h new file mode 100644 index 000000000..48d1e6a93 --- /dev/null +++ b/src/observer/sql/operator/logical/empty_logical_operator.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2021 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. */ + +#pragma once + +#include "sql/operator/logical_operator.h" + +/** + * @brief Empty逻辑算子 + * @ingroup LogicalOperator + */ +class EmptyLogicalOperator : public LogicalOperator +{ +public: + EmptyLogicalOperator() = default; + virtual ~EmptyLogicalOperator() = default; + + OpType get_op_type() const override { return OpType::LOGICALEMPTY; } + + unique_ptr clone() const override + { + return make_unique(); + } +}; diff --git a/src/observer/sql/operator/logical/explain_logical_operator.h b/src/observer/sql/operator/logical/explain_logical_operator.h index 3c0b9ce18..d7d28e84d 100644 --- a/src/observer/sql/operator/logical/explain_logical_operator.h +++ b/src/observer/sql/operator/logical/explain_logical_operator.h @@ -27,4 +27,9 @@ class ExplainLogicalOperator : public LogicalOperator virtual ~ExplainLogicalOperator() = default; OpType get_op_type() const override { return OpType::LOGICALEXPLAIN; } + + unique_ptr clone() const override + { + return make_unique(); + } }; diff --git a/src/observer/sql/operator/logical/group_by_logical_operator.cpp b/src/observer/sql/operator/logical/group_by_logical_operator.cpp index 725853b69..db575659d 100644 --- a/src/observer/sql/operator/logical/group_by_logical_operator.cpp +++ b/src/observer/sql/operator/logical/group_by_logical_operator.cpp @@ -24,3 +24,17 @@ GroupByLogicalOperator::GroupByLogicalOperator(vector> && group_by_expressions_ = std::move(group_by_exprs); aggregate_expressions_ = std::move(expressions); } + +unique_ptr GroupByLogicalOperator::clone() const +{ + vector> group_by_exprs; + for (auto &expr : group_by_expressions_) { + group_by_exprs.push_back(expr->copy()); + } + // aggregate_expressions_ 是 Expression* 指针,不能直接复制 + // 这里需要从 expressions_ 中获取,但 GroupBy 的 aggregate_expressions_ 可能指向不同的表达式 + // 为了简化,我们只复制 group_by 表达式 + vector agg_exprs; + // TODO: 需要正确复制 aggregate_expressions_ + return make_unique(std::move(group_by_exprs), std::move(agg_exprs)); +} diff --git a/src/observer/sql/operator/logical/group_by_logical_operator.h b/src/observer/sql/operator/logical/group_by_logical_operator.h index 610dc7a34..61a6f1fd3 100644 --- a/src/observer/sql/operator/logical/group_by_logical_operator.h +++ b/src/observer/sql/operator/logical/group_by_logical_operator.h @@ -65,6 +65,8 @@ class GroupByLogicalOperator : public LogicalOperator auto &group_by_expressions() { return group_by_expressions_; } auto &aggregate_expressions() { return aggregate_expressions_; } + unique_ptr clone() const override; + private: vector> &group_by_expressions_ = expressions_; vector aggregate_expressions_; ///< 输出的表达式,可能包含聚合函数 diff --git a/src/observer/sql/operator/logical/insert_logical_operator.h b/src/observer/sql/operator/logical/insert_logical_operator.h index 886228f3d..9efb7ed05 100644 --- a/src/observer/sql/operator/logical/insert_logical_operator.h +++ b/src/observer/sql/operator/logical/insert_logical_operator.h @@ -58,6 +58,11 @@ class InsertLogicalOperator : public LogicalOperator const vector &values() const { return values_; } vector &values() { return values_; } + unique_ptr clone() const override + { + return make_unique(table_, values_); + } + private: Table *table_ = nullptr; vector values_; diff --git a/src/observer/sql/operator/logical/join_logical_operator.h b/src/observer/sql/operator/logical/join_logical_operator.h index e3946cad0..8c3c37012 100644 --- a/src/observer/sql/operator/logical/join_logical_operator.h +++ b/src/observer/sql/operator/logical/join_logical_operator.h @@ -68,6 +68,16 @@ class JoinLogicalOperator : public LogicalOperator auto add_join_predicate(unique_ptr &&predicate) { join_predicates_.push_back(std::move(predicate)); } + unique_ptr clone() const override + { + auto new_join = make_unique(); + // 复制 join predicates + for (auto &pred : join_predicates_) { + new_join->add_join_predicate(pred->copy()); + } + return new_join; + } + unique_ptr find_log_prop(const vector &log_props) override { if (log_props.size() != 2) { diff --git a/src/observer/sql/operator/logical/predicate_logical_operator.cpp b/src/observer/sql/operator/logical/predicate_logical_operator.cpp index bceaa708e..f6e2ca546 100644 --- a/src/observer/sql/operator/logical/predicate_logical_operator.cpp +++ b/src/observer/sql/operator/logical/predicate_logical_operator.cpp @@ -39,3 +39,11 @@ unique_ptr PredicateLogicalOperator::find_log_prop(const vector return make_unique(output_card); } + +unique_ptr PredicateLogicalOperator::clone() const +{ + if (expressions_.empty()) { + return nullptr; + } + return make_unique(expressions_[0]->copy()); +} diff --git a/src/observer/sql/operator/logical/predicate_logical_operator.h b/src/observer/sql/operator/logical/predicate_logical_operator.h index 953ad247f..fbf61ee02 100644 --- a/src/observer/sql/operator/logical/predicate_logical_operator.h +++ b/src/observer/sql/operator/logical/predicate_logical_operator.h @@ -31,4 +31,6 @@ class PredicateLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALFILTER; } unique_ptr find_log_prop(const vector &log_props) override; + + unique_ptr clone() const override; }; diff --git a/src/observer/sql/operator/logical/project_logical_operator.cpp b/src/observer/sql/operator/logical/project_logical_operator.cpp index 91803dcc9..b48828fb3 100644 --- a/src/observer/sql/operator/logical/project_logical_operator.cpp +++ b/src/observer/sql/operator/logical/project_logical_operator.cpp @@ -33,3 +33,12 @@ unique_ptr ProjectLogicalOperator::find_log_prop(const vector(card); } + +unique_ptr ProjectLogicalOperator::clone() const +{ + vector> exprs; + for (auto &expr : expressions_) { + exprs.push_back(expr->copy()); + } + return make_unique(std::move(exprs)); +} diff --git a/src/observer/sql/operator/logical/project_logical_operator.h b/src/observer/sql/operator/logical/project_logical_operator.h index 45850aa41..c5a713f14 100644 --- a/src/observer/sql/operator/logical/project_logical_operator.h +++ b/src/observer/sql/operator/logical/project_logical_operator.h @@ -31,4 +31,6 @@ class ProjectLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALPROJECTION; } unique_ptr find_log_prop(const vector &log_props) override; + + unique_ptr clone() const override; }; diff --git a/src/observer/sql/operator/logical/table_get_logical_operator.cpp b/src/observer/sql/operator/logical/table_get_logical_operator.cpp index 803e4d4aa..aba02ab0a 100644 --- a/src/observer/sql/operator/logical/table_get_logical_operator.cpp +++ b/src/observer/sql/operator/logical/table_get_logical_operator.cpp @@ -43,4 +43,18 @@ unique_ptr TableGetLogicalOperator::find_log_prop(const vector< } return make_unique(card); +} + +unique_ptr TableGetLogicalOperator::clone() const +{ + auto new_op = make_unique(table_, mode_); + // 复制 predicates,过滤掉恒真表达式 + vector> predicates; + for (auto &pred : predicates_) { + // 检查是否为恒真表达式 + Value value; + predicates.push_back(pred->copy()); + } + new_op->set_predicates(std::move(predicates)); + return new_op; } \ No newline at end of file diff --git a/src/observer/sql/operator/logical/table_get_logical_operator.h b/src/observer/sql/operator/logical/table_get_logical_operator.h index 6ec549648..0580bf935 100644 --- a/src/observer/sql/operator/logical/table_get_logical_operator.h +++ b/src/observer/sql/operator/logical/table_get_logical_operator.h @@ -68,6 +68,8 @@ class TableGetLogicalOperator : public LogicalOperator void set_predicates(vector> &&exprs); auto predicates() -> vector> & { return predicates_; } + unique_ptr clone() const override; + private: Table *table_ = nullptr; ReadWriteMode mode_ = ReadWriteMode::READ_WRITE; diff --git a/src/observer/sql/operator/logical_operator.cpp b/src/observer/sql/operator/logical_operator.cpp index 5fb4d00b4..8795dcfcb 100644 --- a/src/observer/sql/operator/logical_operator.cpp +++ b/src/observer/sql/operator/logical_operator.cpp @@ -19,6 +19,7 @@ LogicalOperator::~LogicalOperator() {} void LogicalOperator::add_expressions(unique_ptr expr) { expressions_.emplace_back(std::move(expr)); } + bool LogicalOperator::can_generate_vectorized_operator(OpType type) { bool bool_ret = false; @@ -36,3 +37,25 @@ bool LogicalOperator::can_generate_vectorized_operator(OpType type) } return bool_ret; } + +string logical_operator_type_name(OpType type) +{ + switch (type) { + case OpType::LOGICALGET: return "LOGICAL_GET"; + case OpType::LOGICALCALCULATE: return "LOGICAL_CALCULATE"; + case OpType::LOGICALGROUPBY: return "LOGICAL_GROUP_BY"; + case OpType::LOGICALPROJECTION: return "LOGICAL_PROJECTION"; + case OpType::LOGICALFILTER: return "LOGICAL_FILTER"; + case OpType::LOGICALINNERJOIN: return "LOGICAL_INNER_JOIN"; + case OpType::LOGICALINSERT: return "LOGICAL_INSERT"; + case OpType::LOGICALDELETE: return "LOGICAL_DELETE"; + case OpType::LOGICALUPDATE: return "LOGICAL_UPDATE"; + case OpType::LOGICALLIMIT: return "LOGICAL_LIMIT"; + case OpType::LOGICALANALYZE: return "LOGICAL_ANALYZE"; + case OpType::LOGICALEXPLAIN: return "LOGICAL_EXPLAIN"; + case OpType::LOGICALEMPTY: return "LOGICAL_EMPTY"; + default: return "UNKNOWN_LOGICAL"; + } +} + +string LogicalOperator::name() const { return logical_operator_type_name(get_op_type()); } diff --git a/src/observer/sql/operator/logical_operator.h b/src/observer/sql/operator/logical_operator.h index 6f548dc2d..37d23b6d3 100644 --- a/src/observer/sql/operator/logical_operator.h +++ b/src/observer/sql/operator/logical_operator.h @@ -43,6 +43,18 @@ class LogicalOperator : public OperatorNode const vector> &expressions() const { return expressions_; } static bool can_generate_vectorized_operator(OpType type); + /** + * 这两个函数是为了打印时使用的,比如在explain中 + */ + virtual string name() const; + virtual string param() const { return ""; } + + /** + * @brief 克隆逻辑算子 + * @return 返回算子的一个深拷贝 + */ + virtual unique_ptr clone() const = 0; + virtual uint64_t hash() const override { uint64_t hash = std::hash()(static_cast(get_op_type())); diff --git a/src/observer/sql/operator/operator_node.h b/src/observer/sql/operator/operator_node.h index 24fe7748e..09f8b6ab9 100644 --- a/src/observer/sql/operator/operator_node.h +++ b/src/observer/sql/operator/operator_node.h @@ -38,6 +38,7 @@ enum class OpType LOGICALLIMIT, LOGICALANALYZE, LOGICALEXPLAIN, + LOGICALEMPTY, // Separation of logical and physical operators LOGICALPHYSICALDELIMITER, @@ -59,6 +60,7 @@ enum class OpType HASHGROUPBY, ANALYZE, FILTER, + EMPTY, SCALARGROUPBY, STRINGLIST, AGGREGATE_VEC, diff --git a/src/observer/sql/operator/physical/empty_physical_operator.h b/src/observer/sql/operator/physical/empty_physical_operator.h new file mode 100644 index 000000000..95602a2a7 --- /dev/null +++ b/src/observer/sql/operator/physical/empty_physical_operator.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2021 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. */ + +#pragma once + +#include "sql/operator/physical_operator.h" + +/** + * @brief Empty物理算子 + * @ingroup PhysicalOperator + * @details 用于表示一个空的物理算子,不产生任何数据 + */ +class EmptyPhysicalOperator : public PhysicalOperator +{ +public: + EmptyPhysicalOperator() = default; + virtual ~EmptyPhysicalOperator() = default; + + OpType get_op_type() const override { return OpType::EMPTY; } + + double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override + { + return 0.0; + } + + RC open(Trx *trx) override { return RC::SUCCESS; } + + RC next() override { return RC::RECORD_EOF; } + + RC next(Chunk &chunk) override { return RC::RECORD_EOF; } + + RC close() override { return RC::SUCCESS; } + + Tuple *current_tuple() override { return nullptr; } + + RC tuple_schema(TupleSchema &schema) const override { return RC::SUCCESS; } +}; + diff --git a/src/observer/sql/operator/physical_operator.cpp b/src/observer/sql/operator/physical_operator.cpp index 1aad0044c..d40dab611 100644 --- a/src/observer/sql/operator/physical_operator.cpp +++ b/src/observer/sql/operator/physical_operator.cpp @@ -34,6 +34,7 @@ string physical_operator_type_name(OpType type) case OpType::PROJECTION_VEC: return "PROJECT_VEC"; case OpType::SEQSCAN_VEC: return "TABLE_SCAN_VEC"; case OpType::EXPR_VEC: return "EXPR_VEC"; + case OpType::EMPTY: return "EMPTY"; default: return "UNKNOWN"; } } diff --git a/src/observer/sql/optimizer/cascade/group.h b/src/observer/sql/optimizer/cascade/group.h index bcecf58b1..2140f9fc6 100644 --- a/src/observer/sql/optimizer/cascade/group.h +++ b/src/observer/sql/optimizer/cascade/group.h @@ -95,6 +95,13 @@ class Group LogicalProperty *get_logical_prop() { return logical_prop_.get(); } + bool is_alias() const { return alias_target_ != -1; } + int get_alias_target() const { return alias_target_; } + + void set_alias(int target) { + alias_target_ = target; + } + ///< dump the group info, for debug void dump() const; @@ -110,4 +117,6 @@ class Group std::vector physical_expressions_; unique_ptr logical_prop_ = nullptr; + + int alias_target_ = -1; }; \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/group_expr.cpp b/src/observer/sql/optimizer/cascade/group_expr.cpp index be0e4aeba..c9d6fd0c5 100644 --- a/src/observer/sql/optimizer/cascade/group_expr.cpp +++ b/src/observer/sql/optimizer/cascade/group_expr.cpp @@ -14,8 +14,9 @@ uint64_t GroupExpr::hash() const { auto hash = contents_->hash(); for (const auto &child : child_groups_) { - hash ^= std::hash()(child) + 0x9e3779b9 + (hash << 6) + (hash >> 2);; + hash ^= std::hash()(child) + 0x9e3779b9 + (hash << 6) + (hash >> 2); } + hash ^= std::hash()(group_id_) + 0x9e3779b9 + (hash << 6) + (hash >> 2);; return hash; } diff --git a/src/observer/sql/optimizer/cascade/implementation_rules.cpp b/src/observer/sql/optimizer/cascade/implementation_rules.cpp index ae9de5f90..3b2ac5d7d 100644 --- a/src/observer/sql/optimizer/cascade/implementation_rules.cpp +++ b/src/observer/sql/optimizer/cascade/implementation_rules.cpp @@ -32,6 +32,8 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/logical/join_logical_operator.h" #include "sql/operator/physical/nested_loop_join_physical_operator.h" #include "sql/operator/physical/hash_join_physical_operator.h" +#include "sql/operator/physical/empty_physical_operator.h" +#include "sql/operator/logical/empty_logical_operator.h" #include "sql/expr/expression.h" // ------------------------------------------------------------------------------------------------- @@ -371,4 +373,20 @@ void LogicalGroupByToHashGroupBy::transform( auto groupby_phys_oper = make_unique(std::move(group_by_exprs), std::move(aggregate_exprs)); transformed->emplace_back(std::move(groupby_phys_oper), input->get_child_group_ids()); } +} + +// ------------------------------------------------------------------------------------------------- +// Physical Empty +// ------------------------------------------------------------------------------------------------- +LogicalEmptyToEmpty::LogicalEmptyToEmpty() +{ + type_ = RuleType::EMPTY_TO_PHYSICAL; + match_pattern_ = unique_ptr(new Pattern(OpType::LOGICALEMPTY)); +} + +void LogicalEmptyToEmpty::transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const +{ + unique_ptr empty_phys_oper(new EmptyPhysicalOperator()); + transformed->emplace_back(std::move(empty_phys_oper)); } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/implementation_rules.h b/src/observer/sql/optimizer/cascade/implementation_rules.h index ed07c6908..8f34aa586 100644 --- a/src/observer/sql/optimizer/cascade/implementation_rules.h +++ b/src/observer/sql/optimizer/cascade/implementation_rules.h @@ -153,6 +153,18 @@ class LogicalGroupByToHashGroupBy : public Rule public: LogicalGroupByToHashGroupBy(); + void transform( + GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; +}; + +/** + * Rule transforms Logical Empty -> Physical Empty + */ +class LogicalEmptyToEmpty : public Rule +{ +public: + LogicalEmptyToEmpty(); + void transform( GroupExpr *input, std::vector *transformed, OptimizerContext *context) const override; }; \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/memo.h b/src/observer/sql/optimizer/cascade/memo.h index 6ee090b34..ec6f9ea26 100644 --- a/src/observer/sql/optimizer/cascade/memo.h +++ b/src/observer/sql/optimizer/cascade/memo.h @@ -38,9 +38,16 @@ class Memo Group *get_group_by_id(int id) const { - auto idx = id; - ASSERT(idx >= 0 && static_cast(idx) < groups_.size(), "group_id out of bounds"); - return groups_[idx].get(); + Group* g = groups_[id].get(); + ASSERT(id >= 0 && static_cast(id) < groups_.size(), "group_id out of bounds"); + while (g && g->is_alias()) { + g = groups_[g->get_alias_target()].get(); + } + return g; + } + + void make_alias(int src, int target) { + groups_[src]->set_alias(target); } void dump() const; diff --git a/src/observer/sql/optimizer/cascade/rules.cpp b/src/observer/sql/optimizer/cascade/rules.cpp index 58f78665e..526667b27 100644 --- a/src/observer/sql/optimizer/cascade/rules.cpp +++ b/src/observer/sql/optimizer/cascade/rules.cpp @@ -34,4 +34,5 @@ RuleSet::RuleSet() // add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalInnerJoinToHashJoin()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalGroupByToAggregation()); add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalGroupByToHashGroupBy()); + add_rule(RuleSetName::PHYSICAL_IMPLEMENTATION, new LogicalEmptyToEmpty()); } \ No newline at end of file diff --git a/src/observer/sql/optimizer/cascade/rules.h b/src/observer/sql/optimizer/cascade/rules.h index da75084cb..a06c3b451 100644 --- a/src/observer/sql/optimizer/cascade/rules.h +++ b/src/observer/sql/optimizer/cascade/rules.h @@ -44,6 +44,7 @@ enum class RuleType : uint32_t PREDICATE_TO_PHYSICAL, GROUP_BY_TO_PHYSICAL_AGGREGATION, GROUP_BY_TO_PHYSICL_HASH_GROUP_BY, + EMPTY_TO_PHYSICAL, NUM_RULES }; @@ -164,9 +165,29 @@ class RuleWithPromise */ RulePromise get_promise() { return promise_; } - bool operator<(const RuleWithPromise &r) const { return promise_ < r.promise_; } + bool operator<(const RuleWithPromise &r) const + { + // 首先比较 promise,promise 高的先执行 + if (promise_ != r.promise_) { + return promise_ < r.promise_; + } + // promise 相同时,比较 rule type + // 由于使用栈(LIFO),后入栈的先执行,所以 type 值大的应该排在后面(后入栈) + // 执行顺序应该是:EXPRESSION_SIMPLIFY (2) -> PREDICATE_REWRITE (1) -> PREDICATE_PUSHDOWN (0) + // 排序后应该是:PREDICATE_PUSHDOWN (0) 在前面,EXPRESSION_SIMPLIFY (2) 在后面 + // 所以应该按 type 升序排序(小的在前,大的在后) + return static_cast(rule_->get_type()) < static_cast(r.rule_->get_type()); + } - bool operator>(const RuleWithPromise &r) const { return promise_ > r.promise_; } + bool operator>(const RuleWithPromise &r) const + { + // 首先比较 promise,promise 高的先执行 + if (promise_ != r.promise_) { + return promise_ > r.promise_; + } + // promise 相同时,比较 rule type,按 type 降序排序 + return static_cast(rule_->get_type()) > static_cast(r.rule_->get_type()); + } private: /** diff --git a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp index e5711eebd..74ed803af 100644 --- a/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp +++ b/src/observer/sql/optimizer/cascade/tasks/o_expr_task.cpp @@ -13,6 +13,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/tasks/e_group_task.h" #include "sql/optimizer/cascade/group_expr.h" #include "sql/optimizer/cascade/memo.h" +#include "sql/operator/logical_operator.h" #include "common/log/log.h" #include @@ -63,7 +64,9 @@ RC OptimizeExpression::perform() } if(valid_rules.size() == 0 && group_expr_->get_op()->is_logical()) { - LOG_ERROR("Missing physical implementation rule for logical operator type: %d", static_cast(group_expr_->get_op()->get_op_type())); + auto logical_op = static_cast(group_expr_->get_op()); + LOG_ERROR("Missing physical implementation rule for logical operator: %s (type: %d)", + logical_op->name().c_str(), static_cast(group_expr_->get_op()->get_op_type())); return RC::OPTIMIZER_GROUP_EXPR_CREATE_FAILED; } diff --git a/src/observer/sql/optimizer/cascade/transformation_rules.cpp b/src/observer/sql/optimizer/cascade/transformation_rules.cpp index f725bfea3..cd1bf399a 100644 --- a/src/observer/sql/optimizer/cascade/transformation_rules.cpp +++ b/src/observer/sql/optimizer/cascade/transformation_rules.cpp @@ -14,6 +14,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/optimizer/cascade/memo.h" #include "sql/operator/logical/predicate_logical_operator.h" #include "sql/operator/logical/table_get_logical_operator.h" +#include "sql/operator/logical/empty_logical_operator.h" #include "sql/expr/expression.h" // ------------------------------------------------------------------------------------------------- @@ -61,11 +62,10 @@ void PredicatePushdownRule::transform( vector> &child_exprs = conjunction_expr->children(); for (auto &child_expr : child_exprs) { - if (child_expr->type() == ExprType::COMPARISON) { - pushdown_exprs.push_back(child_expr->copy()); - } + pushdown_exprs.push_back(child_expr->copy()); } } else if (predicate_expr->type() == ExprType::COMPARISON) { + // 检查是否为恒真表达式 pushdown_exprs.push_back(predicate_expr->copy()); } @@ -75,17 +75,13 @@ void PredicatePushdownRule::transform( // 创建新的 TableGetLogicalOperator,包含下推的谓词 // 合并原有的 predicates 和下推的 predicates - vector> existing_predicates; for (auto &expr : table_get_oper->predicates()) { - existing_predicates.push_back(expr->copy()); - } - for (auto &expr : pushdown_exprs) { - existing_predicates.push_back(std::move(expr)); + pushdown_exprs.push_back(expr->copy()); } auto new_table_get = make_unique( table_get_oper->table(), table_get_oper->read_write_mode()); - new_table_get->set_predicates(std::move(existing_predicates)); + new_table_get->set_predicates(std::move(pushdown_exprs)); // 返回新的 TableGet,直接替换 Filter(TableGet 是叶子节点,没有子节点) transformed->emplace_back(std::move(new_table_get)); @@ -125,26 +121,10 @@ void PredicateRewriteRule::transform( if (bool_value == true) { // 恒真:删除 Filter,直接返回子节点 Memo &memo = context->get_memo(); - Group *child_group = memo.get_group_by_id(input->get_child_group_ids()[0]); - GroupExpr *child_gexpr = child_group->get_logical_expression(); - if (child_gexpr) { - // 返回子节点的逻辑表达式 - // 注意:这里我们需要创建一个新的 GroupExpr,但实际上应该直接使用子节点 - // 由于 Cascade 架构,我们返回一个空的 transformed,让优化器继续处理子节点 - // 或者我们可以返回子节点的 operator - auto child_op = child_gexpr->get_op(); - if (child_op->is_logical()) { - // 创建新的逻辑算子(复制) - // 这里简化处理:如果恒真,我们返回子节点,但需要保持 GroupExpr 结构 - // 实际上,这个规则应该通过 Memo 来处理,而不是直接返回 - // 暂时不生成新的表达式,让优化器继续处理 - return; - } - } + memo.make_alias(input->get_group_id(), input->get_child_group_ids()[0]); } else { - // 恒假:删除整个子树 - // 在 Cascade 中,这应该返回一个空的 GroupExpr 或者特殊的算子 - // 暂时不处理 + // 在 Cascade 中,这应该返回一个空算子 + transformed->emplace_back(std::unique_ptr(new EmptyLogicalOperator)); return; } } diff --git a/src/observer/sql/optimizer/logical_plan_generator.cpp b/src/observer/sql/optimizer/logical_plan_generator.cpp index fc667c83c..25fd22a7f 100644 --- a/src/observer/sql/optimizer/logical_plan_generator.cpp +++ b/src/observer/sql/optimizer/logical_plan_generator.cpp @@ -108,7 +108,7 @@ RC LogicalPlanGenerator::create_plan(SelectStmt *select_stmt, GroupExpr *&root_g } } - // 2. 创建filter/predicate 0x606000001820 + // 2. 创建filter/predicate if (select_stmt->filter_stmt()) { // 先创建predicate的expressions RC rc = create_plan(select_stmt->filter_stmt(), last_gexpr, context, last_gexpr->get_group_id()); @@ -118,52 +118,12 @@ RC LogicalPlanGenerator::create_plan(SelectStmt *select_stmt, GroupExpr *&root_g } } - // // 3. 创建group by(检查是否有group by或聚合函数) - // bool has_aggregation = false; - // function&)> check_aggregation = [&](unique_ptr &expr) -> RC { - // if (expr->type() == ExprType::AGGREGATION) { - // has_aggregation = true; - // } - // return ExpressionIterator::iterate_child_expr(*expr, check_aggregation); - // }; - // for (auto &expr : select_stmt->query_expressions()) { - // check_aggregation(expr); - // } - - // if (select_stmt->group_by().size() > 0 || has_aggregation) { - // // 创建group by expressions和aggregate expressions - // vector> group_by_exprs; - // for (auto &expr : select_stmt->group_by()) { - // group_by_exprs.push_back(expr->copy()); - // } - - // vector aggregate_expressions; - // function&)> collector = [&](unique_ptr &expr) -> RC { - // RC rc = RC::SUCCESS; - // if (expr->type() == ExprType::AGGREGATION) { - // aggregate_expressions.push_back(expr.get()); - // } - // rc = ExpressionIterator::iterate_child_expr(*expr, collector); - // return rc; - // }; - - // for (auto &expr : select_stmt->query_expressions()) { - // collector(expr); - // } - - // if (last_gexpr) { - // unique_ptr group_by_op(new GroupByLogicalOperator(std::move(group_by_exprs), std::move(aggregate_expressions))); - // std::vector child_groups = {last_gexpr->get_group_id()}; - // CandidateExpression candidate(std::move(group_by_op), std::move(child_groups)); - // bool inserted = context->record_node_into_group(candidate, &group_by_gexpr); - // if (!inserted) { - // Memo &memo = context->get_memo(); - // auto group = memo.get_group_by_id(group_by_gexpr->get_group_id()); - // group_by_gexpr = group->get_logical_expression(); - // } - // last_gexpr = group_by_gexpr; - // } - // } + // 3. 创建group by(检查是否有group by或聚合函数) + RC rc = create_group_by_plan(select_stmt, last_gexpr, context, last_gexpr->get_group_id()); + if (OB_FAIL(rc)) { + LOG_WARN("failed to create group by logical plan. rc=%s", strrc(rc)); + return rc; + } // 4. 创建projection unique_ptr project_op(new ProjectLogicalOperator(std::move(select_stmt->query_expressions()))); @@ -232,11 +192,15 @@ RC LogicalPlanGenerator::create_plan(FilterStmt *filter_stmt, GroupExpr *&root_g cmp_exprs.emplace_back(cmp_expr); } - unique_ptr conjunction_expr(new ConjunctionExpr(ConjunctionExpr::Type::AND, cmp_exprs)); - unique_ptr predicate_op(new PredicateLogicalOperator(std::move(conjunction_expr))); - CandidateExpression candidate(std::move(predicate_op), {gid}); + unique_ptr predicate_oper; + if (cmp_exprs.size() == 1) { + predicate_oper = unique_ptr(new PredicateLogicalOperator(std::move(cmp_exprs[0]))); + } else if(!cmp_exprs.empty()) { + unique_ptr conjunction_expr(new ConjunctionExpr(ConjunctionExpr::Type::AND, cmp_exprs)); + predicate_oper = unique_ptr(new PredicateLogicalOperator(std::move(conjunction_expr))); + } + CandidateExpression candidate(std::move(predicate_oper), {gid}); context->record_node_into_group(candidate, &root_gexpr); - return rc; } @@ -315,3 +279,82 @@ RC LogicalPlanGenerator::create_plan(ExplainStmt *explain_stmt, GroupExpr *&root return rc; } + +RC LogicalPlanGenerator::create_group_by_plan(SelectStmt *select_stmt, GroupExpr *&root_gexpr, OptimizerContext *context, int gid) +{ + vector> &group_by_expressions = select_stmt->group_by(); + vector aggregate_expressions; + vector> &query_expressions = select_stmt->query_expressions(); + function&)> collector = [&](unique_ptr &expr) -> RC { + RC rc = RC::SUCCESS; + if (expr->type() == ExprType::AGGREGATION) { + expr->set_pos(aggregate_expressions.size() + group_by_expressions.size()); + aggregate_expressions.push_back(expr.get()); + } + rc = ExpressionIterator::iterate_child_expr(*expr, collector); + return rc; + }; + + function&)> bind_group_by_expr = [&](unique_ptr &expr) -> RC { + RC rc = RC::SUCCESS; + for (size_t i = 0; i < group_by_expressions.size(); i++) { + auto &group_by = group_by_expressions[i]; + if (expr->type() == ExprType::AGGREGATION) { + break; + } else if (expr->equal(*group_by)) { + expr->set_pos(i); + continue; + } else { + rc = ExpressionIterator::iterate_child_expr(*expr, bind_group_by_expr); + } + } + return rc; + }; + + bool found_unbound_column = false; + function&)> find_unbound_column = [&](unique_ptr &expr) -> RC { + RC rc = RC::SUCCESS; + if (expr->type() == ExprType::AGGREGATION) { + // do nothing + } else if (expr->pos() != -1) { + // do nothing + } else if (expr->type() == ExprType::FIELD) { + found_unbound_column = true; + }else { + rc = ExpressionIterator::iterate_child_expr(*expr, find_unbound_column); + } + return rc; + }; + + + for (unique_ptr &expression : query_expressions) { + bind_group_by_expr(expression); + } + + for (unique_ptr &expression : query_expressions) { + find_unbound_column(expression); + } + + // collect all aggregate expressions + for (unique_ptr &expression : query_expressions) { + collector(expression); + } + + if (group_by_expressions.empty() && aggregate_expressions.empty()) { + // 既没有group by也没有聚合函数,不需要group by + return RC::SUCCESS; + } + + if (found_unbound_column) { + LOG_WARN("column must appear in the GROUP BY clause or must be part of an aggregate function"); + return RC::INVALID_ARGUMENT; + } + + // 如果只需要聚合,但是没有group by 语句,需要生成一个空的group by 语句 + auto group_by_oper = std::unique_ptr(new GroupByLogicalOperator(std::move(group_by_expressions), + std::move(aggregate_expressions))); + std::vector child_groups = {gid}; + CandidateExpression candidate(std::move(group_by_oper), std::move(child_groups)); + context->record_node_into_group(candidate, &root_gexpr); + return RC::SUCCESS; +} \ No newline at end of file diff --git a/src/observer/sql/optimizer/logical_plan_generator.h b/src/observer/sql/optimizer/logical_plan_generator.h index 71a50cf9d..1d2e04220 100644 --- a/src/observer/sql/optimizer/logical_plan_generator.h +++ b/src/observer/sql/optimizer/logical_plan_generator.h @@ -43,6 +43,7 @@ class LogicalPlanGenerator RC create_plan(InsertStmt *insert_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); RC create_plan(DeleteStmt *delete_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); RC create_plan(ExplainStmt *explain_stmt, GroupExpr *&root_gexpr, OptimizerContext *context); + RC create_group_by_plan(SelectStmt *select_stmt, GroupExpr *&root_gexpr, OptimizerContext *context, int gid); int implicit_cast_cost(AttrType from, AttrType to); }; From 1bab754023b7a809deed0557bdd61efc84cefaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Fri, 28 Nov 2025 17:33:48 +0800 Subject: [PATCH 11/12] feat(optimizer): Add index scan implementation rule --- .../physical/index_scan_physical_operator.cpp | 3 +- .../physical/index_scan_physical_operator.h | 30 +++++++++++++ .../physical/table_scan_physical_operator.h | 23 +++++++++- .../cascade/implementation_rules.cpp | 45 +++++++++++++++---- 4 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/observer/sql/operator/physical/index_scan_physical_operator.cpp b/src/observer/sql/operator/physical/index_scan_physical_operator.cpp index 8f03c699c..2d7d63fa1 100644 --- a/src/observer/sql/operator/physical/index_scan_physical_operator.cpp +++ b/src/observer/sql/operator/physical/index_scan_physical_operator.cpp @@ -99,7 +99,8 @@ RC IndexScanPhysicalOperator::next() RC IndexScanPhysicalOperator::close() { - index_scanner_->destroy(); + if(index_scanner_ != nullptr) + index_scanner_->destroy(); index_scanner_ = nullptr; return RC::SUCCESS; } diff --git a/src/observer/sql/operator/physical/index_scan_physical_operator.h b/src/observer/sql/operator/physical/index_scan_physical_operator.h index 5bc14f2a5..98630037e 100644 --- a/src/observer/sql/operator/physical/index_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/index_scan_physical_operator.h @@ -16,6 +16,8 @@ See the Mulan PSL v2 for more details. */ #include "sql/expr/tuple.h" #include "sql/operator/physical_operator.h" +#include "sql/optimizer/cascade/cost_model.h" +#include "sql/optimizer/cascade/property.h" #include "storage/record/record_manager.h" /** @@ -72,6 +74,34 @@ class IndexScanPhysicalOperator : public PhysicalOperator string param() const override; + double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override + { + // 索引扫描的代价计算: + // 1. 索引查找成本:index_probe(查找索引,固定成本,很小) + // 2. IO 成本:访问匹配的行(只访问匹配的行,不需要扫描整个表) + // 3. CPU 成本:处理匹配的行 + int card = prop ? prop->get_card() : 0; + if (card == 0) { + card = 1; // Use minimum cardinality of 1 for cost calculation + } + + // 索引扫描的代价 = 索引查找成本 + IO * 匹配行数 + CPU * 匹配行数 + // 索引扫描的优势: + // - 基数更小(只访问匹配的行,而不是全表扫描) + // - IO 成本更低(不需要扫描整个表,只需要访问匹配的行) + // 索引扫描的 IO 成本应该比表扫描低,因为: + // - 表扫描需要扫描整个表(所有行) + // - 索引扫描只需要访问匹配的行(基数更小) + double index_lookup_cost = cm->index_probe(); // 索引查找的固定成本(很小,0.00001) + // 索引扫描的 IO 成本:只访问匹配的行,不需要扫描整个表 + // 假设每个匹配行需要一次 IO 访问(实际上可能更少,因为索引可以批量访问) + double io_cost = cm->io() * card; + // CPU 成本:处理匹配的行 + double cpu_cost = cm->cpu_op() * card; + + return index_lookup_cost + io_cost + cpu_cost; + } + RC open(Trx *trx) override; RC next() override; RC close() override; diff --git a/src/observer/sql/operator/physical/table_scan_physical_operator.h b/src/observer/sql/operator/physical/table_scan_physical_operator.h index 89fb75b5c..120fd985d 100644 --- a/src/observer/sql/operator/physical/table_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/table_scan_physical_operator.h @@ -67,11 +67,32 @@ class TableScanPhysicalOperator : public PhysicalOperator double calculate_cost(LogicalProperty *prop, const vector &child_log_props, CostModel *cm) override { + // 表扫描的代价计算: + // 1. IO 成本:需要扫描整个表(所有行),而不是只扫描匹配的行 + // 2. CPU 成本:处理所有行并过滤(过滤后的行数) + // 表扫描需要扫描整个表,所以 IO 成本应该基于全表的行数 + // 但为了简化,我们使用 prop 中的基数(过滤后的行数)作为近似 + // TODO: 应该从 Catalog 获取全表的行数来计算 IO 成本 int card = prop ? prop->get_card() : 0; if (card == 0) { card = 1; // Use minimum cardinality of 1 for cost calculation } - return (cm->io() + cm->cpu_op()) * card; + + // 表扫描需要扫描整个表,IO 成本应该基于全表行数 + // 但当前 prop 中的 card 是过滤后的基数,我们假设全表行数 = card * 10(简单估计) + // 实际上应该从 Catalog 获取准确的表统计信息 + int full_table_rows = card * 10; // 简单估计:假设过滤后保留 10% 的数据 + if (full_table_rows < card) { + full_table_rows = card; // 至少等于过滤后的基数 + } + + // 表扫描的代价 = 扫描全表的 IO 成本 + 处理所有行的 CPU 成本 + // 注意:表扫描需要扫描所有行,所以 IO 成本基于全表行数 + double io_cost = cm->io() * full_table_rows; + // CPU 成本:处理所有行(包括过滤) + double cpu_cost = cm->cpu_op() * full_table_rows; + + return io_cost + cpu_cost; } RC open(Trx *trx) override; diff --git a/src/observer/sql/optimizer/cascade/implementation_rules.cpp b/src/observer/sql/optimizer/cascade/implementation_rules.cpp index 3b2ac5d7d..f9c228ae9 100644 --- a/src/observer/sql/optimizer/cascade/implementation_rules.cpp +++ b/src/observer/sql/optimizer/cascade/implementation_rules.cpp @@ -35,6 +35,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/physical/empty_physical_operator.h" #include "sql/operator/logical/empty_logical_operator.h" #include "sql/expr/expression.h" +#include "sql/parser/parse_defs.h" // ------------------------------------------------------------------------------------------------- // PhysicalSeqScan @@ -83,12 +84,20 @@ void LogicalGetToPhysicalIndexScan::transform( // 查找可以用于索引查找的表达式 Index *index = nullptr; - ValueExpr *value_expr = nullptr; + ValueExpr *left_value_expr = nullptr; + ValueExpr *right_value_expr = nullptr; + bool left_inclusive = false; + bool right_inclusive = false; + CompOp comp_op = NO_OP; + for (auto &expr : predicates) { if (expr->type() == ExprType::COMPARISON) { auto comparison_expr = static_cast(expr.get()); - // 简单处理,只找等值查询 - if (comparison_expr->comp() != EQUAL_TO && comparison_expr->comp() != NOT_EQUAL) { + comp_op = comparison_expr->comp(); + + // 支持等值查询和范围查询 + // NOT_EQUAL 不支持索引扫描(需要扫描所有不等于的值) + if (comp_op == NOT_EQUAL) { continue; } @@ -100,6 +109,8 @@ void LogicalGetToPhysicalIndexScan::transform( } FieldExpr *field_expr = nullptr; + ValueExpr *value_expr = nullptr; + if (left_expr->type() == ExprType::FIELD && right_expr->type() == ExprType::VALUE) { field_expr = static_cast(left_expr.get()); value_expr = static_cast(right_expr.get()); @@ -117,23 +128,39 @@ void LogicalGetToPhysicalIndexScan::transform( if (field.table() != table) { continue; } - index = table->find_index_by_field(field.field_name()); - if (nullptr != index) { - break; + + Index *found_index = table->find_index_by_field(field.field_name()); + if (nullptr == found_index) { + continue; } + + // 找到索引,根据比较操作符设置范围 + index = found_index; + + if (comp_op == EQUAL_TO) { + // 等值查询:left_value = right_value = value + left_value_expr = value_expr; + right_value_expr = value_expr; + left_inclusive = true; + right_inclusive = true; + } + + break; // 找到第一个可用的索引查询就退出 } } // 只有在找到索引时才生成 IndexScan - if (index != nullptr && value_expr != nullptr) { + if (index != nullptr) { vector> phys_preds; for (auto &pred : predicates) { phys_preds.push_back(pred->copy()); } - const Value &value = value_expr->get_value(); + const Value *left_value = left_value_expr ? &left_value_expr->get_value() : nullptr; + const Value *right_value = right_value_expr ? &right_value_expr->get_value() : nullptr; + auto index_scan_oper = new IndexScanPhysicalOperator(table, index, table_get_oper->read_write_mode(), - &value, true /*left_inclusive*/, &value, true /*right_inclusive*/); + left_value, left_inclusive, right_value, right_inclusive); index_scan_oper->set_predicates(std::move(phys_preds)); auto oper = unique_ptr(index_scan_oper); From 941e2fa9e2fe187f611f092bf718df748aa85c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E9=9A=8F?= Date: Fri, 28 Nov 2025 18:00:35 +0800 Subject: [PATCH 12/12] fix: Fix ci --- .github/workflows/build-test.yml | 8 ++ .github/workflows/clang-format.yml | 8 ++ src/common/sys/rc.h | 134 +++++++++--------- src/observer/sql/expr/expression.h | 14 +- .../operator/logical/calc_logical_operator.h | 2 +- .../logical/delete_logical_operator.h | 9 +- .../operator/logical/empty_logical_operator.h | 5 +- .../logical/explain_logical_operator.h | 5 +- .../logical/group_by_logical_operator.h | 4 +- .../logical/insert_logical_operator.h | 5 +- .../operator/logical/join_logical_operator.h | 6 +- src/observer/sql/operator/logical_operator.h | 6 +- src/observer/sql/operator/operator_node.h | 2 +- .../physical/calc_physical_operator.h | 2 +- .../physical/empty_physical_operator.h | 1 - .../hash_group_by_physical_operator.h | 2 +- .../physical/index_scan_physical_operator.h | 4 +- .../physical/predicate_physical_operator.h | 2 +- .../physical/project_physical_operator.h | 2 +- .../scalar_group_by_physical_operator.h | 2 +- .../physical/table_scan_physical_operator.h | 10 +- src/observer/sql/optimizer/cascade/group.h | 6 +- src/observer/sql/optimizer/cascade/memo.h | 6 +- .../sql/optimizer/cascade/optimizer_context.h | 2 +- src/observer/sql/optimizer/cascade/rules.h | 6 +- .../optimizer/cascade/transformation_rules.h | 1 - src/observer/sql/optimizer/optimize_stage.h | 2 +- 27 files changed, 127 insertions(+), 129 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index afcb122ea..b96dbad60 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -5,6 +5,14 @@ on: branches: [ "main" ] pull_request: branches: [ "main" ] + types: [opened, reopened, synchronize, ready_for_review] + paths-ignore: + - 'docs/**' + - '.github/ISSUE_TEMPLATE/**' + - '.github/pull_request_template.md' + - 'README.md' + - 'CODE_OF_CONDUCT.md' + - 'CONTRIBUTING.md' env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 0cf0cceb8..75792f5f1 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -2,6 +2,14 @@ name: Clang Format Checker on: pull_request: branches: [ "main" ] + types: [opened, reopened, synchronize, ready_for_review] + paths-ignore: + - 'docs/**' + - '.github/ISSUE_TEMPLATE/**' + - '.github/pull_request_template.md' + - 'README.md' + - 'CODE_OF_CONDUCT.md' + - 'CONTRIBUTING.md' jobs: clang-format-checking: runs-on: ubuntu-latest diff --git a/src/common/sys/rc.h b/src/common/sys/rc.h index 97369a033..b862aa528 100644 --- a/src/common/sys/rc.h +++ b/src/common/sys/rc.h @@ -19,74 +19,74 @@ See the Mulan PSL v2 for more details. */ * @enum RC */ -#define DEFINE_RCS \ - DEFINE_RC(SUCCESS) \ - DEFINE_RC(INVALID_ARGUMENT) \ - DEFINE_RC(UNIMPLEMENTED) \ - DEFINE_RC(SQL_SYNTAX) \ - DEFINE_RC(INTERNAL) \ - DEFINE_RC(NOMEM) \ - DEFINE_RC(NOTFOUND) \ - DEFINE_RC(EMPTY) \ - DEFINE_RC(FULL) \ - DEFINE_RC(EXIST) \ - DEFINE_RC(NOT_EXIST) \ - DEFINE_RC(BUFFERPOOL_OPEN) \ - DEFINE_RC(BUFFERPOOL_NOBUF) \ - DEFINE_RC(BUFFERPOOL_INVALID_PAGE_NUM) \ - DEFINE_RC(RECORD_OPENNED) \ - DEFINE_RC(RECORD_INVALID_RID) \ - DEFINE_RC(RECORD_INVALID_KEY) \ - DEFINE_RC(RECORD_DUPLICATE_KEY) \ - DEFINE_RC(RECORD_NOMEM) \ - DEFINE_RC(RECORD_EOF) \ - DEFINE_RC(RECORD_NOT_EXIST) \ - DEFINE_RC(RECORD_INVISIBLE) \ - DEFINE_RC(SCHEMA_DB_EXIST) \ - DEFINE_RC(SCHEMA_DB_NOT_EXIST) \ - DEFINE_RC(SCHEMA_DB_NOT_OPENED) \ - DEFINE_RC(SCHEMA_TABLE_NOT_EXIST) \ - DEFINE_RC(SCHEMA_TABLE_EXIST) \ - DEFINE_RC(SCHEMA_FIELD_NOT_EXIST) \ - DEFINE_RC(SCHEMA_FIELD_MISSING) \ - DEFINE_RC(SCHEMA_FIELD_TYPE_MISMATCH) \ - DEFINE_RC(SCHEMA_INDEX_NAME_REPEAT) \ - DEFINE_RC(IOERR_READ) \ - DEFINE_RC(IOERR_WRITE) \ - DEFINE_RC(IOERR_ACCESS) \ - DEFINE_RC(IOERR_OPEN) \ - DEFINE_RC(IOERR_CLOSE) \ - DEFINE_RC(IOERR_SEEK) \ - DEFINE_RC(IOERR_TOO_LONG) \ - DEFINE_RC(IOERR_SYNC) \ - DEFINE_RC(LOCKED_UNLOCK) \ - DEFINE_RC(LOCKED_NEED_WAIT) \ - DEFINE_RC(LOCKED_CONCURRENCY_CONFLICT) \ - DEFINE_RC(FILE_EXIST) \ - DEFINE_RC(FILE_NOT_EXIST) \ - DEFINE_RC(FILE_NAME) \ - DEFINE_RC(FILE_BOUND) \ - DEFINE_RC(FILE_CREATE) \ - DEFINE_RC(FILE_OPEN) \ - DEFINE_RC(FILE_NOT_OPENED) \ - DEFINE_RC(FILE_CLOSE) \ - DEFINE_RC(FILE_REMOVE) \ - DEFINE_RC(VARIABLE_NOT_EXISTS) \ - DEFINE_RC(VARIABLE_NOT_VALID) \ - DEFINE_RC(LOGBUF_FULL) \ - DEFINE_RC(LOG_FILE_FULL) \ - DEFINE_RC(LOG_ENTRY_INVALID) \ - DEFINE_RC(JSON_PARSE_FAILED) \ - DEFINE_RC(JSON_MEMBER_MISSING) \ - DEFINE_RC(RANGE_ERROR) \ - DEFINE_RC(WAL_INVALID_FILENAME) \ - DEFINE_RC(INPUT_EOF) \ - DEFINE_RC(INVALID_TOKEN) \ - DEFINE_RC(UNEXPECTED_END_OF_STRING) \ - DEFINE_RC(SYNTAX_ERROR) \ - DEFINE_RC(UNSUPPORTED) \ +#define DEFINE_RCS \ + DEFINE_RC(SUCCESS) \ + DEFINE_RC(INVALID_ARGUMENT) \ + DEFINE_RC(UNIMPLEMENTED) \ + DEFINE_RC(SQL_SYNTAX) \ + DEFINE_RC(INTERNAL) \ + DEFINE_RC(NOMEM) \ + DEFINE_RC(NOTFOUND) \ + DEFINE_RC(EMPTY) \ + DEFINE_RC(FULL) \ + DEFINE_RC(EXIST) \ + DEFINE_RC(NOT_EXIST) \ + DEFINE_RC(BUFFERPOOL_OPEN) \ + DEFINE_RC(BUFFERPOOL_NOBUF) \ + DEFINE_RC(BUFFERPOOL_INVALID_PAGE_NUM) \ + DEFINE_RC(RECORD_OPENNED) \ + DEFINE_RC(RECORD_INVALID_RID) \ + DEFINE_RC(RECORD_INVALID_KEY) \ + DEFINE_RC(RECORD_DUPLICATE_KEY) \ + DEFINE_RC(RECORD_NOMEM) \ + DEFINE_RC(RECORD_EOF) \ + DEFINE_RC(RECORD_NOT_EXIST) \ + DEFINE_RC(RECORD_INVISIBLE) \ + DEFINE_RC(SCHEMA_DB_EXIST) \ + DEFINE_RC(SCHEMA_DB_NOT_EXIST) \ + DEFINE_RC(SCHEMA_DB_NOT_OPENED) \ + DEFINE_RC(SCHEMA_TABLE_NOT_EXIST) \ + DEFINE_RC(SCHEMA_TABLE_EXIST) \ + DEFINE_RC(SCHEMA_FIELD_NOT_EXIST) \ + DEFINE_RC(SCHEMA_FIELD_MISSING) \ + DEFINE_RC(SCHEMA_FIELD_TYPE_MISMATCH) \ + DEFINE_RC(SCHEMA_INDEX_NAME_REPEAT) \ + DEFINE_RC(IOERR_READ) \ + DEFINE_RC(IOERR_WRITE) \ + DEFINE_RC(IOERR_ACCESS) \ + DEFINE_RC(IOERR_OPEN) \ + DEFINE_RC(IOERR_CLOSE) \ + DEFINE_RC(IOERR_SEEK) \ + DEFINE_RC(IOERR_TOO_LONG) \ + DEFINE_RC(IOERR_SYNC) \ + DEFINE_RC(LOCKED_UNLOCK) \ + DEFINE_RC(LOCKED_NEED_WAIT) \ + DEFINE_RC(LOCKED_CONCURRENCY_CONFLICT) \ + DEFINE_RC(FILE_EXIST) \ + DEFINE_RC(FILE_NOT_EXIST) \ + DEFINE_RC(FILE_NAME) \ + DEFINE_RC(FILE_BOUND) \ + DEFINE_RC(FILE_CREATE) \ + DEFINE_RC(FILE_OPEN) \ + DEFINE_RC(FILE_NOT_OPENED) \ + DEFINE_RC(FILE_CLOSE) \ + DEFINE_RC(FILE_REMOVE) \ + DEFINE_RC(VARIABLE_NOT_EXISTS) \ + DEFINE_RC(VARIABLE_NOT_VALID) \ + DEFINE_RC(LOGBUF_FULL) \ + DEFINE_RC(LOG_FILE_FULL) \ + DEFINE_RC(LOG_ENTRY_INVALID) \ + DEFINE_RC(JSON_PARSE_FAILED) \ + DEFINE_RC(JSON_MEMBER_MISSING) \ + DEFINE_RC(RANGE_ERROR) \ + DEFINE_RC(WAL_INVALID_FILENAME) \ + DEFINE_RC(INPUT_EOF) \ + DEFINE_RC(INVALID_TOKEN) \ + DEFINE_RC(UNEXPECTED_END_OF_STRING) \ + DEFINE_RC(SYNTAX_ERROR) \ + DEFINE_RC(UNSUPPORTED) \ DEFINE_RC(OPTIMIZER_GROUP_EXPR_CREATE_FAILED) \ - DEFINE_RC(OPTIMIZER_MEMO_INSERT_FAILED) \ + DEFINE_RC(OPTIMIZER_MEMO_INSERT_FAILED) \ DEFINE_RC(OPTIMIZER_INVALID_GROUP_ID) enum class RC diff --git a/src/observer/sql/expr/expression.h b/src/observer/sql/expr/expression.h index 8cd4b21a7..cd8bdb2bb 100644 --- a/src/observer/sql/expr/expression.h +++ b/src/observer/sql/expr/expression.h @@ -282,7 +282,7 @@ class CastExpr : public Expression AttrType value_type() const override { return cast_type_; } - unique_ptr &child() { return child_; } + unique_ptr &child() { return child_; } const unique_ptr &child() const { return child_; } private: @@ -319,9 +319,9 @@ class ComparisonExpr : public Expression */ RC eval(Chunk &chunk, vector &select) override; - unique_ptr &left() { return left_; } + unique_ptr &left() { return left_; } const unique_ptr &left() const { return left_; } - unique_ptr &right() { return right_; } + unique_ptr &right() { return right_; } const unique_ptr &right() const { return right_; } /** @@ -379,7 +379,7 @@ class ConjunctionExpr : public Expression Type conjunction_type() const { return conjunction_type_; } - vector> &children() { return children_; } + vector> &children() { return children_; } const vector> &children() const { return children_; } private: @@ -431,9 +431,9 @@ class ArithmeticExpr : public Expression Type arithmetic_type() const { return arithmetic_type_; } - unique_ptr &left() { return left_; } + unique_ptr &left() { return left_; } const unique_ptr &left() const { return left_; } - unique_ptr &right() { return right_; } + unique_ptr &right() { return right_; } const unique_ptr &right() const { return right_; } private: @@ -466,7 +466,7 @@ class UnboundAggregateExpr : public Expression const char *aggregate_name() const { return aggregate_name_.c_str(); } - unique_ptr &child() { return child_; } + unique_ptr &child() { return child_; } const unique_ptr &child() const { return child_; } RC get_value(const Tuple &tuple, Value &value) const override { return RC::INTERNAL; } diff --git a/src/observer/sql/operator/logical/calc_logical_operator.h b/src/observer/sql/operator/logical/calc_logical_operator.h index d361534cb..7a5827a30 100644 --- a/src/observer/sql/operator/logical/calc_logical_operator.h +++ b/src/observer/sql/operator/logical/calc_logical_operator.h @@ -26,7 +26,7 @@ class CalcLogicalOperator : public LogicalOperator CalcLogicalOperator(vector> &&expressions) { expressions_.swap(expressions); } virtual ~CalcLogicalOperator() = default; - OpType get_op_type() const override { return OpType::LOGICALCALCULATE; } + OpType get_op_type() const override { return OpType::LOGICALCALCULATE; } unique_ptr clone() const override { diff --git a/src/observer/sql/operator/logical/delete_logical_operator.h b/src/observer/sql/operator/logical/delete_logical_operator.h index 38125c098..f51dbddf2 100644 --- a/src/observer/sql/operator/logical/delete_logical_operator.h +++ b/src/observer/sql/operator/logical/delete_logical_operator.h @@ -26,7 +26,7 @@ class DeleteLogicalOperator : public LogicalOperator DeleteLogicalOperator(Table *table); virtual ~DeleteLogicalOperator() = default; - OpType get_op_type() const override { return OpType::LOGICALDELETE; } + OpType get_op_type() const override { return OpType::LOGICALDELETE; } virtual uint64_t hash() const override { @@ -43,12 +43,9 @@ class DeleteLogicalOperator : public LogicalOperator return table_->table_id() == other_delete.table()->table_id(); } - Table *table() const { return table_; } + Table *table() const { return table_; } - unique_ptr clone() const override - { - return make_unique(table_); - } + unique_ptr clone() const override { return make_unique(table_); } private: Table *table_ = nullptr; diff --git a/src/observer/sql/operator/logical/empty_logical_operator.h b/src/observer/sql/operator/logical/empty_logical_operator.h index 48d1e6a93..5ddf52d9b 100644 --- a/src/observer/sql/operator/logical/empty_logical_operator.h +++ b/src/observer/sql/operator/logical/empty_logical_operator.h @@ -24,8 +24,5 @@ class EmptyLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALEMPTY; } - unique_ptr clone() const override - { - return make_unique(); - } + unique_ptr clone() const override { return make_unique(); } }; diff --git a/src/observer/sql/operator/logical/explain_logical_operator.h b/src/observer/sql/operator/logical/explain_logical_operator.h index d7d28e84d..4a671d214 100644 --- a/src/observer/sql/operator/logical/explain_logical_operator.h +++ b/src/observer/sql/operator/logical/explain_logical_operator.h @@ -28,8 +28,5 @@ class ExplainLogicalOperator : public LogicalOperator OpType get_op_type() const override { return OpType::LOGICALEXPLAIN; } - unique_ptr clone() const override - { - return make_unique(); - } + unique_ptr clone() const override { return make_unique(); } }; diff --git a/src/observer/sql/operator/logical/group_by_logical_operator.h b/src/observer/sql/operator/logical/group_by_logical_operator.h index 61a6f1fd3..826140b82 100644 --- a/src/observer/sql/operator/logical/group_by_logical_operator.h +++ b/src/observer/sql/operator/logical/group_by_logical_operator.h @@ -23,7 +23,7 @@ class GroupByLogicalOperator : public LogicalOperator virtual ~GroupByLogicalOperator() = default; - OpType get_op_type() const override { return OpType::LOGICALGROUPBY; } + OpType get_op_type() const override { return OpType::LOGICALGROUPBY; } virtual uint64_t hash() const override { @@ -69,5 +69,5 @@ class GroupByLogicalOperator : public LogicalOperator private: vector> &group_by_expressions_ = expressions_; - vector aggregate_expressions_; ///< 输出的表达式,可能包含聚合函数 + vector aggregate_expressions_; ///< 输出的表达式,可能包含聚合函数 }; diff --git a/src/observer/sql/operator/logical/insert_logical_operator.h b/src/observer/sql/operator/logical/insert_logical_operator.h index 9efb7ed05..e2b28ba1a 100644 --- a/src/observer/sql/operator/logical/insert_logical_operator.h +++ b/src/observer/sql/operator/logical/insert_logical_operator.h @@ -58,10 +58,7 @@ class InsertLogicalOperator : public LogicalOperator const vector &values() const { return values_; } vector &values() { return values_; } - unique_ptr clone() const override - { - return make_unique(table_, values_); - } + unique_ptr clone() const override { return make_unique(table_, values_); } private: Table *table_ = nullptr; diff --git a/src/observer/sql/operator/logical/join_logical_operator.h b/src/observer/sql/operator/logical/join_logical_operator.h index 8c3c37012..6f7e8cde4 100644 --- a/src/observer/sql/operator/logical/join_logical_operator.h +++ b/src/observer/sql/operator/logical/join_logical_operator.h @@ -27,8 +27,8 @@ class JoinLogicalOperator : public LogicalOperator JoinLogicalOperator() = default; virtual ~JoinLogicalOperator() = default; - void add_predicate_op(LogicalOperator *predicate_op) { predicate_op_ = predicate_op; } - auto predicates() -> Expression * + void add_predicate_op(LogicalOperator *predicate_op) { predicate_op_ = predicate_op; } + auto predicates() -> Expression * { if (predicate_op_ != nullptr && predicate_op_->expressions().size() == 1) { return predicate_op_->expressions()[0].get(); @@ -103,6 +103,6 @@ class JoinLogicalOperator : public LogicalOperator } private: - LogicalOperator *predicate_op_ = nullptr; + LogicalOperator *predicate_op_ = nullptr; std::vector> &join_predicates_ = expressions_; }; diff --git a/src/observer/sql/operator/logical_operator.h b/src/observer/sql/operator/logical_operator.h index 37d23b6d3..675bbea59 100644 --- a/src/observer/sql/operator/logical_operator.h +++ b/src/observer/sql/operator/logical_operator.h @@ -38,10 +38,10 @@ class LogicalOperator : public OperatorNode bool is_physical() const override { return false; } bool is_logical() const override { return true; } - void add_expressions(unique_ptr expr); - auto expressions() -> vector> &{ return expressions_; } + void add_expressions(unique_ptr expr); + auto expressions() -> vector> &{ return expressions_; } const vector> &expressions() const { return expressions_; } - static bool can_generate_vectorized_operator(OpType type); + static bool can_generate_vectorized_operator(OpType type); /** * 这两个函数是为了打印时使用的,比如在explain中 diff --git a/src/observer/sql/operator/operator_node.h b/src/observer/sql/operator/operator_node.h index 09f8b6ab9..bb5e55330 100644 --- a/src/observer/sql/operator/operator_node.h +++ b/src/observer/sql/operator/operator_node.h @@ -121,7 +121,7 @@ class OperatorNode * @param child_log_props A vector containing pointers to child logical properties. * @param cm A pointer to the cost model used for calculating the cost. * @return The calculated cost as a double. - * + * * @note Default implementation: uses CPU operation cost based on input cardinality. * If there are child operators, uses the first child's cardinality. * Otherwise, uses the current operator's cardinality. diff --git a/src/observer/sql/operator/physical/calc_physical_operator.h b/src/observer/sql/operator/physical/calc_physical_operator.h index 70a0b0aa7..30f2baa92 100644 --- a/src/observer/sql/operator/physical/calc_physical_operator.h +++ b/src/observer/sql/operator/physical/calc_physical_operator.h @@ -26,7 +26,7 @@ class CalcPhysicalOperator : public PhysicalOperator virtual ~CalcPhysicalOperator() = default; - OpType get_op_type() const override { return OpType::CALCULATE; } + OpType get_op_type() const override { return OpType::CALCULATE; } virtual uint64_t hash() const override { diff --git a/src/observer/sql/operator/physical/empty_physical_operator.h b/src/observer/sql/operator/physical/empty_physical_operator.h index 95602a2a7..92fa96ae0 100644 --- a/src/observer/sql/operator/physical/empty_physical_operator.h +++ b/src/observer/sql/operator/physical/empty_physical_operator.h @@ -42,4 +42,3 @@ class EmptyPhysicalOperator : public PhysicalOperator RC tuple_schema(TupleSchema &schema) const override { return RC::SUCCESS; } }; - diff --git a/src/observer/sql/operator/physical/hash_group_by_physical_operator.h b/src/observer/sql/operator/physical/hash_group_by_physical_operator.h index cfc81af48..84abd55b1 100644 --- a/src/observer/sql/operator/physical/hash_group_by_physical_operator.h +++ b/src/observer/sql/operator/physical/hash_group_by_physical_operator.h @@ -31,7 +31,7 @@ class HashGroupByPhysicalOperator : public GroupByPhysicalOperator virtual ~HashGroupByPhysicalOperator() = default; - OpType get_op_type() const override { return OpType::HASHGROUPBY; } + OpType get_op_type() const override { return OpType::HASHGROUPBY; } virtual uint64_t hash() const override { diff --git a/src/observer/sql/operator/physical/index_scan_physical_operator.h b/src/observer/sql/operator/physical/index_scan_physical_operator.h index 98630037e..3310c9ce4 100644 --- a/src/observer/sql/operator/physical/index_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/index_scan_physical_operator.h @@ -84,7 +84,7 @@ class IndexScanPhysicalOperator : public PhysicalOperator if (card == 0) { card = 1; // Use minimum cardinality of 1 for cost calculation } - + // 索引扫描的代价 = 索引查找成本 + IO * 匹配行数 + CPU * 匹配行数 // 索引扫描的优势: // - 基数更小(只访问匹配的行,而不是全表扫描) @@ -98,7 +98,7 @@ class IndexScanPhysicalOperator : public PhysicalOperator double io_cost = cm->io() * card; // CPU 成本:处理匹配的行 double cpu_cost = cm->cpu_op() * card; - + return index_lookup_cost + io_cost + cpu_cost; } diff --git a/src/observer/sql/operator/physical/predicate_physical_operator.h b/src/observer/sql/operator/physical/predicate_physical_operator.h index 31d6176e0..cb0b73d83 100644 --- a/src/observer/sql/operator/physical/predicate_physical_operator.h +++ b/src/observer/sql/operator/physical/predicate_physical_operator.h @@ -30,7 +30,7 @@ class PredicatePhysicalOperator : public PhysicalOperator virtual ~PredicatePhysicalOperator() = default; - OpType get_op_type() const override { return OpType::FILTER; } + OpType get_op_type() const override { return OpType::FILTER; } virtual uint64_t hash() const override { diff --git a/src/observer/sql/operator/physical/project_physical_operator.h b/src/observer/sql/operator/physical/project_physical_operator.h index 29d8cc0de..226d91528 100644 --- a/src/observer/sql/operator/physical/project_physical_operator.h +++ b/src/observer/sql/operator/physical/project_physical_operator.h @@ -28,7 +28,7 @@ class ProjectPhysicalOperator : public PhysicalOperator virtual ~ProjectPhysicalOperator() = default; - OpType get_op_type() const override { return OpType::PROJECTION; } + OpType get_op_type() const override { return OpType::PROJECTION; } virtual uint64_t hash() const override { diff --git a/src/observer/sql/operator/physical/scalar_group_by_physical_operator.h b/src/observer/sql/operator/physical/scalar_group_by_physical_operator.h index 6b5ab323a..8645f8ed8 100644 --- a/src/observer/sql/operator/physical/scalar_group_by_physical_operator.h +++ b/src/observer/sql/operator/physical/scalar_group_by_physical_operator.h @@ -26,7 +26,7 @@ class ScalarGroupByPhysicalOperator : public GroupByPhysicalOperator ScalarGroupByPhysicalOperator(vector &&expressions); virtual ~ScalarGroupByPhysicalOperator() = default; - OpType get_op_type() const override { return OpType::SCALARGROUPBY; } + OpType get_op_type() const override { return OpType::SCALARGROUPBY; } RC open(Trx *trx) override; RC next() override; diff --git a/src/observer/sql/operator/physical/table_scan_physical_operator.h b/src/observer/sql/operator/physical/table_scan_physical_operator.h index 120fd985d..ce86d72ae 100644 --- a/src/observer/sql/operator/physical/table_scan_physical_operator.h +++ b/src/observer/sql/operator/physical/table_scan_physical_operator.h @@ -35,8 +35,8 @@ class TableScanPhysicalOperator : public PhysicalOperator string param() const override; - OpType get_op_type() const override { return OpType::SEQSCAN; } - virtual uint64_t hash() const override + OpType get_op_type() const override { return OpType::SEQSCAN; } + virtual uint64_t hash() const override { uint64_t hash = std::hash()(static_cast(get_op_type())); hash ^= std::hash()(table_->table_id()); @@ -77,7 +77,7 @@ class TableScanPhysicalOperator : public PhysicalOperator if (card == 0) { card = 1; // Use minimum cardinality of 1 for cost calculation } - + // 表扫描需要扫描整个表,IO 成本应该基于全表行数 // 但当前 prop 中的 card 是过滤后的基数,我们假设全表行数 = card * 10(简单估计) // 实际上应该从 Catalog 获取准确的表统计信息 @@ -85,13 +85,13 @@ class TableScanPhysicalOperator : public PhysicalOperator if (full_table_rows < card) { full_table_rows = card; // 至少等于过滤后的基数 } - + // 表扫描的代价 = 扫描全表的 IO 成本 + 处理所有行的 CPU 成本 // 注意:表扫描需要扫描所有行,所以 IO 成本基于全表行数 double io_cost = cm->io() * full_table_rows; // CPU 成本:处理所有行(包括过滤) double cpu_cost = cm->cpu_op() * full_table_rows; - + return io_cost + cpu_cost; } diff --git a/src/observer/sql/optimizer/cascade/group.h b/src/observer/sql/optimizer/cascade/group.h index 2140f9fc6..b6eb4f17e 100644 --- a/src/observer/sql/optimizer/cascade/group.h +++ b/src/observer/sql/optimizer/cascade/group.h @@ -96,11 +96,9 @@ class Group LogicalProperty *get_logical_prop() { return logical_prop_.get(); } bool is_alias() const { return alias_target_ != -1; } - int get_alias_target() const { return alias_target_; } + int get_alias_target() const { return alias_target_; } - void set_alias(int target) { - alias_target_ = target; - } + void set_alias(int target) { alias_target_ = target; } ///< dump the group info, for debug void dump() const; diff --git a/src/observer/sql/optimizer/cascade/memo.h b/src/observer/sql/optimizer/cascade/memo.h index ec6f9ea26..e053f2936 100644 --- a/src/observer/sql/optimizer/cascade/memo.h +++ b/src/observer/sql/optimizer/cascade/memo.h @@ -38,7 +38,7 @@ class Memo Group *get_group_by_id(int id) const { - Group* g = groups_[id].get(); + Group *g = groups_[id].get(); ASSERT(id >= 0 && static_cast(id) < groups_.size(), "group_id out of bounds"); while (g && g->is_alias()) { g = groups_[g->get_alias_target()].get(); @@ -46,9 +46,7 @@ class Memo return g; } - void make_alias(int src, int target) { - groups_[src]->set_alias(target); - } + void make_alias(int src, int target) { groups_[src]->set_alias(target); } void dump() const; diff --git a/src/observer/sql/optimizer/cascade/optimizer_context.h b/src/observer/sql/optimizer/cascade/optimizer_context.h index c56a54bb0..d719e68c3 100644 --- a/src/observer/sql/optimizer/cascade/optimizer_context.h +++ b/src/observer/sql/optimizer/cascade/optimizer_context.h @@ -19,7 +19,7 @@ See the Mulan PSL v2 for more details. */ class Memo; class RuleSet; -class CandidateExpression; +struct CandidateExpression; /** * OptimizerContext is a class containing pointers to various objects * that are required during the entire query optimization process. diff --git a/src/observer/sql/optimizer/cascade/rules.h b/src/observer/sql/optimizer/cascade/rules.h index a06c3b451..46dbffc90 100644 --- a/src/observer/sql/optimizer/cascade/rules.h +++ b/src/observer/sql/optimizer/cascade/rules.h @@ -20,9 +20,9 @@ See the Mulan PSL v2 for more details. */ enum class RuleType : uint32_t { // Transformation rules (logical -> logical) - PREDICATE_PUSHDOWN, // 谓词下推 - PREDICATE_REWRITE, // 谓词重写(删除恒真/恒假谓词) - EXPRESSION_SIMPLIFY, // 表达式简化 + PREDICATE_PUSHDOWN, // 谓词下推 + PREDICATE_REWRITE, // 谓词重写(删除恒真/恒假谓词) + EXPRESSION_SIMPLIFY, // 表达式简化 // Don't move this one LogicalPhysicalDelimiter, diff --git a/src/observer/sql/optimizer/cascade/transformation_rules.h b/src/observer/sql/optimizer/cascade/transformation_rules.h index ae982e9a2..a64f10e44 100644 --- a/src/observer/sql/optimizer/cascade/transformation_rules.h +++ b/src/observer/sql/optimizer/cascade/transformation_rules.h @@ -56,4 +56,3 @@ class ExpressionSimplifyRule : public Rule // 简化表达式,返回是否发生变化 bool simplify_expression(unique_ptr &expr) const; }; - diff --git a/src/observer/sql/optimizer/optimize_stage.h b/src/observer/sql/optimizer/optimize_stage.h index ea62af751..1d8b0c184 100644 --- a/src/observer/sql/optimizer/optimize_stage.h +++ b/src/observer/sql/optimizer/optimize_stage.h @@ -33,5 +33,5 @@ class OptimizeStage RC handle_request(SQLStageEvent *event); private: - LogicalPlanGenerator logical_plan_generator_; ///< 根据SQL生成GroupExpr结构 + LogicalPlanGenerator logical_plan_generator_; ///< 根据SQL生成GroupExpr结构 };