OmniSciDB  21ac014ffc
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
QueryRewrite.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "QueryRewrite.h"
18 
19 #include <algorithm>
20 #include <memory>
21 #include <vector>
22 
23 #include "ExpressionRange.h"
24 #include "ExpressionRewrite.h"
25 #include "Logger/Logger.h"
26 #include "Parser/ParserNode.h"
27 
29  const RelAlgExecutionUnit& ra_exe_unit_in) const {
30  auto rewritten_exe_unit = rewriteConstrainedByIn(ra_exe_unit_in);
31  return rewriteOverlapsJoin(rewritten_exe_unit);
32 }
33 
35  const RelAlgExecutionUnit& ra_exe_unit_in) const {
37  return ra_exe_unit_in;
38  }
39  if (ra_exe_unit_in.join_quals.empty()) {
40  return ra_exe_unit_in;
41  }
42 
43  std::list<std::shared_ptr<Analyzer::Expr>> quals;
44  quals.insert(quals.end(), ra_exe_unit_in.quals.begin(), ra_exe_unit_in.quals.end());
45 
46  JoinQualsPerNestingLevel join_condition_per_nesting_level;
47  for (const auto& join_condition_in : ra_exe_unit_in.join_quals) {
48  JoinCondition join_condition{{}, join_condition_in.type};
49 
50  for (const auto& join_qual_expr_in : join_condition_in.quals) {
51  auto new_overlaps_quals = rewrite_overlaps_conjunction(join_qual_expr_in);
52  if (new_overlaps_quals) {
53  const auto& overlaps_quals = *new_overlaps_quals;
54 
55  // Add overlaps qual
56  join_condition.quals.insert(join_condition.quals.end(),
57  overlaps_quals.join_quals.begin(),
58  overlaps_quals.join_quals.end());
59 
60  // Add original quals
61  join_condition.quals.insert(join_condition.quals.end(),
62  overlaps_quals.quals.begin(),
63  overlaps_quals.quals.end());
64  } else {
65  join_condition.quals.push_back(join_qual_expr_in);
66  }
67  }
68  join_condition_per_nesting_level.push_back(join_condition);
69  }
70  return {ra_exe_unit_in.input_descs,
71  ra_exe_unit_in.input_col_descs,
72  ra_exe_unit_in.simple_quals,
73  quals,
74  join_condition_per_nesting_level,
75  ra_exe_unit_in.groupby_exprs,
76  ra_exe_unit_in.target_exprs,
77  ra_exe_unit_in.estimator,
78  ra_exe_unit_in.sort_info,
79  ra_exe_unit_in.scan_limit,
80  ra_exe_unit_in.query_hint,
81  ra_exe_unit_in.query_plan_dag,
82  ra_exe_unit_in.hash_table_build_plan_dag,
83  ra_exe_unit_in.use_bump_allocator};
84 }
85 
87  const RelAlgExecutionUnit& ra_exe_unit_in) const {
88  if (ra_exe_unit_in.groupby_exprs.empty()) {
89  return ra_exe_unit_in;
90  }
91  if (ra_exe_unit_in.groupby_exprs.size() == 1 && !ra_exe_unit_in.groupby_exprs.front()) {
92  return ra_exe_unit_in;
93  }
94  if (!ra_exe_unit_in.simple_quals.empty()) {
95  return ra_exe_unit_in;
96  }
97  if (ra_exe_unit_in.quals.size() != 1) {
98  return ra_exe_unit_in;
99  }
100  auto in_vals =
101  std::dynamic_pointer_cast<Analyzer::InValues>(ra_exe_unit_in.quals.front());
102  if (!in_vals) {
103  in_vals = std::dynamic_pointer_cast<Analyzer::InValues>(
104  rewrite_expr(ra_exe_unit_in.quals.front().get()));
105  }
106  if (!in_vals || in_vals->get_value_list().empty()) {
107  return ra_exe_unit_in;
108  }
109  for (const auto& in_val : in_vals->get_value_list()) {
110  if (!std::dynamic_pointer_cast<Analyzer::Constant>(in_val)) {
111  break;
112  }
113  }
114  if (dynamic_cast<const Analyzer::CaseExpr*>(in_vals->get_arg())) {
115  return ra_exe_unit_in;
116  }
117  auto case_expr = generateCaseForDomainValues(in_vals.get());
118  return rewriteConstrainedByInImpl(ra_exe_unit_in, case_expr, in_vals.get());
119 }
120 
122  const RelAlgExecutionUnit& ra_exe_unit_in,
123  const std::shared_ptr<Analyzer::CaseExpr> case_expr,
124  const Analyzer::InValues* in_vals) const {
125  std::list<std::shared_ptr<Analyzer::Expr>> new_groupby_list;
126  std::vector<Analyzer::Expr*> new_target_exprs;
127  bool rewrite{false};
128  size_t groupby_idx{0};
129  auto it = ra_exe_unit_in.groupby_exprs.begin();
130  for (const auto& group_expr : ra_exe_unit_in.groupby_exprs) {
131  CHECK(group_expr);
132  ++groupby_idx;
133  if (*group_expr == *in_vals->get_arg()) {
134  const auto expr_range = getExpressionRange(it->get(), query_infos_, executor_);
135  if (expr_range.getType() != ExpressionRangeType::Integer) {
136  ++it;
137  continue;
138  }
139  const size_t range_sz = expr_range.getIntMax() - expr_range.getIntMin() + 1;
140  if (range_sz <= in_vals->get_value_list().size() * g_constrained_by_in_threshold) {
141  ++it;
142  continue;
143  }
144  new_groupby_list.push_back(case_expr);
145  for (size_t i = 0; i < ra_exe_unit_in.target_exprs.size(); ++i) {
146  const auto target = ra_exe_unit_in.target_exprs[i];
147  if (*target == *in_vals->get_arg()) {
148  auto var_case_expr = makeExpr<Analyzer::Var>(
149  case_expr->get_type_info(), Analyzer::Var::kGROUPBY, groupby_idx);
150  target_exprs_owned_.push_back(var_case_expr);
151  new_target_exprs.push_back(var_case_expr.get());
152  } else {
153  new_target_exprs.push_back(target);
154  }
155  }
156  rewrite = true;
157  } else {
158  new_groupby_list.push_back(group_expr);
159  }
160  ++it;
161  }
162  if (!rewrite) {
163  return ra_exe_unit_in;
164  }
165  return {ra_exe_unit_in.input_descs,
166  ra_exe_unit_in.input_col_descs,
167  ra_exe_unit_in.simple_quals,
168  ra_exe_unit_in.quals,
169  ra_exe_unit_in.join_quals,
170  new_groupby_list,
171  new_target_exprs,
172  nullptr,
173  ra_exe_unit_in.sort_info,
174  ra_exe_unit_in.scan_limit,
175  ra_exe_unit_in.query_hint,
176  ra_exe_unit_in.query_plan_dag,
177  ra_exe_unit_in.hash_table_build_plan_dag};
178 }
179 
180 std::shared_ptr<Analyzer::CaseExpr> QueryRewriter::generateCaseForDomainValues(
181  const Analyzer::InValues* in_vals) {
182  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
183  case_expr_list;
184  auto in_val_arg = in_vals->get_arg()->deep_copy();
185  for (const auto& in_val : in_vals->get_value_list()) {
186  auto case_cond = makeExpr<Analyzer::BinOper>(
187  SQLTypeInfo(kBOOLEAN, true), false, kEQ, kONE, in_val_arg, in_val);
188  auto in_val_copy = in_val->deep_copy();
189  auto ti = in_val_copy->get_type_info();
190  if (ti.is_string() && ti.get_compression() == kENCODING_DICT) {
191  ti.set_comp_param(0);
192  }
193  in_val_copy->set_type_info(ti);
194  case_expr_list.emplace_back(case_cond, in_val_copy);
195  }
196  // TODO(alex): refine the expression range for case with empty else expression;
197  // for now, add a dummy else which should never be taken
198  auto else_expr = case_expr_list.front().second;
199  return makeExpr<Analyzer::CaseExpr>(
200  case_expr_list.front().second->get_type_info(), false, case_expr_list, else_expr);
201 }
202 
203 namespace {
204 
205 // TODO(adb): centralize and share (e..g with insert_one_dict_str)
206 bool check_string_id_overflow(const int32_t string_id, const SQLTypeInfo& ti) {
207  switch (ti.get_size()) {
208  case 1:
209  return string_id > max_valid_int_value<int8_t>();
210  case 2:
211  return string_id > max_valid_int_value<int16_t>();
212  case 4:
213  return string_id > max_valid_int_value<int32_t>();
214  default:
215  UNREACHABLE();
216  }
217  UNREACHABLE();
218  return false;
219 }
220 
221 } // namespace
222 
223 /* Rewrites an update query of the form `SELECT new_value, OFFSET_IN_FRAGMENT() FROM t
224  * WHERE <update_filter_condition>` to `SELECT CASE WHEN <update_filer_condition> THEN
225  * new_value ELSE existing value END FROM t`
226  */
228  const RelAlgExecutionUnit& ra_exe_unit_in,
229  std::shared_ptr<Analyzer::Expr> column_to_update) const {
230  CHECK_EQ(ra_exe_unit_in.target_exprs.size(), size_t(2));
231  CHECK(ra_exe_unit_in.groupby_exprs.size() == 1 &&
232  !ra_exe_unit_in.groupby_exprs.front());
233 
234  if (ra_exe_unit_in.join_quals.size() > 0) {
235  throw std::runtime_error("Update via join not yet supported for temporary tables.");
236  }
237 
238  auto new_column_value = ra_exe_unit_in.target_exprs.front()->deep_copy();
239  const auto& new_column_ti = new_column_value->get_type_info();
240  if (column_to_update->get_type_info().is_dict_encoded_string()) {
241  CHECK(new_column_ti.is_dict_encoded_string());
242  if (new_column_ti.get_comp_param() > 0 &&
243  new_column_ti.get_comp_param() !=
244  column_to_update->get_type_info().get_comp_param()) {
245  throw std::runtime_error(
246  "Updating a dictionary encoded string using another dictionary encoded string "
247  "column is not yet supported, unless both columns share dictionaries.");
248  }
249  if (auto uoper = dynamic_cast<Analyzer::UOper*>(new_column_value.get())) {
250  if (uoper->get_optype() == kCAST &&
251  dynamic_cast<const Analyzer::Constant*>(uoper->get_operand())) {
252  const auto original_constant_expr =
253  dynamic_cast<const Analyzer::Constant*>(uoper->get_operand());
254  CHECK(original_constant_expr);
255  CHECK(original_constant_expr->get_type_info().is_string());
256  // extract the string, insert it into the dict for the table we are updating,
257  // and place the dictionary ID in the oper
258  auto cat = executor_->getCatalog();
259  CHECK(cat);
260 
261  CHECK(column_to_update->get_type_info().is_dict_encoded_string());
262  const auto dict_id = column_to_update->get_type_info().get_comp_param();
263  std::map<int, StringDictionary*> string_dicts;
264  const auto dd = cat->getMetadataForDict(dict_id, /*load_dict=*/true);
265  CHECK(dd);
266  auto string_dict = dd->stringDict;
267  CHECK(string_dict);
268 
269  auto string_id =
270  string_dict->getOrAdd(*original_constant_expr->get_constval().stringval);
271  if (check_string_id_overflow(string_id, column_to_update->get_type_info())) {
272  throw std::runtime_error(
273  "Ran out of space in dictionary, cannot update column with dictionary "
274  "encoded string value. Dictionary ID: " +
275  std::to_string(dict_id));
276  }
277  if (string_id == inline_int_null_value<int32_t>()) {
278  string_id = inline_fixed_encoding_null_val(column_to_update->get_type_info());
279  }
280 
281  // Codegen expects a string value. The string will be
282  // resolved to its ID during Constant codegen. Copy the string from the
283  // original expr
284  Datum datum;
285  datum.stringval =
286  new std::string(*original_constant_expr->get_constval().stringval);
287  Datum new_string_datum{datum};
288 
289  new_column_value =
290  makeExpr<Analyzer::Constant>(column_to_update->get_type_info(),
291  original_constant_expr->get_is_null(),
292  new_string_datum);
293 
294  // Roll the string dict generation forward, as we have added a string
295  auto row_set_mem_owner = executor_->getRowSetMemoryOwner();
296  CHECK(row_set_mem_owner);
297  auto& str_dict_generations = row_set_mem_owner->getStringDictionaryGenerations();
298  if (str_dict_generations.getGeneration(dict_id) > -1) {
299  str_dict_generations.updateGeneration(dict_id,
300  string_dict->storageEntryCount());
301  } else {
302  // Simple update with no filters does not use a CASE, and therefore does not add
303  // a valid generation
304  str_dict_generations.setGeneration(dict_id, string_dict->storageEntryCount());
305  }
306  }
307  }
308  }
309 
310  auto input_col_descs = ra_exe_unit_in.input_col_descs;
311 
312  std::shared_ptr<Analyzer::Expr> filter;
313  std::vector<std::shared_ptr<Analyzer::Expr>> filter_exprs;
314  filter_exprs.insert(filter_exprs.end(),
315  ra_exe_unit_in.simple_quals.begin(),
316  ra_exe_unit_in.simple_quals.end());
317  filter_exprs.insert(
318  filter_exprs.end(), ra_exe_unit_in.quals.begin(), ra_exe_unit_in.quals.end());
319 
320  if (filter_exprs.size() > 0) {
321  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
322  case_expr_list;
323  if (filter_exprs.size() == 1) {
324  filter = filter_exprs.front();
325  } else {
326  filter = std::accumulate(
327  std::next(filter_exprs.begin()),
328  filter_exprs.end(),
329  filter_exprs.front(),
330  [](const std::shared_ptr<Analyzer::Expr> a,
331  const std::shared_ptr<Analyzer::Expr> b) {
332  CHECK_EQ(a->get_type_info().get_type(), b->get_type_info().get_type());
333  return makeExpr<Analyzer::BinOper>(a->get_type_info().get_type(),
334  SQLOps::kAND,
336  a->deep_copy(),
337  b->deep_copy());
338  });
339  }
340  auto when_expr = filter; // only one filter, will be a BinOper if multiple filters
341  case_expr_list.emplace_back(std::make_pair(when_expr, new_column_value));
342  auto case_expr = Parser::CaseExpr::normalize(case_expr_list, column_to_update);
343 
344  auto col_to_update_var =
345  std::dynamic_pointer_cast<Analyzer::ColumnVar>(column_to_update);
346  CHECK(col_to_update_var);
347  auto col_to_update_desc =
348  std::make_shared<const InputColDescriptor>(col_to_update_var->get_column_id(),
349  col_to_update_var->get_table_id(),
350  col_to_update_var->get_rte_idx());
351  auto existing_col_desc_it = std::find_if(
352  input_col_descs.begin(),
353  input_col_descs.end(),
354  [&col_to_update_desc](const std::shared_ptr<const InputColDescriptor>& in) {
355  return *in == *col_to_update_desc;
356  });
357  if (existing_col_desc_it == input_col_descs.end()) {
358  input_col_descs.push_back(col_to_update_desc);
359  }
360  target_exprs_owned_.emplace_back(case_expr);
361  } else {
362  // no filters, simply project the update value
363  target_exprs_owned_.emplace_back(new_column_value);
364  }
365 
366  std::vector<Analyzer::Expr*> target_exprs;
367  CHECK_EQ(target_exprs_owned_.size(), size_t(1));
368  target_exprs.emplace_back(target_exprs_owned_.front().get());
369 
370  RelAlgExecutionUnit rewritten_exe_unit{ra_exe_unit_in.input_descs,
371  input_col_descs,
372  {},
373  {},
374  ra_exe_unit_in.join_quals,
375  ra_exe_unit_in.groupby_exprs,
376  target_exprs,
377  ra_exe_unit_in.estimator,
378  ra_exe_unit_in.sort_info,
379  ra_exe_unit_in.scan_limit,
380  ra_exe_unit_in.query_hint,
381  ra_exe_unit_in.query_plan_dag,
382  ra_exe_unit_in.hash_table_build_plan_dag,
383  ra_exe_unit_in.use_bump_allocator,
384  ra_exe_unit_in.union_all,
385  ra_exe_unit_in.query_state};
386  return rewritten_exe_unit;
387 }
388 
389 /* Rewrites a delete query of the form `SELECT OFFSET_IN_FRAGMENT() FROM t
390  * WHERE <delete_filter_condition>` to `SELECT CASE WHEN <delete_filter_condition> THEN
391  * true ELSE existing value END FROM t`
392  */
394  const RelAlgExecutionUnit& ra_exe_unit_in,
395  std::shared_ptr<Analyzer::ColumnVar> delete_column) const {
396  CHECK_EQ(ra_exe_unit_in.target_exprs.size(), size_t(1));
397  CHECK(ra_exe_unit_in.groupby_exprs.size() == 1 &&
398  !ra_exe_unit_in.groupby_exprs.front());
399 
400  // TODO(adb): is this possible?
401  if (ra_exe_unit_in.join_quals.size() > 0) {
402  throw std::runtime_error("Delete via join not yet supported for temporary tables.");
403  }
404 
405  Datum true_datum;
406  true_datum.boolval = true;
407  const auto deleted_constant =
408  makeExpr<Analyzer::Constant>(delete_column->get_type_info(), false, true_datum);
409 
410  auto input_col_descs = ra_exe_unit_in.input_col_descs;
411 
412  std::shared_ptr<Analyzer::Expr> filter;
413  std::vector<std::shared_ptr<Analyzer::Expr>> filter_exprs;
414  filter_exprs.insert(filter_exprs.end(),
415  ra_exe_unit_in.simple_quals.begin(),
416  ra_exe_unit_in.simple_quals.end());
417  filter_exprs.insert(
418  filter_exprs.end(), ra_exe_unit_in.quals.begin(), ra_exe_unit_in.quals.end());
419 
420  if (filter_exprs.size() > 0) {
421  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
422  case_expr_list;
423  if (filter_exprs.size() == 1) {
424  filter = filter_exprs.front();
425  } else {
426  filter = std::accumulate(
427  std::next(filter_exprs.begin()),
428  filter_exprs.end(),
429  filter_exprs.front(),
430  [](const std::shared_ptr<Analyzer::Expr> a,
431  const std::shared_ptr<Analyzer::Expr> b) {
432  CHECK_EQ(a->get_type_info().get_type(), b->get_type_info().get_type());
433  return makeExpr<Analyzer::BinOper>(a->get_type_info().get_type(),
434  SQLOps::kAND,
436  a->deep_copy(),
437  b->deep_copy());
438  });
439  }
440  std::shared_ptr<Analyzer::Expr> column_to_update{nullptr};
441  auto when_expr = filter; // only one filter, will be a BinOper if multiple filters
442  case_expr_list.emplace_back(std::make_pair(when_expr, deleted_constant));
443  auto case_expr = Parser::CaseExpr::normalize(case_expr_list, delete_column);
444 
445  // the delete column should not be projected, but check anyway
446  auto delete_col_desc_it = std::find_if(
447  input_col_descs.begin(),
448  input_col_descs.end(),
449  [&delete_column](const std::shared_ptr<const InputColDescriptor>& in) {
450  return in->getColId() == delete_column->get_column_id();
451  });
452  CHECK(delete_col_desc_it == input_col_descs.end());
453  auto delete_col_desc =
454  std::make_shared<const InputColDescriptor>(delete_column->get_column_id(),
455  delete_column->get_table_id(),
456  delete_column->get_rte_idx());
457  input_col_descs.push_back(delete_col_desc);
458  target_exprs_owned_.emplace_back(case_expr);
459  } else {
460  // no filters, simply project the deleted=true column value for all rows
461  auto delete_col_desc =
462  std::make_shared<const InputColDescriptor>(delete_column->get_column_id(),
463  delete_column->get_table_id(),
464  delete_column->get_rte_idx());
465  input_col_descs.push_back(delete_col_desc);
466  target_exprs_owned_.emplace_back(deleted_constant);
467  }
468 
469  std::vector<Analyzer::Expr*> target_exprs;
470  CHECK_EQ(target_exprs_owned_.size(), size_t(1));
471  target_exprs.emplace_back(target_exprs_owned_.front().get());
472 
473  RelAlgExecutionUnit rewritten_exe_unit{ra_exe_unit_in.input_descs,
474  input_col_descs,
475  {},
476  {},
477  ra_exe_unit_in.join_quals,
478  ra_exe_unit_in.groupby_exprs,
479  target_exprs,
480  ra_exe_unit_in.estimator,
481  ra_exe_unit_in.sort_info,
482  ra_exe_unit_in.scan_limit,
483  ra_exe_unit_in.query_hint,
484  ra_exe_unit_in.query_plan_dag,
485  ra_exe_unit_in.hash_table_build_plan_dag,
486  ra_exe_unit_in.use_bump_allocator,
487  ra_exe_unit_in.union_all,
488  ra_exe_unit_in.query_state};
489  return rewritten_exe_unit;
490 }
std::vector< Analyzer::Expr * > target_exprs
#define CHECK_EQ(x, y)
Definition: Logger.h:214
HOST DEVICE int get_size() const
Definition: sqltypes.h:333
size_t g_constrained_by_in_threshold
Definition: Execute.cpp:100
std::string cat(Ts &&...args)
const std::optional< bool > union_all
int8_t boolval
Definition: sqltypes.h:205
std::vector< InputDescriptor > input_descs
#define UNREACHABLE()
Definition: Logger.h:250
Definition: sqldefs.h:49
Definition: sqldefs.h:30
std::vector< JoinCondition > JoinQualsPerNestingLevel
const std::list< std::shared_ptr< Analyzer::Expr > > groupby_exprs
Analyzer::ExpressionPtr rewrite_expr(const Analyzer::Expr *expr)
std::string to_string(char const *&&v)
bool g_enable_overlaps_hashjoin
Definition: Execute.cpp:95
static std::shared_ptr< Analyzer::Expr > normalize(const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &, const std::shared_ptr< Analyzer::Expr >)
Definition: ParserNode.cpp:935
Classes representing a parse tree.
RelAlgExecutionUnit rewrite(const RelAlgExecutionUnit &ra_exe_unit_in) const
const JoinQualsPerNestingLevel join_quals
Executor * executor_
Definition: QueryRewrite.h:51
RelAlgExecutionUnit rewriteOverlapsJoin(const RelAlgExecutionUnit &ra_exe_unit_in) const
Definition: sqldefs.h:37
DEVICE auto accumulate(ARGS &&...args)
Definition: gpu_enabled.h:42
boost::optional< OverlapsJoinConjunction > rewrite_overlaps_conjunction(const std::shared_ptr< Analyzer::Expr > expr)
ExpressionRange getExpressionRange(const Analyzer::BinOper *expr, const std::vector< InputTableInfo > &query_infos, const Executor *, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
const std::shared_ptr< Analyzer::Estimator > estimator
std::string * stringval
Definition: sqltypes.h:214
Definition: sqldefs.h:69
bool check_string_id_overflow(const int32_t string_id, const SQLTypeInfo &ti)
RelAlgExecutionUnit rewriteColumnarUpdate(const RelAlgExecutionUnit &ra_exe_unit_in, std::shared_ptr< Analyzer::Expr > column_to_update) const
const std::list< std::shared_ptr< Analyzer::Expr > > & get_value_list() const
Definition: Analyzer.h:586
virtual std::shared_ptr< Analyzer::Expr > deep_copy() const =0
const std::vector< InputTableInfo > & query_infos_
Definition: QueryRewrite.h:50
std::list< std::shared_ptr< Analyzer::Expr > > quals
int64_t getIntMax() const
RegisteredQueryHint query_hint
#define CHECK(condition)
Definition: Logger.h:206
int64_t inline_fixed_encoding_null_val(const SQL_TYPE_INFO &ti)
std::shared_ptr< const query_state::QueryState > query_state
std::list< std::shared_ptr< const InputColDescriptor > > input_col_descs
RelAlgExecutionUnit rewriteColumnarDelete(const RelAlgExecutionUnit &ra_exe_unit_in, std::shared_ptr< Analyzer::ColumnVar > delete_column) const
static std::shared_ptr< Analyzer::CaseExpr > generateCaseForDomainValues(const Analyzer::InValues *)
RelAlgExecutionUnit rewriteConstrainedByIn(const RelAlgExecutionUnit &ra_exe_unit_in) const
const Expr * get_arg() const
Definition: Analyzer.h:584
std::list< std::shared_ptr< Analyzer::Expr > > simple_quals
RelAlgExecutionUnit rewriteConstrainedByInImpl(const RelAlgExecutionUnit &ra_exe_unit_in, const std::shared_ptr< Analyzer::CaseExpr >, const Analyzer::InValues *) const
std::vector< std::shared_ptr< Analyzer::Expr > > target_exprs_owned_
Definition: QueryRewrite.h:52
HashTableBuildDagMap hash_table_build_plan_dag