Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-organize projection planner #1898

Merged
merged 1 commit into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions src/include/planner/projection_planner.h

This file was deleted.

24 changes: 21 additions & 3 deletions src/include/planner/query_planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "binder/query/reading_clause/bound_in_query_call.h"
#include "join_order_enumerator.h"
#include "planner/join_order/cardinality_estimator.h"
#include "projection_planner.h"

namespace kuzu {
namespace binder {
Expand All @@ -30,7 +29,7 @@ class QueryPlanner {
const storage::RelsStatistics& relsStatistics)
: catalog{catalog}, cardinalityEstimator{std::make_unique<CardinalityEstimator>(
nodesStatistics, relsStatistics)},
joinOrderEnumerator{catalog, this}, projectionPlanner{this} {}
joinOrderEnumerator{catalog, this} {}

std::vector<std::unique_ptr<LogicalPlan>> getAllPlans(const BoundStatement& boundStatement);

Expand Down Expand Up @@ -66,6 +65,16 @@ class QueryPlanner {
void planSetClause(binder::BoundUpdatingClause& updatingClause, LogicalPlan& plan);
void planDeleteClause(binder::BoundUpdatingClause& updatingClause, LogicalPlan& plan);

// Plan projection
void planProjectionBody(const binder::BoundProjectionBody& projectionBody,
const std::vector<std::unique_ptr<LogicalPlan>>& plans);
void planProjectionBody(const binder::BoundProjectionBody& projectionBody, LogicalPlan& plan);
void planAggregate(const binder::expression_vector& expressionsToAggregate,
const binder::expression_vector& expressionsToGroupBy, LogicalPlan& plan);
void planOrderBy(const binder::expression_vector& expressionsToProject,
const binder::expression_vector& expressionsToOrderBy, const std::vector<bool>& isAscOrders,
LogicalPlan& plan);

// Plan subquery
void planOptionalMatch(const QueryGraphCollection& queryGraphCollection,
const expression_vector& predicates, LogicalPlan& leftPlan);
Expand Down Expand Up @@ -122,6 +131,16 @@ class QueryPlanner {
std::vector<std::unique_ptr<BoundSetPropertyInfo>> createLogicalSetPropertyInfo(
const std::vector<binder::BoundCreateInfo*>& boundCreateInfos);

// Append projection operators
void appendProjection(const binder::expression_vector& expressionsToProject, LogicalPlan& plan);
void appendAggregate(const binder::expression_vector& expressionsToGroupBy,
const binder::expression_vector& expressionsToAggregate, LogicalPlan& plan);
void appendOrderBy(const binder::expression_vector& expressions,
const std::vector<bool>& isAscOrders, LogicalPlan& plan);
void appendMultiplicityReducer(LogicalPlan& plan);
void appendLimit(uint64_t limitNumber, LogicalPlan& plan);
void appendSkip(uint64_t skipNumber, LogicalPlan& plan);

std::unique_ptr<LogicalPlan> createUnionPlan(
std::vector<std::unique_ptr<LogicalPlan>>& childrenPlans, bool isUnionAll);

Expand All @@ -138,7 +157,6 @@ class QueryPlanner {
std::unique_ptr<CardinalityEstimator> cardinalityEstimator;
expression_vector propertiesToScan;
JoinOrderEnumerator joinOrderEnumerator;
ProjectionPlanner projectionPlanner;
};

} // namespace planner
Expand Down
1 change: 0 additions & 1 deletion src/planner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ add_library(kuzu_planner
join_order_enumerator.cpp
join_order_enumerator_context.cpp
planner.cpp
projection_planner.cpp
query_planner.cpp
subplans_table.cpp)

Expand Down
4 changes: 2 additions & 2 deletions src/planner/join_order/append_extend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ void JoinOrderEnumerator::createPathNodePropertyScanPlan(
auto expressionsToProject = properties;
expressionsToProject.push_back(recursiveNode->getInternalIDProperty());
expressionsToProject.push_back(recursiveNode->getLabelExpression());
queryPlanner->projectionPlanner.appendProjection(expressionsToProject, plan);
queryPlanner->appendProjection(expressionsToProject, plan);
}

void JoinOrderEnumerator::createPathRelPropertyScanPlan(
Expand All @@ -195,7 +195,7 @@ void JoinOrderEnumerator::createPathRelPropertyScanPlan(
appendNonRecursiveExtend(recursiveNode, nbrNode, recursiveRel, direction, properties, plan);
auto expressionsToProject = properties;
expressionsToProject.push_back(recursiveRel->getLabelExpression());
queryPlanner->projectionPlanner.appendProjection(expressionsToProject, plan);
queryPlanner->appendProjection(expressionsToProject, plan);
}

void JoinOrderEnumerator::appendNodeLabelFilter(std::shared_ptr<Expression> nodeID,
Expand Down
7 changes: 7 additions & 0 deletions src/planner/plan/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
add_library(kuzu_planner_plan_operator
OBJECT
append_accumulate.cpp
append_aggregate.cpp
append_create.cpp
append_cross_product.cpp
append_delete.cpp
append_limit.cpp
append_multiplicity_reducer.cpp
append_order_by.cpp
append_projection.cpp
append_set.cpp
append_skip.cpp
plan_projection.cpp
plan_update.cpp)

set(ALL_OBJECT_FILES
Expand Down
20 changes: 20 additions & 0 deletions src/planner/plan/append_aggregate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "planner/logical_plan/logical_operator/logical_aggregate.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::appendAggregate(const expression_vector& expressionsToGroupBy,
const expression_vector& expressionsToAggregate, LogicalPlan& plan) {
auto aggregate = make_shared<LogicalAggregate>(
expressionsToGroupBy, expressionsToAggregate, plan.getLastOperator());
appendFlattens(aggregate->getGroupsPosToFlattenForGroupBy(), plan);
aggregate->setChild(0, plan.getLastOperator());
appendFlattens(aggregate->getGroupsPosToFlattenForAggregate(), plan);
aggregate->setChild(0, plan.getLastOperator());
aggregate->computeFactorizedSchema();
plan.setLastOperator(std::move(aggregate));
}

} // namespace planner
} // namespace kuzu
17 changes: 17 additions & 0 deletions src/planner/plan/append_limit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "planner/logical_plan/logical_operator/logical_limit.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::appendLimit(uint64_t limitNumber, LogicalPlan& plan) {
auto limit = make_shared<LogicalLimit>(limitNumber, plan.getLastOperator());
appendFlattens(limit->getGroupsPosToFlatten(), plan);
limit->setChild(0, plan.getLastOperator());
limit->computeFactorizedSchema();
plan.setCardinality(limitNumber);
plan.setLastOperator(std::move(limit));
}

} // namespace planner
} // namespace kuzu
14 changes: 14 additions & 0 deletions src/planner/plan/append_multiplicity_reducer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "planner/logical_plan/logical_operator/logical_multiplcity_reducer.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::appendMultiplicityReducer(LogicalPlan& plan) {
auto multiplicityReducer = make_shared<LogicalMultiplicityReducer>(plan.getLastOperator());
multiplicityReducer->computeFactorizedSchema();
plan.setLastOperator(std::move(multiplicityReducer));
}

} // namespace planner
} // namespace kuzu
17 changes: 17 additions & 0 deletions src/planner/plan/append_order_by.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "planner/logical_plan/logical_operator/logical_order_by.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::appendOrderBy(
const expression_vector& expressions, const std::vector<bool>& isAscOrders, LogicalPlan& plan) {
auto orderBy = make_shared<LogicalOrderBy>(expressions, isAscOrders, plan.getLastOperator());
appendFlattens(orderBy->getGroupsPosToFlatten(), plan);
orderBy->setChild(0, plan.getLastOperator());
orderBy->computeFactorizedSchema();
plan.setLastOperator(std::move(orderBy));
}

} // namespace planner
} // namespace kuzu
25 changes: 25 additions & 0 deletions src/planner/plan/append_projection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "planner/logical_plan/logical_operator/flatten_resolver.h"
#include "planner/logical_plan/logical_operator/logical_projection.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::appendProjection(
const expression_vector& expressionsToProject, LogicalPlan& plan) {
for (auto& expression : expressionsToProject) {
planSubqueryIfNecessary(expression, plan);
}
for (auto& expression : expressionsToProject) {
auto dependentGroupsPos = plan.getSchema()->getDependentGroupsPos(expression);
auto groupsPosToFlatten = factorization::FlattenAllButOne::getGroupsPosToFlatten(
dependentGroupsPos, plan.getSchema());
appendFlattens(groupsPosToFlatten, plan);
}
auto projection = make_shared<LogicalProjection>(expressionsToProject, plan.getLastOperator());
projection->computeFactorizedSchema();
plan.setLastOperator(std::move(projection));
}

} // namespace planner
} // namespace kuzu
17 changes: 17 additions & 0 deletions src/planner/plan/append_skip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "planner/logical_plan/logical_operator/logical_skip.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::appendSkip(uint64_t skipNumber, LogicalPlan& plan) {
auto skip = make_shared<LogicalSkip>(skipNumber, plan.getLastOperator());
appendFlattens(skip->getGroupsPosToFlatten(), plan);
skip->setChild(0, plan.getLastOperator());
skip->computeFactorizedSchema();
plan.setCardinality(plan.getCardinality() - skipNumber);
plan.setLastOperator(std::move(skip));
}

} // namespace planner
} // namespace kuzu
82 changes: 82 additions & 0 deletions src/planner/plan/plan_projection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "binder/expression_visitor.h"
#include "planner/query_planner.h"

namespace kuzu {
namespace planner {

void QueryPlanner::planProjectionBody(const BoundProjectionBody& projectionBody,
const std::vector<std::unique_ptr<LogicalPlan>>& plans) {
for (auto& plan : plans) {
planProjectionBody(projectionBody, *plan);
}
}

void QueryPlanner::planProjectionBody(
const BoundProjectionBody& projectionBody, LogicalPlan& plan) {
if (plan.isEmpty()) { // e.g. RETURN 1, COUNT(2)
appendDummyScan(plan);
}
// NOTE: As a temporary solution, we rewrite variables in WITH clause as all properties in scope
// during planning stage. The purpose is to avoid reading unnecessary properties for WITH.
// E.g. MATCH (a) WITH a RETURN a.age -> MATCH (a) WITH a.age RETURN a.age
// This rewrite should be removed once we add an optimizer that can remove unnecessary columns.
auto expressionsToProject = projectionBody.getProjectionExpressions();
auto expressionsToAggregate = projectionBody.getAggregateExpressions();
auto expressionsToGroupBy = projectionBody.getGroupByExpressions();
if (!expressionsToAggregate.empty()) {
planAggregate(expressionsToAggregate, expressionsToGroupBy, plan);
}
if (projectionBody.hasOrderByExpressions()) {
planOrderBy(expressionsToProject, projectionBody.getOrderByExpressions(),
projectionBody.getSortingOrders(), plan);
}
appendProjection(expressionsToProject, plan);
if (projectionBody.getIsDistinct()) {
appendDistinct(expressionsToProject, plan);
}
if (projectionBody.hasSkipOrLimit()) {
appendMultiplicityReducer(plan);
if (projectionBody.hasSkip()) {
appendSkip(projectionBody.getSkipNumber(), plan);
}
if (projectionBody.hasLimit()) {
appendLimit(projectionBody.getLimitNumber(), plan);
}
}
}

void QueryPlanner::planAggregate(const expression_vector& expressionsToAggregate,
const expression_vector& expressionsToGroupBy, LogicalPlan& plan) {
assert(!expressionsToAggregate.empty());
expression_vector expressionsToProject;
for (auto& expressionToAggregate : expressionsToAggregate) {
if (ExpressionChildrenCollector::collectChildren(*expressionToAggregate)
.empty()) { // skip COUNT(*)
continue;
}
expressionsToProject.push_back(expressionToAggregate->getChild(0));
}
for (auto& expressionToGroupBy : expressionsToGroupBy) {
expressionsToProject.push_back(expressionToGroupBy);
}
appendProjection(expressionsToProject, plan);
appendAggregate(expressionsToGroupBy, expressionsToAggregate, plan);
}

void QueryPlanner::planOrderBy(const binder::expression_vector& expressionsToProject,
const binder::expression_vector& expressionsToOrderBy, const std::vector<bool>& isAscOrders,
kuzu::planner::LogicalPlan& plan) {
auto expressionsToProjectBeforeOrderBy = expressionsToProject;
auto expressionsToProjectSet =
expression_set{expressionsToProject.begin(), expressionsToProject.end()};
for (auto& expression : expressionsToOrderBy) {
if (!expressionsToProjectSet.contains(expression)) {
expressionsToProjectBeforeOrderBy.push_back(expression);
}
}
appendProjection(expressionsToProjectBeforeOrderBy, plan);
appendOrderBy(expressionsToOrderBy, isAscOrders, plan);
}

} // namespace planner
} // namespace kuzu
Loading
Loading