OmniSciDB  2b310ab3b2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ExpressionRange.cpp File Reference
#include "ExpressionRange.h"
#include <algorithm>
#include <cfenv>
#include <cmath>
#include "DateTimeTranslator.h"
#include "DateTimeUtils.h"
#include "DateTruncate.h"
#include "Descriptors/InputDescriptors.h"
#include "Execute.h"
#include "ExtractFromTime.h"
#include "GroupByAndAggregate.h"
#include "QueryPhysicalInputsCollector.h"
+ Include dependency graph for ExpressionRange.cpp:

Go to the source code of this file.

Namespaces

 anonymous_namespace{ExpressionRange.cpp}
 

Macros

#define DEF_OPERATOR(fname, op)
 
#define FIND_STAT_FRAG(stat_name)
 

Functions

void apply_fp_qual (const Datum const_datum, const SQLTypes const_type, 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)
 
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)
 
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)
 
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)
 
ExpressionRange getExpressionRange (const Analyzer::Constant *expr)
 
ExpressionRange getExpressionRange (const Analyzer::ColumnVar *col_expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
 
ExpressionRange getExpressionRange (const Analyzer::LikeExpr *like_expr)
 
ExpressionRange getExpressionRange (const Analyzer::CaseExpr *case_expr, const std::vector< InputTableInfo > &query_infos, const Executor *)
 
ExpressionRange getExpressionRange (const Analyzer::UOper *u_expr, const std::vector< InputTableInfo > &query_infos, const Executor *, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
 
ExpressionRange getExpressionRange (const Analyzer::ExtractExpr *extract_expr, const std::vector< InputTableInfo > &query_infos, const Executor *, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
 
ExpressionRange getExpressionRange (const Analyzer::DatetruncExpr *datetrunc_expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
 
ExpressionRange getExpressionRange (const Analyzer::Expr *expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
 
int64_t anonymous_namespace{ExpressionRange.cpp}::scale_up_interval_endpoint (const int64_t endpoint, const SQLTypeInfo &ti)
 
double anonymous_namespace{ExpressionRange.cpp}::extract_min_stat_double (const ChunkStats &stats, const SQLTypeInfo &col_ti)
 
double anonymous_namespace{ExpressionRange.cpp}::extract_max_stat_double (const ChunkStats &stats, const SQLTypeInfo &col_ti)
 
int64_t anonymous_namespace{ExpressionRange.cpp}::get_conservative_datetrunc_bucket (const DatetruncField datetrunc_field)
 
ExpressionRange getLeafColumnRange (const Analyzer::ColumnVar *col_expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, const bool is_outer_join_proj)
 
ExpressionRange anonymous_namespace{ExpressionRange.cpp}::fpRangeFromDecimal (const ExpressionRange &arg_range, const int64_t scale, const SQLTypeInfo &target_ti)
 
ExpressionRange anonymous_namespace{ExpressionRange.cpp}::getDateTimePrecisionCastRange (const ExpressionRange &arg_range, const SQLTypeInfo &oper_ti, const SQLTypeInfo &target_ti)
 

Macro Definition Documentation

#define DEF_OPERATOR (   fname,
  op 
)

Definition at line 30 of file ExpressionRange.cpp.

#define FIND_STAT_FRAG (   stat_name)
Value:
const auto stat_name##_frag_index = std::stat_name##_element( \
nonempty_fragment_indices.begin(), \
nonempty_fragment_indices.end(), \
[&fragments, &has_nulls, col_id, col_ti](const size_t lhs_idx, \
const size_t rhs_idx) { \
const auto& lhs = fragments[lhs_idx]; \
const auto& rhs = fragments[rhs_idx]; \
auto lhs_meta_it = lhs.getChunkMetadataMap().find(col_id); \
if (lhs_meta_it == lhs.getChunkMetadataMap().end()) { \
return false; \
} \
auto rhs_meta_it = rhs.getChunkMetadataMap().find(col_id); \
CHECK(rhs_meta_it != rhs.getChunkMetadataMap().end()); \
if (lhs_meta_it->second->chunkStats.has_nulls || \
rhs_meta_it->second->chunkStats.has_nulls) { \
has_nulls = true; \
} \
if (col_ti.is_fp()) { \
return extract_##stat_name##_stat_double(lhs_meta_it->second->chunkStats, \
col_ti) < \
extract_##stat_name##_stat_double(rhs_meta_it->second->chunkStats, \
col_ti); \
} \
return extract_##stat_name##_stat(lhs_meta_it->second->chunkStats, col_ti) < \
extract_##stat_name##_stat(rhs_meta_it->second->chunkStats, col_ti); \
}); \
if (stat_name##_frag_index == nonempty_fragment_indices.end()) { \
}
CHECK(cgen_state)
static ExpressionRange makeInvalidRange()

Definition at line 455 of file ExpressionRange.cpp.

Referenced by getLeafColumnRange().

Function Documentation

void apply_fp_qual ( const Datum  const_datum,
const SQLTypes  const_type,
const SQLOps  sql_op,
ExpressionRange qual_range 
)

Definition at line 73 of file ExpressionRange.cpp.

References kEQ, kGE, kGT, kLE, and kLT.

Referenced by apply_simple_quals().

76  {
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 }
Definition: sqldefs.h:35
Definition: sqldefs.h:36
Definition: sqldefs.h:30
Definition: sqldefs.h:34
double getFpMax() const
double getFpMin() const
void setFpMax(const double fp_max)
Definition: sqldefs.h:33
void setFpMin(const double fp_min)

+ Here is the caller graph for this function:

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 
)

Definition at line 123 of file ExpressionRange.cpp.

References apply_int_qual(), Datum::bigintval, CHECK(), and DateTimeUtils::get_timestamp_precision_scale().

Referenced by apply_simple_quals().

128  {
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 }
void apply_int_qual(const Datum const_datum, const SQLTypes const_type, const SQLOps sql_op, ExpressionRange &qual_range)
CHECK(cgen_state)
int64_t bigintval
Definition: sqltypes.h:138
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void apply_int_qual ( const Datum  const_datum,
const SQLTypes  const_type,
const SQLOps  sql_op,
ExpressionRange qual_range 
)

Definition at line 96 of file ExpressionRange.cpp.

References ExpressionRange::getIntMax(), ExpressionRange::getIntMin(), kEQ, kGE, kGT, kLE, kLT, ExpressionRange::setIntMax(), and ExpressionRange::setIntMin().

Referenced by apply_hpt_qual(), and apply_simple_quals().

99  {
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 }
int64_t getIntMin() const
Definition: sqldefs.h:35
Definition: sqldefs.h:36
Definition: sqldefs.h:30
void setIntMin(const int64_t int_min)
Definition: sqldefs.h:34
void setIntMax(const int64_t int_max)
int64_t getIntMax() const
Definition: sqldefs.h:33

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 
)

Definition at line 143 of file ExpressionRange.cpp.

References apply_fp_qual(), apply_hpt_qual(), apply_int_qual(), Double, Float, Analyzer::ColumnVar::get_column_id(), Analyzer::ColumnVar::get_table_id(), and ExpressionRange::getType().

Referenced by getExpressionRange().

146  {
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  return qual_range;
204 }
int get_table_id() const
Definition: Analyzer.h:194
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)
void apply_fp_qual(const Datum const_datum, const SQLTypes const_type, const SQLOps sql_op, ExpressionRange &qual_range)
int get_column_id() const
Definition: Analyzer.h:195

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::BinOper expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 377 of file ExpressionRange.cpp.

References CHECK(), Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), Integer, Invalid, kDIVIDE, kMINUS, kMULTIPLY, kPLUS, ExpressionRange::makeIntRange(), ExpressionRange::makeInvalidRange(), and anonymous_namespace{ExpressionRange.cpp}::scale_up_interval_endpoint().

Referenced by CodeGenerator::checkExpressionRanges(), anonymous_namespace{RelAlgExecutor.cpp}::decide_approx_count_distinct_implementation(), getExpressionRange(), GroupByAndAggregate::getExprRangeInfo(), JoinHashTable::getInstance(), GroupByAndAggregate::getKeylessInfo(), anonymous_namespace{QueryMemoryDescriptor.cpp}::pick_baseline_key_width(), and QueryRewriter::rewriteConstrainedByInImpl().

381  {
382  const auto& lhs =
383  getExpressionRange(expr->get_left_operand(), query_infos, executor, simple_quals);
384  const auto& rhs =
385  getExpressionRange(expr->get_right_operand(), query_infos, executor, simple_quals);
386  switch (expr->get_optype()) {
387  case kPLUS:
388  return lhs + rhs;
389  case kMINUS:
390  return lhs - rhs;
391  case kMULTIPLY:
392  return lhs * rhs;
393  case kDIVIDE: {
394  const auto& lhs_type = expr->get_left_operand()->get_type_info();
395  if (lhs_type.is_decimal() && lhs.getType() != ExpressionRangeType::Invalid) {
396  CHECK(lhs.getType() == ExpressionRangeType::Integer);
397  const auto adjusted_lhs = ExpressionRange::makeIntRange(
398  scale_up_interval_endpoint(lhs.getIntMin(), lhs_type),
399  scale_up_interval_endpoint(lhs.getIntMax(), lhs_type),
400  0,
401  lhs.hasNulls());
402  return adjusted_lhs / rhs;
403  }
404  return lhs / rhs;
405  }
406  default:
407  break;
408  }
410 }
const Expr * get_right_operand() const
Definition: Analyzer.h:443
Definition: sqldefs.h:41
int64_t scale_up_interval_endpoint(const int64_t endpoint, const SQLTypeInfo &ti)
SQLOps get_optype() const
Definition: Analyzer.h:439
CHECK(cgen_state)
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 SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
Definition: sqldefs.h:40
const Expr * get_left_operand() const
Definition: Analyzer.h:442
static ExpressionRange makeInvalidRange()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::Constant expr)

Definition at line 412 of file ExpressionRange.cpp.

References Analyzer::Constant::get_constval(), Analyzer::Constant::get_is_null(), SQLTypeInfo::get_type(), Analyzer::Expr::get_type_info(), kBIGINT, kDATE, kDECIMAL, kDOUBLE, kFLOAT, kINT, kNUMERIC, kSMALLINT, kTIME, kTIMESTAMP, kTINYINT, ExpressionRange::makeDoubleRange(), ExpressionRange::makeFloatRange(), ExpressionRange::makeIntRange(), and ExpressionRange::makeInvalidRange().

412  {
413  if (constant_expr->get_is_null()) {
415  }
416  const auto constant_type = constant_expr->get_type_info().get_type();
417  const auto datum = constant_expr->get_constval();
418  switch (constant_type) {
419  case kTINYINT: {
420  const int64_t v = datum.tinyintval;
421  return ExpressionRange::makeIntRange(v, v, 0, false);
422  }
423  case kSMALLINT: {
424  const int64_t v = datum.smallintval;
425  return ExpressionRange::makeIntRange(v, v, 0, false);
426  }
427  case kINT: {
428  const int64_t v = datum.intval;
429  return ExpressionRange::makeIntRange(v, v, 0, false);
430  }
431  case kBIGINT:
432  case kNUMERIC:
433  case kDECIMAL: {
434  const int64_t v = datum.bigintval;
435  return ExpressionRange::makeIntRange(v, v, 0, false);
436  }
437  case kTIME:
438  case kTIMESTAMP:
439  case kDATE: {
440  const int64_t v = datum.bigintval;
441  return ExpressionRange::makeIntRange(v, v, 0, false);
442  }
443  case kFLOAT: {
444  return ExpressionRange::makeFloatRange(datum.floatval, datum.floatval, false);
445  }
446  case kDOUBLE: {
447  return ExpressionRange::makeDoubleRange(datum.doubleval, datum.doubleval, false);
448  }
449  default:
450  break;
451  }
453 }
Definition: sqltypes.h:51
static ExpressionRange makeFloatRange(const float fp_min, const float fp_max, const bool has_nulls)
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
static ExpressionRange makeDoubleRange(const double fp_min, const double fp_max, const bool has_nulls)
Definition: sqltypes.h:55
Definition: sqltypes.h:47
static ExpressionRange makeInvalidRange()

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::ColumnVar col_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 635 of file ExpressionRange.cpp.

References apply_simple_quals(), CHECK_GE, CHECK_LT, Analyzer::ColumnVar::get_column_id(), Analyzer::ColumnVar::get_rte_idx(), Analyzer::ColumnVar::get_table_id(), and getLeafColumnRange().

639  {
640  const int rte_idx = col_expr->get_rte_idx();
641  CHECK_GE(rte_idx, 0);
642  CHECK_LT(static_cast<size_t>(rte_idx), query_infos.size());
643  bool is_outer_join_proj = rte_idx > 0 && executor->containsLeftDeepOuterJoin();
644  if (col_expr->get_table_id() > 0) {
645  auto col_range = executor->getColRange(
646  PhysicalInput{col_expr->get_column_id(), col_expr->get_table_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 }
int get_table_id() const
Definition: Analyzer.h:194
#define CHECK_GE(x, y)
Definition: Logger.h:210
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)
ExpressionRange getLeafColumnRange(const Analyzer::ColumnVar *col_expr, const std::vector< InputTableInfo > &query_infos, const Executor *executor, const bool is_outer_join_proj)
#define CHECK_LT(x, y)
Definition: Logger.h:207
int get_rte_idx() const
Definition: Analyzer.h:196
int get_column_id() const
Definition: Analyzer.h:195

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::LikeExpr like_expr)

Definition at line 655 of file ExpressionRange.cpp.

References CHECK(), Analyzer::LikeExpr::get_arg(), Analyzer::Expr::get_type_info(), inline_int_null_val(), and ExpressionRange::makeIntRange().

655  {
656  const auto& ti = like_expr->get_type_info();
657  CHECK(ti.is_boolean());
658  const auto& arg_ti = like_expr->get_arg()->get_type_info();
660  arg_ti.get_notnull() ? 0 : inline_int_null_val(ti), 1, 0, false);
661 }
const Expr * get_arg() const
Definition: Analyzer.h:905
CHECK(cgen_state)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::CaseExpr case_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor 
)

Definition at line 663 of file ExpressionRange.cpp.

References CHECK(), CHECK_EQ, Analyzer::CaseExpr::get_else_expr(), Analyzer::CaseExpr::get_expr_pair_list(), getExpressionRange(), Invalid, kBOOLEAN, ExpressionRange::makeInvalidRange(), and Null.

665  {
666  const auto& expr_pair_list = case_expr->get_expr_pair_list();
667  auto expr_range = ExpressionRange::makeInvalidRange();
668  bool has_nulls = false;
669  for (const auto& expr_pair : expr_pair_list) {
670  CHECK_EQ(expr_pair.first->get_type_info().get_type(), kBOOLEAN);
671  const auto crt_range =
672  getExpressionRange(expr_pair.second.get(), query_infos, executor);
673  if (crt_range.getType() == ExpressionRangeType::Null) {
674  has_nulls = true;
675  continue;
676  }
677  if (crt_range.getType() == ExpressionRangeType::Invalid) {
679  }
680  expr_range = (expr_range.getType() != ExpressionRangeType::Invalid)
681  ? expr_range || crt_range
682  : crt_range;
683  }
684  if (has_nulls && !(expr_range.getType() == ExpressionRangeType::Invalid)) {
685  expr_range.setHasNulls();
686  }
687  const auto else_expr = case_expr->get_else_expr();
688  CHECK(else_expr);
689  const auto else_null_expr = dynamic_cast<const Analyzer::Constant*>(else_expr);
690  if (else_null_expr && else_null_expr->get_is_null()) {
691  expr_range.setHasNulls();
692  return expr_range;
693  }
694  return expr_range || getExpressionRange(else_expr, query_infos, executor);
695 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
const Expr * get_else_expr() const
Definition: Analyzer.h:1152
CHECK(cgen_state)
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)
static ExpressionRange makeInvalidRange()
const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr > > > & get_expr_pair_list() const
Definition: Analyzer.h:1149

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::UOper u_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 762 of file ExpressionRange.cpp.

References CHECK(), CHECK_EQ, Double, exp_to_scale(), Float, anonymous_namespace{ExpressionRange.cpp}::fpRangeFromDecimal(), Analyzer::UOper::get_operand(), Analyzer::UOper::get_optype(), Analyzer::Expr::get_type_info(), anonymous_namespace{ExpressionRange.cpp}::getDateTimePrecisionCastRange(), getExpressionRange(), Integer, Invalid, kCAST, kDOUBLE, kENCODING_DICT, kFLOAT, kUNNEST, ExpressionRange::makeDoubleRange(), ExpressionRange::makeFloatRange(), ExpressionRange::makeIntRange(), ExpressionRange::makeInvalidRange(), and ExpressionRange::makeNullRange().

766  {
767  if (u_expr->get_optype() == kUNNEST) {
768  return getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
769  }
770  if (u_expr->get_optype() != kCAST) {
772  }
773  const auto& ti = u_expr->get_type_info();
774  if (ti.is_string() && ti.get_compression() == kENCODING_DICT) {
775  const auto sdp = executor->getStringDictionaryProxy(
776  ti.get_comp_param(), executor->getRowSetMemoryOwner(), true);
777  CHECK(sdp);
778  const auto const_operand =
779  dynamic_cast<const Analyzer::Constant*>(u_expr->get_operand());
780  CHECK(const_operand);
781 
782  if (const_operand->get_is_null()) {
784  }
785  CHECK(const_operand->get_constval().stringval);
786  const int64_t v = sdp->getIdOfString(*const_operand->get_constval().stringval);
787  return ExpressionRange::makeIntRange(v, v, 0, false);
788  }
789  const auto arg_range =
790  getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
791  const auto& arg_ti = u_expr->get_operand()->get_type_info();
792  // Timestamp to Date OR Date/Timestamp casts with different precision
793  if ((ti.is_timestamp() && (arg_ti.get_dimension() != ti.get_dimension())) ||
794  ((arg_ti.is_timestamp() && ti.is_date()))) {
795  return getDateTimePrecisionCastRange(arg_range, arg_ti, ti);
796  }
797  switch (arg_range.getType()) {
800  if (ti.is_fp()) {
801  return ti.get_type() == kDOUBLE
803  arg_range.getFpMin(), arg_range.getFpMax(), arg_range.hasNulls())
804  : ExpressionRange::makeFloatRange(arg_range.getFpMin(),
805  arg_range.getFpMax(),
806  arg_range.hasNulls());
807  }
808  if (ti.is_integer()) {
810  arg_range.getFpMin(), arg_range.getFpMax(), 0, arg_range.hasNulls());
811  }
812  break;
813  }
815  if (ti.is_decimal()) {
816  CHECK_EQ(int64_t(0), arg_range.getBucket());
817  const int64_t scale = exp_to_scale(ti.get_scale() - arg_ti.get_scale());
818  return ExpressionRange::makeIntRange(arg_range.getIntMin() * scale,
819  arg_range.getIntMax() * scale,
820  0,
821  arg_range.hasNulls());
822  }
823  if (arg_ti.is_decimal()) {
824  CHECK_EQ(int64_t(0), arg_range.getBucket());
825  const int64_t scale = exp_to_scale(arg_ti.get_scale());
826  const int64_t scale_half = scale / 2;
827  if (ti.is_fp()) {
828  return fpRangeFromDecimal(arg_range, scale, ti);
829  }
830  return ExpressionRange::makeIntRange((arg_range.getIntMin() - scale_half) / scale,
831  (arg_range.getIntMax() + scale_half) / scale,
832  0,
833  arg_range.hasNulls());
834  }
835  if (ti.is_integer() || ti.is_time()) {
836  return arg_range;
837  }
838  if (ti.get_type() == kFLOAT) {
840  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
841  }
842  if (ti.get_type() == kDOUBLE) {
844  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
845  }
846  break;
847  }
849  break;
850  default:
851  CHECK(false);
852  }
854 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
static ExpressionRange makeNullRange()
Definition: sqldefs.h:49
static ExpressionRange makeFloatRange(const float fp_min, const float fp_max, const bool has_nulls)
CHECK(cgen_state)
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 SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
static ExpressionRange makeDoubleRange(const double fp_min, const double fp_max, const bool has_nulls)
const Expr * get_operand() const
Definition: Analyzer.h:371
uint64_t exp_to_scale(const unsigned exp)
static ExpressionRange makeInvalidRange()
ExpressionRange getDateTimePrecisionCastRange(const ExpressionRange &arg_range, const SQLTypeInfo &oper_ti, const SQLTypeInfo &target_ti)
SQLOps get_optype() const
Definition: Analyzer.h:370
ExpressionRange fpRangeFromDecimal(const ExpressionRange &arg_range, const int64_t scale, const SQLTypeInfo &target_ti)

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::ExtractExpr extract_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 856 of file ExpressionRange.cpp.

References CHECK(), ExtractFromTime(), Analyzer::ExtractExpr::get_field(), Analyzer::ExtractExpr::get_from_expr(), DateTimeUtils::get_timestamp_precision_scale(), Analyzer::Expr::get_type_info(), getExpressionRange(), ExpressionRange::getType(), Integer, Invalid, kDATEEPOCH, kDAY, kDOW, kDOY, kEPOCH, kHOUR, kISODOW, kMICROSECOND, kMILLISECOND, kMINUTE, kMONTH, kNANOSECOND, kQUARTER, kQUARTERDAY, kSECOND, kWEEK, kYEAR, ExpressionRange::makeIntRange(), and ExpressionRange::makeInvalidRange().

860  {
861  const int32_t extract_field{extract_expr->get_field()};
862  const auto arg_range = getExpressionRange(
863  extract_expr->get_from_expr(), query_infos, executor, simple_quals);
864  const bool has_nulls =
865  arg_range.getType() == ExpressionRangeType::Invalid || arg_range.hasNulls();
866  const auto& extract_expr_ti = extract_expr->get_from_expr()->get_type_info();
867  switch (extract_field) {
868  case kYEAR: {
869  if (arg_range.getType() == ExpressionRangeType::Invalid) {
871  }
872  CHECK(arg_range.getType() == ExpressionRangeType::Integer);
873  const int64_t year_range_min =
874  extract_expr_ti.is_high_precision_timestamp()
875  ? ExtractFromTime(
876  kYEAR,
877  arg_range.getIntMin() /
878  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
879  : ExtractFromTime(kYEAR, arg_range.getIntMin());
880  const int64_t year_range_max =
881  extract_expr_ti.is_high_precision_timestamp()
882  ? ExtractFromTime(
883  kYEAR,
884  arg_range.getIntMax() /
885  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
886  : ExtractFromTime(kYEAR, arg_range.getIntMax());
888  year_range_min, year_range_max, 0, arg_range.hasNulls());
889  }
890  case kEPOCH:
891  case kDATEEPOCH:
892  return arg_range;
893  case kQUARTERDAY:
894  case kQUARTER:
895  return ExpressionRange::makeIntRange(1, 4, 0, has_nulls);
896  case kMONTH:
897  return ExpressionRange::makeIntRange(1, 12, 0, has_nulls);
898  case kDAY:
899  return ExpressionRange::makeIntRange(1, 31, 0, has_nulls);
900  case kHOUR:
901  return ExpressionRange::makeIntRange(0, 23, 0, has_nulls);
902  case kMINUTE:
903  return ExpressionRange::makeIntRange(0, 59, 0, has_nulls);
904  case kSECOND:
905  return ExpressionRange::makeIntRange(0, 60, 0, has_nulls);
906  case kMILLISECOND:
907  return ExpressionRange::makeIntRange(0, 999, 0, has_nulls);
908  case kMICROSECOND:
909  return ExpressionRange::makeIntRange(0, 999999, 0, has_nulls);
910  case kNANOSECOND:
911  return ExpressionRange::makeIntRange(0, 999999999, 0, has_nulls);
912  case kDOW:
913  return ExpressionRange::makeIntRange(0, 6, 0, has_nulls);
914  case kISODOW:
915  return ExpressionRange::makeIntRange(1, 7, 0, has_nulls);
916  case kDOY:
917  return ExpressionRange::makeIntRange(1, 366, 0, has_nulls);
918  case kWEEK:
919  return ExpressionRange::makeIntRange(1, 53, 0, has_nulls);
920  default:
921  CHECK(false);
922  }
924 }
const Expr * get_from_expr() const
Definition: Analyzer.h:1197
ExtractField get_field() const
Definition: Analyzer.h:1196
CHECK(cgen_state)
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 SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
DEVICE int64_t ExtractFromTime(ExtractField field, const int64_t timeval)
ExpressionRangeType getType() const
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
static ExpressionRange makeInvalidRange()

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::DatetruncExpr datetrunc_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 926 of file ExpressionRange.cpp.

References anonymous_namespace{ExpressionRange.cpp}::get_conservative_datetrunc_bucket(), Analyzer::DatetruncExpr::get_field(), Analyzer::DatetruncExpr::get_from_expr(), DateTimeUtils::get_timestamp_precision_scale(), Analyzer::Expr::get_type_info(), DateTimeTranslator::getDateTruncConstantValue(), getExpressionRange(), Invalid, ExpressionRange::makeIntRange(), and ExpressionRange::makeInvalidRange().

930  {
931  const auto arg_range = getExpressionRange(
932  datetrunc_expr->get_from_expr(), query_infos, executor, simple_quals);
933  if (arg_range.getType() == ExpressionRangeType::Invalid) {
935  }
936  const auto& datetrunc_expr_ti = datetrunc_expr->get_from_expr()->get_type_info();
937  const int64_t min_ts = DateTimeTranslator::getDateTruncConstantValue(
938  arg_range.getIntMin(), datetrunc_expr->get_field(), datetrunc_expr_ti);
939  const int64_t max_ts = DateTimeTranslator::getDateTruncConstantValue(
940  arg_range.getIntMax(), datetrunc_expr->get_field(), datetrunc_expr_ti);
941  const int64_t bucket =
942  datetrunc_expr_ti.is_high_precision_timestamp()
943  ? get_conservative_datetrunc_bucket(datetrunc_expr->get_field()) *
945  datetrunc_expr_ti.get_dimension())
946  : get_conservative_datetrunc_bucket(datetrunc_expr->get_field());
947 
948  return ExpressionRange::makeIntRange(min_ts, max_ts, bucket, arg_range.hasNulls());
949 }
DatetruncField get_field() const
Definition: Analyzer.h:1321
int64_t get_conservative_datetrunc_bucket(const DatetruncField datetrunc_field)
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 SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
const Expr * get_from_expr() const
Definition: Analyzer.h:1322
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
static ExpressionRange makeInvalidRange()
static int64_t getDateTruncConstantValue(const int64_t &timeval, const DatetruncField &field, const SQLTypeInfo &ti)

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::Expr expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 325 of file ExpressionRange.cpp.

References Analyzer::Expr::get_type_info(), getExpressionRange(), ExpressionRange::makeInvalidRange(), and ExpressionRange::typeSupportsRange().

329  {
330  const auto& expr_ti = expr->get_type_info();
331  if (!ExpressionRange::typeSupportsRange(expr_ti)) {
333  }
334  auto bin_oper_expr = dynamic_cast<const Analyzer::BinOper*>(expr);
335  if (bin_oper_expr) {
336  return getExpressionRange(bin_oper_expr, query_infos, executor, simple_quals);
337  }
338  auto constant_expr = dynamic_cast<const Analyzer::Constant*>(expr);
339  if (constant_expr) {
340  return getExpressionRange(constant_expr);
341  }
342  auto column_var_expr = dynamic_cast<const Analyzer::ColumnVar*>(expr);
343  if (column_var_expr) {
344  return getExpressionRange(column_var_expr, query_infos, executor, simple_quals);
345  }
346  auto like_expr = dynamic_cast<const Analyzer::LikeExpr*>(expr);
347  if (like_expr) {
348  return getExpressionRange(like_expr);
349  }
350  auto case_expr = dynamic_cast<const Analyzer::CaseExpr*>(expr);
351  if (case_expr) {
352  return getExpressionRange(case_expr, query_infos, executor);
353  }
354  auto u_expr = dynamic_cast<const Analyzer::UOper*>(expr);
355  if (u_expr) {
356  return getExpressionRange(u_expr, query_infos, executor, simple_quals);
357  }
358  auto extract_expr = dynamic_cast<const Analyzer::ExtractExpr*>(expr);
359  if (extract_expr) {
360  return getExpressionRange(extract_expr, query_infos, executor, simple_quals);
361  }
362  auto datetrunc_expr = dynamic_cast<const Analyzer::DatetruncExpr*>(expr);
363  if (datetrunc_expr) {
364  return getExpressionRange(datetrunc_expr, query_infos, executor, simple_quals);
365  }
367 }
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 SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static bool typeSupportsRange(const SQLTypeInfo &ti)
static ExpressionRange makeInvalidRange()

+ Here is the call graph for this function:

ExpressionRange getLeafColumnRange ( const Analyzer::ColumnVar col_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
const bool  is_outer_join_proj 
)

Definition at line 529 of file ExpressionRange.cpp.

References CHECK(), CHECK_EQ, CHECK_GT, dtDAY, extract_max_stat(), anonymous_namespace{ExpressionRange.cpp}::extract_max_stat_double(), extract_min_stat(), anonymous_namespace{ExpressionRange.cpp}::extract_min_stat_double(), FIND_STAT_FRAG, Analyzer::ColumnVar::get_column_id(), anonymous_namespace{ExpressionRange.cpp}::get_conservative_datetrunc_bucket(), SQLTypeInfo::get_elem_type(), get_logical_type_info(), Analyzer::ColumnVar::get_table_id(), Analyzer::Expr::get_type_info(), SQLTypeInfo::is_array(), kBIGINT, kBOOLEAN, kCHAR, kDATE, kDECIMAL, kDOUBLE, kENCODING_DICT, kFLOAT, kINT, kNUMERIC, kSMALLINT, kTEXT, kTIME, kTIMESTAMP, kTINYINT, kVARCHAR, ExpressionRange::makeDoubleRange(), ExpressionRange::makeFloatRange(), ExpressionRange::makeIntRange(), and ExpressionRange::makeInvalidRange().

Referenced by Executor::computeColRangesCache(), and getExpressionRange().

532  {
533  bool has_nulls = is_outer_join_proj;
534  int col_id = col_expr->get_column_id();
535  const auto& col_phys_ti = col_expr->get_type_info().is_array()
536  ? col_expr->get_type_info().get_elem_type()
537  : col_expr->get_type_info();
538  const auto col_ti = get_logical_type_info(col_phys_ti);
539  switch (col_ti.get_type()) {
540  case kTEXT:
541  case kCHAR:
542  case kVARCHAR:
543  CHECK_EQ(kENCODING_DICT, col_ti.get_compression());
544  case kBOOLEAN:
545  case kTINYINT:
546  case kSMALLINT:
547  case kINT:
548  case kBIGINT:
549  case kDECIMAL:
550  case kNUMERIC:
551  case kDATE:
552  case kTIMESTAMP:
553  case kTIME:
554  case kFLOAT:
555  case kDOUBLE: {
556  std::optional<size_t> ti_idx;
557  for (size_t i = 0; i < query_infos.size(); ++i) {
558  if (col_expr->get_table_id() == query_infos[i].table_id) {
559  ti_idx = i;
560  break;
561  }
562  }
563  CHECK(ti_idx);
564  const auto& query_info = query_infos[*ti_idx].info;
565  const auto& fragments = query_info.fragments;
566  const auto cd = executor->getColumnDescriptor(col_expr);
567  if (cd && cd->isVirtualCol) {
568  CHECK(cd->columnName == "rowid");
569  CHECK_EQ(kBIGINT, col_ti.get_type());
570  const int64_t num_tuples = query_info.getNumTuples();
572  0, std::max(num_tuples - 1, int64_t(0)), 0, has_nulls);
573  }
574  if (query_info.getNumTuples() == 0) {
575  // The column doesn't contain any values, synthesize an empty range.
576  if (col_ti.is_fp()) {
577  return col_ti.get_type() == kFLOAT
578  ? ExpressionRange::makeFloatRange(0, -1, false)
579  : ExpressionRange::makeDoubleRange(0, -1, false);
580  }
581  return ExpressionRange::makeIntRange(0, -1, 0, false);
582  }
583  std::vector<size_t> nonempty_fragment_indices;
584  for (size_t i = 0; i < fragments.size(); ++i) {
585  const auto& fragment = fragments[i];
586  if (!fragment.isEmptyPhysicalFragment()) {
587  nonempty_fragment_indices.push_back(i);
588  }
589  }
590  FIND_STAT_FRAG(min);
591  FIND_STAT_FRAG(max);
592  const auto& min_frag = fragments[*min_frag_index];
593  const auto min_it = min_frag.getChunkMetadataMap().find(col_id);
594  if (min_it == min_frag.getChunkMetadataMap().end()) {
596  }
597  const auto& max_frag = fragments[*max_frag_index];
598  const auto max_it = max_frag.getChunkMetadataMap().find(col_id);
599  CHECK(max_it != max_frag.getChunkMetadataMap().end());
600  for (const auto& fragment : fragments) {
601  const auto it = fragment.getChunkMetadataMap().find(col_id);
602  if (it != fragment.getChunkMetadataMap().end()) {
603  if (it->second->chunkStats.has_nulls) {
604  has_nulls = true;
605  break;
606  }
607  }
608  }
609  if (col_ti.is_fp()) {
610  const auto min_val = extract_min_stat_double(min_it->second->chunkStats, col_ti);
611  const auto max_val = extract_max_stat_double(max_it->second->chunkStats, col_ti);
612  return col_ti.get_type() == kFLOAT
613  ? ExpressionRange::makeFloatRange(min_val, max_val, has_nulls)
614  : ExpressionRange::makeDoubleRange(min_val, max_val, has_nulls);
615  }
616  const auto min_val = extract_min_stat(min_it->second->chunkStats, col_ti);
617  const auto max_val = extract_max_stat(max_it->second->chunkStats, col_ti);
618  if (max_val < min_val) {
619  // The column doesn't contain any non-null values, synthesize an empty range.
620  CHECK_GT(min_val, 0);
621  return ExpressionRange::makeIntRange(0, -1, 0, has_nulls);
622  }
623  const int64_t bucket =
624  col_ti.get_type() == kDATE ? get_conservative_datetrunc_bucket(dtDAY) : 0;
625  return ExpressionRange::makeIntRange(min_val, max_val, bucket, has_nulls);
626  }
627  default:
628  break;
629  }
631 }
int get_table_id() const
Definition: Analyzer.h:194
#define CHECK_EQ(x, y)
Definition: Logger.h:205
#define FIND_STAT_FRAG(stat_name)
Definition: sqltypes.h:51
double extract_min_stat_double(const ChunkStats &stats, const SQLTypeInfo &col_ti)
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:819
#define CHECK_GT(x, y)
Definition: Logger.h:209
static ExpressionRange makeFloatRange(const float fp_min, const float fp_max, const bool has_nulls)
CHECK(cgen_state)
int64_t get_conservative_datetrunc_bucket(const DatetruncField datetrunc_field)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
Definition: sqltypes.h:54
Definition: sqltypes.h:55
Definition: sqltypes.h:43
int64_t extract_min_stat(const ChunkStats &stats, const SQLTypeInfo &ti)
bool g_enable_watchdog false
Definition: Execute.cpp:74
Definition: sqltypes.h:47
int get_column_id() const
Definition: Analyzer.h:195
static ExpressionRange makeInvalidRange()
SQLTypeInfo get_elem_type() const
Definition: sqltypes.h:623
bool is_array() const
Definition: sqltypes.h:424
double extract_max_stat_double(const ChunkStats &stats, const SQLTypeInfo &col_ti)
int64_t extract_max_stat(const ChunkStats &stats, const SQLTypeInfo &ti)

+ Here is the call graph for this function:

+ Here is the caller graph for this function: