OmniSciDB  06b3bd477c
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor Class Reference
+ Inheritance diagram for anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor:
+ Collaboration diagram for anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor:

Public Member Functions

 ConstantFoldingVisitor ()
 
int32_t get_num_overflows ()
 
void reset_num_overflows ()
 
- Public Member Functions inherited from ScalarExprVisitor< std::shared_ptr< Analyzer::Expr > >
std::shared_ptr< Analyzer::Exprvisit (const Analyzer::Expr *expr) const
 

Protected Attributes

std::unordered_map< const
Analyzer::Expr *, const
SQLTypeInfo
casts_
 
int32_t num_overflows_
 

Private Member Functions

template<typename T >
bool foldComparison (SQLOps optype, T t1, T t2) const
 
template<typename T >
bool foldLogic (SQLOps optype, T t1, T t2) const
 
template<typename T >
foldArithmetic (SQLOps optype, T t1, T t2) const
 
bool foldOper (SQLOps optype, SQLTypes type, Datum lhs, Datum rhs, Datum &result, SQLTypes &result_type) const
 
std::shared_ptr< Analyzer::ExprvisitUOper (const Analyzer::UOper *uoper) const override
 
std::shared_ptr< Analyzer::ExprvisitBinOper (const Analyzer::BinOper *bin_oper) const override
 
std::shared_ptr< Analyzer::ExprvisitLower (const Analyzer::LowerExpr *lower_expr) const override
 

Additional Inherited Members

- Protected Types inherited from DeepCopyVisitor
using RetType = std::shared_ptr< Analyzer::Expr >
 
- Protected Member Functions inherited from DeepCopyVisitor
RetType visitColumnVar (const Analyzer::ColumnVar *col_var) const override
 
RetType visitColumnVarTuple (const Analyzer::ExpressionTuple *col_var_tuple) const override
 
RetType visitVar (const Analyzer::Var *var) const override
 
RetType visitConstant (const Analyzer::Constant *constant) const override
 
RetType visitInValues (const Analyzer::InValues *in_values) const override
 
RetType visitInIntegerSet (const Analyzer::InIntegerSet *in_integer_set) const override
 
RetType visitCharLength (const Analyzer::CharLengthExpr *char_length) const override
 
RetType visitKeyForString (const Analyzer::KeyForStringExpr *expr) const override
 
RetType visitSampleRatio (const Analyzer::SampleRatioExpr *expr) const override
 
RetType visitCardinality (const Analyzer::CardinalityExpr *cardinality) const override
 
RetType visitLikeExpr (const Analyzer::LikeExpr *like) const override
 
RetType visitRegexpExpr (const Analyzer::RegexpExpr *regexp) const override
 
RetType visitCaseExpr (const Analyzer::CaseExpr *case_expr) const override
 
RetType visitDatetruncExpr (const Analyzer::DatetruncExpr *datetrunc) const override
 
RetType visitExtractExpr (const Analyzer::ExtractExpr *extract) const override
 
RetType visitArrayOper (const Analyzer::ArrayExpr *array_expr) const override
 
RetType visitGeoUOper (const Analyzer::GeoUOper *geo_expr) const override
 
RetType visitGeoBinOper (const Analyzer::GeoBinOper *geo_expr) const override
 
RetType visitWindowFunction (const Analyzer::WindowFunction *window_func) const override
 
RetType visitFunctionOper (const Analyzer::FunctionOper *func_oper) const override
 
RetType visitDatediffExpr (const Analyzer::DatediffExpr *datediff) const override
 
RetType visitDateaddExpr (const Analyzer::DateaddExpr *dateadd) const override
 
RetType visitFunctionOperWithCustomTypeHandling (const Analyzer::FunctionOperWithCustomTypeHandling *func_oper) const override
 
RetType visitLikelihood (const Analyzer::LikelihoodExpr *likelihood) const override
 
RetType visitAggExpr (const Analyzer::AggExpr *agg) const override
 
RetType visitOffsetInFragment (const Analyzer::OffsetInFragment *) const override
 
- Protected Member Functions inherited from ScalarExprVisitor< std::shared_ptr< Analyzer::Expr > >
virtual std::shared_ptr
< Analyzer::Expr
aggregateResult (const std::shared_ptr< Analyzer::Expr > &aggregate, const std::shared_ptr< Analyzer::Expr > &next_result) const
 
virtual std::shared_ptr
< Analyzer::Expr
defaultResult () const
 

Detailed Description

Definition at line 211 of file ExpressionRewrite.cpp.

Constructor & Destructor Documentation

anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::ConstantFoldingVisitor ( )
inline

Member Function Documentation

template<typename T >
T anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::foldArithmetic ( SQLOps  optype,
t1,
t2 
) const
inlineprivate

Definition at line 251 of file ExpressionRewrite.cpp.

References kDIVIDE, kMINUS, kMULTIPLY, and kPLUS.

251  {
252  bool t2_is_zero = (t2 == (t2 - t2));
253  bool t2_is_negative = (t2 < (t2 - t2));
254  switch (optype) {
255  case kPLUS:
256  // The MIN limit for float and double is the smallest representable value,
257  // not the lowest negative value! Switching to C++11 lowest.
258  if ((t2_is_negative && t1 < std::numeric_limits<T>::lowest() - t2) ||
259  (!t2_is_negative && t1 > std::numeric_limits<T>::max() - t2)) {
260  num_overflows_++;
261  throw std::runtime_error("Plus overflow");
262  }
263  return t1 + t2;
264  case kMINUS:
265  if ((t2_is_negative && t1 > std::numeric_limits<T>::max() + t2) ||
266  (!t2_is_negative && t1 < std::numeric_limits<T>::lowest() + t2)) {
267  num_overflows_++;
268  throw std::runtime_error("Minus overflow");
269  }
270  return t1 - t2;
271  case kMULTIPLY: {
272  if (t2_is_zero) {
273  return t2;
274  }
275  auto ct1 = t1;
276  auto ct2 = t2;
277  // Need to keep t2's sign on the left
278  if (t2_is_negative) {
279  if (t1 == std::numeric_limits<T>::lowest() ||
280  t2 == std::numeric_limits<T>::lowest()) {
281  // negation could overflow - bail
282  num_overflows_++;
283  throw std::runtime_error("Mul neg overflow");
284  }
285  ct1 = -t1; // ct1 gets t2's negativity
286  ct2 = -t2; // ct2 is now positive
287  }
288  // Don't check overlow if we are folding FP mul by a fraction
289  bool ct2_is_fraction = (ct2 < (ct2 / ct2));
290  if (!ct2_is_fraction) {
291  if (ct1 > std::numeric_limits<T>::max() / ct2 ||
292  ct1 < std::numeric_limits<T>::lowest() / ct2) {
293  num_overflows_++;
294  throw std::runtime_error("Mul overflow");
295  }
296  }
297  return t1 * t2;
298  }
299  case kDIVIDE:
300  if (t2_is_zero) {
301  throw std::runtime_error("Will not fold division by zero");
302  }
303  return t1 / t2;
304  default:
305  break;
306  }
307  throw std::runtime_error("Unable to fold");
308  }
Definition: sqldefs.h:41
Definition: sqldefs.h:40
template<typename T >
bool anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::foldComparison ( SQLOps  optype,
t1,
t2 
) const
inlineprivate

Definition at line 213 of file ExpressionRewrite.cpp.

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

213  {
214  switch (optype) {
215  case kEQ:
216  return t1 == t2;
217  case kNE:
218  return t1 != t2;
219  case kLT:
220  return t1 < t2;
221  case kLE:
222  return t1 <= t2;
223  case kGT:
224  return t1 > t2;
225  case kGE:
226  return t1 >= t2;
227  default:
228  break;
229  }
230  throw std::runtime_error("Unable to fold");
231  return false;
232  }
Definition: sqldefs.h:35
Definition: sqldefs.h:36
Definition: sqldefs.h:30
Definition: sqldefs.h:34
Definition: sqldefs.h:32
Definition: sqldefs.h:33
template<typename T >
bool anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::foldLogic ( SQLOps  optype,
t1,
t2 
) const
inlineprivate

Definition at line 235 of file ExpressionRewrite.cpp.

References kAND, kNOT, and kOR.

235  {
236  switch (optype) {
237  case kAND:
238  return t1 && t2;
239  case kOR:
240  return t1 || t2;
241  case kNOT:
242  return !t1;
243  default:
244  break;
245  }
246  throw std::runtime_error("Unable to fold");
247  return false;
248  }
Definition: sqldefs.h:38
Definition: sqldefs.h:37
Definition: sqldefs.h:39
bool anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::foldOper ( SQLOps  optype,
SQLTypes  type,
Datum  lhs,
Datum  rhs,
Datum result,
SQLTypes result_type 
) const
inlineprivate

Definition at line 310 of file ExpressionRewrite.cpp.

References Datum::bigintval, Datum::boolval, CHECK(), Datum::doubleval, Datum::floatval, Datum::intval, IS_ARITHMETIC, IS_COMPARISON, IS_LOGIC, kBIGINT, kBOOLEAN, kDOUBLE, kFLOAT, kINT, kSMALLINT, kTINYINT, Datum::smallintval, Datum::tinyintval, and run_benchmark_import::type.

315  {
316  result_type = type;
317 
318  try {
319  switch (type) {
320  case kBOOLEAN:
321  if (IS_COMPARISON(optype)) {
322  result.boolval = foldComparison<bool>(optype, lhs.boolval, rhs.boolval);
323  result_type = kBOOLEAN;
324  return true;
325  }
326  if (IS_LOGIC(optype)) {
327  result.boolval = foldLogic<bool>(optype, lhs.boolval, rhs.boolval);
328  result_type = kBOOLEAN;
329  return true;
330  }
331  CHECK(!IS_ARITHMETIC(optype));
332  break;
333  case kTINYINT:
334  if (IS_COMPARISON(optype)) {
335  result.boolval =
336  foldComparison<int8_t>(optype, lhs.tinyintval, rhs.tinyintval);
337  result_type = kBOOLEAN;
338  return true;
339  }
340  if (IS_ARITHMETIC(optype)) {
341  result.tinyintval =
342  foldArithmetic<int8_t>(optype, lhs.tinyintval, rhs.tinyintval);
343  result_type = kTINYINT;
344  return true;
345  }
346  CHECK(!IS_LOGIC(optype));
347  break;
348  case kSMALLINT:
349  if (IS_COMPARISON(optype)) {
350  result.boolval =
351  foldComparison<int16_t>(optype, lhs.smallintval, rhs.smallintval);
352  result_type = kBOOLEAN;
353  return true;
354  }
355  if (IS_ARITHMETIC(optype)) {
356  result.smallintval =
357  foldArithmetic<int16_t>(optype, lhs.smallintval, rhs.smallintval);
358  result_type = kSMALLINT;
359  return true;
360  }
361  CHECK(!IS_LOGIC(optype));
362  break;
363  case kINT:
364  if (IS_COMPARISON(optype)) {
365  result.boolval = foldComparison<int32_t>(optype, lhs.intval, rhs.intval);
366  result_type = kBOOLEAN;
367  return true;
368  }
369  if (IS_ARITHMETIC(optype)) {
370  result.intval = foldArithmetic<int32_t>(optype, lhs.intval, rhs.intval);
371  result_type = kINT;
372  return true;
373  }
374  CHECK(!IS_LOGIC(optype));
375  break;
376  case kBIGINT:
377  if (IS_COMPARISON(optype)) {
378  result.boolval =
379  foldComparison<int64_t>(optype, lhs.bigintval, rhs.bigintval);
380  result_type = kBOOLEAN;
381  return true;
382  }
383  if (IS_ARITHMETIC(optype)) {
384  result.bigintval =
385  foldArithmetic<int64_t>(optype, lhs.bigintval, rhs.bigintval);
386  result_type = kBIGINT;
387  return true;
388  }
389  CHECK(!IS_LOGIC(optype));
390  break;
391  case kFLOAT:
392  if (IS_COMPARISON(optype)) {
393  result.boolval = foldComparison<float>(optype, lhs.floatval, rhs.floatval);
394  result_type = kBOOLEAN;
395  return true;
396  }
397  if (IS_ARITHMETIC(optype)) {
398  result.floatval = foldArithmetic<float>(optype, lhs.floatval, rhs.floatval);
399  result_type = kFLOAT;
400  return true;
401  }
402  CHECK(!IS_LOGIC(optype));
403  break;
404  case kDOUBLE:
405  if (IS_COMPARISON(optype)) {
406  result.boolval = foldComparison<double>(optype, lhs.doubleval, rhs.doubleval);
407  result_type = kBOOLEAN;
408  return true;
409  }
410  if (IS_ARITHMETIC(optype)) {
411  result.doubleval =
412  foldArithmetic<double>(optype, lhs.doubleval, rhs.doubleval);
413  result_type = kDOUBLE;
414  return true;
415  }
416  CHECK(!IS_LOGIC(optype));
417  break;
418  default:
419  break;
420  }
421  } catch (...) {
422  return false;
423  }
424  return false;
425  }
int8_t tinyintval
Definition: sqltypes.h:134
#define IS_LOGIC(X)
Definition: sqldefs.h:60
bool boolval
Definition: sqltypes.h:133
int32_t intval
Definition: sqltypes.h:136
float floatval
Definition: sqltypes.h:138
CHECK(cgen_state)
int64_t bigintval
Definition: sqltypes.h:137
int16_t smallintval
Definition: sqltypes.h:135
#define IS_ARITHMETIC(X)
Definition: sqldefs.h:61
Definition: sqltypes.h:46
#define IS_COMPARISON(X)
Definition: sqldefs.h:57
double doubleval
Definition: sqltypes.h:139

+ Here is the call graph for this function:

int32_t anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::get_num_overflows ( )
inline
void anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::reset_num_overflows ( )
inline
std::shared_ptr<Analyzer::Expr> anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::visitBinOper ( const Analyzer::BinOper bin_oper) const
inlineoverrideprivatevirtual

Reimplemented from DeepCopyVisitor.

Definition at line 506 of file ExpressionRewrite.cpp.

References Datum::boolval, decimal_to_int_type(), Analyzer::Expr::get_contains_agg(), Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_own_left_operand(), Analyzer::BinOper::get_own_right_operand(), Analyzer::BinOper::get_qualifier(), Analyzer::Expr::get_type_info(), IS_COMPARISON, SQLTypeInfo::is_decimal(), kAND, kBOOLEAN, kDIVIDE, kDOUBLE, kEQ, kFLOAT, kGE, kGT, kLE, kLT, kMINUS, kMULTIPLY, kNE, kOR, and kPLUS.

507  {
508  const auto optype = bin_oper->get_optype();
509  auto ti = bin_oper->get_type_info();
510  auto left_operand = bin_oper->get_own_left_operand();
511  auto right_operand = bin_oper->get_own_right_operand();
512 
513  // Check if bin_oper result is cast to a larger int or fp type
514  if (casts_.find(bin_oper) != casts_.end()) {
515  const auto cast_ti = casts_[bin_oper];
516  const auto& lhs_ti = bin_oper->get_left_operand()->get_type_info();
517  // Propagate cast down to the operands for folding
518  if ((cast_ti.is_integer() || cast_ti.is_fp()) && lhs_ti.is_integer() &&
519  cast_ti.get_size() > lhs_ti.get_size() &&
520  (optype == kMINUS || optype == kPLUS || optype == kMULTIPLY)) {
521  // Before folding, cast the operands to the bigger type to avoid overflows.
522  // Currently upcasting smaller integer types to larger integers or double.
523  left_operand = left_operand->deep_copy()->add_cast(cast_ti);
524  right_operand = right_operand->deep_copy()->add_cast(cast_ti);
525  ti = cast_ti;
526  }
527  }
528 
529  const auto lhs = visit(left_operand.get());
530  const auto rhs = visit(right_operand.get());
531 
532  auto const_lhs = std::dynamic_pointer_cast<Analyzer::Constant>(lhs);
533  auto const_rhs = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
534  const auto& lhs_ti = lhs->get_type_info();
535  const auto& rhs_ti = rhs->get_type_info();
536  auto lhs_type = lhs_ti.is_decimal() ? decimal_to_int_type(lhs_ti) : lhs_ti.get_type();
537  auto rhs_type = rhs_ti.is_decimal() ? decimal_to_int_type(rhs_ti) : rhs_ti.get_type();
538 
539  if (const_lhs && const_rhs && lhs_type == rhs_type) {
540  auto lhs_datum = const_lhs->get_constval();
541  auto rhs_datum = const_rhs->get_constval();
542  Datum result_datum = {};
543  SQLTypes result_type;
544  if (foldOper(optype, lhs_type, lhs_datum, rhs_datum, result_datum, result_type)) {
545  // Fold all ops that don't take in decimal operands, and also decimal comparisons
546  if (!lhs_ti.is_decimal() || IS_COMPARISON(optype)) {
547  return makeExpr<Analyzer::Constant>(result_type, false, result_datum);
548  }
549  // Decimal arithmetic has been done as kBIGINT. Selectively fold some decimal ops,
550  // using result_datum and BinOper expr typeinfo which was adjusted for these ops.
551  if (optype == kMINUS || optype == kPLUS || optype == kMULTIPLY) {
552  return makeExpr<Analyzer::Constant>(ti, false, result_datum);
553  }
554  }
555  }
556 
557  if (optype == kAND && lhs_type == rhs_type && lhs_type == kBOOLEAN) {
558  if (const_rhs && !const_rhs->get_is_null()) {
559  auto rhs_datum = const_rhs->get_constval();
560  if (rhs_datum.boolval == false) {
561  Datum d;
562  d.boolval = false;
563  // lhs && false --> false
564  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
565  }
566  // lhs && true --> lhs
567  return lhs;
568  }
569  if (const_lhs && !const_lhs->get_is_null()) {
570  auto lhs_datum = const_lhs->get_constval();
571  if (lhs_datum.boolval == false) {
572  Datum d;
573  d.boolval = false;
574  // false && rhs --> false
575  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
576  }
577  // true && rhs --> rhs
578  return rhs;
579  }
580  }
581  if (optype == kOR && lhs_type == rhs_type && lhs_type == kBOOLEAN) {
582  if (const_rhs && !const_rhs->get_is_null()) {
583  auto rhs_datum = const_rhs->get_constval();
584  if (rhs_datum.boolval == true) {
585  Datum d;
586  d.boolval = true;
587  // lhs || true --> true
588  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
589  }
590  // lhs || false --> lhs
591  return lhs;
592  }
593  if (const_lhs && !const_lhs->get_is_null()) {
594  auto lhs_datum = const_lhs->get_constval();
595  if (lhs_datum.boolval == true) {
596  Datum d;
597  d.boolval = true;
598  // true || rhs --> true
599  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
600  }
601  // false || rhs --> rhs
602  return rhs;
603  }
604  }
605  if (*lhs == *rhs) {
606  // Tautologies: v=v; v<=v; v>=v
607  if (optype == kEQ || optype == kLE || optype == kGE) {
608  Datum d;
609  d.boolval = true;
610  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
611  }
612  // Contradictions: v!=v; v<v; v>v
613  if (optype == kNE || optype == kLT || optype == kGT) {
614  Datum d;
615  d.boolval = false;
616  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
617  }
618  // v-v
619  if (optype == kMINUS) {
620  Datum d = {};
621  return makeExpr<Analyzer::Constant>(lhs_type, false, d);
622  }
623  }
624  // Convert fp division by a constant to multiplication by 1/constant
625  if (optype == kDIVIDE && const_rhs && rhs_ti.is_fp()) {
626  auto rhs_datum = const_rhs->get_constval();
627  std::shared_ptr<Analyzer::Expr> recip_rhs = nullptr;
628  if (rhs_ti.get_type() == kFLOAT) {
629  if (rhs_datum.floatval == 1.0) {
630  return lhs;
631  }
632  auto f = std::fabs(rhs_datum.floatval);
633  if (f > 1.0 || (f != 0.0 && 1.0 < f * std::numeric_limits<float>::max())) {
634  rhs_datum.floatval = 1.0 / rhs_datum.floatval;
635  recip_rhs = makeExpr<Analyzer::Constant>(rhs_type, false, rhs_datum);
636  }
637  } else if (rhs_ti.get_type() == kDOUBLE) {
638  if (rhs_datum.doubleval == 1.0) {
639  return lhs;
640  }
641  auto d = std::fabs(rhs_datum.doubleval);
642  if (d > 1.0 || (d != 0.0 && 1.0 < d * std::numeric_limits<double>::max())) {
643  rhs_datum.doubleval = 1.0 / rhs_datum.doubleval;
644  recip_rhs = makeExpr<Analyzer::Constant>(rhs_type, false, rhs_datum);
645  }
646  }
647  if (recip_rhs) {
648  return makeExpr<Analyzer::BinOper>(ti,
649  bin_oper->get_contains_agg(),
650  kMULTIPLY,
651  bin_oper->get_qualifier(),
652  lhs,
653  recip_rhs);
654  }
655  }
656 
657  return makeExpr<Analyzer::BinOper>(ti,
658  bin_oper->get_contains_agg(),
659  bin_oper->get_optype(),
660  bin_oper->get_qualifier(),
661  lhs,
662  rhs);
663  }
SQLTypes
Definition: sqltypes.h:39
bool boolval
Definition: sqltypes.h:133
Definition: sqldefs.h:35
Definition: sqldefs.h:36
Definition: sqldefs.h:38
bool get_contains_agg() const
Definition: Analyzer.h:81
Definition: sqldefs.h:30
Definition: sqldefs.h:41
std::shared_ptr< Analyzer::Expr > visit(const Analyzer::Expr *expr) const
SQLOps get_optype() const
Definition: Analyzer.h:440
Definition: sqldefs.h:37
bool foldOper(SQLOps optype, SQLTypes type, Datum lhs, Datum rhs, Datum &result, SQLTypes &result_type) const
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:311
Definition: sqldefs.h:34
Definition: sqldefs.h:40
Definition: sqldefs.h:32
std::unordered_map< const Analyzer::Expr *, const SQLTypeInfo > casts_
Definition: sqldefs.h:33
const Expr * get_left_operand() const
Definition: Analyzer.h:443
const std::shared_ptr< Analyzer::Expr > get_own_right_operand() const
Definition: Analyzer.h:448
bool is_decimal() const
Definition: sqltypes.h:418
const std::shared_ptr< Analyzer::Expr > get_own_left_operand() const
Definition: Analyzer.h:445
#define IS_COMPARISON(X)
Definition: sqldefs.h:57
SQLQualifier get_qualifier() const
Definition: Analyzer.h:442

+ Here is the call graph for this function:

std::shared_ptr<Analyzer::Expr> anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::visitLower ( const Analyzer::LowerExpr lower_expr) const
inlineoverrideprivatevirtual

Reimplemented from DeepCopyVisitor.

Definition at line 665 of file ExpressionRewrite.cpp.

References Parser::StringLiteral::analyzeValue(), Analyzer::LowerExpr::get_arg(), Analyzer::LowerExpr::get_own_arg(), and to_lower().

666  {
667  const auto constant_arg_expr =
668  dynamic_cast<const Analyzer::Constant*>(lower_expr->get_arg());
669  if (constant_arg_expr) {
671  boost::locale::to_lower(*constant_arg_expr->get_constval().stringval));
672  }
673  return makeExpr<Analyzer::LowerExpr>(lower_expr->get_own_arg());
674  }
std::string to_lower(const std::string &str)
const std::shared_ptr< Analyzer::Expr > get_own_arg() const
Definition: Analyzer.h:798
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &)
Definition: ParserNode.cpp:102
const Expr * get_arg() const
Definition: Analyzer.h:796

+ Here is the call graph for this function:

std::shared_ptr<Analyzer::Expr> anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::visitUOper ( const Analyzer::UOper uoper) const
inlineoverrideprivatevirtual

Reimplemented from DeepCopyVisitor.

Definition at line 427 of file ExpressionRewrite.cpp.

References CHECK_EQ, decimal_to_int_type(), Analyzer::Constant::get_constval(), Analyzer::Expr::get_contains_agg(), Analyzer::UOper::get_operand(), Analyzer::UOper::get_optype(), Analyzer::Expr::get_type_info(), kBOOLEAN, kCAST, kEQ, kMINUS, kNOT, and kUMINUS.

428  {
429  const auto unvisited_operand = uoper->get_operand();
430  const auto optype = uoper->get_optype();
431  const auto& ti = uoper->get_type_info();
432  if (optype == kCAST) {
433  // Cache the cast type so it could be used in operand rewriting/folding
434  casts_.insert({unvisited_operand, ti});
435  }
436  const auto operand = visit(unvisited_operand);
437  const auto& operand_ti = operand->get_type_info();
438  const auto operand_type =
439  operand_ti.is_decimal() ? decimal_to_int_type(operand_ti) : operand_ti.get_type();
440  const auto const_operand =
441  std::dynamic_pointer_cast<const Analyzer::Constant>(operand);
442 
443  if (const_operand) {
444  const auto operand_datum = const_operand->get_constval();
445  Datum zero_datum = {};
446  Datum result_datum = {};
447  SQLTypes result_type;
448  switch (optype) {
449  case kNOT: {
450  if (foldOper(kEQ,
451  operand_type,
452  zero_datum,
453  operand_datum,
454  result_datum,
455  result_type)) {
456  CHECK_EQ(result_type, kBOOLEAN);
457  return makeExpr<Analyzer::Constant>(result_type, false, result_datum);
458  }
459  break;
460  }
461  case kUMINUS: {
462  if (foldOper(kMINUS,
463  operand_type,
464  zero_datum,
465  operand_datum,
466  result_datum,
467  result_type)) {
468  if (!operand_ti.is_decimal()) {
469  return makeExpr<Analyzer::Constant>(result_type, false, result_datum);
470  }
471  return makeExpr<Analyzer::Constant>(ti, false, result_datum);
472  }
473  break;
474  }
475  case kCAST: {
476  // Trying to fold number to number casts only
477  if (!ti.is_number() || !operand_ti.is_number()) {
478  break;
479  }
480  // Disallowing folding of FP to DECIMAL casts for now:
481  // allowing them would make this test pass:
482  // update dectest set d=cast( 1234.0 as float );
483  // which is expected to throw in Update.ImplicitCastToNumericTypes
484  // due to cast codegen currently not supporting these casts
485  if (ti.is_decimal() && operand_ti.is_fp()) {
486  break;
487  }
488  auto operand_copy = const_operand->deep_copy();
489  auto cast_operand = operand_copy->add_cast(ti);
490  auto const_cast_operand =
491  std::dynamic_pointer_cast<const Analyzer::Constant>(cast_operand);
492  if (const_cast_operand) {
493  auto const_cast_datum = const_cast_operand->get_constval();
494  return makeExpr<Analyzer::Constant>(ti, false, const_cast_datum);
495  }
496  }
497  default:
498  break;
499  }
500  }
501 
502  return makeExpr<Analyzer::UOper>(
503  uoper->get_type_info(), uoper->get_contains_agg(), optype, operand);
504  }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
SQLTypes
Definition: sqltypes.h:39
bool get_contains_agg() const
Definition: Analyzer.h:81
Definition: sqldefs.h:49
Definition: sqldefs.h:30
std::shared_ptr< Analyzer::Expr > visit(const Analyzer::Expr *expr) const
bool foldOper(SQLOps optype, SQLTypes type, Datum lhs, Datum rhs, Datum &result, SQLTypes &result_type) const
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:311
Definition: sqldefs.h:40
const Expr * get_operand() const
Definition: Analyzer.h:372
Datum get_constval() const
Definition: Analyzer.h:336
std::unordered_map< const Analyzer::Expr *, const SQLTypeInfo > casts_
Definition: sqldefs.h:39
SQLOps get_optype() const
Definition: Analyzer.h:371

+ Here is the call graph for this function:

Member Data Documentation

std::unordered_map<const Analyzer::Expr*, const SQLTypeInfo> anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::casts_
mutableprotected

Definition at line 677 of file ExpressionRewrite.cpp.

int32_t anonymous_namespace{ExpressionRewrite.cpp}::ConstantFoldingVisitor::num_overflows_
mutableprotected

Definition at line 678 of file ExpressionRewrite.cpp.


The documentation for this class was generated from the following file: