You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by ji...@apache.org on 2017/04/20 20:28:38 UTC
[3/5] incubator-quickstep git commit: Add common-subexpression support
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/query_optimizer/rules/ExtractCommonSubexpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/rules/ExtractCommonSubexpression.cpp b/query_optimizer/rules/ExtractCommonSubexpression.cpp
new file mode 100644
index 0000000..ad2aec1
--- /dev/null
+++ b/query_optimizer/rules/ExtractCommonSubexpression.cpp
@@ -0,0 +1,264 @@
+/**
+ * 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 "query_optimizer/rules/ExtractCommonSubexpression.hpp"
+
+#include <memory>
+#include <unordered_set>
+#include <vector>
+
+#include "query_optimizer/OptimizerContext.hpp"
+#include "query_optimizer/expressions/Alias.hpp"
+#include "query_optimizer/expressions/CommonSubexpression.hpp"
+#include "query_optimizer/expressions/ExpressionType.hpp"
+#include "query_optimizer/expressions/NamedExpression.hpp"
+#include "query_optimizer/expressions/PatternMatcher.hpp"
+#include "query_optimizer/expressions/Scalar.hpp"
+#include "query_optimizer/physical/Aggregate.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "query_optimizer/physical/PhysicalType.hpp"
+#include "query_optimizer/physical/Selection.hpp"
+#include "utility/HashError.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace optimizer {
+
+namespace E = ::quickstep::optimizer::expressions;
+namespace P = ::quickstep::optimizer::physical;
+
+ExtractCommonSubexpression::ExtractCommonSubexpression(
+ OptimizerContext *optimizer_context)
+ : optimizer_context_(optimizer_context) {
+ const std::vector<E::ExpressionType> whitelist = {
+ E::ExpressionType::kAlias,
+ E::ExpressionType::kAttributeReference,
+ E::ExpressionType::kAggregateFunction,
+ E::ExpressionType::kBinaryExpression,
+ E::ExpressionType::kCast,
+ E::ExpressionType::kCommonSubexpression,
+ E::ExpressionType::kScalarLiteral,
+ E::ExpressionType::kUnaryExpression
+ };
+
+ for (const auto &expr_type : whitelist) {
+ homogeneous_whitelist_.emplace(static_cast<int>(expr_type));
+ }
+}
+
+P::PhysicalPtr ExtractCommonSubexpression::apply(const P::PhysicalPtr &input) {
+ DCHECK(input->getPhysicalType() == P::PhysicalType::kTopLevelPlan);
+
+ return applyInternal(input);
+}
+
+P::PhysicalPtr ExtractCommonSubexpression::applyInternal(
+ const P::PhysicalPtr &input) {
+ std::vector<P::PhysicalPtr> new_children;
+ for (const auto &child : input->children()) {
+ new_children.emplace_back(applyInternal(child));
+ }
+
+ const P::PhysicalPtr node =
+ new_children == input->children()
+ ? input
+ : input->copyWithNewChildren(new_children);
+
+ switch (node->getPhysicalType()) {
+ case P::PhysicalType::kSelection: {
+ const P::SelectionPtr selection =
+ std::static_pointer_cast<const P::Selection>(node);
+
+ const std::vector<E::NamedExpressionPtr> new_expressions =
+ DownCast<E::NamedExpression>(
+ transformExpressions(UpCast(selection->project_expressions())));
+
+ if (new_expressions != selection->project_expressions()) {
+ return P::Selection::Create(selection->input(),
+ new_expressions,
+ selection->filter_predicate());
+ }
+ break;
+ }
+ case P::PhysicalType::kAggregate: {
+ const P::AggregatePtr aggregate =
+ std::static_pointer_cast<const P::Aggregate>(node);
+ std::vector<E::ExpressionPtr> expressions =
+ UpCast(aggregate->aggregate_expressions());
+ for (const auto &expr : aggregate->grouping_expressions()) {
+ expressions.emplace_back(expr);
+ }
+
+ const std::vector<E::ExpressionPtr> new_expressions =
+ transformExpressions(expressions);
+
+ if (new_expressions != expressions) {
+ std::vector<E::AliasPtr> new_aggregate_expressions;
+ std::vector<E::NamedExpressionPtr> new_grouping_expressions;
+ const std::size_t num_aggrs = aggregate->aggregate_expressions().size();
+
+ for (std::size_t i = 0; i < num_aggrs; ++i) {
+ DCHECK(E::SomeAlias::Matches(new_expressions[i]));
+ new_aggregate_expressions.emplace_back(
+ std::static_pointer_cast<const E::Alias>(new_expressions[i]));
+ }
+ for (std::size_t i = num_aggrs; i < new_expressions.size(); ++i) {
+ DCHECK(E::SomeNamedExpression::Matches(new_expressions[i]));
+ new_grouping_expressions.emplace_back(
+ std::static_pointer_cast<const E::NamedExpression>(new_expressions[i]));
+ }
+ return P::Aggregate::Create(aggregate->input(),
+ new_grouping_expressions,
+ new_aggregate_expressions,
+ aggregate->filter_predicate());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return node;
+}
+
+std::vector<E::ExpressionPtr> ExtractCommonSubexpression::transformExpressions(
+ const std::vector<E::ExpressionPtr> &expressions) {
+ ScalarCounter counter;
+ ScalarHashable hashable;
+ for (const auto &expr : expressions) {
+ visitAndCount(expr, &counter, &hashable);
+ }
+
+ ScalarMap substitution_map;
+ std::vector<E::ExpressionPtr> new_expressions;
+ for (const auto &expr : expressions) {
+ new_expressions.emplace_back(
+ visitAndTransform(expr, 1, counter, hashable, &substitution_map));
+ }
+ return new_expressions;
+}
+
+E::ExpressionPtr ExtractCommonSubexpression::transformExpression(
+ const E::ExpressionPtr &expression) {
+ return transformExpressions({expression}).front();
+}
+
+bool ExtractCommonSubexpression::visitAndCount(
+ const E::ExpressionPtr &expression,
+ ScalarCounter *counter,
+ ScalarHashable *hashable) {
+ bool children_hashable = true;
+
+ const auto homogeneous_whitelist_it =
+ homogeneous_whitelist_.find(static_cast<int>(expression->getExpressionType()));
+ if (homogeneous_whitelist_it != homogeneous_whitelist_.end()) {
+ for (const auto &child : expression->children()) {
+ children_hashable &= visitAndCount(child, counter, hashable);
+ }
+ }
+
+ E::ScalarPtr scalar;
+ if (children_hashable &&
+ E::SomeScalar::MatchesWithConditionalCast(expression, &scalar)) {
+ try {
+ ++(*counter)[scalar];
+ } catch (const HashNotSupported &e) {
+ return false;
+ }
+ hashable->emplace(scalar);
+ return true;
+ }
+ return false;
+}
+
+E::ExpressionPtr ExtractCommonSubexpression::visitAndTransform(
+ const E::ExpressionPtr &expression,
+ const std::size_t max_reference_count,
+ const ScalarCounter &counter,
+ const ScalarHashable &hashable,
+ ScalarMap *substitution_map) {
+ // TODO: figure out whether it is beneficial.
+ if (expression->getExpressionType() == E::ExpressionType::kScalarLiteral ||
+ expression->getExpressionType() == E::ExpressionType::kAttributeReference) {
+ return expression;
+ }
+
+ E::ScalarPtr scalar;
+ const bool is_hashable =
+ E::SomeScalar::MatchesWithConditionalCast(expression, &scalar)
+ && hashable.find(scalar) != hashable.end();
+
+ std::size_t new_max_reference_count;
+ if (is_hashable) {
+ // CommonSubexpression node already generated.
+ const auto substitution_map_it = substitution_map->find(scalar);
+ if (substitution_map_it != substitution_map->end()) {
+ return substitution_map_it->second;
+ }
+
+ const auto counter_it = counter.find(scalar);
+ DCHECK(counter_it != counter.end());
+ DCHECK_LE(max_reference_count, counter_it->second);
+ new_max_reference_count = counter_it->second;
+ } else {
+ new_max_reference_count = max_reference_count;
+ }
+
+ std::vector<E::ExpressionPtr> new_children;
+ const auto homogeneous_whitelist_it =
+ homogeneous_whitelist_.find(static_cast<int>(expression->getExpressionType()));
+ if (homogeneous_whitelist_it == homogeneous_whitelist_.end()) {
+ for (const auto &child : expression->children()) {
+ new_children.emplace_back(transformExpression(child));
+ }
+ } else {
+ for (const auto &child : expression->children()) {
+ new_children.emplace_back(
+ visitAndTransform(child,
+ new_max_reference_count,
+ counter,
+ hashable,
+ substitution_map));
+ }
+ }
+
+ E::ExpressionPtr output;
+ if (new_children == expression->children()) {
+ output = expression;
+ } else {
+ output = std::static_pointer_cast<const E::Scalar>(
+ expression->copyWithNewChildren(new_children));
+ }
+
+ if (is_hashable && new_max_reference_count > max_reference_count) {
+ DCHECK(E::SomeScalar::Matches(output));
+ const E::CommonSubexpressionPtr common_subexpression =
+ E::CommonSubexpression::Create(
+ optimizer_context_->nextExprId(),
+ std::static_pointer_cast<const E::Scalar>(output));
+ substitution_map->emplace(scalar, common_subexpression);
+ output = common_subexpression;
+ }
+
+ return output;
+}
+
+} // namespace optimizer
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/query_optimizer/rules/ExtractCommonSubexpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/rules/ExtractCommonSubexpression.hpp b/query_optimizer/rules/ExtractCommonSubexpression.hpp
new file mode 100644
index 0000000..0b63b7e
--- /dev/null
+++ b/query_optimizer/rules/ExtractCommonSubexpression.hpp
@@ -0,0 +1,135 @@
+/**
+ * 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.
+ **/
+
+#ifndef QUICKSTEP_QUERY_OPTIMIZER_RULES_EXTRACT_COMMON_SUBEXPRESSION_HPP_
+#define QUICKSTEP_QUERY_OPTIMIZER_RULES_EXTRACT_COMMON_SUBEXPRESSION_HPP_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "query_optimizer/expressions/CommonSubexpression.hpp"
+#include "query_optimizer/expressions/Expression.hpp"
+#include "query_optimizer/expressions/Scalar.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "query_optimizer/rules/Rule.hpp"
+#include "utility/Macros.hpp"
+
+namespace quickstep {
+namespace optimizer {
+
+class OptimizerContext;
+
+/** \addtogroup OptimizerRules
+ * @{
+ */
+
+class ExtractCommonSubexpression : public Rule<physical::Physical> {
+ public:
+ /**
+ * @brief Constructor.
+ */
+ ExtractCommonSubexpression(OptimizerContext *optimizer_context);
+
+ ~ExtractCommonSubexpression() override {}
+
+ std::string getName() const override {
+ return "ExtractCommonSubexpression";
+ }
+
+ physical::PhysicalPtr apply(const physical::PhysicalPtr &input) override;
+
+ private:
+ physical::PhysicalPtr applyInternal(const physical::PhysicalPtr &input);
+
+ struct ScalarHash {
+ inline std::size_t operator()(const expressions::ScalarPtr &scalar) const {
+ return scalar->hash();
+ }
+ };
+
+ struct ScalarEqual {
+ inline bool operator()(const expressions::ScalarPtr &lhs,
+ const expressions::ScalarPtr &rhs) const {
+ return lhs->equals(rhs);
+ }
+ };
+
+ using ScalarCounter =
+ std::unordered_map<expressions::ScalarPtr, std::size_t, ScalarHash, ScalarEqual>;
+
+ using ScalarMap =
+ std::unordered_map<expressions::ScalarPtr,
+ expressions::CommonSubexpressionPtr,
+ ScalarHash,
+ ScalarEqual>;
+
+ using ScalarHashable = std::unordered_set<expressions::ScalarPtr>;
+
+ std::vector<expressions::ExpressionPtr> transformExpressions(
+ const std::vector<expressions::ExpressionPtr> &expressions);
+
+ expressions::ExpressionPtr transformExpression(
+ const expressions::ExpressionPtr &expression);
+
+ bool visitAndCount(
+ const expressions::ExpressionPtr &expression,
+ ScalarCounter *counter,
+ ScalarHashable *hashable);
+
+ expressions::ExpressionPtr visitAndTransform(
+ const expressions::ExpressionPtr &expression,
+ const std::size_t max_reference_count,
+ const ScalarCounter &counter,
+ const ScalarHashable &hashable,
+ ScalarMap *substitution_map);
+
+ template <typename ScalarSubclassT>
+ static std::vector<expressions::ExpressionPtr> UpCast(
+ const std::vector<std::shared_ptr<const ScalarSubclassT>> &expressions) {
+ std::vector<expressions::ExpressionPtr> output;
+ for (const auto &expr : expressions) {
+ output.emplace_back(expr);
+ }
+ return output;
+ }
+
+ template <typename ScalarSubclassT>
+ static std::vector<std::shared_ptr<const ScalarSubclassT>> DownCast(
+ const std::vector<expressions::ExpressionPtr> &expressions) {
+ std::vector<std::shared_ptr<const ScalarSubclassT>> output;
+ for (const auto &expr : expressions) {
+ output.emplace_back(std::static_pointer_cast<const ScalarSubclassT>(expr));
+ }
+ return output;
+ }
+
+ OptimizerContext *optimizer_context_;
+ std::unordered_set<int> homogeneous_whitelist_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtractCommonSubexpression);
+};
+
+/** @} */
+
+} // namespace optimizer
+} // namespace quickstep
+
+#endif // QUICKSTEP_QUERY_OPTIMIZER_RULES_EXTRACT_COMMON_SUBEXPRESSION_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/query_optimizer/rules/ReuseAggregateExpressions.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/rules/ReuseAggregateExpressions.cpp b/query_optimizer/rules/ReuseAggregateExpressions.cpp
new file mode 100644
index 0000000..7151fdf
--- /dev/null
+++ b/query_optimizer/rules/ReuseAggregateExpressions.cpp
@@ -0,0 +1,276 @@
+/**
+ * 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 "query_optimizer/rules/ReuseAggregateExpressions.hpp"
+
+#include <cstddef>
+#include <list>
+#include <map>
+#include <unordered_map>
+#include <vector>
+
+#include "expressions/aggregation/AggregateFunction.hpp"
+#include "expressions/aggregation/AggregateFunctionFactory.hpp"
+#include "expressions/aggregation/AggregationID.hpp"
+#include "query_optimizer/OptimizerContext.hpp"
+#include "query_optimizer/expressions/AggregateFunction.hpp"
+#include "query_optimizer/expressions/Alias.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/expressions/BinaryExpression.hpp"
+#include "query_optimizer/expressions/ExpressionType.hpp"
+#include "query_optimizer/expressions/ExpressionUtil.hpp"
+#include "query_optimizer/expressions/NamedExpression.hpp"
+#include "query_optimizer/expressions/Scalar.hpp"
+#include "query_optimizer/physical/Aggregate.hpp"
+#include "query_optimizer/physical/PatternMatcher.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "query_optimizer/physical/PhysicalType.hpp"
+#include "query_optimizer/physical/Selection.hpp"
+#include "query_optimizer/physical/TopLevelPlan.hpp"
+#include "types/operations/binary_operations/BinaryOperation.hpp"
+#include "types/operations/binary_operations/BinaryOperationFactory.hpp"
+#include "types/operations/binary_operations/BinaryOperationID.hpp"
+#include "utility/EqualsAnyConstant.hpp"
+#include "utility/HashError.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace optimizer {
+
+namespace E = ::quickstep::optimizer::expressions;
+namespace P = ::quickstep::optimizer::physical;
+
+void ReuseAggregateExpressions::init(const P::PhysicalPtr &input) {
+ DCHECK(input->getPhysicalType() == P::PhysicalType::kTopLevelPlan);
+
+ const P::TopLevelPlanPtr top_level_plan =
+ std::static_pointer_cast<const P::TopLevelPlan>(input);
+ cost_model_.reset(
+ new cost::StarSchemaSimpleCostModel(top_level_plan->shared_subplans()));
+}
+
+P::PhysicalPtr ReuseAggregateExpressions::applyToNode(
+ const P::PhysicalPtr &input) {
+ P::AggregatePtr aggregate;
+ if (!P::SomeAggregate::MatchesWithConditionalCast(input, &aggregate)) {
+ return input;
+ }
+
+ const std::vector<E::AliasPtr> &agg_exprs = aggregate->aggregate_expressions();
+
+ std::unordered_map<E::ScalarPtr,
+ std::map<AggregationID, std::vector<std::size_t>>,
+ ScalarHash, ScalarEqual> agg_expr_info;
+
+ std::list<std::size_t> count_star_info;
+
+ for (std::size_t i = 0; i < agg_exprs.size(); ++i) {
+ DCHECK(agg_exprs[i]->expression()->getExpressionType()
+ == E::ExpressionType::kAggregateFunction);
+ const E::AggregateFunctionPtr agg_expr =
+ std::static_pointer_cast<const E::AggregateFunction>(
+ agg_exprs[i]->expression());
+
+ // Skip DISTINCT aggregations.
+ if (agg_expr->is_distinct()) {
+ continue;
+ }
+
+ const AggregationID agg_id = agg_expr->getAggregate().getAggregationID();
+ const std::vector<E::ScalarPtr> &arguments = agg_expr->getArguments();
+
+ // Currently we only consider aggregate functions with 0 or 1 argument.
+ if (agg_id == AggregationID::kCount) {
+ if (arguments.empty()) {
+ count_star_info.emplace_front(i);
+ continue;
+ } else if (!arguments.front()->getValueType().isNullable()) {
+ count_star_info.emplace_back(i);
+ continue;
+ }
+ }
+ if (arguments.size() == 1) {
+ try {
+ agg_expr_info[arguments.front()][agg_id].emplace_back(i);
+ } catch (const HashNotSupported &e) {
+ continue;
+ }
+ }
+ }
+
+ std::vector<std::unique_ptr<AggregateReference>> agg_refs(agg_exprs.size());
+
+ constexpr std::size_t kInvalidRef = static_cast<std::size_t>(-1);
+ std::size_t count_star_ref;
+
+ if (count_star_info.empty()) {
+ count_star_ref = kInvalidRef;
+ } else {
+ auto it = count_star_info.begin();
+ count_star_ref = *it;
+
+ for (++it; it != count_star_info.end(); ++it) {
+ agg_refs[*it].reset(new AggregateReference(count_star_ref));
+ }
+ }
+
+ for (const auto &it : agg_expr_info) {
+ const auto &ref_map = it.second;
+
+ // First, check whether AVG can be reduced to SUM/COUNT.
+ bool is_avg_processed = false;
+
+ const auto avg_it = ref_map.find(AggregationID::kAvg);
+ if (avg_it != ref_map.end()) {
+ std::size_t count_ref = kInvalidRef;
+
+ if (it.first->getValueType().isNullable()) {
+ const auto count_it = ref_map.find(AggregationID::kCount);
+ if (count_it != ref_map.end()) {
+ DCHECK(!count_it->second.empty());
+ count_ref = count_it->second.front();
+ }
+ } else {
+ count_ref = count_star_ref;
+ }
+
+ if (count_ref != kInvalidRef) {
+ const auto sum_it = ref_map.find(AggregationID::kSum);
+ const std::size_t sum_ref =
+ sum_it == ref_map.end() ? kInvalidRef : sum_it->second.front();
+
+ for (const std::size_t idx : avg_it->second) {
+ agg_refs[idx].reset(new AggregateReference(sum_ref, count_ref));
+ }
+ is_avg_processed = true;
+ }
+ }
+
+ // Then, eliminate duplicate aggregate expressions.
+ for (const auto &ref_it : ref_map) {
+ if (ref_it.first == AggregationID::kAvg && is_avg_processed) {
+ continue;
+ }
+
+ const auto &indices = ref_it.second;
+ DCHECK(!indices.empty());
+ const std::size_t ref = indices.front();
+ for (std::size_t i = 1; i < indices.size(); ++i) {
+ agg_refs[indices[i]].reset(new AggregateReference(ref));
+ }
+ }
+ }
+
+ bool need_transform = false;
+ for (const auto &agg_ref : agg_refs) {
+ if (agg_ref != nullptr) {
+ need_transform = true;
+ break;
+ }
+ }
+
+ if (!need_transform) {
+ return input;
+ }
+
+ const std::vector<E::AttributeReferencePtr> agg_attrs = E::ToRefVector(agg_exprs);
+
+ std::vector<E::AliasPtr> new_agg_exprs;
+ std::vector<E::NamedExpressionPtr> new_select_exprs;
+
+ for (const auto &grouping_expr : aggregate->grouping_expressions()) {
+ new_select_exprs.emplace_back(E::ToRef(grouping_expr));
+ }
+
+ for (std::size_t i = 0; i < agg_refs.size(); ++i) {
+ const auto &agg_ref = agg_refs[i];
+ const E::AliasPtr &agg_expr = agg_exprs[i];
+
+ if (agg_ref == nullptr) {
+ new_agg_exprs.emplace_back(agg_expr);
+ new_select_exprs.emplace_back(
+ E::AttributeReference::Create(agg_expr->id(),
+ agg_expr->attribute_name(),
+ agg_expr->attribute_alias(),
+ agg_expr->relation_name(),
+ agg_expr->getValueType(),
+ E::AttributeReferenceScope::kLocal));
+ } else {
+ switch (agg_ref->kind) {
+ case AggregateReference::kDirect: {
+ new_select_exprs.emplace_back(
+ E::Alias::Create(agg_expr->id(),
+ agg_attrs[agg_ref->first_ref],
+ agg_expr->attribute_name(),
+ agg_expr->attribute_alias()));
+ break;
+ }
+ case AggregateReference::kAvg: {
+ E::AttributeReferencePtr sum_attr;
+ if (agg_ref->first_ref == kInvalidRef) {
+ const E::AggregateFunctionPtr avg_expr =
+ std::static_pointer_cast<const E::AggregateFunction>(agg_expr->expression());
+
+ const AggregateFunction &sum_func =
+ AggregateFunctionFactory::Get(AggregationID::kSum);
+ const E::AggregateFunctionPtr sum_expr =
+ E::AggregateFunction::Create(sum_func,
+ avg_expr->getArguments(),
+ avg_expr->is_vector_aggregate(),
+ avg_expr->is_distinct());
+ new_agg_exprs.emplace_back(
+ E::Alias::Create(optimizer_context_->nextExprId(),
+ sum_expr,
+ agg_expr->attribute_name(),
+ agg_expr->attribute_alias()));
+
+ sum_attr = E::ToRef(new_agg_exprs.back());
+ } else {
+ sum_attr = agg_attrs[agg_ref->first_ref];
+ }
+
+ const BinaryOperation ÷_op =
+ BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kDivide);
+ const E::BinaryExpressionPtr avg_expr =
+ E::BinaryExpression::Create(divide_op,
+ sum_attr,
+ agg_attrs[agg_ref->second_ref]);
+ new_select_exprs.emplace_back(
+ E::Alias::Create(agg_expr->id(),
+ avg_expr,
+ agg_expr->attribute_name(),
+ agg_expr->attribute_alias()));
+ }
+ }
+ }
+ }
+
+ const P::AggregatePtr new_aggregate =
+ P::Aggregate::Create(aggregate->input(),
+ aggregate->grouping_expressions(),
+ new_agg_exprs,
+ aggregate->filter_predicate());
+
+ return P::Selection::Create(new_aggregate, new_select_exprs, nullptr);
+}
+
+
+} // namespace optimizer
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/query_optimizer/rules/ReuseAggregateExpressions.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/rules/ReuseAggregateExpressions.hpp b/query_optimizer/rules/ReuseAggregateExpressions.hpp
new file mode 100644
index 0000000..5b78e46
--- /dev/null
+++ b/query_optimizer/rules/ReuseAggregateExpressions.hpp
@@ -0,0 +1,98 @@
+/**
+ * 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.
+ **/
+
+#ifndef QUICKSTEP_QUERY_OPTIMIZER_RULES_REUSE_AGGREGATE_EXPRESSIONS_HPP_
+#define QUICKSTEP_QUERY_OPTIMIZER_RULES_REUSE_AGGREGATE_EXPRESSIONS_HPP_
+
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp"
+#include "query_optimizer/expressions/Scalar.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "query_optimizer/rules/BottomUpRule.hpp"
+#include "utility/Macros.hpp"
+
+namespace quickstep {
+namespace optimizer {
+
+class OptimizerContext;
+
+/** \addtogroup OptimizerRules
+ * @{
+ */
+
+class ReuseAggregateExpressions : public BottomUpRule<physical::Physical> {
+ public:
+ ReuseAggregateExpressions(OptimizerContext *optimizer_context)
+ : optimizer_context_(optimizer_context) {}
+
+ std::string getName() const override {
+ return "ReuseAggregateExpressions";
+ }
+
+ protected:
+ void init(const physical::PhysicalPtr &input) override;
+
+ physical::PhysicalPtr applyToNode(const physical::PhysicalPtr &input) override;
+
+ private:
+ struct ScalarHash {
+ inline std::size_t operator()(const expressions::ScalarPtr &scalar) const {
+ return scalar->hash();
+ }
+ };
+
+ struct ScalarEqual {
+ inline bool operator()(const expressions::ScalarPtr &lhs,
+ const expressions::ScalarPtr &rhs) const {
+ return lhs->equals(rhs);
+ }
+ };
+
+ struct AggregateReference {
+ enum Kind {
+ kDirect = 0,
+ kAvg
+ };
+
+ AggregateReference(const std::size_t ref)
+ : kind(kDirect), first_ref(ref), second_ref(0) {}
+
+ AggregateReference(const std::size_t sum_ref, const std::size_t count_ref)
+ : kind(kAvg), first_ref(sum_ref), second_ref(count_ref) {}
+
+ const Kind kind;
+ const std::size_t first_ref;
+ const std::size_t second_ref;
+ };
+
+ OptimizerContext *optimizer_context_;
+
+ std::unique_ptr<cost::StarSchemaSimpleCostModel> cost_model_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReuseAggregateExpressions);
+};
+
+} // namespace optimizer
+} // namespace quickstep
+
+#endif // QUICKSTEP_QUERY_OPTIMIZER_RULES_REUSE_AGGREGATE_EXPRESSIONS_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/relational_operators/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/relational_operators/CMakeLists.txt b/relational_operators/CMakeLists.txt
index 4ea809b..b93ec49 100644
--- a/relational_operators/CMakeLists.txt
+++ b/relational_operators/CMakeLists.txt
@@ -262,6 +262,7 @@ target_link_libraries(quickstep_relationaloperators_HashJoinOperator
quickstep_expressions_predicate_Predicate
quickstep_expressions_scalar_Scalar
quickstep_expressions_scalar_ScalarAttribute
+ quickstep_expressions_scalar_ScalarCache
quickstep_queryexecution_QueryContext
quickstep_queryexecution_WorkOrderProtosContainer
quickstep_queryexecution_WorkOrdersContainer
@@ -318,6 +319,7 @@ target_link_libraries(quickstep_relationaloperators_NestedLoopsJoinOperator
quickstep_catalog_CatalogTypedefs
quickstep_expressions_predicate_Predicate
quickstep_expressions_scalar_Scalar
+ quickstep_expressions_scalar_ScalarCache
quickstep_queryexecution_QueryContext
quickstep_queryexecution_WorkOrderProtosContainer
quickstep_queryexecution_WorkOrdersContainer
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/relational_operators/HashJoinOperator.cpp
----------------------------------------------------------------------
diff --git a/relational_operators/HashJoinOperator.cpp b/relational_operators/HashJoinOperator.cpp
index 0e75411..cd376c1 100644
--- a/relational_operators/HashJoinOperator.cpp
+++ b/relational_operators/HashJoinOperator.cpp
@@ -32,6 +32,7 @@
#include "expressions/predicate/Predicate.hpp"
#include "expressions/scalar/Scalar.hpp"
#include "expressions/scalar/ScalarAttribute.hpp"
+#include "expressions/scalar/ScalarCache.hpp"
#include "query_execution/QueryContext.hpp"
#include "query_execution/WorkOrderProtosContainer.hpp"
#include "query_execution/WorkOrdersContainer.hpp"
@@ -532,6 +533,7 @@ void HashInnerJoinWorkOrder::executeWithoutCopyElision(ValueAccessor *probe_acce
}
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (auto selection_cit = selection_.begin();
selection_cit != selection_.end();
++selection_cit) {
@@ -539,8 +541,10 @@ void HashInnerJoinWorkOrder::executeWithoutCopyElision(ValueAccessor *probe_acce
build_accessor.get(),
probe_relation_id,
probe_accessor,
- build_block_entry.second));
+ build_block_entry.second,
+ scalar_cache.get()));
}
+ scalar_cache.reset();
output_destination_->bulkInsertTuples(&temp_result);
}
@@ -649,12 +653,14 @@ void HashInnerJoinWorkOrder::executeWithCopyElision(ValueAccessor *probe_accesso
zipped_joined_tuple_ids.emplace_back(build_tids[i], probe_tids[i]);
}
+ ScalarCache scalar_cache;
for (const Scalar *scalar : non_trivial_expressions) {
temp_result.addColumn(scalar->getAllValuesForJoin(build_relation_id,
build_accessor.get(),
probe_relation_id,
probe_accessor,
- zipped_joined_tuple_ids));
+ zipped_joined_tuple_ids,
+ &scalar_cache));
}
}
@@ -765,13 +771,16 @@ void HashSemiJoinWorkOrder::executeWithResidualPredicate() {
std::unique_ptr<ValueAccessor> probe_accessor_with_filter(
probe_store.createValueAccessor(&filter));
+
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (vector<unique_ptr<const Scalar>>::const_iterator selection_it = selection_.begin();
selection_it != selection_.end();
++selection_it) {
temp_result.addColumn((*selection_it)->getAllValues(
- probe_accessor_with_filter.get(), &sub_blocks_ref));
+ probe_accessor_with_filter.get(), &sub_blocks_ref, scalar_cache.get()));
}
+ scalar_cache.reset();
output_destination_->bulkInsertTuples(&temp_result);
}
@@ -828,12 +837,15 @@ void HashSemiJoinWorkOrder::executeWithoutResidualPredicate() {
std::unique_ptr<ValueAccessor> probe_accessor_with_filter(
probe_accessor->createSharedTupleIdSequenceAdapterVirtual(*existence_map));
+
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (vector<unique_ptr<const Scalar>>::const_iterator selection_it = selection_.begin();
selection_it != selection_.end(); ++selection_it) {
temp_result.addColumn((*selection_it)->getAllValues(
- probe_accessor_with_filter.get(), &sub_blocks_ref));
+ probe_accessor_with_filter.get(), &sub_blocks_ref, scalar_cache.get()));
}
+ scalar_cache.reset();
output_destination_->bulkInsertTuples(&temp_result);
}
@@ -886,12 +898,15 @@ void HashAntiJoinWorkOrder::executeWithoutResidualPredicate() {
std::unique_ptr<ValueAccessor> probe_accessor_with_filter(
probe_accessor->createSharedTupleIdSequenceAdapterVirtual(*existence_map));
+
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (vector<unique_ptr<const Scalar>>::const_iterator selection_it = selection_.begin();
selection_it != selection_.end(); ++selection_it) {
temp_result.addColumn((*selection_it)->getAllValues(
- probe_accessor_with_filter.get(), &sub_blocks_ref));
+ probe_accessor_with_filter.get(), &sub_blocks_ref, scalar_cache.get()));
}
+ scalar_cache.reset();
output_destination_->bulkInsertTuples(&temp_result);
}
@@ -976,14 +991,18 @@ void HashAntiJoinWorkOrder::executeWithResidualPredicate() {
std::unique_ptr<ValueAccessor> probe_accessor_with_filter(
probe_accessor->createSharedTupleIdSequenceAdapterVirtual(*existence_map));
+
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (vector<unique_ptr<const Scalar>>::const_iterator selection_it = selection_.begin();
selection_it != selection_.end();
++selection_it) {
temp_result.addColumn(
(*selection_it)->getAllValues(probe_accessor_with_filter.get(),
- &sub_blocks_ref));
+ &sub_blocks_ref,
+ scalar_cache.get()));
}
+ scalar_cache.reset();
output_destination_->bulkInsertTuples(&temp_result);
}
@@ -1032,12 +1051,11 @@ void HashOuterJoinWorkOrder::execute() {
&build_block_entry : *collector.getJoinedTupleMap()) {
const BlockReference build_block =
storage_manager_->getBlock(build_block_entry.first, build_relation_);
- const TupleStorageSubBlock &build_store =
- build_block->getTupleStorageSubBlock();
+ const TupleStorageSubBlock &build_store = build_block->getTupleStorageSubBlock();
+ std::unique_ptr<ValueAccessor> build_accessor(build_store.createValueAccessor());
- std::unique_ptr<ValueAccessor> build_accessor(
- build_store.createValueAccessor());
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (auto selection_it = selection_.begin();
selection_it != selection_.end();
++selection_it) {
@@ -1047,8 +1065,11 @@ void HashOuterJoinWorkOrder::execute() {
build_accessor.get(),
probe_relation_id,
probe_accessor.get(),
- build_block_entry.second));
+ build_block_entry.second,
+ scalar_cache.get()));
}
+ scalar_cache.reset();
+
output_destination_->bulkInsertTuples(&temp_result);
}
@@ -1061,8 +1082,9 @@ void HashOuterJoinWorkOrder::execute() {
if (num_tuples_without_matches > 0) {
std::unique_ptr<ValueAccessor> probe_accessor_with_filter(
probe_accessor->createSharedTupleIdSequenceAdapterVirtual(*existence_map));
- ColumnVectorsValueAccessor temp_result;
+ ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (std::size_t i = 0; i < selection_.size(); ++i) {
if (is_selection_on_build_[i]) {
// NOTE(harshad, jianqiao): The assumption here is that any operation
@@ -1090,9 +1112,12 @@ void HashOuterJoinWorkOrder::execute() {
} else {
temp_result.addColumn(
selection_[i]->getAllValues(probe_accessor_with_filter.get(),
- &sub_blocks_ref));
+ &sub_blocks_ref,
+ scalar_cache.get()));
}
}
+ scalar_cache.reset();
+
output_destination_->bulkInsertTuples(&temp_result);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/relational_operators/NestedLoopsJoinOperator.cpp
----------------------------------------------------------------------
diff --git a/relational_operators/NestedLoopsJoinOperator.cpp b/relational_operators/NestedLoopsJoinOperator.cpp
index f17402f..a6bacc7 100644
--- a/relational_operators/NestedLoopsJoinOperator.cpp
+++ b/relational_operators/NestedLoopsJoinOperator.cpp
@@ -27,6 +27,7 @@
#include "catalog/CatalogRelationSchema.hpp"
#include "expressions/predicate/Predicate.hpp"
#include "expressions/scalar/Scalar.hpp"
+#include "expressions/scalar/ScalarCache.hpp"
#include "query_execution/QueryContext.hpp"
#include "query_execution/WorkOrderProtosContainer.hpp"
#include "query_execution/WorkOrdersContainer.hpp"
@@ -417,6 +418,7 @@ void NestedLoopsJoinWorkOrder::executeHelper(const TupleStorageSubBlock &left_st
// evaluation and data movement, but low enough that temporary memory
// requirements don't get out of hand).
ColumnVectorsValueAccessor temp_result;
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (vector<unique_ptr<const Scalar>>::const_iterator selection_cit = selection_.begin();
selection_cit != selection_.end();
++selection_cit) {
@@ -424,8 +426,10 @@ void NestedLoopsJoinWorkOrder::executeHelper(const TupleStorageSubBlock &left_st
left_accessor.get(),
right_input_relation_id,
right_accessor.get(),
- joined_tuple_ids));
+ joined_tuple_ids,
+ scalar_cache.get()));
}
+ scalar_cache.reset();
output_destination_->bulkInsertTuples(&temp_result);
}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/storage/AggregationOperationState.cpp
----------------------------------------------------------------------
diff --git a/storage/AggregationOperationState.cpp b/storage/AggregationOperationState.cpp
index 90543c4..facc7fa 100644
--- a/storage/AggregationOperationState.cpp
+++ b/storage/AggregationOperationState.cpp
@@ -38,6 +38,7 @@
#include "expressions/aggregation/AggregationHandle.hpp"
#include "expressions/predicate/Predicate.hpp"
#include "expressions/scalar/Scalar.hpp"
+#include "expressions/scalar/ScalarCache.hpp"
#include "storage/AggregationOperationState.pb.h"
#include "storage/CollisionFreeVectorTable.hpp"
#include "storage/HashTableFactory.hpp"
@@ -491,9 +492,10 @@ void AggregationOperationState::aggregateBlock(const block_id input_block,
SubBlocksReference sub_blocks_ref(tuple_store,
block->getIndices(),
block->getIndicesConsistent());
+ ScalarCache scalar_cache;
for (const auto &expression : non_trivial_expressions_) {
non_trivial_results->addColumn(
- expression->getAllValues(accessor, &sub_blocks_ref));
+ expression->getAllValues(accessor, &sub_blocks_ref, &scalar_cache));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/storage/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt
index cb1f098..0a1d484 100644
--- a/storage/CMakeLists.txt
+++ b/storage/CMakeLists.txt
@@ -276,6 +276,7 @@ target_link_libraries(quickstep_storage_AggregationOperationState
quickstep_expressions_aggregation_AggregationHandle
quickstep_expressions_predicate_Predicate
quickstep_expressions_scalar_Scalar
+ quickstep_expressions_scalar_ScalarCache
quickstep_storage_AggregationOperationState_proto
quickstep_storage_CollisionFreeVectorTable
quickstep_storage_HashTableBase
@@ -936,6 +937,7 @@ target_link_libraries(quickstep_storage_StorageBlock
quickstep_catalog_CatalogTypedefs
quickstep_expressions_predicate_Predicate
quickstep_expressions_scalar_Scalar
+ quickstep_expressions_scalar_ScalarCache
quickstep_storage_BasicColumnStoreTupleStorageSubBlock
quickstep_storage_BloomFilterIndexSubBlock
quickstep_storage_CSBTreeIndexSubBlock
@@ -1086,6 +1088,7 @@ target_link_libraries(quickstep_storage_WindowAggregationOperationState
quickstep_expressions_Expressions_proto
quickstep_expressions_scalar_Scalar
quickstep_expressions_scalar_ScalarAttribute
+ quickstep_expressions_scalar_ScalarCache
quickstep_expressions_windowaggregation_WindowAggregateFunction
quickstep_expressions_windowaggregation_WindowAggregateFunctionFactory
quickstep_expressions_windowaggregation_WindowAggregationHandle
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/storage/StorageBlock.cpp
----------------------------------------------------------------------
diff --git a/storage/StorageBlock.cpp b/storage/StorageBlock.cpp
index e91c1ac..d724317 100644
--- a/storage/StorageBlock.cpp
+++ b/storage/StorageBlock.cpp
@@ -30,6 +30,7 @@
#include "catalog/CatalogTypedefs.hpp"
#include "expressions/predicate/Predicate.hpp"
#include "expressions/scalar/Scalar.hpp"
+#include "expressions/scalar/ScalarCache.hpp"
#include "storage/BasicColumnStoreTupleStorageSubBlock.hpp"
#include "storage/BloomFilterIndexSubBlock.hpp"
#include "storage/CSBTreeIndexSubBlock.hpp"
@@ -369,15 +370,18 @@ void StorageBlock::select(const vector<unique_ptr<const Scalar>> &selection,
indices_,
indices_consistent_);
- std::unique_ptr<ValueAccessor> accessor(
- tuple_store_->createValueAccessor(filter));
+ std::unique_ptr<ValueAccessor> accessor(tuple_store_->createValueAccessor(filter));
+ ScalarCache scalar_cache;
for (vector<unique_ptr<const Scalar>>::const_iterator selection_cit = selection.begin();
selection_cit != selection.end();
++selection_cit) {
// TODO(chasseur): Can probably elide some copies for parts of the
// selection that are ScalarAttribute or ScalarLiteral.
- temp_result.addColumn((*selection_cit)->getAllValues(accessor.get(), &sub_blocks_ref));
+ temp_result.addColumn(
+ (*selection_cit)->getAllValues(accessor.get(),
+ &sub_blocks_ref,
+ &scalar_cache));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/storage/WindowAggregationOperationState.cpp
----------------------------------------------------------------------
diff --git a/storage/WindowAggregationOperationState.cpp b/storage/WindowAggregationOperationState.cpp
index 58bdf18..2c571ef 100644
--- a/storage/WindowAggregationOperationState.cpp
+++ b/storage/WindowAggregationOperationState.cpp
@@ -33,6 +33,7 @@
#include "expressions/Expressions.pb.h"
#include "expressions/scalar/Scalar.hpp"
#include "expressions/scalar/ScalarAttribute.hpp"
+#include "expressions/scalar/ScalarCache.hpp"
#include "expressions/window_aggregation/WindowAggregateFunction.hpp"
#include "expressions/window_aggregation/WindowAggregateFunctionFactory.hpp"
#include "expressions/window_aggregation/WindowAggregationHandle.hpp"
@@ -236,11 +237,16 @@ void WindowAggregationOperationState::windowAggregateBlocks(
argument_accessor = new ColumnVectorsValueAccessor();
}
+ std::unique_ptr<ScalarCache> scalar_cache = std::make_unique<ScalarCache>();
for (const std::unique_ptr<const Scalar> &argument : arguments_) {
argument_accessor->addColumn(argument->getAllValues(tuple_accessor,
- &sub_block_ref));
+ &sub_block_ref,
+ scalar_cache.get()));
}
+ // Release common subexpression cache as early as possible.
+ scalar_cache.reset();
+
InvokeOnAnyValueAccessor(tuple_accessor,
[&] (auto *tuple_accessor) -> void { // NOLINT(build/c++11)
tuple_accessor->beginIteration();
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/types/containers/ColumnVector.hpp
----------------------------------------------------------------------
diff --git a/types/containers/ColumnVector.hpp b/types/containers/ColumnVector.hpp
index fc65656..430a844 100644
--- a/types/containers/ColumnVector.hpp
+++ b/types/containers/ColumnVector.hpp
@@ -43,6 +43,9 @@ namespace quickstep {
// TODO(chasseur): Look into ways to allocate ColumnVector memory from the
// StorageManager.
+class ColumnVector;
+typedef std::shared_ptr<const ColumnVector> ColumnVectorPtr;
+
/**
* @brief A vector of values of the same type. Two implementations exist:
* NativeColumnVector (an array of fixed-size data elements) and
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/types/containers/ColumnVectorsValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/types/containers/ColumnVectorsValueAccessor.hpp b/types/containers/ColumnVectorsValueAccessor.hpp
index 6dc1124..d9cf49d 100644
--- a/types/containers/ColumnVectorsValueAccessor.hpp
+++ b/types/containers/ColumnVectorsValueAccessor.hpp
@@ -74,22 +74,23 @@ class ColumnVectorsValueAccessor : public ValueAccessor {
* this value-accessor is responsible for freeing this column
* vector.
**/
- void addColumn(ColumnVector *column, const bool owns = true) {
+ void addColumn(ColumnVectorPtr column) {
// If this is not the first column to be added, make sure it is the same
// length as the others.
DCHECK(columns_.empty()
|| (column->isNative()
- ? (static_cast<const NativeColumnVector*>(column)->size() == column_length_)
- : (static_cast<const IndirectColumnVector*>(column)->size() == column_length_)));
+ ? (static_cast<const NativeColumnVector*>(column.get())->size() == column_length_)
+ : (static_cast<const IndirectColumnVector*>(column.get())->size() == column_length_)));
columns_.push_back(column);
column_native_.push_back(column->isNative());
- if (owns) {
- deleter_.addObject(column);
- }
- column_length_
- = column->isNative()
- ? static_cast<const NativeColumnVector*>(column)->size()
- : static_cast<const IndirectColumnVector*>(column)->size();
+ column_length_ =
+ column->isNative()
+ ? static_cast<const NativeColumnVector*>(column.get())->size()
+ : static_cast<const IndirectColumnVector*>(column.get())->size();
+ }
+
+ void addColumn(ColumnVector *column) {
+ addColumn(ColumnVectorPtr(column));
}
inline void beginIteration() {
@@ -309,11 +310,10 @@ class ColumnVectorsValueAccessor : public ValueAccessor {
&& (static_cast<std::vector<ColumnVector*>::size_type>(attr_id) < columns_.size());
}
- std::vector<ColumnVector*> columns_;
+ std::vector<ColumnVectorPtr> columns_;
std::vector<bool> column_native_;
std::size_t column_length_;
std::size_t current_position_;
- ScopedDeleter deleter_;
DISALLOW_COPY_AND_ASSIGN(ColumnVectorsValueAccessor);
};
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/types/operations/binary_operations/AddBinaryOperation.hpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/AddBinaryOperation.hpp b/types/operations/binary_operations/AddBinaryOperation.hpp
index bc862bf..2309563 100644
--- a/types/operations/binary_operations/AddBinaryOperation.hpp
+++ b/types/operations/binary_operations/AddBinaryOperation.hpp
@@ -51,6 +51,10 @@ class AddBinaryOperation : public ArithmeticBinaryOperation {
return instance;
}
+ bool isCommutative() const override {
+ return true;
+ }
+
bool canApplyToTypes(const Type &left,
const Type &right) const override;
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/types/operations/binary_operations/BinaryOperation.hpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/BinaryOperation.hpp b/types/operations/binary_operations/BinaryOperation.hpp
index 585a1c6..c4841e3 100644
--- a/types/operations/binary_operations/BinaryOperation.hpp
+++ b/types/operations/binary_operations/BinaryOperation.hpp
@@ -334,6 +334,10 @@ class BinaryOperation : public Operation {
return kBinaryOperationShortNames[static_cast<std::size_t>(operation_id_)];
}
+ virtual bool isCommutative() const {
+ return false;
+ }
+
/**
* @brief Determine whether this BinaryOperation can apply to the specified
* Types.
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/types/operations/binary_operations/MultiplyBinaryOperation.hpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/MultiplyBinaryOperation.hpp b/types/operations/binary_operations/MultiplyBinaryOperation.hpp
index 6edc999..cc005e2 100644
--- a/types/operations/binary_operations/MultiplyBinaryOperation.hpp
+++ b/types/operations/binary_operations/MultiplyBinaryOperation.hpp
@@ -51,6 +51,10 @@ class MultiplyBinaryOperation : public ArithmeticBinaryOperation {
return instance;
}
+ bool isCommutative() const override {
+ return true;
+ }
+
bool canApplyToTypes(const Type &left,
const Type &right) const override;
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/utility/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/utility/CMakeLists.txt b/utility/CMakeLists.txt
index ca04462..ea9ee43 100644
--- a/utility/CMakeLists.txt
+++ b/utility/CMakeLists.txt
@@ -182,6 +182,7 @@ add_library(quickstep_utility_ExecutionDAGVisualizer
ExecutionDAGVisualizer.cpp
ExecutionDAGVisualizer.hpp)
add_library(quickstep_utility_Glob Glob.cpp Glob.hpp)
+add_library(quickstep_utility_HashError ../empty_src.cpp HashError.hpp)
add_library(quickstep_utility_HashPair ../empty_src.cpp HashPair.hpp)
add_library(quickstep_utility_Macros ../empty_src.cpp Macros.hpp)
add_library(quickstep_utility_MemStream ../empty_src.cpp MemStream.hpp)
@@ -350,6 +351,7 @@ target_link_libraries(quickstep_utility
quickstep_utility_EqualsAnyConstant
quickstep_utility_ExecutionDAGVisualizer
quickstep_utility_Glob
+ quickstep_utility_HashError
quickstep_utility_HashPair
quickstep_utility_Macros
quickstep_utility_MemStream
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/25506231/utility/HashError.hpp
----------------------------------------------------------------------
diff --git a/utility/HashError.hpp b/utility/HashError.hpp
new file mode 100644
index 0000000..3a59979
--- /dev/null
+++ b/utility/HashError.hpp
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ **/
+
+#ifndef QUICKSTEP_UTILITY_HASH_ERROR_HPP_
+#define QUICKSTEP_UTILITY_HASH_ERROR_HPP_
+
+#include <exception>
+
+namespace quickstep {
+
+/** \addtogroup Utility
+ * @{
+ */
+
+class HashNotSupported : public std::exception {
+ public:
+ /**
+ * @brief Constructor.
+ *
+ * @param message The error message.
+ **/
+ HashNotSupported(const std::string &message)
+ : message_(message) {}
+
+ ~HashNotSupported() throw() {}
+
+ virtual const char* what() const throw() {
+ return message_.c_str();
+ }
+
+ private:
+ const std::string message_;
+};
+
+/** @} */
+
+} // namespace quickstep
+
+#endif // QUICKSTEP_UTILITY_HASH_ERROR_HPP_