OmniSciDB  085a039ca4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RelAlgDagBuilder.h
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 
22 #pragma once
23 
24 #include <atomic>
25 #include <iterator>
26 #include <memory>
27 #include <optional>
28 #include <unordered_map>
29 
30 #include <rapidjson/document.h>
31 #include <boost/core/noncopyable.hpp>
32 #include <boost/functional/hash.hpp>
33 
34 #include "Catalog/Catalog.h"
35 #include "QueryEngine/QueryHint.h"
39 #include "QueryHint.h"
40 #include "Shared/toString.h"
41 #include "Utils/FsiUtils.h"
42 
43 using ColumnNameList = std::vector<std::string>;
44 static auto const HASH_N = boost::hash_value("n");
45 
47  bool skip_input_nodes{false};
48 
50 };
51 
52 class Rex {
53  public:
54  virtual std::string toString(RelRexToStringConfig config) const = 0;
55 
56  // return hashed value of string representation of this rex
57  virtual size_t toHash() const = 0;
58 
59  virtual ~Rex() {}
60 
61  protected:
62  mutable std::optional<size_t> hash_;
63 };
64 
65 class RexScalar : public Rex {};
66 // For internal use of the abstract interpreter only. The result after abstract
67 // interpretation will not have any references to 'RexAbstractInput' objects.
68 class RexAbstractInput : public RexScalar {
69  public:
70  RexAbstractInput(const unsigned in_index) : in_index_(in_index) {}
71 
72  unsigned getIndex() const { return in_index_; }
73 
74  void setIndex(const unsigned in_index) const { in_index_ = in_index; }
75 
76  std::string toString(
77  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
78  return cat(::typeName(this), "(", std::to_string(in_index_), ")");
79  }
80 
81  size_t toHash() const override {
82  if (!hash_) {
83  hash_ = typeid(RexAbstractInput).hash_code();
84  boost::hash_combine(*hash_, in_index_);
85  }
86  return *hash_;
87  }
88 
89  private:
90  mutable unsigned in_index_;
91 };
92 
93 class RexLiteral : public RexScalar {
94  public:
95  RexLiteral(const int64_t val,
96  const SQLTypes type,
97  const SQLTypes target_type,
98  const unsigned scale,
99  const unsigned precision,
100  const unsigned target_scale,
101  const unsigned target_precision)
102  : literal_(val)
103  , type_(type)
104  , target_type_(target_type)
105  , scale_(scale)
106  , precision_(precision)
107  , target_scale_(target_scale)
108  , target_precision_(target_precision) {
109  CHECK(type == kDECIMAL || type == kINTERVAL_DAY_TIME ||
110  type == kINTERVAL_YEAR_MONTH || is_datetime(type) || type == kBIGINT ||
111  type == kINT);
112  }
113 
114  RexLiteral(const double val,
115  const SQLTypes type,
116  const SQLTypes target_type,
117  const unsigned scale,
118  const unsigned precision,
119  const unsigned target_scale,
120  const unsigned target_precision)
121  : literal_(val)
122  , type_(type)
123  , target_type_(target_type)
124  , scale_(scale)
125  , precision_(precision)
126  , target_scale_(target_scale)
127  , target_precision_(target_precision) {
128  CHECK_EQ(kDOUBLE, type);
129  }
130 
131  RexLiteral(const std::string& val,
132  const SQLTypes type,
133  const SQLTypes target_type,
134  const unsigned scale,
135  const unsigned precision,
136  const unsigned target_scale,
137  const unsigned target_precision)
138  : literal_(val)
139  , type_(type)
140  , target_type_(target_type)
141  , scale_(scale)
142  , precision_(precision)
143  , target_scale_(target_scale)
144  , target_precision_(target_precision) {
145  CHECK_EQ(kTEXT, type);
146  }
147 
148  RexLiteral(const bool val,
149  const SQLTypes type,
150  const SQLTypes target_type,
151  const unsigned scale,
152  const unsigned precision,
153  const unsigned target_scale,
154  const unsigned target_precision)
155  : literal_(val)
156  , type_(type)
157  , target_type_(target_type)
158  , scale_(scale)
159  , precision_(precision)
160  , target_scale_(target_scale)
161  , target_precision_(target_precision) {
162  CHECK_EQ(kBOOLEAN, type);
163  }
164 
165  RexLiteral(const SQLTypes target_type)
166  : literal_(nullptr)
167  , type_(kNULLT)
168  , target_type_(target_type)
169  , scale_(0)
170  , precision_(0)
171  , target_scale_(0)
172  , target_precision_(0) {}
173 
174  template <class T>
175  T getVal() const {
176  const auto ptr = boost::get<T>(&literal_);
177  CHECK(ptr);
178  return *ptr;
179  }
180 
181  SQLTypes getType() const { return type_; }
182 
183  SQLTypes getTargetType() const { return target_type_; }
184 
185  unsigned getScale() const { return scale_; }
186 
187  unsigned getPrecision() const { return precision_; }
188 
189  unsigned getTargetScale() const { return target_scale_; }
190 
191  unsigned getTargetPrecision() const { return target_precision_; }
192 
193  std::string toString(
194  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
195  std::ostringstream oss;
196  oss << "RexLiteral(" << literal_ << " type=" << type_ << '(' << precision_ << ','
197  << scale_ << ") target_type=" << target_type_ << '(' << target_precision_ << ','
198  << target_scale_ << "))";
199  return oss.str();
200  }
201 
202  size_t toHash() const override {
203  if (!hash_) {
204  hash_ = typeid(RexLiteral).hash_code();
205  boost::hash_combine(*hash_, literal_);
206  boost::hash_combine(*hash_, type_);
207  boost::hash_combine(*hash_, target_type_);
208  boost::hash_combine(*hash_, scale_);
209  boost::hash_combine(*hash_, precision_);
210  boost::hash_combine(*hash_, target_scale_);
211  boost::hash_combine(*hash_, target_precision_);
212  }
213  return *hash_;
214  }
215 
216  std::unique_ptr<RexLiteral> deepCopy() const {
217  return std::make_unique<RexLiteral>(*this);
218  }
219 
220  private:
221  const boost::variant<int64_t, double, std::string, bool, void*> literal_;
224  const unsigned scale_;
225  const unsigned precision_;
226  const unsigned target_scale_;
227  const unsigned target_precision_;
228 };
229 
230 using RexLiteralArray = std::vector<RexLiteral>;
231 using TupleContentsArray = std::vector<RexLiteralArray>;
232 
233 class RexOperator : public RexScalar {
234  public:
235  RexOperator(const SQLOps op,
236  std::vector<std::unique_ptr<const RexScalar>>& operands,
237  const SQLTypeInfo& type)
238  : op_(op), operands_(std::move(operands)), type_(type) {}
239 
240  virtual std::unique_ptr<const RexOperator> getDisambiguated(
241  std::vector<std::unique_ptr<const RexScalar>>& operands) const {
242  return std::unique_ptr<const RexOperator>(new RexOperator(op_, operands, type_));
243  }
244 
245  size_t size() const { return operands_.size(); }
246 
247  const RexScalar* getOperand(const size_t idx) const {
248  CHECK(idx < operands_.size());
249  return operands_[idx].get();
250  }
251 
252  const RexScalar* getOperandAndRelease(const size_t idx) const {
253  CHECK(idx < operands_.size());
254  return operands_[idx].release();
255  }
256 
257  SQLOps getOperator() const { return op_; }
258 
259  const SQLTypeInfo& getType() const { return type_; }
260 
261  std::string toString(
262  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
263  auto ret = cat(::typeName(this), "(", std::to_string(op_), ", operands=");
264  for (auto& operand : operands_) {
265  ret += operand->toString(config) + " ";
266  }
267  return cat(ret, ", type=", type_.to_string(), ")");
268  };
269 
270  size_t toHash() const override {
271  if (!hash_) {
272  hash_ = typeid(RexOperator).hash_code();
273  boost::hash_combine(*hash_, op_);
274  for (auto& operand : operands_) {
275  boost::hash_combine(*hash_, operand->toHash());
276  }
277  boost::hash_combine(*hash_, getType().get_type_name());
278  }
279  return *hash_;
280  }
281 
282  protected:
283  const SQLOps op_;
284  mutable std::vector<std::unique_ptr<const RexScalar>> operands_;
286 };
287 
288 class RelAlgNode;
289 using RelAlgInputs = std::vector<std::shared_ptr<const RelAlgNode>>;
290 
291 class ExecutionResult;
292 
293 class RexSubQuery : public RexScalar {
294  public:
295  RexSubQuery(const std::shared_ptr<const RelAlgNode> ra)
296  : type_(new SQLTypeInfo(kNULLT, false))
297  , result_(new std::shared_ptr<const ExecutionResult>(nullptr))
298  , ra_(ra) {}
299 
300  // for deep copy
301  RexSubQuery(std::shared_ptr<SQLTypeInfo> type,
302  std::shared_ptr<std::shared_ptr<const ExecutionResult>> result,
303  const std::shared_ptr<const RelAlgNode> ra)
304  : type_(type), result_(result), ra_(ra) {}
305 
306  RexSubQuery(const RexSubQuery&) = delete;
307 
308  RexSubQuery& operator=(const RexSubQuery&) = delete;
309 
310  RexSubQuery(RexSubQuery&&) = delete;
311 
312  RexSubQuery& operator=(RexSubQuery&&) = delete;
313 
314  const SQLTypeInfo& getType() const {
315  CHECK_NE(kNULLT, type_->get_type());
316  return *(type_.get());
317  }
318 
319  std::shared_ptr<const ExecutionResult> getExecutionResult() const {
320  CHECK(result_);
321  CHECK(result_.get());
322  return *(result_.get());
323  }
324 
325  unsigned getId() const;
326 
327  const RelAlgNode* getRelAlg() const { return ra_.get(); }
328 
329  std::string toString(
330  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override;
331 
332  size_t toHash() const override;
333 
334  std::unique_ptr<RexSubQuery> deepCopy() const;
335 
336  void setExecutionResult(const std::shared_ptr<const ExecutionResult> result);
337 
338  private:
339  std::shared_ptr<SQLTypeInfo> type_;
340  std::shared_ptr<std::shared_ptr<const ExecutionResult>> result_;
341  const std::shared_ptr<const RelAlgNode> ra_;
342 };
343 
344 // The actual input node understood by the Executor.
345 // The in_index_ is relative to the output of node_.
346 class RexInput : public RexAbstractInput {
347  public:
348  RexInput(const RelAlgNode* node, const unsigned in_index)
349  : RexAbstractInput(in_index), node_(node) {}
350 
351  const RelAlgNode* getSourceNode() const { return node_; }
352 
353  // This isn't great, but we need it for coalescing nodes to Compound since
354  // RexInput in descendents need to be rebound to the newly created Compound.
355  // Maybe create a fresh RA tree with the required changes after each coalescing?
356  void setSourceNode(const RelAlgNode* node) const { node_ = node; }
357 
358  bool operator==(const RexInput& that) const {
359  return getSourceNode() == that.getSourceNode() && getIndex() == that.getIndex();
360  }
361 
362  std::string toString(
363  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override;
364 
365  size_t toHash() const override;
366 
367  std::unique_ptr<RexInput> deepCopy() const {
368  return std::make_unique<RexInput>(node_, getIndex());
369  }
370 
371  private:
372  mutable const RelAlgNode* node_;
373 };
374 
375 namespace std {
376 
377 template <>
378 struct hash<RexInput> {
379  size_t operator()(const RexInput& rex_in) const {
380  auto addr = rex_in.getSourceNode();
381  return *reinterpret_cast<const size_t*>(may_alias_ptr(&addr)) ^ rex_in.getIndex();
382  }
383 };
384 
385 } // namespace std
386 
387 // Not a real node created by Calcite. Created by us because CaseExpr is a node in our
388 // Analyzer.
389 class RexCase : public RexScalar {
390  public:
391  RexCase(std::vector<std::pair<std::unique_ptr<const RexScalar>,
392  std::unique_ptr<const RexScalar>>>& expr_pair_list,
393  std::unique_ptr<const RexScalar>& else_expr)
394  : expr_pair_list_(std::move(expr_pair_list)), else_expr_(std::move(else_expr)) {}
395 
396  size_t branchCount() const { return expr_pair_list_.size(); }
397 
398  const RexScalar* getWhen(const size_t idx) const {
399  CHECK(idx < expr_pair_list_.size());
400  return expr_pair_list_[idx].first.get();
401  }
402 
403  const RexScalar* getThen(const size_t idx) const {
404  CHECK(idx < expr_pair_list_.size());
405  return expr_pair_list_[idx].second.get();
406  }
407 
408  const RexScalar* getElse() const { return else_expr_.get(); }
409 
410  std::string toString(
411  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
412  auto ret = cat(::typeName(this), "(expr_pair_list=");
413  for (auto& expr : expr_pair_list_) {
414  ret += expr.first->toString(config) + " " + expr.second->toString(config) + " ";
415  }
416  return cat(
417  ret, ", else_expr=", (else_expr_ ? else_expr_->toString(config) : "null"), ")");
418  }
419 
420  size_t toHash() const override {
421  if (!hash_) {
422  hash_ = typeid(RexCase).hash_code();
423  for (size_t i = 0; i < branchCount(); ++i) {
424  boost::hash_combine(*hash_, getWhen(i)->toHash());
425  boost::hash_combine(*hash_, getThen(i)->toHash());
426  }
427  boost::hash_combine(*hash_, getElse() ? getElse()->toHash() : HASH_N);
428  }
429  return *hash_;
430  }
431 
432  private:
433  std::vector<
434  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
436  std::unique_ptr<const RexScalar> else_expr_;
437 };
438 
440  public:
441  using ConstRexScalarPtr = std::unique_ptr<const RexScalar>;
442  using ConstRexScalarPtrVector = std::vector<ConstRexScalarPtr>;
443 
444  RexFunctionOperator(const std::string& name,
445  ConstRexScalarPtrVector& operands,
446  const SQLTypeInfo& ti)
447  : RexOperator(kFUNCTION, operands, ti), name_(name) {}
448 
449  std::unique_ptr<const RexOperator> getDisambiguated(
450  std::vector<std::unique_ptr<const RexScalar>>& operands) const override {
451  return std::unique_ptr<const RexOperator>(
452  new RexFunctionOperator(name_, operands, getType()));
453  }
454 
455  const std::string& getName() const { return name_; }
456 
457  std::string toString(
458  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
459  auto ret = cat(::typeName(this), "(", name_, ", operands=");
460  for (auto& operand : operands_) {
461  ret += operand->toString(config) + " ";
462  }
463  return cat(ret, ")");
464  }
465 
466  size_t toHash() const override {
467  if (!hash_) {
468  hash_ = typeid(RexFunctionOperator).hash_code();
469  boost::hash_combine(*hash_, ::toString(op_));
470  boost::hash_combine(*hash_, getType().get_type_name());
471  for (auto& operand : operands_) {
472  boost::hash_combine(*hash_, operand->toHash());
473  }
474  boost::hash_combine(*hash_, name_);
475  }
476  return *hash_;
477  }
478 
479  private:
480  const std::string name_;
481 };
482 
484 
485 enum class NullSortedPosition { First, Last };
486 
487 class SortField {
488  public:
489  SortField(const size_t field,
490  const SortDirection sort_dir,
491  const NullSortedPosition nulls_pos)
492  : field_(field), sort_dir_(sort_dir), nulls_pos_(nulls_pos) {}
493 
494  bool operator==(const SortField& that) const {
495  return field_ == that.field_ && sort_dir_ == that.sort_dir_ &&
496  nulls_pos_ == that.nulls_pos_;
497  }
498 
499  size_t getField() const { return field_; }
500 
501  SortDirection getSortDir() const { return sort_dir_; }
502 
504 
505  std::string toString() const {
506  return cat(::typeName(this),
507  "(",
509  ", sort_dir=",
510  (sort_dir_ == SortDirection::Ascending ? "asc" : "desc"),
511  ", null_pos=",
512  (nulls_pos_ == NullSortedPosition::First ? "nulls_first" : "nulls_last"),
513  ")");
514  }
515 
516  size_t toHash() const {
517  auto hash = boost::hash_value(field_);
518  boost::hash_combine(hash, sort_dir_ == SortDirection::Ascending ? "a" : "d");
519  boost::hash_combine(hash, nulls_pos_ == NullSortedPosition::First ? "f" : "l");
520  return hash;
521  }
522 
523  private:
524  const size_t field_;
527 };
528 
530  public:
531  struct RexWindowBound {
532  bool unbounded;
533  bool preceding;
534  bool following;
536  std::shared_ptr<const RexScalar> offset;
538  };
539 
541  ConstRexScalarPtrVector& operands,
542  ConstRexScalarPtrVector& partition_keys,
543  ConstRexScalarPtrVector& order_keys,
544  const std::vector<SortField> collation,
547  const bool is_rows,
548  const SQLTypeInfo& ti)
549  : RexFunctionOperator(::toString(kind), operands, ti)
550  , kind_(kind)
551  , partition_keys_(std::move(partition_keys))
552  , order_keys_(std::move(order_keys))
553  , collation_(collation)
554  , lower_bound_(lower_bound)
555  , upper_bound_(upper_bound)
556  , is_rows_(is_rows) {}
557 
558  SqlWindowFunctionKind getKind() const { return kind_; }
559 
561 
563  return std::move(partition_keys_);
564  }
565 
567  return std::move(order_keys_);
568  }
569 
571 
572  void replacePartitionKey(size_t offset,
573  std::unique_ptr<const RexScalar>&& new_partition_key) {
574  CHECK_LT(offset, partition_keys_.size());
575  partition_keys_[offset] = std::move(new_partition_key);
576  }
577 
578  void replaceOrderKey(size_t offset, std::unique_ptr<const RexScalar>&& new_order_key) {
579  CHECK_LT(offset, order_keys_.size());
580  order_keys_[offset] = std::move(new_order_key);
581  }
582 
583  void replaceOperands(std::vector<std::unique_ptr<const RexScalar>>&& new_operands) {
584  operands_ = std::move(new_operands);
585  }
586 
587  const std::vector<SortField>& getCollation() const { return collation_; }
588 
589  const RexWindowBound& getLowerBound() const { return lower_bound_; }
590 
591  const RexWindowBound& getUpperBound() const { return upper_bound_; }
592 
593  bool isRows() const { return is_rows_; }
594 
595  std::unique_ptr<const RexOperator> disambiguatedOperands(
596  ConstRexScalarPtrVector& operands,
597  ConstRexScalarPtrVector& partition_keys,
598  ConstRexScalarPtrVector& order_keys,
599  const std::vector<SortField>& collation) const {
600  return std::unique_ptr<const RexOperator>(
602  operands,
603  partition_keys,
604  order_keys,
605  collation,
606  getLowerBound(),
607  getUpperBound(),
608  isRows(),
609  getType()));
610  }
611 
612  std::string toString(
613  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
614  auto ret = cat(::typeName(this), "(", getName(), ", operands=");
615  for (auto& operand : operands_) {
616  ret += operand->toString(config) + " ";
617  }
618  ret += ", partition_keys=";
619  for (auto& key : partition_keys_) {
620  ret += key->toString(config) + " ";
621  }
622  ret += ", order_keys=";
623  for (auto& key : order_keys_) {
624  ret += key->toString(config) + " ";
625  }
626  return cat(ret, ")");
627  }
628 
629  size_t toHash() const override {
630  if (!hash_) {
631  hash_ = typeid(RexWindowFunctionOperator).hash_code();
632  boost::hash_combine(*hash_, getType().get_type_name());
633  boost::hash_combine(*hash_, getName());
634  boost::hash_combine(*hash_, is_rows_);
635  for (auto& collation : collation_) {
636  boost::hash_combine(*hash_, collation.toHash());
637  }
638  for (auto& operand : operands_) {
639  boost::hash_combine(*hash_, operand->toHash());
640  }
641  for (auto& key : partition_keys_) {
642  boost::hash_combine(*hash_, key->toHash());
643  }
644  for (auto& key : order_keys_) {
645  boost::hash_combine(*hash_, key->toHash());
646  }
647  auto get_window_bound_hash =
649  auto h = boost::hash_value(bound.offset ? bound.offset->toHash() : HASH_N);
650  boost::hash_combine(h, bound.unbounded);
651  boost::hash_combine(h, bound.preceding);
652  boost::hash_combine(h, bound.following);
653  boost::hash_combine(h, bound.is_current_row);
654  boost::hash_combine(h, bound.order_key);
655  return h;
656  };
657  boost::hash_combine(*hash_, get_window_bound_hash(lower_bound_));
658  boost::hash_combine(*hash_, get_window_bound_hash(upper_bound_));
659  }
660  return *hash_;
661  }
662 
663  private:
667  const std::vector<SortField> collation_;
670  const bool is_rows_;
671 };
672 
673 // Not a real node created by Calcite. Created by us because targets of a query
674 // should reference the group by expressions instead of creating completely new one.
675 class RexRef : public RexScalar {
676  public:
677  RexRef(const size_t index) : index_(index) {}
678 
679  size_t getIndex() const { return index_; }
680 
681  std::string toString(
682  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
683  return cat(::typeName(this), "(", std::to_string(index_), ")");
684  }
685 
686  size_t toHash() const override {
687  if (!hash_) {
688  hash_ = typeid(RexRef).hash_code();
689  boost::hash_combine(*hash_, index_);
690  }
691  return *hash_;
692  }
693 
694  std::unique_ptr<RexRef> deepCopy() const { return std::make_unique<RexRef>(index_); }
695 
696  private:
697  const size_t index_;
698 };
699 
700 class RexAgg : public Rex {
701  public:
702  RexAgg(const SQLAgg agg,
703  const bool distinct,
704  const SQLTypeInfo& type,
705  const std::vector<size_t>& operands)
706  : agg_(agg), distinct_(distinct), type_(type), operands_(operands) {}
707 
708  std::string toString(
709  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
710  return cat(::typeName(this),
711  "(agg=",
713  ", distinct=",
715  ", type=",
717  ", operands=",
719  ")");
720  }
721 
722  size_t toHash() const override {
723  if (!hash_) {
724  hash_ = typeid(RexAgg).hash_code();
725  for (auto& operand : operands_) {
726  boost::hash_combine(*hash_, operand);
727  }
728  boost::hash_combine(*hash_, agg_);
729  boost::hash_combine(*hash_, distinct_);
730  boost::hash_combine(*hash_, type_.get_type_name());
731  }
732  return *hash_;
733  }
734 
735  SQLAgg getKind() const { return agg_; }
736 
737  bool isDistinct() const { return distinct_; }
738 
739  size_t size() const { return operands_.size(); }
740 
741  size_t getOperand(size_t idx) const { return operands_[idx]; }
742 
743  const SQLTypeInfo& getType() const { return type_; }
744 
745  std::unique_ptr<RexAgg> deepCopy() const {
746  return std::make_unique<RexAgg>(agg_, distinct_, type_, operands_);
747  }
748 
749  private:
750  const SQLAgg agg_;
751  const bool distinct_;
753  const std::vector<size_t> operands_;
754 };
755 
756 class RaExecutionDesc;
757 
758 class RelAlgNode {
759  public:
761  : inputs_(std::move(inputs))
762  , id_(crt_id_++)
763  , id_in_plan_tree_(std::nullopt)
764  , context_data_(nullptr)
765  , is_nop_(false)
766  , query_plan_dag_("")
767  , query_plan_dag_hash_(0) {}
768 
769  virtual ~RelAlgNode() {}
770 
772  context_data_ = nullptr;
773  targets_metainfo_ = {};
774  }
775 
776  void setContextData(const RaExecutionDesc* context_data) const {
778  context_data_ = context_data;
779  }
780 
781  void setOutputMetainfo(const std::vector<TargetMetaInfo>& targets_metainfo) const {
782  targets_metainfo_ = targets_metainfo;
783  }
784 
785  void setQueryPlanDag(const std::string& extracted_query_plan_dag) const {
786  if (!extracted_query_plan_dag.empty()) {
787  query_plan_dag_ = extracted_query_plan_dag;
788  query_plan_dag_hash_ = boost::hash_value(extracted_query_plan_dag);
789  }
790  }
791 
792  std::string getQueryPlanDag() const { return query_plan_dag_; }
793 
794  size_t getQueryPlanDagHash() const { return query_plan_dag_hash_; }
795 
796  const std::vector<TargetMetaInfo>& getOutputMetainfo() const {
797  return targets_metainfo_;
798  }
799 
800  unsigned getId() const { return id_; }
801 
802  void setIdInPlanTree(size_t id) const { id_in_plan_tree_ = id; }
803 
804  std::optional<size_t> getIdInPlanTree() const { return id_in_plan_tree_; }
805 
806  bool hasContextData() const { return !(context_data_ == nullptr); }
807 
808  const RaExecutionDesc* getContextData() const { return context_data_; }
809 
810  const size_t inputCount() const { return inputs_.size(); }
811 
812  const RelAlgNode* getInput(const size_t idx) const {
813  CHECK_LT(idx, inputs_.size());
814  return inputs_[idx].get();
815  }
816 
817  std::shared_ptr<const RelAlgNode> getAndOwnInput(const size_t idx) const {
818  CHECK_LT(idx, inputs_.size());
819  return inputs_[idx];
820  }
821 
822  void addManagedInput(std::shared_ptr<const RelAlgNode> input) {
823  inputs_.push_back(input);
824  }
825 
826  bool hasInput(const RelAlgNode* needle) const {
827  for (auto& input_ptr : inputs_) {
828  if (input_ptr.get() == needle) {
829  return true;
830  }
831  }
832  return false;
833  }
834 
835  virtual void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
836  std::shared_ptr<const RelAlgNode> input) {
837  for (auto& input_ptr : inputs_) {
838  if (input_ptr == old_input) {
839  input_ptr = input;
840  break;
841  }
842  }
843  }
844 
845  // to keep an assigned DAG node id for data recycler
846  void setRelNodeDagId(const size_t id) const { dag_node_id_ = id; }
847 
848  size_t getRelNodeDagId() const { return dag_node_id_; }
849 
850  bool isNop() const { return is_nop_; }
851 
852  void markAsNop() { is_nop_ = true; }
853 
854  virtual std::string toString(RelRexToStringConfig config) const = 0;
855 
856  // return hashed value of a string representation of this rel node
857  virtual size_t toHash() const = 0;
858 
859  virtual size_t size() const = 0;
860 
861  virtual std::shared_ptr<RelAlgNode> deepCopy() const = 0;
862 
863  static void resetRelAlgFirstId() noexcept;
864 
869  void clearContextData() const { context_data_ = nullptr; }
870 
871  protected:
873  const unsigned id_;
874  mutable std::optional<size_t> id_in_plan_tree_;
875  mutable std::optional<size_t> hash_;
876 
877  private:
879  bool is_nop_;
880  mutable std::vector<TargetMetaInfo> targets_metainfo_;
881  static thread_local unsigned crt_id_;
882  mutable size_t dag_node_id_;
883  mutable std::string query_plan_dag_;
884  mutable size_t query_plan_dag_hash_;
885 };
886 
887 class RelScan : public RelAlgNode {
888  public:
889  RelScan(const TableDescriptor* td, const std::vector<std::string>& field_names)
890  : td_(td)
891  , field_names_(field_names)
893  , hints_(std::make_unique<Hints>()) {}
894 
895  size_t size() const override { return field_names_.size(); }
896 
897  const TableDescriptor* getTableDescriptor() const { return td_; }
898 
899  const size_t getNumFragments() const { return td_->fragmenter->getNumFragments(); }
900 
901  const size_t getNumShards() const { return td_->nShards; }
902 
903  const std::vector<std::string>& getFieldNames() const { return field_names_; }
904 
905  const std::string getFieldName(const size_t i) const { return field_names_[i]; }
906 
907  std::string toString(
908  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
909  return cat(
910  ::typeName(this), "(", td_->tableName, ", ", ::toString(field_names_), ")");
911  }
912 
913  size_t toHash() const override {
914  if (!hash_) {
915  hash_ = typeid(RelScan).hash_code();
916  boost::hash_combine(*hash_, td_->tableId);
917  boost::hash_combine(*hash_, td_->tableName);
918  boost::hash_combine(*hash_, ::toString(field_names_));
919  }
920  return *hash_;
921  }
922 
923  std::shared_ptr<RelAlgNode> deepCopy() const override {
924  CHECK(false);
925  return nullptr;
926  };
927 
928  void addHint(const ExplainedQueryHint& hint_explained) {
929  if (!hint_applied_) {
930  hint_applied_ = true;
931  }
932  hints_->emplace(hint_explained.getHint(), hint_explained);
933  }
934 
935  const bool hasHintEnabled(const QueryHint candidate_hint) const {
936  if (hint_applied_ && !hints_->empty()) {
937  return hints_->find(candidate_hint) != hints_->end();
938  }
939  return false;
940  }
941 
944  CHECK(!hints_->empty());
945  CHECK(hasHintEnabled(hint));
946  return hints_->at(hint);
947  }
948 
949  bool hasDeliveredHint() { return !hints_->empty(); }
950 
951  Hints* getDeliveredHints() { return hints_.get(); }
952 
953  private:
955  const std::vector<std::string> field_names_;
957  std::unique_ptr<Hints> hints_;
958 };
959 
961  public:
962  ModifyManipulationTarget(bool const update_via_select = false,
963  bool const delete_via_select = false,
964  bool const varlen_update_required = false,
965  TableDescriptor const* table_descriptor = nullptr,
966  ColumnNameList target_columns = ColumnNameList())
967  : is_update_via_select_(update_via_select)
968  , is_delete_via_select_(delete_via_select)
969  , varlen_update_required_(varlen_update_required)
970  , table_descriptor_(table_descriptor)
971  , target_columns_(target_columns) {}
972 
977  }
978  void forceRowwiseOutput() const { force_rowwise_output_ = true; }
979 
982  table_descriptor_ = td;
983  }
984 
985  auto const isUpdateViaSelect() const { return is_update_via_select_; }
986  auto const isDeleteViaSelect() const { return is_delete_via_select_; }
987  auto const isVarlenUpdateRequired() const { return varlen_update_required_; }
988  auto const isRowwiseOutputForced() const { return force_rowwise_output_; }
989 
990  void setTargetColumns(ColumnNameList const& target_columns) const {
991  target_columns_ = target_columns;
992  }
994 
995  template <typename VALIDATION_FUNCTOR>
996  bool validateTargetColumns(VALIDATION_FUNCTOR validator) const {
997  for (auto const& column_name : target_columns_) {
998  if (validator(column_name) == false) {
999  return false;
1000  }
1001  }
1002  return true;
1003  }
1004 
1005  private:
1006  mutable bool is_update_via_select_ = false;
1007  mutable bool is_delete_via_select_ = false;
1008  mutable bool varlen_update_required_ = false;
1009  mutable TableDescriptor const* table_descriptor_ = nullptr;
1011  mutable bool force_rowwise_output_ = false;
1012 };
1013 
1015  public:
1016  friend class RelModify;
1017  using ConstRexScalarPtr = std::unique_ptr<const RexScalar>;
1018  using ConstRexScalarPtrVector = std::vector<ConstRexScalarPtr>;
1019 
1020  // Takes memory ownership of the expressions.
1021  RelProject(std::vector<std::unique_ptr<const RexScalar>>& scalar_exprs,
1022  const std::vector<std::string>& fields,
1023  std::shared_ptr<const RelAlgNode> input)
1025  , scalar_exprs_(std::move(scalar_exprs))
1026  , fields_(fields)
1027  , hint_applied_(false)
1028  , hints_(std::make_unique<Hints>()) {
1029  inputs_.push_back(input);
1030  }
1031 
1032  RelProject(RelProject const&);
1033 
1034  void setExpressions(std::vector<std::unique_ptr<const RexScalar>>& exprs) const {
1035  scalar_exprs_ = std::move(exprs);
1036  }
1037 
1038  // True iff all the projected expressions are inputs. If true,
1039  // this node can be elided and merged into the previous node
1040  // since it's just a subset and / or permutation of its outputs.
1041  bool isSimple() const {
1042  for (const auto& expr : scalar_exprs_) {
1043  if (!dynamic_cast<const RexInput*>(expr.get())) {
1044  return false;
1045  }
1046  }
1047  return true;
1048  }
1049 
1050  bool isIdentity() const;
1051 
1052  bool isRenaming() const;
1053 
1054  size_t size() const override { return scalar_exprs_.size(); }
1055 
1056  const RexScalar* getProjectAt(const size_t idx) const {
1057  CHECK(idx < scalar_exprs_.size());
1058  return scalar_exprs_[idx].get();
1059  }
1060 
1061  const RexScalar* getProjectAtAndRelease(const size_t idx) const {
1062  CHECK(idx < scalar_exprs_.size());
1063  return scalar_exprs_[idx].release();
1064  }
1065 
1066  std::vector<std::unique_ptr<const RexScalar>> getExpressionsAndRelease() {
1067  return std::move(scalar_exprs_);
1068  }
1069 
1070  const std::vector<std::string>& getFields() const { return fields_; }
1071  void setFields(std::vector<std::string>&& fields) { fields_ = std::move(fields); }
1072 
1073  const std::string getFieldName(const size_t i) const { return fields_[i]; }
1074 
1075  void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
1076  std::shared_ptr<const RelAlgNode> input) override {
1077  replaceInput(old_input, input, std::nullopt);
1078  }
1079 
1080  void replaceInput(
1081  std::shared_ptr<const RelAlgNode> old_input,
1082  std::shared_ptr<const RelAlgNode> input,
1083  std::optional<std::unordered_map<unsigned, unsigned>> old_to_new_index_map);
1084 
1085  void appendInput(std::string new_field_name,
1086  std::unique_ptr<const RexScalar> new_input);
1087 
1088  std::string toString(
1089  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1090  auto ret = cat(::typeName(this), "(");
1091  for (auto& expr : scalar_exprs_) {
1092  ret += expr->toString(config) + " ";
1093  }
1094  return cat(ret, ", ", ::toString(fields_), ")");
1095  }
1096 
1097  size_t toHash() const override {
1098  if (!hash_) {
1099  hash_ = typeid(RelProject).hash_code();
1100  for (auto& target_expr : scalar_exprs_) {
1101  boost::hash_combine(*hash_, target_expr->toHash());
1102  }
1103  boost::hash_combine(*hash_, ::toString(fields_));
1104  }
1105  return *hash_;
1106  }
1107 
1108  std::shared_ptr<RelAlgNode> deepCopy() const override {
1109  return std::make_shared<RelProject>(*this);
1110  }
1111 
1112  bool hasWindowFunctionExpr() const;
1113 
1114  void addHint(const ExplainedQueryHint& hint_explained) {
1115  if (!hint_applied_) {
1116  hint_applied_ = true;
1117  }
1118  hints_->emplace(hint_explained.getHint(), hint_explained);
1119  }
1120 
1121  const bool hasHintEnabled(QueryHint candidate_hint) const {
1122  if (hint_applied_ && !hints_->empty()) {
1123  return hints_->find(candidate_hint) != hints_->end();
1124  }
1125  return false;
1126  }
1127 
1130  CHECK(!hints_->empty());
1131  CHECK(hasHintEnabled(hint));
1132  return hints_->at(hint);
1133  }
1134 
1135  bool hasDeliveredHint() { return !hints_->empty(); }
1136 
1137  Hints* getDeliveredHints() { return hints_.get(); }
1138 
1139  private:
1140  template <typename EXPR_VISITOR_FUNCTOR>
1141  void visitScalarExprs(EXPR_VISITOR_FUNCTOR visitor_functor) const {
1142  for (int i = 0; i < static_cast<int>(scalar_exprs_.size()); i++) {
1143  visitor_functor(i);
1144  }
1145  }
1146 
1149  scalar_exprs_.emplace_back(
1150  std::make_unique<RexFunctionOperator const>(std::string("OFFSET_IN_FRAGMENT"),
1151  transient_vector,
1152  SQLTypeInfo(kBIGINT, false)));
1153  fields_.emplace_back("EXPR$DELETE_OFFSET_IN_FRAGMENT");
1154  }
1155 
1156  mutable std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_;
1157  mutable std::vector<std::string> fields_;
1159  std::unique_ptr<Hints> hints_;
1160 };
1161 
1162 class RelAggregate : public RelAlgNode {
1163  public:
1164  // Takes ownership of the aggregate expressions.
1165  RelAggregate(const size_t groupby_count,
1166  std::vector<std::unique_ptr<const RexAgg>>& agg_exprs,
1167  const std::vector<std::string>& fields,
1168  std::shared_ptr<const RelAlgNode> input)
1169  : groupby_count_(groupby_count)
1170  , agg_exprs_(std::move(agg_exprs))
1171  , fields_(fields)
1172  , hint_applied_(false)
1173  , hints_(std::make_unique<Hints>()) {
1174  inputs_.push_back(input);
1175  }
1176 
1177  RelAggregate(RelAggregate const&);
1178 
1179  size_t size() const override { return groupby_count_ + agg_exprs_.size(); }
1180 
1181  const size_t getGroupByCount() const { return groupby_count_; }
1182 
1183  const size_t getAggExprsCount() const { return agg_exprs_.size(); }
1184 
1185  const std::vector<std::string>& getFields() const { return fields_; }
1186  void setFields(std::vector<std::string>&& new_fields) {
1187  fields_ = std::move(new_fields);
1188  }
1189 
1190  const std::string getFieldName(const size_t i) const { return fields_[i]; }
1191 
1192  std::vector<const RexAgg*> getAggregatesAndRelease() {
1193  std::vector<const RexAgg*> result;
1194  for (auto& agg_expr : agg_exprs_) {
1195  result.push_back(agg_expr.release());
1196  }
1197  return result;
1198  }
1199 
1200  std::vector<std::unique_ptr<const RexAgg>> getAggExprsAndRelease() {
1201  return std::move(agg_exprs_);
1202  }
1203 
1204  const std::vector<std::unique_ptr<const RexAgg>>& getAggExprs() const {
1205  return agg_exprs_;
1206  }
1207 
1208  void setAggExprs(std::vector<std::unique_ptr<const RexAgg>>& agg_exprs) {
1209  agg_exprs_ = std::move(agg_exprs);
1210  }
1211 
1212  std::string toString(
1213  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1214  auto ret = cat(::typeName(this),
1215  "(",
1217  ", agg_exprs=",
1218  ::toString(agg_exprs_),
1219  ", fields=",
1220  ::toString(fields_));
1221  if (!config.skip_input_nodes) {
1222  ret += ::toString(inputs_);
1223  } else {
1224  ret += ", input node id={";
1225  for (auto& input : inputs_) {
1226  auto node_id_in_plan = input->getIdInPlanTree();
1227  auto node_id_str = node_id_in_plan ? std::to_string(*node_id_in_plan)
1228  : std::to_string(input->getId());
1229  ret += node_id_str + " ";
1230  }
1231  ret += "}";
1232  }
1233  return cat(ret, ")");
1234  }
1235 
1236  size_t toHash() const override {
1237  if (!hash_) {
1238  hash_ = typeid(RelAggregate).hash_code();
1239  boost::hash_combine(*hash_, groupby_count_);
1240  for (auto& agg_expr : agg_exprs_) {
1241  boost::hash_combine(*hash_, agg_expr->toHash());
1242  }
1243  for (auto& node : inputs_) {
1244  boost::hash_combine(*hash_, node->toHash());
1245  }
1246  boost::hash_combine(*hash_, ::toString(fields_));
1247  }
1248  return *hash_;
1249  }
1250 
1251  std::shared_ptr<RelAlgNode> deepCopy() const override {
1252  return std::make_shared<RelAggregate>(*this);
1253  }
1254 
1255  void addHint(const ExplainedQueryHint& hint_explained) {
1256  if (!hint_applied_) {
1257  hint_applied_ = true;
1258  }
1259  hints_->emplace(hint_explained.getHint(), hint_explained);
1260  }
1261 
1262  const bool hasHintEnabled(QueryHint candidate_hint) const {
1263  if (hint_applied_ && !hints_->empty()) {
1264  return hints_->find(candidate_hint) != hints_->end();
1265  }
1266  return false;
1267  }
1268 
1271  CHECK(!hints_->empty());
1272  CHECK(hasHintEnabled(hint));
1273  return hints_->at(hint);
1274  }
1275 
1276  bool hasDeliveredHint() { return !hints_->empty(); }
1277 
1278  Hints* getDeliveredHints() { return hints_.get(); }
1279 
1280  private:
1281  const size_t groupby_count_;
1282  std::vector<std::unique_ptr<const RexAgg>> agg_exprs_;
1283  std::vector<std::string> fields_;
1285  std::unique_ptr<Hints> hints_;
1286 };
1287 
1288 class RelJoin : public RelAlgNode {
1289  public:
1290  RelJoin(std::shared_ptr<const RelAlgNode> lhs,
1291  std::shared_ptr<const RelAlgNode> rhs,
1292  std::unique_ptr<const RexScalar>& condition,
1293  const JoinType join_type)
1294  : condition_(std::move(condition))
1295  , join_type_(join_type)
1296  , hint_applied_(false)
1297  , hints_(std::make_unique<Hints>()) {
1298  inputs_.push_back(lhs);
1299  inputs_.push_back(rhs);
1300  }
1301 
1302  RelJoin(RelJoin const&);
1303 
1304  JoinType getJoinType() const { return join_type_; }
1305 
1306  const RexScalar* getCondition() const { return condition_.get(); }
1307 
1308  const RexScalar* getAndReleaseCondition() const { return condition_.release(); }
1309 
1310  void setCondition(std::unique_ptr<const RexScalar>& condition) {
1311  CHECK(condition);
1312  condition_ = std::move(condition);
1313  }
1314 
1315  void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
1316  std::shared_ptr<const RelAlgNode> input) override;
1317 
1318  std::string toString(
1319  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1320  auto ret = cat(::typeName(this), "(");
1321  if (!config.skip_input_nodes) {
1322  ret += ::toString(inputs_);
1323  } else {
1324  ret += ", input node id={";
1325  for (auto& input : inputs_) {
1326  auto node_id_in_plan = input->getIdInPlanTree();
1327  auto node_id_str = node_id_in_plan ? std::to_string(*node_id_in_plan)
1328  : std::to_string(input->getId());
1329  ret += node_id_str + " ";
1330  }
1331  ret += "}";
1332  }
1333  return cat(ret,
1334  ", condition=",
1335  (condition_ ? condition_->toString(config) : "null"),
1336  ", join_type=",
1337  ::toString(join_type_));
1338  }
1339 
1340  size_t toHash() const override {
1341  if (!hash_) {
1342  hash_ = typeid(RelJoin).hash_code();
1343  boost::hash_combine(*hash_, condition_ ? condition_->toHash() : HASH_N);
1344  for (auto& node : inputs_) {
1345  boost::hash_combine(*hash_, node->toHash());
1346  }
1347  boost::hash_combine(*hash_, ::toString(getJoinType()));
1348  }
1349  return *hash_;
1350  }
1351 
1352  size_t size() const override { return inputs_[0]->size() + inputs_[1]->size(); }
1353 
1354  std::shared_ptr<RelAlgNode> deepCopy() const override {
1355  return std::make_shared<RelJoin>(*this);
1356  }
1357 
1358  void addHint(const ExplainedQueryHint& hint_explained) {
1359  if (!hint_applied_) {
1360  hint_applied_ = true;
1361  }
1362  hints_->emplace(hint_explained.getHint(), hint_explained);
1363  }
1364 
1365  const bool hasHintEnabled(QueryHint candidate_hint) const {
1366  if (hint_applied_ && !hints_->empty()) {
1367  return hints_->find(candidate_hint) != hints_->end();
1368  }
1369  return false;
1370  }
1371 
1374  CHECK(!hints_->empty());
1375  CHECK(hasHintEnabled(hint));
1376  return hints_->at(hint);
1377  }
1378 
1379  bool hasDeliveredHint() { return !hints_->empty(); }
1380 
1381  Hints* getDeliveredHints() { return hints_.get(); }
1382 
1383  private:
1384  mutable std::unique_ptr<const RexScalar> condition_;
1387  std::unique_ptr<Hints> hints_;
1388 };
1389 
1390 // a helper node that contains detailed information of each level of join qual
1391 // which is used when extracting query plan DAG
1393  public:
1395  const RelAlgNode* rhs,
1396  const std::vector<const Analyzer::ColumnVar*> lhs_join_cols,
1397  const std::vector<const Analyzer::ColumnVar*> rhs_join_cols,
1398  const std::vector<std::shared_ptr<const Analyzer::Expr>> filter_ops,
1399  const RexScalar* outer_join_cond,
1400  const bool nested_loop,
1401  const JoinType join_type,
1402  const std::string& op_type,
1403  const std::string& qualifier,
1404  const std::string& op_typeinfo)
1405  : lhs_(lhs)
1406  , rhs_(rhs)
1407  , lhs_join_cols_(lhs_join_cols)
1408  , rhs_join_cols_(rhs_join_cols)
1409  , filter_ops_(filter_ops)
1410  , outer_join_cond_(outer_join_cond)
1411  , nested_loop_(nested_loop)
1412  , join_type_(join_type)
1413  , op_type_(op_type)
1414  , qualifier_(qualifier)
1415  , op_typeinfo_(op_typeinfo) {}
1416 
1417  std::string toString(
1418  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1419  return cat(::typeName(this),
1420  "( join_quals { lhs: ",
1422  ", rhs: ",
1424  " }, filter_quals: { ",
1425  ::toString(filter_ops_),
1426  " }, outer_join_cond: { ",
1427  outer_join_cond_->toString(config),
1428  " }, loop_join: ",
1430  ", join_type: ",
1432  ", op_type: ",
1434  ", qualifier: ",
1436  ", op_type_info: ",
1438  ")");
1439  }
1440  size_t toHash() const override {
1441  if (!hash_) {
1442  hash_ = typeid(RelTranslatedJoin).hash_code();
1443  boost::hash_combine(*hash_, lhs_->toHash());
1444  boost::hash_combine(*hash_, rhs_->toHash());
1445  boost::hash_combine(*hash_, outer_join_cond_ ? outer_join_cond_->toHash() : HASH_N);
1446  boost::hash_combine(*hash_, nested_loop_);
1447  boost::hash_combine(*hash_, ::toString(join_type_));
1448  boost::hash_combine(*hash_, op_type_);
1449  boost::hash_combine(*hash_, qualifier_);
1450  boost::hash_combine(*hash_, op_typeinfo_);
1451  for (auto& filter_op : filter_ops_) {
1452  boost::hash_combine(*hash_, filter_op->toString());
1453  }
1454  }
1455  return *hash_;
1456  }
1457  const RelAlgNode* getLHS() const { return lhs_; }
1458  const RelAlgNode* getRHS() const { return rhs_; }
1459  size_t getFilterCondSize() const { return filter_ops_.size(); }
1460  const std::vector<std::shared_ptr<const Analyzer::Expr>> getFilterCond() const {
1461  return filter_ops_;
1462  }
1463  const RexScalar* getOuterJoinCond() const { return outer_join_cond_; }
1464  std::string getOpType() const { return op_type_; }
1465  std::string getQualifier() const { return qualifier_; }
1466  std::string getOpTypeInfo() const { return op_typeinfo_; }
1467  size_t size() const override { return 0; }
1468  JoinType getJoinType() const { return join_type_; }
1469  const RexScalar* getCondition() const {
1470  CHECK(false);
1471  return nullptr;
1472  }
1474  CHECK(false);
1475  return nullptr;
1476  }
1477  void setCondition(std::unique_ptr<const RexScalar>& condition) { CHECK(false); }
1478  void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
1479  std::shared_ptr<const RelAlgNode> input) override {
1480  CHECK(false);
1481  }
1482  std::shared_ptr<RelAlgNode> deepCopy() const override {
1483  CHECK(false);
1484  return nullptr;
1485  }
1486  std::string getFieldName(const size_t i) const;
1487  std::vector<const Analyzer::ColumnVar*> getJoinCols(bool lhs) const {
1488  if (lhs) {
1489  return lhs_join_cols_;
1490  }
1491  return rhs_join_cols_;
1492  }
1493  bool isNestedLoopQual() const { return nested_loop_; }
1494 
1495  private:
1498  const std::vector<const Analyzer::ColumnVar*> lhs_join_cols_;
1499  const std::vector<const Analyzer::ColumnVar*> rhs_join_cols_;
1500  const std::vector<std::shared_ptr<const Analyzer::Expr>> filter_ops_;
1502  const bool nested_loop_;
1504  const std::string op_type_;
1505  const std::string qualifier_;
1506  const std::string op_typeinfo_;
1507 };
1508 
1509 class RelFilter : public RelAlgNode {
1510  public:
1511  RelFilter(std::unique_ptr<const RexScalar>& filter,
1512  std::shared_ptr<const RelAlgNode> input)
1513  : filter_(std::move(filter)) {
1514  CHECK(filter_);
1515  inputs_.push_back(input);
1516  }
1517 
1518  // for dummy filter node for data recycler
1519  RelFilter(std::unique_ptr<const RexScalar>& filter) : filter_(std::move(filter)) {
1520  CHECK(filter_);
1521  }
1522 
1523  RelFilter(RelFilter const&);
1524 
1525  const RexScalar* getCondition() const { return filter_.get(); }
1526 
1527  const RexScalar* getAndReleaseCondition() { return filter_.release(); }
1528 
1529  void setCondition(std::unique_ptr<const RexScalar>& condition) {
1530  CHECK(condition);
1531  filter_ = std::move(condition);
1532  }
1533 
1534  size_t size() const override { return inputs_[0]->size(); }
1535 
1536  void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
1537  std::shared_ptr<const RelAlgNode> input) override;
1538 
1539  std::string toString(
1540  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1541  auto ret =
1542  cat(::typeName(this), "(", (filter_ ? filter_->toString(config) : "null"), ", ");
1543  if (!config.skip_input_nodes) {
1544  ret += ::toString(inputs_);
1545  } else {
1546  ret += ", input node id={";
1547  for (auto& input : inputs_) {
1548  auto node_id_in_plan = input->getIdInPlanTree();
1549  auto node_id_str = node_id_in_plan ? std::to_string(*node_id_in_plan)
1550  : std::to_string(input->getId());
1551  ret += node_id_str + " ";
1552  }
1553  ret += "}";
1554  }
1555  return cat(ret, ")");
1556  }
1557 
1558  size_t toHash() const override {
1559  if (!hash_) {
1560  hash_ = typeid(RelFilter).hash_code();
1561  boost::hash_combine(*hash_, filter_ ? filter_->toHash() : HASH_N);
1562  for (auto& node : inputs_) {
1563  boost::hash_combine(*hash_, node->toHash());
1564  }
1565  }
1566  return *hash_;
1567  }
1568 
1569  std::shared_ptr<RelAlgNode> deepCopy() const override {
1570  return std::make_shared<RelFilter>(*this);
1571  }
1572 
1573  private:
1574  std::unique_ptr<const RexScalar> filter_;
1575 };
1576 
1577 // Synthetic node to assist execution of left-deep join relational algebra.
1579  public:
1580  RelLeftDeepInnerJoin(const std::shared_ptr<RelFilter>& filter,
1581  RelAlgInputs inputs,
1582  std::vector<std::shared_ptr<const RelJoin>>& original_joins);
1583 
1584  const RexScalar* getInnerCondition() const;
1585 
1586  const RexScalar* getOuterCondition(const size_t nesting_level) const;
1587 
1588  const JoinType getJoinType(const size_t nesting_level) const;
1589 
1590  std::string toString(
1591  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override;
1592 
1593  size_t toHash() const override;
1594 
1595  size_t size() const override;
1596 
1597  std::shared_ptr<RelAlgNode> deepCopy() const override;
1598 
1599  bool coversOriginalNode(const RelAlgNode* node) const;
1600 
1601  const RelFilter* getOriginalFilter() const;
1602 
1603  std::vector<std::shared_ptr<const RelJoin>> getOriginalJoins() const;
1604 
1605  private:
1606  std::unique_ptr<const RexScalar> condition_;
1607  std::vector<std::unique_ptr<const RexScalar>> outer_conditions_per_level_;
1608  const std::shared_ptr<RelFilter> original_filter_;
1609  const std::vector<std::shared_ptr<const RelJoin>> original_joins_;
1610 };
1611 
1612 // The 'RelCompound' node combines filter and on the fly aggregate computation.
1613 // It's the result of combining a sequence of 'RelFilter' (optional), 'RelProject',
1614 // 'RelAggregate' (optional) and a simple 'RelProject' (optional) into a single node
1615 // which can be efficiently executed with no intermediate buffers.
1617  public:
1618  // 'target_exprs_' are either scalar expressions owned by 'scalar_sources_'
1619  // or aggregate expressions owned by 'agg_exprs_', with the arguments
1620  // owned by 'scalar_sources_'.
1621  RelCompound(std::unique_ptr<const RexScalar>& filter_expr,
1622  const std::vector<const Rex*>& target_exprs,
1623  const size_t groupby_count,
1624  const std::vector<const RexAgg*>& agg_exprs,
1625  const std::vector<std::string>& fields,
1626  std::vector<std::unique_ptr<const RexScalar>>& scalar_sources,
1627  const bool is_agg,
1628  bool update_disguised_as_select = false,
1629  bool delete_disguised_as_select = false,
1630  bool varlen_update_required = false,
1631  TableDescriptor const* manipulation_target_table = nullptr,
1632  ColumnNameList target_columns = ColumnNameList())
1633  : ModifyManipulationTarget(update_disguised_as_select,
1634  delete_disguised_as_select,
1635  varlen_update_required,
1636  manipulation_target_table,
1637  target_columns)
1638  , filter_expr_(std::move(filter_expr))
1639  , groupby_count_(groupby_count)
1640  , fields_(fields)
1641  , is_agg_(is_agg)
1642  , scalar_sources_(std::move(scalar_sources))
1643  , target_exprs_(target_exprs)
1644  , hint_applied_(false)
1645  , hints_(std::make_unique<Hints>()) {
1646  CHECK_EQ(fields.size(), target_exprs.size());
1647  for (auto agg_expr : agg_exprs) {
1648  agg_exprs_.emplace_back(agg_expr);
1649  }
1650  }
1651 
1652  RelCompound(RelCompound const&);
1653 
1654  void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
1655  std::shared_ptr<const RelAlgNode> input) override;
1656 
1657  size_t size() const override { return target_exprs_.size(); }
1658 
1659  const RexScalar* getFilterExpr() const { return filter_expr_.get(); }
1660 
1661  void setFilterExpr(std::unique_ptr<const RexScalar>& new_expr) {
1662  filter_expr_ = std::move(new_expr);
1663  }
1664 
1665  const Rex* getTargetExpr(const size_t i) const { return target_exprs_[i]; }
1666 
1667  const std::vector<std::string>& getFields() const { return fields_; }
1668 
1669  const std::string getFieldName(const size_t i) const { return fields_[i]; }
1670 
1671  void setFields(std::vector<std::string>&& fields) { fields_ = std::move(fields); }
1672 
1673  const size_t getScalarSourcesSize() const { return scalar_sources_.size(); }
1674 
1675  const RexScalar* getScalarSource(const size_t i) const {
1676  return scalar_sources_[i].get();
1677  }
1678 
1679  void setScalarSources(std::vector<std::unique_ptr<const RexScalar>>& new_sources) {
1680  CHECK_EQ(new_sources.size(), scalar_sources_.size());
1681  scalar_sources_ = std::move(new_sources);
1682  }
1683 
1684  const size_t getGroupByCount() const { return groupby_count_; }
1685 
1686  bool isAggregate() const { return is_agg_; }
1687 
1688  size_t getAggExprSize() const { return agg_exprs_.size(); }
1689 
1690  const RexAgg* getAggExpr(size_t i) const { return agg_exprs_[i].get(); }
1691 
1692  std::string toString(
1693  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override;
1694 
1695  size_t toHash() const override;
1696 
1697  std::shared_ptr<RelAlgNode> deepCopy() const override {
1698  return std::make_shared<RelCompound>(*this);
1699  }
1700 
1701  void addHint(const ExplainedQueryHint& hint_explained) {
1702  if (!hint_applied_) {
1703  hint_applied_ = true;
1704  }
1705  hints_->emplace(hint_explained.getHint(), hint_explained);
1706  }
1707 
1708  const bool hasHintEnabled(QueryHint candidate_hint) const {
1709  if (hint_applied_ && !hints_->empty()) {
1710  return hints_->find(candidate_hint) != hints_->end();
1711  }
1712  return false;
1713  }
1714 
1717  CHECK(!hints_->empty());
1718  CHECK(hasHintEnabled(hint));
1719  return hints_->at(hint);
1720  }
1721 
1722  bool hasDeliveredHint() { return !hints_->empty(); }
1723 
1724  Hints* getDeliveredHints() { return hints_.get(); }
1725 
1726  private:
1727  std::unique_ptr<const RexScalar> filter_expr_;
1728  const size_t groupby_count_;
1729  std::vector<std::unique_ptr<const RexAgg>> agg_exprs_;
1730  std::vector<std::string> fields_;
1731  const bool is_agg_;
1732  std::vector<std::unique_ptr<const RexScalar>>
1733  scalar_sources_; // building blocks for group_indices_ and agg_exprs_; not actually
1734  // projected, just owned
1735  const std::vector<const Rex*> target_exprs_;
1737  std::unique_ptr<Hints> hints_;
1738 };
1739 
1740 class RelSort : public RelAlgNode {
1741  public:
1742  RelSort(const std::vector<SortField>& collation,
1743  const size_t limit,
1744  const size_t offset,
1745  std::shared_ptr<const RelAlgNode> input,
1746  bool limit_delivered)
1747  : collation_(collation)
1748  , limit_(limit)
1749  , offset_(offset)
1750  , limit_delivered_(limit_delivered) {
1751  inputs_.push_back(input);
1752  }
1753 
1754  bool operator==(const RelSort& that) const {
1755  return limit_ == that.limit_ && offset_ == that.offset_ &&
1756  empty_result_ == that.empty_result_ &&
1758  }
1759 
1760  size_t collationCount() const { return collation_.size(); }
1761 
1762  SortField getCollation(const size_t i) const {
1763  CHECK_LT(i, collation_.size());
1764  return collation_[i];
1765  }
1766 
1767  void setCollation(std::vector<SortField>&& collation) {
1768  collation_ = std::move(collation);
1769  }
1770 
1771  void setEmptyResult(bool emptyResult) { empty_result_ = emptyResult; }
1772 
1773  bool isEmptyResult() const { return empty_result_; }
1774 
1775  bool isLimitDelivered() const { return limit_delivered_; }
1776 
1777  size_t getLimit() const { return limit_; }
1778 
1779  size_t getOffset() const { return offset_; }
1780 
1781  std::string toString(
1782  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1783  const std::string limit_info = limit_delivered_ ? std::to_string(limit_) : "N/A";
1784  auto ret = cat(::typeName(this),
1785  "(",
1786  "empty_result: ",
1788  ", collation=",
1789  ::toString(collation_),
1790  ", limit=",
1791  limit_info,
1792  ", offset",
1793  std::to_string(offset_));
1794  if (!config.skip_input_nodes) {
1795  ret += ", inputs=", ::toString(inputs_);
1796  } else {
1797  ret += ", input node id={";
1798  for (auto& input : inputs_) {
1799  auto node_id_in_plan = input->getIdInPlanTree();
1800  auto node_id_str = node_id_in_plan ? std::to_string(*node_id_in_plan)
1801  : std::to_string(input->getId());
1802  ret += node_id_str + " ";
1803  }
1804  ret += "}";
1805  }
1806  return cat(ret, ")");
1807  }
1808 
1809  size_t toHash() const override {
1810  if (!hash_) {
1811  hash_ = typeid(RelSort).hash_code();
1812  for (auto& collation : collation_) {
1813  boost::hash_combine(*hash_, collation.toHash());
1814  }
1815  boost::hash_combine(*hash_, empty_result_);
1816  boost::hash_combine(*hash_, limit_delivered_);
1817  if (limit_delivered_) {
1818  boost::hash_combine(*hash_, limit_);
1819  }
1820  boost::hash_combine(*hash_, offset_);
1821  for (auto& node : inputs_) {
1822  boost::hash_combine(*hash_, node->toHash());
1823  }
1824  }
1825  return *hash_;
1826  }
1827 
1828  size_t size() const override { return inputs_[0]->size(); }
1829 
1830  std::shared_ptr<RelAlgNode> deepCopy() const override {
1831  return std::make_shared<RelSort>(*this);
1832  }
1833 
1834  private:
1835  std::vector<SortField> collation_;
1836  const size_t limit_;
1837  const size_t offset_;
1840 
1841  bool hasEquivCollationOf(const RelSort& that) const;
1842 };
1843 
1844 class RelModify : public RelAlgNode {
1845  public:
1847  using RelAlgNodeInputPtr = std::shared_ptr<const RelAlgNode>;
1848  using TargetColumnList = std::vector<std::string>;
1849 
1850  static std::string yieldModifyOperationString(ModifyOperation const op) {
1851  switch (op) {
1853  return "DELETE";
1855  return "INSERT";
1857  return "UPDATE";
1858  default:
1859  break;
1860  }
1861  throw std::runtime_error("Unexpected ModifyOperation enum encountered.");
1862  }
1863 
1864  static ModifyOperation yieldModifyOperationEnum(std::string const& op_string) {
1865  if (op_string == "INSERT") {
1866  return ModifyOperation::Insert;
1867  } else if (op_string == "DELETE") {
1868  return ModifyOperation::Delete;
1869  } else if (op_string == "UPDATE") {
1870  return ModifyOperation::Update;
1871  }
1872 
1873  throw std::runtime_error(
1874  std::string("Unsupported logical modify operation encountered " + op_string));
1875  }
1876 
1878  TableDescriptor const* const td,
1879  bool flattened,
1880  std::string const& op_string,
1881  TargetColumnList const& target_column_list,
1882  RelAlgNodeInputPtr input)
1883  : catalog_(cat)
1884  , table_descriptor_(td)
1885  , flattened_(flattened)
1886  , operation_(yieldModifyOperationEnum(op_string))
1887  , target_column_list_(target_column_list) {
1889  inputs_.push_back(input);
1890  }
1891 
1893  TableDescriptor const* const td,
1894  bool flattened,
1895  ModifyOperation op,
1896  TargetColumnList const& target_column_list,
1897  RelAlgNodeInputPtr input)
1898  : catalog_(cat)
1899  , table_descriptor_(td)
1900  , flattened_(flattened)
1901  , operation_(op)
1902  , target_column_list_(target_column_list) {
1904  inputs_.push_back(input);
1905  }
1906 
1907  TableDescriptor const* const getTableDescriptor() const { return table_descriptor_; }
1908  bool const isFlattened() const { return flattened_; }
1911  int getUpdateColumnCount() const { return target_column_list_.size(); }
1912 
1913  size_t size() const override { return 0; }
1914  std::shared_ptr<RelAlgNode> deepCopy() const override {
1915  return std::make_shared<RelModify>(*this);
1916  }
1917 
1918  std::string toString(
1919  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
1920  auto ret = cat(::typeName(this),
1921  "(",
1923  ", flattened=",
1925  ", op=",
1927  ", target_column_list=",
1929  if (!config.skip_input_nodes) {
1930  ret += ", inputs=", ::toString(inputs_);
1931  } else {
1932  ret += ", input node id={";
1933  for (auto& input : inputs_) {
1934  auto node_id_in_plan = input->getIdInPlanTree();
1935  auto node_id_str = node_id_in_plan ? std::to_string(*node_id_in_plan)
1936  : std::to_string(input->getId());
1937  ret += node_id_str + " ";
1938  }
1939  ret += "}";
1940  }
1941  return cat(ret, ")");
1942  }
1943 
1944  size_t toHash() const override {
1945  if (!hash_) {
1946  hash_ = typeid(RelModify).hash_code();
1947  boost::hash_combine(*hash_, table_descriptor_->tableName);
1948  boost::hash_combine(*hash_, flattened_);
1949  boost::hash_combine(*hash_, yieldModifyOperationString(operation_));
1950  boost::hash_combine(*hash_, ::toString(target_column_list_));
1951  for (auto& node : inputs_) {
1952  boost::hash_combine(*hash_, node->toHash());
1953  }
1954  }
1955  return *hash_;
1956  }
1957 
1959  RelProject const* previous_project_node =
1960  dynamic_cast<RelProject const*>(inputs_[0].get());
1961  CHECK(previous_project_node != nullptr);
1962 
1963  if (previous_project_node->hasWindowFunctionExpr()) {
1964  throw std::runtime_error(
1965  "UPDATE of a column using a window function is not currently supported.");
1966  }
1967 
1968  previous_project_node->setUpdateViaSelectFlag();
1969  // remove the offset column in the projection for update handling
1970  target_column_list_.pop_back();
1971 
1972  previous_project_node->setModifiedTableDescriptor(table_descriptor_);
1973  previous_project_node->setTargetColumns(target_column_list_);
1974 
1975  int target_update_column_expr_start = 0;
1976  int target_update_column_expr_end = (int)(target_column_list_.size() - 1);
1977  CHECK(target_update_column_expr_start >= 0);
1978  CHECK(target_update_column_expr_end >= 0);
1979 
1980  bool varlen_update_required = false;
1981 
1982  auto varlen_scan_visitor = [this,
1983  &varlen_update_required,
1984  target_update_column_expr_start,
1985  target_update_column_expr_end](int index) {
1986  if (index >= target_update_column_expr_start &&
1987  index <= target_update_column_expr_end) {
1988  auto target_index = index - target_update_column_expr_start;
1989 
1990  auto* column_desc = catalog_.getMetadataForColumn(
1992  CHECK(column_desc);
1993 
1994  if (table_descriptor_->nShards) {
1995  const auto shard_cd =
1997  CHECK(shard_cd);
1998  if ((column_desc->columnName == shard_cd->columnName)) {
1999  throw std::runtime_error("UPDATE of a shard key is currently unsupported.");
2000  }
2001  }
2002 
2003  // Check for valid types
2004  if (column_desc->columnType.is_varlen()) {
2005  varlen_update_required = true;
2006  }
2007  if (column_desc->columnType.is_geometry()) {
2008  throw std::runtime_error("UPDATE of a geo column is unsupported.");
2009  }
2010  }
2011  };
2012 
2013  previous_project_node->visitScalarExprs(varlen_scan_visitor);
2014  previous_project_node->setVarlenUpdateRequired(varlen_update_required);
2015  }
2016 
2018  RelProject const* previous_project_node =
2019  dynamic_cast<RelProject const*>(inputs_[0].get());
2020  CHECK(previous_project_node != nullptr);
2021  previous_project_node->setDeleteViaSelectFlag();
2022  previous_project_node->setModifiedTableDescriptor(table_descriptor_);
2023  }
2024 
2025  private:
2031 };
2032 
2034  public:
2035  RelTableFunction(const std::string& function_name,
2036  RelAlgInputs inputs,
2037  std::vector<std::string>& fields,
2038  std::vector<const Rex*> col_inputs,
2039  std::vector<std::unique_ptr<const RexScalar>>& table_func_inputs,
2040  std::vector<std::unique_ptr<const RexScalar>>& target_exprs)
2041  : function_name_(function_name)
2042  , fields_(fields)
2043  , col_inputs_(col_inputs)
2044  , table_func_inputs_(std::move(table_func_inputs))
2045  , target_exprs_(std::move(target_exprs)) {
2046  for (const auto& input : inputs) {
2047  inputs_.emplace_back(input);
2048  }
2049  }
2050 
2052 
2053  void replaceInput(std::shared_ptr<const RelAlgNode> old_input,
2054  std::shared_ptr<const RelAlgNode> input) override;
2055 
2056  std::string getFunctionName() const { return function_name_; }
2057 
2058  size_t size() const override { return target_exprs_.size(); }
2059 
2060  const RexScalar* getTargetExpr(size_t idx) const {
2061  CHECK_LT(idx, target_exprs_.size());
2062  return target_exprs_[idx].get();
2063  }
2064 
2065  size_t getTableFuncInputsSize() const { return table_func_inputs_.size(); }
2066 
2067  size_t getColInputsSize() const { return col_inputs_.size(); }
2068 
2069  int32_t countRexLiteralArgs() const;
2070 
2071  const RexScalar* getTableFuncInputAt(const size_t idx) const {
2072  CHECK_LT(idx, table_func_inputs_.size());
2073  return table_func_inputs_[idx].get();
2074  }
2075 
2076  const RexScalar* getTableFuncInputAtAndRelease(const size_t idx) {
2077  CHECK_LT(idx, table_func_inputs_.size());
2078  return table_func_inputs_[idx].release();
2079  }
2080 
2081  void setTableFuncInputs(std::vector<std::unique_ptr<const RexScalar>>& exprs) {
2082  table_func_inputs_ = std::move(exprs);
2083  }
2084 
2085  std::string getFieldName(const size_t idx) const {
2086  CHECK_LT(idx, fields_.size());
2087  return fields_[idx];
2088  }
2089 
2090  const std::vector<std::string>& getFields() const { return fields_; }
2091  void setFields(std::vector<std::string>&& fields) { fields_ = std::move(fields); }
2092 
2093  std::shared_ptr<RelAlgNode> deepCopy() const override {
2094  return std::make_shared<RelTableFunction>(*this);
2095  }
2096 
2097  std::string toString(
2098  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
2099  auto ret = cat(::typeName(this), "(", function_name_);
2100  if (!config.skip_input_nodes) {
2101  ret += ", inputs=", ::toString(inputs_);
2102  } else {
2103  ret += ", input node id={";
2104  for (auto& input : inputs_) {
2105  auto node_id_in_plan = input->getIdInPlanTree();
2106  auto node_id_str = node_id_in_plan ? std::to_string(*node_id_in_plan)
2107  : std::to_string(input->getId());
2108  ret += node_id_str + " ";
2109  }
2110  ret += "}";
2111  }
2112  ret +=
2113  cat(", fields=", ::toString(fields_), ", col_inputs=...", ", table_func_inputs=");
2114  if (!config.skip_input_nodes) {
2116  } else {
2117  for (auto& expr : table_func_inputs_) {
2118  ret += expr->toString(config) + " ";
2119  }
2120  }
2121  ret += ", target_exprs=";
2122  for (auto& expr : target_exprs_) {
2123  ret += expr->toString(config) + " ";
2124  }
2125  return cat(ret, ")");
2126  }
2127 
2128  size_t toHash() const override {
2129  if (!hash_) {
2130  hash_ = typeid(RelTableFunction).hash_code();
2131  for (auto& table_func_input : table_func_inputs_) {
2132  boost::hash_combine(*hash_, table_func_input->toHash());
2133  }
2134  for (auto& target_expr : target_exprs_) {
2135  boost::hash_combine(*hash_, target_expr->toHash());
2136  }
2137  boost::hash_combine(*hash_, function_name_);
2138  boost::hash_combine(*hash_, ::toString(fields_));
2139  for (auto& node : inputs_) {
2140  boost::hash_combine(*hash_, node->toHash());
2141  }
2142  }
2143  return *hash_;
2144  }
2145 
2146  private:
2147  std::string function_name_;
2148  std::vector<std::string> fields_;
2149 
2150  std::vector<const Rex*>
2151  col_inputs_; // owned by `table_func_inputs_`, but allows picking out the specific
2152  // input columns vs other table function inputs (e.g. literals)
2153  std::vector<std::unique_ptr<const RexScalar>> table_func_inputs_;
2154 
2155  std::vector<std::unique_ptr<const RexScalar>>
2156  target_exprs_; // Note: these should all be RexRef but are stored as RexScalar for
2157  // consistency
2158 };
2159 
2161  public:
2162  using RowValues = std::vector<std::unique_ptr<const RexScalar>>;
2163 
2164  RelLogicalValues(const std::vector<TargetMetaInfo>& tuple_type,
2165  std::vector<RowValues>& values)
2166  : tuple_type_(tuple_type), values_(std::move(values)) {}
2167 
2169 
2170  const std::vector<TargetMetaInfo> getTupleType() const { return tuple_type_; }
2171 
2172  std::string toString(
2173  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override {
2174  std::string ret = ::typeName(this) + "(";
2175  for (const auto& target_meta_info : tuple_type_) {
2176  ret += " (" + target_meta_info.get_resname() + " " +
2177  target_meta_info.get_type_info().get_type_name() + ")";
2178  }
2179  ret += ")";
2180  return ret;
2181  }
2182 
2183  size_t toHash() const override {
2184  if (!hash_) {
2185  hash_ = typeid(RelLogicalValues).hash_code();
2186  for (auto& target_meta_info : tuple_type_) {
2187  boost::hash_combine(*hash_, target_meta_info.get_resname());
2188  boost::hash_combine(*hash_, target_meta_info.get_type_info().get_type_name());
2189  }
2190  }
2191  return *hash_;
2192  }
2193 
2194  const RexScalar* getValueAt(const size_t row_idx, const size_t col_idx) const {
2195  CHECK_LT(row_idx, values_.size());
2196  const auto& row = values_[row_idx];
2197  CHECK_LT(col_idx, row.size());
2198  return row[col_idx].get();
2199  }
2200 
2201  size_t getRowsSize() const {
2202  if (values_.empty()) {
2203  return 0;
2204  } else {
2205  return values_.front().size();
2206  }
2207  }
2208 
2209  size_t getNumRows() const { return values_.size(); }
2210 
2211  size_t size() const override { return tuple_type_.size(); }
2212 
2213  bool hasRows() const { return !values_.empty(); }
2214 
2215  std::shared_ptr<RelAlgNode> deepCopy() const override {
2216  return std::make_shared<RelLogicalValues>(*this);
2217  }
2218 
2219  private:
2220  const std::vector<TargetMetaInfo> tuple_type_;
2221  const std::vector<RowValues> values_;
2222 };
2223 
2224 class RelLogicalUnion : public RelAlgNode {
2225  public:
2226  RelLogicalUnion(RelAlgInputs, bool is_all);
2227  std::shared_ptr<RelAlgNode> deepCopy() const override {
2228  return std::make_shared<RelLogicalUnion>(*this);
2229  }
2230  size_t size() const override;
2231  std::string toString(
2232  RelRexToStringConfig config = RelRexToStringConfig::defaults()) const override;
2233  size_t toHash() const override;
2234 
2235  std::string getFieldName(const size_t i) const;
2236 
2237  inline bool isAll() const { return is_all_; }
2238  // Will throw a std::runtime_error if MetaInfo types don't match.
2239  void checkForMatchingMetaInfoTypes() const;
2240  RexScalar const* copyAndRedirectSource(RexScalar const*, size_t input_idx) const;
2241 
2242  // Not unique_ptr to allow for an easy deepCopy() implementation.
2243  mutable std::vector<std::shared_ptr<const RexScalar>> scalar_exprs_;
2244 
2245  private:
2246  bool const is_all_;
2247 };
2248 
2249 class QueryNotSupported : public std::runtime_error {
2250  public:
2251  QueryNotSupported(const std::string& reason) : std::runtime_error(reason) {}
2252 };
2253 
2263 class RelAlgDagBuilder : public boost::noncopyable {
2264  public:
2265  RelAlgDagBuilder() = delete;
2266 
2273  RelAlgDagBuilder(const std::string& query_ra,
2275  const RenderInfo* render_info);
2276 
2286  RelAlgDagBuilder(RelAlgDagBuilder& root_dag_builder,
2287  const rapidjson::Value& query_ast,
2288  const Catalog_Namespace::Catalog& cat,
2289  const RenderInfo* render_opts);
2290 
2291  void eachNode(std::function<void(RelAlgNode const*)> const&) const;
2292 
2296  const RelAlgNode& getRootNode() const {
2297  CHECK(nodes_.size());
2298  const auto& last_ptr = nodes_.back();
2299  CHECK(last_ptr);
2300  return *last_ptr;
2301  }
2302 
2303  std::shared_ptr<const RelAlgNode> getRootNodeShPtr() const {
2304  CHECK(nodes_.size());
2305  return nodes_.back();
2306  }
2307 
2312  void registerSubquery(std::shared_ptr<RexSubQuery> subquery) {
2313  subqueries_.push_back(subquery);
2314  }
2315 
2319  const std::vector<std::shared_ptr<RexSubQuery>>& getSubqueries() const {
2320  return subqueries_;
2321  }
2322 
2323  // todo(yoonmin): simplify and improve query register logic
2324  void registerQueryHints(std::shared_ptr<RelAlgNode> node,
2325  Hints* hints_delivered,
2326  RegisteredQueryHint& global_query_hint) {
2327  std::optional<bool> has_global_columnar_output_hint = std::nullopt;
2328  std::optional<bool> has_global_rowwise_output_hint = std::nullopt;
2329  RegisteredQueryHint query_hint;
2330  for (auto it = hints_delivered->begin(); it != hints_delivered->end(); it++) {
2331  auto target = it->second;
2332  auto hint_type = it->first;
2333  switch (hint_type) {
2334  case QueryHint::kCpuMode: {
2335  query_hint.registerHint(QueryHint::kCpuMode);
2336  query_hint.cpu_mode = true;
2337  if (target.isGlobalHint()) {
2338  global_query_hint.registerHint(QueryHint::kCpuMode);
2339  global_query_hint.cpu_mode = true;
2340  }
2341  break;
2342  }
2344  has_global_columnar_output_hint = target.isGlobalHint();
2345  break;
2346  }
2348  has_global_rowwise_output_hint = target.isGlobalHint();
2349  break;
2350  }
2352  CHECK(target.getListOptions().size() == 1);
2353  double overlaps_bucket_threshold = std::stod(target.getListOptions()[0]);
2354  if (overlaps_bucket_threshold >= 0.0 && overlaps_bucket_threshold <= 90.0) {
2356  query_hint.overlaps_bucket_threshold = overlaps_bucket_threshold;
2357  if (target.isGlobalHint()) {
2359  global_query_hint.overlaps_bucket_threshold = overlaps_bucket_threshold;
2360  }
2361  } else {
2362  VLOG(1) << "Skip the given query hint \"overlaps_bucket_threshold\" ("
2363  << overlaps_bucket_threshold
2364  << ") : the hint value should be within 0.0 ~ 90.0";
2365  }
2366  break;
2367  }
2369  CHECK(target.getListOptions().size() == 1);
2370  std::stringstream ss(target.getListOptions()[0]);
2371  int overlaps_max_size;
2372  ss >> overlaps_max_size;
2373  if (overlaps_max_size >= 0) {
2375  query_hint.overlaps_max_size = (size_t)overlaps_max_size;
2376  if (target.isGlobalHint()) {
2377  global_query_hint.registerHint(QueryHint::kOverlapsMaxSize);
2378  global_query_hint.overlaps_max_size = (size_t)overlaps_max_size;
2379  }
2380  } else {
2381  VLOG(1) << "Skip the query hint \"overlaps_max_size\" (" << overlaps_max_size
2382  << ") : the hint value should be larger than or equal to zero";
2383  }
2384  break;
2385  }
2388  query_hint.overlaps_allow_gpu_build = true;
2389  if (target.isGlobalHint()) {
2391  global_query_hint.overlaps_allow_gpu_build = true;
2392  }
2393  break;
2394  }
2397  query_hint.overlaps_no_cache = true;
2398  if (target.isGlobalHint()) {
2399  global_query_hint.registerHint(QueryHint::kOverlapsNoCache);
2400  global_query_hint.overlaps_no_cache = true;
2401  }
2402  VLOG(1) << "Skip auto tuner and hashtable caching for overlaps join.";
2403  break;
2404  }
2406  CHECK(target.getListOptions().size() == 1);
2407  double overlaps_keys_per_bin = std::stod(target.getListOptions()[0]);
2408  if (overlaps_keys_per_bin > 0.0 &&
2409  overlaps_keys_per_bin < std::numeric_limits<double>::max()) {
2411  query_hint.overlaps_keys_per_bin = overlaps_keys_per_bin;
2412  if (target.isGlobalHint()) {
2413  global_query_hint.registerHint(QueryHint::kOverlapsKeysPerBin);
2414  global_query_hint.overlaps_keys_per_bin = overlaps_keys_per_bin;
2415  }
2416  } else {
2417  VLOG(1) << "Skip the given query hint \"overlaps_keys_per_bin\" ("
2418  << overlaps_keys_per_bin
2419  << ") : the hint value should be larger than zero";
2420  }
2421  break;
2422  }
2423  case QueryHint::kKeepResult: {
2425  VLOG(1) << "Skip query hint \'keep_result\' because neither data recycler "
2426  "nor query resultset recycler is enabled";
2427  } else {
2429  query_hint.keep_result = true;
2430  if (target.isGlobalHint()) {
2431  global_query_hint.registerHint(QueryHint::kKeepResult);
2432  global_query_hint.keep_result = true;
2433  }
2434  }
2435  break;
2436  }
2439  VLOG(1) << "Skip query hint \'keep_table_function_result\' because neither "
2440  "data recycler "
2441  "nor query resultset recycler is enabled";
2442  } else {
2443  // we assume table function's hint is handled as global hint by default
2444  global_query_hint.registerHint(QueryHint::kKeepTableFuncResult);
2445  global_query_hint.keep_table_function_result = true;
2446  }
2447  }
2448  default:
2449  break;
2450  }
2451  }
2452  // we have four cases depending on 1) g_enable_columnar_output flag
2453  // and 2) query hint status: columnar_output and rowwise_output
2454  // case 1. g_enable_columnar_output = true
2455  // case 1.a) columnar_output = true (so rowwise_output = false);
2456  // case 1.b) rowwise_output = true (so columnar_output = false);
2457  // case 2. g_enable_columnar_output = false
2458  // case 2.a) columnar_output = true (so rowwise_output = false);
2459  // case 2.b) rowwise_output = true (so columnar_output = false);
2460  // case 1.a --> use columnar output
2461  // case 1.b --> use rowwise output
2462  // case 2.a --> use columnar output
2463  // case 2.b --> use rowwise output
2464  if (has_global_columnar_output_hint.has_value() &&
2465  has_global_rowwise_output_hint.has_value()) {
2466  VLOG(1)
2467  << "Two hints 1) columnar output and 2) rowwise output are enabled together, "
2468  << "so skip them and use the runtime configuration "
2469  "\"g_enable_columnar_output\"";
2470  } else if (has_global_columnar_output_hint.has_value() &&
2471  !has_global_rowwise_output_hint.has_value()) {
2473  VLOG(1) << "We already enable columnar output by default "
2474  "(g_enable_columnar_output = true), so skip this columnar output hint";
2475  } else {
2477  query_hint.columnar_output = true;
2478  if (*has_global_columnar_output_hint) {
2479  global_query_hint.registerHint(QueryHint::kColumnarOutput);
2480  global_query_hint.columnar_output = true;
2481  }
2482  }
2483  } else if (!has_global_columnar_output_hint.has_value() &&
2484  has_global_rowwise_output_hint.has_value()) {
2485  if (!g_enable_columnar_output) {
2486  VLOG(1) << "We already use the default rowwise output (g_enable_columnar_output "
2487  "= false), so skip this rowwise output hint";
2488  } else {
2490  query_hint.rowwise_output = true;
2491  if (*has_global_rowwise_output_hint) {
2492  global_query_hint.registerHint(QueryHint::kRowwiseOutput);
2493  global_query_hint.rowwise_output = true;
2494  }
2495  }
2496  }
2497  auto node_key = node->toHash();
2498  auto it = query_hint_.find(node_key);
2499  if (it == query_hint_.end()) {
2500  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
2501  hint_map.emplace(node->getId(), query_hint);
2502  query_hint_.emplace(node_key, hint_map);
2503  } else {
2504  it->second.emplace(node->getId(), query_hint);
2505  }
2506  }
2507 
2508  std::optional<RegisteredQueryHint> getQueryHint(const RelAlgNode* node) const {
2509  auto node_it = query_hint_.find(node->toHash());
2510  if (node_it != query_hint_.end()) {
2511  auto const& registered_query_hint_map = node_it->second;
2512  auto hint_it = registered_query_hint_map.find(node->getId());
2513  if (hint_it != registered_query_hint_map.end()) {
2514  auto const& registered_query_hint = hint_it->second;
2516  // apply global hint to the registered query hint for this query block
2517  return std::make_optional(registered_query_hint || global_hints_);
2518  } else {
2519  return std::make_optional(registered_query_hint);
2520  }
2521  }
2522  }
2524  // if no hint is registered from this query block
2525  // we return global hint instead
2526  return std::make_optional(global_hints_);
2527  }
2528  return std::nullopt;
2529  }
2530 
2531  std::unordered_map<size_t, std::unordered_map<unsigned, RegisteredQueryHint>>&
2533  return query_hint_;
2534  }
2535 
2537 
2538  void setGlobalQueryHints(const RegisteredQueryHint& global_hints) {
2539  global_hints_ = global_hints;
2540  }
2541 
2545  void resetQueryExecutionState();
2546 
2547  private:
2548  void build(const rapidjson::Value& query_ast, RelAlgDagBuilder& root_dag_builder);
2549 
2551  std::vector<std::shared_ptr<RelAlgNode>> nodes_;
2552  std::vector<std::shared_ptr<RexSubQuery>> subqueries_;
2554  // node hash --> {node id --> registered hint}
2555  // we additionally consider node id to recognize corresponding hint correctly
2556  // i.e., to recognize the correct hint when two subqueries are identical
2557  std::unordered_map<size_t, std::unordered_map<unsigned, RegisteredQueryHint>>
2560 };
2561 
2562 using RANodeOutput = std::vector<RexInput>;
2563 
2564 RANodeOutput get_node_output(const RelAlgNode* ra_node);
2565 
2566 std::string tree_string(const RelAlgNode*, const size_t depth = 0);
std::vector< std::shared_ptr< const RexScalar > > scalar_exprs_
DEVICE auto upper_bound(ARGS &&...args)
Definition: gpu_enabled.h:123
std::shared_ptr< RelAlgNode > deepCopy() const override
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
const size_t getGroupByCount() const
bool hasRows() const
bool isAll() const
virtual std::string toString(RelRexToStringConfig config) const =0
std::shared_ptr< const RelAlgNode > getRootNodeShPtr() const
bool is_agg(const Analyzer::Expr *expr)
void validate_non_foreign_table_write(const TableDescriptor *table_descriptor)
Definition: FsiUtils.h:22
SortField getCollation(const size_t i) const
std::unique_ptr< const RexScalar > condition_
const RexScalar * getThen(const size_t idx) const
SQLAgg
Definition: sqldefs.h:73
bool isNestedLoopQual() const
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::unique_ptr< const RexScalar > ConstRexScalarPtr
std::vector< std::unique_ptr< const RexScalar > > getExpressionsAndRelease()
size_t getOffset() const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
void setVarlenUpdateRequired(bool required) const
RexLiteral(const bool val, const SQLTypes type, const SQLTypes target_type, const unsigned scale, const unsigned precision, const unsigned target_scale, const unsigned target_precision)
std::vector< std::unique_ptr< const RexScalar > > outer_conditions_per_level_
const size_t limit_
bool const isFlattened() const
std::unique_ptr< RexSubQuery > deepCopy() const
ConstRexScalarPtrVector getPartitionKeysAndRelease() const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
JoinType
Definition: sqldefs.h:136
std::shared_ptr< RelAlgNode > deepCopy() const override
size_t toHash() const
int getUpdateColumnCount() const
bool g_use_query_resultset_cache
Definition: Execute.cpp:148
const bool hasHintEnabled(QueryHint candidate_hint) const
std::vector< std::unique_ptr< const RexScalar > > table_func_inputs_
size_t toHash() const override
std::string cat(Ts &&...args)
void replacePartitionKey(size_t offset, std::unique_ptr< const RexScalar > &&new_partition_key)
const Rex * getTargetExpr(const size_t i) const
SQLAgg getKind() const
size_t toHash() const override
const std::shared_ptr< const RelAlgNode > ra_
RelAlgNode(RelAlgInputs inputs={})
std::string getOpTypeInfo() const
size_t size() const override
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:114
Hints * getDeliveredHints()
const std::vector< std::shared_ptr< const Analyzer::Expr > > getFilterCond() const
size_t size() const override
const size_t index_
SQLTypes
Definition: sqltypes.h:38
std::shared_ptr< RelAlgNode > deepCopy() const override
const ExplainedQueryHint & getHintInfo(QueryHint hint) const
void addHint(const ExplainedQueryHint &hint_explained)
std::string tableName
const std::string name_
bool coversOriginalNode(const RelAlgNode *node) const
const RexScalar * getFilterExpr() const
size_t size() const override
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
size_t getOperand(size_t idx) const
size_t toHash() const override
TargetColumnList const & getUpdateColumnNames() const
bool limit_delivered_
const RexScalar * getElse() const
RexOperator(const SQLOps op, std::vector< std::unique_ptr< const RexScalar >> &operands, const SQLTypeInfo &type)
RelCompound(std::unique_ptr< const RexScalar > &filter_expr, const std::vector< const Rex * > &target_exprs, const size_t groupby_count, const std::vector< const RexAgg * > &agg_exprs, const std::vector< std::string > &fields, std::vector< std::unique_ptr< const RexScalar >> &scalar_sources, const bool is_agg, bool update_disguised_as_select=false, bool delete_disguised_as_select=false, bool varlen_update_required=false, TableDescriptor const *manipulation_target_table=nullptr, ColumnNameList target_columns=ColumnNameList())
size_t getIndex() const
static thread_local unsigned crt_id_
void setCondition(std::unique_ptr< const RexScalar > &condition)
void setTargetColumns(ColumnNameList const &target_columns) const
std::string function_name_
const std::string getFieldName(const size_t i) const
std::unique_ptr< RexRef > deepCopy() const
const RexScalar * outer_join_cond_
void setEmptyResult(bool emptyResult)
bool overlaps_allow_gpu_build
Definition: QueryHint.h:231
RexScalar const * copyAndRedirectSource(RexScalar const *, size_t input_idx) const
std::unique_ptr< const RexScalar > ConstRexScalarPtr
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint > > & getQueryHints()
const RexScalar * getOuterCondition(const size_t nesting_level) const
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
void setQueryPlanDag(const std::string &extracted_query_plan_dag) const
const JoinType join_type_
unsigned getTargetScale() const
NullSortedPosition
void applyDeleteModificationsToInputNode()
bool operator==(const SortField &that) const
std::vector< std::string > TargetColumnList
size_t size() const override
const SQLTypeInfo & getType() const
size_t size() const
Hints * getDeliveredHints()
const RexScalar * getOperand(const size_t idx) const
const RexWindowBound upper_bound_
const SqlWindowFunctionKind kind_
size_t size() const override
std::vector< const Rex * > col_inputs_
const JoinType join_type_
bool hasEquivCollationOf(const RelSort &that) const
const std::vector< SortField > & getCollation() const
SQLOps
Definition: sqldefs.h:29
SortDirection getSortDir() const
size_t getNumRows() const
bool hasDeliveredHint()
const SQLTypeInfo & getType() const
size_t toHash() const override
const bool hasHintEnabled(QueryHint candidate_hint) const
void setRelNodeDagId(const size_t id) const
const std::vector< const Analyzer::ColumnVar * > lhs_join_cols_
void applyUpdateModificationsToInputNode()
const boost::variant< int64_t, double, std::string, bool, void * > literal_
std::string getFieldName(const size_t idx) const
void build(const rapidjson::Value &query_ast, RelAlgDagBuilder &root_dag_builder)
const RexScalar * getCondition() const
std::shared_ptr< std::shared_ptr< const ExecutionResult > > result_
const std::vector< std::shared_ptr< RexSubQuery > > & getSubqueries() const
RexSubQuery & operator=(const RexSubQuery &)=delete
std::unique_ptr< const RexScalar > else_expr_
const std::vector< TargetMetaInfo > getTupleType() const
size_t toHash() const override
const std::vector< std::string > & getFields() const
void addManagedInput(std::shared_ptr< const RelAlgNode > input)
unsigned getScale() const
bool hint_applied_
const std::vector< TargetMetaInfo > tuple_type_
RexSubQuery(std::shared_ptr< SQLTypeInfo > type, std::shared_ptr< std::shared_ptr< const ExecutionResult >> result, const std::shared_ptr< const RelAlgNode > ra)
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
std::optional< size_t > getIdInPlanTree() const
size_t getField() const
std::vector< std::string > fields_
size_t toHash() const override
std::vector< std::unique_ptr< const RexAgg > > getAggExprsAndRelease()
RexInput(const RelAlgNode *node, const unsigned in_index)
void addHint(const ExplainedQueryHint &hint_explained)
std::shared_ptr< RelAlgNode > deepCopy() const override
const RexScalar * getWhen(const size_t idx) const
double overlaps_keys_per_bin
Definition: QueryHint.h:233
void setFields(std::vector< std::string > &&fields)
void setFilterExpr(std::unique_ptr< const RexScalar > &new_expr)
std::vector< const Analyzer::ColumnVar * > getJoinCols(bool lhs) const
bool hasDeliveredHint()
void appendInput(std::string new_field_name, std::unique_ptr< const RexScalar > new_input)
const RexScalar * getCondition() const
std::string getOpType() const
std::string query_plan_dag_
std::shared_ptr< RelAlgNode > deepCopy() const override
bool empty_result_
void addHint(const ExplainedQueryHint &hint_explained)
const RelAlgNode * rhs_
virtual ~Rex()
std::vector< ConstRexScalarPtr > ConstRexScalarPtrVector
void forceRowwiseOutput() const
RelFilter(std::unique_ptr< const RexScalar > &filter)
const TableDescriptor * td_
const Catalog_Namespace::Catalog & cat_
size_t operator()(const RexInput &rex_in) const
RexLiteral(const std::string &val, const SQLTypes type, const SQLTypes target_type, const unsigned scale, const unsigned precision, const unsigned target_scale, const unsigned target_precision)
const std::string op_type_
const RexScalar * getOperandAndRelease(const size_t idx) const
void checkForMatchingMetaInfoTypes() const
std::vector< std::unique_ptr< const RexScalar > > scalar_sources_
bool g_enable_data_recycler
Definition: Execute.cpp:146
const ColumnDescriptor * getShardColumnMetadataForTable(const TableDescriptor *td) const
Definition: Catalog.cpp:4247
virtual std::shared_ptr< RelAlgNode > deepCopy() const =0
const RaExecutionDesc * context_data_
std::shared_ptr< const RelAlgNode > getAndOwnInput(const size_t idx) const
virtual std::unique_ptr< const RexOperator > getDisambiguated(std::vector< std::unique_ptr< const RexScalar >> &operands) const
const SQLOps op_
size_t toHash() const override
const std::string getFieldName(const size_t i) const
std::string to_string(char const *&&v)
void clearContextData() const
TableDescriptor const *const getTableDescriptor() const
const SQLAgg agg_
const size_t groupby_count_
const std::string getFieldName(const size_t i) const
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint > > query_hint_
size_t getQueryPlanDagHash() const
const std::string qualifier_
std::vector< SortField > collation_
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
size_t getRowsSize() const
size_t getColInputsSize() const
const ExplainedQueryHint & getHintInfo(QueryHint hint) const
std::vector< RexLiteral > RexLiteralArray
void setDeleteViaSelectFlag() const
void setIdInPlanTree(size_t id) const
This file contains the class specification and related data structures for Catalog.
const size_t getScalarSourcesSize() const
std::vector< std::shared_ptr< RexSubQuery > > subqueries_
void setExpressions(std::vector< std::unique_ptr< const RexScalar >> &exprs) const
const RenderInfo * render_info_
std::string to_string() const
Definition: sqltypes.h:483
const RelAlgNode * getRHS() const
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
bool g_enable_columnar_output
Definition: Execute.cpp:99
const unsigned precision_
virtual std::string toString(RelRexToStringConfig config) const =0
unsigned getIndex() const
bool isNop() const
auto const isRowwiseOutputForced() const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
void registerQueryHints(std::shared_ptr< RelAlgNode > node, Hints *hints_delivered, RegisteredQueryHint &global_query_hint)
size_t toHash() const override
virtual ~RelAlgNode()
SQLOps getOperator() const
std::vector< std::shared_ptr< RelAlgNode > > nodes_
std::shared_ptr< const RelAlgNode > RelAlgNodeInputPtr
const RexScalar * getCondition() const
bool keep_table_function_result
Definition: QueryHint.h:226
std::shared_ptr< RelAlgNode > deepCopy() const override
unsigned getId() const
bool hasDeliveredHint()
const RexScalar * getTableFuncInputAtAndRelease(const size_t idx)
const SQLTypeInfo & getType() const
const bool hasHintEnabled(const QueryHint candidate_hint) const
const bool distinct_
ColumnNameList const & getTargetColumns() const
size_t dag_node_id_
std::unique_ptr< const RexOperator > disambiguatedOperands(ConstRexScalarPtrVector &operands, ConstRexScalarPtrVector &partition_keys, ConstRexScalarPtrVector &order_keys, const std::vector< SortField > &collation) const
const NullSortedPosition nulls_pos_
const size_t offset_
#define CHECK_NE(x, y)
Definition: Logger.h:232
const std::vector< RowValues > values_
RexCase(std::vector< std::pair< std::unique_ptr< const RexScalar >, std::unique_ptr< const RexScalar >>> &expr_pair_list, std::unique_ptr< const RexScalar > &else_expr)
NullSortedPosition getNullsPosition() const
bool isRenaming() const
void setIndex(const unsigned in_index) const
const ExplainedQueryHint & getHintInfo(QueryHint hint) const
RelSort(const std::vector< SortField > &collation, const size_t limit, const size_t offset, std::shared_ptr< const RelAlgNode > input, bool limit_delivered)
T getVal() const
size_t toHash() const override
Hints * getDeliveredHints()
std::vector< std::string > fields_
const SQLTypeInfo type_
const RexScalar * getAndReleaseCondition() const
std::unique_ptr< Hints > hints_
RexLiteral(const int64_t val, const SQLTypes type, const SQLTypes target_type, const unsigned scale, const unsigned precision, const unsigned target_scale, const unsigned target_precision)
const TableDescriptor * table_descriptor_
const std::vector< std::shared_ptr< const RelJoin > > original_joins_
std::shared_ptr< const RexScalar > offset
std::unique_ptr< Hints > hints_
std::vector< std::unique_ptr< const RexScalar > > scalar_exprs_
void registerHint(const QueryHint hint)
Definition: QueryHint.h:251
const RelAlgNode * lhs_
std::shared_ptr< RelAlgNode > deepCopy() const override
size_t toHash() const override
RegisteredQueryHint global_hints_
size_t size() const override
std::shared_ptr< SQLTypeInfo > type_
size_t size() const override
const RexScalar * getAndReleaseCondition()
std::string getFieldName(const size_t i) const
const ColumnDescriptor * getMetadataForColumn(int tableId, const std::string &colName) const
void addHint(const ExplainedQueryHint &hint_explained)
size_t branchCount() const
RexSubQuery(const std::shared_ptr< const RelAlgNode > ra)
const RelAlgNode * getInput(const size_t idx) const
RexAbstractInput(const unsigned in_index)
RelFilter(std::unique_ptr< const RexScalar > &filter, std::shared_ptr< const RelAlgNode > input)
const std::vector< std::shared_ptr< const Analyzer::Expr > > filter_ops_
std::vector< std::shared_ptr< const RelJoin > > getOriginalJoins() const
Catalog_Namespace::Catalog const & catalog_
const RelAlgNode & getRootNode() const
std::string getQueryPlanDag() const
RelAggregate(const size_t groupby_count, std::vector< std::unique_ptr< const RexAgg >> &agg_exprs, const std::vector< std::string > &fields, std::shared_ptr< const RelAlgNode > input)
std::unique_ptr< const RexScalar > filter_
void setCondition(std::unique_ptr< const RexScalar > &condition)
bool isSimple() const
std::vector< std::unique_ptr< const RexScalar > > operands_
std::optional< size_t > hash_
const size_t groupby_count_
void setContextData(const RaExecutionDesc *context_data) const
size_t toHash() const override
std::vector< std::string > fields_
size_t query_plan_dag_hash_
std::shared_ptr< RelAlgNode > deepCopy() const override
const ExplainedQueryHint & getHintInfo(QueryHint hint) const
std::optional< size_t > hash_
const RexScalar * getProjectAtAndRelease(const size_t idx) const
void visitScalarExprs(EXPR_VISITOR_FUNCTOR visitor_functor) const
unsigned getId() const
std::shared_ptr< RelAlgNode > deepCopy() const override
const RelAlgNode * node_
std::unique_ptr< Hints > hints_
size_t getTableFuncInputsSize() const
std::unique_ptr< RexLiteral > deepCopy() const
virtual void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input)
std::string toString() const
void eachNode(std::function< void(RelAlgNode const *)> const &) const
static std::string yieldModifyOperationString(ModifyOperation const op)
ModifyOperation getOperation() const
std::unique_ptr< RexInput > deepCopy() const
void setModifiedTableDescriptor(TableDescriptor const *td) const
void setFields(std::vector< std::string > &&fields)
size_t size() const override
std::shared_ptr< Fragmenter_Namespace::AbstractFragmenter > fragmenter
const SQLTypes type_
static ModifyOperation yieldModifyOperationEnum(std::string const &op_string)
void setScalarSources(std::vector< std::unique_ptr< const RexScalar >> &new_sources)
std::vector< std::unique_ptr< const RexAgg > > agg_exprs_
std::vector< TargetMetaInfo > targets_metainfo_
const std::vector< std::unique_ptr< const RexAgg > > & getAggExprs() const
Hints * getDeliveredHints()
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
bool isEmptyResult() const
const RelAlgNode * getRelAlg() const
size_t size() const override
size_t toHash() const override
size_t size() const override
SortDirection
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
RexWindowFunctionOperator(const SqlWindowFunctionKind kind, ConstRexScalarPtrVector &operands, ConstRexScalarPtrVector &partition_keys, ConstRexScalarPtrVector &order_keys, const std::vector< SortField > collation, const RexWindowBound &lower_bound, const RexWindowBound &upper_bound, const bool is_rows, const SQLTypeInfo &ti)
const RexScalar * getProjectAt(const size_t idx) const
std::vector< std::shared_ptr< const RelAlgNode >> RelAlgInputs
const std::vector< SortField > collation_
const RaExecutionDesc * getContextData() const
const std::vector< std::string > & getFields() const
#define CHECK_LT(x, y)
Definition: Logger.h:233
Definition: sqltypes.h:52
bool hasInput(const RelAlgNode *needle) const
const std::vector< std::string > & getFieldNames() const
const std::vector< std::string > & getFields() const
const std::vector< const Analyzer::ColumnVar * > rhs_join_cols_
void setCollation(std::vector< SortField > &&collation)
int32_t countRexLiteralArgs() const
std::unique_ptr< Hints > hints_
size_t overlaps_max_size
Definition: QueryHint.h:230
const ConstRexScalarPtrVector & getPartitionKeys() const
const RexWindowBound & getLowerBound() const
const RelAlgNode * getLHS() const
std::string tree_string(const RelAlgNode *ra, const size_t depth)
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
std::unique_ptr< Hints > hints_
const std::vector< const Rex * > target_exprs_
void addHint(const ExplainedQueryHint &hint_explained)
void setTableFuncInputs(std::vector< std::unique_ptr< const RexScalar >> &exprs)
const RexScalar * getOuterJoinCond() const
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
RelLogicalUnion(RelAlgInputs, bool is_all)
std::vector< std::unique_ptr< const RexAgg > > agg_exprs_
static RelRexToStringConfig defaults()
SortField(const size_t field, const SortDirection sort_dir, const NullSortedPosition nulls_pos)
std::unique_ptr< const RexScalar > filter_expr_
void setSourceNode(const RelAlgNode *node) const
void resetQueryExecutionState()
bool hasWindowFunctionExpr() const
std::vector< ConstRexScalarPtr > ConstRexScalarPtrVector
ConstRexScalarPtrVector order_keys_
SqlWindowFunctionKind getKind() const
const size_t getGroupByCount() const
std::unordered_map< QueryHint, ExplainedQueryHint > Hints
Definition: QueryHint.h:263
size_t toHash() const override
size_t collationCount() const
QueryHint
Definition: QueryHint.h:29
RelModify(Catalog_Namespace::Catalog const &cat, TableDescriptor const *const td, bool flattened, ModifyOperation op, TargetColumnList const &target_column_list, RelAlgNodeInputPtr input)
virtual size_t size() const =0
const RelAlgNode * getSourceNode() const
auto const isDeleteViaSelect() const
void registerSubquery(std::shared_ptr< RexSubQuery > subquery)
void setExecutionResult(const std::shared_ptr< const ExecutionResult > result)
bool operator==(const RelSort &that) const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
bool isAggregate() const
const RelFilter * getOriginalFilter() const
size_t getLimit() const
std::shared_ptr< RelAlgNode > deepCopy() const override
JoinType getJoinType() const
RelLogicalValues(const std::vector< TargetMetaInfo > &tuple_type, std::vector< RowValues > &values)
std::string get_type_name() const
Definition: sqltypes.h:443
std::unique_ptr< const RexOperator > getDisambiguated(std::vector< std::unique_ptr< const RexScalar >> &operands) const override
std::optional< size_t > id_in_plan_tree_
bool hint_applied_
void replaceOrderKey(size_t offset, std::unique_ptr< const RexScalar > &&new_order_key)
bool hasDeliveredHint()
const size_t getNumShards() const
std::vector< std::pair< std::unique_ptr< const RexScalar >, std::unique_ptr< const RexScalar > > > expr_pair_list_
std::string typeName(const T *v)
Definition: toString.h:102
RelAlgDagBuilder()=delete
SqlWindowFunctionKind
Definition: sqldefs.h:111
size_t toHash() const override
RexFunctionOperator(const std::string &name, ConstRexScalarPtrVector &operands, const SQLTypeInfo &ti)
const SQLTypes target_type_
std::unique_ptr< const RexScalar > condition_
void replaceOperands(std::vector< std::unique_ptr< const RexScalar >> &&new_operands)
const RexWindowBound & getUpperBound() const
const std::vector< std::string > field_names_
RelLeftDeepInnerJoin(const std::shared_ptr< RelFilter > &filter, RelAlgInputs inputs, std::vector< std::shared_ptr< const RelJoin >> &original_joins)
const RexScalar * getTableFuncInputAt(const size_t idx) const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
static auto const HASH_N
unsigned getPrecision() const
const JoinType getJoinType(const size_t nesting_level) const
RelTableFunction(const std::string &function_name, RelAlgInputs inputs, std::vector< std::string > &fields, std::vector< const Rex * > col_inputs, std::vector< std::unique_ptr< const RexScalar >> &table_func_inputs, std::vector< std::unique_ptr< const RexScalar >> &target_exprs)
std::string getFunctionName() const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
const SortDirection sort_dir_
std::vector< const RexAgg * > getAggregatesAndRelease()
const std::vector< std::string > & getFields() const
bool isDistinct() const
std::string getFieldName(const size_t i) const
const RexScalar * getValueAt(const size_t row_idx, const size_t col_idx) const
size_t toHash() const override
bool g_enable_watchdog false
Definition: Execute.cpp:79
const RexScalar * getInnerCondition() const
ModifyOperation operation_
#define CHECK(condition)
Definition: Logger.h:223
ConstRexScalarPtrVector getOrderKeysAndRelease() const
bool operator==(const RexInput &that) const
const ConstRexScalarPtrVector & getOrderKeys() const
RelProject(std::vector< std::unique_ptr< const RexScalar >> &scalar_exprs, const std::vector< std::string > &fields, std::shared_ptr< const RelAlgNode > input)
auto const isUpdateViaSelect() const
const std::string op_typeinfo_
void setOutputMetainfo(const std::vector< TargetMetaInfo > &targets_metainfo) const
SQLTypes getTargetType() const
RANodeOutput get_node_output(const RelAlgNode *ra_node)
size_t size() const
ConstRexScalarPtrVector partition_keys_
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
RexLiteral(const double val, const SQLTypes type, const SQLTypes target_type, const unsigned scale, const unsigned precision, const unsigned target_scale, const unsigned target_precision)
void setFields(std::vector< std::string > &&fields)
std::vector< RexLiteralArray > TupleContentsArray
const RexAgg * getAggExpr(size_t i) const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
const SQLTypeInfo type_
std::shared_ptr< RelAlgNode > deepCopy() const override
const std::vector< size_t > operands_
void replaceInput(std::shared_ptr< const RelAlgNode > old_input, std::shared_ptr< const RelAlgNode > input) override
const unsigned target_precision_
const RegisteredQueryHint & getGlobalHints() const
std::shared_ptr< RelAlgNode > deepCopy() const override
const std::shared_ptr< RelFilter > original_filter_
void injectOffsetInFragmentExpr() const
const size_t getNumFragments() const
size_t getAggExprSize() const
virtual size_t toHash() const =0
std::string getQualifier() const
std::vector< std::string > ColumnNameList
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
ModifyManipulationTarget(bool const update_via_select=false, bool const delete_via_select=false, bool const varlen_update_required=false, TableDescriptor const *table_descriptor=nullptr, ColumnNameList target_columns=ColumnNameList())
RexLiteral(const SQLTypes target_type)
QueryNotSupported(const std::string &reason)
const unsigned target_scale_
Definition: sqltypes.h:45
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
size_t size() const override
std::vector< RexInput > RANodeOutput
std::vector< std::unique_ptr< const RexScalar >> RowValues
size_t toHash() const override
const size_t getAggExprsCount() const
const std::string & getName() const
const size_t inputCount() const
size_t getRelNodeDagId() const
string name
Definition: setup.in.py:72
auto const isVarlenUpdateRequired() const
double overlaps_bucket_threshold
Definition: QueryHint.h:229
size_t toHash() const override
RexAgg(const SQLAgg agg, const bool distinct, const SQLTypeInfo &type, const std::vector< size_t > &operands)
const RexScalar * getAndReleaseCondition() const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
const size_t field_
size_t toHash() const override
size_t size() const override
std::unique_ptr< RexAgg > deepCopy() const
size_t toHash() const override
void setFields(std::vector< std::string > &&new_fields)
const RexWindowBound lower_bound_
const QueryHint getHint() const
Definition: QueryHint.h:121
void setUpdateViaSelectFlag() const
RelScan(const TableDescriptor *td, const std::vector< std::string > &field_names)
SQLTypes getType() const
size_t size() const override
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
const unsigned scale_
const TableDescriptor * getTableDescriptor() const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
std::shared_ptr< const ExecutionResult > getExecutionResult() const
TargetColumnList target_column_list_
TableDescriptor const * table_descriptor_
void setAggExprs(std::vector< std::unique_ptr< const RexAgg >> &agg_exprs)
std::vector< std::string > fields_
JoinType getJoinType() const
bool hasContextData() const
bool isLimitDelivered() const
RelTranslatedJoin(const RelAlgNode *lhs, const RelAlgNode *rhs, const std::vector< const Analyzer::ColumnVar * > lhs_join_cols, const std::vector< const Analyzer::ColumnVar * > rhs_join_cols, const std::vector< std::shared_ptr< const Analyzer::Expr >> filter_ops, const RexScalar *outer_join_cond, const bool nested_loop, const JoinType join_type, const std::string &op_type, const std::string &qualifier, const std::string &op_typeinfo)
size_t getFilterCondSize() const
void setGlobalQueryHints(const RegisteredQueryHint &global_hints)
const bool hasHintEnabled(QueryHint candidate_hint) const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
size_t toHash() const override
const ExplainedQueryHint & getHintInfo(QueryHint hint) const
bool isAnyQueryHintDelivered() const
Definition: QueryHint.h:246
std::shared_ptr< RelAlgNode > deepCopy() const override
unsigned getTargetPrecision() const
virtual size_t toHash() const =0
#define VLOG(n)
Definition: Logger.h:317
RelJoin(std::shared_ptr< const RelAlgNode > lhs, std::shared_ptr< const RelAlgNode > rhs, std::unique_ptr< const RexScalar > &condition, const JoinType join_type)
RelModify(Catalog_Namespace::Catalog const &cat, TableDescriptor const *const td, bool flattened, std::string const &op_string, TargetColumnList const &target_column_list, RelAlgNodeInputPtr input)
RelAlgInputs inputs_
const RexScalar * getTargetExpr(size_t idx) const
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
RexRef(const size_t index)
TableDescriptor const * getModifiedTableDescriptor() const
void setCondition(std::unique_ptr< const RexScalar > &condition)
bool isIdentity() const
const std::string getFieldName(const size_t i) const
const RexScalar * getScalarSource(const size_t i) const
constexpr auto is_datetime(SQLTypes type)
Definition: sqltypes.h:263
const bool hasHintEnabled(QueryHint candidate_hint) const
size_t toHash() const override
std::vector< std::unique_ptr< const RexScalar > > target_exprs_
Hints * getDeliveredHints()
const bool is_agg_
std::optional< RegisteredQueryHint > getQueryHint(const RelAlgNode *node) const
size_t toHash() const override
bool validateTargetColumns(VALIDATION_FUNCTOR validator) const
const unsigned id_
static void resetRelAlgFirstId() noexcept