OmniSciDB  6686921089
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 visitGeoExpr (const Analyzer::GeoExpr *geo_expr) 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 visitWidthBucket (const Analyzer::WidthBucketExpr *width_bucket_expr) 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 213 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 253 of file ExpressionRewrite.cpp.

References kDIVIDE, kMINUS, kMULTIPLY, and kPLUS.

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

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

215  {
216  switch (optype) {
217  case kEQ:
218  return t1 == t2;
219  case kNE:
220  return t1 != t2;
221  case kLT:
222  return t1 < t2;
223  case kLE:
224  return t1 <= t2;
225  case kGT:
226  return t1 > t2;
227  case kGE:
228  return t1 >= t2;
229  default:
230  break;
231  }
232  throw std::runtime_error("Unable to fold");
233  return false;
234  }
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 237 of file ExpressionRewrite.cpp.

References kAND, kNOT, and kOR.

237  {
238  switch (optype) {
239  case kAND:
240  return t1 && t2;
241  case kOR:
242  return t1 || t2;
243  case kNOT:
244  return !t1;
245  default:
246  break;
247  }
248  throw std::runtime_error("Unable to fold");
249  return false;
250  }
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 312 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.

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

References Datum::boolval, decimal_to_int_type(), f, 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.

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

+ 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 668 of file ExpressionRewrite.cpp.

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

669  {
670  const auto constant_arg_expr =
671  dynamic_cast<const Analyzer::Constant*>(lower_expr->get_arg());
672  if (constant_arg_expr) {
674  boost::locale::to_lower(*constant_arg_expr->get_constval().stringval));
675  }
676  return makeExpr<Analyzer::LowerExpr>(lower_expr->get_own_arg());
677  }
std::string to_lower(const std::string &str)
const std::shared_ptr< Analyzer::Expr > get_own_arg() const
Definition: Analyzer.h:843
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &)
Definition: ParserNode.cpp:125
const Expr * get_arg() const
Definition: Analyzer.h:841

+ 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 429 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.

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

+ 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 680 of file ExpressionRewrite.cpp.

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

Definition at line 681 of file ExpressionRewrite.cpp.


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