OmniSciDB  72c90bc290
 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::shared_ptr< Analyzer::ExprtranslateIntervalExprForWindowFraming (std::shared_ptr< Analyzer::Expr > order_key, bool for_preceding_bound, const Analyzer::BinOper *frame_bound_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 923 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().

925  {
927  return nullptr;
928  }
929  std::vector<int64_t> value_exprs;
930  const size_t fetcher_count = cpu_threads();
931  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
932  std::vector<std::future<void>> fetcher_threads;
933  const auto& arg_type = arg->get_type_info();
934  const auto entry_count = val_set.entryCount();
935  CHECK_EQ(size_t(1), val_set.colCount());
936  const auto& col_type = val_set.getColType(0);
937  if (g_cluster && arg_type.is_string() &&
938  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
939  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
940  return nullptr;
941  }
942  std::atomic<size_t> total_in_vals_count{0};
943  for (size_t i = 0,
944  start_entry = 0,
945  stride = (entry_count + fetcher_count - 1) / fetcher_count;
946  i < fetcher_count && start_entry < entry_count;
947  ++i, start_entry += stride) {
948  expr_set[i].reserve(entry_count / fetcher_count);
949  const auto end_entry = std::min(start_entry + stride, entry_count);
950  if (arg_type.is_string()) {
951  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
952  auto col_expr = dynamic_cast<const Analyzer::ColumnVar*>(arg.get());
953  CHECK(col_expr);
954  const auto& dest_dict_key = arg_type.getStringDictKey();
955  const auto& source_dict_key = col_type.getStringDictKey();
956  const auto dd = executor_->getStringDictionaryProxy(
957  arg_type.getStringDictKey(), val_set.getRowSetMemOwner(), true);
958  const auto sd = executor_->getStringDictionaryProxy(
959  col_type.getStringDictKey(), val_set.getRowSetMemOwner(), true);
960  CHECK(sd);
961  const auto needle_null_val = inline_int_null_val(arg_type);
963  col_expr->getColumnKey().db_id);
964  CHECK(catalog);
965  fetcher_threads.push_back(std::async(
967  [&val_set,
968  &total_in_vals_count,
969  sd,
970  dd,
971  &source_dict_key,
972  &dest_dict_key,
973  needle_null_val,
974  catalog](std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
975  if (g_cluster) {
976  CHECK_GE(dd->getGeneration(), 0);
978  in_vals,
979  total_in_vals_count,
980  &val_set,
981  {start, end},
982  catalog->getStringDictionaryHosts(),
983  {source_dict_key.db_id, source_dict_key.dict_id},
984  {dest_dict_key.db_id, dest_dict_key.dict_id},
985  dd->getGeneration(),
986  needle_null_val);
987  } else {
989  total_in_vals_count,
990  &val_set,
991  {start, end},
992  sd,
993  dd,
994  needle_null_val);
995  }
996  },
997  std::ref(expr_set[i]),
998  start_entry,
999  end_entry));
1000  } else {
1001  CHECK(arg_type.is_integer());
1002  fetcher_threads.push_back(std::async(
1004  [&val_set, &total_in_vals_count](
1005  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
1006  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
1007  },
1008  std::ref(expr_set[i]),
1009  start_entry,
1010  end_entry));
1011  }
1012  }
1013  for (auto& child : fetcher_threads) {
1014  child.get();
1015  }
1016 
1017  val_set.moveToBegin();
1018  value_exprs.reserve(entry_count);
1019  for (auto& exprs : expr_set) {
1020  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
1021  }
1022  return makeExpr<Analyzer::InIntegerSet>(
1023  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
1024 }
#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 58 of file RelAlgTranslator.cpp.

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

Referenced by translateOper().

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

259  {
260  ScopeGuard clear_cache{[this] { cache_.clear(); }};
261  return translateScalarRex(rex);
262 }
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 1608 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().

1609  {
1610  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1611  expr_list;
1612  CHECK_EQ(size_t(1), rex_function->size());
1613  const auto operand = translateScalarRex(rex_function->getOperand(0));
1614  const auto& operand_ti = operand->get_type_info();
1615  CHECK(operand_ti.is_number());
1616  const auto zero = makeNumericConstant(operand_ti, 0);
1617  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1618  const auto uminus_operand =
1619  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1620  expr_list.emplace_back(lt_zero, uminus_operand);
1621  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1622 }
#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:71
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:32

+ 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 278 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().

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

+ 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 1650 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().

1651  {
1652  if (rex_function->getType().get_subtype() == kNULLT) {
1653  auto sql_type = rex_function->getType();
1654  CHECK(sql_type.get_type() == kARRAY);
1655 
1656  // FIX-ME: Deal with NULL arrays
1657  auto translated_function_args(translateFunctionArgs(rex_function));
1658  if (translated_function_args.size() > 0) {
1659  const auto first_element_logical_type =
1660  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1661 
1662  auto diff_elem_itr =
1663  std::find_if(translated_function_args.begin(),
1664  translated_function_args.end(),
1665  [first_element_logical_type](const auto expr) {
1666  const auto element_logical_type =
1667  get_nullable_logical_type_info(expr->get_type_info());
1668  if (first_element_logical_type != element_logical_type) {
1669  if (first_element_logical_type.is_none_encoded_string() &&
1670  element_logical_type.is_none_encoded_string()) {
1671  return false;
1672  }
1673  return true;
1674  }
1675  return false;
1676  });
1677  if (diff_elem_itr != translated_function_args.end()) {
1678  throw std::runtime_error(
1679  "Element " +
1680  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1681  " is not of the same type as other elements of the array. Consider casting "
1682  "to force this condition.\nElement Type: " +
1683  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1684  .to_string() +
1685  "\nArray type: " + first_element_logical_type.to_string());
1686  }
1687 
1688  if (first_element_logical_type.is_string()) {
1689  sql_type.set_subtype(kTEXT);
1690  sql_type.set_compression(kENCODING_DICT);
1691  if (first_element_logical_type.is_none_encoded_string()) {
1692  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1693  sql_type.setStringDictKey(shared::StringDictKey::kTransientDictKey);
1694  } else {
1695  CHECK(first_element_logical_type.is_dict_encoded_string());
1696  sql_type.set_comp_param(first_element_logical_type.get_comp_param());
1697  sql_type.setStringDictKey(first_element_logical_type.getStringDictKey());
1698  }
1699  } else if (first_element_logical_type.is_dict_encoded_string()) {
1700  sql_type.set_subtype(kTEXT);
1701  sql_type.set_compression(kENCODING_DICT);
1702  sql_type.set_comp_param(first_element_logical_type.get_comp_param());
1703  sql_type.setStringDictKey(first_element_logical_type.getStringDictKey());
1704  } else {
1705  sql_type.set_subtype(first_element_logical_type.get_type());
1706  sql_type.set_scale(first_element_logical_type.get_scale());
1707  sql_type.set_precision(first_element_logical_type.get_precision());
1708  }
1709 
1710  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1711  } else {
1712  // defaulting to valid sub-type for convenience
1713  sql_type.set_subtype(kBOOLEAN);
1714  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1715  }
1716  } else {
1717  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1718  translateFunctionArgs(rex_function));
1719  }
1720 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1488
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 948 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().

951  {
952 #ifndef ENABLE_GEOS
953  throw QueryNotSupported(rex_function->getName() +
954  " geo constructor requires enabled GEOS support");
955 #endif
957  if (rex_function->getName() == "ST_Difference"sv) {
959  } else if (rex_function->getName() == "ST_Union"sv) {
961  } else if (rex_function->getName() == "ST_Buffer"sv) {
963  } else if (rex_function->getName() == "ST_ConcaveHull"sv) {
965  }
966 
969  SQLTypeInfo arg0_ti;
970  SQLTypeInfo arg1_ti;
971  if (func_resolve(rex_function->getName(),
972  "ST_Intersection"sv,
973  "ST_Difference"sv,
974  "ST_Union"sv,
975  "ST_Buffer"sv,
976  "ST_ConcaveHull"sv)) {
977  // First arg: geometry
978  geoargs0 = translateGeoFunctionArg(rex_function->getOperand(0),
979  arg0_ti,
980  false,
981  true,
982  true,
983  false,
984  false,
985  /* allow_gdal_transforms = */ true);
986  }
987  if (func_resolve(rex_function->getName(),
988  "ST_Intersection"sv,
989  "ST_Difference"sv,
990  "ST_Union"sv)) {
991  // Second arg: geometry
992  geoargs1 = translateGeoFunctionArg(rex_function->getOperand(1),
993  arg1_ti,
994  false,
995  true,
996  true,
997  false,
998  false,
999  /* allow_gdal_transforms = */ true);
1000  if (arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1001  throw QueryNotSupported(rex_function->getName() +
1002  " geo constructor requires arguments with matching srids");
1003  }
1004  } else if (func_resolve(rex_function->getName(), "ST_Buffer"sv, "ST_ConcaveHull"sv)) {
1005  // Second arg: double scalar
1006  auto param_expr = translateScalarRex(rex_function->getOperand(1));
1007  arg1_ti = SQLTypeInfo(kDOUBLE, false);
1008  if (param_expr->get_type_info().get_type() != kDOUBLE) {
1009  param_expr = param_expr->add_cast(arg1_ti);
1010  }
1011  geoargs1 = {param_expr};
1012  }
1013 
1014  // Record the optional transform request that can be sent by an ecompassing TRANSFORM
1015  auto srid = ti.get_output_srid();
1016  // Build the typeinfo of the constructed geometry
1017  SQLTypeInfo arg_ti = arg0_ti;
1018  arg_ti.set_type(kMULTIPOLYGON);
1019  arg_ti.set_subtype(kGEOMETRY);
1020  arg_ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
1021  arg_ti.set_comp_param(0);
1022  arg_ti.set_input_srid(arg0_ti.get_output_srid());
1023  if (srid > 0) {
1024  if (arg_ti.get_input_srid() > 0) {
1025  // Constructed geometry to be transformed to srid given by encompassing transform
1026  arg_ti.set_output_srid(srid);
1027  } else {
1028  throw QueryNotSupported("Transform of geo constructor " + rex_function->getName() +
1029  " requires its argument(s) to have a valid srid");
1030  }
1031  } else {
1032  arg_ti.set_output_srid(arg_ti.get_input_srid()); // No encompassing transform
1033  }
1034  // If there was an output transform, it's now embedded into arg_ti and the geo operator.
1035  // Now de-register the transform from the return typeinfo:
1036  ti = arg_ti;
1038  return makeExpr<Analyzer::GeoBinOper>(op, arg_ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1039 }
void set_compression(EncodingType c)
Definition: sqltypes.h:479
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:469
void set_input_srid(int d)
Definition: sqltypes.h:472
void set_output_srid(int s)
Definition: sqltypes.h:474
void set_comp_param(int p)
Definition: sqltypes.h:480
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:468

+ 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 1345 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().

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

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

Referenced by translateFunction(), and translateGeoFunctionArg().

1062  {
1063  if (rex_function->getName() != "ST_Equals"sv) {
1064  throw QueryNotSupported(rex_function->getName() + " geo predicate is not supported");
1065  }
1066 #ifndef ENABLE_GEOS
1067  throw QueryNotSupported(rex_function->getName() +
1068  " geo predicate requires enabled GEOS support");
1069 #endif
1070  SQLTypeInfo arg0_ti;
1071  auto geoargs0 =
1072  translateGeoFunctionArg(rex_function->getOperand(0), arg0_ti, false, true, true);
1073  SQLTypeInfo arg1_ti;
1074  auto geoargs1 =
1075  translateGeoFunctionArg(rex_function->getOperand(1), arg1_ti, false, true, true);
1076  ti = SQLTypeInfo(kBOOLEAN, false);
1078  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1079 }
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 1068 of file RelAlgTranslator.cpp.

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

Referenced by translateOper().

1069  {
1070  const auto sql_op = rex_operator->getOperator();
1071  CHECK(sql_op == kBBOX_INTERSECT);
1072 
1073  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
1074  const auto lhs_ti = lhs->get_type_info();
1075  if (lhs_ti.is_geometry()) {
1076  return translateGeoBoundingBoxIntersectOper(rex_operator);
1077  } else {
1078  throw std::runtime_error(
1079  "Bounding Box Intersection equivalence is currently only supported for "
1080  "geospatial types");
1081  }
1082 }
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 1538 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1539  {
1540  const auto ret_ti = rex_function->getType();
1541  const auto arg = translateScalarRex(rex_function->getOperand(0));
1542  const auto arg_ti = arg->get_type_info();
1543  if (!arg_ti.is_array()) {
1544  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1545  }
1546  if (arg_ti.get_subtype() == kARRAY) {
1547  throw std::runtime_error(rex_function->getName() +
1548  " expects one-dimension array expression.");
1549  }
1550  const auto array_size = arg_ti.get_size();
1551  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1552 
1553  if (array_size > 0) {
1554  if (array_elem_size <= 0) {
1555  throw std::runtime_error(rex_function->getName() +
1556  ": unexpected array element type.");
1557  }
1558  // Return cardinality of a fixed length array
1559  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1560  }
1561  // Variable length array cardinality will be calculated at runtime
1562  return makeExpr<Analyzer::CardinalityExpr>(arg);
1563 }
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 1084 of file RelAlgTranslator.cpp.

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

1085  {
1086  std::shared_ptr<Analyzer::Expr> else_expr;
1087  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1088  expr_list;
1089  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1090  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
1091  const auto then_expr = translateScalarRex(rex_case->getThen(i));
1092  expr_list.emplace_back(when_expr, then_expr);
1093  }
1094  if (rex_case->getElse()) {
1095  else_expr = translateScalarRex(rex_case->getElse());
1096  }
1097  return Parser::CaseExpr::normalize(expr_list, else_expr, executor_);
1098 }
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 1574 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1574  {
1575  constexpr bool is_null = false;
1576  Datum datum;
1577  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1578  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1579 }
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: Datum.h:74
Definition: sqltypes.h:80
Definition: Datum.h:69

+ 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 1581 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1581  {
1582  constexpr bool is_null = false;
1583  Datum datum;
1584  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1585  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1586 }
Definition: sqltypes.h:76
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: Datum.h:74
Definition: Datum.h:69

+ 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 1588 of file RelAlgTranslator.cpp.

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

Referenced by translateDatetime(), and translateFunction().

1588  {
1590 }
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:226

+ 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 1464 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1465  {
1466  std::string user{"SESSIONLESS_USER"};
1467  if (query_state_) {
1468  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1469  }
1470  return Parser::UserLiteral::get(user);
1471 }
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:240
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 1287 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().

1288  {
1289  CHECK_EQ(size_t(3), rex_function->size());
1290  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1291  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1293  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1294  const auto number_units_const =
1295  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1296  if (number_units_const && number_units_const->get_is_null()) {
1297  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1298  }
1299  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1300  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1301  const auto& datetime_ti = datetime->get_type_info();
1302  if (datetime_ti.get_type() == kTIME) {
1303  throw std::runtime_error("DateAdd operation not supported for TIME.");
1304  }
1305  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1306  const int dim = datetime_ti.get_dimension();
1307  return makeExpr<Analyzer::DateaddExpr>(
1308  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1309 }
#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 1402 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().

1403  {
1404  CHECK_EQ(size_t(3), rex_function->size());
1405  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1406  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1408  const auto start = translateScalarRex(rex_function->getOperand(1));
1409  const auto end = translateScalarRex(rex_function->getOperand(2));
1410  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1411  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1412 }
#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 1414 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().

1415  {
1416  CHECK_EQ(size_t(2), rex_function->size());
1417  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1418  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1420  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1421  return ExtractExpr::generate(
1422  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1423 }
#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 1320 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().

1321  {
1322  if (rex_operator->size() != 2) {
1323  return nullptr;
1324  }
1325  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1326  const auto datetime_ti = datetime->get_type_info();
1327  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1328  if (datetime_ti.get_type() == kTIME) {
1329  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1330  }
1331  return nullptr;
1332  }
1333  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1334  const auto rhs_ti = rhs->get_type_info();
1335  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1336  if (datetime_ti.is_high_precision_timestamp() ||
1337  rhs_ti.is_high_precision_timestamp()) {
1338  throw std::runtime_error(
1339  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1340  "Use "
1341  "DATEDIFF.");
1342  }
1343  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1344  const auto& rex_operator_ti = rex_operator->getType();
1345  const auto datediff_field =
1346  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1347  auto result =
1348  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1349  // multiply 1000 to result since expected result should be in millisecond precision.
1350  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1351  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1352  kMULTIPLY,
1353  kONE,
1354  result,
1355  makeNumericConstant(bigint_ti, 1000));
1356  } else {
1357  return result;
1358  }
1359  }
1360  const auto op = rex_operator->getOperator();
1361  if (op == kPLUS) {
1362  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1363  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1364  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1365  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1366  if (date_trunc) {
1367  return date_trunc;
1368  }
1369  }
1370  const auto interval = fold_expr(rhs.get());
1371  auto interval_ti = interval->get_type_info();
1372  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1373  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1374  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1375  std::shared_ptr<Analyzer::Expr> interval_sec;
1376  if (interval_lit) {
1377  interval_sec =
1378  makeNumericConstant(bigint_ti,
1379  (op == kMINUS ? -interval_lit->get_constval().bigintval
1380  : interval_lit->get_constval().bigintval) /
1381  1000);
1382  } else {
1383  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1384  kDIVIDE,
1385  kONE,
1386  interval,
1387  makeNumericConstant(bigint_ti, 1000));
1388  if (op == kMINUS) {
1389  interval_sec =
1390  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1391  }
1392  }
1393  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1394  }
1395  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1396  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1397  bigint_ti, false, kUMINUS, interval)
1398  : interval;
1399  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1400 }
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:40
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:39
Definition: sqldefs.h:71
#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 1592 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1593  {
1594  CHECK_EQ(size_t(1), rex_function->size());
1595  const auto arg = translateScalarRex(rex_function->getOperand(0));
1596  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1597  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1598  if (!arg_lit || arg_lit->get_is_null()) {
1599  throw std::runtime_error(datetime_err);
1600  }
1601  CHECK(arg_lit->get_type_info().is_string());
1602  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1603  throw std::runtime_error(datetime_err);
1604  }
1605  return translateCurrentTimestamp();
1606 }
#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 1228 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().

1229  {
1230  CHECK_EQ(size_t(2), rex_function->size());
1231  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1232  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1234  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1235  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1236  if (is_date_trunc) {
1237  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1238  } else {
1239  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1240  }
1241 }
#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::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateFunction ( const RexFunctionOperator rex_function) const
private

Definition at line 1722 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.

1723  {
1724  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1725  return translateLike(rex_function);
1726  }
1727  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1728  return translateRegexp(rex_function);
1729  }
1730  if (rex_function->getName() == "LIKELY"sv) {
1731  return translateLikely(rex_function);
1732  }
1733  if (rex_function->getName() == "UNLIKELY"sv) {
1734  return translateUnlikely(rex_function);
1735  }
1736  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1737  return translateExtract(rex_function);
1738  }
1739  if (rex_function->getName() == "DATEADD"sv) {
1740  return translateDateadd(rex_function);
1741  }
1742  if (rex_function->getName() == "DATEDIFF"sv) {
1743  return translateDatediff(rex_function);
1744  }
1745  if (rex_function->getName() == "DATEPART"sv) {
1746  return translateDatepart(rex_function);
1747  }
1748  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1749  return translateLength(rex_function);
1750  }
1751  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1752  return translateKeyForString(rex_function);
1753  }
1754  if (rex_function->getName() == "WIDTH_BUCKET"sv) {
1755  return translateWidthBucket(rex_function);
1756  }
1757  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1758  return translateSampleRatio(rex_function);
1759  }
1760  if (rex_function->getName() == "CURRENT_USER"sv) {
1761  return translateCurrentUser(rex_function);
1762  }
1763  if (rex_function->getName() == "ML_PREDICT"sv) {
1764  return translateMLPredict(rex_function);
1765  }
1766  if (rex_function->getName() == "PCA_PROJECT"sv) {
1767  return translatePCAProject(rex_function);
1768  }
1769  if (func_resolve(rex_function->getName(),
1770  "LOWER"sv,
1771  "UPPER"sv,
1772  "INITCAP"sv,
1773  "REVERSE"sv,
1774  "REPEAT"sv,
1775  "||"sv,
1776  "LPAD"sv,
1777  "RPAD"sv,
1778  "TRIM"sv,
1779  "LTRIM"sv,
1780  "RTRIM"sv,
1781  "SUBSTRING"sv,
1782  "OVERLAY"sv,
1783  "REPLACE"sv,
1784  "SPLIT_PART"sv,
1785  "REGEXP_REPLACE"sv,
1786  "REGEXP_SUBSTR"sv,
1787  "REGEXP_MATCH"sv,
1788  "JSON_VALUE"sv,
1789  "BASE64_ENCODE"sv,
1790  "BASE64_DECODE"sv,
1791  "TRY_CAST"sv,
1792  "POSITION"sv,
1793  "JAROWINKLER_SIMILARITY"sv,
1794  "LEVENSHTEIN_DISTANCE"sv)) {
1795  return translateStringOper(rex_function);
1796  }
1797  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1798  return translateCardinality(rex_function);
1799  }
1800  if (rex_function->getName() == "ITEM"sv) {
1801  return translateItem(rex_function);
1802  }
1803  if (rex_function->getName() == "CURRENT_DATE"sv) {
1804  return translateCurrentDate();
1805  }
1806  if (rex_function->getName() == "CURRENT_TIME"sv) {
1807  return translateCurrentTime();
1808  }
1809  if (rex_function->getName() == "CURRENT_TIMESTAMP"sv) {
1810  return translateCurrentTimestamp();
1811  }
1812  if (rex_function->getName() == "NOW"sv) {
1813  return translateCurrentTimestamp();
1814  }
1815  if (rex_function->getName() == "DATETIME"sv) {
1816  return translateDatetime(rex_function);
1817  }
1818  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1819  return translateHPTLiteral(rex_function);
1820  }
1821  if (rex_function->getName() == "ABS"sv) {
1822  return translateAbs(rex_function);
1823  }
1824  if (rex_function->getName() == "SIGN"sv) {
1825  return translateSign(rex_function);
1826  }
1827  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1828  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1829  rex_function->getType(),
1830  rex_function->getName(),
1831  translateFunctionArgs(rex_function));
1832  } else if (rex_function->getName() == "ROUND"sv) {
1833  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1834  translateFunctionArgs(rex_function);
1835 
1836  if (rex_function->size() == 1) {
1837  // push a 0 constant if 2nd operand is missing.
1838  // this needs to be done as calcite returns
1839  // only the 1st operand without defaulting the 2nd one
1840  // when the user did not specify the 2nd operand.
1841  SQLTypes t = kSMALLINT;
1842  Datum d;
1843  d.smallintval = 0;
1844  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1845  }
1846 
1847  // make sure we have only 2 operands
1848  CHECK(args.size() == 2);
1849 
1850  if (!args[0]->get_type_info().is_number()) {
1851  throw std::runtime_error("Only numeric 1st operands are supported");
1852  }
1853 
1854  // the 2nd operand does not need to be a constant
1855  // it can happily reference another integer column
1856  if (!args[1]->get_type_info().is_integer()) {
1857  throw std::runtime_error("Only integer 2nd operands are supported");
1858  }
1859 
1860  // Calcite may upcast decimals in a way that is
1861  // incompatible with the extension function input. Play it safe and stick with the
1862  // argument type instead.
1863  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1864  ? args[0]->get_type_info()
1865  : rex_function->getType();
1866 
1867  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1868  ret_ti, rex_function->getName(), args);
1869  }
1870  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1871  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1872  rex_function->getName(),
1873  translateFunctionArgs(rex_function));
1874  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1875  if (date_trunc) {
1876  return date_trunc;
1877  }
1878  return translateDateadd(rex_function);
1879  }
1880  if (rex_function->getName() == "/INT"sv) {
1881  CHECK_EQ(size_t(2), rex_function->size());
1882  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1883  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1884  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1885  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1886  }
1887  if (rex_function->getName() == "Reinterpret"sv) {
1888  CHECK_EQ(size_t(1), rex_function->size());
1889  return translateScalarRex(rex_function->getOperand(0));
1890  }
1891  if (func_resolve(rex_function->getName(),
1892  "ST_X"sv,
1893  "ST_Y"sv,
1894  "ST_XMin"sv,
1895  "ST_YMin"sv,
1896  "ST_XMax"sv,
1897  "ST_YMax"sv,
1898  "ST_NRings"sv,
1899  "ST_NumGeometries"sv,
1900  "ST_NPoints"sv,
1901  "ST_Length"sv,
1902  "ST_Perimeter"sv,
1903  "ST_Area"sv,
1904  "ST_SRID"sv,
1905  "HeavyDB_Geo_PolyBoundsPtr"sv)) {
1906  CHECK_EQ(rex_function->size(), size_t(1));
1907  return translateUnaryGeoFunction(rex_function);
1908  }
1909  if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
1910  CHECK_EQ(rex_function->size(), size_t(1));
1911  SQLTypeInfo ti;
1912  return translateUnaryGeoConstructor(rex_function, ti, false);
1913  }
1914  if (func_resolve(rex_function->getName(),
1915  "convert_meters_to_pixel_width"sv,
1916  "convert_meters_to_pixel_height"sv,
1917  "is_point_in_view"sv,
1918  "is_point_size_in_view"sv)) {
1919  return translateFunctionWithGeoArg(rex_function);
1920  }
1921  if (func_resolve(rex_function->getName(),
1922  "ST_Distance"sv,
1923  "ST_MaxDistance"sv,
1924  "ST_Intersects"sv,
1925  "ST_Disjoint"sv,
1926  "ST_Contains"sv,
1927  "ST_IntersectsBox"sv,
1928  "ST_Approx_Overlaps"sv,
1929  "ST_Within"sv)) {
1930  CHECK_EQ(rex_function->size(), size_t(2));
1931  return translateBinaryGeoFunction(rex_function);
1932  }
1933  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
1934  CHECK_EQ(rex_function->size(), size_t(3));
1935  return translateTernaryGeoFunction(rex_function);
1936  }
1937  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
1938  CHECK_EQ(size_t(0), rex_function->size());
1939  return translateOffsetInFragment();
1940  }
1941  if (rex_function->getName() == "ARRAY"sv) {
1942  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1943  return translateArrayFunction(rex_function);
1944  }
1945  if (func_resolve(rex_function->getName(),
1946  "ST_GeomFromText"sv,
1947  "ST_GeogFromText"sv,
1948  "ST_Centroid"sv,
1949  "ST_SetSRID"sv,
1950  "ST_Point"sv, // TODO: where should this and below live?
1951  "ST_PointN"sv,
1952  "ST_StartPoint"sv,
1953  "ST_EndPoint"sv,
1954  "ST_Transform"sv)) {
1955  SQLTypeInfo ti;
1956  return translateGeoProjection(rex_function, ti, false);
1957  }
1958  if (func_resolve(rex_function->getName(),
1959  "ST_Intersection"sv,
1960  "ST_Difference"sv,
1961  "ST_Union"sv,
1962  "ST_Buffer"sv,
1963  "ST_ConcaveHull"sv)) {
1964  CHECK_EQ(rex_function->size(), size_t(2));
1965  SQLTypeInfo ti;
1966  return translateBinaryGeoConstructor(rex_function, ti, false);
1967  }
1968  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
1969  CHECK_EQ(rex_function->size(), size_t(1));
1970  SQLTypeInfo ti;
1971  return translateUnaryGeoPredicate(rex_function, ti, false);
1972  }
1973  if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
1974  CHECK_EQ(rex_function->size(), size_t(2));
1975  // Attempt to generate a distance based check for points
1976  if (auto distance_check = translateBinaryGeoFunction(rex_function)) {
1977  return distance_check;
1978  }
1979  SQLTypeInfo ti;
1980  return translateBinaryGeoPredicate(rex_function, ti, false);
1981  }
1982 
1983  auto arg_expr_list = translateFunctionArgs(rex_function);
1984  if (rex_function->getName() == std::string("||") ||
1985  rex_function->getName() == std::string("SUBSTRING")) {
1986  SQLTypeInfo ret_ti(kTEXT, false);
1987  return makeExpr<Analyzer::FunctionOper>(
1988  ret_ti, rex_function->getName(), arg_expr_list);
1989  }
1990 
1991  // Reset possibly wrong return type of rex_function to the return
1992  // type of the optimal valid implementation. The return type can be
1993  // wrong in the case of multiple implementations of UDF functions
1994  // that have different return types but Calcite specifies the return
1995  // type according to the first implementation.
1996  SQLTypeInfo ret_ti;
1997  try {
1998  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1999  auto ext_func_args = ext_func_sig.getInputArgs();
2000  CHECK_LE(arg_expr_list.size(), ext_func_args.size());
2001  for (size_t i = 0, di = 0; i < arg_expr_list.size(); i++) {
2002  CHECK_LT(i + di, ext_func_args.size());
2003  auto ext_func_arg = ext_func_args[i + di];
2004  if (ext_func_arg == ExtArgumentType::PInt8 ||
2005  ext_func_arg == ExtArgumentType::PInt16 ||
2006  ext_func_arg == ExtArgumentType::PInt32 ||
2007  ext_func_arg == ExtArgumentType::PInt64 ||
2008  ext_func_arg == ExtArgumentType::PFloat ||
2009  ext_func_arg == ExtArgumentType::PDouble ||
2010  ext_func_arg == ExtArgumentType::PBool) {
2011  di++;
2012  // pointer argument follows length argument:
2013  CHECK(ext_func_args[i + di] == ExtArgumentType::Int64);
2014  }
2015  // fold casts on constants
2016  if (auto constant =
2017  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
2018  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_arg);
2019  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
2020  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
2021  }
2022  }
2023  }
2024 
2025  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
2026  } catch (ExtensionFunctionBindingError& e) {
2027  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
2028  throw;
2029  }
2030 
2031  // By default, the extension function type will not allow nulls. If one of the arguments
2032  // is nullable, the extension function must also explicitly allow nulls.
2033  bool arguments_not_null = true;
2034  for (const auto& arg_expr : arg_expr_list) {
2035  if (!arg_expr->get_type_info().get_notnull()) {
2036  arguments_not_null = false;
2037  break;
2038  }
2039  }
2040  ret_ti.set_notnull(arguments_not_null);
2041 
2042  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
2043 }
#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:379
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:72
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:71
#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:475
#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:69
bool is_decimal() const
Definition: sqltypes.h:568
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 2728 of file RelAlgTranslator.cpp.

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

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

2729  {
2730  std::vector<std::shared_ptr<Analyzer::Expr>> args;
2731  for (size_t i = 0; i < rex_function->size(); ++i) {
2732  args.push_back(translateScalarRex(rex_function->getOperand(i)));
2733  }
2734  return args;
2735 }
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 1785 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().

1786  {
1787  std::string specialized_geofunc{rex_function->getName()};
1788  if (func_resolve(rex_function->getName(),
1789  "convert_meters_to_pixel_width"sv,
1790  "convert_meters_to_pixel_height"sv)) {
1791  CHECK_EQ(rex_function->size(), 6u);
1792  SQLTypeInfo arg_ti;
1793  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1794  args.push_back(translateScalarRex(rex_function->getOperand(0)));
1795  auto geoargs =
1796  translateGeoFunctionArg(rex_function->getOperand(1), arg_ti, false, false);
1797  // only works on points
1798  if (arg_ti.get_type() != kPOINT) {
1799  throw QueryNotSupported(rex_function->getName() +
1800  " expects a point for the second argument");
1801  }
1802 
1803  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1804 
1805  // Add compression information
1806  Datum input_compression;
1807  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1808  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1809  if (arg_ti.get_input_srid() != 4326) {
1810  throw QueryNotSupported(
1811  rex_function->getName() +
1812  " currently only supports points of with SRID WGS84/EPSG:4326");
1813  }
1814  Datum input_srid;
1815  input_srid.intval = arg_ti.get_input_srid();
1816  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1817  Datum output_srid;
1818  // Forcing web-mercator projection for now
1819  // TODO(croot): check that the input-to-output conversion routines exist?
1820  output_srid.intval =
1821  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1822  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1823 
1824  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1825  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1826  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1827  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1828  return makeExpr<Analyzer::FunctionOper>(
1829  rex_function->getType(), specialized_geofunc, args);
1830  } else if (rex_function->getName() == "is_point_in_view"sv) {
1831  CHECK_EQ(rex_function->size(), 5u);
1832  SQLTypeInfo arg_ti;
1833  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1834  auto geoargs =
1835  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, false);
1836  // only works on points
1837  if (arg_ti.get_type() != kPOINT) {
1838  throw QueryNotSupported(rex_function->getName() +
1839  " expects a point for the second argument");
1840  }
1841 
1842  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1843 
1844  // Add compression information
1845  Datum input_compression;
1846  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1847  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1848  if (arg_ti.get_input_srid() != 4326) {
1849  throw QueryNotSupported(
1850  rex_function->getName() +
1851  " currently only supports points of with SRID WGS84/EPSG:4326");
1852  }
1853  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1854  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1855  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1856  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1857  return makeExpr<Analyzer::FunctionOper>(
1858  rex_function->getType(), specialized_geofunc, args);
1859  } else if (rex_function->getName() == "is_point_size_in_view"sv) {
1860  CHECK_EQ(rex_function->size(), 6u);
1861  SQLTypeInfo arg_ti;
1862  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1863  auto geoargs =
1864  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, false);
1865  // only works on points
1866  if (arg_ti.get_type() != kPOINT) {
1867  throw QueryNotSupported(rex_function->getName() +
1868  " expects a point for the second argument");
1869  }
1870 
1871  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1872 
1873  // Add compression information
1874  Datum input_compression;
1875  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1876  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1877  if (arg_ti.get_input_srid() != 4326) {
1878  throw QueryNotSupported(
1879  rex_function->getName() +
1880  " currently only supports points of with SRID WGS84/EPSG:4326");
1881  }
1882  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1883  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1884  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1885  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1886  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1887  return makeExpr<Analyzer::FunctionOper>(
1888  rex_function->getType(), specialized_geofunc, args);
1889  }
1890  CHECK(false);
1891  return nullptr;
1892 }
#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:73
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:69

+ 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 1894 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().

1895  {
1896  CHECK_EQ(rex_operator->size(), 2u);
1897 
1898  auto translate_input =
1899  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1900  const auto input = dynamic_cast<const RexInput*>(operand);
1901  CHECK(input);
1902 
1903  SQLTypeInfo ti;
1904  const auto exprs = translateGeoColumn(input, ti, true, false);
1905  CHECK_GT(exprs.size(), 0u);
1906  if (ti.get_type() == kPOINT) {
1907  return exprs.front();
1908  } else {
1909  return exprs.back();
1910  }
1911  };
1912 
1913  SQLQualifier sql_qual{kONE};
1914  SQLOps sql_op{kBBOX_INTERSECT};
1915  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
1916  false,
1917  sql_op,
1918  sql_qual,
1919  translate_input(rex_operator->getOperand(1)),
1920  translate_input(rex_operator->getOperand(0)));
1921 }
#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:71
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
SQLOps
Definition: sqldefs.h:28
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
#define CHECK_GT(x, y)
Definition: Logger.h:305
Definition: sqldefs.h:71
#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 1764 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateOper().

1765  {
1766  if (rex_operator->size() != size_t(2)) {
1767  return nullptr;
1768  }
1769 
1770  auto geo_distance_expr = translateScalarRex(rex_operator->getOperand(0));
1771  auto func_oper = dynamic_cast<Analyzer::GeoOperator*>(geo_distance_expr.get());
1772  if (func_oper && func_oper->getName() == "ST_Distance"sv) {
1773  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1774  auto distance_expr = translateScalarRex(rex_operator->getOperand(1));
1775  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1776  distance_expr = distance_expr->add_cast(distance_ti);
1777  }
1778  distance_expr = fold_expr(distance_expr.get());
1779  return makeExpr<Analyzer::BinOper>(
1780  kBOOLEAN, rex_operator->getOperator(), kONE, geo_distance_expr, distance_expr);
1781  }
1782  return nullptr;
1783 }
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:71
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  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
552  if (!ce || !e->get_type_info().is_integer()) {
553  throw QueryNotSupported(rex_function->getName() +
554  ": expecting integer index as second argument");
555  }
556  int32_t index = 0;
557  if (e->get_type_info().get_type() == kSMALLINT) {
558  index = static_cast<int32_t>(ce->get_constval().smallintval);
559  } else if (e->get_type_info().get_type() == kTINYINT) {
560  index = static_cast<int32_t>(ce->get_constval().tinyintval);
561  } else if (e->get_type_info().get_type() == kINT) {
562  index = static_cast<int32_t>(ce->get_constval().intval);
563  } else {
564  throw QueryNotSupported(rex_function->getName() + " expecting integer index");
565  }
566  if (index == 0) {
567  // maybe we will just return NULL here?
568  throw QueryNotSupported(rex_function->getName() + ": invalid index");
569  }
570  arg0.push_back(e);
571  auto oper_ti =
572  arg0.front()->get_type_info(); // make a copy so we can reset nullness and type
573  oper_ti.set_type(kPOINT);
574  oper_ti.set_notnull(false);
575 
576  arg_ti = oper_ti; // TODO: remove
577 
578  return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), arg0)};
579 
580  } else if (rex_function->getName() == "ST_StartPoint"sv ||
581  rex_function->getName() == "ST_EndPoint"sv) {
582  std::vector<std::shared_ptr<Analyzer::Expr>> args;
583  CHECK_EQ(size_t(1), rex_function->size());
584  const auto arg_exprs = translateGeoFunctionArg(rex_function->getOperand(0),
585  arg_ti,
586  with_bounds,
587  expand_geo_col,
589  /*use_geo_expressions=*/true);
590  CHECK_EQ(arg_exprs.size(), size_t(1));
591  CHECK(arg_exprs.front());
592  const auto arg_expr_ti = arg_exprs.front()->get_type_info();
593  if (arg_expr_ti.get_type() != kLINESTRING) {
594  throw QueryNotSupported(rex_function->getName() +
595  " expected LINESTRING argument. Received " +
596  arg_expr_ti.toString());
597  }
598  args.push_back(arg_exprs.front());
599 
600  auto oper_ti = args.back()->get_type_info(); // make a copy so we can override type
601  oper_ti.set_type(kPOINT);
602 
603  arg_ti = oper_ti; // TODO: remove
604 
605  return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), args)};
606  } else if (rex_function->getName() == "ST_SRID"sv) {
607  CHECK_EQ(size_t(1), rex_function->size());
608  const auto rex_scalar0 =
609  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
610  if (!rex_scalar0) {
611  throw QueryNotSupported(rex_function->getName() +
612  ": expects scalar as first argument");
613  }
614  auto arg0 =
615  translateGeoFunctionArg(rex_scalar0, arg_ti, with_bounds, expand_geo_col);
616  if (!IS_GEO(arg_ti.get_type())) {
617  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
618  }
619  return arg0;
620  } else if (rex_function->getName() == "ST_SetSRID"sv) {
621  CHECK_EQ(size_t(2), rex_function->size());
622  const auto rex_literal =
623  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
624  if (!rex_literal) {
625  throw QueryNotSupported(rex_function->getName() +
626  ": second argument is expected to be a literal");
627  }
628  const auto e = translateLiteral(rex_literal);
629  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
630  if (!ce || !e->get_type_info().is_integer()) {
631  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
632  }
633  int32_t srid = 0;
634  if (e->get_type_info().get_type() == kSMALLINT) {
635  srid = static_cast<int32_t>(ce->get_constval().smallintval);
636  } else if (e->get_type_info().get_type() == kTINYINT) {
637  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
638  } else if (e->get_type_info().get_type() == kINT) {
639  srid = static_cast<int32_t>(ce->get_constval().intval);
640  } else {
641  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
642  }
643 
644  const auto rex_scalar0 =
645  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
646  if (!rex_scalar0) {
647  throw QueryNotSupported(rex_function->getName() +
648  ": expects scalar as first argument");
649  }
650 
651  // Only convey the request to compress if dealing with 4326 geo
652  auto arg0 = translateGeoFunctionArg(rex_scalar0,
653  arg_ti,
654  with_bounds,
655  expand_geo_col,
656  is_projection,
657  use_geo_expressions,
658  (try_to_compress && (srid == 4326)));
659 
660  CHECK(!arg0.empty() && arg0.front());
661  if (!IS_GEO(arg_ti.get_type()) && !use_geo_expressions) {
662  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
663  }
664  arg_ti.set_input_srid(srid); // Input SRID
665  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
666  if (auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
667  CHECK_EQ(arg0.size(), size_t(1));
668  auto ti = geo_expr->get_type_info();
669  ti.set_input_srid(srid);
670  ti.set_output_srid(srid);
671  return {geo_expr->add_cast(ti)};
672  }
673  return arg0;
674  } else if (rex_function->getName() == "CastToGeography"sv) {
675  CHECK_EQ(size_t(1), rex_function->size());
676  const auto rex_scalar0 =
677  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
678  if (!rex_scalar0) {
679  throw QueryNotSupported(rex_function->getName() +
680  ": expects scalar as first argument");
681  }
682  auto arg0 = translateGeoFunctionArg(rex_scalar0,
683  arg_ti,
684  with_bounds,
685  expand_geo_col,
686  /*is_projection=*/false,
687  use_geo_expressions);
688  CHECK(!arg0.empty());
689  if (auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
690  auto arg_ti = geo_expr->get_type_info(); // make a copy
691  arg_ti.set_subtype(kGEOGRAPHY);
692  return {geo_expr->add_cast(arg_ti)};
693  }
694  if (use_geo_expressions) {
695  arg_ti = arg0.front()->get_type_info();
696  arg_ti.set_subtype(kGEOGRAPHY);
697  arg0.front()->set_type_info(arg_ti);
698  }
699  if (!IS_GEO(arg_ti.get_type())) {
700  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
701  }
702  if (arg_ti.get_output_srid() != 4326) {
703  throw QueryNotSupported(rex_function->getName() +
704  " expects geometry with SRID=4326");
705  }
706  arg_ti.set_subtype(kGEOGRAPHY);
707  return arg0;
708  } else if (rex_function->getName() == "ST_Point"sv) {
709  CHECK_EQ(size_t(2), rex_function->size());
710  arg_ti.set_type(kPOINT);
711  arg_ti.set_subtype(kGEOMETRY);
712  arg_ti.set_input_srid(0);
713  arg_ti.set_output_srid(0);
715 
716  auto coord1 = translateScalarRex(rex_function->getOperand(0));
717  auto coord2 = translateScalarRex(rex_function->getOperand(1));
718  auto d_ti = SQLTypeInfo(kDOUBLE, false);
719  auto cast_coord1 = coord1->add_cast(d_ti);
720  auto cast_coord2 = coord2->add_cast(d_ti);
721  // First try to fold to geo literal
722  auto folded_coord1 = fold_expr(cast_coord1.get());
723  auto folded_coord2 = fold_expr(cast_coord2.get());
724  auto const_coord1 = std::dynamic_pointer_cast<Analyzer::Constant>(folded_coord1);
725  auto const_coord2 = std::dynamic_pointer_cast<Analyzer::Constant>(folded_coord2);
726  if (const_coord1 && const_coord2 && !use_geo_expressions) {
727  CHECK(const_coord1->get_type_info().get_type() == kDOUBLE);
728  CHECK(const_coord2->get_type_info().get_type() == kDOUBLE);
729  std::string wkt = "POINT(" +
730  std::to_string(const_coord1->get_constval().doubleval) + " " +
731  std::to_string(const_coord2->get_constval().doubleval) + ")";
732  RexLiteral rex_literal{wkt, kTEXT, kNULLT, 0, 0, 0, 0};
733  auto args = translateGeoLiteral(&rex_literal, arg_ti, false);
734  CHECK(arg_ti.get_type() == kPOINT);
735  return args;
736  }
737  const auto is_local_alloca = !is_projection;
738  if (!is_local_alloca || use_geo_expressions) {
739  if (try_to_compress) {
740  arg_ti.set_input_srid(4326);
741  arg_ti.set_output_srid(4326);
742  }
743  return {makeExpr<Analyzer::GeoOperator>(
744  arg_ti,
745  rex_function->getName(),
746  std::vector<std::shared_ptr<Analyzer::Expr>>{folded_coord1, folded_coord2})};
747  }
748  // Couldn't fold to geo literal, construct [and compress] on the fly
749  auto da_ti = SQLTypeInfo(kARRAY, true);
750  da_ti.set_subtype(kDOUBLE);
751  da_ti.set_size(16);
752  if (try_to_compress) {
753  // Switch to compressed coord array
754  da_ti.set_subtype(kINT);
755  da_ti.set_size(8);
756  da_ti.set_input_srid(4326);
757  da_ti.set_output_srid(4326);
758  da_ti.set_compression(kENCODING_GEOINT);
759  da_ti.set_comp_param(32);
760  // Register point compression
761  arg_ti.set_input_srid(4326);
762  arg_ti.set_output_srid(4326);
763  arg_ti.set_compression(kENCODING_GEOINT);
764  arg_ti.set_comp_param(32);
765  }
766  auto cast_coords = {folded_coord1, folded_coord2};
767  auto ae = makeExpr<Analyzer::ArrayExpr>(da_ti, cast_coords, false, is_local_alloca);
768  SQLTypeInfo tia_ti = da_ti;
769  tia_ti.set_subtype(kTINYINT);
770  return {makeExpr<Analyzer::UOper>(tia_ti, false, kCAST, ae)};
771  } else if (rex_function->getName() == "ST_Centroid"sv) {
772  CHECK_EQ(size_t(1), rex_function->size());
773  arg_ti.set_type(kPOINT);
774  arg_ti.set_subtype(kGEOMETRY);
775  arg_ti.set_input_srid(0);
776  arg_ti.set_output_srid(0);
777  arg_ti.set_compression(kENCODING_NONE);
778 
779  SQLTypeInfo geo_ti;
780  int legacy_transform_srid = 0; // discard
781  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
782  geo_ti,
783  /*with_bounds=*/false,
784  /*expand_geo_col=*/true,
785  /*is_projection=*/false,
786  /*use_geo_expressions=*/true);
787  CHECK_EQ(geoargs.size(), size_t(1));
788  if (geo_ti.get_output_srid() > 0) {
789  // Pick up the arg's srid
790  arg_ti.set_input_srid(geo_ti.get_output_srid());
791  arg_ti.set_output_srid(geo_ti.get_output_srid());
792  }
793  if (try_to_compress) {
794  // Point compression is requested by a higher level [4326] operation
795  if (geo_ti.get_output_srid() == 0) {
796  // srid-less geo is considered and is forced to be 4326
797  arg_ti.set_input_srid(4326);
798  arg_ti.set_output_srid(4326);
799  } else {
800  CHECK_EQ(arg_ti.get_output_srid(), 4326);
801  }
802  arg_ti.set_compression(kENCODING_GEOINT);
803  arg_ti.set_comp_param(32);
804  }
805  if (geo_ti.get_input_srid() != geo_ti.get_output_srid() &&
806  geo_ti.get_output_srid() > 0 &&
807  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
808  // Centroid argument is transformed before use,
809  // pass the transform to the geo operator
810  legacy_transform_srid = geo_ti.get_output_srid();
811  }
812  return {makeExpr<Analyzer::GeoOperator>(
813  arg_ti,
814  rex_function->getName(),
815  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()},
816  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
817  : std::nullopt)};
818  } else if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
819  CHECK_EQ(size_t(1), rex_function->size());
820  // What geo type will the constructor return? Could be anything.
821  return {translateUnaryGeoConstructor(rex_function, arg_ti, with_bounds)};
822  } else if (func_resolve(rex_function->getName(),
823  "ST_Intersection"sv,
824  "ST_Difference"sv,
825  "ST_Union"sv,
826  "ST_Buffer"sv,
827  "ST_ConcaveHull"sv)) {
828  CHECK_EQ(size_t(2), rex_function->size());
829  // What geo type will the constructor return? Could be anything.
830  return {translateBinaryGeoConstructor(rex_function, arg_ti, with_bounds)};
831  } else if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
832  CHECK_EQ(size_t(1), rex_function->size());
833  return {translateUnaryGeoPredicate(rex_function, arg_ti, with_bounds)};
834  } else if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
835  CHECK_EQ(size_t(2), rex_function->size());
836  return {translateBinaryGeoPredicate(rex_function, arg_ti, with_bounds)};
837  } else {
838  throw QueryNotSupported("Unsupported argument: " + rex_function->getName());
839  }
840  }
841  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
842  if (rex_literal) {
843  if (use_geo_expressions) {
844  const auto translated_literal = translateLiteral(rex_literal);
845  auto const translated_literal_type = translated_literal->get_type_info().get_type();
846  if (!IS_STRING(translated_literal_type) && !IS_GEO(translated_literal_type)) {
847  // This stops crashes in the createGeoType call below due to datum.stringval
848  // being uninitialized when the datum isn't even a string, let alone a geo string
849  // There needs to be specific handling for ST_NumGeometries in the code above
850  // but I don't know what category it would fall over (it's not GEOS, and it
851  // returns an INT, not a BOOL or other geo)
852  // simon.eves 8/15/22
853  throw QueryNotSupported("Geospatial function requires geo literal.");
854  }
855  const auto constant_expr =
856  dynamic_cast<const Analyzer::Constant*>(translated_literal.get());
857  CHECK(constant_expr);
858  if (constant_expr->get_is_null()) {
859  // TODO: we could lift this limitation by assuming a minimum type per function
860  throw QueryNotSupported("Geospatial functions require typed nulls.");
861  }
862  const auto& datum = constant_expr->get_constval();
863  CHECK(datum.stringval);
864  const bool validate_with_geos_if_available = false;
865  auto geospatial_base = Geospatial::GeoTypesFactory::createGeoType(
866  *datum.stringval, validate_with_geos_if_available);
867  CHECK(geospatial_base);
868  SQLTypeInfo ti;
869  ti.set_type(get_ti_from_geo(geospatial_base.get()));
870  if (arg_ti.get_subtype() == kGEOGRAPHY) {
872  } else {
874  }
875  ti.set_input_srid(arg_ti.get_input_srid());
876  ti.set_output_srid(arg_ti.get_output_srid() == 0 ? arg_ti.get_input_srid()
877  : arg_ti.get_output_srid());
878  // TODO: remove dependence on arg_ti
879  if (ti.get_output_srid() == 4326 || arg_ti.get_compression() == kENCODING_GEOINT) {
881  ti.set_comp_param(32);
882  }
883  ti.set_notnull(true);
884  // Before removing dependence on arg_ti need to note that ST_Transform uses it
885  // as a vehicle to pass transform output SRID to its args.
886  // arg_ti is also expected to be filled with relevant data, which wasn't done here.
887  // Not filling arg_ti with the geo constant data (which went to ti instead)
888  // resulted in GeoConstant::add_cast adopting a corrupt type info,
889  // which later killed codegen. Need to complete arg_ti composition:
890  arg_ti = ti;
891  return {makeExpr<Analyzer::GeoConstant>(std::move(geospatial_base), ti)};
892  }
893  return translateGeoLiteral(rex_literal, arg_ti, with_bounds);
894  }
895  throw QueryNotSupported("Geo function argument not supported");
896 }
void set_compression(EncodingType c)
Definition: sqltypes.h:479
#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:469
#define CHECK_GE(x, y)
Definition: Logger.h:306
Definition: sqldefs.h:48
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:472
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
void set_output_srid(int s)
Definition: sqltypes.h:474
void set_comp_param(int p)
Definition: sqltypes.h:480
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:475
#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:3984
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:468

+ 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:71
void set_compression(EncodingType c)
Definition: sqltypes.h:479
void set_size(int s)
Definition: sqltypes.h:476
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:469
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
int32_t intval
Definition: Datum.h:73
void set_input_srid(int d)
Definition: sqltypes.h:472
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:455
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:474
void set_comp_param(int p)
Definition: sqltypes.h:480
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:69
double doubleval
Definition: Datum.h:76
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 898 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateFunction().

901  {
902  // note that this is a bit of a misnomer, as ST_SetSRID embedded in a transform will
903  // eventually use geo expressions -- just not here
904  const bool use_geo_projections = !(rex_function->getName() == "ST_GeomFromText" ||
905  rex_function->getName() == "ST_GeogFromText" ||
906  rex_function->getName() == "ST_SetSRID");
907  auto geoargs = translateGeoFunctionArg(rex_function,
908  ti,
909  /*with_bounds=*/false,
910  /*expand_geo_col=*/true,
911  /*is_projection=*/true,
912  /*use_geo_expressions=*/use_geo_projections);
913  CHECK(!geoargs.empty());
914  if (std::dynamic_pointer_cast<const Analyzer::GeoExpr>(geoargs.front()) &&
915  !geoargs.front()->get_type_info().is_array()) {
916  if (rex_function->getName() == "ST_Transform" &&
917  std::dynamic_pointer_cast<const Analyzer::GeoConstant>(geoargs.front())) {
918  return makeExpr<Analyzer::GeoUOper>(
919  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
920  }
921  // GeoExpression
922  return geoargs.front();
923  }
924  bool allow_gdal_transform = false;
925  if (rex_function->getName() == "ST_Transform") {
926  const auto rex_scalar0 = dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
927  const auto rex_function0 = dynamic_cast<const RexFunctionOperator*>(rex_scalar0);
928  if (rex_function0 && func_resolve(rex_function0->getName(),
929  "ST_Intersection"sv,
930  "ST_Difference"sv,
931  "ST_Union"sv,
932  "ST_Buffer"sv,
933  "ST_ConcaveHull"sv,
934  "ST_ConvexHull"sv)) {
935  // Allow projection of gdal-transformed geos outputs
936  allow_gdal_transform = true;
937  }
938  }
939  if (use_geo_projections && !allow_gdal_transform) {
940  throw std::runtime_error("Geospatial projection for function " +
941  rex_function->toString(RelRexToStringConfig::defaults()) +
942  " not yet supported in this context");
943  }
944  return makeExpr<Analyzer::GeoUOper>(
945  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
946 }
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 2780 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

2781  {
2782  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
2783  Therefore any string having fractional seconds more 3 places after the decimal
2784  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
2785  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
2786  calcite and translating them to generate our own casts.
2787  */
2788  CHECK_EQ(size_t(1), rex_function->size());
2789  const auto operand = translateScalarRex(rex_function->getOperand(0));
2790  const auto& operand_ti = operand->get_type_info();
2791  const auto& target_ti = rex_function->getType();
2792  if (!operand_ti.is_string()) {
2793  throw std::runtime_error(
2794  "High precision timestamp cast argument must be a string. Input type is: " +
2795  operand_ti.get_type_name());
2796  } else if (!target_ti.is_high_precision_timestamp()) {
2797  throw std::runtime_error(
2798  "Cast target type should be high precision timestamp. Input type is: " +
2799  target_ti.get_type_name());
2800  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
2801  throw std::runtime_error(
2802  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
2803  std::to_string(target_ti.get_dimension()) + ")");
2804  } else {
2805  return operand->add_cast(target_ti);
2806  }
2807 }
#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 703 of file RelAlgTranslator.cpp.

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

Referenced by translateOper().

704  {
705  if (just_explain_) {
706  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
707  }
708  CHECK(rex_operator->size() == 2);
709  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
710  const auto rhs = rex_operator->getOperand(1);
711  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
712  CHECK(rex_subquery);
713  auto ti = lhs->get_type_info();
714  auto result = rex_subquery->getExecutionResult();
715  CHECK(result);
716  auto& row_set = result->getRows();
717  CHECK_EQ(size_t(1), row_set->colCount());
718  const auto& rhs_ti = row_set->getColType(0);
719  if (rhs_ti.get_type() != ti.get_type()) {
720  throw std::runtime_error(
721  "The two sides of the IN operator must have the same type; found " +
722  ti.get_type_name() + " and " + rhs_ti.get_type_name());
723  }
724  row_set->moveToBegin();
725  if (row_set->entryCount() > 10000) {
726  std::shared_ptr<Analyzer::Expr> expr;
727  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
728  !row_set->getQueryMemDesc().didOutputColumnar()) {
729  expr = getInIntegerSetExpr(lhs, *row_set);
730  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
731  // Just let it fall through the usual InValues path at the end of this method,
732  // its codegen knows to use inline comparisons for few values.
733  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
734  ->get_value_list()
735  .size() <= 100) {
736  expr = nullptr;
737  }
738  } else {
739  expr = get_in_values_expr(lhs, *row_set);
740  }
741  if (expr) {
742  return expr;
743  }
744  }
745  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
746  while (true) {
747  auto row = row_set->getNextRow(true, false);
748  if (row.empty()) {
749  break;
750  }
751  if (g_enable_watchdog && value_exprs.size() >= 10000) {
752  throw std::runtime_error(
753  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
754  }
755  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
756  Datum d{0};
757  bool is_null_const{false};
758  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
759  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
760  auto ti_none_encoded = ti;
761  ti_none_encoded.set_compression(kENCODING_NONE);
762  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
763  auto dict_encoded_string =
764  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
765  value_exprs.push_back(dict_encoded_string);
766  } else {
767  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
768  }
769  }
770  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
771 }
#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:48
std::shared_ptr< Analyzer::Expr > getInIntegerSetExpr(std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set) const
bool g_enable_watchdog
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:69

+ 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 500 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().

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

Definition at line 2483 of file RelAlgTranslator.cpp.

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

Referenced by translateWindowFunction().

2486  {
2487  // translate time interval expression and prepare appropriate frame bound expression:
2488  // a) manually compute time unit datum: time type
2489  // b) use dateadd expression: date and timestamp
2490  const auto order_key_ti = order_key->get_type_info();
2491  const auto frame_bound_ti = frame_bound_expr->get_type_info();
2492  const auto time_val_expr =
2493  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_left_operand());
2494  const auto time_unit_val_expr =
2495  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_right_operand());
2496  ExtractField time_unit =
2497  determineTimeUnit(frame_bound_ti.get_type(), time_unit_val_expr);
2498  bool invalid_time_unit_type = false;
2499  bool invalid_frame_bound_expr_type = false;
2500  Datum d;
2501  auto prepare_time_value_datum = [&d,
2502  &invalid_frame_bound_expr_type,
2503  &time_val_expr,
2504  &for_preceding_bound](bool is_timestamp_second) {
2505  // currently, Calcite only accepts interval with second, so to represent
2506  // smaller time units like millisecond, we have to use decimal point like
2507  // INTERVAL 0.003 SECOND (for millisecond)
2508  // thus, depending on what time unit we want to represent, Calcite analyzes
2509  // the time value to one of following two types: integer and decimal (and
2510  // numeric) types
2511  switch (time_val_expr->get_type_info().get_type()) {
2512  case kTINYINT: {
2513  d.bigintval = time_val_expr->get_constval().tinyintval;
2514  break;
2515  }
2516  case kSMALLINT: {
2517  d.bigintval = time_val_expr->get_constval().smallintval;
2518  break;
2519  }
2520  case kINT: {
2521  d.bigintval = time_val_expr->get_constval().intval;
2522  break;
2523  }
2524  case kBIGINT: {
2525  d.bigintval = time_val_expr->get_constval().bigintval;
2526  break;
2527  }
2528  case kDECIMAL:
2529  case kNUMERIC: {
2530  if (!is_timestamp_second) {
2531  // date and time type only use integer type as their time value
2532  invalid_frame_bound_expr_type = true;
2533  break;
2534  }
2535  d.bigintval = time_val_expr->get_constval().bigintval;
2536  break;
2537  }
2538  case kDOUBLE: {
2539  if (!is_timestamp_second) {
2540  // date and time type only use integer type as their time value
2541  invalid_frame_bound_expr_type = true;
2542  break;
2543  }
2544  d.bigintval = time_val_expr->get_constval().doubleval *
2545  pow(10, time_val_expr->get_type_info().get_scale());
2546  break;
2547  }
2548  default: {
2549  invalid_frame_bound_expr_type = true;
2550  break;
2551  }
2552  }
2553  if (for_preceding_bound) {
2554  d.bigintval *= -1;
2555  }
2556  };
2557 
2558  switch (order_key_ti.get_type()) {
2559  case kTIME: {
2560  if (time_val_expr->get_type_info().is_integer()) {
2561  if (time_unit == kSECOND || time_unit == kMINUTE || time_unit == kHOUR) {
2562  const auto time_multiplier = determineTimeValMultiplierForTimeType(
2563  frame_bound_ti.get_type(), time_unit_val_expr);
2564  switch (time_val_expr->get_type_info().get_type()) {
2565  case kTINYINT: {
2566  d.bigintval = time_val_expr->get_constval().tinyintval * time_multiplier;
2567  break;
2568  }
2569  case kSMALLINT: {
2570  d.bigintval = time_val_expr->get_constval().smallintval * time_multiplier;
2571  break;
2572  }
2573  case kINT: {
2574  d.bigintval = time_val_expr->get_constval().intval * time_multiplier;
2575  break;
2576  }
2577  case kBIGINT: {
2578  d.bigintval = time_val_expr->get_constval().bigintval * time_multiplier;
2579  break;
2580  }
2581  default: {
2582  UNREACHABLE();
2583  break;
2584  }
2585  }
2586  } else {
2587  invalid_frame_bound_expr_type = true;
2588  }
2589  } else {
2590  invalid_time_unit_type = true;
2591  }
2592  if (invalid_frame_bound_expr_type) {
2593  throw std::runtime_error(
2594  "Invalid time unit is used to define window frame bound expression for " +
2595  order_key_ti.get_type_name() + " type");
2596  } else if (invalid_time_unit_type) {
2597  throw std::runtime_error(
2598  "Window frame bound expression has an invalid type for " +
2599  order_key_ti.get_type_name() + " type");
2600  }
2601  return std::make_shared<Analyzer::Constant>(kBIGINT, false, d);
2602  }
2603  case kDATE: {
2605  if (time_val_expr->get_type_info().is_integer()) {
2606  switch (time_unit) {
2607  case kDAY: {
2608  daField = to_dateadd_field("day");
2609  break;
2610  }
2611  case kMONTH: {
2612  daField = to_dateadd_field("month");
2613  break;
2614  }
2615  case kYEAR: {
2616  daField = to_dateadd_field("year");
2617  break;
2618  }
2619  default: {
2620  invalid_frame_bound_expr_type = true;
2621  break;
2622  }
2623  }
2624  } else {
2625  invalid_time_unit_type = true;
2626  }
2627  if (invalid_frame_bound_expr_type) {
2628  throw std::runtime_error(
2629  "Invalid time unit is used to define window frame bound expression for " +
2630  order_key_ti.get_type_name() + " type");
2631  } else if (invalid_time_unit_type) {
2632  throw std::runtime_error(
2633  "Window frame bound expression has an invalid type for " +
2634  order_key_ti.get_type_name() + " type");
2635  }
2637  prepare_time_value_datum(false);
2638  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2639  const int dim = order_key_ti.get_dimension();
2640  return makeExpr<Analyzer::DateaddExpr>(
2641  SQLTypeInfo(kTIMESTAMP, dim, 0, false), daField, cast_number_units, order_key);
2642  }
2643  case kTIMESTAMP: {
2645  switch (time_unit) {
2646  case kSECOND: {
2647  switch (time_val_expr->get_type_info().get_scale()) {
2648  case 0: {
2649  daField = to_dateadd_field("second");
2650  break;
2651  }
2652  case 3: {
2653  daField = to_dateadd_field("millisecond");
2654  break;
2655  }
2656  case 6: {
2657  daField = to_dateadd_field("microsecond");
2658  break;
2659  }
2660  case 9: {
2661  daField = to_dateadd_field("nanosecond");
2662  break;
2663  }
2664  default:
2665  UNREACHABLE();
2666  break;
2667  }
2668  prepare_time_value_datum(true);
2669  break;
2670  }
2671  case kMINUTE: {
2672  daField = to_dateadd_field("minute");
2673  prepare_time_value_datum(false);
2674  break;
2675  }
2676  case kHOUR: {
2677  daField = to_dateadd_field("hour");
2678  prepare_time_value_datum(false);
2679  break;
2680  }
2681  case kDAY: {
2682  daField = to_dateadd_field("day");
2683  prepare_time_value_datum(false);
2684  break;
2685  }
2686  case kMONTH: {
2687  daField = to_dateadd_field("month");
2688  prepare_time_value_datum(false);
2689  break;
2690  }
2691  case kYEAR: {
2692  daField = to_dateadd_field("year");
2693  prepare_time_value_datum(false);
2694  break;
2695  }
2696  default: {
2697  invalid_time_unit_type = true;
2698  break;
2699  }
2700  }
2701  if (!invalid_time_unit_type) {
2703  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2704  const int dim = order_key_ti.get_dimension();
2705  return makeExpr<Analyzer::DateaddExpr>(SQLTypeInfo(kTIMESTAMP, dim, 0, false),
2706  daField,
2707  cast_number_units,
2708  order_key);
2709  }
2710  return nullptr;
2711  }
2712  default: {
2713  UNREACHABLE();
2714  break;
2715  }
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("Window frame bound expression has an invalid type for " +
2723  order_key_ti.get_type_name() + " type");
2724  }
2725  return nullptr;
2726 }
Definition: sqltypes.h:76
const Expr * get_right_operand() const
Definition: Analyzer.h:456
#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:74
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
Definition: sqltypes.h:80
ExtractField
const Expr * get_left_operand() const
Definition: Analyzer.h:455
Definition: sqltypes.h:72
Definition: Datum.h:69
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 1565 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1566  {
1567  CHECK_EQ(size_t(2), rex_function->size());
1568  const auto base = translateScalarRex(rex_function->getOperand(0));
1569  const auto index = translateScalarRex(rex_function->getOperand(1));
1570  return makeExpr<Analyzer::BinOper>(
1571  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1572 }
#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:71

+ 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 1433 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1434  {
1435  const auto& args = translateFunctionArgs(rex_function);
1436  CHECK_EQ(size_t(1), args.size());
1437  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1438  if (nullptr == expr || !expr->get_type_info().is_string() ||
1439  expr->get_type_info().is_varlen()) {
1440  throw std::runtime_error(rex_function->getName() +
1441  " expects a dictionary encoded text column.");
1442  }
1443  auto unnest_arg = dynamic_cast<Analyzer::UOper*>(expr);
1444  if (unnest_arg && unnest_arg->get_optype() == SQLOps::kUNNEST) {
1445  throw std::runtime_error(
1446  rex_function->getName() +
1447  " does not support unnest operator as its input expression.");
1448  }
1449  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1450 }
#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 1425 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1426  {
1427  CHECK_EQ(size_t(1), rex_function->size());
1428  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1429  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1430  rex_function->getName() == "CHAR_LENGTH"sv);
1431 }
#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 1174 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1175  {
1176  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1177  const auto arg = translateScalarRex(rex_function->getOperand(0));
1178  const auto like = translateScalarRex(rex_function->getOperand(1));
1179  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1180  throw std::runtime_error("The matching pattern must be a literal.");
1181  }
1182  const auto escape = (rex_function->size() == 3)
1183  ? translateScalarRex(rex_function->getOperand(2))
1184  : nullptr;
1185  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1186  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1187 }
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:700
#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 1203 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1204  {
1205  CHECK(rex_function->size() == 1);
1206  const auto arg = translateScalarRex(rex_function->getOperand(0));
1207  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1208 }
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 363 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().

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

+ 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 1100 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1101  {
1102  const auto num_operands = rex_function->size();
1103  CHECK_GE(num_operands, 2UL);
1104  auto model_value = translateScalarRex(rex_function->getOperand(0));
1105  std::vector<std::shared_ptr<Analyzer::Expr>> regressor_values;
1106  for (size_t regressor_idx = 1; regressor_idx < num_operands; ++regressor_idx) {
1107  regressor_values.emplace_back(
1108  translateScalarRex(rex_function->getOperand(regressor_idx)));
1109  }
1110  return makeExpr<Analyzer::MLPredictExpr>(model_value, regressor_values);
1111 }
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 1646 of file RelAlgTranslator.cpp.

Referenced by translateFunction().

1646  {
1647  return makeExpr<Analyzer::OffsetInFragment>();
1648 }

+ Here is the caller graph for this function:

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

Definition at line 1026 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().

1027  {
1028  CHECK_GT(rex_operator->size(), size_t(0));
1029  if (rex_operator->size() == 1) {
1030  return translateUoper(rex_operator);
1031  }
1032  const auto sql_op = rex_operator->getOperator();
1033  if (sql_op == kIN) {
1034  return translateInOper(rex_operator);
1035  }
1036  if (sql_op == kMINUS || sql_op == kPLUS) {
1037  auto date_plus_minus = translateDatePlusMinus(rex_operator);
1038  if (date_plus_minus) {
1039  return date_plus_minus;
1040  }
1041  }
1042  if (sql_op == kBBOX_INTERSECT) {
1043  return translateBoundingBoxIntersectOper(rex_operator);
1044  } else if (IS_COMPARISON(sql_op)) {
1045  auto geo_comp = translateGeoComparison(rex_operator);
1046  if (geo_comp) {
1047  return geo_comp;
1048  }
1049  }
1050  auto lhs = translateScalarRex(rex_operator->getOperand(0));
1051  for (size_t i = 1; i < rex_operator->size(); ++i) {
1052  std::shared_ptr<Analyzer::Expr> rhs;
1053  SQLQualifier sql_qual{kONE};
1054  const auto rhs_op = rex_operator->getOperand(i);
1055  std::tie(rhs, sql_qual) = getQuantifiedRhs(rhs_op);
1056  if (!rhs) {
1057  rhs = translateScalarRex(rhs_op);
1058  }
1059  CHECK(rhs);
1060 
1061  // Pass in executor to get string proxy info if cast needed between
1062  // string columns
1063  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs, executor_);
1064  }
1065  return lhs;
1066 }
const Executor * executor_
SQLQualifier
Definition: sqldefs.h:71
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:379
Definition: sqldefs.h:40
#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:39
Definition: sqldefs.h:71
Definition: sqldefs.h:52
#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:58

+ Here is the call graph for this function:

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

Definition at line 1113 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1114  {
1115  const auto num_operands = rex_function->size();
1116  CHECK_GE(num_operands, 3UL);
1117  auto model_value = translateScalarRex(rex_function->getOperand(0));
1118  std::vector<std::shared_ptr<Analyzer::Expr>> feature_values;
1119  for (size_t feature_idx = 1; feature_idx < num_operands - 1; ++feature_idx) {
1120  feature_values.emplace_back(
1121  translateScalarRex(rex_function->getOperand(feature_idx)));
1122  }
1123  auto pc_dimension_value =
1124  translateScalarRex(rex_function->getOperand(num_operands - 1));
1125  return makeExpr<Analyzer::PCAProjectExpr>(
1126  model_value, feature_values, pc_dimension_value);
1127 }
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 1189 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1190  {
1191  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1192  const auto arg = translateScalarRex(rex_function->getOperand(0));
1193  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1194  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1195  throw std::runtime_error("The matching pattern must be a literal.");
1196  }
1197  const auto escape = (rex_function->size() == 3)
1198  ? translateScalarRex(rex_function->getOperand(2))
1199  : nullptr;
1200  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1201 }
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:795
#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 205 of file RelAlgTranslator.cpp.

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

Definition at line 216 of file RelAlgTranslator.cpp.

217  {
218  return translateFunction(static_cast<RexFunctionOperator const*>(rex));
219 }
std::shared_ptr< Analyzer::Expr > translateFunction(const RexFunctionOperator *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 231 of file RelAlgTranslator.cpp.

232  {
233  return translateScalarSubquery(static_cast<RexSubQuery const*>(rex));
234 }
std::shared_ptr< Analyzer::Expr > translateScalarSubquery(const RexSubQuery *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 211 of file RelAlgTranslator.cpp.

212  {
213  return translateWindowFunction(static_cast<RexWindowFunctionOperator const*>(rex));
214 }
std::shared_ptr< Analyzer::Expr > translateWindowFunction(const RexWindowFunctionOperator *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 221 of file RelAlgTranslator.cpp.

222  {
223  return translateOper(static_cast<RexOperator const*>(rex));
224 }
std::shared_ptr< Analyzer::Expr > translateOper(const RexOperator *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 226 of file RelAlgTranslator.cpp.

227  {
228  return translateCase(static_cast<RexCase const*>(rex));
229 }
std::shared_ptr< Analyzer::Expr > translateCase(const RexCase *) const
template<>
std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateRexScalar ( RexScalar const *  rex) const

Definition at line 200 of file RelAlgTranslator.cpp.

201  {
202  return translateInput(static_cast<RexInput const*>(rex));
203 }
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) 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 1452 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1453  {
1454  CHECK_EQ(size_t(1), rex_function->size());
1455  auto arg = translateScalarRex(rex_function->getOperand(0));
1456  const auto& arg_ti = arg->get_type_info();
1457  if (arg_ti.get_type() != kDOUBLE) {
1458  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1459  arg = arg->add_cast(double_ti);
1460  }
1461  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1462 }
#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 236 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(), translateFunction(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoComparison(), translateGeoFunctionArg(), translateHPTLiteral(), translateInOper(), translateItem(), translateLength(), translateLike(), translateLikely(), translateMLPredict(), translateOper(), translatePCAProject(), translateRegexp(), translateSampleRatio(), translateSign(), translateTernaryGeoFunction(), translateUnlikely(), translateUoper(), translateWidthBucket(), and translateWindowFunction().

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

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

+ Here is the call graph for this function:

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

Definition at line 1624 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().

1625  {
1626  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1627  expr_list;
1628  CHECK_EQ(size_t(1), rex_function->size());
1629  const auto operand = translateScalarRex(rex_function->getOperand(0));
1630  const auto& operand_ti = operand->get_type_info();
1631  CHECK(operand_ti.is_number());
1632  const auto zero = makeNumericConstant(operand_ti, 0);
1633  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1634  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1635  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1636  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1637  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1638  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1639  return makeExpr<Analyzer::CaseExpr>(
1640  operand_ti,
1641  false,
1642  expr_list,
1643  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1644 }
#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:29
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
Definition: sqldefs.h:33
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:32
Definition: Datum.h:69

+ 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 1473 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1474  {
1475  const auto func_name = rex_function->getName();
1477  std::ostringstream oss;
1478  oss << "Function " << func_name << " not supported.";
1479  throw std::runtime_error(oss.str());
1480  }
1481  const auto string_op_kind = ::name_to_string_op_kind(func_name);
1482  auto args = translateFunctionArgs(rex_function);
1483 
1484  switch (string_op_kind) {
1486  return makeExpr<Analyzer::LowerStringOper>(args);
1488  return makeExpr<Analyzer::UpperStringOper>(args);
1490  return makeExpr<Analyzer::InitCapStringOper>(args);
1492  return makeExpr<Analyzer::ReverseStringOper>(args);
1494  return makeExpr<Analyzer::RepeatStringOper>(args);
1496  return makeExpr<Analyzer::ConcatStringOper>(args);
1497  case SqlStringOpKind::LPAD:
1498  case SqlStringOpKind::RPAD: {
1499  return makeExpr<Analyzer::PadStringOper>(string_op_kind, args);
1500  }
1501  case SqlStringOpKind::TRIM:
1503  case SqlStringOpKind::RTRIM: {
1504  return makeExpr<Analyzer::TrimStringOper>(string_op_kind, args);
1505  }
1507  return makeExpr<Analyzer::SubstringStringOper>(args);
1509  return makeExpr<Analyzer::OverlayStringOper>(args);
1511  return makeExpr<Analyzer::ReplaceStringOper>(args);
1513  return makeExpr<Analyzer::SplitPartStringOper>(args);
1515  return makeExpr<Analyzer::RegexpReplaceStringOper>(args);
1517  return makeExpr<Analyzer::RegexpSubstrStringOper>(args);
1519  return makeExpr<Analyzer::JsonValueStringOper>(args);
1521  return makeExpr<Analyzer::Base64EncodeStringOper>(args);
1523  return makeExpr<Analyzer::Base64DecodeStringOper>(args);
1525  return makeExpr<Analyzer::TryStringCastOper>(rex_function->getType(), args);
1527  return makeExpr<Analyzer::PositionStringOper>(args);
1529  return makeExpr<Analyzer::JarowinklerSimilarityStringOper>(args);
1531  return makeExpr<Analyzer::LevenshteinDistanceStringOper>(args);
1532  default: {
1533  throw std::runtime_error("Unsupported string function.");
1534  }
1535  }
1536 }
SqlStringOpKind name_to_string_op_kind(const std::string &func_name)
Definition: sqldefs.h:388
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

+ 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 1659 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().

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

1084  {
1085 #ifndef ENABLE_GEOS
1086  throw QueryNotSupported(rex_function->getName() +
1087  " geo constructor requires enabled GEOS support");
1088 #endif
1090 
1091  Analyzer::ExpressionPtrVector geoargs0{};
1092  SQLTypeInfo arg0_ti;
1093  if (func_resolve(rex_function->getName(), "ST_ConvexHull"sv)) {
1094  // First arg: geometry
1095  geoargs0 = translateGeoFunctionArg(rex_function->getOperand(0),
1096  arg0_ti,
1097  false,
1098  true,
1099  true,
1100  false,
1101  false,
1102  /* allow_gdal_transforms = */ true);
1103  }
1104 
1105  // Record the optional transform request that can be sent by an ecompassing TRANSFORM
1106  auto srid = ti.get_output_srid();
1107  // Build the typeinfo of the constructed geometry
1108  SQLTypeInfo arg_ti = arg0_ti;
1109  arg_ti.set_type(kMULTIPOLYGON);
1110  arg_ti.set_subtype(kGEOMETRY);
1111  arg_ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
1112  arg_ti.set_comp_param(0);
1113  arg_ti.set_input_srid(arg0_ti.get_output_srid());
1114  if (srid > 0) {
1115  if (arg_ti.get_input_srid() > 0) {
1116  // Constructed geometry to be transformed to srid given by encompassing transform
1117  arg_ti.set_output_srid(srid);
1118  } else {
1119  throw QueryNotSupported("Transform of geo constructor " + rex_function->getName() +
1120  " requires its argument(s) to have a valid srid");
1121  }
1122  } else {
1123  arg_ti.set_output_srid(arg_ti.get_input_srid()); // No encompassing transform
1124  }
1125  // If there was an output transform, it's now embedded into arg_ti and the geo operator.
1126  // Now de-register the transform from the return typeinfo:
1127  ti = arg_ti;
1129  return makeExpr<Analyzer::GeoUOper>(op, arg_ti, arg0_ti, geoargs0);
1130 }
void set_compression(EncodingType c)
Definition: sqltypes.h:479
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:469
void set_input_srid(int d)
Definition: sqltypes.h:472
void set_output_srid(int s)
Definition: sqltypes.h:474
void set_comp_param(int p)
Definition: sqltypes.h:480
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:468

+ 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 1132 of file RelAlgTranslatorGeo.cpp.

References CHECK, CHECK_EQ, func_resolve, Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), 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().

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

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

Referenced by translateFunction(), and translateGeoFunctionArg().

1044  {
1045 #ifndef ENABLE_GEOS
1046  throw QueryNotSupported(rex_function->getName() +
1047  " geo predicate requires enabled GEOS support");
1048 #endif
1049  SQLTypeInfo arg_ti;
1050  auto geoargs =
1051  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, true);
1052  ti = SQLTypeInfo(kBOOLEAN, false);
1053  auto op = (rex_function->getName() == "ST_IsEmpty"sv)
1056  return makeExpr<Analyzer::GeoUOper>(op, ti, arg_ti, geoargs);
1057 }
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 1210 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1211  {
1212  CHECK(rex_function->size() == 1);
1213  const auto arg = translateScalarRex(rex_function->getOperand(0));
1214  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.0625);
1215 }
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 556 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, CHECK_NE, g_cluster, 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().

557  {
558  CHECK_EQ(size_t(1), rex_operator->size());
559  const auto operand_expr = translateScalarRex(rex_operator->getOperand(0));
560  const auto sql_op = rex_operator->getOperator();
561  switch (sql_op) {
562  case kCAST: {
563  const auto& target_ti = rex_operator->getType();
564  CHECK_NE(kNULLT, target_ti.get_type());
565  const auto& operand_ti = operand_expr->get_type_info();
566  if (operand_ti.is_string() && target_ti.is_string()) {
567  return operand_expr;
568  }
569  if (target_ti.is_time() ||
570  operand_ti
571  .is_string()) { // TODO(alex): check and unify with the rest of the cases
572  // Do not propogate encoding on small dates
573  return target_ti.is_date_in_days()
574  ? operand_expr->add_cast(SQLTypeInfo(kDATE, false))
575  : operand_expr->add_cast(target_ti);
576  }
577  if (!operand_ti.is_string() && target_ti.is_string()) {
578  return operand_expr->add_cast(target_ti);
579  }
580  return std::make_shared<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
581  }
582  case kENCODE_TEXT: {
583  const auto& target_ti = rex_operator->getType();
584  CHECK_NE(kNULLT, target_ti.get_type());
585  const auto& operand_ti = operand_expr->get_type_info();
586  CHECK(operand_ti.is_string());
587  if (operand_ti.is_dict_encoded_string()) {
588  // No cast needed
589  return operand_expr;
590  }
591  if (operand_expr->get_num_column_vars(true) == 0UL) {
592  return operand_expr;
593  }
594  if (g_cluster) {
595  throw std::runtime_error(
596  "ENCODE_TEXT is not currently supported in distributed mode at this time.");
597  }
598  SQLTypeInfo casted_target_ti = operand_ti;
599  casted_target_ti.set_type(kTEXT);
600  casted_target_ti.set_compression(kENCODING_DICT);
601  casted_target_ti.set_comp_param(TRANSIENT_DICT_ID);
603  casted_target_ti.set_fixed_size();
604  return makeExpr<Analyzer::UOper>(
605  casted_target_ti, operand_expr->get_contains_agg(), kCAST, operand_expr);
606  }
607  case kNOT:
608  case kISNULL: {
609  return std::make_shared<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
610  }
611  case kISNOTNULL: {
612  auto is_null = std::make_shared<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
613  return std::make_shared<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
614  }
615  case kMINUS: {
616  const auto& ti = operand_expr->get_type_info();
617  return std::make_shared<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
618  }
619  case kUNNEST: {
620  const auto& ti = operand_expr->get_type_info();
621  CHECK(ti.is_array());
622  return makeExpr<Analyzer::UOper>(ti.get_elem_type(), false, kUNNEST, operand_expr);
623  }
624  default:
625  CHECK(false);
626  }
627  return nullptr;
628 }
void set_compression(EncodingType c)
Definition: sqltypes.h:479
#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:48
#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:477
#define CHECK_NE(x, y)
Definition: Logger.h:302
void set_comp_param(int p)
Definition: sqltypes.h:480
Definition: sqltypes.h:79
Definition: sqltypes.h:80
Definition: sqldefs.h:39
void setStringDictKey(const shared::StringDictKey &dict_key)
Definition: sqltypes.h:1061
static const StringDictKey kTransientDictKey
Definition: DbObjectKeys.h:45
#define CHECK(condition)
Definition: Logger.h:291
bool g_cluster
Definition: sqldefs.h:38
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:468

+ 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 1129 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().

1130  {
1131  CHECK(rex_function->size() == 4);
1132  auto target_value = translateScalarRex(rex_function->getOperand(0));
1133  auto lower_bound = translateScalarRex(rex_function->getOperand(1));
1134  auto upper_bound = translateScalarRex(rex_function->getOperand(2));
1135  auto partition_count = translateScalarRex(rex_function->getOperand(3));
1136  if (!partition_count->get_type_info().is_integer()) {
1137  throw std::runtime_error(
1138  "PARTITION_COUNT expression of width_bucket function expects an integer type.");
1139  }
1140  auto check_numeric_type =
1141  [](const std::string& col_name, const Analyzer::Expr* expr, bool allow_null_type) {
1142  if (expr->get_type_info().get_type() == kNULLT) {
1143  if (!allow_null_type) {
1144  throw std::runtime_error(
1145  col_name + " expression of width_bucket function expects non-null type.");
1146  }
1147  return;
1148  }
1149  if (!expr->get_type_info().is_number()) {
1150  throw std::runtime_error(
1151  col_name + " expression of width_bucket function expects a numeric type.");
1152  }
1153  };
1154  // target value may have null value
1155  check_numeric_type("TARGET_VALUE", target_value.get(), true);
1156  check_numeric_type("LOWER_BOUND", lower_bound.get(), false);
1157  check_numeric_type("UPPER_BOUND", upper_bound.get(), false);
1158 
1159  auto cast_to_double_if_necessary = [](std::shared_ptr<Analyzer::Expr> arg) {
1160  const auto& arg_ti = arg->get_type_info();
1161  if (arg_ti.get_type() != kDOUBLE) {
1162  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1163  return arg->add_cast(double_ti);
1164  }
1165  return arg;
1166  };
1167  target_value = cast_to_double_if_necessary(target_value);
1168  lower_bound = cast_to_double_if_necessary(lower_bound);
1169  upper_bound = cast_to_double_if_necessary(upper_bound);
1170  return makeExpr<Analyzer::WidthBucketExpr>(
1171  target_value, lower_bound, upper_bound, partition_count);
1172 }
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 2101 of file RelAlgTranslator.cpp.

References anonymous_namespace{QueryMemoryDescriptor.cpp}::any_of(), run_benchmark_import::args, BACKWARD_FILL, CHECK, CHECK_GE, Analyzer::ColumnVar::collect_column_var(), Analyzer::ColumnVar::colvar_comp(), CONDITIONAL_CHANGE_EVENT, COUNT, CURRENT_ROW, EXPR_FOLLOWING, EXPR_PRECEDING, FIRST_VALUE_IN_FRAME, FORWARD_FILL, g_bigint_count, Analyzer::Expr::get_type_info(), RexWindowFunctionOperator::getCollation(), RexWindowFunctionOperator::getFrameEndBound(), RexWindowFunctionOperator::getFrameStartBound(), RexWindowFunctionOperator::getKind(), RexOperator::getOperand(), RexWindowFunctionOperator::getOrderKeys(), RexWindowFunctionOperator::getPartitionKeys(), RexOperator::getType(), logger::INFO, Datum::intval, SQLTypeInfo::is_timeinterval(), Analyzer::WindowFunction::isFramingAvailableWindowFunc(), RexWindowFunctionOperator::isRows(), kBIGINT, kDECIMAL, kDOUBLE, kENCODING_DICT, kINT, kMULTIPLY, kNUMERIC, kSMALLINT, kTINYINT, 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(), translateIntervalExprForWindowFraming(), translateScalarRex(), UNBOUNDED_FOLLOWING, UNBOUNDED_PRECEDING, UNKNOWN, VLOG, and window_function_is_value().

2102  {
2103  std::vector<std::shared_ptr<Analyzer::Expr>> args;
2104  for (size_t i = 0; i < rex_window_function->size(); ++i) {
2105  args.push_back(translateScalarRex(rex_window_function->getOperand(i)));
2106  }
2107  std::vector<std::shared_ptr<Analyzer::Expr>> partition_keys;
2108  for (const auto& partition_key : rex_window_function->getPartitionKeys()) {
2109  partition_keys.push_back(translateScalarRex(partition_key.get()));
2110  }
2111  std::vector<std::shared_ptr<Analyzer::Expr>> order_keys;
2112  for (const auto& order_key : rex_window_function->getOrderKeys()) {
2113  order_keys.push_back(translateScalarRex(order_key.get()));
2114  }
2115  std::vector<Analyzer::OrderEntry> collation =
2116  translate_collation(rex_window_function->getCollation());
2117 
2118  auto ti = rex_window_function->getType();
2119  auto window_func_kind = rex_window_function->getKind();
2120  if (window_function_is_value(window_func_kind)) {
2121  CHECK_GE(args.size(), 1u);
2122  ti = args.front()->get_type_info();
2123  }
2124  auto determine_frame_bound_type =
2126  if (bound.unbounded) {
2127  CHECK(!bound.bound_expr && !bound.is_current_row);
2128  if (bound.following) {
2130  } else if (bound.preceding) {
2132  }
2133  } else {
2134  if (bound.is_current_row) {
2135  CHECK(!bound.unbounded && !bound.bound_expr);
2137  } else {
2138  CHECK(!bound.unbounded && bound.bound_expr);
2139  if (bound.following) {
2141  } else if (bound.preceding) {
2143  }
2144  }
2145  }
2147  };
2148  auto is_negative_framing_bound =
2149  [](const SQLTypes t, const Datum& d, bool is_time_unit = false) {
2150  switch (t) {
2151  case kTINYINT:
2152  return d.tinyintval < 0;
2153  case kSMALLINT:
2154  return d.smallintval < 0;
2155  case kINT:
2156  return d.intval < 0;
2157  case kDOUBLE: {
2158  // the only case that double type is used is for handling time interval
2159  // i.e., represent tiny time units like nanosecond and microsecond as the
2160  // equivalent time value with SECOND time unit
2161  CHECK(is_time_unit);
2162  return d.doubleval < 0;
2163  }
2164  case kDECIMAL:
2165  case kNUMERIC:
2166  case kBIGINT:
2167  return d.bigintval < 0;
2168  default: {
2169  throw std::runtime_error(
2170  "We currently only support integer-type literal expression as a window "
2171  "frame bound expression");
2172  }
2173  }
2174  };
2175 
2176  bool negative_constant = false;
2177  bool detect_invalid_frame_start_bound_expr = false;
2178  bool detect_invalid_frame_end_bound_expr = false;
2179  auto& frame_start_bound = rex_window_function->getFrameStartBound();
2180  auto& frame_end_bound = rex_window_function->getFrameEndBound();
2181  bool has_end_bound_frame_expr = false;
2182  std::shared_ptr<Analyzer::Expr> frame_start_bound_expr;
2183  SqlWindowFrameBoundType frame_start_bound_type =
2184  determine_frame_bound_type(frame_start_bound);
2185  std::shared_ptr<Analyzer::Expr> frame_end_bound_expr;
2186  SqlWindowFrameBoundType frame_end_bound_type =
2187  determine_frame_bound_type(frame_end_bound);
2188  bool has_framing_clause =
2190  auto frame_mode = rex_window_function->isRows()
2193  if (order_keys.empty()) {
2194  if (frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2195  frame_end_bound_type == SqlWindowFrameBoundType::UNBOUNDED_FOLLOWING) {
2196  // Calcite sets UNBOUNDED PRECEDING ~ UNBOUNDED_FOLLOWING as its default frame bound
2197  // if the window context has no order by clause regardless of the existence of
2198  // user-given window frame bound but at this point we have no way to recognize the
2199  // absence of the frame definition of this window context
2200  has_framing_clause = false;
2201  }
2202  } else {
2203  auto translate_frame_bound_expr = [&](const RexScalar* bound_expr) {
2204  std::shared_ptr<Analyzer::Expr> translated_expr;
2205  const auto rex_oper = dynamic_cast<const RexOperator*>(bound_expr);
2206  if (rex_oper && rex_oper->getType().is_timeinterval()) {
2207  translated_expr = translateScalarRex(rex_oper);
2208  const auto bin_oper =
2209  dynamic_cast<const Analyzer::BinOper*>(translated_expr.get());
2210  auto time_literal_expr =
2211  dynamic_cast<const Analyzer::Constant*>(bin_oper->get_left_operand());
2212  CHECK(time_literal_expr);
2213  negative_constant =
2214  is_negative_framing_bound(time_literal_expr->get_type_info().get_type(),
2215  time_literal_expr->get_constval(),
2216  true);
2217  return std::make_pair(false, translated_expr);
2218  }
2219  if (dynamic_cast<const RexLiteral*>(bound_expr)) {
2220  translated_expr = translateScalarRex(bound_expr);
2221  if (auto literal_expr =
2222  dynamic_cast<const Analyzer::Constant*>(translated_expr.get())) {
2223  negative_constant = is_negative_framing_bound(
2224  literal_expr->get_type_info().get_type(), literal_expr->get_constval());
2225  return std::make_pair(false, translated_expr);
2226  }
2227  }
2228  return std::make_pair(true, translated_expr);
2229  };
2230 
2231  if (frame_start_bound.bound_expr) {
2232  std::tie(detect_invalid_frame_start_bound_expr, frame_start_bound_expr) =
2233  translate_frame_bound_expr(frame_start_bound.bound_expr.get());
2234  }
2235 
2236  if (frame_end_bound.bound_expr) {
2237  std::tie(detect_invalid_frame_end_bound_expr, frame_end_bound_expr) =
2238  translate_frame_bound_expr(frame_end_bound.bound_expr.get());
2239  }
2240 
2241  // currently we only support literal expression as frame bound expression
2242  if (detect_invalid_frame_start_bound_expr || detect_invalid_frame_end_bound_expr) {
2243  throw std::runtime_error(
2244  "We currently only support literal expression as a window frame bound "
2245  "expression");
2246  }
2247 
2248  // note that Calcite already has frame-bound constraint checking logic, but we
2249  // also check various invalid cases for safety
2250  if (negative_constant) {
2251  throw std::runtime_error(
2252  "A constant expression for window framing should have nonnegative value.");
2253  }
2254 
2255  auto handle_time_interval_expr_if_necessary = [&](const Analyzer::Expr* bound_expr,
2256  SqlWindowFrameBoundType bound_type,
2257  bool for_start_bound) {
2258  if (bound_expr && bound_expr->get_type_info().is_timeinterval()) {
2259  const auto bound_bin_oper = dynamic_cast<const Analyzer::BinOper*>(bound_expr);
2260  CHECK(bound_bin_oper->get_optype() == kMULTIPLY);
2261  auto translated_expr = translateIntervalExprForWindowFraming(
2262  order_keys.front(),
2264  bound_bin_oper);
2265  if (for_start_bound) {
2266  frame_start_bound_expr = translated_expr;
2267  } else {
2268  frame_end_bound_expr = translated_expr;
2269  }
2270  }
2271  };
2272  handle_time_interval_expr_if_necessary(
2273  frame_start_bound_expr.get(), frame_start_bound_type, true);
2274  handle_time_interval_expr_if_necessary(
2275  frame_end_bound_expr.get(), frame_end_bound_type, false);
2276  }
2277 
2278  if (frame_start_bound.following) {
2279  if (frame_end_bound.is_current_row) {
2280  throw std::runtime_error(
2281  "Window framing starting from following row cannot end with current row.");
2282  } else if (has_end_bound_frame_expr && frame_end_bound.preceding) {
2283  throw std::runtime_error(
2284  "Window framing starting from following row cannot have preceding rows.");
2285  }
2286  }
2287  if (frame_start_bound.is_current_row && frame_end_bound.preceding &&
2288  !frame_end_bound.unbounded && has_end_bound_frame_expr) {
2289  throw std::runtime_error(
2290  "Window framing starting from current row cannot have preceding rows.");
2291  }
2292  if (has_framing_clause) {
2294  if (order_keys.size() != 1) {
2295  throw std::runtime_error(
2296  "Window framing with range mode requires a single order-by column");
2297  }
2298  if (!frame_start_bound_expr &&
2299  frame_start_bound_type == SqlWindowFrameBoundType::UNBOUNDED_PRECEDING &&
2300  !frame_end_bound_expr &&
2301  frame_end_bound_type == SqlWindowFrameBoundType::CURRENT_ROW) {
2302  has_framing_clause = false;
2303  VLOG(1) << "Ignore range framing mode with a frame bound between "
2304  "UNBOUNDED_PRECEDING and CURRENT_ROW";
2305  }
2306  std::set<const Analyzer::ColumnVar*,
2307  bool (*)(const Analyzer::ColumnVar*, const Analyzer::ColumnVar*)>
2309  order_keys.front()->collect_column_var(colvar_set, false);
2310  for (auto cv : colvar_set) {
2311  if (!(cv->get_type_info().is_integer() || cv->get_type_info().is_fp() ||
2312  cv->get_type_info().is_time())) {
2313  has_framing_clause = false;
2314  VLOG(1) << "Range framing mode with non-number type ordering column is not "
2315  "supported yet, skip window framing";
2316  }
2317  }
2318  }
2319  }
2320  auto const func_name = ::toString(window_func_kind);
2321  auto const num_args = args.size();
2322  bool need_order_by_clause = false;
2323  bool need_frame_def = false;
2324  switch (window_func_kind) {
2327  need_order_by_clause = true;
2328  need_frame_def = true;
2329  if (num_args != 2) {
2330  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2331  }
2332  Datum d;
2333  d.intval = 1;
2334  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, d));
2335  const auto target_expr_cv =
2336  dynamic_cast<const Analyzer::ColumnVar*>(args.front().get());
2337  if (!target_expr_cv) {
2338  throw std::runtime_error("Currently, " + func_name +
2339  " only allows a column reference as its first argument");
2340  }
2341  const auto target_ti = target_expr_cv->get_type_info();
2342  if (target_ti.is_dict_encoded_string()) {
2343  // Calcite does not represent a window function having dictionary encoded text
2344  // type as its output properly, so we need to set its output type manually
2345  ti.set_compression(kENCODING_DICT);
2346  ti.set_comp_param(target_expr_cv->get_type_info().get_comp_param());
2347  ti.setStringDictKey(target_expr_cv->get_type_info().getStringDictKey());
2348  ti.set_fixed_size();
2349  }
2350  const auto target_offset_cv =
2351  dynamic_cast<const Analyzer::Constant*>(args[1].get());
2352  if (!target_expr_cv ||
2353  is_negative_framing_bound(target_offset_cv->get_type_info().get_type(),
2354  target_offset_cv->get_constval())) {
2355  throw std::runtime_error(
2356  "Currently, " + func_name +
2357  " only allows non-negative constant as its second argument");
2358  }
2359  break;
2360  }
2363  if (num_args != 1) {
2364  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2365  }
2366  need_order_by_clause = true;
2367  need_frame_def = true;
2368  break;
2371  if (has_framing_clause) {
2372  throw std::runtime_error(func_name + " does not support window framing clause");
2373  }
2374  auto const input_expr_ti = args.front()->get_type_info();
2375  if (input_expr_ti.is_string()) {
2376  throw std::runtime_error(func_name + " not supported on " +
2377  input_expr_ti.get_type_name() + " type yet");
2378  }
2379  need_order_by_clause = true;
2380  std::string const arg_str{args.front()->toString()};
2381  bool needs_inject_input_arg_ordering =
2382  !std::any_of(order_keys.cbegin(),
2383  order_keys.cend(),
2384  [&arg_str](std::shared_ptr<Analyzer::Expr> const& expr) {
2385  return boost::equals(arg_str, expr->toString());
2386  });
2387  if (needs_inject_input_arg_ordering) {
2388  VLOG(1) << "Inject " << args.front()->toString() << " as ordering column of the "
2389  << func_name << " function";
2390  order_keys.push_back(args.front());
2391  // forward_fill can fill null values if it is ordered with NULLS LAST
2392  // in contrast, we make NULLS FIRST ordering for the backward_fill function
2393  collation.emplace_back(collation.size() + 1,
2394  false,
2395  window_func_kind != SqlWindowFunctionKind::FORWARD_FILL);
2396  }
2397  break;
2398  }
2401  // todo (yoonmin) : args.size() will be three if we support default value
2402  if (num_args != 2) {
2403  throw std::runtime_error(func_name + " has an invalid number of input arguments");
2404  }
2405  // NTH_VALUE(_IN_FRAME) may return null value even if the argument is non-null
2406  // column
2407  ti.set_notnull(false);
2408  if (window_func_kind == SqlWindowFunctionKind::NTH_VALUE_IN_FRAME) {
2409  need_order_by_clause = true;
2410  need_frame_def = true;
2411  }
2412  if (!args[1]) {
2413  throw std::runtime_error(func_name +
2414  " must have a positional argument expression.");
2415  }
2416  bool has_valid_arg = false;
2417  if (args[1]->get_type_info().is_integer()) {
2418  if (auto* n_value_ptr = dynamic_cast<Analyzer::Constant*>(args[1].get())) {
2419  if (0 < n_value_ptr->get_constval().intval) {
2420  // i.e., having N larger than the partition size
2421  // set the proper N to match the zero-start index pos
2422  auto d = n_value_ptr->get_constval();
2423  d.intval -= 1;
2424  n_value_ptr->set_constval(d);
2425  has_valid_arg = true;
2426  }
2427  }
2428  }
2429  if (!has_valid_arg) {
2430  throw std::runtime_error("The positional argument of the " + func_name +
2431  " must be a positive integer constant.");
2432  }
2433  break;
2434  }
2436  if (order_keys.empty()) {
2437  throw std::runtime_error(
2438  ::toString(window_func_kind) +
2439  " requires an ORDER BY sub-clause within the window clause");
2440  }
2441  if (has_framing_clause) {
2442  LOG(INFO)
2443  << ::toString(window_func_kind)
2444  << " must use a pre-defined window frame range (e.g., ROWS BETWEEN "
2445  "UNBOUNDED PRECEDING AND CURRENT ROW). "
2446  "Thus, we skip the user-defined window frame for this window function";
2447  }
2448  has_framing_clause = true;
2450  frame_start_bound_type = SqlWindowFrameBoundType::UNBOUNDED_PRECEDING;
2451  frame_end_bound_type = SqlWindowFrameBoundType::CURRENT_ROW;
2452  break;
2453  default:;
2454  }
2455  if (need_order_by_clause && order_keys.empty()) {
2456  throw std::runtime_error(func_name + " requires an ORDER BY clause");
2457  }
2458  if (need_frame_def && !has_framing_clause) {
2459  throw std::runtime_error(func_name + " requires window frame definition");
2460  }
2461  if (!has_framing_clause) {
2462  frame_start_bound_type = SqlWindowFrameBoundType::UNKNOWN;
2463  frame_end_bound_type = SqlWindowFrameBoundType::UNKNOWN;
2464  frame_start_bound_expr = nullptr;
2465  frame_end_bound_expr = nullptr;
2466  }
2467  if (window_func_kind == SqlWindowFunctionKind::COUNT && has_framing_clause &&
2468  args.empty()) {
2469  args.push_back(makeExpr<Analyzer::Constant>(g_bigint_count ? kBIGINT : kINT, true));
2470  }
2471  return makeExpr<Analyzer::WindowFunction>(
2472  ti,
2473  rex_window_function->getKind(),
2474  args,
2475  partition_keys,
2476  order_keys,
2477  has_framing_clause ? frame_mode : Analyzer::WindowFunction::FrameBoundType::NONE,
2478  makeExpr<Analyzer::WindowFrame>(frame_start_bound_type, frame_start_bound_expr),
2479  makeExpr<Analyzer::WindowFrame>(frame_end_bound_type, frame_end_bound_expr),
2480  collation);
2481 }
SqlWindowFrameBoundType
Definition: sqldefs.h:157
static bool colvar_comp(const ColumnVar *l, const ColumnVar *r)
Definition: Analyzer.h:215
SQLTypes
Definition: sqltypes.h:65
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:2835
std::shared_ptr< Analyzer::Expr > translateIntervalExprForWindowFraming(std::shared_ptr< Analyzer::Expr > order_key, bool for_preceding_bound, const Analyzer::BinOper *frame_bound_expr) const
#define CHECK_GE(x, y)
Definition: Logger.h:306
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
int32_t intval
Definition: Datum.h:73
bool window_function_is_value(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:29
bool is_timeinterval() const
Definition: sqltypes.h:592
std::vector< Analyzer::OrderEntry > translate_collation(const std::vector< SortField > &sort_fields)
bool g_bigint_count
const RexWindowBound & getFrameEndBound() const
Definition: RelAlgDag.h:674
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:643
const RexWindowBound & getFrameStartBound() const
Definition: RelAlgDag.h:672
SqlWindowFunctionKind getKind() const
Definition: RelAlgDag.h:641
#define CHECK(condition)
Definition: Logger.h:291
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:69
#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 245 of file RelAlgTranslator.h.

Referenced by translate(), and translateScalarRex().

const Executor* RelAlgTranslator::executor_
private

Definition at line 236 of file RelAlgTranslator.h.

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

bool RelAlgTranslator::generated_geos_ops_
mutableprivate

Definition at line 240 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 237 of file RelAlgTranslator.h.

Referenced by translateGeoColumn(), and translateInput().

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

Definition at line 238 of file RelAlgTranslator.h.

Referenced by translateInput().

const bool RelAlgTranslator::just_explain_
private

Definition at line 241 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 235 of file RelAlgTranslator.h.

Referenced by translateCurrentUser().


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