OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExpressionRange.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 "ExpressionRange.h"
18 #include "DateTimeTranslator.h"
19 #include "DateTimeUtils.h"
20 #include "DateTruncate.h"
22 #include "Execute.h"
23 #include "ExtractFromTime.h"
24 #include "GroupByAndAggregate.h"
26 
27 #include <algorithm>
28 #include <cfenv>
29 #include <cmath>
30 
31 #define DEF_OPERATOR(fname, op) \
32  ExpressionRange fname(const ExpressionRange& other) const { \
33  if (type_ == ExpressionRangeType::Invalid || \
34  other.type_ == ExpressionRangeType::Invalid) { \
35  return ExpressionRange::makeInvalidRange(); \
36  } \
37  CHECK(type_ == other.type_); \
38  switch (type_) { \
39  case ExpressionRangeType::Integer: \
40  return binOp<int64_t>(other, [](const int64_t x, const int64_t y) { \
41  return int64_t(checked_int64_t(x) op y); \
42  }); \
43  case ExpressionRangeType::Float: \
44  return binOp<float>(other, [](const float x, const float y) { \
45  std::feclearexcept(FE_OVERFLOW); \
46  std::feclearexcept(FE_UNDERFLOW); \
47  auto result = x op y; \
48  if (std::fetestexcept(FE_OVERFLOW) || std::fetestexcept(FE_UNDERFLOW)) { \
49  throw std::runtime_error("overflow / underflow"); \
50  } \
51  return result; \
52  }); \
53  case ExpressionRangeType::Double: \
54  return binOp<double>(other, [](const double x, const double y) { \
55  std::feclearexcept(FE_OVERFLOW); \
56  std::feclearexcept(FE_UNDERFLOW); \
57  auto result = x op y; \
58  if (std::fetestexcept(FE_OVERFLOW) || std::fetestexcept(FE_UNDERFLOW)) { \
59  throw std::runtime_error("overflow / underflow"); \
60  } \
61  return result; \
62  }); \
63  default: \
64  CHECK(false); \
65  } \
66  CHECK(false); \
67  return ExpressionRange::makeInvalidRange(); \
68  }
69 
70 DEF_OPERATOR(ExpressionRange::operator+, +)
71 DEF_OPERATOR(ExpressionRange::operator-, -)
72 DEF_OPERATOR(ExpressionRange::operator*, *)
73 
74 void apply_fp_qual(const Datum const_datum,
75  const SQLTypes const_type,
76  const SQLOps sql_op,
77  ExpressionRange& qual_range) {
78  double const_val = get_value_from_datum<double>(const_datum, const_type);
79  switch (sql_op) {
80  case kGT:
81  case kGE:
82  qual_range.setFpMin(std::max(qual_range.getFpMin(), const_val));
83  break;
84  case kLT:
85  case kLE:
86  qual_range.setFpMax(std::min(qual_range.getFpMax(), const_val));
87  break;
88  case kEQ:
89  qual_range.setFpMin(std::max(qual_range.getFpMin(), const_val));
90  qual_range.setFpMax(std::min(qual_range.getFpMax(), const_val));
91  break;
92  default: // there may be other operators, but don't do anything with them
93  break;
94  }
95 }
96 
97 void apply_int_qual(const Datum const_datum,
98  const SQLTypes const_type,
99  const SQLOps sql_op,
100  ExpressionRange& qual_range) {
101  int64_t const_val = get_value_from_datum<int64_t>(const_datum, const_type);
102  switch (sql_op) {
103  case kGT:
104  qual_range.setIntMin(std::max(qual_range.getIntMin(), const_val + 1));
105  break;
106  case kGE:
107  qual_range.setIntMin(std::max(qual_range.getIntMin(), const_val));
108  break;
109  case kLT:
110  qual_range.setIntMax(std::min(qual_range.getIntMax(), const_val - 1));
111  break;
112  case kLE:
113  qual_range.setIntMax(std::min(qual_range.getIntMax(), const_val));
114  break;
115  case kEQ:
116  qual_range.setIntMin(std::max(qual_range.getIntMin(), const_val));
117  qual_range.setIntMax(std::min(qual_range.getIntMax(), const_val));
118  break;
119  default: // there may be other operators, but don't do anything with them
120  break;
121  }
122 }
123 
124 void apply_hpt_qual(const Datum const_datum,
125  const SQLTypes const_type,
126  const int32_t const_dimen,
127  const int32_t col_dimen,
128  const SQLOps sql_op,
129  ExpressionRange& qual_range) {
130  CHECK(const_dimen != col_dimen);
131  Datum datum{0};
132  if (const_dimen > col_dimen) {
133  datum.bigintval =
134  get_value_from_datum<int64_t>(const_datum, const_type) /
135  DateTimeUtils::get_timestamp_precision_scale(const_dimen - col_dimen);
136  } else {
137  datum.bigintval =
138  get_value_from_datum<int64_t>(const_datum, const_type) *
139  DateTimeUtils::get_timestamp_precision_scale(col_dimen - const_dimen);
140  }
141  apply_int_qual(datum, const_type, sql_op, qual_range);
142 }
143 
145  const Analyzer::ColumnVar* col_expr,
146  const ExpressionRange& col_range,
147  const boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
148  if (!simple_quals) {
149  return col_range;
150  }
151  ExpressionRange qual_range(col_range);
152  for (auto const& itr : simple_quals.get()) {
153  auto qual_bin_oper = dynamic_cast<Analyzer::BinOper*>(itr.get());
154  if (!qual_bin_oper) {
155  continue;
156  }
157  const Analyzer::Expr* left_operand = qual_bin_oper->get_left_operand();
158  auto qual_col = dynamic_cast<const Analyzer::ColumnVar*>(left_operand);
159  if (!qual_col) {
160  // Check for possibility that column is wrapped in a cast
161  // Presumes that only simple casts (i.e. timestamp to timestamp or int to int) have
162  // been passed through by BinOper::normalize_simple_predicate
163  auto u_expr = dynamic_cast<const Analyzer::UOper*>(left_operand);
164  if (!u_expr) {
165  continue;
166  }
167  qual_col = dynamic_cast<const Analyzer::ColumnVar*>(u_expr->get_operand());
168  if (!qual_col) {
169  continue;
170  }
171  }
172  if (qual_col->getColumnKey() != col_expr->getColumnKey()) {
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  return qual_range;
204 }
205 
210  }
211  if (other.int_min_ * other.int_max_ <= 0) {
212  // if the other interval contains 0, the rule is more complicated;
213  // punt for now, we can revisit by splitting the other interval and
214  // taking the convex hull of the resulting two intervals
216  }
217  auto div_range = binOp<int64_t>(other, [](const int64_t x, const int64_t y) {
218  return int64_t(checked_int64_t(x) / y);
219  });
220  if (g_null_div_by_zero) {
221  div_range.setHasNulls();
222  }
223  return div_range;
224 }
225 
227  if (type_ != other.type_) {
229  }
231  switch (type_) {
236  result.has_nulls_ = has_nulls_ || other.has_nulls_;
237  result.int_min_ = std::min(int_min_, other.int_min_);
238  result.int_max_ = std::max(int_max_, other.int_max_);
239  result.bucket_ = std::min(bucket_, other.bucket_);
240  break;
241  }
244  result.type_ = type_;
245  result.has_nulls_ = has_nulls_ || other.has_nulls_;
246  result.fp_min_ = std::min(fp_min_, other.fp_min_);
247  result.fp_max_ = std::max(fp_max_, other.fp_max_);
248  break;
249  }
250  default:
251  CHECK(false);
252  }
253  return result;
254 }
255 
257  if (type_ != other.type_) {
258  return false;
259  }
260  switch (type_) {
262  return true;
264  return has_nulls_ == other.has_nulls_ && int_min_ == other.int_min_ &&
265  int_max_ == other.int_max_;
266  }
269  return has_nulls_ == other.has_nulls_ && fp_min_ == other.fp_min_ &&
270  fp_max_ == other.fp_max_;
271  }
272  default:
273  CHECK(false);
274  }
275  return false;
276 }
277 
279  if (ti.is_array()) {
280  return typeSupportsRange(ti.get_elem_type());
281  } else {
282  return (ti.is_number() || ti.is_boolean() || ti.is_time() ||
283  (ti.is_string() && ti.get_compression() == kENCODING_DICT));
284  }
285 }
286 
288  const Analyzer::BinOper* expr,
289  const std::vector<InputTableInfo>& query_infos,
290  const Executor*,
291  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
292 
294 
296  const Analyzer::ColumnVar* col_expr,
297  const std::vector<InputTableInfo>& query_infos,
298  const Executor* executor,
299  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
300 
302  const Executor* executor);
303 
305 
307  const std::vector<InputTableInfo>& query_infos,
308  const Executor*);
309 
311  const Analyzer::UOper* u_expr,
312  const std::vector<InputTableInfo>& query_infos,
313  const Executor*,
314  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
315 
317  const Analyzer::ExtractExpr* extract_expr,
318  const std::vector<InputTableInfo>& query_infos,
319  const Executor*,
320  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
321 
323  const Analyzer::DatetruncExpr* datetrunc_expr,
324  const std::vector<InputTableInfo>& query_infos,
325  const Executor* executor,
326  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
327 
330  const std::vector<InputTableInfo>& query_infos,
331  const Executor* executor,
332  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals);
333 
335  const Analyzer::Expr* expr,
336  const std::vector<InputTableInfo>& query_infos,
337  const Executor* executor,
338  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
341  } else if (auto bin_oper_expr = dynamic_cast<const Analyzer::BinOper*>(expr)) {
342  return getExpressionRange(bin_oper_expr, query_infos, executor, simple_quals);
343  } else if (auto constant_expr = dynamic_cast<const Analyzer::Constant*>(expr)) {
344  return getExpressionRange(constant_expr);
345  } else if (auto column_var_expr = dynamic_cast<const Analyzer::ColumnVar*>(expr)) {
346  return getExpressionRange(column_var_expr, query_infos, executor, simple_quals);
347  } else if (auto string_oper_expr = dynamic_cast<const Analyzer::StringOper*>(expr)) {
348  return getExpressionRange(string_oper_expr, executor);
349  } else if (auto like_expr = dynamic_cast<const Analyzer::LikeExpr*>(expr)) {
350  return getExpressionRange(like_expr);
351  } else if (auto case_expr = dynamic_cast<const Analyzer::CaseExpr*>(expr)) {
352  return getExpressionRange(case_expr, query_infos, executor);
353  } else if (auto u_expr = dynamic_cast<const Analyzer::UOper*>(expr)) {
354  return getExpressionRange(u_expr, query_infos, executor, simple_quals);
355  } else if (auto extract_expr = dynamic_cast<const Analyzer::ExtractExpr*>(expr)) {
356  return getExpressionRange(extract_expr, query_infos, executor, simple_quals);
357  } else if (auto datetrunc_expr = dynamic_cast<const Analyzer::DatetruncExpr*>(expr)) {
358  return getExpressionRange(datetrunc_expr, query_infos, executor, simple_quals);
359  } else if (auto width_expr = dynamic_cast<const Analyzer::WidthBucketExpr*>(expr)) {
360  return getExpressionRange(width_expr, query_infos, executor, simple_quals);
361  }
363 }
364 
365 namespace {
366 
367 int64_t scale_up_interval_endpoint(const int64_t endpoint, const SQLTypeInfo& ti) {
368  return endpoint * static_cast<int64_t>(exp_to_scale(ti.get_scale()));
369 }
370 
371 } // namespace
372 
374  const Analyzer::BinOper* expr,
375  const std::vector<InputTableInfo>& query_infos,
376  const Executor* executor,
377  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
378  const auto& lhs =
379  getExpressionRange(expr->get_left_operand(), query_infos, executor, simple_quals);
380  const auto& rhs =
381  getExpressionRange(expr->get_right_operand(), query_infos, executor, simple_quals);
382  switch (expr->get_optype()) {
383  case kPLUS:
384  return lhs + rhs;
385  case kMINUS:
386  return lhs - rhs;
387  case kMULTIPLY:
388  return lhs * rhs;
389  case kDIVIDE: {
390  const auto& lhs_type = expr->get_left_operand()->get_type_info();
391  if (lhs_type.is_decimal() && lhs.getType() != ExpressionRangeType::Invalid) {
392  CHECK(lhs.getType() == ExpressionRangeType::Integer);
393  const auto adjusted_lhs = ExpressionRange::makeIntRange(
394  scale_up_interval_endpoint(lhs.getIntMin(), lhs_type),
395  scale_up_interval_endpoint(lhs.getIntMax(), lhs_type),
396  0,
397  lhs.hasNulls());
398  return adjusted_lhs / rhs;
399  }
400  return lhs / rhs;
401  }
402  default:
403  break;
404  }
406 }
407 
409  if (constant_expr->get_is_null()) {
411  }
412  const auto constant_type = constant_expr->get_type_info().get_type();
413  const auto datum = constant_expr->get_constval();
414  switch (constant_type) {
415  case kTINYINT: {
416  const int64_t v = datum.tinyintval;
417  return ExpressionRange::makeIntRange(v, v, 0, false);
418  }
419  case kSMALLINT: {
420  const int64_t v = datum.smallintval;
421  return ExpressionRange::makeIntRange(v, v, 0, false);
422  }
423  case kINT: {
424  const int64_t v = datum.intval;
425  return ExpressionRange::makeIntRange(v, v, 0, false);
426  }
427  case kBIGINT:
428  case kNUMERIC:
429  case kDECIMAL: {
430  const int64_t v = datum.bigintval;
431  return ExpressionRange::makeIntRange(v, v, 0, false);
432  }
433  case kTIME:
434  case kTIMESTAMP:
435  case kDATE: {
436  const int64_t v = datum.bigintval;
437  return ExpressionRange::makeIntRange(v, v, 0, false);
438  }
439  case kFLOAT: {
440  return ExpressionRange::makeFloatRange(datum.floatval, datum.floatval, false);
441  }
442  case kDOUBLE: {
443  return ExpressionRange::makeDoubleRange(datum.doubleval, datum.doubleval, false);
444  }
445  default:
446  break;
447  }
449 }
450 
451 #define FIND_STAT_FRAG(stat_name) \
452  const auto stat_name##_frag_index = std::stat_name##_element( \
453  nonempty_fragment_indices.begin(), \
454  nonempty_fragment_indices.end(), \
455  [&fragments, &has_nulls, col_id, col_ti](const size_t lhs_idx, \
456  const size_t rhs_idx) { \
457  const auto& lhs = fragments[lhs_idx]; \
458  const auto& rhs = fragments[rhs_idx]; \
459  auto lhs_meta_it = lhs.getChunkMetadataMap().find(col_id); \
460  if (lhs_meta_it == lhs.getChunkMetadataMap().end()) { \
461  return false; \
462  } \
463  auto rhs_meta_it = rhs.getChunkMetadataMap().find(col_id); \
464  CHECK(rhs_meta_it != rhs.getChunkMetadataMap().end()); \
465  if (lhs_meta_it->second->chunkStats.has_nulls || \
466  rhs_meta_it->second->chunkStats.has_nulls) { \
467  has_nulls = true; \
468  } \
469  if (col_ti.is_fp()) { \
470  return extract_##stat_name##_stat_fp_type(lhs_meta_it->second->chunkStats, \
471  col_ti) < \
472  extract_##stat_name##_stat_fp_type(rhs_meta_it->second->chunkStats, \
473  col_ti); \
474  } \
475  return extract_##stat_name##_stat_int_type(lhs_meta_it->second->chunkStats, \
476  col_ti) < \
477  extract_##stat_name##_stat_int_type(rhs_meta_it->second->chunkStats, \
478  col_ti); \
479  }); \
480  if (stat_name##_frag_index == nonempty_fragment_indices.end()) { \
481  return ExpressionRange::makeInvalidRange(); \
482  }
483 
484 namespace {
485 
486 int64_t get_conservative_datetrunc_bucket(const DatetruncField datetrunc_field) {
487  const int64_t day_seconds{24 * 3600};
488  const int64_t year_days{365};
489  switch (datetrunc_field) {
490  case dtYEAR:
491  return year_days * day_seconds;
492  case dtQUARTER:
493  return 90 * day_seconds; // 90 is least number of days in any quater
494  case dtMONTH:
495  return 28 * day_seconds;
496  case dtDAY:
497  return day_seconds;
498  case dtHOUR:
499  return 3600;
500  case dtMINUTE:
501  return 60;
502  case dtMILLENNIUM:
503  return 1000 * year_days * day_seconds;
504  case dtCENTURY:
505  return 100 * year_days * day_seconds;
506  case dtDECADE:
507  return 10 * year_days * day_seconds;
508  case dtWEEK:
509  case dtWEEK_SUNDAY:
510  case dtWEEK_SATURDAY:
511  return 7 * day_seconds;
512  case dtQUARTERDAY:
513  return 4 * 60 * 50;
514  default:
515  return 0;
516  }
517 }
518 
519 } // namespace
520 
522  const std::vector<InputTableInfo>& query_infos,
523  const Executor* executor,
524  const bool is_outer_join_proj) {
525  bool has_nulls = is_outer_join_proj;
526  int col_id = col_expr->getColumnKey().column_id;
527  const auto& col_phys_ti = col_expr->get_type_info().is_array()
528  ? col_expr->get_type_info().get_elem_type()
529  : col_expr->get_type_info();
530  const auto col_ti = get_logical_type_info(col_phys_ti);
531  switch (col_ti.get_type()) {
532  case kTEXT:
533  case kCHAR:
534  case kVARCHAR:
535  CHECK_EQ(kENCODING_DICT, col_ti.get_compression());
536  case kBOOLEAN:
537  case kTINYINT:
538  case kSMALLINT:
539  case kINT:
540  case kBIGINT:
541  case kDECIMAL:
542  case kNUMERIC:
543  case kDATE:
544  case kTIMESTAMP:
545  case kTIME:
546  case kFLOAT:
547  case kDOUBLE: {
548  std::optional<size_t> ti_idx;
549  for (size_t i = 0; i < query_infos.size(); ++i) {
550  if (col_expr->getTableKey() == query_infos[i].table_key) {
551  ti_idx = i;
552  break;
553  }
554  }
555  CHECK(ti_idx);
556  const auto& query_info = query_infos[*ti_idx].info;
557  const auto& fragments = query_info.fragments;
558  const auto cd = executor->getColumnDescriptor(col_expr);
559  if (cd && cd->isVirtualCol) {
560  CHECK(cd->columnName == "rowid");
561  CHECK_EQ(kBIGINT, col_ti.get_type());
562  const int64_t num_tuples = query_info.getNumTuples();
564  0, std::max(num_tuples - 1, int64_t(0)), 0, has_nulls);
565  }
566  if (query_info.getNumTuples() == 0) {
567  // The column doesn't contain any values, synthesize an empty range.
568  if (col_ti.is_fp()) {
569  return col_ti.get_type() == kFLOAT
570  ? ExpressionRange::makeFloatRange(0, -1, false)
571  : ExpressionRange::makeDoubleRange(0, -1, false);
572  }
573  return ExpressionRange::makeIntRange(0, -1, 0, false);
574  }
575  std::vector<size_t> nonempty_fragment_indices;
576  for (size_t i = 0; i < fragments.size(); ++i) {
577  const auto& fragment = fragments[i];
578  if (!fragment.isEmptyPhysicalFragment()) {
579  nonempty_fragment_indices.push_back(i);
580  }
581  }
582  FIND_STAT_FRAG(min);
583  FIND_STAT_FRAG(max);
584  const auto& min_frag = fragments[*min_frag_index];
585  const auto min_it = min_frag.getChunkMetadataMap().find(col_id);
586  if (min_it == min_frag.getChunkMetadataMap().end()) {
588  }
589  const auto& max_frag = fragments[*max_frag_index];
590  const auto max_it = max_frag.getChunkMetadataMap().find(col_id);
591  CHECK(max_it != max_frag.getChunkMetadataMap().end());
592  for (const auto& fragment : fragments) {
593  const auto it = fragment.getChunkMetadataMap().find(col_id);
594  if (it != fragment.getChunkMetadataMap().end()) {
595  if (it->second->chunkStats.has_nulls) {
596  has_nulls = true;
597  break;
598  }
599  }
600  }
601 
602  // Detect FSI placeholder metadata. If we let this through it will be treated as an
603  // empty range, when it really implies an unknown range.
604  if (min_it->second->isPlaceholder() || max_it->second->isPlaceholder()) {
606  }
607 
608  if (col_ti.is_fp()) {
609  const auto min_val = extract_min_stat_fp_type(min_it->second->chunkStats, col_ti);
610  const auto max_val = extract_max_stat_fp_type(max_it->second->chunkStats, col_ti);
611  return col_ti.get_type() == kFLOAT
612  ? ExpressionRange::makeFloatRange(min_val, max_val, has_nulls)
613  : ExpressionRange::makeDoubleRange(min_val, max_val, has_nulls);
614  }
615  const auto min_val = extract_min_stat_int_type(min_it->second->chunkStats, col_ti);
616  const auto max_val = extract_max_stat_int_type(max_it->second->chunkStats, col_ti);
617  if (max_val < min_val) {
618  // The column doesn't contain any non-null values, synthesize an empty range.
619  CHECK_GT(min_val, 0);
620  return ExpressionRange::makeIntRange(0, -1, 0, has_nulls);
621  }
622  const int64_t bucket =
623  col_ti.get_type() == kDATE ? get_conservative_datetrunc_bucket(dtDAY) : 0;
624  return ExpressionRange::makeIntRange(min_val, max_val, bucket, has_nulls);
625  }
626  default:
627  break;
628  }
630 }
631 
632 #undef FIND_STAT_FRAG
633 
635  const Analyzer::ColumnVar* col_expr,
636  const std::vector<InputTableInfo>& query_infos,
637  const Executor* executor,
638  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
639  const int rte_idx = col_expr->get_rte_idx();
640  CHECK_GE(rte_idx, 0);
641  CHECK_LT(static_cast<size_t>(rte_idx), query_infos.size());
642  bool is_outer_join_proj = rte_idx > 0 && executor->containsLeftDeepOuterJoin();
643  const auto& column_key = col_expr->getColumnKey();
644  if (column_key.table_id > 0) {
645  auto col_range = executor->getColRange(
646  PhysicalInput{column_key.column_id, column_key.table_id, column_key.db_id});
647  if (is_outer_join_proj) {
648  col_range.setHasNulls();
649  }
650  return apply_simple_quals(col_expr, col_range, simple_quals);
651  }
652  return getLeafColumnRange(col_expr, query_infos, executor, is_outer_join_proj);
653 }
654 
656  const Executor* executor) {
657  auto chained_string_op_exprs = string_oper_expr->getChainedStringOpExprs();
658  if (chained_string_op_exprs.empty()) {
659  throw std::runtime_error(
660  "StringOper getExpressionRange() Expected folded string operator but found "
661  "operator unfolded.");
662  }
663  // Consider encapsulating below in an Analyzer::StringOper method to dedup
664  std::vector<StringOps_Namespace::StringOpInfo> string_op_infos;
665  for (const auto& chained_string_op_expr : chained_string_op_exprs) {
666  auto chained_string_op =
667  dynamic_cast<const Analyzer::StringOper*>(chained_string_op_expr.get());
668  CHECK(chained_string_op);
669  StringOps_Namespace::StringOpInfo string_op_info(chained_string_op->get_kind(),
670  chained_string_op->get_type_info(),
671  chained_string_op->getLiteralArgs());
672  string_op_infos.emplace_back(string_op_info);
673  }
674 
675  const auto expr_ti = string_oper_expr->get_type_info();
676  if (expr_ti.is_string() && !string_oper_expr->requiresPerRowTranslation()) {
677  // We can only statically know the range if dictionary translation occured (which
678  // means the output type is a dictionary-encoded text col and is not transient, as
679  // transient dictionaries are used as targets for on-the-fly translation
680  CHECK(expr_ti.is_dict_encoded_string());
681 
682  const auto& dict_key = expr_ti.getStringDictKey();
683  CHECK_NE(dict_key.dict_id, TRANSIENT_DICT_ID);
684  const auto translation_map = executor->getStringProxyTranslationMap(
685  dict_key,
686  dict_key,
688  string_op_infos,
689  executor->getRowSetMemoryOwner(),
690  true);
691 
692  // Todo(todd): Track null presence in StringDictionaryProxy::IdMap
693  return ExpressionRange::makeIntRange(translation_map->rangeStart(),
694  translation_map->rangeEnd() - 1,
695  0 /* bucket */,
696  true /* assume has nulls */);
697 
698  } else {
699  // Todo(todd): Get min/max range stats
700  // Below works fine, we just can't take advantage of low-cardinality
701  // group by optimizations
703  }
704 }
705 
707  const auto& ti = like_expr->get_type_info();
708  CHECK(ti.is_boolean());
709  const auto& arg_ti = like_expr->get_arg()->get_type_info();
711  arg_ti.get_notnull() ? 0 : inline_int_null_val(ti), 1, 0, false);
712 }
713 
715  const std::vector<InputTableInfo>& query_infos,
716  const Executor* executor) {
717  const auto& expr_pair_list = case_expr->get_expr_pair_list();
718  auto expr_range = ExpressionRange::makeInvalidRange();
719  bool has_nulls = false;
720  for (const auto& expr_pair : expr_pair_list) {
721  CHECK_EQ(expr_pair.first->get_type_info().get_type(), kBOOLEAN);
722  const auto crt_range =
723  getExpressionRange(expr_pair.second.get(), query_infos, executor);
724  if (crt_range.getType() == ExpressionRangeType::Null) {
725  has_nulls = true;
726  continue;
727  }
728  if (crt_range.getType() == ExpressionRangeType::Invalid) {
730  }
731  expr_range = (expr_range.getType() != ExpressionRangeType::Invalid)
732  ? expr_range || crt_range
733  : crt_range;
734  }
735  if (has_nulls && !(expr_range.getType() == ExpressionRangeType::Invalid)) {
736  expr_range.setHasNulls();
737  }
738  const auto else_expr = case_expr->get_else_expr();
739  CHECK(else_expr);
740  const auto else_null_expr = dynamic_cast<const Analyzer::Constant*>(else_expr);
741  if (else_null_expr && else_null_expr->get_is_null()) {
742  expr_range.setHasNulls();
743  return expr_range;
744  }
745  return expr_range || getExpressionRange(else_expr, query_infos, executor);
746 }
747 
748 namespace {
749 
751  const int64_t scale,
752  const SQLTypeInfo& target_ti) {
753  CHECK(target_ti.is_fp());
754  if (target_ti.get_type() == kFLOAT) {
756  static_cast<float>(arg_range.getIntMin()) / scale,
757  static_cast<float>(arg_range.getIntMax()) / scale,
758  arg_range.hasNulls());
759  }
761  static_cast<double>(arg_range.getIntMin()) / scale,
762  static_cast<double>(arg_range.getIntMax()) / scale,
763  arg_range.hasNulls());
764 }
765 
767  const SQLTypeInfo& oper_ti,
768  const SQLTypeInfo& target_ti) {
769  if (oper_ti.is_timestamp() && target_ti.is_date()) {
770  const auto field = dtDAY;
771  const int64_t scale =
774  : 1;
775  const int64_t min_ts = oper_ti.is_high_precision_timestamp()
776  ? DateTruncate(field, arg_range.getIntMin() / scale)
777  : DateTruncate(field, arg_range.getIntMin());
778  const int64_t max_ts = oper_ti.is_high_precision_timestamp()
779  ? DateTruncate(field, arg_range.getIntMax() / scale)
780  : DateTruncate(field, arg_range.getIntMax());
781  const int64_t bucket = get_conservative_datetrunc_bucket(field);
782 
783  return ExpressionRange::makeIntRange(min_ts, max_ts, bucket, arg_range.hasNulls());
784  }
785 
786  if (oper_ti.is_timestamp() && target_ti.is_any<kTIME>()) {
787  // The min and max TS wouldn't make sense here, so return a range covering the whole
788  // day
789  return ExpressionRange::makeIntRange(0, kSecsPerDay, 0, arg_range.hasNulls());
790  }
791 
792  const int32_t ti_dimen = target_ti.get_dimension();
793  const int32_t oper_dimen = oper_ti.get_dimension();
794  CHECK(oper_dimen != ti_dimen);
795  const int64_t min_ts =
796  ti_dimen > oper_dimen
798  arg_range.getIntMin(),
799  abs(oper_dimen - ti_dimen))
802  arg_range.getIntMin(),
803  abs(oper_dimen - ti_dimen));
804  const int64_t max_ts =
805  ti_dimen > oper_dimen
807  arg_range.getIntMax(),
808  abs(oper_dimen - ti_dimen))
811  arg_range.getIntMax(),
812  abs(oper_dimen - ti_dimen));
813 
814  return ExpressionRange::makeIntRange(min_ts, max_ts, 0, arg_range.hasNulls());
815 }
816 
817 } // namespace
818 
820  const Analyzer::UOper* u_expr,
821  const std::vector<InputTableInfo>& query_infos,
822  const Executor* executor,
823  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
824  if (u_expr->get_optype() == kUNNEST) {
825  return getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
826  }
827  if (u_expr->get_optype() != kCAST) {
829  }
830  const auto& ti = u_expr->get_type_info();
831  if (ti.is_string() && ti.get_compression() == kENCODING_DICT) {
832  const auto sdp = executor->getStringDictionaryProxy(
833  ti.getStringDictKey(), executor->getRowSetMemoryOwner(), true);
834  CHECK(sdp);
835  const auto colvar_operand =
836  dynamic_cast<const Analyzer::ColumnVar*>(u_expr->get_operand());
837  if (colvar_operand) {
838  const auto& colvar_ti = colvar_operand->get_type_info();
839  if (!(colvar_ti.is_none_encoded_string() &&
840  ti.getStringDictKey().isTransientDict())) {
841  VLOG(1)
842  << "Unable to determine expression range for dictionary encoded expression "
843  << u_expr->get_operand()->toString() << ", proceeding with invalid range.";
845  }
846  CHECK_EQ(ti.getStringDictKey().dict_id, TRANSIENT_DICT_ID);
847  CHECK_EQ(sdp->storageEntryCount(), 0UL);
848  const int64_t transient_entries = static_cast<int64_t>(sdp->transientEntryCount());
849  int64_t const tuples_upper_bound = static_cast<int64_t>(
850  std::accumulate(query_infos.cbegin(),
851  query_infos.cend(),
852  size_t(0),
853  [](auto max, auto const& query_info) {
854  return std::max(max, query_info.info.getNumTuples());
855  }));
856  const int64_t conservative_range_min = -1L - transient_entries - tuples_upper_bound;
857  return ExpressionRange::makeIntRange(conservative_range_min, -2L, 0, true);
858  }
859  const auto const_operand =
860  dynamic_cast<const Analyzer::Constant*>(u_expr->get_operand());
861  if (!const_operand) {
862  // casted subquery result. return invalid for now, but we could attempt to pull the
863  // range from the subquery result in the future
864  CHECK(u_expr->get_operand());
865  VLOG(1) << "Unable to determine expression range for dictionary encoded expression "
866  << u_expr->get_operand()->toString() << ", proceeding with invalid range.";
868  }
869 
870  if (const_operand->get_is_null()) {
872  }
873  CHECK(const_operand->get_constval().stringval);
874  const int64_t v = sdp->getIdOfString(*const_operand->get_constval().stringval);
875  return ExpressionRange::makeIntRange(v, v, 0, false);
876  }
877  const auto arg_range =
878  getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
879  const auto& arg_ti = u_expr->get_operand()->get_type_info();
880  // Timestamp to Date OR Date/Timestamp casts with different precision
881  if ((ti.is_timestamp() && (arg_ti.get_dimension() != ti.get_dimension())) ||
882  ((arg_ti.is_timestamp() && ti.is_any<kDATE, kTIME>()))) {
883  return getDateTimePrecisionCastRange(arg_range, arg_ti, ti);
884  }
885  switch (arg_range.getType()) {
888  if (ti.is_fp()) {
889  return ti.get_type() == kDOUBLE
891  arg_range.getFpMin(), arg_range.getFpMax(), arg_range.hasNulls())
892  : ExpressionRange::makeFloatRange(arg_range.getFpMin(),
893  arg_range.getFpMax(),
894  arg_range.hasNulls());
895  }
896  if (ti.is_integer()) {
897  return ExpressionRange::makeIntRange(std::floor(arg_range.getFpMin()),
898  std::ceil(arg_range.getFpMax()),
899  0,
900  arg_range.hasNulls());
901  }
902  break;
903  }
905  if (ti.is_decimal()) {
906  CHECK_EQ(int64_t(0), arg_range.getBucket());
907  const int64_t scale = exp_to_scale(ti.get_scale() - arg_ti.get_scale());
908  return ExpressionRange::makeIntRange(arg_range.getIntMin() * scale,
909  arg_range.getIntMax() * scale,
910  0,
911  arg_range.hasNulls());
912  }
913  if (arg_ti.is_decimal()) {
914  CHECK_EQ(int64_t(0), arg_range.getBucket());
915  const int64_t scale = exp_to_scale(arg_ti.get_scale());
916  const int64_t scale_half = scale / 2;
917  if (ti.is_fp()) {
918  return fpRangeFromDecimal(arg_range, scale, ti);
919  }
920  return ExpressionRange::makeIntRange((arg_range.getIntMin() - scale_half) / scale,
921  (arg_range.getIntMax() + scale_half) / scale,
922  0,
923  arg_range.hasNulls());
924  }
925  if (ti.is_integer() || ti.is_time()) {
926  return arg_range;
927  }
928  if (ti.get_type() == kFLOAT) {
930  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
931  }
932  if (ti.get_type() == kDOUBLE) {
934  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
935  }
936  break;
937  }
939  break;
940  default:
941  CHECK(false);
942  }
944 }
945 
947  const Analyzer::ExtractExpr* extract_expr,
948  const std::vector<InputTableInfo>& query_infos,
949  const Executor* executor,
950  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
951  const int32_t extract_field{extract_expr->get_field()};
952  const auto arg_range = getExpressionRange(
953  extract_expr->get_from_expr(), query_infos, executor, simple_quals);
954  const bool has_nulls =
955  arg_range.getType() == ExpressionRangeType::Invalid || arg_range.hasNulls();
956  const auto& extract_expr_ti = extract_expr->get_from_expr()->get_type_info();
957  switch (extract_field) {
958  case kYEAR: {
959  if (arg_range.getType() == ExpressionRangeType::Invalid) {
961  }
962  CHECK(arg_range.getType() == ExpressionRangeType::Integer);
963  const int64_t year_range_min =
964  extract_expr_ti.is_high_precision_timestamp()
965  ? ExtractFromTime(
966  kYEAR,
967  arg_range.getIntMin() /
968  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
969  : ExtractFromTime(kYEAR, arg_range.getIntMin());
970  const int64_t year_range_max =
971  extract_expr_ti.is_high_precision_timestamp()
972  ? ExtractFromTime(
973  kYEAR,
974  arg_range.getIntMax() /
975  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
976  : ExtractFromTime(kYEAR, arg_range.getIntMax());
978  year_range_min, year_range_max, 0, arg_range.hasNulls());
979  }
980  case kEPOCH:
981  case kDATEEPOCH:
982  return arg_range;
983  case kQUARTERDAY:
984  case kQUARTER:
985  return ExpressionRange::makeIntRange(1, 4, 0, has_nulls);
986  case kMONTH:
987  return ExpressionRange::makeIntRange(1, 12, 0, has_nulls);
988  case kDAY:
989  return ExpressionRange::makeIntRange(1, 31, 0, has_nulls);
990  case kHOUR:
991  return ExpressionRange::makeIntRange(0, 23, 0, has_nulls);
992  case kMINUTE:
993  return ExpressionRange::makeIntRange(0, 59, 0, has_nulls);
994  case kSECOND:
995  return ExpressionRange::makeIntRange(0, 60, 0, has_nulls);
996  case kMILLISECOND:
997  return ExpressionRange::makeIntRange(0, 999, 0, has_nulls);
998  case kMICROSECOND:
999  return ExpressionRange::makeIntRange(0, 999999, 0, has_nulls);
1000  case kNANOSECOND:
1001  return ExpressionRange::makeIntRange(0, 999999999, 0, has_nulls);
1002  case kDOW:
1003  return ExpressionRange::makeIntRange(0, 6, 0, has_nulls);
1004  case kISODOW:
1005  return ExpressionRange::makeIntRange(1, 7, 0, has_nulls);
1006  case kDOY:
1007  return ExpressionRange::makeIntRange(1, 366, 0, has_nulls);
1008  case kWEEK:
1009  case kWEEK_SUNDAY:
1010  case kWEEK_SATURDAY:
1011  return ExpressionRange::makeIntRange(1, 53, 0, has_nulls);
1012  default:
1013  CHECK(false);
1014  }
1016 }
1017 
1019  const Analyzer::DatetruncExpr* datetrunc_expr,
1020  const std::vector<InputTableInfo>& query_infos,
1021  const Executor* executor,
1022  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
1023  const auto arg_range = getExpressionRange(
1024  datetrunc_expr->get_from_expr(), query_infos, executor, simple_quals);
1025  if (arg_range.getType() == ExpressionRangeType::Invalid) {
1027  }
1028  const auto& datetrunc_expr_ti = datetrunc_expr->get_from_expr()->get_type_info();
1029  const int64_t min_ts = DateTimeTranslator::getDateTruncConstantValue(
1030  arg_range.getIntMin(), datetrunc_expr->get_field(), datetrunc_expr_ti);
1031  const int64_t max_ts = DateTimeTranslator::getDateTruncConstantValue(
1032  arg_range.getIntMax(), datetrunc_expr->get_field(), datetrunc_expr_ti);
1033  const int64_t bucket =
1034  datetrunc_expr_ti.is_high_precision_timestamp()
1035  ? get_conservative_datetrunc_bucket(datetrunc_expr->get_field()) *
1037  datetrunc_expr_ti.get_dimension())
1038  : get_conservative_datetrunc_bucket(datetrunc_expr->get_field());
1039 
1040  return ExpressionRange::makeIntRange(min_ts, max_ts, bucket, arg_range.hasNulls());
1041 }
1042 
1045  const std::vector<InputTableInfo>& query_infos,
1046  const Executor* executor,
1047  boost::optional<std::list<std::shared_ptr<Analyzer::Expr>>> simple_quals) {
1048  auto target_value_expr = width_bucket_expr->get_target_value();
1049  auto target_value_range = getExpressionRange(target_value_expr, query_infos, executor);
1050  auto target_ti = target_value_expr->get_type_info();
1051  if (width_bucket_expr->is_constant_expr() &&
1052  target_value_range.getType() != ExpressionRangeType::Invalid) {
1053  auto const_target_value = dynamic_cast<const Analyzer::Constant*>(target_value_expr);
1054  if (const_target_value) {
1055  if (const_target_value->get_is_null()) {
1056  // null constant, return default width_bucket range
1058  0, width_bucket_expr->get_partition_count_val(), 0, true);
1059  } else {
1060  CHECK(target_value_range.getFpMax() == target_value_range.getFpMin());
1061  auto target_value_bucket =
1062  width_bucket_expr->compute_bucket(target_value_range.getFpMax());
1064  target_value_bucket, target_value_bucket, 0, target_value_range.hasNulls());
1065  }
1066  }
1067  // compute possible bucket range based on lower and upper bound constants
1068  // to elucidate a target bucket range
1069  const auto target_value_range_with_qual =
1070  getExpressionRange(target_value_expr, query_infos, executor, simple_quals);
1071  auto compute_bucket_range = [&width_bucket_expr](const ExpressionRange& target_range,
1072  SQLTypeInfo ti) {
1073  // we casted bucket bound exprs to double
1074  auto lower_bound_bucket =
1075  width_bucket_expr->compute_bucket(target_range.getFpMin());
1076  auto upper_bound_bucket =
1077  width_bucket_expr->compute_bucket(target_range.getFpMax());
1079  lower_bound_bucket, upper_bound_bucket, 0, target_range.hasNulls());
1080  };
1081  auto res_range = compute_bucket_range(target_value_range_with_qual, target_ti);
1082  // check target_value expression's col range to be not nullable iff it has its filter
1083  // expression i.e., in simple_quals
1084  // todo (yoonmin) : need to search simple_quals to cover more cases?
1085  if (target_value_range.getFpMin() < target_value_range_with_qual.getFpMin() ||
1086  target_value_range.getFpMax() > target_value_range_with_qual.getFpMax()) {
1087  res_range.setNulls(false);
1088  }
1089  return res_range;
1090  } else {
1091  // we cannot determine a possibility of skipping oob check safely
1092  const bool has_nulls = target_value_range.getType() == ExpressionRangeType::Invalid ||
1093  target_value_range.hasNulls();
1094  auto partition_expr_range = getExpressionRange(
1095  width_bucket_expr->get_partition_count(), query_infos, executor, simple_quals);
1096  auto res = ExpressionRange::makeIntRange(0, INT32_MAX, 0, has_nulls);
1097  switch (partition_expr_range.getType()) {
1099  res.setIntMax(partition_expr_range.getIntMax() + 1);
1100  break;
1101  }
1104  res.setIntMax(static_cast<int64_t>(partition_expr_range.getFpMax()) + 1);
1105  break;
1106  }
1107  default:
1108  break;
1109  }
1110  return res;
1111  }
1112 }
static constexpr int64_t kSecsPerDay
int64_t getIntMin() const
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define FIND_STAT_FRAG(stat_name)
const Expr * get_from_expr() const
Definition: Analyzer.h:1432
const Expr * get_partition_count() const
Definition: Analyzer.h:1201
bool is_constant_expr() const
Definition: Analyzer.h:1246
const Expr * get_else_expr() const
Definition: Analyzer.h:1387
static ExpressionRange makeNullRange()
Definition: sqltypes.h:76
SQLTypes
Definition: sqltypes.h:65
bool is_timestamp() const
Definition: sqltypes.h:1044
bool operator==(const ExpressionRange &other) const
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 64, 64, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void >> checked_int64_t
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_max_stat_fp_type(const ChunkStats &stats, const SQLTypeInfo &ti)
ExtractField get_field() const
Definition: Analyzer.h:1431
bool is_fp() const
Definition: sqltypes.h:571
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
const Expr * get_right_operand() const
Definition: Analyzer.h:456
SQLOps
Definition: sqldefs.h:28
Definition: sqldefs.h:34
DEVICE int64_t DateTruncate(DatetruncField field, const int64_t timeval)
Definition: sqldefs.h:35
#define DEF_OPERATOR(fname, op)
bool get_is_null() const
Definition: Analyzer.h:347
#define CHECK_GE(x, y)
Definition: Logger.h:306
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1470
Definition: sqldefs.h:48
Definition: sqldefs.h:29
DatetruncField get_field() const
Definition: Analyzer.h:1566
Definition: sqldefs.h:40
bool requiresPerRowTranslation() const
Definition: Analyzer.h:1704
int64_t scale_up_interval_endpoint(const int64_t endpoint, const SQLTypeInfo &ti)
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
void setIntMin(const int64_t int_min)
#define TRANSIENT_DICT_ID
Definition: DbObjectKeys.h:24
bool is_number() const
Definition: sqltypes.h:574
#define CHECK_GT(x, y)
Definition: Logger.h:305
constexpr int64_t get_datetime_scaled_epoch(const ScalingType direction, const int64_t epoch, const int32_t dimen)
const Expr * get_arg() const
Definition: Analyzer.h:1061
int64_t extract_max_stat_int_type(const ChunkStats &stats, const SQLTypeInfo &ti)
bool is_time() const
Definition: sqltypes.h:577
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)
bool g_null_div_by_zero
Definition: Execute.cpp:91
SQLOps get_optype() const
Definition: Analyzer.h:452
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
ExpressionRangeType type_
ExpressionRange operator||(const ExpressionRange &other) const
DatetruncField
Definition: DateTruncate.h:27
int64_t get_conservative_datetrunc_bucket(const DatetruncField datetrunc_field)
double extract_min_stat_fp_type(const ChunkStats &stats, const SQLTypeInfo &ti)
#define CHECK_NE(x, y)
Definition: Logger.h:302
void apply_fp_qual(const Datum const_datum, const SQLTypes const_type, const SQLOps sql_op, ExpressionRange &qual_range)
int64_t bigintval
Definition: Datum.h:74
int64_t extract_min_stat_int_type(const ChunkStats &stats, const SQLTypeInfo &ti)
int32_t compute_bucket(double target_const_val) const
Definition: Analyzer.cpp:3968
DEVICE auto accumulate(ARGS &&...args)
Definition: gpu_enabled.h:42
ExpressionRange getLeafColumnRange(const Analyzer::ColumnVar *col_expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, const bool is_outer_join_proj)
bool is_boolean() const
Definition: sqltypes.h:580
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)
bool hasNulls() const
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
Definition: sqldefs.h:33
static ExpressionRange makeDoubleRange(const double fp_min, const double fp_max, const bool has_nulls)
#define CHECK_LT(x, y)
Definition: Logger.h:303
Definition: sqltypes.h:79
Definition: sqltypes.h:80
double getFpMax() const
Definition: sqldefs.h:39
virtual std::string toString() const =0
Expression class for string functions The &quot;arg&quot; constructor parameter must be an expression that reso...
Definition: Analyzer.h:1601
const Expr * get_from_expr() const
Definition: Analyzer.h:1567
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
double getFpMin() const
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
const Expr * get_operand() const
Definition: Analyzer.h:384
Datum get_constval() const
Definition: Analyzer.h:348
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
ExpressionRange operator/(const ExpressionRange &other) const
int32_t get_partition_count_val() const
Definition: Analyzer.cpp:3923
DEVICE int64_t ExtractFromTime(ExtractField field, const int64_t timeval)
Definition: sqltypes.h:68
void setIntMax(const int64_t int_max)
const Expr * get_target_value() const
Definition: Analyzer.h:1198
ExpressionRangeType getType() const
int64_t getIntMax() const
#define CHECK(condition)
Definition: Logger.h:291
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
bool is_high_precision_timestamp() const
Definition: sqltypes.h:1034
Find out all the physical inputs (columns) a query is using.
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
Definition: sqldefs.h:32
bool is_any() const
Definition: sqltypes.h:556
const Expr * get_left_operand() const
Definition: Analyzer.h:455
static bool typeSupportsRange(const SQLTypeInfo &ti)
Definition: sqltypes.h:72
static ExpressionRange makeInvalidRange()
bool is_string() const
Definition: sqltypes.h:559
static int64_t getDateTruncConstantValue(const int64_t &timeval, const DatetruncField &field, const SQLTypeInfo &ti)
int32_t get_rte_idx() const
Definition: Analyzer.h:202
Definition: Datum.h:69
SQLTypeInfo get_elem_type() const
Definition: sqltypes.h:975
std::vector< std::shared_ptr< Analyzer::Expr > > getChainedStringOpExprs() const
Definition: Analyzer.h:1700
ExpressionRange getDateTimePrecisionCastRange(const ExpressionRange &arg_range, const SQLTypeInfo &oper_ti, const SQLTypeInfo &target_ti)
SQLOps get_optype() const
Definition: Analyzer.h:383
bool is_date() const
Definition: sqltypes.h:1026
bool is_array() const
Definition: sqltypes.h:583
const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr > > > & get_expr_pair_list() const
Definition: Analyzer.h:1384
#define VLOG(n)
Definition: Logger.h:388
shared::TableKey getTableKey() const
Definition: Analyzer.h:199
ExpressionRange fpRangeFromDecimal(const ExpressionRange &arg_range, const int64_t scale, const SQLTypeInfo &target_ti)
RUNTIME_EXPORT ALWAYS_INLINE DEVICE int32_t width_bucket_expr(const double target_value, const bool reversed, const double lower_bound, const double upper_bound, const int32_t partition_count)