OmniSciDB  94e8789169
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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::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::ExprtranslateNow () 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::ExprtranslateGeoPredicate (const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
 
std::shared_ptr< Analyzer::ExprtranslateGeoBinaryConstructor (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, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=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 763 of file RelAlgTranslator.cpp.

References 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(), generate_TableFunctionsFactory_init::i, inline_int_null_val(), and kENCODING_DICT.

Referenced by translateInOper().

765  {
767  return nullptr;
768  }
769  std::vector<int64_t> value_exprs;
770  const size_t fetcher_count = cpu_threads();
771  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
772  std::vector<std::future<void>> fetcher_threads;
773  const auto& arg_type = arg->get_type_info();
774  const auto entry_count = val_set.entryCount();
775  CHECK_EQ(size_t(1), val_set.colCount());
776  const auto& col_type = val_set.getColType(0);
777  if (g_cluster && arg_type.is_string() &&
778  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
779  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
780  return nullptr;
781  }
782  std::atomic<size_t> total_in_vals_count{0};
783  for (size_t i = 0,
784  start_entry = 0,
785  stride = (entry_count + fetcher_count - 1) / fetcher_count;
786  i < fetcher_count && start_entry < entry_count;
787  ++i, start_entry += stride) {
788  expr_set[i].reserve(entry_count / fetcher_count);
789  const auto end_entry = std::min(start_entry + stride, entry_count);
790  if (arg_type.is_string()) {
791  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
792  // const int32_t dest_dict_id = arg_type.get_comp_param();
793  // const int32_t source_dict_id = col_type.get_comp_param();
794  const DictRef dest_dict_ref(arg_type.get_comp_param(), cat_.getDatabaseId());
795  const DictRef source_dict_ref(col_type.get_comp_param(), cat_.getDatabaseId());
796  const auto dd = executor_->getStringDictionaryProxy(
797  arg_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
798  const auto sd = executor_->getStringDictionaryProxy(
799  col_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
800  CHECK(sd);
801  const auto needle_null_val = inline_int_null_val(arg_type);
802  fetcher_threads.push_back(std::async(
803  std::launch::async,
804  [this,
805  &val_set,
806  &total_in_vals_count,
807  sd,
808  dd,
809  source_dict_ref,
810  dest_dict_ref,
811  needle_null_val](
812  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
813  if (g_cluster) {
814  CHECK_GE(dd->getGeneration(), 0);
816  total_in_vals_count,
817  &val_set,
818  {start, end},
820  source_dict_ref,
821  dest_dict_ref,
822  dd->getGeneration(),
823  needle_null_val);
824  } else {
826  total_in_vals_count,
827  &val_set,
828  {start, end},
829  sd,
830  dd,
831  needle_null_val);
832  }
833  },
834  std::ref(expr_set[i]),
835  start_entry,
836  end_entry));
837  } else {
838  CHECK(arg_type.is_integer());
839  fetcher_threads.push_back(std::async(
840  std::launch::async,
841  [&val_set, &total_in_vals_count](
842  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
843  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
844  },
845  std::ref(expr_set[i]),
846  start_entry,
847  end_entry));
848  }
849  }
850  for (auto& child : fetcher_threads) {
851  child.get();
852  }
853 
854  val_set.moveToBegin();
855  value_exprs.reserve(entry_count);
856  for (auto& exprs : expr_set) {
857  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
858  }
859  return makeExpr<Analyzer::InIntegerSet>(
860  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
861 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
const Executor * executor_
#define CHECK_GE(x, y)
Definition: Logger.h:210
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:274
const std::vector< LeafHostInfo > & getStringDictionaryHosts() const
Definition: Catalog.cpp:1492
#define CHECK(condition)
Definition: Logger.h:197
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:1131
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 1297 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().

1298  {
1299  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1300  expr_list;
1301  CHECK_EQ(size_t(1), rex_function->size());
1302  const auto operand = translateScalarRex(rex_function->getOperand(0));
1303  const auto& operand_ti = operand->get_type_info();
1304  CHECK(operand_ti.is_number());
1305  const auto zero = makeNumericConstant(operand_ti, 0);
1306  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1307  const auto uminus_operand =
1308  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1309  expr_list.emplace_back(lt_zero, uminus_operand);
1310  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1311 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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:197
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, 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, kINT, RexAgg::size(), and ThriftSerializers::takes_arg().

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

227  {
228  const auto 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> err_rate;
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  err_rate = std::dynamic_pointer_cast<Analyzer::Constant>(
240  scalar_sources[rex->getOperand(1)]);
241  if (!err_rate || err_rate->get_type_info().get_type() != kINT ||
242  err_rate->get_constval().intval < 1 || err_rate->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  }
248  const auto& arg_ti = arg_expr->get_type_info();
249  if (!is_agg_supported_for_type(agg_kind, arg_ti)) {
250  throw std::runtime_error("Aggregate on " + arg_ti.get_type_name() +
251  " is not supported yet.");
252  }
253  }
254  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
255  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, err_rate);
256 }
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:207
#define CHECK_LE(x, y)
Definition: Logger.h:208
bool takes_arg(const TargetInfo &target_info)
bool isDistinct() const
size_t size() const
Definition: sqltypes.h:44
bool is_distinct(const size_t input_idx, const RelAlgNode *node)

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

1340  {
1341  if (rex_function->getType().get_subtype() == kNULLT) {
1342  auto sql_type = rex_function->getType();
1343  CHECK(sql_type.get_type() == kARRAY);
1344 
1345  // FIX-ME: Deal with NULL arrays
1346  auto translated_function_args(translateFunctionArgs(rex_function));
1347  if (translated_function_args.size() > 0) {
1348  const auto first_element_logical_type =
1349  get_nullable_logical_type_info(translated_function_args[0]->get_type_info());
1350 
1351  auto diff_elem_itr =
1352  std::find_if(translated_function_args.begin(),
1353  translated_function_args.end(),
1354  [first_element_logical_type](const auto expr) {
1355  return first_element_logical_type !=
1356  get_nullable_logical_type_info(expr->get_type_info());
1357  });
1358  if (diff_elem_itr != translated_function_args.end()) {
1359  throw std::runtime_error(
1360  "Element " +
1361  std::to_string(diff_elem_itr - translated_function_args.begin()) +
1362  " is not of the same type as other elements of the array. Consider casting "
1363  "to force this condition.\nElement Type: " +
1364  get_nullable_logical_type_info((*diff_elem_itr)->get_type_info())
1365  .to_string() +
1366  "\nArray type: " + first_element_logical_type.to_string());
1367  }
1368 
1369  if (first_element_logical_type.is_string() &&
1370  !first_element_logical_type.is_dict_encoded_string()) {
1371  sql_type.set_subtype(first_element_logical_type.get_type());
1372  sql_type.set_compression(kENCODING_FIXED);
1373  } else if (first_element_logical_type.is_dict_encoded_string()) {
1374  sql_type.set_subtype(first_element_logical_type.get_type());
1375  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1376  } else {
1377  sql_type.set_subtype(first_element_logical_type.get_type());
1378  sql_type.set_scale(first_element_logical_type.get_scale());
1379  sql_type.set_precision(first_element_logical_type.get_precision());
1380  }
1381 
1382  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1383  } else {
1384  // defaulting to valid sub-type for convenience
1385  sql_type.set_subtype(kBOOLEAN);
1386  return makeExpr<Analyzer::ArrayExpr>(sql_type, translated_function_args);
1387  }
1388  } else {
1389  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1390  translateFunctionArgs(rex_function));
1391  }
1392 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:312
SQLTypeInfo get_nullable_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:914
const SQLTypeInfo & getType() const
std::string to_string(char const *&&v)
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:250
#define CHECK(condition)
Definition: Logger.h:197

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

References CHECK_EQ, CHECK_GT, Datum::doubleval, fold_expr(), 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(), Datum::intval, kBOOLEAN, kDOUBLE, kGEOGRAPHY, kINT, kLINESTRING, kNOT, kNULLT, kPOINT, run_benchmark_import::result, RexOperator::size(), anonymous_namespace{RelAlgTranslatorGeo.cpp}::suffix(), translateGeoColumn(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction(), and translateTernaryGeoFunction().

911  {
912  auto function_name = rex_function->getName();
913  auto return_type = rex_function->getType();
914 
915  if (function_name == "ST_Overlaps"sv) {
916  // Overlaps join is the only implementation supported for now, only translate bounds
917  CHECK_EQ(size_t(2), rex_function->size());
918  auto extract_geo_bounds_from_input =
919  [this, &rex_function](const size_t index) -> std::shared_ptr<Analyzer::Expr> {
920  const auto rex_input =
921  dynamic_cast<const RexInput*>(rex_function->getOperand(index));
922  if (rex_input) {
923  SQLTypeInfo ti;
924  const auto exprs = translateGeoColumn(rex_input, ti, true, false, false);
925  CHECK_GT(exprs.size(), size_t(0));
926  if (ti.get_type() == kPOINT) {
927  throw std::runtime_error("ST_Overlaps is not supported for point arguments.");
928  } else {
929  return exprs.back();
930  }
931  } else {
932  throw std::runtime_error(
933  "Only inputs are supported as arguments to ST_Overlaps for now.");
934  }
935  };
936  std::vector<std::shared_ptr<Analyzer::Expr>> geo_args;
937  geo_args.push_back(extract_geo_bounds_from_input(0));
938  geo_args.push_back(extract_geo_bounds_from_input(1));
939 
940  return makeExpr<Analyzer::FunctionOper>(return_type, function_name, geo_args);
941  }
942 
943  bool swap_args = false;
944  bool with_bounds = false;
945  bool negate_result = false;
946  Analyzer::ExpressionPtr threshold_expr = nullptr;
947  if (function_name == "ST_DWithin"sv) {
948  CHECK_EQ(size_t(3), rex_function->size());
949  function_name = "ST_Distance";
950  return_type = SQLTypeInfo(kDOUBLE, false);
951  // Inject ST_DWithin's short-circuiting threshold into ST_MaxDistance
952  threshold_expr = translateScalarRex(rex_function->getOperand(2));
953  } else if (function_name == "ST_DFullyWithin"sv) {
954  CHECK_EQ(size_t(3), rex_function->size());
955  function_name = "ST_MaxDistance";
956  return_type = SQLTypeInfo(kDOUBLE, false);
957  // TODO: inject ST_DFullyWithin's short-circuiting threshold into ST_MaxDistance
958  threshold_expr = nullptr;
959  } else if (function_name == "ST_Distance"sv) {
960  // TODO: pick up an outside short-circuiting threshold and inject into ST_Distance
961  threshold_expr = nullptr;
962  } else if (function_name == "ST_MaxDistance"sv) {
963  // TODO: pick up an outside short-circuiting threshold and inject into ST_MaxDistance
964  threshold_expr = nullptr;
965  } else {
966  CHECK_EQ(size_t(2), rex_function->size());
967  }
968  if (function_name == "ST_Within"sv) {
969  function_name = "ST_Contains";
970  swap_args = true;
971  } else if (function_name == "ST_Disjoint"sv) {
972  function_name = "ST_Intersects";
973  negate_result = true;
974  }
975  if (func_resolve(
976  function_name, "ST_Contains"sv, "ST_Intersects"sv, "ST_Approx_Overlaps"sv)) {
977  with_bounds = true;
978  }
979 
980  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
981  SQLTypeInfo arg0_ti;
982  SQLTypeInfo arg1_ti;
983  int32_t lindex0 = 0;
984  int32_t lindex1 = 0;
985 
986  auto geoargs0 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 1 : 0),
987  arg0_ti,
988  lindex0,
989  with_bounds,
990  false,
991  false);
992  if (arg0_ti.get_type() == kLINESTRING) {
993  Datum index;
994  index.intval = lindex0;
995  geoargs0.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
996  }
997  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
998  auto geoargs1 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 0 : 1),
999  arg1_ti,
1000  lindex1,
1001  with_bounds,
1002  false,
1003  false);
1004  if (arg1_ti.get_type() == kLINESTRING) {
1005  Datum index;
1006  index.intval = lindex1;
1007  geoargs1.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
1008  }
1009  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1010 
1011  if (arg0_ti.get_subtype() != kNULLT && arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1012  throw QueryNotSupported(rex_function->getName() +
1013  " accepts either two GEOGRAPHY or two GEOMETRY arguments");
1014  }
1015  // Check SRID match if at least one is set/valid
1016  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1017  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1018  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1019  }
1020 
1021  std::string specialized_geofunc{function_name + suffix(arg0_ti.get_type()) +
1022  suffix(arg1_ti.get_type())};
1023 
1024  if (arg0_ti.get_subtype() == kGEOGRAPHY && arg0_ti.get_output_srid() == 4326) {
1025  // Need to call geodesic runtime functions
1026  if (function_name == "ST_Distance"sv) {
1027  if ((arg0_ti.get_type() == kPOINT ||
1028  (arg0_ti.get_type() == kLINESTRING && lindex0 != 0)) &&
1029  (arg1_ti.get_type() == kPOINT ||
1030  (arg1_ti.get_type() == kLINESTRING && lindex1 != 0))) {
1031  // Geodesic distance between points (or indexed linestrings)
1032  specialized_geofunc += "_Geodesic"s;
1033  } else {
1034  throw QueryNotSupported(function_name +
1035  " currently doesn't accept non-POINT geographies");
1036  }
1037  } else if (rex_function->getName() == "ST_Contains"sv) {
1038  // We currently don't have a geodesic implementation of ST_Contains,
1039  // allowing calls to a [less precise] cartesian implementation.
1040  } else {
1041  throw QueryNotSupported(function_name + " doesn't accept geographies");
1042  }
1043  } else if (function_name == "ST_Distance"sv && rex_function->size() == 3) {
1044  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
1045  // Cartesian distance between points used by ST_DWithin - switch to faster Squared
1046  specialized_geofunc += "_Squared"s;
1047  }
1048  }
1049 
1050  // Add first input's compression mode and SRID args to enable on-the-fly
1051  // decompression/transforms
1052  Datum input_compression0;
1053  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1054  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1055  Datum input_srid0;
1056  input_srid0.intval = arg0_ti.get_input_srid();
1057  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1058 
1059  // Add second input's compression mode and SRID args to enable on-the-fly
1060  // decompression/transforms
1061  Datum input_compression1;
1062  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1063  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1064  Datum input_srid1;
1065  input_srid1.intval = arg1_ti.get_input_srid();
1066  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1067 
1068  // Add output SRID arg to enable on-the-fly transforms
1069  Datum output_srid;
1070  output_srid.intval = arg0_ti.get_output_srid();
1071  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1072 
1073  // Some geo distance functions will be injected with a short-circuit threshold.
1074  // Threshold value would come from Geo comparison operations or from other outer
1075  // geo operations, e.g. ST_DWithin
1076  // At this point, only ST_Distance_LineString_LineString requires a threshold arg.
1077  // TODO: Other combinations that involve LINESTRING, POLYGON and MULTIPOLYGON args
1078  // TODO: Inject threshold into ST_MaxDistance
1079  if (function_name == "ST_Distance"sv && arg0_ti.get_subtype() != kGEOGRAPHY &&
1080  (arg0_ti.get_type() != kPOINT || arg1_ti.get_type() != kPOINT)) {
1081  if (threshold_expr) {
1082  if (threshold_expr->get_type_info().get_type() != kDOUBLE) {
1083  const auto& threshold_ti = SQLTypeInfo(kDOUBLE, false);
1084  threshold_expr = threshold_expr->add_cast(threshold_ti);
1085  }
1086  threshold_expr = fold_expr(threshold_expr.get());
1087  } else {
1088  Datum d;
1089  d.doubleval = 0.0;
1090  threshold_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
1091  }
1092  geoargs.push_back(threshold_expr);
1093  }
1094 
1095  auto result =
1096  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1097  if (negate_result) {
1098  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, result);
1099  }
1100  return result;
1101 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:312
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
std::shared_ptr< Analyzer::Expr > ExpressionPtr
Definition: Analyzer.h:180
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
#define CHECK_GT(x, y)
Definition: Logger.h:209
int32_t intval
Definition: sqltypes.h:205
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:315
Definition: sqltypes.h:44
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)
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) const
double doubleval
Definition: sqltypes.h:208
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:317

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

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

Referenced by translateFunction().

1242  {
1243  const auto ret_ti = rex_function->getType();
1244  const auto arg = translateScalarRex(rex_function->getOperand(0));
1245  const auto arg_ti = arg->get_type_info();
1246  if (!arg_ti.is_array()) {
1247  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1248  }
1249  if (arg_ti.get_subtype() == kARRAY) {
1250  throw std::runtime_error(rex_function->getName() +
1251  " expects one-dimension array expression.");
1252  }
1253  const auto array_size = arg_ti.get_size();
1254  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1255 
1256  if (array_size > 0) {
1257  if (array_elem_size <= 0) {
1258  throw std::runtime_error(rex_function->getName() +
1259  ": unexpected array element type.");
1260  }
1261  // Return cardinality of a fixed length array
1262  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1263  }
1264  // Variable length array cardinality will be calculated at runtime
1265  return makeExpr<Analyzer::CardinalityExpr>(arg);
1266 }
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 917 of file RelAlgTranslator.cpp.

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

Referenced by translateScalarRex().

918  {
919  std::shared_ptr<Analyzer::Expr> else_expr;
920  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
921  expr_list;
922  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
923  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
924  const auto then_expr = translateScalarRex(rex_case->getThen(i));
925  expr_list.emplace_back(when_expr, then_expr);
926  }
927  if (rex_case->getElse()) {
928  else_expr = translateScalarRex(rex_case->getElse());
929  }
930  return Parser::CaseExpr::normalize(expr_list, else_expr);
931 }
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:922
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::translateCurrentUser ( const RexFunctionOperator rex_function) const
private

Definition at line 1217 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1218  {
1219  std::string user{"SESSIONLESS_USER"};
1220  if (query_state_) {
1221  user = query_state_->getConstSessionInfo()->get_currentUser().userName;
1222  }
1223  return Parser::UserLiteral::get(user);
1224 }
static std::shared_ptr< Analyzer::Expr > get(const std::string &)
Definition: ParserNode.cpp:196
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 1046 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().

1047  {
1048  CHECK_EQ(size_t(3), rex_function->size());
1049  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1050  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1052  const auto number_units = translateScalarRex(rex_function->getOperand(1));
1053  const auto number_units_const =
1054  std::dynamic_pointer_cast<Analyzer::Constant>(number_units);
1055  if (number_units_const && number_units_const->get_is_null()) {
1056  throw std::runtime_error("The 'Interval' argument literal must not be 'null'.");
1057  }
1058  const auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
1059  const auto datetime = translateScalarRex(rex_function->getOperand(2));
1060  const auto& datetime_ti = datetime->get_type_info();
1061  if (datetime_ti.get_type() == kTIME) {
1062  throw std::runtime_error("DateAdd operation not supported for TIME.");
1063  }
1064  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
1065  const int dim = datetime_ti.get_dimension();
1066  return makeExpr<Analyzer::DateaddExpr>(
1067  SQLTypeInfo(kTIMESTAMP, dim, 0, false), field, cast_number_units, datetime);
1068 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
Definition: sqltypes.h:48
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 1161 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().

1162  {
1163  CHECK_EQ(size_t(3), rex_function->size());
1164  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1165  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1167  const auto start = translateScalarRex(rex_function->getOperand(1));
1168  const auto end = translateScalarRex(rex_function->getOperand(2));
1169  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1170  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1171 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 1173 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().

1174  {
1175  CHECK_EQ(size_t(2), rex_function->size());
1176  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1177  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1179  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1180  return ExtractExpr::generate(
1181  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1182 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 1079 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().

1080  {
1081  if (rex_operator->size() != 2) {
1082  return nullptr;
1083  }
1084  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1085  const auto datetime_ti = datetime->get_type_info();
1086  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1087  if (datetime_ti.get_type() == kTIME) {
1088  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1089  }
1090  return nullptr;
1091  }
1092  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1093  const auto rhs_ti = rhs->get_type_info();
1094  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1095  if (datetime_ti.is_high_precision_timestamp() ||
1096  rhs_ti.is_high_precision_timestamp()) {
1097  throw std::runtime_error(
1098  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. "
1099  "Use "
1100  "DATEDIFF.");
1101  }
1102  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1103  const auto& rex_operator_ti = rex_operator->getType();
1104  const auto datediff_field =
1105  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1106  auto result =
1107  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1108  // multiply 1000 to result since expected result should be in millisecond precision.
1109  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1110  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1111  kMULTIPLY,
1112  kONE,
1113  result,
1114  makeNumericConstant(bigint_ti, 1000));
1115  } else {
1116  return result;
1117  }
1118  }
1119  const auto op = rex_operator->getOperator();
1120  if (op == kPLUS) {
1121  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1122  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1123  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1124  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1125  if (date_trunc) {
1126  return date_trunc;
1127  }
1128  }
1129  const auto interval = fold_expr(rhs.get());
1130  auto interval_ti = interval->get_type_info();
1131  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1132  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1133  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1134  std::shared_ptr<Analyzer::Expr> interval_sec;
1135  if (interval_lit) {
1136  interval_sec =
1137  makeNumericConstant(bigint_ti,
1138  (op == kMINUS ? -interval_lit->get_constval().bigintval
1139  : interval_lit->get_constval().bigintval) /
1140  1000);
1141  } else {
1142  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1143  kDIVIDE,
1144  kONE,
1145  interval,
1146  makeNumericConstant(bigint_ti, 1000));
1147  if (op == kMINUS) {
1148  interval_sec =
1149  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1150  }
1151  }
1152  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1153  }
1154  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1155  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1156  bigint_ti, false, kUMINUS, interval)
1157  : interval;
1158  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1159 }
Definition: sqltypes.h:48
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:52
Definition: sqldefs.h:40
Definition: sqldefs.h:69
#define CHECK(condition)
Definition: Logger.h:197
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 1281 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1282  {
1283  CHECK_EQ(size_t(1), rex_function->size());
1284  const auto arg = translateScalarRex(rex_function->getOperand(0));
1285  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1286  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1287  if (!arg_lit || arg_lit->get_is_null()) {
1288  throw std::runtime_error(datetime_err);
1289  }
1290  CHECK(arg_lit->get_type_info().is_string());
1291  if (*arg_lit->get_constval().stringval != "NOW"sv) {
1292  throw std::runtime_error(datetime_err);
1293  }
1294  return translateNow();
1295 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 > translateNow() const
#define CHECK(condition)
Definition: Logger.h:197

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

988  {
989  CHECK_EQ(size_t(2), rex_function->size());
990  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
991  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
993  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
994  const bool is_date_trunc = rex_function->getName() == "PG_DATE_TRUNC"sv;
995  if (is_date_trunc) {
996  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
997  } else {
998  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
999  }
1000 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 1394 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(), generate_TableFunctionsFactory_init::i, SQLTypeInfo::is_decimal(), kDIVIDE, kONE, kSMALLINT, kTEXT, LOG, Parser::OperExpr::normalize(), rewrite_to_date_trunc(), SQLTypeInfo::set_notnull(), RexOperator::size(), Datum::smallintval, generate_TableFunctionsFactory_init::t, translateAbs(), translateArrayFunction(), translateBinaryGeoFunction(), translateCardinality(), translateCurrentUser(), translateDateadd(), translateDatediff(), translateDatepart(), translateDatetime(), translateExtract(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoBinaryConstructor(), translateGeoPredicate(), translateGeoProjection(), translateHPTLiteral(), translateItem(), translateKeyForString(), translateLength(), translateLike(), translateLikely(), translateLower(), translateNow(), translateOffsetInFragment(), translateRegexp(), translateSampleRatio(), translateScalarRex(), translateSign(), translateTernaryGeoFunction(), translateUnaryGeoFunction(), translateUnlikely(), and logger::WARNING.

Referenced by translateScalarRex().

1395  {
1396  if (func_resolve(rex_function->getName(), "LIKE"sv, "PG_ILIKE"sv)) {
1397  return translateLike(rex_function);
1398  }
1399  if (rex_function->getName() == "REGEXP_LIKE"sv) {
1400  return translateRegexp(rex_function);
1401  }
1402  if (rex_function->getName() == "LIKELY"sv) {
1403  return translateLikely(rex_function);
1404  }
1405  if (rex_function->getName() == "UNLIKELY"sv) {
1406  return translateUnlikely(rex_function);
1407  }
1408  if (func_resolve(rex_function->getName(), "PG_EXTRACT"sv, "PG_DATE_TRUNC"sv)) {
1409  return translateExtract(rex_function);
1410  }
1411  if (rex_function->getName() == "DATEADD"sv) {
1412  return translateDateadd(rex_function);
1413  }
1414  if (rex_function->getName() == "DATEDIFF"sv) {
1415  return translateDatediff(rex_function);
1416  }
1417  if (rex_function->getName() == "DATEPART"sv) {
1418  return translateDatepart(rex_function);
1419  }
1420  if (func_resolve(rex_function->getName(), "LENGTH"sv, "CHAR_LENGTH"sv)) {
1421  return translateLength(rex_function);
1422  }
1423  if (rex_function->getName() == "KEY_FOR_STRING"sv) {
1424  return translateKeyForString(rex_function);
1425  }
1426  if (rex_function->getName() == "SAMPLE_RATIO"sv) {
1427  return translateSampleRatio(rex_function);
1428  }
1429  if (rex_function->getName() == "CURRENT_USER"sv) {
1430  return translateCurrentUser(rex_function);
1431  }
1432  if (g_enable_experimental_string_functions && rex_function->getName() == "LOWER"sv) {
1433  return translateLower(rex_function);
1434  }
1435  if (func_resolve(rex_function->getName(), "CARDINALITY"sv, "ARRAY_LENGTH"sv)) {
1436  return translateCardinality(rex_function);
1437  }
1438  if (rex_function->getName() == "ITEM"sv) {
1439  return translateItem(rex_function);
1440  }
1441  if (rex_function->getName() == "NOW"sv) {
1442  return translateNow();
1443  }
1444  if (rex_function->getName() == "DATETIME"sv) {
1445  return translateDatetime(rex_function);
1446  }
1447  if (func_resolve(rex_function->getName(), "usTIMESTAMP"sv, "nsTIMESTAMP"sv)) {
1448  return translateHPTLiteral(rex_function);
1449  }
1450  if (rex_function->getName() == "ABS"sv) {
1451  return translateAbs(rex_function);
1452  }
1453  if (rex_function->getName() == "SIGN"sv) {
1454  return translateSign(rex_function);
1455  }
1456  if (func_resolve(rex_function->getName(), "CEIL"sv, "FLOOR"sv)) {
1457  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1458  rex_function->getType(),
1459  rex_function->getName(),
1460  translateFunctionArgs(rex_function));
1461  } else if (rex_function->getName() == "ROUND"sv) {
1462  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1463  translateFunctionArgs(rex_function);
1464 
1465  if (rex_function->size() == 1) {
1466  // push a 0 constant if 2nd operand is missing.
1467  // this needs to be done as calcite returns
1468  // only the 1st operand without defaulting the 2nd one
1469  // when the user did not specify the 2nd operand.
1470  SQLTypes t = kSMALLINT;
1471  Datum d;
1472  d.smallintval = 0;
1473  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1474  }
1475 
1476  // make sure we have only 2 operands
1477  CHECK(args.size() == 2);
1478 
1479  if (!args[0]->get_type_info().is_number()) {
1480  throw std::runtime_error("Only numeric 1st operands are supported");
1481  }
1482 
1483  // the 2nd operand does not need to be a constant
1484  // it can happily reference another integer column
1485  if (!args[1]->get_type_info().is_integer()) {
1486  throw std::runtime_error("Only integer 2nd operands are supported");
1487  }
1488 
1489  // Calcite may upcast decimals in a way that is
1490  // incompatible with the extension function input. Play it safe and stick with the
1491  // argument type instead.
1492  const SQLTypeInfo ret_ti = args[0]->get_type_info().is_decimal()
1493  ? args[0]->get_type_info()
1494  : rex_function->getType();
1495 
1496  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1497  ret_ti, rex_function->getName(), args);
1498  }
1499  if (rex_function->getName() == "DATETIME_PLUS"sv) {
1500  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1501  rex_function->getName(),
1502  translateFunctionArgs(rex_function));
1503  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1504  if (date_trunc) {
1505  return date_trunc;
1506  }
1507  return translateDateadd(rex_function);
1508  }
1509  if (rex_function->getName() == "/INT"sv) {
1510  CHECK_EQ(size_t(2), rex_function->size());
1511  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1512  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1513  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1514  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1515  }
1516  if (rex_function->getName() == "Reinterpret"sv) {
1517  CHECK_EQ(size_t(1), rex_function->size());
1518  return translateScalarRex(rex_function->getOperand(0));
1519  }
1520  if (func_resolve(rex_function->getName(),
1521  "ST_X"sv,
1522  "ST_Y"sv,
1523  "ST_XMin"sv,
1524  "ST_YMin"sv,
1525  "ST_XMax"sv,
1526  "ST_YMax"sv,
1527  "ST_NRings"sv,
1528  "ST_NPoints"sv,
1529  "ST_Length"sv,
1530  "ST_Perimeter"sv,
1531  "ST_Area"sv,
1532  "ST_SRID"sv,
1533  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
1534  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
1535  "OmniSci_Geo_PolyBoundsPtr"sv,
1536  "OmniSci_Geo_PolyRenderGroup"sv)) {
1537  CHECK_EQ(rex_function->size(), size_t(1));
1538  return translateUnaryGeoFunction(rex_function);
1539  }
1540  if (func_resolve(rex_function->getName(),
1541  "convert_meters_to_pixel_width"sv,
1542  "convert_meters_to_pixel_height"sv,
1543  "is_point_in_view"sv,
1544  "is_point_size_in_view"sv)) {
1545  return translateFunctionWithGeoArg(rex_function);
1546  }
1547  if (func_resolve(rex_function->getName(),
1548  "ST_Distance"sv,
1549  "ST_MaxDistance"sv,
1550  "ST_Intersects"sv,
1551  "ST_Disjoint"sv,
1552  "ST_Contains"sv,
1553  "ST_Overlaps"sv,
1554  "ST_Approx_Overlaps"sv,
1555  "ST_Within"sv)) {
1556  CHECK_EQ(rex_function->size(), size_t(2));
1557  return translateBinaryGeoFunction(rex_function);
1558  }
1559  if (func_resolve(rex_function->getName(), "ST_DWithin"sv, "ST_DFullyWithin"sv)) {
1560  CHECK_EQ(rex_function->size(), size_t(3));
1561  return translateTernaryGeoFunction(rex_function);
1562  }
1563  if (rex_function->getName() == "OFFSET_IN_FRAGMENT"sv) {
1564  CHECK_EQ(size_t(0), rex_function->size());
1565  return translateOffsetInFragment();
1566  }
1567  if (rex_function->getName() == "ARRAY"sv) {
1568  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1569  return translateArrayFunction(rex_function);
1570  }
1571  if (func_resolve(rex_function->getName(),
1572  "ST_GeomFromText"sv,
1573  "ST_GeogFromText"sv,
1574  "ST_Point"sv,
1575  "ST_Centroid"sv,
1576  "ST_SetSRID"sv)) {
1577  SQLTypeInfo ti;
1578  return translateGeoProjection(rex_function, ti, false);
1579  }
1580  if (func_resolve(rex_function->getName(),
1581  "ST_Intersection"sv,
1582  "ST_Difference"sv,
1583  "ST_Union"sv,
1584  "ST_Buffer"sv)) {
1585  SQLTypeInfo ti;
1586  return translateGeoBinaryConstructor(rex_function, ti, false);
1587  }
1588  if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
1589  SQLTypeInfo ti;
1590  return translateGeoPredicate(rex_function, ti, false);
1591  }
1592 
1593  auto arg_expr_list = translateFunctionArgs(rex_function);
1594  if (rex_function->getName() == std::string("||") ||
1595  rex_function->getName() == std::string("SUBSTRING")) {
1596  SQLTypeInfo ret_ti(kTEXT, false);
1597  return makeExpr<Analyzer::FunctionOper>(
1598  ret_ti, rex_function->getName(), arg_expr_list);
1599  }
1600  // Reset possibly wrong return type of rex_function to the return
1601  // type of the optimal valid implementation. The return type can be
1602  // wrong in the case of multiple implementations of UDF functions
1603  // that have different return types but Calcite specifies the return
1604  // type according to the first implementation.
1605  SQLTypeInfo ret_ti;
1606  try {
1607  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1608 
1609  auto ext_func_args = ext_func_sig.getArgs();
1610  CHECK_EQ(arg_expr_list.size(), ext_func_args.size());
1611  for (size_t i = 0; i < arg_expr_list.size(); i++) {
1612  // fold casts on constants
1613  if (auto constant =
1614  std::dynamic_pointer_cast<Analyzer::Constant>(arg_expr_list[i])) {
1615  auto ext_func_arg_ti = ext_arg_type_to_type_info(ext_func_args[i]);
1616  if (ext_func_arg_ti != arg_expr_list[i]->get_type_info()) {
1617  arg_expr_list[i] = constant->add_cast(ext_func_arg_ti);
1618  }
1619  }
1620  }
1621 
1622  ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
1623  } catch (ExtensionFunctionBindingError& e) {
1624  LOG(WARNING) << "RelAlgTranslator::translateFunction: " << e.what();
1625  throw;
1626  }
1627 
1628  // By default, the extension function type will not allow nulls. If one of the arguments
1629  // is nullable, the extension function must also explicitly allow nulls.
1630  bool arguments_not_null = true;
1631  for (const auto& arg_expr : arg_expr_list) {
1632  if (!arg_expr->get_type_info().get_notnull()) {
1633  arguments_not_null = false;
1634  break;
1635  }
1636  }
1637  ret_ti.set_notnull(arguments_not_null);
1638 
1639  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
1640 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateOffsetInFragment() const
std::shared_ptr< Analyzer::Expr > translateRegexp(const RexFunctionOperator *) const
SQLTypes
Definition: sqltypes.h:37
std::shared_ptr< Analyzer::Expr > translateUnlikely(const RexFunctionOperator *) const
#define LOG(tag)
Definition: Logger.h:188
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 > translateNow() 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
int16_t smallintval
Definition: sqltypes.h:204
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:272
Definition: sqltypes.h:51
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) 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 > translateGeoBinaryConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
T bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< T > &ext_funcs, const std::string processor)
std::shared_ptr< Analyzer::Expr > translateLikely(const RexFunctionOperator *) const
void set_notnull(bool n)
Definition: sqltypes.h:408
#define CHECK(condition)
Definition: Logger.h:197
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateFunctionWithGeoArg(const RexFunctionOperator *) const
const std::string & getName() const
std::shared_ptr< Analyzer::Expr > translateCardinality(const RexFunctionOperator *) const
bool is_decimal() const
Definition: sqltypes.h:481
std::shared_ptr< Analyzer::Expr > translateHPTLiteral(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatepart(const RexFunctionOperator *) 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 > translateGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) 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 1721 of file RelAlgTranslator.cpp.

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

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

1722  {
1723  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1724  for (size_t i = 0; i < rex_function->size(); ++i) {
1725  args.push_back(translateScalarRex(rex_function->getOperand(i)));
1726  }
1727  return args;
1728 }
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 1233 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().

1234  {
1235  int32_t lindex = 0;
1236  std::string specialized_geofunc{rex_function->getName()};
1237  if (func_resolve(rex_function->getName(),
1238  "convert_meters_to_pixel_width"sv,
1239  "convert_meters_to_pixel_height"sv)) {
1240  CHECK_EQ(rex_function->size(), 6u);
1241  SQLTypeInfo arg_ti;
1242  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1243  args.push_back(translateScalarRex(rex_function->getOperand(0)));
1244  auto geoargs = translateGeoFunctionArg(
1245  rex_function->getOperand(1), arg_ti, lindex, false, true, false);
1246  // only works on points
1247  if (arg_ti.get_type() != kPOINT) {
1248  throw QueryNotSupported(rex_function->getName() +
1249  " expects a point for the second argument");
1250  }
1251 
1252  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1253 
1254  // Add compression information
1255  Datum input_compression;
1256  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1257  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1258  if (arg_ti.get_input_srid() != 4326) {
1259  throw QueryNotSupported(
1260  rex_function->getName() +
1261  " currently only supports points of with SRID WGS84/EPSG:4326");
1262  }
1263  Datum input_srid;
1264  input_srid.intval = arg_ti.get_input_srid();
1265  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
1266  Datum output_srid;
1267  // Forcing web-mercator projection for now
1268  // TODO(croot): check that the input-to-output conversion routines exist?
1269  output_srid.intval =
1270  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1271  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1272 
1273  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1274  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1275  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1276  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1277  return makeExpr<Analyzer::FunctionOper>(
1278  rex_function->getType(), specialized_geofunc, args);
1279  } else if (rex_function->getName() == "is_point_in_view"sv) {
1280  CHECK_EQ(rex_function->size(), 5u);
1281  SQLTypeInfo arg_ti;
1282  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1283  auto geoargs = translateGeoFunctionArg(
1284  rex_function->getOperand(0), arg_ti, lindex, false, true, false);
1285  // only works on points
1286  if (arg_ti.get_type() != kPOINT) {
1287  throw QueryNotSupported(rex_function->getName() +
1288  " expects a point for the second argument");
1289  }
1290 
1291  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1292 
1293  // Add compression information
1294  Datum input_compression;
1295  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1296  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1297  if (arg_ti.get_input_srid() != 4326) {
1298  throw QueryNotSupported(
1299  rex_function->getName() +
1300  " currently only supports points of with SRID WGS84/EPSG:4326");
1301  }
1302  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1303  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1304  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1305  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1306  return makeExpr<Analyzer::FunctionOper>(
1307  rex_function->getType(), specialized_geofunc, args);
1308  } else if (rex_function->getName() == "is_point_size_in_view"sv) {
1309  CHECK_EQ(rex_function->size(), 6u);
1310  SQLTypeInfo arg_ti;
1311  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1312  auto geoargs = translateGeoFunctionArg(
1313  rex_function->getOperand(0), arg_ti, lindex, false, true, false);
1314  // only works on points
1315  if (arg_ti.get_type() != kPOINT) {
1316  throw QueryNotSupported(rex_function->getName() +
1317  " expects a point for the second argument");
1318  }
1319 
1320  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1321 
1322  // Add compression information
1323  Datum input_compression;
1324  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
1325  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1326  if (arg_ti.get_input_srid() != 4326) {
1327  throw QueryNotSupported(
1328  rex_function->getName() +
1329  " currently only supports points of with SRID WGS84/EPSG:4326");
1330  }
1331  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1332  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1333  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1334  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1335  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1336  return makeExpr<Analyzer::FunctionOper>(
1337  rex_function->getType(), specialized_geofunc, args);
1338  }
1339  CHECK(false);
1340  return nullptr;
1341 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
int32_t intval
Definition: sqltypes.h:205
#define CHECK(condition)
Definition: Logger.h:197
Definition: sqltypes.h:44
const std::string & getName() const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 630 of file RelAlgTranslatorGeo.cpp.

References func_resolve, SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_type(), RexFunctionOperator::getName(), RexOperator::getOperand(), Geospatial::GeoBase::kBUFFER, Geospatial::GeoBase::kDIFFERENCE, kDOUBLE, kENCODING_NONE, Geospatial::GeoBase::kINTERSECTION, kLINESTRING, 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().

633  {
634 #ifndef ENABLE_GEOS
635  throw QueryNotSupported(rex_function->getName() +
636  " geo constructor requires enabled GEOS support");
637 #endif
639  if (rex_function->getName() == "ST_Difference"sv) {
641  } else if (rex_function->getName() == "ST_Union"sv) {
643  } else if (rex_function->getName() == "ST_Buffer"sv) {
645  }
646 
649  SQLTypeInfo arg0_ti;
650  SQLTypeInfo arg1_ti;
651  if (func_resolve(rex_function->getName(),
652  "ST_Intersection"sv,
653  "ST_Difference"sv,
654  "ST_Union"sv,
655  "ST_Buffer"sv)) {
656  // First arg: geometry
657  int32_t lindex0 = 0;
658  geoargs0 = translateGeoFunctionArg(
659  rex_function->getOperand(0), arg0_ti, lindex0, false, false, true, true);
660  if (arg0_ti.get_type() == kLINESTRING) {
661  if (lindex0 != 0) {
662  throw QueryNotSupported(
663  "Indexed LINESTRING geometries not supported in this context");
664  }
665  }
666  }
667  if (func_resolve(rex_function->getName(),
668  "ST_Intersection"sv,
669  "ST_Difference"sv,
670  "ST_Union"sv)) {
671  // Second arg: geometry
672  int32_t lindex1 = 0;
673  geoargs1 = translateGeoFunctionArg(
674  rex_function->getOperand(1), arg1_ti, lindex1, false, false, true, true);
675  if (arg1_ti.get_type() == kLINESTRING) {
676  if (lindex1 != 0) {
677  throw QueryNotSupported(
678  "Indexed LINESTRING geometries not supported in this context");
679  }
680  }
681  } else if (func_resolve(rex_function->getName(), "ST_Buffer"sv)) {
682  // Second arg: double scalar
683  auto param_expr = translateScalarRex(rex_function->getOperand(1));
684  arg1_ti = SQLTypeInfo(kDOUBLE, false);
685  if (param_expr->get_type_info().get_type() != kDOUBLE) {
686  param_expr = param_expr->add_cast(arg1_ti);
687  }
688  geoargs1 = {param_expr};
689  }
690 
691  auto srid = ti.get_output_srid();
692  ti = arg0_ti;
694  ti.set_compression(kENCODING_NONE); // Constructed geometries are not compressed
695  ti.set_comp_param(0);
696  if (srid > 0) {
697  ti.set_output_srid(srid); // Requested SRID sent from above
698  }
699  return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
700 }
void set_compression(EncodingType c)
Definition: sqltypes.h:411
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
void set_output_srid(int s)
Definition: sqltypes.h:407
void set_comp_param(int p)
Definition: sqltypes.h:412
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:182
const std::string & getName() const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:317
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:401

+ 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(), generate_TableFunctionsFactory_init::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:75
#define CHECK_GE(x, y)
Definition: Logger.h:210
unsigned getIndex() const
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
Definition: Catalog.cpp:1547
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:207
const RelAlgNode * getSourceNode() const
#define CHECK(condition)
Definition: Logger.h:197
SQLTypeInfo columnType
#define IS_GEO(T)
Definition: sqltypes.h:242
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 1208 of file RelAlgTranslatorGeo.cpp.

References RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getOperandAndRelease(), RexOperator::getOperator(), RexOperator::getType(), kLE, RexOperator::size(), and translateTernaryGeoFunction().

Referenced by translateOper().

1209  {
1210  if (rex_operator->size() != size_t(2)) {
1211  return nullptr;
1212  }
1213 
1214  const auto rex_operand = rex_operator->getOperand(0);
1215  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_operand);
1216  if (!rex_function) {
1217  return nullptr;
1218  }
1219  if (rex_function->getName() == "ST_Distance"sv && rex_operator->getOperator() == kLE) {
1220  auto ti = rex_operator->getType();
1221  std::vector<std::unique_ptr<const RexScalar>> st_dwithin_operands;
1222  st_dwithin_operands.emplace_back(rex_function->getOperandAndRelease(0));
1223  st_dwithin_operands.emplace_back(rex_function->getOperandAndRelease(1));
1224  st_dwithin_operands.emplace_back(rex_operator->getOperandAndRelease(1));
1225  std::unique_ptr<RexFunctionOperator> st_dwithin(
1226  new RexFunctionOperator("ST_DWithin", st_dwithin_operands, ti));
1227  return translateTernaryGeoFunction(st_dwithin.get());
1228  }
1229 
1230  return nullptr;
1231 }
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:35
const RexScalar * getOperandAndRelease(const size_t idx) const
SQLOps getOperator() const
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) 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::translateGeoFunctionArg ( const RexScalar rex_scalar,
SQLTypeInfo arg_ti,
int32_t &  lindex,
const bool  with_bounds,
const bool  with_render_group,
const bool  expand_geo_col,
const bool  is_projection = false 
) const
private

Definition at line 225 of file RelAlgTranslatorGeo.cpp.

References run_benchmark_import::args, Datum::boolval, CHECK, CHECK_EQ, fold_expr(), func_resolve, Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_type(), Datum::intval, IS_GEO, kARRAY, kBOOLEAN, kCAST, kDOUBLE, kENCODING_NONE, kGEOGRAPHY, kGEOMETRY, kINT, kLINESTRING, kNULLT, kPOINT, kSMALLINT, kTEXT, kTINYINT, SQLTypeInfo::set_compression(), SQLTypeInfo::set_input_srid(), SQLTypeInfo::set_output_srid(), SQLTypeInfo::set_subtype(), SQLTypeInfo::set_type(), anonymous_namespace{RelAlgTranslatorGeo.cpp}::suffix(), to_string(), translateGeoBinaryConstructor(), translateGeoColumn(), translateGeoLiteral(), translateGeoPredicate(), translateInput(), translateLiteral(), and translateScalarRex().

Referenced by translateBinaryGeoFunction(), translateFunctionWithGeoArg(), translateGeoBinaryConstructor(), translateGeoPredicate(), translateGeoProjection(), translateTernaryGeoFunction(), and translateUnaryGeoFunction().

232  {
233  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
234 
235  const auto rex_input = dynamic_cast<const RexInput*>(rex_scalar);
236  if (rex_input) {
237  const auto input = translateInput(rex_input);
238  const auto column = dynamic_cast<const Analyzer::ColumnVar*>(input.get());
239  if (!column || !column->get_type_info().is_geometry()) {
240  throw QueryNotSupported("Geo function is expecting a geo column argument");
241  }
242  return translateGeoColumn(
243  rex_input, arg_ti, with_bounds, with_render_group, expand_geo_col);
244  }
245  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_scalar);
246  if (rex_function) {
247  if (rex_function->getName() == "ST_Transform"sv) {
248  CHECK_EQ(size_t(2), rex_function->size());
249  const auto rex_scalar0 =
250  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
251  if (!rex_scalar0) {
252  throw QueryNotSupported(rex_function->getName() + ": unexpected first argument");
253  }
254 
255  const auto rex_literal =
256  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
257  if (!rex_literal) {
258  throw QueryNotSupported(rex_function->getName() +
259  ": second argument is expected to be a literal");
260  }
261  const auto e = translateLiteral(rex_literal);
262  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
263  if (!ce || !e->get_type_info().is_integer()) {
264  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
265  }
266  int32_t srid = 0;
267  if (e->get_type_info().get_type() == kSMALLINT) {
268  srid = static_cast<int32_t>(ce->get_constval().smallintval);
269  } else if (e->get_type_info().get_type() == kTINYINT) {
270  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
271  } else if (e->get_type_info().get_type() == kINT) {
272  srid = static_cast<int32_t>(ce->get_constval().intval);
273  } else {
274  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
275  }
276  if (srid != 900913) {
277  throw QueryNotSupported(rex_function->getName() + ": unsupported output SRID " +
278  std::to_string(srid));
279  }
280  arg_ti.set_output_srid(srid); // Forward output srid down to argument translation
281  auto arg0 = translateGeoFunctionArg(
282  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
283 
284  if (arg_ti.get_input_srid() > 0) {
285  if (arg_ti.get_input_srid() != 4326) {
286  throw QueryNotSupported(rex_function->getName() + ": unsupported input SRID " +
287  std::to_string(arg_ti.get_input_srid()));
288  }
289  arg_ti.set_output_srid(
290  srid); // We have a valid input SRID, register the output SRID for transform
291  } else {
292  throw QueryNotSupported(rex_function->getName() +
293  ": unexpected input SRID, unable to transform");
294  }
295  return arg0;
296  } else if (func_resolve(
297  rex_function->getName(), "ST_GeomFromText"sv, "ST_GeogFromText"sv)) {
298  CHECK(rex_function->size() == size_t(1) || rex_function->size() == size_t(2));
299  // First - register srid, then send it to geo literal translation
300  int32_t srid = 0;
301  if (rex_function->size() == 2) {
302  const auto rex_literal =
303  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
304  if (!rex_literal) {
305  throw QueryNotSupported(rex_function->getName() +
306  ": second argument is expected to be a literal");
307  }
308  const auto e = translateLiteral(rex_literal);
309  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
310  if (!ce || !e->get_type_info().is_integer()) {
311  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
312  }
313  if (e->get_type_info().get_type() == kSMALLINT) {
314  srid = static_cast<int32_t>(ce->get_constval().smallintval);
315  } else if (e->get_type_info().get_type() == kTINYINT) {
316  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
317  } else if (e->get_type_info().get_type() == kINT) {
318  srid = static_cast<int32_t>(ce->get_constval().intval);
319  } else {
320  throw QueryNotSupported(rex_function->getName() + " expecting integer SRID");
321  }
322  if (srid != 0 && srid != 4326 && srid != 900913) {
323  throw QueryNotSupported(rex_function->getName() + ": unsupported SRID " +
324  std::to_string(srid));
325  }
326  }
327  arg_ti.set_input_srid(srid); // Input SRID
328  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
329 
330  const auto rex_literal =
331  dynamic_cast<const RexLiteral*>(rex_function->getOperand(0));
332  if (!rex_literal) {
333  throw QueryNotSupported(rex_function->getName() +
334  " expects a string literal as first argument");
335  }
336  auto arg0 = translateGeoLiteral(rex_literal, arg_ti, with_bounds);
337  arg_ti.set_subtype((rex_function->getName() == "ST_GeogFromText"sv) ? kGEOGRAPHY
338  : kGEOMETRY);
339  return arg0;
340  } else if (rex_function->getName() == "ST_PointN"sv) {
341  CHECK_EQ(size_t(2), rex_function->size());
342  const auto rex_scalar0 =
343  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
344  if (!rex_scalar0) {
345  throw QueryNotSupported(rex_function->getName() +
346  ": expects scalar as first argument");
347  }
348  auto arg0 = translateGeoFunctionArg(
349  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
350  if (arg_ti.get_type() != kLINESTRING) {
351  throw QueryNotSupported(rex_function->getName() +
352  " expects LINESTRING as first argument");
353  }
354  const auto rex_literal =
355  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
356  if (!rex_literal) {
357  throw QueryNotSupported(rex_function->getName() +
358  ": second argument is expected to be a literal");
359  }
360  const auto e = translateLiteral(rex_literal);
361  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
362  if (!ce || !e->get_type_info().is_integer()) {
363  throw QueryNotSupported(rex_function->getName() +
364  ": expecting integer index as second argument");
365  }
366  int32_t index = 0;
367  if (e->get_type_info().get_type() == kSMALLINT) {
368  index = static_cast<int32_t>(ce->get_constval().smallintval);
369  } else if (e->get_type_info().get_type() == kTINYINT) {
370  index = static_cast<int32_t>(ce->get_constval().tinyintval);
371  } else if (e->get_type_info().get_type() == kINT) {
372  index = static_cast<int32_t>(ce->get_constval().intval);
373  } else {
374  throw QueryNotSupported(rex_function->getName() + " expecting integer index");
375  }
376  if (lindex != 0) {
377  throw QueryNotSupported(rex_function->getName() +
378  ": LINESTRING is already indexed");
379  }
380  if (index == 0) {
381  throw QueryNotSupported(rex_function->getName() + ": invalid index");
382  }
383  lindex = index;
384  return arg0;
385  } else if (rex_function->getName() == "ST_StartPoint"sv) {
386  CHECK_EQ(size_t(1), rex_function->size());
387  const auto rex_scalar0 =
388  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
389  if (!rex_scalar0) {
390  throw QueryNotSupported(rex_function->getName() +
391  ": expects scalar as first argument");
392  }
393  auto arg0 = translateGeoFunctionArg(
394  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
395  if (arg_ti.get_type() != kLINESTRING) {
396  throw QueryNotSupported(rex_function->getName() +
397  " expects LINESTRING as first argument");
398  }
399  if (lindex != 0) {
400  throw QueryNotSupported(rex_function->getName() +
401  ": LINESTRING is already indexed");
402  }
403  lindex = 1;
404  return arg0;
405  } else if (rex_function->getName() == "ST_EndPoint"sv) {
406  CHECK_EQ(size_t(1), rex_function->size());
407  const auto rex_scalar0 =
408  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
409  if (!rex_scalar0) {
410  throw QueryNotSupported(rex_function->getName() +
411  ": expects scalar as first argument");
412  }
413  auto arg0 = translateGeoFunctionArg(
414  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
415  if (arg_ti.get_type() != kLINESTRING) {
416  throw QueryNotSupported(rex_function->getName() +
417  " expects LINESTRING as first argument");
418  }
419  if (lindex != 0) {
420  throw QueryNotSupported(rex_function->getName() +
421  ": LINESTRING is already indexed");
422  }
423  lindex = -1;
424  return arg0;
425  } else if (rex_function->getName() == "ST_SRID"sv) {
426  CHECK_EQ(size_t(1), rex_function->size());
427  const auto rex_scalar0 =
428  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
429  if (!rex_scalar0) {
430  throw QueryNotSupported(rex_function->getName() +
431  ": expects scalar as first argument");
432  }
433  auto arg0 = translateGeoFunctionArg(
434  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
435  if (!IS_GEO(arg_ti.get_type())) {
436  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
437  }
438  return arg0;
439  } else if (rex_function->getName() == "ST_SetSRID"sv) {
440  CHECK_EQ(size_t(2), rex_function->size());
441  const auto rex_scalar0 =
442  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
443  if (!rex_scalar0) {
444  throw QueryNotSupported(rex_function->getName() +
445  ": expects scalar as first argument");
446  }
447  auto arg0 = translateGeoFunctionArg(rex_scalar0,
448  arg_ti,
449  lindex,
450  with_bounds,
451  with_render_group,
452  expand_geo_col,
453  is_projection);
454  if (!IS_GEO(arg_ti.get_type())) {
455  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
456  }
457  const auto rex_literal =
458  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
459  if (!rex_literal) {
460  throw QueryNotSupported(rex_function->getName() +
461  ": second argument is expected to be a literal");
462  }
463  const auto e = translateLiteral(rex_literal);
464  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
465  if (!ce || !e->get_type_info().is_integer()) {
466  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
467  }
468  int32_t srid = 0;
469  if (e->get_type_info().get_type() == kSMALLINT) {
470  srid = static_cast<int32_t>(ce->get_constval().smallintval);
471  } else if (e->get_type_info().get_type() == kTINYINT) {
472  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
473  } else if (e->get_type_info().get_type() == kINT) {
474  srid = static_cast<int32_t>(ce->get_constval().intval);
475  } else {
476  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
477  }
478  arg_ti.set_input_srid(srid); // Input SRID
479  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
480  return arg0;
481  } else if (rex_function->getName() == "CastToGeography"sv) {
482  CHECK_EQ(size_t(1), rex_function->size());
483  const auto rex_scalar0 =
484  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
485  if (!rex_scalar0) {
486  throw QueryNotSupported(rex_function->getName() +
487  ": expects scalar as first argument");
488  }
489  auto arg0 = translateGeoFunctionArg(
490  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
491  if (!IS_GEO(arg_ti.get_type())) {
492  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
493  }
494  if (arg_ti.get_output_srid() != 4326) {
495  throw QueryNotSupported(rex_function->getName() +
496  " expects geometry with SRID=4326");
497  }
498  arg_ti.set_subtype(kGEOGRAPHY);
499  return arg0;
500  } else if (rex_function->getName() == "ST_Point"sv) {
501  CHECK_EQ(size_t(2), rex_function->size());
502  arg_ti.set_type(kPOINT);
503  arg_ti.set_subtype(kGEOMETRY);
504  arg_ti.set_input_srid(0);
505  arg_ti.set_output_srid(0);
507 
508  auto coord1 = translateScalarRex(rex_function->getOperand(0));
509  auto coord2 = translateScalarRex(rex_function->getOperand(1));
510  auto d_ti = SQLTypeInfo(kDOUBLE, true);
511  auto cast_coord1 = coord1->add_cast(d_ti);
512  auto cast_coord2 = coord2->add_cast(d_ti);
513  // First try to fold to geo literal
514  auto fold1 = fold_expr(cast_coord1.get());
515  auto fold2 = fold_expr(cast_coord2.get());
516  auto const_coord1 = std::dynamic_pointer_cast<Analyzer::Constant>(fold1);
517  auto const_coord2 = std::dynamic_pointer_cast<Analyzer::Constant>(fold2);
518  if (const_coord1 && const_coord2) {
519  CHECK(const_coord1->get_type_info().get_type() == kDOUBLE);
520  CHECK(const_coord2->get_type_info().get_type() == kDOUBLE);
521  std::string wkt = "POINT(" +
522  std::to_string(const_coord1->get_constval().doubleval) + " " +
523  std::to_string(const_coord2->get_constval().doubleval) + ")";
524  RexLiteral rex_literal{wkt, kTEXT, kNULLT, 0, 0, 0, 0};
525  auto args = translateGeoLiteral(&rex_literal, arg_ti, false);
526  CHECK(arg_ti.get_type() == kPOINT);
527  return args;
528  }
529  // Couldn't fold to geo literal, construct on the fly
530  auto da_ti = SQLTypeInfo(kARRAY, true);
531  da_ti.set_subtype(kDOUBLE);
532  da_ti.set_size(16);
533  auto cast_coords = {cast_coord1, cast_coord2};
534  auto is_local_alloca = !is_projection;
535  auto ae = makeExpr<Analyzer::ArrayExpr>(da_ti, cast_coords, false, is_local_alloca);
536  // cast it to tinyint[16]
537  SQLTypeInfo tia_ti = SQLTypeInfo(kARRAY, true);
538  tia_ti.set_subtype(kTINYINT);
539  tia_ti.set_size(16);
540  return {makeExpr<Analyzer::UOper>(tia_ti, false, kCAST, ae)};
541  } else if (rex_function->getName() == "ST_Centroid"sv) {
542  CHECK_EQ(size_t(1), rex_function->size());
543  arg_ti.set_type(kPOINT);
544  arg_ti.set_subtype(kGEOMETRY);
545  arg_ti.set_input_srid(0);
546  arg_ti.set_output_srid(0);
548 
549  SQLTypeInfo geo_ti;
550  bool with_bounds = false;
551  auto geoargs = translateGeoFunctionArg(
552  rex_function->getOperand(0), geo_ti, lindex, with_bounds, false, false);
553 
554  auto specialized_geofunc = rex_function->getName() + suffix(geo_ti.get_type());
555  if (lindex != 0) {
556  throw QueryNotSupported(rex_function->getName() +
557  " doesn't support indexed LINESTRINGs");
558  }
559  Datum input_compression;
560  input_compression.intval = Geospatial::get_compression_scheme(geo_ti);
561  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
562  Datum input_srid;
563  input_srid.intval = geo_ti.get_input_srid();
564  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
565  Datum output_srid;
566  output_srid.intval = geo_ti.get_output_srid();
567  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
568 
569  // TODO: find a better way to get 2 coords from the centroid functions
570  Datum coord_selector;
571  coord_selector.boolval = false;
572  geoargs.push_back(makeExpr<Analyzer::Constant>(kBOOLEAN, false, coord_selector));
573  std::shared_ptr<Analyzer::Expr> coord1 = makeExpr<Analyzer::FunctionOper>(
574  rex_function->getType(), specialized_geofunc, geoargs);
575  geoargs.pop_back();
576  coord_selector.boolval = true;
577  geoargs.push_back(makeExpr<Analyzer::Constant>(kBOOLEAN, false, coord_selector));
578  std::shared_ptr<Analyzer::Expr> coord2 = makeExpr<Analyzer::FunctionOper>(
579  rex_function->getType(), specialized_geofunc, geoargs);
580 
581  auto da_ti = SQLTypeInfo(kARRAY, true);
582  da_ti.set_subtype(kDOUBLE);
583  da_ti.set_size(16);
584  auto centroid_coords = {coord1, coord2};
585  auto is_local_alloca = !is_projection;
586  auto ae =
587  makeExpr<Analyzer::ArrayExpr>(da_ti, centroid_coords, false, is_local_alloca);
588  // cast it to tinyint[16]
589  SQLTypeInfo tia_ti = SQLTypeInfo(kARRAY, true);
590  tia_ti.set_subtype(kTINYINT);
591  tia_ti.set_size(16);
592  return {makeExpr<Analyzer::UOper>(tia_ti, false, kCAST, ae)};
593  } else if (func_resolve(rex_function->getName(),
594  "ST_Intersection"sv,
595  "ST_Difference"sv,
596  "ST_Union"sv,
597  "ST_Buffer"sv)) {
598  CHECK_EQ(size_t(2), rex_function->size());
599  // What geo type will the constructor return? Could be anything.
600  return {translateGeoBinaryConstructor(rex_function, arg_ti, with_bounds)};
601  } else if (func_resolve(rex_function->getName(), "ST_IsEmpty"sv, "ST_IsValid"sv)) {
602  CHECK_EQ(size_t(1), rex_function->size());
603  return {translateGeoPredicate(rex_function, arg_ti, with_bounds)};
604  } else {
605  throw QueryNotSupported("Unsupported argument: " + rex_function->getName());
606  }
607  }
608  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
609  if (rex_literal) {
610  return translateGeoLiteral(rex_literal, arg_ti, with_bounds);
611  }
612  throw QueryNotSupported("Geo function argument not supported");
613 }
void set_compression(EncodingType c)
Definition: sqltypes.h:411
#define CHECK_EQ(x, y)
Definition: Logger.h:205
auto func_resolve
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
bool boolval
Definition: sqltypes.h:202
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:402
Definition: sqldefs.h:49
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
int32_t intval
Definition: sqltypes.h:205
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:405
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
void set_output_srid(int s)
Definition: sqltypes.h:407
Definition: sqltypes.h:51
std::shared_ptr< Analyzer::Expr > translateGeoBinaryConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:315
#define CHECK(condition)
Definition: Logger.h:197
Definition: sqltypes.h:44
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:242
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:317
std::shared_ptr< Analyzer::Expr > translateGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:401

+ 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  const auto e = translateLiteral(rex_literal);
119  auto wkt = std::dynamic_pointer_cast<Analyzer::Constant>(e);
120  CHECK(wkt);
121  std::vector<double> coords;
122  std::vector<double> bounds;
123  std::vector<int> ring_sizes;
124  std::vector<int> poly_rings;
125  int32_t srid = ti.get_output_srid();
127  *wkt->get_constval().stringval, ti, coords, bounds, ring_sizes, poly_rings)) {
128  throw QueryNotSupported("Could not read geometry from text");
129  }
131  ti.set_input_srid(srid);
132  ti.set_output_srid(srid);
133  // Compress geo literals by default
134  if (srid == 4326) {
136  ti.set_comp_param(32);
137  }
138 
139  std::vector<std::shared_ptr<Analyzer::Expr>> args;
140 
141  std::vector<uint8_t> compressed_coords = Geospatial::compress_coords(coords, ti);
142  std::list<std::shared_ptr<Analyzer::Expr>> compressed_coords_exprs;
143  for (auto cc : compressed_coords) {
144  Datum d;
145  d.tinyintval = cc;
146  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
147  compressed_coords_exprs.push_back(e);
148  }
149  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
150  arr_ti.set_subtype(kTINYINT);
151  arr_ti.set_size(compressed_coords.size() * sizeof(int8_t));
152  arr_ti.set_compression(ti.get_compression());
153  arr_ti.set_comp_param((ti.get_compression() == kENCODING_GEOINT) ? 32 : 64);
154  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, compressed_coords_exprs));
155 
156  auto lit_type = ti.get_type();
157  if (lit_type == kPOLYGON || lit_type == kMULTIPOLYGON) {
158  // ring sizes
159  std::list<std::shared_ptr<Analyzer::Expr>> ring_size_exprs;
160  for (auto c : ring_sizes) {
161  Datum d;
162  d.intval = c;
163  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
164  ring_size_exprs.push_back(e);
165  }
166  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
167  arr_ti.set_subtype(kINT);
168  arr_ti.set_size(ring_sizes.size() * sizeof(int32_t));
169  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, ring_size_exprs));
170 
171  // poly rings
172  if (lit_type == kMULTIPOLYGON) {
173  std::list<std::shared_ptr<Analyzer::Expr>> poly_rings_exprs;
174  for (auto c : poly_rings) {
175  Datum d;
176  d.intval = c;
177  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
178  poly_rings_exprs.push_back(e);
179  }
180  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
181  arr_ti.set_subtype(kINT);
182  arr_ti.set_size(poly_rings.size() * sizeof(int32_t));
183  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, poly_rings_exprs));
184  }
185  }
186 
187  if (with_bounds && ti.has_bounds()) {
188  // bounds
189  std::list<std::shared_ptr<Analyzer::Expr>> bounds_exprs;
190  for (auto b : bounds) {
191  Datum d;
192  d.doubleval = b;
193  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
194  bounds_exprs.push_back(e);
195  }
196  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
197  arr_ti.set_subtype(kDOUBLE);
198  arr_ti.set_size(bounds.size() * sizeof(double));
199  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, bounds_exprs));
200  }
201 
202  return args;
203 }
int8_t tinyintval
Definition: sqltypes.h:203
void set_compression(EncodingType c)
Definition: sqltypes.h:411
void set_size(int s)
Definition: sqltypes.h:409
std::vector< uint8_t > compress_coords(std::vector< double > &coords, const SQLTypeInfo &ti)
Definition: Compression.cpp:52
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:402
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
int32_t intval
Definition: sqltypes.h:205
void set_input_srid(int d)
Definition: sqltypes.h:405
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
bool has_bounds() const
Definition: sqltypes.h:380
void set_output_srid(int s)
Definition: sqltypes.h:407
void set_comp_param(int p)
Definition: sqltypes.h:412
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:907
Definition: sqltypes.h:51
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:319
#define CHECK(condition)
Definition: Logger.h:197
Definition: sqltypes.h:44
double doubleval
Definition: sqltypes.h:208
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:317

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

1344  {
1345  CHECK_EQ(rex_operator->size(), 2u);
1346 
1347  auto translate_input =
1348  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1349  const auto input = dynamic_cast<const RexInput*>(operand);
1350  CHECK(input);
1351 
1352  SQLTypeInfo ti;
1353  const auto exprs = translateGeoColumn(input, ti, true, false, false);
1354  CHECK_GT(exprs.size(), 0u);
1355  if (ti.get_type() == kPOINT) {
1356  return exprs.front();
1357  } else {
1358  return exprs.back();
1359  }
1360  };
1361 
1362  SQLQualifier sql_qual{kONE};
1363  SQLOps sql_op{kOVERLAPS};
1364  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
1365  false,
1366  sql_op,
1367  sql_qual,
1368  translate_input(rex_operator->getOperand(1)),
1369  translate_input(rex_operator->getOperand(0)));
1370 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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:311
#define CHECK_GT(x, y)
Definition: Logger.h:209
Definition: sqldefs.h:69
#define CHECK(condition)
Definition: Logger.h:197
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::translateGeoPredicate ( const RexFunctionOperator rex_function,
SQLTypeInfo ti,
const bool  with_bounds 
) const
private

Definition at line 702 of file RelAlgTranslatorGeo.cpp.

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

Referenced by translateFunction(), and translateGeoFunctionArg().

705  {
706 #ifndef ENABLE_GEOS
707  throw QueryNotSupported(rex_function->getName() +
708  " geo predicate requires enabled GEOS support");
709 #endif
710  int32_t lindex = 0;
711  SQLTypeInfo arg_ti;
712  auto geoargs = translateGeoFunctionArg(
713  rex_function->getOperand(0), arg_ti, lindex, false, false, true, true);
714  if (lindex != 0) {
715  throw QueryNotSupported(
716  "Indexed LINESTRING geometries not supported in this context");
717  }
718  ti = SQLTypeInfo(kBOOLEAN, false);
719  auto op = (rex_function->getName() == "ST_IsEmpty"sv)
722  return makeExpr<Analyzer::GeoUOper>(op, ti, arg_ti, geoargs);
723 }
const RexScalar * getOperand(const size_t idx) const
const std::string & getName() const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) 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 615 of file RelAlgTranslatorGeo.cpp.

References Geospatial::GeoBase::kPROJECTION, and translateGeoFunctionArg().

Referenced by translateFunction().

618  {
619  int32_t lindex = 0;
620  auto geoargs =
621  translateGeoFunctionArg(rex_function, ti, lindex, false, false, true, true);
622  if (lindex != 0) {
623  throw QueryNotSupported(
624  "Indexed LINESTRING geometries not supported in this context");
625  }
626  return makeExpr<Analyzer::GeoUOper>(
627  Geospatial::GeoBase::GeoOp::kPROJECTION, ti, ti, geoargs);
628 }
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) 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 1773 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1774  {
1775  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
1776  Therefore any string having fractional seconds more 3 places after the decimal
1777  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
1778  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
1779  calcite and translating them to generate our own casts.
1780  */
1781  CHECK_EQ(size_t(1), rex_function->size());
1782  const auto operand = translateScalarRex(rex_function->getOperand(0));
1783  const auto& operand_ti = operand->get_type_info();
1784  const auto& target_ti = rex_function->getType();
1785  if (!operand_ti.is_string()) {
1786  throw std::runtime_error(
1787  "High precision timestamp cast argument must be a string. Input type is: " +
1788  operand_ti.get_type_name());
1789  } else if (!target_ti.is_high_precision_timestamp()) {
1790  throw std::runtime_error(
1791  "Cast target type should be high precision timestamp. Input type is: " +
1792  target_ti.get_type_name());
1793  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
1794  throw std::runtime_error(
1795  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
1796  std::to_string(target_ti.get_dimension()) + ")");
1797  } else {
1798  return operand->add_cast(target_ti);
1799  }
1800 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 543 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().

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

371  {
372  const auto source = rex_input->getSourceNode();
373  const auto it_rte_idx = input_to_nest_level_.find(source);
374  CHECK(it_rte_idx != input_to_nest_level_.end())
375  << "Not found in input_to_nest_level_, source=" << source->toString();
376  const int rte_idx = it_rte_idx->second;
377  const auto scan_source = dynamic_cast<const RelScan*>(source);
378  const auto& in_metainfo = source->getOutputMetainfo();
379  if (scan_source) {
380  // We're at leaf (scan) level and not supposed to have input metadata,
381  // the name and type information come directly from the catalog.
382  CHECK(in_metainfo.empty());
383  const auto table_desc = scan_source->getTableDescriptor();
384  const auto cd =
385  cat_.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
386  CHECK(cd);
387  auto col_ti = cd->columnType;
388  if (col_ti.is_string()) {
389  col_ti.set_type(kTEXT);
390  }
391  if (cd->isVirtualCol) {
392  // TODO(alex): remove at some point, we only need this fixup for backwards
393  // compatibility with old imported data
394  CHECK_EQ("rowid", cd->columnName);
395  col_ti.set_size(8);
396  }
397  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
398  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
399  col_ti.set_notnull(false);
400  }
401  return std::make_shared<Analyzer::ColumnVar>(
402  col_ti, table_desc->tableId, cd->columnId, rte_idx);
403  }
404  CHECK(!in_metainfo.empty()) << "for " << source->toString();
405  CHECK_GE(rte_idx, 0);
406  const size_t col_id = rex_input->getIndex();
407  CHECK_LT(col_id, in_metainfo.size());
408  auto col_ti = in_metainfo[col_id].get_type_info();
409 
410  if (join_types_.size() > 0) {
411  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
412  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
413  col_ti.set_notnull(false);
414  }
415  }
416 
417  return std::make_shared<Analyzer::ColumnVar>(col_ti, -source->getId(), col_id, rte_idx);
418 }
const std::vector< JoinType > join_types_
#define CHECK_EQ(x, y)
Definition: Logger.h:205
#define CHECK_GE(x, y)
Definition: Logger.h:210
unsigned getIndex() const
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
Definition: Catalog.cpp:1547
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:207
Definition: sqltypes.h:51
#define CHECK_LE(x, y)
Definition: Logger.h:208
const RelAlgNode * getSourceNode() const
#define CHECK(condition)
Definition: Logger.h:197
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 1268 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1269  {
1270  CHECK_EQ(size_t(2), rex_function->size());
1271  const auto base = translateScalarRex(rex_function->getOperand(0));
1272  const auto index = translateScalarRex(rex_function->getOperand(1));
1273  return makeExpr<Analyzer::BinOper>(
1274  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1275 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 1192 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1193  {
1194  const auto& args = translateFunctionArgs(rex_function);
1195  CHECK_EQ(size_t(1), args.size());
1196  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1197  if (nullptr == expr || !expr->get_type_info().is_string() ||
1198  expr->get_type_info().is_varlen()) {
1199  throw std::runtime_error(rex_function->getName() +
1200  " expects a dictionary encoded text column.");
1201  }
1202  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1203 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 1184 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

1185  {
1186  CHECK_EQ(size_t(1), rex_function->size());
1187  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1188  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
1189  rex_function->getName() == "CHAR_LENGTH"sv);
1190 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 933 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

934  {
935  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
936  const auto arg = translateScalarRex(rex_function->getOperand(0));
937  const auto like = translateScalarRex(rex_function->getOperand(1));
938  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
939  throw std::runtime_error("The matching pattern must be a literal.");
940  }
941  const auto escape = (rex_function->size() == 3)
942  ? translateScalarRex(rex_function->getOperand(2))
943  : nullptr;
944  const bool is_ilike = rex_function->getName() == "PG_ILIKE"sv;
945  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
946 }
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:547
#define CHECK(condition)
Definition: Logger.h:197
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 962 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

963  {
964  CHECK(rex_function->size() == 1);
965  const auto arg = translateScalarRex(rex_function->getOperand(0));
966  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
967 }
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:197

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

259  {
260  auto lit_ti = build_type_info(
261  rex_literal->getType(), rex_literal->getScale(), rex_literal->getPrecision());
262  auto target_ti = build_type_info(rex_literal->getTargetType(),
263  rex_literal->getTypeScale(),
264  rex_literal->getTypePrecision());
265  switch (rex_literal->getType()) {
266  case kINT:
267  case kBIGINT: {
268  Datum d;
269  d.bigintval = rex_literal->getVal<int64_t>();
270  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
271  }
272  case kDECIMAL: {
273  const auto val = rex_literal->getVal<int64_t>();
274  const int precision = rex_literal->getPrecision();
275  const int scale = rex_literal->getScale();
276  if (target_ti.is_fp() && !scale) {
277  return make_fp_constant(val, target_ti);
278  }
279  auto lit_expr = scale ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
280  : Parser::IntLiteral::analyzeValue(val);
281  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
282  }
283  case kTEXT: {
284  return Parser::StringLiteral::analyzeValue(rex_literal->getVal<std::string>());
285  }
286  case kBOOLEAN: {
287  Datum d;
288  d.boolval = rex_literal->getVal<bool>();
289  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
290  }
291  case kDOUBLE: {
292  Datum d;
293  d.doubleval = rex_literal->getVal<double>();
294  auto lit_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
295  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
296  }
297  case kINTERVAL_DAY_TIME:
298  case kINTERVAL_YEAR_MONTH: {
299  Datum d;
300  d.bigintval = rex_literal->getVal<int64_t>();
301  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
302  }
303  case kTIME:
304  case kTIMESTAMP: {
305  Datum d;
306  d.bigintval =
307  rex_literal->getType() == kTIMESTAMP && rex_literal->getPrecision() > 0
308  ? rex_literal->getVal<int64_t>()
309  : rex_literal->getVal<int64_t>() / 1000;
310  return makeExpr<Analyzer::Constant>(
311  SQLTypeInfo(rex_literal->getType(), rex_literal->getPrecision(), 0, false),
312  false,
313  d);
314  }
315  case kDATE: {
316  Datum d;
317  d.bigintval = rex_literal->getVal<int64_t>() * 24 * 3600;
318  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
319  }
320  case kNULLT: {
321  if (target_ti.is_array()) {
323  // defaulting to valid sub-type for convenience
324  target_ti.set_subtype(kBOOLEAN);
325  return makeExpr<Analyzer::ArrayExpr>(target_ti, args, true);
326  }
327  return makeExpr<Analyzer::Constant>(rex_literal->getTargetType(), true, Datum{0});
328  }
329  default: {
330  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
331  }
332  }
333  return nullptr;
334 }
Definition: sqltypes.h:48
#define LOG(tag)
Definition: Logger.h:188
bool boolval
Definition: sqltypes.h:202
int64_t bigintval
Definition: sqltypes.h:206
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:106
Definition: sqltypes.h:51
Definition: sqltypes.h:52
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t numericval, const int scale, const int precision)
Definition: ParserNode.cpp:146
std::shared_ptr< Analyzer::Constant > make_fp_constant(const int64_t val, const SQLTypeInfo &ti)
std::vector< ExpressionPtr > ExpressionPtrVector
Definition: Analyzer.h:182
Definition: sqltypes.h:44
double doubleval
Definition: sqltypes.h:208

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

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

Referenced by translateFunction().

1227  {
1228  const auto& args = translateFunctionArgs(rex_function);
1229  CHECK_EQ(size_t(1), args.size());
1230  CHECK(args[0]);
1231 
1232  if (args[0]->get_type_info().is_dict_encoded_string() ||
1233  dynamic_cast<Analyzer::Constant*>(args[0].get())) {
1234  return makeExpr<Analyzer::LowerExpr>(args[0]);
1235  }
1236 
1237  throw std::runtime_error(rex_function->getName() +
1238  " expects a dictionary encoded text column or a literal.");
1239 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
#define CHECK(condition)
Definition: Logger.h:197
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::translateNow ( ) const
private

Definition at line 1277 of file RelAlgTranslator.cpp.

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

Referenced by translateDatetime(), and translateFunction().

1277  {
1279 }
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:182

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

Referenced by translateFunction().

1335  {
1336  return makeExpr<Analyzer::OffsetInFragment>();
1337 }

+ Here is the caller graph for this function:

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

Definition at line 863 of file RelAlgTranslator.cpp.

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

Referenced by translateScalarRex().

864  {
865  CHECK_GT(rex_operator->size(), size_t(0));
866  if (rex_operator->size() == 1) {
867  return translateUoper(rex_operator);
868  }
869  const auto sql_op = rex_operator->getOperator();
870  if (sql_op == kIN) {
871  return translateInOper(rex_operator);
872  }
873  if (sql_op == kMINUS || sql_op == kPLUS) {
874  auto date_plus_minus = translateDatePlusMinus(rex_operator);
875  if (date_plus_minus) {
876  return date_plus_minus;
877  }
878  }
879  if (sql_op == kOVERLAPS) {
880  return translateOverlapsOper(rex_operator);
881  } else if (IS_COMPARISON(sql_op)) {
882  auto geo_comp = translateGeoComparison(rex_operator);
883  if (geo_comp) {
884  return geo_comp;
885  }
886  }
887  auto lhs = translateScalarRex(rex_operator->getOperand(0));
888  for (size_t i = 1; i < rex_operator->size(); ++i) {
889  std::shared_ptr<Analyzer::Expr> rhs;
890  SQLQualifier sql_qual{kONE};
891  const auto rhs_op = rex_operator->getOperand(i);
892  std::tie(rhs, sql_qual) = get_quantified_rhs(rhs_op, *this);
893  if (!rhs) {
894  rhs = translateScalarRex(rhs_op);
895  }
896  CHECK(rhs);
897  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs);
898  }
899  return lhs;
900 }
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:209
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:272
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:197
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 902 of file RelAlgTranslator.cpp.

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

Referenced by translateOper().

903  {
904  const auto sql_op = rex_operator->getOperator();
905  CHECK(sql_op == kOVERLAPS);
906 
907  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
908  const auto lhs_ti = lhs->get_type_info();
909  if (lhs_ti.is_geometry()) {
910  return translateGeoOverlapsOper(rex_operator);
911  } else {
912  throw std::runtime_error(
913  "Overlaps equivalence is currently only supported for geospatial types");
914  }
915 }
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:197

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

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

Referenced by translateFunction().

949  {
950  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
951  const auto arg = translateScalarRex(rex_function->getOperand(0));
952  const auto pattern = translateScalarRex(rex_function->getOperand(1));
953  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
954  throw std::runtime_error("The matching pattern must be a literal.");
955  }
956  const auto escape = (rex_function->size() == 3)
957  ? translateScalarRex(rex_function->getOperand(2))
958  : nullptr;
959  return Parser::RegexpExpr::get(arg, pattern, escape, false);
960 }
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:642
#define CHECK(condition)
Definition: Logger.h:197

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

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

Referenced by translateFunction().

1206  {
1207  CHECK_EQ(size_t(1), rex_function->size());
1208  auto arg = translateScalarRex(rex_function->getOperand(0));
1209  const auto& arg_ti = arg->get_type_info();
1210  if (arg_ti.get_type() != kDOUBLE) {
1211  const auto& double_ti = SQLTypeInfo(kDOUBLE, arg_ti.get_notnull());
1212  arg = arg->add_cast(double_ti);
1213  }
1214  return makeExpr<Analyzer::SampleRatioExpr>(arg);
1215 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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(), translateBinaryGeoFunction(), translateCardinality(), translateCase(), translateDateadd(), translateDatediff(), translateDatepart(), translateDatePlusMinus(), translateDatetime(), translateExtract(), translateFunction(), translateFunctionArgs(), translateFunctionWithGeoArg(), translateGeoBinaryConstructor(), translateGeoFunctionArg(), translateHPTLiteral(), translateInOper(), translateItem(), translateLength(), translateLike(), translateLikely(), translateOper(), translateOverlapsOper(), translateRegexp(), translateSampleRatio(), translateSign(), translateTernaryGeoFunction(), translateUnlikely(), translateUoper(), and translateWindowFunction().

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:197
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 336 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().

337  {
338  if (just_explain_) {
339  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
340  }
341  CHECK(rex_subquery);
342  auto result = rex_subquery->getExecutionResult();
343  auto row_set = result->getRows();
344  const size_t row_count = row_set->rowCount();
345  if (row_count > size_t(1)) {
346  throw std::runtime_error("Scalar sub-query returned multiple rows");
347  }
348  if (row_count == size_t(0)) {
349  if (row_set->isValidationOnlyRes()) {
350  Datum d{0};
351  return makeExpr<Analyzer::Constant>(rex_subquery->getType(), false, d);
352  }
353  throw std::runtime_error("Scalar sub-query returned no results");
354  }
355  CHECK_EQ(row_count, size_t(1));
356  row_set->moveToBegin();
357  auto first_row = row_set->getNextRow(false, false);
358  CHECK_EQ(first_row.size(), size_t(1));
359  auto scalar_tv = boost::get<ScalarTargetValue>(&first_row[0]);
360  auto ti = rex_subquery->getType();
361  if (ti.is_string()) {
362  throw std::runtime_error("Scalar sub-queries which return strings not supported");
363  }
364  Datum d{0};
365  bool is_null_const{false};
366  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
367  return makeExpr<Analyzer::Constant>(ti, is_null_const, d);
368 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
#define CHECK(condition)
Definition: Logger.h:197
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 1313 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().

1314  {
1315  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1316  expr_list;
1317  CHECK_EQ(size_t(1), rex_function->size());
1318  const auto operand = translateScalarRex(rex_function->getOperand(0));
1319  const auto& operand_ti = operand->get_type_info();
1320  CHECK(operand_ti.is_number());
1321  const auto zero = makeNumericConstant(operand_ti, 0);
1322  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1323  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1324  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1325  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1326  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1327  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1328  return makeExpr<Analyzer::CaseExpr>(
1329  operand_ti,
1330  false,
1331  expr_list,
1332  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1333 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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:197
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 1103 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, kGEOMETRY, kINT, kLE, kLINESTRING, kMULTIPOLYGON, kONE, kPOINT, kPOLYGON, run_benchmark_import::result, RexOperator::size(), anonymous_namespace{RelAlgTranslatorGeo.cpp}::suffix(), translateBinaryGeoFunction(), translateGeoFunctionArg(), and translateScalarRex().

Referenced by translateFunction(), and translateGeoComparison().

1104  {
1105  CHECK_EQ(size_t(3), rex_function->size());
1106 
1107  auto distance_expr = translateScalarRex(rex_function->getOperand(2));
1108  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
1109  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
1110  distance_expr = distance_expr->add_cast(distance_ti);
1111  }
1112 
1113  auto function_name = rex_function->getName();
1114  if (function_name == "ST_DWithin"sv) {
1115  auto return_type = rex_function->getType();
1116  bool swap_args = false;
1117  bool with_bounds = true;
1118  SQLTypeInfo arg0_ti;
1119  SQLTypeInfo arg1_ti;
1120  int32_t lindex0 = 0;
1121  int32_t lindex1 = 0;
1122 
1123  auto geoargs0 = translateGeoFunctionArg(
1124  rex_function->getOperand(0), arg0_ti, lindex0, with_bounds, false, false);
1125  if (arg0_ti.get_type() == kLINESTRING) {
1126  Datum index;
1127  index.intval = lindex0;
1128  geoargs0.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
1129  }
1130  auto geoargs1 = translateGeoFunctionArg(
1131  rex_function->getOperand(1), arg1_ti, lindex1, with_bounds, false, false);
1132  if (arg1_ti.get_type() == kLINESTRING) {
1133  Datum index;
1134  index.intval = lindex1;
1135  geoargs1.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
1136  }
1137  if (arg0_ti.get_subtype() == kGEOMETRY &&
1138  arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
1139  throw QueryNotSupported(rex_function->getName() +
1140  " accepts only accepts GEOMETRY arguments");
1141  }
1142  // Check SRID match if at least one is set/valid
1143  if ((arg0_ti.get_output_srid() > 0 || arg1_ti.get_output_srid() > 0) &&
1144  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
1145  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
1146  }
1147 
1148  if ((arg1_ti.get_type() == kPOINT && arg0_ti.get_type() != kPOINT) ||
1149  (arg1_ti.get_type() == kLINESTRING && arg0_ti.get_type() == kPOLYGON) ||
1150  (arg1_ti.get_type() == kPOLYGON && arg0_ti.get_type() == kMULTIPOLYGON)) {
1151  // Swap arguments and use single implementation per arg pair
1152  swap_args = true;
1153  }
1154 
1155  // First input's compression mode and SRID args to enable on-the-fly
1156  // decompression/transforms
1157  Datum input_compression0;
1158  input_compression0.intval = Geospatial::get_compression_scheme(arg0_ti);
1159  Datum input_srid0;
1160  input_srid0.intval = arg0_ti.get_input_srid();
1161 
1162  // Second input's compression mode and SRID args to enable on-the-fly
1163  // decompression/transforms
1164  Datum input_compression1;
1165  input_compression1.intval = Geospatial::get_compression_scheme(arg1_ti);
1166  Datum input_srid1;
1167  input_srid1.intval = arg1_ti.get_input_srid();
1168 
1169  // Output SRID arg to enable on-the-fly transforms
1170  Datum output_srid;
1171  output_srid.intval = arg0_ti.get_output_srid();
1172 
1173  std::string specialized_geofunc{function_name};
1174  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1175  if (swap_args) {
1176  specialized_geofunc += suffix(arg1_ti.get_type()) + suffix(arg0_ti.get_type());
1177  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1178  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1179  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1180  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1181  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1182  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1183  } else {
1184  specialized_geofunc += suffix(arg0_ti.get_type()) + suffix(arg1_ti.get_type());
1185  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1186  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1187  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
1188  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
1189  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
1190  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
1191  }
1192  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
1193  // Also add the within distance
1194  geoargs.push_back(distance_expr);
1195 
1196  auto result =
1197  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1198  return result;
1199  }
1200 
1201  // Otherwise translate function as binary geo to get distance,
1202  // with optional short-circuiting threshold held in the third operand
1203  const auto geo_distance = translateBinaryGeoFunction(rex_function);
1204  // and generate the comparison
1205  return makeExpr<Analyzer::BinOper>(kBOOLEAN, kLE, kONE, geo_distance, distance_expr);
1206 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:312
#define CHECK_EQ(x, y)
Definition: Logger.h:205
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:35
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
int32_t intval
Definition: sqltypes.h:205
Definition: sqldefs.h:69
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:315
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
Definition: sqltypes.h:44
const std::string & getName() const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:317

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

References 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, RexOperator::size(), anonymous_namespace{RelAlgTranslatorGeo.cpp}::suffix(), and translateGeoFunctionArg().

Referenced by translateFunction().

726  {
727  CHECK_EQ(size_t(1), rex_function->size());
728 
729  int32_t lindex = 0;
730  std::string specialized_geofunc{rex_function->getName()};
731 
732  // Geo function calls which do not need the coords col but do need cols associated with
733  // physical coords (e.g. ring_sizes / poly_rings)
734  if (rex_function->getName() == "ST_NRings"sv) {
735  SQLTypeInfo arg_ti;
736  auto geoargs = translateGeoFunctionArg(
737  rex_function->getOperand(0), arg_ti, lindex, false, false, true);
738  if (arg_ti.get_type() == kPOLYGON) {
739  CHECK_EQ(geoargs.size(), 2u);
740  geoargs.erase(geoargs.begin(), geoargs.begin() + 1); // remove the coords
741  return makeExpr<Analyzer::FunctionOper>(
742  rex_function->getType(), specialized_geofunc, geoargs);
743  } else if (arg_ti.get_type() == kMULTIPOLYGON) {
744  CHECK_EQ(geoargs.size(), 3u);
745  geoargs.erase(geoargs.begin(), geoargs.begin() + 1); // remove the coords
746  geoargs.erase(geoargs.begin() + 1, geoargs.end()); // remove the poly_rings
747  return makeExpr<Analyzer::FunctionOper>(
748  rex_function->getType(), specialized_geofunc, geoargs);
749  } else {
750  throw QueryNotSupported(rex_function->getName() +
751  " expects a POLYGON or MULTIPOLYGON");
752  }
753  } else if (rex_function->getName() == "ST_NPoints"sv) {
754  SQLTypeInfo arg_ti;
755  auto geoargs = translateGeoFunctionArg(
756  rex_function->getOperand(0), arg_ti, lindex, false, false, true);
757  geoargs.erase(geoargs.begin() + 1, geoargs.end()); // remove all but coords
758  // Add compression information
759  Datum input_compression;
760  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
761  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
762  return makeExpr<Analyzer::FunctionOper>(
763  rex_function->getType(), specialized_geofunc, geoargs);
764  } else if (func_resolve(rex_function->getName(), "ST_Perimeter"sv, "ST_Area"sv)) {
765  SQLTypeInfo arg_ti;
766  auto geoargs = translateGeoFunctionArg(
767  rex_function->getOperand(0), arg_ti, lindex, false, false, true);
768  if (arg_ti.get_type() != kPOLYGON && arg_ti.get_type() != kMULTIPOLYGON) {
769  throw QueryNotSupported(rex_function->getName() +
770  " expects a POLYGON or MULTIPOLYGON");
771  }
772  specialized_geofunc += suffix(arg_ti.get_type());
773  if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
774  specialized_geofunc += "_Geodesic"s;
775  }
776  // Add compression information
777  Datum input_compression;
778  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
779  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
780  Datum input_srid;
781  input_srid.intval = arg_ti.get_input_srid();
782  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
783  Datum output_srid;
784  output_srid.intval = arg_ti.get_output_srid();
785  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
786  return makeExpr<Analyzer::FunctionOper>(
787  rex_function->getType(), specialized_geofunc, geoargs);
788  }
789 
790  // Accessors for poly bounds and render group for in-situ poly render queries
791  if (func_resolve(rex_function->getName(),
792  "MapD_GeoPolyBoundsPtr"sv /* deprecated */,
793  "OmniSci_Geo_PolyBoundsPtr"sv)) {
794  SQLTypeInfo arg_ti;
795  // get geo column plus bounds only (not expanded)
796  auto geoargs = translateGeoFunctionArg(
797  rex_function->getOperand(0), arg_ti, lindex, true, false, false);
798  // this function only works on polys
799  if (!IS_GEO_POLY(arg_ti.get_type())) {
800  throw QueryNotSupported(rex_function->getName() +
801  " expects a POLYGON or MULTIPOLYGON");
802  }
803  // only need the bounds argument (last), discard the rest
804  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
805  // done
806  return makeExpr<Analyzer::FunctionOper>(
807  rex_function->getType(), specialized_geofunc, geoargs);
808  } else if (func_resolve(rex_function->getName(),
809  "MapD_GeoPolyRenderGroup"sv /* deprecated */,
810  "OmniSci_Geo_PolyRenderGroup"sv)) {
811  SQLTypeInfo arg_ti;
812  // get geo column plus render_group only (not expanded)
813  auto geoargs = translateGeoFunctionArg(
814  rex_function->getOperand(0), arg_ti, lindex, false, true, false);
815  // this function only works on polys
816  if (!IS_GEO_POLY(arg_ti.get_type())) {
817  throw QueryNotSupported(rex_function->getName() +
818  " expects a POLYGON or MULTIPOLYGON");
819  }
820  // only need the render_group argument (last), discard the rest
821  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
822  // done
823  return makeExpr<Analyzer::FunctionOper>(
824  rex_function->getType(), specialized_geofunc, geoargs);
825  }
826 
827  // All functions below use geo col as reference and expand it as necessary
828  SQLTypeInfo arg_ti;
829  bool with_bounds = true;
830  auto geoargs = translateGeoFunctionArg(
831  rex_function->getOperand(0), arg_ti, lindex, with_bounds, false, false);
832 
833  if (rex_function->getName() == "ST_SRID"sv) {
834  Datum output_srid;
835  output_srid.intval = arg_ti.get_output_srid();
836  return makeExpr<Analyzer::Constant>(kINT, false, output_srid);
837  }
838 
839  if (func_resolve(
840  rex_function->getName(), "ST_XMin"sv, "ST_YMin"sv, "ST_XMax"sv, "ST_YMax"sv)) {
841  // If type has bounds - use them, otherwise look at coords
842  if (arg_ti.has_bounds()) {
843  if (lindex != 0) {
844  throw QueryNotSupported(rex_function->getName() +
845  " doesn't support indexed LINESTRINGs");
846  }
847  // Only need the bounds argument, discard the rest
848  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
849 
850  // Supply srids too - transformed geo would have a transformed bounding box
851  Datum input_srid;
852  input_srid.intval = arg_ti.get_input_srid();
853  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
854  Datum output_srid;
855  output_srid.intval = arg_ti.get_output_srid();
856  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
857 
858  specialized_geofunc += "_Bounds"s;
859  return makeExpr<Analyzer::FunctionOper>(
860  rex_function->getType(), specialized_geofunc, geoargs);
861  }
862  }
863 
864  // All geo function calls translated below only need the coords, extras e.g. ring_sizes
865  // are dropped. Specialize for other/new functions if needed.
866  geoargs.erase(geoargs.begin() + 1, geoargs.end());
867 
868  if (func_resolve(rex_function->getName(), "ST_X"sv, "ST_Y"sv)) {
869  if (arg_ti.get_type() == kLINESTRING) {
870  if (lindex == 0) {
871  throw QueryNotSupported(
872  rex_function->getName() +
873  " expects a POINT, use LINESTRING accessor, e.g. ST_POINTN");
874  }
875  Datum index;
876  index.intval = lindex;
877  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
878  } else if (arg_ti.get_type() != kPOINT) {
879  throw QueryNotSupported(rex_function->getName() + " expects a POINT");
880  }
881  specialized_geofunc += suffix(arg_ti.get_type());
882  } else if (rex_function->getName() == "ST_Length"sv) {
883  if (arg_ti.get_type() != kLINESTRING || lindex != 0) {
884  throw QueryNotSupported(rex_function->getName() + " expects unindexed LINESTRING");
885  }
886  specialized_geofunc += suffix(arg_ti.get_type());
887  if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
888  specialized_geofunc += "_Geodesic"s;
889  }
890  }
891 
892  // Add input compression mode and SRID args to enable on-the-fly
893  // decompression/transforms
894  Datum input_compression;
895  input_compression.intval = Geospatial::get_compression_scheme(arg_ti);
896  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
897  Datum input_srid;
898  input_srid.intval = arg_ti.get_input_srid();
899  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
900 
901  // Add output SRID arg to enable on-the-fly transforms
902  Datum output_srid;
903  output_srid.intval = arg_ti.get_output_srid();
904  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
905 
906  return makeExpr<Analyzer::FunctionOper>(
907  rex_function->getType(), specialized_geofunc, geoargs);
908 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:312
#define CHECK_EQ(x, y)
Definition: Logger.h:205
auto func_resolve
const SQLTypeInfo & getType() const
size_t size() const
const RexScalar * getOperand(const size_t idx) const
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
int32_t intval
Definition: sqltypes.h:205
bool has_bounds() const
Definition: sqltypes.h:380
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:315
Definition: sqltypes.h:44
const std::string & getName() const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false) const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:317
#define IS_GEO_POLY(T)
Definition: sqltypes.h:246

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 969 of file RelAlgTranslator.cpp.

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

Referenced by translateFunction().

970  {
971  CHECK(rex_function->size() == 1);
972  const auto arg = translateScalarRex(rex_function->getOperand(0));
973  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.0625);
974 }
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:197

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 420 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, CHECK_NE, RexOperator::getOperand(), RexOperator::getOperator(), RexOperator::getType(), is_null(), kBOOLEAN, kCAST, kDATE, kISNOTNULL, kISNULL, kMINUS, kNOT, kNULLT, kUMINUS, kUNNEST, RexOperator::size(), and translateScalarRex().

Referenced by translateOper().

421  {
422  CHECK_EQ(size_t(1), rex_operator->size());
423  const auto operand_expr = translateScalarRex(rex_operator->getOperand(0));
424  const auto sql_op = rex_operator->getOperator();
425  switch (sql_op) {
426  case kCAST: {
427  const auto& target_ti = rex_operator->getType();
428  CHECK_NE(kNULLT, target_ti.get_type());
429  const auto& operand_ti = operand_expr->get_type_info();
430  if (operand_ti.is_string() && target_ti.is_string()) {
431  return operand_expr;
432  }
433  if (target_ti.is_time() ||
434  operand_ti
435  .is_string()) { // TODO(alex): check and unify with the rest of the cases
436  // Do not propogate encoding on small dates
437  return target_ti.is_date_in_days()
438  ? operand_expr->add_cast(SQLTypeInfo(kDATE, false))
439  : operand_expr->add_cast(target_ti);
440  }
441  if (!operand_ti.is_string() && target_ti.is_string()) {
442  return operand_expr->add_cast(target_ti);
443  }
444 
445  return std::make_shared<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
446  }
447  case kNOT:
448  case kISNULL: {
449  return std::make_shared<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
450  }
451  case kISNOTNULL: {
452  auto is_null = std::make_shared<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
453  return std::make_shared<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
454  }
455  case kMINUS: {
456  const auto& ti = operand_expr->get_type_info();
457  return std::make_shared<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
458  }
459  case kUNNEST: {
460  const auto& ti = operand_expr->get_type_info();
461  CHECK(ti.is_array());
462  return makeExpr<Analyzer::UOper>(ti.get_elem_type(), false, kUNNEST, operand_expr);
463  }
464  default:
465  CHECK(false);
466  }
467  return nullptr;
468 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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:49
SQLOps getOperator() const
CONSTEXPR DEVICE bool is_null(const T &value)
#define CHECK_NE(x, y)
Definition: Logger.h:206
Definition: sqltypes.h:52
Definition: sqldefs.h:40
#define CHECK(condition)
Definition: Logger.h:197
Definition: sqldefs.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateWindowFunction ( const RexWindowFunctionOperator rex_window_function) const
private

Definition at line 1687 of file RelAlgTranslator.cpp.

References run_benchmark_import::args, CHECK_GE, RexWindowFunctionOperator::getCollation(), RexWindowFunctionOperator::getKind(), RexWindowFunctionOperator::getLowerBound(), RexOperator::getOperand(), RexWindowFunctionOperator::getOrderKeys(), RexWindowFunctionOperator::getPartitionKeys(), RexOperator::getType(), generate_TableFunctionsFactory_init::i, RexWindowFunctionOperator::isRows(), ROW_NUMBER, RexOperator::size(), anonymous_namespace{RelAlgTranslator.cpp}::supported_lower_bound(), anonymous_namespace{RelAlgTranslator.cpp}::supported_upper_bound(), anonymous_namespace{RelAlgTranslator.cpp}::translate_collation(), translateScalarRex(), and window_function_is_value().

Referenced by translateScalarRex().

1688  {
1689  if (!supported_lower_bound(rex_window_function->getLowerBound()) ||
1690  !supported_upper_bound(rex_window_function) ||
1691  ((rex_window_function->getKind() == SqlWindowFunctionKind::ROW_NUMBER) !=
1692  rex_window_function->isRows())) {
1693  throw std::runtime_error("Frame specification not supported");
1694  }
1695  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1696  for (size_t i = 0; i < rex_window_function->size(); ++i) {
1697  args.push_back(translateScalarRex(rex_window_function->getOperand(i)));
1698  }
1699  std::vector<std::shared_ptr<Analyzer::Expr>> partition_keys;
1700  for (const auto& partition_key : rex_window_function->getPartitionKeys()) {
1701  partition_keys.push_back(translateScalarRex(partition_key.get()));
1702  }
1703  std::vector<std::shared_ptr<Analyzer::Expr>> order_keys;
1704  for (const auto& order_key : rex_window_function->getOrderKeys()) {
1705  order_keys.push_back(translateScalarRex(order_key.get()));
1706  }
1707  auto ti = rex_window_function->getType();
1708  if (window_function_is_value(rex_window_function->getKind())) {
1709  CHECK_GE(args.size(), 1u);
1710  ti = args.front()->get_type_info();
1711  }
1712  return makeExpr<Analyzer::WindowFunction>(
1713  ti,
1714  rex_window_function->getKind(),
1715  args,
1716  partition_keys,
1717  order_keys,
1718  translate_collation(rex_window_function->getCollation()));
1719 }
bool supported_lower_bound(const RexWindowFunctionOperator::RexWindowBound &window_bound)
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
const std::vector< SortField > & getCollation() const
#define CHECK_GE(x, y)
Definition: Logger.h:210
bool window_function_is_value(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:27
std::vector< Analyzer::OrderEntry > translate_collation(const std::vector< SortField > &sort_fields)
const ConstRexScalarPtrVector & getPartitionKeys() const
const RexWindowBound & getLowerBound() const
SqlWindowFunctionKind getKind() const
bool supported_upper_bound(const RexWindowFunctionOperator *rex_window_function)
const ConstRexScalarPtrVector & getOrderKeys() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Member Data Documentation

const Catalog_Namespace::Catalog& RelAlgTranslator::cat_
private

Definition at line 196 of file RelAlgTranslator.h.

Referenced by getInIntegerSetExpr(), translateGeoColumn(), and translateInput().

const Executor* RelAlgTranslator::executor_
private

Definition at line 198 of file RelAlgTranslator.h.

Referenced by getInIntegerSetExpr().

bool RelAlgTranslator::generated_geos_ops_
mutableprivate

Definition at line 202 of file RelAlgTranslator.h.

Referenced by generated_geos_ops().

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

Definition at line 199 of file RelAlgTranslator.h.

Referenced by translateGeoColumn(), and translateInput().

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

Definition at line 200 of file RelAlgTranslator.h.

Referenced by translateInput().

const bool RelAlgTranslator::just_explain_
private

Definition at line 203 of file RelAlgTranslator.h.

Referenced by translateInOper(), and translateScalarSubquery().

time_t RelAlgTranslator::now_
private

Definition at line 201 of file RelAlgTranslator.h.

Referenced by translateNow().

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

Definition at line 197 of file RelAlgTranslator.h.

Referenced by translateCurrentUser().


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