OmniSciDB  c0231cc57d
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
anonymous_namespace{RelAlgDag.cpp} Namespace Reference

Namespaces

 anonymous_namespace{RelAlgDag.cpp}
 

Classes

class  RexRebindInputsVisitor
 
class  RexRebindReindexInputsVisitor
 
class  PushDownGenericExpressionInWindowFunction
 
class  RANodeIterator
 
class  WindowFunctionCollector
 
class  RexWindowFuncReplacementVisitor
 
class  RexInputCollector
 

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, RelAlgDag &root_dag)
 
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, RelAlgDag &root_dag)
 
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, RelAlgDag &root_dag)
 
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, RelAlgDag &root_dag)
 
RexWindowFunctionOperator::RexWindowBound parse_window_bound (const rapidjson::Value &window_bound_obj, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
 
std::unique_ptr< const
RexSubQuery
parse_subquery (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
 
std::unique_ptr< RexOperatorparse_operator (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
 
std::unique_ptr< RexCaseparse_case (const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
 
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
RexOperator
disambiguate_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 handle_query_hint (const std::vector< std::shared_ptr< RelAlgNode >> &nodes, RelAlgDag &rel_alg_dag) noexcept
 
void compute_node_hash (const std::vector< std::shared_ptr< RelAlgNode >> &nodes)
 
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, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints) noexcept
 
void coalesce_nodes (std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< const RelAlgNode * > &left_deep_joins, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
 
void propagate_hints_to_new_project (std::shared_ptr< RelProject > prev_node, std::shared_ptr< RelProject > new_node, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
 
void separate_window_function_expressions (std::vector< std::shared_ptr< RelAlgNode >> &nodes, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
 
void add_window_function_pre_project (std::vector< std::shared_ptr< RelAlgNode >> &nodes, const bool always_add_project_if_first_project_is_window_expr, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
 
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

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

Definition at line 2381 of file RelAlgDag.cpp.

Function Documentation

void anonymous_namespace{RelAlgDag.cpp}::add_window_function_pre_project ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
const bool  always_add_project_if_first_project_is_window_expr,
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &  query_hints 
)

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). This is also needed when a window function node is preceded by a filter node, both for correctness (otherwise a window operator will be coalesced with its preceding filter node and be computer over unfiltered results, and for performance, as currently filter nodes that are not coalesced into projects keep all columns from the table as inputs, and hence bring everything in memory. 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 2410 of file RelAlgDag.cpp.

References anonymous_namespace{Utm.h}::a, CHECK, CHECK_EQ, RelAggregate::getGroupByCount(), RelProject::getProjectAt(), propagate_hints_to_new_project(), gpu_enabled::sort(), and VLOG.

Referenced by RelAlgDagBuilder::optimizeDag().

2414  {
2415  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2416  size_t project_node_counter{0};
2417  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2418  const auto node = *node_itr;
2419 
2420  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2421  if (!window_func_project_node) {
2422  continue;
2423  }
2424  project_node_counter++;
2425  if (!window_func_project_node->hasWindowFunctionExpr()) {
2426  // this projection node does not have a window function
2427  // expression -- skip to the next node in the DAG.
2428  continue;
2429  }
2430 
2431  auto need_pushdown_generic_expr = [&window_func_project_node]() {
2432  for (size_t i = 0; i < window_func_project_node->size(); ++i) {
2433  const auto projected_target = window_func_project_node->getProjectAt(i);
2434  if (auto window_expr =
2435  dynamic_cast<const RexWindowFunctionOperator*>(projected_target)) {
2436  for (const auto& partition_key : window_expr->getPartitionKeys()) {
2437  auto partition_input = dynamic_cast<const RexInput*>(partition_key.get());
2438  if (!partition_input) {
2439  return true;
2440  }
2441  }
2442  for (const auto& order_key : window_expr->getOrderKeys()) {
2443  auto order_input = dynamic_cast<const RexInput*>(order_key.get());
2444  if (!order_input) {
2445  return true;
2446  }
2447  }
2448  }
2449  }
2450  return false;
2451  };
2452 
2453  const auto prev_node_itr = std::prev(node_itr);
2454  const auto prev_node = *prev_node_itr;
2455  CHECK(prev_node);
2456 
2457  auto filter_node = std::dynamic_pointer_cast<RelFilter>(prev_node);
2458  auto join_node = std::dynamic_pointer_cast<RelJoin>(prev_node);
2459 
2460  auto scan_node = std::dynamic_pointer_cast<RelScan>(prev_node);
2461  const bool has_multi_fragment_scan_input =
2462  (scan_node &&
2463  (scan_node->getNumShards() > 0 || scan_node->getNumFragments() > 1));
2464  const bool needs_expr_pushdown = need_pushdown_generic_expr();
2465 
2466  // We currently add a preceding project node in one of two conditions:
2467  // 1. always_add_project_if_first_project_is_window_expr = true, which
2468  // we currently only set for distributed, but could also be set to support
2469  // multi-frag window function inputs, either if we can detect that an input table
2470  // is multi-frag up front, or using a retry mechanism like we do for join filter
2471  // push down.
2472  // TODO(todd): Investigate a viable approach for the above.
2473  // 2. Regardless of #1, if the window function project node is preceded by a
2474  // filter node. This is required both for correctness and to avoid pulling
2475  // all source input columns into memory since non-coalesced filter node
2476  // inputs are currently not pruned or eliminated via dead column elimination.
2477  // Note that we expect any filter node followed by a project node to be coalesced
2478  // into a single compound node in RelAlgDag::coalesce_nodes, and that action
2479  // prunes unused inputs.
2480  // TODO(todd): Investigate whether the shotgun filter node issue affects other
2481  // query plans, i.e. filters before joins, and whether there is a more general
2482  // approach to solving this (will still need the preceding project node for
2483  // window functions preceded by filter nodes for correctness though)
2484  // 3. Similar to the above, when the window function project node is preceded
2485  // by a join node.
2486  // 4. when partition by / order by clauses have a general expression instead of
2487  // referencing column
2488 
2489  if (!((always_add_project_if_first_project_is_window_expr &&
2490  project_node_counter == 1) ||
2491  filter_node || join_node || has_multi_fragment_scan_input ||
2492  needs_expr_pushdown)) {
2493  continue;
2494  }
2495 
2496  if (needs_expr_pushdown || join_node) {
2497  // previous logic cannot cover join_node case well, so use the newly introduced
2498  // push-down expression logic to safely add pre_project node before processing
2499  // window function
2500  std::unordered_map<size_t, size_t> expr_offset_cache;
2501  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_for_new_project;
2502  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_for_window_project;
2503  std::vector<std::string> fields_for_window_project;
2504  std::vector<std::string> fields_for_new_project;
2505 
2506  // step 0. create new project node with an empty scalar expr to rebind target exprs
2507  std::vector<std::unique_ptr<const RexScalar>> dummy_scalar_exprs;
2508  std::vector<std::string> dummy_fields;
2509  auto new_project =
2510  std::make_shared<RelProject>(dummy_scalar_exprs, dummy_fields, prev_node);
2511 
2512  // step 1 - 2
2513  PushDownGenericExpressionInWindowFunction visitor(new_project,
2514  scalar_exprs_for_new_project,
2515  fields_for_new_project,
2516  expr_offset_cache);
2517  for (size_t i = 0; i < window_func_project_node->size(); ++i) {
2518  auto projected_target = window_func_project_node->getProjectAt(i);
2519  auto new_projection_target = visitor.visit(projected_target);
2520  scalar_exprs_for_window_project.emplace_back(
2521  std::move(new_projection_target.release()));
2522  }
2523  new_project->setExpressions(scalar_exprs_for_new_project);
2524  new_project->setFields(std::move(fields_for_new_project));
2525  bool has_groupby = false;
2526  auto aggregate = std::dynamic_pointer_cast<RelAggregate>(prev_node);
2527  if (aggregate) {
2528  has_groupby = aggregate->getGroupByCount() > 0;
2529  }
2530  if (has_groupby && visitor.hasPartitionExpression()) {
2531  // we currently may compute incorrect result with columnar output when
2532  // 1) the window function has partition expression, and
2533  // 2) a parent node of the window function projection node has group by expression
2534  // so we force rowwise output (only) for the newly injected projection node
2535  // to prevent computing incorrect query result
2536  // todo (yoonmin) : relax this
2537  VLOG(1)
2538  << "Query output overridden to row-wise format due to presence of a window "
2539  "function with partition expression and group-by expression.";
2540  new_project->forceRowwiseOutput();
2541  }
2542  if (visitor.hasCaseExprAsWindowOperand()) {
2543  // force rowwise output
2544  VLOG(1)
2545  << "Query output overridden to row-wise format due to presence of a window "
2546  "function with a case statement as its operand.";
2547  new_project->forceRowwiseOutput();
2548  }
2549 
2550  // step 3. finalize
2551  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2552  new_project->setPushedDownWindowExpr();
2553  node_list.insert(node_itr, new_project);
2554  window_func_project_node->replaceInput(prev_node, new_project);
2555  window_func_project_node->setExpressions(scalar_exprs_for_window_project);
2556  } else {
2557  // only push rex_inputs listed in the window function down to a new project node
2558  RexInputSet inputs;
2559  RexInputCollector input_collector;
2560  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2561  auto new_inputs =
2562  input_collector.visit(window_func_project_node->getProjectAt(i));
2563  inputs.insert(new_inputs.begin(), new_inputs.end());
2564  }
2565 
2566  // Note: Technically not required since we are mapping old inputs to new input
2567  // indices, but makes the re-mapping of inputs easier to follow.
2568  std::vector<RexInput> sorted_inputs(inputs.begin(), inputs.end());
2569  std::sort(sorted_inputs.begin(),
2570  sorted_inputs.end(),
2571  [](const auto& a, const auto& b) { return a.getIndex() < b.getIndex(); });
2572 
2573  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs;
2574  std::vector<std::string> fields;
2575  std::unordered_map<unsigned, unsigned> old_index_to_new_index;
2576  for (auto& input : sorted_inputs) {
2577  CHECK_EQ(input.getSourceNode(), prev_node.get());
2578  CHECK(old_index_to_new_index
2579  .insert(std::make_pair(input.getIndex(), scalar_exprs.size()))
2580  .second);
2581  scalar_exprs.emplace_back(input.deepCopy());
2582  fields.emplace_back("");
2583  }
2584 
2585  auto new_project = std::make_shared<RelProject>(scalar_exprs, fields, prev_node);
2586  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2587  new_project->setPushedDownWindowExpr();
2588  node_list.insert(node_itr, new_project);
2589  window_func_project_node->replaceInput(
2590  prev_node, new_project, old_index_to_new_index);
2591  }
2592  }
2593  nodes.assign(node_list.begin(), node_list.end());
2594 }
const size_t getGroupByCount() const
Definition: RelAlgDag.h:1237
#define CHECK_EQ(x, y)
Definition: Logger.h:230
DEVICE void sort(ARGS &&...args)
Definition: gpu_enabled.h:105
void propagate_hints_to_new_project(std::shared_ptr< RelProject > prev_node, std::shared_ptr< RelProject > new_node, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
Definition: RelAlgDag.cpp:2223
constexpr double a
Definition: Utm.h:32
std::unordered_set< RexInput > RexInputSet
Definition: RelAlgDag.cpp:2381
const RexScalar * getProjectAt(const size_t idx) const
Definition: RelAlgDag.h:1104
#define CHECK(condition)
Definition: Logger.h:222
#define VLOG(n)
Definition: Logger.h:316

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1425 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::build().

1425  {
1426  for (auto ra_node : nodes) {
1427  const auto filter_node = std::dynamic_pointer_cast<RelFilter>(ra_node);
1428  if (filter_node) {
1429  CHECK_EQ(size_t(1), filter_node->inputCount());
1430  auto disambiguated_condition = disambiguate_rex(
1431  filter_node->getCondition(), get_node_output(filter_node->getInput(0)));
1432  filter_node->setCondition(disambiguated_condition);
1433  continue;
1434  }
1435  const auto join_node = std::dynamic_pointer_cast<RelJoin>(ra_node);
1436  if (join_node) {
1437  CHECK_EQ(size_t(2), join_node->inputCount());
1438  auto disambiguated_condition =
1439  disambiguate_rex(join_node->getCondition(), get_node_output(join_node.get()));
1440  join_node->setCondition(disambiguated_condition);
1441  continue;
1442  }
1443  const auto project_node = std::dynamic_pointer_cast<RelProject>(ra_node);
1444  if (project_node) {
1445  bind_project_to_input(project_node.get(),
1446  get_node_output(project_node->getInput(0)));
1447  continue;
1448  }
1449  const auto table_func_node = std::dynamic_pointer_cast<RelTableFunction>(ra_node);
1450  if (table_func_node) {
1451  /*
1452  Collect all inputs from table function input (non-literal)
1453  arguments.
1454  */
1455  RANodeOutput input;
1456  input.reserve(table_func_node->inputCount());
1457  for (size_t i = 0; i < table_func_node->inputCount(); i++) {
1458  auto node_output = get_node_output(table_func_node->getInput(i));
1459  input.insert(input.end(), node_output.begin(), node_output.end());
1460  }
1461  bind_table_func_to_input(table_func_node.get(), input);
1462  }
1463  }
1464 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
std::vector< RexInput > RANodeOutput
Definition: RelAlgDag.h:2688
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1371
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1397
void bind_table_func_to_input(RelTableFunction *table_func_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1411
RANodeOutput get_node_output(const RelAlgNode *ra_node)
Definition: RelAlgDag.cpp:370

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1397 of file RelAlgDag.cpp.

References CHECK_EQ, and disambiguate_rex().

Referenced by bind_inputs(), and create_compound().

1397  {
1398  CHECK_EQ(size_t(1), project_node->inputCount());
1399  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1400  for (size_t i = 0; i < project_node->size(); ++i) {
1401  const auto projected_expr = project_node->getProjectAt(i);
1402  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
1403  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
1404  } else {
1405  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
1406  }
1407  }
1408  project_node->setExpressions(disambiguated_exprs);
1409 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
size_t size() const override
Definition: RelAlgDag.h:1074
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1371
void setExpressions(std::vector< std::unique_ptr< const RexScalar >> &exprs) const
Definition: RelAlgDag.h:1054
const RexScalar * getProjectAtAndRelease(const size_t idx) const
Definition: RelAlgDag.h:1109
const RexScalar * getProjectAt(const size_t idx) const
Definition: RelAlgDag.h:1104
const size_t inputCount() const
Definition: RelAlgDag.h:824

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1411 of file RelAlgDag.cpp.

References disambiguate_rex().

Referenced by bind_inputs().

1412  {
1413  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1414  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
1415  const auto target_expr = table_func_node->getTableFuncInputAt(i);
1416  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
1417  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
1418  } else {
1419  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
1420  }
1421  }
1422  table_func_node->setTableFuncInputs(disambiguated_exprs);
1423 }
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1371
const RexScalar * getTableFuncInputAtAndRelease(const size_t idx)
Definition: RelAlgDag.h:2140
size_t getTableFuncInputsSize() const
Definition: RelAlgDag.h:2129
void setTableFuncInputs(std::vector< std::unique_ptr< const RexScalar >> &exprs)
Definition: RelAlgDag.h:2145
const RexScalar * getTableFuncInputAt(const size_t idx) const
Definition: RelAlgDag.h:2135

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2610 of file RelAlgDag.cpp.

References CHECK, and field().

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

2610  {
2611  const auto& inputs_json = field(node, "inputs");
2612  CHECK(inputs_json.IsArray() && !inputs_json.Size());
2613 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void anonymous_namespace{RelAlgDag.cpp}::coalesce_nodes ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
const std::vector< const RelAlgNode * > &  left_deep_joins,
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &  query_hints 
)

Definition at line 1912 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

1916  {
1917  enum class CoalesceState { Initial, Filter, FirstProject, Aggregate };
1918  std::vector<size_t> crt_pattern;
1919  CoalesceState crt_state{CoalesceState::Initial};
1920 
1921  auto reset_state = [&crt_pattern, &crt_state]() {
1922  crt_state = CoalesceState::Initial;
1923  std::vector<size_t>().swap(crt_pattern);
1924  };
1925 
1926  for (RANodeIterator nodeIt(nodes); !nodeIt.allVisited();) {
1927  const auto ra_node = nodeIt != nodes.end() ? *nodeIt : nullptr;
1928  switch (crt_state) {
1929  case CoalesceState::Initial: {
1930  if (std::dynamic_pointer_cast<const RelFilter>(ra_node) &&
1931  std::find(left_deep_joins.begin(), left_deep_joins.end(), ra_node.get()) ==
1932  left_deep_joins.end()) {
1933  crt_pattern.push_back(size_t(nodeIt));
1934  crt_state = CoalesceState::Filter;
1935  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1936  } else if (auto project_node =
1937  std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1938  if (project_node->hasWindowFunctionExpr()) {
1939  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
1940  } else {
1941  crt_pattern.push_back(size_t(nodeIt));
1942  crt_state = CoalesceState::FirstProject;
1943  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1944  }
1945  } else {
1946  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
1947  }
1948  break;
1949  }
1950  case CoalesceState::Filter: {
1951  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1952  // Given we now add preceding projects for all window functions following
1953  // RelFilter nodes, the following should never occur
1954  CHECK(!project_node->hasWindowFunctionExpr());
1955  crt_pattern.push_back(size_t(nodeIt));
1956  crt_state = CoalesceState::FirstProject;
1957  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1958  } else {
1959  reset_state();
1960  }
1961  break;
1962  }
1963  case CoalesceState::FirstProject: {
1964  if (std::dynamic_pointer_cast<const RelAggregate>(ra_node)) {
1965  crt_pattern.push_back(size_t(nodeIt));
1966  crt_state = CoalesceState::Aggregate;
1967  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
1968  } else {
1969  if (crt_pattern.size() >= 2) {
1970  create_compound(nodes, crt_pattern, query_hints);
1971  }
1972  reset_state();
1973  }
1974  break;
1975  }
1976  case CoalesceState::Aggregate: {
1977  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
1978  if (!project_node->hasWindowFunctionExpr()) {
1979  // TODO(adb): overloading the simple project terminology again here
1980  bool is_simple_project{true};
1981  for (size_t i = 0; i < project_node->size(); i++) {
1982  const auto scalar_rex = project_node->getProjectAt(i);
1983  // If the top level scalar rex is an input node, we can bypass the visitor
1984  if (auto input_rex = dynamic_cast<const RexInput*>(scalar_rex)) {
1986  input_rex->getSourceNode(), input_rex->getIndex(), true)) {
1987  is_simple_project = false;
1988  break;
1989  }
1990  continue;
1991  }
1992  CoalesceSecondaryProjectVisitor visitor;
1993  if (!visitor.visit(project_node->getProjectAt(i))) {
1994  is_simple_project = false;
1995  break;
1996  }
1997  }
1998  if (is_simple_project) {
1999  crt_pattern.push_back(size_t(nodeIt));
2000  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
2001  }
2002  }
2003  }
2004  CHECK_GE(crt_pattern.size(), size_t(2));
2005  create_compound(nodes, crt_pattern, query_hints);
2006  reset_state();
2007  break;
2008  }
2009  default:
2010  CHECK(false);
2011  }
2012  }
2013  if (crt_state == CoalesceState::FirstProject || crt_state == CoalesceState::Aggregate) {
2014  if (crt_pattern.size() >= 2) {
2015  create_compound(nodes, crt_pattern, query_hints);
2016  }
2017  CHECK(!crt_pattern.empty());
2018  }
2019 }
bool input_can_be_coalesced(const RelAlgNode *parent_node, const size_t index, const bool first_rex_is_input)
Definition: RelAlgDag.cpp:1812
#define CHECK_GE(x, y)
Definition: Logger.h:235
#define CHECK(condition)
Definition: Logger.h:222
void create_compound(std::vector< std::shared_ptr< RelAlgNode >> &nodes, const std::vector< size_t > &pattern, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints) noexcept
Definition: RelAlgDag.cpp:1573
DEVICE void swap(ARGS &&...args)
Definition: gpu_enabled.h:114

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void anonymous_namespace{RelAlgDag.cpp}::compute_node_hash ( const std::vector< std::shared_ptr< RelAlgNode >> &  nodes)

Definition at line 1499 of file RelAlgDag.cpp.

References CHECK_NE.

Referenced by RelAlgDagBuilder::optimizeDag().

1499  {
1500  // compute each rel node's hash value in advance to avoid inconsistency of their hash
1501  // values depending on the toHash's caller
1502  // specifically, we manipulate our logical query plan before retrieving query step
1503  // sequence but once we compute a hash value we cached it so there is no way to update
1504  // it after the plan has been changed starting from the top node, we compute the hash
1505  // value (top-down manner)
1506  std::for_each(
1507  nodes.rbegin(), nodes.rend(), [](const std::shared_ptr<RelAlgNode>& node) {
1508  auto node_hash = node->toHash();
1509  CHECK_NE(node_hash, static_cast<size_t>(0));
1510  });
1511 }
#define CHECK_NE(x, y)
Definition: Logger.h:231

+ Here is the caller graph for this function:

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

Definition at line 615 of file RelAlgDag.cpp.

616  {
617  std::vector<std::unique_ptr<const RexAgg>> agg_exprs_copy;
618  agg_exprs_copy.reserve(agg_exprs.size());
619  for (auto const& agg_expr : agg_exprs) {
620  agg_exprs_copy.push_back(agg_expr->deepCopy());
621  }
622  return agg_exprs_copy;
623 }
std::vector<std::unique_ptr<const RexScalar> > anonymous_namespace{RelAlgDag.cpp}::copyRexScalars ( std::vector< std::unique_ptr< const RexScalar >> const &  scalar_sources)

Definition at line 625 of file RelAlgDag.cpp.

References RexVisitorBase< T >::visit().

626  {
627  std::vector<std::unique_ptr<const RexScalar>> scalar_sources_copy;
628  scalar_sources_copy.reserve(scalar_sources.size());
629  RexDeepCopyVisitor copier;
630  for (auto const& scalar_source : scalar_sources) {
631  scalar_sources_copy.push_back(copier.visit(scalar_source.get()));
632  }
633  return scalar_sources_copy;
634 }
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27

+ Here is the call graph for this function:

void anonymous_namespace{RelAlgDag.cpp}::create_compound ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
const std::vector< size_t > &  pattern,
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &  query_hints 
)
noexcept

Definition at line 1573 of file RelAlgDag.cpp.

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

Referenced by coalesce_nodes().

1577  {
1578  CHECK_GE(pattern.size(), size_t(2));
1579  CHECK_LE(pattern.size(), size_t(4));
1580 
1581  std::unique_ptr<const RexScalar> filter_rex;
1582  std::vector<std::unique_ptr<const RexScalar>> scalar_sources;
1583  size_t groupby_count{0};
1584  std::vector<std::string> fields;
1585  std::vector<const RexAgg*> agg_exprs;
1586  std::vector<const Rex*> target_exprs;
1587  bool first_project{true};
1588  bool is_agg{false};
1589  RelAlgNode* last_node{nullptr};
1590 
1591  std::shared_ptr<ModifyManipulationTarget> manipulation_target;
1592  size_t node_hash{0};
1593  unsigned node_id{0};
1594  bool hint_registered{false};
1595  RegisteredQueryHint registered_query_hint = RegisteredQueryHint::defaults();
1596  for (const auto node_idx : pattern) {
1597  const auto ra_node = nodes[node_idx];
1598  auto registered_query_hint_map_it = query_hints.find(ra_node->toHash());
1599  if (registered_query_hint_map_it != query_hints.end()) {
1600  auto& registered_query_hint_map = registered_query_hint_map_it->second;
1601  auto registered_query_hint_it = registered_query_hint_map.find(ra_node->getId());
1602  if (registered_query_hint_it != registered_query_hint_map.end()) {
1603  hint_registered = true;
1604  node_hash = registered_query_hint_map_it->first;
1605  node_id = registered_query_hint_it->first;
1606  registered_query_hint = registered_query_hint_it->second;
1607  }
1608  }
1609  const auto ra_filter = std::dynamic_pointer_cast<RelFilter>(ra_node);
1610  if (ra_filter) {
1611  CHECK(!filter_rex);
1612  filter_rex.reset(ra_filter->getAndReleaseCondition());
1613  CHECK(filter_rex);
1614  last_node = ra_node.get();
1615  continue;
1616  }
1617  const auto ra_project = std::dynamic_pointer_cast<RelProject>(ra_node);
1618  if (ra_project) {
1619  fields = ra_project->getFields();
1620  manipulation_target = ra_project;
1621 
1622  if (first_project) {
1623  CHECK_EQ(size_t(1), ra_project->inputCount());
1624  // Rebind the input of the project to the input of the filter itself
1625  // since we know that we'll evaluate the filter on the fly, with no
1626  // intermediate buffer.
1627  const auto filter_input = dynamic_cast<const RelFilter*>(ra_project->getInput(0));
1628  if (filter_input) {
1629  CHECK_EQ(size_t(1), filter_input->inputCount());
1630  bind_project_to_input(ra_project.get(),
1631  get_node_output(filter_input->getInput(0)));
1632  }
1633  scalar_sources = ra_project->getExpressionsAndRelease();
1634  for (const auto& scalar_expr : scalar_sources) {
1635  target_exprs.push_back(scalar_expr.get());
1636  }
1637  first_project = false;
1638  } else {
1639  if (ra_project->isSimple()) {
1640  target_exprs = reproject_targets(ra_project.get(), target_exprs);
1641  } else {
1642  // TODO(adb): This is essentially a more general case of simple project, we
1643  // could likely merge the two
1644  std::vector<const Rex*> result;
1645  RexInputReplacementVisitor visitor(last_node, scalar_sources);
1646  for (size_t i = 0; i < ra_project->size(); ++i) {
1647  const auto rex = ra_project->getProjectAt(i);
1648  if (auto rex_input = dynamic_cast<const RexInput*>(rex)) {
1649  const auto index = rex_input->getIndex();
1650  CHECK_LT(index, target_exprs.size());
1651  result.push_back(target_exprs[index]);
1652  } else {
1653  scalar_sources.push_back(visitor.visit(rex));
1654  result.push_back(scalar_sources.back().get());
1655  }
1656  }
1657  target_exprs = result;
1658  }
1659  }
1660  last_node = ra_node.get();
1661  continue;
1662  }
1663  const auto ra_aggregate = std::dynamic_pointer_cast<RelAggregate>(ra_node);
1664  if (ra_aggregate) {
1665  is_agg = true;
1666  fields = ra_aggregate->getFields();
1667  agg_exprs = ra_aggregate->getAggregatesAndRelease();
1668  groupby_count = ra_aggregate->getGroupByCount();
1669  decltype(target_exprs){}.swap(target_exprs);
1670  CHECK_LE(groupby_count, scalar_sources.size());
1671  for (size_t group_idx = 0; group_idx < groupby_count; ++group_idx) {
1672  const auto rex_ref = new RexRef(group_idx + 1);
1673  target_exprs.push_back(rex_ref);
1674  scalar_sources.emplace_back(rex_ref);
1675  }
1676  for (const auto rex_agg : agg_exprs) {
1677  target_exprs.push_back(rex_agg);
1678  }
1679  last_node = ra_node.get();
1680  continue;
1681  }
1682  }
1683 
1684  auto compound_node =
1685  std::make_shared<RelCompound>(filter_rex,
1686  target_exprs,
1687  groupby_count,
1688  agg_exprs,
1689  fields,
1690  scalar_sources,
1691  is_agg,
1692  manipulation_target->isUpdateViaSelect(),
1693  manipulation_target->isDeleteViaSelect(),
1694  manipulation_target->isVarlenUpdateRequired(),
1695  manipulation_target->getModifiedTableDescriptor(),
1696  manipulation_target->getTargetColumns());
1697  auto old_node = nodes[pattern.back()];
1698  nodes[pattern.back()] = compound_node;
1699  auto first_node = nodes[pattern.front()];
1700  CHECK_EQ(size_t(1), first_node->inputCount());
1701  compound_node->addManagedInput(first_node->getAndOwnInput(0));
1702  if (hint_registered) {
1703  // pass the registered hint from the origin node to newly created compound node
1704  // where it is coalesced
1705  auto registered_query_hint_map_it = query_hints.find(node_hash);
1706  CHECK(registered_query_hint_map_it != query_hints.end());
1707  auto registered_query_hint_map = registered_query_hint_map_it->second;
1708  if (registered_query_hint_map.size() > 1) {
1709  registered_query_hint_map.erase(node_id);
1710  } else {
1711  CHECK_EQ(registered_query_hint_map.size(), static_cast<size_t>(1));
1712  query_hints.erase(node_hash);
1713  }
1714  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
1715  hint_map.emplace(compound_node->getId(), registered_query_hint);
1716  query_hints.emplace(compound_node->toHash(), hint_map);
1717  }
1718  for (size_t i = 0; i < pattern.size() - 1; ++i) {
1719  nodes[pattern[i]].reset();
1720  }
1721  for (auto node : nodes) {
1722  if (!node) {
1723  continue;
1724  }
1725  node->replaceInput(old_node, compound_node);
1726  }
1727 }
bool is_agg(const Analyzer::Expr *expr)
#define CHECK_EQ(x, y)
Definition: Logger.h:230
#define CHECK_GE(x, y)
Definition: Logger.h:235
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1397
#define CHECK_LT(x, y)
Definition: Logger.h:232
static RegisteredQueryHint defaults()
Definition: QueryHint.h:247
std::vector< const Rex * > reproject_targets(const RelProject *simple_project, const std::vector< const Rex * > &target_exprs) noexcept
Definition: RelAlgDag.cpp:1530
#define CHECK_LE(x, y)
Definition: Logger.h:233
const std::vector< std::string > & getFields() const
Definition: RelAlgDag.h:1118
#define CHECK(condition)
Definition: Logger.h:222
unsigned node_id(const rapidjson::Value &ra_node) noexcept
Definition: RelAlgDag.cpp:899
RANodeOutput get_node_output(const RelAlgNode *ra_node)
Definition: RelAlgDag.cpp:370

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1350 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

1351  {
1352  std::vector<
1353  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1354  disambiguated_expr_pair_list;
1355  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1356  auto disambiguated_when = disambiguate_rex(rex_case->getWhen(i), ra_output);
1357  auto disambiguated_then = disambiguate_rex(rex_case->getThen(i), ra_output);
1358  disambiguated_expr_pair_list.emplace_back(std::move(disambiguated_when),
1359  std::move(disambiguated_then));
1360  }
1361  std::unique_ptr<const RexScalar> disambiguated_else{
1362  disambiguate_rex(rex_case->getElse(), ra_output)};
1363  return std::unique_ptr<const RexCase>(
1364  new RexCase(disambiguated_expr_pair_list, disambiguated_else));
1365 }
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:400
const RexScalar * getElse() const
Definition: RelAlgDag.h:405
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:395
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1371
size_t branchCount() const
Definition: RelAlgDag.h:393

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1315 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

1317  {
1318  std::vector<std::unique_ptr<const RexScalar>> disambiguated_operands;
1319  for (size_t i = 0; i < rex_operator->size(); ++i) {
1320  auto operand = rex_operator->getOperand(i);
1321  if (dynamic_cast<const RexSubQuery*>(operand)) {
1322  disambiguated_operands.emplace_back(rex_operator->getOperandAndRelease(i));
1323  } else {
1324  disambiguated_operands.emplace_back(disambiguate_rex(operand, ra_output));
1325  }
1326  }
1327  const auto rex_window_function_operator =
1328  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
1329  if (rex_window_function_operator) {
1330  const auto& partition_keys = rex_window_function_operator->getPartitionKeys();
1331  std::vector<std::unique_ptr<const RexScalar>> disambiguated_partition_keys;
1332  for (const auto& partition_key : partition_keys) {
1333  disambiguated_partition_keys.emplace_back(
1334  disambiguate_rex(partition_key.get(), ra_output));
1335  }
1336  std::vector<std::unique_ptr<const RexScalar>> disambiguated_order_keys;
1337  const auto& order_keys = rex_window_function_operator->getOrderKeys();
1338  for (const auto& order_key : order_keys) {
1339  disambiguated_order_keys.emplace_back(disambiguate_rex(order_key.get(), ra_output));
1340  }
1341  return rex_window_function_operator->disambiguatedOperands(
1342  disambiguated_operands,
1343  disambiguated_partition_keys,
1344  disambiguated_order_keys,
1345  rex_window_function_operator->getCollation());
1346  }
1347  return rex_operator->getDisambiguated(disambiguated_operands);
1348 }
size_t size() const
Definition: RelAlgDag.h:245
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:247
const RexScalar * getOperandAndRelease(const size_t idx) const
Definition: RelAlgDag.h:252
virtual std::unique_ptr< const RexOperator > getDisambiguated(std::vector< std::unique_ptr< const RexScalar >> &operands) const
Definition: RelAlgDag.h:240
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1371
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:573

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1371 of file RelAlgDag.cpp.

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

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

1372  {
1373  const auto rex_abstract_input = dynamic_cast<const RexAbstractInput*>(rex_scalar);
1374  if (rex_abstract_input) {
1375  CHECK_LT(static_cast<size_t>(rex_abstract_input->getIndex()), ra_output.size());
1376  return std::unique_ptr<const RexInput>(
1377  new RexInput(ra_output[rex_abstract_input->getIndex()]));
1378  }
1379  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
1380  if (rex_operator) {
1381  return disambiguate_operator(rex_operator, ra_output);
1382  }
1383  const auto rex_case = dynamic_cast<const RexCase*>(rex_scalar);
1384  if (rex_case) {
1385  return disambiguate_case(rex_case, ra_output);
1386  }
1387  if (auto const rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar)) {
1388  return rex_literal->deepCopy();
1389  } else if (auto const rex_subquery = dynamic_cast<const RexSubQuery*>(rex_scalar)) {
1390  return rex_subquery->deepCopy();
1391  } else {
1392  throw QueryNotSupported("Unable to disambiguate expression of type " +
1393  std::string(typeid(*rex_scalar).name()));
1394  }
1395 }
std::unique_ptr< const RexOperator > disambiguate_operator(const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
Definition: RelAlgDag.cpp:1315
std::unique_ptr< const RexCase > disambiguate_case(const RexCase *rex_case, const RANodeOutput &ra_output)
Definition: RelAlgDag.cpp:1350
#define CHECK_LT(x, y)
Definition: Logger.h:232

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 740 of file RelAlgDag.cpp.

References CHECK, and CHECK_EQ.

Referenced by RelSort::hasEquivCollationOf().

741  {
742  std::set<std::pair<const RelAlgNode*, int>> work_set;
743  auto walker = node;
744  auto curr_col = which_col;
745  while (true) {
746  work_set.insert(std::make_pair(walker, curr_col));
747  if (dynamic_cast<const RelScan*>(walker) || dynamic_cast<const RelJoin*>(walker)) {
748  break;
749  }
750  CHECK_EQ(size_t(1), walker->inputCount());
751  auto only_source = walker->getInput(0);
752  if (auto project = dynamic_cast<const RelProject*>(walker)) {
753  if (auto input = dynamic_cast<const RexInput*>(project->getProjectAt(curr_col))) {
754  const auto join_source = dynamic_cast<const RelJoin*>(only_source);
755  if (join_source) {
756  CHECK_EQ(size_t(2), join_source->inputCount());
757  auto lhs = join_source->getInput(0);
758  CHECK((input->getIndex() < lhs->size() && lhs == input->getSourceNode()) ||
759  join_source->getInput(1) == input->getSourceNode());
760  } else {
761  CHECK_EQ(input->getSourceNode(), only_source);
762  }
763  curr_col = input->getIndex();
764  } else {
765  break;
766  }
767  } else if (auto aggregate = dynamic_cast<const RelAggregate*>(walker)) {
768  if (curr_col >= aggregate->getGroupByCount()) {
769  break;
770  }
771  }
772  walker = only_source;
773  }
774  return work_set;
775 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the caller graph for this function:

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

Definition at line 2596 of file RelAlgDag.cpp.

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

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

2598  {
2599  const auto it = obj.FindMember(field);
2600  if (it == obj.MemberEnd()) {
2601  return default_val;
2602  }
2603  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
2604  CHECK_EQ(kDECIMAL, lit->getType());
2605  CHECK_EQ(unsigned(0), lit->getScale());
2606  CHECK_EQ(unsigned(0), lit->getTargetScale());
2607  return lit->getVal<int64_t>();
2608 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
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)
Definition: RelAlgDag.cpp:921

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2625 of file RelAlgDag.cpp.

References field(), and strings_from_json_array().

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

2625  {
2626  const auto& fields_json = field(scan_ra, "fieldNames");
2627  return strings_from_json_array(fields_json);
2628 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::vector< std::string > strings_from_json_array(const rapidjson::Value &json_str_arr) noexcept
Definition: RelAlgDag.cpp:1232

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2615 of file RelAlgDag.cpp.

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

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

2616  {
2617  const auto& table_json = field(scan_ra, "table");
2618  CHECK(table_json.IsArray());
2619  CHECK_EQ(unsigned(2), table_json.Size());
2620  const auto td = cat.getMetadataForTable(table_json[1].GetString());
2621  CHECK(td);
2622  return td;
2623 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:222
const TableDescriptor * getMetadataForTable(const std::string &tableName, const bool populateFragmenter=true) const
Returns a pointer to a const TableDescriptor struct matching the provided tableName.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void anonymous_namespace{RelAlgDag.cpp}::handle_query_hint ( const std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
RelAlgDag rel_alg_dag 
)
noexcept

Definition at line 1466 of file RelAlgDag.cpp.

References RelProject::getDeliveredHints(), RelAggregate::getDeliveredHints(), and RelCompound::getDeliveredHints().

Referenced by RelAlgDagBuilder::optimizeDag().

1467  {
1468  // query hint is delivered by the above three nodes
1469  // when a query block has top-sort node, a hint is registered to
1470  // one of the node which locates at the nearest from the sort node
1471  RegisteredQueryHint global_query_hint;
1472  for (auto node : nodes) {
1473  Hints* hint_delivered = nullptr;
1474  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1475  if (agg_node) {
1476  if (agg_node->hasDeliveredHint()) {
1477  hint_delivered = agg_node->getDeliveredHints();
1478  }
1479  }
1480  const auto project_node = std::dynamic_pointer_cast<RelProject>(node);
1481  if (project_node) {
1482  if (project_node->hasDeliveredHint()) {
1483  hint_delivered = project_node->getDeliveredHints();
1484  }
1485  }
1486  const auto compound_node = std::dynamic_pointer_cast<RelCompound>(node);
1487  if (compound_node) {
1488  if (compound_node->hasDeliveredHint()) {
1489  hint_delivered = compound_node->getDeliveredHints();
1490  }
1491  }
1492  if (hint_delivered && !hint_delivered->empty()) {
1493  rel_alg_dag.registerQueryHints(node, hint_delivered, global_query_hint);
1494  }
1495  }
1496  rel_alg_dag.setGlobalQueryHints(global_query_hint);
1497 }
void setGlobalQueryHints(const RegisteredQueryHint &global_hints)
Definition: RelAlgDag.h:2595
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1192
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1334
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1780
std::unordered_map< QueryHint, ExplainedQueryHint > Hints
Definition: QueryHint.h:273
void registerQueryHints(std::shared_ptr< RelAlgNode > node, Hints *hints_delivered, RegisteredQueryHint &global_query_hint)
Definition: RelAlgDag.h:2364

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1244 of file RelAlgDag.cpp.

References CHECK, and CHECK_GE.

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

1245  {
1246  CHECK(json_idx_arr.IsArray());
1247  std::vector<size_t> indices;
1248  for (auto json_idx_arr_it = json_idx_arr.Begin(); json_idx_arr_it != json_idx_arr.End();
1249  ++json_idx_arr_it) {
1250  CHECK(json_idx_arr_it->IsInt());
1251  CHECK_GE(json_idx_arr_it->GetInt(), 0);
1252  indices.emplace_back(json_idx_arr_it->GetInt());
1253  }
1254  return indices;
1255 }
#define CHECK_GE(x, y)
Definition: Logger.h:235
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the caller graph for this function:

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

Definition at line 469 of file RelAlgDag.cpp.

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

Referenced by RelProject::isRenaming().

471  {
472  CHECK_LT(index, node->size());
473  if (auto join = dynamic_cast<const RelJoin*>(node)) {
474  CHECK_EQ(size_t(2), join->inputCount());
475  const auto lhs_size = join->getInput(0)->size();
476  if (index < lhs_size) {
477  return isRenamedInput(join->getInput(0), index, new_name);
478  }
479  CHECK_GE(index, lhs_size);
480  return isRenamedInput(join->getInput(1), index - lhs_size, new_name);
481  }
482 
483  if (auto scan = dynamic_cast<const RelScan*>(node)) {
484  return new_name != scan->getFieldName(index);
485  }
486 
487  if (auto aggregate = dynamic_cast<const RelAggregate*>(node)) {
488  return new_name != aggregate->getFieldName(index);
489  }
490 
491  if (auto project = dynamic_cast<const RelProject*>(node)) {
492  return new_name != project->getFieldName(index);
493  }
494 
495  if (auto table_func = dynamic_cast<const RelTableFunction*>(node)) {
496  return new_name != table_func->getFieldName(index);
497  }
498 
499  if (auto logical_values = dynamic_cast<const RelLogicalValues*>(node)) {
500  const auto& tuple_type = logical_values->getTupleType();
501  CHECK_LT(index, tuple_type.size());
502  return new_name != tuple_type[index].get_resname();
503  }
504 
505  CHECK(dynamic_cast<const RelSort*>(node) || dynamic_cast<const RelFilter*>(node) ||
506  dynamic_cast<const RelLogicalUnion*>(node));
507  return isRenamedInput(node->getInput(0), index, new_name);
508 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
std::string join(T const &container, std::string const &delim)
#define CHECK_GE(x, y)
Definition: Logger.h:235
bool isRenamedInput(const RelAlgNode *node, const size_t index, const std::string &new_name)
Definition: RelAlgDag.cpp:469
const RelAlgNode * getInput(const size_t idx) const
Definition: RelAlgDag.h:826
#define CHECK_LT(x, y)
Definition: Logger.h:232
virtual size_t size() const =0
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 904 of file RelAlgDag.cpp.

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

904  {
905  rapidjson::StringBuffer buffer;
906  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
907  node.Accept(writer);
908  return buffer.GetString();
909 }

+ Here is the caller graph for this function:

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

Definition at line 1513 of file RelAlgDag.cpp.

References CHECK_EQ, and RelAlgNode::markAsNop().

Referenced by RelAlgDagBuilder::optimizeDag().

1513  {
1514  for (auto node : nodes) {
1515  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1516  if (!agg_node || agg_node->getAggExprsCount()) {
1517  continue;
1518  }
1519  CHECK_EQ(size_t(1), node->inputCount());
1520  const auto agg_input_node = dynamic_cast<const RelAggregate*>(node->getInput(0));
1521  if (agg_input_node && !agg_input_node->getAggExprsCount() &&
1522  agg_node->getGroupByCount() == agg_input_node->getGroupByCount()) {
1523  agg_node->markAsNop();
1524  }
1525  }
1526 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
void markAsNop()
Definition: RelAlgDag.h:866

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 95 of file RelAlgDag.cpp.

References anonymous_namespace{Utm.h}::n.

Referenced by get_node_output().

95  {
96  std::vector<RexInput> outputs;
97  outputs.reserve(n);
98  for (size_t i = 0; i < n; ++i) {
99  outputs.emplace_back(node, i);
100  }
101  return outputs;
102 }
constexpr double n
Definition: Utm.h:38

+ Here is the caller graph for this function:

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

Definition at line 899 of file RelAlgDag.cpp.

References field(), and json_str().

Referenced by create_compound(), details::RelAlgDispatcher::dispatchFilter(), RaExecutionSequence::extractQueryStepSkippingInfo(), QueryPlanDagExtractor::handleTranslatedJoin(), details::RelAlgDispatcher::prev(), and details::RelAlgDispatcher::run().

899  {
900  const auto& id = field(ra_node, "id");
901  return std::stoi(json_str(id));
902 }
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:

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

Definition at line 915 of file RelAlgDag.cpp.

References field(), and json_i64().

Referenced by parse_scalar_expr().

916  {
917  const auto& input = field(expr, "input");
918  return std::unique_ptr<RexAbstractInput>(new RexAbstractInput(json_i64(input)));
919 }
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:

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

Definition at line 1257 of file RelAlgDag.cpp.

References field(), indices_from_json_array(), logger::INFO, json_bool(), json_str(), kAPPROX_COUNT_DISTINCT, kAPPROX_QUANTILE, LOG, parse_type(), and to_agg_kind().

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

1257  {
1258  const auto agg_str = json_str(field(expr, "agg"));
1259  if (agg_str == "APPROX_QUANTILE") {
1260  LOG(INFO) << "APPROX_QUANTILE is deprecated. Please use APPROX_PERCENTILE instead.";
1261  }
1262  const auto agg = to_agg_kind(agg_str);
1263  const auto distinct = json_bool(field(expr, "distinct"));
1264  const auto agg_ti = parse_type(field(expr, "type"));
1265  const auto operands = indices_from_json_array(field(expr, "operands"));
1266  if (operands.size() > 1 && (operands.size() != 2 || (agg != kAPPROX_COUNT_DISTINCT &&
1267  agg != kAPPROX_QUANTILE))) {
1268  throw QueryNotSupported("Multiple arguments for aggregates aren't supported");
1269  }
1270  return std::unique_ptr<const RexAgg>(new RexAgg(agg, distinct, agg_ti, operands));
1271 }
SQLAgg to_agg_kind(const std::string &agg_name)
#define LOG(tag)
Definition: Logger.h:216
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
std::vector< size_t > indices_from_json_array(const rapidjson::Value &json_idx_arr) noexcept
Definition: RelAlgDag.cpp:1244
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
Definition: RelAlgDag.cpp:1007

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1210 of file RelAlgDag.cpp.

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

Referenced by parse_scalar_expr().

1212  {
1213  const auto& operands = field(expr, "operands");
1214  CHECK(operands.IsArray());
1215  CHECK_GE(operands.Size(), unsigned(2));
1216  std::unique_ptr<const RexScalar> else_expr;
1217  std::vector<
1218  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1219  expr_pair_list;
1220  for (auto operands_it = operands.Begin(); operands_it != operands.End();) {
1221  auto when_expr = parse_scalar_expr(*operands_it++, cat, root_dag);
1222  if (operands_it == operands.End()) {
1223  else_expr = std::move(when_expr);
1224  break;
1225  }
1226  auto then_expr = parse_scalar_expr(*operands_it++, cat, root_dag);
1227  expr_pair_list.emplace_back(std::move(when_expr), std::move(then_expr));
1228  }
1229  return std::unique_ptr<RexCase>(new RexCase(expr_pair_list, else_expr));
1230 }
#define CHECK_GE(x, y)
Definition: Logger.h:235
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1273
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1026 of file RelAlgDag.cpp.

References parse_scalar_expr().

Referenced by parse_operator().

1029  {
1030  std::vector<std::unique_ptr<const RexScalar>> exprs;
1031  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1032  exprs.emplace_back(parse_scalar_expr(*it, cat, root_dag));
1033  }
1034  return exprs;
1035 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1273

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 921 of file RelAlgDag.cpp.

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

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

921  {
922  CHECK(expr.IsObject());
923  const auto& literal = field(expr, "literal");
924  const auto type = to_sql_type(json_str(field(expr, "type")));
925  const auto target_type = to_sql_type(json_str(field(expr, "target_type")));
926  const auto scale = json_i64(field(expr, "scale"));
927  const auto precision = json_i64(field(expr, "precision"));
928  const auto type_scale = json_i64(field(expr, "type_scale"));
929  const auto type_precision = json_i64(field(expr, "type_precision"));
930  if (literal.IsNull()) {
931  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
932  }
933  switch (type) {
934  case kINT:
935  case kBIGINT:
936  case kDECIMAL:
937  case kINTERVAL_DAY_TIME:
939  case kTIME:
940  case kTIMESTAMP:
941  case kDATE:
942  return std::unique_ptr<RexLiteral>(new RexLiteral(json_i64(literal),
943  type,
944  target_type,
945  scale,
946  precision,
947  type_scale,
948  type_precision));
949  case kDOUBLE: {
950  if (literal.IsDouble()) {
951  return std::unique_ptr<RexLiteral>(new RexLiteral(json_double(literal),
952  type,
953  target_type,
954  scale,
955  precision,
956  type_scale,
957  type_precision));
958  } else if (literal.IsInt64()) {
959  return std::make_unique<RexLiteral>(static_cast<double>(literal.GetInt64()),
960  type,
961  target_type,
962  scale,
963  precision,
964  type_scale,
965  type_precision);
966 
967  } else if (literal.IsUint64()) {
968  return std::make_unique<RexLiteral>(static_cast<double>(literal.GetUint64()),
969  type,
970  target_type,
971  scale,
972  precision,
973  type_scale,
974  type_precision);
975  }
976  UNREACHABLE() << "Unhandled type: " << literal.GetType();
977  }
978  case kTEXT:
979  return std::unique_ptr<RexLiteral>(new RexLiteral(json_str(literal),
980  type,
981  target_type,
982  scale,
983  precision,
984  type_scale,
985  type_precision));
986  case kBOOLEAN:
987  return std::unique_ptr<RexLiteral>(new RexLiteral(json_bool(literal),
988  type,
989  target_type,
990  scale,
991  precision,
992  type_scale,
993  type_precision));
994  case kNULLT:
995  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
996  default:
997  CHECK(false);
998  }
999  CHECK(false);
1000  return nullptr;
1001 }
SQLTypes to_sql_type(const std::string &type_name)
Definition: sqltypes.h:63
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
#define UNREACHABLE()
Definition: Logger.h:266
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:66
Definition: sqltypes.h:67
#define CHECK(condition)
Definition: Logger.h:222
Definition: sqltypes.h:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1112 of file RelAlgDag.cpp.

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

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

1112  {
1113  return json_str(field(collation, "nulls")) == std::string("FIRST")
1116 }
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:

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

Definition at line 1165 of file RelAlgDag.cpp.

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

Referenced by parse_scalar_expr().

1167  {
1168  const auto op_name = json_str(field(expr, "op"));
1169  const bool is_quantifier =
1170  op_name == std::string("PG_ANY") || op_name == std::string("PG_ALL");
1171  const auto op = is_quantifier ? kFUNCTION : to_sql_op(op_name);
1172  const auto& operators_json_arr = field(expr, "operands");
1173  CHECK(operators_json_arr.IsArray());
1174  auto operands = parse_expr_array(operators_json_arr, cat, root_dag);
1175  const auto type_it = expr.FindMember("type");
1176  CHECK(type_it != expr.MemberEnd());
1177  auto ti = parse_type(type_it->value);
1178  if (op == kIN && expr.HasMember("subquery")) {
1179  auto subquery = parse_subquery(expr, cat, root_dag);
1180  operands.emplace_back(std::move(subquery));
1181  }
1182  if (expr.FindMember("partition_keys") != expr.MemberEnd()) {
1183  const auto& partition_keys_arr = field(expr, "partition_keys");
1184  auto partition_keys = parse_expr_array(partition_keys_arr, cat, root_dag);
1185  const auto& order_keys_arr = field(expr, "order_keys");
1186  auto order_keys = parse_window_order_exprs(order_keys_arr, cat, root_dag);
1187  const auto collation = parse_window_order_collation(order_keys_arr, cat, root_dag);
1188  const auto kind = parse_window_function_kind(op_name);
1189  const auto lower_bound =
1190  parse_window_bound(field(expr, "lower_bound"), cat, root_dag);
1191  const auto upper_bound =
1192  parse_window_bound(field(expr, "upper_bound"), cat, root_dag);
1193  bool is_rows = json_bool(field(expr, "is_rows"));
1194  ti.set_notnull(false);
1195  return std::make_unique<RexWindowFunctionOperator>(kind,
1196  operands,
1197  partition_keys,
1198  order_keys,
1199  collation,
1200  lower_bound,
1201  upper_bound,
1202  is_rows,
1203  ti);
1204  }
1205  return std::unique_ptr<RexOperator>(op == kFUNCTION
1206  ? new RexFunctionOperator(op_name, operands, ti)
1207  : new RexOperator(op, operands, ti));
1208 }
DEVICE auto upper_bound(ARGS &&...args)
Definition: gpu_enabled.h:123
SqlWindowFunctionKind parse_window_function_kind(const std::string &name)
Definition: RelAlgDag.cpp:1037
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1151
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
std::vector< std::unique_ptr< const RexScalar > > parse_window_order_exprs(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1095
std::vector< SortField > parse_window_order_collation(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1118
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
SQLOps to_sql_op(const std::string &op_str)
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
Definition: RelAlgDag.cpp:1007
std::vector< std::unique_ptr< const RexScalar > > parse_expr_array(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1026
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
Definition: sqldefs.h:52
RexWindowFunctionOperator::RexWindowBound parse_window_bound(const rapidjson::Value &window_bound_obj, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1131
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1273 of file RelAlgDag.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_window_bound(), and parse_window_order_exprs().

1275  {
1276  CHECK(expr.IsObject());
1277  if (expr.IsObject() && expr.HasMember("input")) {
1278  return std::unique_ptr<const RexScalar>(parse_abstract_input(expr));
1279  }
1280  if (expr.IsObject() && expr.HasMember("literal")) {
1281  return std::unique_ptr<const RexScalar>(parse_literal(expr));
1282  }
1283  if (expr.IsObject() && expr.HasMember("op")) {
1284  const auto op_str = json_str(field(expr, "op"));
1285  if (op_str == std::string("CASE")) {
1286  return std::unique_ptr<const RexScalar>(parse_case(expr, cat, root_dag));
1287  }
1288  if (op_str == std::string("$SCALAR_QUERY")) {
1289  return std::unique_ptr<const RexScalar>(parse_subquery(expr, cat, root_dag));
1290  }
1291  return std::unique_ptr<const RexScalar>(parse_operator(expr, cat, root_dag));
1292  }
1293  throw QueryNotSupported("Expression node " + json_node_to_string(expr) +
1294  " not supported");
1295 }
std::unique_ptr< RexOperator > parse_operator(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1165
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1151
std::string json_node_to_string(const rapidjson::Value &node) noexcept
Definition: RelAlgDag.cpp:904
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
std::unique_ptr< RexAbstractInput > parse_abstract_input(const rapidjson::Value &expr) noexcept
Definition: RelAlgDag.cpp:915
std::unique_ptr< RexCase > parse_case(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1210
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)
Definition: RelAlgDag.cpp:921
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1106 of file RelAlgDag.cpp.

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

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

1106  {
1107  return json_str(field(collation, "direction")) == std::string("DESCENDING")
1110 }
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:

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

Definition at line 1151 of file RelAlgDag.cpp.

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

Referenced by parse_operator(), and parse_scalar_expr().

1153  {
1154  const auto& operands = field(expr, "operands");
1155  CHECK(operands.IsArray());
1156  CHECK_GE(operands.Size(), unsigned(0));
1157  const auto& subquery_ast = field(expr, "subquery");
1158 
1159  auto subquery_dag = RelAlgDagBuilder::buildDagForSubquery(root_dag, subquery_ast, cat);
1160  auto subquery = std::make_shared<RexSubQuery>(subquery_dag->getRootNodeShPtr());
1161  root_dag.registerSubquery(subquery);
1162  return subquery->deepCopy();
1163 }
#define CHECK_GE(x, y)
Definition: Logger.h:235
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
void registerSubquery(std::shared_ptr< RexSubQuery > subquery)
Definition: RelAlgDag.h:2352
#define CHECK(condition)
Definition: Logger.h:222
static std::unique_ptr< RelAlgDag > buildDagForSubquery(RelAlgDag &root_dag, const rapidjson::Value &query_ast, const Catalog_Namespace::Catalog &cat)
Definition: RelAlgDag.cpp:3124

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1007 of file RelAlgDag.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().

1007  {
1008  if (type_obj.IsArray()) {
1009  throw QueryNotSupported("Composite types are not currently supported.");
1010  }
1011  CHECK(type_obj.IsObject() && type_obj.MemberCount() >= 2)
1012  << json_node_to_string(type_obj);
1013  const auto type = to_sql_type(json_str(field(type_obj, "type")));
1014  const auto nullable = json_bool(field(type_obj, "nullable"));
1015  const auto precision_it = type_obj.FindMember("precision");
1016  const int precision =
1017  precision_it != type_obj.MemberEnd() ? json_i64(precision_it->value) : 0;
1018  const auto scale_it = type_obj.FindMember("scale");
1019  const int scale = scale_it != type_obj.MemberEnd() ? json_i64(scale_it->value) : 0;
1020  SQLTypeInfo ti(type, !nullable);
1021  ti.set_precision(precision);
1022  ti.set_scale(scale);
1023  return ti;
1024 }
SQLTypes to_sql_type(const std::string &type_name)
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
std::string json_node_to_string(const rapidjson::Value &node) noexcept
Definition: RelAlgDag.cpp:904
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:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1131 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

1134  {
1135  CHECK(window_bound_obj.IsObject());
1137  window_bound.unbounded = json_bool(field(window_bound_obj, "unbounded"));
1138  window_bound.preceding = json_bool(field(window_bound_obj, "preceding"));
1139  window_bound.following = json_bool(field(window_bound_obj, "following"));
1140  window_bound.is_current_row = json_bool(field(window_bound_obj, "is_current_row"));
1141  const auto& offset_field = field(window_bound_obj, "offset");
1142  if (offset_field.IsObject()) {
1143  window_bound.bound_expr = parse_scalar_expr(offset_field, cat, root_dag);
1144  } else {
1145  CHECK(offset_field.IsNull());
1146  }
1147  window_bound.order_key = json_i64(field(window_bound_obj, "order_key"));
1148  return window_bound;
1149 }
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1273
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:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1037 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

1037  {
1038  if (name == "ROW_NUMBER") {
1040  }
1041  if (name == "RANK") {
1043  }
1044  if (name == "DENSE_RANK") {
1046  }
1047  if (name == "PERCENT_RANK") {
1049  }
1050  if (name == "CUME_DIST") {
1052  }
1053  if (name == "NTILE") {
1055  }
1056  if (name == "LAG") {
1058  }
1059  if (name == "LAG_IN_FRAME") {
1061  }
1062  if (name == "LEAD") {
1064  }
1065  if (name == "LEAD_IN_FRAME") {
1067  }
1068  if (name == "FIRST_VALUE") {
1070  }
1071  if (name == "LAST_VALUE") {
1073  }
1074  if (name == "AVG") {
1076  }
1077  if (name == "MIN") {
1079  }
1080  if (name == "MAX") {
1082  }
1083  if (name == "SUM") {
1085  }
1086  if (name == "COUNT") {
1088  }
1089  if (name == "$SUM0") {
1091  }
1092  throw std::runtime_error("Unsupported window function: " + name);
1093 }
string name
Definition: setup.in.py:72

+ Here is the caller graph for this function:

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

Definition at line 1118 of file RelAlgDag.cpp.

References parse_nulls_position(), and parse_sort_direction().

Referenced by parse_operator().

1120  {
1121  std::vector<SortField> collation;
1122  size_t field_idx = 0;
1123  for (auto it = arr.Begin(); it != arr.End(); ++it, ++field_idx) {
1124  const auto sort_dir = parse_sort_direction(*it);
1125  const auto null_pos = parse_nulls_position(*it);
1126  collation.emplace_back(field_idx, sort_dir, null_pos);
1127  }
1128  return collation;
1129 }
NullSortedPosition parse_nulls_position(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1112
SortDirection parse_sort_direction(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1106

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1095 of file RelAlgDag.cpp.

References field(), and parse_scalar_expr().

Referenced by parse_operator().

1098  {
1099  std::vector<std::unique_ptr<const RexScalar>> exprs;
1100  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1101  exprs.emplace_back(parse_scalar_expr(field(*it, "field"), cat, root_dag));
1102  }
1103  return exprs;
1104 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1273
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:

void anonymous_namespace{RelAlgDag.cpp}::propagate_hints_to_new_project ( std::shared_ptr< RelProject prev_node,
std::shared_ptr< RelProject new_node,
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &  query_hints 
)

Definition at line 2223 of file RelAlgDag.cpp.

References CHECK.

Referenced by add_window_function_pre_project(), and separate_window_function_expressions().

2227  {
2228  auto delivered_hints = prev_node->getDeliveredHints();
2229  bool needs_propagate_hints = !delivered_hints->empty();
2230  if (needs_propagate_hints) {
2231  for (auto& kv : *delivered_hints) {
2232  new_node->addHint(kv.second);
2233  }
2234  auto prev_it = query_hints.find(prev_node->toHash());
2235  // query hint for the prev projection node should be registered
2236  CHECK(prev_it != query_hints.end());
2237  auto prev_hint_it = prev_it->second.find(prev_node->getId());
2238  CHECK(prev_hint_it != prev_it->second.end());
2239  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
2240  hint_map.emplace(new_node->getId(), prev_hint_it->second);
2241  query_hints.emplace(new_node->toHash(), hint_map);
2242  }
2243 }
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the caller graph for this function:

std::vector<const Rex*> anonymous_namespace{RelAlgDag.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 636 of file RelAlgDag.cpp.

References CHECK.

641  {
642  std::vector<const Rex*> target_exprs(target_exprs_old);
643  std::unordered_map<const Rex*, const Rex*> old_to_new_target(target_exprs.size());
644  for (size_t i = 0; i < agg_exprs_new.size(); ++i) {
645  old_to_new_target.emplace(agg_exprs_old[i].get(), agg_exprs_new[i].get());
646  }
647  for (size_t i = 0; i < scalar_sources_new.size(); ++i) {
648  old_to_new_target.emplace(scalar_sources_old[i].get(), scalar_sources_new[i].get());
649  }
650  for (auto& target : target_exprs) {
651  auto target_it = old_to_new_target.find(target);
652  CHECK(target_it != old_to_new_target.end());
653  target = target_it->second;
654  }
655  return target_exprs;
656 }
#define CHECK(condition)
Definition: Logger.h:222
void anonymous_namespace{RelAlgDag.cpp}::separate_window_function_expressions ( std::vector< std::shared_ptr< RelAlgNode >> &  nodes,
std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &  query_hints 
)

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 by pushing the expression to a new project node, and replacing the nested window function operator with a RexInput. Also move all input nodes to the newly created project node. Overall, we have the following query plan: from: Window_Project -> Child to: Window_Project -> New_Project -> Child In pseudocode: for each rex in project list: detect nested window function expression if nested window function expression: push the nested window function expression to the new project P create a new RexInput r_i which references the w_i in P and put it to M (M: a map between nested window function expression w_i and r_i) else push it down to the new project P create a new RexInput r_i which references the rex in P and put it to M for each rex in the project list: visit the rex and find a chance to replace it (or its operand) by using M

Definition at line 2267 of file RelAlgDag.cpp.

References CHECK, anonymous_namespace{RelAlgDag.cpp}::anonymous_namespace{RelAlgDag.cpp}::is_window_function_operator(), propagate_hints_to_new_project(), and RexVisitorBase< T >::visit().

Referenced by RelAlgDagBuilder::optimizeDag().

2270  {
2271  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2272  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2273  const auto node = *node_itr;
2274  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2275  if (!window_func_project_node) {
2276  continue;
2277  }
2278 
2279  const auto prev_node_itr = std::prev(node_itr);
2280  const auto prev_node = *prev_node_itr;
2281  CHECK(prev_node);
2282 
2283  // map scalar expression index in the project node to window function ptr
2284  std::unordered_map<size_t, const RexScalar*> collected_window_func;
2285  WindowFunctionCollector collector(collected_window_func);
2286  // Iterate the target exprs of the project node and check for window function
2287  // expressions. If an embedded expression exists, collect it
2288  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2289  const auto scalar_rex = window_func_project_node->getProjectAt(i);
2290  if (is_window_function_operator(scalar_rex)) {
2291  // top level window function exprs are fine
2292  continue;
2293  }
2294  collector.visit(scalar_rex);
2295  }
2296 
2297  if (!collected_window_func.empty()) {
2298  // we have a nested window function expression
2299  std::unordered_set<size_t> collected_window_func_hash;
2300  // the current window function needs a set of new rex input which references
2301  // expressions in the newly introduced projection node
2302  std::vector<std::unique_ptr<const RexScalar>> new_rex_input_for_window_func;
2303  // a target projection expression of the newly created projection node
2304  std::vector<std::unique_ptr<const RexScalar>> new_scalar_expr_for_window_project;
2305  // a map between nested window function (hash val) and
2306  // its rex index stored in the `new_rex_input_for_window_func`
2307  std::unordered_map<size_t, size_t> window_func_to_new_rex_input_idx_map;
2308  // a map between RexInput of the current window function projection node (hash val)
2309  // and its corresponding new RexInput which is pushed down to the new projection
2310  // node
2311  std::unordered_map<size_t, std::unique_ptr<const RexInput>>
2312  new_rex_input_from_child_node;
2313  RexDeepCopyVisitor copier;
2314 
2315  std::vector<std::unique_ptr<const RexScalar>> dummy_scalar_exprs;
2316  std::vector<std::string> dummy_fields;
2317  std::vector<std::string> new_project_field_names;
2318  // create a new project node, it will contain window function expressions
2319  auto new_project =
2320  std::make_shared<RelProject>(dummy_scalar_exprs, dummy_fields, prev_node);
2321  // insert this new project node between the current window project node and its
2322  // child node
2323  node_list.insert(node_itr, new_project);
2324 
2325  // retrieve various information to replace expressions in the current window
2326  // function project node w/ considering scalar expressions in the new project node
2327  std::for_each(collected_window_func.begin(),
2328  collected_window_func.end(),
2329  [&new_project_field_names,
2330  &collected_window_func_hash,
2331  &new_rex_input_for_window_func,
2332  &new_scalar_expr_for_window_project,
2333  &copier,
2334  &new_project,
2335  &window_func_to_new_rex_input_idx_map](const auto& kv) {
2336  // compute window function expr's hash, and create a new rex_input
2337  // for it
2338  collected_window_func_hash.insert(kv.first);
2339 
2340  // map an old expression in the window function project node
2341  // to an index of the corresponding new RexInput
2342  const auto rex_idx = new_rex_input_for_window_func.size();
2343  window_func_to_new_rex_input_idx_map.emplace(kv.first, rex_idx);
2344 
2345  // create a new RexInput and make it as one of new expression of the
2346  // newly created project node
2347  new_rex_input_for_window_func.emplace_back(
2348  std::make_unique<const RexInput>(new_project.get(), rex_idx));
2349  new_scalar_expr_for_window_project.push_back(
2350  std::move(copier.visit(kv.second)));
2351  new_project_field_names.emplace_back("");
2352  });
2353  new_project->setExpressions(new_scalar_expr_for_window_project);
2354  new_project->setFields(std::move(new_project_field_names));
2355 
2356  auto window_func_scalar_exprs =
2357  window_func_project_node->getExpressionsAndRelease();
2358  RexWindowFuncReplacementVisitor replacer(collected_window_func_hash,
2359  new_rex_input_for_window_func,
2360  window_func_to_new_rex_input_idx_map,
2361  new_project.get(),
2362  new_rex_input_from_child_node);
2363  size_t rex_idx = 0;
2364  for (auto& scalar_expr : window_func_scalar_exprs) {
2365  // try to replace the old expressions in the window function project node
2366  // with expressions of the newly created project node
2367  auto new_parent_rex = replacer.visit(scalar_expr.get());
2368  window_func_scalar_exprs[rex_idx] = std::move(new_parent_rex);
2369  rex_idx++;
2370  }
2371  // Update the previous window project node
2372  window_func_project_node->setExpressions(window_func_scalar_exprs);
2373  window_func_project_node->replaceInput(prev_node, new_project);
2374  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2375  new_project->setPushedDownWindowExpr();
2376  }
2377  }
2378  nodes.assign(node_list.begin(), node_list.end());
2379 }
void propagate_hints_to_new_project(std::shared_ptr< RelProject > prev_node, std::shared_ptr< RelProject > new_node, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
Definition: RelAlgDag.cpp:2223
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1232 of file RelAlgDag.cpp.

References CHECK.

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

1233  {
1234  CHECK(json_str_arr.IsArray());
1235  std::vector<std::string> fields;
1236  for (auto json_str_arr_it = json_str_arr.Begin(); json_str_arr_it != json_str_arr.End();
1237  ++json_str_arr_it) {
1238  CHECK(json_str_arr_it->IsString());
1239  fields.emplace_back(json_str_arr_it->GetString());
1240  }
1241  return fields;
1242 }
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the caller graph for this function:

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

Definition at line 1297 of file RelAlgDag.cpp.

References ANTI, INNER, LEFT, and SEMI.

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

1297  {
1298  if (join_type_name == "inner") {
1299  return JoinType::INNER;
1300  }
1301  if (join_type_name == "left") {
1302  return JoinType::LEFT;
1303  }
1304  if (join_type_name == "semi") {
1305  return JoinType::SEMI;
1306  }
1307  if (join_type_name == "anti") {
1308  return JoinType::ANTI;
1309  }
1310  throw QueryNotSupported("Join type (" + join_type_name + ") not supported");
1311 }

+ Here is the caller graph for this function:

Variable Documentation

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

Definition at line 40 of file RelAlgDag.cpp.

Referenced by RelAlgNode::resetRelAlgFirstId().