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::Expr > left_expr, std::shared_ptr< Analyzer::Expr > right_expr, const Executor *executor=nullptr)
Definition: ParserNode.cpp:380
Definition: sqldefs.h:43
#define CHECK_GT(x, y)
Definition: Logger.h:305
std::shared_ptr< Analyzer::Expr > translateBoundingBoxIntersectOper(const RexOperator *) const
SQLOps getOperator() const
Definition: RelAlgDag.h:376
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > getQuantifiedRhs(const RexScalar *) const
Definition: sqldefs.h:42
Definition: sqldefs.h:74
Definition: sqldefs.h:55
#define CHECK(condition)
Definition: Logger.h:291
std::shared_ptr< Analyzer::Expr > translateInOper(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateGeoComparison(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatePlusMinus(const RexOperator *) const
#define IS_COMPARISON(X)
Definition: sqldefs.h:61

+ Here is the call graph for this function:

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

Definition at line 1166 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1167  {
1168  const auto num_operands = rex_function->size();
1169  CHECK_GE(num_operands, 3UL);
1170  auto model_value = translateScalarRex(rex_function->getOperand(0));
1171  std::vector<std::shared_ptr<Analyzer::Expr>> feature_values;
1172  for (size_t feature_idx = 1; feature_idx < num_operands - 1; ++feature_idx) {
1173  feature_values.emplace_back(
1174  translateScalarRex(rex_function->getOperand(feature_idx)));
1175  }
1176  auto pc_dimension_value =
1177  translateScalarRex(rex_function->getOperand(num_operands - 1));
1178  return makeExpr<Analyzer::PCAProjectExpr>(
1179  model_value, feature_values, pc_dimension_value);
1180 }
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::translateRegexp ( const RexFunctionOperator rex_function) const
private

Definition at line 1242 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1243  {
1244  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1245  const auto arg = translateScalarRex(rex_function->getOperand(0));
1246  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1247  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1248  throw std::runtime_error("The matching pattern must be a literal.");
1249  }
1250  const auto escape = (rex_function->size() == 3)
1251  ? translateScalarRex(rex_function->getOperand(2))
1252  : nullptr;
1253  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1254 }
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 > pattern_expr, std::shared_ptr< Analyzer::Expr > escape_expr, const bool is_not)
Definition: ParserNode.cpp:796
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 203 of file RelAlgTranslator.cpp.

204  {
205  return translateInput(static_cast<RexInput const*>(rex));
206 }
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 208 of file RelAlgTranslator.cpp.

209  {
210  return translateLiteral(static_cast<RexLiteral const*>(rex));
211 }
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 219 of file RelAlgTranslator.cpp.

220  {
221  return translateFunction(static_cast<RexFunctionOperator const*>(rex));
222 }
std::shared_ptr< Analyzer::Expr > translateFunction(const RexFunctionOperator *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 234 of file RelAlgTranslator.cpp.

235  {
236  return translateScalarSubquery(static_cast<RexSubQuery const*>(rex));
237 }
std::shared_ptr< Analyzer::Expr > translateScalarSubquery(const RexSubQuery *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 214 of file RelAlgTranslator.cpp.

215  {
216  return translateWindowFunction(static_cast<RexWindowFunctionOperator const*>(rex));
217 }
std::shared_ptr< Analyzer::Expr > translateWindowFunction(const RexWindowFunctionOperator *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 224 of file RelAlgTranslator.cpp.

225  {
226  return translateOper(static_cast<RexOperator const*>(rex));
227 }
std::shared_ptr< Analyzer::Expr > translateOper(const RexOperator *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 229 of file RelAlgTranslator.cpp.

230  {
231  return translateCase(static_cast<RexCase const*>(rex));
232 }
std::shared_ptr< Analyzer::Expr > translateCase(const RexCase *) const
template<typename T >
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  ) const
inline

Definition at line 77 of file RelAlgTranslator.h.

77  {
78  throw std::runtime_error("Specialization of translateRexScalar() required.");
79  }
std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateSampleRatio ( const RexFunctionOperator rex_function) const
private

Definition at line 1505 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1506  {
1507  CHECK_EQ(size_t(1), rex_function->size());
1508  auto arg = translateScalarRex(rex_function->getOperand(0));
1509  const auto& arg_ti = arg->get_type_info();
1510  if (arg_ti.get_type() != kDOUBLE) {
1511  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1512  arg = arg->add_cast(double_ti);
1513  }
1514  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1515 }
#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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 239 of file RelAlgTranslator.cpp.

References cache_, CHECK, and anonymous_namespace{RelAlgTranslator.cpp}::makeHandlers().

Referenced by getQuantifiedRhs(), translate(), translateAbs(), translateBinaryGeoConstructor(), translateBinaryGeoFunction(), translateBoundingBoxIntersectOper(), translateCardinality(), translateCase(), translateDateadd(), translateDatediff(), translateDatepart(), translateDatePlusMinus(), translateDatetime(), translateExtract(), translateFrameBoundExpr(), translateFunction(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoComparison(), translateGeoFunctionArg(), translateHPTLiteral(), translateInOper(), translateItem(), translateLength(), translateLike(), translateLikely(), translateMLPredict(), translateOper(), translatePCAProject(), translateRegexp(), translateSampleRatio(), translateSign(), translateTernaryGeoFunction(), translateUnlikely(), translateUoper(), translateWidthBucket(), and translateWindowFunction().

240  {
241  auto cache_itr = cache_.find(rex);
242  if (cache_itr == cache_.end()) {
243  // Order types from most likely to least as they are compared seriatim.
244  static auto const handlers = makeHandlers<RexInput,
245  RexLiteral,
246  RexOperator,
247  RexCase,
250  RexSubQuery>();
251  static_assert(std::is_trivially_destructible_v<decltype(handlers)>);
252  auto it = std::find_if(handlers.cbegin(), handlers.cend(), ByTypeIndex{typeid(*rex)});
253  CHECK(it != handlers.cend()) << "Unhandled type: " << typeid(*rex).name();
254  // Call handler based on typeid(*rex) and cache the std::shared_ptr<Analyzer::Expr>.
255  auto cached = cache_.emplace(rex, (this->*it->second)(rex));
256  CHECK(cached.second) << "Failed to emplace rex of type " << typeid(*rex).name();
257  cache_itr = cached.first;
258  }
259  return cache_itr->second;
260 }
robin_hood::unordered_map< RexScalar const *, std::shared_ptr< Analyzer::Expr > > cache_
std::array< IndexedHandler, sizeof...(Ts)> makeHandlers()
#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::translateScalarSubquery ( const RexSubQuery rex_subquery) const
private

Definition at line 455 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, anonymous_namespace{RelAlgTranslator.cpp}::datum_from_scalar_tv(), g_cluster, just_explain_, kENCODING_NONE, run_benchmark_import::result, and Datum::stringval.

456  {
457  if (just_explain_) {
458  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
459  }
460  CHECK(rex_subquery);
461  auto result = rex_subquery->getExecutionResult();
462  auto row_set = result->getRows();
463  const size_t row_count = row_set->rowCount();
464  if (row_count > size_t(1)) {
465  throw std::runtime_error("Scalar sub-query returned multiple rows");
466  }
467  auto ti = rex_subquery->getType();
468  if (g_cluster && ti.is_string()) {
469  throw std::runtime_error(
470  "Scalar sub-queries which return strings not supported in distributed mode");
471  }
472  if (row_count == size_t(0)) {
473  if (row_set->isValidationOnlyRes()) {
474  Datum d{0};
475  if (ti.is_string()) {
476  // keep the valid ptr to avoid crash during the query validation
477  // this ptr will be removed when destructing corresponding constant variable
478  d.stringval = new std::string();
479  }
480  if (ti.is_dict_encoded_string()) {
481  // we set a valid ptr for string literal in above which is not dictionary-encoded
482  ti.set_compression(EncodingType::kENCODING_NONE);
483  }
484  return makeExpr<Analyzer::Constant>(ti, false, d);
485  }
486  throw std::runtime_error("Scalar sub-query returned no results");
487  }
488  CHECK_EQ(row_count, size_t(1));
489  row_set->moveToBegin();
490  auto const first_row = row_set->getNextRow(ti.is_dict_encoded_string(), false);
491  CHECK_EQ(first_row.size(), size_t(1));
492  Datum d{0};
493  bool is_null_const{false};
494  auto scalar_tv = boost::get<ScalarTargetValue>(&first_row[0]);
495  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
496  if (ti.is_dict_encoded_string()) {
497  // we already translate the string, so let's make its type as a string literal
498  ti.set_compression(EncodingType::kENCODING_NONE);
499  }
500  return makeExpr<Analyzer::Constant>(ti, is_null_const, d);
501 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::string * stringval
Definition: Datum.h:81
#define CHECK(condition)
Definition: Logger.h:291
std::pair< Datum, bool > datum_from_scalar_tv(const ScalarTargetValue *scalar_tv, const SQLTypeInfo &ti) noexcept
bool g_cluster
const bool just_explain_
Definition: Datum.h:71

+ Here is the call graph for this function:

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

Definition at line 1690 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1691  {
1692  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1693  expr_list;
1694  CHECK_EQ(size_t(1), rex_function->size());
1695  const auto operand = translateScalarRex(rex_function->getOperand(0));
1696  const auto& operand_ti = operand->get_type_info();
1697  CHECK(operand_ti.is_number());
1698  const auto zero = makeNumericConstant(operand_ti, 0);
1699  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1700  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1701  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1702  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1703  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1704  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1705  return makeExpr<Analyzer::CaseExpr>(
1706  operand_ti,
1707  false,
1708  expr_list,
1709  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1710 }
#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:32
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
Definition: sqldefs.h:36
Definition: sqldefs.h:74
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:35
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::translateStringOper ( const RexFunctionOperator rex_function) const
private

Definition at line 1526 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, BASE64_DECODE, BASE64_ENCODE, CONCAT, g_enable_string_functions, RexFunctionOperator::getName(), RexOperator::getType(), HASH, INITCAP, SQLTypeInfo::is_string(), JAROWINKLER_SIMILARITY, JSON_VALUE, LEVENSHTEIN_DISTANCE, LOWER, LPAD, LTRIM, name_to_string_op_kind(), OVERLAY, POSITION, REGEXP_COUNT, REGEXP_REPLACE, REGEXP_SUBSTR, REPEAT, REPLACE, REVERSE, RPAD, RTRIM, SPLIT_PART, SUBSTRING, translateFunctionArgs(), TRIM, TRY_STRING_CAST, UPPER, URL_DECODE, and URL_ENCODE.

Referenced by translateFunction().

1527  {
1528  const auto func_name = rex_function->getName();
1530  std::ostringstream oss;
1531  oss << "Function " << func_name << " not supported.";
1532  throw std::runtime_error(oss.str());
1533  }
1534  const auto string_op_kind = ::name_to_string_op_kind(func_name);
1535  auto args = translateFunctionArgs(rex_function);
1536 
1537  switch (string_op_kind) {
1539  return makeExpr<Analyzer::LowerStringOper>(args);
1541  return makeExpr<Analyzer::UpperStringOper>(args);
1543  return makeExpr<Analyzer::InitCapStringOper>(args);
1545  return makeExpr<Analyzer::ReverseStringOper>(args);
1547  return makeExpr<Analyzer::RepeatStringOper>(args);
1549  return makeExpr<Analyzer::ConcatStringOper>(args);
1550  case SqlStringOpKind::LPAD:
1551  case SqlStringOpKind::RPAD: {
1552  return makeExpr<Analyzer::PadStringOper>(string_op_kind, args);
1553  }
1554  case SqlStringOpKind::TRIM:
1556  case SqlStringOpKind::RTRIM: {
1557  return makeExpr<Analyzer::TrimStringOper>(string_op_kind, args);
1558  }
1560  return makeExpr<Analyzer::SubstringStringOper>(args);
1562  return makeExpr<Analyzer::OverlayStringOper>(args);
1564  return makeExpr<Analyzer::ReplaceStringOper>(args);
1566  return makeExpr<Analyzer::SplitPartStringOper>(args);
1568  return makeExpr<Analyzer::RegexpReplaceStringOper>(args);
1570  return makeExpr<Analyzer::RegexpSubstrStringOper>(args);
1572  return makeExpr<Analyzer::RegexpCountStringOper>(args);
1574  return makeExpr<Analyzer::JsonValueStringOper>(args);
1576  return makeExpr<Analyzer::Base64EncodeStringOper>(args);
1578  return makeExpr<Analyzer::Base64DecodeStringOper>(args);
1580  if (rex_function->getType().is_string() &&
1581  args.front()->get_type_info().is_string()) {
1582  // ignore try_cast and return string as is
1583  return args.front();
1584  }
1585  return makeExpr<Analyzer::TryStringCastOper>(rex_function->getType(), args);
1587  return makeExpr<Analyzer::PositionStringOper>(args);
1589  return makeExpr<Analyzer::JarowinklerSimilarityStringOper>(args);
1591  return makeExpr<Analyzer::LevenshteinDistanceStringOper>(args);
1592  case SqlStringOpKind::HASH:
1593  return makeExpr<Analyzer::HashStringOper>(args);
1595  return makeExpr<Analyzer::UrlEncodeStringOper>(args);
1597  return makeExpr<Analyzer::UrlDecodeStringOper>(args);
1598  default: {
1599  throw std::runtime_error("Unsupported string function.");
1600  }
1601  }
1602 }
SqlStringOpKind name_to_string_op_kind(const std::string &func_name)
Definition: sqldefs.h:460
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
bool g_enable_string_functions
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
const std::string & getName() const
Definition: RelAlgDag.h:506
bool is_string() const
Definition: sqltypes.h:561

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1647 of file RelAlgTranslatorGeo.cpp.

References CHECK_EQ, 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, kGEOGRAPHY, kINT, kLE, kLINESTRING, kMULTIPOLYGON, kONE, kPOINT, kPOLYGON, run_benchmark_import::result, RexOperator::size(), spatial_type::suffix(), translateBinaryGeoFunction(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction().

1648  {
1649  CHECK_EQ(size_t(3), rex_function->size());
1650 
1651  auto distance_expr = translateScalarRex(rex_function->getOperand(2));
1652  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1653  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1654  distance_expr = distance_expr->add_cast(distance_ti);
1655  }
1656 
1657  auto function_name = rex_function->getName();
1658  if (function_name == "ST_DWithin"sv) {
1659  auto return_type = rex_function->getType();
1660  bool swap_args = false;
1661  bool with_bounds = true;
1662  SQLTypeInfo arg0_ti;
1663  SQLTypeInfo arg1_ti;
1664 
1665  auto geoargs0 =
1666  translateGeoFunctionArg(rex_function->getOperand(0), arg0_ti, with_bounds, false);
1667  auto geoargs1 =
1668  translateGeoFunctionArg(rex_function->getOperand(1), arg1_ti, with_bounds, false);
1669  if (arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1670  throw QueryNotSupported(rex_function->getName() +
1671  " cannot accept mixed GEOMETRY/GEOGRAPHY arguments");
1672  }
1673  auto is_geodesic = false;
1674  if (arg0_ti.get_subtype() == kGEOGRAPHY) {
1675  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1676  is_geodesic = true;
1677  } else {
1678  throw QueryNotSupported(
1679  rex_function->getName() +
1680  " in geodesic form can only accept POINT GEOGRAPHY arguments");
1681  }
1682  }
1683  // Check SRID match if at least one is set/valid
1684  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1685  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1686  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1687  }
1688 
1689  if ((arg1_ti.get_type() == kPOINT && arg0_ti.get_type() != kPOINT) ||
1690  (arg1_ti.get_type() == kLINESTRING && arg0_ti.get_type() == kPOLYGON) ||
1691  (arg1_ti.get_type() == kPOLYGON && arg0_ti.get_type() == kMULTIPOLYGON)) {
1692  // Swap arguments and use single implementation per arg pair
1693  swap_args = true;
1694  }
1695 
1696  // First input's compression mode and SRID args to enable on-the-fly
1697  // decompression/transforms
1698  Datum input_compression0;
1699  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1700  Datum input_srid0;
1701  input_srid0.intval = arg0_ti.get_input_srid();
1702 
1703  // Second input's compression mode and SRID args to enable on-the-fly
1704  // decompression/transforms
1705  Datum input_compression1;
1706  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1707  Datum input_srid1;
1708  input_srid1.intval = arg1_ti.get_input_srid();
1709 
1710  // Output SRID arg to enable on-the-fly transforms
1711  Datum output_srid;
1712  output_srid.intval = arg0_ti.get_output_srid();
1713 
1714  std::string specialized_geofunc{function_name};
1715  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1716  if (swap_args) {
1717  specialized_geofunc += suffix(arg1_ti.get_type()) + suffix(arg0_ti.get_type());
1718  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1719  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1720  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1721  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1722  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1723  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1724  } else {
1725  specialized_geofunc += suffix(arg0_ti.get_type()) + suffix(arg1_ti.get_type());
1726  if (is_geodesic) {
1727  specialized_geofunc += "_Geodesic"s;
1728  }
1729  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1730  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1731  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1732  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1733  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1734  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1735  }
1736  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1737  // Also add the within distance
1738  geoargs.push_back(distance_expr);
1739 
1740  auto result =
1741  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1742  return result;
1743  }
1744 
1745  // Otherwise translate function as binary geo to get distance,
1746  // with optional short-circuiting threshold held in the third operand
1747  const auto geo_distance = translateBinaryGeoFunction(rex_function);
1748  // and generate the comparison
1749  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, geo_distance, distance_expr);
1750 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
#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
Definition: sqldefs.h:37
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
int32_t intval
Definition: Datum.h:75
std::string suffix(SQLTypes type)
Definition: Codegen.cpp:75
Definition: sqldefs.h:74
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::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
Definition: sqltypes.h:72
const std::string & getName() const
Definition: RelAlgDag.h:506
Definition: Datum.h:71
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::translateUnaryGeoConstructor ( const RexFunctionOperator rex_function,
SQLTypeInfo ti,
const bool  with_bounds 
) const
private

Definition at line 1067 of file RelAlgTranslatorGeo.cpp.

References func_resolve, SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), RexFunctionOperator::getName(), RexOperator::getOperand(), Geospatial::GeoBase::kCONVEXHULL, kENCODING_NONE, kGEOMETRY, kMULTIPOLYGON, SQLTypeInfo::set_comp_param(), SQLTypeInfo::set_compression(), SQLTypeInfo::set_input_srid(), SQLTypeInfo::set_output_srid(), SQLTypeInfo::set_subtype(), SQLTypeInfo::set_type(), and translateGeoFunctionArg().

Referenced by translateFunction(), and translateGeoFunctionArg().

1070  {
1071 #ifndef ENABLE_GEOS
1072  throw QueryNotSupported(rex_function->getName() +
1073  " geo constructor requires enabled GEOS support");
1074 #endif
1076 
1077  Analyzer::ExpressionPtrVector geoargs0{};
1078  SQLTypeInfo arg0_ti;
1079  if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
1080  // First arg: geometry
1081  geoargs0 = translateGeoFunctionArg(rex_function->getOperand(0),
1082  arg0_ti,
1083  false,
1084  true,
1085  true,
1086  false,
1087  false,
1088  /* allow_gdal_transforms = */ true);
1089  }
1090 
1091  // Record the optional transform request that can be sent by an ecompassing TRANSFORM
1092  auto srid = ti.get_output_srid();
1093  // Build the typeinfo of the constructed geometry
1094  SQLTypeInfo arg_ti = arg0_ti;
1095  arg_ti.set_type(kMULTIPOLYGON);
1096  arg_ti.set_subtype(kGEOMETRY);
1097  arg_ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
1098  arg_ti.set_comp_param(0);
1099  arg_ti.set_input_srid(arg0_ti.get_output_srid());
1100  if (srid > 0) {
1101  if (arg_ti.get_input_srid() > 0) {
1102  // Constructed geometry to be transformed to srid given by encompassing transform
1103  arg_ti.set_output_srid(srid);
1104  } else {
1105  throw QueryNotSupported("Transform of geo constructor " + rex_function->getName() +
1106  " requires its argument(s) to have a valid srid");
1107  }
1108  } else {
1109  arg_ti.set_output_srid(arg_ti.get_input_srid()); // No encompassing transform
1110  }
1111  // If there was an output transform, it's now embedded into arg_ti and the geo operator.
1112  // Now de-register the transform from the return typeinfo:
1113  ti = arg_ti;
1115  return makeExpr<Analyzer::GeoUOper>(op, arg_ti, arg0_ti, geoargs0);
1116 }
void set_compression(EncodingType c)
Definition: sqltypes.h:481
auto func_resolve
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::translateUnaryGeoFunction ( const RexFunctionOperator rex_function) const
private

Definition at line 1118 of file RelAlgTranslatorGeo.cpp.

References CHECK, CHECK_EQ, func_resolve, Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_subtype(), SQLTypeInfo::get_type(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), SQLTypeInfo::has_bounds(), Datum::intval, IS_GEO, IS_GEO_POLY, kARRAY, kGEOGRAPHY, kINT, kLINESTRING, kMULTILINESTRING, kPOINT, kTINYINT, SQLTypeInfo::set_notnull(), RexOperator::size(), spatial_type::suffix(), and translateGeoFunctionArg().

Referenced by translateFunction().

1119  {
1120  CHECK_EQ(size_t(1), rex_function->size());
1121 
1122  std::string specialized_geofunc{rex_function->getName()};
1123 
1124  // Geo function calls which do not need the coords col but do need cols associated
1125  // with physical coords (e.g. ring_sizes / poly_rings)
1126  if (rex_function->getName() == "ST_NRings"sv) {
1127  SQLTypeInfo arg_ti;
1128  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
1129  arg_ti,
1130  /*with_bounds=*/false,
1131  /*expand_geo_col=*/true,
1132  /*is_projection=*/false,
1133  /*use_geo_expressions=*/true);
1134  if (!IS_GEO_POLY(arg_ti.get_type())) {
1135  throw QueryNotSupported(rex_function->getName() +
1136  " expects a POLYGON or MULTIPOLYGON");
1137  }
1138  CHECK_EQ(geoargs.size(), size_t(1));
1139  arg_ti = rex_function->getType(); // TODO: remove
1140  return makeExpr<Analyzer::GeoOperator>(
1141  rex_function->getType(),
1142  rex_function->getName(),
1143  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
1144  } else if (rex_function->getName() == "ST_NumGeometries"sv) {
1145  SQLTypeInfo arg_ti;
1146  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
1147  arg_ti,
1148  /*with_bounds=*/false,
1149  /*expand_geo_col=*/true,
1150  /*is_projection=*/false,
1151  /*use_geo_expressions=*/true);
1152  if (!IS_GEO(arg_ti.get_type())) {
1153  throw QueryNotSupported(rex_function->getName() + " expects a geo parameter");
1154  }
1155  CHECK_EQ(geoargs.size(), size_t(1));
1156  arg_ti = rex_function->getType(); // TODO: remove
1157  return makeExpr<Analyzer::GeoOperator>(
1158  rex_function->getType(),
1159  rex_function->getName(),
1160  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
1161  } else if (rex_function->getName() == "ST_NPoints"sv) {
1162  SQLTypeInfo arg_ti;
1163  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
1164  arg_ti,
1165  /*with_bounds=*/false,
1166  /*expand_geo_col=*/true,
1167  /*is_projection=*/false,
1168  /*use_geo_expressions=*/true);
1169  CHECK_EQ(geoargs.size(), size_t(1));
1170  auto expr_ti = rex_function->getType();
1171  expr_ti.set_notnull(arg_ti.get_notnull());
1172  return makeExpr<Analyzer::GeoOperator>(
1173  expr_ti,
1174  rex_function->getName(),
1175  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
1176  } else if (func_resolve(rex_function->getName(), "ST_Perimeter"sv, "ST_Area"sv)) {
1177  SQLTypeInfo arg_ti;
1178  int legacy_transform_srid = 0; // discard
1179  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
1180  arg_ti,
1181  /*with_bounds=*/false,
1182  /*expand_geo_col=*/true,
1183  /*is_projection=*/false,
1184  /*use_geo_expressions=*/true);
1185  CHECK_EQ(geoargs.size(), size_t(1));
1186  if (arg_ti.get_input_srid() != arg_ti.get_output_srid() &&
1187  arg_ti.get_output_srid() > 0 &&
1188  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
1189  // legacy transform
1190  legacy_transform_srid = arg_ti.get_output_srid();
1191  // Reset the transform, transform will be given to the operator as an override
1192  arg_ti = geoargs.front()->get_type_info();
1193  }
1194  if (!IS_GEO_POLY(arg_ti.get_type())) {
1195  throw QueryNotSupported(rex_function->getName() +
1196  " expects a POLYGON or MULTIPOLYGON");
1197  }
1198  return makeExpr<Analyzer::GeoOperator>(
1199  rex_function->getType(),
1200  rex_function->getName(),
1201  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()},
1202  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1203  : std::nullopt);
1204  }
1205 
1206  // Accessor for poly bounds for in-situ poly render queries
1207  if (func_resolve(rex_function->getName(), "HeavyDB_Geo_PolyBoundsPtr"sv)) {
1208  SQLTypeInfo arg_ti;
1209  // get geo column plus bounds only (not expanded)
1210  auto geoargs =
1211  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, true, false, false);
1212  // this function only works on polys
1213  if (!IS_GEO_POLY(arg_ti.get_type())) {
1214  throw QueryNotSupported(rex_function->getName() +
1215  " expects a POLYGON or MULTIPOLYGON");
1216  }
1217  // only need the bounds argument (last), discard the rest
1218  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1219  // done
1220  return makeExpr<Analyzer::FunctionOper>(
1221  rex_function->getType(), specialized_geofunc, geoargs);
1222  }
1223 
1224  // start to move geo expressions above the generic translation call, as geo expression
1225  // error handling can differ
1226  if (func_resolve(rex_function->getName(), "ST_X"sv, "ST_Y"sv)) {
1227  SQLTypeInfo arg_ti;
1228  auto new_geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
1229  arg_ti,
1230  /*with_bounds=*/false,
1231  /*expand_geo_col=*/true,
1232  /*is_projection=*/true,
1233  /*use_geo_expressions=*/true);
1234  CHECK_EQ(new_geoargs.size(), size_t(1));
1235  CHECK(new_geoargs.front());
1236  const auto& arg_expr_ti = new_geoargs.front()->get_type_info();
1237  if (arg_expr_ti.get_type() != kPOINT) {
1238  throw QueryNotSupported(rex_function->getName() + " expects a POINT");
1239  }
1240  auto function_ti = rex_function->getType();
1241  if (std::dynamic_pointer_cast<Analyzer::GeoOperator>(new_geoargs.front())) {
1242  function_ti.set_notnull(false);
1243  }
1244  if (std::dynamic_pointer_cast<Analyzer::GeoConstant>(new_geoargs.front())) {
1245  // TODO(adb): fixup null handling
1246  function_ti.set_notnull(true);
1247  }
1248  return makeExpr<Analyzer::GeoOperator>(
1249  function_ti,
1250  rex_function->getName(),
1251  std::vector<std::shared_ptr<Analyzer::Expr>>{new_geoargs.front()});
1252  }
1253 
1254  // All functions below use geo col as reference and expand it as necessary
1255  SQLTypeInfo arg_ti;
1256  bool with_bounds = true;
1257  auto geoargs =
1258  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, with_bounds, false);
1259 
1260  if (rex_function->getName() == "ST_SRID"sv) {
1261  Datum output_srid;
1262  output_srid.intval = arg_ti.get_output_srid();
1263  return makeExpr<Analyzer::Constant>(kINT, false, output_srid);
1264  }
1265 
1266  if (func_resolve(
1267  rex_function->getName(), "ST_XMin"sv, "ST_YMin"sv, "ST_XMax"sv, "ST_YMax"sv)) {
1268  // If type has bounds - use them, otherwise look at coords
1269  if (arg_ti.has_bounds()) {
1270  // Only need the bounds argument, discard the rest
1271  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1272 
1273  // Supply srids too - transformed geo would have a transformed bounding box
1274  Datum input_srid;
1275  input_srid.intval = arg_ti.get_input_srid();
1276  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1277  Datum output_srid;
1278  output_srid.intval = arg_ti.get_output_srid();
1279  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1280 
1281  specialized_geofunc += "_Bounds"s;
1282  return makeExpr<Analyzer::FunctionOper>(
1283  rex_function->getType(), specialized_geofunc, geoargs);
1284  }
1285  }
1286 
1287  // Unless overriden, function is assumed to be interested in the first geoarg only,
1288  // which may be a geo object (e.g. geo column), or a coord array (e.g. geo literal)
1289  auto discard_after_arg = 1;
1290 
1291  if (rex_function->getName() == "ST_Length"sv) {
1292  if (arg_ti.get_type() != kLINESTRING && arg_ti.get_type() != kMULTILINESTRING) {
1293  throw QueryNotSupported(rex_function->getName() +
1294  " expects LINESTRING or MULTILINESTRING");
1295  }
1296  if (arg_ti.get_type() == kMULTILINESTRING) {
1297  auto ti0 = geoargs[0]->get_type_info();
1298  if (ti0.get_type() == kARRAY && ti0.get_subtype() == kTINYINT) {
1299  // Received expanded geo: widen the reach to grab linestring size array as well
1300  discard_after_arg = 2;
1301  }
1302  }
1303  specialized_geofunc += suffix(arg_ti.get_type());
1304  if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
1305  if (arg_ti.get_type() == kMULTILINESTRING) {
1306  throw QueryNotSupported(rex_function->getName() +
1307  " Geodesic is not supported for MULTILINESTRING");
1308  }
1309  specialized_geofunc += "_Geodesic"s;
1310  }
1311  }
1312 
1313  geoargs.erase(geoargs.begin() + discard_after_arg, geoargs.end());
1314 
1315  // Add input compression mode and SRID args to enable on-the-fly
1316  // decompression/transforms
1317  Datum input_compression;
1318  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1319  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1320  Datum input_srid;
1321  input_srid.intval = arg_ti.get_input_srid();
1322  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1323 
1324  // Add output SRID arg to enable on-the-fly transforms
1325  Datum output_srid;
1326  output_srid.intval = arg_ti.get_output_srid();
1327  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1328 
1329  return makeExpr<Analyzer::FunctionOper>(
1330  rex_function->getType(), specialized_geofunc, geoargs);
1331 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
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
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
int32_t intval
Definition: Datum.h:75
std::string suffix(SQLTypes type)
Definition: Codegen.cpp:75
bool has_bounds() const
Definition: sqltypes.h:457
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
void set_notnull(bool n)
Definition: sqltypes.h:477
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
const std::string & getName() const
Definition: RelAlgDag.h:506
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
Definition: Datum.h:71
#define IS_GEO(T)
Definition: sqltypes.h:310
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397
#define IS_GEO_POLY(T)
Definition: sqltypes.h:315

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1027 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateFunction(), and translateGeoFunctionArg().

1030  {
1031 #ifndef ENABLE_GEOS
1032  throw QueryNotSupported(rex_function->getName() +
1033  " geo predicate requires enabled GEOS support");
1034 #endif
1035  SQLTypeInfo arg_ti;
1036  auto geoargs =
1037  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, true);
1038  ti = SQLTypeInfo(kBOOLEAN, false);
1039  auto op = (rex_function->getName() == "ST_IsEmpty"sv)
1042  return makeExpr<Analyzer::GeoUOper>(op, ti, arg_ti, geoargs);
1043 }
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::translateUnlikely ( const RexFunctionOperator rex_function) const
private

Definition at line 1263 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1264  {
1265  CHECK(rex_function->size() == 1);
1266  const auto arg = translateScalarRex(rex_function->getOperand(0));
1267  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.0625);
1268 }
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::translateUoper ( const RexOperator rex_operator) const
private

Definition at line 559 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, CHECK_NE, g_cluster, SQLTypeInfo::get_type(), RexOperator::getOperand(), RexOperator::getOperator(), RexOperator::getType(), is_null(), kBOOLEAN, kCAST, kDATE, kENCODE_TEXT, kENCODING_DICT, kISNOTNULL, kISNULL, kMINUS, kNOT, kNULLT, kTEXT, shared::StringDictKey::kTransientDictKey, kUMINUS, kUNNEST, SQLTypeInfo::set_comp_param(), SQLTypeInfo::set_compression(), SQLTypeInfo::set_fixed_size(), SQLTypeInfo::set_type(), SQLTypeInfo::setStringDictKey(), RexOperator::size(), TRANSIENT_DICT_ID, and translateScalarRex().

Referenced by translateOper().

560  {
561  CHECK_EQ(size_t(1), rex_operator->size());
562  auto operand_expr = translateScalarRex(rex_operator->getOperand(0));
563  const auto sql_op = rex_operator->getOperator();
564  switch (sql_op) {
565  case kCAST: {
566  const auto& target_ti = rex_operator->getType();
567  CHECK_NE(kNULLT, target_ti.get_type());
568  const auto& operand_ti = operand_expr->get_type_info();
569  if (operand_ti.is_string() && target_ti.is_string()) {
570  return operand_expr;
571  }
572  if (target_ti.is_time() ||
573  operand_ti
574  .is_string()) { // TODO(alex): check and unify with the rest of the cases
575  // Do not propogate encoding on small dates
576  return target_ti.is_date_in_days()
577  ? operand_expr->add_cast(SQLTypeInfo(kDATE, false))
578  : operand_expr->add_cast(target_ti);
579  }
580  if (!operand_ti.is_string() && target_ti.is_string()) {
581  return operand_expr->add_cast(target_ti);
582  }
583  return std::make_shared<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
584  }
585  case kENCODE_TEXT: {
586  SQLTypeInfo target_ti = rex_operator->getType();
587  if (target_ti.get_type() == kNULLT) {
588  if (auto const_expr =
589  dynamic_cast<const Analyzer::Constant*>(operand_expr.get())) {
590  if (const_expr->get_type_info() == kNULLT && const_expr->get_is_null()) {
591  // make a typed NULL constant and sync it to target_ti
592  operand_expr = makeExpr<Analyzer::Constant>(kTEXT, true);
593  target_ti.set_type(kTEXT);
594  }
595  }
596  }
597  CHECK_NE(kNULLT, target_ti.get_type());
598  const auto& operand_ti = operand_expr->get_type_info();
599  CHECK(operand_ti.is_string());
600  if (operand_ti.is_dict_encoded_string()) {
601  // No cast needed
602  return operand_expr;
603  }
604  if (operand_expr->get_num_column_vars(true) == 0UL) {
605  return operand_expr;
606  }
607  if (g_cluster) {
608  throw std::runtime_error(
609  "ENCODE_TEXT is not currently supported in distributed mode at this time.");
610  }
611  SQLTypeInfo casted_target_ti = operand_ti;
612  casted_target_ti.set_type(kTEXT);
613  casted_target_ti.set_compression(kENCODING_DICT);
614  casted_target_ti.set_comp_param(TRANSIENT_DICT_ID);
616  casted_target_ti.set_fixed_size();
617  return makeExpr<Analyzer::UOper>(
618  casted_target_ti, operand_expr->get_contains_agg(), kCAST, operand_expr);
619  }
620  case kNOT:
621  case kISNULL: {
622  return std::make_shared<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
623  }
624  case kISNOTNULL: {
625  auto is_null = std::make_shared<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
626  return std::make_shared<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
627  }
628  case kMINUS: {
629  const auto& ti = operand_expr->get_type_info();
630  return std::make_shared<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
631  }
632  case kUNNEST: {
633  const auto& ti = operand_expr->get_type_info();
634  CHECK(ti.is_array());
635  return makeExpr<Analyzer::UOper>(ti.get_elem_type(), false, kUNNEST, operand_expr);
636  }
637  default:
638  CHECK(false);
639  }
640  return nullptr;
641 }
void set_compression(EncodingType c)
Definition: sqltypes.h:481
#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
Definition: sqldefs.h:51
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
#define TRANSIENT_DICT_ID
Definition: DbObjectKeys.h:24
SQLOps getOperator() const
Definition: RelAlgDag.h:376
CONSTEXPR DEVICE bool is_null(const T &value)
void set_fixed_size()
Definition: sqltypes.h:479
#define CHECK_NE(x, y)
Definition: Logger.h:302
void set_comp_param(int p)
Definition: sqltypes.h:482
Definition: sqltypes.h:79
Definition: sqltypes.h:80
Definition: sqldefs.h:42
void setStringDictKey(const shared::StringDictKey &dict_key)
Definition: sqltypes.h:1063
static const StringDictKey kTransientDictKey
Definition: DbObjectKeys.h:45
#define CHECK(condition)
Definition: Logger.h:291
bool g_cluster
Definition: sqldefs.h:41
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::translateWidthBucket ( const RexFunctionOperator rex_function) const
private

Definition at line 1182 of file RelAlgTranslator.cpp.

References CHECK, RexOperator::getOperand(), kDOUBLE, kNULLT, gpu_enabled::lower_bound(), RexOperator::size(), translateScalarRex(), and gpu_enabled::upper_bound().

Referenced by translateFunction().

1183  {
1184  CHECK(rex_function->size() == 4);
1185  auto target_value = translateScalarRex(rex_function->getOperand(0));
1186  auto lower_bound = translateScalarRex(rex_function->getOperand(1));
1187  auto upper_bound = translateScalarRex(rex_function->getOperand(2));
1188  auto partition_count = translateScalarRex(rex_function->getOperand(3));
1189  if (!partition_count->get_type_info().is_integer()) {
1190  throw std::runtime_error(
1191  "PARTITION_COUNT expression of width_bucket function expects an integer type.");
1192  }
1193  auto check_numeric_type =
1194  [](const std::string& col_name, const Analyzer::Expr* expr, bool allow_null_type) {
1195  if (expr->get_type_info().get_type() == kNULLT) {
1196  if (!allow_null_type) {
1197  throw std::runtime_error(
1198  col_name + " expression of width_bucket function expects non-null type.");
1199  }
1200  return;
1201  }
1202  if (!expr->get_type_info().is_number()) {
1203  throw std::runtime_error(
1204  col_name + " expression of width_bucket function expects a numeric type.");
1205  }
1206  };
1207  // target value may have null value
1208  check_numeric_type("TARGET_VALUE", target_value.get(), true);
1209  check_numeric_type("LOWER_BOUND", lower_bound.get(), false);
1210  check_numeric_type("UPPER_BOUND", upper_bound.get(), false);
1211 
1212  auto cast_to_double_if_necessary = [](std::shared_ptr<Analyzer::Expr> arg) {
1213  const auto& arg_ti = arg->get_type_info();
1214  if (arg_ti.get_type() != kDOUBLE) {
1215  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1216  return arg->add_cast(double_ti);
1217  }
1218  return arg;
1219  };
1220  target_value = cast_to_double_if_necessary(target_value);
1221  lower_bound = cast_to_double_if_necessary(lower_bound);
1222  upper_bound = cast_to_double_if_necessary(upper_bound);
1223  return makeExpr<Analyzer::WidthBucketExpr>(
1224  target_value, lower_bound, upper_bound, partition_count);
1225 }
DEVICE auto upper_bound(ARGS &&...args)
Definition: gpu_enabled.h:123
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
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
#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::translateWindowFunction ( const RexWindowFunctionOperator rex_window_function) const
private

Definition at line 2256 of file RelAlgTranslator.cpp.

References anonymous_namespace{QueryMemoryDescriptor.cpp}::any_of(), run_benchmark_import::args, BACKWARD_FILL, CHECK_GE, Analyzer::ColumnVar::collect_column_var(), Analyzer::ColumnVar::colvar_comp(), CONDITIONAL_CHANGE_EVENT, COUNT, CURRENT_ROW, anonymous_namespace{RelAlgTranslator.cpp}::determine_frame_bound_type(), EXPR_PRECEDING, FIRST_VALUE_IN_FRAME, FORWARD_FILL, g_bigint_count, RexWindowFunctionOperator::getCollation(), RexWindowFunctionOperator::getFrameEndBound(), RexWindowFunctionOperator::getFrameStartBound(), RexWindowFunctionOperator::getKind(), RexOperator::getOperand(), RexWindowFunctionOperator::getOrderKeys(), RexWindowFunctionOperator::getPartitionKeys(), RexOperator::getType(), logger::INFO, Datum::intval, anonymous_namespace{RelAlgTranslator.cpp}::is_negative_framing_bound(), Analyzer::WindowFunction::isFramingAvailableWindowFunc(), RexWindowFunctionOperator::isRows(), kBIGINT, kENCODING_DICT, kINT, LAG_IN_FRAME, LAST_VALUE_IN_FRAME, LEAD_IN_FRAME, LOG, Analyzer::WindowFunction::NONE, NTH_VALUE, NTH_VALUE_IN_FRAME, Analyzer::WindowFunction::RANGE, Analyzer::WindowFunction::ROW, RexOperator::size(), toString(), anonymous_namespace{RelAlgTranslator.cpp}::translate_collation(), translateFrameBoundExpr(), translateIntervalExprForWindowFraming(), translateScalarRex(), UNBOUNDED_FOLLOWING, UNBOUNDED_PRECEDING, UNKNOWN, VLOG, window_function_is_value(), and window_function_is_value_with_frame().

2257  {
2258  std::vector<std::shared_ptr<Analyzer::Expr>> args;
2259  for (size_t i = 0; i < rex_window_function->size(); ++i) {
2260  args.push_back(translateScalarRex(rex_window_function->getOperand(i)));
2261  }
2262  std::vector<std::shared_ptr<Analyzer::Expr>> partition_keys;
2263  for (const auto& partition_key : rex_window_function->getPartitionKeys()) {
2264  partition_keys.push_back(translateScalarRex(partition_key.get()));
2265  }
2266  std::vector<std::shared_ptr<Analyzer::Expr>> order_keys;
2267  for (const auto& order_key : rex_window_function->getOrderKeys()) {
2268  order_keys.push_back(translateScalarRex(order_key.get()));
2269  }
2270  std::vector<Analyzer::OrderEntry> collation =
2271  translate_collation(rex_window_function->getCollation());
2272 
2273  auto ti = rex_window_function->getType();
2274  auto window_func_kind = rex_window_function->getKind();
2275  if (window_function_is_value(window_func_kind)) {
2276  CHECK_GE(args.size(), 1u);
2277  if (!window_function_is_value_with_frame(window_func_kind)) {
2278  // value window functions w/ frame have logic to access argument's typeinfo
2279  // during codegen, i.e., codegenWindowNavigationFunctionOnFrame(...)
2280  // but not for non-framed value window function, so we use their arg's typeinfo
2281  // as window function's typeinfo
2282  ti = args.front()->get_type_info();
2283  }
2284  // set value type window functions' nullability
2285  ti.set_notnull(false);
2286  }
2287 
2288  bool negative_constant = false;
2289  bool detect_invalid_frame_start_bound_expr = false;
2290  bool detect_invalid_frame_end_bound_expr = false;
2291  auto& frame_start_bound = rex_window_function->getFrameStartBound();
2292  auto& frame_end_bound = rex_window_function->getFrameEndBound();
2293  bool has_end_bound_frame_expr = false;
2294  std::shared_ptr<Analyzer::Expr> frame_start_bound_expr;
2295  SqlWindowFrameBoundType frame_start_bound_type =
2296  determine_frame_bound_type(frame_start_bound);
2297  std::shared_ptr<Analyzer::Expr> frame_end_bound_expr;
2298  SqlWindowFrameBoundType frame_end_bound_type =
2299  determine_frame_bound_type(frame_end_bound);
2300  bool has_framing_clause =
2302  auto frame_mode = rex_window_function->isRows()
2305  if (order_keys.empty()) {
2306  if (frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2307  frame_end_bound_type == SqlWindowFrameBoundType::UNBOUNDED_FOLLOWING) {
2308  // Calcite sets UNBOUNDED PRECEDING ~ UNBOUNDED_FOLLOWING as its default frame
2309  // bound if the window context has no order by clause regardless of the existence
2310  // of user-given window frame bound but at this point we have no way to recognize
2311  // the absence of the frame definition of this window context
2312  has_framing_clause = false;
2313  }
2314  } else {
2315  if (frame_start_bound.bound_expr) {
2316  std::tie(detect_invalid_frame_start_bound_expr,
2317  negative_constant,
2318  frame_start_bound_expr) =
2319  translateFrameBoundExpr(frame_start_bound.bound_expr.get());
2320  }
2321 
2322  if (frame_end_bound.bound_expr) {
2323  std::tie(
2324  detect_invalid_frame_end_bound_expr, negative_constant, frame_end_bound_expr) =
2325  translateFrameBoundExpr(frame_end_bound.bound_expr.get());
2326  }
2327 
2328  // currently we only support literal expression as frame bound expression
2329  if (detect_invalid_frame_start_bound_expr || detect_invalid_frame_end_bound_expr) {
2330  throw std::runtime_error(
2331  "We currently only support literal expression as a window frame bound "
2332  "expression");
2333  }
2334 
2335  // note that Calcite already has frame-bound constraint checking logic, but we
2336  // also check various invalid cases for safety
2337  if (negative_constant) {
2338  throw std::runtime_error(
2339  "A constant expression for window framing should have nonnegative value.");
2340  }
2341 
2342  if (frame_start_bound_expr &&
2343  frame_start_bound_expr->get_type_info().is_timeinterval()) {
2344  frame_start_bound_expr = translateIntervalExprForWindowFraming(
2345  order_keys.front(),
2346  frame_start_bound_type == SqlWindowFrameBoundType::EXPR_PRECEDING,
2347  frame_start_bound_expr.get());
2348  }
2349 
2350  if (frame_end_bound_expr && frame_end_bound_expr->get_type_info().is_timeinterval()) {
2351  frame_end_bound_expr = translateIntervalExprForWindowFraming(
2352  order_keys.front(),
2353  frame_end_bound_type == SqlWindowFrameBoundType::EXPR_PRECEDING,
2354  frame_end_bound_expr.get());
2355  }
2356  }
2357 
2358  if (frame_start_bound.following) {
2359  if (frame_end_bound.is_current_row) {
2360  throw std::runtime_error(
2361  "Window framing starting from following row cannot end with current row.");
2362  } else if (has_end_bound_frame_expr && frame_end_bound.preceding) {
2363  throw std::runtime_error(
2364  "Window framing starting from following row cannot have preceding rows.");
2365  }
2366  }
2367 
2368  if (frame_start_bound.is_current_row && frame_end_bound.preceding &&
2369  !frame_end_bound.unbounded && has_end_bound_frame_expr) {
2370  throw std::runtime_error(
2371  "Window framing starting from current row cannot have preceding rows.");
2372  }
2373 
2374  if (!frame_start_bound_expr &&
2375  frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2376  !frame_end_bound_expr &&
2377  frame_end_bound_type == SqlWindowFrameBoundType::CURRENT_ROW) {
2378  has_framing_clause = false;
2379  VLOG(1) << "Ignore range framing mode with a frame bound between "
2380  "UNBOUNDED_PRECEDING and CURRENT_ROW";
2381  }
2382 
2383  if (has_framing_clause) {
2385  if (order_keys.size() != 1) {
2386  throw std::runtime_error(
2387  "Window framing with range mode requires a single order-by column");
2388  }
2389  std::set<const Analyzer::ColumnVar*,
2390  bool (*)(const Analyzer::ColumnVar*, const Analyzer::ColumnVar*)>
2392  order_keys.front()->collect_column_var(colvar_set, false);
2393  for (auto cv : colvar_set) {
2394  if (!(cv->get_type_info().is_integer() || cv->get_type_info().is_fp() ||
2395  cv->get_type_info().is_time())) {
2396  has_framing_clause = false;
2397  VLOG(1) << "Range framing mode with non-number type ordering column is not "
2398  "supported yet, skip window framing";
2399  }
2400  }
2401  }
2402  }
2403 
2404  std::string const func_name = toString(window_func_kind);
2405  auto const num_args = args.size();
2406  bool need_order_by_clause = false;
2407  bool need_frame_def = false;
2408  switch (window_func_kind) {
2410  if (has_framing_clause && args.empty()) {
2411  args.push_back(
2412  makeExpr<Analyzer::Constant>(g_bigint_count ? kBIGINT : kINT, true));
2413  }
2414  break;
2415  }
2418  need_order_by_clause = true;
2419  need_frame_def = true;
2420  if (num_args != 2) {
2421  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2422  }
2423  Datum d;
2424  d.intval = 1;
2425  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, d));
2426  const auto target_expr_cv =
2427  dynamic_cast<const Analyzer::ColumnVar*>(args.front().get());
2428  if (!target_expr_cv) {
2429  throw std::runtime_error("Currently, " + func_name +
2430  " only allows a column reference as its first argument");
2431  }
2432  const auto target_ti = target_expr_cv->get_type_info();
2433  if (target_ti.is_dict_encoded_string()) {
2434  // Calcite does not represent a window function having dictionary encoded text
2435  // type as its output properly, so we need to set its output type manually
2436  ti.set_compression(kENCODING_DICT);
2437  ti.set_comp_param(target_expr_cv->get_type_info().get_comp_param());
2438  ti.setStringDictKey(target_expr_cv->get_type_info().getStringDictKey());
2439  ti.set_fixed_size();
2440  }
2441  const auto target_offset_cv =
2442  dynamic_cast<const Analyzer::Constant*>(args[1].get());
2443  if (!target_expr_cv ||
2444  is_negative_framing_bound(target_offset_cv->get_type_info().get_type(),
2445  target_offset_cv->get_constval())) {
2446  throw std::runtime_error(
2447  "Currently, " + func_name +
2448  " only allows non-negative constant as its second argument");
2449  }
2450  break;
2451  }
2454  if (num_args != 1) {
2455  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2456  }
2457  need_order_by_clause = true;
2458  need_frame_def = true;
2459  break;
2462  if (has_framing_clause) {
2463  throw std::runtime_error(func_name + " does not support window framing clause");
2464  }
2465  auto const input_expr_ti = args.front()->get_type_info();
2466  if (input_expr_ti.is_string()) {
2467  throw std::runtime_error(func_name + " not supported on " +
2468  input_expr_ti.get_type_name() + " type yet");
2469  }
2470  need_order_by_clause = true;
2471  std::string const arg_str{args.front()->toString()};
2472  bool needs_inject_input_arg_ordering =
2473  !std::any_of(order_keys.cbegin(),
2474  order_keys.cend(),
2475  [&arg_str](std::shared_ptr<Analyzer::Expr> const& expr) {
2476  return boost::equals(arg_str, expr->toString());
2477  });
2478  if (needs_inject_input_arg_ordering) {
2479  VLOG(1) << "Inject " << args.front()->toString() << " as ordering column of the "
2480  << func_name << " function";
2481  order_keys.push_back(args.front());
2482  // forward_fill can fill null values if it is ordered with NULLS LAST
2483  // in contrast, we make NULLS FIRST ordering for the backward_fill function
2484  collation.emplace_back(collation.size() + 1,
2485  false,
2486  window_func_kind != SqlWindowFunctionKind::FORWARD_FILL);
2487  }
2488  break;
2489  }
2492  // todo (yoonmin) : args.size() will be three if we support default value
2493  if (num_args != 2) {
2494  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2495  }
2496  if (window_func_kind == SqlWindowFunctionKind::NTH_VALUE_IN_FRAME) {
2497  need_order_by_clause = true;
2498  need_frame_def = true;
2499  }
2500  if (!args[1]) {
2501  throw std::runtime_error(func_name +
2502  " must have a positional argument expression.");
2503  }
2504  bool has_valid_arg = false;
2505  if (args[1]->get_type_info().is_integer()) {
2506  if (auto* n_value_ptr = dynamic_cast<Analyzer::Constant*>(args[1].get())) {
2507  if (0 < n_value_ptr->get_constval().intval) {
2508  // i.e., having N larger than the partition size
2509  // set the proper N to match the zero-start index pos
2510  auto d = n_value_ptr->get_constval();
2511  d.intval -= 1;
2512  n_value_ptr->set_constval(d);
2513  has_valid_arg = true;
2514  }
2515  }
2516  }
2517  if (!has_valid_arg) {
2518  throw std::runtime_error("The positional argument of the " + func_name +
2519  " must be a positive integer constant.");
2520  }
2521  break;
2522  }
2524  if (order_keys.empty()) {
2525  throw std::runtime_error(
2526  func_name + " requires an ORDER BY sub-clause within the window clause");
2527  }
2528  if (has_framing_clause) {
2529  LOG(INFO)
2530  << window_func_kind
2531  << " must use a pre-defined window frame range (e.g., ROWS BETWEEN "
2532  "UNBOUNDED PRECEDING AND CURRENT ROW). "
2533  "Thus, we skip the user-defined window frame for this window function";
2534  }
2535  has_framing_clause = true;
2537  frame_start_bound_type = SqlWindowFrameBoundType::UNBOUNDED_PRECEDING;
2538  frame_end_bound_type = SqlWindowFrameBoundType::CURRENT_ROW;
2539  break;
2540  default:;
2541  }
2542 
2543  if (need_order_by_clause && order_keys.empty()) {
2544  throw std::runtime_error(func_name + " requires an ORDER BY clause");
2545  }
2546 
2547  if (need_frame_def && !has_framing_clause) {
2548  throw std::runtime_error(func_name + " requires window frame definition");
2549  }
2550 
2551  if (!has_framing_clause) {
2552  frame_start_bound_type = SqlWindowFrameBoundType::UNKNOWN;
2553  frame_end_bound_type = SqlWindowFrameBoundType::UNKNOWN;
2554  frame_start_bound_expr = nullptr;
2555  frame_end_bound_expr = nullptr;
2556  }
2557 
2558  return makeExpr<Analyzer::WindowFunction>(
2559  ti,
2560  rex_window_function->getKind(),
2561  args,
2562  partition_keys,
2563  order_keys,
2564  has_framing_clause ? frame_mode : Analyzer::WindowFunction::FrameBoundType::NONE,
2565  makeExpr<Analyzer::WindowFrame>(frame_start_bound_type, frame_start_bound_expr),
2566  makeExpr<Analyzer::WindowFrame>(frame_end_bound_type, frame_end_bound_expr),
2567  collation);
2568 }
SqlWindowFrameBoundType
Definition: sqldefs.h:202
SqlWindowFrameBoundType determine_frame_bound_type(const RexWindowFunctionOperator::RexWindowBound &bound)
static bool colvar_comp(const ColumnVar *l, const ColumnVar *r)
Definition: Analyzer.h:215
void collect_column_var(std::set< const ColumnVar *, bool(*)(const ColumnVar *, const ColumnVar *)> &colvar_set, bool include_agg) const override
Definition: Analyzer.h:222
#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
const std::vector< SortField > & getCollation() const
Definition: RelAlgDag.h:670
static bool isFramingAvailableWindowFunc(SqlWindowFunctionKind kind)
Definition: Analyzer.h:2966
#define CHECK_GE(x, y)
Definition: Logger.h:306
int32_t intval
Definition: Datum.h:75
bool window_function_is_value(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:29
std::vector< Analyzer::OrderEntry > translate_collation(const std::vector< SortField > &sort_fields)
bool g_bigint_count
const RexWindowBound & getFrameEndBound() const
Definition: RelAlgDag.h:674
std::tuple< bool, bool, std::shared_ptr< Analyzer::Expr > > translateFrameBoundExpr(const RexScalar *bound_expr) const
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:643
std::shared_ptr< Analyzer::Expr > translateIntervalExprForWindowFraming(std::shared_ptr< Analyzer::Expr > order_key, bool for_preceding_bound, const Analyzer::Expr *expr) const
bool is_negative_framing_bound(const SQLTypes t, const Datum &d, bool is_time_unit=false)
const RexWindowBound & getFrameStartBound() const
Definition: RelAlgDag.h:672
SqlWindowFunctionKind getKind() const
Definition: RelAlgDag.h:641
bool window_function_is_value_with_frame(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:47
const ConstRexScalarPtrVector & getOrderKeys() const
Definition: RelAlgDag.h:653
bool isRows() const
Definition: RelAlgDag.h:676
Definition: sqltypes.h:72
bool any_of(std::vector< Analyzer::Expr * > const &target_exprs)
Definition: Datum.h:71
#define VLOG(n)
Definition: Logger.h:388

+ Here is the call graph for this function:

Member Data Documentation

robin_hood::unordered_map<RexScalar const*, std::shared_ptr<Analyzer::Expr> > RelAlgTranslator::cache_
mutableprivate

Definition at line 248 of file RelAlgTranslator.h.

Referenced by translate(), and translateScalarRex().

const Executor* RelAlgTranslator::executor_
private

Definition at line 239 of file RelAlgTranslator.h.

Referenced by getInIntegerSetExpr(), translateCase(), and translateOper().

bool RelAlgTranslator::generated_geos_ops_
mutableprivate

Definition at line 243 of file RelAlgTranslator.h.

Referenced by generated_geos_ops().

const std::unordered_map<const RelAlgNode*, int> RelAlgTranslator::input_to_nest_level_
private

Definition at line 240 of file RelAlgTranslator.h.

Referenced by translateGeoColumn(), and translateInput().

const std::vector<JoinType> RelAlgTranslator::join_types_
private

Definition at line 241 of file RelAlgTranslator.h.

Referenced by translateInput().

const bool RelAlgTranslator::just_explain_
private

Definition at line 244 of file RelAlgTranslator.h.

Referenced by translateInOper(), and translateScalarSubquery().

time_t RelAlgTranslator::now_
private
std::shared_ptr<const query_state::QueryState> RelAlgTranslator::query_state_
private

Definition at line 238 of file RelAlgTranslator.h.

Referenced by translateCurrentUser().


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