blob: b7e9fe70de62cfcac5ea7d6fb47aa3b539e17298 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "univplan/common/subplan-util.h"
#include "univplan/common/plannode-util.h"
#include "univplan/common/plannode-walker.h"
namespace univplan {
class SubplanWalker : public PlanNodeWalker {
public:
void walk(UnivPlanPlanNodePoly* planNodePoly, PlanNodeWalker* walker,
PlanNodeWalkerContext* ctx) override {
auto planNode = PlanNodeUtil::getMutablePlanNode(planNodePoly);
// Basic check
PlanNodeWalker::walkExpressionTree(planNode->mutable_targetlist(), walker,
ctx);
PlanNodeWalker::walkExpressionTree(planNode->mutable_quallist(), walker,
ctx);
PlanNodeWalker::walkExpressionTree(planNode->mutable_initplan(), walker,
ctx);
// Special check for shuffle
if (planNodePoly->has_shuffle()) {
auto sf = planNodePoly->mutable_shuffle();
PlanNodeWalker::walkExpressionTree(sf->mutable_hashexpr(), walker, ctx);
}
// Special check for joinQual
if (planNodePoly->has_nestloop()) {
auto nl = planNodePoly->mutable_nestloop();
PlanNodeWalker::walkExpressionTree(nl->mutable_joinqual(), walker, ctx);
}
if (planNodePoly->has_hashjoin()) {
auto hj = planNodePoly->mutable_hashjoin();
PlanNodeWalker::walkExpressionTree(hj->mutable_joinqual(), walker, ctx);
PlanNodeWalker::walkExpressionTree(hj->mutable_hashclauses(), walker,
ctx);
PlanNodeWalker::walkExpressionTree(hj->mutable_hashqualclauses(), walker,
ctx);
}
if (planNodePoly->has_mergejoin()) {
auto mj = planNodePoly->mutable_mergejoin();
PlanNodeWalker::walkExpressionTree(mj->mutable_joinqual(), walker, ctx);
PlanNodeWalker::walkExpressionTree(mj->mutable_mergeclauses(), walker,
ctx);
}
// Special check for limit
if (planNodePoly->has_limit()) {
auto limit = planNodePoly->mutable_limit();
if (limit->has_limitoffset())
PlanNodeWalker::walkExpressionTree(limit->mutable_limitoffset(), walker,
ctx);
if (limit->has_limitcount())
PlanNodeWalker::walkExpressionTree(limit->mutable_limitcount(), walker,
ctx);
}
if (planNodePoly->has_sort()) {
auto sort = planNodePoly->mutable_sort();
if (sort->has_limitoffset())
PlanNodeWalker::walkExpressionTree(sort->mutable_limitoffset(), walker,
ctx);
if (sort->has_limitcount())
PlanNodeWalker::walkExpressionTree(sort->mutable_limitcount(), walker,
ctx);
}
// Special check from result
if (planNodePoly->has_result()) {
auto result = planNodePoly->mutable_result();
PlanNodeWalker::walkExpressionTree(result->mutable_resconstantqual(),
walker, ctx);
}
}
};
class SubplanPlanidWalkerContext : public PlanNodeWalkerContext {
public:
std::vector<int32_t> planids;
};
class SubplanPlanidWalker : public SubplanWalker {
public:
void walk(UnivPlanExprPoly* expr, PlanNodeWalkerContext* ctx) override {
if (expr->has_subplan() && !expr->subplan().initplan()) {
SubplanPlanidWalkerContext* context =
reinterpret_cast<SubplanPlanidWalkerContext*>(ctx);
context->planids.push_back(expr->subplan().planid());
}
}
};
std::vector<int32_t> SubplanUtil::getRelatedSubplanIds(
const UnivPlanPlanNodePoly& planNodePolyInput) {
SubplanPlanidWalkerContext ctx;
SubplanPlanidWalker walker;
walker.SubplanWalker::walk(
&(const_cast<UnivPlanPlanNodePoly&>(planNodePolyInput)), &walker, &ctx);
return ctx.planids;
}
class SubplanAttachWalkerContext : public PlanNodeWalkerContext {
public:
const UnivPlanPlan* rootPlan;
UnivPlanPlan* currStage;
};
class SubplanAttachWalker : public SubplanWalker {
public:
void walk(UnivPlanExprPoly* expr, PlanNodeWalkerContext* ctx) override {
if (expr->has_subplan() && !expr->subplan().initplan()) {
auto context = reinterpret_cast<SubplanAttachWalkerContext*>(ctx);
// count plan ID from 1
auto oldPlanId = expr->subplan().planid();
context->currStage->add_subplans()->CopyFrom(
context->rootPlan->subplans(oldPlanId - 1));
expr->mutable_subplan()->set_planid(context->currStage->subplans_size());
}
}
};
void SubplanUtil::linkSubplan(UnivPlanPlan* rootPlan, UnivPlanPlan* currStage) {
SubplanAttachWalker walker;
SubplanAttachWalkerContext ctx;
ctx.rootPlan = rootPlan;
ctx.currStage = currStage;
PlanNodeWalker::walkPlanTree(currStage->mutable_plan(), &walker, &ctx);
for (auto i = 0; i < currStage->childstages_size(); i++) {
linkSubplan(rootPlan, currStage->mutable_childstages(i));
}
}
} // namespace univplan