OmniSciDB  6686921089
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExpressionRange.cpp File Reference
#include "ExpressionRange.h"
#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 <algorithm>
#include <cfenv>
#include <cmath>
+ 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::WidthBucketExpr *width_bucket_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 31 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()) { \
}
#define const
#define CHECK(condition)
Definition: Logger.h:209
static ExpressionRange makeInvalidRange()
if(yyssp >=yyss+yystacksize-1)

Definition at line 466 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 74 of file ExpressionRange.cpp.

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

Referenced by apply_simple_quals().

77  {
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 }
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 124 of file ExpressionRange.cpp.

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

Referenced by apply_simple_quals().

129  {
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 }
void apply_int_qual(const Datum const_datum, const SQLTypes const_type, const SQLOps sql_op, ExpressionRange &qual_range)
int64_t bigintval
Definition: sqltypes.h:215
#define CHECK(condition)
Definition: Logger.h:209
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 97 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().

100  {
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 }
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 144 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().

147  {
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->get_table_id() != col_expr->get_table_id() ||
173  qual_col->get_column_id() != col_expr->get_column_id()) {
174  continue;
175  }
176  const Analyzer::Expr* right_operand = qual_bin_oper->get_right_operand();
177  auto qual_const = dynamic_cast<const Analyzer::Constant*>(right_operand);
178  if (!qual_const) {
179  continue;
180  }
181  if (qual_range.getType() == ExpressionRangeType::Float ||
182  qual_range.getType() == ExpressionRangeType::Double) {
183  apply_fp_qual(qual_const->get_constval(),
184  qual_const->get_type_info().get_type(),
185  qual_bin_oper->get_optype(),
186  qual_range);
187  } else if ((qual_col->get_type_info().is_timestamp() ||
188  qual_const->get_type_info().is_timestamp()) &&
189  (qual_col->get_type_info().get_dimension() !=
190  qual_const->get_type_info().get_dimension())) {
191  apply_hpt_qual(qual_const->get_constval(),
192  qual_const->get_type_info().get_type(),
193  qual_const->get_type_info().get_dimension(),
194  qual_col->get_type_info().get_dimension(),
195  qual_bin_oper->get_optype(),
196  qual_range);
197  } else {
198  apply_int_qual(qual_const->get_constval(),
199  qual_const->get_type_info().get_type(),
200  qual_bin_oper->get_optype(),
201  qual_range);
202  }
203  }
204  return qual_range;
205 }
int get_table_id() const
Definition: Analyzer.h:193
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:194

+ 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 388 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(), CodeGenerator::codegen(), anonymous_namespace{RelAlgExecutor.cpp}::decide_approx_count_distinct_implementation(), anonymous_namespace{GroupByAndAggregate.cpp}::get_expr_range_info(), anonymous_namespace{GroupByAndAggregate.cpp}::get_keyless_info(), getExpressionRange(), PerfectJoinHashTable::getInstance(), anonymous_namespace{QueryMemoryDescriptor.cpp}::pick_baseline_key_width(), and QueryRewriter::rewriteConstrainedByInImpl().

392  {
393  const auto& lhs =
394  getExpressionRange(expr->get_left_operand(), query_infos, executor, simple_quals);
395  const auto& rhs =
396  getExpressionRange(expr->get_right_operand(), query_infos, executor, simple_quals);
397  switch (expr->get_optype()) {
398  case kPLUS:
399  return lhs + rhs;
400  case kMINUS:
401  return lhs - rhs;
402  case kMULTIPLY:
403  return lhs * rhs;
404  case kDIVIDE: {
405  const auto& lhs_type = expr->get_left_operand()->get_type_info();
406  if (lhs_type.is_decimal() && lhs.getType() != ExpressionRangeType::Invalid) {
407  CHECK(lhs.getType() == ExpressionRangeType::Integer);
408  const auto adjusted_lhs = ExpressionRange::makeIntRange(
409  scale_up_interval_endpoint(lhs.getIntMin(), lhs_type),
410  scale_up_interval_endpoint(lhs.getIntMax(), lhs_type),
411  0,
412  lhs.hasNulls());
413  return adjusted_lhs / rhs;
414  }
415  return lhs / rhs;
416  }
417  default:
418  break;
419  }
421 }
const Expr * get_right_operand() const
Definition: Analyzer.h:442
Definition: sqldefs.h:41
int64_t scale_up_interval_endpoint(const int64_t endpoint, const SQLTypeInfo &ti)
SQLOps get_optype() const
Definition: Analyzer.h:438
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:77
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
#define CHECK(condition)
Definition: Logger.h:209
const Expr * get_left_operand() const
Definition: Analyzer.h:441
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 423 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().

423  {
424  if (constant_expr->get_is_null()) {
426  }
427  const auto constant_type = constant_expr->get_type_info().get_type();
428  const auto datum = constant_expr->get_constval();
429  switch (constant_type) {
430  case kTINYINT: {
431  const int64_t v = datum.tinyintval;
432  return ExpressionRange::makeIntRange(v, v, 0, false);
433  }
434  case kSMALLINT: {
435  const int64_t v = datum.smallintval;
436  return ExpressionRange::makeIntRange(v, v, 0, false);
437  }
438  case kINT: {
439  const int64_t v = datum.intval;
440  return ExpressionRange::makeIntRange(v, v, 0, false);
441  }
442  case kBIGINT:
443  case kNUMERIC:
444  case kDECIMAL: {
445  const int64_t v = datum.bigintval;
446  return ExpressionRange::makeIntRange(v, v, 0, false);
447  }
448  case kTIME:
449  case kTIMESTAMP:
450  case kDATE: {
451  const int64_t v = datum.bigintval;
452  return ExpressionRange::makeIntRange(v, v, 0, false);
453  }
454  case kFLOAT: {
455  return ExpressionRange::makeFloatRange(datum.floatval, datum.floatval, false);
456  }
457  case kDOUBLE: {
458  return ExpressionRange::makeDoubleRange(datum.doubleval, datum.doubleval, false);
459  }
460  default:
461  break;
462  }
464 }
Definition: sqltypes.h:49
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:53
Definition: sqltypes.h:45
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 648 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().

652  {
653  const int rte_idx = col_expr->get_rte_idx();
654  CHECK_GE(rte_idx, 0);
655  CHECK_LT(static_cast<size_t>(rte_idx), query_infos.size());
656  bool is_outer_join_proj = rte_idx > 0 && executor->containsLeftDeepOuterJoin();
657  if (col_expr->get_table_id() > 0) {
658  auto col_range = executor->getColRange(
659  PhysicalInput{col_expr->get_column_id(), col_expr->get_table_id()});
660  if (is_outer_join_proj) {
661  col_range.setHasNulls();
662  }
663  return apply_simple_quals(col_expr, col_range, simple_quals);
664  }
665  return getLeafColumnRange(col_expr, query_infos, executor, is_outer_join_proj);
666 }
int get_table_id() const
Definition: Analyzer.h:193
#define CHECK_GE(x, y)
Definition: Logger.h:222
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:219
int get_rte_idx() const
Definition: Analyzer.h:195
int get_column_id() const
Definition: Analyzer.h:194

+ Here is the call graph for this function:

ExpressionRange getExpressionRange ( const Analyzer::LikeExpr like_expr)

Definition at line 668 of file ExpressionRange.cpp.

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

668  {
669  const auto& ti = like_expr->get_type_info();
670  CHECK(ti.is_boolean());
671  const auto& arg_ti = like_expr->get_arg()->get_type_info();
673  arg_ti.get_notnull() ? 0 : inline_int_null_val(ti), 1, 0, false);
674 }
const Expr * get_arg() const
Definition: Analyzer.h:951
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
#define CHECK(condition)
Definition: Logger.h:209
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 676 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.

678  {
679  const auto& expr_pair_list = case_expr->get_expr_pair_list();
680  auto expr_range = ExpressionRange::makeInvalidRange();
681  bool has_nulls = false;
682  for (const auto& expr_pair : expr_pair_list) {
683  CHECK_EQ(expr_pair.first->get_type_info().get_type(), kBOOLEAN);
684  const auto crt_range =
685  getExpressionRange(expr_pair.second.get(), query_infos, executor);
686  if (crt_range.getType() == ExpressionRangeType::Null) {
687  has_nulls = true;
688  continue;
689  }
690  if (crt_range.getType() == ExpressionRangeType::Invalid) {
692  }
693  expr_range = (expr_range.getType() != ExpressionRangeType::Invalid)
694  ? expr_range || crt_range
695  : crt_range;
696  }
697  if (has_nulls && !(expr_range.getType() == ExpressionRangeType::Invalid)) {
698  expr_range.setHasNulls();
699  }
700  const auto else_expr = case_expr->get_else_expr();
701  CHECK(else_expr);
702  const auto else_null_expr = dynamic_cast<const Analyzer::Constant*>(else_expr);
703  if (else_null_expr && else_null_expr->get_is_null()) {
704  expr_range.setHasNulls();
705  return expr_range;
706  }
707  return expr_range || getExpressionRange(else_expr, query_infos, executor);
708 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
const Expr * get_else_expr() const
Definition: Analyzer.h:1307
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)
#define CHECK(condition)
Definition: Logger.h:209
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:1304

+ 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 775 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(), ExpressionRange::makeNullRange(), Analyzer::Expr::toString(), and VLOG.

779  {
780  if (u_expr->get_optype() == kUNNEST) {
781  return getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
782  }
783  if (u_expr->get_optype() != kCAST) {
785  }
786  const auto& ti = u_expr->get_type_info();
787  if (ti.is_string() && ti.get_compression() == kENCODING_DICT) {
788  const auto sdp = executor->getStringDictionaryProxy(
789  ti.get_comp_param(), executor->getRowSetMemoryOwner(), true);
790  CHECK(sdp);
791  const auto const_operand =
792  dynamic_cast<const Analyzer::Constant*>(u_expr->get_operand());
793  if (!const_operand) {
794  // casted subquery result. return invalid for now, but we could attempt to pull the
795  // range from the subquery result in the future
796  CHECK(u_expr->get_operand());
797  VLOG(1) << "Unable to determine expression range for dictionary encoded expression "
798  << u_expr->get_operand()->toString() << ", proceeding with invalid range.";
800  }
801 
802  if (const_operand->get_is_null()) {
804  }
805  CHECK(const_operand->get_constval().stringval);
806  const int64_t v = sdp->getIdOfString(*const_operand->get_constval().stringval);
807  return ExpressionRange::makeIntRange(v, v, 0, false);
808  }
809  const auto arg_range =
810  getExpressionRange(u_expr->get_operand(), query_infos, executor, simple_quals);
811  const auto& arg_ti = u_expr->get_operand()->get_type_info();
812  // Timestamp to Date OR Date/Timestamp casts with different precision
813  if ((ti.is_timestamp() && (arg_ti.get_dimension() != ti.get_dimension())) ||
814  ((arg_ti.is_timestamp() && ti.is_date()))) {
815  return getDateTimePrecisionCastRange(arg_range, arg_ti, ti);
816  }
817  switch (arg_range.getType()) {
820  if (ti.is_fp()) {
821  return ti.get_type() == kDOUBLE
823  arg_range.getFpMin(), arg_range.getFpMax(), arg_range.hasNulls())
824  : ExpressionRange::makeFloatRange(arg_range.getFpMin(),
825  arg_range.getFpMax(),
826  arg_range.hasNulls());
827  }
828  if (ti.is_integer()) {
829  return ExpressionRange::makeIntRange(std::floor(arg_range.getFpMin()),
830  std::ceil(arg_range.getFpMax()),
831  0,
832  arg_range.hasNulls());
833  }
834  break;
835  }
837  if (ti.is_decimal()) {
838  CHECK_EQ(int64_t(0), arg_range.getBucket());
839  const int64_t scale = exp_to_scale(ti.get_scale() - arg_ti.get_scale());
840  return ExpressionRange::makeIntRange(arg_range.getIntMin() * scale,
841  arg_range.getIntMax() * scale,
842  0,
843  arg_range.hasNulls());
844  }
845  if (arg_ti.is_decimal()) {
846  CHECK_EQ(int64_t(0), arg_range.getBucket());
847  const int64_t scale = exp_to_scale(arg_ti.get_scale());
848  const int64_t scale_half = scale / 2;
849  if (ti.is_fp()) {
850  return fpRangeFromDecimal(arg_range, scale, ti);
851  }
852  return ExpressionRange::makeIntRange((arg_range.getIntMin() - scale_half) / scale,
853  (arg_range.getIntMax() + scale_half) / scale,
854  0,
855  arg_range.hasNulls());
856  }
857  if (ti.is_integer() || ti.is_time()) {
858  return arg_range;
859  }
860  if (ti.get_type() == kFLOAT) {
862  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
863  }
864  if (ti.get_type() == kDOUBLE) {
866  arg_range.getIntMin(), arg_range.getIntMax(), arg_range.hasNulls());
867  }
868  break;
869  }
871  break;
872  default:
873  CHECK(false);
874  }
876 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
static ExpressionRange makeNullRange()
Definition: sqldefs.h:49
static ExpressionRange makeFloatRange(const float fp_min, const float fp_max, const bool has_nulls)
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:77
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)
virtual std::string toString() const =0
const Expr * get_operand() const
Definition: Analyzer.h:370
#define CHECK(condition)
Definition: Logger.h:209
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:369
#define VLOG(n)
Definition: Logger.h:303
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 878 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, kWEEK_SATURDAY, kWEEK_SUNDAY, kYEAR, ExpressionRange::makeIntRange(), and ExpressionRange::makeInvalidRange().

882  {
883  const int32_t extract_field{extract_expr->get_field()};
884  const auto arg_range = getExpressionRange(
885  extract_expr->get_from_expr(), query_infos, executor, simple_quals);
886  const bool has_nulls =
887  arg_range.getType() == ExpressionRangeType::Invalid || arg_range.hasNulls();
888  const auto& extract_expr_ti = extract_expr->get_from_expr()->get_type_info();
889  switch (extract_field) {
890  case kYEAR: {
891  if (arg_range.getType() == ExpressionRangeType::Invalid) {
893  }
894  CHECK(arg_range.getType() == ExpressionRangeType::Integer);
895  const int64_t year_range_min =
896  extract_expr_ti.is_high_precision_timestamp()
897  ? ExtractFromTime(
898  kYEAR,
899  arg_range.getIntMin() /
900  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
901  : ExtractFromTime(kYEAR, arg_range.getIntMin());
902  const int64_t year_range_max =
903  extract_expr_ti.is_high_precision_timestamp()
904  ? ExtractFromTime(
905  kYEAR,
906  arg_range.getIntMax() /
907  get_timestamp_precision_scale(extract_expr_ti.get_dimension()))
908  : ExtractFromTime(kYEAR, arg_range.getIntMax());
910  year_range_min, year_range_max, 0, arg_range.hasNulls());
911  }
912  case kEPOCH:
913  case kDATEEPOCH:
914  return arg_range;
915  case kQUARTERDAY:
916  case kQUARTER:
917  return ExpressionRange::makeIntRange(1, 4, 0, has_nulls);
918  case kMONTH:
919  return ExpressionRange::makeIntRange(1, 12, 0, has_nulls);
920  case kDAY:
921  return ExpressionRange::makeIntRange(1, 31, 0, has_nulls);
922  case kHOUR:
923  return ExpressionRange::makeIntRange(0, 23, 0, has_nulls);
924  case kMINUTE:
925  return ExpressionRange::makeIntRange(0, 59, 0, has_nulls);
926  case kSECOND:
927  return ExpressionRange::makeIntRange(0, 60, 0, has_nulls);
928  case kMILLISECOND:
929  return ExpressionRange::makeIntRange(0, 999, 0, has_nulls);
930  case kMICROSECOND:
931  return ExpressionRange::makeIntRange(0, 999999, 0, has_nulls);
932  case kNANOSECOND:
933  return ExpressionRange::makeIntRange(0, 999999999, 0, has_nulls);
934  case kDOW:
935  return ExpressionRange::makeIntRange(0, 6, 0, has_nulls);
936  case kISODOW:
937  return ExpressionRange::makeIntRange(1, 7, 0, has_nulls);
938  case kDOY:
939  return ExpressionRange::makeIntRange(1, 366, 0, has_nulls);
940  case kWEEK:
941  case kWEEK_SUNDAY:
942  case kWEEK_SATURDAY:
943  return ExpressionRange::makeIntRange(1, 53, 0, has_nulls);
944  default:
945  CHECK(false);
946  }
948 }
const Expr * get_from_expr() const
Definition: Analyzer.h:1352
ExtractField get_field() const
Definition: Analyzer.h:1351
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:77
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
#define CHECK(condition)
Definition: Logger.h:209
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 950 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().

954  {
955  const auto arg_range = getExpressionRange(
956  datetrunc_expr->get_from_expr(), query_infos, executor, simple_quals);
957  if (arg_range.getType() == ExpressionRangeType::Invalid) {
959  }
960  const auto& datetrunc_expr_ti = datetrunc_expr->get_from_expr()->get_type_info();
961  const int64_t min_ts = DateTimeTranslator::getDateTruncConstantValue(
962  arg_range.getIntMin(), datetrunc_expr->get_field(), datetrunc_expr_ti);
963  const int64_t max_ts = DateTimeTranslator::getDateTruncConstantValue(
964  arg_range.getIntMax(), datetrunc_expr->get_field(), datetrunc_expr_ti);
965  const int64_t bucket =
966  datetrunc_expr_ti.is_high_precision_timestamp()
967  ? get_conservative_datetrunc_bucket(datetrunc_expr->get_field()) *
969  datetrunc_expr_ti.get_dimension())
970  : get_conservative_datetrunc_bucket(datetrunc_expr->get_field());
971 
972  return ExpressionRange::makeIntRange(min_ts, max_ts, bucket, arg_range.hasNulls());
973 }
DatetruncField get_field() const
Definition: Analyzer.h:1476
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:77
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:1477
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::WidthBucketExpr width_bucket_expr,
const std::vector< InputTableInfo > &  query_infos,
const Executor executor,
boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>>  simple_quals 
)

Definition at line 975 of file ExpressionRange.cpp.

References CHECK, Analyzer::WidthBucketExpr::compute_bucket(), Double, Float, Analyzer::WidthBucketExpr::get_partition_count(), Analyzer::WidthBucketExpr::get_partition_count_val(), Analyzer::WidthBucketExpr::get_target_value(), getExpressionRange(), ExpressionRange::getFpMax(), ExpressionRange::getFpMin(), ExpressionRange::hasNulls(), INT32_MAX, Integer, Invalid, Analyzer::WidthBucketExpr::is_constant_expr(), ExpressionRange::makeIntRange(), run_benchmark_import::res, and width_bucket_expr().

979  {
980  auto target_value_expr = width_bucket_expr->get_target_value();
981  auto target_value_range = getExpressionRange(target_value_expr, query_infos, executor);
982  auto target_ti = target_value_expr->get_type_info();
983  if (width_bucket_expr->is_constant_expr() &&
984  target_value_range.getType() != ExpressionRangeType::Invalid) {
985  auto const_target_value = dynamic_cast<const Analyzer::Constant*>(target_value_expr);
986  if (const_target_value) {
987  if (const_target_value->get_is_null()) {
988  // null constant, return default width_bucket range
990  0, width_bucket_expr->get_partition_count_val(), 0, true);
991  } else {
992  CHECK(target_value_range.getFpMax() == target_value_range.getFpMin());
993  auto target_value_bucket =
994  width_bucket_expr->compute_bucket(target_value_range.getFpMax(), target_ti);
996  target_value_bucket, target_value_bucket, 0, target_value_range.hasNulls());
997  }
998  }
999  // compute possible bucket range based on lower and upper bound constants
1000  // to elucidate a target bucket range
1001  const auto target_value_range_with_qual =
1002  getExpressionRange(target_value_expr, query_infos, executor, simple_quals);
1003  auto compute_bucket_range = [&width_bucket_expr](const ExpressionRange& target_range,
1004  SQLTypeInfo ti) {
1005  // we casted bucket bound exprs to double
1006  auto lower_bound_bucket =
1007  width_bucket_expr->compute_bucket<double>(target_range.getFpMin(), ti);
1008  auto upper_bound_bucket =
1009  width_bucket_expr->compute_bucket<double>(target_range.getFpMax(), ti);
1011  lower_bound_bucket, upper_bound_bucket, 0, target_range.hasNulls());
1012  };
1013  auto res_range = compute_bucket_range(target_value_range_with_qual, target_ti);
1014  // check target_value expression's col range to be not nullable iff it has its filter
1015  // expression i.e., in simple_quals
1016  // todo (yoonmin) : need to search simple_quals to cover more cases?
1017  if (target_value_range.getFpMin() < target_value_range_with_qual.getFpMin() ||
1018  target_value_range.getFpMax() > target_value_range_with_qual.getFpMax()) {
1019  res_range.setNulls(false);
1020  }
1021  return res_range;
1022  } else {
1023  // we cannot determine a possibility of skipping oob check safely
1024  const bool has_nulls = target_value_range.getType() == ExpressionRangeType::Invalid ||
1025  target_value_range.hasNulls();
1026  auto partition_expr_range = getExpressionRange(
1027  width_bucket_expr->get_partition_count(), query_infos, executor, simple_quals);
1028  auto res = ExpressionRange::makeIntRange(0, INT32_MAX, 0, has_nulls);
1029  switch (partition_expr_range.getType()) {
1031  res.setIntMax(partition_expr_range.getIntMax() + 1);
1032  break;
1033  }
1036  res.setIntMax(static_cast<int64_t>(partition_expr_range.getFpMax()) + 1);
1037  break;
1038  }
1039  default:
1040  break;
1041  }
1042  return res;
1043  }
1044 }
const Expr * get_partition_count() const
Definition: Analyzer.h:1091
bool is_constant_expr() const
Definition: Analyzer.h:1166
#define INT32_MAX
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
static ExpressionRange makeIntRange(const int64_t int_min, const int64_t int_max, const int64_t bucket, const bool has_nulls)
double getFpMax() const
double getFpMin() const
int32_t get_partition_count_val() const
Definition: Analyzer.cpp:3430
const Expr * get_target_value() const
Definition: Analyzer.h:1088
#define CHECK(condition)
Definition: Logger.h:209
int32_t compute_bucket(T target_const_val, SQLTypeInfo &ti) const
Definition: Analyzer.h:1129
ALWAYS_INLINE DEVICE double width_bucket_expr(const double target_value, const bool reversed, const double lower_bound, const double upper_bound, const int32_t partition_count)

+ 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 332 of file ExpressionRange.cpp.

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

336  {
337  const auto& expr_ti = expr->get_type_info();
338  if (!ExpressionRange::typeSupportsRange(expr_ti)) {
340  }
341  auto bin_oper_expr = dynamic_cast<const Analyzer::BinOper*>(expr);
342  if (bin_oper_expr) {
343  return getExpressionRange(bin_oper_expr, query_infos, executor, simple_quals);
344  }
345  auto constant_expr = dynamic_cast<const Analyzer::Constant*>(expr);
346  if (constant_expr) {
347  return getExpressionRange(constant_expr);
348  }
349  auto column_var_expr = dynamic_cast<const Analyzer::ColumnVar*>(expr);
350  if (column_var_expr) {
351  return getExpressionRange(column_var_expr, query_infos, executor, simple_quals);
352  }
353  auto like_expr = dynamic_cast<const Analyzer::LikeExpr*>(expr);
354  if (like_expr) {
355  return getExpressionRange(like_expr);
356  }
357  auto case_expr = dynamic_cast<const Analyzer::CaseExpr*>(expr);
358  if (case_expr) {
359  return getExpressionRange(case_expr, query_infos, executor);
360  }
361  auto u_expr = dynamic_cast<const Analyzer::UOper*>(expr);
362  if (u_expr) {
363  return getExpressionRange(u_expr, query_infos, executor, simple_quals);
364  }
365  auto extract_expr = dynamic_cast<const Analyzer::ExtractExpr*>(expr);
366  if (extract_expr) {
367  return getExpressionRange(extract_expr, query_infos, executor, simple_quals);
368  }
369  auto datetrunc_expr = dynamic_cast<const Analyzer::DatetruncExpr*>(expr);
370  if (datetrunc_expr) {
371  return getExpressionRange(datetrunc_expr, query_infos, executor, simple_quals);
372  }
373  auto width_bucket_expr = dynamic_cast<const Analyzer::WidthBucketExpr*>(expr);
374  if (width_bucket_expr) {
375  return getExpressionRange(width_bucket_expr, query_infos, executor, simple_quals);
376  }
378 }
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:77
static bool typeSupportsRange(const SQLTypeInfo &ti)
static ExpressionRange makeInvalidRange()
ALWAYS_INLINE DEVICE double width_bucket_expr(const double target_value, const bool reversed, const double lower_bound, const double upper_bound, const int32_t partition_count)

+ 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 542 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(), i, 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().

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