OmniSciDB  1dac507f6e
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RelAlgAbstractInterpreter.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 #include "../Shared/sqldefs.h"
20 #include "JsonAccessors.h"
21 #include "RelAlgExecutor.h"
22 #include "RelAlgOptimizer.h"
23 #include "RelLeftDeepInnerJoin.h"
25 #include "RexVisitor.h"
26 
27 #include <rapidjson/stringbuffer.h>
28 #include <rapidjson/writer.h>
29 
30 #include <string>
31 #include <unordered_set>
32 
33 namespace {
34 
35 const unsigned FIRST_RA_NODE_ID = 1;
36 
37 } // namespace
38 
39 thread_local unsigned RelAlgNode::crt_id_ = FIRST_RA_NODE_ID;
40 
43 }
44 
46  const std::shared_ptr<const ExecutionResult> result) {
47  auto row_set = result->getRows();
48  CHECK(row_set);
49  CHECK_EQ(size_t(1), row_set->colCount());
50  *(type_.get()) = row_set->getColType(0);
51  (*(result_.get())) = result;
52 }
53 
54 std::unique_ptr<RexSubQuery> RexSubQuery::deepCopy() const {
55  return std::make_unique<RexSubQuery>(type_, result_, ra_->deepCopy());
56 }
57 
58 namespace {
59 
60 class RexRebindInputsVisitor : public RexVisitor<void*> {
61  public:
62  RexRebindInputsVisitor(const RelAlgNode* old_input, const RelAlgNode* new_input)
63  : old_input_(old_input), new_input_(new_input) {}
64 
65  void* visitInput(const RexInput* rex_input) const override {
66  const auto old_source = rex_input->getSourceNode();
67  if (old_source == old_input_) {
68  const auto left_deep_join = dynamic_cast<const RelLeftDeepInnerJoin*>(new_input_);
69  if (left_deep_join) {
70  rebind_inputs_from_left_deep_join(rex_input, left_deep_join);
71  return nullptr;
72  }
73  rex_input->setSourceNode(new_input_);
74  }
75  return nullptr;
76  };
77 
78  private:
79  const RelAlgNode* old_input_;
81 };
82 
83 // Creates an output with n columns.
84 std::vector<RexInput> n_outputs(const RelAlgNode* node, const size_t n) {
85  std::vector<RexInput> outputs;
86  for (size_t i = 0; i < n; ++i) {
87  outputs.emplace_back(node, i);
88  }
89  return outputs;
90 }
91 
92 } // namespace
93 
94 void RelProject::replaceInput(std::shared_ptr<const RelAlgNode> old_input,
95  std::shared_ptr<const RelAlgNode> input) {
96  RelAlgNode::replaceInput(old_input, input);
97  RexRebindInputsVisitor rebind_inputs(old_input.get(), input.get());
98  for (const auto& scalar_expr : scalar_exprs_) {
99  rebind_inputs.visit(scalar_expr.get());
100  }
101 }
102 
103 void RelProject::appendInput(std::string new_field_name,
104  std::unique_ptr<const RexScalar> new_input) {
105  fields_.emplace_back(std::move(new_field_name));
106  scalar_exprs_.emplace_back(std::move(new_input));
107 }
108 
110  RANodeOutput outputs;
111  const auto scan_node = dynamic_cast<const RelScan*>(ra_node);
112  if (scan_node) {
113  // Scan node has no inputs, output contains all columns in the table.
114  CHECK_EQ(size_t(0), scan_node->inputCount());
115  return n_outputs(scan_node, scan_node->size());
116  }
117  const auto project_node = dynamic_cast<const RelProject*>(ra_node);
118  if (project_node) {
119  // Project output count doesn't depend on the input
120  CHECK_EQ(size_t(1), project_node->inputCount());
121  return n_outputs(project_node, project_node->size());
122  }
123  const auto filter_node = dynamic_cast<const RelFilter*>(ra_node);
124  if (filter_node) {
125  // Filter preserves shape
126  CHECK_EQ(size_t(1), filter_node->inputCount());
127  const auto prev_out = get_node_output(filter_node->getInput(0));
128  return n_outputs(filter_node, prev_out.size());
129  }
130  const auto aggregate_node = dynamic_cast<const RelAggregate*>(ra_node);
131  if (aggregate_node) {
132  // Aggregate output count doesn't depend on the input
133  CHECK_EQ(size_t(1), aggregate_node->inputCount());
134  return n_outputs(aggregate_node, aggregate_node->size());
135  }
136  const auto compound_node = dynamic_cast<const RelCompound*>(ra_node);
137  if (compound_node) {
138  // Compound output count doesn't depend on the input
139  CHECK_EQ(size_t(1), compound_node->inputCount());
140  return n_outputs(compound_node, compound_node->size());
141  }
142  const auto join_node = dynamic_cast<const RelJoin*>(ra_node);
143  if (join_node) {
144  // Join concatenates the outputs from the inputs and the output
145  // directly references the nodes in the input.
146  CHECK_EQ(size_t(2), join_node->inputCount());
147  auto lhs_out =
148  n_outputs(join_node->getInput(0), get_node_output(join_node->getInput(0)).size());
149  const auto rhs_out =
150  n_outputs(join_node->getInput(1), get_node_output(join_node->getInput(1)).size());
151  lhs_out.insert(lhs_out.end(), rhs_out.begin(), rhs_out.end());
152  return lhs_out;
153  }
154  const auto table_func_node = dynamic_cast<const RelTableFunction*>(ra_node);
155  if (table_func_node) {
156  // Table Function output count doesn't depend on the input
157  CHECK_EQ(size_t(1), table_func_node->inputCount());
158  return n_outputs(table_func_node, table_func_node->size());
159  }
160  const auto sort_node = dynamic_cast<const RelSort*>(ra_node);
161  if (sort_node) {
162  // Sort preserves shape
163  CHECK_EQ(size_t(1), sort_node->inputCount());
164  const auto prev_out = get_node_output(sort_node->getInput(0));
165  return n_outputs(sort_node, prev_out.size());
166  }
167  const auto logical_values_node = dynamic_cast<const RelLogicalValues*>(ra_node);
168  if (logical_values_node) {
169  CHECK_EQ(size_t(0), logical_values_node->inputCount());
170  return n_outputs(logical_values_node, logical_values_node->size());
171  }
172  CHECK(false);
173  return outputs;
174 }
175 
177  if (!isSimple()) {
178  return false;
179  }
180  CHECK_EQ(size_t(1), inputCount());
181  const auto source = getInput(0);
182  if (dynamic_cast<const RelJoin*>(source)) {
183  return false;
184  }
185  const auto source_shape = get_node_output(source);
186  if (source_shape.size() != scalar_exprs_.size()) {
187  return false;
188  }
189  for (size_t i = 0; i < scalar_exprs_.size(); ++i) {
190  const auto& scalar_expr = scalar_exprs_[i];
191  const auto input = dynamic_cast<const RexInput*>(scalar_expr.get());
192  CHECK(input);
193  CHECK_EQ(source, input->getSourceNode());
194  // We should add the additional check that input->getIndex() !=
195  // source_shape[i].getIndex(), but Calcite doesn't generate the right
196  // Sort-Project-Sort sequence when joins are involved.
197  if (input->getSourceNode() != source_shape[i].getSourceNode()) {
198  return false;
199  }
200  }
201  return true;
202 }
203 
204 namespace {
205 
206 bool isRenamedInput(const RelAlgNode* node,
207  const size_t index,
208  const std::string& new_name) {
209  CHECK_LT(index, node->size());
210  if (auto join = dynamic_cast<const RelJoin*>(node)) {
211  CHECK_EQ(size_t(2), join->inputCount());
212  const auto lhs_size = join->getInput(0)->size();
213  if (index < lhs_size) {
214  return isRenamedInput(join->getInput(0), index, new_name);
215  }
216  CHECK_GE(index, lhs_size);
217  return isRenamedInput(join->getInput(1), index - lhs_size, new_name);
218  }
219 
220  if (auto scan = dynamic_cast<const RelScan*>(node)) {
221  return new_name != scan->getFieldName(index);
222  }
223 
224  if (auto aggregate = dynamic_cast<const RelAggregate*>(node)) {
225  return new_name != aggregate->getFieldName(index);
226  }
227 
228  if (auto project = dynamic_cast<const RelProject*>(node)) {
229  return new_name != project->getFieldName(index);
230  }
231 
232  if (auto table_func = dynamic_cast<const RelTableFunction*>(node)) {
233  return new_name != table_func->getFieldName(index);
234  }
235 
236  if (auto logical_values = dynamic_cast<const RelLogicalValues*>(node)) {
237  const auto& tuple_type = logical_values->getTupleType();
238  CHECK_LT(index, tuple_type.size());
239  return new_name != tuple_type[index].get_resname();
240  }
241 
242  CHECK(dynamic_cast<const RelSort*>(node) || dynamic_cast<const RelFilter*>(node));
243  return isRenamedInput(node->getInput(0), index, new_name);
244 }
245 
246 } // namespace
247 
249  if (!isSimple()) {
250  return false;
251  }
252  CHECK_EQ(scalar_exprs_.size(), fields_.size());
253  for (size_t i = 0; i < fields_.size(); ++i) {
254  auto rex_in = dynamic_cast<const RexInput*>(scalar_exprs_[i].get());
255  CHECK(rex_in);
256  if (isRenamedInput(rex_in->getSourceNode(), rex_in->getIndex(), fields_[i])) {
257  return true;
258  }
259  }
260  return false;
261 }
262 
263 void RelJoin::replaceInput(std::shared_ptr<const RelAlgNode> old_input,
264  std::shared_ptr<const RelAlgNode> input) {
265  RelAlgNode::replaceInput(old_input, input);
266  RexRebindInputsVisitor rebind_inputs(old_input.get(), input.get());
267  if (condition_) {
268  rebind_inputs.visit(condition_.get());
269  }
270 }
271 
272 void RelFilter::replaceInput(std::shared_ptr<const RelAlgNode> old_input,
273  std::shared_ptr<const RelAlgNode> input) {
274  RelAlgNode::replaceInput(old_input, input);
275  RexRebindInputsVisitor rebind_inputs(old_input.get(), input.get());
276  rebind_inputs.visit(filter_.get());
277 }
278 
279 void RelCompound::replaceInput(std::shared_ptr<const RelAlgNode> old_input,
280  std::shared_ptr<const RelAlgNode> input) {
281  RelAlgNode::replaceInput(old_input, input);
282  RexRebindInputsVisitor rebind_inputs(old_input.get(), input.get());
283  for (const auto& scalar_source : scalar_sources_) {
284  rebind_inputs.visit(scalar_source.get());
285  }
286  if (filter_expr_) {
287  rebind_inputs.visit(filter_expr_.get());
288  }
289 }
290 
291 std::shared_ptr<RelAlgNode> RelProject::deepCopy() const {
292  RexDeepCopyVisitor copier;
293  std::vector<std::unique_ptr<const RexScalar>> exprs_copy;
294  for (auto& expr : scalar_exprs_) {
295  exprs_copy.push_back(copier.visit(expr.get()));
296  }
297  return std::make_shared<RelProject>(exprs_copy, fields_, inputs_[0]);
298 }
299 
300 std::shared_ptr<RelAlgNode> RelFilter::deepCopy() const {
301  RexDeepCopyVisitor copier;
302  auto filter_copy = copier.visit(filter_.get());
303  return std::make_shared<RelFilter>(filter_copy, inputs_[0]);
304 }
305 
306 std::shared_ptr<RelAlgNode> RelAggregate::deepCopy() const {
307  std::vector<std::unique_ptr<const RexAgg>> aggs_copy;
308  for (auto& agg : agg_exprs_) {
309  auto copy = agg->deepCopy();
310  aggs_copy.push_back(std::move(copy));
311  }
312  return std::make_shared<RelAggregate>(groupby_count_, aggs_copy, fields_, inputs_[0]);
313 }
314 
315 std::shared_ptr<RelAlgNode> RelJoin::deepCopy() const {
316  RexDeepCopyVisitor copier;
317  auto condition_copy = copier.visit(condition_.get());
318  return std::make_shared<RelJoin>(inputs_[0], inputs_[1], condition_copy, join_type_);
319 }
320 
321 std::shared_ptr<RelAlgNode> RelCompound::deepCopy() const {
322  RexDeepCopyVisitor copier;
323  auto filter_copy = filter_expr_ ? copier.visit(filter_expr_.get()) : nullptr;
324  std::unordered_map<const Rex*, const Rex*> old_to_new_target;
325  std::vector<const RexAgg*> aggs_copy;
326  for (auto& agg : agg_exprs_) {
327  auto copy = agg->deepCopy();
328  old_to_new_target.insert(std::make_pair(agg.get(), copy.get()));
329  aggs_copy.push_back(copy.release());
330  }
331  std::vector<std::unique_ptr<const RexScalar>> sources_copy;
332  for (size_t i = 0; i < scalar_sources_.size(); ++i) {
333  auto copy = copier.visit(scalar_sources_[i].get());
334  old_to_new_target.insert(std::make_pair(scalar_sources_[i].get(), copy.get()));
335  sources_copy.push_back(std::move(copy));
336  }
337  std::vector<const Rex*> target_exprs_copy;
338  for (auto target : target_exprs_) {
339  auto target_it = old_to_new_target.find(target);
340  CHECK(target_it != old_to_new_target.end());
341  target_exprs_copy.push_back(target_it->second);
342  }
343  auto new_compound = std::make_shared<RelCompound>(filter_copy,
344  target_exprs_copy,
346  aggs_copy,
347  fields_,
348  sources_copy,
349  is_agg_);
350  new_compound->addManagedInput(inputs_[0]);
351  return new_compound;
352 }
353 
354 std::shared_ptr<RelAlgNode> RelSort::deepCopy() const {
355  auto ret = std::make_shared<RelSort>(collation_, limit_, offset_, inputs_[0]);
356  ret->setEmptyResult(isEmptyResult());
357  return ret;
358 }
359 
360 void RelTableFunction::replaceInput(std::shared_ptr<const RelAlgNode> old_input,
361  std::shared_ptr<const RelAlgNode> input) {
362  RelAlgNode::replaceInput(old_input, input);
363  RexRebindInputsVisitor rebind_inputs(old_input.get(), input.get());
364  for (const auto& target_expr : target_exprs_) {
365  rebind_inputs.visit(target_expr.get());
366  }
367  for (const auto& func_input : table_func_inputs_) {
368  rebind_inputs.visit(func_input.get());
369  }
370 }
371 
372 std::shared_ptr<RelAlgNode> RelTableFunction::deepCopy() const {
373  RexDeepCopyVisitor copier;
374 
375  std::unordered_map<const Rex*, const Rex*> old_to_new_input;
376 
377  std::vector<std::unique_ptr<const RexScalar>> table_func_inputs_copy;
378  for (auto& expr : table_func_inputs_) {
379  table_func_inputs_copy.push_back(copier.visit(expr.get()));
380  old_to_new_input.insert(
381  std::make_pair(expr.get(), table_func_inputs_copy.back().get()));
382  }
383 
384  std::vector<const Rex*> col_inputs_copy;
385  for (auto target : col_inputs_) {
386  auto target_it = old_to_new_input.find(target);
387  CHECK(target_it != old_to_new_input.end());
388  col_inputs_copy.push_back(target_it->second);
389  }
390  auto fields_copy = fields_;
391 
392  std::vector<std::unique_ptr<const RexScalar>> target_exprs_copy;
393  for (auto& expr : target_exprs_) {
394  target_exprs_copy.push_back(copier.visit(expr.get()));
395  }
396 
397  return std::make_shared<RelTableFunction>(function_name_,
398  inputs_[0],
399  fields_copy,
400  col_inputs_copy,
401  table_func_inputs_copy,
402  target_exprs_copy);
403 }
404 
405 namespace std {
406 template <>
407 struct hash<std::pair<const RelAlgNode*, int>> {
408  size_t operator()(const std::pair<const RelAlgNode*, int>& input_col) const {
409  auto ptr_val = reinterpret_cast<const int64_t*>(&input_col.first);
410  return static_cast<int64_t>(*ptr_val) ^ input_col.second;
411  }
412 };
413 } // namespace std
414 
415 namespace {
416 
417 std::set<std::pair<const RelAlgNode*, int>> get_equiv_cols(const RelAlgNode* node,
418  const size_t which_col) {
419  std::set<std::pair<const RelAlgNode*, int>> work_set;
420  auto walker = node;
421  auto curr_col = which_col;
422  while (true) {
423  work_set.insert(std::make_pair(walker, curr_col));
424  if (dynamic_cast<const RelScan*>(walker) || dynamic_cast<const RelJoin*>(walker)) {
425  break;
426  }
427  CHECK_EQ(size_t(1), walker->inputCount());
428  auto only_source = walker->getInput(0);
429  if (auto project = dynamic_cast<const RelProject*>(walker)) {
430  if (auto input = dynamic_cast<const RexInput*>(project->getProjectAt(curr_col))) {
431  const auto join_source = dynamic_cast<const RelJoin*>(only_source);
432  if (join_source) {
433  CHECK_EQ(size_t(2), join_source->inputCount());
434  auto lhs = join_source->getInput(0);
435  CHECK((input->getIndex() < lhs->size() && lhs == input->getSourceNode()) ||
436  join_source->getInput(1) == input->getSourceNode());
437  } else {
438  CHECK_EQ(input->getSourceNode(), only_source);
439  }
440  curr_col = input->getIndex();
441  } else {
442  break;
443  }
444  } else if (auto aggregate = dynamic_cast<const RelAggregate*>(walker)) {
445  if (curr_col >= aggregate->getGroupByCount()) {
446  break;
447  }
448  }
449  walker = only_source;
450  }
451  return work_set;
452 }
453 
454 } // namespace
455 
456 bool RelSort::hasEquivCollationOf(const RelSort& that) const {
457  if (collation_.size() != that.collation_.size()) {
458  return false;
459  }
460 
461  for (size_t i = 0, e = collation_.size(); i < e; ++i) {
462  auto this_sort_key = collation_[i];
463  auto that_sort_key = that.collation_[i];
464  if (this_sort_key.getSortDir() != that_sort_key.getSortDir()) {
465  return false;
466  }
467  if (this_sort_key.getNullsPosition() != that_sort_key.getNullsPosition()) {
468  return false;
469  }
470  auto this_equiv_keys = get_equiv_cols(this, this_sort_key.getField());
471  auto that_equiv_keys = get_equiv_cols(&that, that_sort_key.getField());
472  std::vector<std::pair<const RelAlgNode*, int>> intersect;
473  std::set_intersection(this_equiv_keys.begin(),
474  this_equiv_keys.end(),
475  that_equiv_keys.begin(),
476  that_equiv_keys.end(),
477  std::back_inserter(intersect));
478  if (intersect.empty()) {
479  return false;
480  }
481  }
482  return true;
483 }
484 
485 namespace {
486 
487 unsigned node_id(const rapidjson::Value& ra_node) noexcept {
488  const auto& id = field(ra_node, "id");
489  return std::stoi(json_str(id));
490 }
491 
492 // The parse_* functions below de-serialize expressions as they come from Calcite.
493 // RelAlgAbstractInterpreter will take care of making the representation easy to
494 // navigate for lower layers, for example by replacing RexAbstractInput with RexInput.
495 
496 std::unique_ptr<RexAbstractInput> parse_abstract_input(
497  const rapidjson::Value& expr) noexcept {
498  const auto& input = field(expr, "input");
499  return std::unique_ptr<RexAbstractInput>(new RexAbstractInput(json_i64(input)));
500 }
501 
502 std::unique_ptr<RexLiteral> parse_literal(const rapidjson::Value& expr) {
503  CHECK(expr.IsObject());
504  const auto& literal = field(expr, "literal");
505  const auto type = to_sql_type(json_str(field(expr, "type")));
506  const auto target_type = to_sql_type(json_str(field(expr, "target_type")));
507  const auto scale = json_i64(field(expr, "scale"));
508  const auto precision = json_i64(field(expr, "precision"));
509  const auto type_scale = json_i64(field(expr, "type_scale"));
510  const auto type_precision = json_i64(field(expr, "type_precision"));
511  switch (type) {
512  case kDECIMAL:
513  case kINTERVAL_DAY_TIME:
515  case kTIME:
516  case kTIMESTAMP:
517  case kDATE:
518  return std::unique_ptr<RexLiteral>(new RexLiteral(json_i64(literal),
519  type,
520  target_type,
521  scale,
522  precision,
523  type_scale,
524  type_precision));
525  case kDOUBLE: {
526  if (literal.IsDouble()) {
527  return std::unique_ptr<RexLiteral>(new RexLiteral(json_double(literal),
528  type,
529  target_type,
530  scale,
531  precision,
532  type_scale,
533  type_precision));
534  }
535  CHECK(literal.IsInt64());
536  return std::unique_ptr<RexLiteral>(
537  new RexLiteral(static_cast<double>(json_i64(literal)),
538  type,
539  target_type,
540  scale,
541  precision,
542  type_scale,
543  type_precision));
544  }
545  case kTEXT:
546  return std::unique_ptr<RexLiteral>(new RexLiteral(json_str(literal),
547  type,
548  target_type,
549  scale,
550  precision,
551  type_scale,
552  type_precision));
553  case kBOOLEAN:
554  return std::unique_ptr<RexLiteral>(new RexLiteral(json_bool(literal),
555  type,
556  target_type,
557  scale,
558  precision,
559  type_scale,
560  type_precision));
561  case kNULLT:
562  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
563  default:
564  CHECK(false);
565  }
566  CHECK(false);
567  return nullptr;
568 }
569 
570 std::unique_ptr<const RexScalar> parse_scalar_expr(const rapidjson::Value& expr,
571  const Catalog_Namespace::Catalog& cat,
572  RelAlgExecutor* ra_executor);
573 
574 std::unique_ptr<const RexSubQuery> parse_subquery(const rapidjson::Value& expr,
575  const Catalog_Namespace::Catalog& cat,
576  RelAlgExecutor* ra_executor);
577 
578 SQLTypeInfo parse_type(const rapidjson::Value& type_obj) {
579  CHECK(type_obj.IsObject() && type_obj.MemberCount() >= 2);
580  const auto type = to_sql_type(json_str(field(type_obj, "type")));
581  const auto nullable = json_bool(field(type_obj, "nullable"));
582  const auto precision_it = type_obj.FindMember("precision");
583  const int precision =
584  precision_it != type_obj.MemberEnd() ? json_i64(precision_it->value) : 0;
585  const auto scale_it = type_obj.FindMember("scale");
586  const int scale = scale_it != type_obj.MemberEnd() ? json_i64(scale_it->value) : 0;
587  SQLTypeInfo ti(type, !nullable);
588  ti.set_precision(precision);
589  ti.set_scale(scale);
590  return ti;
591 }
592 
593 std::vector<std::unique_ptr<const RexScalar>> parse_expr_array(
594  const rapidjson::Value& arr,
595  const Catalog_Namespace::Catalog& cat,
596  RelAlgExecutor* ra_executor) {
597  std::vector<std::unique_ptr<const RexScalar>> exprs;
598  for (auto it = arr.Begin(); it != arr.End(); ++it) {
599  exprs.emplace_back(parse_scalar_expr(*it, cat, ra_executor));
600  }
601  return exprs;
602 }
603 
605  if (name == "ROW_NUMBER") {
607  }
608  if (name == "RANK") {
610  }
611  if (name == "DENSE_RANK") {
613  }
614  if (name == "PERCENT_RANK") {
616  }
617  if (name == "CUME_DIST") {
619  }
620  if (name == "NTILE") {
622  }
623  if (name == "LAG") {
625  }
626  if (name == "LEAD") {
628  }
629  if (name == "FIRST_VALUE") {
631  }
632  if (name == "LAST_VALUE") {
634  }
635  if (name == "AVG") {
637  }
638  if (name == "MIN") {
640  }
641  if (name == "MAX") {
643  }
644  if (name == "SUM") {
646  }
647  if (name == "COUNT") {
649  }
650  if (name == "$SUM0") {
652  }
653  throw std::runtime_error("Unsupported window function: " + name);
654 }
655 
656 std::vector<std::unique_ptr<const RexScalar>> parse_window_order_exprs(
657  const rapidjson::Value& arr,
658  const Catalog_Namespace::Catalog& cat,
659  RelAlgExecutor* ra_executor) {
660  std::vector<std::unique_ptr<const RexScalar>> exprs;
661  for (auto it = arr.Begin(); it != arr.End(); ++it) {
662  exprs.emplace_back(parse_scalar_expr(field(*it, "field"), cat, ra_executor));
663  }
664  return exprs;
665 }
666 
667 SortDirection parse_sort_direction(const rapidjson::Value& collation) {
668  return json_str(field(collation, "direction")) == std::string("DESCENDING")
671 }
672 
673 NullSortedPosition parse_nulls_position(const rapidjson::Value& collation) {
674  return json_str(field(collation, "nulls")) == std::string("FIRST")
677 }
678 
679 std::vector<SortField> parse_window_order_collation(const rapidjson::Value& arr,
680  const Catalog_Namespace::Catalog& cat,
681  RelAlgExecutor* ra_executor) {
682  std::vector<SortField> collation;
683  size_t field_idx = 0;
684  for (auto it = arr.Begin(); it != arr.End(); ++it, ++field_idx) {
685  const auto sort_dir = parse_sort_direction(*it);
686  const auto null_pos = parse_nulls_position(*it);
687  collation.emplace_back(field_idx, sort_dir, null_pos);
688  }
689  return collation;
690 }
691 
693  const rapidjson::Value& window_bound_obj,
694  const Catalog_Namespace::Catalog& cat,
695  RelAlgExecutor* ra_executor) {
696  CHECK(window_bound_obj.IsObject());
698  window_bound.unbounded = json_bool(field(window_bound_obj, "unbounded"));
699  window_bound.preceding = json_bool(field(window_bound_obj, "preceding"));
700  window_bound.following = json_bool(field(window_bound_obj, "following"));
701  window_bound.is_current_row = json_bool(field(window_bound_obj, "is_current_row"));
702  const auto& offset_field = field(window_bound_obj, "offset");
703  if (offset_field.IsObject()) {
704  window_bound.offset = parse_scalar_expr(offset_field, cat, ra_executor);
705  } else {
706  CHECK(offset_field.IsNull());
707  }
708  window_bound.order_key = json_i64(field(window_bound_obj, "order_key"));
709  return window_bound;
710 }
711 
712 std::unique_ptr<RexOperator> parse_operator(const rapidjson::Value& expr,
713  const Catalog_Namespace::Catalog& cat,
714  RelAlgExecutor* ra_executor) {
715  const auto op_name = json_str(field(expr, "op"));
716  const bool is_quantifier =
717  op_name == std::string("PG_ANY") || op_name == std::string("PG_ALL");
718  const auto op = is_quantifier ? kFUNCTION : to_sql_op(op_name);
719  const auto& operators_json_arr = field(expr, "operands");
720  CHECK(operators_json_arr.IsArray());
721  auto operands = parse_expr_array(operators_json_arr, cat, ra_executor);
722  const auto type_it = expr.FindMember("type");
723  CHECK(type_it != expr.MemberEnd());
724  auto ti = parse_type(type_it->value);
725  if (op == kIN && expr.HasMember("subquery")) {
726  auto subquery = parse_subquery(expr, cat, ra_executor);
727  operands.emplace_back(std::move(subquery));
728  }
729  if (expr.FindMember("partition_keys") != expr.MemberEnd()) {
730  const auto& partition_keys_arr = field(expr, "partition_keys");
731  auto partition_keys = parse_expr_array(partition_keys_arr, cat, ra_executor);
732  const auto& order_keys_arr = field(expr, "order_keys");
733  auto order_keys = parse_window_order_exprs(order_keys_arr, cat, ra_executor);
734  const auto collation = parse_window_order_collation(order_keys_arr, cat, ra_executor);
735  const auto kind = parse_window_function_kind(op_name);
736  const auto lower_bound =
737  parse_window_bound(field(expr, "lower_bound"), cat, ra_executor);
738  const auto upper_bound =
739  parse_window_bound(field(expr, "upper_bound"), cat, ra_executor);
740  bool is_rows = json_bool(field(expr, "is_rows"));
741  ti.set_notnull(false);
742  return std::make_unique<RexWindowFunctionOperator>(kind,
743  operands,
744  partition_keys,
745  order_keys,
746  collation,
747  lower_bound,
748  upper_bound,
749  is_rows,
750  ti);
751  }
752  return std::unique_ptr<RexOperator>(op == kFUNCTION
753  ? new RexFunctionOperator(op_name, operands, ti)
754  : new RexOperator(op, operands, ti));
755 }
756 
757 std::unique_ptr<RexCase> parse_case(const rapidjson::Value& expr,
758  const Catalog_Namespace::Catalog& cat,
759  RelAlgExecutor* ra_executor) {
760  const auto& operands = field(expr, "operands");
761  CHECK(operands.IsArray());
762  CHECK_GE(operands.Size(), unsigned(2));
763  std::unique_ptr<const RexScalar> else_expr;
764  std::vector<
765  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
766  expr_pair_list;
767  for (auto operands_it = operands.Begin(); operands_it != operands.End();) {
768  auto when_expr = parse_scalar_expr(*operands_it++, cat, ra_executor);
769  if (operands_it == operands.End()) {
770  else_expr = std::move(when_expr);
771  break;
772  }
773  auto then_expr = parse_scalar_expr(*operands_it++, cat, ra_executor);
774  expr_pair_list.emplace_back(std::move(when_expr), std::move(then_expr));
775  }
776  return std::unique_ptr<RexCase>(new RexCase(expr_pair_list, else_expr));
777 }
778 
779 std::vector<std::string> strings_from_json_array(
780  const rapidjson::Value& json_str_arr) noexcept {
781  CHECK(json_str_arr.IsArray());
782  std::vector<std::string> fields;
783  for (auto json_str_arr_it = json_str_arr.Begin(); json_str_arr_it != json_str_arr.End();
784  ++json_str_arr_it) {
785  CHECK(json_str_arr_it->IsString());
786  fields.emplace_back(json_str_arr_it->GetString());
787  }
788  return fields;
789 }
790 
791 std::vector<size_t> indices_from_json_array(
792  const rapidjson::Value& json_idx_arr) noexcept {
793  CHECK(json_idx_arr.IsArray());
794  std::vector<size_t> indices;
795  for (auto json_idx_arr_it = json_idx_arr.Begin(); json_idx_arr_it != json_idx_arr.End();
796  ++json_idx_arr_it) {
797  CHECK(json_idx_arr_it->IsInt());
798  CHECK_GE(json_idx_arr_it->GetInt(), 0);
799  indices.emplace_back(json_idx_arr_it->GetInt());
800  }
801  return indices;
802 }
803 
804 std::string json_node_to_string(const rapidjson::Value& node) noexcept {
805  rapidjson::StringBuffer buffer;
806  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
807  node.Accept(writer);
808  return buffer.GetString();
809 }
810 
811 std::unique_ptr<const RexAgg> parse_aggregate_expr(const rapidjson::Value& expr) {
812  const auto agg = to_agg_kind(json_str(field(expr, "agg")));
813  const auto distinct = json_bool(field(expr, "distinct"));
814  const auto agg_ti = parse_type(field(expr, "type"));
815  const auto operands = indices_from_json_array(field(expr, "operands"));
816  if (operands.size() > 1 && (operands.size() != 2 || agg != kAPPROX_COUNT_DISTINCT)) {
817  throw QueryNotSupported("Multiple arguments for aggregates aren't supported");
818  }
819  return std::unique_ptr<const RexAgg>(new RexAgg(agg, distinct, agg_ti, operands));
820 }
821 
822 std::unique_ptr<const RexScalar> parse_scalar_expr(const rapidjson::Value& expr,
823  const Catalog_Namespace::Catalog& cat,
824  RelAlgExecutor* ra_executor) {
825  CHECK(expr.IsObject());
826  if (expr.IsObject() && expr.HasMember("input")) {
827  return std::unique_ptr<const RexScalar>(parse_abstract_input(expr));
828  }
829  if (expr.IsObject() && expr.HasMember("literal")) {
830  return std::unique_ptr<const RexScalar>(parse_literal(expr));
831  }
832  if (expr.IsObject() && expr.HasMember("op")) {
833  const auto op_str = json_str(field(expr, "op"));
834  if (op_str == std::string("CASE")) {
835  return std::unique_ptr<const RexScalar>(parse_case(expr, cat, ra_executor));
836  }
837  if (op_str == std::string("$SCALAR_QUERY")) {
838  return std::unique_ptr<const RexScalar>(parse_subquery(expr, cat, ra_executor));
839  }
840  return std::unique_ptr<const RexScalar>(parse_operator(expr, cat, ra_executor));
841  }
842  throw QueryNotSupported("Expression node " + json_node_to_string(expr) +
843  " not supported");
844 }
845 
846 JoinType to_join_type(const std::string& join_type_name) {
847  if (join_type_name == "inner") {
848  return JoinType::INNER;
849  }
850  if (join_type_name == "left") {
851  return JoinType::LEFT;
852  }
853  throw QueryNotSupported("Join type (" + join_type_name + ") not supported");
854 }
855 
856 std::unique_ptr<const RexScalar> disambiguate_rex(const RexScalar*, const RANodeOutput&);
857 
858 std::unique_ptr<const RexOperator> disambiguate_operator(
859  const RexOperator* rex_operator,
860  const RANodeOutput& ra_output) noexcept {
861  std::vector<std::unique_ptr<const RexScalar>> disambiguated_operands;
862  for (size_t i = 0; i < rex_operator->size(); ++i) {
863  auto operand = rex_operator->getOperand(i);
864  if (dynamic_cast<const RexSubQuery*>(operand)) {
865  disambiguated_operands.emplace_back(rex_operator->getOperandAndRelease(i));
866  } else {
867  disambiguated_operands.emplace_back(disambiguate_rex(operand, ra_output));
868  }
869  }
870  const auto rex_window_function_operator =
871  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
872  if (rex_window_function_operator) {
873  const auto& partition_keys = rex_window_function_operator->getPartitionKeys();
874  std::vector<std::unique_ptr<const RexScalar>> disambiguated_partition_keys;
875  for (const auto& partition_key : partition_keys) {
876  disambiguated_partition_keys.emplace_back(
877  disambiguate_rex(partition_key.get(), ra_output));
878  }
879  std::vector<std::unique_ptr<const RexScalar>> disambiguated_order_keys;
880  const auto& order_keys = rex_window_function_operator->getOrderKeys();
881  for (const auto& order_key : order_keys) {
882  disambiguated_order_keys.emplace_back(disambiguate_rex(order_key.get(), ra_output));
883  }
884  return rex_window_function_operator->disambiguatedOperands(
885  disambiguated_operands,
886  disambiguated_partition_keys,
887  disambiguated_order_keys,
888  rex_window_function_operator->getCollation());
889  }
890  return rex_operator->getDisambiguated(disambiguated_operands);
891 }
892 
893 std::unique_ptr<const RexCase> disambiguate_case(const RexCase* rex_case,
894  const RANodeOutput& ra_output) {
895  std::vector<
896  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
897  disambiguated_expr_pair_list;
898  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
899  auto disambiguated_when = disambiguate_rex(rex_case->getWhen(i), ra_output);
900  auto disambiguated_then = disambiguate_rex(rex_case->getThen(i), ra_output);
901  disambiguated_expr_pair_list.emplace_back(std::move(disambiguated_when),
902  std::move(disambiguated_then));
903  }
904  std::unique_ptr<const RexScalar> disambiguated_else{
905  disambiguate_rex(rex_case->getElse(), ra_output)};
906  return std::unique_ptr<const RexCase>(
907  new RexCase(disambiguated_expr_pair_list, disambiguated_else));
908 }
909 
910 // The inputs used by scalar expressions are given as indices in the serialized
911 // representation of the query. This is hard to navigate; make the relationship
912 // explicit by creating RexInput expressions which hold a pointer to the source
913 // relational algebra node and the index relative to the output of that node.
914 std::unique_ptr<const RexScalar> disambiguate_rex(const RexScalar* rex_scalar,
915  const RANodeOutput& ra_output) {
916  const auto rex_abstract_input = dynamic_cast<const RexAbstractInput*>(rex_scalar);
917  if (rex_abstract_input) {
918  CHECK_LT(static_cast<size_t>(rex_abstract_input->getIndex()), ra_output.size());
919  return std::unique_ptr<const RexInput>(
920  new RexInput(ra_output[rex_abstract_input->getIndex()]));
921  }
922  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
923  if (rex_operator) {
924  return disambiguate_operator(rex_operator, ra_output);
925  }
926  const auto rex_case = dynamic_cast<const RexCase*>(rex_scalar);
927  if (rex_case) {
928  return disambiguate_case(rex_case, ra_output);
929  }
930  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
931  CHECK(rex_literal);
932  return std::unique_ptr<const RexLiteral>(new RexLiteral(*rex_literal));
933 }
934 
935 void bind_project_to_input(RelProject* project_node, const RANodeOutput& input) noexcept {
936  CHECK_EQ(size_t(1), project_node->inputCount());
937  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
938  for (size_t i = 0; i < project_node->size(); ++i) {
939  const auto projected_expr = project_node->getProjectAt(i);
940  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
941  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
942  } else {
943  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
944  }
945  }
946  project_node->setExpressions(disambiguated_exprs);
947 }
948 
950  const RANodeOutput& input) noexcept {
951  CHECK_EQ(size_t(1), table_func_node->inputCount());
952  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
953  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
954  const auto target_expr = table_func_node->getTableFuncInputAt(i);
955  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
956  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
957  } else {
958  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
959  }
960  }
961  table_func_node->setTableFuncInputs(disambiguated_exprs);
962 }
963 
964 void bind_inputs(const std::vector<std::shared_ptr<RelAlgNode>>& nodes) noexcept {
965  for (auto ra_node : nodes) {
966  const auto filter_node = std::dynamic_pointer_cast<RelFilter>(ra_node);
967  if (filter_node) {
968  CHECK_EQ(size_t(1), filter_node->inputCount());
969  auto disambiguated_condition = disambiguate_rex(
970  filter_node->getCondition(), get_node_output(filter_node->getInput(0)));
971  filter_node->setCondition(disambiguated_condition);
972  continue;
973  }
974  const auto join_node = std::dynamic_pointer_cast<RelJoin>(ra_node);
975  if (join_node) {
976  CHECK_EQ(size_t(2), join_node->inputCount());
977  auto disambiguated_condition =
978  disambiguate_rex(join_node->getCondition(), get_node_output(join_node.get()));
979  join_node->setCondition(disambiguated_condition);
980  continue;
981  }
982  const auto project_node = std::dynamic_pointer_cast<RelProject>(ra_node);
983  if (project_node) {
984  bind_project_to_input(project_node.get(),
985  get_node_output(project_node->getInput(0)));
986  continue;
987  }
988  const auto table_func_node = std::dynamic_pointer_cast<RelTableFunction>(ra_node);
989  if (table_func_node) {
990  bind_table_func_to_input(table_func_node.get(),
991  get_node_output(table_func_node->getInput(0)));
992  }
993  }
994 }
995 
996 void mark_nops(const std::vector<std::shared_ptr<RelAlgNode>>& nodes) noexcept {
997  for (auto node : nodes) {
998  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
999  if (!agg_node || agg_node->getAggExprsCount()) {
1000  continue;
1001  }
1002  CHECK_EQ(size_t(1), node->inputCount());
1003  const auto agg_input_node = dynamic_cast<const RelAggregate*>(node->getInput(0));
1004  if (agg_input_node && !agg_input_node->getAggExprsCount() &&
1005  agg_node->getGroupByCount() == agg_input_node->getGroupByCount()) {
1006  agg_node->markAsNop();
1007  }
1008  }
1009 }
1010 
1011 namespace {
1012 
1013 std::vector<const Rex*> reproject_targets(
1014  const RelProject* simple_project,
1015  const std::vector<const Rex*>& target_exprs) noexcept {
1016  std::vector<const Rex*> result;
1017  for (size_t i = 0; i < simple_project->size(); ++i) {
1018  const auto input_rex = dynamic_cast<const RexInput*>(simple_project->getProjectAt(i));
1019  CHECK(input_rex);
1020  CHECK_LT(static_cast<size_t>(input_rex->getIndex()), target_exprs.size());
1021  result.push_back(target_exprs[input_rex->getIndex()]);
1022  }
1023  return result;
1024 }
1025 
1032  public:
1034  const RelAlgNode* node_to_keep,
1035  const std::vector<std::unique_ptr<const RexScalar>>& scalar_sources)
1036  : node_to_keep_(node_to_keep), scalar_sources_(scalar_sources) {}
1037 
1038  // Reproject the RexInput from its current RA Node to the RA Node we intend to keep
1039  RetType visitInput(const RexInput* input) const final {
1040  if (input->getSourceNode() == node_to_keep_) {
1041  const auto index = input->getIndex();
1042  CHECK_LT(index, scalar_sources_.size());
1043  return visit(scalar_sources_[index].get());
1044  } else {
1045  return input->deepCopy();
1046  }
1047  }
1048 
1049  private:
1051  const std::vector<std::unique_ptr<const RexScalar>>& scalar_sources_;
1052 };
1053 
1054 } // namespace
1055 
1056 void create_compound(std::vector<std::shared_ptr<RelAlgNode>>& nodes,
1057  const std::vector<size_t>& pattern) noexcept {
1058  CHECK_GE(pattern.size(), size_t(2));
1059  CHECK_LE(pattern.size(), size_t(4));
1060 
1061  std::unique_ptr<const RexScalar> filter_rex;
1062  std::vector<std::unique_ptr<const RexScalar>> scalar_sources;
1063  size_t groupby_count{0};
1064  std::vector<std::string> fields;
1065  std::vector<const RexAgg*> agg_exprs;
1066  std::vector<const Rex*> target_exprs;
1067  bool first_project{true};
1068  bool is_agg{false};
1069  RelAlgNode* last_node{nullptr};
1070 
1071  std::shared_ptr<ModifyManipulationTarget> manipulation_target;
1072 
1073  for (const auto node_idx : pattern) {
1074  const auto ra_node = nodes[node_idx];
1075  const auto ra_filter = std::dynamic_pointer_cast<RelFilter>(ra_node);
1076  if (ra_filter) {
1077  CHECK(!filter_rex);
1078  filter_rex.reset(ra_filter->getAndReleaseCondition());
1079  CHECK(filter_rex);
1080  last_node = ra_node.get();
1081  continue;
1082  }
1083  const auto ra_project = std::dynamic_pointer_cast<RelProject>(ra_node);
1084  if (ra_project) {
1085  fields = ra_project->getFields();
1086  manipulation_target = ra_project;
1087 
1088  if (first_project) {
1089  CHECK_EQ(size_t(1), ra_project->inputCount());
1090  // Rebind the input of the project to the input of the filter itself
1091  // since we know that we'll evaluate the filter on the fly, with no
1092  // intermediate buffer.
1093  const auto filter_input = dynamic_cast<const RelFilter*>(ra_project->getInput(0));
1094  if (filter_input) {
1095  CHECK_EQ(size_t(1), filter_input->inputCount());
1096  bind_project_to_input(ra_project.get(),
1097  get_node_output(filter_input->getInput(0)));
1098  }
1099  scalar_sources = ra_project->getExpressionsAndRelease();
1100  for (const auto& scalar_expr : scalar_sources) {
1101  target_exprs.push_back(scalar_expr.get());
1102  }
1103  first_project = false;
1104  } else {
1105  if (ra_project->isSimple()) {
1106  target_exprs = reproject_targets(ra_project.get(), target_exprs);
1107  } else {
1108  // TODO(adb): This is essentially a more general case of simple project, we
1109  // could likely merge the two
1110  std::vector<const Rex*> result;
1111  RexInputReplacementVisitor visitor(last_node, scalar_sources);
1112  for (size_t i = 0; i < ra_project->size(); ++i) {
1113  const auto rex = ra_project->getProjectAt(i);
1114  if (auto rex_input = dynamic_cast<const RexInput*>(rex)) {
1115  const auto index = rex_input->getIndex();
1116  CHECK_LT(index, target_exprs.size());
1117  result.push_back(target_exprs[index]);
1118  } else {
1119  scalar_sources.push_back(visitor.visit(rex));
1120  result.push_back(scalar_sources.back().get());
1121  }
1122  }
1123  target_exprs = result;
1124  }
1125  }
1126  last_node = ra_node.get();
1127  continue;
1128  }
1129  const auto ra_aggregate = std::dynamic_pointer_cast<RelAggregate>(ra_node);
1130  if (ra_aggregate) {
1131  is_agg = true;
1132  fields = ra_aggregate->getFields();
1133  agg_exprs = ra_aggregate->getAggregatesAndRelease();
1134  groupby_count = ra_aggregate->getGroupByCount();
1135  decltype(target_exprs){}.swap(target_exprs);
1136  CHECK_LE(groupby_count, scalar_sources.size());
1137  for (size_t group_idx = 0; group_idx < groupby_count; ++group_idx) {
1138  const auto rex_ref = new RexRef(group_idx + 1);
1139  target_exprs.push_back(rex_ref);
1140  scalar_sources.emplace_back(rex_ref);
1141  }
1142  for (const auto rex_agg : agg_exprs) {
1143  target_exprs.push_back(rex_agg);
1144  }
1145  last_node = ra_node.get();
1146  continue;
1147  }
1148  }
1149 
1150  auto compound_node =
1151  std::make_shared<RelCompound>(filter_rex,
1152  target_exprs,
1153  groupby_count,
1154  agg_exprs,
1155  fields,
1156  scalar_sources,
1157  is_agg,
1158  manipulation_target->isUpdateViaSelect(),
1159  manipulation_target->isDeleteViaSelect(),
1160  manipulation_target->isVarlenUpdateRequired(),
1161  manipulation_target->getModifiedTableDescriptor(),
1162  manipulation_target->getTargetColumns());
1163  auto old_node = nodes[pattern.back()];
1164  nodes[pattern.back()] = compound_node;
1165  auto first_node = nodes[pattern.front()];
1166  CHECK_EQ(size_t(1), first_node->inputCount());
1167  compound_node->addManagedInput(first_node->getAndOwnInput(0));
1168  for (size_t i = 0; i < pattern.size() - 1; ++i) {
1169  nodes[pattern[i]].reset();
1170  }
1171  for (auto node : nodes) {
1172  if (!node) {
1173  continue;
1174  }
1175  node->replaceInput(old_node, compound_node);
1176  }
1177 }
1178 
1179 class RANodeIterator : public std::vector<std::shared_ptr<RelAlgNode>>::const_iterator {
1180  using ElementType = std::shared_ptr<RelAlgNode>;
1181  using Super = std::vector<ElementType>::const_iterator;
1182  using Container = std::vector<ElementType>;
1183 
1184  public:
1185  enum class AdvancingMode { DUChain, InOrder };
1186 
1187  explicit RANodeIterator(const Container& nodes)
1188  : Super(nodes.begin()), owner_(nodes), nodeCount_([&nodes]() -> size_t {
1189  size_t non_zero_count = 0;
1190  for (const auto& node : nodes) {
1191  if (node) {
1192  ++non_zero_count;
1193  }
1194  }
1196  }()) {}
1197 
1198  explicit operator size_t() {
1199  return std::distance(owner_.begin(), *static_cast<Super*>(this));
1200  }
1201 
1202  RANodeIterator operator++() = delete;
1203 
1204  void advance(AdvancingMode mode) {
1205  Super& super = *this;
1206  switch (mode) {
1207  case AdvancingMode::DUChain: {
1208  size_t use_count = 0;
1209  Super only_use = owner_.end();
1210  for (Super nodeIt = std::next(super); nodeIt != owner_.end(); ++nodeIt) {
1211  if (!*nodeIt) {
1212  continue;
1213  }
1214  for (size_t i = 0; i < (*nodeIt)->inputCount(); ++i) {
1215  if ((*super) == (*nodeIt)->getAndOwnInput(i)) {
1216  ++use_count;
1217  if (1 == use_count) {
1218  only_use = nodeIt;
1219  } else {
1220  super = owner_.end();
1221  return;
1222  }
1223  }
1224  }
1225  }
1226  super = only_use;
1227  break;
1228  }
1229  case AdvancingMode::InOrder:
1230  for (size_t i = 0; i != owner_.size(); ++i) {
1231  if (!visited_.count(i)) {
1232  super = owner_.begin();
1233  std::advance(super, i);
1234  return;
1235  }
1236  }
1237  super = owner_.end();
1238  break;
1239  default:
1240  CHECK(false);
1241  }
1242  }
1243 
1244  bool allVisited() { return visited_.size() == nodeCount_; }
1245 
1247  visited_.insert(size_t(*this));
1248  Super& super = *this;
1249  return *super;
1250  }
1251 
1252  const ElementType* operator->() { return &(operator*()); }
1253 
1254  private:
1256  const size_t nodeCount_;
1257  std::unordered_set<size_t> visited_;
1258 };
1259 
1260 namespace {
1261 
1262 bool input_can_be_coalesced(const RelAlgNode* parent_node,
1263  const size_t index,
1264  const bool first_rex_is_input) {
1265  if (auto agg_node = dynamic_cast<const RelAggregate*>(parent_node)) {
1266  if (index == 0 && agg_node->getGroupByCount() > 0) {
1267  return true;
1268  } else {
1269  // Is an aggregated target, only allow the project to be elided if the aggregate
1270  // target is simply passed through (i.e. if the top level expression attached to
1271  // the project node is a RexInput expression)
1272  return first_rex_is_input;
1273  }
1274  }
1275  return first_rex_is_input;
1276 }
1277 
1284  public:
1285  bool visitInput(const RexInput* input) const final {
1286  // The top level expression node is checked before we apply the visitor. If we get
1287  // here, this input rex is a child of another rex node, and we handle the can be
1288  // coalesced check slightly differently
1289  return input_can_be_coalesced(input->getSourceNode(), input->getIndex(), false);
1290  }
1291 
1292  bool visitLiteral(const RexLiteral*) const final { return false; }
1293 
1294  bool visitSubQuery(const RexSubQuery*) const final { return false; }
1295 
1296  bool visitRef(const RexRef*) const final { return false; }
1297 
1298  protected:
1299  bool aggregateResult(const bool& aggregate, const bool& next_result) const final {
1300  return aggregate && next_result;
1301  }
1302 
1303  bool defaultResult() const final { return true; }
1304 };
1305 
1306 // Detect the window function SUM pattern: CASE WHEN COUNT() > 0 THEN SUM ELSE 0
1308  const auto case_operator = dynamic_cast<const RexCase*>(rex);
1309  if (case_operator && case_operator->branchCount() == 1) {
1310  const auto then_window =
1311  dynamic_cast<const RexWindowFunctionOperator*>(case_operator->getThen(0));
1312  if (then_window && then_window->getKind() == SqlWindowFunctionKind::SUM_INTERNAL) {
1313  return true;
1314  }
1315  }
1316  return false;
1317 }
1318 
1319 // Detect both window function operators and window function operators embedded in case
1320 // statements (for null handling)
1322  if (dynamic_cast<const RexWindowFunctionOperator*>(rex)) {
1323  return true;
1324  }
1325 
1326  // unwrap from casts, if they exist
1327  const auto rex_cast = dynamic_cast<const RexOperator*>(rex);
1328  if (rex_cast && rex_cast->getOperator() == kCAST) {
1329  CHECK_EQ(rex_cast->size(), size_t(1));
1330  return is_window_function_operator(rex_cast->getOperand(0));
1331  }
1332 
1333  if (is_window_function_sum(rex)) {
1334  return true;
1335  }
1336  // Check for Window Function AVG:
1337  // (CASE WHEN count > 0 THEN sum ELSE 0) / COUNT
1338  const RexOperator* divide_operator = dynamic_cast<const RexOperator*>(rex);
1339  if (divide_operator && divide_operator->getOperator() == kDIVIDE) {
1340  CHECK_EQ(divide_operator->size(), size_t(2));
1341  const auto case_operator =
1342  dynamic_cast<const RexCase*>(divide_operator->getOperand(0));
1343  const auto second_window =
1344  dynamic_cast<const RexWindowFunctionOperator*>(divide_operator->getOperand(1));
1345  if (case_operator && second_window &&
1346  second_window->getKind() == SqlWindowFunctionKind::COUNT) {
1347  if (is_window_function_sum(case_operator)) {
1348  return true;
1349  }
1350  }
1351  }
1352  return false;
1353 }
1354 
1355 inline bool project_has_window_function_input(const RelProject* ra_project) {
1356  for (size_t i = 0; i < ra_project->size(); i++) {
1357  if (is_window_function_operator(ra_project->getProjectAt(i))) {
1358  return true;
1359  }
1360  }
1361  return false;
1362 }
1363 
1364 } // namespace
1365 
1366 void coalesce_nodes(std::vector<std::shared_ptr<RelAlgNode>>& nodes,
1367  const std::vector<const RelAlgNode*>& left_deep_joins) {
1368  enum class CoalesceState { Initial, Filter, FirstProject, Aggregate };
1369  std::vector<size_t> crt_pattern;
1370  CoalesceState crt_state{CoalesceState::Initial};
1371 
1372  auto reset_state = [&crt_pattern, &crt_state]() {
1373  crt_state = CoalesceState::Initial;
1374  decltype(crt_pattern)().swap(crt_pattern);
1375  };
1376 
1377  for (RANodeIterator nodeIt(nodes); !nodeIt.allVisited();) {
1378  const auto ra_node = nodeIt != nodes.end() ? *nodeIt : nullptr;
1379  switch (crt_state) {
1380  case CoalesceState::Initial: {
1381  if (std::dynamic_pointer_cast<const RelFilter>(ra_node) &&
1382  std::find(left_deep_joins.begin(), left_deep_joins.end(), ra_node.get()) ==
1383  left_deep_joins.end()) {
1384  crt_pattern.push_back(size_t(nodeIt));
1385  crt_state = CoalesceState::Filter;
1386  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1387  } else if (std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1388  crt_pattern.push_back(size_t(nodeIt));
1389  crt_state = CoalesceState::FirstProject;
1390  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1391  } else {
1392  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
1393  }
1394  break;
1395  }
1396  case CoalesceState::Filter: {
1397  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1398  if (project_has_window_function_input(project_node.get())) {
1399  reset_state();
1400  break;
1401  }
1402  crt_pattern.push_back(size_t(nodeIt));
1403  crt_state = CoalesceState::FirstProject;
1404  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1405  } else {
1406  reset_state();
1407  }
1408  break;
1409  }
1410  case CoalesceState::FirstProject: {
1411  if (std::dynamic_pointer_cast<const RelAggregate>(ra_node)) {
1412  crt_pattern.push_back(size_t(nodeIt));
1413  crt_state = CoalesceState::Aggregate;
1414  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1415  } else {
1416  if (crt_pattern.size() >= 2) {
1417  create_compound(nodes, crt_pattern);
1418  }
1419  reset_state();
1420  }
1421  break;
1422  }
1423  case CoalesceState::Aggregate: {
1424  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1425  // TODO(adb): overloading the simple project terminology again here
1426  bool is_simple_project{true};
1427  for (size_t i = 0; i < project_node->size(); i++) {
1428  const auto scalar_rex = project_node->getProjectAt(i);
1429  // If the top level scalar rex is an input node, we can bypass the visitor
1430  if (auto input_rex = dynamic_cast<const RexInput*>(scalar_rex)) {
1432  input_rex->getSourceNode(), input_rex->getIndex(), true)) {
1433  is_simple_project = false;
1434  break;
1435  }
1436  continue;
1437  }
1438  CoalesceSecondaryProjectVisitor visitor;
1439  if (!visitor.visit(project_node->getProjectAt(i))) {
1440  is_simple_project = false;
1441  break;
1442  }
1443  }
1444  if (is_simple_project) {
1445  crt_pattern.push_back(size_t(nodeIt));
1446  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
1447  }
1448  }
1449  CHECK_GE(crt_pattern.size(), size_t(2));
1450  create_compound(nodes, crt_pattern);
1451  reset_state();
1452  break;
1453  }
1454  default:
1455  CHECK(false);
1456  }
1457  }
1458  if (crt_state == CoalesceState::FirstProject || crt_state == CoalesceState::Aggregate) {
1459  if (crt_pattern.size() >= 2) {
1460  create_compound(nodes, crt_pattern);
1461  }
1462  CHECK(!crt_pattern.empty());
1463  }
1464 }
1465 
1473 class WindowFunctionDetectionVisitor : public RexVisitor<const RexScalar*> {
1474  protected:
1475  // Detect embedded window function expressions in operators
1476  const RexScalar* visitOperator(const RexOperator* rex_operator) const final {
1477  if (is_window_function_operator(rex_operator)) {
1478  return rex_operator;
1479  }
1480 
1481  const size_t operand_count = rex_operator->size();
1482  for (size_t i = 0; i < operand_count; ++i) {
1483  const auto operand = rex_operator->getOperand(i);
1484  if (is_window_function_operator(operand)) {
1485  // Handle both RexWindowFunctionOperators and window functions built up from
1486  // multiple RexScalar objects (e.g. AVG)
1487  return operand;
1488  }
1489  const auto operandResult = visit(operand);
1490  if (operandResult) {
1491  return operandResult;
1492  }
1493  }
1494 
1495  return defaultResult();
1496  }
1497 
1498  // Detect embedded window function expressions in case statements. Note that this may
1499  // manifest as a nested case statement inside a top level case statement, as some window
1500  // functions (sum, avg) are represented as a case statement. Use the
1501  // is_window_function_operator helper to detect complete window function expressions.
1502  const RexScalar* visitCase(const RexCase* rex_case) const final {
1503  if (is_window_function_operator(rex_case)) {
1504  return rex_case;
1505  }
1506 
1507  auto result = defaultResult();
1508  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1509  const auto when = rex_case->getWhen(i);
1510  result = is_window_function_operator(when) ? when : visit(when);
1511  if (result) {
1512  return result;
1513  }
1514  const auto then = rex_case->getThen(i);
1515  result = is_window_function_operator(then) ? then : visit(then);
1516  if (result) {
1517  return result;
1518  }
1519  }
1520  if (rex_case->getElse()) {
1521  auto else_expr = rex_case->getElse();
1522  result = is_window_function_operator(else_expr) ? else_expr : visit(else_expr);
1523  }
1524  return result;
1525  }
1526 
1527  const RexScalar* aggregateResult(const RexScalar* const& aggregate,
1528  const RexScalar* const& next_result) const final {
1529  // all methods calling aggregate result should be overriden
1530  UNREACHABLE();
1531  return nullptr;
1532  }
1533 
1534  const RexScalar* defaultResult() const final { return nullptr; }
1535 };
1536 
1546  public:
1547  RexWindowFuncReplacementVisitor(std::unique_ptr<const RexScalar> replacement_rex)
1548  : replacement_rex_(std::move(replacement_rex)) {}
1549 
1550  ~RexWindowFuncReplacementVisitor() { CHECK(replacement_rex_ == nullptr); }
1551 
1552  protected:
1553  RetType visitOperator(const RexOperator* rex_operator) const final {
1554  if (should_replace_operand(rex_operator)) {
1555  return std::move(replacement_rex_);
1556  }
1557 
1558  const auto rex_window_function_operator =
1559  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
1560  if (rex_window_function_operator) {
1561  // Deep copy the embedded window function operator
1562  return visitWindowFunctionOperator(rex_window_function_operator);
1563  }
1564 
1565  const size_t operand_count = rex_operator->size();
1566  std::vector<RetType> new_opnds;
1567  for (size_t i = 0; i < operand_count; ++i) {
1568  const auto operand = rex_operator->getOperand(i);
1569  if (should_replace_operand(operand)) {
1570  new_opnds.push_back(std::move(replacement_rex_));
1571  } else {
1572  new_opnds.emplace_back(visit(rex_operator->getOperand(i)));
1573  }
1574  }
1575  return rex_operator->getDisambiguated(new_opnds);
1576  }
1577 
1578  RetType visitCase(const RexCase* rex_case) const final {
1579  if (should_replace_operand(rex_case)) {
1580  return std::move(replacement_rex_);
1581  }
1582 
1583  std::vector<std::pair<RetType, RetType>> new_pair_list;
1584  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1585  auto when_operand = rex_case->getWhen(i);
1586  auto then_operand = rex_case->getThen(i);
1587  new_pair_list.emplace_back(
1588  should_replace_operand(when_operand) ? std::move(replacement_rex_)
1589  : visit(when_operand),
1590  should_replace_operand(then_operand) ? std::move(replacement_rex_)
1591  : visit(then_operand));
1592  }
1593  auto new_else = should_replace_operand(rex_case->getElse())
1594  ? std::move(replacement_rex_)
1595  : visit(rex_case->getElse());
1596  return std::make_unique<RexCase>(new_pair_list, new_else);
1597  }
1598 
1599  private:
1600  bool should_replace_operand(const RexScalar* rex) const {
1601  return replacement_rex_ && is_window_function_operator(rex);
1602  }
1603 
1604  mutable std::unique_ptr<const RexScalar> replacement_rex_;
1605 };
1606 
1617  public:
1618  RexInputBackpropagationVisitor(RelProject* node) : node_(node) { CHECK(node_); }
1619 
1620  protected:
1621  RetType visitInput(const RexInput* rex_input) const final {
1622  if (rex_input->getSourceNode() != node_) {
1623  const auto cur_index = rex_input->getIndex();
1624  auto cur_source_node = rex_input->getSourceNode();
1625  std::string field_name = "";
1626  if (auto cur_project_node = dynamic_cast<const RelProject*>(cur_source_node)) {
1627  field_name = cur_project_node->getFieldName(cur_index);
1628  }
1629  node_->appendInput(field_name, rex_input->deepCopy());
1630  return std::make_unique<RexInput>(node_, node_->size() - 1);
1631  } else {
1632  return rex_input->deepCopy();
1633  }
1634  }
1635 
1636  private:
1637  mutable RelProject* node_;
1638 };
1639 
1656  std::vector<std::shared_ptr<RelAlgNode>>& nodes) {
1657  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
1658 
1660  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
1661  const auto node = *node_itr;
1662  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
1663  if (!window_func_project_node) {
1664  continue;
1665  }
1666 
1667  // map scalar expression index in the project node to wiondow function ptr
1668  std::unordered_map<size_t, const RexScalar*> embedded_window_function_expressions;
1669 
1670  // Iterate the target exprs of the project node and check for window function
1671  // expressions. If an embedded expression exists, save it in the
1672  // embedded_window_function_expressions map and split the expression into a window
1673  // function expression and a parent expression in a subsequent project node
1674  for (size_t i = 0; i < window_func_project_node->size(); i++) {
1675  const auto scalar_rex = window_func_project_node->getProjectAt(i);
1676  if (is_window_function_operator(scalar_rex)) {
1677  // top level window function exprs are fine
1678  continue;
1679  }
1680 
1681  if (const auto window_func_rex = visitor.visit(scalar_rex)) {
1682  const auto ret = embedded_window_function_expressions.insert(
1683  std::make_pair(i, window_func_rex));
1684  CHECK(ret.second);
1685  }
1686  }
1687 
1688  if (!embedded_window_function_expressions.empty()) {
1689  std::vector<std::unique_ptr<const RexScalar>> new_scalar_exprs;
1690 
1691  auto window_func_scalar_exprs =
1692  window_func_project_node->getExpressionsAndRelease();
1693  for (size_t rex_idx = 0; rex_idx < window_func_scalar_exprs.size(); ++rex_idx) {
1694  const auto embedded_window_func_expr_pair =
1695  embedded_window_function_expressions.find(rex_idx);
1696  if (embedded_window_func_expr_pair ==
1697  embedded_window_function_expressions.end()) {
1698  new_scalar_exprs.emplace_back(
1699  std::make_unique<const RexInput>(window_func_project_node.get(), rex_idx));
1700  } else {
1701  const auto window_func_rex_idx = embedded_window_func_expr_pair->first;
1702  CHECK_LT(window_func_rex_idx, window_func_scalar_exprs.size());
1703 
1704  const auto& window_func_rex = embedded_window_func_expr_pair->second;
1705 
1706  RexDeepCopyVisitor copier;
1707  auto window_func_rex_copy = copier.visit(window_func_rex);
1708 
1709  auto window_func_parent_expr =
1710  window_func_scalar_exprs[window_func_rex_idx].get();
1711 
1712  // Replace window func rex with an input rex
1713  auto window_func_result_input = std::make_unique<const RexInput>(
1714  window_func_project_node.get(), window_func_rex_idx);
1715  RexWindowFuncReplacementVisitor replacer(std::move(window_func_result_input));
1716  auto new_parent_rex = replacer.visit(window_func_parent_expr);
1717 
1718  // Put the parent expr in the new scalar exprs
1719  new_scalar_exprs.emplace_back(std::move(new_parent_rex));
1720 
1721  // Put the window func expr in cur scalar exprs
1722  window_func_scalar_exprs[window_func_rex_idx] = std::move(window_func_rex_copy);
1723  }
1724  }
1725 
1726  CHECK_EQ(window_func_scalar_exprs.size(), new_scalar_exprs.size());
1727  window_func_project_node->setExpressions(window_func_scalar_exprs);
1728 
1729  // Ensure any inputs from the node containing the expression (the "new" node)
1730  // exist on the window function project node, e.g. if we had a binary operation
1731  // involving an aggregate value or column not included in the top level
1732  // projection list.
1733  RexInputBackpropagationVisitor input_visitor(window_func_project_node.get());
1734  for (size_t i = 0; i < new_scalar_exprs.size(); i++) {
1735  if (dynamic_cast<const RexInput*>(new_scalar_exprs[i].get())) {
1736  // ignore top level inputs, these were copied directly from the previous
1737  // node
1738  continue;
1739  }
1740  new_scalar_exprs[i] = input_visitor.visit(new_scalar_exprs[i].get());
1741  }
1742 
1743  // Build the new project node and insert it into the list after the project node
1744  // containing the window function
1745  auto new_project =
1746  std::make_shared<RelProject>(new_scalar_exprs,
1747  window_func_project_node->getFields(),
1748  window_func_project_node);
1749  node_list.insert(std::next(node_itr), new_project);
1750 
1751  // Rebind all the following inputs
1752  for (auto rebind_itr = std::next(node_itr, 2); rebind_itr != node_list.end();
1753  rebind_itr++) {
1754  (*rebind_itr)->replaceInput(window_func_project_node, new_project);
1755  }
1756  }
1757  }
1758  nodes.assign(node_list.begin(), node_list.end());
1759 }
1760 
1761 int64_t get_int_literal_field(const rapidjson::Value& obj,
1762  const char field[],
1763  const int64_t default_val) noexcept {
1764  const auto it = obj.FindMember(field);
1765  if (it == obj.MemberEnd()) {
1766  return default_val;
1767  }
1768  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
1769  CHECK_EQ(kDECIMAL, lit->getType());
1770  CHECK_EQ(unsigned(0), lit->getScale());
1771  CHECK_EQ(unsigned(0), lit->getTypeScale());
1772  return lit->getVal<int64_t>();
1773 }
1774 
1775 void check_empty_inputs_field(const rapidjson::Value& node) noexcept {
1776  const auto& inputs_json = field(node, "inputs");
1777  CHECK(inputs_json.IsArray() && !inputs_json.Size());
1778 }
1779 
1780 // Create an in-memory, easy to navigate relational algebra DAG from its serialized,
1781 // JSON representation. Also, apply high level optimizations which can be expressed
1782 // through relational algebra extended with RelCompound. The RelCompound node is an
1783 // equivalent representation for sequences of RelFilter, RelProject and RelAggregate
1784 // nodes. This coalescing minimizes the amount of intermediate buffers required to
1785 // evaluate a query. Lower level optimizations are taken care by lower levels, mainly
1786 // RelAlgTranslator and the IR code generation.
1788  public:
1789  RelAlgAbstractInterpreter(const rapidjson::Value& query_ast,
1790  const Catalog_Namespace::Catalog& cat,
1791  RelAlgExecutor* ra_executor,
1792  const RenderQueryOptions* render_opts)
1793  : query_ast_(query_ast)
1794  , cat_(cat)
1795  , ra_executor_(ra_executor)
1796  , render_opts_(render_opts) {}
1797 
1798  std::shared_ptr<const RelAlgNode> run() {
1799  const auto& rels = field(query_ast_, "rels");
1800  CHECK(rels.IsArray());
1801  try {
1802  dispatchNodes(rels);
1803  } catch (const QueryNotSupported&) {
1804  throw;
1805  }
1806  CHECK(!nodes_.empty());
1807  bind_inputs(nodes_);
1808 
1809  if (render_opts_) {
1810  // Alter the RA for render. Do this before any flattening/optimizations are done to
1811  // the tree.
1812  alterRAForRender(nodes_, *render_opts_);
1813  }
1814 
1815  mark_nops(nodes_);
1816  simplify_sort(nodes_);
1818  eliminate_identical_copy(nodes_);
1819  fold_filters(nodes_);
1820  std::vector<const RelAlgNode*> filtered_left_deep_joins;
1821  std::vector<const RelAlgNode*> left_deep_joins;
1822  for (const auto& node : nodes_) {
1823  const auto left_deep_join_root = get_left_deep_join_root(node);
1824  // The filter which starts a left-deep join pattern must not be coalesced
1825  // since it contains (part of) the join condition.
1826  if (left_deep_join_root) {
1827  left_deep_joins.push_back(left_deep_join_root.get());
1828  if (std::dynamic_pointer_cast<const RelFilter>(left_deep_join_root)) {
1829  filtered_left_deep_joins.push_back(left_deep_join_root.get());
1830  }
1831  }
1832  }
1833  if (filtered_left_deep_joins.empty()) {
1835  }
1836  eliminate_dead_columns(nodes_);
1838  coalesce_nodes(nodes_, left_deep_joins);
1839  CHECK(nodes_.back().unique());
1840  create_left_deep_join(nodes_);
1841  return nodes_.back();
1842  }
1843 
1844  private:
1845  void dispatchNodes(const rapidjson::Value& rels) {
1846  for (auto rels_it = rels.Begin(); rels_it != rels.End(); ++rels_it) {
1847  const auto& crt_node = *rels_it;
1848  const auto id = node_id(crt_node);
1849  CHECK_EQ(static_cast<size_t>(id), nodes_.size());
1850  CHECK(crt_node.IsObject());
1851  std::shared_ptr<RelAlgNode> ra_node = nullptr;
1852  const auto rel_op = json_str(field(crt_node, "relOp"));
1853  if (rel_op == std::string("EnumerableTableScan")) {
1854  ra_node = dispatchTableScan(crt_node);
1855  } else if (rel_op == std::string("LogicalProject")) {
1856  ra_node = dispatchProject(crt_node);
1857  } else if (rel_op == std::string("LogicalFilter")) {
1858  ra_node = dispatchFilter(crt_node);
1859  } else if (rel_op == std::string("LogicalAggregate")) {
1860  ra_node = dispatchAggregate(crt_node);
1861  } else if (rel_op == std::string("LogicalJoin")) {
1862  ra_node = dispatchJoin(crt_node);
1863  } else if (rel_op == std::string("LogicalSort")) {
1864  ra_node = dispatchSort(crt_node);
1865  } else if (rel_op == std::string("LogicalValues")) {
1866  ra_node = dispatchLogicalValues(crt_node);
1867  } else if (rel_op == std::string("LogicalTableModify")) {
1868  ra_node = dispatchModify(crt_node);
1869  } else if (rel_op == std::string("LogicalTableFunctionScan")) {
1870  ra_node = dispatchTableFunction(crt_node);
1871  } else {
1872  throw QueryNotSupported(std::string("Node ") + rel_op + " not supported yet");
1873  }
1874  nodes_.push_back(ra_node);
1875  }
1876  }
1877 
1878  std::shared_ptr<RelScan> dispatchTableScan(const rapidjson::Value& scan_ra) {
1879  check_empty_inputs_field(scan_ra);
1880  CHECK(scan_ra.IsObject());
1881  const auto td = getTableFromScanNode(scan_ra);
1882  const auto field_names = getFieldNamesFromScanNode(scan_ra);
1883  return std::make_shared<RelScan>(td, field_names);
1884  }
1885 
1886  std::shared_ptr<RelProject> dispatchProject(const rapidjson::Value& proj_ra) {
1887  const auto inputs = getRelAlgInputs(proj_ra);
1888  CHECK_EQ(size_t(1), inputs.size());
1889  const auto& exprs_json = field(proj_ra, "exprs");
1890  CHECK(exprs_json.IsArray());
1891  std::vector<std::unique_ptr<const RexScalar>> exprs;
1892  for (auto exprs_json_it = exprs_json.Begin(); exprs_json_it != exprs_json.End();
1893  ++exprs_json_it) {
1894  exprs.emplace_back(parse_scalar_expr(*exprs_json_it, cat_, ra_executor_));
1895  }
1896  const auto& fields = field(proj_ra, "fields");
1897  return std::make_shared<RelProject>(
1898  exprs, strings_from_json_array(fields), inputs.front());
1899  }
1900 
1901  std::shared_ptr<RelFilter> dispatchFilter(const rapidjson::Value& filter_ra) {
1902  const auto inputs = getRelAlgInputs(filter_ra);
1903  CHECK_EQ(size_t(1), inputs.size());
1904  const auto id = node_id(filter_ra);
1905  CHECK(id);
1906  auto condition = parse_scalar_expr(field(filter_ra, "condition"), cat_, ra_executor_);
1907  return std::make_shared<RelFilter>(condition, inputs.front());
1908  }
1909 
1910  std::shared_ptr<RelAggregate> dispatchAggregate(const rapidjson::Value& agg_ra) {
1911  const auto inputs = getRelAlgInputs(agg_ra);
1912  CHECK_EQ(size_t(1), inputs.size());
1913  const auto fields = strings_from_json_array(field(agg_ra, "fields"));
1914  const auto group = indices_from_json_array(field(agg_ra, "group"));
1915  for (size_t i = 0; i < group.size(); ++i) {
1916  CHECK_EQ(i, group[i]);
1917  }
1918  if (agg_ra.HasMember("groups") || agg_ra.HasMember("indicator")) {
1919  throw QueryNotSupported("GROUP BY extensions not supported");
1920  }
1921  const auto& aggs_json_arr = field(agg_ra, "aggs");
1922  CHECK(aggs_json_arr.IsArray());
1923  std::vector<std::unique_ptr<const RexAgg>> aggs;
1924  for (auto aggs_json_arr_it = aggs_json_arr.Begin();
1925  aggs_json_arr_it != aggs_json_arr.End();
1926  ++aggs_json_arr_it) {
1927  aggs.emplace_back(parse_aggregate_expr(*aggs_json_arr_it));
1928  }
1929  return std::make_shared<RelAggregate>(group.size(), aggs, fields, inputs.front());
1930  }
1931 
1932  std::shared_ptr<RelJoin> dispatchJoin(const rapidjson::Value& join_ra) {
1933  const auto inputs = getRelAlgInputs(join_ra);
1934  CHECK_EQ(size_t(2), inputs.size());
1935  const auto join_type = to_join_type(json_str(field(join_ra, "joinType")));
1936  auto filter_rex = parse_scalar_expr(field(join_ra, "condition"), cat_, ra_executor_);
1937  return std::make_shared<RelJoin>(inputs[0], inputs[1], filter_rex, join_type);
1938  }
1939 
1940  std::shared_ptr<RelSort> dispatchSort(const rapidjson::Value& sort_ra) {
1941  const auto inputs = getRelAlgInputs(sort_ra);
1942  CHECK_EQ(size_t(1), inputs.size());
1943  std::vector<SortField> collation;
1944  const auto& collation_arr = field(sort_ra, "collation");
1945  CHECK(collation_arr.IsArray());
1946  for (auto collation_arr_it = collation_arr.Begin();
1947  collation_arr_it != collation_arr.End();
1948  ++collation_arr_it) {
1949  const size_t field_idx = json_i64(field(*collation_arr_it, "field"));
1950  const auto sort_dir = parse_sort_direction(*collation_arr_it);
1951  const auto null_pos = parse_nulls_position(*collation_arr_it);
1952  collation.emplace_back(field_idx, sort_dir, null_pos);
1953  }
1954  auto limit = get_int_literal_field(sort_ra, "fetch", -1);
1955  const auto offset = get_int_literal_field(sort_ra, "offset", 0);
1956  auto ret = std::make_shared<RelSort>(
1957  collation, limit > 0 ? limit : 0, offset, inputs.front());
1958  ret->setEmptyResult(limit == 0);
1959  return ret;
1960  }
1961 
1962  std::shared_ptr<RelModify> dispatchModify(const rapidjson::Value& logical_modify_ra) {
1963  const auto inputs = getRelAlgInputs(logical_modify_ra);
1964  CHECK_EQ(size_t(1), inputs.size());
1965 
1966  const auto table_descriptor = getTableFromScanNode(logical_modify_ra);
1967  if (table_descriptor->isView) {
1968  throw std::runtime_error("UPDATE of a view is unsupported.");
1969  }
1970 
1971  bool flattened = json_bool(field(logical_modify_ra, "flattened"));
1972  std::string op = json_str(field(logical_modify_ra, "operation"));
1973  RelModify::TargetColumnList target_column_list;
1974 
1975  if (op == "UPDATE") {
1976  const auto& update_columns = field(logical_modify_ra, "updateColumnList");
1977  CHECK(update_columns.IsArray());
1978 
1979  for (auto column_arr_it = update_columns.Begin();
1980  column_arr_it != update_columns.End();
1981  ++column_arr_it) {
1982  target_column_list.push_back(column_arr_it->GetString());
1983  }
1984  }
1985 
1986  auto modify_node = std::make_shared<RelModify>(
1987  cat_, table_descriptor, flattened, op, target_column_list, inputs[0]);
1988  switch (modify_node->getOperation()) {
1990  modify_node->applyDeleteModificationsToInputNode();
1991  break;
1992  }
1994  modify_node->applyUpdateModificationsToInputNode();
1995  }
1996  default:
1997  break;
1998  }
1999 
2000  return modify_node;
2001  }
2002 
2003  std::shared_ptr<RelTableFunction> dispatchTableFunction(
2004  const rapidjson::Value& table_func_ra) {
2005  const auto inputs = getRelAlgInputs(table_func_ra);
2006  CHECK_EQ(size_t(1), inputs.size());
2007 
2008  const auto& invocation = field(table_func_ra, "invocation");
2009  CHECK(invocation.IsObject());
2010 
2011  const auto& operands = field(invocation, "operands");
2012  CHECK(operands.IsArray());
2013  CHECK_GE(operands.Size(), unsigned(0));
2014 
2015  std::vector<const Rex*> col_inputs;
2016  std::vector<std::unique_ptr<const RexScalar>> table_func_inputs;
2017  std::vector<std::string> fields;
2018 
2019  for (auto exprs_json_it = operands.Begin(); exprs_json_it != operands.End();
2020  ++exprs_json_it) {
2021  const auto& expr_json = *exprs_json_it;
2022  CHECK(expr_json.IsObject());
2023 
2024  if (expr_json.HasMember("op")) {
2025  const auto op_str = json_str(field(expr_json, "op"));
2026  if (op_str == "CAST" && expr_json.HasMember("type")) {
2027  const auto& expr_type = field(expr_json, "type");
2028  CHECK(expr_type.IsObject());
2029  CHECK(expr_type.HasMember("type"));
2030  const auto& expr_type_name = json_str(field(expr_type, "type"));
2031  if (expr_type_name == "CURSOR") {
2032  CHECK(expr_json.HasMember("operands"));
2033  const auto& expr_operands = field(expr_json, "operands");
2034  CHECK(expr_operands.IsArray());
2035  if (expr_operands.Size() != 1) {
2036  throw std::runtime_error(
2037  "Table functions currently only support one ResultSet input");
2038  }
2039 
2040  CHECK(expr_json.HasMember("type"));
2041  const auto& expr_types = field(invocation, "type");
2042  CHECK(expr_types.IsArray());
2043 
2044  const auto prior_node = prev(table_func_ra);
2045  CHECK(prior_node);
2046  CHECK_EQ(prior_node->size(), expr_types.Size());
2047 
2048  // Forward the values from the prior node as RexInputs
2049  for (size_t i = 0; i < prior_node->size(); i++) {
2050  table_func_inputs.emplace_back(std::make_unique<RexAbstractInput>(i));
2051  col_inputs.emplace_back(table_func_inputs.back().get());
2052  }
2053  continue;
2054  }
2055  }
2056  }
2057  table_func_inputs.emplace_back(
2058  parse_scalar_expr(*exprs_json_it, cat_, ra_executor_));
2059  }
2060 
2061  const auto& op_name = field(invocation, "op");
2062  CHECK(op_name.IsString());
2063 
2064  std::vector<std::unique_ptr<const RexScalar>> table_function_projected_outputs;
2065  const auto& row_types = field(table_func_ra, "rowType");
2066  CHECK(row_types.IsArray());
2067  CHECK_GE(row_types.Size(), unsigned(0));
2068  const auto& row_types_array = row_types.GetArray();
2069 
2070  for (size_t i = 0; i < row_types_array.Size(); i++) {
2071  // We don't care about the type information in rowType -- replace each output with a
2072  // reference to be resolved later in the translator
2073  table_function_projected_outputs.emplace_back(std::make_unique<RexRef>(i));
2074  fields.emplace_back("");
2075  }
2076 
2077  return std::make_shared<RelTableFunction>(op_name.GetString(),
2078  inputs[0],
2079  fields,
2080  col_inputs,
2081  table_func_inputs,
2082  table_function_projected_outputs);
2083  }
2084 
2085  std::shared_ptr<RelLogicalValues> dispatchLogicalValues(
2086  const rapidjson::Value& logical_values_ra) {
2087  const auto& tuple_type_arr = field(logical_values_ra, "type");
2088  CHECK(tuple_type_arr.IsArray());
2089  std::vector<TargetMetaInfo> tuple_type;
2090  for (auto tuple_type_arr_it = tuple_type_arr.Begin();
2091  tuple_type_arr_it != tuple_type_arr.End();
2092  ++tuple_type_arr_it) {
2093  const auto component_type = parse_type(*tuple_type_arr_it);
2094  const auto component_name = json_str(field(*tuple_type_arr_it, "name"));
2095  tuple_type.emplace_back(component_name, component_type);
2096  }
2097  const auto& inputs_arr = field(logical_values_ra, "inputs");
2098  CHECK(inputs_arr.IsArray());
2099  const auto& tuples_arr = field(logical_values_ra, "tuples");
2100  CHECK(tuples_arr.IsArray());
2101 
2102  if (inputs_arr.Size() || tuples_arr.Size()) {
2103  throw QueryNotSupported("Non-empty LogicalValues not supported yet");
2104  }
2105  return std::make_shared<RelLogicalValues>(tuple_type);
2106  }
2107 
2108  const TableDescriptor* getTableFromScanNode(const rapidjson::Value& scan_ra) const {
2109  const auto& table_json = field(scan_ra, "table");
2110  CHECK(table_json.IsArray());
2111  CHECK_EQ(unsigned(2), table_json.Size());
2112  const auto td = cat_.getMetadataForTable(table_json[1].GetString());
2113  CHECK(td);
2114  return td;
2115  }
2116 
2117  std::vector<std::string> getFieldNamesFromScanNode(
2118  const rapidjson::Value& scan_ra) const {
2119  const auto& fields_json = field(scan_ra, "fieldNames");
2120  return strings_from_json_array(fields_json);
2121  }
2122 
2123  std::vector<std::shared_ptr<const RelAlgNode>> getRelAlgInputs(
2124  const rapidjson::Value& node) {
2125  if (node.HasMember("inputs")) {
2126  const auto str_input_ids = strings_from_json_array(field(node, "inputs"));
2127  std::vector<std::shared_ptr<const RelAlgNode>> ra_inputs;
2128  for (const auto str_id : str_input_ids) {
2129  ra_inputs.push_back(nodes_[std::stoi(str_id)]);
2130  }
2131  return ra_inputs;
2132  }
2133  return {prev(node)};
2134  }
2135 
2136  std::shared_ptr<const RelAlgNode> prev(const rapidjson::Value& crt_node) {
2137  const auto id = node_id(crt_node);
2138  CHECK(id);
2139  CHECK_EQ(static_cast<size_t>(id), nodes_.size());
2140  return nodes_.back();
2141  }
2142 
2143  const rapidjson::Value& query_ast_;
2145  std::vector<std::shared_ptr<RelAlgNode>> nodes_;
2148 };
2149 
2150 std::shared_ptr<const RelAlgNode> ra_interpret(const rapidjson::Value& query_ast,
2151  const Catalog_Namespace::Catalog& cat,
2152  RelAlgExecutor* ra_executor,
2153  const RenderQueryOptions* render_opts) {
2154  RelAlgAbstractInterpreter interp(query_ast, cat, ra_executor, render_opts);
2155  return interp.run();
2156 }
2157 
2158 std::unique_ptr<const RexSubQuery> parse_subquery(const rapidjson::Value& expr,
2159  const Catalog_Namespace::Catalog& cat,
2160  RelAlgExecutor* ra_executor) {
2161  const auto& operands = field(expr, "operands");
2162  CHECK(operands.IsArray());
2163  CHECK_GE(operands.Size(), unsigned(0));
2164  const auto& subquery_ast = field(expr, "subquery");
2165 
2166  const auto ra = ra_interpret(subquery_ast, cat, ra_executor, nullptr);
2167  auto subquery = std::make_shared<RexSubQuery>(ra);
2168  ra_executor->registerSubquery(subquery);
2169  return subquery->deepCopy();
2170 }
2171 
2172 } // namespace
2173 
2174 // Driver for the query de-serialization and high level optimization.
2175 std::shared_ptr<const RelAlgNode> deserialize_ra_dag(
2176  const std::string& query_ra,
2177  const Catalog_Namespace::Catalog& cat,
2178  RelAlgExecutor* ra_executor,
2179  const RenderQueryOptions* render_opts) {
2180  rapidjson::Document query_ast;
2181  query_ast.Parse(query_ra.c_str());
2182  CHECK(!query_ast.HasParseError());
2183  CHECK(query_ast.IsObject());
2185  return ra_interpret(query_ast, cat, ra_executor, render_opts);
2186 }
2187 
2188 // Prints the relational algebra as a tree; useful for debugging.
2189 std::string tree_string(const RelAlgNode* ra, const size_t indent) {
2190  std::string result = std::string(indent, ' ') + ra->toString() + "\n";
2191  for (size_t i = 0; i < ra->inputCount(); ++i) {
2192  result += tree_string(ra->getInput(i), indent + 2);
2193  }
2194  return result;
2195 }
SQLTypes to_sql_type(const std::string &type_name)
std::vector< std::shared_ptr< const RelAlgNode > > inputs_
void registerSubquery(std::shared_ptr< RexSubQuery > subquery) noexcept
bool is_agg(const Analyzer::Expr *expr)
std::unique_ptr< const RexScalar > condition_
const RexScalar * getThen(const size_t idx) const
#define CHECK_EQ(x, y)
Definition: Logger.h:198
std::unique_ptr< RexAbstractInput > parse_abstract_input(const rapidjson::Value &expr) noexcept
void alterRAForRender(std::vector< std::shared_ptr< RelAlgNode >> &nodes, const RenderQueryOptions &render_opts)
std::unique_ptr< RexSubQuery > deepCopy() const
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
JoinType
Definition: sqldefs.h:98
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
std::vector< std::unique_ptr< const RexScalar > > parse_window_order_exprs(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
std::vector< std::unique_ptr< const RexScalar > > table_func_inputs_
std::unique_ptr< const RexCase > disambiguate_case(const RexCase *rex_case, const RANodeOutput &ra_output)
void hoist_filter_cond_to_cross_join(std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:81
Definition: sqltypes.h:52
std::vector< std::unique_ptr< const RexScalar > > parse_expr_array(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
std::string json_node_to_string(const rapidjson::Value &node) noexcept
size_t size() const override
std::shared_ptr< const RelAlgNode > get_left_deep_join_root(const std::shared_ptr< RelAlgNode > &node)
void sink_projected_boolean_expr_to_join(std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
std::shared_ptr< RelProject > dispatchProject(const rapidjson::Value &proj_ra)
void eliminate_identical_copy(std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
const RexScalar * getElse() const
static thread_local unsigned crt_id_
std::shared_ptr< RelLogicalValues > dispatchLogicalValues(const rapidjson::Value &logical_values_ra)
std::pair< std::shared_ptr< RelLeftDeepInnerJoin >, std::shared_ptr< const RelAlgNode > > create_left_deep_join(const std::shared_ptr< RelAlgNode > &left_deep_join_root)
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
SQLAgg to_agg_kind(const std::string &agg_name)
const JoinType join_type_
std::vector< std::string > TargetColumnList
size_t size() const
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
const RexScalar * getOperand(const size_t idx) const
unsigned node_id(const rapidjson::Value &ra_node) noexcept
std::vector< const Rex * > col_inputs_
bool hasEquivCollationOf(const RelSort &that) const
const std::vector< std::string > fields_
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
std::string join(T const &container, std::string const &delim)
#define UNREACHABLE()
Definition: Logger.h:234
NullSortedPosition parse_nulls_position(const rapidjson::Value &collation)
#define CHECK_GE(x, y)
Definition: Logger.h:203
std::vector< std::string > fields_
Definition: sqldefs.h:49
std::vector< size_t > indices_from_json_array(const rapidjson::Value &json_idx_arr) noexcept
const RexScalar * getWhen(const size_t idx) const
void appendInput(std::string new_field_name, std::unique_ptr< const RexScalar > new_input)
std::unique_ptr< RexOperator > parse_operator(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
SqlWindowFunctionKind parse_window_function_kind(const std::string &name)
std::vector< RexInput > n_outputs(const RelAlgNode *node, const size_t n)
void set_scale(int s)
Definition: sqltypes.h:421
std::vector< std::unique_ptr< const RexScalar > > scalar_sources_
std::vector< SortField > parse_window_order_collation(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
std::shared_ptr< const RelAlgNode > deserialize_ra_dag(const std::string &query_ra, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor, const RenderQueryOptions *render_opts)
void simplify_sort(std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
std::vector< SortField > collation_
std::vector< RexInput > RANodeOutput
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
void set_precision(int d)
Definition: sqltypes.h:419
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
SQLOps getOperator() const
CHECK(cgen_state)
std::shared_ptr< RelAlgNode > deepCopy() const override
const size_t offset_
void create_compound(std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< size_t > &pattern) noexcept
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
bool isRenamedInput(const RelAlgNode *node, const size_t index, const std::string &new_name)
SQLOps to_sql_op(const std::string &op_str)
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39
std::vector< std::unique_ptr< const RexScalar > > scalar_exprs_
std::unique_ptr< RexCase > parse_case(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
const double json_double(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:54
std::shared_ptr< RelAlgNode > deepCopy() const override
std::vector< std::shared_ptr< const RelAlgNode > > getRelAlgInputs(const rapidjson::Value &node)
std::set< std::pair< const RelAlgNode *, int > > get_equiv_cols(const RelAlgNode *node, const size_t which_col)
size_t branchCount() const
const RelAlgNode * getInput(const size_t idx) const
std::shared_ptr< RelAlgNode > deepCopy() const override
void bind_inputs(const std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
std::shared_ptr< RelJoin > dispatchJoin(const rapidjson::Value &join_ra)
std::unique_ptr< const RexScalar > filter_
bool isSimple() const
std::vector< std::string > strings_from_json_array(const rapidjson::Value &json_str_arr) noexcept
std::tuple< const rapidjson::Value *, SQLTypeInfo, SQLTypeInfo > parse_literal(const rapidjson::Value &expr)
RexWindowFunctionOperator::RexWindowBound parse_window_bound(const rapidjson::Value &window_bound_obj, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor)
std::vector< std::string > fields_
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
const RexScalar * aggregateResult(const RexScalar *const &aggregate, const RexScalar *const &next_result) const final
void separate_window_function_expressions(std::vector< std::shared_ptr< RelAlgNode >> &nodes)
virtual void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input)
std::shared_ptr< RelSort > dispatchSort(const rapidjson::Value &sort_ra)
const RexScalar * visitOperator(const RexOperator *rex_operator) const final
std::shared_ptr< RelAggregate > dispatchAggregate(const rapidjson::Value &agg_ra)
std::vector< std::unique_ptr< const RexAgg > > agg_exprs_
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
std::shared_ptr< RelAlgNode > deepCopy() const override
bool isEmptyResult() const
std::shared_ptr< RelModify > dispatchModify(const rapidjson::Value &logical_modify_ra)
const RexScalar * getProjectAt(const size_t idx) const
#define CHECK_LT(x, y)
Definition: Logger.h:200
Definition: sqltypes.h:55
Definition: sqltypes.h:56
const ConstRexScalarPtrVector & getPartitionKeys() const
#define CHECK_LE(x, y)
Definition: Logger.h:201
const std::vector< const Rex * > target_exprs_
std::vector< std::string > getFieldNamesFromScanNode(const rapidjson::Value &scan_ra) const
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
void coalesce_nodes(std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< const RelAlgNode * > &left_deep_joins)
std::vector< std::unique_ptr< const RexAgg > > agg_exprs_
bool input_can_be_coalesced(const RelAlgNode *parent_node, const size_t index, const bool first_rex_is_input)
std::unique_ptr< const RexOperator > disambiguate_operator(const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
std::unique_ptr< const RexScalar > filter_expr_
void setSourceNode(const RelAlgNode *node) const
void bind_table_func_to_input(RelTableFunction *table_func_node, const RANodeOutput &input) noexcept
virtual size_t size() const =0
const RelAlgNode * getSourceNode() const
void setExecutionResult(const std::shared_ptr< const ExecutionResult > result)
void check_empty_inputs_field(const rapidjson::Value &node) noexcept
SqlWindowFunctionKind
Definition: sqldefs.h:73
RexRebindInputsVisitor(const RelAlgNode *old_input, const RelAlgNode *new_input)
Definition: sqldefs.h:53
const std::vector< std::string > & getFields() const
RANodeOutput get_node_output(const RelAlgNode *ra_node)
JoinType to_join_type(const std::string &join_type_name)
virtual std::string toString() const =0
std::shared_ptr< const RelAlgNode > ra_interpret(const rapidjson::Value &query_ast, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor, const RenderQueryOptions *render_opts)
int64_t get_int_literal_field(const rapidjson::Value &obj, const char field[], const int64_t default_val) noexcept
std::string tree_string(const RelAlgNode *ra, const size_t indent)
std::vector< const Rex * > reproject_targets(const RelProject *simple_project, const std::vector< const Rex * > &target_exprs) noexcept
std::shared_ptr< const RelAlgNode > prev(const rapidjson::Value &crt_node)
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
std::shared_ptr< RelScan > dispatchTableScan(const rapidjson::Value &scan_ra)
void fold_filters(std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
const size_t inputCount() const
specifies the content in-memory of a row in the table metadata table
void rebind_inputs_from_left_deep_join(const RexScalar *rex, const RelLeftDeepInnerJoin *left_deep_join)
std::shared_ptr< RelFilter > dispatchFilter(const rapidjson::Value &filter_ra)
size_t operator()(const std::pair< const RelAlgNode *, int > &input_col) const
std::shared_ptr< RelAlgNode > deepCopy() const override
SortDirection parse_sort_direction(const rapidjson::Value &collation)
std::unique_ptr< const RexAgg > parse_aggregate_expr(const rapidjson::Value &expr)
std::vector< std::string > fields_
RelAlgAbstractInterpreter(const rapidjson::Value &query_ast, const Catalog_Namespace::Catalog &cat, RelAlgExecutor *ra_executor, const RenderQueryOptions *render_opts)
void mark_nops(const std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
std::unique_ptr< const RexScalar > RetType
Definition: RexVisitor.h:139
std::shared_ptr< RelAlgNode > deepCopy() const override
std::shared_ptr< RelTableFunction > dispatchTableFunction(const rapidjson::Value &table_func_ra)
RexInputReplacementVisitor(const RelAlgNode *node_to_keep, const std::vector< std::unique_ptr< const RexScalar >> &scalar_sources)
void eliminate_dead_columns(std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
std::shared_ptr< RelAlgNode > deepCopy() const override
std::vector< std::unique_ptr< const RexScalar > > target_exprs_
const TableDescriptor * getTableFromScanNode(const rapidjson::Value &scan_ra) const
static void resetRelAlgFirstId() noexcept