OmniSciDB  1dac507f6e
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 #include "ExpressionRange.h"
19 #include "ExpressionRewrite.h"
20 #include "Shared/Logger.h"
21 
23  const RelAlgExecutionUnit& ra_exe_unit_in) const {
24  auto rewritten_exe_unit = rewriteConstrainedByIn(ra_exe_unit_in);
25  return rewriteOverlapsJoin(rewritten_exe_unit);
26 }
27 
29  const RelAlgExecutionUnit& ra_exe_unit_in) const {
31  return ra_exe_unit_in;
32  }
33  if (ra_exe_unit_in.join_quals.empty()) {
34  return ra_exe_unit_in;
35  }
36 
37  std::list<std::shared_ptr<Analyzer::Expr>> quals;
38  quals.insert(quals.end(), ra_exe_unit_in.quals.begin(), ra_exe_unit_in.quals.end());
39 
40  JoinQualsPerNestingLevel join_condition_per_nesting_level;
41  for (const auto& join_condition_in : ra_exe_unit_in.join_quals) {
42  JoinCondition join_condition{{}, join_condition_in.type};
43 
44  for (const auto& join_qual_expr_in : join_condition_in.quals) {
45  auto new_overlaps_quals = rewrite_overlaps_conjunction(join_qual_expr_in);
46  if (new_overlaps_quals) {
47  const auto& overlaps_quals = *new_overlaps_quals;
48  join_condition.quals.insert(join_condition.quals.end(),
49  overlaps_quals.join_quals.begin(),
50  overlaps_quals.join_quals.end());
51 
52  quals.insert(
53  quals.end(), overlaps_quals.quals.begin(), overlaps_quals.quals.end());
54  } else {
55  join_condition.quals.push_back(join_qual_expr_in);
56  }
57  }
58  join_condition_per_nesting_level.push_back(join_condition);
59  }
60  return {ra_exe_unit_in.input_descs,
61  ra_exe_unit_in.input_col_descs,
62  ra_exe_unit_in.simple_quals,
63  quals,
64  join_condition_per_nesting_level,
65  ra_exe_unit_in.groupby_exprs,
66  ra_exe_unit_in.target_exprs,
67  ra_exe_unit_in.estimator,
68  ra_exe_unit_in.sort_info,
69  ra_exe_unit_in.scan_limit,
70  ra_exe_unit_in.query_features,
71  ra_exe_unit_in.use_bump_allocator};
72 }
73 
75  const RelAlgExecutionUnit& ra_exe_unit_in) const {
76  if (ra_exe_unit_in.groupby_exprs.empty()) {
77  return ra_exe_unit_in;
78  }
79  if (ra_exe_unit_in.groupby_exprs.size() == 1 && !ra_exe_unit_in.groupby_exprs.front()) {
80  return ra_exe_unit_in;
81  }
82  if (!ra_exe_unit_in.simple_quals.empty()) {
83  return ra_exe_unit_in;
84  }
85  if (ra_exe_unit_in.quals.size() != 1) {
86  return ra_exe_unit_in;
87  }
88  auto in_vals =
89  std::dynamic_pointer_cast<Analyzer::InValues>(ra_exe_unit_in.quals.front());
90  if (!in_vals) {
91  in_vals = std::dynamic_pointer_cast<Analyzer::InValues>(
92  rewrite_expr(ra_exe_unit_in.quals.front().get()));
93  }
94  if (!in_vals || in_vals->get_value_list().empty()) {
95  return ra_exe_unit_in;
96  }
97  for (const auto in_val : in_vals->get_value_list()) {
98  if (!std::dynamic_pointer_cast<Analyzer::Constant>(in_val)) {
99  break;
100  }
101  }
102  if (dynamic_cast<const Analyzer::CaseExpr*>(in_vals->get_arg())) {
103  return ra_exe_unit_in;
104  }
105  auto case_expr = generateCaseForDomainValues(in_vals.get());
106  return rewriteConstrainedByInImpl(ra_exe_unit_in, case_expr, in_vals.get());
107 }
108 
110  const RelAlgExecutionUnit& ra_exe_unit_in,
111  const std::shared_ptr<Analyzer::CaseExpr> case_expr,
112  const Analyzer::InValues* in_vals) const {
113  std::list<std::shared_ptr<Analyzer::Expr>> new_groupby_list;
114  std::vector<Analyzer::Expr*> new_target_exprs;
115  bool rewrite{false};
116  size_t groupby_idx{0};
117  auto it = ra_exe_unit_in.groupby_exprs.begin();
118  for (const auto group_expr : ra_exe_unit_in.groupby_exprs) {
119  CHECK(group_expr);
120  ++groupby_idx;
121  if (*group_expr == *in_vals->get_arg()) {
122  const auto expr_range = getExpressionRange(it->get(), query_infos_, executor_);
123  if (expr_range.getType() != ExpressionRangeType::Integer) {
124  ++it;
125  continue;
126  }
127  const size_t range_sz = expr_range.getIntMax() - expr_range.getIntMin() + 1;
128  if (range_sz <= in_vals->get_value_list().size() * g_constrained_by_in_threshold) {
129  ++it;
130  continue;
131  }
132  new_groupby_list.push_back(case_expr);
133  for (size_t i = 0; i < ra_exe_unit_in.target_exprs.size(); ++i) {
134  const auto target = ra_exe_unit_in.target_exprs[i];
135  if (*target == *in_vals->get_arg()) {
136  auto var_case_expr = makeExpr<Analyzer::Var>(
137  case_expr->get_type_info(), Analyzer::Var::kGROUPBY, groupby_idx);
138  target_exprs_owned_.push_back(var_case_expr);
139  new_target_exprs.push_back(var_case_expr.get());
140  } else {
141  new_target_exprs.push_back(target);
142  }
143  }
144  rewrite = true;
145  } else {
146  new_groupby_list.push_back(group_expr);
147  }
148  ++it;
149  }
150  if (!rewrite) {
151  return ra_exe_unit_in;
152  }
153  return {ra_exe_unit_in.input_descs,
154  ra_exe_unit_in.input_col_descs,
155  ra_exe_unit_in.simple_quals,
156  ra_exe_unit_in.quals,
157  ra_exe_unit_in.join_quals,
158  new_groupby_list,
159  new_target_exprs,
160  nullptr,
161  ra_exe_unit_in.sort_info,
162  ra_exe_unit_in.scan_limit};
163 }
164 
165 std::shared_ptr<Analyzer::CaseExpr> QueryRewriter::generateCaseForDomainValues(
166  const Analyzer::InValues* in_vals) {
167  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
168  case_expr_list;
169  auto in_val_arg = in_vals->get_arg()->deep_copy();
170  for (const auto in_val : in_vals->get_value_list()) {
171  auto case_cond = makeExpr<Analyzer::BinOper>(
172  SQLTypeInfo(kBOOLEAN, true), false, kEQ, kONE, in_val_arg, in_val);
173  auto in_val_copy = in_val->deep_copy();
174  auto ti = in_val_copy->get_type_info();
175  if (ti.is_string() && ti.get_compression() == kENCODING_DICT) {
176  ti.set_comp_param(0);
177  }
178  in_val_copy->set_type_info(ti);
179  case_expr_list.emplace_back(case_cond, in_val_copy);
180  }
181  // TODO(alex): refine the expression range for case with empty else expression;
182  // for now, add a dummy else which should never be taken
183  auto else_expr = case_expr_list.front().second;
184  return makeExpr<Analyzer::CaseExpr>(
185  case_expr_list.front().second->get_type_info(), false, case_expr_list, else_expr);
186 }
std::vector< Analyzer::Expr * > target_exprs
size_t g_constrained_by_in_threshold
Definition: Execute.cpp:91
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)
const std::vector< InputDescriptor > input_descs
bool g_enable_overlaps_hashjoin
Definition: Execute.cpp:87
QueryFeatureDescriptor query_features
CHECK(cgen_state)
RelAlgExecutionUnit rewrite(const RelAlgExecutionUnit &ra_exe_unit_in) const
const SortInfo sort_info
const JoinQualsPerNestingLevel join_quals
RelAlgExecutionUnit rewriteOverlapsJoin(const RelAlgExecutionUnit &ra_exe_unit_in) const
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
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:852
Definition: sqldefs.h:69
const std::list< std::shared_ptr< Analyzer::Expr > > & get_value_list() const
Definition: Analyzer.h:580
virtual std::shared_ptr< Analyzer::Expr > deep_copy() const =0
const std::vector< InputTableInfo > & query_infos_
Definition: QueryRewrite.h:43
std::list< std::shared_ptr< Analyzer::Expr > > quals
int64_t getIntMax() const
const Executor * executor_
Definition: QueryRewrite.h:44
std::list< std::shared_ptr< const InputColDescriptor > > input_col_descs
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:578
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:45