OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PlanState.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, 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 
17 #include "PlanState.h"
18 
19 #include "Execute.h"
20 #include "Shared/misc.h"
21 
22 bool PlanState::isLazyFetchColumn(const Analyzer::Expr* target_expr) const {
23  if (!allow_lazy_fetch_) {
24  return false;
25  }
26  const auto do_not_fetch_column = dynamic_cast<const Analyzer::ColumnVar*>(target_expr);
27  if (!do_not_fetch_column || dynamic_cast<const Analyzer::Var*>(do_not_fetch_column)) {
28  return false;
29  }
30  const auto& column_key = do_not_fetch_column->getColumnKey();
31  if (column_key.table_id > 0) {
32  const auto cd = get_column_descriptor(column_key);
33  if (cd->isVirtualCol) {
34  return false;
35  }
36  }
37  return columns_to_fetch_.find(column_key) == columns_to_fetch_.end();
38 }
39 
41  const std::list<std::shared_ptr<const InputColDescriptor>>& global_col_ids) {
42  for (const auto& col_id : global_col_ids) {
43  CHECK(col_id);
44  const auto local_col_id = global_to_local_col_ids_.size();
45  const auto it_ok =
46  global_to_local_col_ids_.insert(std::make_pair(*col_id, local_col_id));
47  // enforce uniqueness of the column ids in the scan plan
48  CHECK(it_ok.second);
49  }
50 }
51 
53  const bool fetch_column) {
54  // Previously, we consider `rte_idx` of `col_var` w/ its column key together
55  // to specify columns in the `global_to_local_col_ids_`.
56  // But there is a case when the same col has multiple 'rte_idx's
57  // For instance, the same geometry col is used not only as input col of the geo join op,
58  // but also included as input col of filter predicate
59  // In such a case, the same geometry col has two rte_idxs (the one defined by the filter
60  // predicate and the other determined by the geo join operator)
61  // The previous logic cannot cover this case b/c it allows only one `rte_idx` per col
62  // But it is safe to share `rte_idx` of among all use cases of the same col
63  CHECK(col_var);
64  const auto& global_col_key = col_var->getColumnKey();
65  InputColDescriptor scan_col_desc(global_col_key.column_id,
66  global_col_key.table_id,
67  global_col_key.db_id,
68  col_var->get_rte_idx());
69  std::optional<int> col_id{std::nullopt};
70  // let's try to find col_id w/ considering `rte_idx`
71  const auto it = global_to_local_col_ids_.find(scan_col_desc);
72  if (it != global_to_local_col_ids_.end()) {
73  // we have a valid col_id
74  col_id = it->second;
75  } else {
76  // otherwise, let's try to find col_id for the same col
77  // (but have different 'rte_idx') to share it w/ `col_var`
78  for (auto const& kv : global_to_local_col_ids_) {
79  if (kv.first.getColumnKey() == global_col_key) {
80  col_id = kv.second;
81  break;
82  }
83  }
84  }
85  if (col_id && *col_id >= 0) {
86  if (fetch_column) {
87  addColumnToFetch(global_col_key);
88  }
89  return *col_id;
90  }
91  CHECK(false) << "Expected to find " << global_col_key;
92  return {};
93 }
94 
96  std::shared_ptr<Analyzer::Expr> expr) {
97  auto it = left_join_non_hashtable_quals_.find(idx);
98  if (it == left_join_non_hashtable_quals_.end()) {
99  std::vector<std::shared_ptr<Analyzer::Expr>> expr_vec{expr};
100  left_join_non_hashtable_quals_.emplace(idx, std::move(expr_vec));
101  } else {
102  it->second.emplace_back(expr);
103  }
104 }
105 
106 const std::unordered_set<shared::ColumnKey>& PlanState::getColumnsToFetch() const {
107  return columns_to_fetch_;
108 }
109 
110 const std::unordered_set<shared::ColumnKey>& PlanState::getColumnsToNotFetch() const {
111  return columns_to_not_fetch_;
112 }
113 
114 bool PlanState::isColumnToFetch(const shared::ColumnKey& column_key) const {
115  return shared::contains(columns_to_fetch_, column_key);
116 }
117 
118 bool PlanState::isColumnToNotFetch(const shared::ColumnKey& column_key) const {
119  return shared::contains(columns_to_not_fetch_, column_key);
120 }
121 
122 // todo (yoonmin): determine non-lazy fetch compilation in a high-level; to avoid
123 // recompilation which may incur noticeable overhead
125  bool unmark_lazy_fetch) {
126  if (unmark_lazy_fetch) {
127  // This column was previously marked for lazy fetch but we now intentionally
128  // mark it as non-lazy fetch column
129  auto it = columns_to_not_fetch_.find(column_key);
130  if (it != columns_to_not_fetch_.end()) {
131  columns_to_not_fetch_.erase(it);
132  }
133  } else {
134  if (columns_to_not_fetch_.count(column_key)) {
135  // this case represents a query w/ fetching expressions with the order of
136  // cv and an expression on it, i.e., SELECT col1, ST_NPoints(col1) FROM ...
137  // since we first touch the cv itself and we forcely mark it as lazy-fetch
138  // but to evaluate the expression, we must fetch the same cv;
139  // so let's fetch the cv to allow evaluating the expression using the same cv
141  }
142  }
143  CHECK(!isColumnToNotFetch(column_key)) << column_key;
144  columns_to_fetch_.emplace(column_key);
145 }
146 
148  CHECK(!isColumnToFetch(column_key)) << column_key;
149  columns_to_not_fetch_.emplace(column_key);
150 }
151 
153  const std::vector<TargetExprCodegen>& target_exprs_to_codegen) const {
154  return std::any_of(target_exprs_to_codegen.begin(),
155  target_exprs_to_codegen.end(),
156  [](const TargetExprCodegen& target_expr) {
157  return target_expr.target_info.sql_type.usesFlatBuffer();
158  });
159 }
160 
162  const std::vector<TargetExprCodegen>& target_exprs_to_codegen) {
163  auto const needs_lazy_fetch = hasExpressionNeedsLazyFetch(target_exprs_to_codegen);
164  for (const auto& expr : target_exprs_to_codegen) {
165  if (needs_lazy_fetch && !expr.target_info.sql_type.usesFlatBuffer()) {
166  if (auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(expr.target_expr)) {
167  // force non-lazy fetch on all other columns that don't support flatbuffer
168  addColumnToFetch(col_var->getColumnKey(), /*unmark_lazy_fetch=*/true);
169  }
170  }
171  }
172 }
bool contains(const T &container, const U &element)
Definition: misc.h:195
std::unordered_map< size_t, std::vector< std::shared_ptr< Analyzer::Expr > > > left_join_non_hashtable_quals_
Definition: PlanState.h:61
std::unordered_map< InputColDescriptor, size_t > global_to_local_col_ids_
Definition: PlanState.h:59
void addColumnToFetch(const shared::ColumnKey &column_key, bool unmark_lazy_fetch=false)
Definition: PlanState.cpp:124
bool allow_lazy_fetch_
Definition: PlanState.h:62
std::unordered_set< shared::ColumnKey > columns_to_not_fetch_
Definition: PlanState.h:117
void addNonHashtableQualForLeftJoin(size_t idx, std::shared_ptr< Analyzer::Expr > expr)
Definition: PlanState.cpp:95
bool hasExpressionNeedsLazyFetch(const std::vector< TargetExprCodegen > &target_exprs_to_codegen) const
Definition: PlanState.cpp:152
void addColumnToNotFetch(const shared::ColumnKey &column_key)
Definition: PlanState.cpp:147
bool isColumnToFetch(const shared::ColumnKey &column_key) const
Definition: PlanState.cpp:114
int getLocalColumnId(const Analyzer::ColumnVar *col_var, const bool fetch_column)
Definition: PlanState.cpp:52
bool isLazyFetchColumn(const Analyzer::Expr *target_expr) const
Definition: PlanState.cpp:22
const ColumnDescriptor * get_column_descriptor(const shared::ColumnKey &column_key)
Definition: Execute.h:213
void allocateLocalColumnIds(const std::list< std::shared_ptr< const InputColDescriptor >> &global_col_ids)
Definition: PlanState.cpp:40
const std::unordered_set< shared::ColumnKey > & getColumnsToFetch() const
Definition: PlanState.cpp:106
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
bool isColumnToNotFetch(const shared::ColumnKey &column_key) const
Definition: PlanState.cpp:118
const std::unordered_set< shared::ColumnKey > & getColumnsToNotFetch() const
Definition: PlanState.cpp:110
#define CHECK(condition)
Definition: Logger.h:291
bool any_of(std::vector< Analyzer::Expr * > const &target_exprs)
std::unordered_set< shared::ColumnKey > columns_to_fetch_
Definition: PlanState.h:116
void registerNonLazyFetchExpression(const std::vector< TargetExprCodegen > &target_exprs_to_codegen)
Definition: PlanState.cpp:161
int32_t get_rte_idx() const
Definition: Analyzer.h:202