OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RelAlgTranslator Class Reference

#include <RelAlgTranslator.h>

+ Collaboration diagram for RelAlgTranslator:

Public Member Functions

 RelAlgTranslator (std::shared_ptr< const query_state::QueryState > q_s, const Executor *executor, const std::unordered_map< const RelAlgNode *, int > &input_to_nest_level, const std::vector< JoinType > &join_types, const time_t now, const bool just_explain)
 
std::shared_ptr< Analyzer::Exprtranslate (const RexScalar *rex) const
 
bool generated_geos_ops ()
 
template<typename T >
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 
template<>
std::shared_ptr< Analyzer::ExprtranslateRexScalar (RexScalar const *rex) const
 

Static Public Member Functions

static std::shared_ptr
< Analyzer::Expr
translateAggregateRex (const RexAgg *rex, const std::vector< std::shared_ptr< Analyzer::Expr >> &scalar_sources)
 
static std::shared_ptr
< Analyzer::Expr
translateLiteral (const RexLiteral *)
 

Private Member Functions

std::shared_ptr< Analyzer::ExprtranslateScalarRex (const RexScalar *rex) const
 
std::shared_ptr< Analyzer::ExprtranslateScalarSubquery (const RexSubQuery *) const
 
std::shared_ptr< Analyzer::ExprtranslateInput (const RexInput *) const
 
std::shared_ptr< Analyzer::ExprtranslateUoper (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateInOper (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprgetInIntegerSetExpr (std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set) const
 
std::shared_ptr< Analyzer::ExprtranslateOper (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateBoundingBoxIntersectOper (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateCase (const RexCase *) const
 
std::shared_ptr< Analyzer::ExprtranslateWidthBucket (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateMLPredict (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslatePCAProject (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateLike (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateRegexp (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateLikely (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateUnlikely (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateExtract (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateDateadd (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateDatePlusMinus (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateDatediff (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateDatepart (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateLength (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateKeyForString (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateSampleRatio (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateCurrentUser (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateStringOper (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateCardinality (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateItem (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateCurrentDate () const
 
std::shared_ptr< Analyzer::ExprtranslateCurrentTime () const
 
std::shared_ptr< Analyzer::ExprtranslateCurrentTimestamp () const
 
std::shared_ptr< Analyzer::ExprtranslateDatetime (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateHPTLiteral (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateAbs (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateSign (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateOffsetInFragment () const
 
std::shared_ptr< Analyzer::ExprtranslateArrayFunction (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateFunction (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateWindowFunction (const RexWindowFunctionOperator *) const
 
std::tuple< bool, bool,
std::shared_ptr
< Analyzer::Expr > > 
translateFrameBoundExpr (const RexScalar *bound_expr) const
 
std::shared_ptr< Analyzer::ExprtranslateIntervalExprForWindowFraming (std::shared_ptr< Analyzer::Expr > order_key, bool for_preceding_bound, const Analyzer::Expr *expr) const
 
Analyzer::ExpressionPtrVector translateFunctionArgs (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateUnaryGeoFunction (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateBinaryGeoFunction (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateTernaryGeoFunction (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateFunctionWithGeoArg (const RexFunctionOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateGeoComparison (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateGeoProjection (const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
 
std::shared_ptr< Analyzer::ExprtranslateUnaryGeoPredicate (const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
 
std::shared_ptr< Analyzer::ExprtranslateUnaryGeoConstructor (const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
 
std::shared_ptr< Analyzer::ExprtranslateBinaryGeoPredicate (const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
 
std::shared_ptr< Analyzer::ExprtranslateBinaryGeoConstructor (const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
 
std::shared_ptr< Analyzer::ExprtranslateGeoBoundingBoxIntersectOper (const RexOperator *) const
 
std::vector< std::shared_ptr
< Analyzer::Expr > > 
translateGeoFunctionArg (const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
 
std::vector< std::shared_ptr
< Analyzer::Expr > > 
translateGeoColumn (const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool expand_geo_col) const
 
std::vector< std::shared_ptr
< Analyzer::Expr > > 
translateGeoLiteral (const RexLiteral *, SQLTypeInfo &, bool) const
 
std::pair< std::shared_ptr
< Analyzer::Expr >
, SQLQualifier
getQuantifiedRhs (const RexScalar *) const
 

Private Attributes

std::shared_ptr< const
query_state::QueryState
query_state_
 
const Executorexecutor_
 
const std::unordered_map
< const RelAlgNode *, int > 
input_to_nest_level_
 
const std::vector< JoinTypejoin_types_
 
time_t now_
 
bool generated_geos_ops_
 
const bool just_explain_
 
robin_hood::unordered_map
< RexScalar const
*, std::shared_ptr
< Analyzer::Expr > > 
cache_
 

Detailed Description

Definition at line 49 of file RelAlgTranslator.h.

Constructor & Destructor Documentation

RelAlgTranslator::RelAlgTranslator ( std::shared_ptr< const query_state::QueryState q_s,
const Executor executor,
const std::unordered_map< const RelAlgNode *, int > &  input_to_nest_level,
const std::vector< JoinType > &  join_types,
const time_t  now,
const bool  just_explain 
)
inline

Definition at line 51 of file RelAlgTranslator.h.

57  : query_state_(q_s)
58  , executor_(executor)
59  , input_to_nest_level_(input_to_nest_level)
60  , join_types_(join_types)
61  , now_(now)
62  , generated_geos_ops_(false)
63  , just_explain_(just_explain) {}
const std::vector< JoinType > join_types_
const Executor * executor_
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
std::shared_ptr< const query_state::QueryState > query_state_
const bool just_explain_

Member Function Documentation

bool RelAlgTranslator::generated_geos_ops ( )
inline

Definition at line 74 of file RelAlgTranslator.h.

References generated_geos_ops_.

74 { return generated_geos_ops_; }
std::shared_ptr< Analyzer::Expr > RelAlgTranslator::getInIntegerSetExpr ( std::shared_ptr< Analyzer::Expr arg,
const ResultSet val_set 
) const
private

Definition at line 976 of file RelAlgTranslator.cpp.

References threading_serial::async(), result_set::can_use_parallel_algorithms(), CHECK, CHECK_EQ, CHECK_GE, cpu_threads(), executor_, anonymous_namespace{RelAlgTranslator.cpp}::fill_dictionary_encoded_in_vals(), anonymous_namespace{RelAlgTranslator.cpp}::fill_integer_in_vals(), g_cluster, Catalog_Namespace::SysCatalog::getCatalog(), inline_int_null_val(), Catalog_Namespace::SysCatalog::instance(), and kENCODING_DICT.

Referenced by translateInOper().

978  {
980  return nullptr;
981  }
982  std::vector<int64_t> value_exprs;
983  const size_t fetcher_count = cpu_threads();
984  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
985  std::vector<std::future<void>> fetcher_threads;
986  const auto& arg_type = arg->get_type_info();
987  const auto entry_count = val_set.entryCount();
988  CHECK_EQ(size_t(1), val_set.colCount());
989  const auto& col_type = val_set.getColType(0);
990  if (g_cluster && arg_type.is_string() &&
991  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
992  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
993  return nullptr;
994  }
995  std::atomic<size_t> total_in_vals_count{0};
996  for (size_t i = 0,
997  start_entry = 0,
998  stride = (entry_count + fetcher_count - 1) / fetcher_count;
999  i < fetcher_count && start_entry < entry_count;
1000  ++i, start_entry += stride) {
1001  expr_set[i].reserve(entry_count / fetcher_count);
1002  const auto end_entry = std::min(start_entry + stride, entry_count);
1003  if (arg_type.is_string()) {
1004  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
1005  auto col_expr = dynamic_cast<const Analyzer::ColumnVar*>(arg.get());
1006  CHECK(col_expr);
1007  const auto& dest_dict_key = arg_type.getStringDictKey();
1008  const auto& source_dict_key = col_type.getStringDictKey();
1009  const auto dd = executor_->getStringDictionaryProxy(
1010  arg_type.getStringDictKey(), val_set.getRowSetMemOwner(), true);
1011  const auto sd = executor_->getStringDictionaryProxy(
1012  col_type.getStringDictKey(), val_set.getRowSetMemOwner(), true);
1013  CHECK(sd);
1014  const auto needle_null_val = inline_int_null_val(arg_type);
1015  const auto catalog =
1016  Catalog_Namespace::SysCatalog::instance().getCatalog(source_dict_key.db_id);
1017  CHECK(catalog);
1018  fetcher_threads.push_back(std::async(
1020  [&val_set,
1021  &total_in_vals_count,
1022  sd,
1023  dd,
1024  &source_dict_key,
1025  &dest_dict_key,
1026  needle_null_val,
1027  catalog](std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
1028  if (g_cluster) {
1029  CHECK_GE(dd->getGeneration(), 0);
1031  in_vals,
1032  total_in_vals_count,
1033  &val_set,
1034  {start, end},
1035  catalog->getStringDictionaryHosts(),
1036  {source_dict_key.db_id, source_dict_key.dict_id},
1037  {dest_dict_key.db_id, dest_dict_key.dict_id},
1038  dd->getGeneration(),
1039  needle_null_val);
1040  } else {
1042  total_in_vals_count,
1043  &val_set,
1044  {start, end},
1045  sd,
1046  dd,
1047  needle_null_val);
1048  }
1049  },
1050  std::ref(expr_set[i]),
1051  start_entry,
1052  end_entry));
1053  } else {
1054  CHECK(arg_type.is_integer());
1055  fetcher_threads.push_back(std::async(
1057  [&val_set, &total_in_vals_count](
1058  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
1059  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
1060  },
1061  std::ref(expr_set[i]),
1062  start_entry,
1063  end_entry));
1064  }
1065  }
1066  for (auto& child : fetcher_threads) {
1067  child.get();
1068  }
1069 
1070  val_set.moveToBegin();
1071  value_exprs.reserve(entry_count);
1072  for (auto& exprs : expr_set) {
1073  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
1074  }
1075  return makeExpr<Analyzer::InIntegerSet>(
1076  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
1077 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Executor * executor_
#define CHECK_GE(x, y)
Definition: Logger.h:306
future< Result > async(Fn &&fn, Args &&...args)
static SysCatalog & instance()
Definition: SysCatalog.h:343
void fill_dictionary_encoded_in_vals(std::vector< int64_t > &in_vals, std::atomic< size_t > &total_in_vals_count, const ResultSet *values_rowset, const std::pair< int64_t, int64_t > values_rowset_slice, const StringDictionaryProxy *source_dict, const StringDictionaryProxy *dest_dict, const int64_t needle_null_val)
std::shared_ptr< Catalog > getCatalog(const std::string &dbName)
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool g_cluster
int cpu_threads()
Definition: thread_count.h:25
bool can_use_parallel_algorithms(const ResultSet &rows)
Definition: ResultSet.cpp:1581
void fill_integer_in_vals(std::vector< int64_t > &in_vals, std::atomic< size_t > &total_in_vals_count, const ResultSet *values_rowset, const std::pair< int64_t, int64_t > values_rowset_slice)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > RelAlgTranslator::getQuantifiedRhs ( const RexScalar rex_scalar) const
private

Definition at line 61 of file RelAlgTranslator.cpp.

References CHECK_EQ, RexFunctionOperator::getName(), kALL, kANY, kCAST, kONE, and translateScalarRex().

Referenced by translateOper().

61  {
62  std::shared_ptr<Analyzer::Expr> rhs;
63  SQLQualifier sql_qual{kONE};
64  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
65  if (!rex_operator) {
66  return std::make_pair(rhs, sql_qual);
67  }
68  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_operator);
69  const auto qual_str = rex_function ? rex_function->getName() : "";
70  if (qual_str == "PG_ANY"sv || qual_str == "PG_ALL"sv) {
71  CHECK_EQ(size_t(1), rex_function->size());
72  rhs = translateScalarRex(rex_function->getOperand(0));
73  sql_qual = (qual_str == "PG_ANY"sv) ? kANY : kALL;
74  }
75  if (!rhs && rex_operator->getOperator() == kCAST) {
76  CHECK_EQ(size_t(1), rex_operator->size());
77  std::tie(rhs, sql_qual) = getQuantifiedRhs(rex_operator->getOperand(0));
78  }
79  return std::make_pair(rhs, sql_qual);
80 }
Definition: sqldefs.h:74
#define CHECK_EQ(x, y)
Definition: Logger.h:301
SQLQualifier
Definition: sqldefs.h:74
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
Definition: sqldefs.h:51
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > getQuantifiedRhs(const RexScalar *) const
Definition: sqldefs.h:74
Definition: sqldefs.h:74
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translate ( const RexScalar rex) const

Definition at line 262 of file RelAlgTranslator.cpp.

References cache_, and translateScalarRex().

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

262  {
263  ScopeGuard clear_cache{[this] { cache_.clear(); }};
264  return translateScalarRex(rex);
265 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
robin_hood::unordered_map< RexScalar const *, std::shared_ptr< Analyzer::Expr > > cache_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateAbs ( const RexFunctionOperator rex_function) const
private

Definition at line 1674 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, RexOperator::getOperand(), kBOOLEAN, kLT, kONE, kUMINUS, anonymous_namespace{RelAlgTranslator.cpp}::makeNumericConstant(), RexOperator::size(), and translateScalarRex().

Referenced by translateFunction().

1675  {
1676  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1677  expr_list;
1678  CHECK_EQ(size_t(1), rex_function->size());
1679  const auto operand = translateScalarRex(rex_function->getOperand(0));
1680  const auto& operand_ti = operand->get_type_info();
1681  CHECK(operand_ti.is_number());
1682  const auto zero = makeNumericConstant(operand_ti, 0);
1683  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1684  const auto uminus_operand =
1685  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1686  expr_list.emplace_back(lt_zero, uminus_operand);
1687  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1688 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
Definition: sqldefs.h:74
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:35

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateAggregateRex ( const RexAgg rex,
const std::vector< std::shared_ptr< Analyzer::Expr >> &  scalar_sources 
)
static

Definition at line 281 of file RelAlgTranslator.cpp.

References CHECK_LE, CHECK_LT, Datum::doubleval, g_cluster, get_agg_type(), RexAgg::getKind(), RexAgg::getOperand(), anonymous_namespace{RelAlgTranslator.cpp}::is_agg_supported_for_type(), anonymous_namespace{RelAlgOptimizer.cpp}::is_distinct(), anonymous_namespace{RelAlgTranslator.cpp}::is_distinct_supported(), RexAgg::isDistinct(), kAPPROX_COUNT_DISTINCT, kAPPROX_QUANTILE, kBOOLEAN, kCOUNT_IF, kDOUBLE, kINT, kMODE, kSUM_IF, RexAgg::size(), ThriftSerializers::takes_arg(), and toString().

Referenced by anonymous_namespace{RelAlgExecutor.cpp}::translate_targets().

283  {
284  SQLAgg agg_kind = rex->getKind();
285  const bool is_distinct = rex->isDistinct();
286  const bool takes_arg{rex->size() > 0};
287  std::shared_ptr<Analyzer::Expr> arg_expr;
288  std::shared_ptr<Analyzer::Expr> arg1; // 2nd aggregate parameter
289  if (takes_arg) {
290  const auto operand = rex->getOperand(0);
291  CHECK_LT(operand, scalar_sources.size());
292  CHECK_LE(rex->size(), 2u);
293  arg_expr = scalar_sources[operand];
294  switch (agg_kind) {
296  if (rex->size() == 2) {
297  auto const const_arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
298  scalar_sources[rex->getOperand(1)]);
299  if (!const_arg1 || const_arg1->get_type_info().get_type() != kINT ||
300  const_arg1->get_constval().intval < 1 ||
301  const_arg1->get_constval().intval > 100) {
302  throw std::runtime_error(
303  "APPROX_COUNT_DISTINCT's second parameter must be a SMALLINT literal "
304  "between 1 and 100");
305  }
306  arg1 = scalar_sources[rex->getOperand(1)];
307  }
308  break;
309  case kAPPROX_QUANTILE:
310  if (g_cluster) {
311  throw std::runtime_error(
312  "APPROX_PERCENTILE/MEDIAN is not supported in distributed mode at this "
313  "time.");
314  }
315  // If second parameter is not given then APPROX_MEDIAN is assumed.
316  if (rex->size() == 2) {
317  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
318  std::dynamic_pointer_cast<Analyzer::Constant>(
319  scalar_sources[rex->getOperand(1)])
320  ->add_cast(SQLTypeInfo(kDOUBLE)));
321  } else {
322 #ifdef _WIN32
323  Datum median;
324  median.doubleval = 0.5;
325 #else
326  constexpr Datum median{.doubleval = 0.5};
327 #endif
328  arg1 = std::make_shared<Analyzer::Constant>(kDOUBLE, false, median);
329  }
330  break;
331  case kMODE:
332  if (g_cluster) {
333  throw std::runtime_error(
334  "MODE is not supported in distributed mode at this time.");
335  }
336  break;
337  case kCOUNT_IF:
338  if (arg_expr->get_type_info().is_geometry()) {
339  throw std::runtime_error(
340  "COUNT_IF does not currently support geospatial types.");
341  }
342  break;
343  case kSUM_IF:
344  arg1 = scalar_sources[rex->getOperand(1)];
345  if (arg1->get_type_info().get_type() != kBOOLEAN) {
346  throw std::runtime_error("Conditional argument must be a boolean expression.");
347  }
348  break;
349  default:
350  break;
351  }
352  const auto& arg_ti = arg_expr->get_type_info();
353  if (!is_agg_supported_for_type(agg_kind, arg_ti)) {
354  throw std::runtime_error("Aggregate on " + arg_ti.get_type_name() +
355  " is not supported yet.");
356  }
357  if (is_distinct && !is_distinct_supported(agg_kind)) {
358  throw std::runtime_error(toString(agg_kind) +
359  " does not currently support the DISTINCT qualifier.");
360  }
361  }
362  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
363  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, arg1);
364 }
SQLAgg
Definition: sqldefs.h:76
SQLAgg getKind() const
Definition: RelAlgDag.h:799
size_t getOperand(size_t idx) const
Definition: RelAlgDag.h:805
SQLTypeInfo get_agg_type(const SQLAgg agg_kind, const Analyzer::Expr *arg_expr)
bool is_agg_supported_for_type(const SQLAgg &agg_kind, const SQLTypeInfo &arg_ti)
bool is_distinct_supported(SQLAgg const agg_kind)
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
#define CHECK_LT(x, y)
Definition: Logger.h:303
#define CHECK_LE(x, y)
Definition: Logger.h:304
bool takes_arg(const TargetInfo &target_info)
bool isDistinct() const
Definition: RelAlgDag.h:801
size_t size() const
Definition: RelAlgDag.h:803
bool g_cluster
Definition: sqltypes.h:72
Definition: Datum.h:71
bool is_distinct(const size_t input_idx, const RelAlgNode *node)
Definition: sqldefs.h:86
double doubleval
Definition: Datum.h:78

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Analyzer::ExpressionPtr RelAlgTranslator::translateArrayFunction ( const RexFunctionOperator rex_function) const
private

Definition at line 1716 of file RelAlgTranslator.cpp.

References CHECK, get_nullable_logical_type_info(), SQLTypeInfo::get_subtype(), RexOperator::getType(), kARRAY, kBOOLEAN, kENCODING_DICT, kNULLT, kTEXT, shared::StringDictKey::kTransientDictKey, to_string(), TRANSIENT_DICT_ID, and translateFunctionArgs().

Referenced by translateFunction().

1717  {
1718  if (rex_function->getType().get_subtype() == kNULLT) {
1719  auto sql_type = rex_function->getType();
1720  CHECK(sql_type.get_type() == kARRAY);
1721 
1722  // FIX-ME: Deal with NULL arrays
1723  auto translated_function_args(translateFunctionArgs(rex_function));
1724  if (translated_function_args.size() > 0) {
1725  const auto first_element_logical_type =
1726  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1727 
1728  auto diff_elem_itr =
1729  std::find_if(translated_function_args.begin(),
1730  translated_function_args.end(),
1731  [first_element_logical_type](const auto expr) {
1732  const auto element_logical_type =
1733  get_nullable_logical_type_info(expr->get_type_info());
1734  if (first_element_logical_type != element_logical_type) {
1735  if (first_element_logical_type.is_none_encoded_string() &&
1736  element_logical_type.is_none_encoded_string()) {
1737  return false;
1738  }
1739  return true;
1740  }
1741  return false;
1742  });
1743  if (diff_elem_itr != translated_function_args.end()) {
1744  throw std::runtime_error(
1745  "Element " +
1746  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1747  " is not of the same type as other elements of the array. Consider casting "
1748  "to force this condition.\nElement Type: " +
1749  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1750  .to_string() +
1751  "\nArray type: " + first_element_logical_type.to_string());
1752  }
1753 
1754  if (first_element_logical_type.is_string()) {
1755  sql_type.set_subtype(kTEXT);
1756  sql_type.set_compression(kENCODING_DICT);
1757  if (first_element_logical_type.is_none_encoded_string()) {
1758  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1759  sql_type.setStringDictKey(shared::StringDictKey::kTransientDictKey);
1760  } else {
1761  CHECK(first_element_logical_type.is_dict_encoded_string());
1762  sql_type.set_comp_param(first_element_logical_type.get_comp_param());
1763  sql_type.setStringDictKey(first_element_logical_type.getStringDictKey());
1764  }
1765  } else if (first_element_logical_type.is_dict_encoded_string()) {
1766  sql_type.set_subtype(kTEXT);
1767  sql_type.set_compression(kENCODING_DICT);
1768  sql_type.set_comp_param(first_element_logical_type.get_comp_param());
1769  sql_type.setStringDictKey(first_element_logical_type.getStringDictKey());
1770  } else {
1771  sql_type.set_subtype(first_element_logical_type.get_type());
1772  sql_type.set_scale(first_element_logical_type.get_scale());
1773  sql_type.set_precision(first_element_logical_type.get_precision());
1774  }
1775 
1776  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1777  } else {
1778  // defaulting to valid sub-type for convenience
1779  sql_type.set_subtype(kBOOLEAN);
1780  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1781  }
1782  } else {
1783  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1784  translateFunctionArgs(rex_function));
1785  }
1786 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1490
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
#define TRANSIENT_DICT_ID
Definition: DbObjectKeys.h:24
std::string to_string(char const *&&v)
Definition: sqltypes.h:79
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
static const StringDictKey kTransientDictKey
Definition: DbObjectKeys.h:45
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateBinaryGeoConstructor ( const RexFunctionOperator rex_function,
SQLTypeInfo ti,
const bool  with_bounds 
) const
private

Definition at line 934 of file RelAlgTranslatorGeo.cpp.

References func_resolve, SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), RexFunctionOperator::getName(), RexOperator::getOperand(), Geospatial::GeoBase::kBUFFER, Geospatial::GeoBase::kCONCAVEHULL, Geospatial::GeoBase::kDIFFERENCE, kDOUBLE, kENCODING_NONE, kGEOMETRY, Geospatial::GeoBase::kINTERSECTION, kMULTIPOLYGON, Geospatial::GeoBase::kUNION, SQLTypeInfo::set_comp_param(), SQLTypeInfo::set_compression(), SQLTypeInfo::set_input_srid(), SQLTypeInfo::set_output_srid(), SQLTypeInfo::set_subtype(), SQLTypeInfo::set_type(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction(), and translateGeoFunctionArg().

937  {
938 #ifndef ENABLE_GEOS
939  throw QueryNotSupported(rex_function->getName() +
940  " geo constructor requires enabled GEOS support");
941 #endif
943  if (rex_function->getName() == "ST_Difference"sv) {
945  } else if (rex_function->getName() == "ST_Union"sv) {
947  } else if (rex_function->getName() == "ST_Buffer"sv) {
949  } else if (rex_function->getName() == "ST_ConcaveHull"sv) {
951  }
952 
955  SQLTypeInfo arg0_ti;
956  SQLTypeInfo arg1_ti;
957  if (func_resolve(rex_function->getName(),
958  "ST_Intersection"sv,
959  "ST_Difference"sv,
960  "ST_Union"sv,
961  "ST_Buffer"sv,
962  "ST_ConcaveHull"sv)) {
963  // First arg: geometry
964  geoargs0 = translateGeoFunctionArg(rex_function->getOperand(0),
965  arg0_ti,
966  false,
967  true,
968  true,
969  false,
970  false,
971  /* allow_gdal_transforms = */ true);
972  }
973  if (func_resolve(rex_function->getName(),
974  "ST_Intersection"sv,
975  "ST_Difference"sv,
976  "ST_Union"sv)) {
977  // Second arg: geometry
978  geoargs1 = translateGeoFunctionArg(rex_function->getOperand(1),
979  arg1_ti,
980  false,
981  true,
982  true,
983  false,
984  false,
985  /* allow_gdal_transforms = */ true);
986  if (arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
987  throw QueryNotSupported(rex_function->getName() +
988  " geo constructor requires arguments with matching srids");
989  }
990  } else if (func_resolve(rex_function->getName(), "ST_Buffer"sv, "ST_ConcaveHull"sv)) {
991  // Second arg: double scalar
992  auto param_expr = translateScalarRex(rex_function->getOperand(1));
993  arg1_ti = SQLTypeInfo(kDOUBLE, false);
994  if (param_expr->get_type_info().get_type() != kDOUBLE) {
995  param_expr = param_expr->add_cast(arg1_ti);
996  }
997  geoargs1 = {param_expr};
998  }
999 
1000  // Record the optional transform request that can be sent by an ecompassing TRANSFORM
1001  auto srid = ti.get_output_srid();
1002  // Build the typeinfo of the constructed geometry
1003  SQLTypeInfo arg_ti = arg0_ti;
1004  arg_ti.set_type(kMULTIPOLYGON);
1005  arg_ti.set_subtype(kGEOMETRY);
1006  arg_ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
1007  arg_ti.set_comp_param(0);
1008  arg_ti.set_input_srid(arg0_ti.get_output_srid());
1009  if (srid > 0) {
1010  if (arg_ti.get_input_srid() > 0) {
1011  // Constructed geometry to be transformed to srid given by encompassing transform
1012  arg_ti.set_output_srid(srid);
1013  } else {
1014  throw QueryNotSupported("Transform of geo constructor " + rex_function->getName() +
1015  " requires its argument(s) to have a valid srid");
1016  }
1017  } else {
1018  arg_ti.set_output_srid(arg_ti.get_input_srid()); // No encompassing transform
1019  }
1020  // If there was an output transform, it's now embedded into arg_ti and the geo operator.
1021  // Now de-register the transform from the return typeinfo:
1022  ti = arg_ti;
1024  return makeExpr<Analyzer::GeoBinOper>(op, arg_ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1025 }
void set_compression(EncodingType c)
Definition: sqltypes.h:481
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:471
void set_input_srid(int d)
Definition: sqltypes.h:474
void set_output_srid(int s)
Definition: sqltypes.h:476
void set_comp_param(int p)
Definition: sqltypes.h:482
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:395
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:186
const std::string & getName() const
Definition: RelAlgDag.h:506
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:470

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateBinaryGeoFunction ( const RexFunctionOperator rex_function) const
private

Definition at line 1333 of file RelAlgTranslatorGeo.cpp.

References run_benchmark_import::args, CHECK, CHECK_EQ, CHECK_GT, Datum::doubleval, fold_expr(), func_resolve, g_enable_geo_ops_on_uncompressed_coords, SQLTypeInfo::get_comp_param(), SQLTypeInfo::get_compression(), Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_subtype(), SQLTypeInfo::get_type(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Datum::intval, kBOOLEAN, kDOUBLE, kENCODING_GEOINT, kENCODING_NONE, kGEOGRAPHY, kINT, kLE, kLINESTRING, kMULTILINESTRING, kMULTIPOLYGON, kNOT, kNULLT, kONE, kPOINT, kPOLYGON, run_benchmark_import::result, RexOperator::size(), spatial_type::suffix(), TOLERANCE_GEOINT32, translateGeoColumn(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction(), and translateTernaryGeoFunction().

1334  {
1335  auto function_name = rex_function->getName();
1336  auto return_type = rex_function->getType();
1337 
1338  if (function_name == "ST_IntersectsBox"sv) {
1339  // Bounding box intersection is the only implementation supported for now, only
1340  // translate bounds
1341  CHECK_EQ(size_t(2), rex_function->size());
1342  auto extract_geo_bounds_from_input =
1343  [this, &rex_function](const size_t index) -> std::shared_ptr<Analyzer::Expr> {
1344  const auto rex_input =
1345  dynamic_cast<const RexInput*>(rex_function->getOperand(index));
1346  if (rex_input) {
1347  SQLTypeInfo ti;
1348  const auto exprs = translateGeoColumn(rex_input, ti, true, false);
1349  CHECK_GT(exprs.size(), size_t(0));
1350  if (ti.get_type() == kPOINT) {
1351  throw std::runtime_error(
1352  "ST_IntersectsBox is not supported for point arguments.");
1353  } else {
1354  return exprs.back();
1355  }
1356  } else {
1357  throw std::runtime_error(
1358  "Only inputs are supported as arguments to ST_IntersectsBox for now.");
1359  }
1360  };
1361  std::vector<std::shared_ptr<Analyzer::Expr>> geo_args;
1362  geo_args.push_back(extract_geo_bounds_from_input(0));
1363  geo_args.push_back(extract_geo_bounds_from_input(1));
1364 
1365  return makeExpr<Analyzer::FunctionOper>(return_type, function_name, geo_args);
1366  }
1367 
1368  if (function_name == "ST_Distance"sv || function_name == "ST_MaxDistance"sv) {
1369  CHECK_EQ(size_t(2), rex_function->size());
1370  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1371  int legacy_transform_srid = 0;
1372  for (size_t i = 0; i < rex_function->size(); i++) {
1373  SQLTypeInfo arg0_ti; // discard
1374  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(i),
1375  arg0_ti,
1376  /*with_bounds=*/false, // TODO
1377  /*expand_geo_col=*/false,
1378  /*is_projection = */ false,
1379  /*use_geo_expressions=*/true);
1380  if (arg0_ti.get_input_srid() != arg0_ti.get_output_srid() &&
1381  arg0_ti.get_output_srid() > 0 &&
1382  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
1383  // legacy transform
1384  CHECK(legacy_transform_srid == 0 ||
1385  legacy_transform_srid == arg0_ti.get_output_srid());
1386  legacy_transform_srid = arg0_ti.get_output_srid();
1387  }
1388  args.insert(args.end(), geoargs.begin(), geoargs.end());
1389  }
1390  return makeExpr<Analyzer::GeoOperator>(
1391  SQLTypeInfo(kDOUBLE, /*not_null=*/false),
1392  function_name,
1393  args,
1394  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1395  : std::nullopt);
1396  }
1397 
1398  bool swap_args = false;
1399  bool with_bounds = false;
1400  bool negate_result = false;
1401  Analyzer::ExpressionPtr threshold_expr = nullptr;
1402  Analyzer::ExpressionPtr compare_expr = nullptr;
1403  if (function_name == "ST_DWithin"sv) {
1404  CHECK_EQ(size_t(3), rex_function->size());
1405  function_name = "ST_Distance";
1406  return_type = SQLTypeInfo(kDOUBLE, false);
1407  // Inject ST_DWithin's short-circuiting threshold into ST_MaxDistance
1408  threshold_expr = translateScalarRex(rex_function->getOperand(2));
1409  } else if (function_name == "ST_Equals"sv) {
1410  // Translate ST_Equals(g1,g2) to ST_Distance(g1,g2)<=0.0
1411  CHECK_EQ(size_t(2), rex_function->size());
1412  function_name = "ST_Distance";
1413  return_type = SQLTypeInfo(kDOUBLE, false);
1414  threshold_expr = nullptr;
1415  Datum d;
1416  d.doubleval = 0.0;
1417  compare_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1418  } else if (function_name == "ST_DFullyWithin"sv) {
1419  CHECK_EQ(size_t(3), rex_function->size());
1420  function_name = "ST_MaxDistance";
1421  return_type = SQLTypeInfo(kDOUBLE, false);
1422  // TODO: inject ST_DFullyWithin's short-circuiting threshold into ST_MaxDistance
1423  threshold_expr = nullptr;
1424  } else if (function_name == "ST_Distance"sv) {
1425  // TODO: pick up an outside short-circuiting threshold and inject into ST_Distance
1426  threshold_expr = nullptr;
1427  } else if (function_name == "ST_MaxDistance"sv) {
1428  // TODO: pick up an outside short-circuiting threshold and inject into
1429  // ST_MaxDistance
1430  threshold_expr = nullptr;
1431  } else {
1432  CHECK_EQ(size_t(2), rex_function->size());
1433  }
1434  if (function_name == "ST_Within"sv) {
1435  function_name = "ST_Contains";
1436  swap_args = true;
1437  } else if (function_name == "ST_Disjoint"sv) {
1438  function_name = "ST_Intersects";
1439  negate_result = true;
1440  }
1441  if (func_resolve(
1442  function_name, "ST_Contains"sv, "ST_Intersects"sv, "ST_Approx_Overlaps"sv)) {
1443  with_bounds = true;
1444  }
1445 
1446  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1447  SQLTypeInfo arg0_ti;
1448  SQLTypeInfo arg1_ti;
1449 
1450  // Proactively try to compress the first arg of ST_Intersects to preempt arg swap
1451  bool try_to_compress_arg0 = g_enable_geo_ops_on_uncompressed_coords &&
1452  func_resolve(function_name, "ST_Intersects"sv);
1453 
1454  auto geoargs0 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 1 : 0),
1455  arg0_ti,
1456  with_bounds,
1457  false,
1458  false,
1459  false,
1460  try_to_compress_arg0);
1461  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1462 
1463  // If first arg is compressed, try to compress the second one to be able to
1464  // switch to faster implementations working directly on uncompressed coords
1465  bool try_to_compress_arg1 =
1467  func_resolve(function_name, "ST_Contains"sv, "ST_Intersects"sv) &&
1468  arg0_ti.get_compression() == kENCODING_GEOINT &&
1469  arg0_ti.get_output_srid() == 4326);
1470 
1471  auto geoargs1 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 0 : 1),
1472  arg1_ti,
1473  with_bounds,
1474  false,
1475  false,
1476  false,
1477  try_to_compress_arg1);
1478  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1479 
1480  if (arg0_ti.get_subtype() != kNULLT && arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1481  throw QueryNotSupported(rex_function->getName() +
1482  " accepts either two GEOGRAPHY or two GEOMETRY arguments");
1483  }
1484  // Check SRID match if at least one is set/valid
1485  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1486  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1487  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1488  }
1489  if (compare_expr) {
1490  // We could fold the check to false here if argument geo types are different, e.g.
1491  // POLYGON vs POINT. However, tiny POLYGON could be "spatially" equal to a POINT.
1492  if (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT) {
1493  // ST_Equals is translated to a simple distance check for POINTs,
1494  // otherwise geometries are passed to GEOS's Equals
1495  return nullptr;
1496  }
1497  // Look at POINT compression modes.
1498  if (arg0_ti.get_compression() != arg1_ti.get_compression()) {
1499  if ((arg0_ti.get_compression() == kENCODING_GEOINT &&
1500  arg0_ti.get_comp_param() == 32 &&
1501  arg1_ti.get_compression() == kENCODING_NONE) ||
1502  (arg0_ti.get_compression() == kENCODING_NONE &&
1503  arg1_ti.get_compression() == kENCODING_GEOINT &&
1504  arg0_ti.get_comp_param() == 32)) {
1505  // Spatial equality comparison of a compressed point vs uncompressed point.
1506  // Introduce tolerance into distance calculation and comparison, translate
1507  // ST_Equals(g1,g2) to ST_Distance(g1,g2,thereshold=tolerance)<=tolerance
1508  Datum tolerance;
1509  // Tolerance representing 0.44" to cover shifts due to GEOINT(32) compression
1510  tolerance.doubleval = TOLERANCE_GEOINT32;
1511  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, tolerance);
1512  compare_expr = threshold_expr;
1513  } else {
1514  throw QueryNotSupported(
1515  rex_function->getName() +
1516  " unable to calculate compression tolerance for arguments");
1517  }
1518  }
1519  }
1520  if (arg0_ti.get_type() == kMULTILINESTRING || arg1_ti.get_type() == kMULTILINESTRING) {
1521  throw QueryNotSupported(rex_function->getName() +
1522  " currently doesn't support this argument combination");
1523  }
1524 
1525  auto can_use_compressed_coords = [](const SQLTypeInfo& i0_ti,
1526  const Analyzer::ExpressionPtrVector& i0_operands,
1527  const SQLTypeInfo& i1_ti,
1528  const Analyzer::ExpressionPtrVector& i1_operands) {
1529  const bool i0_is_poly =
1530  i0_ti.get_type() == kPOLYGON || i0_ti.get_type() == kMULTIPOLYGON;
1531  const bool i1_is_point = i1_ti.get_type() == kPOINT;
1532  const bool i1_is_literal =
1533  i1_operands.size() == 1 && std::dynamic_pointer_cast<const Analyzer::Constant>(
1534  i1_operands.front()) != nullptr;
1535  return (i0_is_poly && !i1_is_literal && i1_is_point &&
1536  i0_ti.get_compression() == kENCODING_GEOINT &&
1537  i0_ti.get_input_srid() == i0_ti.get_output_srid() &&
1538  i0_ti.get_compression() == i1_ti.get_compression() &&
1539  i1_ti.get_input_srid() == i1_ti.get_output_srid());
1540  };
1541  if (g_enable_geo_ops_on_uncompressed_coords && function_name == "ST_Contains"sv) {
1542  if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1543  // Switch to Contains implementation working directly on uncompressed coords
1544  function_name = "ST_cContains";
1545  }
1546  }
1547  if (g_enable_geo_ops_on_uncompressed_coords && function_name == "ST_Intersects"sv) {
1548  if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1549  // Switch to Intersects implementation working directly on uncompressed coords
1550  function_name = "ST_cIntersects";
1551  } else if (can_use_compressed_coords(arg1_ti, geoargs1, arg0_ti, geoargs0)) {
1552  // Switch to Intersects implementation working on uncompressed coords, swapped args
1553  function_name = "ST_cIntersects";
1554  geoargs.clear();
1555  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1556  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1557  auto tmp_ti = arg0_ti;
1558  arg0_ti = arg1_ti;
1559  arg1_ti = tmp_ti;
1560  }
1561  }
1562 
1563  std::string specialized_geofunc{function_name + suffix(arg0_ti.get_type()) +
1564  suffix(arg1_ti.get_type())};
1565 
1566  if (arg0_ti.get_subtype() == kGEOGRAPHY && arg0_ti.get_output_srid() == 4326) {
1567  // Need to call geodesic runtime functions
1568  if (function_name == "ST_Distance"sv) {
1569  if ((arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) ||
1570  (arg0_ti.get_type() == kLINESTRING && arg1_ti.get_type() == kPOINT) ||
1571  (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kLINESTRING)) {
1572  // Geodesic distance between points
1573  specialized_geofunc += "_Geodesic"s;
1574  } else {
1575  throw QueryNotSupported(function_name +
1576  " currently doesn't accept non-POINT geographies");
1577  }
1578  } else if (rex_function->getName() == "ST_Contains"sv) {
1579  // We currently don't have a geodesic implementation of ST_Contains,
1580  // allowing calls to a [less precise] cartesian implementation.
1581  } else {
1582  throw QueryNotSupported(function_name + " doesn't accept geographies");
1583  }
1584  } else if (function_name == "ST_Distance"sv && rex_function->size() == 3) {
1585  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1586  // Cartesian distance between points used by ST_DWithin - switch to faster Squared
1587  specialized_geofunc += "_Squared"s;
1588  }
1589  }
1590 
1591  // Add first input's compression mode and SRID args to enable on-the-fly
1592  // decompression/transforms
1593  Datum input_compression0;
1594  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1595  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1596  Datum input_srid0;
1597  input_srid0.intval = arg0_ti.get_input_srid();
1598  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1599 
1600  // Add second input's compression mode and SRID args to enable on-the-fly
1601  // decompression/transforms
1602  Datum input_compression1;
1603  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1604  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1605  Datum input_srid1;
1606  input_srid1.intval = arg1_ti.get_input_srid();
1607  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1608 
1609  // Add output SRID arg to enable on-the-fly transforms
1610  Datum output_srid;
1611  output_srid.intval = arg0_ti.get_output_srid();
1612  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1613 
1614  // Some geo distance functions will be injected with a short-circuit threshold.
1615  // Threshold value would come from Geo comparison operations or from other outer
1616  // geo operations, e.g. ST_DWithin
1617  // At this point, only ST_Distance_LineString_LineString requires a threshold arg.
1618  // TODO: Other combinations that involve LINESTRING, POLYGON and MULTIPOLYGON args
1619  // TODO: Inject threshold into ST_MaxDistance
1620  if (function_name == "ST_Distance"sv && arg0_ti.get_subtype() != kGEOGRAPHY &&
1621  (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT)) {
1622  if (threshold_expr) {
1623  if (threshold_expr->get_type_info().get_type() != kDOUBLE) {
1624  const auto& threshold_ti = SQLTypeInfo(kDOUBLE, false);
1625  threshold_expr = threshold_expr->add_cast(threshold_ti);
1626  }
1627  threshold_expr = fold_expr(threshold_expr.get());
1628  } else {
1629  Datum d;
1630  d.doubleval = 0.0;
1631  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1632  }
1633  geoargs.push_back(threshold_expr);
1634  }
1635 
1636  auto result =
1637  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1638  if (negate_result) {
1639  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, result);
1640  }
1641  if (compare_expr) {
1642  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, result, compare_expr);
1643  }
1644  return result;
1645 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoColumn(const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool expand_geo_col) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
Definition: sqldefs.h:37
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
std::shared_ptr< Analyzer::Expr > ExpressionPtr
Definition: Analyzer.h:184
bool g_enable_geo_ops_on_uncompressed_coords
Definition: Execute.cpp:125
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
#define CHECK_GT(x, y)
Definition: Logger.h:305
int32_t intval
Definition: Datum.h:75
#define TOLERANCE_GEOINT32
std::string suffix(SQLTypes type)
Definition: Codegen.cpp:75
Definition: sqldefs.h:74
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:402
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:395
#define CHECK(condition)
Definition: Logger.h:291
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:186
Definition: sqltypes.h:72
const std::string & getName() const
Definition: RelAlgDag.h:506
Definition: Datum.h:71
Definition: sqldefs.h:41
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
double doubleval
Definition: Datum.h:78
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateBinaryGeoPredicate ( const RexFunctionOperator rex_function,
SQLTypeInfo ti,
const bool  with_bounds 
) const
private

Definition at line 1045 of file RelAlgTranslatorGeo.cpp.

References RexFunctionOperator::getName(), RexOperator::getOperand(), kBOOLEAN, Geospatial::GeoBase::kEQUALS, and translateGeoFunctionArg().

Referenced by translateFunction(), and translateGeoFunctionArg().

1048  {
1049  if (rex_function->getName() != "ST_Equals"sv) {
1050  throw QueryNotSupported(rex_function->getName() + " geo predicate is not supported");
1051  }
1052 #ifndef ENABLE_GEOS
1053  throw QueryNotSupported(rex_function->getName() +
1054  " geo predicate requires enabled GEOS support");
1055 #endif
1056  SQLTypeInfo arg0_ti;
1057  auto geoargs0 =
1058  translateGeoFunctionArg(rex_function->getOperand(0), arg0_ti, false, true, true);
1059  SQLTypeInfo arg1_ti;
1060  auto geoargs1 =
1061  translateGeoFunctionArg(rex_function->getOperand(1), arg1_ti, false, true, true);
1062  ti = SQLTypeInfo(kBOOLEAN, false);
1064  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1065 }
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateBoundingBoxIntersectOper ( const RexOperator rex_operator) const
private

Definition at line 1121 of file RelAlgTranslator.cpp.

References CHECK, RexOperator::getOperand(), RexOperator::getOperator(), kBBOX_INTERSECT, translateGeoBoundingBoxIntersectOper(), and translateScalarRex().

Referenced by translateOper().

1122  {
1123  const auto sql_op = rex_operator->getOperator();
1124  CHECK(sql_op == kBBOX_INTERSECT);
1125 
1126  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
1127  const auto lhs_ti = lhs->get_type_info();
1128  if (lhs_ti.is_geometry()) {
1129  return translateGeoBoundingBoxIntersectOper(rex_operator);
1130  } else {
1131  throw std::runtime_error(
1132  "Bounding Box Intersection equivalence is currently only supported for "
1133  "geospatial types");
1134  }
1135 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
SQLOps getOperator() const
Definition: RelAlgDag.h:376
#define CHECK(condition)
Definition: Logger.h:291
std::shared_ptr< Analyzer::Expr > translateGeoBoundingBoxIntersectOper(const RexOperator *) const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Analyzer::ExpressionPtr RelAlgTranslator::translateCardinality ( const RexFunctionOperator rex_function) const
private

Definition at line 1604 of file RelAlgTranslator.cpp.

References RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), kARRAY, anonymous_namespace{RelAlgTranslator.cpp}::makeNumericConstant(), and translateScalarRex().

Referenced by translateFunction().

1605  {
1606  const auto ret_ti = rex_function->getType();
1607  const auto arg = translateScalarRex(rex_function->getOperand(0));
1608  const auto arg_ti = arg->get_type_info();
1609  if (!arg_ti.is_array()) {
1610  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1611  }
1612  if (arg_ti.get_subtype() == kARRAY) {
1613  throw std::runtime_error(rex_function->getName() +
1614  " expects one-dimension array expression.");
1615  }
1616  const auto array_size = arg_ti.get_size();
1617  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1618 
1619  if (array_size > 0) {
1620  if (array_elem_size <= 0) {
1621  throw std::runtime_error(rex_function->getName() +
1622  ": unexpected array element type.");
1623  }
1624  // Return cardinality of a fixed length array
1625  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1626  }
1627  // Variable length array cardinality will be calculated at runtime
1628  return makeExpr<Analyzer::CardinalityExpr>(arg);
1629 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateCase ( const RexCase rex_case) const
private

Definition at line 1137 of file RelAlgTranslator.cpp.

References RexCase::branchCount(), executor_, RexCase::getElse(), RexCase::getThen(), RexCase::getWhen(), Parser::CaseExpr::normalize(), and translateScalarRex().

1138  {
1139  std::shared_ptr<Analyzer::Expr> else_expr;
1140  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1141  expr_list;
1142  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1143  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
1144  const auto then_expr = translateScalarRex(rex_case->getThen(i));
1145  expr_list.emplace_back(when_expr, then_expr);
1146  }
1147  if (rex_case->getElse()) {
1148  else_expr = translateScalarRex(rex_case->getElse());
1149  }
1150  return Parser::CaseExpr::normalize(expr_list, else_expr, executor_);
1151 }
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:440
static std::shared_ptr< Analyzer::Expr > normalize(const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &, const std::shared_ptr< Analyzer::Expr >, const Executor *executor=nullptr)
const Executor * executor_
const RexScalar * getElse() const
Definition: RelAlgDag.h:445
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:435
size_t branchCount() const
Definition: RelAlgDag.h:433

+ Here is the call graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateCurrentDate ( ) const
private

Definition at line 1640 of file RelAlgTranslator.cpp.

References Datum::bigintval, is_null(), kDATE, and now_.

Referenced by translateFunction().

1640  {
1641  constexpr bool is_null = false;
1642  Datum datum;
1643  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1644  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1645 }
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: Datum.h:76
Definition: sqltypes.h:80
Definition: Datum.h:71

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateCurrentTime ( ) const
private

Definition at line 1647 of file RelAlgTranslator.cpp.

References Datum::bigintval, is_null(), kTIME, and now_.

Referenced by translateFunction().

1647  {
1648  constexpr bool is_null = false;
1649  Datum datum;
1650  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1651  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1652 }
Definition: sqltypes.h:76
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: Datum.h:76
Definition: Datum.h:71

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateCurrentTimestamp ( ) const
private

Definition at line 1654 of file RelAlgTranslator.cpp.

References Parser::TimestampLiteral::get(), and now_.

Referenced by translateDatetime(), and translateFunction().

1654  {
1656 }
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:227

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateCurrentUser ( const RexFunctionOperator rex_function) const
private

Definition at line 1517 of file RelAlgTranslator.cpp.

References Parser::UserLiteral::get(), and query_state_.

Referenced by translateFunction().

1518  {
1519  std::string user{"SESSIONLESS_USER"};
1520  if (query_state_) {
1521  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1522  }
1523  return Parser::UserLiteral::get(user);
1524 }
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:241
std::shared_ptr< const query_state::QueryState > query_state_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateDateadd ( const RexFunctionOperator rex_function) const
private

Definition at line 1340 of file RelAlgTranslator.cpp.

References CHECK_EQ, field(), RexOperator::getOperand(), kBIGINT, kTIME, kTIMESTAMP, RexOperator::size(), to_dateadd_field(), translateScalarRex(), and anonymous_namespace{RelAlgTranslator.cpp}::validate_datetime_datepart_argument().

Referenced by translateFunction().

1341  {
1342  CHECK_EQ(size_t(3), rex_function->size());
1343  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1344  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1346  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1347  const auto number_units_const =
1348  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1349  if (number_units_const && number_units_const->get_is_null()) {
1350  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1351  }
1352  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1353  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1354  const auto& datetime_ti = datetime->get_type_info();
1355  if (datetime_ti.get_type() == kTIME) {
1356  throw std::runtime_error("DateAdd operation not supported for TIME.");
1357  }
1358  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1359  const int dim = datetime_ti.get_dimension();
1360  return makeExpr<Analyzer::DateaddExpr>(
1361  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1362 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Definition: sqltypes.h:76
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
void validate_datetime_datepart_argument(const std::shared_ptr< Analyzer::Constant > literal_expr)
DateaddField to_dateadd_field(const std::string &field)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateDatediff ( const RexFunctionOperator rex_function) const
private

Definition at line 1455 of file RelAlgTranslator.cpp.

References CHECK_EQ, field(), RexOperator::getOperand(), kBIGINT, RexOperator::size(), to_datediff_field(), translateScalarRex(), and anonymous_namespace{RelAlgTranslator.cpp}::validate_datetime_datepart_argument().

Referenced by translateFunction().

1456  {
1457  CHECK_EQ(size_t(3), rex_function->size());
1458  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1459  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1461  const auto start = translateScalarRex(rex_function->getOperand(1));
1462  const auto end = translateScalarRex(rex_function->getOperand(2));
1463  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1464  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1465 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
DatetruncField to_datediff_field(const std::string &field)
void validate_datetime_datepart_argument(const std::shared_ptr< Analyzer::Constant > literal_expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateDatepart ( const RexFunctionOperator rex_function) const
private

Definition at line 1467 of file RelAlgTranslator.cpp.

References CHECK_EQ, ExtractExpr::generate(), RexOperator::getOperand(), RexOperator::size(), to_datepart_field(), translateScalarRex(), and anonymous_namespace{RelAlgTranslator.cpp}::validate_datetime_datepart_argument().

Referenced by translateFunction().

1468  {
1469  CHECK_EQ(size_t(2), rex_function->size());
1470  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1471  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1473  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1474  return ExtractExpr::generate(
1475  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1476 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
ExtractField to_datepart_field(const std::string &field)
const std::shared_ptr< Analyzer::Expr > generate() const
void validate_datetime_datepart_argument(const std::shared_ptr< Analyzer::Constant > literal_expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateDatePlusMinus ( const RexOperator rex_operator) const
private

Definition at line 1373 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, CHECK, daMONTH, daSECOND, dtMONTH, dtSECOND, fold_expr(), anonymous_namespace{RelAlgTranslator.cpp}::get_datetimeplus_rewrite_funcname(), RexOperator::getOperand(), RexOperator::getOperator(), RexOperator::getType(), kBIGINT, kDATE, kDIVIDE, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kMINUS, kMULTIPLY, kONE, kPLUS, kTIME, kTIMESTAMP, kUMINUS, anonymous_namespace{RelAlgTranslator.cpp}::makeNumericConstant(), run_benchmark_import::result, rewrite_to_date_trunc(), RexOperator::size(), and translateScalarRex().

Referenced by translateOper().

1374  {
1375  if (rex_operator->size() != 2) {
1376  return nullptr;
1377  }
1378  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1379  const auto datetime_ti = datetime->get_type_info();
1380  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1381  if (datetime_ti.get_type() == kTIME) {
1382  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1383  }
1384  return nullptr;
1385  }
1386  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1387  const auto rhs_ti = rhs->get_type_info();
1388  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1389  if (datetime_ti.is_high_precision_timestamp() ||
1390  rhs_ti.is_high_precision_timestamp()) {
1391  throw std::runtime_error(
1392  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1393  "Use "
1394  "DATEDIFF.");
1395  }
1396  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1397  const auto& rex_operator_ti = rex_operator->getType();
1398  const auto datediff_field =
1399  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1400  auto result =
1401  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1402  // multiply 1000 to result since expected result should be in millisecond precision.
1403  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1404  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1405  kMULTIPLY,
1406  kONE,
1407  result,
1408  makeNumericConstant(bigint_ti, 1000));
1409  } else {
1410  return result;
1411  }
1412  }
1413  const auto op = rex_operator->getOperator();
1414  if (op == kPLUS) {
1415  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1416  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1417  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1418  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1419  if (date_trunc) {
1420  return date_trunc;
1421  }
1422  }
1423  const auto interval = fold_expr(rhs.get());
1424  auto interval_ti = interval->get_type_info();
1425  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1426  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1427  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1428  std::shared_ptr<Analyzer::Expr> interval_sec;
1429  if (interval_lit) {
1430  interval_sec =
1431  makeNumericConstant(bigint_ti,
1432  (op == kMINUS ? -interval_lit->get_constval().bigintval
1433  : interval_lit->get_constval().bigintval) /
1434  1000);
1435  } else {
1436  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1437  kDIVIDE,
1438  kONE,
1439  interval,
1440  makeNumericConstant(bigint_ti, 1000));
1441  if (op == kMINUS) {
1442  interval_sec =
1443  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1444  }
1445  }
1446  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1447  }
1448  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1449  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1450  bigint_ti, false, kUMINUS, interval)
1451  : interval;
1452  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1453 }
Definition: sqltypes.h:76
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
Definition: sqldefs.h:43
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
SQLOps getOperator() const
Definition: RelAlgDag.h:376
Definition: sqltypes.h:80
Definition: sqldefs.h:42
Definition: sqldefs.h:74
#define CHECK(condition)
Definition: Logger.h:291
std::string get_datetimeplus_rewrite_funcname(const SQLOps &op)
std::shared_ptr< Analyzer::Expr > rewrite_to_date_trunc(const Analyzer::FunctionOper *dt_plus)
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateDatetime ( const RexFunctionOperator rex_function) const
private

Definition at line 1658 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, RexOperator::getOperand(), RexOperator::size(), translateCurrentTimestamp(), and translateScalarRex().

Referenced by translateFunction().

1659  {
1660  CHECK_EQ(size_t(1), rex_function->size());
1661  const auto arg = translateScalarRex(rex_function->getOperand(0));
1662  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1663  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1664  if (!arg_lit || arg_lit->get_is_null()) {
1665  throw std::runtime_error(datetime_err);
1666  }
1667  CHECK(arg_lit->get_type_info().is_string());
1668  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1669  throw std::runtime_error(datetime_err);
1670  }
1671  return translateCurrentTimestamp();
1672 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateCurrentTimestamp() const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateExtract ( const RexFunctionOperator rex_function) const
private

Definition at line 1281 of file RelAlgTranslator.cpp.

References CHECK_EQ, ExtractExpr::generate(), DateTruncExpr::generate(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::size(), translateScalarRex(), and anonymous_namespace{RelAlgTranslator.cpp}::validate_datetime_datepart_argument().

Referenced by translateFunction().

1282  {
1283  CHECK_EQ(size_t(2), rex_function->size());
1284  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1285  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1287  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1288  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1289  if (is_date_trunc) {
1290  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1291  } else {
1292  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1293  }
1294 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
const std::shared_ptr< Analyzer::Expr > generate() const
const std::string & getName() const
Definition: RelAlgDag.h:506
void validate_datetime_datepart_argument(const std::shared_ptr< Analyzer::Constant > literal_expr)
const std::shared_ptr< Analyzer::Expr > generate() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::tuple< bool, bool, std::shared_ptr< Analyzer::Expr > > RelAlgTranslator::translateFrameBoundExpr ( const RexScalar bound_expr) const
private

Definition at line 2231 of file RelAlgTranslator.cpp.

References CHECK, anonymous_namespace{RelAlgTranslator.cpp}::is_negative_framing_bound(), and translateScalarRex().

Referenced by translateWindowFunction().

2231  {
2232  bool negative_constant = false;
2233  if (dynamic_cast<const RexOperator*>(bound_expr)) {
2234  auto translated_expr = translateScalarRex(bound_expr);
2235  const auto bin_oper = dynamic_cast<const Analyzer::BinOper*>(translated_expr.get());
2236  auto time_literal_expr =
2237  dynamic_cast<const Analyzer::Constant*>(bin_oper->get_left_operand());
2238  CHECK(time_literal_expr);
2239  negative_constant =
2240  is_negative_framing_bound(time_literal_expr->get_type_info().get_type(),
2241  time_literal_expr->get_constval(),
2242  true);
2243  return std::make_tuple(false, negative_constant, translated_expr);
2244  } else if (dynamic_cast<const RexLiteral*>(bound_expr)) {
2245  auto translated_expr = translateScalarRex(bound_expr);
2246  if (auto literal_expr =
2247  dynamic_cast<const Analyzer::Constant*>(translated_expr.get())) {
2248  negative_constant = is_negative_framing_bound(
2249  literal_expr->get_type_info().get_type(), literal_expr->get_constval());
2250  return std::make_tuple(false, negative_constant, translated_expr);
2251  }
2252  }
2253  return std::make_tuple(true, negative_constant, nullptr);
2254 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
bool is_negative_framing_bound(const SQLTypes t, const Datum &d, bool is_time_unit=false)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateFunction ( const RexFunctionOperator rex_function) const
private

Definition at line 1788 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, bind_function(), CHECK, CHECK_EQ, CHECK_LE, CHECK_LT, ext_arg_type_to_type_info(), func_resolve, RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Int64, SQLTypeInfo::is_decimal(), kDIVIDE, kONE, kSMALLINT, kTEXT, LOG, Parser::OperExpr::normalize(), PBool, PDouble, PFloat, PInt16, PInt32, PInt64, PInt8, rewrite_to_date_trunc(), SQLTypeInfo::set_notnull(), RexOperator::size(), Datum::smallintval, translateAbs(), translateArrayFunction(), translateBinaryGeoConstructor(), translateBinaryGeoFunction(), translateBinaryGeoPredicate(), translateCardinality(), translateCurrentDate(), translateCurrentTime(), translateCurrentTimestamp(), translateCurrentUser(), translateDateadd(), translateDatediff(), translateDatepart(), translateDatetime(), translateExtract(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoProjection(), translateHPTLiteral(), translateItem(), translateKeyForString(), translateLength(), translateLike(), translateLikely(), translateMLPredict(), translateOffsetInFragment(), translatePCAProject(), translateRegexp(), translateSampleRatio(), translateScalarRex(), translateSign(), translateStringOper(), translateTernaryGeoFunction(), translateUnaryGeoConstructor(), translateUnaryGeoFunction(), translateUnaryGeoPredicate(), translateUnlikely(), translateWidthBucket(), and logger::WARNING.

1789  {
1790  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1791  return translateLike(rex_function);
1792  }
1793  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1794  return translateRegexp(rex_function);
1795  }
1796  if (rex_function->getName() == "LIKELY"sv) {
1797  return translateLikely(rex_function);
1798  }
1799  if (rex_function->getName() == "UNLIKELY"sv) {
1800  return translateUnlikely(rex_function);
1801  }
1802  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1803  return translateExtract(rex_function);
1804  }
1805  if (rex_function->getName() == "DATEADD"sv) {
1806  return translateDateadd(rex_function);
1807  }
1808  if (rex_function->getName() == "DATEDIFF"sv) {
1809  return translateDatediff(rex_function);
1810  }
1811  if (rex_function->getName() == "DATEPART"sv) {
1812  return translateDatepart(rex_function);
1813  }
1814  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1815  return translateLength(rex_function);
1816  }
1817  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1818  return translateKeyForString(rex_function);
1819  }
1820  if (rex_function->getName() == "WIDTH_BUCKET"sv) {
1821  return translateWidthBucket(rex_function);
1822  }
1823  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1824  return translateSampleRatio(rex_function);
1825  }
1826  if (rex_function->getName() == "CURRENT_USER"sv) {
1827  return translateCurrentUser(rex_function);
1828  }
1829  if (rex_function->getName() == "ML_PREDICT"sv) {
1830  return translateMLPredict(rex_function);
1831  }
1832  if (rex_function->getName() == "PCA_PROJECT"sv) {
1833  return translatePCAProject(rex_function);
1834  }
1835  if (func_resolve(rex_function->getName(),
1836  "LOWER"sv,
1837  "UPPER"sv,
1838  "INITCAP"sv,
1839  "REVERSE"sv,
1840  "REPEAT"sv,
1841  "||"sv,
1842  "LPAD"sv,
1843  "RPAD"sv,
1844  "TRIM"sv,
1845  "LTRIM"sv,
1846  "RTRIM"sv,
1847  "SUBSTRING"sv,
1848  "OVERLAY"sv,
1849  "REPLACE"sv,
1850  "SPLIT_PART"sv,
1851  "REGEXP_REPLACE"sv,
1852  "REGEXP_SUBSTR"sv,
1853  "REGEXP_MATCH"sv,
1854  "REGEXP_COUNT"sv,
1855  "JSON_VALUE"sv,
1856  "BASE64_ENCODE"sv,
1857  "BASE64_DECODE"sv,
1858  "URL_ENCODE"sv,
1859  "URL_DECODE"sv,
1860  "TRY_CAST"sv,
1861  "POSITION"sv,
1862  "JAROWINKLER_SIMILARITY"sv,
1863  "LEVENSHTEIN_DISTANCE"sv,
1864  "HASH"sv)) {
1865  return translateStringOper(rex_function);
1866  }
1867  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1868  return translateCardinality(rex_function);
1869  }
1870  if (rex_function->getName() == "ITEM"sv) {
1871  return translateItem(rex_function);
1872  }
1873  if (rex_function->getName() == "CURRENT_DATE"sv) {
1874  return translateCurrentDate();
1875  }
1876  if (rex_function->getName() == "CURRENT_TIME"sv) {
1877  return translateCurrentTime();
1878  }
1879  if (rex_function->getName() == "CURRENT_TIMESTAMP"sv) {
1880  return translateCurrentTimestamp();
1881  }
1882  if (rex_function->getName() == "NOW"sv) {
1883  return translateCurrentTimestamp();
1884  }
1885  if (rex_function->getName() == "DATETIME"sv) {
1886  return translateDatetime(rex_function);
1887  }
1888  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1889  return translateHPTLiteral(rex_function);
1890  }
1891  if (rex_function->getName() == "ABS"sv) {
1892  return translateAbs(rex_function);
1893  }
1894  if (rex_function->getName() == "SIGN"sv) {
1895  return translateSign(rex_function);
1896  }
1897  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1898  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1899  rex_function->getType(),
1900  rex_function->getName(),
1901  translateFunctionArgs(rex_function));
1902  } else if (rex_function->getName() == "ROUND"sv) {
1903  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1904  translateFunctionArgs(rex_function);
1905 
1906  if (rex_function->size() == 1) {
1907  // push a 0 constant if 2nd operand is missing.
1908  // this needs to be done as calcite returns
1909  // only the 1st operand without defaulting the 2nd one
1910  // when the user did not specify the 2nd operand.
1911  SQLTypes t = kSMALLINT;
1912  Datum d;
1913  d.smallintval = 0;
1914  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1915  }
1916 
1917  // make sure we have only 2 operands
1918  CHECK(args.size() == 2);
1919 
1920  if (!args[0]->get_type_info().is_number()) {
1921  throw std::runtime_error("Only numeric 1st operands are supported");
1922  }
1923 
1924  // the 2nd operand does not need to be a constant
1925  // it can happily reference another integer column
1926  if (!args[1]->get_type_info().is_integer()) {
1927  throw std::runtime_error("Only integer 2nd operands are supported");
1928  }
1929 
1930  // Calcite may upcast decimals in a way that is
1931  // incompatible with the extension function input. Play it safe and stick with the
1932  // argument type instead.
1933  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1934  ? args[0]->get_type_info()
1935  : rex_function->getType();
1936 
1937  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1938  ret_ti, rex_function->getName(), args);
1939  }
1940  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1941  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1942  rex_function->getName(),
1943  translateFunctionArgs(rex_function));
1944  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1945  if (date_trunc) {
1946  return date_trunc;
1947  }
1948  return translateDateadd(rex_function);
1949  }
1950  if (rex_function->getName() == "/INT"sv) {
1951  CHECK_EQ(size_t(2), rex_function->size());
1952  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1953  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1954  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1955  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1956  }
1957  if (rex_function->getName() == "Reinterpret"sv) {
1958  CHECK_EQ(size_t(1), rex_function->size());
1959  return translateScalarRex(rex_function->getOperand(0));
1960  }
1961  if (func_resolve(rex_function->getName(),
1962  "ST_X"sv,
1963  "ST_Y"sv,
1964  "ST_XMin"sv,
1965  "ST_YMin"sv,
1966  "ST_XMax"sv,
1967  "ST_YMax"sv,
1968  "ST_NRings"sv,
1969  "ST_NumGeometries"sv,
1970  "ST_NPoints"sv,
1971  "ST_Length"sv,
1972  "ST_Perimeter"sv,
1973  "ST_Area"sv,
1974  "ST_SRID"sv,
1975  "HeavyDB_Geo_PolyBoundsPtr"sv)) {
1976  CHECK_EQ(rex_function->size(), size_t(1));
1977  return translateUnaryGeoFunction(rex_function);
1978  }
1979  if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
1980  CHECK_EQ(rex_function->size(), size_t(1));
1981  SQLTypeInfo ti;
1982  return translateUnaryGeoConstructor(rex_function, ti, false);
1983  }
1984  if (func_resolve(rex_function->getName(),
1985  "convert_meters_to_pixel_width"sv,
1986  "convert_meters_to_pixel_height"sv,
1987  "is_point_in_view"sv,
1988  "is_point_size_in_view"sv)) {
1989  return translateFunctionWithGeoArg(rex_function);
1990  }
1991  if (func_resolve(rex_function->getName(),
1992  "ST_Distance"sv,
1993  "ST_MaxDistance"sv,
1994  "ST_Intersects"sv,
1995  "ST_Disjoint"sv,
1996  "ST_Contains"sv,
1997  "ST_IntersectsBox"sv,
1998  "ST_Approx_Overlaps"sv,
1999  "ST_Within"sv)) {
2000  CHECK_EQ(rex_function->size(), size_t(2));
2001  return translateBinaryGeoFunction(rex_function);
2002  }
2003  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
2004  CHECK_EQ(rex_function->size(), size_t(3));
2005  return translateTernaryGeoFunction(rex_function);
2006  }
2007  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
2008  CHECK_EQ(size_t(0), rex_function->size());
2009  return translateOffsetInFragment();
2010  }
2011  if (rex_function->getName() == "ARRAY"sv) {
2012  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
2013  return translateArrayFunction(rex_function);
2014  }
2015  if (func_resolve(rex_function->getName(),
2016  "ST_GeomFromText"sv,
2017  "ST_GeogFromText"sv,
2018  "ST_Centroid"sv,
2019  "ST_SetSRID"sv,
2020  "ST_Point"sv, // TODO: where should this and below live?
2021  "ST_PointN"sv,
2022  "ST_StartPoint"sv,
2023  "ST_EndPoint"sv,
2024  "ST_Transform"sv)) {
2025  SQLTypeInfo ti;
2026  return translateGeoProjection(rex_function, ti, false);
2027  }
2028  if (func_resolve(rex_function->getName(),
2029  "ST_Intersection"sv,
2030  "ST_Difference"sv,
2031  "ST_Union"sv,
2032  "ST_Buffer"sv,
2033  "ST_ConcaveHull"sv)) {
2034  CHECK_EQ(rex_function->size(), size_t(2));
2035  SQLTypeInfo ti;
2036  return translateBinaryGeoConstructor(rex_function, ti, false);
2037  }
2038  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
2039  CHECK_EQ(rex_function->size(), size_t(1));
2040  SQLTypeInfo ti;
2041  return translateUnaryGeoPredicate(rex_function, ti, false);
2042  }
2043  if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
2044  CHECK_EQ(rex_function->size(), size_t(2));
2045  // Attempt to generate a distance based check for points
2046  if (auto distance_check = translateBinaryGeoFunction(rex_function)) {
2047  return distance_check;
2048  }
2049  SQLTypeInfo ti;
2050  return translateBinaryGeoPredicate(rex_function, ti, false);
2051  }
2052 
2053  auto arg_expr_list = translateFunctionArgs(rex_function);
2054  if (rex_function->getName() == std::string("||") ||
2055  rex_function->getName() == std::string("SUBSTRING")) {
2056  SQLTypeInfo ret_ti(kTEXT, false);
2057  return makeExpr<Analyzer::FunctionOper>(
2058  ret_ti, rex_function->getName(), arg_expr_list);
2059  }
2060 
2061  // Reset possibly wrong return type of rex_function to the return
2062  // type of the optimal valid implementation. The return type can be
2063  // wrong in the case of multiple implementations of UDF functions
2064  // that have different return types but Calcite specifies the return
2065  // type according to the first implementation.
2066  SQLTypeInfo ret_ti;
2067  try {
2068  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
2069  auto ext_func_args = ext_func_sig.getInputArgs();
2070  CHECK_LE(arg_expr_list.size(), ext_func_args.size());
2071  for (size_t i = 0, di = 0; i < arg_expr_list.size(); i++) {
2072  CHECK_LT(i + di, ext_func_args.size());
2073  auto ext_func_arg = ext_func_args[i + di];
2074  if (ext_func_arg == ExtArgumentType::PInt8 ||
2075  ext_func_arg == ExtArgumentType::PInt16 ||
2076  ext_func_arg == ExtArgumentType::PInt32 ||
2077  ext_func_arg == ExtArgumentType::PInt64 ||
2078  ext_func_arg == ExtArgumentType::PFloat ||
2079  ext_func_arg == ExtArgumentType::PDouble ||
2080  ext_func_arg == ExtArgumentType::PBool) {
2081  di++;
2082  // pointer argument follows length argument:
2083  CHECK(ext_func_args[i + di] == ExtArgumentType::Int64);
2084  }
2085  // fold casts on constants
2086  if (auto constant =
2087  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
2088  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_arg);
2089  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
2090  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
2091  }
2092  }
2093  }
2094 
2095  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
2096  } catch (ExtensionFunctionBindingError& e) {
2097  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
2098  throw;
2099  }
2100 
2101  // By default, the extension function type will not allow nulls. If one of the
2102  // arguments is nullable, the extension function must also explicitly allow nulls.
2103  bool arguments_not_null = true;
2104  for (const auto& arg_expr : arg_expr_list) {
2105  if (!arg_expr->get_type_info().get_notnull()) {
2106  arguments_not_null = false;
2107  break;
2108  }
2109  }
2110  ret_ti.set_notnull(arguments_not_null);
2111 
2112  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
2113 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateOffsetInFragment() const
std::shared_ptr< Analyzer::Expr > translateCurrentTimestamp() const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::shared_ptr< Analyzer::Expr > translateRegexp(const RexFunctionOperator *) const
SQLTypes
Definition: sqltypes.h:65
std::shared_ptr< Analyzer::Expr > translateUnlikely(const RexFunctionOperator *) const
#define LOG(tag)
Definition: Logger.h:285
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
std::shared_ptr< Analyzer::Expr > translateDateadd(const RexFunctionOperator *) const
static std::shared_ptr< Analyzer::Expr > normalize(const SQLOps optype, const SQLQualifier qual, std::shared_ptr< Analyzer::Expr > left_expr, std::shared_ptr< Analyzer::Expr > right_expr, const Executor *executor=nullptr)
Definition: ParserNode.cpp:380
std::shared_ptr< Analyzer::Expr > translateAbs(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateItem(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateGeoProjection(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::shared_ptr< Analyzer::Expr > translateDatediff(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateSign(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatetime(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateStringOper(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateCurrentTime() const
int16_t smallintval
Definition: Datum.h:74
std::tuple< T, std::vector< SQLTypeInfo > > bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< T > &ext_funcs, const std::string processor)
std::shared_ptr< Analyzer::Expr > translatePCAProject(const RexFunctionOperator *) const
#define CHECK_LT(x, y)
Definition: Logger.h:303
Definition: sqltypes.h:79
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
Definition: sqldefs.h:74
#define CHECK_LE(x, y)
Definition: Logger.h:304
std::shared_ptr< Analyzer::Expr > translateUnaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::shared_ptr< Analyzer::Expr > translateArrayFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateMLPredict(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateCurrentUser(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateSampleRatio(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateLike(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateLikely(const RexFunctionOperator *) const
void set_notnull(bool n)
Definition: sqltypes.h:477
#define CHECK(condition)
Definition: Logger.h:291
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateWidthBucket(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateFunctionWithGeoArg(const RexFunctionOperator *) const
const std::string & getName() const
Definition: RelAlgDag.h:506
std::shared_ptr< Analyzer::Expr > translateCurrentDate() const
std::shared_ptr< Analyzer::Expr > translateCardinality(const RexFunctionOperator *) const
Definition: Datum.h:71
bool is_decimal() const
Definition: sqltypes.h:570
std::shared_ptr< Analyzer::Expr > translateHPTLiteral(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatepart(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::shared_ptr< Analyzer::Expr > rewrite_to_date_trunc(const Analyzer::FunctionOper *dt_plus)
SQLTypeInfo ext_arg_type_to_type_info(const ExtArgumentType ext_arg_type)
std::shared_ptr< Analyzer::Expr > translateKeyForString(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateLength(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateExtract(const RexFunctionOperator *) const

+ Here is the call graph for this function:

Analyzer::ExpressionPtrVector RelAlgTranslator::translateFunctionArgs ( const RexFunctionOperator rex_function) const
private

Definition at line 2818 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, RexOperator::getOperand(), RexOperator::size(), and translateScalarRex().

Referenced by translateArrayFunction(), translateFunction(), translateKeyForString(), and translateStringOper().

2819  {
2820  std::vector<std::shared_ptr<Analyzer::Expr>> args;
2821  for (size_t i = 0; i < rex_function->size(); ++i) {
2822  args.push_back(translateScalarRex(rex_function->getOperand(i)));
2823  }
2824  return args;
2825 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateFunctionWithGeoArg ( const RexFunctionOperator rex_function) const
private

Definition at line 1773 of file RelAlgTranslatorGeo.cpp.

References run_benchmark_import::args, CHECK, CHECK_EQ, func_resolve, Geospatial::get_compression_scheme(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Datum::intval, kINT, kPOINT, RexOperator::size(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction().

1774  {
1775  std::string specialized_geofunc{rex_function->getName()};
1776  if (func_resolve(rex_function->getName(),
1777  "convert_meters_to_pixel_width"sv,
1778  "convert_meters_to_pixel_height"sv)) {
1779  CHECK_EQ(rex_function->size(), 6u);
1780  SQLTypeInfo arg_ti;
1781  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1782  args.push_back(translateScalarRex(rex_function->getOperand(0)));
1783  auto geoargs =
1784  translateGeoFunctionArg(rex_function->getOperand(1), arg_ti, false, false);
1785  // only works on points
1786  if (arg_ti.get_type() != kPOINT) {
1787  throw QueryNotSupported(rex_function->getName() +
1788  " expects a point for the second argument");
1789  }
1790 
1791  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1792 
1793  // Add compression information
1794  Datum input_compression;
1795  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1796  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1797  if (arg_ti.get_input_srid() != 4326) {
1798  throw QueryNotSupported(
1799  rex_function->getName() +
1800  " currently only supports points of with SRID WGS84/EPSG:4326");
1801  }
1802  Datum input_srid;
1803  input_srid.intval = arg_ti.get_input_srid();
1804  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1805  Datum output_srid;
1806  // Forcing web-mercator projection for now
1807  // TODO(croot): check that the input-to-output conversion routines exist?
1808  output_srid.intval =
1809  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1810  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1811 
1812  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1813  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1814  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1815  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1816  return makeExpr<Analyzer::FunctionOper>(
1817  rex_function->getType(), specialized_geofunc, args);
1818  } else if (rex_function->getName() == "is_point_in_view"sv) {
1819  CHECK_EQ(rex_function->size(), 5u);
1820  SQLTypeInfo arg_ti;
1821  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1822  auto geoargs =
1823  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, false);
1824  // only works on points
1825  if (arg_ti.get_type() != kPOINT) {
1826  throw QueryNotSupported(rex_function->getName() +
1827  " expects a point for the second argument");
1828  }
1829 
1830  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1831 
1832  // Add compression information
1833  Datum input_compression;
1834  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1835  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1836  if (arg_ti.get_input_srid() != 4326) {
1837  throw QueryNotSupported(
1838  rex_function->getName() +
1839  " currently only supports points of with SRID WGS84/EPSG:4326");
1840  }
1841  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1842  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1843  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1844  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1845  return makeExpr<Analyzer::FunctionOper>(
1846  rex_function->getType(), specialized_geofunc, args);
1847  } else if (rex_function->getName() == "is_point_size_in_view"sv) {
1848  CHECK_EQ(rex_function->size(), 6u);
1849  SQLTypeInfo arg_ti;
1850  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1851  auto geoargs =
1852  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, false);
1853  // only works on points
1854  if (arg_ti.get_type() != kPOINT) {
1855  throw QueryNotSupported(rex_function->getName() +
1856  " expects a point for the second argument");
1857  }
1858 
1859  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1860 
1861  // Add compression information
1862  Datum input_compression;
1863  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1864  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1865  if (arg_ti.get_input_srid() != 4326) {
1866  throw QueryNotSupported(
1867  rex_function->getName() +
1868  " currently only supports points of with SRID WGS84/EPSG:4326");
1869  }
1870  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1871  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1872  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1873  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1874  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1875  return makeExpr<Analyzer::FunctionOper>(
1876  rex_function->getType(), specialized_geofunc, args);
1877  }
1878  CHECK(false);
1879  return nullptr;
1880 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
int32_t intval
Definition: Datum.h:75
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
const std::string & getName() const
Definition: RelAlgDag.h:506
Definition: Datum.h:71

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateGeoBoundingBoxIntersectOper ( const RexOperator rex_operator) const
private

Definition at line 1882 of file RelAlgTranslatorGeo.cpp.

References CHECK, CHECK_EQ, CHECK_GT, SQLTypeInfo::get_type(), RexOperator::getOperand(), kBBOX_INTERSECT, kBOOLEAN, kONE, kPOINT, RexOperator::size(), and translateGeoColumn().

Referenced by translateBoundingBoxIntersectOper().

1883  {
1884  CHECK_EQ(rex_operator->size(), 2u);
1885 
1886  auto translate_input =
1887  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1888  const auto input = dynamic_cast<const RexInput*>(operand);
1889  CHECK(input);
1890 
1891  SQLTypeInfo ti;
1892  const auto exprs = translateGeoColumn(input, ti, true, false);
1893  CHECK_GT(exprs.size(), 0u);
1894  if (ti.get_type() == kPOINT) {
1895  return exprs.front();
1896  } else {
1897  return exprs.back();
1898  }
1899  };
1900 
1901  SQLQualifier sql_qual{kONE};
1902  SQLOps sql_op{kBBOX_INTERSECT};
1903  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
1904  false,
1905  sql_op,
1906  sql_qual,
1907  translate_input(rex_operator->getOperand(1)),
1908  translate_input(rex_operator->getOperand(0)));
1909 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoColumn(const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool expand_geo_col) const
SQLQualifier
Definition: sqldefs.h:74
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
SQLOps
Definition: sqldefs.h:31
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
#define CHECK_GT(x, y)
Definition: Logger.h:305
Definition: sqldefs.h:74
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< std::shared_ptr< Analyzer::Expr > > RelAlgTranslator::translateGeoColumn ( const RexInput rex_input,
SQLTypeInfo ti,
const bool  with_bounds,
const bool  expand_geo_col 
) const
private

Definition at line 28 of file RelAlgTranslatorGeo.cpp.

References run_benchmark_import::args, CHECK, CHECK_GE, CHECK_LT, SQLTypeInfo::get_physical_coord_cols(), SQLTypeInfo::get_type(), RexAbstractInput::getIndex(), RexInput::getSourceNode(), SQLTypeInfo::has_bounds(), input_to_nest_level_, IS_GEO, and SPIMAP_GEO_PHYSICAL_INPUT.

Referenced by translateBinaryGeoFunction(), translateGeoBoundingBoxIntersectOper(), and translateGeoFunctionArg().

32  {
33  std::vector<std::shared_ptr<Analyzer::Expr>> args;
34  const auto source = rex_input->getSourceNode();
35  const auto it_rte_idx = input_to_nest_level_.find(source);
36  CHECK(it_rte_idx != input_to_nest_level_.end());
37  const int rte_idx = it_rte_idx->second;
38  const auto& in_metainfo = source->getOutputMetainfo();
39 
40  int32_t db_id{0};
41  int32_t table_id{0};
42  int column_id{-1};
43  const Catalog_Namespace::Catalog* catalog{nullptr};
44  const auto scan_source = dynamic_cast<const RelScan*>(source);
45  if (scan_source) {
46  // We're at leaf (scan) level and not supposed to have input metadata,
47  // the name and type information come directly from the catalog.
48  CHECK(in_metainfo.empty());
49 
50  const auto td = scan_source->getTableDescriptor();
51  table_id = td->tableId;
52 
53  catalog = &scan_source->getCatalog();
54  db_id = catalog->getDatabaseId();
55  const auto gcd =
56  catalog->getMetadataForColumnBySpi(table_id, rex_input->getIndex() + 1);
57  CHECK(gcd);
58  ti = gcd->columnType;
59  column_id = gcd->columnId;
60 
61  } else {
62  // Likely backed by a temp table. Read the table ID from the source node and negate it
63  // (see RelAlgTranslator::translateInput)
64  table_id = -source->getId();
65 
66  if (with_bounds) {
67  throw QueryNotSupported(
68  "Geospatial columns not yet supported in intermediate results.");
69  }
70 
71  CHECK(!in_metainfo.empty());
72  CHECK_GE(rte_idx, 0);
73  column_id = rex_input->getIndex();
74  CHECK_LT(static_cast<size_t>(column_id), in_metainfo.size());
75  ti = in_metainfo[column_id].get_type_info();
76  if (expand_geo_col && ti.is_geometry()) {
77  throw QueryNotSupported(
78  "Geospatial columns not yet supported in this temporary table context.");
79  }
80  }
81 
82  if (!IS_GEO(ti.get_type())) {
83  throw QueryNotSupported(
84  "Geospatial expression and operator require geospatial column as their input "
85  "argument(s)");
86  }
87 
88  // Return geo column reference. The geo column may be expanded if required for extension
89  // function arguments. Otherwise, the geo column reference will be translated into
90  // physical columns as required. Bounds column will be added if present and requested.
91  if (expand_geo_col) {
92  for (auto i = 0; i < ti.get_physical_coord_cols(); i++) {
93  CHECK(catalog);
94  const auto pcd = catalog->getMetadataForColumnBySpi(
95  table_id, SPIMAP_GEO_PHYSICAL_INPUT(rex_input->getIndex(), i + 1));
96  auto pcol_ti = pcd->columnType;
97  args.push_back(std::make_shared<Analyzer::ColumnVar>(
98  pcol_ti, shared::ColumnKey{db_id, table_id, pcd->columnId}, rte_idx));
99  }
100  } else {
101  args.push_back(std::make_shared<Analyzer::ColumnVar>(
102  ti, shared::ColumnKey{db_id, table_id, column_id}, rte_idx));
103  }
104  if (with_bounds && ti.has_bounds()) {
105  CHECK(catalog);
106  const auto bounds_cd = catalog->getMetadataForColumnBySpi(
107  table_id,
108  SPIMAP_GEO_PHYSICAL_INPUT(rex_input->getIndex(),
109  ti.get_physical_coord_cols() + 1));
110  auto bounds_ti = bounds_cd->columnType;
111  args.push_back(std::make_shared<Analyzer::ColumnVar>(
112  bounds_ti, shared::ColumnKey{db_id, table_id, bounds_cd->columnId}, rte_idx));
113  }
114  return args;
115 }
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:143
#define SPIMAP_GEO_PHYSICAL_INPUT(c, i)
Definition: Catalog.h:84
#define CHECK_GE(x, y)
Definition: Logger.h:306
unsigned getIndex() const
Definition: RelAlgDag.h:174
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:303
const RelAlgNode * getSourceNode() const
Definition: RelAlgDag.h:1056
#define CHECK(condition)
Definition: Logger.h:291
#define IS_GEO(T)
Definition: sqltypes.h:310

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateGeoComparison ( const RexOperator rex_operator) const
private

Definition at line 1752 of file RelAlgTranslatorGeo.cpp.

References fold_expr(), RexOperator::getOperand(), RexOperator::getOperator(), kBOOLEAN, kDOUBLE, kONE, RexOperator::size(), and translateScalarRex().

Referenced by translateOper().

1753  {
1754  if (rex_operator->size() != size_t(2)) {
1755  return nullptr;
1756  }
1757 
1758  auto geo_distance_expr = translateScalarRex(rex_operator->getOperand(0));
1759  auto func_oper = dynamic_cast<Analyzer::GeoOperator*>(geo_distance_expr.get());
1760  if (func_oper && func_oper->getName() == "ST_Distance"sv) {
1761  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1762  auto distance_expr = translateScalarRex(rex_operator->getOperand(1));
1763  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1764  distance_expr = distance_expr->add_cast(distance_ti);
1765  }
1766  distance_expr = fold_expr(distance_expr.get());
1767  return makeExpr<Analyzer::BinOper>(
1768  kBOOLEAN, rex_operator->getOperator(), kONE, geo_distance_expr, distance_expr);
1769  }
1770  return nullptr;
1771 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
SQLOps getOperator() const
Definition: RelAlgDag.h:376
Definition: sqldefs.h:74
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< std::shared_ptr< Analyzer::Expr > > RelAlgTranslator::translateGeoFunctionArg ( const RexScalar rex_scalar,
SQLTypeInfo arg_ti,
const bool  with_bounds,
const bool  expand_geo_col,
const bool  is_projection = false,
const bool  use_geo_expressions = false,
const bool  try_to_compress = false,
const bool  allow_gdal_transforms = false 
) const
private

Definition at line 273 of file RelAlgTranslatorGeo.cpp.

References run_benchmark_import::args, CHECK, CHECK_EQ, CHECK_GE, Geospatial::GeoTypesFactory::createGeoType(), fold_expr(), func_resolve, SQLTypeInfo::get_compression(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_subtype(), Analyzer::anonymous_namespace{Analyzer.cpp}::get_ti_from_geo(), SQLTypeInfo::get_type(), IS_GEO, anonymous_namespace{RelAlgExecutor.cpp}::is_projection(), IS_STRING, spatial_type::Transform::isUtm(), kARRAY, kCAST, kDOUBLE, kENCODING_GEOINT, kENCODING_NONE, kGEOGRAPHY, kGEOMETRY, kINT, kLINESTRING, kNULLT, kPOINT, kSMALLINT, kTEXT, kTINYINT, SQLTypeInfo::set_comp_param(), SQLTypeInfo::set_compression(), SQLTypeInfo::set_input_srid(), SQLTypeInfo::set_notnull(), SQLTypeInfo::set_output_srid(), SQLTypeInfo::set_subtype(), SQLTypeInfo::set_type(), to_string(), translateBinaryGeoConstructor(), translateBinaryGeoPredicate(), translateGeoColumn(), translateGeoLiteral(), translateInput(), translateLiteral(), translateScalarRex(), translateUnaryGeoConstructor(), and translateUnaryGeoPredicate().

Referenced by translateBinaryGeoConstructor(), translateBinaryGeoFunction(), translateBinaryGeoPredicate(), translateFunctionWithGeoArg(), translateGeoProjection(), translateTernaryGeoFunction(), translateUnaryGeoConstructor(), translateUnaryGeoFunction(), and translateUnaryGeoPredicate().

281  {
282  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
283 
284  const auto rex_input = dynamic_cast<const RexInput*>(rex_scalar);
285  if (rex_input) {
286  const auto input = translateInput(rex_input);
287  const auto column = dynamic_cast<const Analyzer::ColumnVar*>(input.get());
288  if (!column || !column->get_type_info().is_geometry()) {
289  throw QueryNotSupported("Geo function is expecting a geo column argument");
290  }
291  if (use_geo_expressions) {
292  arg_ti = column->get_type_info();
293  return {makeExpr<Analyzer::GeoColumnVar>(column, with_bounds)};
294  }
295  return translateGeoColumn(rex_input, arg_ti, with_bounds, expand_geo_col);
296  }
297  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_scalar);
298  if (rex_function) {
299  if (rex_function->getName() == "ST_Transform"sv) {
300  CHECK_EQ(size_t(2), rex_function->size());
301  const auto rex_scalar0 =
302  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
303  if (!rex_scalar0) {
304  throw QueryNotSupported(rex_function->getName() + ": unexpected first argument");
305  }
306 
307  const auto rex_literal =
308  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
309  if (!rex_literal) {
310  throw QueryNotSupported(rex_function->getName() +
311  ": second argument is expected to be a literal");
312  }
313  const auto e = translateLiteral(rex_literal);
314  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
315  if (!ce || !e->get_type_info().is_integer()) {
316  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
317  }
318  int32_t srid = 0;
319  if (e->get_type_info().get_type() == kSMALLINT) {
320  srid = static_cast<int32_t>(ce->get_constval().smallintval);
321  } else if (e->get_type_info().get_type() == kTINYINT) {
322  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
323  } else if (e->get_type_info().get_type() == kINT) {
324  srid = static_cast<int32_t>(ce->get_constval().intval);
325  } else {
326  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
327  }
328  bool allow_result_gdal_transform = false;
329  const auto rex_function0 = dynamic_cast<const RexFunctionOperator*>(rex_scalar0);
330  if (rex_function0 && func_resolve(rex_function0->getName(),
331  "ST_Intersection"sv,
332  "ST_Difference"sv,
333  "ST_Union"sv,
334  "ST_Buffer"sv,
335  "ST_ConcaveHull"sv,
336  "ST_ConvexHull"sv)) {
337  // TODO: the design of geo operators currently doesn't allow input srid overrides.
338  // For example, in case of ST_Area(ST_Transform(ST_Buffer(geo_column,0), 900913))
339  // we can ask geos runtime to transform ST_Buffer's output from 4326 to 900913,
340  // however, ST_Area geo operator would still rely on the first arg's typeinfo
341  // to codegen srid arg values in the ST_Area_ extension function call. And it will
342  // still pick up that transform so the coords will be transformed to 900913 twice.
343 
344  // Sink result transform into geos runtime
345  // allow_result_gdal_transform = true;
346  }
347  if (!allow_gdal_transforms && !allow_result_gdal_transform) {
348  if (srid != 900913 && ((use_geo_expressions || is_projection) && srid != 4326 &&
350  throw QueryNotSupported(rex_function->getName() + ": unsupported output SRID " +
351  std::to_string(srid));
352  }
353  }
354  arg_ti.set_output_srid(srid); // Forward output srid down to argument translation
355  bool arg0_use_geo_expressions = is_projection ? true : use_geo_expressions;
356  if (allow_gdal_transforms) {
357  arg0_use_geo_expressions = false;
358  }
359  auto arg0 = translateGeoFunctionArg(rex_scalar0,
360  arg_ti,
361  with_bounds,
362  expand_geo_col,
364  arg0_use_geo_expressions);
365 
366  if (use_geo_expressions) {
367  CHECK_EQ(arg0.size(), size_t(1));
368  auto arg0_ti = arg0.front()->get_type_info(); // make a copy so we can override
369  arg0_ti.set_output_srid(srid);
370  if (arg0_ti.get_type() == kPOINT) {
371  // the output type is going to be fully transformed, so set the input srid to
372  // the output srid
373  const auto input_srid = arg0_ti.get_input_srid();
374  arg0_ti.set_input_srid(srid);
375  // geo transforms projections leave the result decompressed in a register
376  arg0_ti.set_compression(kENCODING_NONE);
377  arg0_ti.set_comp_param(0);
378  // reset recursive arg_ti, as the output type of transform will be properly
379  // transformed to the desired SRID
380  arg_ti.set_output_srid(srid);
381  arg_ti.set_input_srid(srid);
382  return {makeExpr<Analyzer::GeoTransformOperator>(
383  arg0_ti, rex_function->getName(), arg0, input_srid, srid)};
384  } else {
385  if (auto geo_constant =
386  std::dynamic_pointer_cast<Analyzer::GeoConstant>(arg0.front())) {
387  // fold transform
388  auto cast_geo_constant = geo_constant->add_cast(arg0_ti);
389  // update return type info
390  arg_ti = cast_geo_constant->get_type_info();
391  return {cast_geo_constant};
392  } else if (auto col_var =
393  std::dynamic_pointer_cast<Analyzer::ColumnVar>(arg0.front())) {
394  const auto& col_ti = col_var->get_type_info();
395  CHECK(col_ti.is_geometry());
396  if (col_ti.get_type() != kPOINT) {
397  arg_ti.set_input_srid(col_ti.get_input_srid());
398  // fall through to transform code below
399  }
400  } else {
401  if (!allow_gdal_transforms && !allow_result_gdal_transform) {
402  throw std::runtime_error(
403  "Transform on non-POINT geospatial types not yet supported in this "
404  "context.");
405  }
406  }
407  }
408  }
409 
410  if (arg_ti.get_input_srid() > 0) {
411  if (!allow_gdal_transforms && !allow_result_gdal_transform) {
412  if (arg_ti.get_input_srid() != 4326) {
413  throw QueryNotSupported(rex_function->getName() +
414  ": unsupported input SRID " +
415  std::to_string(arg_ti.get_input_srid()));
416  }
417  }
418  // Established that the input SRID is valid
419  if (allow_result_gdal_transform) {
420  // If gdal transform has been allowed, then it has been sunk into geos runtime.
421  // The returning geometry has already been transformed, de-register transform.
422  if (arg_ti.get_input_srid() != srid) {
423  arg_ti.set_input_srid(srid);
424  }
425  }
426  arg_ti.set_output_srid(srid);
427  } else {
428  throw QueryNotSupported(rex_function->getName() +
429  ": unexpected input SRID, unable to transform");
430  }
431  return arg0;
432  } else if (func_resolve(
433  rex_function->getName(), "ST_GeomFromText"sv, "ST_GeogFromText"sv)) {
434  CHECK(rex_function->size() == size_t(1) || rex_function->size() == size_t(2));
435  if (use_geo_expressions) {
436  int32_t srid = 0;
437  if (rex_function->size() == 2) {
438  // user supplied srid
439  const auto rex_literal =
440  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
441  if (!rex_literal) {
442  throw QueryNotSupported(rex_function->getName() +
443  ": second argument is expected to be a literal");
444  }
445  const auto e = translateLiteral(rex_literal);
446  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
447  if (!ce || !e->get_type_info().is_integer()) {
448  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
449  }
450  if (e->get_type_info().get_type() == kSMALLINT) {
451  srid = static_cast<int32_t>(ce->get_constval().smallintval);
452  } else if (e->get_type_info().get_type() == kTINYINT) {
453  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
454  } else if (e->get_type_info().get_type() == kINT) {
455  srid = static_cast<int32_t>(ce->get_constval().intval);
456  } else {
457  throw QueryNotSupported(rex_function->getName() + " expecting integer SRID");
458  }
459  if (srid != 0 && srid != 4326 && srid != 900913) {
460  throw QueryNotSupported(rex_function->getName() + ": unsupported SRID " +
461  std::to_string(srid));
462  }
463  }
464  arg_ti.set_input_srid(srid); // Input SRID
465  // leave the output srid unset in case a transform was above us
466 
467  if (rex_function->getName() == "ST_GeogFromText"sv) {
468  arg_ti.set_subtype(kGEOGRAPHY);
469  } else {
470  arg_ti.set_subtype(kGEOMETRY);
471  }
472 
473  auto func_args = translateGeoFunctionArg(rex_function->getOperand(0),
474  arg_ti,
475  with_bounds,
476  expand_geo_col,
478  use_geo_expressions);
479  CHECK_GE(func_args.size(), size_t(1));
480  return func_args;
481  }
482 
483  // First - register srid, then send it to geo literal translation
484  int32_t srid = 0;
485  if (rex_function->size() == 2) {
486  const auto rex_literal =
487  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
488  if (!rex_literal) {
489  throw QueryNotSupported(rex_function->getName() +
490  ": second argument is expected to be a literal");
491  }
492  const auto e = translateLiteral(rex_literal);
493  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
494  if (!ce || !e->get_type_info().is_integer()) {
495  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
496  }
497  if (e->get_type_info().get_type() == kSMALLINT) {
498  srid = static_cast<int32_t>(ce->get_constval().smallintval);
499  } else if (e->get_type_info().get_type() == kTINYINT) {
500  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
501  } else if (e->get_type_info().get_type() == kINT) {
502  srid = static_cast<int32_t>(ce->get_constval().intval);
503  } else {
504  throw QueryNotSupported(rex_function->getName() + " expecting integer SRID");
505  }
506  if (srid != 0 && srid != 4326 && srid != 900913) {
507  throw QueryNotSupported(rex_function->getName() + ": unsupported SRID " +
508  std::to_string(srid));
509  }
510  }
511  arg_ti.set_input_srid(srid); // Input SRID
512  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
513 
514  const auto rex_literal =
515  dynamic_cast<const RexLiteral*>(rex_function->getOperand(0));
516  if (!rex_literal) {
517  throw QueryNotSupported(rex_function->getName() +
518  " expects a string literal as first argument");
519  }
520  auto arg0 = translateGeoLiteral(rex_literal, arg_ti, with_bounds);
521  arg_ti.set_subtype((rex_function->getName() == "ST_GeogFromText"sv) ? kGEOGRAPHY
522  : kGEOMETRY);
523  return arg0;
524  } else if (rex_function->getName() == "ST_PointN"sv) {
525  // uses geo expressions
526  const auto rex_scalar0 =
527  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
528  if (!rex_scalar0) {
529  throw QueryNotSupported(rex_function->getName() +
530  ": expects scalar as first argument");
531  }
532  auto arg0 = translateGeoFunctionArg(rex_scalar0,
533  arg_ti,
534  with_bounds,
535  expand_geo_col,
536  /*is_projection=*/false,
537  /*use_geo_expressions=*/true);
538  CHECK_EQ(arg0.size(), size_t(1));
539  CHECK(arg0.front());
540  if (arg0.front()->get_type_info().get_type() != kLINESTRING) {
541  throw QueryNotSupported(rex_function->getName() +
542  " expects LINESTRING as first argument");
543  }
544  const auto rex_literal =
545  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
546  if (!rex_literal) {
547  throw QueryNotSupported(rex_function->getName() +
548  ": second argument is expected to be a literal");
549  }
550  const auto e = translateLiteral(rex_literal);
551  if (!e ||
552  !shared::is_any<kSMALLINT, kTINYINT, kINT>(e->get_type_info().get_type())) {
553  throw QueryNotSupported(rex_function->getName() +
554  " expecting integer index as second argument");
555  }
556  arg0.push_back(e);
557  auto oper_ti =
558  arg0.front()->get_type_info(); // make a copy so we can reset nullness and type
559  oper_ti.set_type(kPOINT);
560  oper_ti.set_notnull(false);
561 
562  arg_ti = oper_ti; // TODO: remove
563 
564  return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), arg0)};
565 
566  } else if (rex_function->getName() == "ST_StartPoint"sv ||
567  rex_function->getName() == "ST_EndPoint"sv) {
568  std::vector<std::shared_ptr<Analyzer::Expr>> args;
569  CHECK_EQ(size_t(1), rex_function->size());
570  const auto arg_exprs = translateGeoFunctionArg(rex_function->getOperand(0),
571  arg_ti,
572  with_bounds,
573  expand_geo_col,
575  /*use_geo_expressions=*/true);
576  CHECK_EQ(arg_exprs.size(), size_t(1));
577  CHECK(arg_exprs.front());
578  const auto arg_expr_ti = arg_exprs.front()->get_type_info();
579  if (arg_expr_ti.get_type() != kLINESTRING) {
580  throw QueryNotSupported(rex_function->getName() +
581  " expected LINESTRING argument. Received " +
582  arg_expr_ti.toString());
583  }
584  args.push_back(arg_exprs.front());
585 
586  auto oper_ti = args.back()->get_type_info(); // make a copy so we can override type
587  oper_ti.set_type(kPOINT);
588 
589  arg_ti = oper_ti; // TODO: remove
590 
591  return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), args)};
592  } else if (rex_function->getName() == "ST_SRID"sv) {
593  CHECK_EQ(size_t(1), rex_function->size());
594  const auto rex_scalar0 =
595  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
596  if (!rex_scalar0) {
597  throw QueryNotSupported(rex_function->getName() +
598  ": expects scalar as first argument");
599  }
600  auto arg0 =
601  translateGeoFunctionArg(rex_scalar0, arg_ti, with_bounds, expand_geo_col);
602  if (!IS_GEO(arg_ti.get_type())) {
603  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
604  }
605  return arg0;
606  } else if (rex_function->getName() == "ST_SetSRID"sv) {
607  CHECK_EQ(size_t(2), rex_function->size());
608  const auto rex_literal =
609  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
610  if (!rex_literal) {
611  throw QueryNotSupported(rex_function->getName() +
612  ": second argument is expected to be a literal");
613  }
614  const auto e = translateLiteral(rex_literal);
615  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
616  if (!ce || !e->get_type_info().is_integer()) {
617  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
618  }
619  int32_t srid = 0;
620  if (e->get_type_info().get_type() == kSMALLINT) {
621  srid = static_cast<int32_t>(ce->get_constval().smallintval);
622  } else if (e->get_type_info().get_type() == kTINYINT) {
623  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
624  } else if (e->get_type_info().get_type() == kINT) {
625  srid = static_cast<int32_t>(ce->get_constval().intval);
626  } else {
627  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
628  }
629 
630  const auto rex_scalar0 =
631  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
632  if (!rex_scalar0) {
633  throw QueryNotSupported(rex_function->getName() +
634  ": expects scalar as first argument");
635  }
636 
637  // Only convey the request to compress if dealing with 4326 geo
638  auto arg0 = translateGeoFunctionArg(rex_scalar0,
639  arg_ti,
640  with_bounds,
641  expand_geo_col,
642  is_projection,
643  use_geo_expressions,
644  (try_to_compress && (srid == 4326)));
645 
646  CHECK(!arg0.empty() && arg0.front());
647  if (!IS_GEO(arg_ti.get_type()) && !use_geo_expressions) {
648  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
649  }
650  arg_ti.set_input_srid(srid); // Input SRID
651  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
652  if (auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
653  CHECK_EQ(arg0.size(), size_t(1));
654  auto ti = geo_expr->get_type_info();
655  ti.set_input_srid(srid);
656  ti.set_output_srid(srid);
657  return {geo_expr->add_cast(ti)};
658  }
659  return arg0;
660  } else if (rex_function->getName() == "CastToGeography"sv) {
661  CHECK_EQ(size_t(1), rex_function->size());
662  const auto rex_scalar0 =
663  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
664  if (!rex_scalar0) {
665  throw QueryNotSupported(rex_function->getName() +
666  ": expects scalar as first argument");
667  }
668  auto arg0 = translateGeoFunctionArg(rex_scalar0,
669  arg_ti,
670  with_bounds,
671  expand_geo_col,
672  /*is_projection=*/false,
673  use_geo_expressions);
674  CHECK(!arg0.empty());
675  if (auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
676  auto arg_ti = geo_expr->get_type_info(); // make a copy
677  arg_ti.set_subtype(kGEOGRAPHY);
678  return {geo_expr->add_cast(arg_ti)};
679  }
680  if (use_geo_expressions) {
681  arg_ti = arg0.front()->get_type_info();
682  arg_ti.set_subtype(kGEOGRAPHY);
683  arg0.front()->set_type_info(arg_ti);
684  }
685  if (!IS_GEO(arg_ti.get_type())) {
686  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
687  }
688  if (arg_ti.get_output_srid() != 4326) {
689  throw QueryNotSupported(rex_function->getName() +
690  " expects geometry with SRID=4326");
691  }
692  arg_ti.set_subtype(kGEOGRAPHY);
693  return arg0;
694  } else if (rex_function->getName() == "ST_Point"sv) {
695  CHECK_EQ(size_t(2), rex_function->size());
696  arg_ti.set_type(kPOINT);
697  arg_ti.set_subtype(kGEOMETRY);
698  arg_ti.set_input_srid(0);
699  arg_ti.set_output_srid(0);
701 
702  auto coord1 = translateScalarRex(rex_function->getOperand(0));
703  auto coord2 = translateScalarRex(rex_function->getOperand(1));
704  auto d_ti = SQLTypeInfo(kDOUBLE, false);
705  auto cast_coord1 = coord1->add_cast(d_ti);
706  auto cast_coord2 = coord2->add_cast(d_ti);
707  // First try to fold to geo literal
708  auto folded_coord1 = fold_expr(cast_coord1.get());
709  auto folded_coord2 = fold_expr(cast_coord2.get());
710  auto const_coord1 = std::dynamic_pointer_cast<Analyzer::Constant>(folded_coord1);
711  auto const_coord2 = std::dynamic_pointer_cast<Analyzer::Constant>(folded_coord2);
712  if (const_coord1 && const_coord2 && !use_geo_expressions) {
713  CHECK(const_coord1->get_type_info().get_type() == kDOUBLE);
714  CHECK(const_coord2->get_type_info().get_type() == kDOUBLE);
715  std::string wkt = "POINT(" +
716  std::to_string(const_coord1->get_constval().doubleval) + " " +
717  std::to_string(const_coord2->get_constval().doubleval) + ")";
718  RexLiteral rex_literal{wkt, kTEXT, kNULLT, 0, 0, 0, 0};
719  auto args = translateGeoLiteral(&rex_literal, arg_ti, false);
720  CHECK(arg_ti.get_type() == kPOINT);
721  return args;
722  }
723  const auto is_local_alloca = !is_projection;
724  if (!is_local_alloca || use_geo_expressions) {
725  if (try_to_compress) {
726  arg_ti.set_input_srid(4326);
727  arg_ti.set_output_srid(4326);
728  }
729  return {makeExpr<Analyzer::GeoOperator>(
730  arg_ti,
731  rex_function->getName(),
732  std::vector<std::shared_ptr<Analyzer::Expr>>{folded_coord1, folded_coord2})};
733  }
734  // Couldn't fold to geo literal, construct [and compress] on the fly
735  auto da_ti = SQLTypeInfo(kARRAY, true);
736  da_ti.set_subtype(kDOUBLE);
737  da_ti.set_size(16);
738  if (try_to_compress) {
739  // Switch to compressed coord array
740  da_ti.set_subtype(kINT);
741  da_ti.set_size(8);
742  da_ti.set_input_srid(4326);
743  da_ti.set_output_srid(4326);
744  da_ti.set_compression(kENCODING_GEOINT);
745  da_ti.set_comp_param(32);
746  // Register point compression
747  arg_ti.set_input_srid(4326);
748  arg_ti.set_output_srid(4326);
749  arg_ti.set_compression(kENCODING_GEOINT);
750  arg_ti.set_comp_param(32);
751  }
752  auto cast_coords = {folded_coord1, folded_coord2};
753  auto ae = makeExpr<Analyzer::ArrayExpr>(da_ti, cast_coords, false, is_local_alloca);
754  SQLTypeInfo tia_ti = da_ti;
755  tia_ti.set_subtype(kTINYINT);
756  return {makeExpr<Analyzer::UOper>(tia_ti, false, kCAST, ae)};
757  } else if (rex_function->getName() == "ST_Centroid"sv) {
758  CHECK_EQ(size_t(1), rex_function->size());
759  arg_ti.set_type(kPOINT);
760  arg_ti.set_subtype(kGEOMETRY);
761  arg_ti.set_input_srid(0);
762  arg_ti.set_output_srid(0);
763  arg_ti.set_compression(kENCODING_NONE);
764 
765  SQLTypeInfo geo_ti;
766  int legacy_transform_srid = 0; // discard
767  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
768  geo_ti,
769  /*with_bounds=*/false,
770  /*expand_geo_col=*/true,
771  /*is_projection=*/false,
772  /*use_geo_expressions=*/true);
773  CHECK_EQ(geoargs.size(), size_t(1));
774  if (geo_ti.get_output_srid() > 0) {
775  // Pick up the arg's srid
776  arg_ti.set_input_srid(geo_ti.get_output_srid());
777  arg_ti.set_output_srid(geo_ti.get_output_srid());
778  }
779  if (try_to_compress) {
780  // Point compression is requested by a higher level [4326] operation
781  if (geo_ti.get_output_srid() == 0) {
782  // srid-less geo is considered and is forced to be 4326
783  arg_ti.set_input_srid(4326);
784  arg_ti.set_output_srid(4326);
785  } else {
786  CHECK_EQ(arg_ti.get_output_srid(), 4326);
787  }
788  arg_ti.set_compression(kENCODING_GEOINT);
789  arg_ti.set_comp_param(32);
790  }
791  if (geo_ti.get_input_srid() != geo_ti.get_output_srid() &&
792  geo_ti.get_output_srid() > 0 &&
793  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
794  // Centroid argument is transformed before use,
795  // pass the transform to the geo operator
796  legacy_transform_srid = geo_ti.get_output_srid();
797  }
798  return {makeExpr<Analyzer::GeoOperator>(
799  arg_ti,
800  rex_function->getName(),
801  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()},
802  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
803  : std::nullopt)};
804  } else if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
805  CHECK_EQ(size_t(1), rex_function->size());
806  // What geo type will the constructor return? Could be anything.
807  return {translateUnaryGeoConstructor(rex_function, arg_ti, with_bounds)};
808  } else if (func_resolve(rex_function->getName(),
809  "ST_Intersection"sv,
810  "ST_Difference"sv,
811  "ST_Union"sv,
812  "ST_Buffer"sv,
813  "ST_ConcaveHull"sv)) {
814  CHECK_EQ(size_t(2), rex_function->size());
815  // What geo type will the constructor return? Could be anything.
816  return {translateBinaryGeoConstructor(rex_function, arg_ti, with_bounds)};
817  } else if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
818  CHECK_EQ(size_t(1), rex_function->size());
819  return {translateUnaryGeoPredicate(rex_function, arg_ti, with_bounds)};
820  } else if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
821  CHECK_EQ(size_t(2), rex_function->size());
822  return {translateBinaryGeoPredicate(rex_function, arg_ti, with_bounds)};
823  } else {
824  throw QueryNotSupported("Unsupported argument: " + rex_function->getName());
825  }
826  }
827  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
828  if (rex_literal) {
829  if (use_geo_expressions) {
830  const auto translated_literal = translateLiteral(rex_literal);
831  auto const translated_literal_type = translated_literal->get_type_info().get_type();
832  if (!IS_STRING(translated_literal_type) && !IS_GEO(translated_literal_type)) {
833  // This stops crashes in the createGeoType call below due to datum.stringval
834  // being uninitialized when the datum isn't even a string, let alone a geo string
835  // There needs to be specific handling for ST_NumGeometries in the code above
836  // but I don't know what category it would fall over (it's not GEOS, and it
837  // returns an INT, not a BOOL or other geo)
838  // simon.eves 8/15/22
839  throw QueryNotSupported("Geospatial function requires geo literal.");
840  }
841  const auto constant_expr =
842  dynamic_cast<const Analyzer::Constant*>(translated_literal.get());
843  CHECK(constant_expr);
844  if (constant_expr->get_is_null()) {
845  // TODO: we could lift this limitation by assuming a minimum type per function
846  throw QueryNotSupported("Geospatial functions require typed nulls.");
847  }
848  const auto& datum = constant_expr->get_constval();
849  CHECK(datum.stringval);
850  const bool validate_with_geos_if_available = false;
851  auto geospatial_base = Geospatial::GeoTypesFactory::createGeoType(
852  *datum.stringval, validate_with_geos_if_available);
853  CHECK(geospatial_base);
854  SQLTypeInfo ti;
855  ti.set_type(get_ti_from_geo(geospatial_base.get()));
856  if (arg_ti.get_subtype() == kGEOGRAPHY) {
858  } else {
860  }
861  ti.set_input_srid(arg_ti.get_input_srid());
862  ti.set_output_srid(arg_ti.get_output_srid() == 0 ? arg_ti.get_input_srid()
863  : arg_ti.get_output_srid());
864  // TODO: remove dependence on arg_ti
865  if (ti.get_output_srid() == 4326 || arg_ti.get_compression() == kENCODING_GEOINT) {
867  ti.set_comp_param(32);
868  }
869  ti.set_notnull(true);
870  // Before removing dependence on arg_ti need to note that ST_Transform uses it
871  // as a vehicle to pass transform output SRID to its args.
872  // arg_ti is also expected to be filled with relevant data, which wasn't done here.
873  // Not filling arg_ti with the geo constant data (which went to ti instead)
874  // resulted in GeoConstant::add_cast adopting a corrupt type info,
875  // which later killed codegen. Need to complete arg_ti composition:
876  arg_ti = ti;
877  return {makeExpr<Analyzer::GeoConstant>(std::move(geospatial_base), ti)};
878  }
879  return translateGeoLiteral(rex_literal, arg_ti, with_bounds);
880  }
881  throw QueryNotSupported("Geo function argument not supported");
882 }
void set_compression(EncodingType c)
Definition: sqltypes.h:481
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoColumn(const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool expand_geo_col) const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:471
#define CHECK_GE(x, y)
Definition: Logger.h:306
Definition: sqldefs.h:51
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
std::string to_string(char const *&&v)
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoLiteral(const RexLiteral *, SQLTypeInfo &, bool) const
void set_input_srid(int d)
Definition: sqltypes.h:474
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
void set_output_srid(int s)
Definition: sqltypes.h:476
void set_comp_param(int p)
Definition: sqltypes.h:482
Definition: sqltypes.h:79
std::shared_ptr< Analyzer::Expr > translateUnaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
static std::unique_ptr< GeoBase > createGeoType(const std::string &wkt_or_wkb_hex, const bool validate_with_geos_if_available)
Definition: Types.cpp:1085
std::shared_ptr< Analyzer::Expr > translateUnaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
bool is_projection(const RelAlgExecutionUnit &ra_exe_unit)
static bool isUtm(unsigned const srid)
Definition: Transform.h:42
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
#define IS_STRING(T)
Definition: sqltypes.h:309
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:395
void set_notnull(bool n)
Definition: sqltypes.h:477
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
#define IS_GEO(T)
Definition: sqltypes.h:310
std::shared_ptr< Analyzer::Expr > translateBinaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
SQLTypes get_ti_from_geo(const Geospatial::GeoBase *geo)
Definition: Analyzer.cpp:4007
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:470

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< std::shared_ptr< Analyzer::Expr > > RelAlgTranslator::translateGeoLiteral ( const RexLiteral rex_literal,
SQLTypeInfo ti,
bool  with_bounds 
) const
private

Definition at line 117 of file RelAlgTranslatorGeo.cpp.

References run_benchmark_import::args, CHECK, Geospatial::compress_coords(), Datum::doubleval, SQLTypeInfo::get_compression(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_type(), Geospatial::GeoTypesFactory::getGeoColumns(), SQLTypeInfo::has_bounds(), Datum::intval, kARRAY, kDOUBLE, kENCODING_GEOINT, kGEOMETRY, kINT, kMULTILINESTRING, kMULTIPOLYGON, kPOLYGON, kTEXT, kTINYINT, SQLTypeInfo::set_comp_param(), SQLTypeInfo::set_compression(), SQLTypeInfo::set_input_srid(), SQLTypeInfo::set_output_srid(), SQLTypeInfo::set_size(), SQLTypeInfo::set_subtype(), Datum::tinyintval, and translateLiteral().

Referenced by translateGeoFunctionArg().

120  {
121  CHECK(rex_literal);
122  if (rex_literal->getType() != kTEXT) {
123  throw std::runtime_error("Geo literals must be strings");
124  }
125 
126  // TODO: use geo conversion here
127  const auto e = translateLiteral(rex_literal);
128  auto wkt = std::dynamic_pointer_cast<Analyzer::Constant>(e);
129  CHECK(wkt);
130  std::vector<double> coords;
131  std::vector<double> bounds;
132  std::vector<int> ring_sizes;
133  std::vector<int> poly_rings;
134  int32_t srid = ti.get_output_srid();
135  const bool validate_with_geos_if_available = false;
136  if (!Geospatial::GeoTypesFactory::getGeoColumns(*wkt->get_constval().stringval,
137  ti,
138  coords,
139  bounds,
140  ring_sizes,
141  poly_rings,
142  validate_with_geos_if_available)) {
143  throw QueryNotSupported("Could not read geometry from text");
144  }
146  ti.set_input_srid(srid);
147  ti.set_output_srid(srid);
148  // Compress geo literals by default
149  if (srid == 4326) {
151  ti.set_comp_param(32);
152  }
153 
154  std::vector<std::shared_ptr<Analyzer::Expr>> args;
155 
156  std::vector<uint8_t> compressed_coords = Geospatial::compress_coords(coords, ti);
157  std::list<std::shared_ptr<Analyzer::Expr>> compressed_coords_exprs;
158  for (auto cc : compressed_coords) {
159  Datum d;
160  d.tinyintval = cc;
161  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
162  compressed_coords_exprs.push_back(e);
163  }
164  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
165  arr_ti.set_subtype(kTINYINT);
166  arr_ti.set_size(compressed_coords.size() * sizeof(int8_t));
167  arr_ti.set_compression(ti.get_compression());
168  arr_ti.set_comp_param((ti.get_compression() == kENCODING_GEOINT) ? 32 : 64);
169  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, compressed_coords_exprs));
170 
171  auto lit_type = ti.get_type();
172  if (lit_type == kMULTILINESTRING || lit_type == kPOLYGON || lit_type == kMULTIPOLYGON) {
173  // [linest]ring sizes
174  std::list<std::shared_ptr<Analyzer::Expr>> ring_size_exprs;
175  for (auto c : ring_sizes) {
176  Datum d;
177  d.intval = c;
178  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
179  ring_size_exprs.push_back(e);
180  }
181  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
182  arr_ti.set_subtype(kINT);
183  arr_ti.set_size(ring_sizes.size() * sizeof(int32_t));
184  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, ring_size_exprs));
185 
186  // poly rings
187  if (lit_type == kMULTIPOLYGON) {
188  std::list<std::shared_ptr<Analyzer::Expr>> poly_rings_exprs;
189  for (auto c : poly_rings) {
190  Datum d;
191  d.intval = c;
192  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
193  poly_rings_exprs.push_back(e);
194  }
195  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
196  arr_ti.set_subtype(kINT);
197  arr_ti.set_size(poly_rings.size() * sizeof(int32_t));
198  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, poly_rings_exprs));
199  }
200  }
201 
202  if (with_bounds && ti.has_bounds()) {
203  // bounds
204  std::list<std::shared_ptr<Analyzer::Expr>> bounds_exprs;
205  for (auto b : bounds) {
206  Datum d;
207  d.doubleval = b;
208  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
209  bounds_exprs.push_back(e);
210  }
211  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
212  arr_ti.set_subtype(kDOUBLE);
213  arr_ti.set_size(bounds.size() * sizeof(double));
214  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, bounds_exprs));
215  }
216 
217  return args;
218 }
int8_t tinyintval
Definition: Datum.h:73
void set_compression(EncodingType c)
Definition: sqltypes.h:481
void set_size(int s)
Definition: sqltypes.h:478
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:471
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
int32_t intval
Definition: Datum.h:75
void set_input_srid(int d)
Definition: sqltypes.h:474
std::vector< uint8_t > compress_coords(const std::vector< double > &coords, const SQLTypeInfo &ti)
Definition: Compression.cpp:52
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
bool has_bounds() const
Definition: sqltypes.h:457
static bool getGeoColumns(const std::string &wkt_or_wkb_hex, SQLTypeInfo &ti, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, const bool validate_with_geos_if_available)
Definition: Types.cpp:1121
void set_output_srid(int s)
Definition: sqltypes.h:476
void set_comp_param(int p)
Definition: sqltypes.h:482
Definition: sqltypes.h:79
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
Definition: Datum.h:71
double doubleval
Definition: Datum.h:78
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateGeoProjection ( const RexFunctionOperator rex_function,
SQLTypeInfo ti,
const bool  with_bounds 
) const
private

Definition at line 884 of file RelAlgTranslatorGeo.cpp.

References CHECK, RelRexToStringConfig::defaults(), func_resolve, RexFunctionOperator::getName(), RexOperator::getOperand(), Geospatial::GeoBase::kPROJECTION, RexFunctionOperator::toString(), and translateGeoFunctionArg().

Referenced by translateFunction().

887  {
888  // note that this is a bit of a misnomer, as ST_SetSRID embedded in a transform will
889  // eventually use geo expressions -- just not here
890  const bool use_geo_projections = !(rex_function->getName() == "ST_GeomFromText" ||
891  rex_function->getName() == "ST_GeogFromText" ||
892  rex_function->getName() == "ST_SetSRID");
893  auto geoargs = translateGeoFunctionArg(rex_function,
894  ti,
895  /*with_bounds=*/false,
896  /*expand_geo_col=*/true,
897  /*is_projection=*/true,
898  /*use_geo_expressions=*/use_geo_projections);
899  CHECK(!geoargs.empty());
900  if (std::dynamic_pointer_cast<const Analyzer::GeoExpr>(geoargs.front()) &&
901  !geoargs.front()->get_type_info().is_array()) {
902  if (rex_function->getName() == "ST_Transform" &&
903  std::dynamic_pointer_cast<const Analyzer::GeoConstant>(geoargs.front())) {
904  return makeExpr<Analyzer::GeoUOper>(
905  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
906  }
907  // GeoExpression
908  return geoargs.front();
909  }
910  bool allow_gdal_transform = false;
911  if (rex_function->getName() == "ST_Transform") {
912  const auto rex_scalar0 = dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
913  const auto rex_function0 = dynamic_cast<const RexFunctionOperator*>(rex_scalar0);
914  if (rex_function0 && func_resolve(rex_function0->getName(),
915  "ST_Intersection"sv,
916  "ST_Difference"sv,
917  "ST_Union"sv,
918  "ST_Buffer"sv,
919  "ST_ConcaveHull"sv,
920  "ST_ConvexHull"sv)) {
921  // Allow projection of gdal-transformed geos outputs
922  allow_gdal_transform = true;
923  }
924  }
925  if (use_geo_projections && !allow_gdal_transform) {
926  throw std::runtime_error("Geospatial projection for function " +
927  rex_function->toString(RelRexToStringConfig::defaults()) +
928  " not yet supported in this context");
929  }
930  return makeExpr<Analyzer::GeoUOper>(
931  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
932 }
auto func_resolve
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
static RelRexToStringConfig defaults()
Definition: RelAlgDag.h:78
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
#define CHECK(condition)
Definition: Logger.h:291
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
Definition: RelAlgDag.h:508
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateHPTLiteral ( const RexFunctionOperator rex_function) const
private

Definition at line 2870 of file RelAlgTranslator.cpp.

References CHECK_EQ, RexOperator::getOperand(), RexOperator::getType(), RexOperator::size(), to_string(), and translateScalarRex().

Referenced by translateFunction().

2871  {
2872  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
2873  Therefore any string having fractional seconds more 3 places after the decimal
2874  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
2875  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
2876  calcite and translating them to generate our own casts.
2877  */
2878  CHECK_EQ(size_t(1), rex_function->size());
2879  const auto operand = translateScalarRex(rex_function->getOperand(0));
2880  const auto& operand_ti = operand->get_type_info();
2881  const auto& target_ti = rex_function->getType();
2882  if (!operand_ti.is_string()) {
2883  throw std::runtime_error(
2884  "High precision timestamp cast argument must be a string. Input type is: " +
2885  operand_ti.get_type_name());
2886  } else if (!target_ti.is_high_precision_timestamp()) {
2887  throw std::runtime_error(
2888  "Cast target type should be high precision timestamp. Input type is: " +
2889  target_ti.get_type_name());
2890  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
2891  throw std::runtime_error(
2892  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
2893  std::to_string(target_ti.get_dimension()) + ")");
2894  } else {
2895  return operand->add_cast(target_ti);
2896  }
2897 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
std::string to_string(char const *&&v)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateInOper ( const RexOperator rex_operator) const
private

Definition at line 719 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, anonymous_namespace{RelAlgTranslator.cpp}::datum_from_scalar_tv(), g_enable_watchdog, g_in_clause_num_elem_skip_bitmap, g_watchdog_in_clause_max_num_elem_non_bitmap, anonymous_namespace{RelAlgTranslator.cpp}::get_in_values_expr(), getInIntegerSetExpr(), RexOperator::getOperand(), just_explain_, kCAST, kENCODING_DICT, kENCODING_NONE, run_benchmark_import::result, RexOperator::size(), timer_start(), timer_stop(), toString(), translateScalarRex(), and VLOG.

Referenced by translateOper().

720  {
721  if (just_explain_) {
722  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
723  }
724  CHECK(rex_operator->size() == 2);
725  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
726  const auto rhs = rex_operator->getOperand(1);
727  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
728  CHECK(rex_subquery);
729  auto ti = lhs->get_type_info();
730  auto result = rex_subquery->getExecutionResult();
731  CHECK(result);
732  auto& row_set = result->getRows();
733  CHECK_EQ(size_t(1), row_set->colCount());
734  const auto& rhs_ti = row_set->getColType(0);
735  if (rhs_ti.get_type() != ti.get_type()) {
736  throw std::runtime_error(
737  "The two sides of the IN operator must have the same type; found " +
738  ti.get_type_name() + " and " + rhs_ti.get_type_name());
739  }
740  ScopeGuard elapsed_time_log = [clock_begin = timer_start()] {
741  VLOG(1) << "RelAlgTranslator::translateInOper: took " << timer_stop(clock_begin)
742  << " ms";
743  };
744  row_set->moveToBegin();
745  std::shared_ptr<Analyzer::Expr> expr;
746  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
747  !row_set->didOutputColumnar()) {
748  expr = getInIntegerSetExpr(lhs, *row_set);
749  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
750  // Just let it fall through the usual InValues path at the end of this method,
751  // its codegen knows to use inline comparisons for few values.
752  if (expr) {
753  auto const num_values =
754  std::static_pointer_cast<Analyzer::InIntegerSet>(expr)->get_value_list().size();
755  if (num_values <= g_in_clause_num_elem_skip_bitmap) {
756  VLOG(1) << "Skip to build a bitmap for tiny integer-set case: # values ("
757  << ::toString(num_values) << ") <= threshold ("
759  expr = nullptr;
760  }
761  } else {
762  expr = get_in_values_expr(lhs, *row_set);
763  }
764  if (expr) {
765  return expr;
766  }
767  }
768  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
769  while (true) {
770  auto row = row_set->getNextRow(true, false);
771  if (row.empty()) {
772  break;
773  }
774  if (g_enable_watchdog &&
775  value_exprs.size() >= g_watchdog_in_clause_max_num_elem_non_bitmap) {
776  std::ostringstream oss;
777  oss << "Unable to handle 'expr IN (subquery)' via non-bitmap, # unique values ("
778  << value_exprs.size()
779  << ") is larger than the threshold "
780  "'g_watchdog_in_clause_max_num_elem_non_bitmap': "
782  throw std::runtime_error(oss.str());
783  }
784  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
785  Datum d{0};
786  bool is_null_const{false};
787  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
788  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
789  auto ti_none_encoded = ti;
790  ti_none_encoded.set_compression(kENCODING_NONE);
791  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
792  auto dict_encoded_string =
793  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
794  value_exprs.push_back(dict_encoded_string);
795  } else {
796  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
797  }
798  }
799  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
800 }
size_t g_watchdog_in_clause_max_num_elem_non_bitmap
Definition: Execute.cpp:85
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
TypeR::rep timer_stop(Type clock_begin)
Definition: measure.h:48
Definition: sqldefs.h:51
std::shared_ptr< Analyzer::Expr > getInIntegerSetExpr(std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set) const
bool g_enable_watchdog
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
size_t g_in_clause_num_elem_skip_bitmap
Definition: Execute.cpp:88
std::shared_ptr< Analyzer::Expr > get_in_values_expr(std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set)
#define CHECK(condition)
Definition: Logger.h:291
std::pair< Datum, bool > datum_from_scalar_tv(const ScalarTargetValue *scalar_tv, const SQLTypeInfo &ti) noexcept
const bool just_explain_
Definition: Datum.h:71
#define VLOG(n)
Definition: Logger.h:388
Type timer_start()
Definition: measure.h:42

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateInput ( const RexInput rex_input) const
private

Definition at line 503 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, CHECK_GE, CHECK_LE, CHECK_LT, RelRexToStringConfig::defaults(), RexAbstractInput::getIndex(), RelAlgNode::getOutputMetainfo(), RexInput::getSourceNode(), input_to_nest_level_, join_types_, kTEXT, and LEFT.

Referenced by translateGeoFunctionArg().

504  {
505  const auto source = rex_input->getSourceNode();
506  const auto it_rte_idx = input_to_nest_level_.find(source);
507  CHECK(it_rte_idx != input_to_nest_level_.end())
508  << "Not found in input_to_nest_level_, source="
509  << source->toString(RelRexToStringConfig::defaults());
510  const int rte_idx = it_rte_idx->second;
511  const auto scan_source = dynamic_cast<const RelScan*>(source);
512  const auto& in_metainfo = source->getOutputMetainfo();
513  if (scan_source) {
514  // We're at leaf (scan) level and not supposed to have input metadata,
515  // the name and type information come directly from the catalog.
516  CHECK(in_metainfo.empty());
517  const auto table_desc = scan_source->getTableDescriptor();
518  const auto& catalog = scan_source->getCatalog();
519  const auto cd =
520  catalog.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
521  CHECK(cd);
522  auto col_ti = cd->columnType;
523  if (col_ti.is_string()) {
524  col_ti.set_type(kTEXT);
525  }
526  if (cd->isVirtualCol) {
527  // TODO(alex): remove at some point, we only need this fixup for backwards
528  // compatibility with old imported data
529  CHECK_EQ("rowid", cd->columnName);
530  col_ti.set_size(8);
531  }
532  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
533  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
534  col_ti.set_notnull(false);
535  }
536  return std::make_shared<Analyzer::ColumnVar>(
537  col_ti,
538  shared::ColumnKey{catalog.getDatabaseId(), table_desc->tableId, cd->columnId},
539  rte_idx);
540  }
541  CHECK(!in_metainfo.empty()) << "for "
542  << source->toString(RelRexToStringConfig::defaults());
543  CHECK_GE(rte_idx, 0);
544  const int32_t col_id = rex_input->getIndex();
545  CHECK_LT(col_id, in_metainfo.size());
546  auto col_ti = in_metainfo[col_id].get_type_info();
547 
548  if (join_types_.size() > 0) {
549  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
550  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
551  col_ti.set_notnull(false);
552  }
553  }
554 
555  return std::make_shared<Analyzer::ColumnVar>(
556  col_ti, shared::ColumnKey{0, int32_t(-source->getId()), col_id}, rte_idx);
557 }
const std::vector< JoinType > join_types_
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define CHECK_GE(x, y)
Definition: Logger.h:306
unsigned getIndex() const
Definition: RelAlgDag.h:174
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:303
Definition: sqltypes.h:79
#define CHECK_LE(x, y)
Definition: Logger.h:304
static RelRexToStringConfig defaults()
Definition: RelAlgDag.h:78
const RelAlgNode * getSourceNode() const
Definition: RelAlgDag.h:1056
#define CHECK(condition)
Definition: Logger.h:291
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
Definition: RelAlgDag.h:865

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateIntervalExprForWindowFraming ( std::shared_ptr< Analyzer::Expr order_key,
bool  for_preceding_bound,
const Analyzer::Expr expr 
) const
private

Definition at line 2570 of file RelAlgTranslator.cpp.

References Datum::bigintval, CHECK, CHECK_EQ, CHECK_NE, daINVALID, anonymous_namespace{RelAlgTranslator.cpp}::determineTimeUnit(), anonymous_namespace{RelAlgTranslator.cpp}::determineTimeValMultiplierForTimeType(), kBIGINT, kDATE, kDAY, kDECIMAL, kDOUBLE, kHOUR, kINT, kMINUTE, kMONTH, kMULTIPLY, kNUMERIC, kSECOND, kSMALLINT, kTIME, kTIMESTAMP, kTINYINT, kYEAR, to_dateadd_field(), and UNREACHABLE.

Referenced by translateWindowFunction().

2573  {
2574  // translate time interval expression and prepare appropriate frame bound expression:
2575  // a) manually compute time unit datum: time type
2576  // b) use dateadd expression: date and timestamp
2577  const auto frame_bound_expr = dynamic_cast<const Analyzer::BinOper*>(expr);
2578  CHECK(frame_bound_expr);
2579  CHECK_EQ(frame_bound_expr->get_optype(), kMULTIPLY);
2580  const auto order_key_ti = order_key->get_type_info();
2581  const auto frame_bound_ti = frame_bound_expr->get_type_info();
2582  const auto time_val_expr =
2583  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_left_operand());
2584  const auto time_unit_val_expr =
2585  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_right_operand());
2586  ExtractField time_unit =
2587  determineTimeUnit(frame_bound_ti.get_type(), time_unit_val_expr);
2588  bool invalid_time_unit_type = false;
2589  bool invalid_frame_bound_expr_type = false;
2590  Datum d;
2591  auto prepare_time_value_datum = [&d,
2592  &invalid_frame_bound_expr_type,
2593  &time_val_expr,
2594  &for_preceding_bound](bool is_timestamp_second) {
2595  // currently, Calcite only accepts interval with second, so to represent
2596  // smaller time units like millisecond, we have to use decimal point like
2597  // INTERVAL 0.003 SECOND (for millisecond)
2598  // thus, depending on what time unit we want to represent, Calcite analyzes
2599  // the time value to one of following two types: integer and decimal (and
2600  // numeric) types
2601  switch (time_val_expr->get_type_info().get_type()) {
2602  case kTINYINT: {
2603  d.bigintval = time_val_expr->get_constval().tinyintval;
2604  break;
2605  }
2606  case kSMALLINT: {
2607  d.bigintval = time_val_expr->get_constval().smallintval;
2608  break;
2609  }
2610  case kINT: {
2611  d.bigintval = time_val_expr->get_constval().intval;
2612  break;
2613  }
2614  case kBIGINT: {
2615  d.bigintval = time_val_expr->get_constval().bigintval;
2616  break;
2617  }
2618  case kDECIMAL:
2619  case kNUMERIC: {
2620  if (!is_timestamp_second) {
2621  // date and time type only use integer type as their time value
2622  invalid_frame_bound_expr_type = true;
2623  break;
2624  }
2625  d.bigintval = time_val_expr->get_constval().bigintval;
2626  break;
2627  }
2628  case kDOUBLE: {
2629  if (!is_timestamp_second) {
2630  // date and time type only use integer type as their time value
2631  invalid_frame_bound_expr_type = true;
2632  break;
2633  }
2634  d.bigintval = time_val_expr->get_constval().doubleval *
2635  pow(10, time_val_expr->get_type_info().get_scale());
2636  break;
2637  }
2638  default: {
2639  invalid_frame_bound_expr_type = true;
2640  break;
2641  }
2642  }
2643  if (for_preceding_bound) {
2644  d.bigintval *= -1;
2645  }
2646  };
2647 
2648  switch (order_key_ti.get_type()) {
2649  case kTIME: {
2650  if (time_val_expr->get_type_info().is_integer()) {
2651  if (time_unit == kSECOND || time_unit == kMINUTE || time_unit == kHOUR) {
2652  const auto time_multiplier = determineTimeValMultiplierForTimeType(
2653  frame_bound_ti.get_type(), time_unit_val_expr);
2654  switch (time_val_expr->get_type_info().get_type()) {
2655  case kTINYINT: {
2656  d.bigintval = time_val_expr->get_constval().tinyintval * time_multiplier;
2657  break;
2658  }
2659  case kSMALLINT: {
2660  d.bigintval = time_val_expr->get_constval().smallintval * time_multiplier;
2661  break;
2662  }
2663  case kINT: {
2664  d.bigintval = time_val_expr->get_constval().intval * time_multiplier;
2665  break;
2666  }
2667  case kBIGINT: {
2668  d.bigintval = time_val_expr->get_constval().bigintval * time_multiplier;
2669  break;
2670  }
2671  default: {
2672  UNREACHABLE();
2673  break;
2674  }
2675  }
2676  } else {
2677  invalid_frame_bound_expr_type = true;
2678  }
2679  } else {
2680  invalid_time_unit_type = true;
2681  }
2682  if (invalid_frame_bound_expr_type) {
2683  throw std::runtime_error(
2684  "Invalid time unit is used to define window frame bound expression for " +
2685  order_key_ti.get_type_name() + " type");
2686  } else if (invalid_time_unit_type) {
2687  throw std::runtime_error(
2688  "Window frame bound expression has an invalid type for " +
2689  order_key_ti.get_type_name() + " type");
2690  }
2691  return std::make_shared<Analyzer::Constant>(kBIGINT, false, d);
2692  }
2693  case kDATE: {
2695  if (time_val_expr->get_type_info().is_integer()) {
2696  switch (time_unit) {
2697  case kDAY: {
2698  daField = to_dateadd_field("day");
2699  break;
2700  }
2701  case kMONTH: {
2702  daField = to_dateadd_field("month");
2703  break;
2704  }
2705  case kYEAR: {
2706  daField = to_dateadd_field("year");
2707  break;
2708  }
2709  default: {
2710  invalid_frame_bound_expr_type = true;
2711  break;
2712  }
2713  }
2714  } else {
2715  invalid_time_unit_type = true;
2716  }
2717  if (invalid_frame_bound_expr_type) {
2718  throw std::runtime_error(
2719  "Invalid time unit is used to define window frame bound expression for " +
2720  order_key_ti.get_type_name() + " type");
2721  } else if (invalid_time_unit_type) {
2722  throw std::runtime_error(
2723  "Window frame bound expression has an invalid type for " +
2724  order_key_ti.get_type_name() + " type");
2725  }
2727  prepare_time_value_datum(false);
2728  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2729  const int dim = order_key_ti.get_dimension();
2730  return makeExpr<Analyzer::DateaddExpr>(
2731  SQLTypeInfo(kTIMESTAMP, dim, 0, false), daField, cast_number_units, order_key);
2732  }
2733  case kTIMESTAMP: {
2735  switch (time_unit) {
2736  case kSECOND: {
2737  switch (time_val_expr->get_type_info().get_scale()) {
2738  case 0: {
2739  daField = to_dateadd_field("second");
2740  break;
2741  }
2742  case 3: {
2743  daField = to_dateadd_field("millisecond");
2744  break;
2745  }
2746  case 6: {
2747  daField = to_dateadd_field("microsecond");
2748  break;
2749  }
2750  case 9: {
2751  daField = to_dateadd_field("nanosecond");
2752  break;
2753  }
2754  default:
2755  UNREACHABLE();
2756  break;
2757  }
2758  prepare_time_value_datum(true);
2759  break;
2760  }
2761  case kMINUTE: {
2762  daField = to_dateadd_field("minute");
2763  prepare_time_value_datum(false);
2764  break;
2765  }
2766  case kHOUR: {
2767  daField = to_dateadd_field("hour");
2768  prepare_time_value_datum(false);
2769  break;
2770  }
2771  case kDAY: {
2772  daField = to_dateadd_field("day");
2773  prepare_time_value_datum(false);
2774  break;
2775  }
2776  case kMONTH: {
2777  daField = to_dateadd_field("month");
2778  prepare_time_value_datum(false);
2779  break;
2780  }
2781  case kYEAR: {
2782  daField = to_dateadd_field("year");
2783  prepare_time_value_datum(false);
2784  break;
2785  }
2786  default: {
2787  invalid_time_unit_type = true;
2788  break;
2789  }
2790  }
2791  if (!invalid_time_unit_type) {
2793  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2794  const int dim = order_key_ti.get_dimension();
2795  return makeExpr<Analyzer::DateaddExpr>(SQLTypeInfo(kTIMESTAMP, dim, 0, false),
2796  daField,
2797  cast_number_units,
2798  order_key);
2799  }
2800  return nullptr;
2801  }
2802  default: {
2803  UNREACHABLE();
2804  break;
2805  }
2806  }
2807  if (invalid_frame_bound_expr_type) {
2808  throw std::runtime_error(
2809  "Invalid time unit is used to define window frame bound expression for " +
2810  order_key_ti.get_type_name() + " type");
2811  } else if (invalid_time_unit_type) {
2812  throw std::runtime_error("Window frame bound expression has an invalid type for " +
2813  order_key_ti.get_type_name() + " type");
2814  }
2815  return nullptr;
2816 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Definition: sqltypes.h:76
#define UNREACHABLE()
Definition: Logger.h:338
DateaddField
Definition: DateAdd.h:42
#define CHECK_NE(x, y)
Definition: Logger.h:302
size_t determineTimeValMultiplierForTimeType(const SQLTypes &window_frame_bound_type, const Analyzer::Constant *const_expr)
int64_t bigintval
Definition: Datum.h:76
Definition: sqltypes.h:80
ExtractField
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
Definition: Datum.h:71
DateaddField to_dateadd_field(const std::string &field)
ExtractField determineTimeUnit(const SQLTypes &window_frame_bound_type, const Analyzer::Constant *const_expr)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateItem ( const RexFunctionOperator rex_function) const
private

Definition at line 1631 of file RelAlgTranslator.cpp.

References CHECK_EQ, RexOperator::getOperand(), kARRAY_AT, kONE, RexOperator::size(), and translateScalarRex().

Referenced by translateFunction().

1632  {
1633  CHECK_EQ(size_t(2), rex_function->size());
1634  const auto base = translateScalarRex(rex_function->getOperand(0));
1635  const auto index = translateScalarRex(rex_function->getOperand(1));
1636  return makeExpr<Analyzer::BinOper>(
1637  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1638 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
Definition: sqldefs.h:74

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateKeyForString ( const RexFunctionOperator rex_function) const
private

Definition at line 1486 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, CHECK_EQ, RexFunctionOperator::getName(), kUNNEST, and translateFunctionArgs().

Referenced by translateFunction().

1487  {
1488  const auto& args = translateFunctionArgs(rex_function);
1489  CHECK_EQ(size_t(1), args.size());
1490  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1491  if (nullptr == expr || !expr->get_type_info().is_string() ||
1492  expr->get_type_info().is_varlen()) {
1493  throw std::runtime_error(rex_function->getName() +
1494  " expects a dictionary encoded text column.");
1495  }
1496  auto unnest_arg = dynamic_cast<Analyzer::UOper*>(expr);
1497  if (unnest_arg && unnest_arg->get_optype() == SQLOps::kUNNEST) {
1498  throw std::runtime_error(
1499  rex_function->getName() +
1500  " does not support unnest operator as its input expression.");
1501  }
1502  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1503 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateLength ( const RexFunctionOperator rex_function) const
private

Definition at line 1478 of file RelAlgTranslator.cpp.

References CHECK_EQ, RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::size(), and translateScalarRex().

Referenced by translateFunction().

1479  {
1480  CHECK_EQ(size_t(1), rex_function->size());
1481  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1482  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1483  rex_function->getName() == "CHAR_LENGTH"sv);
1484 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateLike ( const RexFunctionOperator rex_function) const
private

Definition at line 1227 of file RelAlgTranslator.cpp.

References CHECK, Parser::LikeExpr::get(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::size(), and translateScalarRex().

Referenced by translateFunction().

1228  {
1229  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1230  const auto arg = translateScalarRex(rex_function->getOperand(0));
1231  const auto like = translateScalarRex(rex_function->getOperand(1));
1232  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1233  throw std::runtime_error("The matching pattern must be a literal.");
1234  }
1235  const auto escape = (rex_function->size() == 3)
1236  ? translateScalarRex(rex_function->getOperand(2))
1237  : nullptr;
1238  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1239  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1240 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
static std::shared_ptr< Analyzer::Expr > get(std::shared_ptr< Analyzer::Expr > arg_expr, std::shared_ptr< Analyzer::Expr > like_expr, std::shared_ptr< Analyzer::Expr > escape_expr, const bool is_ilike, const bool is_not)
Definition: ParserNode.cpp:701
#define CHECK(condition)
Definition: Logger.h:291
const std::string & getName() const
Definition: RelAlgDag.h:506

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateLikely ( const RexFunctionOperator rex_function) const
private

Definition at line 1256 of file RelAlgTranslator.cpp.

References CHECK, RexOperator::getOperand(), RexOperator::size(), and translateScalarRex().

Referenced by translateFunction().

1257  {
1258  CHECK(rex_function->size() == 1);
1259  const auto arg = translateScalarRex(rex_function->getOperand(0));
1260  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1261 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateLiteral ( const RexLiteral rex_literal)
static

Definition at line 366 of file RelAlgTranslator.cpp.

References Parser::StringLiteral::analyzeValue(), Parser::IntLiteral::analyzeValue(), Parser::FixedPtLiteral::analyzeValue(), run_benchmark_import::args, Datum::bigintval, Datum::boolval, anonymous_namespace{RelAlgTranslator.cpp}::build_type_info(), Datum::doubleval, logger::FATAL, kBIGINT, kBOOLEAN, kDATE, kDECIMAL, kDOUBLE, kGEOMETRY, kINT, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kNULLT, kTEXT, kTIME, kTIMESTAMP, LOG, and make_fp_constant().

Referenced by ResultSetLogicalValuesBuilder::build(), translateGeoFunctionArg(), and translateGeoLiteral().

367  {
368  auto lit_ti = build_type_info(
369  rex_literal->getType(), rex_literal->getScale(), rex_literal->getPrecision());
370  auto target_ti = build_type_info(rex_literal->getTargetType(),
371  rex_literal->getTargetScale(),
372  rex_literal->getTargetPrecision());
373  switch (rex_literal->getType()) {
374  case kINT:
375  case kBIGINT: {
376  Datum d;
377  d.bigintval = rex_literal->getVal<int64_t>();
378  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
379  }
380  case kDECIMAL: {
381  const auto val = rex_literal->getVal<int64_t>();
382  const int precision = rex_literal->getPrecision();
383  const int scale = rex_literal->getScale();
384  if (target_ti.is_fp() && !scale) {
385  return make_fp_constant(val, target_ti);
386  }
387  auto lit_expr = scale ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
388  : Parser::IntLiteral::analyzeValue(val);
389  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
390  }
391  case kTEXT: {
392  return Parser::StringLiteral::analyzeValue(rex_literal->getVal<std::string>(),
393  false);
394  }
395  case kBOOLEAN: {
396  Datum d;
397  d.boolval = rex_literal->getVal<bool>();
398  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
399  }
400  case kDOUBLE: {
401  Datum d;
402  d.doubleval = rex_literal->getVal<double>();
403  auto lit_expr =
404  makeExpr<Analyzer::Constant>(SQLTypeInfo(rex_literal->getType(),
405  rex_literal->getPrecision(),
406  rex_literal->getScale(),
407  false),
408  false,
409  d);
410  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
411  }
412  case kINTERVAL_DAY_TIME:
413  case kINTERVAL_YEAR_MONTH: {
414  Datum d;
415  d.bigintval = rex_literal->getVal<int64_t>();
416  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
417  }
418  case kTIME:
419  case kTIMESTAMP: {
420  Datum d;
421  d.bigintval =
422  rex_literal->getType() == kTIMESTAMP && rex_literal->getPrecision() > 0
423  ? rex_literal->getVal<int64_t>()
424  : rex_literal->getVal<int64_t>() / 1000;
425  return makeExpr<Analyzer::Constant>(
426  SQLTypeInfo(rex_literal->getType(), rex_literal->getPrecision(), 0, false),
427  false,
428  d);
429  }
430  case kDATE: {
431  Datum d;
432  d.bigintval = rex_literal->getVal<int64_t>() * 24 * 3600;
433  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
434  }
435  case kNULLT: {
436  if (target_ti.is_array()) {
438  // defaulting to valid sub-type for convenience
439  target_ti.set_subtype(kBOOLEAN);
440  return makeExpr<Analyzer::ArrayExpr>(target_ti, args, true);
441  }
442  if (target_ti.get_type() == kGEOMETRY) {
443  // Specific geo type will be set in a normalization step if needed.
444  return makeExpr<Analyzer::Constant>(kNULLT, true, Datum{0});
445  }
446  return makeExpr<Analyzer::Constant>(rex_literal->getTargetType(), true, Datum{0});
447  }
448  default: {
449  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
450  }
451  }
452  return nullptr;
453 }
Definition: sqltypes.h:76
#define LOG(tag)
Definition: Logger.h:285
int8_t boolval
Definition: Datum.h:72
int64_t bigintval
Definition: Datum.h:76
SQLTypeInfo build_type_info(const SQLTypes sql_type, const int scale, const int precision)
Definition: sqltypes.h:79
Definition: sqltypes.h:80
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &stringval, const bool is_null)
Definition: ParserNode.cpp:147
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t numericval, const int scale, const int precision)
Definition: ParserNode.cpp:191
std::shared_ptr< Analyzer::Constant > make_fp_constant(const int64_t val, const SQLTypeInfo &ti)
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:186
Definition: sqltypes.h:72
Definition: Datum.h:71
double doubleval
Definition: Datum.h:78

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateMLPredict ( const RexFunctionOperator rex_function) const
private

Definition at line 1153 of file RelAlgTranslator.cpp.

References CHECK_GE, RexOperator::getOperand(), RexOperator::size(), and translateScalarRex().

Referenced by translateFunction().

1154  {
1155  const auto num_operands = rex_function->size();
1156  CHECK_GE(num_operands, 2UL);
1157  auto model_value = translateScalarRex(rex_function->getOperand(0));
1158  std::vector<std::shared_ptr<Analyzer::Expr>> regressor_values;
1159  for (size_t regressor_idx = 1; regressor_idx < num_operands; ++regressor_idx) {
1160  regressor_values.emplace_back(
1161  translateScalarRex(rex_function->getOperand(regressor_idx)));
1162  }
1163  return makeExpr<Analyzer::MLPredictExpr>(model_value, regressor_values);
1164 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
#define CHECK_GE(x, y)
Definition: Logger.h:306

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateOffsetInFragment ( ) const
private

Definition at line 1712 of file RelAlgTranslator.cpp.

Referenced by translateFunction().

1712  {
1713  return makeExpr<Analyzer::OffsetInFragment>();
1714 }

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateOper ( const RexOperator rex_operator) const
private

Definition at line 1079 of file RelAlgTranslator.cpp.

References CHECK, CHECK_GT, executor_, RexOperator::getOperand(), RexOperator::getOperator(), getQuantifiedRhs(), IS_COMPARISON, kBBOX_INTERSECT, kIN, kMINUS, kONE, kPLUS, Parser::OperExpr::normalize(), RexOperator::size(), translateBoundingBoxIntersectOper(), translateDatePlusMinus(), translateGeoComparison(), translateInOper(), translateScalarRex(), and translateUoper().

1080  {
1081  CHECK_GT(rex_operator->size(), size_t(0));
1082  if (rex_operator->size() == 1) {
1083  return translateUoper(rex_operator);
1084  }
1085  const auto sql_op = rex_operator->getOperator();
1086  if (sql_op == kIN) {
1087  return translateInOper(rex_operator);
1088  }
1089  if (sql_op == kMINUS || sql_op == kPLUS) {
1090  auto date_plus_minus = translateDatePlusMinus(rex_operator);
1091  if (date_plus_minus) {
1092  return date_plus_minus;
1093  }
1094  }
1095  if (sql_op == kBBOX_INTERSECT) {
1096  return translateBoundingBoxIntersectOper(rex_operator);
1097  } else if (IS_COMPARISON(sql_op)) {
1098  auto geo_comp = translateGeoComparison(rex_operator);
1099  if (geo_comp) {
1100  return geo_comp;
1101  }
1102  }
1103  auto lhs = translateScalarRex(rex_operator->getOperand(0));
1104  for (size_t i = 1; i < rex_operator->size(); ++i) {
1105  std::shared_ptr<Analyzer::Expr> rhs;
1106  SQLQualifier sql_qual{kONE};
1107  const auto rhs_op = rex_operator->getOperand(i);
1108  std::tie(rhs, sql_qual) = getQuantifiedRhs(rhs_op);
1109  if (!rhs) {
1110  rhs = translateScalarRex(rhs_op);
1111  }
1112  CHECK(rhs);
1113 
1114  // Pass in executor to get string proxy info if cast needed between
1115  // string columns
1116  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs, executor_);
1117  }
1118  return lhs;
1119 }
const Executor * executor_
SQLQualifier
Definition: sqldefs.h:74
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
std::shared_ptr< Analyzer::Expr > translateUoper(const RexOperator *) const
static std::shared_ptr< Analyzer::Expr > normalize(const SQLOps optype, const SQLQualifier qual, std::shared_ptr< Analyzer::