OmniSciDB  c07336695a
RelAlgTranslator Class Reference

#include <RelAlgTranslator.h>

+ Collaboration diagram for RelAlgTranslator:

Public Member Functions

 RelAlgTranslator (const Catalog_Namespace::Catalog &cat, 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, QueryFeatureDescriptor &feature_stash)
 
std::shared_ptr< Analyzer::ExprtranslateScalarRex (const RexScalar *rex) const
 

Static Public Member Functions

static std::shared_ptr< Analyzer::ExprtranslateAggregateRex (const RexAgg *rex, const std::vector< std::shared_ptr< Analyzer::Expr >> &scalar_sources)
 

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

Static Private Member Functions

static std::shared_ptr< Analyzer::ExprtranslateLiteral (const RexLiteral *)
 

Private Attributes

const Catalog_Namespace::Catalogcat_
 
const Executorexecutor_
 
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
 
const std::vector< JoinTypejoin_types_
 
time_t now_
 
const bool just_explain_
 
QueryFeatureDescriptorfeature_stash_
 

Detailed Description

Definition at line 41 of file RelAlgTranslator.h.

Constructor & Destructor Documentation

◆ RelAlgTranslator()

RelAlgTranslator::RelAlgTranslator ( const Catalog_Namespace::Catalog cat,
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,
QueryFeatureDescriptor feature_stash 
)
inline

Definition at line 43 of file RelAlgTranslator.h.

50  : cat_(cat)
51  , executor_(executor)
52  , input_to_nest_level_(input_to_nest_level)
53  , join_types_(join_types)
54  , now_(now)
55  , just_explain_(just_explain)
56  , feature_stash_(feature_stash) {}
const std::vector< JoinType > join_types_
const Executor * executor_
QueryFeatureDescriptor & feature_stash_
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
const bool just_explain_
const Catalog_Namespace::Catalog & cat_

Member Function Documentation

◆ getInIntegerSetExpr()

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::getInIntegerSetExpr ( std::shared_ptr< Analyzer::Expr arg,
const ResultSet val_set 
) const
private

Definition at line 706 of file RelAlgTranslator.cpp.

References can_use_parallel_algorithms(), CHECK, CHECK_EQ, CHECK_GE, cpu_threads(), anonymous_namespace{RelAlgTranslator.cpp}::fill_dictionary_encoded_in_vals(), anonymous_namespace{RelAlgTranslator.cpp}::fill_integer_in_vals(), g_cluster, inline_int_null_val(), and kENCODING_DICT.

708  {
709  if (!can_use_parallel_algorithms(val_set)) {
710  return nullptr;
711  }
712  std::vector<int64_t> value_exprs;
713  const size_t fetcher_count = cpu_threads();
714  std::vector<std::vector<int64_t>> expr_set(fetcher_count);
715  std::vector<std::future<void>> fetcher_threads;
716  const auto& arg_type = arg->get_type_info();
717  const auto entry_count = val_set.entryCount();
718  CHECK_EQ(size_t(1), val_set.colCount());
719  const auto& col_type = val_set.getColType(0);
720  if (g_cluster && arg_type.is_string() &&
721  (col_type.get_comp_param() <= 0 || arg_type.get_comp_param() <= 0)) {
722  // Skip this case for now, see comment for fill_dictionary_encoded_in_vals.
723  return nullptr;
724  }
725  std::atomic<size_t> total_in_vals_count{0};
726  for (size_t i = 0,
727  start_entry = 0,
728  stride = (entry_count + fetcher_count - 1) / fetcher_count;
729  i < fetcher_count && start_entry < entry_count;
730  ++i, start_entry += stride) {
731  expr_set[i].reserve(entry_count / fetcher_count);
732  const auto end_entry = std::min(start_entry + stride, entry_count);
733  if (arg_type.is_string()) {
734  CHECK_EQ(kENCODING_DICT, arg_type.get_compression());
735  // const int32_t dest_dict_id = arg_type.get_comp_param();
736  // const int32_t source_dict_id = col_type.get_comp_param();
737  const DictRef dest_dict_ref(arg_type.get_comp_param(), cat_.getDatabaseId());
738  const DictRef source_dict_ref(col_type.get_comp_param(), cat_.getDatabaseId());
739  const auto dd = executor_->getStringDictionaryProxy(
740  arg_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
741  const auto sd = executor_->getStringDictionaryProxy(
742  col_type.get_comp_param(), val_set.getRowSetMemOwner(), true);
743  CHECK(sd);
744  const auto needle_null_val = inline_int_null_val(arg_type);
745  fetcher_threads.push_back(std::async(
746  std::launch::async,
747  [this,
748  &val_set,
749  &total_in_vals_count,
750  sd,
751  dd,
752  source_dict_ref,
753  dest_dict_ref,
754  needle_null_val](
755  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
756  if (g_cluster) {
757  CHECK_GE(dd->getGeneration(), 0);
759  total_in_vals_count,
760  &val_set,
761  {start, end},
763  source_dict_ref,
764  dest_dict_ref,
765  dd->getGeneration(),
766  needle_null_val);
767  } else {
769  total_in_vals_count,
770  &val_set,
771  {start, end},
772  sd,
773  dd,
774  needle_null_val);
775  }
776  },
777  std::ref(expr_set[i]),
778  start_entry,
779  end_entry));
780  } else {
781  CHECK(arg_type.is_integer());
782  fetcher_threads.push_back(std::async(
783  std::launch::async,
784  [&val_set, &total_in_vals_count](
785  std::vector<int64_t>& in_vals, const size_t start, const size_t end) {
786  fill_integer_in_vals(in_vals, total_in_vals_count, &val_set, {start, end});
787  },
788  std::ref(expr_set[i]),
789  start_entry,
790  end_entry));
791  }
792  }
793  for (auto& child : fetcher_threads) {
794  child.get();
795  }
796 
797  val_set.moveToBegin();
798  value_exprs.reserve(entry_count);
799  for (auto& exprs : expr_set) {
800  value_exprs.insert(value_exprs.end(), exprs.begin(), exprs.end());
801  }
802  return makeExpr<Analyzer::InIntegerSet>(
803  arg, value_exprs, arg_type.get_notnull() && col_type.get_notnull());
804 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
const std::vector< LeafHostInfo > & getStringDictionaryHosts() const
Definition: Catalog.cpp:1384
const Executor * executor_
#define CHECK_GE(x, y)
Definition: Logger.h:200
int getDatabaseId() const
Definition: Catalog.h:192
bool can_use_parallel_algorithms(const ResultSet &rows)
Definition: ResultSet.cpp:869
#define CHECK(condition)
Definition: Logger.h:187
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool g_cluster
int cpu_threads()
Definition: thread_count.h:23
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 std::vector< LeafHostInfo > &leaf_hosts, const DictRef source_dict_ref, const DictRef dest_dict_ref, const int32_t dest_generation, const int64_t needle_null_val)
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:

◆ translateAbs()

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

Definition at line 1227 of file RelAlgTranslator.cpp.

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

1228  {
1229  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1230  expr_list;
1231  CHECK_EQ(size_t(1), rex_function->size());
1232  const auto operand = translateScalarRex(rex_function->getOperand(0));
1233  const auto& operand_ti = operand->get_type_info();
1234  CHECK(operand_ti.is_number());
1235  const auto zero = makeNumericConstant(operand_ti, 0);
1236  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1237  const auto uminus_operand =
1238  makeExpr<Analyzer::UOper>(operand_ti.get_type(), kUMINUS, operand);
1239  expr_list.emplace_back(lt_zero, uminus_operand);
1240  return makeExpr<Analyzer::CaseExpr>(operand_ti, false, expr_list, operand);
1241 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:69
#define CHECK(condition)
Definition: Logger.h:187
Definition: sqldefs.h:33
+ Here is the call graph for this function:

◆ translateAggregateRex()

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateAggregateRex ( const RexAgg rex,
const std::vector< std::shared_ptr< Analyzer::Expr >> &  scalar_sources 
)
static

Definition at line 198 of file RelAlgTranslator.cpp.

References CHECK_LE, CHECK_LT, get_agg_type(), RexAgg::getKind(), RexAgg::getOperand(), 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(), and anonymous_namespace{RelAlgExecutor.cpp}::translate_targets_for_update().

200  {
201  const auto agg_kind = rex->getKind();
202  const bool is_distinct = rex->isDistinct();
203  const bool takes_arg{rex->size() > 0};
204  std::shared_ptr<Analyzer::Expr> arg_expr;
205  std::shared_ptr<Analyzer::Constant> err_rate;
206  if (takes_arg) {
207  const auto operand = rex->getOperand(0);
208  CHECK_LT(operand, scalar_sources.size());
209  CHECK_LE(rex->size(), 2u);
210  arg_expr = scalar_sources[operand];
211  if (agg_kind == kAPPROX_COUNT_DISTINCT && rex->size() == 2) {
212  err_rate = std::dynamic_pointer_cast<Analyzer::Constant>(
213  scalar_sources[rex->getOperand(1)]);
214  if (!err_rate || err_rate->get_type_info().get_type() != kINT ||
215  err_rate->get_constval().intval < 1 || err_rate->get_constval().intval > 100) {
216  throw std::runtime_error(
217  "APPROX_COUNT_DISTINCT's second parameter should be SMALLINT literal between "
218  "1 and 100");
219  }
220  }
221  }
222  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
223  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, err_rate);
224 }
size_t size() const
size_t getOperand(size_t idx) const
SQLTypeInfo get_agg_type(const SQLAgg agg_kind, const Analyzer::Expr *arg_expr)
#define CHECK_LT(x, y)
Definition: Logger.h:197
#define CHECK_LE(x, y)
Definition: Logger.h:198
SQLAgg getKind() const
bool takes_arg(const TargetInfo &target_info)
Definition: sqltypes.h:47
bool is_distinct(const size_t input_idx, const RelAlgNode *node)
bool isDistinct() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ translateArrayFunction()

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

Definition at line 1269 of file RelAlgTranslator.cpp.

References CHECK, get_logical_type_info(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_subtype(), RexOperator::getType(), kARRAY, kENCODING_FIXED, kNULLT, and TRANSIENT_DICT_ID.

1270  {
1271  if (rex_function->getType().get_subtype() == kNULLT) {
1272  auto sql_type = rex_function->getType();
1273  CHECK(sql_type.get_type() == kARRAY);
1274 
1275  // FIX-ME: Deal with NULL arrays
1276  auto translated_function_args(translateFunctionArgs(rex_function));
1277  if (translated_function_args.size() > 0) {
1278  auto const& first_element_logical_type(
1279  get_logical_type_info(translated_function_args[0]->get_type_info()));
1280 
1281  on_member_of_typeset<kCHAR, kVARCHAR, kTEXT>(
1282  first_element_logical_type,
1283  [&] {
1284  bool same_type_status = true;
1285  for (auto const& expr_ptr : translated_function_args) {
1286  same_type_status =
1287  same_type_status && (expr_ptr->get_type_info().is_string());
1288  }
1289 
1290  if (same_type_status == false) {
1291  throw std::runtime_error(
1292  "All elements of the array are not of the same logical subtype; "
1293  "consider casting to force this condition.");
1294  }
1295 
1296  sql_type.set_subtype(first_element_logical_type.get_type());
1297  sql_type.set_compression(kENCODING_FIXED);
1298  sql_type.set_comp_param(TRANSIENT_DICT_ID);
1299  },
1300  [&] {
1301  // Non string types
1302  bool same_type_status = true;
1303  for (auto const& expr_ptr : translated_function_args) {
1304  same_type_status =
1305  same_type_status && (first_element_logical_type ==
1306  get_logical_type_info(expr_ptr->get_type_info()));
1307  }
1308 
1309  if (same_type_status == false) {
1310  throw std::runtime_error(
1311  "All elements of the array are not of the same logical subtype; "
1312  "consider casting to force this condition.");
1313  }
1314  sql_type.set_subtype(first_element_logical_type.get_type());
1315  sql_type.set_scale(first_element_logical_type.get_scale());
1316  sql_type.set_precision(first_element_logical_type.get_precision());
1317  });
1318 
1319  feature_stash_.setCPUOnlyExecutionRequired();
1320  return makeExpr<Analyzer::ArrayExpr>(
1321  sql_type, translated_function_args, feature_stash_.getAndBumpArrayExprCount());
1322  } else {
1323  throw std::runtime_error("NULL ARRAY[] expressions not supported yet. FIX-ME.");
1324  }
1325  } else {
1326  feature_stash_.setCPUOnlyExecutionRequired();
1327  return makeExpr<Analyzer::ArrayExpr>(rex_function->getType(),
1328  translateFunctionArgs(rex_function),
1329  feature_stash_.getAndBumpArrayExprCount());
1330  }
1331 }
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:836
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
QueryFeatureDescriptor & feature_stash_
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:320
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:187
#define CHECK(condition)
Definition: Logger.h:187
const SQLTypeInfo & getType() const
+ Here is the call graph for this function:

◆ translateBinaryGeoFunction()

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

Definition at line 737 of file RelAlgTranslatorGeo.cpp.

References CHECK_EQ, SQLTypeInfoCore< TYPE_FACET_PACK >::get_comp_param(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_compression(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_input_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_output_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_subtype(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_type(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Datum::intval, kBOOLEAN, kDOUBLE, kENCODING_GEOINT, kGEOGRAPHY, kINT, kLINESTRING, kNOT, kNULLT, kPOINT, run-benchmark-import::result, RexOperator::size(), anonymous_namespace{RelAlgTranslatorGeo.cpp}::suffix(), and translateGeoFunctionArg().

Referenced by translateTernaryGeoFunction().

738  {
739  auto function_name = rex_function->getName();
740  auto return_type = rex_function->getType();
741  bool swap_args = false;
742  bool with_bounds = false;
743  bool negate_result = false;
744  if (function_name == "ST_DWithin") {
745  CHECK_EQ(size_t(3), rex_function->size());
746  function_name = "ST_Distance";
747  return_type = SQLTypeInfo(kDOUBLE, false);
748  } else if (function_name == "ST_DFullyWithin") {
749  CHECK_EQ(size_t(3), rex_function->size());
750  function_name = "ST_MaxDistance";
751  return_type = SQLTypeInfo(kDOUBLE, false);
752  } else {
753  CHECK_EQ(size_t(2), rex_function->size());
754  }
755  if (function_name == std::string("ST_Within")) {
756  function_name = "ST_Contains";
757  swap_args = true;
758  } else if (function_name == std::string("ST_Disjoint")) {
759  function_name = "ST_Intersects";
760  negate_result = true;
761  }
762  if (function_name == std::string("ST_Contains") ||
763  function_name == std::string("ST_Intersects")) {
764  with_bounds = true;
765  }
766 
767  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
768  SQLTypeInfo arg0_ti;
769  SQLTypeInfo arg1_ti;
770  int32_t lindex0 = 0;
771  int32_t lindex1 = 0;
772 
773  auto geoargs0 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 1 : 0),
774  arg0_ti,
775  lindex0,
776  with_bounds,
777  false,
778  false);
779  if (arg0_ti.get_type() == kLINESTRING) {
780  Datum index;
781  index.intval = lindex0;
782  geoargs0.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
783  }
784  geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
785  auto geoargs1 = translateGeoFunctionArg(rex_function->getOperand(swap_args ? 0 : 1),
786  arg1_ti,
787  lindex1,
788  with_bounds,
789  false,
790  false);
791  if (arg1_ti.get_type() == kLINESTRING) {
792  Datum index;
793  index.intval = lindex1;
794  geoargs1.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
795  }
796  geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
797 
798  if (arg0_ti.get_subtype() != kNULLT && arg0_ti.get_subtype() != arg1_ti.get_subtype()) {
799  throw QueryNotSupported(rex_function->getName() +
800  " accepts either two GEOGRAPHY or two GEOMETRY arguments");
801  }
802  if (arg0_ti.get_output_srid() > 0 &&
803  arg0_ti.get_output_srid() != arg1_ti.get_output_srid()) {
804  throw QueryNotSupported(rex_function->getName() + " cannot accept different SRIDs");
805  }
806 
807  std::string specialized_geofunc{function_name + suffix(arg0_ti.get_type()) +
808  suffix(arg1_ti.get_type())};
809 
810  if (arg0_ti.get_subtype() == kGEOGRAPHY && arg0_ti.get_output_srid() == 4326) {
811  // Need to call geodesic runtime functions
812  if (function_name == std::string("ST_Distance")) {
813  if ((arg0_ti.get_type() == kPOINT ||
814  (arg0_ti.get_type() == kLINESTRING && lindex0 != 0)) &&
815  (arg1_ti.get_type() == kPOINT ||
816  (arg1_ti.get_type() == kLINESTRING && lindex1 != 0))) {
817  // Geodesic distance between points (or indexed linestrings)
818  specialized_geofunc += std::string("_Geodesic");
819  } else {
820  throw QueryNotSupported(function_name +
821  " currently doesn't accept non-POINT geographies");
822  }
823  } else if (rex_function->getName() == std::string("ST_Contains")) {
824  // We currently don't have a geodesic implementation of ST_Contains,
825  // allowing calls to a [less precise] cartesian implementation.
826  } else {
827  throw QueryNotSupported(function_name + " doesn't accept geographies");
828  }
829  } else if (function_name == std::string("ST_Distance") && rex_function->size() == 3) {
830  if (arg0_ti.get_type() == kPOINT && arg1_ti.get_type() == kPOINT) {
831  // Cartesian distance between points used by ST_DWithin - switch to faster Squared
832  specialized_geofunc += std::string("_Squared");
833  }
834  }
835 
836  // Add first input's compression mode and SRID args to enable on-the-fly
837  // decompression/transforms
838  Datum input_compression0;
839  input_compression0.intval =
840  (arg0_ti.get_compression() == kENCODING_GEOINT && arg0_ti.get_comp_param() == 32)
841  ? 1
842  : 0;
843  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression0));
844  Datum input_srid0;
845  input_srid0.intval = arg0_ti.get_input_srid();
846  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid0));
847 
848  // Add second input's compression mode and SRID args to enable on-the-fly
849  // decompression/transforms
850  Datum input_compression1;
851  input_compression1.intval =
852  (arg1_ti.get_compression() == kENCODING_GEOINT && arg1_ti.get_comp_param() == 32)
853  ? 1
854  : 0;
855  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression1));
856  Datum input_srid1;
857  input_srid1.intval = arg1_ti.get_input_srid();
858  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid1));
859 
860  // Add output SRID arg to enable on-the-fly transforms
861  Datum output_srid;
862  output_srid.intval = arg0_ti.get_output_srid();
863  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
864 
865  auto result =
866  makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
867  if (negate_result) {
868  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, result);
869  }
870  return result;
871 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:319
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:327
int32_t intval
Definition: sqltypes.h:125
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:320
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:323
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:325
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
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:328
const SQLTypeInfo & getType() const
Definition: sqltypes.h:47
const std::string & getName() const
Definition: sqldefs.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ translateCardinality()

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

Definition at line 1171 of file RelAlgTranslator.cpp.

References SQLTypeInfoCore< TYPE_FACET_PACK >::get_size(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), kARRAY, and anonymous_namespace{RelAlgTranslator.cpp}::makeNumericConstant().

1172  {
1173  const auto ret_ti = rex_function->getType();
1174  const auto arg = translateScalarRex(rex_function->getOperand(0));
1175  const auto arg_ti = arg->get_type_info();
1176  if (!arg_ti.is_array()) {
1177  throw std::runtime_error(rex_function->getName() + " expects an array expression.");
1178  }
1179  if (arg_ti.get_subtype() == kARRAY) {
1180  throw std::runtime_error(rex_function->getName() +
1181  " expects one-dimension array expression.");
1182  }
1183  const auto array_size = arg_ti.get_size();
1184  const auto array_elem_size = arg_ti.get_elem_type().get_array_context_logical_size();
1185 
1186  if (array_size > 0) {
1187  if (array_elem_size <= 0) {
1188  throw std::runtime_error(rex_function->getName() +
1189  ": unexpected array element type.");
1190  }
1191  // Return cardinality of a fixed length array
1192  return makeNumericConstant(ret_ti, array_size / array_elem_size);
1193  }
1194  // Variable length array cardinality will be calculated at runtime
1195  return makeExpr<Analyzer::CardinalityExpr>(arg);
1196 }
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
const SQLTypeInfo & getType() const
const std::string & getName() const
+ Here is the call graph for this function:

◆ translateCase()

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateCase ( const RexCase rex_case) const
private

Definition at line 860 of file RelAlgTranslator.cpp.

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

861  {
862  std::shared_ptr<Analyzer::Expr> else_expr;
863  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
864  expr_list;
865  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
866  const auto when_expr = translateScalarRex(rex_case->getWhen(i));
867  const auto then_expr = translateScalarRex(rex_case->getThen(i));
868  expr_list.emplace_back(when_expr, then_expr);
869  }
870  if (rex_case->getElse()) {
871  else_expr = translateScalarRex(rex_case->getElse());
872  }
873  return Parser::CaseExpr::normalize(expr_list, else_expr);
874 }
size_t branchCount() 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:890
const RexScalar * getWhen(const size_t idx) const
const RexScalar * getThen(const size_t idx) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getElse() const
+ Here is the call graph for this function:

◆ translateDateadd()

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

Definition at line 980 of file RelAlgTranslator.cpp.

References CHECK_EQ, field(), fold_expr(), DateTimeUtils::get_dateadd_high_precision_adjusted_scale(), DateTimeUtils::get_dateadd_timestamp_precision_scale(), RexOperator::getOperand(), DateTimeUtils::is_subsecond_dateadd_field(), kBIGINT, kDIVIDE, kONE, kTIME, kTIMESTAMP, anonymous_namespace{RelAlgTranslator.cpp}::makeNumericConstant(), RexOperator::size(), and to_dateadd_field().

981  {
982  CHECK_EQ(size_t(3), rex_function->size());
983  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
984  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
985  if (!timeunit_lit) {
986  throw std::runtime_error("The time unit parameter must be a literal.");
987  }
988 
989  const auto number_units = translateScalarRex(rex_function->getOperand(1));
990  auto cast_number_units = number_units->add_cast(SQLTypeInfo(kBIGINT, false));
991  const auto datetime = translateScalarRex(rex_function->getOperand(2));
992  const auto& datetime_ti = datetime->get_type_info();
993  if (datetime_ti.get_type() == kTIME) {
994  throw std::runtime_error("DateAdd operation not supported for TIME.");
995  }
996  const auto& field = to_dateadd_field(*timeunit_lit->get_constval().stringval);
997  if (!datetime_ti.is_high_precision_timestamp() &&
999  // Scale the number to get value in seconds
1000  const auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1001  cast_number_units = makeExpr<Analyzer::BinOper>(
1002  bigint_ti.get_type(),
1003  kDIVIDE,
1004  kONE,
1005  cast_number_units,
1006  makeNumericConstant(bigint_ti,
1008  cast_number_units = fold_expr(cast_number_units.get());
1009  }
1010  if (datetime_ti.is_high_precision_timestamp() &&
1013  field, datetime_ti.get_dimension());
1014  if (oper_scale.first) {
1015  // scale number to desired precision
1016  const auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1017  cast_number_units =
1018  makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1019  oper_scale.first,
1020  kONE,
1021  cast_number_units,
1022  makeNumericConstant(bigint_ti, oper_scale.second));
1023  cast_number_units = fold_expr(cast_number_units.get());
1024  }
1025  }
1026  return makeExpr<Analyzer::DateaddExpr>(
1027  SQLTypeInfo(kTIMESTAMP, datetime_ti.get_dimension(), 0, false),
1028  to_dateadd_field(*timeunit_lit->get_constval().stringval),
1029  cast_number_units,
1030  datetime);
1031 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
Definition: sqltypes.h:51
constexpr int64_t get_dateadd_timestamp_precision_scale(const DateaddField field)
Definition: DateTimeUtils.h:64
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const std::pair< SQLOps, int64_t > get_dateadd_high_precision_adjusted_scale(const DateaddField field, int32_t dimen)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqldefs.h:69
constexpr bool is_subsecond_dateadd_field(const DateaddField field)
Definition: DateTimeUtils.h:96
DateaddField to_dateadd_field(const std::string &field)
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
+ Here is the call graph for this function:

◆ translateDatediff()

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

Definition at line 1123 of file RelAlgTranslator.cpp.

References CHECK_EQ, field(), RexOperator::getOperand(), kBIGINT, RexOperator::size(), and to_datediff_field().

1124  {
1125  CHECK_EQ(size_t(3), rex_function->size());
1126  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1127  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1128  if (!timeunit_lit) {
1129  throw std::runtime_error("The time unit parameter must be a literal.");
1130  }
1131  const auto start = translateScalarRex(rex_function->getOperand(1));
1132  const auto end = translateScalarRex(rex_function->getOperand(2));
1133  const auto field = to_datediff_field(*timeunit_lit->get_constval().stringval);
1134  return makeExpr<Analyzer::DatediffExpr>(SQLTypeInfo(kBIGINT, false), field, start, end);
1135 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
DatetruncField to_datediff_field(const std::string &field)
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
+ Here is the call graph for this function:

◆ translateDatepart()

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

Definition at line 1137 of file RelAlgTranslator.cpp.

References CHECK_EQ, ExtractExpr::generate(), RexOperator::getOperand(), RexOperator::size(), and to_datepart_field().

1138  {
1139  CHECK_EQ(size_t(2), rex_function->size());
1140  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
1141  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
1142  if (!timeunit_lit) {
1143  throw std::runtime_error("The time unit parameter must be a literal.");
1144  }
1145  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
1146  return ExtractExpr::generate(
1147  from_expr, to_datepart_field(*timeunit_lit->get_constval().stringval));
1148 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
ExtractField to_datepart_field(const std::string &field)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
const std::shared_ptr< Analyzer::Expr > generate() const
+ Here is the call graph for this function:

◆ translateDatePlusMinus()

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

Definition at line 1042 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(), and RexOperator::size().

1043  {
1044  if (rex_operator->size() != 2) {
1045  return nullptr;
1046  }
1047  const auto datetime = translateScalarRex(rex_operator->getOperand(0));
1048  const auto datetime_ti = datetime->get_type_info();
1049  if (!datetime_ti.is_timestamp() && !datetime_ti.is_date()) {
1050  if (datetime_ti.get_type() == kTIME) {
1051  throw std::runtime_error("DateTime addition/subtraction not supported for TIME.");
1052  }
1053  return nullptr;
1054  }
1055  const auto rhs = translateScalarRex(rex_operator->getOperand(1));
1056  const auto rhs_ti = rhs->get_type_info();
1057  if (rhs_ti.get_type() == kTIMESTAMP || rhs_ti.get_type() == kDATE) {
1058  if (datetime_ti.is_high_precision_timestamp() ||
1059  rhs_ti.is_high_precision_timestamp()) {
1060  throw std::runtime_error(
1061  "High Precision timestamps are not supported for TIMESTAMPDIFF operation. Use "
1062  "DATEDIFF.");
1063  }
1064  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1065  const auto& rex_operator_ti = rex_operator->getType();
1066  const auto datediff_field =
1067  (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) ? dtSECOND : dtMONTH;
1068  auto result =
1069  makeExpr<Analyzer::DatediffExpr>(bigint_ti, datediff_field, rhs, datetime);
1070  // multiply 1000 to result since expected result should be in millisecond precision.
1071  if (rex_operator_ti.get_type() == kINTERVAL_DAY_TIME) {
1072  return makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1073  kMULTIPLY,
1074  kONE,
1075  result,
1076  makeNumericConstant(bigint_ti, 1000));
1077  } else {
1078  return result;
1079  }
1080  }
1081  const auto op = rex_operator->getOperator();
1082  if (op == kPLUS) {
1083  std::vector<std::shared_ptr<Analyzer::Expr>> args = {datetime, rhs};
1084  auto dt_plus = makeExpr<Analyzer::FunctionOper>(
1085  datetime_ti, get_datetimeplus_rewrite_funcname(op), args);
1086  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1087  if (date_trunc) {
1088  return date_trunc;
1089  }
1090  }
1091  const auto interval = fold_expr(rhs.get());
1092  auto interval_ti = interval->get_type_info();
1093  auto bigint_ti = SQLTypeInfo(kBIGINT, false);
1094  const auto interval_lit = std::dynamic_pointer_cast<Analyzer::Constant>(interval);
1095  if (interval_ti.get_type() == kINTERVAL_DAY_TIME) {
1096  std::shared_ptr<Analyzer::Expr> interval_sec;
1097  if (interval_lit) {
1098  interval_sec =
1099  makeNumericConstant(bigint_ti,
1100  (op == kMINUS ? -interval_lit->get_constval().bigintval
1101  : interval_lit->get_constval().bigintval) /
1102  1000);
1103  } else {
1104  interval_sec = makeExpr<Analyzer::BinOper>(bigint_ti.get_type(),
1105  kDIVIDE,
1106  kONE,
1107  interval,
1108  makeNumericConstant(bigint_ti, 1000));
1109  if (op == kMINUS) {
1110  interval_sec =
1111  std::make_shared<Analyzer::UOper>(bigint_ti, false, kUMINUS, interval_sec);
1112  }
1113  }
1114  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daSECOND, interval_sec, datetime);
1115  }
1116  CHECK(interval_ti.get_type() == kINTERVAL_YEAR_MONTH);
1117  const auto interval_months = op == kMINUS ? std::make_shared<Analyzer::UOper>(
1118  bigint_ti, false, kUMINUS, interval)
1119  : interval;
1120  return makeExpr<Analyzer::DateaddExpr>(datetime_ti, daMONTH, interval_months, datetime);
1121 }
SQLOps getOperator() const
Definition: sqltypes.h:51
Definition: sqldefs.h:41
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqltypes.h:55
Definition: sqldefs.h:40
Definition: sqldefs.h:69
#define CHECK(condition)
Definition: Logger.h:187
const SQLTypeInfo & getType() const
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:

◆ translateDatetime()

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

Definition at line 1211 of file RelAlgTranslator.cpp.

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

1212  {
1213  CHECK_EQ(size_t(1), rex_function->size());
1214  const auto arg = translateScalarRex(rex_function->getOperand(0));
1215  const auto arg_lit = std::dynamic_pointer_cast<Analyzer::Constant>(arg);
1216  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
1217  if (!arg_lit) {
1218  throw std::runtime_error(datetime_err);
1219  }
1220  CHECK(arg_lit->get_type_info().is_string());
1221  if (*arg_lit->get_constval().stringval != std::string("NOW")) {
1222  throw std::runtime_error(datetime_err);
1223  }
1224  return translateNow();
1225 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:187
std::shared_ptr< Analyzer::Expr > translateNow() const
+ Here is the call graph for this function:

◆ translateExtract()

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

Definition at line 919 of file RelAlgTranslator.cpp.

References CHECK_EQ, ExtractExpr::generate(), DateTruncExpr::generate(), RexFunctionOperator::getName(), RexOperator::getOperand(), and RexOperator::size().

920  {
921  CHECK_EQ(size_t(2), rex_function->size());
922  const auto timeunit = translateScalarRex(rex_function->getOperand(0));
923  const auto timeunit_lit = std::dynamic_pointer_cast<Analyzer::Constant>(timeunit);
924  if (!timeunit_lit) {
925  throw std::runtime_error("The time unit parameter must be a literal.");
926  }
927  const auto from_expr = translateScalarRex(rex_function->getOperand(1));
928  const bool is_date_trunc = rex_function->getName() == std::string("PG_DATE_TRUNC");
929  if (is_date_trunc) {
930  return DateTruncExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
931  } else {
932  return ExtractExpr::generate(from_expr, *timeunit_lit->get_constval().stringval);
933  }
934 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
const std::shared_ptr< Analyzer::Expr > generate() const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
const std::string & getName() const
const std::shared_ptr< Analyzer::Expr > generate() const
+ Here is the call graph for this function:

◆ translateFunction()

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

Definition at line 1333 of file RelAlgTranslator.cpp.

References run-benchmark-import::args, bind_function(), CHECK, CHECK_EQ, anonymous_namespace{ImportTest.cpp}::d(), ext_arg_type_to_type_info(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), kDIVIDE, kONE, kSMALLINT, Parser::OperExpr::normalize(), rewrite_to_date_trunc(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_notnull(), RexOperator::size(), and Datum::smallintval.

1334  {
1335  if (rex_function->getName() == std::string("LIKE") ||
1336  rex_function->getName() == std::string("PG_ILIKE")) {
1337  return translateLike(rex_function);
1338  }
1339  if (rex_function->getName() == std::string("REGEXP_LIKE")) {
1340  return translateRegexp(rex_function);
1341  }
1342  if (rex_function->getName() == std::string("LIKELY")) {
1343  return translateLikely(rex_function);
1344  }
1345  if (rex_function->getName() == std::string("UNLIKELY")) {
1346  return translateUnlikely(rex_function);
1347  }
1348  if (rex_function->getName() == std::string("PG_EXTRACT") ||
1349  rex_function->getName() == std::string("PG_DATE_TRUNC")) {
1350  return translateExtract(rex_function);
1351  }
1352  if (rex_function->getName() == std::string("DATEADD")) {
1353  return translateDateadd(rex_function);
1354  }
1355  if (rex_function->getName() == std::string("DATEDIFF")) {
1356  return translateDatediff(rex_function);
1357  }
1358  if (rex_function->getName() == std::string("DATEPART")) {
1359  return translateDatepart(rex_function);
1360  }
1361  if (rex_function->getName() == std::string("LENGTH") ||
1362  rex_function->getName() == std::string("CHAR_LENGTH")) {
1363  return translateLength(rex_function);
1364  }
1365  if (rex_function->getName() == std::string("KEY_FOR_STRING")) {
1366  return translateKeyForString(rex_function);
1367  }
1368  if (rex_function->getName() == std::string("CARDINALITY") ||
1369  rex_function->getName() == std::string("ARRAY_LENGTH")) {
1370  return translateCardinality(rex_function);
1371  }
1372  if (rex_function->getName() == std::string("ITEM")) {
1373  return translateItem(rex_function);
1374  }
1375  if (rex_function->getName() == std::string("NOW")) {
1376  return translateNow();
1377  }
1378  if (rex_function->getName() == std::string("DATETIME")) {
1379  return translateDatetime(rex_function);
1380  }
1381  if (rex_function->getName() == std::string("usTIMESTAMP") ||
1382  rex_function->getName() == std::string("nsTIMESTAMP")) {
1383  return translateHPTLiteral(rex_function);
1384  }
1385  if (rex_function->getName() == std::string("ABS")) {
1386  return translateAbs(rex_function);
1387  }
1388  if (rex_function->getName() == std::string("SIGN")) {
1389  return translateSign(rex_function);
1390  }
1391  if (rex_function->getName() == std::string("CEIL") ||
1392  rex_function->getName() == std::string("FLOOR")) {
1393  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1394  rex_function->getType(),
1395  rex_function->getName(),
1396  translateFunctionArgs(rex_function));
1397  } else if (rex_function->getName() == std::string("ROUND")) {
1398  std::vector<std::shared_ptr<Analyzer::Expr>> args =
1399  translateFunctionArgs(rex_function);
1400 
1401  if (rex_function->size() == 1) {
1402  // push a 0 constant if 2nd operand is missing.
1403  // this needs to be done as calcite returns
1404  // only the 1st operand without defaulting the 2nd one
1405  // when the user did not specify the 2nd operand.
1406  SQLTypes t = kSMALLINT;
1407  Datum d;
1408  d.smallintval = 0;
1409  args.push_back(makeExpr<Analyzer::Constant>(t, false, d));
1410  }
1411 
1412  // make sure we have only 2 operands
1413  CHECK(args.size() == 2);
1414 
1415  if (!args[0]->get_type_info().is_number()) {
1416  throw std::runtime_error("Only numeric 1st operands are supported");
1417  }
1418 
1419  // the 2nd operand does not need to be a constant
1420  // it can happily reference another integer column
1421  if (!args[1]->get_type_info().is_integer()) {
1422  throw std::runtime_error("Only integer 2nd operands are supported");
1423  }
1424 
1425  return makeExpr<Analyzer::FunctionOperWithCustomTypeHandling>(
1426  rex_function->getType(), rex_function->getName(), args);
1427  }
1428  if (rex_function->getName() == std::string("DATETIME_PLUS")) {
1429  auto dt_plus = makeExpr<Analyzer::FunctionOper>(rex_function->getType(),
1430  rex_function->getName(),
1431  translateFunctionArgs(rex_function));
1432  const auto date_trunc = rewrite_to_date_trunc(dt_plus.get());
1433  if (date_trunc) {
1434  return date_trunc;
1435  }
1436  return translateDateadd(rex_function);
1437  }
1438  if (rex_function->getName() == std::string("/INT")) {
1439  CHECK_EQ(size_t(2), rex_function->size());
1440  std::shared_ptr<Analyzer::Expr> lhs = translateScalarRex(rex_function->getOperand(0));
1441  std::shared_ptr<Analyzer::Expr> rhs = translateScalarRex(rex_function->getOperand(1));
1442  const auto rhs_lit = std::dynamic_pointer_cast<Analyzer::Constant>(rhs);
1443  return Parser::OperExpr::normalize(kDIVIDE, kONE, lhs, rhs);
1444  }
1445  if (rex_function->getName() == std::string("Reinterpret")) {
1446  CHECK_EQ(size_t(1), rex_function->size());
1447  return translateScalarRex(rex_function->getOperand(0));
1448  }
1449  if (rex_function->getName() == std::string("ST_X") ||
1450  rex_function->getName() == std::string("ST_Y") ||
1451  rex_function->getName() == std::string("ST_XMin") ||
1452  rex_function->getName() == std::string("ST_YMin") ||
1453  rex_function->getName() == std::string("ST_XMax") ||
1454  rex_function->getName() == std::string("ST_YMax") ||
1455  rex_function->getName() == std::string("ST_NRings") ||
1456  rex_function->getName() == std::string("ST_NPoints") ||
1457  rex_function->getName() == std::string("ST_Length") ||
1458  rex_function->getName() == std::string("ST_Perimeter") ||
1459  rex_function->getName() == std::string("ST_Area") ||
1460  rex_function->getName() == std::string("ST_SRID") ||
1461  rex_function->getName() == std::string("MapD_GeoPolyBoundsPtr") || // deprecated
1462  rex_function->getName() == std::string("MapD_GeoPolyRenderGroup") || // deprecated
1463  rex_function->getName() == std::string("OmniSci_Geo_PolyBoundsPtr") ||
1464  rex_function->getName() == std::string("OmniSci_Geo_PolyRenderGroup")) {
1465  CHECK_EQ(rex_function->size(), size_t(1));
1466  return translateUnaryGeoFunction(rex_function);
1467  }
1468  if (rex_function->getName() == std::string("convert_meters_to_pixel_width") ||
1469  rex_function->getName() == std::string("convert_meters_to_pixel_height") ||
1470  rex_function->getName() == std::string("is_point_in_view") ||
1471  rex_function->getName() == std::string("is_point_size_in_view")) {
1472  return translateFunctionWithGeoArg(rex_function);
1473  }
1474  if (rex_function->getName() == std::string("ST_Distance") ||
1475  rex_function->getName() == std::string("ST_MaxDistance") ||
1476  rex_function->getName() == std::string("ST_Intersects") ||
1477  rex_function->getName() == std::string("ST_Disjoint") ||
1478  rex_function->getName() == std::string("ST_Contains") ||
1479  rex_function->getName() == std::string("ST_Within")) {
1480  CHECK_EQ(rex_function->size(), size_t(2));
1481  return translateBinaryGeoFunction(rex_function);
1482  }
1483  if (rex_function->getName() == std::string("ST_DWithin") ||
1484  rex_function->getName() == std::string("ST_DFullyWithin")) {
1485  CHECK_EQ(rex_function->size(), size_t(3));
1486  return translateTernaryGeoFunction(rex_function);
1487  }
1488  if (rex_function->getName() == std::string("OFFSET_IN_FRAGMENT")) {
1489  CHECK_EQ(size_t(0), rex_function->size());
1490  return translateOffsetInFragment();
1491  }
1492  if (rex_function->getName() == std::string("ARRAY")) {
1493  // Var args; currently no check. Possible fix-me -- can array have 0 elements?
1494  return translateArrayFunction(rex_function);
1495  }
1496  if (rex_function->getName() == std::string("ST_GeomFromText") ||
1497  rex_function->getName() == std::string("ST_GeogFromText") ||
1498  rex_function->getName() == std::string("ST_Point")) {
1499  throw QueryNotSupported("Geo constructor " + rex_function->getName() +
1500  " currently not supported in this context");
1501  }
1502 
1503  auto arg_expr_list = translateFunctionArgs(rex_function);
1504  // Reset possibly wrong return type of rex_function to the return
1505  // type of the optimal valid implementation. The return type can be
1506  // wrong in the case of multiple implementations of UDF functions
1507  // that have different return types but Calcite specifies the return
1508  // type according to the first implementation.
1509  auto ext_func_sig = bind_function(rex_function->getName(), arg_expr_list);
1510  auto ret_ti = ext_arg_type_to_type_info(ext_func_sig.getRet());
1511  // By defualt, the extension function type will not allow nulls. If one of the arguments
1512  // is nullable, the extension function must also explicitly allow nulls.
1513  bool arguments_not_null = true;
1514  for (const auto& arg_expr : arg_expr_list) {
1515  if (!arg_expr->get_type_info().get_notnull()) {
1516  arguments_not_null = false;
1517  break;
1518  }
1519  }
1520  ret_ti.set_notnull(arguments_not_null);
1521  return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
1522 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
std::shared_ptr< Analyzer::Expr > translateDatediff(const RexFunctionOperator *) const
void d(const SQLTypes expected_type, const std::string &str)
Definition: ImportTest.cpp:268
SQLTypes
Definition: sqltypes.h:40
std::shared_ptr< Analyzer::Expr > translateCardinality(const RexFunctionOperator *) const
ExtensionFunction bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< ExtensionFunction > &ext_funcs)
std::shared_ptr< Analyzer::Expr > translateKeyForString(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateAbs(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateItem(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateFunctionWithGeoArg(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateSign(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateLength(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateUnlikely(const RexFunctionOperator *) const
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
void set_notnull(bool n)
Definition: sqltypes.h:416
std::shared_ptr< Analyzer::Expr > translateOffsetInFragment() const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateDateadd(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
int16_t smallintval
Definition: sqltypes.h:124
std::shared_ptr< Analyzer::Expr > translateArrayFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateLike(const RexFunctionOperator *) const
const RexScalar * getOperand(const size_t idx) 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:257
Definition: sqldefs.h:69
std::shared_ptr< Analyzer::Expr > translateExtract(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateLikely(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateRegexp(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateHPTLiteral(const RexFunctionOperator *) const
#define CHECK(condition)
Definition: Logger.h:187
const SQLTypeInfo & getType() const
const std::string & getName() const
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateNow() const
std::shared_ptr< Analyzer::Expr > translateDatetime(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 > translateDatepart(const RexFunctionOperator *) const
+ Here is the call graph for this function:

◆ translateFunctionArgs()

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

Definition at line 1603 of file RelAlgTranslator.cpp.

References run-benchmark-import::args, RexOperator::getOperand(), and RexOperator::size().

1604  {
1605  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1606  for (size_t i = 0; i < rex_function->size(); ++i) {
1607  args.push_back(translateScalarRex(rex_function->getOperand(i)));
1608  }
1609  return args;
1610 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
+ Here is the call graph for this function:

◆ translateFunctionWithGeoArg()

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

Definition at line 939 of file RelAlgTranslatorGeo.cpp.

References run-benchmark-import::args, CHECK, CHECK_EQ, RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Datum::intval, kENCODING_GEOINT, kINT, kPOINT, RexOperator::size(), translateGeoFunctionArg(), and translateScalarRex().

940  {
941  int32_t lindex = 0;
942  std::string specialized_geofunc{rex_function->getName()};
943  if (rex_function->getName() == std::string("convert_meters_to_pixel_width") ||
944  rex_function->getName() == std::string("convert_meters_to_pixel_height")) {
945  CHECK_EQ(rex_function->size(), 6u);
946  SQLTypeInfo arg_ti;
947  std::vector<std::shared_ptr<Analyzer::Expr>> args;
948  args.push_back(translateScalarRex(rex_function->getOperand(0)));
949  auto geoargs = translateGeoFunctionArg(
950  rex_function->getOperand(1), arg_ti, lindex, false, true, false);
951  // only works on points
952  if (arg_ti.get_type() != kPOINT) {
953  throw QueryNotSupported(rex_function->getName() +
954  " expects a point for the second argument");
955  }
956 
957  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
958 
959  // Add compression information
960  Datum input_compression;
961  input_compression.intval =
962  (arg_ti.get_compression() == kENCODING_GEOINT && arg_ti.get_comp_param() == 32)
963  ? 1
964  : 0;
965  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
966  if (arg_ti.get_input_srid() != 4326) {
967  throw QueryNotSupported(
968  rex_function->getName() +
969  " currently only supports points of with SRID WGS84/EPSG:4326");
970  }
971  Datum input_srid;
972  input_srid.intval = arg_ti.get_input_srid();
973  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
974  Datum output_srid;
975  // Forcing web-mercator projection for now
976  // TODO(croot): check that the input-to-output conversion routines exist?
977  output_srid.intval =
978  arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
979  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
980 
981  args.push_back(translateScalarRex(rex_function->getOperand(2)));
982  args.push_back(translateScalarRex(rex_function->getOperand(3)));
983  args.push_back(translateScalarRex(rex_function->getOperand(4)));
984  args.push_back(translateScalarRex(rex_function->getOperand(5)));
985  return makeExpr<Analyzer::FunctionOper>(
986  rex_function->getType(), specialized_geofunc, args);
987  } else if (rex_function->getName() == std::string("is_point_in_view")) {
988  CHECK_EQ(rex_function->size(), 5u);
989  SQLTypeInfo arg_ti;
990  std::vector<std::shared_ptr<Analyzer::Expr>> args;
991  auto geoargs = translateGeoFunctionArg(
992  rex_function->getOperand(0), arg_ti, lindex, false, true, false);
993  // only works on points
994  if (arg_ti.get_type() != kPOINT) {
995  throw QueryNotSupported(rex_function->getName() +
996  " expects a point for the second argument");
997  }
998 
999  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1000 
1001  // Add compression information
1002  Datum input_compression;
1003  input_compression.intval =
1004  (arg_ti.get_compression() == kENCODING_GEOINT && arg_ti.get_comp_param() == 32)
1005  ? 1
1006  : 0;
1007  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1008  if (arg_ti.get_input_srid() != 4326) {
1009  throw QueryNotSupported(
1010  rex_function->getName() +
1011  " currently only supports points of with SRID WGS84/EPSG:4326");
1012  }
1013  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1014  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1015  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1016  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1017  return makeExpr<Analyzer::FunctionOper>(
1018  rex_function->getType(), specialized_geofunc, args);
1019  } else if (rex_function->getName() == std::string("is_point_size_in_view")) {
1020  CHECK_EQ(rex_function->size(), 6u);
1021  SQLTypeInfo arg_ti;
1022  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1023  auto geoargs = translateGeoFunctionArg(
1024  rex_function->getOperand(0), arg_ti, lindex, false, true, false);
1025  // only works on points
1026  if (arg_ti.get_type() != kPOINT) {
1027  throw QueryNotSupported(rex_function->getName() +
1028  " expects a point for the second argument");
1029  }
1030 
1031  args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1032 
1033  // Add compression information
1034  Datum input_compression;
1035  input_compression.intval =
1036  (arg_ti.get_compression() == kENCODING_GEOINT && arg_ti.get_comp_param() == 32)
1037  ? 1
1038  : 0;
1039  args.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
1040  if (arg_ti.get_input_srid() != 4326) {
1041  throw QueryNotSupported(
1042  rex_function->getName() +
1043  " currently only supports points of with SRID WGS84/EPSG:4326");
1044  }
1045  args.push_back(translateScalarRex(rex_function->getOperand(1)));
1046  args.push_back(translateScalarRex(rex_function->getOperand(2)));
1047  args.push_back(translateScalarRex(rex_function->getOperand(3)));
1048  args.push_back(translateScalarRex(rex_function->getOperand(4)));
1049  args.push_back(translateScalarRex(rex_function->getOperand(5)));
1050  return makeExpr<Analyzer::FunctionOper>(
1051  rex_function->getType(), specialized_geofunc, args);
1052  }
1053  CHECK(false);
1054  return nullptr;
1055 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
int32_t intval
Definition: sqltypes.h:125
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, int32_t &lindex, const bool with_bounds, const bool with_render_group, const bool expand_geo_col) const
#define CHECK(condition)
Definition: Logger.h:187
const SQLTypeInfo & getType() const
Definition: sqltypes.h:47
const std::string & getName() const
+ Here is the call graph for this function:

◆ translateGeoColumn()

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

References run-benchmark-import::args, cat_, CHECK, CHECK_GE, CHECK_LT, ColumnDescriptor::columnType, Importer_NS::compress_coords(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_physical_coord_cols(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_type(), RexAbstractInput::getIndex(), Catalog_Namespace::Catalog::getMetadataForColumnBySpi(), RexInput::getSourceNode(), SQLTypeInfoCore< TYPE_FACET_PACK >::has_bounds(), SQLTypeInfoCore< TYPE_FACET_PACK >::has_render_group(), input_to_nest_level_, IS_GEO, and SPIMAP_GEO_PHYSICAL_INPUT.

Referenced by translateGeoFunctionArg(), and translateGeoOverlapsOper().

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

◆ translateGeoComparison()

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

Definition at line 906 of file RelAlgTranslatorGeo.cpp.

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

907  {
908  if (rex_operator->size() != size_t(2)) {
909  return nullptr;
910  }
911 
912  auto geo_distance_expr = translateScalarRex(rex_operator->getOperand(0));
913  auto func_oper = dynamic_cast<Analyzer::FunctionOper*>(geo_distance_expr.get());
914  if (func_oper && func_oper->getName() == std::string("ST_Distance_Point_Point")) {
915  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
916  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
917  for (size_t i = 0; i < func_oper->getArity(); i++) {
918  geoargs.push_back(func_oper->getOwnArg(i));
919  }
920  geo_distance_expr = makeExpr<Analyzer::FunctionOper>(
921  distance_ti, std::string("ST_Distance_Point_Point_Squared"), geoargs);
922  auto distance_expr = translateScalarRex(rex_operator->getOperand(1));
923  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
924  distance_expr->add_cast(distance_ti);
925  }
926  distance_expr = makeExpr<Analyzer::BinOper>(distance_ti,
927  distance_expr->get_contains_agg(),
928  kMULTIPLY,
929  kONE,
930  distance_expr,
931  distance_expr);
932  distance_expr = fold_expr(distance_expr.get());
933  return makeExpr<Analyzer::BinOper>(
934  kBOOLEAN, rex_operator->getOperator(), kONE, geo_distance_expr, distance_expr);
935  }
936  return nullptr;
937 }
SQLOps getOperator() const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqldefs.h:69
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
+ Here is the call graph for this function:

◆ translateGeoFunctionArg()

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
private

Definition at line 202 of file RelAlgTranslatorGeo.cpp.

References run-benchmark-import::args, CHECK, CHECK_EQ, fold_expr(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_input_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_output_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_type(), IS_GEO, kARRAY, kCAST, kDOUBLE, kENCODING_NONE, kGEOGRAPHY, kGEOMETRY, kINT, kLINESTRING, kNULLT, kPOINT, kSMALLINT, kTEXT, kTINYINT, SQLTypeInfoCore< TYPE_FACET_PACK >::set_compression(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_input_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_output_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_subtype(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_type(), to_string(), translateGeoColumn(), translateGeoLiteral(), translateInput(), translateLiteral(), and translateScalarRex().

Referenced by translateBinaryGeoFunction(), translateFunctionWithGeoArg(), and translateUnaryGeoFunction().

208  {
209  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
210 
211  const auto rex_input = dynamic_cast<const RexInput*>(rex_scalar);
212  if (rex_input) {
213  const auto input = translateInput(rex_input);
214  const auto column = dynamic_cast<const Analyzer::ColumnVar*>(input.get());
215  if (!column || !column->get_type_info().is_geometry()) {
216  throw QueryNotSupported("Geo function is expecting a geo column argument");
217  }
218  return translateGeoColumn(
219  rex_input, arg_ti, with_bounds, with_render_group, expand_geo_col);
220  }
221  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex_scalar);
222  if (rex_function) {
223  if (rex_function->getName() == std::string("ST_Transform")) {
224  CHECK_EQ(size_t(2), rex_function->size());
225  const auto rex_scalar0 =
226  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
227  if (!rex_scalar0) {
228  throw QueryNotSupported(rex_function->getName() + ": unexpected first argument");
229  }
230  auto arg0 = translateGeoFunctionArg(
231  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
232 
233  const auto rex_literal =
234  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
235  if (!rex_literal) {
236  throw QueryNotSupported(rex_function->getName() +
237  ": second argument is expected to be a literal");
238  }
239  const auto e = translateLiteral(rex_literal);
240  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
241  if (!ce || !e->get_type_info().is_integer()) {
242  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
243  }
244  int32_t srid = 0;
245  if (e->get_type_info().get_type() == kSMALLINT) {
246  srid = static_cast<int32_t>(ce->get_constval().smallintval);
247  } else if (e->get_type_info().get_type() == kTINYINT) {
248  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
249  } else if (e->get_type_info().get_type() == kINT) {
250  srid = static_cast<int32_t>(ce->get_constval().intval);
251  } else {
252  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
253  }
254  if (srid != 900913) {
255  throw QueryNotSupported(rex_function->getName() + ": unsupported output SRID " +
256  std::to_string(srid));
257  }
258  if (arg_ti.get_input_srid() > 0) {
259  if (arg_ti.get_input_srid() != 4326) {
260  throw QueryNotSupported(rex_function->getName() + ": unsupported input SRID " +
261  std::to_string(arg_ti.get_input_srid()));
262  }
263  arg_ti.set_output_srid(
264  srid); // We have a valid input SRID, register the output SRID for transform
265  } else {
266  throw QueryNotSupported(rex_function->getName() +
267  ": unexpected input SRID, unable to transform");
268  }
269  return arg0;
270  } else if (rex_function->getName() == std::string("ST_GeomFromText") ||
271  rex_function->getName() == std::string("ST_GeogFromText")) {
272  CHECK(rex_function->size() == size_t(1) || rex_function->size() == size_t(2));
273  // First - register srid, then send it to geo literal translation
274  int32_t srid = 0;
275  if (rex_function->size() == 2) {
276  const auto rex_literal =
277  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
278  if (!rex_literal) {
279  throw QueryNotSupported(rex_function->getName() +
280  ": second argument is expected to be a literal");
281  }
282  const auto e = translateLiteral(rex_literal);
283  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
284  if (!ce || !e->get_type_info().is_integer()) {
285  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
286  }
287  if (e->get_type_info().get_type() == kSMALLINT) {
288  srid = static_cast<int32_t>(ce->get_constval().smallintval);
289  } else if (e->get_type_info().get_type() == kTINYINT) {
290  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
291  } else if (e->get_type_info().get_type() == kINT) {
292  srid = static_cast<int32_t>(ce->get_constval().intval);
293  } else {
294  throw QueryNotSupported(rex_function->getName() + " expecting integer SRID");
295  }
296  if (srid != 0 && srid != 4326 && srid != 900913) {
297  throw QueryNotSupported(rex_function->getName() + ": unsupported SRID " +
298  std::to_string(srid));
299  }
300  }
301  arg_ti.set_input_srid(srid); // Input SRID
302  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
303 
304  const auto rex_literal =
305  dynamic_cast<const RexLiteral*>(rex_function->getOperand(0));
306  if (!rex_literal) {
307  throw QueryNotSupported(rex_function->getName() +
308  " expects a string literal as first argument");
309  }
310  auto arg0 = translateGeoLiteral(rex_literal, arg_ti, with_bounds);
311  arg_ti.set_subtype((rex_function->getName() == std::string("ST_GeogFromText"))
312  ? kGEOGRAPHY
313  : kGEOMETRY);
314  return arg0;
315  } else if (rex_function->getName() == std::string("ST_PointN")) {
316  CHECK_EQ(size_t(2), rex_function->size());
317  const auto rex_scalar0 =
318  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
319  if (!rex_scalar0) {
320  throw QueryNotSupported(rex_function->getName() +
321  ": expects scalar as first argument");
322  }
323  auto arg0 = translateGeoFunctionArg(
324  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
325  if (arg_ti.get_type() != kLINESTRING) {
326  throw QueryNotSupported(rex_function->getName() +
327  " expects LINESTRING as first argument");
328  }
329  const auto rex_literal =
330  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
331  if (!rex_literal) {
332  throw QueryNotSupported(rex_function->getName() +
333  ": second argument is expected to be a literal");
334  }
335  const auto e = translateLiteral(rex_literal);
336  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
337  if (!ce || !e->get_type_info().is_integer()) {
338  throw QueryNotSupported(rex_function->getName() +
339  ": expecting integer index as second argument");
340  }
341  int32_t index = 0;
342  if (e->get_type_info().get_type() == kSMALLINT) {
343  index = static_cast<int32_t>(ce->get_constval().smallintval);
344  } else if (e->get_type_info().get_type() == kTINYINT) {
345  index = static_cast<int32_t>(ce->get_constval().tinyintval);
346  } else if (e->get_type_info().get_type() == kINT) {
347  index = static_cast<int32_t>(ce->get_constval().intval);
348  } else {
349  throw QueryNotSupported(rex_function->getName() + " expecting integer index");
350  }
351  if (lindex != 0) {
352  throw QueryNotSupported(rex_function->getName() +
353  ": LINESTRING is already indexed");
354  }
355  if (index == 0) {
356  throw QueryNotSupported(rex_function->getName() + ": invalid index");
357  }
358  lindex = index;
359  return arg0;
360  } else if (rex_function->getName() == std::string("ST_StartPoint")) {
361  CHECK_EQ(size_t(1), rex_function->size());
362  const auto rex_scalar0 =
363  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
364  if (!rex_scalar0) {
365  throw QueryNotSupported(rex_function->getName() +
366  ": expects scalar as first argument");
367  }
368  auto arg0 = translateGeoFunctionArg(
369  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
370  if (arg_ti.get_type() != kLINESTRING) {
371  throw QueryNotSupported(rex_function->getName() +
372  " expects LINESTRING as first argument");
373  }
374  if (lindex != 0) {
375  throw QueryNotSupported(rex_function->getName() +
376  ": LINESTRING is already indexed");
377  }
378  lindex = 1;
379  return arg0;
380  } else if (rex_function->getName() == std::string("ST_EndPoint")) {
381  CHECK_EQ(size_t(1), rex_function->size());
382  const auto rex_scalar0 =
383  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
384  if (!rex_scalar0) {
385  throw QueryNotSupported(rex_function->getName() +
386  ": expects scalar as first argument");
387  }
388  auto arg0 = translateGeoFunctionArg(
389  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
390  if (arg_ti.get_type() != kLINESTRING) {
391  throw QueryNotSupported(rex_function->getName() +
392  " expects LINESTRING as first argument");
393  }
394  if (lindex != 0) {
395  throw QueryNotSupported(rex_function->getName() +
396  ": LINESTRING is already indexed");
397  }
398  lindex = -1;
399  return arg0;
400  } else if (rex_function->getName() == std::string("ST_SRID")) {
401  CHECK_EQ(size_t(1), rex_function->size());
402  const auto rex_scalar0 =
403  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
404  if (!rex_scalar0) {
405  throw QueryNotSupported(rex_function->getName() +
406  ": expects scalar as first argument");
407  }
408  auto arg0 = translateGeoFunctionArg(
409  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
410  if (!IS_GEO(arg_ti.get_type())) {
411  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
412  }
413  return arg0;
414  } else if (rex_function->getName() == std::string("ST_SetSRID")) {
415  CHECK_EQ(size_t(2), rex_function->size());
416  const auto rex_scalar0 =
417  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
418  if (!rex_scalar0) {
419  throw QueryNotSupported(rex_function->getName() +
420  ": expects scalar as first argument");
421  }
422  auto arg0 = translateGeoFunctionArg(
423  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
424  if (!IS_GEO(arg_ti.get_type())) {
425  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
426  }
427  const auto rex_literal =
428  dynamic_cast<const RexLiteral*>(rex_function->getOperand(1));
429  if (!rex_literal) {
430  throw QueryNotSupported(rex_function->getName() +
431  ": second argument is expected to be a literal");
432  }
433  const auto e = translateLiteral(rex_literal);
434  auto ce = std::dynamic_pointer_cast<Analyzer::Constant>(e);
435  if (!ce || !e->get_type_info().is_integer()) {
436  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
437  }
438  int32_t srid = 0;
439  if (e->get_type_info().get_type() == kSMALLINT) {
440  srid = static_cast<int32_t>(ce->get_constval().smallintval);
441  } else if (e->get_type_info().get_type() == kTINYINT) {
442  srid = static_cast<int32_t>(ce->get_constval().tinyintval);
443  } else if (e->get_type_info().get_type() == kINT) {
444  srid = static_cast<int32_t>(ce->get_constval().intval);
445  } else {
446  throw QueryNotSupported(rex_function->getName() + ": expecting integer SRID");
447  }
448  arg_ti.set_input_srid(srid); // Input SRID
449  arg_ti.set_output_srid(srid); // Output SRID is the same - no transform
450  return arg0;
451  } else if (rex_function->getName() == std::string("CastToGeography")) {
452  CHECK_EQ(size_t(1), rex_function->size());
453  const auto rex_scalar0 =
454  dynamic_cast<const RexScalar*>(rex_function->getOperand(0));
455  if (!rex_scalar0) {
456  throw QueryNotSupported(rex_function->getName() +
457  ": expects scalar as first argument");
458  }
459  auto arg0 = translateGeoFunctionArg(
460  rex_scalar0, arg_ti, lindex, with_bounds, with_render_group, expand_geo_col);
461  if (!IS_GEO(arg_ti.get_type())) {
462  throw QueryNotSupported(rex_function->getName() + " expects geometry argument");
463  }
464  if (arg_ti.get_output_srid() != 4326) {
465  throw QueryNotSupported(rex_function->getName() +
466  " expects geometry with SRID=4326");
467  }
468  arg_ti.set_subtype(kGEOGRAPHY);
469  return arg0;
470  } else if (rex_function->getName() == std::string("ST_Point")) {
471  CHECK_EQ(size_t(2), rex_function->size());
472  arg_ti.set_type(kPOINT);
473  arg_ti.set_subtype(kGEOMETRY);
474  arg_ti.set_input_srid(0);
475  arg_ti.set_output_srid(0);
477 
478  auto coord1 = translateScalarRex(rex_function->getOperand(0));
479  auto coord2 = translateScalarRex(rex_function->getOperand(1));
480  auto d_ti = SQLTypeInfo(kDOUBLE, true);
481  auto cast_coord1 = coord1->add_cast(d_ti);
482  auto cast_coord2 = coord2->add_cast(d_ti);
483  // First try to fold to geo literal
484  auto fold1 = fold_expr(cast_coord1.get());
485  auto fold2 = fold_expr(cast_coord2.get());
486  auto const_coord1 = std::dynamic_pointer_cast<Analyzer::Constant>(fold1);
487  auto const_coord2 = std::dynamic_pointer_cast<Analyzer::Constant>(fold2);
488  if (const_coord1 && const_coord2) {
489  CHECK(const_coord1->get_type_info().get_type() == kDOUBLE);
490  CHECK(const_coord2->get_type_info().get_type() == kDOUBLE);
491  std::string wkt = "POINT(" +
492  std::to_string(const_coord1->get_constval().doubleval) + " " +
493  std::to_string(const_coord2->get_constval().doubleval) + ")";
494  RexLiteral rex_literal{wkt, kTEXT, kNULLT, 0, 0, 0, 0};
495  auto args = translateGeoLiteral(&rex_literal, arg_ti, false);
496  CHECK(arg_ti.get_type() == kPOINT);
497  return args;
498  }
499  // Couldn't fold to geo literal, construct on the fly
500  auto da_ti = SQLTypeInfo(kARRAY, true);
501  da_ti.set_subtype(kDOUBLE);
502  da_ti.set_size(16);
503  auto cast_coords = {cast_coord1, cast_coord2};
504  auto ae = makeExpr<Analyzer::ArrayExpr>(da_ti, cast_coords, 0, true);
505  // cast it to tinyint[16]
506  SQLTypeInfo tia_ti = SQLTypeInfo(kARRAY, true);
507  tia_ti.set_subtype(kTINYINT);
508  tia_ti.set_size(16);
509  return {makeExpr<Analyzer::UOper>(tia_ti, false, kCAST, ae)};
510  } else {
511  throw QueryNotSupported("Unsupported argument: " + rex_function->getName());
512  }
513  }
514  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
515  if (rex_literal) {
516  return translateGeoLiteral(rex_literal, arg_ti, with_bounds);
517  }
518  throw QueryNotSupported("Geo function argument not supported");
519 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:319
void set_input_srid(int d)
Definition: sqltypes.h:413
Definition: sqldefs.h:49
HOST DEVICE void set_type(SQLTypes t)
Definition: sqltypes.h:409
void set_compression(EncodingType c)
Definition: sqltypes.h:419
std::string to_string(char const *&&v)
void set_output_srid(int s)
Definition: sqltypes.h:415
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:410
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:323
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoLiteral(const RexLiteral *, SQLTypeInfo &, bool) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqltypes.h:54
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:325
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
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 CHECK(condition)
Definition: Logger.h:187
Definition: sqltypes.h:47
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
#define IS_GEO(T)
Definition: sqltypes.h:165
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:

◆ translateGeoLiteral()

std::vector< std::shared_ptr< Analyzer::Expr > > RelAlgTranslator::translateGeoLiteral ( const RexLiteral rex_literal,
SQLTypeInfo ti,
bool  with_bounds 
) const
private

Definition at line 107 of file RelAlgTranslatorGeo.cpp.

References run-benchmark-import::args, anonymous_namespace{ExecuteTest.cpp}::c(), CHECK, Importer_NS::compress_coords(), anonymous_namespace{ImportTest.cpp}::d(), Datum::doubleval, SQLTypeInfoCore< TYPE_FACET_PACK >::get_compression(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_output_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_type(), Geo_namespace::GeoTypesFactory::getGeoColumns(), SQLTypeInfoCore< TYPE_FACET_PACK >::has_bounds(), Datum::intval, kARRAY, kDOUBLE, kENCODING_GEOINT, kGEOMETRY, kINT, kMULTIPOLYGON, kPOLYGON, kTEXT, kTINYINT, SQLTypeInfoCore< TYPE_FACET_PACK >::set_comp_param(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_compression(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_input_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_output_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_size(), SQLTypeInfoCore< TYPE_FACET_PACK >::set_subtype(), Datum::tinyintval, and translateLiteral().

Referenced by translateGeoFunctionArg().

110  {
111  CHECK(rex_literal);
112  if (rex_literal->getType() != kTEXT) {
113  throw std::runtime_error("Geo literals must be strings");
114  }
115  const auto e = translateLiteral(rex_literal);
116  auto wkt = std::dynamic_pointer_cast<Analyzer::Constant>(e);
117  CHECK(wkt);
118  std::vector<double> coords;
119  std::vector<double> bounds;
120  std::vector<int> ring_sizes;
121  std::vector<int> poly_rings;
122  int32_t srid = ti.get_output_srid();
124  *wkt->get_constval().stringval, ti, coords, bounds, ring_sizes, poly_rings)) {
125  throw QueryNotSupported("Could not read geometry from text");
126  }
128  ti.set_input_srid(srid);
129  ti.set_output_srid(srid);
130  // Compress geo literals by default
131  if (srid == 4326) {
133  ti.set_comp_param(32);
134  }
135 
136  std::vector<std::shared_ptr<Analyzer::Expr>> args;
137 
138  std::vector<uint8_t> compressed_coords = Importer_NS::compress_coords(coords, ti);
139  std::list<std::shared_ptr<Analyzer::Expr>> compressed_coords_exprs;
140  for (auto cc : compressed_coords) {
141  Datum d;
142  d.tinyintval = cc;
143  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
144  compressed_coords_exprs.push_back(e);
145  }
146  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
147  arr_ti.set_subtype(kTINYINT);
148  arr_ti.set_size(compressed_coords.size() * sizeof(int8_t));
149  arr_ti.set_compression(ti.get_compression());
150  arr_ti.set_comp_param((ti.get_compression() == kENCODING_GEOINT) ? 32 : 64);
151  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, compressed_coords_exprs));
152 
153  auto lit_type = ti.get_type();
154  if (lit_type == kPOLYGON || lit_type == kMULTIPOLYGON) {
155  // ring sizes
156  std::list<std::shared_ptr<Analyzer::Expr>> ring_size_exprs;
157  for (auto c : ring_sizes) {
158  Datum d;
159  d.intval = c;
160  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
161  ring_size_exprs.push_back(e);
162  }
163  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
164  arr_ti.set_subtype(kINT);
165  arr_ti.set_size(ring_sizes.size() * sizeof(int32_t));
166  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, ring_size_exprs));
167 
168  // poly rings
169  if (lit_type == kMULTIPOLYGON) {
170  std::list<std::shared_ptr<Analyzer::Expr>> poly_rings_exprs;
171  for (auto c : poly_rings) {
172  Datum d;
173  d.intval = c;
174  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
175  poly_rings_exprs.push_back(e);
176  }
177  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
178  arr_ti.set_subtype(kINT);
179  arr_ti.set_size(poly_rings.size() * sizeof(int32_t));
180  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, poly_rings_exprs));
181  }
182  }
183 
184  if (with_bounds && ti.has_bounds()) {
185  // bounds
186  std::list<std::shared_ptr<Analyzer::Expr>> bounds_exprs;
187  for (auto b : bounds) {
188  Datum d;
189  d.doubleval = b;
190  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
191  bounds_exprs.push_back(e);
192  }
193  SQLTypeInfo arr_ti = SQLTypeInfo(kARRAY, true);
194  arr_ti.set_subtype(kDOUBLE);
195  arr_ti.set_size(bounds.size() * sizeof(double));
196  args.push_back(makeExpr<Analyzer::Constant>(arr_ti, false, bounds_exprs));
197  }
198 
199  return args;
200 }
int8_t tinyintval
Definition: sqltypes.h:123
void d(const SQLTypes expected_type, const std::string &str)
Definition: ImportTest.cpp:268
void set_size(int s)
Definition: sqltypes.h:417
void c(const std::string &query_string, const ExecutorDeviceType device_type)
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:319
std::vector< uint8_t > compress_coords(std::vector< double > &coords, const SQLTypeInfo &ti)
Definition: Importer.cpp:1546
void set_input_srid(int d)
Definition: sqltypes.h:413
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:327
void set_compression(EncodingType c)
Definition: sqltypes.h:419
int32_t intval
Definition: sqltypes.h:125
void set_output_srid(int s)
Definition: sqltypes.h:415
HOST DEVICE void set_subtype(SQLTypes st)
Definition: sqltypes.h:410
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqltypes.h:54
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:325
static bool getGeoColumns(const std::string &wkt, 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: geo_types.cpp:459
void set_comp_param(int p)
Definition: sqltypes.h:420
#define CHECK(condition)
Definition: Logger.h:187
Definition: sqltypes.h:47
bool has_bounds() const
Definition: sqltypes.h:388
double doubleval
Definition: sqltypes.h:128
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ translateGeoOverlapsOper()

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

Definition at line 1057 of file RelAlgTranslatorGeo.cpp.

References CHECK, CHECK_EQ, CHECK_GT, SQLTypeInfoCore< TYPE_FACET_PACK >::get_type(), RexOperator::getOperand(), kBOOLEAN, kONE, kOVERLAPS, kPOINT, RexOperator::size(), and translateGeoColumn().

1058  {
1059  CHECK_EQ(rex_operator->size(), 2u);
1060 
1061  auto translate_input =
1062  [&](const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1063  const auto input = dynamic_cast<const RexInput*>(operand);
1064  CHECK(input);
1065 
1066  SQLTypeInfo ti;
1067  const auto exprs = translateGeoColumn(input, ti, true, false, false);
1068  CHECK_GT(exprs.size(), 0u);
1069  if (ti.get_type() == kPOINT) {
1070  return exprs.front();
1071  } else {
1072  return exprs.back();
1073  }
1074  };
1075 
1076  SQLQualifier sql_qual{kONE};
1077  SQLOps sql_op{kOVERLAPS};
1078  return makeExpr<Analyzer::BinOper>(SQLTypeInfo(kBOOLEAN, false),
1079  false,
1080  sql_op,
1081  sql_qual,
1082  translate_input(rex_operator->getOperand(1)),
1083  translate_input(rex_operator->getOperand(0)));
1084 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
SQLQualifier
Definition: sqldefs.h:69
SQLOps
Definition: sqldefs.h:29
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:319
#define CHECK_GT(x, y)
Definition: Logger.h:199
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqldefs.h:69
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 CHECK(condition)
Definition: Logger.h:187
+ Here is the call graph for this function:

◆ translateHPTLiteral()

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

Definition at line 1655 of file RelAlgTranslator.cpp.

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

1656  {
1657  /* since calcite uses Avatica package called DateTimeUtils to parse timestamp strings.
1658  Therefore any string having fractional seconds more 3 places after the decimal
1659  (milliseconds) will get truncated to 3 decimal places, therefore we lose precision
1660  (us|ns). Issue: [BE-2461] Here we are hijacking literal cast to Timestamp(6|9) from
1661  calcite and translating them to generate our own casts.
1662  */
1663  CHECK_EQ(size_t(1), rex_function->size());
1664  const auto operand = translateScalarRex(rex_function->getOperand(0));
1665  const auto& operand_ti = operand->get_type_info();
1666  const auto& target_ti = rex_function->getType();
1667  if (!operand_ti.is_string()) {
1668  throw std::runtime_error(
1669  "High precision timestamp cast argument must be a string. Input type is: " +
1670  operand_ti.get_type_name());
1671  } else if (!target_ti.is_high_precision_timestamp()) {
1672  throw std::runtime_error(
1673  "Cast target type should be high precision timestamp. Input type is: " +
1674  target_ti.get_type_name());
1675  } else if (target_ti.get_dimension() != 6 && target_ti.get_dimension() != 9) {
1676  throw std::runtime_error(
1677  "Cast target type should be TIMESTAMP(6|9). Input type is: TIMESTAMP(" +
1678  std::to_string(target_ti.get_dimension()) + ")");
1679  } else {
1680  return operand->add_cast(target_ti);
1681  }
1682 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
std::string to_string(char const *&&v)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
const SQLTypeInfo & getType() const
+ Here is the call graph for this function:

◆ translateInOper()

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

Definition at line 487 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, anonymous_namespace{ImportTest.cpp}::d(), anonymous_namespace{RelAlgTranslator.cpp}::datum_from_scalar_tv(), g_enable_watchdog, anonymous_namespace{RelAlgTranslator.cpp}::get_in_values_expr(), RexOperator::getOperand(), kCAST, kENCODING_DICT, kENCODING_NONE, run-benchmark-import::result, RexOperator::size(), and RelAlgNode::size().

488  {
489  if (just_explain_) {
490  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
491  }
492  CHECK(rex_operator->size() == 2);
493  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
494  const auto rhs = rex_operator->getOperand(1);
495  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rhs);
496  CHECK(rex_subquery);
497  auto ti = lhs->get_type_info();
498  auto result = rex_subquery->getExecutionResult();
499  auto& row_set = result->getRows();
500  CHECK_EQ(size_t(1), row_set->colCount());
501  const auto& rhs_ti = row_set->getColType(0);
502  if (rhs_ti.get_type() != ti.get_type()) {
503  throw std::runtime_error(
504  "The two sides of the IN operator must have the same type; found " +
505  ti.get_type_name() + " and " + rhs_ti.get_type_name());
506  }
507  row_set->moveToBegin();
508  if (row_set->entryCount() > 10000) {
509  std::shared_ptr<Analyzer::Expr> expr;
510  if ((ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT)) &&
511  !row_set->getQueryMemDesc().didOutputColumnar()) {
512  expr = getInIntegerSetExpr(lhs, *row_set);
513  // Handle the highly unlikely case when the InIntegerSet ended up being tiny.
514  // Just let it fall through the usual InValues path at the end of this method,
515  // its codegen knows to use inline comparisons for few values.
516  if (expr && std::static_pointer_cast<Analyzer::InIntegerSet>(expr)
517  ->get_value_list()
518  .size() <= 100) {
519  expr = nullptr;
520  }
521  } else {
522  expr = get_in_values_expr(lhs, *row_set);
523  }
524  if (expr) {
525  return expr;
526  }
527  }
528  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
529  while (true) {
530  auto row = row_set->getNextRow(true, false);
531  if (row.empty()) {
532  break;
533  }
534  if (g_enable_watchdog && value_exprs.size() >= 10000) {
535  throw std::runtime_error(
536  "Unable to handle 'expr IN (subquery)', subquery returned 10000+ rows.");
537  }
538  auto scalar_tv = boost::get<ScalarTargetValue>(&row[0]);
539  Datum d{0};
540  bool is_null_const{false};
541  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
542  if (ti.is_string() && ti.get_compression() != kENCODING_NONE) {
543  auto ti_none_encoded = ti;
544  ti_none_encoded.set_compression(kENCODING_NONE);
545  auto none_encoded_string = makeExpr<Analyzer::Constant>(ti, is_null_const, d);
546  auto dict_encoded_string =
547  std::make_shared<Analyzer::UOper>(ti, false, kCAST, none_encoded_string);
548  value_exprs.push_back(dict_encoded_string);
549  } else {
550  value_exprs.push_back(makeExpr<Analyzer::Constant>(ti, is_null_const, d));
551  }
552  }
553  return makeExpr<Analyzer::InValues>(lhs, value_exprs);
554 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
void d(const SQLTypes expected_type, const std::string &str)
Definition: ImportTest.cpp:268
bool g_enable_watchdog
Definition: Execute.cpp:69
std::shared_ptr< Analyzer::Expr > getInIntegerSetExpr(std::shared_ptr< Analyzer::Expr > arg, const ResultSet &val_set) const
Definition: sqldefs.h:49
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) 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:187
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:

◆ translateInput()

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateInput ( const RexInput rex_input) const
private

Definition at line 319 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, CHECK_GE, CHECK_LE, CHECK_LT, RexAbstractInput::getIndex(), RelAlgNode::getOutputMetainfo(), RexInput::getSourceNode(), kTEXT, and LEFT.

Referenced by translateGeoFunctionArg().

320  {
321  const auto source = rex_input->getSourceNode();
322  const auto it_rte_idx = input_to_nest_level_.find(source);
323  CHECK(it_rte_idx != input_to_nest_level_.end());
324  const int rte_idx = it_rte_idx->second;
325  const auto scan_source = dynamic_cast<const RelScan*>(source);
326  const auto& in_metainfo = source->getOutputMetainfo();
327  if (scan_source) {
328  // We're at leaf (scan) level and not supposed to have input metadata,
329  // the name and type information come directly from the catalog.
330  CHECK(in_metainfo.empty());
331  const auto table_desc = scan_source->getTableDescriptor();
332  const auto cd =
333  cat_.getMetadataForColumnBySpi(table_desc->tableId, rex_input->getIndex() + 1);
334  CHECK(cd);
335  auto col_ti = cd->columnType;
336  if (col_ti.is_string()) {
337  col_ti.set_type(kTEXT);
338  }
339  if (cd->isVirtualCol) {
340  // TODO(alex): remove at some point, we only need this fixup for backwards
341  // compatibility with old imported data
342  CHECK_EQ("rowid", cd->columnName);
343  col_ti.set_size(8);
344  }
345  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
346  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
347  col_ti.set_notnull(false);
348  }
349  return std::make_shared<Analyzer::ColumnVar>(
350  col_ti, table_desc->tableId, cd->columnId, rte_idx);
351  }
352  CHECK(!in_metainfo.empty());
353  CHECK_GE(rte_idx, 0);
354  const size_t col_id = rex_input->getIndex();
355  CHECK_LT(col_id, in_metainfo.size());
356  auto col_ti = in_metainfo[col_id].get_type_info();
357  CHECK_LE(static_cast<size_t>(rte_idx), join_types_.size());
358  if (rte_idx > 0 && join_types_[rte_idx - 1] == JoinType::LEFT) {
359  col_ti.set_notnull(false);
360  }
361  return std::make_shared<Analyzer::ColumnVar>(col_ti, -source->getId(), col_id, rte_idx);
362 }
const std::vector< JoinType > join_types_
#define CHECK_EQ(x, y)
Definition: Logger.h:195
#define CHECK_GE(x, y)
Definition: Logger.h:200
const RelAlgNode * getSourceNode() const
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
#define CHECK_LT(x, y)
Definition: Logger.h:197
Definition: sqltypes.h:54
const std::vector< TargetMetaInfo > & getOutputMetainfo() const
#define CHECK_LE(x, y)
Definition: Logger.h:198
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
Definition: Catalog.cpp:1435
#define CHECK(condition)
Definition: Logger.h:187
const Catalog_Namespace::Catalog & cat_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ translateItem()

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

Definition at line 1198 of file RelAlgTranslator.cpp.

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

1199  {
1200  CHECK_EQ(size_t(2), rex_function->size());
1201  const auto base = translateScalarRex(rex_function->getOperand(0));
1202  const auto index = translateScalarRex(rex_function->getOperand(1));
1203  return makeExpr<Analyzer::BinOper>(
1204  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
1205 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:69
+ Here is the call graph for this function:

◆ translateKeyForString()

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

Definition at line 1158 of file RelAlgTranslator.cpp.

References run-benchmark-import::args, CHECK_EQ, and RexFunctionOperator::getName().

1159  {
1160  const auto& args = translateFunctionArgs(rex_function);
1161  CHECK_EQ(size_t(1), args.size());
1162  const auto expr = dynamic_cast<Analyzer::Expr*>(args[0].get());
1163  if (nullptr == expr || !expr->get_type_info().is_string() ||
1164  expr->get_type_info().is_varlen()) {
1165  throw std::runtime_error(rex_function->getName() +
1166  " expects a dictionary encoded text column.");
1167  }
1168  return makeExpr<Analyzer::KeyForStringExpr>(args[0]);
1169 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
Analyzer::ExpressionPtrVector translateFunctionArgs(const RexFunctionOperator *) const
const std::string & getName() const
+ Here is the call graph for this function:

◆ translateLength()

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

Definition at line 1150 of file RelAlgTranslator.cpp.

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

1151  {
1152  CHECK_EQ(size_t(1), rex_function->size());
1153  const auto str_arg = translateScalarRex(rex_function->getOperand(0));
1154  return makeExpr<Analyzer::CharLengthExpr>(
1155  str_arg->decompress(), rex_function->getName() == std::string("CHAR_LENGTH"));
1156 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
const std::string & getName() const
+ Here is the call graph for this function:

◆ translateLike()

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

Definition at line 876 of file RelAlgTranslator.cpp.

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

877  {
878  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
879  const auto arg = translateScalarRex(rex_function->getOperand(0));
880  const auto like = translateScalarRex(rex_function->getOperand(1));
881  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(like)) {
882  throw std::runtime_error("The matching pattern must be a literal.");
883  }
884  const auto escape = (rex_function->size() == 3)
885  ? translateScalarRex(rex_function->getOperand(2))
886  : nullptr;
887  const bool is_ilike = rex_function->getName() == std::string("PG_ILIKE");
888  return Parser::LikeExpr::get(arg, like, escape, is_ilike, false);
889 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) 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:526
#define CHECK(condition)
Definition: Logger.h:187
const std::string & getName() const
+ Here is the call graph for this function:

◆ translateLikely()

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

Definition at line 905 of file RelAlgTranslator.cpp.

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

906  {
907  CHECK(rex_function->size() == 1);
908  const auto arg = translateScalarRex(rex_function->getOperand(0));
909  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.9375);
910 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:187
+ Here is the call graph for this function:

◆ translateLiteral()

std::shared_ptr< Analyzer::Expr > RelAlgTranslator::translateLiteral ( const RexLiteral rex_literal)
staticprivate

Definition at line 226 of file RelAlgTranslator.cpp.

References Parser::StringLiteral::analyzeValue(), Parser::IntLiteral::analyzeValue(), Parser::FixedPtLiteral::analyzeValue(), Datum::bigintval, Datum::boolval, anonymous_namespace{RelAlgTranslator.cpp}::build_type_info(), anonymous_namespace{ImportTest.cpp}::d(), Datum::doubleval, logger::FATAL, kBOOLEAN, kDATE, kDECIMAL, kDOUBLE, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kNULLT, kTEXT, kTIME, kTIMESTAMP, LOG, and make_fp_constant().

Referenced by translateGeoFunctionArg(), and translateGeoLiteral().

227  {
228  const auto lit_ti = build_type_info(
229  rex_literal->getType(), rex_literal->getScale(), rex_literal->getPrecision());
230  const auto target_ti = build_type_info(rex_literal->getTargetType(),
231  rex_literal->getTypeScale(),
232  rex_literal->getTypePrecision());
233  switch (rex_literal->getType()) {
234  case kDECIMAL: {
235  const auto val = rex_literal->getVal<int64_t>();
236  const int precision = rex_literal->getPrecision();
237  const int scale = rex_literal->getScale();
238  if (target_ti.is_fp() && !scale) {
239  return make_fp_constant(val, target_ti);
240  }
241  auto lit_expr = scale ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
242  : Parser::IntLiteral::analyzeValue(val);
243  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
244  }
245  case kTEXT: {
246  return Parser::StringLiteral::analyzeValue(rex_literal->getVal<std::string>());
247  }
248  case kBOOLEAN: {
249  Datum d;
250  d.boolval = rex_literal->getVal<bool>();
251  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
252  }
253  case kDOUBLE: {
254  Datum d;
255  d.doubleval = rex_literal->getVal<double>();
256  auto lit_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
257  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
258  }
259  case kINTERVAL_DAY_TIME:
260  case kINTERVAL_YEAR_MONTH: {
261  Datum d;
262  d.bigintval = rex_literal->getVal<int64_t>();
263  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
264  }
265  case kTIME:
266  case kTIMESTAMP: {
267  Datum d;
268  d.bigintval =
269  rex_literal->getType() == kTIMESTAMP && rex_literal->getPrecision() > 0
270  ? rex_literal->getVal<int64_t>()
271  : rex_literal->getVal<int64_t>() / 1000;
272  return makeExpr<Analyzer::Constant>(
273  SQLTypeInfo(rex_literal->getType(), rex_literal->getPrecision(), 0, false),
274  false,
275  d);
276  }
277  case kDATE: {
278  Datum d;
279  d.bigintval = rex_literal->getVal<int64_t>() * 24 * 3600;
280  return makeExpr<Analyzer::Constant>(rex_literal->getType(), false, d);
281  }
282  case kNULLT: {
283  return makeExpr<Analyzer::Constant>(rex_literal->getTargetType(), true, Datum{0});
284  }
285  default: {
286  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
287  }
288  }
289  return nullptr;
290 }
void d(const SQLTypes expected_type, const std::string &str)
Definition: ImportTest.cpp:268
Definition: sqltypes.h:51
#define LOG(tag)
Definition: Logger.h:182
bool boolval
Definition: sqltypes.h:122
int64_t bigintval
Definition: sqltypes.h:126
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:93
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqltypes.h:54
Definition: sqltypes.h:55
Definition: Catalog.h:60
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t numericval, const int scale, const int precision)
Definition: ParserNode.cpp:133
std::shared_ptr< Analyzer::Constant > make_fp_constant(const int64_t val, const SQLTypeInfo &ti)
double doubleval
Definition: sqltypes.h:128
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ translateNow()

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

Definition at line 1207 of file RelAlgTranslator.cpp.

References Parser::TimestampLiteral::get().

1207  {
1209 }
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:169
+ Here is the call graph for this function:

◆ translateOffsetInFragment()

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

Definition at line 1265 of file RelAlgTranslator.cpp.

1265  {
1266  return makeExpr<Analyzer::OffsetInFragment>();
1267 }

◆ translateOper()

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

Definition at line 806 of file RelAlgTranslator.cpp.

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

807  {
808  CHECK_GT(rex_operator->size(), size_t(0));
809  if (rex_operator->size() == 1) {
810  return translateUoper(rex_operator);
811  }
812  const auto sql_op = rex_operator->getOperator();
813  if (sql_op == kIN) {
814  return translateInOper(rex_operator);
815  }
816  if (sql_op == kMINUS || sql_op == kPLUS) {
817  auto date_plus_minus = translateDatePlusMinus(rex_operator);
818  if (date_plus_minus) {
819  return date_plus_minus;
820  }
821  }
822  if (sql_op == kOVERLAPS) {
823  return translateOverlapsOper(rex_operator);
824  } else if (IS_COMPARISON(sql_op)) {
825  auto geo_comp = translateGeoComparison(rex_operator);
826  if (geo_comp) {
827  return geo_comp;
828  }
829  }
830  auto lhs = translateScalarRex(rex_operator->getOperand(0));
831  for (size_t i = 1; i < rex_operator->size(); ++i) {
832  std::shared_ptr<Analyzer::Expr> rhs;
833  SQLQualifier sql_qual{kONE};
834  const auto rhs_op = rex_operator->getOperand(i);
835  std::tie(rhs, sql_qual) = get_quantified_rhs(rhs_op, *this);
836  if (!rhs) {
837  rhs = translateScalarRex(rhs_op);
838  }
839  CHECK(rhs);
840  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs);
841  }
842  return lhs;
843 }
std::shared_ptr< Analyzer::Expr > translateGeoComparison(const RexOperator *) const
SQLOps getOperator() const
SQLQualifier
Definition: sqldefs.h:69
Definition: sqldefs.h:41
#define CHECK_GT(x, y)
Definition: Logger.h:199
std::shared_ptr< Analyzer::Expr > translateOverlapsOper(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateDatePlusMinus(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateUoper(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) 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:257
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
Definition: sqldefs.h:53
std::shared_ptr< Analyzer::Expr > translateInOper(const RexOperator *) const
#define CHECK(condition)
Definition: Logger.h:187
#define IS_COMPARISON(X)
Definition: sqldefs.h:57
+ Here is the call graph for this function:

◆ translateOverlapsOper()

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

Definition at line 845 of file RelAlgTranslator.cpp.

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

846  {
847  const auto sql_op = rex_operator->getOperator();
848  CHECK(sql_op == kOVERLAPS);
849 
850  const auto lhs = translateScalarRex(rex_operator->getOperand(0));
851  const auto lhs_ti = lhs->get_type_info();
852  if (lhs_ti.is_geometry()) {
853  return translateGeoOverlapsOper(rex_operator);
854  } else {
855  throw std::runtime_error(
856  "Overlaps equivalence is currently only supported for geospatial types");
857  }
858 }
SQLOps getOperator() const
std::shared_ptr< Analyzer::Expr > translateGeoOverlapsOper(const RexOperator *) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:187
+ Here is the call graph for this function:

◆ translateRegexp()

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

Definition at line 891 of file RelAlgTranslator.cpp.

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

892  {
893  CHECK(rex_function->size() == 2 || rex_function->size() == 3);
894  const auto arg = translateScalarRex(rex_function->getOperand(0));
895  const auto pattern = translateScalarRex(rex_function->getOperand(1));
896  if (!std::dynamic_pointer_cast<const Analyzer::Constant>(pattern)) {
897  throw std::runtime_error("The matching pattern must be a literal.");
898  }
899  const auto escape = (rex_function->size() == 3)
900  ? translateScalarRex(rex_function->getOperand(2))
901  : nullptr;
902  return Parser::RegexpExpr::get(arg, pattern, escape, false);
903 }
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:621
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:187
+ Here is the call graph for this function:

◆ translateScalarRex()

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

Definition at line 164 of file RelAlgTranslator.cpp.

References CHECK.

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(), anonymous_namespace{RelAlgExecutor.cpp}::translate_targets_for_update(), translateFunctionWithGeoArg(), translateGeoComparison(), translateGeoFunctionArg(), and translateTernaryGeoFunction().

165  {
166  const auto rex_input = dynamic_cast<const RexInput*>(rex);
167  if (rex_input) {
168  return translateInput(rex_input);
169  }
170  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex);
171  if (rex_literal) {
172  return translateLiteral(rex_literal);
173  }
174  const auto rex_window_function = dynamic_cast<const RexWindowFunctionOperator*>(rex);
175  if (rex_window_function) {
176  return translateWindowFunction(rex_window_function);
177  }
178  const auto rex_function = dynamic_cast<const RexFunctionOperator*>(rex);
179  if (rex_function) {
180  return translateFunction(rex_function);
181  }
182  const auto rex_operator = dynamic_cast<const RexOperator*>(rex);
183  if (rex_operator) {
184  return translateOper(rex_operator);
185  }
186  const auto rex_case = dynamic_cast<const RexCase*>(rex);
187  if (rex_case) {
188  return translateCase(rex_case);
189  }
190  const auto rex_subquery = dynamic_cast<const RexSubQuery*>(rex);
191  if (rex_subquery) {
192  return translateScalarSubquery(rex_subquery);
193  }
194  CHECK(false);
195  return nullptr;
196 }
std::shared_ptr< Analyzer::Expr > translateWindowFunction(const RexWindowFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateOper(const RexOperator *) const
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
std::shared_ptr< Analyzer::Expr > translateScalarSubquery(const RexSubQuery *) const
std::shared_ptr< Analyzer::Expr > translateFunction(const RexFunctionOperator *) const
#define CHECK(condition)
Definition: Logger.h:187
std::shared_ptr< Analyzer::Expr > translateCase(const RexCase *) const
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
+ Here is the caller graph for this function:

◆ translateScalarSubquery()

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

Definition at line 292 of file RelAlgTranslator.cpp.

References CHECK, CHECK_EQ, anonymous_namespace{ImportTest.cpp}::d(), anonymous_namespace{RelAlgTranslator.cpp}::datum_from_scalar_tv(), and run-benchmark-import::result.

293  {
294  if (just_explain_) {
295  throw std::runtime_error("EXPLAIN is not supported with sub-queries");
296  }
297  CHECK(rex_subquery);
298  auto result = rex_subquery->getExecutionResult();
299  auto row_set = result->getRows();
300  if (row_set->rowCount() > size_t(1)) {
301  throw std::runtime_error("Scalar sub-query returned multiple rows");
302  }
303  if (row_set->rowCount() < size_t(1)) {
304  CHECK_EQ(row_set->rowCount(), size_t(0));
305  throw std::runtime_error("Scalar sub-query returned no results");
306  }
307  auto first_row = row_set->getNextRow(false, false);
308  auto scalar_tv = boost::get<ScalarTargetValue>(&first_row[0]);
309  auto ti = rex_subquery->getType();
310  if (ti.is_string()) {
311  throw std::runtime_error("Scalar sub-queries which return strings not supported");
312  }
313  Datum d{0};
314  bool is_null_const{false};
315  std::tie(d, is_null_const) = datum_from_scalar_tv(scalar_tv, ti);
316  return makeExpr<Analyzer::Constant>(ti, is_null_const, d);
317 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
void d(const SQLTypes expected_type, const std::string &str)
Definition: ImportTest.cpp:268
#define CHECK(condition)
Definition: Logger.h:187
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:

◆ translateSign()

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

Definition at line 1243 of file RelAlgTranslator.cpp.

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

1244  {
1245  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1246  expr_list;
1247  CHECK_EQ(size_t(1), rex_function->size());
1248  const auto operand = translateScalarRex(rex_function->getOperand(0));
1249  const auto& operand_ti = operand->get_type_info();
1250  CHECK(operand_ti.is_number());
1251  const auto zero = makeNumericConstant(operand_ti, 0);
1252  const auto lt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kLT, kONE, operand, zero);
1253  expr_list.emplace_back(lt_zero, makeNumericConstant(operand_ti, -1));
1254  const auto eq_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, operand, zero);
1255  expr_list.emplace_back(eq_zero, makeNumericConstant(operand_ti, 0));
1256  const auto gt_zero = makeExpr<Analyzer::BinOper>(kBOOLEAN, kGT, kONE, operand, zero);
1257  expr_list.emplace_back(gt_zero, makeNumericConstant(operand_ti, 1));
1258  return makeExpr<Analyzer::CaseExpr>(
1259  operand_ti,
1260  false,
1261  expr_list,
1262  makeExpr<Analyzer::Constant>(operand_ti, true, Datum{0}));
1263 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
Definition: sqldefs.h:30
std::shared_ptr< Analyzer::Constant > makeNumericConstant(const SQLTypeInfo &ti, const long val)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
Definition: sqldefs.h:34
Definition: sqldefs.h:69
#define CHECK(condition)
Definition: Logger.h:187
Definition: sqldefs.h:33
+ Here is the call graph for this function:

◆ translateTernaryGeoFunction()

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

Definition at line 873 of file RelAlgTranslatorGeo.cpp.

References CHECK_EQ, fold_expr(), RexFunctionOperator::getName(), RexOperator::getOperand(), kBOOLEAN, kDOUBLE, kLE, kMULTIPLY, kONE, RexOperator::size(), translateBinaryGeoFunction(), and translateScalarRex().

874  {
875  CHECK_EQ(size_t(3), rex_function->size());
876 
877  auto distance_expr = translateScalarRex(rex_function->getOperand(2));
878  const auto& distance_ti = SQLTypeInfo(kDOUBLE, false);
879  if (distance_expr->get_type_info().get_type() != kDOUBLE) {
880  distance_expr->add_cast(distance_ti);
881  }
882 
883  // Translate the geo distance function call portion
884  const auto geo_distance_expr = translateBinaryGeoFunction(rex_function);
885 
886  if (rex_function->getName() == std::string("ST_DWithin")) {
887  auto func_oper = dynamic_cast<Analyzer::FunctionOper*>(geo_distance_expr.get());
888  if (func_oper &&
889  func_oper->getName() == std::string("ST_Distance_Point_Point_Squared")) {
890  // Point_Point combination will yield geo_distance squared which is faster,
891  // need to compare it with distance squared
892  distance_expr = makeExpr<Analyzer::BinOper>(distance_ti,
893  distance_expr->get_contains_agg(),
894  kMULTIPLY,
895  kONE,
896  distance_expr,
897  distance_expr);
898  distance_expr = fold_expr(distance_expr.get());
899  }
900  }
901 
902  return makeExpr<Analyzer::BinOper>(
903  kBOOLEAN, kLE, kONE, geo_distance_expr, distance_expr);
904 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
Definition: sqldefs.h:35
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqldefs.h:69
const std::string & getName() const
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
+ Here is the call graph for this function:

◆ translateUnaryGeoFunction()

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

Definition at line 541 of file RelAlgTranslatorGeo.cpp.

References CHECK_EQ, SQLTypeInfoCore< TYPE_FACET_PACK >::get_comp_param(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_compression(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_input_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_output_srid(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_subtype(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_type(), RexFunctionOperator::getName(), RexOperator::getOperand(), RexOperator::getType(), Datum::intval, IS_GEO_POLY, kENCODING_GEOINT, kGEOGRAPHY, kINT, kLINESTRING, kMULTIPOLYGON, kPOINT, kPOLYGON, RexOperator::size(), anonymous_namespace{RelAlgTranslatorGeo.cpp}::suffix(), and translateGeoFunctionArg().

542  {
543  CHECK_EQ(size_t(1), rex_function->size());
544 
545  int32_t lindex = 0;
546  std::string specialized_geofunc{rex_function->getName()};
547 
548  // Geo function calls which do not need the coords col but do need cols associated with
549  // physical coords (e.g. ring_sizes / poly_rings)
550  if (rex_function->getName() == std::string("ST_NRings")) {
551  SQLTypeInfo arg_ti;
552  auto geoargs = translateGeoFunctionArg(
553  rex_function->getOperand(0), arg_ti, lindex, false, false, true);
554  if (arg_ti.get_type() == kPOLYGON) {
555  CHECK_EQ(geoargs.size(), 2u);
556  geoargs.erase(geoargs.begin(), geoargs.begin() + 1); // remove the coords
557  return makeExpr<Analyzer::FunctionOper>(
558  rex_function->getType(), specialized_geofunc, geoargs);
559  } else if (arg_ti.get_type() == kMULTIPOLYGON) {
560  CHECK_EQ(geoargs.size(), 3u);
561  geoargs.erase(geoargs.begin(), geoargs.begin() + 1); // remove the coords
562  geoargs.erase(geoargs.begin() + 1, geoargs.end()); // remove the poly_rings
563  return makeExpr<Analyzer::FunctionOper>(
564  rex_function->getType(), specialized_geofunc, geoargs);
565  } else {
566  throw QueryNotSupported(rex_function->getName() +
567  " expects a POLYGON or MULTIPOLYGON");
568  }
569  } else if (rex_function->getName() == std::string("ST_NPoints")) {
570  SQLTypeInfo arg_ti;
571  auto geoargs = translateGeoFunctionArg(
572  rex_function->getOperand(0), arg_ti, lindex, false, false, true);
573  geoargs.erase(geoargs.begin() + 1, geoargs.end()); // remove all but coords
574  // Add compression information
575  Datum input_compression;
576  input_compression.intval =
577  (arg_ti.get_compression() == kENCODING_GEOINT && arg_ti.get_comp_param() == 32)
578  ? 1
579  : 0;
580  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
581  return makeExpr<Analyzer::FunctionOper>(
582  rex_function->getType(), specialized_geofunc, geoargs);
583  } else if (rex_function->getName() == std::string("ST_Perimeter") ||
584  rex_function->getName() == std::string("ST_Area")) {
585  SQLTypeInfo arg_ti;
586  auto geoargs = translateGeoFunctionArg(
587  rex_function->getOperand(0), arg_ti, lindex, false, false, true);
588  if (arg_ti.get_type() != kPOLYGON && arg_ti.get_type() != kMULTIPOLYGON) {
589  throw QueryNotSupported(rex_function->getName() +
590  " expects a POLYGON or MULTIPOLYGON");
591  }
592  specialized_geofunc += suffix(arg_ti.get_type());
593  if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
594  specialized_geofunc += std::string("_Geodesic");
595  }
596  // Add compression information
597  Datum input_compression;
598  input_compression.intval =
599  (arg_ti.get_compression() == kENCODING_GEOINT && arg_ti.get_comp_param() == 32)
600  ? 1
601  : 0;
602  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
603  Datum input_srid;
604  input_srid.intval = arg_ti.get_input_srid();
605  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
606  Datum output_srid;
607  output_srid.intval = arg_ti.get_output_srid();
608  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
609  return makeExpr<Analyzer::FunctionOper>(
610  rex_function->getType(), specialized_geofunc, geoargs);
611  }
612 
613  // Accessors for poly bounds and render group for in-situ poly render queries
614  if (rex_function->getName() == std::string("MapD_GeoPolyBoundsPtr") || // deprecated
615  rex_function->getName() == std::string("OmniSci_Geo_PolyBoundsPtr")) {
616  SQLTypeInfo arg_ti;
617  // get geo column plus bounds only (not expanded)
618  auto geoargs = translateGeoFunctionArg(
619  rex_function->getOperand(0), arg_ti, lindex, true, false, false);
620  // this function only works on polys
621  if (!IS_GEO_POLY(arg_ti.get_type())) {
622  throw QueryNotSupported(rex_function->getName() +
623  " expects a POLYGON or MULTIPOLYGON");
624  }
625  // only need the bounds argument (last), discard the rest
626  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
627  // done
628  return makeExpr<Analyzer::FunctionOper>(
629  rex_function->getType(), specialized_geofunc, geoargs);
630  } else if (rex_function->getName() ==
631  std::string("MapD_GeoPolyRenderGroup") || // deprecated
632  rex_function->getName() == std::string("OmniSci_Geo_PolyRenderGroup")) {
633  SQLTypeInfo arg_ti;
634  // get geo column plus render_group only (not expanded)
635  auto geoargs = translateGeoFunctionArg(
636  rex_function->getOperand(0), arg_ti, lindex, false, true, false);
637  // this function only works on polys
638  if (!IS_GEO_POLY(arg_ti.get_type())) {
639  throw QueryNotSupported(rex_function->getName() +
640  " expects a POLYGON or MULTIPOLYGON");
641  }
642  // only need the render_group argument (last), discard the rest
643  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
644  // done
645  return makeExpr<Analyzer::FunctionOper>(
646  rex_function->getType(), specialized_geofunc, geoargs);
647  }
648 
649  // All functions below use geo col as reference and expand it as necessary
650  SQLTypeInfo arg_ti;
651  bool with_bounds = true;
652  auto geoargs = translateGeoFunctionArg(
653  rex_function->getOperand(0), arg_ti, lindex, with_bounds, false, false);
654 
655  if (rex_function->getName() == std::string("ST_SRID")) {
656  Datum output_srid;
657  output_srid.intval = arg_ti.get_output_srid();
658  return makeExpr<Analyzer::Constant>(kINT, false, output_srid);
659  }
660 
661  if (rex_function->getName() == std::string("ST_XMin") ||
662  rex_function->getName() == std::string("ST_YMin") ||
663  rex_function->getName() == std::string("ST_XMax") ||
664  rex_function->getName() == std::string("ST_YMax")) {
665  // If type has bounds - use them, otherwise look at coords
666  if (arg_ti.has_bounds()) {
667  if (lindex != 0) {
668  throw QueryNotSupported(rex_function->getName() +
669  " doesn't support indexed LINESTRINGs");
670  }
671  // Only need the bounds argument, discard the rest
672  geoargs.erase(geoargs.begin(), geoargs.end() - 1);
673 
674  // Supply srids too - transformed geo would have a transformed bounding box
675  Datum input_srid;
676  input_srid.intval = arg_ti.get_input_srid();
677  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
678  Datum output_srid;
679  output_srid.intval = arg_ti.get_output_srid();
680  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
681 
682  specialized_geofunc += std::string("_Bounds");
683  return makeExpr<Analyzer::FunctionOper>(
684  rex_function->getType(), specialized_geofunc, geoargs);
685  }
686  }
687 
688  // All geo function calls translated below only need the coords, extras e.g. ring_sizes
689  // are dropped. Specialize for other/new functions if needed.
690  geoargs.erase(geoargs.begin() + 1, geoargs.end());
691 
692  if (rex_function->getName() == std::string("ST_X") ||
693  rex_function->getName() == std::string("ST_Y")) {
694  if (arg_ti.get_type() == kLINESTRING) {
695  if (lindex == 0) {
696  throw QueryNotSupported(
697  rex_function->getName() +
698  " expects a POINT, use LINESTRING accessor, e.g. ST_POINTN");
699  }
700  Datum index;
701  index.intval = lindex;
702  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, index));
703  } else if (arg_ti.get_type() != kPOINT) {
704  throw QueryNotSupported(rex_function->getName() + " expects a POINT");
705  }
706  specialized_geofunc += suffix(arg_ti.get_type());
707  } else if (rex_function->getName() == std::string("ST_Length")) {
708  if (arg_ti.get_type() != kLINESTRING || lindex != 0) {
709  throw QueryNotSupported(rex_function->getName() + " expects unindexed LINESTRING");
710  }
711  specialized_geofunc += suffix(arg_ti.get_type());
712  if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
713  specialized_geofunc += std::string("_Geodesic");
714  }
715  }
716 
717  // Add input compression mode and SRID args to enable on-the-fly
718  // decompression/transforms
719  Datum input_compression;
720  input_compression.intval =
721  (arg_ti.get_compression() == kENCODING_GEOINT && arg_ti.get_comp_param() == 32) ? 1
722  : 0;
723  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
724  Datum input_srid;
725  input_srid.intval = arg_ti.get_input_srid();
726  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
727 
728  // Add output SRID arg to enable on-the-fly transforms
729  Datum output_srid;
730  output_srid.intval = arg_ti.get_output_srid();
731  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
732 
733  return makeExpr<Analyzer::FunctionOper>(
734  rex_function->getType(), specialized_geofunc, geoargs);
735 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:319
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:327
int32_t intval
Definition: sqltypes.h:125
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:320
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:323
const RexScalar * getOperand(const size_t idx) const
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:325
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
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:328
const SQLTypeInfo & getType() const
Definition: sqltypes.h:47
const std::string & getName() const
#define IS_GEO_POLY(T)
Definition: sqltypes.h:169
+ Here is the call graph for this function:

◆ translateUnlikely()

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

Definition at line 912 of file RelAlgTranslator.cpp.

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

913  {
914  CHECK(rex_function->size() == 1);
915  const auto arg = translateScalarRex(rex_function->getOperand(0));
916  return makeExpr<Analyzer::LikelihoodExpr>(arg, 0.0625);
917 }
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
#define CHECK(condition)
Definition: Logger.h:187
+ Here is the call graph for this function:

◆ translateUoper()

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

Definition at line 364 of file RelAlgTranslator.cpp.

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

365  {
366  CHECK_EQ(size_t(1), rex_operator->size());
367  const auto operand_expr = translateScalarRex(rex_operator->getOperand(0));
368  const auto sql_op = rex_operator->getOperator();
369  switch (sql_op) {
370  case kCAST: {
371  const auto& target_ti = rex_operator->getType();
372  CHECK_NE(kNULLT, target_ti.get_type());
373  const auto& operand_ti = operand_expr->get_type_info();
374  if (operand_ti.is_string() && target_ti.is_string()) {
375  return operand_expr;
376  }
377  if (target_ti.is_time() ||
378  operand_ti
379  .is_string()) { // TODO(alex): check and unify with the rest of the cases
380  // Do not propogate encoding on small dates
381  return target_ti.is_date_in_days()
382  ? operand_expr->add_cast(SQLTypeInfo(kDATE, false))
383  : operand_expr->add_cast(target_ti);
384  }
385  if (!operand_ti.is_string() && target_ti.is_string()) {
386  return operand_expr->add_cast(target_ti);
387  }
388 
389  return std::make_shared<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
390  }
391  case kNOT:
392  case kISNULL: {
393  return std::make_shared<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
394  }
395  case kISNOTNULL: {
396  auto is_null = std::make_shared<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
397  return std::make_shared<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
398  }
399  case kMINUS: {
400  const auto& ti = operand_expr->get_type_info();
401  return std::make_shared<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
402  }
403  case kUNNEST: {
404  const auto& ti = operand_expr->get_type_info();
405  CHECK(ti.is_array());
406  return makeExpr<Analyzer::UOper>(ti.get_elem_type(), false, kUNNEST, operand_expr);
407  }
408  default:
409  CHECK(false);
410  }
411  return nullptr;
412 }
SQLOps getOperator() const
#define CHECK_EQ(x, y)
Definition: Logger.h:195
Definition: sqldefs.h:49
#define CHECK_NE(x, y)
Definition: Logger.h:196
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const RexScalar * getOperand(const size_t idx) const
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:819
Definition: sqltypes.h:55
Definition: sqldefs.h:40
bool is_null(const T &v, const SQLTypeInfo &t)
#define CHECK(condition)
Definition: Logger.h:187
const SQLTypeInfo & getType() const
Definition: sqldefs.h:39
+ Here is the call graph for this function:

◆ translateWindowFunction()

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

Definition at line 1569 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(), 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(), and window_function_is_value().

1570  {
1571  if (!supported_lower_bound(rex_window_function->getLowerBound()) ||
1572  !supported_upper_bound(rex_window_function) ||
1573  ((rex_window_function->getKind() == SqlWindowFunctionKind::ROW_NUMBER) !=
1574  rex_window_function->isRows())) {
1575  throw std::runtime_error("Frame specification not supported");
1576  }
1577  std::vector<std::shared_ptr<Analyzer::Expr>> args;
1578  for (size_t i = 0; i < rex_window_function->size(); ++i) {
1579  args.push_back(translateScalarRex(rex_window_function->getOperand(i)));
1580  }
1581  std::vector<std::shared_ptr<Analyzer::Expr>> partition_keys;
1582  for (const auto& partition_key : rex_window_function->getPartitionKeys()) {
1583  partition_keys.push_back(translateScalarRex(partition_key.get()));
1584  }
1585  std::vector<std::shared_ptr<Analyzer::Expr>> order_keys;
1586  for (const auto& order_key : rex_window_function->getOrderKeys()) {
1587  order_keys.push_back(translateScalarRex(order_key.get()));
1588  }
1589  auto ti = rex_window_function->getType();
1590  if (window_function_is_value(rex_window_function->getKind())) {
1591  CHECK_GE(args.size(), 1u);
1592  ti = args.front()->get_type_info();
1593  }
1594  return makeExpr<Analyzer::WindowFunction>(
1595  ti,
1596  rex_window_function->getKind(),
1597  args,
1598  partition_keys,
1599  order_keys,
1600  translate_collation(rex_window_function->getCollation()));
1601 }
const std::vector< SortField > & getCollation() const
const ConstRexScalarPtrVector & getPartitionKeys() const
SqlWindowFunctionKind getKind() const
bool supported_lower_bound(const RexWindowFunctionOperator::RexWindowBound &window_bound)
const RexWindowBound & getLowerBound() const
const ConstRexScalarPtrVector & getOrderKeys() const
#define CHECK_GE(x, y)
Definition: Logger.h:200
bool window_function_is_value(const SqlWindowFunctionKind kind)
Definition: WindowContext.h:27
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
std::vector< Analyzer::OrderEntry > translate_collation(const std::vector< SortField > &sort_fields)
const RexScalar * getOperand(const size_t idx) const
bool supported_upper_bound(const RexWindowFunctionOperator *rex_window_function)
const SQLTypeInfo & getType() const
+ Here is the call graph for this function:

Member Data Documentation

◆ cat_

const Catalog_Namespace::Catalog& RelAlgTranslator::cat_
private

Definition at line 167 of file RelAlgTranslator.h.

Referenced by translateGeoColumn().

◆ executor_

const Executor* RelAlgTranslator::executor_
private

Definition at line 168 of file RelAlgTranslator.h.

◆ feature_stash_

QueryFeatureDescriptor& RelAlgTranslator::feature_stash_
private

Definition at line 173 of file RelAlgTranslator.h.

◆ input_to_nest_level_

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

Definition at line 169 of file RelAlgTranslator.h.

Referenced by translateGeoColumn().

◆ join_types_

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

Definition at line 170 of file RelAlgTranslator.h.

◆ just_explain_

const bool RelAlgTranslator::just_explain_
private

Definition at line 172 of file RelAlgTranslator.h.

◆ now_

time_t RelAlgTranslator::now_
private

Definition at line 171 of file RelAlgTranslator.h.


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