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