OmniSciDB  29e35f4d58
ExpressionRange.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 "ExpressionRange.h"
18 #include <algorithm>
19 #include <cfenv>
20 #include <cmath>
21 #include "DateTimeTranslator.h"
22 #include "DateTimeUtils.h"
23 #include "DateTruncate.h"
25 #include "Execute.h"
26 #include "ExtractFromTime.h"
27 #include "GroupByAndAggregate.h"
29 
30 #define DEF_OPERATOR(fname, op) \
31  ExpressionRange fname(const ExpressionRange& other) const { \
32  if (type_ == ExpressionRangeType::Invalid || \
33  other.type_ == ExpressionRangeType::Invalid) { \
34  return ExpressionRange::makeInvalidRange(); \
35  } \
36  CHECK(type_ == other.type_); \
37  switch (type_) { \
38  case ExpressionRangeType::Integer: \
39  return binOp<int64_t>(other, [](const int64_t x, const int64_t y) { \
40  return int64_t(checked_int64_t(x) op y); \
41  }); \
42  case ExpressionRangeType::Float: \
43  return binOp<float>(other, [](const float x, const float y) { \
44  std::feclearexcept(FE_OVERFLOW); \
45  std::feclearexcept(FE_UNDERFLOW); \
46  auto result = x op y; \
47  if (std::fetestexcept(FE_OVERFLOW) || std::fetestexcept(FE_UNDERFLOW)) { \
48  throw std::runtime_error("overflow / underflow"); \
49  } \
50  return result; \
51  }); \
52  case ExpressionRangeType::Double: \
53  return binOp<double>(other, [](const double x, const double y) { \
54  std::feclearexcept(FE_OVERFLOW); \
55  std::feclearexcept(FE_UNDERFLOW); \
56  auto result = x op y; \
57  if (std::fetestexcept(FE_OVERFLOW) || std::fetestexcept(FE_UNDERFLOW)) { \
58  throw std::runtime_error("overflow / underflow"); \
59  } \
60  return result; \
61  }); \
62  default: \
63  CHECK(false); \
64  } \
65  CHECK(false); \
66  return ExpressionRange::makeInvalidRange(); \
67  }
68 
69 DEF_OPERATOR(ExpressionRange::operator+, +)
70 DEF_OPERATOR(ExpressionRange::operator-, -)
71 DEF_OPERATOR(ExpressionRange::operator*, *)
72 
73 void apply_fp_qual(const Datum const_datum,
74  const SQLTypes const_type,
75  const SQLOps sql_op,
76  ExpressionRange& qual_range) {
77  double const_val = get_value_from_datum<double>(const_datum, const_type);
78  switch (sql_op) {
79  case kGT:
80  case kGE:
81  qual_range.setFpMin(std::max(qual_range.getFpMin(), const_val));
82  break;
83  case kLT:
84  case kLE:
85  qual_range.setFpMax(std::min(qual_range.getFpMax(), const_val));
86  break;
87  case kEQ:
88  qual_range.setFpMin(std::max(qual_range.getFpMin(), const_val));
89  qual_range.setFpMax(std::min(qual_range.getFpMax(), const_val));
90  break;
91  default: // there may be other operators, but don't do anything with them
92  break;
93  }
94 }
95 
96 void apply_int_qual(const Datum const_datum,
97  const SQLTypes const_type,
98  const SQLOps sql_op,
99  ExpressionRange& qual_range) {
100  int64_t const_val = get_value_from_datum<int64_t>(const_datum, const_type);
101  switch (sql_op) {
102  case kGT:
103  qual_range.setIntMin(std::max(qual_range.getIntMin(), const_val + 1));
104  break;
105  case kGE:
106  qual_range.setIntMin(std::max(qual_range.getIntMin(), const_val));
107  break;
108  case kLT:
109  qual_range.setIntMax(std::min(qual_range.getIntMax(), const_val - 1));
110  break;
111  case kLE:
112  qual_range.setIntMax(std::min(qual_range.getIntMax(), const_val));
113  break;
114  case kEQ:
115  qual_range.setIntMin(std::max(qual_range.getIntMin(), const_val));
116  qual_range.setIntMax(std::min(qual_range.getIntMax(), const_val));
117  break;
118  default: // there may be other operators, but don't do anything with them
119  break;
120  }
121 }
122 
123 void apply_hpt_qual(const Datum const_datum,
124  const SQLTypes const_type,
125  const int32_t const_dimen,
126  const int32_t col_dimen,
127  const SQLOps sql_op,
128  ExpressionRange& qual_range) {
129  CHECK(const_dimen != col_dimen);
130  Datum datum{0};
131  if (const_dimen > col_dimen) {
132  datum.bigintval =
133  get_value_from_datum<int64_t>(const_datum, const_type) /
134  DateTimeUtils::get_timestamp_precision_scale(const_dimen - col_dimen);
135  } else {
136  datum.bigintval =
137  get_value_from_datum<int64_t>(const_datum, const_type) *
138  DateTimeUtils::get_timestamp_precision_scale(col_dimen - const_dimen);
139  }
140  apply_int_qual(datum, const_type, sql_op, qual_range);
141 }
142 
144  const Analyzer::ColumnVar* col_expr,
145  const ExpressionRange& col_range,
146  const boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
147  if (!simple_quals) {
148  return col_range;
149  }
150  ExpressionRange qual_range(col_range);
151  for (auto const& itr : simple_quals.get()) {
152  auto qual_bin_oper = dynamic_cast<Analyzer::BinOper*>(itr.get());
153  if (!qual_bin_oper) {
154  continue;
155  }
156  const Analyzer::Expr* left_operand = qual_bin_oper->get_left_operand();
157  auto qual_col = dynamic_cast<const Analyzer::ColumnVar*>(left_operand);
158  if (!qual_col) {
159  // Check for possibility that column is wrapped in a cast
160  // Presumes that only simple casts (i.e. timestamp to timestamp or int to int) have
161  // been passed through by BinOper::normalize_simple_predicate
162  auto u_expr = dynamic_cast<const Analyzer::UOper*>(left_operand);
163  if (!u_expr) {
164  continue;
165  }
166  qual_col = dynamic_cast<const Analyzer::ColumnVar*>(u_expr->get_operand());
167  if (!qual_col) {
168  continue;
169  }
170  }
171  if (qual_col->get_table_id() != col_expr->get_table_id() ||
172  qual_col->get_column_id() != col_expr->get_column_id()) {
173  continue;
174  }
175  const Analyzer::Expr* right_operand = qual_bin_oper->get_right_operand();
176  auto qual_const = dynamic_cast<const Analyzer::Constant*>(right_operand);
177  if (!qual_const) {
178  continue;
179  }
180  if (qual_range.getType() == ExpressionRangeType::Float ||
181  qual_range.getType() == ExpressionRangeType::Double) {
182  apply_fp_qual(qual_const->get_constval(),
183  qual_const->get_type_info().get_type(),
184  qual_bin_oper->get_optype(),
185  qual_range);
186  } else if ((qual_col->get_type_info().is_timestamp() ||
187  qual_const->get_type_info().is_timestamp()) &&
188  (qual_col->get_type_info().get_dimension() !=
189  qual_const->get_type_info().get_dimension())) {
190  apply_hpt_qual(qual_const->get_constval(),
191  qual_const->get_type_info().get_type(),
192  qual_const->get_type_info().get_dimension(),
193  qual_col->get_type_info().get_dimension(),
194  qual_bin_oper->get_optype(),
195  qual_range);
196  } else {
197  apply_int_qual(qual_const->get_constval(),
198  qual_const->get_type_info().get_type(),
199  qual_bin_oper->get_optype(),
200  qual_range);
201  }
202  }
203  if (qual_range.getType() == ExpressionRangeType::Integer) {
204  if (qual_range.getIntMin() > qual_range.getIntMax()) {
205  return ExpressionRange::makeIntRange(0, -1, 0, qual_range.hasNulls());
206  }
207  }
208  return qual_range;
209 }
210 
215  }
216  if (other.int_min_ * other.int_max_ <= 0) {
217  // if the other interval contains 0, the rule is more complicated;
218  // punt for now, we can revisit by splitting the other interval and
219  // taking the convex hull of the resulting two intervals
221  }
222  auto div_range = binOp<int64_t>(other, [](const int64_t x, const int64_t y) {
223  return int64_t(checked_int64_t(x) / y);
224  });
225  if (g_null_div_by_zero) {
226  div_range.setHasNulls();
227  }
228  return div_range;
229 }
230 
232  if (type_ != other.type_) {
234  }
236  switch (type_) {
241  result.has_nulls_ = has_nulls_ || other.has_nulls_;
242  result.int_min_ = std::min(int_min_, other.int_min_);
243  result.int_max_ = std::max(int_max_, other.int_max_);
244  result.bucket_ = std::min(bucket_, other.bucket_);
245  break;
246  }
249  result.type_ = type_;
250  result.has_nulls_ = has_nulls_ || other.has_nulls_;
251  result.fp_min_ = std::min(fp_min_, other.fp_min_);
252  result.fp_max_ = std::max(fp_max_, other.fp_max_);
253  break;
254  }
255  default:
256  CHECK(false);
257  }
258  return result;
259 }
260 
262  if (type_ != other.type_) {
263  return false;
264  }
265  switch (type_) {
267  return true;
269  return has_nulls_ == other.has_nulls_ && int_min_ == other.int_min_ &&
270  int_max_ == other.int_max_;
271  }
274  return has_nulls_ == other.has_nulls_ && fp_min_ == other.fp_min_ &&
275  fp_max_ == other.fp_max_;
276  }
277  default:
278  CHECK(false);
279  }
280  return false;
281 }
282 
284  if (ti.is_array()) {
285  return typeSupportsRange(ti.get_elem_type());
286  } else {
287  return (ti.is_number() || ti.is_boolean() || ti.is_time() ||
288  (ti.is_string() && ti.get_compression() == kENCODING_DICT));
289  }
290 }
291 
293  const Analyzer::BinOper* expr,
294  const std::vector<InputTableInfo>& query_infos,
295  const Executor*,
296  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
297 
299 
301  const Analyzer::ColumnVar* col_expr,
302  const std::vector<InputTableInfo>& query_infos,
303  const Executor* executor,
304  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
305 
307 
309  const std::vector<InputTableInfo>& query_infos,
310  const Executor*);
311 
313  const Analyzer::UOper* u_expr,
314  const std::vector<InputTableInfo>& query_infos,
315  const Executor*,
316  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
317 
319  const Analyzer::ExtractExpr* extract_expr,
320  const std::vector<InputTableInfo>& query_infos,
321  const Executor*,
322  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
323 
325  const Analyzer::DatetruncExpr* datetrunc_expr,
326  const std::vector<InputTableInfo>& query_infos,
327  const Executor* executor,
328  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
329 
331  const Analyzer::Expr* expr,
332  const std::vector<InputTableInfo>& query_infos,
333  const Executor* executor,
334  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
335  const auto& expr_ti = expr->get_type_info();
336  if (!ExpressionRange::typeSupportsRange(expr_ti)) {
338  }
339  auto bin_oper_expr = dynamic_cast<const Analyzer::BinOper*>(expr);
340  if (bin_oper_expr) {
341  return getExpressionRange(bin_oper_expr, query_infos, executor, simple_quals);
342  }
343  auto constant_expr = dynamic_cast<const Analyzer::Constant*>(expr);
344  if (constant_expr) {
345  return getExpressionRange(constant_expr);
346  }
347  auto column_var_expr = dynamic_cast<const Analyzer::ColumnVar*>(expr);
348  if (column_var_expr) {
349  return getExpressionRange(column_var_expr, query_infos, executor, simple_quals);
350  }
351  auto like_expr = dynamic_cast<const Analyzer::LikeExpr*>(expr);
352  if (like_expr) {
353  return getExpressionRange(like_expr);
354  }
355  auto case_expr = dynamic_cast<const Analyzer::CaseExpr*>(expr);
356  if (case_expr) {
357  return getExpressionRange(case_expr, query_infos, executor);
358  }
359  auto u_expr = dynamic_cast<const Analyzer::UOper*>(expr);
360  if (u_expr) {
361  return getExpressionRange(u_expr, query_infos, executor, simple_quals);
362  }
363  auto extract_expr = dynamic_cast<const Analyzer::ExtractExpr*>(expr);
364  if (extract_expr) {
365  return getExpressionRange(extract_expr, query_infos, executor, simple_quals);
366  }
367  auto datetrunc_expr = dynamic_cast<const Analyzer::DatetruncExpr*>(expr);
368  if (datetrunc_expr) {
369  return getExpressionRange(datetrunc_expr, query_infos, executor, simple_quals);
370  }
372 }
373 
374 namespace {
375 
376 int64_t scale_up_interval_endpoint(const int64_t endpoint, const SQLTypeInfo& ti) {
377  return endpoint * static_cast<int64_t>(exp_to_scale(ti.get_scale()));
378 }
379 
380 } // namespace
381 
383  const Analyzer::BinOper* expr,
384  const std::vector<InputTableInfo>& query_infos,
385  const Executor* executor,
386  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
387  const auto& lhs =
388  getExpressionRange(expr->get_left_operand(), query_infos, executor, simple_quals);
389  const auto& rhs =
390  getExpressionRange(expr->get_right_operand(), query_infos, executor, simple_quals);
391  switch (expr->get_optype()) {
392  case kPLUS:
393  return lhs + rhs;
394  case kMINUS:
395  return lhs - rhs;
396  case kMULTIPLY:
397  return lhs * rhs;
398  case kDIVIDE: {
399  const auto& lhs_type = expr->get_left_operand()->get_type_info();
400  if (lhs_type.is_decimal() && lhs.getType() != ExpressionRangeType::Invalid) {
401  CHECK(lhs.getType() == ExpressionRangeType::Integer);
402  const auto adjusted_lhs = ExpressionRange::makeIntRange(
403  scale_up_interval_endpoint(lhs.getIntMin(), lhs_type),
404  scale_up_interval_endpoint(lhs.getIntMax(), lhs_type),
405  0,
406  lhs.hasNulls());
407  return adjusted_lhs / rhs;
408  }
409  return lhs / rhs;
410  }
411  default:
412  break;
413  }
415 }
416 
418  if (constant_expr->get_is_null()) {
420  }
421  const auto constant_type = constant_expr->get_type_info().get_type();
422  const auto datum = constant_expr->get_constval();
423  switch (constant_type) {
424  case kTINYINT: {
425  const int64_t v = datum.tinyintval;
426  return ExpressionRange::makeIntRange(v, v, 0, false);
427  }
428  case kSMALLINT: {
429  const int64_t v = datum.smallintval;
430  return ExpressionRange::makeIntRange(v, v, 0, false);
431  }
432  case kINT: {
433  const int64_t v = datum.intval;
434  return ExpressionRange::makeIntRange(v, v, 0, false);
435  }
436  case kBIGINT:
437  case kNUMERIC:
438  case kDECIMAL: {
439  const int64_t v = datum.bigintval;
440  return ExpressionRange::makeIntRange(v, v, 0, false);
441  }
442  case kTIME:
443  case kTIMESTAMP:
444  case kDATE: {
445  const int64_t v = datum.bigintval;
446  return ExpressionRange::makeIntRange(v, v, 0, false);
447  }
448  case kFLOAT: {
449  return ExpressionRange::makeFloatRange(datum.floatval, datum.floatval, false);
450  }
451  case kDOUBLE: {
452  return ExpressionRange::makeDoubleRange(datum.doubleval, datum.doubleval, false);
453  }
454  default:
455  break;
456  }
458 }
459 
460 #define FIND_STAT_FRAG(stat_name) \
461  const auto stat_name##_frag_index = std::stat_name##_element( \
462  nonempty_fragment_indices.begin(), \
463  nonempty_fragment_indices.end(), \
464  [&fragments, &has_nulls, col_id, col_ti](const size_t lhs_idx, \
465  const size_t rhs_idx) { \
466  const auto& lhs = fragments[lhs_idx]; \
467  const auto& rhs = fragments[rhs_idx]; \
468  auto lhs_meta_it = lhs.getChunkMetadataMap().find(col_id); \
469  if (lhs_meta_it == lhs.getChunkMetadataMap().end()) { \
470  return false; \
471  } \
472  auto rhs_meta_it = rhs.getChunkMetadataMap().find(col_id); \
473  CHECK(rhs_meta_it != rhs.getChunkMetadataMap().end()); \
474  if (lhs_meta_it->second.chunkStats.has_nulls || \
475  rhs_meta_it->second.chunkStats.has_nulls) { \
476  has_nulls = true; \
477  } \
478  if (col_ti.is_fp()) { \
479  return extract_##stat_name##_stat_double(lhs_meta_it->second.chunkStats, \
480  col_ti) < \
481  extract_##stat_name##_stat_double(rhs_meta_it->second.chunkStats, \
482  col_ti); \
483  } \
484  return extract_##stat_name##_stat(lhs_meta_it->second.chunkStats, col_ti) < \
485  extract_##stat_name##_stat(rhs_meta_it->second.chunkStats, col_ti); \
486  }); \
487  if (stat_name##_frag_index == nonempty_fragment_indices.end()) { \
488  return ExpressionRange::makeInvalidRange(); \
489  }
490 
491 namespace {
492 
493 double extract_min_stat_double(const ChunkStats& stats, const SQLTypeInfo& col_ti) {
494  return col_ti.get_type() == kDOUBLE ? stats.min.doubleval : stats.min.floatval;
495 }
496 
497 double extract_max_stat_double(const ChunkStats& stats, const SQLTypeInfo& col_ti) {
498  return col_ti.get_type() == kDOUBLE ? stats.max.doubleval : stats.max.floatval;
499 }
500 
501 int64_t get_conservative_datetrunc_bucket(const DatetruncField datetrunc_field) {
502  const int64_t day_seconds{24 * 3600};
503  const int64_t year_days{365};
504  switch (datetrunc_field) {
505  case dtYEAR:
506  return year_days * day_seconds;
507  case dtQUARTER:
508  return 90 * day_seconds; // 90 is least number of days in any quater
509  case dtMONTH:
510  return 28 * day_seconds;
511  case dtDAY:
512  return day_seconds;
513  case dtHOUR:
514  return 3600;
515  case dtMINUTE:
516  return 60;
517  case dtMILLENNIUM:
518  return 1000 * year_days * day_seconds;
519  case dtCENTURY:
520  return 100 * year_days * day_seconds;
521  case dtDECADE:
522  return 10 * year_days * day_seconds;
523  case dtWEEK:
524  return 7 * day_seconds;
525  case dtQUARTERDAY:
526  return 4 * 60 * 50;
527  default:
528  return 0;
529  }
530 }
531 
532 } // namespace
533 
535  const std::vector<InputTableInfo>& query_infos,
536  const Executor* executor,
537  const bool is_outer_join_proj) {
538  bool has_nulls = is_outer_join_proj;
539  int col_id = col_expr->get_column_id();
540  const auto& col_phys_ti = col_expr->get_type_info().is_array()
541  ? col_expr->get_type_info().get_elem_type()
542  : col_expr->get_type_info();
543  const auto col_ti = get_logical_type_info(col_phys_ti);
544  switch (col_ti.get_type()) {
545  case kTEXT:
546  case kCHAR:
547  case kVARCHAR:
548  CHECK_EQ(kENCODING_DICT, col_ti.get_compression());
549  case kBOOLEAN:
550  case kTINYINT:
551  case kSMALLINT:
552  case kINT:
553  case kBIGINT:
554  case kDECIMAL:
555  case kNUMERIC:
556  case kDATE:
557  case kTIMESTAMP:
558  case kTIME:
559  case kFLOAT:
560  case kDOUBLE: {
561  ssize_t ti_idx = -1;
562  for (size_t i = 0; i < query_infos.size(); ++i) {
563  if (col_expr->get_table_id() == query_infos[i].table_id) {
564  ti_idx = i;
565  break;
566  }
567  }
568  CHECK_NE(ssize_t(-1), ti_idx);
569  const auto& query_info = query_infos[ti_idx].info;
570  const auto& fragments = query_info.fragments;
571  const auto cd = executor->getColumnDescriptor(col_expr);
572  if (cd && cd->isVirtualCol) {
573  CHECK(cd->columnName == "rowid");
574  CHECK_EQ(kBIGINT, col_ti.get_type());
575  const int64_t num_tuples = query_info.getNumTuples();
577  0, std::max(num_tuples - 1, int64_t(0)), 0, has_nulls);
578  }
579  if (query_info.getNumTuples() == 0) {
580  // The column doesn't contain any values, synthesize an empty range.
581  if (col_ti.is_fp()) {
582  return col_ti.get_type() == kFLOAT
583  ? ExpressionRange::makeFloatRange(0, -1, false)
584  : ExpressionRange::makeDoubleRange(0, -1, false);
585  }
586  return ExpressionRange::makeIntRange(0, -1, 0, false);
587  }
588  std::vector<size_t> nonempty_fragment_indices;
589  for (size_t i = 0; i < fragments.size(); ++i) {
590  const auto& fragment = fragments[i];
591  if (!fragment.isEmptyPhysicalFragment()) {
592  nonempty_fragment_indices.push_back(i);
593  }
594  }
595  FIND_STAT_FRAG(min);
596  FIND_STAT_FRAG(max);
597  const auto& min_frag = fragments[*min_frag_index];
598  const auto min_it = min_frag.getChunkMetadataMap().find(col_id);
599  if (min_it == min_frag.getChunkMetadataMap().end()) {
601  }
602  const auto& max_frag = fragments[*max_frag_index];
603  const auto max_it = max_frag.getChunkMetadataMap().find(col_id);
604  CHECK(max_it != max_frag.getChunkMetadataMap().end());
605  for (const auto& fragment : fragments) {
606  const auto it = fragment.getChunkMetadataMap().find(col_id);
607  if (it != fragment.getChunkMetadataMap().end()) {
608  if (it->second.chunkStats.has_nulls) {
609  has_nulls = true;
610  break;
611  }
612  }
613  }
614  if (col_ti.is_fp()) {
615  const auto min_val = extract_min_stat_double(min_it->second.chunkStats, col_ti);
616  const auto max_val = extract_max_stat_double(max_it->second.chunkStats, col_ti);
617  return col_ti.get_type() == kFLOAT
618  ? ExpressionRange::makeFloatRange(min_val, max_val, has_nulls)
619  : ExpressionRange::makeDoubleRange(min_val, max_val, has_nulls);
620  }
621  const auto min_val = extract_min_stat(min_it->second.chunkStats, col_ti);
622  const auto max_val = extract_max_stat(max_it->second.chunkStats, col_ti);
623  if (max_val < min_val) {
624  // The column doesn't contain any non-null values, synthesize an empty range.
625  CHECK_GT(min_val, 0);
626  return ExpressionRange::makeIntRange(0, -1, 0, has_nulls);
627  }
628  const int64_t bucket =
629  col_ti.get_type() == kDATE ? get_conservative_datetrunc_bucket(dtDAY) : 0;
630  return ExpressionRange::makeIntRange(min_val, max_val, bucket, has_nulls);
631  }
632  default:
633  break;
634  }
636 }
637 
638 #undef FIND_STAT_FRAG
639 
641  const Analyzer::ColumnVar* col_expr,
642  const std::vector<InputTableInfo>& query_infos,
643  const Executor* executor,
644  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
645  const int rte_idx = col_expr->get_rte_idx();
646  CHECK_GE(rte_idx, 0);
647  CHECK_LT(static_cast<size_t>(rte_idx), query_infos.size());
648  bool is_outer_join_proj = rte_idx > 0 && executor->containsLeftDeepOuterJoin();
649  if (col_expr->get_table_id() > 0) {
650  auto col_range = executor->getColRange(
651  PhysicalInput{col_expr->get_column_id(), col_expr->get_table_id()});
652  if (is_outer_join_proj) {
653  col_range.setHasNulls();
654  }
655  return apply_simple_quals(col_expr, col_range, simple_quals);
656  }
657  return getLeafColumnRange(col_expr, query_infos, executor, is_outer_join_proj);
658 }
659 
661  const auto& ti = like_expr->get_type_info();
662  CHECK(ti.is_boolean());
663  const auto& arg_ti = like_expr->get_arg()->get_type_info();
665  arg_ti.get_notnull() ? 0 : inline_int_null_val(ti), 1, 0, false);
666 }
667 
669  const std::vector<InputTableInfo>& query_infos,
670  const Executor* executor) {
671  const auto& expr_pair_list = case_expr->get_expr_pair_list();
672  auto expr_range = ExpressionRange::makeInvalidRange();
673  bool has_nulls = false;
674  for (const auto& expr_pair : expr_pair_list) {
675  CHECK_EQ(expr_pair.first->get_type_info().get_type(), kBOOLEAN);
676  const auto crt_range =
677  getExpressionRange(expr_pair.second.get(), query_infos, executor);
678  if (crt_range.getType() == ExpressionRangeType::Null) {
679  has_nulls = true;
680  continue;
681  }
682  if (crt_range.getType() == ExpressionRangeType::Invalid) {
684  }
685  expr_range = (expr_range.getType() != ExpressionRangeType::Invalid)
686  ? expr_range || crt_range
687  : crt_range;
688  }
689  if (has_nulls && !(expr_range.getType() == ExpressionRangeType::Invalid)) {
690  expr_range.setHasNulls();
691  }
692  const auto else_expr = case_expr->get_else_expr();
693  CHECK(else_expr);
694  const auto else_null_expr = dynamic_cast<const Analyzer::Constant*>(else_expr);
695  if (else_null_expr && else_null_expr->get_is_null()) {
696  expr_range.setHasNulls();
697  return expr_range;
698  }
699  return expr_range || getExpressionRange(else_expr, query_infos, executor);
700 }
701 
702 namespace {
703 
705  const int64_t scale,
706  const SQLTypeInfo& target_ti) {
707  CHECK(target_ti.is_fp());
708  if (target_ti.get_type() == kFLOAT) {
710  static_cast<float>(arg_range.getIntMin()) / scale,
711  static_cast<float>(arg_range.getIntMax()) / scale,
712  arg_range.hasNulls());
713  }
715  static_cast<double>(arg_range.getIntMin()) / scale,
716  static_cast<double>(arg_range.getIntMax()) / scale,
717  arg_range.hasNulls());
718 }
719 
721  const SQLTypeInfo& oper_ti,
722  const SQLTypeInfo& target_ti) {
723  if (oper_ti.is_timestamp() && target_ti.is_date()) {
724  const auto field = dtDAY;
725  const int64_t scale =
726  oper_ti.is_high_precision_timestamp()
728  : 1;
729  const int64_t min_ts = oper_ti.is_high_precision_timestamp()
730  ? DateTruncate(field, arg_range.getIntMin() / scale)
731  : DateTruncate(field, arg_range.getIntMin());
732  const int64_t max_ts = oper_ti.is_high_precision_timestamp()
733  ? DateTruncate(field, arg_range.getIntMax() / scale)
734  : DateTruncate(field, arg_range.getIntMax());
735  const int64_t bucket = get_conservative_datetrunc_bucket(field);
736 
737  return ExpressionRange::makeIntRange(min_ts, max_ts, bucket, arg_range.hasNulls());
738  }
739 
740  const int32_t ti_dimen = target_ti.get_dimension();
741  const int32_t oper_dimen = oper_ti.get_dimension();
742  CHECK(oper_dimen != ti_dimen);
743  const int64_t min_ts =
744  ti_dimen > oper_dimen
746  arg_range.getIntMin(),
747  abs(oper_dimen - ti_dimen))
750  arg_range.getIntMin(),
751  abs(oper_dimen - ti_dimen));
752  const int64_t max_ts =
753  ti_dimen > oper_dimen
755  arg_range.getIntMax(),
756  abs(oper_dimen - ti_dimen))
759  arg_range.getIntMax(),
760  abs(oper_dimen - ti_dimen));
761 
762  return ExpressionRange::makeIntRange(min_ts, max_ts, 0, arg_range.hasNulls());
763 }
764 
765 } // namespace
766 
768  const Analyzer::UOper* u_expr,
769  const std::vector<InputTableInfo>& query_infos,
770  const Executor* executor,
771  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
772  if (u_expr->get_optype() == kUNNEST) {
773  return getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
774  }
775  if (u_expr->get_optype() != kCAST) {
777  }
778  const auto& ti = u_expr->get_type_info();
779  if (ti.is_string() && ti.get_compression() == kENCODING_DICT) {
780  const auto sdp = executor->getStringDictionaryProxy(
781  ti.get_comp_param(), executor->getRowSetMemoryOwner(), true);
782  CHECK(sdp);
783  const auto const_operand =
784  dynamic_cast<const Analyzer::Constant*>(u_expr->get_operand());
785  CHECK(const_operand);
786 
787  if (const_operand->get_is_null()) {
789  }
790  CHECK(const_operand->get_constval().stringval);
791  const int64_t v = sdp->getIdOfString(*const_operand->get_constval().stringval);
792  return ExpressionRange::makeIntRange(v, v, 0, false);
793  }
794  const auto arg_range =
795  getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
796  const auto& arg_ti = u_expr->get_operand()->get_type_info();
797  // Timestamp to Date OR Date/Timestamp casts with different precision
798  if ((ti.is_timestamp() && (arg_ti.get_dimension() != ti.get_dimension())) ||
799  ((arg_ti.is_timestamp() && ti.is_date()))) {
800  return getDateTimePrecisionCastRange(arg_range, arg_ti, ti);
801  }
802  switch (arg_range.getType()) {
805  if (ti.is_fp()) {
806  return ti.get_type() == kDOUBLE
808  arg_range.getFpMin(), arg_range.getFpMax(), arg_range.hasNulls())
809  : ExpressionRange::makeFloatRange(arg_range.getFpMin(),
810  arg_range.getFpMax(),
811  arg_range.hasNulls());
812  }
813  if (ti.is_integer()) {
815  arg_range.getFpMin(), arg_range.getFpMax(), 0, arg_range.hasNulls());
816  }
817  break;
818  }
820  if (ti.is_decimal()) {
821  CHECK_EQ(int64_t(0), arg_range.getBucket());
822  const int64_t scale = exp_to_scale(ti.get_scale() - arg_ti.get_scale());
823  return ExpressionRange::makeIntRange(arg_range.getIntMin() * scale,
824  arg_range.getIntMax() * scale,
825  0,
826  arg_range.hasNulls());
827  }
828  if (arg_ti.is_decimal()) {
829  CHECK_EQ(int64_t(0), arg_range.getBucket());
830  const int64_t scale = exp_to_scale(arg_ti.get_scale());
831  const int64_t scale_half = scale / 2;
832  if (ti.is_fp()) {
833  return fpRangeFromDecimal(arg_range, scale, ti);
834  }
835  return ExpressionRange::makeIntRange((arg_range.getIntMin() - scale_half) / scale,
836  (arg_range.getIntMax() + scale_half) / scale,
837  0,
838  arg_range.hasNulls());
839  }
840  if (ti.is_integer() || ti.is_time()) {
841  return arg_range;
842  }
843  if (ti.get_type() == kFLOAT) {
845  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
846  }
847  if (ti.get_type() == kDOUBLE) {
849  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
850  }
851  break;
852  }
854  break;
855  default:
856  CHECK(false);
857  }
859 }
860 
862  const Analyzer::ExtractExpr* extract_expr,
863  const std::vector<InputTableInfo>& query_infos,
864  const Executor* executor,
865  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
866  const int32_t extract_field{extract_expr->get_field()};
867  const auto arg_range = getExpressionRange(
868  extract_expr->get_from_expr(), query_infos, executor, simple_quals);
869  const bool has_nulls =
870  arg_range.getType() == ExpressionRangeType::Invalid || arg_range.hasNulls();
871  const auto& extract_expr_ti = extract_expr->get_from_expr()->get_type_info();
872  switch (extract_field) {
873  case kYEAR: {
874  if (arg_range.getType() == ExpressionRangeType::Invalid) {
876  }
877  CHECK(arg_range.getType() == ExpressionRangeType::Integer);
878  const int64_t year_range_min =
879  extract_expr_ti.is_high_precision_timestamp()
880  ? ExtractFromTime(
881  kYEAR,
882  arg_range.getIntMin() /
883  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
884  : ExtractFromTime(kYEAR, arg_range.getIntMin());
885  const int64_t year_range_max =
886  extract_expr_ti.is_high_precision_timestamp()
887  ? ExtractFromTime(
888  kYEAR,
889  arg_range.getIntMax() /
890  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
891  : ExtractFromTime(kYEAR, arg_range.getIntMax());
893  year_range_min, year_range_max, 0, arg_range.hasNulls());
894  }
895  case kEPOCH:
896  return arg_range;
897  case kQUARTERDAY:
898  case kQUARTER:
899  return ExpressionRange::makeIntRange(1, 4, 0, has_nulls);
900  case kMONTH:
901  return ExpressionRange::makeIntRange(1, 12, 0, has_nulls);
902  case kDAY:
903  return ExpressionRange::makeIntRange(1, 31, 0, has_nulls);
904  case kHOUR:
905  return ExpressionRange::makeIntRange(0, 23, 0, has_nulls);
906  case kMINUTE:
907  return ExpressionRange::makeIntRange(0, 59, 0, has_nulls);
908  case kSECOND:
909  return ExpressionRange::makeIntRange(0, 60, 0, has_nulls);
910  case kMILLISECOND:
911  return ExpressionRange::makeIntRange(0, 999, 0, has_nulls);
912  case kMICROSECOND:
913  return ExpressionRange::makeIntRange(0, 999999, 0, has_nulls);
914  case kNANOSECOND:
915  return ExpressionRange::makeIntRange(0, 999999999, 0, has_nulls);
916  case kDOW:
917  return ExpressionRange::makeIntRange(0, 6, 0, has_nulls);
918  case kISODOW:
919  return ExpressionRange::makeIntRange(1, 7, 0, has_nulls);
920  case kDOY:
921  return ExpressionRange::makeIntRange(1, 366, 0, has_nulls);
922  case kWEEK:
923  return ExpressionRange::makeIntRange(1, 53, 0, has_nulls);
924  default:
925  CHECK(false);
926  }
928 }
929 
931  const Analyzer::DatetruncExpr* datetrunc_expr,
932  const std::vector<InputTableInfo>& query_infos,
933  const Executor* executor,
934  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
935  const auto arg_range = getExpressionRange(
936  datetrunc_expr->get_from_expr(), query_infos, executor, simple_quals);
937  if (arg_range.getType() == ExpressionRangeType::Invalid) {
939  }
940  const auto& datetrunc_expr_ti = datetrunc_expr->get_from_expr()->get_type_info();
941  const int64_t min_ts = DateTimeTranslator::getDateTruncConstantValue(
942  arg_range.getIntMin(), datetrunc_expr->get_field(), datetrunc_expr_ti);
943  const int64_t max_ts = DateTimeTranslator::getDateTruncConstantValue(
944  arg_range.getIntMax(), datetrunc_expr->get_field(), datetrunc_expr_ti);
945  const int64_t bucket =
946  datetrunc_expr_ti.is_high_precision_timestamp()
947  ? get_conservative_datetrunc_bucket(datetrunc_expr->get_field()) *
949  datetrunc_expr_ti.get_dimension())
950  : get_conservative_datetrunc_bucket(datetrunc_expr->get_field());
951 
952  return ExpressionRange::makeIntRange(min_ts, max_ts, bucket, arg_range.hasNulls());
953 }
NEVER_INLINE DEVICE int64_t DateTruncate(DatetruncField field, const int64_t timeval)
#define CHECK_EQ(x, y)
Definition: Logger.h:201
#define FIND_STAT_FRAG(stat_name)
bool is_time() const
Definition: sqltypes.h:483
int get_column_id() const
Definition: Analyzer.h:195
static ExpressionRange makeNullRange()
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:328
Definition: sqltypes.h:52
bool is_fp() const
Definition: sqltypes.h:481
SQLTypes
Definition: sqltypes.h:41
ExpressionRange operator/(const ExpressionRange &other) const
void apply_hpt_qual(const Datum const_datum, const SQLTypes const_type, const int32_t const_dimen, const int32_t col_dimen, const SQLOps sql_op, ExpressionRange &qual_range)
void apply_int_qual(const Datum const_datum, const SQLTypes const_type, const SQLOps sql_op, ExpressionRange &qual_range)
double extract_min_stat_double(const ChunkStats &stats, const SQLTypeInfo &col_ti)
SQLOps
Definition: sqldefs.h:29
Definition: sqldefs.h:35
HOST DEVICE int get_scale() const
Definition: sqltypes.h:331
Definition: sqldefs.h:36
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:326
#define DEF_OPERATOR(fname, op)
#define CHECK_GE(x, y)
Definition: Logger.h:206
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:869
Definition: sqldefs.h:49
Definition: sqldefs.h:30
Definition: sqldefs.h:41
ExpressionRange operator||(const ExpressionRange &other) const
int64_t scale_up_interval_endpoint(const int64_t endpoint, const SQLTypeInfo &ti)
const Expr * get_from_expr() const
Definition: Analyzer.h:1146
void setIntMin(const int64_t int_min)
int64_t getIntMax() const
#define CHECK_GT(x, y)
Definition: Logger.h:205
ExpressionRangeType getType() const
constexpr int64_t get_datetime_scaled_epoch(const ScalingType direction, const int64_t epoch, const int32_t dimen)
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:334
static ExpressionRange makeFloatRange(const float fp_min, const float fp_max, const bool has_nulls)
ExpressionRange apply_simple_quals(const Analyzer::ColumnVar *col_expr, const ExpressionRange &col_range, const boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
SQLOps get_optype() const
Definition: Analyzer.h:433
DatetruncField get_field() const
Definition: Analyzer.h:1270
const Expr * get_arg() const
Definition: Analyzer.h:854
bool g_null_div_by_zero
Definition: Execute.cpp:75
const Expr * get_else_expr() const
Definition: Analyzer.h:1101
float floatval
Definition: sqltypes.h:130
Datum get_constval() const
Definition: Analyzer.h:329
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
ExpressionRangeType type_
bool is_array() const
Definition: sqltypes.h:485
int64_t getIntMin() const
DatetruncField
Definition: DateTruncate.h:42
int64_t get_conservative_datetrunc_bucket(const DatetruncField datetrunc_field)
#define CHECK_NE(x, y)
Definition: Logger.h:202
const Expr * get_from_expr() const
Definition: Analyzer.h:1271
void apply_fp_qual(const Datum const_datum, const SQLTypes const_type, const SQLOps sql_op, ExpressionRange &qual_range)
int64_t bigintval
Definition: sqltypes.h:129
NEVER_INLINE DEVICE int64_t ExtractFromTime(ExtractField field, const int64_t timeval)
const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr > > > & get_expr_pair_list() const
Definition: Analyzer.h:1098
ExpressionRange getLeafColumnRange(const Analyzer::ColumnVar *col_expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, const bool is_outer_join_proj)
SQLTypeInfoCore get_elem_type() const
Definition: sqltypes.h:659
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)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 64, 64, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void > > checked_int64_t
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
Definition: sqldefs.h:34
bool is_boolean() const
Definition: sqltypes.h:484
static ExpressionRange makeDoubleRange(const double fp_min, const double fp_max, const bool has_nulls)
bool get_is_null() const
Definition: Analyzer.h:328
#define CHECK_LT(x, y)
Definition: Logger.h:203
Definition: sqltypes.h:55
Definition: sqltypes.h:56
Definition: sqldefs.h:40
bool operator==(const ExpressionRange &other) const
int get_rte_idx() const
Definition: Analyzer.h:196
bool hasNulls() const
int get_table_id() const
Definition: Analyzer.h:194
Definition: sqltypes.h:44
void setIntMax(const int64_t int_max)
int64_t extract_min_stat(const ChunkStats &stats, const SQLTypeInfo &ti)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
bool is_number() const
Definition: sqltypes.h:482
#define CHECK(condition)
Definition: Logger.h:193
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
Definition: sqldefs.h:33
static bool typeSupportsRange(const SQLTypeInfo &ti)
Definition: sqltypes.h:48
static ExpressionRange makeInvalidRange()
static int64_t getDateTruncConstantValue(const int64_t &timeval, const DatetruncField &field, const SQLTypeInfo &ti)
ExtractField get_field() const
Definition: Analyzer.h:1145
bool is_string() const
Definition: sqltypes.h:477
ExpressionRange getDateTimePrecisionCastRange(const ExpressionRange &arg_range, const SQLTypeInfo &oper_ti, const SQLTypeInfo &target_ti)
double extract_max_stat_double(const ChunkStats &stats, const SQLTypeInfo &col_ti)
int64_t extract_max_stat(const ChunkStats &stats, const SQLTypeInfo &ti)
SQLOps get_optype() const
Definition: Analyzer.h:364
double doubleval
Definition: sqltypes.h:131
const Expr * get_right_operand() const
Definition: Analyzer.h:437
ExpressionRange fpRangeFromDecimal(const ExpressionRange &arg_range, const int64_t scale, const SQLTypeInfo &target_ti)
const Expr * get_left_operand() const
Definition: Analyzer.h:436
const Expr * get_operand() const
Definition: Analyzer.h:365