OmniSciDB  085a039ca4
 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 (const Catalog_Namespace::Catalog &cat, 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::ExprtranslateScalarRex (const RexScalar *rex) const
 
bool generated_geos_ops ()
 

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::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
 
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::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
 

Private Attributes

const Catalog_Namespace::Catalogcat_
 
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_
 

Detailed Description

Definition at line 47 of file RelAlgTranslator.h.

Constructor & Destructor Documentation

RelAlgTranslator::RelAlgTranslator ( const Catalog_Namespace::Catalog cat,
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 49 of file RelAlgTranslator.h.

56  : cat_(cat)
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_
const Catalog_Namespace::Catalog & cat_

Member Function Documentation

bool RelAlgTranslator::generated_geos_ops ( )
inline

Definition at line 73 of file RelAlgTranslator.h.

References generated_geos_ops_.

73 { 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 812 of file RelAlgTranslator.cpp.

References threading_serial::async(), result_set::can_use_parallel_algorithms(), cat_, 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::Catalog::getDatabaseId(), Catalog_Namespace::Catalog::getStringDictionaryHosts(), inline_int_null_val(), and kENCODING_DICT.

Referenced by translateInOper().

814  {
816  return nullptr;
817  }
818  std::vector<int64_t> value_exprs;
819  const size_t fetcher_count = cpu_threads();
820  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
821  std::vector<std::future<void>> fetcher_threads;
822  const auto& arg_type = arg->get_type_info();
823  const auto entry_count = val_set.entryCount();
824  CHECK_EQ(size_t(1), val_set.colCount());
825  const auto& col_type = val_set.getColType(0);
826  if (g_cluster && arg_type.is_string() &&
827  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
828  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
829  return nullptr;
830  }
831  std::atomic<size_t> total_in_vals_count{0};
832  for (size_t i = 0,
833  start_entry = 0,
834  stride = (entry_count + fetcher_count - 1) / fetcher_count;
835  i < fetcher_count && start_entry < entry_count;
836  ++i, start_entry += stride) {
837  expr_set[i].reserve(entry_count / fetcher_count);
838  const auto end_entry = std::min(start_entry + stride, entry_count);
839  if (arg_type.is_string()) {
840  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
841  // const int32_t dest_dict_id = arg_type.get_comp_param();
842  // const int32_t source_dict_id = col_type.get_comp_param();
843  const DictRef dest_dict_ref(arg_type.get_comp_param(), cat_.getDatabaseId());
844  const DictRef source_dict_ref(col_type.get_comp_param(), cat_.getDatabaseId());
845  const auto dd = executor_->getStringDictionaryProxy(
846  arg_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
847  const auto sd = executor_->getStringDictionaryProxy(
848  col_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
849  CHECK(sd);
850  const auto needle_null_val = inline_int_null_val(arg_type);
851  fetcher_threads.push_back(std::async(
853  [this,
854  &val_set,
855  &total_in_vals_count,
856  sd,
857  dd,
858  source_dict_ref,
859  dest_dict_ref,
860  needle_null_val](
861  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
862  if (g_cluster) {
863  CHECK_GE(dd->getGeneration(), 0);
865  total_in_vals_count,
866  &val_set,
867  {start, end},
869  source_dict_ref,
870  dest_dict_ref,
871  dd->getGeneration(),
872  needle_null_val);
873  } else {
875  total_in_vals_count,
876  &val_set,
877  {start, end},
878  sd,
879  dd,
880  needle_null_val);
881  }
882  },
883  std::ref(expr_set[i]),
884  start_entry,
885  end_entry));
886  } else {
887  CHECK(arg_type.is_integer());
888  fetcher_threads.push_back(std::async(
890  [&val_set, &total_in_vals_count](
891  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
892  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
893  },
894  std::ref(expr_set[i]),
895  start_entry,
896  end_entry));
897  }
898  }
899  for (auto& child : fetcher_threads) {
900  child.get();
901  }
902 
903  val_set.moveToBegin();
904  value_exprs.reserve(entry_count);
905  for (auto& exprs : expr_set) {
906  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
907  }
908  return makeExpr<Analyzer::InIntegerSet>(
909  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
910 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
const Executor * executor_
#define CHECK_GE(x, y)
Definition: Logger.h:236
future< Result > async(Fn &&fn, Args &&...args)
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)
int getDatabaseId() const
Definition: Catalog.h:284
const std::vector< LeafHostInfo > & getStringDictionaryHosts() const
Definition: Catalog.cpp:1709
#define CHECK(condition)
Definition: Logger.h:223
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool g_cluster
int cpu_threads()
Definition: thread_count.h:24
bool can_use_parallel_algorithms(const ResultSet &rows)
Definition: ResultSet.cpp:1449
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)
const Catalog_Namespace::Catalog & cat_

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

1458  {
1459  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1460  expr_list;
1461  CHECK_EQ(size_t(1), rex_function->size());
1462  const auto operand = translateScalarRex(rex_function->getOperand(0));
1463  const auto& operand_ti = operand->get_type_info();
1464  CHECK(operand_ti.is_number());
1465  const auto zero = makeNumericConstant(operand_ti, 0);
1466  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1467  const auto uminus_operand =
1468  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1469  expr_list.emplace_back(lt_zero, uminus_operand);
1470  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1471 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:223
Definition: sqldefs.h:33

+ 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 227 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, kDOUBLE, kINT, RexAgg::size(), and ThriftSerializers::takes_arg().

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

229  {
230  SQLAgg agg_kind = rex->getKind();
231  const bool is_distinct = rex->isDistinct();
232  const bool takes_arg{rex->size() > 0};
233  std::shared_ptr<Analyzer::Expr> arg_expr;
234  std::shared_ptr<Analyzer::Constant> arg1; // 2nd aggregate parameter
235  if (takes_arg) {
236  const auto operand = rex->getOperand(0);
237  CHECK_LT(operand, scalar_sources.size());
238  CHECK_LE(rex->size(), 2u);
239  arg_expr = scalar_sources[operand];
240  if (agg_kind == kAPPROX_COUNT_DISTINCT && rex->size() == 2) {
241  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
242  scalar_sources[rex->getOperand(1)]);
243  if (!arg1 || arg1->get_type_info().get_type() != kINT ||
244  arg1->get_constval().intval < 1 || arg1->get_constval().intval > 100) {
245  throw std::runtime_error(
246  "APPROX_COUNT_DISTINCT's second parameter should be SMALLINT literal between "
247  "1 and 100");
248  }
249  } else if (agg_kind == kAPPROX_QUANTILE) {
250  if (g_cluster) {
251  throw std::runtime_error(
252  "APPROX_PERCENTILE/MEDIAN is not supported in distributed mode at this "
253  "time.");
254  }
255  // If second parameter is not given then APPROX_MEDIAN is assumed.
256  if (rex->size() == 2) {
257  arg1 = std::dynamic_pointer_cast<Analyzer::Constant>(
258  std::dynamic_pointer_cast<Analyzer::Constant>(
259  scalar_sources[rex->getOperand(1)])
260  ->add_cast(SQLTypeInfo(kDOUBLE)));
261  } else {
262 #ifdef _WIN32
263  Datum median;
264  median.doubleval = 0.5;
265 #else
266  constexpr Datum median{.doubleval = 0.5};
267 #endif
268  arg1 = std::make_shared<Analyzer::Constant>(kDOUBLE, false, median);
269  }
270  }
271  const auto& arg_ti = arg_expr->get_type_info();
272  if (!is_agg_supported_for_type(agg_kind, arg_ti)) {
273  throw std::runtime_error("Aggregate on " + arg_ti.get_type_name() +
274  " is not supported yet.");
275  }
276  }
277  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
278  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, arg1);
279 }
SQLAgg
Definition: sqldefs.h:73
SQLAgg getKind() const
size_t getOperand(size_t idx) const
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:233
#define CHECK_LE(x, y)
Definition: Logger.h:234
bool takes_arg(const TargetInfo &target_info)
bool isDistinct() const
size_t size() const
bool g_cluster
Definition: sqltypes.h:45
bool is_distinct(const size_t input_idx, const RelAlgNode *node)
double doubleval
Definition: sqltypes.h:217

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

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

Referenced by translateFunction().

1500  {
1501  if (rex_function->getType().get_subtype() == kNULLT) {
1502  auto sql_type = rex_function->getType();
1503  CHECK(sql_type.get_type() == kARRAY);
1504 
1505  // FIX-ME: Deal with NULL arrays
1506  auto translated_function_args(translateFunctionArgs(rex_function));
1507  if (translated_function_args.size() > 0) {
1508  const auto first_element_logical_type =
1509  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1510 
1511  auto diff_elem_itr =
1512  std::find_if(translated_function_args.begin(),
1513  translated_function_args.end(),
1514  [first_element_logical_type](const auto expr) {
1515  return first_element_logical_type !=
1516  get_nullable_logical_type_info(expr->get_type_info());
1517  });
1518  if (diff_elem_itr != translated_function_args.end()) {
1519  throw std::runtime_error(
1520  "Element " +
1521  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1522  " is not of the same type as other elements of the array. Consider casting "
1523  "to force this condition.\nElement Type: " +
1524  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1525  .to_string() +
1526  "\nArray type: " + first_element_logical_type.to_string());
1527  }
1528 
1529  if (first_element_logical_type.is_string() &&
1530  !first_element_logical_type.is_dict_encoded_string()) {
1531  sql_type.set_subtype(first_element_logical_type.get_type());
1532  sql_type.set_compression(kENCODING_FIXED);
1533  } else if (first_element_logical_type.is_dict_encoded_string()) {
1534  sql_type.set_subtype(first_element_logical_type.get_type());
1535  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1536  } else {
1537  sql_type.set_subtype(first_element_logical_type.get_type());
1538  sql_type.set_scale(first_element_logical_type.get_scale());
1539  sql_type.set_precision(first_element_logical_type.get_precision());
1540  }
1541 
1542  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1543  } else {
1544  // defaulting to valid sub-type for convenience
1545  sql_type.set_subtype(kBOOLEAN);
1546  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1547  }
1548  } else {
1549  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1550  translateFunctionArgs(rex_function));
1551  }
1552 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1108
const SQLTypeInfo & getType() const
std::string to_string(char const *&&v)
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:259
#define CHECK(condition)
Definition: Logger.h:223

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

References func_resolve, SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), RexFunctionOperator::getName(), RexOperator::getOperand(), Geospatial::GeoBase::kBUFFER, 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().

909  {
910 #ifndef ENABLE_GEOS
911  throw QueryNotSupported(rex_function->getName() +
912  " geo constructor requires enabled GEOS support");
913 #endif
915  if (rex_function->getName() == "ST_Difference"sv) {
917  } else if (rex_function->getName() == "ST_Union"sv) {
919  } else if (rex_function->getName() == "ST_Buffer"sv) {
921  }
922 
925  SQLTypeInfo arg0_ti;
926  SQLTypeInfo arg1_ti;
927  if (func_resolve(rex_function->getName(),
928  "ST_Intersection"sv,
929  "ST_Difference"sv,
930  "ST_Union"sv,
931  "ST_Buffer"sv)) {
932  // First arg: geometry
933  geoargs0 = translateGeoFunctionArg(rex_function->getOperand(0),
934  arg0_ti,
935  false,
936  false,
937  true,
938  true,
939  false,
940  false,
941  /* allow_gdal_transforms = */ true);
942  }
943  if (func_resolve(rex_function->getName(),
944  "ST_Intersection"sv,
945  "ST_Difference"sv,
946  "ST_Union"sv)) {
947  // Second arg: geometry
948  geoargs1 = translateGeoFunctionArg(rex_function->getOperand(1),
949  arg1_ti,
950  false,
951  false,
952  true,
953  true,
954  false,
955  false,
956  /* allow_gdal_transforms = */ true);
957  if (arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
958  throw QueryNotSupported(rex_function->getName() +
959  " geo constructor requires arguments with matching srids");
960  }
961  } else if (func_resolve(rex_function->getName(), "ST_Buffer"sv)) {
962  // Second arg: double scalar
963  auto param_expr = translateScalarRex(rex_function->getOperand(1));
964  arg1_ti = SQLTypeInfo(kDOUBLE, false);
965  if (param_expr->get_type_info().get_type() != kDOUBLE) {
966  param_expr = param_expr->add_cast(arg1_ti);
967  }
968  geoargs1 = {param_expr};
969  }
970 
971  // Record the optional transform request that can be sent by an ecompassing TRANSFORM
972  auto srid = ti.get_output_srid();
973  // Build the typeinfo of the constructed geometry
974  SQLTypeInfo arg_ti = arg0_ti;
975  arg_ti.set_type(kMULTIPOLYGON);
976  arg_ti.set_subtype(kGEOMETRY);
977  arg_ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
978  arg_ti.set_comp_param(0);
979  arg_ti.set_input_srid(arg0_ti.get_output_srid());
980  if (srid > 0) {
981  if (arg_ti.get_input_srid() > 0) {
982  // Constructed geometry to be transformed to srid given by encompassing transform
983  arg_ti.set_output_srid(srid);
984  } else {
985  throw QueryNotSupported("Transform of geo constructor " + rex_function->getName() +
986  " requires its argument(s) to have a valid srid");
987  }
988  } else {
989  arg_ti.set_output_srid(arg_ti.get_input_srid()); // No encompassing transform
990  }
991  // If there was an output transform, it's now embedded into arg_ti and the geo operator.
992  // Now de-register the transform from the return typeinfo:
993  ti = arg_ti;
995  return makeExpr<Analyzer::GeoBinOper>(op, arg_ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
996 }
void set_compression(EncodingType c)
Definition: sqltypes.h:440
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
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:430
void set_input_srid(int d)
Definition: sqltypes.h:433
void set_output_srid(int s)
Definition: sqltypes.h:435
void set_comp_param(int p)
Definition: sqltypes.h:441
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:333
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:188
const std::string & getName() const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:335
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:429

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

1237  {
1238  auto function_name = rex_function->getName();
1239  auto return_type = rex_function->getType();
1240 
1241  if (function_name == "ST_Overlaps"sv) {
1242  // Overlaps join is the only implementation supported for now, only translate bounds
1243  CHECK_EQ(size_t(2), rex_function->size());
1244  auto extract_geo_bounds_from_input =
1245  [this, &rex_function](const size_t index) -> std::shared_ptr<Analyzer::Expr> {
1246  const auto rex_input =
1247  dynamic_cast<const RexInput*>(rex_function->getOperand(index));
1248  if (rex_input) {
1249  SQLTypeInfo ti;
1250  const auto exprs = translateGeoColumn(rex_input, ti, true, false, false);
1251  CHECK_GT(exprs.size(), size_t(0));
1252  if (ti.get_type() == kPOINT) {
1253  throw std::runtime_error("ST_Overlaps is not supported for point arguments.");
1254  } else {
1255  return exprs.back();
1256  }
1257  } else {
1258  throw std::runtime_error(
1259  "Only inputs are supported as arguments to ST_Overlaps for now.");
1260  }
1261  };
1262  std::vector<std::shared_ptr<Analyzer::Expr>> geo_args;
1263  geo_args.push_back(extract_geo_bounds_from_input(0));
1264  geo_args.push_back(extract_geo_bounds_from_input(1));
1265 
1266  return makeExpr<Analyzer::FunctionOper>(return_type, function_name, geo_args);
1267  }
1268 
1269  if (function_name == "ST_Distance"sv || function_name == "ST_MaxDistance"sv) {
1270  CHECK_EQ(size_t(2), rex_function->size());
1271  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1272  int legacy_transform_srid = 0;
1273  for (size_t i = 0; i < rex_function->size(); i++) {
1274  SQLTypeInfo arg0_ti; // discard
1275  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(i),
1276  arg0_ti,
1277  /*with_bounds=*/false, // TODO
1278  /*with_render_group=*/false,
1279  /*expand_geo_col=*/false,
1280  /*is_projection = */ false,
1281  /*use_geo_expressions=*/true);
1282  if (arg0_ti.get_input_srid() != arg0_ti.get_output_srid() &&
1283  arg0_ti.get_output_srid() > 0 &&
1284  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
1285  // legacy transform
1286  CHECK(legacy_transform_srid == 0 ||
1287  legacy_transform_srid == arg0_ti.get_output_srid());
1288  legacy_transform_srid = arg0_ti.get_output_srid();
1289  }
1290  args.insert(args.end(), geoargs.begin(), geoargs.end());
1291  }
1292  return makeExpr<Analyzer::GeoOperator>(
1293  SQLTypeInfo(kDOUBLE, /*not_null=*/false),
1294  function_name,
1295  args,
1296  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1297  : std::nullopt);
1298  }
1299 
1300  bool swap_args = false;
1301  bool with_bounds = false;
1302  bool negate_result = false;
1303  Analyzer::ExpressionPtr threshold_expr = nullptr;
1304  Analyzer::ExpressionPtr compare_expr = nullptr;
1305  if (function_name == "ST_DWithin"sv) {
1306  CHECK_EQ(size_t(3), rex_function->size());
1307  function_name = "ST_Distance";
1308  return_type = SQLTypeInfo(kDOUBLE, false);
1309  // Inject ST_DWithin's short-circuiting threshold into ST_MaxDistance
1310  threshold_expr = translateScalarRex(rex_function->getOperand(2));
1311  } else if (function_name == "ST_Equals"sv) {
1312  // Translate ST_Equals(g1,g2) to ST_Distance(g1,g2)<=0.0
1313  CHECK_EQ(size_t(2), rex_function->size());
1314  function_name = "ST_Distance";
1315  return_type = SQLTypeInfo(kDOUBLE, false);
1316  threshold_expr = nullptr;
1317  Datum d;
1318  d.doubleval = 0.0;
1319  compare_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1320  } else if (function_name == "ST_DFullyWithin"sv) {
1321  CHECK_EQ(size_t(3), rex_function->size());
1322  function_name = "ST_MaxDistance";
1323  return_type = SQLTypeInfo(kDOUBLE, false);
1324  // TODO: inject ST_DFullyWithin's short-circuiting threshold into ST_MaxDistance
1325  threshold_expr = nullptr;
1326  } else if (function_name == "ST_Distance"sv) {
1327  // TODO: pick up an outside short-circuiting threshold and inject into ST_Distance
1328  threshold_expr = nullptr;
1329  } else if (function_name == "ST_MaxDistance"sv) {
1330  // TODO: pick up an outside short-circuiting threshold and inject into
1331  // ST_MaxDistance
1332  threshold_expr = nullptr;
1333  } else {
1334  CHECK_EQ(size_t(2), rex_function->size());
1335  }
1336  if (function_name == "ST_Within"sv) {
1337  function_name = "ST_Contains";
1338  swap_args = true;
1339  } else if (function_name == "ST_Disjoint"sv) {
1340  function_name = "ST_Intersects";
1341  negate_result = true;
1342  }
1343  if (func_resolve(
1344  function_name, "ST_Contains"sv, "ST_Intersects"sv, "ST_Approx_Overlaps"sv)) {
1345  with_bounds = true;
1346  }
1347 
1348  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1349  SQLTypeInfo arg0_ti;
1350  SQLTypeInfo arg1_ti;
1351 
1352  // Proactively try to compress the first arg of ST_Intersects to preempt arg swap
1353  bool try_to_compress_arg0 = g_enable_geo_ops_on_uncompressed_coords &&
1354  func_resolve(function_name, "ST_Intersects"sv);
1355 
1356  auto geoargs0 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 1 : 0),
1357  arg0_ti,
1358  with_bounds,
1359  false,
1360  false,
1361  false,
1362  false,
1363  try_to_compress_arg0);
1364  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1365 
1366  // If first arg is compressed, try to compress the second one to be able to
1367  // switch to faster implementations working directly on uncompressed coords
1368  bool try_to_compress_arg1 =
1370  func_resolve(function_name, "ST_Contains"sv, "ST_Intersects"sv) &&
1371  arg0_ti.get_compression() == kENCODING_GEOINT &&
1372  arg0_ti.get_output_srid() == 4326);
1373 
1374  auto geoargs1 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 0 : 1),
1375  arg1_ti,
1376  with_bounds,
1377  false,
1378  false,
1379  false,
1380  false,
1381  try_to_compress_arg1);
1382  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1383 
1384  if (arg0_ti.get_subtype() != kNULLT && arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1385  throw QueryNotSupported(rex_function->getName() +
1386  " accepts either two GEOGRAPHY or two GEOMETRY arguments");
1387  }
1388  // Check SRID match if at least one is set/valid
1389  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1390  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1391  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1392  }
1393  if (compare_expr) {
1394  // We could fold the check to false here if argument geo types are different, e.g.
1395  // POLYGON vs POINT. However, tiny POLYGON could be "spatially" equal to a POINT.
1396  if (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT) {
1397  // ST_Equals is translated to a simple distance check for POINTs,
1398  // otherwise geometries are passed to GEOS's Equals
1399  return nullptr;
1400  }
1401  // Look at POINT compression modes.
1402  if (arg0_ti.get_compression() != arg1_ti.get_compression()) {
1403  if ((arg0_ti.get_compression() == kENCODING_GEOINT &&
1404  arg0_ti.get_comp_param() == 32 &&
1405  arg1_ti.get_compression() == kENCODING_NONE) ||
1406  (arg0_ti.get_compression() == kENCODING_NONE &&
1407  arg1_ti.get_compression() == kENCODING_GEOINT &&
1408  arg0_ti.get_comp_param() == 32)) {
1409  // Spatial equality comparison of a compressed point vs uncompressed point.
1410  // Introduce tolerance into distance calculation and comparison, translate
1411  // ST_Equals(g1,g2) to ST_Distance(g1,g2,thereshold=tolerance)<=tolerance
1412  Datum tolerance;
1413  // Tolerance representing 0.44" to cover shifts due to GEOINT(32) compression
1414  tolerance.doubleval = TOLERANCE_GEOINT32;
1415  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, tolerance);
1416  compare_expr = threshold_expr;
1417  } else {
1418  throw QueryNotSupported(
1419  rex_function->getName() +
1420  " unable to calculate compression tolerance for arguments");
1421  }
1422  }
1423  }
1424 
1425  auto can_use_compressed_coords = [](const SQLTypeInfo& i0_ti,
1426  const Analyzer::ExpressionPtrVector& i0_operands,
1427  const SQLTypeInfo& i1_ti,
1428  const Analyzer::ExpressionPtrVector& i1_operands) {
1429  const bool i0_is_poly =
1430  i0_ti.get_type() == kPOLYGON || i0_ti.get_type() == kMULTIPOLYGON;
1431  const bool i1_is_point = i1_ti.get_type() == kPOINT;
1432  const bool i1_is_literal =
1433  i1_operands.size() == 1 && std::dynamic_pointer_cast<const Analyzer::Constant>(
1434  i1_operands.front()) != nullptr;
1435  return (i0_is_poly && !i1_is_literal && i1_is_point &&
1436  i0_ti.get_compression() == kENCODING_GEOINT &&
1437  i0_ti.get_input_srid() == i0_ti.get_output_srid() &&
1438  i0_ti.get_compression() == i1_ti.get_compression() &&
1439  i1_ti.get_input_srid() == i1_ti.get_output_srid());
1440  };
1441  if (g_enable_geo_ops_on_uncompressed_coords && function_name == "ST_Contains"sv) {
1442  if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1443  // Switch to Contains implementation working directly on uncompressed coords
1444  function_name = "ST_cContains";
1445  }
1446  }
1447  if (g_enable_geo_ops_on_uncompressed_coords && function_name == "ST_Intersects"sv) {
1448  if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1449  // Switch to Intersects implementation working directly on uncompressed coords
1450  function_name = "ST_cIntersects";
1451  } else if (can_use_compressed_coords(arg1_ti, geoargs1, arg0_ti, geoargs0)) {
1452  // Switch to Intersects implementation working on uncompressed coords, swapped args
1453  function_name = "ST_cIntersects";
1454  geoargs.clear();
1455  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1456  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1457  auto tmp_ti = arg0_ti;
1458  arg0_ti = arg1_ti;
1459  arg1_ti = tmp_ti;
1460  }
1461  }
1462 
1463  std::string specialized_geofunc{function_name + suffix(arg0_ti.get_type()) +
1464  suffix(arg1_ti.get_type())};
1465 
1466  if (arg0_ti.get_subtype() == kGEOGRAPHY && arg0_ti.get_output_srid() == 4326) {
1467  // Need to call geodesic runtime functions
1468  if (function_name == "ST_Distance"sv) {
1469  if ((arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) ||
1470  (arg0_ti.get_type() == kLINESTRING && arg1_ti.get_type() == kPOINT) ||
1471  (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kLINESTRING)) {
1472  // Geodesic distance between points
1473  specialized_geofunc += "_Geodesic"s;
1474  } else {
1475  throw QueryNotSupported(function_name +
1476  " currently doesn't accept non-POINT geographies");
1477  }
1478  } else if (rex_function->getName() == "ST_Contains"sv) {
1479  // We currently don't have a geodesic implementation of ST_Contains,
1480  // allowing calls to a [less precise] cartesian implementation.
1481  } else {
1482  throw QueryNotSupported(function_name + " doesn't accept geographies");
1483  }
1484  } else if (function_name == "ST_Distance"sv && rex_function->size() == 3) {
1485  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1486  // Cartesian distance between points used by ST_DWithin - switch to faster Squared
1487  specialized_geofunc += "_Squared"s;
1488  }
1489  }
1490 
1491  // Add first input's compression mode and SRID args to enable on-the-fly
1492  // decompression/transforms
1493  Datum input_compression0;
1494  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1495  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1496  Datum input_srid0;
1497  input_srid0.intval = arg0_ti.get_input_srid();
1498  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1499 
1500  // Add second input's compression mode and SRID args to enable on-the-fly
1501  // decompression/transforms
1502  Datum input_compression1;
1503  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1504  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1505  Datum input_srid1;
1506  input_srid1.intval = arg1_ti.get_input_srid();
1507  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1508 
1509  // Add output SRID arg to enable on-the-fly transforms
1510  Datum output_srid;
1511  output_srid.intval = arg0_ti.get_output_srid();
1512  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1513 
1514  // Some geo distance functions will be injected with a short-circuit threshold.
1515  // Threshold value would come from Geo comparison operations or from other outer
1516  // geo operations, e.g. ST_DWithin
1517  // At this point, only ST_Distance_LineString_LineString requires a threshold arg.
1518  // TODO: Other combinations that involve LINESTRING, POLYGON and MULTIPOLYGON args
1519  // TODO: Inject threshold into ST_MaxDistance
1520  if (function_name == "ST_Distance"sv && arg0_ti.get_subtype() != kGEOGRAPHY &&
1521  (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT)) {
1522  if (threshold_expr) {
1523  if (threshold_expr->get_type_info().get_type() != kDOUBLE) {
1524  const auto& threshold_ti = SQLTypeInfo(kDOUBLE, false);
1525  threshold_expr = threshold_expr->add_cast(threshold_ti);
1526  }
1527  threshold_expr = fold_expr(threshold_expr.get());
1528  } else {
1529  Datum d;
1530  d.doubleval = 0.0;
1531  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1532  }
1533  geoargs.push_back(threshold_expr);
1534  }
1535 
1536  auto result =
1537  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1538  if (negate_result) {
1539  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, result);
1540  }
1541  if (compare_expr) {
1542  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, result, compare_expr);
1543  }
1544  return result;
1545 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
Definition: Logger.h:231
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
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:35
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
std::shared_ptr< Analyzer::Expr > ExpressionPtr
Definition: Analyzer.h:186
bool g_enable_geo_ops_on_uncompressed_coords
Definition: Execute.cpp:114
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
#define CHECK_GT(x, y)
Definition: Logger.h:235
int32_t intval
Definition: sqltypes.h:214
#define TOLERANCE_GEOINT32
std::string suffix(SQLTypes type)
Definition: Codegen.cpp:68
Definition: sqldefs.h:71
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:337
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:338
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:333
#define CHECK(condition)
Definition: Logger.h:223
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:188
Definition: sqltypes.h:45
const std::string & getName() 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
Definition: sqldefs.h:39
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
double doubleval
Definition: sqltypes.h:217
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:335

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

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

Referenced by translateFunction(), and translateGeoFunctionArg().

1019  {
1020  if (rex_function->getName() != "ST_Equals"sv) {
1021  throw QueryNotSupported(rex_function->getName() + " geo predicate is not supported");
1022  }
1023 #ifndef ENABLE_GEOS
1024  throw QueryNotSupported(rex_function->getName() +
1025  " geo predicate requires enabled GEOS support");
1026 #endif
1027  SQLTypeInfo arg0_ti;
1028  auto geoargs0 = translateGeoFunctionArg(
1029  rex_function->getOperand(0), arg0_ti, false, false, true, true);
1030  SQLTypeInfo arg1_ti;
1031  auto geoargs1 = translateGeoFunctionArg(
1032  rex_function->getOperand(1), arg1_ti, false, false, true, true);
1033  ti = SQLTypeInfo(kBOOLEAN, false);
1035  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1036 }
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
const std::string & getName() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1387 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1388  {
1389  const auto ret_ti = rex_function->getType();
1390  const auto arg = translateScalarRex(rex_function->getOperand(0));
1391  const auto arg_ti = arg->get_type_info();
1392  if (!arg_ti.is_array()) {
1393  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1394  }
1395  if (arg_ti.get_subtype() == kARRAY) {
1396  throw std::runtime_error(rex_function->getName() +
1397  " expects one-dimension array expression.");
1398  }
1399  const auto array_size = arg_ti.get_size();
1400  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1401 
1402  if (array_size > 0) {
1403  if (array_elem_size <= 0) {
1404  throw std::runtime_error(rex_function->getName() +
1405  ": unexpected array element type.");
1406  }
1407  // Return cardinality of a fixed length array
1408  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1409  }
1410  // Variable length array cardinality will be calculated at runtime
1411  return makeExpr<Analyzer::CardinalityExpr>(arg);
1412 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
const RexScalar * getOperand(const size_t idx) const
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
const std::string & getName() const

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

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

Referenced by translateScalarRex().

970  {
971  std::shared_ptr<Analyzer::Expr> else_expr;
972  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
973  expr_list;
974  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
975  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
976  const auto then_expr = translateScalarRex(rex_case->getThen(i));
977  expr_list.emplace_back(when_expr, then_expr);
978  }
979  if (rex_case->getElse()) {
980  else_expr = translateScalarRex(rex_case->getElse());
981  }
982  return Parser::CaseExpr::normalize(expr_list, else_expr, executor_);
983 }
const RexScalar * getThen(const size_t idx) const
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
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getWhen(const size_t idx) const
size_t branchCount() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1423 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1423  {
1424  constexpr bool is_null = false;
1425  Datum datum;
1426  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1427  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1428 }
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: sqltypes.h:215
Definition: sqltypes.h:53

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

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

Referenced by translateFunction().

1430  {
1431  constexpr bool is_null = false;
1432  Datum datum;
1433  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1434  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1435 }
Definition: sqltypes.h:49
CONSTEXPR DEVICE bool is_null(const T &value)
int64_t bigintval
Definition: sqltypes.h:215

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

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

Referenced by translateDatetime(), and translateFunction().

1437  {
1439 }
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 1314 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1315  {
1316  std::string user{"SESSIONLESS_USER"};
1317  if (query_state_) {
1318  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1319  }
1320  return Parser::UserLiteral::get(user);
1321 }
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 1143 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().

1144  {
1145  CHECK_EQ(size_t(3), rex_function->size());
1146  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1147  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1149  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1150  const auto number_units_const =
1151  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1152  if (number_units_const && number_units_const->get_is_null()) {
1153  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1154  }
1155  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1156  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1157  const auto& datetime_ti = datetime->get_type_info();
1158  if (datetime_ti.get_type() == kTIME) {
1159  throw std::runtime_error("DateAdd operation not supported for TIME.");
1160  }
1161  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1162  const int dim = datetime_ti.get_dimension();
1163  return makeExpr<Analyzer::DateaddExpr>(
1164  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1165 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
Definition: sqltypes.h:49
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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 1258 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().

1259  {
1260  CHECK_EQ(size_t(3), rex_function->size());
1261  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1262  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1264  const auto start = translateScalarRex(rex_function->getOperand(1));
1265  const auto end = translateScalarRex(rex_function->getOperand(2));
1266  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1267  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1268 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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 1270 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().

1271  {
1272  CHECK_EQ(size_t(2), rex_function->size());
1273  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1274  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1276  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1277  return ExtractExpr::generate(
1278  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1279 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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 1176 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().

1177  {
1178  if (rex_operator->size() != 2) {
1179  return nullptr;
1180  }
1181  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1182  const auto datetime_ti = datetime->get_type_info();
1183  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1184  if (datetime_ti.get_type() == kTIME) {
1185  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1186  }
1187  return nullptr;
1188  }
1189  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1190  const auto rhs_ti = rhs->get_type_info();
1191  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1192  if (datetime_ti.is_high_precision_timestamp() ||
1193  rhs_ti.is_high_precision_timestamp()) {
1194  throw std::runtime_error(
1195  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1196  "Use "
1197  "DATEDIFF.");
1198  }
1199  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1200  const auto& rex_operator_ti = rex_operator->getType();
1201  const auto datediff_field =
1202  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1203  auto result =
1204  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1205  // multiply 1000 to result since expected result should be in millisecond precision.
1206  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1207  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1208  kMULTIPLY,
1209  kONE,
1210  result,
1211  makeNumericConstant(bigint_ti, 1000));
1212  } else {
1213  return result;
1214  }
1215  }
1216  const auto op = rex_operator->getOperator();
1217  if (op == kPLUS) {
1218  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1219  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1220  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1221  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1222  if (date_trunc) {
1223  return date_trunc;
1224  }
1225  }
1226  const auto interval = fold_expr(rhs.get());
1227  auto interval_ti = interval->get_type_info();
1228  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1229  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1230  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1231  std::shared_ptr<Analyzer::Expr> interval_sec;
1232  if (interval_lit) {
1233  interval_sec =
1234  makeNumericConstant(bigint_ti,
1235  (op == kMINUS ? -interval_lit->get_constval().bigintval
1236  : interval_lit->get_constval().bigintval) /
1237  1000);
1238  } else {
1239  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1240  kDIVIDE,
1241  kONE,
1242  interval,
1243  makeNumericConstant(bigint_ti, 1000));
1244  if (op == kMINUS) {
1245  interval_sec =
1246  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1247  }
1248  }
1249  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1250  }
1251  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1252  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1253  bigint_ti, false, kUMINUS, interval)
1254  : interval;
1255  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1256 }
Definition: sqltypes.h:49
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:41
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
SQLOps getOperator() const
Definition: sqltypes.h:53
Definition: sqldefs.h:40
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:223
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 1441 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1442  {
1443  CHECK_EQ(size_t(1), rex_function->size());
1444  const auto arg = translateScalarRex(rex_function->getOperand(0));
1445  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1446  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1447  if (!arg_lit || arg_lit->get_is_null()) {
1448  throw std::runtime_error(datetime_err);
1449  }
1450  CHECK(arg_lit->get_type_info().is_string());
1451  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1452  throw std::runtime_error(datetime_err);
1453  }
1454  return translateCurrentTimestamp();
1455 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateCurrentTimestamp() const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:223

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

1085  {
1086  CHECK_EQ(size_t(2), rex_function->size());
1087  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1088  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1090  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1091  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1092  if (is_date_trunc) {
1093  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1094  } else {
1095  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1096  }
1097 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
const std::shared_ptr< Analyzer::Expr > generate() const
const std::string & getName() const
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 1554 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, bind_function(), CHECK, CHECK_EQ, ext_arg_type_to_type_info(), func_resolve, RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), SQLTypeInfo::is_decimal(), kDIVIDE, kONE, kSMALLINT, kTEXT, LOG, Parser::OperExpr::normalize(), 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(), translateUnaryGeoFunction(), translateUnaryGeoPredicate(), translateUnlikely(), translateWidthBucket(), and logger::WARNING.

Referenced by translateScalarRex().

1555  {
1556  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1557  return translateLike(rex_function);
1558  }
1559  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1560  return translateRegexp(rex_function);
1561  }
1562  if (rex_function->getName() == "LIKELY"sv) {
1563  return translateLikely(rex_function);
1564  }
1565  if (rex_function->getName() == "UNLIKELY"sv) {
1566  return translateUnlikely(rex_function);
1567  }
1568  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1569  return translateExtract(rex_function);
1570  }
1571  if (rex_function->getName() == "DATEADD"sv) {
1572  return translateDateadd(rex_function);
1573  }
1574  if (rex_function->getName() == "DATEDIFF"sv) {
1575  return translateDatediff(rex_function);
1576  }
1577  if (rex_function->getName() == "DATEPART"sv) {
1578  return translateDatepart(rex_function);
1579  }
1580  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1581  return translateLength(rex_function);
1582  }
1583  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1584  return translateKeyForString(rex_function);
1585  }
1586  if (rex_function->getName() == "WIDTH_BUCKET"sv) {
1587  return translateWidthBucket(rex_function);
1588  }
1589  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1590  return translateSampleRatio(rex_function);
1591  }
1592  if (rex_function->getName() == "CURRENT_USER"sv) {
1593  return translateCurrentUser(rex_function);
1594  }
1595  if (func_resolve(rex_function->getName(),
1596  "LOWER"sv,
1597  "UPPER"sv,
1598  "INITCAP"sv,
1599  "REVERSE"sv,
1600  "REPEAT"sv,
1601  "||"sv,
1602  "LPAD"sv,
1603  "RPAD"sv,
1604  "TRIM"sv,
1605  "LTRIM"sv,
1606  "RTRIM"sv,
1607  "SUBSTRING"sv,
1608  "OVERLAY"sv,
1609  "REPLACE"sv,
1610  "SPLIT_PART"sv,
1611  "REGEXP_REPLACE"sv,
1612  "REGEXP_SUBSTR"sv,
1613  "REGEXP_MATCH"sv)) {
1614  return translateStringOper(rex_function);
1615  }
1616  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1617  return translateCardinality(rex_function);
1618  }
1619  if (rex_function->getName() == "ITEM"sv) {
1620  return translateItem(rex_function);
1621  }
1622  if (rex_function->getName() == "CURRENT_DATE"sv) {
1623  return translateCurrentDate();
1624  }
1625  if (rex_function->getName() == "CURRENT_TIME"sv) {
1626  return translateCurrentTime();
1627  }
1628  if (rex_function->getName() == "CURRENT_TIMESTAMP"sv) {
1629  return translateCurrentTimestamp();
1630  }
1631  if (rex_function->getName() == "NOW"sv) {
1632  return translateCurrentTimestamp();
1633  }
1634  if (rex_function->getName() == "DATETIME"sv) {
1635  return translateDatetime(rex_function);
1636  }
1637  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1638  return translateHPTLiteral(rex_function);
1639  }
1640  if (rex_function->getName() == "ABS"sv) {
1641  return translateAbs(rex_function);
1642  }
1643  if (rex_function->getName() == "SIGN"sv) {
1644  return translateSign(rex_function);
1645  }
1646  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1647  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1648  rex_function->getType(),
1649  rex_function->getName(),
1650  translateFunctionArgs(rex_function));
1651  } else if (rex_function->getName() == "ROUND"sv) {
1652  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1653  translateFunctionArgs(rex_function);
1654 
1655  if (rex_function->size() == 1) {
1656  // push a 0 constant if 2nd operand is missing.
1657  // this needs to be done as calcite returns
1658  // only the 1st operand without defaulting the 2nd one
1659  // when the user did not specify the 2nd operand.
1660  SQLTypes t = kSMALLINT;
1661  Datum d;
1662  d.smallintval = 0;
1663  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1664  }
1665 
1666  // make sure we have only 2 operands
1667  CHECK(args.size() == 2);
1668 
1669  if (!args[0]->get_type_info().is_number()) {
1670  throw std::runtime_error("Only numeric 1st operands are supported");
1671  }
1672 
1673  // the 2nd operand does not need to be a constant
1674  // it can happily reference another integer column
1675  if (!args[1]->get_type_info().is_integer()) {
1676  throw std::runtime_error("Only integer 2nd operands are supported");
1677  }
1678 
1679  // Calcite may upcast decimals in a way that is
1680  // incompatible with the extension function input. Play it safe and stick with the
1681  // argument type instead.
1682  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1683  ? args[0]->get_type_info()
1684  : rex_function->getType();
1685 
1686  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1687  ret_ti, rex_function->getName(), args);
1688  }
1689  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1690  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1691  rex_function->getName(),
1692  translateFunctionArgs(rex_function));
1693  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1694  if (date_trunc) {
1695  return date_trunc;
1696  }
1697  return translateDateadd(rex_function);
1698  }
1699  if (rex_function->getName() == "/INT"sv) {
1700  CHECK_EQ(size_t(2), rex_function->size());
1701  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1702  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1703  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1704  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1705  }
1706  if (rex_function->getName() == "Reinterpret"sv) {
1707  CHECK_EQ(size_t(1), rex_function->size());
1708  return translateScalarRex(rex_function->getOperand(0));
1709  }
1710  if (func_resolve(rex_function->getName(),
1711  "ST_X"sv,
1712  "ST_Y"sv,
1713  "ST_XMin"sv,
1714  "ST_YMin"sv,
1715  "ST_XMax"sv,
1716  "ST_YMax"sv,
1717  "ST_NRings"sv,
1718  "ST_NPoints"sv,
1719  "ST_Length"sv,
1720  "ST_Perimeter"sv,
1721  "ST_Area"sv,
1722  "ST_SRID"sv,
1723  "HeavyDB_Geo_PolyBoundsPtr"sv,
1724  "HeavyDB_Geo_PolyRenderGroup"sv)) {
1725  CHECK_EQ(rex_function->size(), size_t(1));
1726  return translateUnaryGeoFunction(rex_function);
1727  }
1728  if (func_resolve(rex_function->getName(),
1729  "convert_meters_to_pixel_width"sv,
1730  "convert_meters_to_pixel_height"sv,
1731  "is_point_in_view"sv,
1732  "is_point_size_in_view"sv)) {
1733  return translateFunctionWithGeoArg(rex_function);
1734  }
1735  if (func_resolve(rex_function->getName(),
1736  "ST_Distance"sv,
1737  "ST_MaxDistance"sv,
1738  "ST_Intersects"sv,
1739  "ST_Disjoint"sv,
1740  "ST_Contains"sv,
1741  "ST_Overlaps"sv,
1742  "ST_Approx_Overlaps"sv,
1743  "ST_Within"sv)) {
1744  CHECK_EQ(rex_function->size(), size_t(2));
1745  return translateBinaryGeoFunction(rex_function);
1746  }
1747  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
1748  CHECK_EQ(rex_function->size(), size_t(3));
1749  return translateTernaryGeoFunction(rex_function);
1750  }
1751  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
1752  CHECK_EQ(size_t(0), rex_function->size());
1753  return translateOffsetInFragment();
1754  }
1755  if (rex_function->getName() == "ARRAY"sv) {
1756  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1757  return translateArrayFunction(rex_function);
1758  }
1759  if (func_resolve(rex_function->getName(),
1760  "ST_GeomFromText"sv,
1761  "ST_GeogFromText"sv,
1762  "ST_Centroid"sv,
1763  "ST_SetSRID"sv,
1764  "ST_Point"sv, // TODO: where should this and below live?
1765  "ST_PointN"sv,
1766  "ST_StartPoint"sv,
1767  "ST_EndPoint"sv,
1768  "ST_Transform"sv)) {
1769  SQLTypeInfo ti;
1770  return translateGeoProjection(rex_function, ti, false);
1771  }
1772  if (func_resolve(rex_function->getName(),
1773  "ST_Intersection"sv,
1774  "ST_Difference"sv,
1775  "ST_Union"sv,
1776  "ST_Buffer"sv)) {
1777  SQLTypeInfo ti;
1778  return translateBinaryGeoConstructor(rex_function, ti, false);
1779  }
1780  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
1781  CHECK_EQ(rex_function->size(), size_t(1));
1782  SQLTypeInfo ti;
1783  return translateUnaryGeoPredicate(rex_function, ti, false);
1784  }
1785  if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
1786  CHECK_EQ(rex_function->size(), size_t(2));
1787  // Attempt to generate a distance based check for points
1788  if (auto distance_check = translateBinaryGeoFunction(rex_function)) {
1789  return distance_check;
1790  }
1791  SQLTypeInfo ti;
1792  return translateBinaryGeoPredicate(rex_function, ti, false);
1793  }
1794 
1795  auto arg_expr_list = translateFunctionArgs(rex_function);
1796  if (rex_function->getName() == std::string("||") ||
1797  rex_function->getName() == std::string("SUBSTRING")) {
1798  SQLTypeInfo ret_ti(kTEXT, false);
1799  return makeExpr<Analyzer::FunctionOper>(
1800  ret_ti, rex_function->getName(), arg_expr_list);
1801  }
1802  // Reset possibly wrong return type of rex_function to the return
1803  // type of the optimal valid implementation. The return type can be
1804  // wrong in the case of multiple implementations of UDF functions
1805  // that have different return types but Calcite specifies the return
1806  // type according to the first implementation.
1807  SQLTypeInfo ret_ti;
1808  try {
1809  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1810 
1811  auto ext_func_args = ext_func_sig.getArgs();
1812  CHECK_EQ(arg_expr_list.size(), ext_func_args.size());
1813  for (size_t i = 0; i < arg_expr_list.size(); i++) {
1814  // fold casts on constants
1815  if (auto constant =
1816  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
1817  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_args[i]);
1818  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
1819  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
1820  }
1821  }
1822  }
1823 
1824  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
1825  } catch (ExtensionFunctionBindingError& e) {
1826  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
1827  throw;
1828  }
1829 
1830  // By default, the extension function type will not allow nulls. If one of the arguments
1831  // is nullable, the extension function must also explicitly allow nulls.
1832  bool arguments_not_null = true;
1833  for (const auto& arg_expr : arg_expr_list) {
1834  if (!arg_expr->get_type_info().get_notnull()) {
1835  arguments_not_null = false;
1836  break;
1837  }
1838  }
1839  ret_ti.set_notnull(arguments_not_null);
1840 
1841  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
1842 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
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:38
std::shared_ptr< Analyzer::Expr > translateUnlikely(const RexFunctionOperator *) const
#define LOG(tag)
Definition: Logger.h:217
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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:371
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: sqltypes.h:213
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)
Definition: sqltypes.h:52
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
Definition: sqldefs.h:71
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:436
#define CHECK(condition)
Definition: Logger.h:223
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
std::shared_ptr< Analyzer::Expr > translateCurrentDate() const
std::shared_ptr< Analyzer::Expr > translateCardinality(const RexFunctionOperator *) const
bool is_decimal() const
Definition: sqltypes.h:513
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:

+ Here is the caller graph for this function:

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

Definition at line 1923 of file RelAlgTranslator.cpp.

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

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

1924  {
1925  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1926  for (size_t i = 0; i < rex_function->size(); ++i) {
1927  args.push_back(translateScalarRex(rex_function->getOperand(i)));
1928  }
1929  return args;
1930 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const

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

1674  {
1675  std::string specialized_geofunc{rex_function->getName()};
1676  if (func_resolve(rex_function->getName(),
1677  "convert_meters_to_pixel_width"sv,
1678  "convert_meters_to_pixel_height"sv)) {
1679  CHECK_EQ(rex_function->size(), 6u);
1680  SQLTypeInfo arg_ti;
1681  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1682  args.push_back(translateScalarRex(rex_function->getOperand(0)));
1683  auto geoargs =
1684  translateGeoFunctionArg(rex_function->getOperand(1), arg_ti, false, true, false);
1685  // only works on points
1686  if (arg_ti.get_type() != kPOINT) {
1687  throw QueryNotSupported(rex_function->getName() +
1688  " expects a point for the second argument");
1689  }
1690 
1691  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1692 
1693  // Add compression information
1694  Datum input_compression;
1695  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1696  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1697  if (arg_ti.get_input_srid() != 4326) {
1698  throw QueryNotSupported(
1699  rex_function->getName() +
1700  " currently only supports points of with SRID WGS84/EPSG:4326");
1701  }
1702  Datum input_srid;
1703  input_srid.intval = arg_ti.get_input_srid();
1704  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1705  Datum output_srid;
1706  // Forcing web-mercator projection for now
1707  // TODO(croot): check that the input-to-output conversion routines exist?
1708  output_srid.intval =
1709  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1710  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1711 
1712  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1713  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1714  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1715  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1716  return makeExpr<Analyzer::FunctionOper>(
1717  rex_function->getType(), specialized_geofunc, args);
1718  } else if (rex_function->getName() == "is_point_in_view"sv) {
1719  CHECK_EQ(rex_function->size(), 5u);
1720  SQLTypeInfo arg_ti;
1721  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1722  auto geoargs =
1723  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
1724  // only works on points
1725  if (arg_ti.get_type() != kPOINT) {
1726  throw QueryNotSupported(rex_function->getName() +
1727  " expects a point for the second argument");
1728  }
1729 
1730  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1731 
1732  // Add compression information
1733  Datum input_compression;
1734  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1735  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1736  if (arg_ti.get_input_srid() != 4326) {
1737  throw QueryNotSupported(
1738  rex_function->getName() +
1739  " currently only supports points of with SRID WGS84/EPSG:4326");
1740  }
1741  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1742  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1743  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1744  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1745  return makeExpr<Analyzer::FunctionOper>(
1746  rex_function->getType(), specialized_geofunc, args);
1747  } else if (rex_function->getName() == "is_point_size_in_view"sv) {
1748  CHECK_EQ(rex_function->size(), 6u);
1749  SQLTypeInfo arg_ti;
1750  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1751  auto geoargs =
1752  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
1753  // only works on points
1754  if (arg_ti.get_type() != kPOINT) {
1755  throw QueryNotSupported(rex_function->getName() +
1756  " expects a point for the second argument");
1757  }
1758 
1759  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1760 
1761  // Add compression information
1762  Datum input_compression;
1763  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1764  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1765  if (arg_ti.get_input_srid() != 4326) {
1766  throw QueryNotSupported(
1767  rex_function->getName() +
1768  " currently only supports points of with SRID WGS84/EPSG:4326");
1769  }
1770  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1771  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1772  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1773  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1774  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1775  return makeExpr<Analyzer::FunctionOper>(
1776  rex_function->getType(), specialized_geofunc, args);
1777  }
1778  CHECK(false);
1779  return nullptr;
1780 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
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
size_t size() const
const RexScalar * getOperand(const size_t idx) const
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
int32_t intval
Definition: sqltypes.h:214
#define CHECK(condition)
Definition: Logger.h:223
Definition: sqltypes.h:45
const std::string & getName() const

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

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

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

Referenced by translateOper().

1653  {
1654  if (rex_operator->size() != size_t(2)) {
1655  return nullptr;
1656  }
1657 
1658  auto geo_distance_expr = translateScalarRex(rex_operator->getOperand(0));
1659  auto func_oper = dynamic_cast<Analyzer::GeoOperator*>(geo_distance_expr.get());
1660  if (func_oper && func_oper->getName() == "ST_Distance"sv) {
1661  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1662  auto distance_expr = translateScalarRex(rex_operator->getOperand(1));
1663  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1664  distance_expr = distance_expr->add_cast(distance_ti);
1665  }
1666  distance_expr = fold_expr(distance_expr.get());
1667  return makeExpr<Analyzer::BinOper>(
1668  kBOOLEAN, rex_operator->getOperator(), kONE, geo_distance_expr, distance_expr);
1669  }
1670  return nullptr;
1671 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
SQLOps getOperator() const
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 258 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(), 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(), and translateUnaryGeoPredicate().

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

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

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

123  {
124  CHECK(rex_literal);
125  if (rex_literal->getType() != kTEXT) {
126  throw std::runtime_error("Geo literals must be strings");
127  }
128 
129  // TODO: use geo conversion here
130  const auto e = translateLiteral(rex_literal);
131  auto wkt = std::dynamic_pointer_cast<Analyzer::Constant>(e);
132  CHECK(wkt);
133  std::vector<double> coords;
134  std::vector<double> bounds;
135  std::vector<int> ring_sizes;
136  std::vector<int> poly_rings;
137  int32_t srid = ti.get_output_srid();
139  *wkt->get_constval().stringval, ti, coords, bounds, ring_sizes, poly_rings)) {
140  throw QueryNotSupported("Could not read geometry from text");
141  }
143  ti.set_input_srid(srid);
144  ti.set_output_srid(srid);
145  // Compress geo literals by default
146  if (srid == 4326) {
148  ti.set_comp_param(32);
149  }
150 
151  std::vector<std::shared_ptr<Analyzer::Expr>> args;
152 
153  std::vector<uint8_t> compressed_coords = Geospatial::compress_coords(coords, ti);
154  std::list<std::shared_ptr<Analyzer::Expr>> compressed_coords_exprs;
155  for (auto cc : compressed_coords) {
156  Datum d;
157  d.tinyintval = cc;
158  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
159  compressed_coords_exprs.push_back(e);
160  }
161  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
162  arr_ti.set_subtype(kTINYINT);
163  arr_ti.set_size(compressed_coords.size() * sizeof(int8_t));
164  arr_ti.set_compression(ti.get_compression());
165  arr_ti.set_comp_param((ti.get_compression() == kENCODING_GEOINT) ? 32 : 64);
166  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, compressed_coords_exprs));
167 
168  auto lit_type = ti.get_type();
169  if (lit_type == kPOLYGON || lit_type == kMULTIPOLYGON) {
170  // ring sizes
171  std::list<std::shared_ptr<Analyzer::Expr>> ring_size_exprs;
172  for (auto c : ring_sizes) {
173  Datum d;
174  d.intval = c;
175  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
176  ring_size_exprs.push_back(e);
177  }
178  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
179  arr_ti.set_subtype(kINT);
180  arr_ti.set_size(ring_sizes.size() * sizeof(int32_t));
181  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, ring_size_exprs));
182 
183  // poly rings
184  if (lit_type == kMULTIPOLYGON) {
185  std::list<std::shared_ptr<Analyzer::Expr>> poly_rings_exprs;
186  for (auto c : poly_rings) {
187  Datum d;
188  d.intval = c;
189  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
190  poly_rings_exprs.push_back(e);
191  }
192  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
193  arr_ti.set_subtype(kINT);
194  arr_ti.set_size(poly_rings.size() * sizeof(int32_t));
195  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, poly_rings_exprs));
196  }
197  }
198 
199  if (with_bounds && ti.has_bounds()) {
200  // bounds
201  std::list<std::shared_ptr<Analyzer::Expr>> bounds_exprs;
202  for (auto b : bounds) {
203  Datum d;
204  d.doubleval = b;
205  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
206  bounds_exprs.push_back(e);
207  }
208  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
209  arr_ti.set_subtype(kDOUBLE);
210  arr_ti.set_size(bounds.size() * sizeof(double));
211  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, bounds_exprs));
212  }
213 
214  return args;
215 }
int8_t tinyintval
Definition: sqltypes.h:212
void set_compression(EncodingType c)
Definition: sqltypes.h:440
void set_size(int s)
Definition: sqltypes.h:437
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:430
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
int32_t intval
Definition: sqltypes.h:214
void set_input_srid(int d)
Definition: sqltypes.h:433
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:408
void set_output_srid(int s)
Definition: sqltypes.h:435
void set_comp_param(int p)
Definition: sqltypes.h:441
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:937
Definition: sqltypes.h:52
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:337
#define CHECK(condition)
Definition: Logger.h:223
Definition: sqltypes.h:45
double doubleval
Definition: sqltypes.h:217
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:335

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

1783  {
1784  CHECK_EQ(rex_operator->size(), 2u);
1785 
1786  auto translate_input =
1787  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1788  const auto input = dynamic_cast<const RexInput*>(operand);
1789  CHECK(input);
1790 
1791  SQLTypeInfo ti;
1792  const auto exprs = translateGeoColumn(input, ti, true, false, false);
1793  CHECK_GT(exprs.size(), 0u);
1794  if (ti.get_type() == kPOINT) {
1795  return exprs.front();
1796  } else {
1797  return exprs.back();
1798  }
1799  };
1800 
1801  SQLQualifier sql_qual{kONE};
1802  SQLOps sql_op{kOVERLAPS};
1803  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
1804  false,
1805  sql_op,
1806  sql_qual,
1807  translate_input(rex_operator->getOperand(1)),
1808  translate_input(rex_operator->getOperand(0)));
1809 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
SQLQualifier
Definition: sqldefs.h:71
size_t size() const
const RexScalar * getOperand(const size_t idx) const
SQLOps
Definition: sqldefs.h:29
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
#define CHECK_GT(x, y)
Definition: Logger.h:235
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:223
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 862 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateFunction().

865  {
866  // note that this is a bit of a misnomer, as ST_SetSRID embedded in a transform will
867  // eventually use geo expressions -- just not here
868  const bool use_geo_projections = !(rex_function->getName() == "ST_GeomFromText" ||
869  rex_function->getName() == "ST_GeogFromText" ||
870  rex_function->getName() == "ST_SetSRID");
871  auto geoargs = translateGeoFunctionArg(rex_function,
872  ti,
873  /*with_bounds=*/false,
874  /*with_render_group=*/false,
875  /*expand_geo_col=*/true,
876  /*is_projection=*/true,
877  /*use_geo_expressions=*/use_geo_projections);
878  CHECK(!geoargs.empty());
879  if (std::dynamic_pointer_cast<const Analyzer::GeoExpr>(geoargs.front()) &&
880  !geoargs.front()->get_type_info().is_array()) {
881  // GeoExpression
882  return geoargs.front();
883  }
884  bool allow_gdal_transform = false;
885  if (rex_function->getName() == "ST_Transform") {
886  const auto rex_scalar0 = dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
887  const auto rex_function0 = dynamic_cast<const RexFunctionOperator*>(rex_scalar0);
888  if (rex_function0 && func_resolve(rex_function0->getName(),
889  "ST_Intersection"sv,
890  "ST_Difference"sv,
891  "ST_Union"sv,
892  "ST_Buffer"sv)) {
893  // Allow projection of gdal-transformed geos outputs
894  allow_gdal_transform = true;
895  }
896  }
897  if (use_geo_projections && !allow_gdal_transform) {
898  throw std::runtime_error("Geospatial projection for function " +
899  rex_function->toString(RelRexToStringConfig::defaults()) +
900  " not yet supported in this context");
901  }
902  return makeExpr<Analyzer::GeoUOper>(
903  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
904 }
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
static RelRexToStringConfig defaults()
#define CHECK(condition)
Definition: Logger.h:223
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
const std::string & getName() const

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

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

Referenced by translateFunction().

1976  {
1977  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
1978  Therefore any string having fractional seconds more 3 places after the decimal
1979  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
1980  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
1981  calcite and translating them to generate our own casts.
1982  */
1983  CHECK_EQ(size_t(1), rex_function->size());
1984  const auto operand = translateScalarRex(rex_function->getOperand(0));
1985  const auto& operand_ti = operand->get_type_info();
1986  const auto& target_ti = rex_function->getType();
1987  if (!operand_ti.is_string()) {
1988  throw std::runtime_error(
1989  "High precision timestamp cast argument must be a string. Input type is: " +
1990  operand_ti.get_type_name());
1991  } else if (!target_ti.is_high_precision_timestamp()) {
1992  throw std::runtime_error(
1993  "Cast target type should be high precision timestamp. Input type is: " +
1994  target_ti.get_type_name());
1995  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
1996  throw std::runtime_error(
1997  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
1998  std::to_string(target_ti.get_dimension()) + ")");
1999  } else {
2000  return operand->add_cast(target_ti);
2001  }
2002 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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 592 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().

593  {
594  if (just_explain_) {
595  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
596  }
597  CHECK(rex_operator->size() == 2);
598  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
599  const auto rhs = rex_operator->getOperand(1);
600  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
601  CHECK(rex_subquery);
602  auto ti = lhs->get_type_info();
603  auto result = rex_subquery->getExecutionResult();
604  CHECK(result);
605  auto& row_set = result->getRows();
606  CHECK_EQ(size_t(1), row_set->colCount());
607  const auto& rhs_ti = row_set->getColType(0);
608  if (rhs_ti.get_type() != ti.get_type()) {
609  throw std::runtime_error(
610  "The two sides of the IN operator must have the same type; found " +
611  ti.get_type_name() + " and " + rhs_ti.get_type_name());
612  }
613  row_set->moveToBegin();
614  if (row_set->entryCount() > 10000) {
615  std::shared_ptr<Analyzer::Expr> expr;
616  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
617  !row_set->getQueryMemDesc().didOutputColumnar()) {
618  expr = getInIntegerSetExpr(lhs, *row_set);
619  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
620  // Just let it fall through the usual InValues path at the end of this method,
621  // its codegen knows to use inline comparisons for few values.
622  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
623  ->get_value_list()
624  .size() <= 100) {
625  expr = nullptr;
626  }
627  } else {
628  expr = get_in_values_expr(lhs, *row_set);
629  }
630  if (expr) {
631  return expr;
632  }
633  }
634  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
635  while (true) {
636  auto row = row_set->getNextRow(true, false);
637  if (row.empty()) {
638  break;
639  }
640  if (g_enable_watchdog && value_exprs.size() >= 10000) {
641  throw std::runtime_error(
642  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
643  }
644  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
645  Datum d{0};
646  bool is_null_const{false};
647  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
648  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
649  auto ti_none_encoded = ti;
650  ti_none_encoded.set_compression(kENCODING_NONE);
651  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
652  auto dict_encoded_string =
653  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
654  value_exprs.push_back(dict_encoded_string);
655  } else {
656  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
657  }
658  }
659  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
660 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:49
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:223
std::pair< Datum, bool > datum_from_scalar_tv(const ScalarTargetValue *scalar_tv, const SQLTypeInfo &ti) noexcept
const bool just_explain_

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

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

Referenced by translateGeoFunctionArg(), and translateScalarRex().

395  {
396  const auto source = rex_input->getSourceNode();
397  const auto it_rte_idx = input_to_nest_level_.find(source);
398  CHECK(it_rte_idx != input_to_nest_level_.end())
399  << "Not found in input_to_nest_level_, source="
400  << source->toString(RelRexToStringConfig::defaults());
401  const int rte_idx = it_rte_idx->second;
402  const auto scan_source = dynamic_cast<const RelScan*>(source);
403  const auto& in_metainfo = source->getOutputMetainfo();
404  if (scan_source) {
405  // We're at leaf (scan) level and not supposed to have input metadata,
406  // the name and type information come directly from the catalog.
407  CHECK(in_metainfo.empty());
408  const auto table_desc = scan_source->getTableDescriptor();
409  const auto cd =
410  cat_.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
411  CHECK(cd);
412  auto col_ti = cd->columnType;
413  if (col_ti.is_string()) {
414  col_ti.set_type(kTEXT);
415  }
416  if (cd->isVirtualCol) {
417  // TODO(alex): remove at some point, we only need this fixup for backwards
418  // compatibility with old imported data
419  CHECK_EQ("rowid", cd->columnName);
420  col_ti.set_size(8);
421  }
422  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
423  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
424  col_ti.set_notnull(false);
425  }
426  return std::make_shared<Analyzer::ColumnVar>(
427  col_ti, table_desc->tableId, cd->columnId, rte_idx);
428  }
429  CHECK(!in_metainfo.empty()) << "for "
430  << source->toString(RelRexToStringConfig::defaults());
431  CHECK_GE(rte_idx, 0);
432  const size_t col_id = rex_input->getIndex();
433  CHECK_LT(col_id, in_metainfo.size());
434  auto col_ti = in_metainfo[col_id].get_type_info();
435 
436  if (join_types_.size() > 0) {
437  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
438  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
439  col_ti.set_notnull(false);
440  }
441  }
442 
443  return std::make_shared<Analyzer::ColumnVar>(col_ti, -source->getId(), col_id, rte_idx);
444 }
const std::vector< JoinType > join_types_
#define CHECK_EQ(x, y)
Definition: Logger.h:231
#define CHECK_GE(x, y)
Definition: Logger.h:236
unsigned getIndex() const
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
Definition: Catalog.cpp:1770
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:233
Definition: sqltypes.h:52
#define CHECK_LE(x, y)
Definition: Logger.h:234
static RelRexToStringConfig defaults()
const RelAlgNode * getSourceNode() const
#define CHECK(condition)
Definition: Logger.h:223
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
const Catalog_Namespace::Catalog & cat_

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

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

Referenced by translateFunction().

1415  {
1416  CHECK_EQ(size_t(2), rex_function->size());
1417  const auto base = translateScalarRex(rex_function->getOperand(0));
1418  const auto index = translateScalarRex(rex_function->getOperand(1));
1419  return makeExpr<Analyzer::BinOper>(
1420  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1421 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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 1289 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1290  {
1291  const auto& args = translateFunctionArgs(rex_function);
1292  CHECK_EQ(size_t(1), args.size());
1293  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1294  if (nullptr == expr || !expr->get_type_info().is_string() ||
1295  expr->get_type_info().is_varlen()) {
1296  throw std::runtime_error(rex_function->getName() +
1297  " expects a dictionary encoded text column.");
1298  }
1299  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1300 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
const std::string & getName() const

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

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

Referenced by translateFunction().

1282  {
1283  CHECK_EQ(size_t(1), rex_function->size());
1284  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1285  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1286  rex_function->getName() == "CHAR_LENGTH"sv);
1287 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
const std::string & getName() const

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

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

Referenced by translateFunction().

1031  {
1032  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1033  const auto arg = translateScalarRex(rex_function->getOperand(0));
1034  const auto like = translateScalarRex(rex_function->getOperand(1));
1035  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1036  throw std::runtime_error("The matching pattern must be a literal.");
1037  }
1038  const auto escape = (rex_function->size() == 3)
1039  ? translateScalarRex(rex_function->getOperand(2))
1040  : nullptr;
1041  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1042  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1043 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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:692
#define CHECK(condition)
Definition: Logger.h:223
const std::string & getName() const

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

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

Referenced by translateFunction().

1060  {
1061  CHECK(rex_function->size() == 1);
1062  const auto arg = translateScalarRex(rex_function->getOperand(0));
1063  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1064 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:223

+ 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 281 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(), translateGeoLiteral(), and translateScalarRex().

282  {
283  auto lit_ti = build_type_info(
284  rex_literal->getType(), rex_literal->getScale(), rex_literal->getPrecision());
285  auto target_ti = build_type_info(rex_literal->getTargetType(),
286  rex_literal->getTargetScale(),
287  rex_literal->getTargetPrecision());
288  switch (rex_literal->getType()) {
289  case kINT:
290  case kBIGINT: {
291  Datum d;
292  d.bigintval = rex_literal->getVal<int64_t>();
293  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
294  }
295  case kDECIMAL: {
296  const auto val = rex_literal->getVal<int64_t>();
297  const int precision = rex_literal->getPrecision();
298  const int scale = rex_literal->getScale();
299  if (target_ti.is_fp() && !scale) {
300  return make_fp_constant(val, target_ti);
301  }
302  auto lit_expr = scale ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
303  : Parser::IntLiteral::analyzeValue(val);
304  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
305  }
306  case kTEXT: {
307  return Parser::StringLiteral::analyzeValue(rex_literal->getVal<std::string>(),
308  false);
309  }
310  case kBOOLEAN: {
311  Datum d;
312  d.boolval = rex_literal->getVal<bool>();
313  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
314  }
315  case kDOUBLE: {
316  Datum d;
317  d.doubleval = rex_literal->getVal<double>();
318  auto lit_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
319  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
320  }
321  case kINTERVAL_DAY_TIME:
322  case kINTERVAL_YEAR_MONTH: {
323  Datum d;
324  d.bigintval = rex_literal->getVal<int64_t>();
325  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
326  }
327  case kTIME:
328  case kTIMESTAMP: {
329  Datum d;
330  d.bigintval =
331  rex_literal->getType() == kTIMESTAMP && rex_literal->getPrecision() > 0
332  ? rex_literal->getVal<int64_t>()
333  : rex_literal->getVal<int64_t>() / 1000;
334  return makeExpr<Analyzer::Constant>(
335  SQLTypeInfo(rex_literal->getType(), rex_literal->getPrecision(), 0, false),
336  false,
337  d);
338  }
339  case kDATE: {
340  Datum d;
341  d.bigintval = rex_literal->getVal<int64_t>() * 24 * 3600;
342  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
343  }
344  case kNULLT: {
345  if (target_ti.is_array()) {
347  // defaulting to valid sub-type for convenience
348  target_ti.set_subtype(kBOOLEAN);
349  return makeExpr<Analyzer::ArrayExpr>(target_ti, args, true);
350  }
351  return makeExpr<Analyzer::Constant>(rex_literal->getTargetType(), true, Datum{0});
352  }
353  default: {
354  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
355  }
356  }
357  return nullptr;
358 }
Definition: sqltypes.h:49
#define LOG(tag)
Definition: Logger.h:217
int8_t boolval
Definition: sqltypes.h:211
int64_t bigintval
Definition: sqltypes.h:215
SQLTypeInfo build_type_info(const SQLTypes sql_type, const int scale, const int precision)
Definition: sqltypes.h:52
Definition: sqltypes.h:53
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:188
Definition: sqltypes.h:45
double doubleval
Definition: sqltypes.h:217

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

Referenced by translateFunction().

1495  {
1496  return makeExpr<Analyzer::OffsetInFragment>();
1497 }

+ Here is the caller graph for this function:

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

Definition at line 912 of file RelAlgTranslator.cpp.

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

Referenced by translateScalarRex().

913  {
914  CHECK_GT(rex_operator->size(), size_t(0));
915  if (rex_operator->size() == 1) {
916  return translateUoper(rex_operator);
917  }
918  const auto sql_op = rex_operator->getOperator();
919  if (sql_op == kIN) {
920  return translateInOper(rex_operator);
921  }
922  if (sql_op == kMINUS || sql_op == kPLUS) {
923  auto date_plus_minus = translateDatePlusMinus(rex_operator);
924  if (date_plus_minus) {
925  return date_plus_minus;
926  }
927  }
928  if (sql_op == kOVERLAPS) {
929  return translateOverlapsOper(rex_operator);
930  } else if (IS_COMPARISON(sql_op)) {
931  auto geo_comp = translateGeoComparison(rex_operator);
932  if (geo_comp) {
933  return geo_comp;
934  }
935  }
936  auto lhs = translateScalarRex(rex_operator->getOperand(0));
937  for (size_t i = 1; i < rex_operator->size(); ++i) {
938  std::shared_ptr<Analyzer::Expr> rhs;
939  SQLQualifier sql_qual{kONE};
940  const auto rhs_op = rex_operator->getOperand(i);
941  std::tie(rhs, sql_qual) = get_quantified_rhs(rhs_op, *this);
942  if (!rhs) {
943  rhs = translateScalarRex(rhs_op);
944  }
945  CHECK(rhs);
946 
947  // Pass in executor to get string proxy info if cast needed between
948  // string columns
949  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs, executor_);
950  }
951  return lhs;
952 }
const Executor * executor_
SQLQualifier
Definition: sqldefs.h:71
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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:371
Definition: sqldefs.h:41
#define CHECK_GT(x, y)
Definition: Logger.h:235
SQLOps getOperator() const
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > get_quantified_rhs(const RexScalar *rex_scalar, const RelAlgTranslator &translator)
Definition: sqldefs.h:40
Definition: sqldefs.h:71
std::shared_ptr< Analyzer::Expr > translateOverlapsOper(const RexOperator *) const
Definition: sqldefs.h:53
#define CHECK(condition)
Definition: Logger.h:223
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:

+ Here is the caller graph for this function:

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

Definition at line 954 of file RelAlgTranslator.cpp.

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

Referenced by translateOper().

955  {
956  const auto sql_op = rex_operator->getOperator();
957  CHECK(sql_op == kOVERLAPS);
958 
959  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
960  const auto lhs_ti = lhs->get_type_info();
961  if (lhs_ti.is_geometry()) {
962  return translateGeoOverlapsOper(rex_operator);
963  } else {
964  throw std::runtime_error(
965  "Overlaps equivalence is currently only supported for geospatial types");
966  }
967 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
std::shared_ptr< Analyzer::Expr > translateGeoOverlapsOper(const RexOperator *) const
SQLOps getOperator() const
#define CHECK(condition)
Definition: Logger.h:223

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

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

Referenced by translateFunction().

1046  {
1047  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1048  const auto arg = translateScalarRex(rex_function->getOperand(0));
1049  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1050  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1051  throw std::runtime_error("The matching pattern must be a literal.");
1052  }
1053  const auto escape = (rex_function->size() == 3)
1054  ? translateScalarRex(rex_function->getOperand(2))
1055  : nullptr;
1056  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1057 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
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:787
#define CHECK(condition)
Definition: Logger.h:223

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1302 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1303  {
1304  CHECK_EQ(size_t(1), rex_function->size());
1305  auto arg = translateScalarRex(rex_function->getOperand(0));
1306  const auto& arg_ti = arg->get_type_info();
1307  if (arg_ti.get_type() != kDOUBLE) {
1308  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1309  arg = arg->add_cast(double_ti);
1310  }
1311  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1312 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 180 of file RelAlgTranslator.cpp.

References CHECK, translateCase(), translateFunction(), translateInput(), translateLiteral(), translateOper(), translateScalarSubquery(), and translateWindowFunction().

Referenced by anonymous_namespace{RelAlgExecutor.cpp}::get_inputs_meta(), anonymous_namespace{RelAlgTranslator.cpp}::get_quantified_rhs(), RelAlgExecutor::makeJoinQuals(), anonymous_namespace{RelAlgExecutor.cpp}::translate_quals(), anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources(), anonymous_namespace{RelAlgExecutor.cpp}::translate_scalar_sources_for_update(), anonymous_namespace{RelAlgExecutor.cpp}::translate_targets(), translateAbs(), translateBinaryGeoConstructor(), translateBinaryGeoFunction(), translateCardinality(), translateCase(), translateDateadd(), translateDatediff(), translateDatepart(), translateDatePlusMinus(), translateDatetime(), translateExtract(), translateFunction(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoComparison(), translateGeoFunctionArg(), translateHPTLiteral(), translateInOper(), translateItem(), translateLength(), translateLike(), translateLikely(), translateOper(), translateOverlapsOper(), translateRegexp(), translateSampleRatio(), translateSign(), translateTernaryGeoFunction(), translateUnlikely(), translateUoper(), translateWidthBucket(), and translateWindowFunction().

181  {
182  const auto rex_input = dynamic_cast<const RexInput*>(rex);
183  if (rex_input) {
184  return translateInput(rex_input);
185  }
186  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex);
187  if (rex_literal) {
188  return translateLiteral(rex_literal);
189  }
190  const auto rex_window_function = dynamic_cast<const RexWindowFunctionOperator*>(rex);
191  if (rex_window_function) {
192  return translateWindowFunction(rex_window_function);
193  }
194  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex);
195  if (rex_function) {
196  return translateFunction(rex_function);
197  }
198  const auto rex_operator = dynamic_cast<const RexOperator*>(rex);
199  if (rex_operator) {
200  return translateOper(rex_operator);
201  }
202  const auto rex_case = dynamic_cast<const RexCase*>(rex);
203  if (rex_case) {
204  return translateCase(rex_case);
205  }
206  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rex);
207  if (rex_subquery) {
208  return translateScalarSubquery(rex_subquery);
209  }
210  CHECK(false);
211  return nullptr;
212 }
std::shared_ptr< Analyzer::Expr > translateFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateOper(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
#define CHECK(condition)
Definition: Logger.h:223
std::shared_ptr< Analyzer::Expr > translateCase(const RexCase *) const
std::shared_ptr< Analyzer::Expr > translateWindowFunction(const RexWindowFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateScalarSubquery(const RexSubQuery *) const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateScalarSubquery ( const RexSubQuery rex_subquery) const
private

Definition at line 360 of file RelAlgTranslator.cpp.

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

Referenced by translateScalarRex().

361  {
362  if (just_explain_) {
363  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
364  }
365  CHECK(rex_subquery);
366  auto result = rex_subquery->getExecutionResult();
367  auto row_set = result->getRows();
368  const size_t row_count = row_set->rowCount();
369  if (row_count > size_t(1)) {
370  throw std::runtime_error("Scalar sub-query returned multiple rows");
371  }
372  if (row_count == size_t(0)) {
373  if (row_set->isValidationOnlyRes()) {
374  Datum d{0};
375  return makeExpr<Analyzer::Constant>(rex_subquery->getType(), false, d);
376  }
377  throw std::runtime_error("Scalar sub-query returned no results");
378  }
379  CHECK_EQ(row_count, size_t(1));
380  row_set->moveToBegin();
381  auto first_row = row_set->getNextRow(false, false);
382  CHECK_EQ(first_row.size(), size_t(1));
383  auto scalar_tv = boost::get<ScalarTargetValue>(&first_row[0]);
384  auto ti = rex_subquery->getType();
385  if (ti.is_string()) {
386  throw std::runtime_error("Scalar sub-queries which return strings not supported");
387  }
388  Datum d{0};
389  bool is_null_const{false};
390  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
391  return makeExpr<Analyzer::Constant>(ti, is_null_const, d);
392 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
#define CHECK(condition)
Definition: Logger.h:223
std::pair< Datum, bool > datum_from_scalar_tv(const ScalarTargetValue *scalar_tv, const SQLTypeInfo &ti) noexcept
const bool just_explain_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1473 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1474  {
1475  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1476  expr_list;
1477  CHECK_EQ(size_t(1), rex_function->size());
1478  const auto operand = translateScalarRex(rex_function->getOperand(0));
1479  const auto& operand_ti = operand->get_type_info();
1480  CHECK(operand_ti.is_number());
1481  const auto zero = makeNumericConstant(operand_ti, 0);
1482  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1483  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1484  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1485  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1486  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1487  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1488  return makeExpr<Analyzer::CaseExpr>(
1489  operand_ti,
1490  false,
1491  expr_list,
1492  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1493 }
#define CHECK_EQ(x, y)
Definition: Logger.h:231
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:30
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
Definition: sqldefs.h:34
Definition: sqldefs.h:71
#define CHECK(condition)
Definition: Logger.h:223
Definition: sqldefs.h:33

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1323 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, CONCAT, g_enable_string_functions, RexFunctionOperator::getName(), INITCAP, kCAST, kENCODING_DICT, kTEXT, LOWER, LPAD, LTRIM, name_to_string_op_kind(), OVERLAY, REGEXP_REPLACE, REGEXP_SUBSTR, REPEAT, REPLACE, REVERSE, RPAD, RTRIM, SQLTypeInfo::set_comp_param(), SQLTypeInfo::set_compression(), SQLTypeInfo::set_fixed_size(), SQLTypeInfo::set_type(), SPLIT_PART, SUBSTRING, TRANSIENT_DICT_ID, translateFunctionArgs(), TRIM, and UPPER.

Referenced by translateFunction().

1324  {
1325  const auto func_name = rex_function->getName();
1327  std::ostringstream oss;
1328  oss << "Function " << func_name << " not supported.";
1329  throw std::runtime_error(oss.str());
1330  }
1331  const auto string_op_kind = ::name_to_string_op_kind(func_name);
1332  auto args = translateFunctionArgs(rex_function);
1333  // Used by watchdog later to gate queries based on
1334  if (!args.empty() && !dynamic_cast<const Analyzer::Constant*>(args[0].get())) {
1335  const auto& arg0_ti = args[0]->get_type_info();
1336  if (arg0_ti.is_none_encoded_string()) {
1337  SQLTypeInfo casted_target_ti = arg0_ti;
1338  casted_target_ti.set_type(kTEXT);
1339  casted_target_ti.set_compression(kENCODING_DICT);
1340  casted_target_ti.set_comp_param(TRANSIENT_DICT_ID);
1341  casted_target_ti.set_fixed_size();
1342  args[0] = makeExpr<Analyzer::UOper>(
1343  casted_target_ti, args[0]->get_contains_agg(), kCAST, args[0]);
1344  }
1345  }
1346 
1347  switch (string_op_kind) {
1349  return makeExpr<Analyzer::LowerStringOper>(args);
1351  return makeExpr<Analyzer::UpperStringOper>(args);
1353  return makeExpr<Analyzer::InitCapStringOper>(args);
1355  return makeExpr<Analyzer::ReverseStringOper>(args);
1357  return makeExpr<Analyzer::RepeatStringOper>(args);
1359  return makeExpr<Analyzer::ConcatStringOper>(args);
1360  case SqlStringOpKind::LPAD:
1361  case SqlStringOpKind::RPAD: {
1362  return makeExpr<Analyzer::PadStringOper>(string_op_kind, args);
1363  }
1364  case SqlStringOpKind::TRIM:
1366  case SqlStringOpKind::RTRIM: {
1367  return makeExpr<Analyzer::TrimStringOper>(string_op_kind, args);
1368  }
1370  return makeExpr<Analyzer::SubstringStringOper>(args);
1372  return makeExpr<Analyzer::OverlayStringOper>(args);
1374  return makeExpr<Analyzer::ReplaceStringOper>(args);
1376  return makeExpr<Analyzer::SplitPartStringOper>(args);
1378  return makeExpr<Analyzer::RegexpReplaceStringOper>(args);
1380  return makeExpr<Analyzer::RegexpSubstrStringOper>(args);
1381  default: {
1382  throw std::runtime_error("Unsupported string function.");
1383  }
1384  }
1385 }
void set_compression(EncodingType c)
Definition: sqltypes.h:440
SqlStringOpKind name_to_string_op_kind(const std::string &func_name)
Definition: sqldefs.h:255
Definition: sqldefs.h:49
bool g_enable_string_functions
void set_fixed_size()
Definition: sqltypes.h:438
void set_comp_param(int p)
Definition: sqltypes.h:441
Definition: sqltypes.h:52
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:259
const std::string & getName() const
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:429

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1547 of file RelAlgTranslatorGeo.cpp.

References CHECK_EQ, Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_subtype(), SQLTypeInfo::get_type(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Datum::intval, kBOOLEAN, kDOUBLE, kGEOGRAPHY, kINT, kLE, kLINESTRING, kMULTIPOLYGON, kONE, kPOINT, kPOLYGON, run_benchmark_import::result, RexOperator::size(), spatial_type::suffix(), translateBinaryGeoFunction(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction().

1548  {
1549  CHECK_EQ(size_t(3), rex_function->size());
1550 
1551  auto distance_expr = translateScalarRex(rex_function->getOperand(2));
1552  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1553  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1554  distance_expr = distance_expr->add_cast(distance_ti);
1555  }
1556 
1557  auto function_name = rex_function->getName();
1558  if (function_name == "ST_DWithin"sv) {
1559  auto return_type = rex_function->getType();
1560  bool swap_args = false;
1561  bool with_bounds = true;
1562  SQLTypeInfo arg0_ti;
1563  SQLTypeInfo arg1_ti;
1564 
1565  auto geoargs0 = translateGeoFunctionArg(
1566  rex_function->getOperand(0), arg0_ti, with_bounds, false, false);
1567  auto geoargs1 = translateGeoFunctionArg(
1568  rex_function->getOperand(1), arg1_ti, with_bounds, false, false);
1569  if (arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1570  throw QueryNotSupported(rex_function->getName() +
1571  " cannot accept mixed GEOMETRY/GEOGRAPHY arguments");
1572  }
1573  auto is_geodesic = false;
1574  if (arg0_ti.get_subtype() == kGEOGRAPHY) {
1575  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1576  is_geodesic = true;
1577  } else {
1578  throw QueryNotSupported(
1579  rex_function->getName() +
1580  " in geodesic form can only accept POINT GEOGRAPHY arguments");
1581  }
1582  }
1583  // Check SRID match if at least one is set/valid
1584  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1585  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1586  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1587  }
1588 
1589  if ((arg1_ti.get_type() == kPOINT && arg0_ti.get_type() != kPOINT) ||
1590  (arg1_ti.get_type() == kLINESTRING && arg0_ti.get_type() == kPOLYGON) ||
1591  (arg1_ti.get_type() == kPOLYGON && arg0_ti.get_type() == kMULTIPOLYGON)) {
1592  // Swap arguments and use single implementation per arg pair
1593  swap_args = true;
1594  }
1595 
1596  // First input's compression mode and SRID args to enable on-the-fly
1597  // decompression/transforms
1598  Datum input_compression0;
1599  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1600  Datum input_srid0;
1601  input_srid0.intval = arg0_ti.get_input_srid();
1602 
1603  // Second input's compression mode and SRID args to enable on-the-fly
1604  // decompression/transforms
1605  Datum input_compression1;
1606  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1607  Datum input_srid1;
1608  input_srid1.intval = arg1_ti.get_input_srid();
1609 
1610  // Output SRID arg to enable on-the-fly transforms
1611  Datum output_srid;
1612  output_srid.intval = arg0_ti.get_output_srid();
1613 
1614  std::string specialized_geofunc{function_name};
1615  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1616  if (swap_args) {
1617  specialized_geofunc += suffix(arg1_ti.get_type()) + suffix(arg0_ti.get_type());
1618  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1619  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1620  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1621  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1622  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1623  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1624  } else {
1625  specialized_geofunc += suffix(arg0_ti.get_type()) + suffix(arg1_ti.get_type());
1626  if (is_geodesic) {
1627  specialized_geofunc += "_Geodesic"s;
1628  }
1629  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1630  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1631  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1632  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1633  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1634  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1635  }
1636  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1637  // Also add the within distance
1638  geoargs.push_back(distance_expr);
1639 
1640  auto result =
1641  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1642  return result;
1643  }
1644 
1645  // Otherwise translate function as binary geo to get distance,
1646  // with optional short-circuiting threshold held in the third operand
1647  const auto geo_distance = translateBinaryGeoFunction(rex_function);
1648  // and generate the comparison
1649  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, geo_distance, distance_expr);
1650 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
Definition: Logger.h:231
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
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:35
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
int32_t intval
Definition: sqltypes.h:214
std::string suffix(SQLTypes type)
Definition: Codegen.cpp:68
Definition: sqldefs.h:71
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:333
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
Definition: sqltypes.h:45
const std::string & getName() const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:335

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1038 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateFunction().

1039  {
1040  CHECK_EQ(size_t(1), rex_function->size());
1041 
1042  std::string specialized_geofunc{rex_function->getName()};
1043 
1044  // Geo function calls which do not need the coords col but do need cols associated
1045  // with physical coords (e.g. ring_sizes / poly_rings)