OmniSciDB  6686921089
 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::ExprtranslateLower (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
 
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 784 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(), i, inline_int_null_val(), and kENCODING_DICT.

Referenced by translateInOper().

786  {
788  return nullptr;
789  }
790  std::vector<int64_t> value_exprs;
791  const size_t fetcher_count = cpu_threads();
792  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
793  std::vector<std::future<void>> fetcher_threads;
794  const auto& arg_type = arg->get_type_info();
795  const auto entry_count = val_set.entryCount();
796  CHECK_EQ(size_t(1), val_set.colCount());
797  const auto& col_type = val_set.getColType(0);
798  if (g_cluster && arg_type.is_string() &&
799  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
800  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
801  return nullptr;
802  }
803  std::atomic<size_t> total_in_vals_count{0};
804  for (size_t i = 0,
805  start_entry = 0,
806  stride = (entry_count + fetcher_count - 1) / fetcher_count;
807  i < fetcher_count && start_entry < entry_count;
808  ++i, start_entry += stride) {
809  expr_set[i].reserve(entry_count / fetcher_count);
810  const auto end_entry = std::min(start_entry + stride, entry_count);
811  if (arg_type.is_string()) {
812  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
813  // const int32_t dest_dict_id = arg_type.get_comp_param();
814  // const int32_t source_dict_id = col_type.get_comp_param();
815  const DictRef dest_dict_ref(arg_type.get_comp_param(), cat_.getDatabaseId());
816  const DictRef source_dict_ref(col_type.get_comp_param(), cat_.getDatabaseId());
817  const auto dd = executor_->getStringDictionaryProxy(
818  arg_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
819  const auto sd = executor_->getStringDictionaryProxy(
820  col_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
821  CHECK(sd);
822  const auto needle_null_val = inline_int_null_val(arg_type);
823  fetcher_threads.push_back(std::async(
825  [this,
826  &val_set,
827  &total_in_vals_count,
828  sd,
829  dd,
830  source_dict_ref,
831  dest_dict_ref,
832  needle_null_val](
833  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
834  if (g_cluster) {
835  CHECK_GE(dd->getGeneration(), 0);
837  total_in_vals_count,
838  &val_set,
839  {start, end},
841  source_dict_ref,
842  dest_dict_ref,
843  dd->getGeneration(),
844  needle_null_val);
845  } else {
847  total_in_vals_count,
848  &val_set,
849  {start, end},
850  sd,
851  dd,
852  needle_null_val);
853  }
854  },
855  std::ref(expr_set[i]),
856  start_entry,
857  end_entry));
858  } else {
859  CHECK(arg_type.is_integer());
860  fetcher_threads.push_back(std::async(
862  [&val_set, &total_in_vals_count](
863  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
864  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
865  },
866  std::ref(expr_set[i]),
867  start_entry,
868  end_entry));
869  }
870  }
871  for (auto& child : fetcher_threads) {
872  child.get();
873  }
874 
875  val_set.moveToBegin();
876  value_exprs.reserve(entry_count);
877  for (auto& exprs : expr_set) {
878  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
879  }
880  return makeExpr<Analyzer::InIntegerSet>(
881  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
882 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
const Executor * executor_
#define CHECK_GE(x, y)
Definition: Logger.h:222
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:275
const std::vector< LeafHostInfo > & getStringDictionaryHosts() const
Definition: Catalog.cpp:1573
#define CHECK(condition)
Definition: Logger.h:209
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:1135
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 1377 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().

1378  {
1379  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1380  expr_list;
1381  CHECK_EQ(size_t(1), rex_function->size());
1382  const auto operand = translateScalarRex(rex_function->getOperand(0));
1383  const auto& operand_ti = operand->get_type_info();
1384  CHECK(operand_ti.is_number());
1385  const auto zero = makeNumericConstant(operand_ti, 0);
1386  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1387  const auto uminus_operand =
1388  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1389  expr_list.emplace_back(lt_zero, uminus_operand);
1390  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1391 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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:69
#define CHECK(condition)
Definition: Logger.h:209
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 225 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().

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

1420  {
1421  if (rex_function->getType().get_subtype() == kNULLT) {
1422  auto sql_type = rex_function->getType();
1423  CHECK(sql_type.get_type() == kARRAY);
1424 
1425  // FIX-ME: Deal with NULL arrays
1426  auto translated_function_args(translateFunctionArgs(rex_function));
1427  if (translated_function_args.size() > 0) {
1428  const auto first_element_logical_type =
1429  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1430 
1431  auto diff_elem_itr =
1432  std::find_if(translated_function_args.begin(),
1433  translated_function_args.end(),
1434  [first_element_logical_type](const auto expr) {
1435  return first_element_logical_type !=
1436  get_nullable_logical_type_info(expr->get_type_info());
1437  });
1438  if (diff_elem_itr != translated_function_args.end()) {
1439  throw std::runtime_error(
1440  "Element " +
1441  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1442  " is not of the same type as other elements of the array. Consider casting "
1443  "to force this condition.\nElement Type: " +
1444  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1445  .to_string() +
1446  "\nArray type: " + first_element_logical_type.to_string());
1447  }
1448 
1449  if (first_element_logical_type.is_string() &&
1450  !first_element_logical_type.is_dict_encoded_string()) {
1451  sql_type.set_subtype(first_element_logical_type.get_type());
1452  sql_type.set_compression(kENCODING_FIXED);
1453  } else if (first_element_logical_type.is_dict_encoded_string()) {
1454  sql_type.set_subtype(first_element_logical_type.get_type());
1455  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1456  } else {
1457  sql_type.set_subtype(first_element_logical_type.get_type());
1458  sql_type.set_scale(first_element_logical_type.get_scale());
1459  sql_type.set_precision(first_element_logical_type.get_precision());
1460  }
1461 
1462  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1463  } else {
1464  // defaulting to valid sub-type for convenience
1465  sql_type.set_subtype(kBOOLEAN);
1466  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1467  }
1468  } else {
1469  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1470  translateFunctionArgs(rex_function));
1471  }
1472 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1070
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:209

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

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

Referenced by translateFunction(), and translateGeoFunctionArg().

817  {
818 #ifndef ENABLE_GEOS
819  throw QueryNotSupported(rex_function->getName() +
820  " geo constructor requires enabled GEOS support");
821 #endif
823  if (rex_function->getName() == "ST_Difference"sv) {
825  } else if (rex_function->getName() == "ST_Union"sv) {
827  } else if (rex_function->getName() == "ST_Buffer"sv) {
829  }
830 
833  SQLTypeInfo arg0_ti;
834  SQLTypeInfo arg1_ti;
835  if (func_resolve(rex_function->getName(),
836  "ST_Intersection"sv,
837  "ST_Difference"sv,
838  "ST_Union"sv,
839  "ST_Buffer"sv)) {
840  // First arg: geometry
841  geoargs0 = translateGeoFunctionArg(
842  rex_function->getOperand(0), arg0_ti, false, false, true, true);
843  }
844  if (func_resolve(rex_function->getName(),
845  "ST_Intersection"sv,
846  "ST_Difference"sv,
847  "ST_Union"sv)) {
848  // Second arg: geometry
849  geoargs1 = translateGeoFunctionArg(
850  rex_function->getOperand(1), arg1_ti, false, false, true, true);
851  } else if (func_resolve(rex_function->getName(), "ST_Buffer"sv)) {
852  // Second arg: double scalar
853  auto param_expr = translateScalarRex(rex_function->getOperand(1));
854  arg1_ti = SQLTypeInfo(kDOUBLE, false);
855  if (param_expr->get_type_info().get_type() != kDOUBLE) {
856  param_expr = param_expr->add_cast(arg1_ti);
857  }
858  geoargs1 = {param_expr};
859  }
860 
861  auto srid = ti.get_output_srid();
862  ti = arg0_ti;
864  ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
865  ti.set_comp_param(0);
866  if (srid > 0) {
867  ti.set_output_srid(srid); // Requested SRID sent from above
868  }
869  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
870 }
void set_compression(EncodingType c)
Definition: sqltypes.h:429
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) 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
void set_output_srid(int s)
Definition: sqltypes.h:425
void set_comp_param(int p)
Definition: sqltypes.h:430
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:181
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:419

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

References run_benchmark_import::args, CHECK, CHECK_EQ, CHECK_GT, Datum::doubleval, fold_expr(), func_resolve, 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(), i, Datum::intval, kBOOLEAN, kDOUBLE, kENCODING_GEOINT, kENCODING_NONE, kGEOGRAPHY, kINT, kLE, kLINESTRING, kNOT, kNULLT, kONE, kPOINT, run_benchmark_import::result, RexOperator::size(), spatial_type::suffix(), TOLERANCE_GEOINT32, translateGeoColumn(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction(), and translateTernaryGeoFunction().

1105  {
1106  auto function_name = rex_function->getName();
1107  auto return_type = rex_function->getType();
1108 
1109  if (function_name == "ST_Overlaps"sv) {
1110  // Overlaps join is the only implementation supported for now, only translate bounds
1111  CHECK_EQ(size_t(2), rex_function->size());
1112  auto extract_geo_bounds_from_input =
1113  [this, &rex_function](const size_t index) -> std::shared_ptr<Analyzer::Expr> {
1114  const auto rex_input =
1115  dynamic_cast<const RexInput*>(rex_function->getOperand(index));
1116  if (rex_input) {
1117  SQLTypeInfo ti;
1118  const auto exprs = translateGeoColumn(rex_input, ti, true, false, false);
1119  CHECK_GT(exprs.size(), size_t(0));
1120  if (ti.get_type() == kPOINT) {
1121  throw std::runtime_error("ST_Overlaps is not supported for point arguments.");
1122  } else {
1123  return exprs.back();
1124  }
1125  } else {
1126  throw std::runtime_error(
1127  "Only inputs are supported as arguments to ST_Overlaps for now.");
1128  }
1129  };
1130  std::vector<std::shared_ptr<Analyzer::Expr>> geo_args;
1131  geo_args.push_back(extract_geo_bounds_from_input(0));
1132  geo_args.push_back(extract_geo_bounds_from_input(1));
1133 
1134  return makeExpr<Analyzer::FunctionOper>(return_type, function_name, geo_args);
1135  }
1136 
1137  if (function_name == "ST_Distance"sv || function_name == "ST_MaxDistance"sv) {
1138  CHECK_EQ(size_t(2), rex_function->size());
1139  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1140  int legacy_transform_srid = 0;
1141  for (size_t i = 0; i < rex_function->size(); i++) {
1142  SQLTypeInfo arg0_ti; // discard
1143  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(i),
1144  arg0_ti,
1145  /*with_bounds=*/false, // TODO
1146  /*with_render_group=*/false,
1147  /*expand_geo_col=*/false,
1148  /*is_projection = */ false,
1149  /*use_geo_expressions=*/true);
1150  if (arg0_ti.get_output_srid() > 0 &&
1151  std::dynamic_pointer_cast<Analyzer::ColumnVar>(geoargs.front())) {
1152  // legacy transform
1153  CHECK(legacy_transform_srid == 0 ||
1154  legacy_transform_srid == arg0_ti.get_output_srid());
1155  legacy_transform_srid = arg0_ti.get_output_srid();
1156  }
1157  args.insert(args.end(), geoargs.begin(), geoargs.end());
1158  }
1159  return makeExpr<Analyzer::GeoOperator>(
1160  SQLTypeInfo(kDOUBLE, /*not_null=*/false),
1161  function_name,
1162  args,
1163  legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1164  : std::nullopt);
1165  }
1166 
1167  bool swap_args = false;
1168  bool with_bounds = false;
1169  bool negate_result = false;
1170  Analyzer::ExpressionPtr threshold_expr = nullptr;
1171  Analyzer::ExpressionPtr compare_expr = nullptr;
1172  if (function_name == "ST_DWithin"sv) {
1173  CHECK_EQ(size_t(3), rex_function->size());
1174  function_name = "ST_Distance";
1175  return_type = SQLTypeInfo(kDOUBLE, false);
1176  // Inject ST_DWithin's short-circuiting threshold into ST_MaxDistance
1177  threshold_expr = translateScalarRex(rex_function->getOperand(2));
1178  } else if (function_name == "ST_Equals"sv) {
1179  // Translate ST_Equals(g1,g2) to ST_Distance(g1,g2)<=0.0
1180  CHECK_EQ(size_t(2), rex_function->size());
1181  function_name = "ST_Distance";
1182  return_type = SQLTypeInfo(kDOUBLE, false);
1183  threshold_expr = nullptr;
1184  Datum d;
1185  d.doubleval = 0.0;
1186  compare_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1187  } else if (function_name == "ST_DFullyWithin"sv) {
1188  CHECK_EQ(size_t(3), rex_function->size());
1189  function_name = "ST_MaxDistance";
1190  return_type = SQLTypeInfo(kDOUBLE, false);
1191  // TODO: inject ST_DFullyWithin's short-circuiting threshold into ST_MaxDistance
1192  threshold_expr = nullptr;
1193  } else if (function_name == "ST_Distance"sv) {
1194  // TODO: pick up an outside short-circuiting threshold and inject into ST_Distance
1195  threshold_expr = nullptr;
1196  } else if (function_name == "ST_MaxDistance"sv) {
1197  // TODO: pick up an outside short-circuiting threshold and inject into
1198  // ST_MaxDistance
1199  threshold_expr = nullptr;
1200  } else {
1201  CHECK_EQ(size_t(2), rex_function->size());
1202  }
1203  if (function_name == "ST_Within"sv) {
1204  function_name = "ST_Contains";
1205  swap_args = true;
1206  } else if (function_name == "ST_Disjoint"sv) {
1207  function_name = "ST_Intersects";
1208  negate_result = true;
1209  }
1210  if (func_resolve(
1211  function_name, "ST_Contains"sv, "ST_Intersects"sv, "ST_Approx_Overlaps"sv)) {
1212  with_bounds = true;
1213  }
1214 
1215  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1216  SQLTypeInfo arg0_ti;
1217  SQLTypeInfo arg1_ti;
1218 
1219  auto geoargs0 = translateGeoFunctionArg(
1220  rex_function->getOperand(swap_args ? 1 : 0), arg0_ti, with_bounds, false, false);
1221  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1222 
1223  // If first arg of ST_Contains is compressed, try to compress the second one
1224  // to be able to switch to ST_cContains
1225  bool try_to_compress_arg1 = (function_name == "ST_Contains"sv &&
1226  arg0_ti.get_compression() == kENCODING_GEOINT &&
1227  arg0_ti.get_output_srid() == 4326);
1228 
1229  auto geoargs1 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 0 : 1),
1230  arg1_ti,
1231  with_bounds,
1232  false,
1233  false,
1234  false,
1235  false,
1236  try_to_compress_arg1);
1237  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1238 
1239  if (arg0_ti.get_subtype() != kNULLT && arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1240  throw QueryNotSupported(rex_function->getName() +
1241  " accepts either two GEOGRAPHY or two GEOMETRY arguments");
1242  }
1243  // Check SRID match if at least one is set/valid
1244  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1245  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1246  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1247  }
1248  if (compare_expr) {
1249  // We could fold the check to false here if argument geo types are different, e.g.
1250  // POLYGON vs POINT. However, tiny POLYGON could be "spatially" equal to a POINT.
1251  if (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT) {
1252  // ST_Equals is translated to a simple distance check for POINTs,
1253  // otherwise geometries are passed to GEOS's Equals
1254  return nullptr;
1255  }
1256  // Look at POINT compression modes.
1257  if (arg0_ti.get_compression() != arg1_ti.get_compression()) {
1258  if ((arg0_ti.get_compression() == kENCODING_GEOINT &&
1259  arg0_ti.get_comp_param() == 32 &&
1260  arg1_ti.get_compression() == kENCODING_NONE) ||
1261  (arg0_ti.get_compression() == kENCODING_NONE &&
1262  arg1_ti.get_compression() == kENCODING_GEOINT &&
1263  arg0_ti.get_comp_param() == 32)) {
1264  // Spatial equality comparison of a compressed point vs uncompressed point.
1265  // Introduce tolerance into distance calculation and comparison, translate
1266  // ST_Equals(g1,g2) to ST_Distance(g1,g2,thereshold=tolerance)<=tolerance
1267  Datum tolerance;
1268  // Tolerance representing 0.44" to cover shifts due to GEOINT(32) compression
1269  tolerance.doubleval = TOLERANCE_GEOINT32;
1270  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, tolerance);
1271  compare_expr = threshold_expr;
1272  } else {
1273  throw QueryNotSupported(
1274  rex_function->getName() +
1275  " unable to calculate compression tolerance for arguments");
1276  }
1277  }
1278  }
1279 
1280  if (function_name == "ST_Contains"sv) {
1281  const bool lhs_is_literal =
1282  geoargs1.size() == 1 &&
1283  std::dynamic_pointer_cast<const Analyzer::Constant>(geoargs1.front()) != nullptr;
1284  const bool lhs_is_point = arg1_ti.get_type() == kPOINT;
1285  if (!lhs_is_literal && lhs_is_point &&
1286  arg0_ti.get_compression() == kENCODING_GEOINT &&
1287  arg0_ti.get_input_srid() == arg0_ti.get_output_srid() &&
1288  arg0_ti.get_compression() == arg1_ti.get_compression() &&
1289  arg1_ti.get_input_srid() == arg1_ti.get_output_srid()) {
1290  // use the compressed version of ST_Contains
1291  function_name = "ST_cContains";
1292  }
1293  }
1294 
1295  std::string specialized_geofunc{function_name + suffix(arg0_ti.get_type()) +
1296  suffix(arg1_ti.get_type())};
1297 
1298  if (arg0_ti.get_subtype() == kGEOGRAPHY && arg0_ti.get_output_srid() == 4326) {
1299  // Need to call geodesic runtime functions
1300  if (function_name == "ST_Distance"sv) {
1301  if ((arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) ||
1302  (arg0_ti.get_type() == kLINESTRING && arg1_ti.get_type() == kPOINT) ||
1303  (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kLINESTRING)) {
1304  // Geodesic distance between points
1305  specialized_geofunc += "_Geodesic"s;
1306  } else {
1307  throw QueryNotSupported(function_name +
1308  " currently doesn't accept non-POINT geographies");
1309  }
1310  } else if (rex_function->getName() == "ST_Contains"sv) {
1311  // We currently don't have a geodesic implementation of ST_Contains,
1312  // allowing calls to a [less precise] cartesian implementation.
1313  } else {
1314  throw QueryNotSupported(function_name + " doesn't accept geographies");
1315  }
1316  } else if (function_name == "ST_Distance"sv && rex_function->size() == 3) {
1317  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1318  // Cartesian distance between points used by ST_DWithin - switch to faster Squared
1319  specialized_geofunc += "_Squared"s;
1320  }
1321  }
1322 
1323  // Add first input's compression mode and SRID args to enable on-the-fly
1324  // decompression/transforms
1325  Datum input_compression0;
1326  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1327  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1328  Datum input_srid0;
1329  input_srid0.intval = arg0_ti.get_input_srid();
1330  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1331 
1332  // Add second input's compression mode and SRID args to enable on-the-fly
1333  // decompression/transforms
1334  Datum input_compression1;
1335  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1336  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1337  Datum input_srid1;
1338  input_srid1.intval = arg1_ti.get_input_srid();
1339  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1340 
1341  // Add output SRID arg to enable on-the-fly transforms
1342  Datum output_srid;
1343  output_srid.intval = arg0_ti.get_output_srid();
1344  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1345 
1346  // Some geo distance functions will be injected with a short-circuit threshold.
1347  // Threshold value would come from Geo comparison operations or from other outer
1348  // geo operations, e.g. ST_DWithin
1349  // At this point, only ST_Distance_LineString_LineString requires a threshold arg.
1350  // TODO: Other combinations that involve LINESTRING, POLYGON and MULTIPOLYGON args
1351  // TODO: Inject threshold into ST_MaxDistance
1352  if (function_name == "ST_Distance"sv && arg0_ti.get_subtype() != kGEOGRAPHY &&
1353  (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT)) {
1354  if (threshold_expr) {
1355  if (threshold_expr->get_type_info().get_type() != kDOUBLE) {
1356  const auto& threshold_ti = SQLTypeInfo(kDOUBLE, false);
1357  threshold_expr = threshold_expr->add_cast(threshold_ti);
1358  }
1359  threshold_expr = fold_expr(threshold_expr.get());
1360  } else {
1361  Datum d;
1362  d.doubleval = 0.0;
1363  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1364  }
1365  geoargs.push_back(threshold_expr);
1366  }
1367 
1368  auto result =
1369  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1370  if (negate_result) {
1371  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, result);
1372  }
1373  if (compare_expr) {
1374  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, result, compare_expr);
1375  }
1376  return result;
1377 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
Definition: Logger.h:217
auto func_resolve
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
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
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
std::shared_ptr< Analyzer::Expr > ExpressionPtr
Definition: Analyzer.h:179
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
#define CHECK_GT(x, y)
Definition: Logger.h:221
int32_t intval
Definition: sqltypes.h:214
#define TOLERANCE_GEOINT32
std::string suffix(SQLTypes type)
Definition: Codegen.cpp:68
Definition: sqldefs.h:69
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:209
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 890 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateFunction(), and translateGeoFunctionArg().

893  {
894  if (rex_function->getName() != "ST_Equals"sv) {
895  throw QueryNotSupported(rex_function->getName() + " geo predicate is not supported");
896  }
897 #ifndef ENABLE_GEOS
898  throw QueryNotSupported(rex_function->getName() +
899  " geo predicate requires enabled GEOS support");
900 #endif
901  SQLTypeInfo arg0_ti;
902  auto geoargs0 = translateGeoFunctionArg(
903  rex_function->getOperand(0), arg0_ti, false, false, true, true);
904  SQLTypeInfo arg1_ti;
905  auto geoargs1 = translateGeoFunctionArg(
906  rex_function->getOperand(1), arg1_ti, false, false, true, true);
907  ti = SQLTypeInfo(kBOOLEAN, false);
909  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
910 }
const RexScalar * getOperand(const size_t idx) 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
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 1307 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1308  {
1309  const auto ret_ti = rex_function->getType();
1310  const auto arg = translateScalarRex(rex_function->getOperand(0));
1311  const auto arg_ti = arg->get_type_info();
1312  if (!arg_ti.is_array()) {
1313  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1314  }
1315  if (arg_ti.get_subtype() == kARRAY) {
1316  throw std::runtime_error(rex_function->getName() +
1317  " expects one-dimension array expression.");
1318  }
1319  const auto array_size = arg_ti.get_size();
1320  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1321 
1322  if (array_size > 0) {
1323  if (array_elem_size <= 0) {
1324  throw std::runtime_error(rex_function->getName() +
1325  ": unexpected array element type.");
1326  }
1327  // Return cardinality of a fixed length array
1328  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1329  }
1330  // Variable length array cardinality will be calculated at runtime
1331  return makeExpr<Analyzer::CardinalityExpr>(arg);
1332 }
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 938 of file RelAlgTranslator.cpp.

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

Referenced by translateScalarRex().

939  {
940  std::shared_ptr<Analyzer::Expr> else_expr;
941  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
942  expr_list;
943  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
944  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
945  const auto then_expr = translateScalarRex(rex_case->getThen(i));
946  expr_list.emplace_back(when_expr, then_expr);
947  }
948  if (rex_case->getElse()) {
949  else_expr = translateScalarRex(rex_case->getElse());
950  }
951  return Parser::CaseExpr::normalize(expr_list, else_expr);
952 }
const RexScalar * getThen(const size_t idx) const
const RexScalar * getElse() const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getWhen(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 >)
Definition: ParserNode.cpp:963
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 1343 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1343  {
1344  constexpr bool is_null = false;
1345  Datum datum;
1346  datum.bigintval = now_ - now_ % (24 * 60 * 60); // Assumes 0 < now_.
1347  return makeExpr<Analyzer::Constant>(kDATE, is_null, datum);
1348 }
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 1350 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1350  {
1351  constexpr bool is_null = false;
1352  Datum datum;
1353  datum.bigintval = now_ % (24 * 60 * 60); // Assumes 0 < now_.
1354  return makeExpr<Analyzer::Constant>(kTIME, is_null, datum);
1355 }
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 1357 of file RelAlgTranslator.cpp.

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

Referenced by translateDatetime(), and translateFunction().

1357  {
1359 }
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:201

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

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

Referenced by translateFunction().

1284  {
1285  std::string user{"SESSIONLESS_USER"};
1286  if (query_state_) {
1287  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1288  }
1289  return Parser::UserLiteral::get(user);
1290 }
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:215
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 1112 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().

1113  {
1114  CHECK_EQ(size_t(3), rex_function->size());
1115  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1116  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1118  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1119  const auto number_units_const =
1120  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1121  if (number_units_const && number_units_const->get_is_null()) {
1122  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1123  }
1124  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1125  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1126  const auto& datetime_ti = datetime->get_type_info();
1127  if (datetime_ti.get_type() == kTIME) {
1128  throw std::runtime_error("DateAdd operation not supported for TIME.");
1129  }
1130  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1131  const int dim = datetime_ti.get_dimension();
1132  return makeExpr<Analyzer::DateaddExpr>(
1133  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1134 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 1227 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().

1228  {
1229  CHECK_EQ(size_t(3), rex_function->size());
1230  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1231  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1233  const auto start = translateScalarRex(rex_function->getOperand(1));
1234  const auto end = translateScalarRex(rex_function->getOperand(2));
1235  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1236  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1237 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 1239 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().

1240  {
1241  CHECK_EQ(size_t(2), rex_function->size());
1242  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1243  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1245  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1246  return ExtractExpr::generate(
1247  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1248 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 1145 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().

1146  {
1147  if (rex_operator->size() != 2) {
1148  return nullptr;
1149  }
1150  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1151  const auto datetime_ti = datetime->get_type_info();
1152  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1153  if (datetime_ti.get_type() == kTIME) {
1154  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1155  }
1156  return nullptr;
1157  }
1158  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1159  const auto rhs_ti = rhs->get_type_info();
1160  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1161  if (datetime_ti.is_high_precision_timestamp() ||
1162  rhs_ti.is_high_precision_timestamp()) {
1163  throw std::runtime_error(
1164  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1165  "Use "
1166  "DATEDIFF.");
1167  }
1168  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1169  const auto& rex_operator_ti = rex_operator->getType();
1170  const auto datediff_field =
1171  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1172  auto result =
1173  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1174  // multiply 1000 to result since expected result should be in millisecond precision.
1175  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1176  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1177  kMULTIPLY,
1178  kONE,
1179  result,
1180  makeNumericConstant(bigint_ti, 1000));
1181  } else {
1182  return result;
1183  }
1184  }
1185  const auto op = rex_operator->getOperator();
1186  if (op == kPLUS) {
1187  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1188  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1189  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1190  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1191  if (date_trunc) {
1192  return date_trunc;
1193  }
1194  }
1195  const auto interval = fold_expr(rhs.get());
1196  auto interval_ti = interval->get_type_info();
1197  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1198  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1199  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1200  std::shared_ptr<Analyzer::Expr> interval_sec;
1201  if (interval_lit) {
1202  interval_sec =
1203  makeNumericConstant(bigint_ti,
1204  (op == kMINUS ? -interval_lit->get_constval().bigintval
1205  : interval_lit->get_constval().bigintval) /
1206  1000);
1207  } else {
1208  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1209  kDIVIDE,
1210  kONE,
1211  interval,
1212  makeNumericConstant(bigint_ti, 1000));
1213  if (op == kMINUS) {
1214  interval_sec =
1215  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1216  }
1217  }
1218  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1219  }
1220  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1221  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1222  bigint_ti, false, kUMINUS, interval)
1223  : interval;
1224  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1225 }
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:69
#define CHECK(condition)
Definition: Logger.h:209
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 1361 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1362  {
1363  CHECK_EQ(size_t(1), rex_function->size());
1364  const auto arg = translateScalarRex(rex_function->getOperand(0));
1365  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1366  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1367  if (!arg_lit || arg_lit->get_is_null()) {
1368  throw std::runtime_error(datetime_err);
1369  }
1370  CHECK(arg_lit->get_type_info().is_string());
1371  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1372  throw std::runtime_error(datetime_err);
1373  }
1374  return translateCurrentTimestamp();
1375 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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:209

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

1054  {
1055  CHECK_EQ(size_t(2), rex_function->size());
1056  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1057  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1059  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1060  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
1061  if (is_date_trunc) {
1062  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1063  } else {
1064  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
1065  }
1066 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 1474 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, bind_function(), CHECK, CHECK_EQ, ext_arg_type_to_type_info(), func_resolve, g_enable_experimental_string_functions, RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), i, SQLTypeInfo::is_decimal(), kDIVIDE, kONE, kSMALLINT, kTEXT, LOG, Parser::OperExpr::normalize(), rewrite_to_date_trunc(), SQLTypeInfo::set_notnull(), RexOperator::size(), Datum::smallintval, t, translateAbs(), translateArrayFunction(), translateBinaryGeoConstructor(), translateBinaryGeoFunction(), translateBinaryGeoPredicate(), translateCardinality(), translateCurrentDate(), translateCurrentTime(), translateCurrentTimestamp(), translateCurrentUser(), translateDateadd(), translateDatediff(), translateDatepart(), translateDatetime(), translateExtract(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoProjection(), translateHPTLiteral(), translateItem(), translateKeyForString(), translateLength(), translateLike(), translateLikely(), translateLower(), translateOffsetInFragment(), translateRegexp(), translateSampleRatio(), translateScalarRex(), translateSign(), translateTernaryGeoFunction(), translateUnaryGeoFunction(), translateUnaryGeoPredicate(), translateUnlikely(), translateWidthBucket(), and logger::WARNING.

Referenced by translateScalarRex().

1475  {
1476  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1477  return translateLike(rex_function);
1478  }
1479  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1480  return translateRegexp(rex_function);
1481  }
1482  if (rex_function->getName() == "LIKELY"sv) {
1483  return translateLikely(rex_function);
1484  }
1485  if (rex_function->getName() == "UNLIKELY"sv) {
1486  return translateUnlikely(rex_function);
1487  }
1488  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1489  return translateExtract(rex_function);
1490  }
1491  if (rex_function->getName() == "DATEADD"sv) {
1492  return translateDateadd(rex_function);
1493  }
1494  if (rex_function->getName() == "DATEDIFF"sv) {
1495  return translateDatediff(rex_function);
1496  }
1497  if (rex_function->getName() == "DATEPART"sv) {
1498  return translateDatepart(rex_function);
1499  }
1500  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1501  return translateLength(rex_function);
1502  }
1503  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1504  return translateKeyForString(rex_function);
1505  }
1506  if (rex_function->getName() == "WIDTH_BUCKET"sv) {
1507  return translateWidthBucket(rex_function);
1508  }
1509  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1510  return translateSampleRatio(rex_function);
1511  }
1512  if (rex_function->getName() == "CURRENT_USER"sv) {
1513  return translateCurrentUser(rex_function);
1514  }
1515  if (g_enable_experimental_string_functions && rex_function->getName() == "LOWER"sv) {
1516  return translateLower(rex_function);
1517  }
1518  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1519  return translateCardinality(rex_function);
1520  }
1521  if (rex_function->getName() == "ITEM"sv) {
1522  return translateItem(rex_function);
1523  }
1524  if (rex_function->getName() == "CURRENT_DATE"sv) {
1525  return translateCurrentDate();
1526  }
1527  if (rex_function->getName() == "CURRENT_TIME"sv) {
1528  return translateCurrentTime();
1529  }
1530  if (rex_function->getName() == "CURRENT_TIMESTAMP"sv) {
1531  return translateCurrentTimestamp();
1532  }
1533  if (rex_function->getName() == "NOW"sv) {
1534  return translateCurrentTimestamp();
1535  }
1536  if (rex_function->getName() == "DATETIME"sv) {
1537  return translateDatetime(rex_function);
1538  }
1539  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1540  return translateHPTLiteral(rex_function);
1541  }
1542  if (rex_function->getName() == "ABS"sv) {
1543  return translateAbs(rex_function);
1544  }
1545  if (rex_function->getName() == "SIGN"sv) {
1546  return translateSign(rex_function);
1547  }
1548  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1549  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1550  rex_function->getType(),
1551  rex_function->getName(),
1552  translateFunctionArgs(rex_function));
1553  } else if (rex_function->getName() == "ROUND"sv) {
1554  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1555  translateFunctionArgs(rex_function);
1556 
1557  if (rex_function->size() == 1) {
1558  // push a 0 constant if 2nd operand is missing.
1559  // this needs to be done as calcite returns
1560  // only the 1st operand without defaulting the 2nd one
1561  // when the user did not specify the 2nd operand.
1562  SQLTypes t = kSMALLINT;
1563  Datum d;
1564  d.smallintval = 0;
1565  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1566  }
1567 
1568  // make sure we have only 2 operands
1569  CHECK(args.size() == 2);
1570 
1571  if (!args[0]->get_type_info().is_number()) {
1572  throw std::runtime_error("Only numeric 1st operands are supported");
1573  }
1574 
1575  // the 2nd operand does not need to be a constant
1576  // it can happily reference another integer column
1577  if (!args[1]->get_type_info().is_integer()) {
1578  throw std::runtime_error("Only integer 2nd operands are supported");
1579  }
1580 
1581  // Calcite may upcast decimals in a way that is
1582  // incompatible with the extension function input. Play it safe and stick with the
1583  // argument type instead.
1584  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1585  ? args[0]->get_type_info()
1586  : rex_function->getType();
1587 
1588  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1589  ret_ti, rex_function->getName(), args);
1590  }
1591  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1592  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1593  rex_function->getName(),
1594  translateFunctionArgs(rex_function));
1595  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1596  if (date_trunc) {
1597  return date_trunc;
1598  }
1599  return translateDateadd(rex_function);
1600  }
1601  if (rex_function->getName() == "/INT"sv) {
1602  CHECK_EQ(size_t(2), rex_function->size());
1603  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1604  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1605  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1606  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1607  }
1608  if (rex_function->getName() == "Reinterpret"sv) {
1609  CHECK_EQ(size_t(1), rex_function->size());
1610  return translateScalarRex(rex_function->getOperand(0));
1611  }
1612  if (func_resolve(rex_function->getName(),
1613  "ST_X"sv,
1614  "ST_Y"sv,
1615  "ST_XMin"sv,
1616  "ST_YMin"sv,
1617  "ST_XMax"sv,
1618  "ST_YMax"sv,
1619  "ST_NRings"sv,
1620  "ST_NPoints"sv,
1621  "ST_Length"sv,
1622  "ST_Perimeter"sv,
1623  "ST_Area"sv,
1624  "ST_SRID"sv,
1625  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
1626  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
1627  "OmniSci_Geo_PolyBoundsPtr"sv,
1628  "OmniSci_Geo_PolyRenderGroup"sv)) {
1629  CHECK_EQ(rex_function->size(), size_t(1));
1630  return translateUnaryGeoFunction(rex_function);
1631  }
1632  if (func_resolve(rex_function->getName(),
1633  "convert_meters_to_pixel_width"sv,
1634  "convert_meters_to_pixel_height"sv,
1635  "is_point_in_view"sv,
1636  "is_point_size_in_view"sv)) {
1637  return translateFunctionWithGeoArg(rex_function);
1638  }
1639  if (func_resolve(rex_function->getName(),
1640  "ST_Distance"sv,
1641  "ST_MaxDistance"sv,
1642  "ST_Intersects"sv,
1643  "ST_Disjoint"sv,
1644  "ST_Contains"sv,
1645  "ST_Overlaps"sv,
1646  "ST_Approx_Overlaps"sv,
1647  "ST_Within"sv)) {
1648  CHECK_EQ(rex_function->size(), size_t(2));
1649  return translateBinaryGeoFunction(rex_function);
1650  }
1651  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
1652  CHECK_EQ(rex_function->size(), size_t(3));
1653  return translateTernaryGeoFunction(rex_function);
1654  }
1655  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
1656  CHECK_EQ(size_t(0), rex_function->size());
1657  return translateOffsetInFragment();
1658  }
1659  if (rex_function->getName() == "ARRAY"sv) {
1660  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1661  return translateArrayFunction(rex_function);
1662  }
1663  if (func_resolve(rex_function->getName(),
1664  "ST_GeomFromText"sv,
1665  "ST_GeogFromText"sv,
1666  "ST_Centroid"sv,
1667  "ST_SetSRID"sv,
1668  "ST_Point"sv, // TODO: where should this and below live?
1669  "ST_PointN"sv,
1670  "ST_StartPoint"sv,
1671  "ST_EndPoint"sv,
1672  "ST_Transform"sv)) {
1673  SQLTypeInfo ti;
1674  return translateGeoProjection(rex_function, ti, false);
1675  }
1676  if (func_resolve(rex_function->getName(),
1677  "ST_Intersection"sv,
1678  "ST_Difference"sv,
1679  "ST_Union"sv,
1680  "ST_Buffer"sv)) {
1681  SQLTypeInfo ti;
1682  return translateBinaryGeoConstructor(rex_function, ti, false);
1683  }
1684  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
1685  CHECK_EQ(rex_function->size(), size_t(1));
1686  SQLTypeInfo ti;
1687  return translateUnaryGeoPredicate(rex_function, ti, false);
1688  }
1689  if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
1690  CHECK_EQ(rex_function->size(), size_t(2));
1691  // Attempt to generate a distance based check for points
1692  if (auto distance_check = translateBinaryGeoFunction(rex_function)) {
1693  return distance_check;
1694  }
1695  SQLTypeInfo ti;
1696  return translateBinaryGeoPredicate(rex_function, ti, false);
1697  }
1698 
1699  auto arg_expr_list = translateFunctionArgs(rex_function);
1700  if (rex_function->getName() == std::string("||") ||
1701  rex_function->getName() == std::string("SUBSTRING")) {
1702  SQLTypeInfo ret_ti(kTEXT, false);
1703  return makeExpr<Analyzer::FunctionOper>(
1704  ret_ti, rex_function->getName(), arg_expr_list);
1705  }
1706  // Reset possibly wrong return type of rex_function to the return
1707  // type of the optimal valid implementation. The return type can be
1708  // wrong in the case of multiple implementations of UDF functions
1709  // that have different return types but Calcite specifies the return
1710  // type according to the first implementation.
1711  SQLTypeInfo ret_ti;
1712  try {
1713  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1714 
1715  auto ext_func_args = ext_func_sig.getArgs();
1716  CHECK_EQ(arg_expr_list.size(), ext_func_args.size());
1717  for (size_t i = 0; i < arg_expr_list.size(); i++) {
1718  // fold casts on constants
1719  if (auto constant =
1720  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
1721  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_args[i]);
1722  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
1723  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
1724  }
1725  }
1726  }
1727 
1728  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
1729  } catch (ExtensionFunctionBindingError& e) {
1730  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
1731  throw;
1732  }
1733 
1734  // By default, the extension function type will not allow nulls. If one of the arguments
1735  // is nullable, the extension function must also explicitly allow nulls.
1736  bool arguments_not_null = true;
1737  for (const auto& arg_expr : arg_expr_list) {
1738  if (!arg_expr->get_type_info().get_notnull()) {
1739  arguments_not_null = false;
1740  break;
1741  }
1742  }
1743  ret_ti.set_notnull(arguments_not_null);
1744 
1745  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
1746 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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:203
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
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 > translateLower(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatetime(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)
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)
Definition: ParserNode.cpp:291
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:69
std::shared_ptr< Analyzer::Expr > translateArrayFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateCurrentUser(const RexFunctionOperator *) const
bool g_enable_experimental_string_functions
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:426
#define CHECK(condition)
Definition: Logger.h:209
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
char * t
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:512
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 1827 of file RelAlgTranslator.cpp.

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

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

1828  {
1829  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1830  for (size_t i = 0; i < rex_function->size(); ++i) {
1831  args.push_back(translateScalarRex(rex_function->getOperand(i)));
1832  }
1833  return args;
1834 }
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 1505 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().

1506  {
1507  std::string specialized_geofunc{rex_function->getName()};
1508  if (func_resolve(rex_function->getName(),
1509  "convert_meters_to_pixel_width"sv,
1510  "convert_meters_to_pixel_height"sv)) {
1511  CHECK_EQ(rex_function->size(), 6u);
1512  SQLTypeInfo arg_ti;
1513  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1514  args.push_back(translateScalarRex(rex_function->getOperand(0)));
1515  auto geoargs =
1516  translateGeoFunctionArg(rex_function->getOperand(1), arg_ti, false, true, false);
1517  // only works on points
1518  if (arg_ti.get_type() != kPOINT) {
1519  throw QueryNotSupported(rex_function->getName() +
1520  " expects a point for the second argument");
1521  }
1522 
1523  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1524 
1525  // Add compression information
1526  Datum input_compression;
1527  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1528  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1529  if (arg_ti.get_input_srid() != 4326) {
1530  throw QueryNotSupported(
1531  rex_function->getName() +
1532  " currently only supports points of with SRID WGS84/EPSG:4326");
1533  }
1534  Datum input_srid;
1535  input_srid.intval = arg_ti.get_input_srid();
1536  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1537  Datum output_srid;
1538  // Forcing web-mercator projection for now
1539  // TODO(croot): check that the input-to-output conversion routines exist?
1540  output_srid.intval =
1541  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1542  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1543 
1544  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1545  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1546  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1547  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1548  return makeExpr<Analyzer::FunctionOper>(
1549  rex_function->getType(), specialized_geofunc, args);
1550  } else if (rex_function->getName() == "is_point_in_view"sv) {
1551  CHECK_EQ(rex_function->size(), 5u);
1552  SQLTypeInfo arg_ti;
1553  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1554  auto geoargs =
1555  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
1556  // only works on points
1557  if (arg_ti.get_type() != kPOINT) {
1558  throw QueryNotSupported(rex_function->getName() +
1559  " expects a point for the second argument");
1560  }
1561 
1562  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1563 
1564  // Add compression information
1565  Datum input_compression;
1566  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1567  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1568  if (arg_ti.get_input_srid() != 4326) {
1569  throw QueryNotSupported(
1570  rex_function->getName() +
1571  " currently only supports points of with SRID WGS84/EPSG:4326");
1572  }
1573  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1574  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1575  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1576  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1577  return makeExpr<Analyzer::FunctionOper>(
1578  rex_function->getType(), specialized_geofunc, args);
1579  } else if (rex_function->getName() == "is_point_size_in_view"sv) {
1580  CHECK_EQ(rex_function->size(), 6u);
1581  SQLTypeInfo arg_ti;
1582  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1583  auto geoargs =
1584  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
1585  // only works on points
1586  if (arg_ti.get_type() != kPOINT) {
1587  throw QueryNotSupported(rex_function->getName() +
1588  " expects a point for the second argument");
1589  }
1590 
1591  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1592 
1593  // Add compression information
1594  Datum input_compression;
1595  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1596  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1597  if (arg_ti.get_input_srid() != 4326) {
1598  throw QueryNotSupported(
1599  rex_function->getName() +
1600  " currently only supports points of with SRID WGS84/EPSG:4326");
1601  }
1602  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1603  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1604  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1605  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1606  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1607  return makeExpr<Analyzer::FunctionOper>(
1608  rex_function->getType(), specialized_geofunc, args);
1609  }
1610  CHECK(false);
1611  return nullptr;
1612 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
auto func_resolve
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::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
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:209
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 26 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(), i, input_to_nest_level_, IS_GEO, and SPIMAP_GEO_PHYSICAL_INPUT.

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

31  {
32  std::vector<std::shared_ptr<Analyzer::Expr>> args;
33  const auto source = rex_input->getSourceNode();
34  const auto it_rte_idx = input_to_nest_level_.find(source);
35  CHECK(it_rte_idx != input_to_nest_level_.end());
36  const int rte_idx = it_rte_idx->second;
37  const auto& in_metainfo = source->getOutputMetainfo();
38 
39  int32_t table_id{0};
40  int column_id{-1};
41  const auto scan_source = dynamic_cast<const RelScan*>(source);
42  if (scan_source) {
43  // We're at leaf (scan) level and not supposed to have input metadata,
44  // the name and type information come directly from the catalog.
45  CHECK(in_metainfo.empty());
46 
47  const auto td = scan_source->getTableDescriptor();
48  table_id = td->tableId;
49 
50  const auto gcd = cat_.getMetadataForColumnBySpi(table_id, rex_input->getIndex() + 1);
51  CHECK(gcd);
52  ti = gcd->columnType;
53  column_id = gcd->columnId;
54 
55  } else {
56  // Likely backed by a temp table. Read the table ID from the source node and negate it
57  // (see RelAlgTranslator::translateInput)
58  table_id = -source->getId();
59 
60  CHECK(!expand_geo_col);
61  if (with_bounds || with_render_group) {
62  throw QueryNotSupported(
63  "Geospatial columns not yet supported in intermediate results.");
64  }
65 
66  CHECK(!in_metainfo.empty());
67  CHECK_GE(rte_idx, 0);
68  column_id = rex_input->getIndex();
69  CHECK_LT(static_cast<size_t>(column_id), in_metainfo.size());
70  ti = in_metainfo[column_id].get_type_info();
71  }
72  CHECK(IS_GEO(ti.get_type()));
73 
74  // Return geo column reference. The geo column may be expanded if required for extension
75  // function arguments. Otherwise, the geo column reference will be translated into
76  // physical columns as required. Bounds column will be added if present and requested.
77  if (expand_geo_col) {
78  for (auto i = 0; i < ti.get_physical_coord_cols(); i++) {
79  const auto pcd = cat_.getMetadataForColumnBySpi(
80  table_id, SPIMAP_GEO_PHYSICAL_INPUT(rex_input->getIndex(), i + 1));
81  auto pcol_ti = pcd->columnType;
82  args.push_back(std::make_shared<Analyzer::ColumnVar>(
83  pcol_ti, table_id, pcd->columnId, rte_idx));
84  }
85  } else {
86  args.push_back(
87  std::make_shared<Analyzer::ColumnVar>(ti, table_id, column_id, rte_idx));
88  }
89  if (with_bounds && ti.has_bounds()) {
90  const auto bounds_cd = cat_.getMetadataForColumnBySpi(
91  table_id,
93  ti.get_physical_coord_cols() + 1));
94  auto bounds_ti = bounds_cd->columnType;
95  args.push_back(std::make_shared<Analyzer::ColumnVar>(
96  bounds_ti, table_id, bounds_cd->columnId, rte_idx));
97  }
98  if (with_render_group && ti.has_render_group()) {
99  const auto render_group_cd = cat_.getMetadataForColumnBySpi(
100  table_id,
101  SPIMAP_GEO_PHYSICAL_INPUT(rex_input->getIndex(),
102  ti.get_physical_coord_cols() + 2));
103  auto render_group_ti = render_group_cd->columnType;
104  args.push_back(std::make_shared<Analyzer::ColumnVar>(
105  render_group_ti, table_id, render_group_cd->columnId, rte_idx));
106  }
107  return args;
108 }
#define SPIMAP_GEO_PHYSICAL_INPUT(c, i)
Definition: Catalog.h:77
#define CHECK_GE(x, y)
Definition: Logger.h:222
unsigned getIndex() const
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
Definition: Catalog.cpp:1623
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:219
const RelAlgNode * getSourceNode() const
#define CHECK(condition)
Definition: Logger.h:209
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 1484 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateOper().

1485  {
1486  if (rex_operator->size() != size_t(2)) {
1487  return nullptr;
1488  }
1489 
1490  auto geo_distance_expr = translateScalarRex(rex_operator->getOperand(0));
1491  auto func_oper = dynamic_cast<Analyzer::GeoOperator*>(geo_distance_expr.get());
1492  if (func_oper && func_oper->getName() == "ST_Distance"sv) {
1493  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1494  auto distance_expr = translateScalarRex(rex_operator->getOperand(1));
1495  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1496  distance_expr = distance_expr->add_cast(distance_ti);
1497  }
1498  distance_expr = fold_expr(distance_expr.get());
1499  return makeExpr<Analyzer::BinOper>(
1500  kBOOLEAN, rex_operator->getOperator(), kONE, geo_distance_expr, distance_expr);
1501  }
1502  return nullptr;
1503 }
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:69
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
private

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

256  {
257  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
258 
259  const auto rex_input = dynamic_cast<const RexInput*>(rex_scalar);
260  if (rex_input) {
261  const auto input = translateInput(rex_input);
262  const auto column = dynamic_cast<const Analyzer::ColumnVar*>(input.get());
263  if (!column || !column->get_type_info().is_geometry()) {
264  throw QueryNotSupported("Geo function is expecting a geo column argument");
265  }
266  if (use_geo_expressions) {
267  return {makeExpr<Analyzer::GeoColumnVar>(column, with_bounds, with_render_group)};
268  }
269  return translateGeoColumn(
270  rex_input, arg_ti, with_bounds, with_render_group, expand_geo_col);
271  }
272  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_scalar);
273  if (rex_function) {
274  if (rex_function->getName() == "ST_Transform"sv) {
275  CHECK_EQ(size_t(2), rex_function->size());
276  const auto rex_scalar0 =
277  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
278  if (!rex_scalar0) {
279  throw QueryNotSupported(rex_function->getName() + ": unexpected first argument");
280  }
281 
282  const auto rex_literal =
283  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
284  if (!rex_literal) {
285  throw QueryNotSupported(rex_function->getName() +
286  ": second argument is expected to be a literal");
287  }
288  const auto e = translateLiteral(rex_literal);
289  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
290  if (!ce || !e->get_type_info().is_integer()) {
291  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
292  }
293  int32_t srid = 0;
294  if (e->get_type_info().get_type() == kSMALLINT) {
295  srid = static_cast<int32_t>(ce->get_constval().smallintval);
296  } else if (e->get_type_info().get_type() == kTINYINT) {
297  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
298  } else if (e->get_type_info().get_type() == kINT) {
299  srid = static_cast<int32_t>(ce->get_constval().intval);
300  } else {
301  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
302  }
303  if (srid != 900913 && ((use_geo_expressions || is_projection) && srid != 4326 &&
305  throw QueryNotSupported(rex_function->getName() + ": unsupported output SRID " +
306  std::to_string(srid));
307  }
308  arg_ti.set_output_srid(srid); // Forward output srid down to argument translation
309  auto arg0 = translateGeoFunctionArg(
310  rex_scalar0,
311  arg_ti,
312  with_bounds,
313  with_render_group,
314  expand_geo_col,
315  is_projection,
316  is_projection ? /*use_geo_expressions=*/true : use_geo_expressions);
317 
318  if (use_geo_expressions) {
319  CHECK_EQ(arg0.size(), size_t(1));
320  auto arg0_ti = arg0.front()->get_type_info(); // make a copy so we can override
321  arg0_ti.set_output_srid(srid);
322  if (arg0_ti.get_type() == kPOINT) {
323  // geo transforms projections leave the result decompressed in a register
324  arg0_ti.set_compression(kENCODING_NONE);
325  arg0_ti.set_comp_param(0);
326  return {makeExpr<Analyzer::GeoTransformOperator>(
327  arg0_ti, rex_function->getName(), arg0, arg0_ti.get_input_srid(), srid)};
328  } else {
329  if (auto geo_constant =
330  std::dynamic_pointer_cast<Analyzer::GeoConstant>(arg0.front())) {
331  // fold transform
332  return {geo_constant->add_cast(arg0_ti)};
333  } else if (auto col_var =
334  std::dynamic_pointer_cast<Analyzer::ColumnVar>(arg0.front())) {
335  const auto& col_ti = col_var->get_type_info();
336  CHECK(col_ti.is_geometry());
337  if (col_ti.get_type() != kPOINT) {
338  arg_ti.set_input_srid(col_ti.get_input_srid());
339  // fall through to transform code below
340  }
341  } else {
342  throw std::runtime_error(
343  "Transform on non-POINT geospatial types not yet supported in this "
344  "context.");
345  }
346  }
347  }
348 
349  if (arg_ti.get_input_srid() > 0) {
350  if (arg_ti.get_input_srid() != 4326) {
351  throw QueryNotSupported(rex_function->getName() + ": unsupported input SRID " +
352  std::to_string(arg_ti.get_input_srid()));
353  }
354  arg_ti.set_output_srid(
355  srid); // We have a valid input SRID, register the output SRID for transform
356  } else {
357  throw QueryNotSupported(rex_function->getName() +
358  ": unexpected input SRID, unable to transform");
359  }
360  return arg0;
361  } else if (func_resolve(
362  rex_function->getName(), "ST_GeomFromText"sv, "ST_GeogFromText"sv)) {
363  CHECK(rex_function->size() == size_t(1) || rex_function->size() == size_t(2));
364  if (use_geo_expressions) {
365  int32_t srid = 0;
366  if (rex_function->size() == 2) {
367  // user supplied srid
368  const auto rex_literal =
369  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
370  if (!rex_literal) {
371  throw QueryNotSupported(rex_function->getName() +
372  ": second argument is expected to be a literal");
373  }
374  const auto e = translateLiteral(rex_literal);
375  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
376  if (!ce || !e->get_type_info().is_integer()) {
377  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
378  }
379  if (e->get_type_info().get_type() == kSMALLINT) {
380  srid = static_cast<int32_t>(ce->get_constval().smallintval);
381  } else if (e->get_type_info().get_type() == kTINYINT) {
382  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
383  } else if (e->get_type_info().get_type() == kINT) {
384  srid = static_cast<int32_t>(ce->get_constval().intval);
385  } else {
386  throw QueryNotSupported(rex_function->getName() + " expecting integer SRID");
387  }
388  if (srid != 0 && srid != 4326 && srid != 900913) {
389  throw QueryNotSupported(rex_function->getName() + ": unsupported SRID " +
390  std::to_string(srid));
391  }
392  }
393  arg_ti.set_input_srid(srid); // Input SRID
394  // leave the output srid unset in case a transform was above us
395 
396  if (rex_function->getName() == "ST_GeogFromText"sv) {
397  arg_ti.set_subtype(kGEOGRAPHY);
398  }
399 
400  auto func_args = translateGeoFunctionArg(rex_function->getOperand(0),
401  arg_ti,
402  with_bounds,
403  with_render_group,
404  expand_geo_col,
405  is_projection,
406  use_geo_expressions);
407  CHECK_GE(func_args.size(), size_t(1));
408  return func_args;
409  }
410 
411  // First - register srid, then send it to geo literal translation
412  int32_t srid = 0;
413  if (rex_function->size() == 2) {
414  const auto rex_literal =
415  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
416  if (!rex_literal) {
417  throw QueryNotSupported(rex_function->getName() +
418  ": second argument is expected to be a literal");
419  }
420  const auto e = translateLiteral(rex_literal);
421  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
422  if (!ce || !e->get_type_info().is_integer()) {
423  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
424  }
425  if (e->get_type_info().get_type() == kSMALLINT) {
426  srid = static_cast<int32_t>(ce->get_constval().smallintval);
427  } else if (e->get_type_info().get_type() == kTINYINT) {
428  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
429  } else if (e->get_type_info().get_type() == kINT) {
430  srid = static_cast<int32_t>(ce->get_constval().intval);
431  } else {
432  throw QueryNotSupported(rex_function->getName() + " expecting integer SRID");
433  }
434  if (srid != 0 && srid != 4326 && srid != 900913) {
435  throw QueryNotSupported(rex_function->getName() + ": unsupported SRID " +
436  std::to_string(srid));
437  }
438  }
439  arg_ti.set_input_srid(srid); // Input SRID
440  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
441 
442  const auto rex_literal =
443  dynamic_cast<const RexLiteral*>(rex_function->getOperand(0));
444  if (!rex_literal) {
445  throw QueryNotSupported(rex_function->getName() +
446  " expects a string literal as first argument");
447  }
448  auto arg0 = translateGeoLiteral(rex_literal, arg_ti, with_bounds);
449  arg_ti.set_subtype((rex_function->getName() == "ST_GeogFromText"sv) ? kGEOGRAPHY
450  : kGEOMETRY);
451  return arg0;
452  } else if (rex_function->getName() == "ST_PointN"sv) {
453  // uses geo expressions
454  const auto rex_scalar0 =
455  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
456  if (!rex_scalar0) {
457  throw QueryNotSupported(rex_function->getName() +
458  ": expects scalar as first argument");
459  }
460  auto arg0 = translateGeoFunctionArg(rex_scalar0,
461  arg_ti,
462  with_bounds,
463  with_render_group,
464  expand_geo_col,
465  /*is_projection=*/false,
466  /*use_geo_expressions=*/true);
467  CHECK_EQ(arg0.size(), size_t(1));
468  CHECK(arg0.front());
469  if (arg0.front()->get_type_info().get_type() != kLINESTRING) {
470  throw QueryNotSupported(rex_function->getName() +
471  " expects LINESTRING as first argument");
472  }
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() +
483  ": expecting integer index as second argument");
484  }
485  int32_t index = 0;
486  if (e->get_type_info().get_type() == kSMALLINT) {
487  index = static_cast<int32_t>(ce->get_constval().smallintval);
488  } else if (e->get_type_info().get_type() == kTINYINT) {
489  index = static_cast<int32_t>(ce->get_constval().tinyintval);
490  } else if (e->get_type_info().get_type() == kINT) {
491  index = static_cast<int32_t>(ce->get_constval().intval);
492  } else {
493  throw QueryNotSupported(rex_function->getName() + " expecting integer index");
494  }
495  if (index == 0) {
496  // maybe we will just return NULL here?
497  throw QueryNotSupported(rex_function->getName() + ": invalid index");
498  }
499  arg0.push_back(e);
500  auto oper_ti =
501  arg0.front()->get_type_info(); // make a copy so we can reset nullness and type
502  oper_ti.set_type(kPOINT);
503  oper_ti.set_notnull(false);
504 
505  arg_ti = oper_ti; // TODO: remove
506 
507  return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), arg0)};
508 
509  } else if (rex_function->getName() == "ST_StartPoint"sv ||
510  rex_function->getName() == "ST_EndPoint"sv) {
511  std::vector<std::shared_ptr<Analyzer::Expr>> args;
512  CHECK_EQ(size_t(1), rex_function->size());
513  const auto arg_exprs = translateGeoFunctionArg(rex_function->getOperand(0),
514  arg_ti,
515  with_bounds,
516  with_render_group,
517  expand_geo_col,
518  is_projection,
519  /*use_geo_expressions=*/true);
520  CHECK_EQ(arg_exprs.size(), size_t(1));
521  CHECK(arg_exprs.front());
522  const auto arg_expr_ti = arg_exprs.front()->get_type_info();
523  if (arg_expr_ti.get_type() != kLINESTRING) {
524  throw QueryNotSupported(rex_function->getName() +
525  " expected LINESTRING argument. Received " +
526  arg_expr_ti.toString());
527  }
528  args.push_back(arg_exprs.front());
529 
530  auto oper_ti = args.back()->get_type_info(); // make a copy so we can override type
531  oper_ti.set_type(kPOINT);
532 
533  arg_ti = oper_ti; // TODO: remove
534 
535  return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), args)};
536  } else if (rex_function->getName() == "ST_SRID"sv) {
537  CHECK_EQ(size_t(1), rex_function->size());
538  const auto rex_scalar0 =
539  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
540  if (!rex_scalar0) {
541  throw QueryNotSupported(rex_function->getName() +
542  ": expects scalar as first argument");
543  }
544  auto arg0 = translateGeoFunctionArg(
545  rex_scalar0, arg_ti, with_bounds, with_render_group, expand_geo_col);
546  if (!IS_GEO(arg_ti.get_type())) {
547  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
548  }
549  return arg0;
550  } else if (rex_function->getName() == "ST_SetSRID"sv) {
551  CHECK_EQ(size_t(2), rex_function->size());
552  const auto rex_literal =
553  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
554  if (!rex_literal) {
555  throw QueryNotSupported(rex_function->getName() +
556  ": second argument is expected to be a literal");
557  }
558  const auto e = translateLiteral(rex_literal);
559  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
560  if (!ce || !e->get_type_info().is_integer()) {
561  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
562  }
563  int32_t srid = 0;
564  if (e->get_type_info().get_type() == kSMALLINT) {
565  srid = static_cast<int32_t>(ce->get_constval().smallintval);
566  } else if (e->get_type_info().get_type() == kTINYINT) {
567  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
568  } else if (e->get_type_info().get_type() == kINT) {
569  srid = static_cast<int32_t>(ce->get_constval().intval);
570  } else {
571  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
572  }
573 
574  const auto rex_scalar0 =
575  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
576  if (!rex_scalar0) {
577  throw QueryNotSupported(rex_function->getName() +
578  ": expects scalar as first argument");
579  }
580 
581  // Only convey the request to compress if dealing with 4326 geo
582  auto arg0 = translateGeoFunctionArg(rex_scalar0,
583  arg_ti,
584  with_bounds,
585  with_render_group,
586  expand_geo_col,
587  is_projection,
588  use_geo_expressions,
589  (try_to_compress && (srid == 4326)));
590 
591  CHECK(!arg0.empty() && arg0.front());
592  if (!IS_GEO(arg_ti.get_type()) && !use_geo_expressions) {
593  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
594  }
595  arg_ti.set_input_srid(srid); // Input SRID
596  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
597  if (auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
598  CHECK_EQ(arg0.size(), size_t(1));
599  auto ti = geo_expr->get_type_info();
600  ti.set_input_srid(srid);
601  ti.set_output_srid(srid);
602  return {geo_expr->add_cast(ti)};
603  }
604  return arg0;
605  } else if (rex_function->getName() == "CastToGeography"sv) {
606  CHECK_EQ(size_t(1), rex_function->size());
607  const auto rex_scalar0 =
608  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
609  if (!rex_scalar0) {
610  throw QueryNotSupported(rex_function->getName() +
611  ": expects scalar as first argument");
612  }
613  auto arg0 = translateGeoFunctionArg(rex_scalar0,
614  arg_ti,
615  with_bounds,
616  with_render_group,
617  expand_geo_col,
618  /*is_projection=*/false,
619  use_geo_expressions);
620  CHECK(!arg0.empty());
621  if (auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
622  auto arg_ti = geo_expr->get_type_info(); // make a copy
623  arg_ti.set_subtype(kGEOGRAPHY);
624  return {geo_expr->add_cast(arg_ti)};
625  }
626  if (use_geo_expressions) {
627  arg_ti = arg0.front()->get_type_info();
628  arg_ti.set_subtype(kGEOGRAPHY);
629  arg0.front()->set_type_info(arg_ti);
630  }
631  if (!IS_GEO(arg_ti.get_type())) {
632  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
633  }
634  if (arg_ti.get_output_srid() != 4326) {
635  throw QueryNotSupported(rex_function->getName() +
636  " expects geometry with SRID=4326");
637  }
638  arg_ti.set_subtype(kGEOGRAPHY);
639  return arg0;
640  } else if (rex_function->getName() == "ST_Point"sv) {
641  CHECK_EQ(size_t(2), rex_function->size());
642  arg_ti.set_type(kPOINT);
643  arg_ti.set_subtype(kGEOMETRY);
644  arg_ti.set_input_srid(0);
645  arg_ti.set_output_srid(0);
647 
648  auto coord1 = translateScalarRex(rex_function->getOperand(0));
649  auto coord2 = translateScalarRex(rex_function->getOperand(1));
650  auto d_ti = SQLTypeInfo(kDOUBLE, false);
651  auto cast_coord1 = coord1->add_cast(d_ti);
652  auto cast_coord2 = coord2->add_cast(d_ti);
653  // First try to fold to geo literal
654  auto fold1 = fold_expr(cast_coord1.get());
655  auto fold2 = fold_expr(cast_coord2.get());
656  auto const_coord1 = std::dynamic_pointer_cast<Analyzer::Constant>(fold1);
657  auto const_coord2 = std::dynamic_pointer_cast<Analyzer::Constant>(fold2);
658  if (const_coord1 && const_coord2 && !use_geo_expressions) {
659  CHECK(const_coord1->get_type_info().get_type() == kDOUBLE);
660  CHECK(const_coord2->get_type_info().get_type() == kDOUBLE);
661  std::string wkt = "POINT(" +
662  std::to_string(const_coord1->get_constval().doubleval) + " " +
663  std::to_string(const_coord2->get_constval().doubleval) + ")";
664  RexLiteral rex_literal{wkt, kTEXT, kNULLT, 0, 0, 0, 0};
665  auto args = translateGeoLiteral(&rex_literal, arg_ti, false);
666  CHECK(arg_ti.get_type() == kPOINT);
667  return args;
668  }
669  const auto is_local_alloca = !is_projection;
670  if (!is_local_alloca || use_geo_expressions) {
671  if (try_to_compress) {
672  arg_ti.set_input_srid(4326);
673  arg_ti.set_output_srid(4326);
674  }
675  return {makeExpr<Analyzer::GeoOperator>(
676  arg_ti,
677  rex_function->getName(),
678  std::vector<std::shared_ptr<Analyzer::Expr>>{cast_coord1, cast_coord2})};
679  }
680  // Couldn't fold to geo literal, construct [and compress] on the fly
681  auto da_ti = SQLTypeInfo(kARRAY, true);
682  da_ti.set_subtype(kDOUBLE);
683  da_ti.set_size(16);
684  if (try_to_compress) {
685  // Switch to compressed coord array
686  da_ti.set_subtype(kINT);
687  da_ti.set_size(8);
688  da_ti.set_input_srid(4326);
689  da_ti.set_output_srid(4326);
690  da_ti.set_compression(kENCODING_GEOINT);
691  da_ti.set_comp_param(32);
692  // Register point compression
693  arg_ti.set_input_srid(4326);
694  arg_ti.set_output_srid(4326);
695  arg_ti.set_compression(kENCODING_GEOINT);
696  arg_ti.set_comp_param(32);
697  }
698  auto cast_coords = {cast_coord1, cast_coord2};
699  auto ae = makeExpr<Analyzer::ArrayExpr>(da_ti, cast_coords, false, is_local_alloca);
700  SQLTypeInfo tia_ti = da_ti;
701  tia_ti.set_subtype(kTINYINT);
702  return {makeExpr<Analyzer::UOper>(tia_ti, false, kCAST, ae)};
703  } else if (rex_function->getName() == "ST_Centroid"sv) {
704  CHECK_EQ(size_t(1), rex_function->size());
705  arg_ti.set_type(kPOINT);
706  arg_ti.set_subtype(kGEOMETRY);
707  arg_ti.set_input_srid(0);
708  arg_ti.set_output_srid(0);
709  arg_ti.set_compression(kENCODING_NONE);
710 
711  SQLTypeInfo geo_ti;
712  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
713  geo_ti,
714  /*with_bounds=*/false,
715  /*with_render_group=*/false,
716  /*expand_geo_col=*/true,
717  /*is_projection=*/false,
718  /*use_geo_expressions=*/true);
719  CHECK_EQ(geoargs.size(), size_t(1));
720  if (try_to_compress) {
721  // Request point compression
722  arg_ti.set_input_srid(4326);
723  arg_ti.set_output_srid(4326);
724  arg_ti.set_compression(kENCODING_GEOINT);
725  arg_ti.set_comp_param(32);
726  }
727  return {makeExpr<Analyzer::GeoOperator>(
728  arg_ti,
729  rex_function->getName(),
730  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()})};
731  } else if (func_resolve(rex_function->getName(),
732  "ST_Intersection"sv,
733  "ST_Difference"sv,
734  "ST_Union"sv,
735  "ST_Buffer"sv)) {
736  CHECK_EQ(size_t(2), rex_function->size());
737  // What geo type will the constructor return? Could be anything.
738  return {translateBinaryGeoConstructor(rex_function, arg_ti, with_bounds)};
739  } else if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
740  CHECK_EQ(size_t(1), rex_function->size());
741  return {translateUnaryGeoPredicate(rex_function, arg_ti, with_bounds)};
742  } else if (func_resolve(rex_function->getName(), "ST_Equals"sv)) {
743  CHECK_EQ(size_t(2), rex_function->size());
744  return {translateBinaryGeoPredicate(rex_function, arg_ti, with_bounds)};
745  } else {
746  throw QueryNotSupported("Unsupported argument: " + rex_function->getName());
747  }
748  }
749  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
750  if (rex_literal) {
751  if (use_geo_expressions) {
752  const auto translated_literal = translateLiteral(rex_literal);
753  const auto constant_expr =
754  dynamic_cast<const Analyzer::Constant*>(translated_literal.get());
755  CHECK(constant_expr);
756  if (constant_expr->get_is_null()) {
757  // TODO: we could lift this limitation by assuming a minimum type per function
758  throw QueryNotSupported("Geospatial functions require typed nulls.");
759  }
760  const auto& datum = constant_expr->get_constval();
761  CHECK(datum.stringval);
762  auto geospatial_base = Geospatial::GeoTypesFactory::createGeoType(*datum.stringval);
763  CHECK(geospatial_base);
764  SQLTypeInfo ti;
765  ti.set_type(get_ti_from_geo(geospatial_base.get()));
766  if (arg_ti.get_subtype() == kGEOGRAPHY) {
768  } else {
770  }
771  ti.set_input_srid(arg_ti.get_input_srid());
772  ti.set_output_srid(arg_ti.get_output_srid() == 0 ? arg_ti.get_input_srid()
773  : arg_ti.get_output_srid());
774  // TODO: remove dependence on arg_ti
775  if (ti.get_output_srid() == 4326 || arg_ti.get_compression() == kENCODING_GEOINT) {
777  ti.set_comp_param(32);
778  }
779  ti.set_notnull(true);
780  return {makeExpr<Analyzer::GeoConstant>(std::move(geospatial_base), ti)};
781  }
782  return translateGeoLiteral(rex_literal, arg_ti, with_bounds);
783  }
784  throw QueryNotSupported("Geo function argument not supported");
785 }
void set_compression(EncodingType c)
Definition: sqltypes.h:429
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) 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
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:420
#define CHECK_GE(x, y)
Definition: Logger.h:222
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:423
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
void set_output_srid(int s)
Definition: sqltypes.h:425
void set_comp_param(int p)
Definition: sqltypes.h:430
Definition: sqltypes.h:52
std::shared_ptr< Analyzer::Expr > translateUnaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
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:426
#define CHECK(condition)
Definition: Logger.h:209
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:3458
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:419

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

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

1615  {
1616  CHECK_EQ(rex_operator->size(), 2u);
1617 
1618  auto translate_input =
1619  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1620  const auto input = dynamic_cast<const RexInput*>(operand);
1621  CHECK(input);
1622 
1623  SQLTypeInfo ti;
1624  const auto exprs = translateGeoColumn(input, ti, true, false, false);
1625  CHECK_GT(exprs.size(), 0u);
1626  if (ti.get_type() == kPOINT) {
1627  return exprs.front();
1628  } else {
1629  return exprs.back();
1630  }
1631  };
1632 
1633  SQLQualifier sql_qual{kONE};
1634  SQLOps sql_op{kOVERLAPS};
1635  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
1636  false,
1637  sql_op,
1638  sql_qual,
1639  translate_input(rex_operator->getOperand(1)),
1640  translate_input(rex_operator->getOperand(0)));
1641 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
SQLQualifier
Definition: sqldefs.h:69
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:221
Definition: sqldefs.h:69
#define CHECK(condition)
Definition: Logger.h:209
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 787 of file RelAlgTranslatorGeo.cpp.

References CHECK, RexFunctionOperator::getName(), Geospatial::GeoBase::kPROJECTION, and translateGeoFunctionArg().

Referenced by translateFunction().

790  {
791  // note that this is a bit of a misnomer, as ST_SetSRID embedded in a transform will
792  // eventually use geo expressions -- just not here
793  const bool use_geo_projections = !(rex_function->getName() == "ST_GeomFromText" ||
794  rex_function->getName() == "ST_GeogFromText" ||
795  rex_function->getName() == "ST_SetSRID");
796  auto geoargs = translateGeoFunctionArg(rex_function,
797  ti,
798  /*with_bounds=*/false,
799  /*with_render_group=*/false,
800  /*expand_geo_col=*/true,
801  /*is_projection=*/true,
802  /*use_geo_expressions=*/use_geo_projections);
803  CHECK(!geoargs.empty());
804  if (std::dynamic_pointer_cast<const Analyzer::GeoExpr>(geoargs.front()) &&
805  !geoargs.front()->get_type_info().is_array()) {
806  // GeoExpression
807  return geoargs.front();
808  }
809  CHECK(!use_geo_projections);
810  return makeExpr<Analyzer::GeoUOper>(
811  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
812 }
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
#define CHECK(condition)
Definition: Logger.h:209
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 1879 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1880  {
1881  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
1882  Therefore any string having fractional seconds more 3 places after the decimal
1883  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
1884  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
1885  calcite and translating them to generate our own casts.
1886  */
1887  CHECK_EQ(size_t(1), rex_function->size());
1888  const auto operand = translateScalarRex(rex_function->getOperand(0));
1889  const auto& operand_ti = operand->get_type_info();
1890  const auto& target_ti = rex_function->getType();
1891  if (!operand_ti.is_string()) {
1892  throw std::runtime_error(
1893  "High precision timestamp cast argument must be a string. Input type is: " +
1894  operand_ti.get_type_name());
1895  } else if (!target_ti.is_high_precision_timestamp()) {
1896  throw std::runtime_error(
1897  "Cast target type should be high precision timestamp. Input type is: " +
1898  target_ti.get_type_name());
1899  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
1900  throw std::runtime_error(
1901  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
1902  std::to_string(target_ti.get_dimension()) + ")");
1903  } else {
1904  return operand->add_cast(target_ti);
1905  }
1906 }
#define CHECK_EQ(x, y)
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::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 564 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().

565  {
566  if (just_explain_) {
567  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
568  }
569  CHECK(rex_operator->size() == 2);
570  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
571  const auto rhs = rex_operator->getOperand(1);
572  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
573  CHECK(rex_subquery);
574  auto ti = lhs->get_type_info();
575  auto result = rex_subquery->getExecutionResult();
576  CHECK(result);
577  auto& row_set = result->getRows();
578  CHECK_EQ(size_t(1), row_set->colCount());
579  const auto& rhs_ti = row_set->getColType(0);
580  if (rhs_ti.get_type() != ti.get_type()) {
581  throw std::runtime_error(
582  "The two sides of the IN operator must have the same type; found " +
583  ti.get_type_name() + " and " + rhs_ti.get_type_name());
584  }
585  row_set->moveToBegin();
586  if (row_set->entryCount() > 10000) {
587  std::shared_ptr<Analyzer::Expr> expr;
588  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
589  !row_set->getQueryMemDesc().didOutputColumnar()) {
590  expr = getInIntegerSetExpr(lhs, *row_set);
591  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
592  // Just let it fall through the usual InValues path at the end of this method,
593  // its codegen knows to use inline comparisons for few values.
594  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
595  ->get_value_list()
596  .size() <= 100) {
597  expr = nullptr;
598  }
599  } else {
600  expr = get_in_values_expr(lhs, *row_set);
601  }
602  if (expr) {
603  return expr;
604  }
605  }
606  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
607  while (true) {
608  auto row = row_set->getNextRow(true, false);
609  if (row.empty()) {
610  break;
611  }
612  if (g_enable_watchdog && value_exprs.size() >= 10000) {
613  throw std::runtime_error(
614  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
615  }
616  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
617  Datum d{0};
618  bool is_null_const{false};
619  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
620  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
621  auto ti_none_encoded = ti;
622  ti_none_encoded.set_compression(kENCODING_NONE);
623  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
624  auto dict_encoded_string =
625  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
626  value_exprs.push_back(dict_encoded_string);
627  } else {
628  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
629  }
630  }
631  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
632 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
bool g_enable_watchdog
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
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:209
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 391 of file RelAlgTranslator.cpp.

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

Referenced by translateGeoFunctionArg(), and translateScalarRex().

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

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

Referenced by translateFunction().

1335  {
1336  CHECK_EQ(size_t(2), rex_function->size());
1337  const auto base = translateScalarRex(rex_function->getOperand(0));
1338  const auto index = translateScalarRex(rex_function->getOperand(1));
1339  return makeExpr<Analyzer::BinOper>(
1340  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1341 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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:69

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

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

Referenced by translateFunction().

1259  {
1260  const auto& args = translateFunctionArgs(rex_function);
1261  CHECK_EQ(size_t(1), args.size());
1262  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1263  if (nullptr == expr || !expr->get_type_info().is_string() ||
1264  expr->get_type_info().is_varlen()) {
1265  throw std::runtime_error(rex_function->getName() +
1266  " expects a dictionary encoded text column.");
1267  }
1268  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1269 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 1250 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1251  {
1252  CHECK_EQ(size_t(1), rex_function->size());
1253  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1254  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1255  rex_function->getName() == "CHAR_LENGTH"sv);
1256 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 999 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1000  {
1001  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1002  const auto arg = translateScalarRex(rex_function->getOperand(0));
1003  const auto like = translateScalarRex(rex_function->getOperand(1));
1004  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
1005  throw std::runtime_error("The matching pattern must be a literal.");
1006  }
1007  const auto escape = (rex_function->size() == 3)
1008  ? translateScalarRex(rex_function->getOperand(2))
1009  : nullptr;
1010  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
1011  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
1012 }
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:566
#define CHECK(condition)
Definition: Logger.h:209
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 1028 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1029  {
1030  CHECK(rex_function->size() == 1);
1031  const auto arg = translateScalarRex(rex_function->getOperand(0));
1032  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
1033 }
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:209

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

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

Definition at line 1292 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1293  {
1294  const auto& args = translateFunctionArgs(rex_function);
1295  CHECK_EQ(size_t(1), args.size());
1296  CHECK(args[0]);
1297 
1298  if (args[0]->get_type_info().is_dict_encoded_string() ||
1299  dynamic_cast<Analyzer::Constant*>(args[0].get())) {
1300  return makeExpr<Analyzer::LowerExpr>(args[0]);
1301  }
1302 
1303  throw std::runtime_error(rex_function->getName() +
1304  " expects a dictionary encoded text column or a literal.");
1305 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
#define CHECK(condition)
Definition: Logger.h:209
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::translateOffsetInFragment ( ) const
private

Definition at line 1415 of file RelAlgTranslator.cpp.

Referenced by translateFunction().

1415  {
1416  return makeExpr<Analyzer::OffsetInFragment>();
1417 }

+ Here is the caller graph for this function:

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

Definition at line 884 of file RelAlgTranslator.cpp.

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

Referenced by translateScalarRex().

885  {
886  CHECK_GT(rex_operator->size(), size_t(0));
887  if (rex_operator->size() == 1) {
888  return translateUoper(rex_operator);
889  }
890  const auto sql_op = rex_operator->getOperator();
891  if (sql_op == kIN) {
892  return translateInOper(rex_operator);
893  }
894  if (sql_op == kMINUS || sql_op == kPLUS) {
895  auto date_plus_minus = translateDatePlusMinus(rex_operator);
896  if (date_plus_minus) {
897  return date_plus_minus;
898  }
899  }
900  if (sql_op == kOVERLAPS) {
901  return translateOverlapsOper(rex_operator);
902  } else if (IS_COMPARISON(sql_op)) {
903  auto geo_comp = translateGeoComparison(rex_operator);
904  if (geo_comp) {
905  return geo_comp;
906  }
907  }
908  auto lhs = translateScalarRex(rex_operator->getOperand(0));
909  for (size_t i = 1; i < rex_operator->size(); ++i) {
910  std::shared_ptr<Analyzer::Expr> rhs;
911  SQLQualifier sql_qual{kONE};
912  const auto rhs_op = rex_operator->getOperand(i);
913  std::tie(rhs, sql_qual) = get_quantified_rhs(rhs_op, *this);
914  if (!rhs) {
915  rhs = translateScalarRex(rhs_op);
916  }
917  CHECK(rhs);
918  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs);
919  }
920  return lhs;
921 }
SQLQualifier
Definition: sqldefs.h:69
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
Definition: sqldefs.h:41
#define CHECK_GT(x, y)
Definition: Logger.h:221
SQLOps getOperator() 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)
Definition: ParserNode.cpp:291
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:69
std::shared_ptr< Analyzer::Expr > translateOverlapsOper(const RexOperator *) const
Definition: sqldefs.h:53
#define CHECK(condition)
Definition: Logger.h:209
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:57

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

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

Referenced by translateOper().

924  {
925  const auto sql_op = rex_operator->getOperator();
926  CHECK(sql_op == kOVERLAPS);
927 
928  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
929  const auto lhs_ti = lhs->get_type_info();
930  if (lhs_ti.is_geometry()) {
931  return translateGeoOverlapsOper(rex_operator);
932  } else {
933  throw std::runtime_error(
934  "Overlaps equivalence is currently only supported for geospatial types");
935  }
936 }
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:209

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

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

Referenced by translateFunction().

1015  {
1016  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
1017  const auto arg = translateScalarRex(rex_function->getOperand(0));
1018  const auto pattern = translateScalarRex(rex_function->getOperand(1));
1019  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
1020  throw std::runtime_error("The matching pattern must be a literal.");
1021  }
1022  const auto escape = (rex_function->size() == 3)
1023  ? translateScalarRex(rex_function->getOperand(2))
1024  : nullptr;
1025  return Parser::RegexpExpr::get(arg, pattern, escape, false);
1026 }
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:661
#define CHECK(condition)
Definition: Logger.h:209

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

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

Referenced by translateFunction().

1272  {
1273  CHECK_EQ(size_t(1), rex_function->size());
1274  auto arg = translateScalarRex(rex_function->getOperand(0));
1275  const auto& arg_ti = arg->get_type_info();
1276  if (arg_ti.get_type() != kDOUBLE) {
1277  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1278  arg = arg->add_cast(double_ti);
1279  }
1280  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1281 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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 178 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(), translateWindowFunction(), and QueryPlanDagChecker::visit().

179  {
180  const auto rex_input = dynamic_cast<const RexInput*>(rex);
181  if (rex_input) {
182  return translateInput(rex_input);
183  }
184  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex);
185  if (rex_literal) {
186  return translateLiteral(rex_literal);
187  }
188  const auto rex_window_function = dynamic_cast<const RexWindowFunctionOperator*>(rex);
189  if (rex_window_function) {
190  return translateWindowFunction(rex_window_function);
191  }
192  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex);
193  if (rex_function) {
194  return translateFunction(rex_function);
195  }
196  const auto rex_operator = dynamic_cast<const RexOperator*>(rex);
197  if (rex_operator) {
198  return translateOper(rex_operator);
199  }
200  const auto rex_case = dynamic_cast<const RexCase*>(rex);
201  if (rex_case) {
202  return translateCase(rex_case);
203  }
204  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rex);
205  if (rex_subquery) {
206  return translateScalarSubquery(rex_subquery);
207  }
208  CHECK(false);
209  return nullptr;
210 }
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:209
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 357 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().

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

1394  {
1395  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1396  expr_list;
1397  CHECK_EQ(size_t(1), rex_function->size());
1398  const auto operand = translateScalarRex(rex_function->getOperand(0));
1399  const auto& operand_ti = operand->get_type_info();
1400  CHECK(operand_ti.is_number());
1401  const auto zero = makeNumericConstant(operand_ti, 0);
1402  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1403  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1404  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1405  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1406  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1407  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1408  return makeExpr<Analyzer::CaseExpr>(
1409  operand_ti,
1410  false,
1411  expr_list,
1412  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1413 }
#define CHECK_EQ(x, y)
Definition: Logger.h:217
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:69
#define CHECK(condition)
Definition: Logger.h:209
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::translateTernaryGeoFunction ( const RexFunctionOperator rex_function) const
private

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

1380  {
1381  CHECK_EQ(size_t(3), rex_function->size());
1382 
1383  auto distance_expr = translateScalarRex(rex_function->getOperand(2));
1384  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1385  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1386  distance_expr = distance_expr->add_cast(distance_ti);
1387  }
1388 
1389  auto function_name = rex_function->getName();
1390  if (function_name == "ST_DWithin"sv) {
1391  auto return_type = rex_function->getType();
1392  bool swap_args = false;
1393  bool with_bounds = true;
1394  SQLTypeInfo arg0_ti;
1395  SQLTypeInfo arg1_ti;
1396 
1397  auto geoargs0 = translateGeoFunctionArg(
1398  rex_function->getOperand(0), arg0_ti, with_bounds, false, false);
1399  auto geoargs1 = translateGeoFunctionArg(
1400  rex_function->getOperand(1), arg1_ti, with_bounds, false, false);
1401  if (arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1402  throw QueryNotSupported(rex_function->getName() +
1403  " cannot accept mixed GEOMETRY/GEOGRAPHY arguments");
1404  }
1405  auto is_geodesic = false;
1406  if (arg0_ti.get_subtype() == kGEOGRAPHY) {
1407  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1408  is_geodesic = true;
1409  } else {
1410  throw QueryNotSupported(
1411  rex_function->getName() +
1412  " in geodesic form can only accept POINT GEOGRAPHY arguments");
1413  }
1414  }
1415  // Check SRID match if at least one is set/valid
1416  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1417  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1418  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1419  }
1420 
1421  if ((arg1_ti.get_type() == kPOINT && arg0_ti.get_type() != kPOINT) ||
1422  (arg1_ti.get_type() == kLINESTRING && arg0_ti.get_type() == kPOLYGON) ||
1423  (arg1_ti.get_type() == kPOLYGON && arg0_ti.get_type() == kMULTIPOLYGON)) {
1424  // Swap arguments and use single implementation per arg pair
1425  swap_args = true;
1426  }
1427 
1428  // First input's compression mode and SRID args to enable on-the-fly
1429  // decompression/transforms
1430  Datum input_compression0;
1431  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1432  Datum input_srid0;
1433  input_srid0.intval = arg0_ti.get_input_srid();
1434 
1435  // Second input's compression mode and SRID args to enable on-the-fly
1436  // decompression/transforms
1437  Datum input_compression1;
1438  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1439  Datum input_srid1;
1440  input_srid1.intval = arg1_ti.get_input_srid();
1441 
1442  // Output SRID arg to enable on-the-fly transforms
1443  Datum output_srid;
1444  output_srid.intval = arg0_ti.get_output_srid();
1445 
1446  std::string specialized_geofunc{function_name};
1447  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1448  if (swap_args) {
1449  specialized_geofunc += suffix(arg1_ti.get_type()) + suffix(arg0_ti.get_type());
1450  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1451  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1452  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1453  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1454  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1455  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1456  } else {
1457  specialized_geofunc += suffix(arg0_ti.get_type()) + suffix(arg1_ti.get_type());
1458  if (is_geodesic) {
1459  specialized_geofunc += "_Geodesic"s;
1460  }
1461  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1462  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1463  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1464  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1465  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1466  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1467  }
1468  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1469  // Also add the within distance
1470  geoargs.push_back(distance_expr);
1471 
1472  auto result =
1473  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1474  return result;
1475  }
1476 
1477  // Otherwise translate function as binary geo to get distance,
1478  // with optional short-circuiting threshold held in the third operand
1479  const auto geo_distance = translateBinaryGeoFunction(rex_function);
1480  // and generate the comparison
1481  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, geo_distance, distance_expr);
1482 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
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
Definition: sqldefs.h:35
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
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:69
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 912 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().

913  {
914  CHECK_EQ(size_t(1), rex_function->size());
915 
916  std::string specialized_geofunc{rex_function->getName()};
917 
918  // Geo function calls which do not need the coords col but do need cols associated
919  // with physical coords (e.g. ring_sizes / poly_rings)
920  if (rex_function->getName() == "ST_NRings"sv) {
921  SQLTypeInfo arg_ti;
922  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
923  arg_ti,
924  /*with_bounds=*/false,
925  /*with_render_group=*/false,
926  /*expand_geo_col=*/true,
927  /*is_projection=*/false,
928  /*use_geo_expressions=*/true);
929  CHECK_EQ(geoargs.size(), size_t(1));
930  arg_ti = rex_function->getType(); // TODO: remove
931  return makeExpr<Analyzer::GeoOperator>(
932  rex_function->getType(),
933  rex_function->getName(),
934  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
935  } else if (rex_function->getName() == "ST_NPoints"sv) {
936  SQLTypeInfo arg_ti;
937  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
938  arg_ti,
939  /*with_bounds=*/false,
940  /*with_render_group=*/false,
941  /*expand_geo_col=*/true,
942  /*is_projection=*/false,
943  /*use_geo_expressions=*/true);
944  CHECK_EQ(geoargs.size(), size_t(1));
945  return makeExpr<Analyzer::GeoOperator>(
946  rex_function->getType(),
947  rex_function->getName(),
948  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
949  } else if (func_resolve(rex_function->getName(), "ST_Perimeter"sv, "ST_Area"sv)) {
950  SQLTypeInfo arg_ti;
951  auto geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
952  arg_ti,
953  /*with_bounds=*/false,
954  /*with_render_group=*/false,
955  /*expand_geo_col=*/true,
956  /*is_projection=*/false,
957  /*use_geo_expressions=*/true);
958  CHECK_EQ(geoargs.size(), size_t(1));
959  arg_ti = geoargs.front()->get_type_info();
960  if (arg_ti.get_type() != kPOLYGON && arg_ti.get_type() != kMULTIPOLYGON) {
961  throw QueryNotSupported(rex_function->getName() +
962  " expects a POLYGON or MULTIPOLYGON");
963  }
964 
965  return makeExpr<Analyzer::GeoOperator>(
966  rex_function->getType(),
967  rex_function->getName(),
968  std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
969  }
970 
971  // Accessors for poly bounds and render group for in-situ poly render queries
972  if (func_resolve(rex_function->getName(),
973  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
974  "OmniSci_Geo_PolyBoundsPtr"sv)) {
975  SQLTypeInfo arg_ti;
976  // get geo column plus bounds only (not expanded)
977  auto geoargs =
978  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, true, false, false);
979  // this function only works on polys
980  if (!IS_GEO_POLY(arg_ti.get_type())) {
981  throw QueryNotSupported(rex_function->getName() +
982  " expects a POLYGON or MULTIPOLYGON");
983  }
984  // only need the bounds argument (last), discard the rest
985  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
986  // done
987  return makeExpr<Analyzer::FunctionOper>(
988  rex_function->getType(), specialized_geofunc, geoargs);
989  } else if (func_resolve(rex_function->getName(),
990  "MapD_GeoPolyRenderGroup"sv /* deprecated */,
991  "OmniSci_Geo_PolyRenderGroup"sv)) {
992  SQLTypeInfo arg_ti;
993  // get geo column plus render_group only (not expanded)
994  auto geoargs =
995  translateGeoFunctionArg(rex_function->getOperand(0), arg_ti, false, true, false);
996  // this function only works on polys
997  if (!IS_GEO_POLY(arg_ti.get_type())) {
998  throw QueryNotSupported(rex_function->getName() +
999  " expects a POLYGON or MULTIPOLYGON");
1000  }
1001  // only need the render_group argument (last), discard the rest
1002  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1003  // done
1004  return makeExpr<Analyzer::FunctionOper>(
1005  rex_function->getType(), specialized_geofunc, geoargs);
1006  }
1007 
1008  // start to move geo expressions above the generic translation call, as geo expression
1009  // error handling can differ
1010  if (func_resolve(rex_function->getName(), "ST_X"sv, "ST_Y"sv)) {
1011  SQLTypeInfo arg_ti;
1012  auto new_geoargs = translateGeoFunctionArg(rex_function->getOperand(0),
1013  arg_ti,
1014  /*with_bounds=*/false,
1015  /*with_render_group=*/false,
1016  /*expand_geo_col=*/true,
1017  /*is_projection=*/true,
1018  /*use_geo_expressions=*/true);
1019  CHECK_EQ(new_geoargs.size(), size_t(1));
1020  CHECK(new_geoargs.front());
1021  const auto& arg_expr_ti = new_geoargs.front()->get_type_info();
1022  if (arg_expr_ti.get_type() != kPOINT) {
1023  throw QueryNotSupported(rex_function->getName() + " expects a POINT");
1024  }
1025  auto function_ti = rex_function->getType();
1026  if (std::dynamic_pointer_cast<Analyzer::GeoOperator>(new_geoargs.front())) {
1027  function_ti.set_notnull(false);
1028  }
1029  if (std::dynamic_pointer_cast<Analyzer::GeoConstant>(new_geoargs.front())) {
1030  // TODO(adb): fixup null handling
1031  function_ti.set_notnull(true);
1032  }
1033  return makeExpr<Analyzer::GeoOperator>(
1034  function_ti,
1035  rex_function->getName(),
1036  std::vector<std::shared_ptr<Analyzer::Expr>>{new_geoargs.front()});
1037  }
1038 
1039  // All functions below use geo col as reference and expand it as necessary
1040  SQLTypeInfo arg_ti;
1041  bool with_bounds = true;
1042  auto geoargs = translateGeoFunctionArg(
1043  rex_function->getOperand(0), arg_ti, with_bounds, false, false);
1044 
1045  if (rex_function->getName() == "ST_SRID"sv) {
1046  Datum output_srid;
1047  output_srid.intval = arg_ti.get_output_srid();
1048  return makeExpr<Analyzer::Constant>(kINT, false, output_srid);
1049  }
1050 
1051  if (func_resolve(
1052  rex_function->getName(), "ST_XMin"sv, "ST_YMin"sv, "ST_XMax"sv, "ST_YMax"sv)) {
1053  // If type has bounds - use them, otherwise look at coords
1054  if (arg_ti.has_bounds()) {
1055  // Only need the bounds argument, discard the rest
1056  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1057 
1058  // Supply srids too - transformed geo would have a transformed bounding box
1059  Datum input_srid;
1060  input_srid.intval = arg_ti.get_input_srid();
1061  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1062  Datum output_srid;
1063  output_srid.intval = arg_ti.get_output_srid();
1064  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1065 
1066  specialized_geofunc += "_Bounds"s;
1067  return makeExpr<Analyzer::FunctionOper>(
1068  rex_function->getType(), specialized_geofunc, geoargs);
1069  }
1070  }
1071 
1072  // All geo function calls translated below only need the coords, extras e.g.
1073  // ring_sizes are dropped. Specialize for other/new functions if needed.
1074  geoargs.erase(geoargs.begin() + 1, geoargs.end());
1075 
1076  if (rex_function->getName() == "ST_Length"sv) {
1077  if (arg_ti.get_type() != kLINESTRING) {
1078  throw QueryNotSupported(rex_function->getName() + " expects LINESTRING");
1079  }
1080  specialized_geofunc += suffix(arg_ti.get_type());
1081  if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
1082  specialized_geofunc += "_Geodesic"s;
1083  }
1084  }
1085 
1086  // Add input compression mode and SRID args to enable on-the-fly
1087  // decompression/transforms
1088  Datum input_compression;
1089  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1090  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1091  Datum input_srid;
1092  input_srid.intval = arg_ti.get_input_srid();
1093  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1094 
1095  // Add output SRID arg to enable on-the-fly transforms
1096  Datum output_srid;
1097  output_srid.intval = arg_ti.get_output_srid();
1098  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1099 
1100  return makeExpr<Analyzer::FunctionOper>(
1101  rex_function->getType(), specialized_geofunc, geoargs);
1102 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
Definition: Logger.h:217
auto func_resolve
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) 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
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE SQLTypes get_type() const
Definition: