|
7 | 7 | #include "QueryExecutionSequence.h"
|
8 | 8 | #include "ScalarExprVisitor.h"
|
9 | 9 |
|
| 10 | +#include "IR/UnnestDetector.h" |
| 11 | + |
10 | 12 | #include <boost/graph/adjacency_list.hpp>
|
11 | 13 | #include <boost/graph/topological_sort.hpp>
|
12 | 14 |
|
@@ -115,6 +117,40 @@ class QueryExecutionSequenceImpl {
|
115 | 117 | execution_points_.insert(node->getInput(0));
|
116 | 118 | }
|
117 | 119 |
|
| 120 | + // Similar limitation applies to the UNNEST operation. We support |
| 121 | + // only column references as an unnest operand in projections and |
| 122 | + // therefore have to execution its input. Also, we don't have any |
| 123 | + // special unnesting expression in the execution unit and rely on |
| 124 | + // target expression. So, subsequent nodes that drop unnested arrays |
| 125 | + // can completely remove unnesting from execution units, so all |
| 126 | + // projections with UNNEST operation should be executed directly. |
| 127 | + // We also support UNNEST operation in aggregation keys. So, allow |
| 128 | + // to merge a projection with appropriate aggregate node. |
| 129 | + // TODO: add unnest_exprs to execution unit to enable merge with |
| 130 | + // other nodes. |
| 131 | + if (node->is<ir::Project>() && node->as<ir::Project>()->hasUnnestExpr()) { |
| 132 | + execution_points_.insert(node->getInput(0)); |
| 133 | + bool can_be_merged = false; |
| 134 | + auto [start, end] = boost::in_edges(node_to_vertex_[node], graph_); |
| 135 | + if (start != end) { |
| 136 | + auto parent_node = graph_[start->m_source]; |
| 137 | + if (parent_node->is<ir::Aggregate>()) { |
| 138 | + size_t keys_count = parent_node->as<ir::Aggregate>()->getGroupByCount(); |
| 139 | + auto proj = node->as<ir::Project>(); |
| 140 | + can_be_merged = true; |
| 141 | + for (size_t i = keys_count; i < proj->size(); ++i) { |
| 142 | + if (ir::UnnestDetector::collect(proj->getExpr(i))) { |
| 143 | + can_be_merged = false; |
| 144 | + break; |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + } |
| 149 | + if (!can_be_merged) { |
| 150 | + execution_points_.insert(node); |
| 151 | + } |
| 152 | + } |
| 153 | + |
118 | 154 | // Currently, we cannot merge union code into any other execution
|
119 | 155 | // module. Therefore, mark it and all its inputs as execution points.
|
120 | 156 | // TODO: UNION ALL should be able to be merged into other execution
|
@@ -175,7 +211,8 @@ class QueryExecutionSequenceImpl {
|
175 | 211 | CHECK(start != end);
|
176 | 212 | auto node = graph_[start->m_source];
|
177 | 213 |
|
178 |
| - if (node->is<ir::Project>() && !node->as<ir::Project>()->hasWindowFunctionExpr()) { |
| 214 | + if (node->is<ir::Project>() && !node->as<ir::Project>()->hasWindowFunctionExpr() && |
| 215 | + !node->as<ir::Project>()->hasUnnestExpr()) { |
179 | 216 | // In case of aggregation we allow only 'simple' projections which
|
180 | 217 | // don't have complex expressions referencing aggregate exprs.
|
181 | 218 | bool is_simple = true;
|
|
0 commit comments