Fixed the union-all elimiation bug regarding non-attribute project expression.
diff --git a/cli/tests/command_executor/Analyze.test b/cli/tests/command_executor/Analyze.test
index ff20d9e..c391848 100644
--- a/cli/tests/command_executor/Analyze.test
+++ b/cli/tests/command_executor/Analyze.test
@@ -36,6 +36,7 @@
+--------------------+
==
+# EliminateEmptyNode applies after having the exact stats.
\analyze
--
Analyzing r ... done
@@ -43,6 +44,7 @@
Analyzing t ... done
==
+# Aggregate on an empty table.
SELECT COUNT(*) FROM r;
--
+--------------------+
@@ -52,6 +54,7 @@
+--------------------+
==
+# Aggregate on an empty table.
SELECT MIN(src) FROM r;
--
+-----------+
@@ -61,6 +64,7 @@
+-----------+
==
+# InsertSelection on an empty table.
INSERT INTO r SELECT * FROM s;
SELECT r.src, r.dst FROM r;
DELETE FROM r;
@@ -73,6 +77,12 @@
+-----------+-----------+
==
+# Compute the exact stats for r after updates.
+\analyze r
+--
+Analyzing r ... done
+==
+
# One side of InnerJoin is empty.
SELECT r.src, r.dst
FROM r, t
@@ -136,9 +146,9 @@
==
# Union on two InnerJoins, one of which involves an empty relation.
-SELECT r.src, r.dst FROM r, s WHERE r.src=s.src AND r.dst=s.dst
+SELECT r.src, s.dst FROM r, s WHERE r.src=s.src AND r.dst=s.dst
UNION
-SELECT s.src, s.dst FROM s, t WHERE s.src=t.src AND s.dst=t.dst;
+SELECT s.src, t.dst FROM s, t WHERE s.src=t.src AND s.dst=t.dst;
--
+-----------+-----------+
|src |dst |
@@ -148,9 +158,9 @@
==
# Union All on two InnerJoins, one of which involves an empty relation.
-SELECT r.src, r.dst FROM r, s WHERE r.src=s.src AND r.dst=s.dst
+SELECT r.src, s.dst FROM r, s WHERE r.src=s.src AND r.dst=s.dst
UNION ALL
-SELECT s.src, s.dst FROM s, t WHERE s.src=t.src AND s.dst=t.dst;
+SELECT s.src, t.dst FROM s, t WHERE s.src=t.src AND s.dst=t.dst;
--
+-----------+-----------+
|src |dst |
@@ -160,6 +170,20 @@
+-----------+-----------+
==
+# Union All on two InnerJoins, one of which involves an empty relation.
+# One of the project expressions is a ScalarLiteral.
+SELECT s.src, r.dst FROM r, s WHERE r.src=s.src AND r.dst=s.dst
+UNION ALL
+SELECT 1 AS src, s.dst FROM s, t WHERE s.src=t.src AND s.dst=t.dst;
+--
++-----------+-----------+
+|src |dst |
++-----------+-----------+
+| 1| 0|
+| 1| 0|
++-----------+-----------+
+==
+
DROP TABLE r;
DROP TABLE s;
DROP TABLE t;
diff --git a/query_optimizer/physical/Aggregate.cpp b/query_optimizer/physical/Aggregate.cpp
index 5ae9fc7..a8b86b6 100644
--- a/query_optimizer/physical/Aggregate.cpp
+++ b/query_optimizer/physical/Aggregate.cpp
@@ -27,7 +27,6 @@
#include "query_optimizer/expressions/AttributeReference.hpp"
#include "query_optimizer/expressions/ExpressionUtil.hpp"
#include "query_optimizer/expressions/NamedExpression.hpp"
-#include "query_optimizer/expressions/PatternMatcher.hpp"
#include "query_optimizer/expressions/Predicate.hpp"
#include "query_optimizer/physical/PartitionSchemeHeader.hpp"
#include "query_optimizer/physical/Physical.hpp"
@@ -93,22 +92,6 @@
return referenced_attributes;
}
-PhysicalPtr Aggregate::copyWithNewProjectExpressions(
- const std::vector<E::NamedExpressionPtr> &output_expressions) const {
- DCHECK_EQ(aggregate_expressions_.size(), output_expressions.size());
-
- std::vector<E::AliasPtr> new_aggregate_expressions;
- new_aggregate_expressions.reserve(aggregate_expressions_.size());
- for (const auto &output_expression : output_expressions) {
- DCHECK(E::SomeAlias::Matches(output_expression));
-
- new_aggregate_expressions.push_back(
- std::static_pointer_cast<const E::Alias>(output_expression));
- }
-
- return Create(input_, grouping_expressions_, new_aggregate_expressions, filter_predicate_);
-}
-
void Aggregate::getFieldStringItems(
std::vector<std::string> *inline_field_names,
std::vector<std::string> *inline_field_values,
diff --git a/query_optimizer/physical/Aggregate.hpp b/query_optimizer/physical/Aggregate.hpp
index 736082c..68f8811 100644
--- a/query_optimizer/physical/Aggregate.hpp
+++ b/query_optimizer/physical/Aggregate.hpp
@@ -103,9 +103,6 @@
has_repartition, partition_scheme_header);
}
- PhysicalPtr copyWithNewProjectExpressions(
- const std::vector<expressions::NamedExpressionPtr> &output_expressions) const override;
-
bool maybeCopyWithPrunedExpressions(
const expressions::UnorderedNamedExpressionSet &referenced_expressions,
PhysicalPtr *output) const override {
diff --git a/query_optimizer/physical/CMakeLists.txt b/query_optimizer/physical/CMakeLists.txt
index 9f866b8..437488a 100644
--- a/query_optimizer/physical/CMakeLists.txt
+++ b/query_optimizer/physical/CMakeLists.txt
@@ -59,7 +59,6 @@
quickstep_queryoptimizer_expressions_AttributeReference
quickstep_queryoptimizer_expressions_ExpressionUtil
quickstep_queryoptimizer_expressions_NamedExpression
- quickstep_queryoptimizer_expressions_PatternMatcher
quickstep_queryoptimizer_expressions_Predicate
quickstep_queryoptimizer_physical_PartitionSchemeHeader
quickstep_queryoptimizer_physical_Physical
diff --git a/query_optimizer/rules/EliminateEmptyNode.cpp b/query_optimizer/rules/EliminateEmptyNode.cpp
index fd1c383..f619e67 100644
--- a/query_optimizer/rules/EliminateEmptyNode.cpp
+++ b/query_optimizer/rules/EliminateEmptyNode.cpp
@@ -153,42 +153,37 @@
P::PhysicalPtr CopyWithNewProjectExpressions(const P::UnionAllPtr &union_all,
const P::PhysicalPtr &child) {
- const auto &project_attributes = union_all->project_attributes();
+ const std::vector<E::NamedExpressionPtr> *project_expressions = nullptr;
+
+ switch (child->getPhysicalType()) {
+ case P::PhysicalType::kHashJoin:
+ case P::PhysicalType::kNestedLoopsJoin: {
+ const auto &join = std::static_pointer_cast<const P::Join>(child);
+ project_expressions = &(join->project_expressions());
+ break;
+ }
+ case P::PhysicalType::kSelection: {
+ const auto &selection = std::static_pointer_cast<const P::Selection>(child);
+ project_expressions = &(selection->project_expressions());
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unexpected PhysicalType.";
+ }
+ DCHECK(project_expressions);
std::vector<E::NamedExpressionPtr> alias_expressions;
- P::AggregatePtr aggregate;
- if (P::SomeAggregate::MatchesWithConditionalCast(child, &aggregate)) {
- const auto &aggregate_expressions = aggregate->aggregate_expressions();
- alias_expressions.reserve(aggregate_expressions.size());
+ alias_expressions.reserve(project_expressions->size());
- int aid = 0;
- for (const auto &project_attribute : project_attributes) {
- const auto alias_referenced_attributes =
- aggregate_expressions[aid]->getReferencedAttributes();
- DCHECK_EQ(1u, alias_referenced_attributes.size());
-
- alias_expressions.emplace_back(E::Alias::Create(
- project_attribute->id(),
- alias_referenced_attributes.front(),
- project_attribute->attribute_name(),
- project_attribute->attribute_alias(),
- project_attribute->relation_name()));
- ++aid;
- }
- } else {
- const auto child_output_attributes = child->getOutputAttributes();
- alias_expressions.reserve(child_output_attributes.size());
-
- int aid = 0;
- for (const auto &project_attribute : project_attributes) {
- alias_expressions.emplace_back(E::Alias::Create(
- project_attribute->id(),
- child_output_attributes[aid],
- project_attribute->attribute_name(),
- project_attribute->attribute_alias(),
- project_attribute->relation_name()));
- ++aid;
- }
+ int aid = 0;
+ for (const auto &project_attribute : union_all->project_attributes()) {
+ alias_expressions.emplace_back(E::Alias::Create(
+ project_attribute->id(),
+ (*project_expressions)[aid],
+ project_attribute->attribute_name(),
+ project_attribute->attribute_alias(),
+ project_attribute->relation_name()));
+ ++aid;
}
return child->copyWithNewProjectExpressions(alias_expressions);