OmniSciDB  c1a53651b2
 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::ExprtranslateOverlapsOper (const RexOperator *) const
 
std::shared_ptr< Analyzer::ExprtranslateCase (const RexCase *) const
 
std::shared_ptr< Analyzer::ExprtranslateWidthBucket (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::ExprtranslateGeoOverlapsOper (const RexOperator *) const
 
std::vector< std::shared_ptr
< Analyzer::Expr > > 
translateGeoFunctionArg (const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, 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 with_render_group, 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 900 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().

902  {
904  return nullptr;
905  }
906  std::vector<int64_t> value_exprs;
907  const size_t fetcher_count = cpu_threads();
908  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
909  std::vector<std::future<void>> fetcher_threads;
910  const auto& arg_type = arg->get_type_info();
911  const auto entry_count = val_set.entryCount();
912  CHECK_EQ(size_t(1), val_set.colCount());
913  const auto& col_type = val_set.getColType(0);
914  if (g_cluster && arg_type.is_string() &&
915  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
916  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
917  return nullptr;
918  }
919  std::atomic<size_t> total_in_vals_count{0};
920  for (size_t i = 0,
921  start_entry = 0,
922  stride = (entry_count + fetcher_count - 1) / fetcher_count;
923  i < fetcher_count && start_entry < entry_count;
924  ++i, start_entry += stride) {
925  expr_set[i].reserve(entry_count / fetcher_count);
926  const auto end_entry = std::min(start_entry + stride, entry_count);
927  if (arg_type.is_string()) {
928  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
929  auto col_expr = dynamic_cast<const Analyzer::ColumnVar*>(arg.get());
930  CHECK(col_expr);
931  const auto& dest_dict_key = arg_type.getStringDictKey();
932  const auto& source_dict_key = col_type.getStringDictKey();
933  const auto dd = executor_->getStringDictionaryProxy(
934  arg_type.getStringDictKey(), val_set.getRowSetMemOwner(), true);
935  const auto sd = executor_->getStringDictionaryProxy(
936  col_type.getStringDictKey(), val_set.getRowSetMemOwner(), true);
937  CHECK(sd);
938  const auto needle_null_val = inline_int_null_val(arg_type);
940  col_expr->getColumnKey().db_id);
941  CHECK(catalog);
942  fetcher_threads.push_back(std::async(
944  [this,
945  &val_set,
946  &total_in_vals_count,
947  sd,
948  dd,
949  &source_dict_key,
950  &dest_dict_key,
951  needle_null_val,
952  catalog](std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
953  if (g_cluster) {
954  CHECK_GE(dd->getGeneration(), 0);
956  in_vals,
957  total_in_vals_count,
958  &val_set,
959  {start, end},
960  catalog->getStringDictionaryHosts(),
961  {source_dict_key.db_id, source_dict_key.dict_id},
962  {dest_dict_key.db_id, dest_dict_key.dict_id},
963  dd->getGeneration(),
964  needle_null_val);
965  } else {
967  total_in_vals_count,
968  &val_set,
969  {start, end},
970  sd,
971  dd,
972  needle_null_val);
973  }
974  },
975  std::ref(expr_set[i]),
976  start_entry,
977  end_entry));
978  } else {
979  CHECK(arg_type.is_integer());
980  fetcher_threads.push_back(std::async(
982  [&val_set, &total_in_vals_count](
983  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
984  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
985  },
986  std::ref(expr_set[i]),
987  start_entry,
988  end_entry));
989  }
990  }
991  for (auto& child : fetcher_threads) {
992  child.get();
993  }
994 
995  val_set.moveToBegin();
996  value_exprs.reserve(entry_count);
997  for (auto& exprs : expr_set) {
998  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
999  }
1000  return makeExpr<Analyzer::InIntegerSet>(
1001  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
1002 }
#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:1558
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:500

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

1553  {
1554  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1555  expr_list;
1556  CHECK_EQ(size_t(1), rex_function->size());
1557  const auto operand = translateScalarRex(rex_function->getOperand(0));
1558  const auto& operand_ti = operand->get_type_info();
1559  CHECK(operand_ti.is_number());
1560  const auto zero = makeNumericConstant(operand_ti, 0);
1561  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1562  const auto uminus_operand =
1563  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1564  expr_list.emplace_back(lt_zero, uminus_operand);
1565  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1566 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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 277 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(), RexAgg::isDistinct(), kAPPROX_COUNT_DISTINCT, kAPPROX_QUANTILE, kBOOLEAN, kCOUNT_IF, kDOUBLE, kINT, kMODE, kSUM_IF, RexAgg::size(), and ThriftSerializers::takes_arg().

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

279  {
280  SQLAgg agg_kind = rex->getKind();
281  const bool is_distinct = rex->isDistinct();
282  const bool takes_arg{rex->size() > 0};
283  std::shared_ptr<Analyzer::Expr> arg_expr;
284  std::shared_ptr<Analyzer::Expr> arg1; // 2nd aggregate parameter
285  if (takes_arg) {
286  const auto operand = rex->getOperand(0);
287  CHECK_LT(operand, scalar_sources.size());
288  CHECK_LE(rex->size(), 2u);
289  arg_expr = scalar_sources[operand];
290  switch (agg_kind) {
292  if (rex->size() == 2) {
293  auto const const_arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
294  scalar_sources[rex->getOperand(1)]);
295  if (!const_arg1 || const_arg1->get_type_info().get_type() != kINT ||
296  const_arg1->get_constval().intval < 1 ||
297  const_arg1->get_constval().intval > 100) {
298  throw std::runtime_error(
299  "APPROX_COUNT_DISTINCT's second parameter should be SMALLINT literal "
300  "between "
301  "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 (rex->isDistinct()) {
336  throw std::runtime_error(
337  "Currently, COUNT_IF function does not support DISTINCT qualifier.");
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  }
355  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
356  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, arg1);
357 }
SQLAgg
Definition: sqldefs.h:73
SQLAgg getKind() const
Definition: RelAlgDag.h:813
size_t getOperand(size_t idx) const
Definition: RelAlgDag.h:819
SQLTypeInfo get_agg_type(const SQLAgg agg_kind, const Analyzer::Expr *arg_expr)
bool is_agg_supported_for_type(const SQLAgg &agg_kind, const SQLTypeInfo &arg_ti)
#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:815
size_t size() const
Definition: RelAlgDag.h:817
bool g_cluster
Definition: sqltypes.h:62
Definition: Datum.h:67
bool is_distinct(const size_t input_idx, const RelAlgNode *node)
Definition: sqldefs.h:83
double doubleval
Definition: Datum.h:74

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

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

Referenced by translateFunction().

1595  {
1596  if (rex_function->getType().get_subtype() == kNULLT) {
1597  auto sql_type = rex_function->getType();
1598  CHECK(sql_type.get_type() == kARRAY);
1599 
1600  // FIX-ME: Deal with NULL arrays
1601  auto translated_function_args(translateFunctionArgs(rex_function));
1602  if (translated_function_args.size() > 0) {
1603  const auto first_element_logical_type =
1604  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1605 
1606  auto diff_elem_itr =
1607  std::find_if(translated_function_args.begin(),
1608  translated_function_args.end(),
1609  [first_element_logical_type](const auto expr) {
1610  const auto element_logical_type =
1611  get_nullable_logical_type_info(expr->get_type_info());
1612  if (first_element_logical_type != element_logical_type) {
1613  if (first_element_logical_type.is_none_encoded_string() &&
1614  element_logical_type.is_none_encoded_string()) {
1615  return false;
1616  }
1617  return true;
1618  }
1619  return false;
1620  });
1621  if (diff_elem_itr != translated_function_args.end()) {
1622  throw std::runtime_error(
1623  "Element " +
1624  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1625  " is not of the same type as other elements of the array. Consider casting "
1626  "to force this condition.\nElement Type: " +
1627  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1628  .to_string() +
1629  "\nArray type: " + first_element_logical_type.to_string());
1630  }
1631 
1632  if (first_element_logical_type.is_string()) {
1633  sql_type.set_subtype(kTEXT);
1634  sql_type.set_compression(kENCODING_DICT);
1635  if (first_element_logical_type.is_none_encoded_string()) {
1636  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1637  sql_type.setStringDictKey({TRANSIENT_DICT_DB_ID, TRANSIENT_DICT_ID});
1638  } else {
1639  CHECK(first_element_logical_type.is_dict_encoded_string());
1640  sql_type.set_comp_param(first_element_logical_type.get_comp_param());
1641  sql_type.setStringDictKey(first_element_logical_type.getStringDictKey());
1642  }
1643  } else if (first_element_logical_type.is_dict_encoded_string()) {
1644  sql_type.set_subtype(kTEXT);
1645  sql_type.set_compression(kENCODING_DICT);
1646  sql_type.set_comp_param(first_element_logical_type.get_comp_param());
1647  sql_type.setStringDictKey(first_element_logical_type.getStringDictKey());
1648  } else {
1649  sql_type.set_subtype(first_element_logical_type.get_type());
1650  sql_type.set_scale(first_element_logical_type.get_scale());
1651  sql_type.set_precision(first_element_logical_type.get_precision());
1652  }
1653 
1654  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1655  } else {
1656  // defaulting to valid sub-type for convenience
1657  sql_type.set_subtype(kBOOLEAN);
1658  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1659  }
1660  } else {
1661  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1662  translateFunctionArgs(rex_function));
1663  }
1664 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:382
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1253
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:284
#define TRANSIENT_DICT_DB_ID
Definition: DbObjectKeys.h:25
#define TRANSIENT_DICT_ID
Definition: DbObjectKeys.h:24
std::string to_string(char const *&&v)
Definition: sqltypes.h:69
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
#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 963 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().

966  {
967 #ifndef ENABLE_GEOS
968  throw QueryNotSupported(rex_function->getName() +
969  " geo constructor requires enabled GEOS support");
970 #endif
972  if (rex_function->getName() == "ST_Difference"sv) {
974  } else if (rex_function->getName() == "ST_Union"sv) {
976  } else if (rex_function->getName() == "ST_Buffer"sv) {
978  } else if (rex_function->getName() == "ST_ConcaveHull"sv) {
980  }
981 
984  SQLTypeInfo arg0_ti;
985  SQLTypeInfo arg1_ti;
986  if (func_resolve(rex_function->getName(),
987  "ST_Intersection"sv,
988  "ST_Difference"sv,
989  "ST_Union"sv,
990  "ST_Buffer"sv,
991  "ST_ConcaveHull"sv)) {
992  // First arg: geometry
993  geoargs0 = translateGeoFunctionArg(rex_function->getOperand(0),
994  arg0_ti,
995  false,
996  false,
997  true,
998  true,
999  false,
1000  false,
1001  /* allow_gdal_transforms = */ true);
1002  }
1003  if (func_resolve(rex_function->getName(),
1004  "ST_Intersection"sv,
1005  "ST_Difference"sv,
1006  "ST_Union"sv)) {
1007  // Second arg: geometry
1008  geoargs1 = translateGeoFunctionArg(rex_function->getOperand(1),
1009  arg1_ti,
1010  false,
1011  false,
1012  true,
1013  true,
1014  false,
1015  false,
1016  /* allow_gdal_transforms = */ true);
1017  if (arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1018  throw QueryNotSupported(rex_function->getName() +
1019  " geo constructor requires arguments with matching srids");
1020  }
1021  } else if (func_resolve(rex_function->getName(), "ST_Buffer"sv, "ST_ConcaveHull"sv)) {
1022  // Second arg: double scalar
1023  auto param_expr = translateScalarRex(rex_function->getOperand(1));
1024  arg1_ti = SQLTypeInfo(kDOUBLE, false);
1025  if (param_expr->get_type_info().get_type() != kDOUBLE) {
1026  param_expr = param_expr->add_cast(arg1_ti);
1027  }
1028  geoargs1 = {param_expr};
1029  }
1030 
1031  // Record the optional transform request that can be sent by an ecompassing TRANSFORM
1032  auto srid = ti.get_output_srid();
1033  // Build the typeinfo of the constructed geometry
1034  SQLTypeInfo arg_ti = arg0_ti;
1035  arg_ti.set_type(kMULTIPOLYGON);
1036  arg_ti.set_subtype(kGEOMETRY);
1037  arg_ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
1038  arg_ti.set_comp_param(0);
1039  arg_ti.set_input_srid(arg0_ti.get_output_srid());
1040  if (srid > 0) {
1041  if (arg_ti.get_input_srid() > 0) {
1042  // Constructed geometry to be transformed to srid given by encompassing transform
1043  arg_ti.set_output_srid(srid);
1044  } else {
1045  throw QueryNotSupported("Transform of geo constructor " + rex_function->getName() +
1046  " requires its argument(s) to have a valid srid");
1047  }
1048  } else {
1049  arg_ti.set_output_srid(arg_ti.get_input_srid()); // No encompassing transform
1050  }
1051  // If there was an output transform, it's now embedded into arg_ti and the geo operator.
1052  // Now de-register the transform from the return typeinfo:
1053  ti = arg_ti;
1055  return makeExpr<Analyzer::GeoBinOper>(op, arg_ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1056 }
void set_compression(EncodingType c)
Definition: sqltypes.h:504
auto func_resolve
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, 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::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:494
void set_input_srid(int d)
Definition: sqltypes.h:497
void set_output_srid(int s)
Definition: sqltypes.h:499
void set_comp_param(int p)
Definition: sqltypes.h:505
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:385
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:186
const std::string & getName() const
Definition: RelAlgDag.h:500
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:387
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:493

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

1463  {
1464  auto function_name = rex_function->getName();
1465  auto return_type = rex_function->getType();
1466 
1467  if (function_name == "ST_Overlaps"sv) {
1468  // Overlaps join is the only implementation supported for now, only translate bounds
1469  CHECK_EQ(size_t(2), rex_function->size());
1470  auto extract_geo_bounds_from_input =
1471  [this, &rex_function](const size_t index) -> std::shared_ptr<Analyzer::Expr> {
1472  const auto rex_input =
1473  dynamic_cast<const RexInput*>(rex_function->getOperand(index));
1474  if (rex_input) {
1475  SQLTypeInfo ti;
1476  const auto exprs = translateGeoColumn(rex_input, ti, true, false, false);
1477  CHECK_GT(exprs.size(), size_t(0));
1478  if (ti.get_type() == kPOINT) {
1479  throw std::runtime_error("ST_Overlaps is not supported for point arguments.");
1480  } else {
1481  return exprs.back();
1482  }
1483  } else {
1484  throw std::runtime_error(
1485  "Only inputs are supported as arguments to ST_Overlaps for now.");
1486  }
1487  };
1488  std::vector<std::shared_ptr<Analyzer::Expr>> geo_args;
1489  geo_args.push_back(extract_geo_bounds_from_input(0));
1490  geo_args.push_back(extract_geo_bounds_from_input(1));
1491 
1492  return makeExpr<Analyzer::FunctionOper>(return_type, function_name, geo_args);
1493  }
1494 
1495  if (function_name == "ST_Distance"sv || function_name == "ST_MaxDistance"sv) {
1496  CHECK_EQ(size_t(2), rex_function->size());
1497  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1498  int legacy_transform_srid = 0;
1499  for (size_t i = 0; i < rex_function->size(); i++) {
1500  SQLTypeInfo arg0_ti; // discard
1501  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(i),
1502  arg0_ti,
1503  /*with_bounds=*/false, // TODO
1504  /*with_render_group=*/false,
1505  /*expand_geo_col=*/false,
1506  /*is_projection = */ false,
1507  /*use_geo_expressions=*/true);
1508  if (arg0_ti.get_input_srid() != arg0_ti.get_output_srid() &&
1509  arg0_ti.get_output_srid() > 0 &&
1510  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
1511  // legacy transform
1512  CHECK(legacy_transform_srid == 0 ||
1513  legacy_transform_srid == arg0_ti.get_output_srid());
1514  legacy_transform_srid = arg0_ti.get_output_srid();
1515  }
1516  args.insert(args.end(), geoargs.begin(), geoargs.end());
1517  }
1518  return makeExpr<Analyzer::GeoOperator>(
1519  SQLTypeInfo(kDOUBLE, /*not_null=*/false),
1520  function_name,
1521  args,
1522  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1523  : std::nullopt);
1524  }
1525 
1526  bool swap_args = false;
1527  bool with_bounds = false;
1528  bool negate_result = false;
1529  Analyzer::ExpressionPtr threshold_expr = nullptr;
1530  Analyzer::ExpressionPtr compare_expr = nullptr;
1531  if (function_name == "ST_DWithin"sv) {
1532  CHECK_EQ(size_t(3), rex_function->size());
1533  function_name = "ST_Distance";
1534  return_type = SQLTypeInfo(kDOUBLE, false);
1535  // Inject ST_DWithin's short-circuiting threshold into ST_MaxDistance
1536  threshold_expr = translateScalarRex(rex_function->getOperand(2));
1537  } else if (function_name == "ST_Equals"sv) {
1538  // Translate ST_Equals(g1,g2) to ST_Distance(g1,g2)<=0.0
1539  CHECK_EQ(size_t(2), rex_function->size());
1540  function_name = "ST_Distance";
1541  return_type = SQLTypeInfo(kDOUBLE, false);
1542  threshold_expr = nullptr;
1543  Datum d;
1544  d.doubleval = 0.0;
1545  compare_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1546  } else if (function_name == "ST_DFullyWithin"sv) {
1547  CHECK_EQ(size_t(3), rex_function->size());
1548  function_name = "ST_MaxDistance";
1549  return_type = SQLTypeInfo(kDOUBLE, false);
1550  // TODO: inject ST_DFullyWithin's short-circuiting threshold into ST_MaxDistance
1551  threshold_expr = nullptr;
1552  } else if (function_name == "ST_Distance"sv) {
1553  // TODO: pick up an outside short-circuiting threshold and inject into ST_Distance
1554  threshold_expr = nullptr;
1555  } else if (function_name == "ST_MaxDistance"sv) {
1556  // TODO: pick up an outside short-circuiting threshold and inject into
1557  // ST_MaxDistance
1558  threshold_expr = nullptr;
1559  } else {
1560  CHECK_EQ(size_t(2), rex_function->size());
1561  }
1562  if (function_name == "ST_Within"sv) {
1563  function_name = "ST_Contains";
1564  swap_args = true;
1565  } else if (function_name == "ST_Disjoint"sv) {
1566  function_name = "ST_Intersects";
1567  negate_result = true;
1568  }
1569  if (func_resolve(
1570  function_name, "ST_Contains"sv, "ST_Intersects"sv, "ST_Approx_Overlaps"sv)) {
1571  with_bounds = true;
1572  }
1573 
1574  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1575  SQLTypeInfo arg0_ti;
1576  SQLTypeInfo arg1_ti;
1577 
1578  // Proactively try to compress the first arg of ST_Intersects to preempt arg swap
1579  bool try_to_compress_arg0 = g_enable_geo_ops_on_uncompressed_coords &&
1580  func_resolve(function_name, "ST_Intersects"sv);
1581 
1582  auto geoargs0 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 1 : 0),
1583  arg0_ti,
1584  with_bounds,
1585  false,
1586  false,
1587  false,
1588  false,
1589  try_to_compress_arg0);
1590  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1591 
1592  // If first arg is compressed, try to compress the second one to be able to
1593  // switch to faster implementations working directly on uncompressed coords
1594  bool try_to_compress_arg1 =
1596  func_resolve(function_name, "ST_Contains"sv, "ST_Intersects"sv) &&
1597  arg0_ti.get_compression() == kENCODING_GEOINT &&
1598  arg0_ti.get_output_srid() == 4326);
1599 
1600  auto geoargs1 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 0 : 1),
1601  arg1_ti,
1602  with_bounds,
1603  false,
1604  false,
1605  false,
1606  false,
1607  try_to_compress_arg1);
1608  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1609 
1610  if (arg0_ti.get_subtype() != kNULLT && arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1611  throw QueryNotSupported(rex_function->getName() +
1612  " accepts either two GEOGRAPHY or two GEOMETRY arguments");
1613  }
1614  // Check SRID match if at least one is set/valid
1615  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1616  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1617  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1618  }
1619  if (compare_expr) {
1620  // We could fold the check to false here if argument geo types are different, e.g.
1621  // POLYGON vs POINT. However, tiny POLYGON could be "spatially" equal to a POINT.
1622  if (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT) {
1623  // ST_Equals is translated to a simple distance check for POINTs,
1624  // otherwise geometries are passed to GEOS's Equals
1625  return nullptr;
1626  }
1627  // Look at POINT compression modes.
1628  if (arg0_ti.get_compression() != arg1_ti.get_compression()) {
1629  if ((arg0_ti.get_compression() == kENCODING_GEOINT &&
1630  arg0_ti.get_comp_param() == 32 &&
1631  arg1_ti.get_compression() == kENCODING_NONE) ||
1632  (arg0_ti.get_compression() == kENCODING_NONE &&
1633  arg1_ti.get_compression() == kENCODING_GEOINT &&
1634  arg0_ti.get_comp_param() == 32)) {
1635  // Spatial equality comparison of a compressed point vs uncompressed point.
1636  // Introduce tolerance into distance calculation and comparison, translate
1637  // ST_Equals(g1,g2) to ST_Distance(g1,g2,thereshold=tolerance)<=tolerance
1638  Datum tolerance;
1639  // Tolerance representing 0.44" to cover shifts due to GEOINT(32) compression
1640  tolerance.doubleval = TOLERANCE_GEOINT32;
1641  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, tolerance);
1642  compare_expr = threshold_expr;
1643  } else {
1644  throw QueryNotSupported(
1645  rex_function->getName() +
1646  " unable to calculate compression tolerance for arguments");
1647  }
1648  }
1649  }
1650  if (arg0_ti.get_type() == kMULTILINESTRING || arg1_ti.get_type() == kMULTILINESTRING) {
1651  throw QueryNotSupported(rex_function->getName() +
1652  " currently doesn't support this argument combination");
1653  }
1654 
1655  auto can_use_compressed_coords = [](const SQLTypeInfo& i0_ti,
1656  const Analyzer::ExpressionPtrVector& i0_operands,
1657  const SQLTypeInfo& i1_ti,
1658  const Analyzer::ExpressionPtrVector& i1_operands) {
1659  const bool i0_is_poly =
1660  i0_ti.get_type() == kPOLYGON || i0_ti.get_type() == kMULTIPOLYGON;
1661  const bool i1_is_point = i1_ti.get_type() == kPOINT;
1662  const bool i1_is_literal =
1663  i1_operands.size() == 1 && std::dynamic_pointer_cast<const Analyzer::Constant>(
1664  i1_operands.front()) != nullptr;
1665  return (i0_is_poly && !i1_is_literal && i1_is_point &&
1666  i0_ti.get_compression() == kENCODING_GEOINT &&
1667  i0_ti.get_input_srid() == i0_ti.get_output_srid() &&
1668  i0_ti.get_compression() == i1_ti.get_compression() &&
1669  i1_ti.get_input_srid() == i1_ti.get_output_srid());
1670  };
1671  if (g_enable_geo_ops_on_uncompressed_coords && function_name == "ST_Contains"sv) {
1672  if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1673  // Switch to Contains implementation working directly on uncompressed coords
1674  function_name = "ST_cContains";
1675  }
1676  }
1677  if (g_enable_geo_ops_on_uncompressed_coords && function_name == "ST_Intersects"sv) {
1678  if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1679  // Switch to Intersects implementation working directly on uncompressed coords
1680  function_name = "ST_cIntersects";
1681  } else if (can_use_compressed_coords(arg1_ti, geoargs1, arg0_ti, geoargs0)) {
1682  // Switch to Intersects implementation working on uncompressed coords, swapped args
1683  function_name = "ST_cIntersects";
1684  geoargs.clear();
1685  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1686  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1687  auto tmp_ti = arg0_ti;
1688  arg0_ti = arg1_ti;
1689  arg1_ti = tmp_ti;
1690  }
1691  }
1692 
1693  std::string specialized_geofunc{function_name + suffix(arg0_ti.get_type()) +
1694  suffix(arg1_ti.get_type())};
1695 
1696  if (arg0_ti.get_subtype() == kGEOGRAPHY && arg0_ti.get_output_srid() == 4326) {
1697  // Need to call geodesic runtime functions
1698  if (function_name == "ST_Distance"sv) {
1699  if ((arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) ||
1700  (arg0_ti.get_type() == kLINESTRING && arg1_ti.get_type() == kPOINT) ||
1701  (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kLINESTRING)) {
1702  // Geodesic distance between points
1703  specialized_geofunc += "_Geodesic"s;
1704  } else {
1705  throw QueryNotSupported(function_name +
1706  " currently doesn't accept non-POINT geographies");
1707  }
1708  } else if (rex_function->getName() == "ST_Contains"sv) {
1709  // We currently don't have a geodesic implementation of ST_Contains,
1710  // allowing calls to a [less precise] cartesian implementation.
1711  } else {
1712  throw QueryNotSupported(function_name + " doesn't accept geographies");
1713  }
1714  } else if (function_name == "ST_Distance"sv && rex_function->size() == 3) {
1715  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1716  // Cartesian distance between points used by ST_DWithin - switch to faster Squared
1717  specialized_geofunc += "_Squared"s;
1718  }
1719  }
1720 
1721  // Add first input's compression mode and SRID args to enable on-the-fly
1722  // decompression/transforms
1723  Datum input_compression0;
1724  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1725  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1726  Datum input_srid0;
1727  input_srid0.intval = arg0_ti.get_input_srid();
1728  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1729 
1730  // Add second input's compression mode and SRID args to enable on-the-fly
1731  // decompression/transforms
1732  Datum input_compression1;
1733  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1734  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1735  Datum input_srid1;
1736  input_srid1.intval = arg1_ti.get_input_srid();
1737  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1738 
1739  // Add output SRID arg to enable on-the-fly transforms
1740  Datum output_srid;
1741  output_srid.intval = arg0_ti.get_output_srid();
1742  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1743 
1744  // Some geo distance functions will be injected with a short-circuit threshold.
1745  // Threshold value would come from Geo comparison operations or from other outer
1746  // geo operations, e.g. ST_DWithin
1747  // At this point, only ST_Distance_LineString_LineString requires a threshold arg.
1748  // TODO: Other combinations that involve LINESTRING, POLYGON and MULTIPOLYGON args
1749  // TODO: Inject threshold into ST_MaxDistance
1750  if (function_name == "ST_Distance"sv && arg0_ti.get_subtype() != kGEOGRAPHY &&
1751  (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT)) {
1752  if (threshold_expr) {
1753  if (threshold_expr->get_type_info().get_type() != kDOUBLE) {
1754  const auto& threshold_ti = SQLTypeInfo(kDOUBLE, false);
1755  threshold_expr = threshold_expr->add_cast(threshold_ti);
1756  }
1757  threshold_expr = fold_expr(threshold_expr.get());
1758  } else {
1759  Datum d;
1760  d.doubleval = 0.0;
1761  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1762  }
1763  geoargs.push_back(threshold_expr);
1764  }
1765 
1766  auto result =
1767  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1768  if (negate_result) {
1769  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, result);
1770  }
1771  if (compare_expr) {
1772  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, result, compare_expr);
1773  }
1774  return result;
1775 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:382
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, 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::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:284
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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:114
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:381
#define CHECK_GT(x, y)
Definition: Logger.h:305
int32_t intval
Definition: Datum.h:71
#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:389
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:392
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:385
#define CHECK(condition)
Definition: Logger.h:291
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:186
Definition: sqltypes.h:62
const std::string & getName() const
Definition: RelAlgDag.h:500
Definition: Datum.h:67
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoColumn(const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool with_render_group, const bool expand_geo_col) const
Definition: sqldefs.h:38
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
double doubleval
Definition: Datum.h:74
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:387

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

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

Referenced by translateFunction(), and translateGeoFunctionArg().

1079  {
1080  if (rex_function->getName() != "ST_Equals"sv) {
1081  throw QueryNotSupported(rex_function->getName() + " geo predicate is not supported");
1082  }
1083 #ifndef ENABLE_GEOS
1084  throw QueryNotSupported(rex_function->getName() +
1085  " geo predicate requires enabled GEOS support");
1086 #endif
1087  SQLTypeInfo arg0_ti;
1088  auto geoargs0 = translateGeoFunctionArg(
1089  rex_function->getOperand(0), arg0_ti, false, false, true, true);
1090  SQLTypeInfo arg1_ti;
1091  auto geoargs1 = translateGeoFunctionArg(
1092  rex_function->getOperand(1), arg1_ti, false, false, true, true);
1093  ti = SQLTypeInfo(kBOOLEAN, false);
1095  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1096 }
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, 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 RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
const std::string & getName() const
Definition: RelAlgDag.h:500

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

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

Referenced by translateFunction().

1483  {
1484  const auto ret_ti = rex_function->getType();
1485  const auto arg = translateScalarRex(rex_function->getOperand(0));
1486  const auto arg_ti = arg->get_type_info();
1487  if (!arg_ti.is_array()) {
1488  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1489  }
1490  if (arg_ti.get_subtype() == kARRAY) {
1491  throw std::runtime_error(rex_function->getName() +
1492  " expects one-dimension array expression.");
1493  }
1494  const auto array_size = arg_ti.get_size();
1495  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1496 
1497  if (array_size > 0) {
1498  if (array_elem_size <= 0) {
1499  throw std::runtime_error(rex_function->getName() +
1500  ": unexpected array element type.");
1501  }
1502  // Return cardinality of a fixed length array
1503  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1504  }
1505  // Variable length array cardinality will be calculated at runtime
1506  return makeExpr<Analyzer::CardinalityExpr>(arg);
1507 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:284
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
const std::string & getName() const
Definition: RelAlgDag.h:500

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

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

1062  {
1063  std::shared_ptr<Analyzer::Expr> else_expr;
1064  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1065  expr_list;
1066  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1067  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
1068  const auto then_expr = translateScalarRex(rex_case->getThen(i));
1069  expr_list.emplace_back(when_expr, then_expr);
1070  }
1071  if (rex_case->getElse()) {
1072  else_expr = translateScalarRex(rex_case->getElse());
1073  }
1074  return Parser::CaseExpr::normalize(expr_list, else_expr, executor_);
1075 }
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:443
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:448
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:438
size_t branchCount() const
Definition: RelAlgDag.h:436

+ Here is the call graph for this function:

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

Definition at line 1518 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1518  {
1519  constexpr bool is_null = false;
1520  Datum datum;
1521  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1522  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1523 }
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: Datum.h:72
Definition: sqltypes.h:70
Definition: Datum.h:67

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

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

Referenced by translateFunction().

1525  {
1526  constexpr bool is_null = false;
1527  Datum datum;
1528  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1529  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1530 }
Definition: sqltypes.h:66
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: Datum.h:72
Definition: Datum.h:67

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

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

Referenced by translateDatetime(), and translateFunction().

1532  {
1534 }
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:223

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

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

Referenced by translateFunction().

1413  {
1414  std::string user{"SESSIONLESS_USER"};
1415  if (query_state_) {
1416  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1417  }
1418  return Parser::UserLiteral::get(user);
1419 }
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:237
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 1235 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().

1236  {
1237  CHECK_EQ(size_t(3), rex_function->size());
1238  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1239  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1241  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1242  const auto number_units_const =
1243  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1244  if (number_units_const && number_units_const->get_is_null()) {
1245  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1246  }
1247  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1248  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1249  const auto& datetime_ti = datetime->get_type_info();
1250  if (datetime_ti.get_type() == kTIME) {
1251  throw std::runtime_error("DateAdd operation not supported for TIME.");
1252  }
1253  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1254  const int dim = datetime_ti.get_dimension();
1255  return makeExpr<Analyzer::DateaddExpr>(
1256  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1257 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Definition: sqltypes.h:66
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
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 1350 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().

1351  {
1352  CHECK_EQ(size_t(3), rex_function->size());
1353  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1354  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1356  const auto start = translateScalarRex(rex_function->getOperand(1));
1357  const auto end = translateScalarRex(rex_function->getOperand(2));
1358  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1359  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1360 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
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 1362 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().

1363  {
1364  CHECK_EQ(size_t(2), rex_function->size());
1365  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1366  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1368  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1369  return ExtractExpr::generate(
1370  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1371 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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 1268 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().

1269  {
1270  if (rex_operator->size() != 2) {
1271  return nullptr;
1272  }
1273  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1274  const auto datetime_ti = datetime->get_type_info();
1275  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1276  if (datetime_ti.get_type() == kTIME) {
1277  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1278  }
1279  return nullptr;
1280  }
1281  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1282  const auto rhs_ti = rhs->get_type_info();
1283  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1284  if (datetime_ti.is_high_precision_timestamp() ||
1285  rhs_ti.is_high_precision_timestamp()) {
1286  throw std::runtime_error(
1287  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1288  "Use "
1289  "DATEDIFF.");
1290  }
1291  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1292  const auto& rex_operator_ti = rex_operator->getType();
1293  const auto datediff_field =
1294  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1295  auto result =
1296  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1297  // multiply 1000 to result since expected result should be in millisecond precision.
1298  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1299  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1300  kMULTIPLY,
1301  kONE,
1302  result,
1303  makeNumericConstant(bigint_ti, 1000));
1304  } else {
1305  return result;
1306  }
1307  }
1308  const auto op = rex_operator->getOperator();
1309  if (op == kPLUS) {
1310  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1311  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1312  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1313  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1314  if (date_trunc) {
1315  return date_trunc;
1316  }
1317  }
1318  const auto interval = fold_expr(rhs.get());
1319  auto interval_ti = interval->get_type_info();
1320  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1321  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1322  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1323  std::shared_ptr<Analyzer::Expr> interval_sec;
1324  if (interval_lit) {
1325  interval_sec =
1326  makeNumericConstant(bigint_ti,
1327  (op == kMINUS ? -interval_lit->get_constval().bigintval
1328  : interval_lit->get_constval().bigintval) /
1329  1000);
1330  } else {
1331  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1332  kDIVIDE,
1333  kONE,
1334  interval,
1335  makeNumericConstant(bigint_ti, 1000));
1336  if (op == kMINUS) {
1337  interval_sec =
1338  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1339  }
1340  }
1341  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1342  }
1343  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1344  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1345  bigint_ti, false, kUMINUS, interval)
1346  : interval;
1347  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1348 }
Definition: sqltypes.h:66
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:284
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
Definition: sqldefs.h:40
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
SQLOps getOperator() const
Definition: RelAlgDag.h:282
Definition: sqltypes.h:70
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 1536 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1537  {
1538  CHECK_EQ(size_t(1), rex_function->size());
1539  const auto arg = translateScalarRex(rex_function->getOperand(0));
1540  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1541  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1542  if (!arg_lit || arg_lit->get_is_null()) {
1543  throw std::runtime_error(datetime_err);
1544  }
1545  CHECK(arg_lit->get_type_info().is_string());
1546  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1547  throw std::runtime_error(datetime_err);
1548  }
1549  return translateCurrentTimestamp();
1550 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
#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 1176 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().

1177  {
1178  CHECK_EQ(size_t(2), rex_function->size());
1179  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1180  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1182  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1183  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1184  if (is_date_trunc) {
1185  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1186  } else {
1187  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1188  }
1189 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
const std::shared_ptr< Analyzer::Expr > generate() const
const std::string & getName() const
Definition: RelAlgDag.h:500
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 1666 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(), translateOffsetInFragment(), translateRegexp(), translateSampleRatio(), translateScalarRex(), translateSign(), translateStringOper(), translateTernaryGeoFunction(), translateUnaryGeoConstructor(), translateUnaryGeoFunction(), translateUnaryGeoPredicate(), translateUnlikely(), translateWidthBucket(), and logger::WARNING.

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

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

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

2629  {
2630  std::vector<std::shared_ptr<Analyzer::Expr>> args;
2631  for (size_t i = 0; i < rex_function->size(); ++i) {
2632  args.push_back(translateScalarRex(rex_function->getOperand(i)));
2633  }
2634  return args;
2635 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272

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

1904  {
1905  std::string specialized_geofunc{rex_function->getName()};
1906  if (func_resolve(rex_function->getName(),
1907  "convert_meters_to_pixel_width"sv,
1908  "convert_meters_to_pixel_height"sv)) {
1909  CHECK_EQ(rex_function->size(), 6u);
1910  SQLTypeInfo arg_ti;
1911  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1912  args.push_back(translateScalarRex(rex_function->getOperand(0)));
1913  auto geoargs =
1914  translateGeoFunctionArg(rex_function->getOperand(1), arg_ti, false, true, false);
1915  // only works on points
1916  if (arg_ti.get_type() != kPOINT) {
1917  throw QueryNotSupported(rex_function->getName() +
1918  " expects a point for the second argument");
1919  }
1920 
1921  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1922 
1923  // Add compression information
1924  Datum input_compression;
1925  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1926  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1927  if (arg_ti.get_input_srid() != 4326) {
1928  throw QueryNotSupported(
1929  rex_function->getName() +
1930  " currently only supports points of with SRID WGS84/EPSG:4326");
1931  }
1932  Datum input_srid;
1933  input_srid.intval = arg_ti.get_input_srid();
1934  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1935  Datum output_srid;
1936  // Forcing web-mercator projection for now
1937  // TODO(croot): check that the input-to-output conversion routines exist?
1938  output_srid.intval =
1939  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1940  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1941 
1942  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1943  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1944  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1945  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1946  return makeExpr<Analyzer::FunctionOper>(
1947  rex_function->getType(), specialized_geofunc, args);
1948  } else if (rex_function->getName() == "is_point_in_view"sv) {
1949  CHECK_EQ(rex_function->size(), 5u);
1950  SQLTypeInfo arg_ti;
1951  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1952  auto geoargs =
1953  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
1954  // only works on points
1955  if (arg_ti.get_type() != kPOINT) {
1956  throw QueryNotSupported(rex_function->getName() +
1957  " expects a point for the second argument");
1958  }
1959 
1960  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1961 
1962  // Add compression information
1963  Datum input_compression;
1964  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1965  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1966  if (arg_ti.get_input_srid() != 4326) {
1967  throw QueryNotSupported(
1968  rex_function->getName() +
1969  " currently only supports points of with SRID WGS84/EPSG:4326");
1970  }
1971  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1972  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1973  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1974  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1975  return makeExpr<Analyzer::FunctionOper>(
1976  rex_function->getType(), specialized_geofunc, args);
1977  } else if (rex_function->getName() == "is_point_size_in_view"sv) {
1978  CHECK_EQ(rex_function->size(), 6u);
1979  SQLTypeInfo arg_ti;
1980  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1981  auto geoargs =
1982  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
1983  // only works on points
1984  if (arg_ti.get_type() != kPOINT) {
1985  throw QueryNotSupported(rex_function->getName() +
1986  " expects a point for the second argument");
1987  }
1988 
1989  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1990 
1991  // Add compression information
1992  Datum input_compression;
1993  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1994  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1995  if (arg_ti.get_input_srid() != 4326) {
1996  throw QueryNotSupported(
1997  rex_function->getName() +
1998  " currently only supports points of with SRID WGS84/EPSG:4326");
1999  }
2000  args.push_back(translateScalarRex(rex_function->getOperand(1)));
2001  args.push_back(translateScalarRex(rex_function->getOperand(2)));
2002  args.push_back(translateScalarRex(rex_function->getOperand(3)));
2003  args.push_back(translateScalarRex(rex_function->getOperand(4)));
2004  args.push_back(translateScalarRex(rex_function->getOperand(5)));
2005  return makeExpr<Analyzer::FunctionOper>(
2006  rex_function->getType(), specialized_geofunc, args);
2007  }
2008  CHECK(false);
2009  return nullptr;
2010 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, 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::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:284
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
int32_t intval
Definition: Datum.h:71
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:62
const std::string & getName() const
Definition: RelAlgDag.h:500
Definition: Datum.h:67

+ 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  with_render_group,
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(), SQLTypeInfo::has_render_group(), input_to_nest_level_, IS_GEO, and SPIMAP_GEO_PHYSICAL_INPUT.

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

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

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

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

Referenced by translateOper().

1883  {
1884  if (rex_operator->size() != size_t(2)) {
1885  return nullptr;
1886  }
1887 
1888  auto geo_distance_expr = translateScalarRex(rex_operator->getOperand(0));
1889  auto func_oper = dynamic_cast<Analyzer::GeoOperator*>(geo_distance_expr.get());
1890  if (func_oper && func_oper->getName() == "ST_Distance"sv) {
1891  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1892  auto distance_expr = translateScalarRex(rex_operator->getOperand(1));
1893  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1894  distance_expr = distance_expr->add_cast(distance_ti);
1895  }
1896  distance_expr = fold_expr(distance_expr.get());
1897  return makeExpr<Analyzer::BinOper>(
1898  kBOOLEAN, rex_operator->getOperator(), kONE, geo_distance_expr, distance_expr);
1899  }
1900  return nullptr;
1901 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
SQLOps getOperator() const
Definition: RelAlgDag.h:282
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  with_render_group,
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 280 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().

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

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

133  {
134  CHECK(rex_literal);
135  if (rex_literal->getType() != kTEXT) {
136  throw std::runtime_error("Geo literals must be strings");
137  }
138 
139  // TODO: use geo conversion here
140  const auto e = translateLiteral(rex_literal);
141  auto wkt = std::dynamic_pointer_cast<Analyzer::Constant>(e);
142  CHECK(wkt);
143  std::vector<double> coords;
144  std::vector<double> bounds;
145  std::vector<int> ring_sizes;
146  std::vector<int> poly_rings;
147  int32_t srid = ti.get_output_srid();
149  *wkt->get_constval().stringval, ti, coords, bounds, ring_sizes, poly_rings)) {
150  throw QueryNotSupported("Could not read geometry from text");
151  }
153  ti.set_input_srid(srid);
154  ti.set_output_srid(srid);
155  // Compress geo literals by default
156  if (srid == 4326) {
158  ti.set_comp_param(32);
159  }
160 
161  std::vector<std::shared_ptr<Analyzer::Expr>> args;
162 
163  std::vector<uint8_t> compressed_coords = Geospatial::compress_coords(coords, ti);
164  std::list<std::shared_ptr<Analyzer::Expr>> compressed_coords_exprs;
165  for (auto cc : compressed_coords) {
166  Datum d;
167  d.tinyintval = cc;
168  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
169  compressed_coords_exprs.push_back(e);
170  }
171  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
172  arr_ti.set_subtype(kTINYINT);
173  arr_ti.set_size(compressed_coords.size() * sizeof(int8_t));
174  arr_ti.set_compression(ti.get_compression());
175  arr_ti.set_comp_param((ti.get_compression() == kENCODING_GEOINT) ? 32 : 64);
176  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, compressed_coords_exprs));
177 
178  auto lit_type = ti.get_type();
179  if (lit_type == kMULTILINESTRING || lit_type == kPOLYGON || lit_type == kMULTIPOLYGON) {
180  // [linest]ring sizes
181  std::list<std::shared_ptr<Analyzer::Expr>> ring_size_exprs;
182  for (auto c : ring_sizes) {
183  Datum d;
184  d.intval = c;
185  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
186  ring_size_exprs.push_back(e);
187  }
188  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
189  arr_ti.set_subtype(kINT);
190  arr_ti.set_size(ring_sizes.size() * sizeof(int32_t));
191  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, ring_size_exprs));
192 
193  // poly rings
194  if (lit_type == kMULTIPOLYGON) {
195  std::list<std::shared_ptr<Analyzer::Expr>> poly_rings_exprs;
196  for (auto c : poly_rings) {
197  Datum d;
198  d.intval = c;
199  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
200  poly_rings_exprs.push_back(e);
201  }
202  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
203  arr_ti.set_subtype(kINT);
204  arr_ti.set_size(poly_rings.size() * sizeof(int32_t));
205  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, poly_rings_exprs));
206  }
207  }
208 
209  if (with_bounds && ti.has_bounds()) {
210  // bounds
211  std::list<std::shared_ptr<Analyzer::Expr>> bounds_exprs;
212  for (auto b : bounds) {
213  Datum d;
214  d.doubleval = b;
215  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
216  bounds_exprs.push_back(e);
217  }
218  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
219  arr_ti.set_subtype(kDOUBLE);
220  arr_ti.set_size(bounds.size() * sizeof(double));
221  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, bounds_exprs));
222  }
223 
224  return args;
225 }
int8_t tinyintval
Definition: Datum.h:69
void set_compression(EncodingType c)
Definition: sqltypes.h:504
void set_size(int s)
Definition: sqltypes.h:501
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:494
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:381
int32_t intval
Definition: Datum.h:71
void set_input_srid(int d)
Definition: sqltypes.h:497
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:470
void set_output_srid(int s)
Definition: sqltypes.h:499
void set_comp_param(int p)
Definition: sqltypes.h:505
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 promote_poly_to_mpoly=false)
Definition: Types.cpp:1079
Definition: sqltypes.h:69
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:389
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:62
Definition: Datum.h:67
double doubleval
Definition: Datum.h:74
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:387

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2012 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateOverlapsOper().

2013  {
2014  CHECK_EQ(rex_operator->size(), 2u);
2015 
2016  auto translate_input =
2017  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
2018  const auto input = dynamic_cast<const RexInput*>(operand);
2019  CHECK(input);
2020 
2021  SQLTypeInfo ti;
2022  const auto exprs = translateGeoColumn(input, ti, true, false, false);
2023  CHECK_GT(exprs.size(), 0u);
2024  if (ti.get_type() == kPOINT) {
2025  return exprs.front();
2026  } else {
2027  return exprs.back();
2028  }
2029  };
2030 
2031  SQLQualifier sql_qual{kONE};
2032  SQLOps sql_op{kOVERLAPS};
2033  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
2034  false,
2035  sql_op,
2036  sql_qual,
2037  translate_input(rex_operator->getOperand(1)),
2038  translate_input(rex_operator->getOperand(0)));
2039 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
SQLQualifier
Definition: sqldefs.h:71
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
SQLOps
Definition: sqldefs.h:28
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:381
#define CHECK_GT(x, y)
Definition: Logger.h:305
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:291
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoColumn(const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool with_render_group, const bool expand_geo_col) const

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

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

Referenced by translateFunction().

915  {
916  // note that this is a bit of a misnomer, as ST_SetSRID embedded in a transform will
917  // eventually use geo expressions -- just not here
918  const bool use_geo_projections = !(rex_function->getName() == "ST_GeomFromText" ||
919  rex_function->getName() == "ST_GeogFromText" ||
920  rex_function->getName() == "ST_SetSRID");
921  auto geoargs = translateGeoFunctionArg(rex_function,
922  ti,
923  /*with_bounds=*/false,
924  /*with_render_group=*/false,
925  /*expand_geo_col=*/true,
926  /*is_projection=*/true,
927  /*use_geo_expressions=*/use_geo_projections);
928  CHECK(!geoargs.empty());
929  if (std::dynamic_pointer_cast<const Analyzer::GeoExpr>(geoargs.front()) &&
930  !geoargs.front()->get_type_info().is_array()) {
931  if (rex_function->getName() == "ST_Transform" &&
932  std::dynamic_pointer_cast<const Analyzer::GeoConstant>(geoargs.front())) {
933  return makeExpr<Analyzer::GeoUOper>(
934  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
935  }
936  // GeoExpression
937  return geoargs.front();
938  }
939  bool allow_gdal_transform = false;
940  if (rex_function->getName() == "ST_Transform") {
941  const auto rex_scalar0 = dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
942  const auto rex_function0 = dynamic_cast<const RexFunctionOperator*>(rex_scalar0);
943  if (rex_function0 && func_resolve(rex_function0->getName(),
944  "ST_Intersection"sv,
945  "ST_Difference"sv,
946  "ST_Union"sv,
947  "ST_Buffer"sv,
948  "ST_ConcaveHull"sv,
949  "ST_ConvexHull"sv)) {
950  // Allow projection of gdal-transformed geos outputs
951  allow_gdal_transform = true;
952  }
953  }
954  if (use_geo_projections && !allow_gdal_transform) {
955  throw std::runtime_error("Geospatial projection for function " +
956  rex_function->toString(RelRexToStringConfig::defaults()) +
957  " not yet supported in this context");
958  }
959  return makeExpr<Analyzer::GeoUOper>(
960  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
961 }
auto func_resolve
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, 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 RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
static RelRexToStringConfig defaults()
Definition: RelAlgDag.h:49
#define CHECK(condition)
Definition: Logger.h:291
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
Definition: RelAlgDag.h:502
const std::string & getName() const
Definition: RelAlgDag.h:500

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

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

Referenced by translateFunction().

2681  {
2682  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
2683  Therefore any string having fractional seconds more 3 places after the decimal
2684  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
2685  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
2686  calcite and translating them to generate our own casts.
2687  */
2688  CHECK_EQ(size_t(1), rex_function->size());
2689  const auto operand = translateScalarRex(rex_function->getOperand(0));
2690  const auto& operand_ti = operand->get_type_info();
2691  const auto& target_ti = rex_function->getType();
2692  if (!operand_ti.is_string()) {
2693  throw std::runtime_error(
2694  "High precision timestamp cast argument must be a string. Input type is: " +
2695  operand_ti.get_type_name());
2696  } else if (!target_ti.is_high_precision_timestamp()) {
2697  throw std::runtime_error(
2698  "Cast target type should be high precision timestamp. Input type is: " +
2699  target_ti.get_type_name());
2700  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
2701  throw std::runtime_error(
2702  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
2703  std::to_string(target_ti.get_dimension()) + ")");
2704  } else {
2705  return operand->add_cast(target_ti);
2706  }
2707 }
#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:284
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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 680 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().

681  {
682  if (just_explain_) {
683  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
684  }
685  CHECK(rex_operator->size() == 2);
686  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
687  const auto rhs = rex_operator->getOperand(1);
688  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
689  CHECK(rex_subquery);
690  auto ti = lhs->get_type_info();
691  auto result = rex_subquery->getExecutionResult();
692  CHECK(result);
693  auto& row_set = result->getRows();
694  CHECK_EQ(size_t(1), row_set->colCount());
695  const auto& rhs_ti = row_set->getColType(0);
696  if (rhs_ti.get_type() != ti.get_type()) {
697  throw std::runtime_error(
698  "The two sides of the IN operator must have the same type; found " +
699  ti.get_type_name() + " and " + rhs_ti.get_type_name());
700  }
701  row_set->moveToBegin();
702  if (row_set->entryCount() > 10000) {
703  std::shared_ptr<Analyzer::Expr> expr;
704  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
705  !row_set->getQueryMemDesc().didOutputColumnar()) {
706  expr = getInIntegerSetExpr(lhs, *row_set);
707  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
708  // Just let it fall through the usual InValues path at the end of this method,
709  // its codegen knows to use inline comparisons for few values.
710  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
711  ->get_value_list()
712  .size() <= 100) {
713  expr = nullptr;
714  }
715  } else {
716  expr = get_in_values_expr(lhs, *row_set);
717  }
718  if (expr) {
719  return expr;
720  }
721  }
722  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
723  while (true) {
724  auto row = row_set->getNextRow(true, false);
725  if (row.empty()) {
726  break;
727  }
728  if (g_enable_watchdog && value_exprs.size() >= 10000) {
729  throw std::runtime_error(
730  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
731  }
732  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
733  Datum d{0};
734  bool is_null_const{false};
735  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
736  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
737  auto ti_none_encoded = ti;
738  ti_none_encoded.set_compression(kENCODING_NONE);
739  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
740  auto dict_encoded_string =
741  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
742  value_exprs.push_back(dict_encoded_string);
743  } else {
744  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
745  }
746  }
747  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
748 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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:67

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

479  {
480  const auto source = rex_input->getSourceNode();
481  const auto it_rte_idx = input_to_nest_level_.find(source);
482  CHECK(it_rte_idx != input_to_nest_level_.end())
483  << "Not found in input_to_nest_level_, source="
484  << source->toString(RelRexToStringConfig::defaults());
485  const int rte_idx = it_rte_idx->second;
486  const auto scan_source = dynamic_cast<const RelScan*>(source);
487  const auto& in_metainfo = source->getOutputMetainfo();
488  if (scan_source) {
489  // We're at leaf (scan) level and not supposed to have input metadata,
490  // the name and type information come directly from the catalog.
491  CHECK(in_metainfo.empty());
492  const auto table_desc = scan_source->getTableDescriptor();
493  const auto& catalog = scan_source->getCatalog();
494  const auto cd =
495  catalog.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
496  CHECK(cd);
497  auto col_ti = cd->columnType;
498  if (col_ti.is_string()) {
499  col_ti.set_type(kTEXT);
500  }
501  if (cd->isVirtualCol) {
502  // TODO(alex): remove at some point, we only need this fixup for backwards
503  // compatibility with old imported data
504  CHECK_EQ("rowid", cd->columnName);
505  col_ti.set_size(8);
506  }
507  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
508  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
509  col_ti.set_notnull(false);
510  }
511  return std::make_shared<Analyzer::ColumnVar>(
512  col_ti,
513  shared::ColumnKey{catalog.getDatabaseId(), table_desc->tableId, cd->columnId},
514  rte_idx);
515  }
516  CHECK(!in_metainfo.empty()) << "for "
517  << source->toString(RelRexToStringConfig::defaults());
518  CHECK_GE(rte_idx, 0);
519  const int32_t col_id = rex_input->getIndex();
520  CHECK_LT(col_id, in_metainfo.size());
521  auto col_ti = in_metainfo[col_id].get_type_info();
522 
523  if (join_types_.size() > 0) {
524  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
525  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
526  col_ti.set_notnull(false);
527  }
528  }
529 
530  return std::make_shared<Analyzer::ColumnVar>(
531  col_ti, shared::ColumnKey{0, int32_t(-source->getId()), col_id}, rte_idx);
532 }
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:77
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:303
Definition: sqltypes.h:69
#define CHECK_LE(x, y)
Definition: Logger.h:304
static RelRexToStringConfig defaults()
Definition: RelAlgDag.h:49
const RelAlgNode * getSourceNode() const
Definition: RelAlgDag.h:389
#define CHECK(condition)
Definition: Logger.h:291
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
Definition: RelAlgDag.h:876

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

2386  {
2387  // translate time interval expression and prepare appropriate frame bound expression:
2388  // a) manually compute time unit datum: time type
2389  // b) use dateadd expression: date and timestamp
2390  const auto order_key_ti = order_key->get_type_info();
2391  const auto frame_bound_ti = frame_bound_expr->get_type_info();
2392  const auto time_val_expr =
2393  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_left_operand());
2394  const auto time_unit_val_expr =
2395  dynamic_cast<const Analyzer::Constant*>(frame_bound_expr->get_right_operand());
2396  ExtractField time_unit =
2397  determineTimeUnit(frame_bound_ti.get_type(), time_unit_val_expr);
2398  bool invalid_time_unit_type = false;
2399  bool invalid_frame_bound_expr_type = false;
2400  Datum d;
2401  auto prepare_time_value_datum = [&d,
2402  &invalid_frame_bound_expr_type,
2403  &time_val_expr,
2404  &for_preceding_bound](bool is_timestamp_second) {
2405  // currently, Calcite only accepts interval with second, so to represent
2406  // smaller time units like millisecond, we have to use decimal point like
2407  // INTERVAL 0.003 SECOND (for millisecond)
2408  // thus, depending on what time unit we want to represent, Calcite analyzes
2409  // the time value to one of following two types: integer and decimal (and
2410  // numeric) types
2411  switch (time_val_expr->get_type_info().get_type()) {
2412  case kTINYINT: {
2413  d.bigintval = time_val_expr->get_constval().tinyintval;
2414  break;
2415  }
2416  case kSMALLINT: {
2417  d.bigintval = time_val_expr->get_constval().smallintval;
2418  break;
2419  }
2420  case kINT: {
2421  d.bigintval = time_val_expr->get_constval().intval;
2422  break;
2423  }
2424  case kBIGINT: {
2425  d.bigintval = time_val_expr->get_constval().bigintval;
2426  break;
2427  }
2428  case kDECIMAL:
2429  case kNUMERIC: {
2430  if (!is_timestamp_second) {
2431  // date and time type only use integer type as their time value
2432  invalid_frame_bound_expr_type = true;
2433  break;
2434  }
2435  d.bigintval = time_val_expr->get_constval().bigintval;
2436  break;
2437  }
2438  case kDOUBLE: {
2439  if (!is_timestamp_second) {
2440  // date and time type only use integer type as their time value
2441  invalid_frame_bound_expr_type = true;
2442  break;
2443  }
2444  d.bigintval = time_val_expr->get_constval().doubleval *
2445  pow(10, time_val_expr->get_type_info().get_scale());
2446  break;
2447  }
2448  default: {
2449  invalid_frame_bound_expr_type = true;
2450  break;
2451  }
2452  }
2453  if (for_preceding_bound) {
2454  d.bigintval *= -1;
2455  }
2456  };
2457 
2458  switch (order_key_ti.get_type()) {
2459  case kTIME: {
2460  if (time_val_expr->get_type_info().is_integer()) {
2461  if (time_unit == kSECOND || time_unit == kMINUTE || time_unit == kHOUR) {
2462  const auto time_multiplier = determineTimeValMultiplierForTimeType(
2463  frame_bound_ti.get_type(), time_unit_val_expr);
2464  switch (time_val_expr->get_type_info().get_type()) {
2465  case kTINYINT: {
2466  d.bigintval = time_val_expr->get_constval().tinyintval * time_multiplier;
2467  break;
2468  }
2469  case kSMALLINT: {
2470  d.bigintval = time_val_expr->get_constval().smallintval * time_multiplier;
2471  break;
2472  }
2473  case kINT: {
2474  d.bigintval = time_val_expr->get_constval().intval * time_multiplier;
2475  break;
2476  }
2477  case kBIGINT: {
2478  d.bigintval = time_val_expr->get_constval().bigintval * time_multiplier;
2479  break;
2480  }
2481  default: {
2482  UNREACHABLE();
2483  break;
2484  }
2485  }
2486  } else {
2487  invalid_frame_bound_expr_type = true;
2488  }
2489  } else {
2490  invalid_time_unit_type = true;
2491  }
2492  if (invalid_frame_bound_expr_type) {
2493  throw std::runtime_error(
2494  "Invalid time unit is used to define window frame bound expression for " +
2495  order_key_ti.get_type_name() + " type");
2496  } else if (invalid_time_unit_type) {
2497  throw std::runtime_error(
2498  "Window frame bound expression has an invalid type for " +
2499  order_key_ti.get_type_name() + " type");
2500  }
2501  return std::make_shared<Analyzer::Constant>(kBIGINT, false, d);
2502  }
2503  case kDATE: {
2505  if (time_val_expr->get_type_info().is_integer()) {
2506  switch (time_unit) {
2507  case kDAY: {
2508  daField = to_dateadd_field("day");
2509  break;
2510  }
2511  case kMONTH: {
2512  daField = to_dateadd_field("month");
2513  break;
2514  }
2515  case kYEAR: {
2516  daField = to_dateadd_field("year");
2517  break;
2518  }
2519  default: {
2520  invalid_frame_bound_expr_type = true;
2521  break;
2522  }
2523  }
2524  } else {
2525  invalid_time_unit_type = true;
2526  }
2527  if (invalid_frame_bound_expr_type) {
2528  throw std::runtime_error(
2529  "Invalid time unit is used to define window frame bound expression for " +
2530  order_key_ti.get_type_name() + " type");
2531  } else if (invalid_time_unit_type) {
2532  throw std::runtime_error(
2533  "Window frame bound expression has an invalid type for " +
2534  order_key_ti.get_type_name() + " type");
2535  }
2537  prepare_time_value_datum(false);
2538  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2539  const int dim = order_key_ti.get_dimension();
2540  return makeExpr<Analyzer::DateaddExpr>(
2541  SQLTypeInfo(kTIMESTAMP, dim, 0, false), daField, cast_number_units, order_key);
2542  }
2543  case kTIMESTAMP: {
2545  switch (time_unit) {
2546  case kSECOND: {
2547  switch (time_val_expr->get_type_info().get_scale()) {
2548  case 0: {
2549  daField = to_dateadd_field("second");
2550  break;
2551  }
2552  case 3: {
2553  daField = to_dateadd_field("millisecond");
2554  break;
2555  }
2556  case 6: {
2557  daField = to_dateadd_field("microsecond");
2558  break;
2559  }
2560  case 9: {
2561  daField = to_dateadd_field("nanosecond");
2562  break;
2563  }
2564  default:
2565  UNREACHABLE();
2566  break;
2567  }
2568  prepare_time_value_datum(true);
2569  break;
2570  }
2571  case kMINUTE: {
2572  daField = to_dateadd_field("minute");
2573  prepare_time_value_datum(false);
2574  break;
2575  }
2576  case kHOUR: {
2577  daField = to_dateadd_field("hour");
2578  prepare_time_value_datum(false);
2579  break;
2580  }
2581  case kDAY: {
2582  daField = to_dateadd_field("day");
2583  prepare_time_value_datum(false);
2584  break;
2585  }
2586  case kMONTH: {
2587  daField = to_dateadd_field("month");
2588  prepare_time_value_datum(false);
2589  break;
2590  }
2591  case kYEAR: {
2592  daField = to_dateadd_field("year");
2593  prepare_time_value_datum(false);
2594  break;
2595  }
2596  default: {
2597  invalid_time_unit_type = true;
2598  break;
2599  }
2600  }
2601  if (!invalid_time_unit_type) {
2603  const auto cast_number_units = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
2604  const int dim = order_key_ti.get_dimension();
2605  return makeExpr<Analyzer::DateaddExpr>(SQLTypeInfo(kTIMESTAMP, dim, 0, false),
2606  daField,
2607  cast_number_units,
2608  order_key);
2609  }
2610  return nullptr;
2611  }
2612  default: {
2613  UNREACHABLE();
2614  break;
2615  }
2616  }
2617  if (invalid_frame_bound_expr_type) {
2618  throw std::runtime_error(
2619  "Invalid time unit is used to define window frame bound expression for " +
2620  order_key_ti.get_type_name() + " type");
2621  } else if (invalid_time_unit_type) {
2622  throw std::runtime_error("Window frame bound expression has an invalid type for " +
2623  order_key_ti.get_type_name() + " type");
2624  }
2625  return nullptr;
2626 }
Definition: sqltypes.h:66
const Expr * get_right_operand() const
Definition: Analyzer.h:456
#define UNREACHABLE()
Definition: Logger.h:337
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:72
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
Definition: sqltypes.h:70
ExtractField
const Expr * get_left_operand() const
Definition: Analyzer.h:455
Definition: sqltypes.h:62
Definition: Datum.h:67
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 1509 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1510  {
1511  CHECK_EQ(size_t(2), rex_function->size());
1512  const auto base = translateScalarRex(rex_function->getOperand(0));
1513  const auto index = translateScalarRex(rex_function->getOperand(1));
1514  return makeExpr<Analyzer::BinOper>(
1515  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1516 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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 1381 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1382  {
1383  const auto& args = translateFunctionArgs(rex_function);
1384  CHECK_EQ(size_t(1), args.size());
1385  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1386  if (nullptr == expr || !expr->get_type_info().is_string() ||
1387  expr->get_type_info().is_varlen()) {
1388  throw std::runtime_error(rex_function->getName() +
1389  " expects a dictionary encoded text column.");
1390  }
1391  auto unnest_arg = dynamic_cast<Analyzer::UOper*>(expr);
1392  if (unnest_arg && unnest_arg->get_optype() == SQLOps::kUNNEST) {
1393  throw std::runtime_error(
1394  rex_function->getName() +
1395  " does not support unnest operator as its input expression.");
1396  }
1397  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1398 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
const std::string & getName() const
Definition: RelAlgDag.h:500

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

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

Referenced by translateFunction().

1374  {
1375  CHECK_EQ(size_t(1), rex_function->size());
1376  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1377  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1378  rex_function->getName() == "CHAR_LENGTH"sv);
1379 }
#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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
const std::string & getName() const
Definition: RelAlgDag.h:500

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

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

Referenced by translateFunction().

1123  {
1124  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1125  const auto arg = translateScalarRex(rex_function->getOperand(0));
1126  const auto like = translateScalarRex(rex_function->getOperand(1));
1127  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1128  throw std::runtime_error("The matching pattern must be a literal.");
1129  }
1130  const auto escape = (rex_function->size() == 3)
1131  ? translateScalarRex(rex_function->getOperand(2))
1132  : nullptr;
1133  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1134  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1135 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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:695
#define CHECK(condition)
Definition: Logger.h:291
const std::string & getName() const
Definition: RelAlgDag.h:500

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

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

Referenced by translateFunction().

1152  {
1153  CHECK(rex_function->size() == 1);
1154  const auto arg = translateScalarRex(rex_function->getOperand(0));
1155  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1156 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
#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 359 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, kINT, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kNULLT, kTEXT, kTIME, kTIMESTAMP, LOG, and make_fp_constant().

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

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

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

Referenced by translateFunction().

1590  {
1591  return makeExpr<Analyzer::OffsetInFragment>();
1592 }

+ Here is the caller graph for this function:

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

Definition at line 1004 of file RelAlgTranslator.cpp.

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

1005  {
1006  CHECK_GT(rex_operator->size(), size_t(0));
1007  if (rex_operator->size() == 1) {
1008  return translateUoper(rex_operator);
1009  }
1010  const auto sql_op = rex_operator->getOperator();
1011  if (sql_op == kIN) {
1012  return translateInOper(rex_operator);
1013  }
1014  if (sql_op == kMINUS || sql_op == kPLUS) {
1015  auto date_plus_minus = translateDatePlusMinus(rex_operator);
1016  if (date_plus_minus) {
1017  return date_plus_minus;
1018  }
1019  }
1020  if (sql_op == kOVERLAPS) {
1021  return translateOverlapsOper(rex_operator);
1022  } else if (IS_COMPARISON(sql_op)) {
1023  auto geo_comp = translateGeoComparison(rex_operator);
1024  if (geo_comp) {
1025  return geo_comp;
1026  }
1027  }
1028  auto lhs = translateScalarRex(rex_operator->getOperand(0));
1029  for (size_t i = 1; i < rex_operator->size(); ++i) {
1030  std::shared_ptr<Analyzer::Expr> rhs;
1031  SQLQualifier sql_qual{kONE};
1032  const auto rhs_op = rex_operator->getOperand(i);
1033  std::tie(rhs, sql_qual) = getQuantifiedRhs(rhs_op);
1034  if (!rhs) {
1035  rhs = translateScalarRex(rhs_op);
1036  }
1037  CHECK(rhs);
1038 
1039  // Pass in executor to get string proxy info if cast needed between
1040  // string columns
1041  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs, executor_);
1042  }
1043  return lhs;
1044 }
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:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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:372
Definition: sqldefs.h:40
#define CHECK_GT(x, y)
Definition: Logger.h:305
SQLOps getOperator() const
Definition: RelAlgDag.h:282
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > getQuantifiedRhs(const RexScalar *) const
Definition: sqldefs.h:39
Definition: sqldefs.h:71
std::shared_ptr< Analyzer::Expr > translateOverlapsOper(const RexOperator *) const
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::translateOverlapsOper ( const RexOperator rex_operator) const
private

Definition at line 1046 of file RelAlgTranslator.cpp.

References CHECK, RexOperator::getOperand(), RexOperator::getOperator(), kOVERLAPS, translateGeoOverlapsOper(), and translateScalarRex().

Referenced by translateOper().

1047  {
1048  const auto sql_op = rex_operator->getOperator();
1049  CHECK(sql_op == kOVERLAPS);
1050 
1051  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
1052  const auto lhs_ti = lhs->get_type_info();
1053  if (lhs_ti.is_geometry()) {
1054  return translateGeoOverlapsOper(rex_operator);
1055  } else {
1056  throw std::runtime_error(
1057  "Overlaps equivalence is currently only supported for geospatial types");
1058  }
1059 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
std::shared_ptr< Analyzer::Expr > translateGeoOverlapsOper(const RexOperator *) const
SQLOps getOperator() const
Definition: RelAlgDag.h:282
#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::translateRegexp ( const RexFunctionOperator rex_function) const
private

Definition at line 1137 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1138  {
1139  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1140  const auto arg = translateScalarRex(rex_function->getOperand(0));
1141  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1142  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1143  throw std::runtime_error("The matching pattern must be a literal.");
1144  }
1145  const auto escape = (rex_function->size() == 3)
1146  ? translateScalarRex(rex_function->getOperand(2))
1147  : nullptr;
1148  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1149 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
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:790
#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 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 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 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 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 211 of file RelAlgTranslator.cpp.

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