18 #include "../Analyzer/Analyzer.h"
19 #include "../Parser/ParserNode.h"
20 #include "../Shared/sqldefs.h"
28 #include <boost/locale/conversion.hpp>
29 #include <unordered_set>
41 if (!dynamic_cast<const Analyzer::Constant*>(rhs_no_cast)) {
45 const auto& arg_ti = arg->get_type_info();
46 auto rhs = rhs_no_cast->deep_copy()->add_cast(arg_ti);
47 return makeExpr<Analyzer::InValues>(
48 arg, std::list<std::shared_ptr<Analyzer::Expr>>{rhs});
136 const std::shared_ptr<Analyzer::InValues>& lhs,
137 const std::shared_ptr<Analyzer::InValues>& rhs)
const override {
141 if (!(*lhs->get_arg() == *rhs->get_arg())) {
144 auto union_values = lhs->get_value_list();
145 const auto& rhs_values = rhs->get_value_list();
146 union_values.insert(union_values.end(), rhs_values.begin(), rhs_values.end());
147 return makeExpr<Analyzer::InValues>(lhs->get_own_arg(), union_values);
157 auto rewritten = simple_visitor.
visit(bin_oper);
164 auto rewritten_lhs = visit(lhs.get());
165 auto rewritten_rhs = visit(rhs.get());
166 return makeExpr<Analyzer::BinOper>(bin_oper->
get_type_info(),
170 rewritten_lhs ? rewritten_lhs : lhs,
171 rewritten_rhs ? rewritten_rhs : rhs);
180 std::vector<std::shared_ptr<Analyzer::Expr>> args_copy;
182 auto const element_expr_ptr = visit(array_expr->
getElement(i));
183 auto const& element_expr_type_info = element_expr_ptr->get_type_info();
185 if (!element_expr_type_info.is_string() ||
187 args_copy.push_back(element_expr_ptr);
189 auto transient_dict_type_info = element_expr_type_info;
193 transient_dict_type_info.set_fixed_size();
194 args_copy.push_back(element_expr_ptr->add_cast(transient_dict_type_info));
199 return makeExpr<Analyzer::ArrayExpr>(
205 template <
typename T>
223 throw std::runtime_error(
"Unable to fold");
227 template <
typename T>
239 throw std::runtime_error(
"Unable to fold");
243 template <
typename T>
245 bool t2_is_zero = (t2 == (t2 - t2));
246 bool t2_is_negative = (t2 < (t2 - t2));
251 if ((t2_is_negative && t1 < std::numeric_limits<T>::lowest() - t2) ||
252 (!t2_is_negative && t1 > std::numeric_limits<T>::max() - t2)) {
254 throw std::runtime_error(
"Plus overflow");
258 if ((t2_is_negative && t1 > std::numeric_limits<T>::max() + t2) ||
259 (!t2_is_negative && t1 < std::numeric_limits<T>::lowest() + t2)) {
261 throw std::runtime_error(
"Minus overflow");
271 if (t2_is_negative) {
272 if (t1 == std::numeric_limits<T>::lowest() ||
273 t2 == std::numeric_limits<T>::lowest()) {
276 throw std::runtime_error(
"Mul neg overflow");
282 bool ct2_is_fraction = (ct2 < (ct2 / ct2));
283 if (!ct2_is_fraction) {
284 if (ct1 > std::numeric_limits<T>::max() / ct2 ||
285 ct1 < std::numeric_limits<T>::lowest() / ct2) {
287 throw std::runtime_error(
"Mul overflow");
294 throw std::runtime_error(
"Will not fold division by zero");
300 throw std::runtime_error(
"Unable to fold");
422 const auto unvisited_operand = uoper->
get_operand();
425 if (optype ==
kCAST) {
427 casts_.insert({unvisited_operand, ti});
429 const auto operand = visit(unvisited_operand);
430 const auto& operand_ti = operand->get_type_info();
431 const auto operand_type =
433 const auto const_operand =
437 const auto operand_datum = const_operand->
get_constval();
438 Datum zero_datum = {};
439 Datum result_datum = {};
450 return makeExpr<Analyzer::Constant>(result_type,
false, result_datum);
461 if (!operand_ti.is_decimal()) {
462 return makeExpr<Analyzer::Constant>(result_type,
false, result_datum);
464 return makeExpr<Analyzer::Constant>(ti,
false, result_datum);
470 if (!ti.is_number() || !operand_ti.is_number()) {
478 if (ti.is_decimal() && operand_ti.is_fp()) {
481 auto operand_copy = const_operand->deep_copy();
482 auto cast_operand = operand_copy->add_cast(ti);
483 auto const_cast_operand =
485 if (const_cast_operand) {
486 auto const_cast_datum = const_cast_operand->
get_constval();
487 return makeExpr<Analyzer::Constant>(ti,
false, const_cast_datum);
495 return makeExpr<Analyzer::UOper>(
507 if (casts_.find(bin_oper) != casts_.end()) {
508 const auto cast_ti = casts_[bin_oper];
511 if ((cast_ti.is_integer() || cast_ti.is_fp()) && lhs_ti.is_integer() &&
512 cast_ti.get_size() > lhs_ti.get_size() &&
516 left_operand = left_operand->deep_copy()->add_cast(cast_ti);
517 right_operand = right_operand->deep_copy()->add_cast(cast_ti);
522 const auto lhs = visit(left_operand.get());
523 const auto rhs = visit(right_operand.get());
528 const auto& rhs_ti = rhs->get_type_info();
532 if (const_lhs && const_rhs && lhs_type == rhs_type) {
533 auto lhs_datum = const_lhs->get_constval();
534 auto rhs_datum = const_rhs->get_constval();
535 Datum result_datum = {};
537 if (foldOper(optype, lhs_type, lhs_datum, rhs_datum, result_datum, result_type)) {
540 return makeExpr<Analyzer::Constant>(result_type,
false, result_datum);
545 return makeExpr<Analyzer::Constant>(ti,
false, result_datum);
550 if (optype ==
kAND && lhs_type == rhs_type && lhs_type ==
kBOOLEAN) {
551 if (const_rhs && !const_rhs->get_is_null()) {
552 auto rhs_datum = const_rhs->get_constval();
553 if (rhs_datum.boolval ==
false) {
557 return makeExpr<Analyzer::Constant>(
kBOOLEAN,
false, d);
562 if (const_lhs && !const_lhs->get_is_null()) {
563 auto lhs_datum = const_lhs->get_constval();
564 if (lhs_datum.boolval ==
false) {
568 return makeExpr<Analyzer::Constant>(
kBOOLEAN,
false, d);
574 if (optype ==
kOR && lhs_type == rhs_type && lhs_type ==
kBOOLEAN) {
575 if (const_rhs && !const_rhs->get_is_null()) {
576 auto rhs_datum = const_rhs->get_constval();
577 if (rhs_datum.boolval ==
true) {
581 return makeExpr<Analyzer::Constant>(
kBOOLEAN,
false, d);
586 if (const_lhs && !const_lhs->get_is_null()) {
587 auto lhs_datum = const_lhs->get_constval();
588 if (lhs_datum.boolval ==
true) {
592 return makeExpr<Analyzer::Constant>(
kBOOLEAN,
false, d);
600 if (optype ==
kEQ || optype ==
kLE || optype ==
kGE) {
603 return makeExpr<Analyzer::Constant>(
kBOOLEAN,
false, d);
606 if (optype ==
kNE || optype ==
kLT || optype ==
kGT) {
609 return makeExpr<Analyzer::Constant>(
kBOOLEAN,
false, d);
614 return makeExpr<Analyzer::Constant>(lhs_type,
false, d);
618 if (optype ==
kDIVIDE && const_rhs && rhs_ti.is_fp()) {
619 auto rhs_datum = const_rhs->get_constval();
620 std::shared_ptr<Analyzer::Expr> recip_rhs =
nullptr;
621 if (rhs_ti.get_type() ==
kFLOAT) {
622 if (rhs_datum.floatval == 1.0) {
625 auto f = std::fabs(rhs_datum.floatval);
626 if (f > 1.0 || (f != 0.0 && 1.0 < f * std::numeric_limits<float>::max())) {
627 rhs_datum.floatval = 1.0 / rhs_datum.floatval;
628 recip_rhs = makeExpr<Analyzer::Constant>(rhs_type,
false, rhs_datum);
630 }
else if (rhs_ti.get_type() ==
kDOUBLE) {
631 if (rhs_datum.doubleval == 1.0) {
634 auto d = std::fabs(rhs_datum.doubleval);
635 if (d > 1.0 || (d != 0.0 && 1.0 < d * std::numeric_limits<double>::max())) {
636 rhs_datum.doubleval = 1.0 / rhs_datum.doubleval;
637 recip_rhs = makeExpr<Analyzer::Constant>(rhs_type,
false, rhs_datum);
641 return makeExpr<Analyzer::BinOper>(ti,
650 return makeExpr<Analyzer::BinOper>(ti,
660 const auto constant_arg_expr =
662 if (constant_arg_expr) {
664 boost::locale::to_lower(*constant_arg_expr->get_constval().stringval));
666 return makeExpr<Analyzer::LowerExpr>(lower_expr->
get_own_arg());
670 mutable std::unordered_map<const Analyzer::Expr*, const SQLTypeInfo>
casts_;
681 if (!with_likelihood) {
684 return with_likelihood->get_arg();
690 return ArrayElementStringLiteralEncodingVisitor().visit(expr);
706 RecursiveOrToInVisitor visitor;
707 auto rewritten_expr = visitor.visit(expr_no_likelihood);
708 const auto expr_with_likelihood =
710 if (expr_with_likelihood) {
712 return std::make_shared<Analyzer::LikelihoodExpr>(
713 rewritten_expr, expr_with_likelihood->get_likelihood());
715 return rewritten_expr;
721 "ST_Contains_MultiPolygon_Point",
722 "ST_Contains_Polygon_Point"};
727 const std::shared_ptr<Analyzer::Expr> expr) {
734 CHECK_GE(func_oper->getArity(), size_t(3));
737 auto lhs = func_oper->getOwnArg(2);
738 auto rewritten_lhs = deep_copy_visitor.
visit(lhs.get());
739 CHECK(rewritten_lhs);
740 const auto& lhs_ti = rewritten_lhs->get_type_info();
741 if (!lhs_ti.is_geometry()) {
749 LOG(
WARNING) <<
"Failed to rewrite " << func_oper->getName()
750 <<
" to overlaps conjunction. LHS input type is not a geospatial "
751 "type. Are both inputs geospatial columns?";
757 auto rhs = func_oper->getOwnArg(1);
758 auto rewritten_rhs = deep_copy_visitor.visit(rhs.get());
759 CHECK(rewritten_rhs);
761 auto overlaps_oper = makeExpr<Analyzer::BinOper>(
781 for (
const auto& join_condition : join_quals) {
782 for (
const auto& qual : join_condition.quals) {
786 qual_bin_oper->get_right_operand());
795 const auto lhs = func_oper->
getArg(2);
796 const auto rhs = func_oper->
getArg(1);
798 if (*lhs == *qual_pair.first && *rhs == *qual_pair.second) {
813 const std::list<std::shared_ptr<Analyzer::Expr>>& quals,
819 if (join_quals.empty()) {
823 std::list<std::shared_ptr<Analyzer::Expr>> quals_to_return;
826 for (
const auto& qual : quals) {
827 if (!visitor.
visit(qual.get())) {
829 quals_to_return.push_back(qual);
833 return quals_to_return;
841 ConstantFoldingVisitor visitor;
842 auto rewritten_expr = visitor.visit(expr_no_likelihood);
843 if (visitor.get_num_overflows() > 0 && rewritten_expr->get_type_info().is_integer() &&
844 rewritten_expr->get_type_info().get_type() !=
kBIGINT) {
845 auto rewritten_expr_const =
847 if (!rewritten_expr_const) {
851 auto bigint_expr_no_likelihood = expr_no_likelihood->deep_copy()->add_cast(ti);
852 auto rewritten_expr_take2 = visitor.visit(bigint_expr_no_likelihood.get());
853 auto rewritten_expr_take2_const =
855 if (rewritten_expr_take2_const) {
857 rewritten_expr = rewritten_expr_take2_const;
862 if (expr_with_likelihood) {
864 return std::make_shared<Analyzer::LikelihoodExpr>(
865 rewritten_expr, expr_with_likelihood->get_likelihood());
867 return rewritten_expr;
Analyzer::ExpressionPtr rewrite_array_elements(Analyzer::Expr const *expr)
std::shared_ptr< Analyzer::InValues > visitLikeExpr(const Analyzer::LikeExpr *) const override
std::shared_ptr< Analyzer::InValues > visitDateaddExpr(const Analyzer::DateaddExpr *) const override
const std::shared_ptr< Analyzer::Expr > get_own_arg() const
std::shared_ptr< Analyzer::WindowFunction > rewrite_avg_window(const Analyzer::Expr *expr)
int32_t getExprIndex() const
bool g_strip_join_covered_quals
std::shared_ptr< Analyzer::InValues > visitKeyForString(const Analyzer::KeyForStringExpr *) const override
std::shared_ptr< Analyzer::WindowFunction > rewrite_sum_window(const Analyzer::Expr *expr)
std::shared_ptr< Analyzer::InValues > visitBinOper(const Analyzer::BinOper *bin_oper) const override
const Expr * get_right_operand() const
bool get_contains_agg() const
std::shared_ptr< Analyzer::Expr > ExpressionPtr
const Analyzer::Expr * extract_cast_arg(const Analyzer::Expr *expr)
std::vector< JoinCondition > JoinQualsPerNestingLevel
T visit(const Analyzer::Expr *expr) const
Analyzer::ExpressionPtr rewrite_expr(const Analyzer::Expr *expr)
static const std::unordered_set< std::string > overlaps_supported_functions
std::shared_ptr< Analyzer::InValues > aggregateResult(const std::shared_ptr< Analyzer::InValues > &lhs, const std::shared_ptr< Analyzer::InValues > &rhs) const override
std::list< std::shared_ptr< Analyzer::Expr > > strip_join_covered_filter_quals(const std::list< std::shared_ptr< Analyzer::Expr >> &quals, const JoinQualsPerNestingLevel &join_quals)
std::shared_ptr< Analyzer::InValues > visitUOper(const Analyzer::UOper *uoper) const override
std::shared_ptr< Analyzer::Expr > visitBinOper(const Analyzer::BinOper *bin_oper) const override
std::shared_ptr< Analyzer::Expr > RetType
std::shared_ptr< Analyzer::InValues > visitCharLength(const Analyzer::CharLengthExpr *) const override
std::shared_ptr< Analyzer::InValues > visitInIntegerSet(const Analyzer::InIntegerSet *) const override
SQLOps get_optype() const
std::shared_ptr< Analyzer::Expr > visitUOper(const Analyzer::UOper *uoper) const override
std::shared_ptr< Analyzer::InValues > visitRegexpExpr(const Analyzer::RegexpExpr *) const override
std::shared_ptr< Analyzer::InValues > visitAggExpr(const Analyzer::AggExpr *) const override
bool visitFunctionOper(const Analyzer::FunctionOper *func_oper) const override
bool foldOper(SQLOps optype, SQLTypes type, Datum lhs, Datum rhs, Datum &result, SQLTypes &result_type) const
bool defaultResult() const override
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &)
boost::optional< OverlapsJoinConjunction > rewrite_overlaps_conjunction(const std::shared_ptr< Analyzer::Expr > expr)
RetType visitArrayOper(const Analyzer::ArrayExpr *array_expr) const override
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
const SQLTypeInfo & get_type_info() const
std::shared_ptr< Analyzer::Expr > visitBinOper(const Analyzer::BinOper *bin_oper) const override
size_t getElementCount() const
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
bool foldLogic(SQLOps optype, T t1, T t2) const
std::vector< std::pair< const Analyzer::Expr *, const Analyzer::Expr * > > join_qual_pairs
#define TRANSIENT_DICT_ID
bool isLocalAlloc() const
const Analyzer::Expr * getArg(const size_t i) const
const Expr * get_operand() const
Datum get_constval() const
Expression class for the LOWER (lowercase) string function. The "arg" constructor parameter must be a...
std::unordered_map< const Analyzer::Expr *, const SQLTypeInfo > casts_
std::shared_ptr< Analyzer::InValues > visitDatediffExpr(const Analyzer::DatediffExpr *) const override
std::shared_ptr< Analyzer::InValues > visitLikelihood(const Analyzer::LikelihoodExpr *) const override
std::shared_ptr< Analyzer::Expr > visitLower(const Analyzer::LowerExpr *lower_expr) const override
std::shared_ptr< Analyzer::InValues > visitInValues(const Analyzer::InValues *) const override
T foldArithmetic(SQLOps optype, T t1, T t2) const
int32_t get_num_overflows()
const Expr * get_left_operand() const
std::shared_ptr< Analyzer::InValues > visitCaseExpr(const Analyzer::CaseExpr *) const override
JoinCoveredQualVisitor(const JoinQualsPerNestingLevel &join_quals)
const std::shared_ptr< Analyzer::Expr > get_own_right_operand() const
std::string getName() const
bool foldComparison(SQLOps optype, T t1, T t2) const
std::shared_ptr< Analyzer::InValues > visitDatetruncExpr(const Analyzer::DatetruncExpr *) const override
const std::shared_ptr< Analyzer::Expr > get_own_left_operand() const
SQLOps get_optype() const
const Expr * get_arg() const
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
std::shared_ptr< Analyzer::InValues > visitExtractExpr(const Analyzer::ExtractExpr *) const override
const Analyzer::Expr * getElement(const size_t i) const
SQLQualifier get_qualifier() const
const Analyzer::Expr * strip_likelihood(const Analyzer::Expr *expr)
void reset_num_overflows()
std::shared_ptr< Analyzer::InValues > visitCardinality(const Analyzer::CardinalityExpr *) const override