OmniSciDB  2e3a973ef4
anonymous_namespace{RelAlgDagBuilder.cpp} Namespace Reference

Namespaces

 anonymous_namespace{RelAlgDagBuilder.cpp}
 

Classes

class  RANodeIterator
 
class  RexInputBackpropagationVisitor
 
class  RexInputCollector
 
class  RexRebindInputsVisitor
 
class  RexRebindReindexInputsVisitor
 
class  RexWindowFuncReplacementVisitor
 
class  WindowFunctionDetectionVisitor
 

Typedefs

using RexInputSet = std::unordered_set< RexInput >
 

Functions

std::vector< RexInputn_outputs (const RelAlgNode *node, const size_t n)
 
bool isRenamedInput (const RelAlgNode *node, const size_t index, const std::string &new_name)
 
std::vector< std::unique_ptr< const RexAgg > > copyAggExprs (std::vector< std::unique_ptr< const RexAgg >> const &agg_exprs)
 
std::vector< std::unique_ptr< const RexScalar > > copyRexScalars (std::vector< std::unique_ptr< const RexScalar >> const &scalar_sources)
 
std::vector< const Rex * > remapTargetPointers (std::vector< std::unique_ptr< const RexAgg >> const &agg_exprs_new, std::vector< std::unique_ptr< const RexScalar >> const &scalar_sources_new, std::vector< std::unique_ptr< const RexAgg >> const &agg_exprs_old, std::vector< std::unique_ptr< const RexScalar >> const &scalar_sources_old, std::vector< const Rex *> const &target_exprs_old)
 
std::set< std::pair< const RelAlgNode *, int > > get_equiv_cols (const RelAlgNode *node, const size_t which_col)
 
unsigned node_id (const rapidjson::Value &ra_node) noexcept
 
std::string json_node_to_string (const rapidjson::Value &node) noexcept
 
std::unique_ptr< RexAbstractInputparse_abstract_input (const rapidjson::Value &expr) noexcept
 
std::unique_ptr< RexLiteralparse_literal (const rapidjson::Value &expr)
 
std::unique_ptr< const RexScalarparse_scalar_expr (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
SQLTypeInfo parse_type (const rapidjson::Value &type_obj)
 
std::vector< std::unique_ptr< const RexScalar > > parse_expr_array (const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
SqlWindowFunctionKind parse_window_function_kind (const std::string &name)
 
std::vector< std::unique_ptr< const RexScalar > > parse_window_order_exprs (const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
SortDirection parse_sort_direction (const rapidjson::Value &collation)
 
NullSortedPosition parse_nulls_position (const rapidjson::Value &collation)
 
std::vector< SortFieldparse_window_order_collation (const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
RexWindowFunctionOperator::RexWindowBound parse_window_bound (const rapidjson::Value &window_bound_obj, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
std::unique_ptr< const RexSubQueryparse_subquery (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
std::unique_ptr< RexOperatorparse_operator (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
std::unique_ptr< RexCaseparse_case (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
 
std::vector< std::string > strings_from_json_array (const rapidjson::Value &json_str_arr) noexcept
 
std::vector< size_t > indices_from_json_array (const rapidjson::Value &json_idx_arr) noexcept
 
std::unique_ptr< const RexAggparse_aggregate_expr (const rapidjson::Value &expr)
 
JoinType to_join_type (const std::string &join_type_name)
 
std::unique_ptr< const RexScalardisambiguate_rex (const RexScalar *, const RANodeOutput &)
 
std::unique_ptr< const RexOperatordisambiguate_operator (const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
 
std::unique_ptr< const RexCasedisambiguate_case (const RexCase *rex_case, const RANodeOutput &ra_output)
 
void bind_project_to_input (RelProject *project_node, const RANodeOutput &input) noexcept
 
void bind_table_func_to_input (RelTableFunction *table_func_node, const RANodeOutput &input) noexcept
 
void bind_inputs (const std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
 
void handleQueryHint (const std::vector< std::shared_ptr< RelAlgNode >> &nodes, RelAlgDagBuilder *dag_builder) noexcept
 
void mark_nops (const std::vector< std::shared_ptr< RelAlgNode >> &nodes) noexcept
 
void create_compound (std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< size_t > &pattern) noexcept
 
void coalesce_nodes (std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< const RelAlgNode *> &left_deep_joins)
 
void separate_window_function_expressions (std::vector< std::shared_ptr< RelAlgNode >> &nodes)
 
void add_window_function_pre_project (std::vector< std::shared_ptr< RelAlgNode >> &nodes)
 
int64_t get_int_literal_field (const rapidjson::Value &obj, const char field[], const int64_t default_val) noexcept
 
void check_empty_inputs_field (const rapidjson::Value &node) noexcept
 
const TableDescriptorgetTableFromScanNode (const Catalog_Namespace::Catalog &cat, const rapidjson::Value &scan_ra)
 
std::vector< std::string > getFieldNamesFromScanNode (const rapidjson::Value &scan_ra)
 

Variables

const unsigned FIRST_RA_NODE_ID = 1
 

Typedef Documentation

◆ RexInputSet

using anonymous_namespace{RelAlgDagBuilder.cpp}::RexInputSet = typedef std::unordered_set<RexInput>

Definition at line 1995 of file RelAlgDagBuilder.cpp.

Function Documentation

◆ add_window_function_pre_project()

void anonymous_namespace{RelAlgDagBuilder.cpp}::add_window_function_pre_project ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes)

Inserts a simple project before any project containing a window function node. Forces all window function inputs into a single contiguous buffer for centralized processing (e.g. in distributed mode). Once the new project has been created, the inputs in the window function project must be rewritten to read from the new project, and to index off the projected exprs in the new project.

Definition at line 2019 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_EQ, and RexVisitorBase< T >::visit().

Referenced by RelAlgDagBuilder::build().

2019  {
2020  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2021 
2022  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2023  const auto node = *node_itr;
2024  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2025  if (!window_func_project_node) {
2026  continue;
2027  }
2028  if (!window_func_project_node->hasWindowFunctionExpr()) {
2029  // the first projection node in the query plan does not have a window function
2030  // expression -- this step is not requierd.
2031  return;
2032  }
2033 
2034  const auto prev_node_itr = std::prev(node_itr);
2035  const auto prev_node = *prev_node_itr;
2036  CHECK(prev_node);
2037 
2038  RexInputSet inputs;
2039  RexInputCollector input_collector;
2040  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2041  auto new_inputs = input_collector.visit(window_func_project_node->getProjectAt(i));
2042  inputs.insert(new_inputs.begin(), new_inputs.end());
2043  }
2044 
2045  // Note: Technically not required since we are mapping old inputs to new input
2046  // indices, but makes the re-mapping of inputs easier to follow.
2047  std::vector<RexInput> sorted_inputs(inputs.begin(), inputs.end());
2048  std::sort(sorted_inputs.begin(),
2049  sorted_inputs.end(),
2050  [](const auto& a, const auto& b) { return a.getIndex() < b.getIndex(); });
2051 
2052  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs;
2053  std::vector<std::string> fields;
2054  std::unordered_map<unsigned, unsigned> old_index_to_new_index;
2055  for (auto& input : sorted_inputs) {
2056  CHECK_EQ(input.getSourceNode(), prev_node.get());
2057  CHECK(old_index_to_new_index
2058  .insert(std::make_pair(input.getIndex(), scalar_exprs.size()))
2059  .second);
2060  scalar_exprs.emplace_back(input.deepCopy());
2061  fields.emplace_back("");
2062  }
2063 
2064  auto new_project = std::make_shared<RelProject>(scalar_exprs, fields, prev_node);
2065  node_list.insert(node_itr, new_project);
2066  window_func_project_node->replaceInput(
2067  prev_node, new_project, old_index_to_new_index);
2068 
2069  break;
2070  }
2071 
2072  nodes.assign(node_list.begin(), node_list.end());
2073 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
std::unordered_set< RexInput > RexInputSet
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bind_inputs()

void anonymous_namespace{RelAlgDagBuilder.cpp}::bind_inputs ( const std::vector< std::shared_ptr< RelAlgNode >> &  nodes)
noexcept

Definition at line 1157 of file RelAlgDagBuilder.cpp.

References bind_project_to_input(), bind_table_func_to_input(), CHECK_EQ, disambiguate_rex(), and get_node_output().

Referenced by RelAlgDagBuilder::build().

1157  {
1158  for (auto ra_node : nodes) {
1159  const auto filter_node = std::dynamic_pointer_cast<RelFilter>(ra_node);
1160  if (filter_node) {
1161  CHECK_EQ(size_t(1), filter_node->inputCount());
1162  auto disambiguated_condition = disambiguate_rex(
1163  filter_node->getCondition(), get_node_output(filter_node->getInput(0)));
1164  filter_node->setCondition(disambiguated_condition);
1165  continue;
1166  }
1167  const auto join_node = std::dynamic_pointer_cast<RelJoin>(ra_node);
1168  if (join_node) {
1169  CHECK_EQ(size_t(2), join_node->inputCount());
1170  auto disambiguated_condition =
1171  disambiguate_rex(join_node->getCondition(), get_node_output(join_node.get()));
1172  join_node->setCondition(disambiguated_condition);
1173  continue;
1174  }
1175  const auto project_node = std::dynamic_pointer_cast<RelProject>(ra_node);
1176  if (project_node) {
1177  bind_project_to_input(project_node.get(),
1178  get_node_output(project_node->getInput(0)));
1179  continue;
1180  }
1181  const auto table_func_node = std::dynamic_pointer_cast<RelTableFunction>(ra_node);
1182  if (table_func_node) {
1183  /*
1184  Collect all inputs from table function input (non-literal)
1185  arguments.
1186  */
1187  RANodeOutput input;
1188  input.reserve(table_func_node->inputCount());
1189  for (size_t i = 0; i < table_func_node->inputCount(); i++) {
1190  auto node_output = get_node_output(table_func_node->getInput(i));
1191  input.insert(input.end(), node_output.begin(), node_output.end());
1192  }
1193  bind_table_func_to_input(table_func_node.get(), input);
1194  }
1195  }
1196 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
void bind_table_func_to_input(RelTableFunction *table_func_node, const RANodeOutput &input) noexcept
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
RANodeOutput get_node_output(const RelAlgNode *ra_node)
std::vector< RexInput > RANodeOutput
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bind_project_to_input()

void anonymous_namespace{RelAlgDagBuilder.cpp}::bind_project_to_input ( RelProject project_node,
const RANodeOutput input 
)
noexcept

Definition at line 1129 of file RelAlgDagBuilder.cpp.

References CHECK_EQ, and disambiguate_rex().

Referenced by bind_inputs(), and create_compound().

1129  {
1130  CHECK_EQ(size_t(1), project_node->inputCount());
1131  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1132  for (size_t i = 0; i < project_node->size(); ++i) {
1133  const auto projected_expr = project_node->getProjectAt(i);
1134  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
1135  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
1136  } else {
1137  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
1138  }
1139  }
1140  project_node->setExpressions(disambiguated_exprs);
1141 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
size_t size() const override
const RexScalar * getProjectAt(const size_t idx) const
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
const RexScalar * getProjectAtAndRelease(const size_t idx) const
const size_t inputCount() const
void setExpressions(std::vector< std::unique_ptr< const RexScalar >> &exprs) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bind_table_func_to_input()

void anonymous_namespace{RelAlgDagBuilder.cpp}::bind_table_func_to_input ( RelTableFunction table_func_node,
const RANodeOutput input 
)
noexcept

Definition at line 1143 of file RelAlgDagBuilder.cpp.

References disambiguate_rex().

Referenced by bind_inputs().

1144  {
1145  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1146  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
1147  const auto target_expr = table_func_node->getTableFuncInputAt(i);
1148  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
1149  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
1150  } else {
1151  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
1152  }
1153  }
1154  table_func_node->setTableFuncInputs(disambiguated_exprs);
1155 }
const RexScalar * getTableFuncInputAt(const size_t idx) const
const RexScalar * getTableFuncInputAtAndRelease(const size_t idx)
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
void setTableFuncInputs(std::vector< std::unique_ptr< const RexScalar >> &exprs)
size_t getTableFuncInputsSize() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_empty_inputs_field()

void anonymous_namespace{RelAlgDagBuilder.cpp}::check_empty_inputs_field ( const rapidjson::Value &  node)
noexcept

Definition at line 2089 of file RelAlgDagBuilder.cpp.

References CHECK, and field().

Referenced by details::RelAlgDispatcher::dispatchTableScan().

2089  {
2090  const auto& inputs_json = field(node, "inputs");
2091  CHECK(inputs_json.IsArray() && !inputs_json.Size());
2092 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ coalesce_nodes()

void anonymous_namespace{RelAlgDagBuilder.cpp}::coalesce_nodes ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
const std::vector< const RelAlgNode *> &  left_deep_joins 
)

Definition at line 1600 of file RelAlgDagBuilder.cpp.

References anonymous_namespace{RelAlgDagBuilder.cpp}::RANodeIterator::allVisited(), CHECK, CHECK_GE, create_compound(), and anonymous_namespace{RelAlgDagBuilder.cpp}::anonymous_namespace{RelAlgDagBuilder.cpp}::input_can_be_coalesced().

Referenced by RelAlgDagBuilder::build().

1601  {
1602  enum class CoalesceState { Initial, Filter, FirstProject, Aggregate };
1603  std::vector<size_t> crt_pattern;
1604  CoalesceState crt_state{CoalesceState::Initial};
1605 
1606  auto reset_state = [&crt_pattern, &crt_state]() {
1607  crt_state = CoalesceState::Initial;
1608  decltype(crt_pattern)().swap(crt_pattern);
1609  };
1610 
1611  for (RANodeIterator nodeIt(nodes); !nodeIt.allVisited();) {
1612  const auto ra_node = nodeIt != nodes.end() ? *nodeIt : nullptr;
1613  switch (crt_state) {
1614  case CoalesceState::Initial: {
1615  if (std::dynamic_pointer_cast<const RelFilter>(ra_node) &&
1616  std::find(left_deep_joins.begin(), left_deep_joins.end(), ra_node.get()) ==
1617  left_deep_joins.end()) {
1618  crt_pattern.push_back(size_t(nodeIt));
1619  crt_state = CoalesceState::Filter;
1620  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1621  } else if (std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1622  crt_pattern.push_back(size_t(nodeIt));
1623  crt_state = CoalesceState::FirstProject;
1624  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1625  } else {
1626  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
1627  }
1628  break;
1629  }
1630  case CoalesceState::Filter: {
1631  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1632  if (project_node->hasWindowFunctionExpr()) {
1633  reset_state();
1634  break;
1635  }
1636  crt_pattern.push_back(size_t(nodeIt));
1637  crt_state = CoalesceState::FirstProject;
1638  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1639  } else {
1640  reset_state();
1641  }
1642  break;
1643  }
1644  case CoalesceState::FirstProject: {
1645  if (std::dynamic_pointer_cast<const RelAggregate>(ra_node)) {
1646  crt_pattern.push_back(size_t(nodeIt));
1647  crt_state = CoalesceState::Aggregate;
1648  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1649  } else {
1650  if (crt_pattern.size() >= 2) {
1651  create_compound(nodes, crt_pattern);
1652  }
1653  reset_state();
1654  }
1655  break;
1656  }
1657  case CoalesceState::Aggregate: {
1658  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1659  // TODO(adb): overloading the simple project terminology again here
1660  bool is_simple_project{true};
1661  for (size_t i = 0; i < project_node->size(); i++) {
1662  const auto scalar_rex = project_node->getProjectAt(i);
1663  // If the top level scalar rex is an input node, we can bypass the visitor
1664  if (auto input_rex = dynamic_cast<const RexInput*>(scalar_rex)) {
1666  input_rex->getSourceNode(), input_rex->getIndex(), true)) {
1667  is_simple_project = false;
1668  break;
1669  }
1670  continue;
1671  }
1672  CoalesceSecondaryProjectVisitor visitor;
1673  if (!visitor.visit(project_node->getProjectAt(i))) {
1674  is_simple_project = false;
1675  break;
1676  }
1677  }
1678  if (is_simple_project) {
1679  crt_pattern.push_back(size_t(nodeIt));
1680  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
1681  }
1682  }
1683  CHECK_GE(crt_pattern.size(), size_t(2));
1684  create_compound(nodes, crt_pattern);
1685  reset_state();
1686  break;
1687  }
1688  default:
1689  CHECK(false);
1690  }
1691  }
1692  if (crt_state == CoalesceState::FirstProject || crt_state == CoalesceState::Aggregate) {
1693  if (crt_pattern.size() >= 2) {
1694  create_compound(nodes, crt_pattern);
1695  }
1696  CHECK(!crt_pattern.empty());
1697  }
1698 }
#define CHECK_GE(x, y)
Definition: Logger.h:210
#define CHECK(condition)
Definition: Logger.h:197
void create_compound(std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< size_t > &pattern) noexcept
bool input_can_be_coalesced(const RelAlgNode *parent_node, const size_t index, const bool first_rex_is_input)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ copyAggExprs()

std::vector<std::unique_ptr<const RexAgg> > anonymous_namespace{RelAlgDagBuilder.cpp}::copyAggExprs ( std::vector< std::unique_ptr< const RexAgg >> const &  agg_exprs)

Definition at line 397 of file RelAlgDagBuilder.cpp.

398  {
399  std::vector<std::unique_ptr<const RexAgg>> agg_exprs_copy;
400  agg_exprs_copy.reserve(agg_exprs.size());
401  for (auto const& agg_expr : agg_exprs) {
402  agg_exprs_copy.push_back(agg_expr->deepCopy());
403  }
404  return agg_exprs_copy;
405 }

◆ copyRexScalars()

std::vector<std::unique_ptr<const RexScalar> > anonymous_namespace{RelAlgDagBuilder.cpp}::copyRexScalars ( std::vector< std::unique_ptr< const RexScalar >> const &  scalar_sources)

Definition at line 407 of file RelAlgDagBuilder.cpp.

References RexVisitorBase< T >::visit().

408  {
409  std::vector<std::unique_ptr<const RexScalar>> scalar_sources_copy;
410  scalar_sources_copy.reserve(scalar_sources.size());
411  RexDeepCopyVisitor copier;
412  for (auto const& scalar_source : scalar_sources) {
413  scalar_sources_copy.push_back(copier.visit(scalar_source.get()));
414  }
415  return scalar_sources_copy;
416 }
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
+ Here is the call graph for this function:

◆ create_compound()

void anonymous_namespace{RelAlgDagBuilder.cpp}::create_compound ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
const std::vector< size_t > &  pattern 
)
noexcept

Definition at line 1299 of file RelAlgDagBuilder.cpp.

References bind_project_to_input(), CHECK, CHECK_EQ, CHECK_GE, CHECK_LE, CHECK_LT, get_node_output(), RelProject::getFields(), anonymous_namespace{RelAlgExecutor.cpp}::is_agg(), anonymous_namespace{RelAlgDagBuilder.cpp}::anonymous_namespace{RelAlgDagBuilder.cpp}::reproject_targets(), and run_benchmark_import::result.

Referenced by coalesce_nodes().

1300  {
1301  CHECK_GE(pattern.size(), size_t(2));
1302  CHECK_LE(pattern.size(), size_t(4));
1303 
1304  std::unique_ptr<const RexScalar> filter_rex;
1305  std::vector<std::unique_ptr<const RexScalar>> scalar_sources;
1306  size_t groupby_count{0};
1307  std::vector<std::string> fields;
1308  std::vector<const RexAgg*> agg_exprs;
1309  std::vector<const Rex*> target_exprs;
1310  bool first_project{true};
1311  bool is_agg{false};
1312  RelAlgNode* last_node{nullptr};
1313 
1314  std::shared_ptr<ModifyManipulationTarget> manipulation_target;
1315 
1316  for (const auto node_idx : pattern) {
1317  const auto ra_node = nodes[node_idx];
1318  const auto ra_filter = std::dynamic_pointer_cast<RelFilter>(ra_node);
1319  if (ra_filter) {
1320  CHECK(!filter_rex);
1321  filter_rex.reset(ra_filter->getAndReleaseCondition());
1322  CHECK(filter_rex);
1323  last_node = ra_node.get();
1324  continue;
1325  }
1326  const auto ra_project = std::dynamic_pointer_cast<RelProject>(ra_node);
1327  if (ra_project) {
1328  fields = ra_project->getFields();
1329  manipulation_target = ra_project;
1330 
1331  if (first_project) {
1332  CHECK_EQ(size_t(1), ra_project->inputCount());
1333  // Rebind the input of the project to the input of the filter itself
1334  // since we know that we'll evaluate the filter on the fly, with no
1335  // intermediate buffer.
1336  const auto filter_input = dynamic_cast<const RelFilter*>(ra_project->getInput(0));
1337  if (filter_input) {
1338  CHECK_EQ(size_t(1), filter_input->inputCount());
1339  bind_project_to_input(ra_project.get(),
1340  get_node_output(filter_input->getInput(0)));
1341  }
1342  scalar_sources = ra_project->getExpressionsAndRelease();
1343  for (const auto& scalar_expr : scalar_sources) {
1344  target_exprs.push_back(scalar_expr.get());
1345  }
1346  first_project = false;
1347  } else {
1348  if (ra_project->isSimple()) {
1349  target_exprs = reproject_targets(ra_project.get(), target_exprs);
1350  } else {
1351  // TODO(adb): This is essentially a more general case of simple project, we
1352  // could likely merge the two
1353  std::vector<const Rex*> result;
1354  RexInputReplacementVisitor visitor(last_node, scalar_sources);
1355  for (size_t i = 0; i < ra_project->size(); ++i) {
1356  const auto rex = ra_project->getProjectAt(i);
1357  if (auto rex_input = dynamic_cast<const RexInput*>(rex)) {
1358  const auto index = rex_input->getIndex();
1359  CHECK_LT(index, target_exprs.size());
1360  result.push_back(target_exprs[index]);
1361  } else {
1362  scalar_sources.push_back(visitor.visit(rex));
1363  result.push_back(scalar_sources.back().get());
1364  }
1365  }
1366  target_exprs = result;
1367  }
1368  }
1369  last_node = ra_node.get();
1370  continue;
1371  }
1372  const auto ra_aggregate = std::dynamic_pointer_cast<RelAggregate>(ra_node);
1373  if (ra_aggregate) {
1374  is_agg = true;
1375  fields = ra_aggregate->getFields();
1376  agg_exprs = ra_aggregate->getAggregatesAndRelease();
1377  groupby_count = ra_aggregate->getGroupByCount();
1378  decltype(target_exprs){}.swap(target_exprs);
1379  CHECK_LE(groupby_count, scalar_sources.size());
1380  for (size_t group_idx = 0; group_idx < groupby_count; ++group_idx) {
1381  const auto rex_ref = new RexRef(group_idx + 1);
1382  target_exprs.push_back(rex_ref);
1383  scalar_sources.emplace_back(rex_ref);
1384  }
1385  for (const auto rex_agg : agg_exprs) {
1386  target_exprs.push_back(rex_agg);
1387  }
1388  last_node = ra_node.get();
1389  continue;
1390  }
1391  }
1392 
1393  auto compound_node =
1394  std::make_shared<RelCompound>(filter_rex,
1395  target_exprs,
1396  groupby_count,
1397  agg_exprs,
1398  fields,
1399  scalar_sources,
1400  is_agg,
1401  manipulation_target->isUpdateViaSelect(),
1402  manipulation_target->isDeleteViaSelect(),
1403  manipulation_target->isVarlenUpdateRequired(),
1404  manipulation_target->getModifiedTableDescriptor(),
1405  manipulation_target->getTargetColumns());
1406  auto old_node = nodes[pattern.back()];
1407  nodes[pattern.back()] = compound_node;
1408  auto first_node = nodes[pattern.front()];
1409  CHECK_EQ(size_t(1), first_node->inputCount());
1410  compound_node->addManagedInput(first_node->getAndOwnInput(0));
1411  for (size_t i = 0; i < pattern.size() - 1; ++i) {
1412  nodes[pattern[i]].reset();
1413  }
1414  for (auto node : nodes) {
1415  if (!node) {
1416  continue;
1417  }
1418  node->replaceInput(old_node, compound_node);
1419  }
1420 }
bool is_agg(const Analyzer::Expr *expr)
#define CHECK_EQ(x, y)
Definition: Logger.h:205
#define CHECK_GE(x, y)
Definition: Logger.h:210
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
std::vector< const Rex * > reproject_targets(const RelProject *simple_project, const std::vector< const Rex *> &target_exprs) noexcept
#define CHECK_LT(x, y)
Definition: Logger.h:207
#define CHECK_LE(x, y)
Definition: Logger.h:208
#define CHECK(condition)
Definition: Logger.h:197
RANodeOutput get_node_output(const RelAlgNode *ra_node)
const std::vector< std::string > & getFields() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ disambiguate_case()

std::unique_ptr<const RexCase> anonymous_namespace{RelAlgDagBuilder.cpp}::disambiguate_case ( const RexCase rex_case,
const RANodeOutput ra_output 
)

Definition at line 1087 of file RelAlgDagBuilder.cpp.

References RexCase::branchCount(), disambiguate_rex(), RexCase::getElse(), RexCase::getThen(), and RexCase::getWhen().

Referenced by disambiguate_rex().

1088  {
1089  std::vector<
1090  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1091  disambiguated_expr_pair_list;
1092  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1093  auto disambiguated_when = disambiguate_rex(rex_case->getWhen(i), ra_output);
1094  auto disambiguated_then = disambiguate_rex(rex_case->getThen(i), ra_output);
1095  disambiguated_expr_pair_list.emplace_back(std::move(disambiguated_when),
1096  std::move(disambiguated_then));
1097  }
1098  std::unique_ptr<const RexScalar> disambiguated_else{
1099  disambiguate_rex(rex_case->getElse(), ra_output)};
1100  return std::unique_ptr<const RexCase>(
1101  new RexCase(disambiguated_expr_pair_list, disambiguated_else));
1102 }
size_t branchCount() const
const RexScalar * getWhen(const size_t idx) const
const RexScalar * getThen(const size_t idx) const
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
const RexScalar * getElse() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ disambiguate_operator()

std::unique_ptr<const RexOperator> anonymous_namespace{RelAlgDagBuilder.cpp}::disambiguate_operator ( const RexOperator rex_operator,
const RANodeOutput ra_output 
)
noexcept

Definition at line 1052 of file RelAlgDagBuilder.cpp.

References disambiguate_rex(), and RexWindowFunctionOperator::getPartitionKeys().

Referenced by disambiguate_rex().

1054  {
1055  std::vector<std::unique_ptr<const RexScalar>> disambiguated_operands;
1056  for (size_t i = 0; i < rex_operator->size(); ++i) {
1057  auto operand = rex_operator->getOperand(i);
1058  if (dynamic_cast<const RexSubQuery*>(operand)) {
1059  disambiguated_operands.emplace_back(rex_operator->getOperandAndRelease(i));
1060  } else {
1061  disambiguated_operands.emplace_back(disambiguate_rex(operand, ra_output));
1062  }
1063  }
1064  const auto rex_window_function_operator =
1065  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
1066  if (rex_window_function_operator) {
1067  const auto& partition_keys = rex_window_function_operator->getPartitionKeys();
1068  std::vector<std::unique_ptr<const RexScalar>> disambiguated_partition_keys;
1069  for (const auto& partition_key : partition_keys) {
1070  disambiguated_partition_keys.emplace_back(
1071  disambiguate_rex(partition_key.get(), ra_output));
1072  }
1073  std::vector<std::unique_ptr<const RexScalar>> disambiguated_order_keys;
1074  const auto& order_keys = rex_window_function_operator->getOrderKeys();
1075  for (const auto& order_key : order_keys) {
1076  disambiguated_order_keys.emplace_back(disambiguate_rex(order_key.get(), ra_output));
1077  }
1078  return rex_window_function_operator->disambiguatedOperands(
1079  disambiguated_operands,
1080  disambiguated_partition_keys,
1081  disambiguated_order_keys,
1082  rex_window_function_operator->getCollation());
1083  }
1084  return rex_operator->getDisambiguated(disambiguated_operands);
1085 }
const ConstRexScalarPtrVector & getPartitionKeys() const
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
virtual std::unique_ptr< const RexOperator > getDisambiguated(std::vector< std::unique_ptr< const RexScalar >> &operands) const
const RexScalar * getOperand(const size_t idx) const
const RexScalar * getOperandAndRelease(const size_t idx) const
size_t size() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ disambiguate_rex()

std::unique_ptr< const RexScalar > anonymous_namespace{RelAlgDagBuilder.cpp}::disambiguate_rex ( const RexScalar rex_scalar,
const RANodeOutput ra_output 
)

Definition at line 1108 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_LT, disambiguate_case(), and disambiguate_operator().

Referenced by bind_inputs(), bind_project_to_input(), bind_table_func_to_input(), disambiguate_case(), disambiguate_operator(), and to_join_type().

1109  {
1110  const auto rex_abstract_input = dynamic_cast<const RexAbstractInput*>(rex_scalar);
1111  if (rex_abstract_input) {
1112  CHECK_LT(static_cast<size_t>(rex_abstract_input->getIndex()), ra_output.size());
1113  return std::unique_ptr<const RexInput>(
1114  new RexInput(ra_output[rex_abstract_input->getIndex()]));
1115  }
1116  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
1117  if (rex_operator) {
1118  return disambiguate_operator(rex_operator, ra_output);
1119  }
1120  const auto rex_case = dynamic_cast<const RexCase*>(rex_scalar);
1121  if (rex_case) {
1122  return disambiguate_case(rex_case, ra_output);
1123  }
1124  const auto rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar);
1125  CHECK(rex_literal);
1126  return std::unique_ptr<const RexLiteral>(new RexLiteral(*rex_literal));
1127 }
#define CHECK_LT(x, y)
Definition: Logger.h:207
std::unique_ptr< const RexOperator > disambiguate_operator(const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
std::unique_ptr< const RexCase > disambiguate_case(const RexCase *rex_case, const RANodeOutput &ra_output)
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_equiv_cols()

std::set<std::pair<const RelAlgNode*, int> > anonymous_namespace{RelAlgDagBuilder.cpp}::get_equiv_cols ( const RelAlgNode node,
const size_t  which_col 
)

Definition at line 509 of file RelAlgDagBuilder.cpp.

References CHECK, and CHECK_EQ.

Referenced by RelSort::hasEquivCollationOf().

510  {
511  std::set<std::pair<const RelAlgNode*, int>> work_set;
512  auto walker = node;
513  auto curr_col = which_col;
514  while (true) {
515  work_set.insert(std::make_pair(walker, curr_col));
516  if (dynamic_cast<const RelScan*>(walker) || dynamic_cast<const RelJoin*>(walker)) {
517  break;
518  }
519  CHECK_EQ(size_t(1), walker->inputCount());
520  auto only_source = walker->getInput(0);
521  if (auto project = dynamic_cast<const RelProject*>(walker)) {
522  if (auto input = dynamic_cast<const RexInput*>(project->getProjectAt(curr_col))) {
523  const auto join_source = dynamic_cast<const RelJoin*>(only_source);
524  if (join_source) {
525  CHECK_EQ(size_t(2), join_source->inputCount());
526  auto lhs = join_source->getInput(0);
527  CHECK((input->getIndex() < lhs->size() && lhs == input->getSourceNode()) ||
528  join_source->getInput(1) == input->getSourceNode());
529  } else {
530  CHECK_EQ(input->getSourceNode(), only_source);
531  }
532  curr_col = input->getIndex();
533  } else {
534  break;
535  }
536  } else if (auto aggregate = dynamic_cast<const RelAggregate*>(walker)) {
537  if (curr_col >= aggregate->getGroupByCount()) {
538  break;
539  }
540  }
541  walker = only_source;
542  }
543  return work_set;
544 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the caller graph for this function:

◆ get_int_literal_field()

int64_t anonymous_namespace{RelAlgDagBuilder.cpp}::get_int_literal_field ( const rapidjson::Value &  obj,
const char  field[],
const int64_t  default_val 
)
noexcept

Definition at line 2075 of file RelAlgDagBuilder.cpp.

References CHECK_EQ, field(), kDECIMAL, and parse_literal().

Referenced by details::RelAlgDispatcher::dispatchSort().

2077  {
2078  const auto it = obj.FindMember(field);
2079  if (it == obj.MemberEnd()) {
2080  return default_val;
2081  }
2082  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
2083  CHECK_EQ(kDECIMAL, lit->getType());
2084  CHECK_EQ(unsigned(0), lit->getScale());
2085  CHECK_EQ(unsigned(0), lit->getTypeScale());
2086  return lit->getVal<int64_t>();
2087 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::unique_ptr< RexLiteral > parse_literal(const rapidjson::Value &expr)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getFieldNamesFromScanNode()

std::vector<std::string> anonymous_namespace{RelAlgDagBuilder.cpp}::getFieldNamesFromScanNode ( const rapidjson::Value &  scan_ra)

Definition at line 2104 of file RelAlgDagBuilder.cpp.

References field(), and strings_from_json_array().

Referenced by details::RelAlgDispatcher::dispatchTableScan().

2104  {
2105  const auto& fields_json = field(scan_ra, "fieldNames");
2106  return strings_from_json_array(fields_json);
2107 }
std::vector< std::string > strings_from_json_array(const rapidjson::Value &json_str_arr) noexcept
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getTableFromScanNode()

const TableDescriptor* anonymous_namespace{RelAlgDagBuilder.cpp}::getTableFromScanNode ( const Catalog_Namespace::Catalog cat,
const rapidjson::Value &  scan_ra 
)

Definition at line 2094 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_EQ, field(), and Catalog_Namespace::Catalog::getMetadataForTable().

Referenced by details::RelAlgDispatcher::dispatchModify(), and details::RelAlgDispatcher::dispatchTableScan().

2095  {
2096  const auto& table_json = field(scan_ra, "table");
2097  CHECK(table_json.IsArray());
2098  CHECK_EQ(unsigned(2), table_json.Size());
2099  const auto td = cat.getMetadataForTable(table_json[1].GetString());
2100  CHECK(td);
2101  return td;
2102 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
const TableDescriptor * getMetadataForTable(const std::string &tableName, const bool populateFragmenter=true) const
Returns a pointer to a const TableDescriptor struct matching the provided tableName.
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ handleQueryHint()

void anonymous_namespace{RelAlgDagBuilder.cpp}::handleQueryHint ( const std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
RelAlgDagBuilder dag_builder 
)
noexcept

Definition at line 1198 of file RelAlgDagBuilder.cpp.

References QueryHint::cpu_mode, and VLOG.

Referenced by RelAlgDagBuilder::build().

1199  {
1200  QueryHint query_hints;
1201  for (auto node : nodes) {
1202  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1203  if (agg_node) {
1204  if (agg_node->hasHintEnabled("cpu_mode")) {
1205  query_hints.cpu_mode = true;
1206  }
1207  }
1208  const auto project_node = std::dynamic_pointer_cast<RelProject>(node);
1209  if (project_node) {
1210  if (project_node->hasHintEnabled("cpu_mode")) {
1211  query_hints.cpu_mode = true;
1212  }
1213  }
1214  const auto scan_node = std::dynamic_pointer_cast<RelScan>(node);
1215  if (scan_node) {
1216  if (scan_node->hasHintEnabled("cpu_mode")) {
1217  query_hints.cpu_mode = true;
1218  }
1219  }
1220  const auto join_node = std::dynamic_pointer_cast<RelJoin>(node);
1221  if (join_node) {
1222  if (join_node->hasHintEnabled("cpu_mode")) {
1223  query_hints.cpu_mode = true;
1224  }
1225  }
1226  const auto compound_node = std::dynamic_pointer_cast<RelCompound>(node);
1227  if (compound_node) {
1228  if (compound_node->hasHintEnabled("cpu_mode")) {
1229  query_hints.cpu_mode = true;
1230  }
1231  }
1232  }
1233  if (query_hints.cpu_mode) {
1234  VLOG(1) << "A user forces to run the query on the CPU execution mode";
1235  }
1236  dag_builder->registerQueryHints(query_hints);
1237 }
bool cpu_mode
Definition: QueryHint.h:21
void registerQueryHints(QueryHint &query_hint)
#define VLOG(n)
Definition: Logger.h:291
+ Here is the caller graph for this function:

◆ indices_from_json_array()

std::vector<size_t> anonymous_namespace{RelAlgDagBuilder.cpp}::indices_from_json_array ( const rapidjson::Value &  json_idx_arr)
noexcept

Definition at line 991 of file RelAlgDagBuilder.cpp.

References CHECK, and CHECK_GE.

Referenced by details::RelAlgDispatcher::dispatchAggregate(), and parse_aggregate_expr().

992  {
993  CHECK(json_idx_arr.IsArray());
994  std::vector<size_t> indices;
995  for (auto json_idx_arr_it = json_idx_arr.Begin(); json_idx_arr_it != json_idx_arr.End();
996  ++json_idx_arr_it) {
997  CHECK(json_idx_arr_it->IsInt());
998  CHECK_GE(json_idx_arr_it->GetInt(), 0);
999  indices.emplace_back(json_idx_arr_it->GetInt());
1000  }
1001  return indices;
1002 }
#define CHECK_GE(x, y)
Definition: Logger.h:210
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the caller graph for this function:

◆ isRenamedInput()

bool anonymous_namespace{RelAlgDagBuilder.cpp}::isRenamedInput ( const RelAlgNode node,
const size_t  index,
const std::string &  new_name 
)

Definition at line 251 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_EQ, CHECK_GE, CHECK_LT, RelAlgNode::getInput(), join(), and RelAlgNode::size().

Referenced by RelProject::isRenaming().

253  {
254  CHECK_LT(index, node->size());
255  if (auto join = dynamic_cast<const RelJoin*>(node)) {
256  CHECK_EQ(size_t(2), join->inputCount());
257  const auto lhs_size = join->getInput(0)->size();
258  if (index < lhs_size) {
259  return isRenamedInput(join->getInput(0), index, new_name);
260  }
261  CHECK_GE(index, lhs_size);
262  return isRenamedInput(join->getInput(1), index - lhs_size, new_name);
263  }
264 
265  if (auto scan = dynamic_cast<const RelScan*>(node)) {
266  return new_name != scan->getFieldName(index);
267  }
268 
269  if (auto aggregate = dynamic_cast<const RelAggregate*>(node)) {
270  return new_name != aggregate->getFieldName(index);
271  }
272 
273  if (auto project = dynamic_cast<const RelProject*>(node)) {
274  return new_name != project->getFieldName(index);
275  }
276 
277  if (auto table_func = dynamic_cast<const RelTableFunction*>(node)) {
278  return new_name != table_func->getFieldName(index);
279  }
280 
281  if (auto logical_values = dynamic_cast<const RelLogicalValues*>(node)) {
282  const auto& tuple_type = logical_values->getTupleType();
283  CHECK_LT(index, tuple_type.size());
284  return new_name != tuple_type[index].get_resname();
285  }
286 
287  CHECK(dynamic_cast<const RelSort*>(node) || dynamic_cast<const RelFilter*>(node) ||
288  dynamic_cast<const RelLogicalUnion*>(node));
289  return isRenamedInput(node->getInput(0), index, new_name);
290 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
std::string join(T const &container, std::string const &delim)
bool isRenamedInput(const RelAlgNode *node, const size_t index, const std::string &new_name)
#define CHECK_GE(x, y)
Definition: Logger.h:210
#define CHECK_LT(x, y)
Definition: Logger.h:207
virtual size_t size() const =0
#define CHECK(condition)
Definition: Logger.h:197
const RelAlgNode * getInput(const size_t idx) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ json_node_to_string()

std::string anonymous_namespace{RelAlgDagBuilder.cpp}::json_node_to_string ( const rapidjson::Value &  node)
noexcept

Definition at line 667 of file RelAlgDagBuilder.cpp.

Referenced by details::RelAlgDispatcher::dispatchModify(), parse_scalar_expr(), and parse_type().

667  {
668  rapidjson::StringBuffer buffer;
669  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
670  node.Accept(writer);
671  return buffer.GetString();
672 }
+ Here is the caller graph for this function:

◆ mark_nops()

void anonymous_namespace{RelAlgDagBuilder.cpp}::mark_nops ( const std::vector< std::shared_ptr< RelAlgNode >> &  nodes)
noexcept

Definition at line 1239 of file RelAlgDagBuilder.cpp.

References CHECK_EQ, and RelAlgNode::markAsNop().

Referenced by RelAlgDagBuilder::build().

1239  {
1240  for (auto node : nodes) {
1241  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1242  if (!agg_node || agg_node->getAggExprsCount()) {
1243  continue;
1244  }
1245  CHECK_EQ(size_t(1), node->inputCount());
1246  const auto agg_input_node = dynamic_cast<const RelAggregate*>(node->getInput(0));
1247  if (agg_input_node && !agg_input_node->getAggExprsCount() &&
1248  agg_node->getGroupByCount() == agg_input_node->getGroupByCount()) {
1249  agg_node->markAsNop();
1250  }
1251  }
1252 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ n_outputs()

std::vector<RexInput> anonymous_namespace{RelAlgDagBuilder.cpp}::n_outputs ( const RelAlgNode node,
const size_t  n 
)

Definition at line 96 of file RelAlgDagBuilder.cpp.

Referenced by get_node_output().

96  {
97  std::vector<RexInput> outputs;
98  outputs.reserve(n);
99  for (size_t i = 0; i < n; ++i) {
100  outputs.emplace_back(node, i);
101  }
102  return outputs;
103 }
+ Here is the caller graph for this function:

◆ node_id()

unsigned anonymous_namespace{RelAlgDagBuilder.cpp}::node_id ( const rapidjson::Value &  ra_node)
noexcept

Definition at line 662 of file RelAlgDagBuilder.cpp.

References field(), and json_str().

Referenced by details::RelAlgDispatcher::dispatchFilter(), details::RelAlgDispatcher::prev(), and details::RelAlgDispatcher::run().

662  {
663  const auto& id = field(ra_node, "id");
664  return std::stoi(json_str(id));
665 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_abstract_input()

std::unique_ptr<RexAbstractInput> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_abstract_input ( const rapidjson::Value &  expr)
noexcept

Definition at line 678 of file RelAlgDagBuilder.cpp.

References field(), and json_i64().

Referenced by parse_scalar_expr().

679  {
680  const auto& input = field(expr, "input");
681  return std::unique_ptr<RexAbstractInput>(new RexAbstractInput(json_i64(input)));
682 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_aggregate_expr()

std::unique_ptr<const RexAgg> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_aggregate_expr ( const rapidjson::Value &  expr)

Definition at line 1004 of file RelAlgDagBuilder.cpp.

References field(), indices_from_json_array(), json_bool(), json_str(), kAPPROX_COUNT_DISTINCT, parse_type(), and to_agg_kind().

Referenced by details::RelAlgDispatcher::dispatchAggregate().

1004  {
1005  const auto agg = to_agg_kind(json_str(field(expr, "agg")));
1006  const auto distinct = json_bool(field(expr, "distinct"));
1007  const auto agg_ti = parse_type(field(expr, "type"));
1008  const auto operands = indices_from_json_array(field(expr, "operands"));
1009  if (operands.size() > 1 && (operands.size() != 2 || agg != kAPPROX_COUNT_DISTINCT)) {
1010  throw QueryNotSupported("Multiple arguments for aggregates aren't supported");
1011  }
1012  return std::unique_ptr<const RexAgg>(new RexAgg(agg, distinct, agg_ti, operands));
1013 }
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
SQLAgg to_agg_kind(const std::string &agg_name)
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::vector< size_t > indices_from_json_array(const rapidjson::Value &json_idx_arr) noexcept
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_case()

std::unique_ptr<RexCase> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_case ( const rapidjson::Value &  expr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 957 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_GE, field(), and parse_scalar_expr().

Referenced by parse_scalar_expr().

959  {
960  const auto& operands = field(expr, "operands");
961  CHECK(operands.IsArray());
962  CHECK_GE(operands.Size(), unsigned(2));
963  std::unique_ptr<const RexScalar> else_expr;
964  std::vector<
965  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
966  expr_pair_list;
967  for (auto operands_it = operands.Begin(); operands_it != operands.End();) {
968  auto when_expr = parse_scalar_expr(*operands_it++, cat, root_dag_builder);
969  if (operands_it == operands.End()) {
970  else_expr = std::move(when_expr);
971  break;
972  }
973  auto then_expr = parse_scalar_expr(*operands_it++, cat, root_dag_builder);
974  expr_pair_list.emplace_back(std::move(when_expr), std::move(then_expr));
975  }
976  return std::unique_ptr<RexCase>(new RexCase(expr_pair_list, else_expr));
977 }
#define CHECK_GE(x, y)
Definition: Logger.h:210
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:197
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_expr_array()

std::vector<std::unique_ptr<const RexScalar> > anonymous_namespace{RelAlgDagBuilder.cpp}::parse_expr_array ( const rapidjson::Value &  arr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 778 of file RelAlgDagBuilder.cpp.

References parse_scalar_expr().

Referenced by parse_operator().

781  {
782  std::vector<std::unique_ptr<const RexScalar>> exprs;
783  for (auto it = arr.Begin(); it != arr.End(); ++it) {
784  exprs.emplace_back(parse_scalar_expr(*it, cat, root_dag_builder));
785  }
786  return exprs;
787 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_literal()

std::unique_ptr<RexLiteral> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_literal ( const rapidjson::Value &  expr)

Definition at line 684 of file RelAlgDagBuilder.cpp.

References cat(), CHECK, field(), json_bool(), json_double(), json_i64(), json_str(), kBOOLEAN, kDATE, kDECIMAL, kDOUBLE, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kNULLT, kTEXT, kTIME, kTIMESTAMP, parse_scalar_expr(), to_sql_type(), and run_benchmark_import::type.

Referenced by details::RelAlgDispatcher::dispatchLogicalValues(), get_int_literal_field(), and parse_scalar_expr().

684  {
685  CHECK(expr.IsObject());
686  const auto& literal = field(expr, "literal");
687  const auto type = to_sql_type(json_str(field(expr, "type")));
688  const auto target_type = to_sql_type(json_str(field(expr, "target_type")));
689  const auto scale = json_i64(field(expr, "scale"));
690  const auto precision = json_i64(field(expr, "precision"));
691  const auto type_scale = json_i64(field(expr, "type_scale"));
692  const auto type_precision = json_i64(field(expr, "type_precision"));
693  if (literal.IsNull()) {
694  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
695  }
696  switch (type) {
697  case kDECIMAL:
698  case kINTERVAL_DAY_TIME:
700  case kTIME:
701  case kTIMESTAMP:
702  case kDATE:
703  return std::unique_ptr<RexLiteral>(new RexLiteral(json_i64(literal),
704  type,
705  target_type,
706  scale,
707  precision,
708  type_scale,
709  type_precision));
710  case kDOUBLE: {
711  if (literal.IsDouble()) {
712  return std::unique_ptr<RexLiteral>(new RexLiteral(json_double(literal),
713  type,
714  target_type,
715  scale,
716  precision,
717  type_scale,
718  type_precision));
719  }
720  CHECK(literal.IsInt64());
721  return std::unique_ptr<RexLiteral>(
722  new RexLiteral(static_cast<double>(json_i64(literal)),
723  type,
724  target_type,
725  scale,
726  precision,
727  type_scale,
728  type_precision));
729  }
730  case kTEXT:
731  return std::unique_ptr<RexLiteral>(new RexLiteral(json_str(literal),
732  type,
733  target_type,
734  scale,
735  precision,
736  type_scale,
737  type_precision));
738  case kBOOLEAN:
739  return std::unique_ptr<RexLiteral>(new RexLiteral(json_bool(literal),
740  type,
741  target_type,
742  scale,
743  precision,
744  type_scale,
745  type_precision));
746  case kNULLT:
747  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
748  default:
749  CHECK(false);
750  }
751  CHECK(false);
752  return nullptr;
753 }
SQLTypes to_sql_type(const std::string &type_name)
Definition: sqltypes.h:51
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39
const double json_double(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:54
Definition: sqltypes.h:54
Definition: sqltypes.h:55
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_nulls_position()

NullSortedPosition anonymous_namespace{RelAlgDagBuilder.cpp}::parse_nulls_position ( const rapidjson::Value &  collation)

Definition at line 858 of file RelAlgDagBuilder.cpp.

References field(), First, json_str(), and Last.

Referenced by details::RelAlgDispatcher::dispatchSort(), and parse_window_order_collation().

858  {
859  return json_str(field(collation, "nulls")) == std::string("FIRST")
862 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_operator()

std::unique_ptr<RexOperator> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_operator ( const rapidjson::Value &  expr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 911 of file RelAlgDagBuilder.cpp.

References CHECK, field(), json_bool(), json_str(), kFUNCTION, kIN, parse_expr_array(), parse_subquery(), parse_type(), parse_window_bound(), parse_window_function_kind(), parse_window_order_collation(), parse_window_order_exprs(), and to_sql_op().

Referenced by parse_scalar_expr().

913  {
914  const auto op_name = json_str(field(expr, "op"));
915  const bool is_quantifier =
916  op_name == std::string("PG_ANY") || op_name == std::string("PG_ALL");
917  const auto op = is_quantifier ? kFUNCTION : to_sql_op(op_name);
918  const auto& operators_json_arr = field(expr, "operands");
919  CHECK(operators_json_arr.IsArray());
920  auto operands = parse_expr_array(operators_json_arr, cat, root_dag_builder);
921  const auto type_it = expr.FindMember("type");
922  CHECK(type_it != expr.MemberEnd());
923  auto ti = parse_type(type_it->value);
924  if (op == kIN && expr.HasMember("subquery")) {
925  auto subquery = parse_subquery(expr, cat, root_dag_builder);
926  operands.emplace_back(std::move(subquery));
927  }
928  if (expr.FindMember("partition_keys") != expr.MemberEnd()) {
929  const auto& partition_keys_arr = field(expr, "partition_keys");
930  auto partition_keys = parse_expr_array(partition_keys_arr, cat, root_dag_builder);
931  const auto& order_keys_arr = field(expr, "order_keys");
932  auto order_keys = parse_window_order_exprs(order_keys_arr, cat, root_dag_builder);
933  const auto collation =
934  parse_window_order_collation(order_keys_arr, cat, root_dag_builder);
935  const auto kind = parse_window_function_kind(op_name);
936  const auto lower_bound =
937  parse_window_bound(field(expr, "lower_bound"), cat, root_dag_builder);
938  const auto upper_bound =
939  parse_window_bound(field(expr, "upper_bound"), cat, root_dag_builder);
940  bool is_rows = json_bool(field(expr, "is_rows"));
941  ti.set_notnull(false);
942  return std::make_unique<RexWindowFunctionOperator>(kind,
943  operands,
944  partition_keys,
945  order_keys,
946  collation,
947  lower_bound,
948  upper_bound,
949  is_rows,
950  ti);
951  }
952  return std::unique_ptr<RexOperator>(op == kFUNCTION
953  ? new RexFunctionOperator(op_name, operands, ti)
954  : new RexOperator(op, operands, ti));
955 }
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
RexWindowFunctionOperator::RexWindowBound parse_window_bound(const rapidjson::Value &window_bound_obj, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
std::vector< std::unique_ptr< const RexScalar > > parse_window_order_exprs(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
SqlWindowFunctionKind parse_window_function_kind(const std::string &name)
std::vector< std::unique_ptr< const RexScalar > > parse_expr_array(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::vector< SortField > parse_window_order_collation(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
SQLOps to_sql_op(const std::string &op_str)
Definition: sqldefs.h:53
#define CHECK(condition)
Definition: Logger.h:197
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_scalar_expr()

std::unique_ptr< const RexScalar > anonymous_namespace{RelAlgDagBuilder.cpp}::parse_scalar_expr ( const rapidjson::Value &  expr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 1015 of file RelAlgDagBuilder.cpp.

References CHECK, field(), json_node_to_string(), json_str(), parse_abstract_input(), parse_case(), parse_literal(), parse_operator(), and parse_subquery().

Referenced by details::RelAlgDispatcher::dispatchFilter(), details::RelAlgDispatcher::dispatchJoin(), details::RelAlgDispatcher::dispatchProject(), details::RelAlgDispatcher::dispatchTableFunction(), parse_case(), parse_expr_array(), parse_literal(), parse_window_bound(), and parse_window_order_exprs().

1017  {
1018  CHECK(expr.IsObject());
1019  if (expr.IsObject() && expr.HasMember("input")) {
1020  return std::unique_ptr<const RexScalar>(parse_abstract_input(expr));
1021  }
1022  if (expr.IsObject() && expr.HasMember("literal")) {
1023  return std::unique_ptr<const RexScalar>(parse_literal(expr));
1024  }
1025  if (expr.IsObject() && expr.HasMember("op")) {
1026  const auto op_str = json_str(field(expr, "op"));
1027  if (op_str == std::string("CASE")) {
1028  return std::unique_ptr<const RexScalar>(parse_case(expr, cat, root_dag_builder));
1029  }
1030  if (op_str == std::string("$SCALAR_QUERY")) {
1031  return std::unique_ptr<const RexScalar>(
1032  parse_subquery(expr, cat, root_dag_builder));
1033  }
1034  return std::unique_ptr<const RexScalar>(parse_operator(expr, cat, root_dag_builder));
1035  }
1036  throw QueryNotSupported("Expression node " + json_node_to_string(expr) +
1037  " not supported");
1038 }
std::unique_ptr< RexCase > parse_case(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
std::unique_ptr< RexOperator > parse_operator(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::unique_ptr< RexAbstractInput > parse_abstract_input(const rapidjson::Value &expr) noexcept
std::unique_ptr< RexLiteral > parse_literal(const rapidjson::Value &expr)
#define CHECK(condition)
Definition: Logger.h:197
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
std::string json_node_to_string(const rapidjson::Value &node) noexcept
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_sort_direction()

SortDirection anonymous_namespace{RelAlgDagBuilder.cpp}::parse_sort_direction ( const rapidjson::Value &  collation)

Definition at line 852 of file RelAlgDagBuilder.cpp.

References Ascending, Descending, field(), and json_str().

Referenced by details::RelAlgDispatcher::dispatchSort(), and parse_window_order_collation().

852  {
853  return json_str(field(collation, "direction")) == std::string("DESCENDING")
856 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_subquery()

std::unique_ptr<const RexSubQuery> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_subquery ( const rapidjson::Value &  expr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 897 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_GE, field(), RelAlgDagBuilder::getRootNodeShPtr(), and RelAlgDagBuilder::registerSubquery().

Referenced by parse_operator(), and parse_scalar_expr().

899  {
900  const auto& operands = field(expr, "operands");
901  CHECK(operands.IsArray());
902  CHECK_GE(operands.Size(), unsigned(0));
903  const auto& subquery_ast = field(expr, "subquery");
904 
905  RelAlgDagBuilder subquery_dag(root_dag_builder, subquery_ast, cat, nullptr);
906  auto subquery = std::make_shared<RexSubQuery>(subquery_dag.getRootNodeShPtr());
907  root_dag_builder.registerSubquery(subquery);
908  return subquery->deepCopy();
909 }
#define CHECK_GE(x, y)
Definition: Logger.h:210
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
void registerSubquery(std::shared_ptr< RexSubQuery > subquery)
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_type()

SQLTypeInfo anonymous_namespace{RelAlgDagBuilder.cpp}::parse_type ( const rapidjson::Value &  type_obj)

Definition at line 759 of file RelAlgDagBuilder.cpp.

References CHECK, field(), json_bool(), json_i64(), json_node_to_string(), json_str(), SQLTypeInfo::set_precision(), SQLTypeInfo::set_scale(), to_sql_type(), and run_benchmark_import::type.

Referenced by details::RelAlgDispatcher::dispatchLogicalValues(), parse_aggregate_expr(), and parse_operator().

759  {
760  if (type_obj.IsArray()) {
761  throw QueryNotSupported("Composite types are not currently supported.");
762  }
763  CHECK(type_obj.IsObject() && type_obj.MemberCount() >= 2)
764  << json_node_to_string(type_obj);
765  const auto type = to_sql_type(json_str(field(type_obj, "type")));
766  const auto nullable = json_bool(field(type_obj, "nullable"));
767  const auto precision_it = type_obj.FindMember("precision");
768  const int precision =
769  precision_it != type_obj.MemberEnd() ? json_i64(precision_it->value) : 0;
770  const auto scale_it = type_obj.FindMember("scale");
771  const int scale = scale_it != type_obj.MemberEnd() ? json_i64(scale_it->value) : 0;
772  SQLTypeInfo ti(type, !nullable);
773  ti.set_precision(precision);
774  ti.set_scale(scale);
775  return ti;
776 }
SQLTypes to_sql_type(const std::string &type_name)
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39
#define CHECK(condition)
Definition: Logger.h:197
std::string json_node_to_string(const rapidjson::Value &node) noexcept
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_window_bound()

RexWindowFunctionOperator::RexWindowBound anonymous_namespace{RelAlgDagBuilder.cpp}::parse_window_bound ( const rapidjson::Value &  window_bound_obj,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 877 of file RelAlgDagBuilder.cpp.

References CHECK, field(), json_bool(), json_i64(), parse_scalar_expr(), and RexWindowFunctionOperator::RexWindowBound::unbounded.

Referenced by parse_operator().

880  {
881  CHECK(window_bound_obj.IsObject());
883  window_bound.unbounded = json_bool(field(window_bound_obj, "unbounded"));
884  window_bound.preceding = json_bool(field(window_bound_obj, "preceding"));
885  window_bound.following = json_bool(field(window_bound_obj, "following"));
886  window_bound.is_current_row = json_bool(field(window_bound_obj, "is_current_row"));
887  const auto& offset_field = field(window_bound_obj, "offset");
888  if (offset_field.IsObject()) {
889  window_bound.offset = parse_scalar_expr(offset_field, cat, root_dag_builder);
890  } else {
891  CHECK(offset_field.IsNull());
892  }
893  window_bound.order_key = json_i64(field(window_bound_obj, "order_key"));
894  return window_bound;
895 }
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39
#define CHECK(condition)
Definition: Logger.h:197
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_window_function_kind()

SqlWindowFunctionKind anonymous_namespace{RelAlgDagBuilder.cpp}::parse_window_function_kind ( const std::string &  name)

Definition at line 789 of file RelAlgDagBuilder.cpp.

References AVG, COUNT, CUME_DIST, DENSE_RANK, FIRST_VALUE, LAG, LAST_VALUE, LEAD, MAX, MIN, NTILE, PERCENT_RANK, RANK, ROW_NUMBER, SUM, and SUM_INTERNAL.

Referenced by parse_operator().

789  {
790  if (name == "ROW_NUMBER") {
792  }
793  if (name == "RANK") {
795  }
796  if (name == "DENSE_RANK") {
798  }
799  if (name == "PERCENT_RANK") {
801  }
802  if (name == "CUME_DIST") {
804  }
805  if (name == "NTILE") {
807  }
808  if (name == "LAG") {
810  }
811  if (name == "LEAD") {
813  }
814  if (name == "FIRST_VALUE") {
816  }
817  if (name == "LAST_VALUE") {
819  }
820  if (name == "AVG") {
822  }
823  if (name == "MIN") {
825  }
826  if (name == "MAX") {
828  }
829  if (name == "SUM") {
831  }
832  if (name == "COUNT") {
834  }
835  if (name == "$SUM0") {
837  }
838  throw std::runtime_error("Unsupported window function: " + name);
839 }
+ Here is the caller graph for this function:

◆ parse_window_order_collation()

std::vector<SortField> anonymous_namespace{RelAlgDagBuilder.cpp}::parse_window_order_collation ( const rapidjson::Value &  arr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 864 of file RelAlgDagBuilder.cpp.

References parse_nulls_position(), and parse_sort_direction().

Referenced by parse_operator().

866  {
867  std::vector<SortField> collation;
868  size_t field_idx = 0;
869  for (auto it = arr.Begin(); it != arr.End(); ++it, ++field_idx) {
870  const auto sort_dir = parse_sort_direction(*it);
871  const auto null_pos = parse_nulls_position(*it);
872  collation.emplace_back(field_idx, sort_dir, null_pos);
873  }
874  return collation;
875 }
SortDirection parse_sort_direction(const rapidjson::Value &collation)
NullSortedPosition parse_nulls_position(const rapidjson::Value &collation)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_window_order_exprs()

std::vector<std::unique_ptr<const RexScalar> > anonymous_namespace{RelAlgDagBuilder.cpp}::parse_window_order_exprs ( const rapidjson::Value &  arr,
const Catalog_Namespace::Catalog cat,
RelAlgDagBuilder root_dag_builder 
)

Definition at line 841 of file RelAlgDagBuilder.cpp.

References field(), and parse_scalar_expr().

Referenced by parse_operator().

844  {
845  std::vector<std::unique_ptr<const RexScalar>> exprs;
846  for (auto it = arr.Begin(); it != arr.End(); ++it) {
847  exprs.emplace_back(parse_scalar_expr(field(*it, "field"), cat, root_dag_builder));
848  }
849  return exprs;
850 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDagBuilder &root_dag_builder)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remapTargetPointers()

std::vector<const Rex*> anonymous_namespace{RelAlgDagBuilder.cpp}::remapTargetPointers ( std::vector< std::unique_ptr< const RexAgg >> const &  agg_exprs_new,
std::vector< std::unique_ptr< const RexScalar >> const &  scalar_sources_new,
std::vector< std::unique_ptr< const RexAgg >> const &  agg_exprs_old,
std::vector< std::unique_ptr< const RexScalar >> const &  scalar_sources_old,
std::vector< const Rex *> const &  target_exprs_old 
)

Definition at line 418 of file RelAlgDagBuilder.cpp.

References CHECK.

423  {
424  std::vector<const Rex*> target_exprs(target_exprs_old);
425  std::unordered_map<const Rex*, const Rex*> old_to_new_target(target_exprs.size());
426  for (size_t i = 0; i < agg_exprs_new.size(); ++i) {
427  old_to_new_target.emplace(agg_exprs_old[i].get(), agg_exprs_new[i].get());
428  }
429  for (size_t i = 0; i < scalar_sources_new.size(); ++i) {
430  old_to_new_target.emplace(scalar_sources_old[i].get(), scalar_sources_new[i].get());
431  }
432  for (auto& target : target_exprs) {
433  auto target_it = old_to_new_target.find(target);
434  CHECK(target_it != old_to_new_target.end());
435  target = target_it->second;
436  }
437  return target_exprs;
438 }
#define CHECK(condition)
Definition: Logger.h:197

◆ separate_window_function_expressions()

void anonymous_namespace{RelAlgDagBuilder.cpp}::separate_window_function_expressions ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes)

Detect the presence of window function operators nested inside expressions. Separate the window function operator from the expression, computing the expression as a subsequent step and replacing the window function operator with a RexInput. Also move all input nodes to the newly created project node. In pseudocode: for each rex in project list: detect window function expression if window function expression: copy window function expression replace window function expression in base expression w/ input add base expression to new project node after the current node replace base expression in current project node with the window function expression copy

Definition at line 1889 of file RelAlgDagBuilder.cpp.

References CHECK, CHECK_EQ, CHECK_LT, RelProject::getProjectAt(), anonymous_namespace{RelAlgDagBuilder.cpp}::anonymous_namespace{RelAlgDagBuilder.cpp}::is_window_function_operator(), and RexVisitorBase< T >::visit().

Referenced by RelAlgDagBuilder::build().

1890  {
1891  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
1892 
1893  WindowFunctionDetectionVisitor visitor;
1894  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
1895  const auto node = *node_itr;
1896  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
1897  if (!window_func_project_node) {
1898  continue;
1899  }
1900 
1901  // map scalar expression index in the project node to wiondow function ptr
1902  std::unordered_map<size_t, const RexScalar*> embedded_window_function_expressions;
1903 
1904  // Iterate the target exprs of the project node and check for window function
1905  // expressions. If an embedded expression exists, save it in the
1906  // embedded_window_function_expressions map and split the expression into a window
1907  // function expression and a parent expression in a subsequent project node
1908  for (size_t i = 0; i < window_func_project_node->size(); i++) {
1909  const auto scalar_rex = window_func_project_node->getProjectAt(i);
1910  if (is_window_function_operator(scalar_rex)) {
1911  // top level window function exprs are fine
1912  continue;
1913  }
1914 
1915  if (const auto window_func_rex = visitor.visit(scalar_rex)) {
1916  const auto ret = embedded_window_function_expressions.insert(
1917  std::make_pair(i, window_func_rex));
1918  CHECK(ret.second);
1919  }
1920  }
1921 
1922  if (!embedded_window_function_expressions.empty()) {
1923  std::vector<std::unique_ptr<const RexScalar>> new_scalar_exprs;
1924 
1925  auto window_func_scalar_exprs =
1926  window_func_project_node->getExpressionsAndRelease();
1927  for (size_t rex_idx = 0; rex_idx < window_func_scalar_exprs.size(); ++rex_idx) {
1928  const auto embedded_window_func_expr_pair =
1929  embedded_window_function_expressions.find(rex_idx);
1930  if (embedded_window_func_expr_pair ==
1931  embedded_window_function_expressions.end()) {
1932  new_scalar_exprs.emplace_back(
1933  std::make_unique<const RexInput>(window_func_project_node.get(), rex_idx));
1934  } else {
1935  const auto window_func_rex_idx = embedded_window_func_expr_pair->first;
1936  CHECK_LT(window_func_rex_idx, window_func_scalar_exprs.size());
1937 
1938  const auto& window_func_rex = embedded_window_func_expr_pair->second;
1939 
1940  RexDeepCopyVisitor copier;
1941  auto window_func_rex_copy = copier.visit(window_func_rex);
1942 
1943  auto window_func_parent_expr =
1944  window_func_scalar_exprs[window_func_rex_idx].get();
1945 
1946  // Replace window func rex with an input rex
1947  auto window_func_result_input = std::make_unique<const RexInput>(
1948  window_func_project_node.get(), window_func_rex_idx);
1949  RexWindowFuncReplacementVisitor replacer(std::move(window_func_result_input));
1950  auto new_parent_rex = replacer.visit(window_func_parent_expr);
1951 
1952  // Put the parent expr in the new scalar exprs
1953  new_scalar_exprs.emplace_back(std::move(new_parent_rex));
1954 
1955  // Put the window func expr in cur scalar exprs
1956  window_func_scalar_exprs[window_func_rex_idx] = std::move(window_func_rex_copy);
1957  }
1958  }
1959 
1960  CHECK_EQ(window_func_scalar_exprs.size(), new_scalar_exprs.size());
1961  window_func_project_node->setExpressions(window_func_scalar_exprs);
1962 
1963  // Ensure any inputs from the node containing the expression (the "new" node)
1964  // exist on the window function project node, e.g. if we had a binary operation
1965  // involving an aggregate value or column not included in the top level
1966  // projection list.
1967  RexInputBackpropagationVisitor input_visitor(window_func_project_node.get());
1968  for (size_t i = 0; i < new_scalar_exprs.size(); i++) {
1969  if (dynamic_cast<const RexInput*>(new_scalar_exprs[i].get())) {
1970  // ignore top level inputs, these were copied directly from the previous
1971  // node
1972  continue;
1973  }
1974  new_scalar_exprs[i] = input_visitor.visit(new_scalar_exprs[i].get());
1975  }
1976 
1977  // Build the new project node and insert it into the list after the project node
1978  // containing the window function
1979  auto new_project =
1980  std::make_shared<RelProject>(new_scalar_exprs,
1981  window_func_project_node->getFields(),
1982  window_func_project_node);
1983  node_list.insert(std::next(node_itr), new_project);
1984 
1985  // Rebind all the following inputs
1986  for (auto rebind_itr = std::next(node_itr, 2); rebind_itr != node_list.end();
1987  rebind_itr++) {
1988  (*rebind_itr)->replaceInput(window_func_project_node, new_project);
1989  }
1990  }
1991  }
1992  nodes.assign(node_list.begin(), node_list.end());
1993 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
const RexScalar * getProjectAt(const size_t idx) const
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
#define CHECK_LT(x, y)
Definition: Logger.h:207
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ strings_from_json_array()

std::vector<std::string> anonymous_namespace{RelAlgDagBuilder.cpp}::strings_from_json_array ( const rapidjson::Value &  json_str_arr)
noexcept

Definition at line 979 of file RelAlgDagBuilder.cpp.

References CHECK.

Referenced by details::RelAlgDispatcher::dispatchAggregate(), details::RelAlgDispatcher::dispatchProject(), getFieldNamesFromScanNode(), and details::RelAlgDispatcher::getRelAlgInputs().

980  {
981  CHECK(json_str_arr.IsArray());
982  std::vector<std::string> fields;
983  for (auto json_str_arr_it = json_str_arr.Begin(); json_str_arr_it != json_str_arr.End();
984  ++json_str_arr_it) {
985  CHECK(json_str_arr_it->IsString());
986  fields.emplace_back(json_str_arr_it->GetString());
987  }
988  return fields;
989 }
#define CHECK(condition)
Definition: Logger.h:197
+ Here is the caller graph for this function:

◆ to_join_type()

JoinType anonymous_namespace{RelAlgDagBuilder.cpp}::to_join_type ( const std::string &  join_type_name)

Definition at line 1040 of file RelAlgDagBuilder.cpp.

References disambiguate_rex(), INNER, and LEFT.

Referenced by details::RelAlgDispatcher::dispatchJoin().

1040  {
1041  if (join_type_name == "inner") {
1042  return JoinType::INNER;
1043  }
1044  if (join_type_name == "left") {
1045  return JoinType::LEFT;
1046  }
1047  throw QueryNotSupported("Join type (" + join_type_name + ") not supported");
1048 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ FIRST_RA_NODE_ID

const unsigned anonymous_namespace{RelAlgDagBuilder.cpp}::FIRST_RA_NODE_ID = 1

Definition at line 41 of file RelAlgDagBuilder.cpp.

Referenced by RelAlgNode::resetRelAlgFirstId().