OmniSciDB  c1a53651b2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExpressionRewrite.h File Reference
#include <llvm/IR/Value.h>
#include <boost/optional.hpp>
#include <list>
#include <memory>
#include <vector>
#include "Analyzer/Analyzer.h"
#include "RelAlgExecutionUnit.h"
+ Include dependency graph for ExpressionRewrite.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  OverlapsJoinConjunction
 
struct  OverlapsJoinSupportedFunction
 

Namespaces

 Analyzer
 

Enumerations

enum  OverlapsJoinRewriteType { OverlapsJoinRewriteType::OVERLAPS_JOIN, OverlapsJoinRewriteType::RANGE_JOIN, OverlapsJoinRewriteType::UNKNOWN }
 

Functions

Analyzer::ExpressionPtr rewrite_expr (const Analyzer::Expr *)
 
Analyzer::ExpressionPtr rewrite_array_elements (const Analyzer::Expr *)
 
boost::optional
< OverlapsJoinConjunction
rewrite_overlaps_conjunction (const std::shared_ptr< Analyzer::Expr > expr, const std::vector< InputDescriptor > &input_table_info, const OverlapsJoinRewriteType rewrite_type, const Executor *executor)
 
boost::optional
< OverlapsJoinConjunction
convert_to_range_join_oper (const std::shared_ptr< Analyzer::Expr > expr, const Analyzer::BinOper *range_join_expr, const Analyzer::GeoOperator *lhs, const Analyzer::Constant *rhs)
 
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::Exprfold_expr (const Analyzer::Expr *)
 
bool self_join_not_covered_by_left_deep_tree (const Analyzer::ColumnVar *lhs, const Analyzer::ColumnVar *rhs, const int max_rte_covered)
 
const int get_max_rte_scan_table (std::unordered_map< int, llvm::Value * > &scan_idx_to_hash_pos)
 

Enumeration Type Documentation

Function Documentation

boost::optional<OverlapsJoinConjunction> convert_to_range_join_oper ( const std::shared_ptr< Analyzer::Expr expr,
const Analyzer::BinOper range_join_expr,
const Analyzer::GeoOperator lhs,
const Analyzer::Constant rhs 
)

Referenced by rewrite_overlaps_conjunction().

+ Here is the caller graph for this function:

std::shared_ptr<Analyzer::Expr> fold_expr ( const Analyzer::Expr )

Definition at line 1175 of file ExpressionRewrite.cpp.

References kBIGINT, and anonymous_namespace{ExpressionRewrite.cpp}::strip_likelihood().

Referenced by RelAlgExecutor::createFilterWorkUnit(), RelAlgExecutor::makeJoinQuals(), anonymous_namespace{RelAlgExecutor.cpp}::set_transient_dict_maybe(), anonymous_namespace{RelAlgExecutor.cpp}::translate_quals(), anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources(), anonymous_namespace{RelAlgExecutor.cpp}::translate_targets(), RelAlgTranslator::translateBinaryGeoFunction(), RelAlgTranslator::translateDatePlusMinus(), RelAlgTranslator::translateGeoComparison(), and RelAlgTranslator::translateGeoFunctionArg().

1175  {
1176  if (!expr) {
1177  return nullptr;
1178  }
1179  const auto expr_no_likelihood = strip_likelihood(expr);
1180  ConstantFoldingVisitor visitor;
1181  auto rewritten_expr = visitor.visit(expr_no_likelihood);
1182  if (visitor.get_num_overflows() > 0 && rewritten_expr->get_type_info().is_integer() &&
1183  rewritten_expr->get_type_info().get_type() != kBIGINT) {
1184  auto rewritten_expr_const =
1185  std::dynamic_pointer_cast<const Analyzer::Constant>(rewritten_expr);
1186  if (!rewritten_expr_const) {
1187  // Integer expression didn't fold completely the first time due to
1188  // overflows in smaller type subexpressions, trying again with a cast
1189  const auto& ti = SQLTypeInfo(kBIGINT, false);
1190  auto bigint_expr_no_likelihood = expr_no_likelihood->deep_copy()->add_cast(ti);
1191  auto rewritten_expr_take2 = visitor.visit(bigint_expr_no_likelihood.get());
1192  auto rewritten_expr_take2_const =
1193  std::dynamic_pointer_cast<Analyzer::Constant>(rewritten_expr_take2);
1194  if (rewritten_expr_take2_const) {
1195  // Managed to fold, switch to the new constant
1196  rewritten_expr = rewritten_expr_take2_const;
1197  }
1198  }
1199  }
1200  const auto expr_with_likelihood = dynamic_cast<const Analyzer::LikelihoodExpr*>(expr);
1201  if (expr_with_likelihood) {
1202  // Add back likelihood
1203  return std::make_shared<Analyzer::LikelihoodExpr>(
1204  rewritten_expr, expr_with_likelihood->get_likelihood());
1205  }
1206  return rewritten_expr;
1207 }
const Analyzer::Expr * strip_likelihood(const Analyzer::Expr *expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const int get_max_rte_scan_table ( std::unordered_map< int, llvm::Value * > &  scan_idx_to_hash_pos)

Definition at line 1220 of file ExpressionRewrite.cpp.

Referenced by BaselineJoinHashTable::codegenKey(), PerfectJoinHashTable::codegenMatchingSet(), and PerfectJoinHashTable::codegenSlot().

1221  {
1222  int ret = INT32_MIN;
1223  for (auto& kv : scan_idx_to_hash_pos) {
1224  if (kv.first > ret) {
1225  ret = kv.first;
1226  }
1227  }
1228  return ret;
1229 }

+ Here is the caller graph for this function:

Analyzer::ExpressionPtr rewrite_array_elements ( const Analyzer::Expr )

Definition at line 765 of file ExpressionRewrite.cpp.

Referenced by anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources(), anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources_for_update(), and anonymous_namespace{RelAlgExecutor.cpp}::translate_targets().

765  {
766  return ArrayElementStringLiteralEncodingVisitor().visit(expr);
767 }

+ Here is the caller graph for this function:

Analyzer::ExpressionPtr rewrite_expr ( const Analyzer::Expr )

Definition at line 769 of file ExpressionRewrite.cpp.

References rewrite_avg_window(), rewrite_sum_window(), and anonymous_namespace{ExpressionRewrite.cpp}::strip_likelihood().

Referenced by RelAlgExecutor::createFilterWorkUnit(), qual_to_conjunctive_form(), qual_to_disjunctive_form(), anonymous_namespace{RelAlgExecutor.cpp}::rewrite_quals(), QueryRewriter::rewriteConstrainedByIn(), anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources(), anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources_for_update(), and anonymous_namespace{RelAlgExecutor.cpp}::translate_targets().

769  {
770  const auto sum_window = rewrite_sum_window(expr);
771  if (sum_window) {
772  return sum_window;
773  }
774  const auto avg_window = rewrite_avg_window(expr);
775  if (avg_window) {
776  return avg_window;
777  }
778  const auto expr_no_likelihood = strip_likelihood(expr);
779  // The following check is not strictly needed, but seems silly to transform a
780  // simple string comparison to an IN just to codegen the same thing anyway.
781 
782  RecursiveOrToInVisitor visitor;
783  auto rewritten_expr = visitor.visit(expr_no_likelihood);
784  const auto expr_with_likelihood =
785  std::dynamic_pointer_cast<const Analyzer::LikelihoodExpr>(rewritten_expr);
786  if (expr_with_likelihood) {
787  // Add back likelihood
788  return std::make_shared<Analyzer::LikelihoodExpr>(
789  rewritten_expr, expr_with_likelihood->get_likelihood());
790  }
791  return rewritten_expr;
792 }
std::shared_ptr< Analyzer::WindowFunction > rewrite_avg_window(const Analyzer::Expr *expr)
std::shared_ptr< Analyzer::WindowFunction > rewrite_sum_window(const Analyzer::Expr *expr)
const Analyzer::Expr * strip_likelihood(const Analyzer::Expr *expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

boost::optional<OverlapsJoinConjunction> rewrite_overlaps_conjunction ( const std::shared_ptr< Analyzer::Expr expr,
const std::vector< InputDescriptor > &  input_table_info,
const OverlapsJoinRewriteType  rewrite_type,
const Executor executor 
)

Definition at line 794 of file ExpressionRewrite.cpp.

References run_benchmark_import::args, CHECK, CHECK_EQ, CHECK_GE, Analyzer::Expr::collect_rte_idx(), convert_to_range_join_oper(), g_enable_hashjoin_many_to_many, Catalog_Namespace::get_metadata_for_table(), logger::INFO, is_constructed_point(), OverlapsJoinSupportedFunction::is_many_to_many_func(), OverlapsJoinSupportedFunction::is_point_poly_rewrite_target_func(), OverlapsJoinSupportedFunction::is_poly_mpoly_rewrite_target_func(), OverlapsJoinSupportedFunction::is_poly_point_rewrite_target_func(), OverlapsJoinSupportedFunction::is_range_join_rewrite_target_func(), kARRAY, kBOOLEAN, kDOUBLE, kGEOGRAPHY, kLE, kONE, kOVERLAPS, kPOINT, LOG, OVERLAPS_JOIN, RANGE_JOIN, OverlapsJoinSupportedFunction::ST_APPROX_OVERLAPS_MULTIPOLYGON_POINT_sv, OverlapsJoinSupportedFunction::ST_DISTANCE_sv, OverlapsJoinSupportedFunction::ST_DWITHIN_POINT_POINT_sv, OverlapsJoinSupportedFunction::ST_OVERLAPS_sv, ScalarExprVisitor< T >::visit(), VLOG, and logger::WARNING.

Referenced by QueryRewriter::rewriteOverlapsJoin().

798  {
799  auto collect_table_cardinality =
800  [](const Analyzer::Expr* lhs, const Analyzer::Expr* rhs, const Executor* executor) {
801  const auto lhs_cv = dynamic_cast<const Analyzer::ColumnVar*>(lhs);
802  const auto rhs_cv = dynamic_cast<const Analyzer::ColumnVar*>(rhs);
803  if (lhs_cv && rhs_cv) {
804  const auto inner_table_metadata = Catalog_Namespace::get_metadata_for_table(
805  {lhs_cv->getColumnKey().db_id, lhs_cv->getColumnKey().table_id});
806  const auto outer_table_metadata = Catalog_Namespace::get_metadata_for_table(
807  {rhs_cv->getColumnKey().db_id, rhs_cv->getColumnKey().table_id});
808  if (inner_table_metadata->fragmenter && outer_table_metadata->fragmenter) {
809  return std::make_pair<int64_t, int64_t>(
810  inner_table_metadata->fragmenter->getNumRows(),
811  outer_table_metadata->fragmenter->getNumRows());
812  }
813  }
814  // otherwise, return an invalid table cardinality
815  return std::make_pair<int64_t, int64_t>(-1, -1);
816  };
817 
818  auto has_invalid_join_col_order = [](const Analyzer::Expr* lhs,
819  const Analyzer::Expr* rhs) {
820  // Check for compatible join ordering. If the join ordering does not match expected
821  // ordering for overlaps, the join builder will fail.
822  std::set<int> lhs_rte_idx;
823  lhs->collect_rte_idx(lhs_rte_idx);
824  CHECK(!lhs_rte_idx.empty());
825  std::set<int> rhs_rte_idx;
826  rhs->collect_rte_idx(rhs_rte_idx);
827  CHECK(!rhs_rte_idx.empty());
828  auto has_invalid_num_join_cols = lhs_rte_idx.size() > 1 || rhs_rte_idx.size() > 1;
829  auto has_invalid_rte_idx = lhs_rte_idx > rhs_rte_idx;
830  return std::make_pair(has_invalid_num_join_cols || has_invalid_rte_idx,
831  has_invalid_rte_idx);
832  };
833 
835  [&](std::string_view func_name,
836  const std::shared_ptr<Analyzer::Expr> expr,
837  const Analyzer::BinOper* range_join_expr,
838  const Analyzer::GeoOperator* lhs,
839  const Analyzer::Constant* rhs,
840  const Executor* executor) -> std::shared_ptr<Analyzer::BinOper> {
842  CHECK_EQ(lhs->size(), size_t(2));
843  auto l_arg = lhs->getOperand(0);
844  // we try to build an overlaps join hash table based on the rhs
845  auto r_arg = lhs->getOperand(1);
846  const bool is_geography = l_arg->get_type_info().get_subtype() == kGEOGRAPHY ||
847  r_arg->get_type_info().get_subtype() == kGEOGRAPHY;
848  if (is_geography) {
849  VLOG(1) << "Range join not yet supported for geodesic distance "
850  << expr->toString();
851  return nullptr;
852  }
853 
854  // Check for compatible join ordering. If the join ordering does not match expected
855  // ordering for overlaps, the join builder will fail.
856  Analyzer::Expr* range_join_arg = r_arg;
857  Analyzer::Expr* bin_oper_arg = l_arg;
858  auto invalid_range_join_qual =
859  has_invalid_join_col_order(bin_oper_arg, range_join_arg);
860  if (invalid_range_join_qual.first) {
861  LOG(INFO) << "Unable to rewrite " << func_name
862  << " to overlaps conjunction. Cannot build hash table over LHS type. "
863  "Check join order.\n"
864  << range_join_expr->toString();
865  return nullptr;
866  }
867  // swapping rule for range join argument
868  // lhs | rhs
869  // 1. pt | pt : swap if |lhs| < |rhs| or has invalid rte values
870  // 2. pt | non-pt : return nullptr
871  // 3. non-pt | pt : return nullptr
872  // 4. non-pt | non-pt : return nullptr
873  // todo (yoonmin) : improve logic for cases 2 and 3
874  bool lhs_is_point{l_arg->get_type_info().get_type() == kPOINT};
875  bool rhs_is_point{r_arg->get_type_info().get_type() == kPOINT};
876  if (!lhs_is_point || !rhs_is_point) {
877  // case 2 ~ 4
878  VLOG(1) << "Currently, we only support range hash join for Point-to-Point "
879  "distance query: fallback to a loop join";
880  return nullptr;
881  }
882 
883  bool swap_args = false;
884  auto const card_info =
885  collect_table_cardinality(range_join_arg, bin_oper_arg, executor);
886  if (invalid_range_join_qual.second && card_info.first > 0 && lhs_is_point) {
887  swap_args = true;
888  } else if (card_info.first >= 0 && card_info.first < card_info.second) {
889  swap_args = true;
890  }
891 
892  if (swap_args) {
893  // to exploit range hash join, we need to assign point geometry to rhs
894  r_arg = lhs->getOperand(0);
895  l_arg = lhs->getOperand(1);
896  VLOG(1) << "Swap range join qual's input arguments to exploit overlaps "
897  "hash join framework";
898  invalid_range_join_qual.first = false;
899  }
900 
901  const bool inclusive = range_join_expr->get_optype() == kLE;
902  auto range_expr = makeExpr<Analyzer::RangeOper>(
903  inclusive, inclusive, r_arg->deep_copy(), rhs->deep_copy());
904  VLOG(1) << "Successfully converted to range hash join";
905  return makeExpr<Analyzer::BinOper>(
906  kBOOLEAN, kOVERLAPS, kONE, l_arg->deep_copy(), range_expr);
907  }
908  return nullptr;
909  };
910 
911  /*
912  * Currently, our overlaps hash join framework supports limited join quals especially
913  * when 1) the FunctionOperator is listed in the function list, i.e.,
914  * is_overlaps_supported_func, 2) the argument order of the join qual must match the
915  * input argument order of the corresponding native function, and 3) input tables match
916  * rte index requirement (the column used to build a hash table has larger rte compared
917  * with that of probing column) And depending on the type of the function, we try to
918  * convert it to corresponding overlaps hash join qual if possible After rewriting, we
919  * create an overlaps join operator which is converted from the original expression and
920  * return OverlapsJoinConjunction object which is a pair of 1) the original expr and 2)
921  * converted overlaps join expr Here, returning the original expr means we additionally
922  * call its corresponding native function to compute the result accurately (i.e.,
923  * overlaps hash join operates a kind of filter expression which may include
924  * false-positive of the true resultset) Note that ST_Overlaps is the only function that
925  * does not return the original expr
926  * */
927  std::shared_ptr<Analyzer::BinOper> overlaps_oper{nullptr};
928  bool needs_to_return_original_expr = false;
929  std::string func_name{""};
930  if (rewrite_type == OverlapsJoinRewriteType::OVERLAPS_JOIN) {
931  auto func_oper = dynamic_cast<Analyzer::FunctionOper*>(expr.get());
932  CHECK(func_oper);
933  func_name = func_oper->getName();
936  LOG(WARNING) << "Many-to-many hashjoin support is disabled, unable to rewrite "
937  << func_oper->toString() << " to use accelerated geo join.";
938  return boost::none;
939  }
940  DeepCopyVisitor deep_copy_visitor;
942  CHECK_GE(func_oper->getArity(), size_t(2));
943  // this case returns {empty quals, overlaps join quals} b/c our join key matching
944  // logic for this case is the same as the implementation of ST_Overlaps function
945  // Note that we can build an overlaps join hash table regardless of table ordering
946  // and the argument order in this case b/c selecting lhs and rhs by arguments 0
947  // and 1 always match the rte index requirement (rte_lhs < rte_rhs)
948  // so what table ordering we take, the rte index requirement satisfies
949  // TODO(adb): we will likely want to actually check for true overlaps, but this
950  // works for now
951  auto lhs = func_oper->getOwnArg(0);
952  auto rewritten_lhs = deep_copy_visitor.visit(lhs.get());
953  CHECK(rewritten_lhs);
954 
955  auto rhs = func_oper->getOwnArg(1);
956  auto rewritten_rhs = deep_copy_visitor.visit(rhs.get());
957  CHECK(rewritten_rhs);
958  overlaps_oper = makeExpr<Analyzer::BinOper>(
959  kBOOLEAN, kOVERLAPS, kONE, rewritten_lhs, rewritten_rhs);
961  CHECK_EQ(func_oper->getArity(), size_t(8));
962  const auto lhs = func_oper->getOwnArg(0);
963  const auto rhs = func_oper->getOwnArg(1);
964  // the correctness of geo args used in the ST_DWithin function is checked by
965  // geo translation logic, i.e., RelAlgTranslator::translateTernaryGeoFunction
966  const auto distance_const_val =
967  dynamic_cast<const Analyzer::Constant*>(func_oper->getArg(7));
968  if (lhs && rhs && distance_const_val) {
969  std::vector<std::shared_ptr<Analyzer::Expr>> args{lhs, rhs};
970  auto range_oper = makeExpr<Analyzer::GeoOperator>(
971  SQLTypeInfo(kDOUBLE, 0, 8, true),
973  args,
974  std::nullopt);
975  auto distance_oper = makeExpr<Analyzer::BinOper>(
976  kBOOLEAN, kLE, kONE, range_oper, distance_const_val->deep_copy());
977  VLOG(1) << "Rewrite " << func_oper->getName() << " to ST_Distance_Point_Point";
978  overlaps_oper =
980  distance_oper,
981  distance_oper.get(),
982  range_oper.get(),
983  distance_const_val,
984  executor);
985  needs_to_return_original_expr = true;
986  }
988  func_name)) {
989  // in the five functions fall into this case,
990  // ST_Contains is for a pair of polygons, and for ST_Intersect cases they are
991  // combo of polygon and multipolygon so what table orders we choose, rte index
992  // requirement for overlaps join can be satisfied if we choose lhs and rhs
993  // from left-to-right order (i.e., get lhs from the arg-1 instead of arg-3)
994  // Note that we choose them from right-to-left argument order in the past
995  CHECK_GE(func_oper->getArity(), size_t(4));
996  auto lhs = func_oper->getOwnArg(1);
997  auto rewritten_lhs = deep_copy_visitor.visit(lhs.get());
998  CHECK(rewritten_lhs);
999  auto rhs = func_oper->getOwnArg(3);
1000  auto rewritten_rhs = deep_copy_visitor.visit(rhs.get());
1001  CHECK(rewritten_rhs);
1002 
1003  overlaps_oper = makeExpr<Analyzer::BinOper>(
1004  kBOOLEAN, kOVERLAPS, kONE, rewritten_lhs, rewritten_rhs);
1005  needs_to_return_original_expr = true;
1007  func_name)) {
1008  // now, we try to look at one more chance to exploit overlaps hash join by
1009  // rewriting the qual as: ST_INTERSECT(POLY, POINT) -> ST_INTERSECT(POINT, POLY)
1010  // to support efficient evaluation of 1) ST_Intersects_Point_Polygon and
1011  // 2) ST_Intersects_Point_MultiPolygon based on our overlaps hash join framework
1012  // here, we have implementation of native functions for both 1) Point-Polygon pair
1013  // and 2) Polygon-Point pair, but we currently do not support hash table
1014  // generation on top of point column thus, the goal of this rewriting is to place
1015  // a non-point geometry to the right-side of the overlaps join operator (to build
1016  // hash table based on it) iff the inner table is larger than that of non-point
1017  // geometry (to reduce expensive hash join performance)
1018  size_t point_arg_idx = 0;
1019  size_t poly_arg_idx = 2;
1020  if (func_oper->getOwnArg(point_arg_idx)->get_type_info().get_type() != kPOINT) {
1021  point_arg_idx = 2;
1022  poly_arg_idx = 1;
1023  }
1024  auto point_cv = func_oper->getOwnArg(point_arg_idx);
1025  auto poly_cv = func_oper->getOwnArg(poly_arg_idx);
1026  CHECK_EQ(point_cv->get_type_info().get_type(), kPOINT);
1027  CHECK_EQ(poly_cv->get_type_info().get_type(), kARRAY);
1028  auto rewritten_lhs = deep_copy_visitor.visit(point_cv.get());
1029  CHECK(rewritten_lhs);
1030  auto rewritten_rhs = deep_copy_visitor.visit(poly_cv.get());
1031  CHECK(rewritten_rhs);
1032  VLOG(1) << "Rewriting the " << func_name << " to use overlaps join with lhs as "
1033  << rewritten_lhs->toString() << " and rhs as " << rewritten_rhs->toString();
1034  overlaps_oper = makeExpr<Analyzer::BinOper>(
1035  kBOOLEAN, kOVERLAPS, kONE, rewritten_lhs, rewritten_rhs);
1036  needs_to_return_original_expr = true;
1038  func_name)) {
1039  // rest of functions reaching here is poly and point geo join query
1040  // to use overlaps hash join in this case, poly column must have its rte == 1
1041  // lhs is the point col_var
1042  auto lhs = func_oper->getOwnArg(2);
1043  auto rewritten_lhs = deep_copy_visitor.visit(lhs.get());
1044  CHECK(rewritten_lhs);
1045  const auto& lhs_ti = rewritten_lhs->get_type_info();
1046 
1047  if (!lhs_ti.is_geometry() && !is_constructed_point(rewritten_lhs.get())) {
1048  // TODO(adb): If ST_Contains is passed geospatial literals instead of columns,
1049  // the function will be expanded during translation rather than during code
1050  // generation. While this scenario does not make sense for the overlaps join, we
1051  // need to detect and abort the overlaps rewrite. Adding a GeospatialConstant
1052  // dervied class to the Analyzer may prove to be a better way to handle geo
1053  // literals, but for now we ensure the LHS type is a geospatial type, which
1054  // would mean the function has not been expanded to the physical types, yet.
1055  LOG(INFO) << "Unable to rewrite " << func_name
1056  << " to overlaps conjunction. LHS input type is neither a geospatial "
1057  "column nor a constructed point"
1058  << func_oper->toString();
1059  return boost::none;
1060  }
1061 
1062  // rhs is coordinates of the poly col
1063  auto rhs = func_oper->getOwnArg(1);
1064  auto rewritten_rhs = deep_copy_visitor.visit(rhs.get());
1065  CHECK(rewritten_rhs);
1066 
1067  if (has_invalid_join_col_order(lhs.get(), rhs.get()).first) {
1068  LOG(INFO) << "Unable to rewrite " << func_name
1069  << " to overlaps conjunction. Cannot build hash table over LHS type. "
1070  "Check join order."
1071  << func_oper->toString();
1072  return boost::none;
1073  }
1074 
1075  VLOG(1) << "Rewriting " << func_name << " to use overlaps join with lhs as "
1076  << rewritten_lhs->toString() << " and rhs as " << rewritten_rhs->toString();
1077 
1078  overlaps_oper = makeExpr<Analyzer::BinOper>(
1079  kBOOLEAN, kOVERLAPS, kONE, rewritten_lhs, rewritten_rhs);
1080  if (func_name !=
1082  needs_to_return_original_expr = true;
1083  }
1084  }
1085  } else if (rewrite_type == OverlapsJoinRewriteType::RANGE_JOIN) {
1086  auto bin_oper = dynamic_cast<Analyzer::BinOper*>(expr.get());
1087  CHECK(bin_oper);
1088  auto lhs = dynamic_cast<const Analyzer::GeoOperator*>(bin_oper->get_left_operand());
1089  CHECK(lhs);
1090  auto rhs = dynamic_cast<const Analyzer::Constant*>(bin_oper->get_right_operand());
1091  CHECK(rhs);
1092  func_name = lhs->getName();
1093  overlaps_oper =
1094  convert_to_range_join_oper(func_name, expr, bin_oper, lhs, rhs, executor);
1095  needs_to_return_original_expr = true;
1096  }
1097  const auto expr_str = !func_name.empty() ? func_name : expr->toString();
1098  if (overlaps_oper) {
1099  VLOG(1) << "Successfully converted " << expr_str << " to overlaps join";
1100  if (needs_to_return_original_expr) {
1101  return OverlapsJoinConjunction{{expr}, {overlaps_oper}};
1102  } else {
1103  return OverlapsJoinConjunction{{}, {overlaps_oper}};
1104  }
1105  }
1106  VLOG(1) << "Overlaps join not enabled for " << expr_str;
1107  return boost::none;
1108 }
static bool is_poly_mpoly_rewrite_target_func(std::string_view target_func_name)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define LOG(tag)
Definition: Logger.h:285
bool is_constructed_point(const Analyzer::Expr *expr)
Definition: Execute.h:1508
Definition: sqldefs.h:34
const TableDescriptor * get_metadata_for_table(const ::shared::TableKey &table_key, bool populate_fragmenter)
#define CHECK_GE(x, y)
Definition: Logger.h:306
T visit(const Analyzer::Expr *expr) const
static constexpr std::string_view ST_DWITHIN_POINT_POINT_sv
static constexpr std::string_view ST_OVERLAPS_sv
static constexpr std::string_view ST_DISTANCE_sv
bool g_enable_hashjoin_many_to_many
Definition: Execute.cpp:104
static bool is_many_to_many_func(std::string_view target_func_name)
static bool is_range_join_rewrite_target_func(std::string_view target_func_name)
static bool is_poly_point_rewrite_target_func(std::string_view target_func_name)
static constexpr std::string_view ST_APPROX_OVERLAPS_MULTIPOLYGON_POINT_sv
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:291
boost::optional< OverlapsJoinConjunction > convert_to_range_join_oper(const std::shared_ptr< Analyzer::Expr > expr, const Analyzer::BinOper *range_join_expr, const Analyzer::GeoOperator *lhs, const Analyzer::Constant *rhs)
virtual void collect_rte_idx(std::set< int > &rte_idx_set) const
Definition: Analyzer.h:110
#define VLOG(n)
Definition: Logger.h:387
static bool is_point_poly_rewrite_target_func(std::string_view target_func_name)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool self_join_not_covered_by_left_deep_tree ( const Analyzer::ColumnVar lhs,
const Analyzer::ColumnVar rhs,
const int  max_rte_covered 
)

Definition at line 1209 of file ExpressionRewrite.cpp.

References Analyzer::ColumnVar::get_rte_idx(), and Analyzer::ColumnVar::getTableKey().

Referenced by BaselineJoinHashTable::codegenKey(), PerfectJoinHashTable::codegenMatchingSet(), and PerfectJoinHashTable::codegenSlot().

1211  {
1212  if (key_side->getTableKey() == val_side->getTableKey() &&
1213  key_side->get_rte_idx() == val_side->get_rte_idx() &&
1214  key_side->get_rte_idx() > max_rte_covered) {
1215  return true;
1216  }
1217  return false;
1218 }

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 
)

Definition at line 1151 of file ExpressionRewrite.cpp.

References g_strip_join_covered_quals, and ScalarExprVisitor< T >::visit().

Referenced by RelAlgExecutionUnit::createCountAllExecutionUnit().

1153  {
1155  return quals;
1156  }
1157 
1158  if (join_quals.empty()) {
1159  return quals;
1160  }
1161 
1162  std::list<std::shared_ptr<Analyzer::Expr>> quals_to_return;
1163 
1164  JoinCoveredQualVisitor visitor(join_quals);
1165  for (const auto& qual : quals) {
1166  if (!visitor.visit(qual.get())) {
1167  // Not a covered qual, don't elide it from the filtered count
1168  quals_to_return.push_back(qual);
1169  }
1170  }
1171 
1172  return quals_to_return;
1173 }
bool g_strip_join_covered_quals
Definition: Execute.cpp:107

+ Here is the call graph for this function:

+ Here is the caller graph for this function: