OmniSciDB  a987f07e93
 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)
 
void reset_table_function_inputs (std::vector< const Rex * > &column_inputs, const std::vector< std::unique_ptr< const RexScalar >> &old_table_func_inputs, const std::vector< std::unique_ptr< const RexScalar >> &new_table_func_inputs)
 
std::set< std::pair< const
RelAlgNode *, int > > 
get_equiv_cols (const RelAlgNode *node, const size_t which_col)
 
std::vector< bool > get_notnulls (std::vector< TargetMetaInfo > const &tmis0)
 
bool same_ignoring_notnull (SQLTypeInfo ti0, SQLTypeInfo ti1)
 
void set_notnulls (std::vector< TargetMetaInfo > *tmis0, std::vector< bool > const &notnulls)
 
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 2483 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 2563 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

2567  {
2568  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2569  size_t project_node_counter{0};
2570  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2571  const auto node = *node_itr;
2572 
2573  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2574  if (!window_func_project_node) {
2575  continue;
2576  }
2577  project_node_counter++;
2578  if (!window_func_project_node->hasWindowFunctionExpr()) {
2579  // this projection node does not have a window function
2580  // expression -- skip to the next node in the DAG.
2581  continue;
2582  }
2583 
2584  const auto prev_node_itr = std::prev(node_itr);
2585  const auto prev_node = *prev_node_itr;
2586  CHECK(prev_node);
2587 
2588  auto filter_node = std::dynamic_pointer_cast<RelFilter>(prev_node);
2589  auto join_node = std::dynamic_pointer_cast<RelJoin>(prev_node);
2590 
2591  auto scan_node = std::dynamic_pointer_cast<RelScan>(prev_node);
2592  const bool has_multi_fragment_scan_input =
2593  (scan_node &&
2594  (scan_node->getNumShards() > 0 || scan_node->getNumFragments() > 1));
2595  auto const [has_generic_expr_in_window_func, needs_expr_pushdown] =
2596  need_pushdown_generic_expr(window_func_project_node.get());
2597 
2598  // We currently add a preceding project node in one of two conditions:
2599  // 1. always_add_project_if_first_project_is_window_expr = true, which
2600  // we currently only set for distributed, but could also be set to support
2601  // multi-frag window function inputs, either if we can detect that an input table
2602  // is multi-frag up front, or using a retry mechanism like we do for join filter
2603  // push down.
2604  // TODO(todd): Investigate a viable approach for the above.
2605  // 2. Regardless of #1, if the window function project node is preceded by a
2606  // filter node. This is required both for correctness and to avoid pulling
2607  // all source input columns into memory since non-coalesced filter node
2608  // inputs are currently not pruned or eliminated via dead column elimination.
2609  // Note that we expect any filter node followed by a project node to be coalesced
2610  // into a single compound node in RelAlgDag::coalesce_nodes, and that action
2611  // prunes unused inputs.
2612  // TODO(todd): Investigate whether the shotgun filter node issue affects other
2613  // query plans, i.e. filters before joins, and whether there is a more general
2614  // approach to solving this (will still need the preceding project node for
2615  // window functions preceded by filter nodes for correctness though)
2616  // 3. Similar to the above, when the window function project node is preceded
2617  // by a join node.
2618  // 4. when partition by / order by clauses have a general expression instead of
2619  // referencing column
2620 
2621  if (!((always_add_project_if_first_project_is_window_expr &&
2622  project_node_counter == 1) ||
2623  filter_node || join_node || has_multi_fragment_scan_input ||
2624  needs_expr_pushdown)) {
2625  continue;
2626  }
2627 
2628  if (needs_expr_pushdown || join_node) {
2629  // previous logic cannot cover join_node case well, so use the newly introduced
2630  // push-down expression logic to safely add pre_project node before processing
2631  // window function
2632  std::unordered_map<size_t, size_t> expr_offset_cache;
2633  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_for_new_project;
2634  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_for_window_project;
2635  std::vector<std::string> fields_for_window_project;
2636  std::vector<std::string> fields_for_new_project;
2637 
2638  // step 0. create new project node with an empty scalar expr to rebind target exprs
2639  std::vector<std::unique_ptr<const RexScalar>> dummy_scalar_exprs;
2640  std::vector<std::string> dummy_fields;
2641  auto new_project =
2642  std::make_shared<RelProject>(dummy_scalar_exprs, dummy_fields, prev_node);
2643 
2644  // step 1 - 2
2645  PushDownGenericExpressionInWindowFunction visitor(new_project,
2646  scalar_exprs_for_new_project,
2647  fields_for_new_project,
2648  expr_offset_cache);
2649  for (size_t i = 0; i < window_func_project_node->size(); ++i) {
2650  auto projected_target = window_func_project_node->getProjectAt(i);
2651  auto new_projection_target = visitor.visit(projected_target);
2652  scalar_exprs_for_window_project.emplace_back(
2653  std::move(new_projection_target.release()));
2654  }
2655  new_project->setExpressions(scalar_exprs_for_new_project);
2656  new_project->setFields(std::move(fields_for_new_project));
2657  bool has_groupby = false;
2658  auto aggregate = std::dynamic_pointer_cast<RelAggregate>(prev_node);
2659  if (aggregate) {
2660  has_groupby = aggregate->getGroupByCount() > 0;
2661  }
2662  // force rowwise output to prevent computing incorrect query result
2663  if (has_groupby && visitor.hasPartitionExpression()) {
2664  // we currently may compute incorrect result with columnar output when
2665  // 1) the window function has partition expression, and
2666  // 2) a parent node of the window function projection node has group by expression
2667  // todo (yoonmin) : relax this
2668  VLOG(1)
2669  << "Query output overridden to row-wise format due to presence of a window "
2670  "function with partition expression and group-by expression.";
2671  new_project->forceRowwiseOutput();
2672  } else if (has_generic_expr_in_window_func) {
2673  VLOG(1) << "Query output overridden to row-wise format due to presence of a "
2674  "generic expression as an input expression of the window "
2675  "function.";
2676  new_project->forceRowwiseOutput();
2677  } else if (visitor.hasCaseExprAsWindowOperand()) {
2678  VLOG(1)
2679  << "Query output overridden to row-wise format due to presence of a window "
2680  "function with a case statement as its operand.";
2681  new_project->forceRowwiseOutput();
2682  }
2683 
2684  // step 3. finalize
2685  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2686  new_project->setPushedDownWindowExpr();
2687  node_list.insert(node_itr, new_project);
2688  window_func_project_node->replaceInput(prev_node, new_project);
2689  window_func_project_node->setExpressions(scalar_exprs_for_window_project);
2690  } else {
2691  // only push rex_inputs listed in the window function down to a new project node
2692  RexInputSet inputs;
2693  RexInputCollector input_collector;
2694  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2695  auto new_inputs =
2696  input_collector.visit(window_func_project_node->getProjectAt(i));
2697  inputs.insert(new_inputs.begin(), new_inputs.end());
2698  }
2699 
2700  // Note: Technically not required since we are mapping old inputs to new input
2701  // indices, but makes the re-mapping of inputs easier to follow.
2702  std::vector<RexInput> sorted_inputs(inputs.begin(), inputs.end());
2703  std::sort(sorted_inputs.begin(),
2704  sorted_inputs.end(),
2705  [](const auto& a, const auto& b) { return a.getIndex() < b.getIndex(); });
2706 
2707  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs;
2708  std::vector<std::string> fields;
2709  std::unordered_map<unsigned, unsigned> old_index_to_new_index;
2710  for (auto& input : sorted_inputs) {
2711  CHECK_EQ(input.getSourceNode(), prev_node.get());
2712  CHECK(old_index_to_new_index
2713  .insert(std::make_pair(input.getIndex(), scalar_exprs.size()))
2714  .second);
2715  scalar_exprs.emplace_back(input.deepCopy());
2716  fields.emplace_back("");
2717  }
2718 
2719  auto new_project = std::make_shared<RelProject>(scalar_exprs, fields, prev_node);
2720  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2721  new_project->setPushedDownWindowExpr();
2722  node_list.insert(node_itr, new_project);
2723  window_func_project_node->replaceInput(
2724  prev_node, new_project, old_index_to_new_index);
2725  }
2726  }
2727  nodes.assign(node_list.begin(), node_list.end());
2728 }
const size_t getGroupByCount() const
Definition: RelAlgDag.h:1324
#define CHECK_EQ(x, y)
Definition: Logger.h:297
std::pair< bool, bool > need_pushdown_generic_expr(RelProject const *window_func_project_node)
Definition: RelAlgDag.cpp:2525
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:2325
constexpr double a
Definition: Utm.h:32
std::unordered_set< RexInput > RexInputSet
Definition: RelAlgDag.cpp:2483
#define CHECK(condition)
Definition: Logger.h:289
#define VLOG(n)
Definition: Logger.h:383

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

1507  {
1508  for (auto ra_node : nodes) {
1509  const auto filter_node = std::dynamic_pointer_cast<RelFilter>(ra_node);
1510  if (filter_node) {
1511  CHECK_EQ(size_t(1), filter_node->inputCount());
1512  auto disambiguated_condition = disambiguate_rex(
1513  filter_node->getCondition(), get_node_output(filter_node->getInput(0)));
1514  filter_node->setCondition(disambiguated_condition);
1515  continue;
1516  }
1517  const auto join_node = std::dynamic_pointer_cast<RelJoin>(ra_node);
1518  if (join_node) {
1519  CHECK_EQ(size_t(2), join_node->inputCount());
1520  auto disambiguated_condition =
1521  disambiguate_rex(join_node->getCondition(), get_node_output(join_node.get()));
1522  join_node->setCondition(disambiguated_condition);
1523  continue;
1524  }
1525  const auto project_node = std::dynamic_pointer_cast<RelProject>(ra_node);
1526  if (project_node) {
1527  bind_project_to_input(project_node.get(),
1528  get_node_output(project_node->getInput(0)));
1529  continue;
1530  }
1531  const auto table_func_node = std::dynamic_pointer_cast<RelTableFunction>(ra_node);
1532  if (table_func_node) {
1533  /*
1534  Collect all inputs from table function input (non-literal)
1535  arguments.
1536  */
1537  RANodeOutput input;
1538  input.reserve(table_func_node->inputCount());
1539  for (size_t i = 0; i < table_func_node->inputCount(); i++) {
1540  auto node_output = get_node_output(table_func_node->getInput(i));
1541  input.insert(input.end(), node_output.begin(), node_output.end());
1542  }
1543  bind_table_func_to_input(table_func_node.get(), input);
1544  }
1545  }
1546 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
std::vector< RexInput > RANodeOutput
Definition: RelAlgDag.h:3044
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1453
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1479
void bind_table_func_to_input(RelTableFunction *table_func_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1493
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 1479 of file RelAlgDag.cpp.

References CHECK_EQ, and disambiguate_rex().

Referenced by bind_inputs(), and create_compound().

1479  {
1480  CHECK_EQ(size_t(1), project_node->inputCount());
1481  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1482  for (size_t i = 0; i < project_node->size(); ++i) {
1483  const auto projected_expr = project_node->getProjectAt(i);
1484  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
1485  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
1486  } else {
1487  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
1488  }
1489  }
1490  project_node->setExpressions(disambiguated_exprs);
1491 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
size_t size() const override
Definition: RelAlgDag.h:1156
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1453
void setExpressions(std::vector< std::unique_ptr< const RexScalar >> &exprs) const
Definition: RelAlgDag.h:1136
const RexScalar * getProjectAtAndRelease(const size_t idx) const
Definition: RelAlgDag.h:1191
const RexScalar * getProjectAt(const size_t idx) const
Definition: RelAlgDag.h:1186
const size_t inputCount() const
Definition: RelAlgDag.h:890

+ 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 1493 of file RelAlgDag.cpp.

References disambiguate_rex().

Referenced by bind_inputs().

1494  {
1495  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1496  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
1497  const auto target_expr = table_func_node->getTableFuncInputAt(i);
1498  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
1499  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
1500  } else {
1501  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
1502  }
1503  }
1504  table_func_node->setTableFuncInputs(std::move(disambiguated_exprs));
1505 }
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1453
const RexScalar * getTableFuncInputAtAndRelease(const size_t idx)
Definition: RelAlgDag.h:2270
size_t getTableFuncInputsSize() const
Definition: RelAlgDag.h:2259
void setTableFuncInputs(std::vector< std::unique_ptr< const RexScalar >> &&exprs)
Definition: RelAlgDag.cpp:729
const RexScalar * getTableFuncInputAt(const size_t idx) const
Definition: RelAlgDag.h:2265

+ 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 2744 of file RelAlgDag.cpp.

References CHECK, and field().

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

2744  {
2745  const auto& inputs_json = field(node, "inputs");
2746  CHECK(inputs_json.IsArray() && !inputs_json.Size());
2747 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:289

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

2003  {
2004  enum class CoalesceState { Initial, Filter, FirstProject, Aggregate };
2005  std::vector<size_t> crt_pattern;
2006  CoalesceState crt_state{CoalesceState::Initial};
2007 
2008  auto reset_state = [&crt_pattern, &crt_state]() {
2009  crt_state = CoalesceState::Initial;
2010  std::vector<size_t>().swap(crt_pattern);
2011  };
2012 
2013  for (RANodeIterator nodeIt(nodes); !nodeIt.allVisited();) {
2014  const auto ra_node = nodeIt != nodes.end() ? *nodeIt : nullptr;
2015  switch (crt_state) {
2016  case CoalesceState::Initial: {
2017  if (std::dynamic_pointer_cast<const RelFilter>(ra_node) &&
2018  std::find(left_deep_joins.begin(), left_deep_joins.end(), ra_node.get()) ==
2019  left_deep_joins.end()) {
2020  crt_pattern.push_back(size_t(nodeIt));
2021  crt_state = CoalesceState::Filter;
2022  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
2023  } else if (auto project_node =
2024  std::dynamic_pointer_cast<const RelProject>(ra_node)) {
2025  if (project_node->hasWindowFunctionExpr()) {
2026  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
2027  } else {
2028  crt_pattern.push_back(size_t(nodeIt));
2029  crt_state = CoalesceState::FirstProject;
2030  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
2031  }
2032  } else {
2033  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
2034  }
2035  break;
2036  }
2037  case CoalesceState::Filter: {
2038  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
2039  // Given we now add preceding projects for all window functions following
2040  // RelFilter nodes, the following should never occur
2041  CHECK(!project_node->hasWindowFunctionExpr());
2042  crt_pattern.push_back(size_t(nodeIt));
2043  crt_state = CoalesceState::FirstProject;
2044  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
2045  } else {
2046  reset_state();
2047  }
2048  break;
2049  }
2050  case CoalesceState::FirstProject: {
2051  if (std::dynamic_pointer_cast<const RelAggregate>(ra_node)) {
2052  crt_pattern.push_back(size_t(nodeIt));
2053  crt_state = CoalesceState::Aggregate;
2054  nodeIt.advance(RANodeIterator::AdvancingMode::DUChain);
2055  } else {
2056  if (crt_pattern.size() >= 2) {
2057  create_compound(nodes, crt_pattern, query_hints);
2058  }
2059  reset_state();
2060  }
2061  break;
2062  }
2063  case CoalesceState::Aggregate: {
2064  if (auto project_node = std::dynamic_pointer_cast<const RelProject>(ra_node)) {
2065  if (!project_node->hasWindowFunctionExpr()) {
2066  // TODO(adb): overloading the simple project terminology again here
2067  bool is_simple_project{true};
2068  for (size_t i = 0; i < project_node->size(); i++) {
2069  const auto scalar_rex = project_node->getProjectAt(i);
2070  // If the top level scalar rex is an input node, we can bypass the visitor
2071  if (auto input_rex = dynamic_cast<const RexInput*>(scalar_rex)) {
2073  input_rex->getSourceNode(), input_rex->getIndex(), true)) {
2074  is_simple_project = false;
2075  break;
2076  }
2077  continue;
2078  }
2079  CoalesceSecondaryProjectVisitor visitor;
2080  if (!visitor.visit(project_node->getProjectAt(i))) {
2081  is_simple_project = false;
2082  break;
2083  }
2084  }
2085  if (is_simple_project) {
2086  crt_pattern.push_back(size_t(nodeIt));
2087  nodeIt.advance(RANodeIterator::AdvancingMode::InOrder);
2088  }
2089  }
2090  }
2091  CHECK_GE(crt_pattern.size(), size_t(2));
2092  create_compound(nodes, crt_pattern, query_hints);
2093  reset_state();
2094  break;
2095  }
2096  default:
2097  CHECK(false);
2098  }
2099  }
2100  if (crt_state == CoalesceState::FirstProject || crt_state == CoalesceState::Aggregate) {
2101  if (crt_pattern.size() >= 2) {
2102  create_compound(nodes, crt_pattern, query_hints);
2103  }
2104  CHECK(!crt_pattern.empty());
2105  }
2106 }
bool input_can_be_coalesced(const RelAlgNode *parent_node, const size_t index, const bool first_rex_is_input)
Definition: RelAlgDag.cpp:1899
#define CHECK_GE(x, y)
Definition: Logger.h:302
#define CHECK(condition)
Definition: Logger.h:289
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:1660
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 1586 of file RelAlgDag.cpp.

References CHECK_NE.

Referenced by RelAlgDagBuilder::optimizeDag().

1586  {
1587  // compute each rel node's hash value in advance to avoid inconsistency of their hash
1588  // values depending on the toHash's caller
1589  // specifically, we manipulate our logical query plan before retrieving query step
1590  // sequence but once we compute a hash value we cached it so there is no way to update
1591  // it after the plan has been changed starting from the top node, we compute the hash
1592  // value (top-down manner)
1593  std::for_each(
1594  nodes.rbegin(), nodes.rend(), [](const std::shared_ptr<RelAlgNode>& node) {
1595  auto node_hash = node->toHash();
1596  CHECK_NE(node_hash, static_cast<size_t>(0));
1597  });
1598 }
#define CHECK_NE(x, y)
Definition: Logger.h:298

+ 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 616 of file RelAlgDag.cpp.

617  {
618  std::vector<std::unique_ptr<const RexAgg>> agg_exprs_copy;
619  agg_exprs_copy.reserve(agg_exprs.size());
620  for (auto const& agg_expr : agg_exprs) {
621  agg_exprs_copy.push_back(agg_expr->deepCopy());
622  }
623  return agg_exprs_copy;
624 }
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 626 of file RelAlgDag.cpp.

References RexVisitorBase< T >::visit().

627  {
628  std::vector<std::unique_ptr<const RexScalar>> scalar_sources_copy;
629  scalar_sources_copy.reserve(scalar_sources.size());
630  RexDeepCopyVisitor copier;
631  for (auto const& scalar_source : scalar_sources) {
632  scalar_sources_copy.push_back(copier.visit(scalar_source.get()));
633  }
634  return scalar_sources_copy;
635 }
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 1660 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().

1664  {
1665  CHECK_GE(pattern.size(), size_t(2));
1666  CHECK_LE(pattern.size(), size_t(4));
1667 
1668  std::unique_ptr<const RexScalar> filter_rex;
1669  std::vector<std::unique_ptr<const RexScalar>> scalar_sources;
1670  size_t groupby_count{0};
1671  std::vector<std::string> fields;
1672  std::vector<const RexAgg*> agg_exprs;
1673  std::vector<const Rex*> target_exprs;
1674  bool first_project{true};
1675  bool is_agg{false};
1676  RelAlgNode* last_node{nullptr};
1677 
1678  std::shared_ptr<ModifyManipulationTarget> manipulation_target;
1679  size_t node_hash{0};
1680  unsigned node_id{0};
1681  bool hint_registered{false};
1682  RegisteredQueryHint registered_query_hint = RegisteredQueryHint::defaults();
1683  for (const auto node_idx : pattern) {
1684  const auto ra_node = nodes[node_idx];
1685  auto registered_query_hint_map_it = query_hints.find(ra_node->toHash());
1686  if (registered_query_hint_map_it != query_hints.end()) {
1687  auto& registered_query_hint_map = registered_query_hint_map_it->second;
1688  auto registered_query_hint_it = registered_query_hint_map.find(ra_node->getId());
1689  if (registered_query_hint_it != registered_query_hint_map.end()) {
1690  hint_registered = true;
1691  node_hash = registered_query_hint_map_it->first;
1692  node_id = registered_query_hint_it->first;
1693  registered_query_hint = registered_query_hint_it->second;
1694  }
1695  }
1696  const auto ra_filter = std::dynamic_pointer_cast<RelFilter>(ra_node);
1697  if (ra_filter) {
1698  CHECK(!filter_rex);
1699  filter_rex.reset(ra_filter->getAndReleaseCondition());
1700  CHECK(filter_rex);
1701  last_node = ra_node.get();
1702  continue;
1703  }
1704  const auto ra_project = std::dynamic_pointer_cast<RelProject>(ra_node);
1705  if (ra_project) {
1706  fields = ra_project->getFields();
1707  manipulation_target = ra_project;
1708 
1709  if (first_project) {
1710  CHECK_EQ(size_t(1), ra_project->inputCount());
1711  // Rebind the input of the project to the input of the filter itself
1712  // since we know that we'll evaluate the filter on the fly, with no
1713  // intermediate buffer.
1714  const auto filter_input = dynamic_cast<const RelFilter*>(ra_project->getInput(0));
1715  if (filter_input) {
1716  CHECK_EQ(size_t(1), filter_input->inputCount());
1717  bind_project_to_input(ra_project.get(),
1718  get_node_output(filter_input->getInput(0)));
1719  }
1720  scalar_sources = ra_project->getExpressionsAndRelease();
1721  for (const auto& scalar_expr : scalar_sources) {
1722  target_exprs.push_back(scalar_expr.get());
1723  }
1724  first_project = false;
1725  } else {
1726  if (ra_project->isSimple()) {
1727  target_exprs = reproject_targets(ra_project.get(), target_exprs);
1728  } else {
1729  // TODO(adb): This is essentially a more general case of simple project, we
1730  // could likely merge the two
1731  std::vector<const Rex*> result;
1732  RexInputReplacementVisitor visitor(last_node, scalar_sources);
1733  for (size_t i = 0; i < ra_project->size(); ++i) {
1734  const auto rex = ra_project->getProjectAt(i);
1735  if (auto rex_input = dynamic_cast<const RexInput*>(rex)) {
1736  const auto index = rex_input->getIndex();
1737  CHECK_LT(index, target_exprs.size());
1738  result.push_back(target_exprs[index]);
1739  } else {
1740  scalar_sources.push_back(visitor.visit(rex));
1741  result.push_back(scalar_sources.back().get());
1742  }
1743  }
1744  target_exprs = result;
1745  }
1746  }
1747  last_node = ra_node.get();
1748  continue;
1749  }
1750  const auto ra_aggregate = std::dynamic_pointer_cast<RelAggregate>(ra_node);
1751  if (ra_aggregate) {
1752  is_agg = true;
1753  fields = ra_aggregate->getFields();
1754  agg_exprs = ra_aggregate->getAggregatesAndRelease();
1755  groupby_count = ra_aggregate->getGroupByCount();
1756  decltype(target_exprs){}.swap(target_exprs);
1757  CHECK_LE(groupby_count, scalar_sources.size());
1758  for (size_t group_idx = 0; group_idx < groupby_count; ++group_idx) {
1759  const auto rex_ref = new RexRef(group_idx + 1);
1760  target_exprs.push_back(rex_ref);
1761  scalar_sources.emplace_back(rex_ref);
1762  }
1763  for (const auto rex_agg : agg_exprs) {
1764  target_exprs.push_back(rex_agg);
1765  }
1766  last_node = ra_node.get();
1767  continue;
1768  }
1769  }
1770 
1771  auto compound_node =
1772  std::make_shared<RelCompound>(filter_rex,
1773  target_exprs,
1774  groupby_count,
1775  agg_exprs,
1776  fields,
1777  scalar_sources,
1778  is_agg,
1779  manipulation_target->isUpdateViaSelect(),
1780  manipulation_target->isDeleteViaSelect(),
1781  manipulation_target->isVarlenUpdateRequired(),
1782  manipulation_target->getModifiedTableDescriptor(),
1783  manipulation_target->getTargetColumns());
1784  auto old_node = nodes[pattern.back()];
1785  nodes[pattern.back()] = compound_node;
1786  auto first_node = nodes[pattern.front()];
1787  CHECK_EQ(size_t(1), first_node->inputCount());
1788  compound_node->addManagedInput(first_node->getAndOwnInput(0));
1789  if (hint_registered) {
1790  // pass the registered hint from the origin node to newly created compound node
1791  // where it is coalesced
1792  auto registered_query_hint_map_it = query_hints.find(node_hash);
1793  CHECK(registered_query_hint_map_it != query_hints.end());
1794  auto registered_query_hint_map = registered_query_hint_map_it->second;
1795  if (registered_query_hint_map.size() > 1) {
1796  registered_query_hint_map.erase(node_id);
1797  } else {
1798  CHECK_EQ(registered_query_hint_map.size(), static_cast<size_t>(1));
1799  query_hints.erase(node_hash);
1800  }
1801  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
1802  hint_map.emplace(compound_node->getId(), registered_query_hint);
1803  query_hints.emplace(compound_node->toHash(), hint_map);
1804  }
1805  for (size_t i = 0; i < pattern.size() - 1; ++i) {
1806  nodes[pattern[i]].reset();
1807  }
1808  for (auto node : nodes) {
1809  if (!node) {
1810  continue;
1811  }
1812  node->replaceInput(old_node, compound_node);
1813  }
1814 }
bool is_agg(const Analyzer::Expr *expr)
#define CHECK_EQ(x, y)
Definition: Logger.h:297
#define CHECK_GE(x, y)
Definition: Logger.h:302
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1479
#define CHECK_LT(x, y)
Definition: Logger.h:299
static RegisteredQueryHint defaults()
Definition: QueryHint.h:329
std::vector< const Rex * > reproject_targets(const RelProject *simple_project, const std::vector< const Rex * > &target_exprs) noexcept
Definition: RelAlgDag.cpp:1617
#define CHECK_LE(x, y)
Definition: Logger.h:300
const std::vector< std::string > & getFields() const
Definition: RelAlgDag.h:1200
#define CHECK(condition)
Definition: Logger.h:289
unsigned node_id(const rapidjson::Value &ra_node) noexcept
Definition: RelAlgDag.cpp:957
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 1432 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

1433  {
1434  std::vector<
1435  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1436  disambiguated_expr_pair_list;
1437  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1438  auto disambiguated_when = disambiguate_rex(rex_case->getWhen(i), ra_output);
1439  auto disambiguated_then = disambiguate_rex(rex_case->getThen(i), ra_output);
1440  disambiguated_expr_pair_list.emplace_back(std::move(disambiguated_when),
1441  std::move(disambiguated_then));
1442  }
1443  std::unique_ptr<const RexScalar> disambiguated_else{
1444  disambiguate_rex(rex_case->getElse(), ra_output)};
1445  return std::unique_ptr<const RexCase>(
1446  new RexCase(disambiguated_expr_pair_list, disambiguated_else));
1447 }
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:443
const RexScalar * getElse() const
Definition: RelAlgDag.h:448
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:438
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1453
size_t branchCount() const
Definition: RelAlgDag.h:436

+ 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 1397 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

1399  {
1400  std::vector<std::unique_ptr<const RexScalar>> disambiguated_operands;
1401  for (size_t i = 0; i < rex_operator->size(); ++i) {
1402  auto operand = rex_operator->getOperand(i);
1403  if (dynamic_cast<const RexSubQuery*>(operand)) {
1404  disambiguated_operands.emplace_back(rex_operator->getOperandAndRelease(i));
1405  } else {
1406  disambiguated_operands.emplace_back(disambiguate_rex(operand, ra_output));
1407  }
1408  }
1409  const auto rex_window_function_operator =
1410  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
1411  if (rex_window_function_operator) {
1412  const auto& partition_keys = rex_window_function_operator->getPartitionKeys();
1413  std::vector<std::unique_ptr<const RexScalar>> disambiguated_partition_keys;
1414  for (const auto& partition_key : partition_keys) {
1415  disambiguated_partition_keys.emplace_back(
1416  disambiguate_rex(partition_key.get(), ra_output));
1417  }
1418  std::vector<std::unique_ptr<const RexScalar>> disambiguated_order_keys;
1419  const auto& order_keys = rex_window_function_operator->getOrderKeys();
1420  for (const auto& order_key : order_keys) {
1421  disambiguated_order_keys.emplace_back(disambiguate_rex(order_key.get(), ra_output));
1422  }
1423  return rex_window_function_operator->disambiguatedOperands(
1424  disambiguated_operands,
1425  disambiguated_partition_keys,
1426  disambiguated_order_keys,
1427  rex_window_function_operator->getCollation());
1428  }
1429  return rex_operator->getDisambiguated(disambiguated_operands);
1430 }
size_t size() const
Definition: RelAlgDag.h:270
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:272
const RexScalar * getOperandAndRelease(const size_t idx) const
Definition: RelAlgDag.h:277
virtual std::unique_ptr< const RexOperator > getDisambiguated(std::vector< std::unique_ptr< const RexScalar >> &operands) const
Definition: RelAlgDag.h:265
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1453
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:627

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

1454  {
1455  const auto rex_abstract_input = dynamic_cast<const RexAbstractInput*>(rex_scalar);
1456  if (rex_abstract_input) {
1457  CHECK_LT(static_cast<size_t>(rex_abstract_input->getIndex()), ra_output.size());
1458  return std::unique_ptr<const RexInput>(
1459  new RexInput(ra_output[rex_abstract_input->getIndex()]));
1460  }
1461  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
1462  if (rex_operator) {
1463  return disambiguate_operator(rex_operator, ra_output);
1464  }
1465  const auto rex_case = dynamic_cast<const RexCase*>(rex_scalar);
1466  if (rex_case) {
1467  return disambiguate_case(rex_case, ra_output);
1468  }
1469  if (auto const rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar)) {
1470  return rex_literal->deepCopy();
1471  } else if (auto const rex_subquery = dynamic_cast<const RexSubQuery*>(rex_scalar)) {
1472  return rex_subquery->deepCopy();
1473  } else {
1474  throw QueryNotSupported("Unable to disambiguate expression of type " +
1475  std::string(typeid(*rex_scalar).name()));
1476  }
1477 }
std::unique_ptr< const RexOperator > disambiguate_operator(const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
Definition: RelAlgDag.cpp:1397
std::unique_ptr< const RexCase > disambiguate_case(const RexCase *rex_case, const RANodeOutput &ra_output)
Definition: RelAlgDag.cpp:1432
#define CHECK_LT(x, y)
Definition: Logger.h:299

+ 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 763 of file RelAlgDag.cpp.

References CHECK, and CHECK_EQ.

Referenced by RelSort::hasEquivCollationOf().

764  {
765  std::set<std::pair<const RelAlgNode*, int>> work_set;
766  auto walker = node;
767  auto curr_col = which_col;
768  while (true) {
769  work_set.insert(std::make_pair(walker, curr_col));
770  if (dynamic_cast<const RelScan*>(walker) || dynamic_cast<const RelJoin*>(walker)) {
771  break;
772  }
773  CHECK_EQ(size_t(1), walker->inputCount());
774  auto only_source = walker->getInput(0);
775  if (auto project = dynamic_cast<const RelProject*>(walker)) {
776  if (auto input = dynamic_cast<const RexInput*>(project->getProjectAt(curr_col))) {
777  const auto join_source = dynamic_cast<const RelJoin*>(only_source);
778  if (join_source) {
779  CHECK_EQ(size_t(2), join_source->inputCount());
780  auto lhs = join_source->getInput(0);
781  CHECK((input->getIndex() < lhs->size() && lhs == input->getSourceNode()) ||
782  join_source->getInput(1) == input->getSourceNode());
783  } else {
784  CHECK_EQ(input->getSourceNode(), only_source);
785  }
786  curr_col = input->getIndex();
787  } else {
788  break;
789  }
790  } else if (auto aggregate = dynamic_cast<const RelAggregate*>(walker)) {
791  if (curr_col >= aggregate->getGroupByCount()) {
792  break;
793  }
794  }
795  walker = only_source;
796  }
797  return work_set;
798 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
#define CHECK(condition)
Definition: Logger.h:289

+ 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 2730 of file RelAlgDag.cpp.

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

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

2732  {
2733  const auto it = obj.FindMember(field);
2734  if (it == obj.MemberEnd()) {
2735  return default_val;
2736  }
2737  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
2738  CHECK_EQ(kDECIMAL, lit->getType());
2739  CHECK_EQ(unsigned(0), lit->getScale());
2740  CHECK_EQ(unsigned(0), lit->getTargetScale());
2741  return lit->getVal<int64_t>();
2742 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
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:979

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector<bool> anonymous_namespace{RelAlgDag.cpp}::get_notnulls ( std::vector< TargetMetaInfo > const &  tmis0)

Definition at line 882 of file RelAlgDag.cpp.

Referenced by RelLogicalUnion::getCompatibleMetainfoTypes().

882  {
883  std::vector<bool> notnulls(tmis0.size());
884  for (size_t j = 0; j < tmis0.size(); ++j) {
885  notnulls[j] = tmis0[j].get_type_info().get_notnull();
886  }
887  return notnulls;
888 }

+ 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 2759 of file RelAlgDag.cpp.

References field(), and strings_from_json_array().

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

2759  {
2760  const auto& fields_json = field(scan_ra, "fieldNames");
2761  return strings_from_json_array(fields_json);
2762 }
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:1313

+ 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 2749 of file RelAlgDag.cpp.

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

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

2750  {
2751  const auto& table_json = field(scan_ra, "table");
2752  CHECK(table_json.IsArray());
2753  CHECK_EQ(unsigned(2), table_json.Size());
2754  const auto td = cat.getMetadataForTable(table_json[1].GetString());
2755  CHECK(td);
2756  return td;
2757 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:289
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 1548 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

1549  {
1550  // query hint is delivered by the above three nodes
1551  // when a query block has top-sort node, a hint is registered to
1552  // one of the node which locates at the nearest from the sort node
1553  RegisteredQueryHint global_query_hint;
1554  for (auto node : nodes) {
1555  Hints* hint_delivered = nullptr;
1556  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1557  if (agg_node) {
1558  if (agg_node->hasDeliveredHint()) {
1559  hint_delivered = agg_node->getDeliveredHints();
1560  }
1561  }
1562  const auto project_node = std::dynamic_pointer_cast<RelProject>(node);
1563  if (project_node) {
1564  if (project_node->hasDeliveredHint()) {
1565  hint_delivered = project_node->getDeliveredHints();
1566  }
1567  }
1568  const auto compound_node = std::dynamic_pointer_cast<RelCompound>(node);
1569  if (compound_node) {
1570  if (compound_node->hasDeliveredHint()) {
1571  hint_delivered = compound_node->getDeliveredHints();
1572  }
1573  }
1574  if (hint_delivered && !hint_delivered->empty()) {
1575  rel_alg_dag.registerQueryHints(node, hint_delivered, global_query_hint);
1576  }
1577  }
1578  // the current rel_alg_dag may contain global query hints from the subquery
1579  // so we combine the current global hint we collected with the original one together
1580  // to propagate global query hints correctly
1581  const auto existing_global_query_hints = rel_alg_dag.getGlobalHints();
1582  const auto new_global_query_hints = existing_global_query_hints || global_query_hint;
1583  rel_alg_dag.setGlobalQueryHints(new_global_query_hints);
1584 }
void setGlobalQueryHints(const RegisteredQueryHint &global_hints)
Definition: RelAlgDag.h:2949
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1274
const RegisteredQueryHint & getGlobalHints() const
Definition: RelAlgDag.h:2947
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1421
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1891
std::unordered_map< QueryHint, ExplainedQueryHint > Hints
Definition: QueryHint.h:355
void registerQueryHints(std::shared_ptr< RelAlgNode > node, Hints *hints_delivered, RegisteredQueryHint &global_query_hint)
Definition: RelAlgDag.h:2517

+ 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 1325 of file RelAlgDag.cpp.

References CHECK, and CHECK_GE.

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

1326  {
1327  CHECK(json_idx_arr.IsArray());
1328  std::vector<size_t> indices;
1329  for (auto json_idx_arr_it = json_idx_arr.Begin(); json_idx_arr_it != json_idx_arr.End();
1330  ++json_idx_arr_it) {
1331  CHECK(json_idx_arr_it->IsInt());
1332  CHECK_GE(json_idx_arr_it->GetInt(), 0);
1333  indices.emplace_back(json_idx_arr_it->GetInt());
1334  }
1335  return indices;
1336 }
#define CHECK_GE(x, y)
Definition: Logger.h:302
#define CHECK(condition)
Definition: Logger.h:289

+ 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:297
std::string join(T const &container, std::string const &delim)
#define CHECK_GE(x, y)
Definition: Logger.h:302
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:892
#define CHECK_LT(x, y)
Definition: Logger.h:299
virtual size_t size() const =0
#define CHECK(condition)
Definition: Logger.h:289

+ 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 962 of file RelAlgDag.cpp.

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

962  {
963  rapidjson::StringBuffer buffer;
964  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
965  node.Accept(writer);
966  return buffer.GetString();
967 }

+ 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 1600 of file RelAlgDag.cpp.

References CHECK_EQ, and RelAlgNode::markAsNop().

Referenced by RelAlgDagBuilder::optimizeDag().

1600  {
1601  for (auto node : nodes) {
1602  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1603  if (!agg_node || agg_node->getAggExprsCount()) {
1604  continue;
1605  }
1606  CHECK_EQ(size_t(1), node->inputCount());
1607  const auto agg_input_node = dynamic_cast<const RelAggregate*>(node->getInput(0));
1608  if (agg_input_node && !agg_input_node->getAggExprsCount() &&
1609  agg_node->getGroupByCount() == agg_input_node->getGroupByCount()) {
1610  agg_node->markAsNop();
1611  }
1612  }
1613 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
void markAsNop()
Definition: RelAlgDag.h:932

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

957  {
958  const auto& id = field(ra_node, "id");
959  return std::stoi(json_str(id));
960 }
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 973 of file RelAlgDag.cpp.

References field(), and json_i64().

Referenced by parse_scalar_expr().

974  {
975  const auto& input = field(expr, "input");
976  return std::unique_ptr<RexAbstractInput>(new RexAbstractInput(json_i64(input)));
977 }
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 1338 of file RelAlgDag.cpp.

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

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

1338  {
1339  const auto agg_str = json_str(field(expr, "agg"));
1340  if (agg_str == "APPROX_QUANTILE") {
1341  LOG(INFO) << "APPROX_QUANTILE is deprecated. Please use APPROX_PERCENTILE instead.";
1342  }
1343  const auto agg = to_agg_kind(agg_str);
1344  const auto distinct = json_bool(field(expr, "distinct"));
1345  const auto agg_ti = parse_type(field(expr, "type"));
1346  const auto operands = indices_from_json_array(field(expr, "operands"));
1347  bool const allow_multiple_args =
1348  shared::is_any<kAPPROX_COUNT_DISTINCT, kAPPROX_QUANTILE, kSUM_IF>(agg);
1349  if (operands.size() > 1 && (operands.size() != 2 || !allow_multiple_args)) {
1350  throw QueryNotSupported("Multiple arguments for aggregates aren't supported");
1351  }
1352  return std::unique_ptr<const RexAgg>(new RexAgg(agg, distinct, agg_ti, operands));
1353 }
SQLAgg to_agg_kind(const std::string &agg_name)
#define LOG(tag)
Definition: Logger.h:283
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:1325
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:1065

+ 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 1291 of file RelAlgDag.cpp.

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

Referenced by parse_scalar_expr().

1293  {
1294  const auto& operands = field(expr, "operands");
1295  CHECK(operands.IsArray());
1296  CHECK_GE(operands.Size(), unsigned(2));
1297  std::unique_ptr<const RexScalar> else_expr;
1298  std::vector<
1299  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1300  expr_pair_list;
1301  for (auto operands_it = operands.Begin(); operands_it != operands.End();) {
1302  auto when_expr = parse_scalar_expr(*operands_it++, cat, root_dag);
1303  if (operands_it == operands.End()) {
1304  else_expr = std::move(when_expr);
1305  break;
1306  }
1307  auto then_expr = parse_scalar_expr(*operands_it++, cat, root_dag);
1308  expr_pair_list.emplace_back(std::move(when_expr), std::move(then_expr));
1309  }
1310  return std::unique_ptr<RexCase>(new RexCase(expr_pair_list, else_expr));
1311 }
#define CHECK_GE(x, y)
Definition: Logger.h:302
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1355
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
#define CHECK(condition)
Definition: Logger.h:289

+ 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 1084 of file RelAlgDag.cpp.

References parse_scalar_expr().

Referenced by parse_operator().

1087  {
1088  std::vector<std::unique_ptr<const RexScalar>> exprs;
1089  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1090  exprs.emplace_back(parse_scalar_expr(*it, cat, root_dag));
1091  }
1092  return exprs;
1093 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1355

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

979  {
980  CHECK(expr.IsObject());
981  const auto& literal = field(expr, "literal");
982  const auto type = to_sql_type(json_str(field(expr, "type")));
983  const auto target_type = to_sql_type(json_str(field(expr, "target_type")));
984  const auto scale = json_i64(field(expr, "scale"));
985  const auto precision = json_i64(field(expr, "precision"));
986  const auto type_scale = json_i64(field(expr, "type_scale"));
987  const auto type_precision = json_i64(field(expr, "type_precision"));
988  if (literal.IsNull()) {
989  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
990  }
991  switch (type) {
992  case kINT:
993  case kBIGINT:
994  case kDECIMAL:
995  case kINTERVAL_DAY_TIME:
997  case kTIME:
998  case kTIMESTAMP:
999  case kDATE:
1000  return std::unique_ptr<RexLiteral>(new RexLiteral(json_i64(literal),
1001  type,
1002  target_type,
1003  scale,
1004  precision,
1005  type_scale,
1006  type_precision));
1007  case kDOUBLE: {
1008  if (literal.IsDouble()) {
1009  return std::unique_ptr<RexLiteral>(new RexLiteral(json_double(literal),
1010  type,
1011  target_type,
1012  scale,
1013  precision,
1014  type_scale,
1015  type_precision));
1016  } else if (literal.IsInt64()) {
1017  return std::make_unique<RexLiteral>(static_cast<double>(literal.GetInt64()),
1018  type,
1019  target_type,
1020  scale,
1021  precision,
1022  type_scale,
1023  type_precision);
1024 
1025  } else if (literal.IsUint64()) {
1026  return std::make_unique<RexLiteral>(static_cast<double>(literal.GetUint64()),
1027  type,
1028  target_type,
1029  scale,
1030  precision,
1031  type_scale,
1032  type_precision);
1033  }
1034  UNREACHABLE() << "Unhandled type: " << literal.GetType();
1035  }
1036  case kTEXT:
1037  return std::unique_ptr<RexLiteral>(new RexLiteral(json_str(literal),
1038  type,
1039  target_type,
1040  scale,
1041  precision,
1042  type_scale,
1043  type_precision));
1044  case kBOOLEAN:
1045  return std::unique_ptr<RexLiteral>(new RexLiteral(json_bool(literal),
1046  type,
1047  target_type,
1048  scale,
1049  precision,
1050  type_scale,
1051  type_precision));
1052  case kNULLT:
1053  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
1054  default:
1055  CHECK(false);
1056  }
1057  CHECK(false);
1058  return nullptr;
1059 }
SQLTypes to_sql_type(const std::string &type_name)
Definition: sqltypes.h:64
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:333
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:67
Definition: sqltypes.h:68
#define CHECK(condition)
Definition: Logger.h:289
Definition: sqltypes.h:60

+ 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 1179 of file RelAlgDag.cpp.

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

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

1179  {
1180  return json_str(field(collation, "nulls")) == std::string("FIRST")
1183 }
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 1246 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().

1248  {
1249  const auto op_name = json_str(field(expr, "op"));
1250  const bool is_quantifier =
1251  op_name == std::string("PG_ANY") || op_name == std::string("PG_ALL");
1252  const auto op = is_quantifier ? kFUNCTION : to_sql_op(op_name);
1253  const auto& operators_json_arr = field(expr, "operands");
1254  CHECK(operators_json_arr.IsArray());
1255  auto operands = parse_expr_array(operators_json_arr, cat, root_dag);
1256  const auto type_it = expr.FindMember("type");
1257  CHECK(type_it != expr.MemberEnd());
1258  auto ti = parse_type(type_it->value);
1259  if (op == kIN && expr.HasMember("subquery")) {
1260  auto subquery = parse_subquery(expr, cat, root_dag);
1261  operands.emplace_back(std::move(subquery));
1262  }
1263  if (expr.FindMember("partition_keys") != expr.MemberEnd()) {
1264  const auto& partition_keys_arr = field(expr, "partition_keys");
1265  auto partition_keys = parse_expr_array(partition_keys_arr, cat, root_dag);
1266  const auto& order_keys_arr = field(expr, "order_keys");
1267  auto order_keys = parse_window_order_exprs(order_keys_arr, cat, root_dag);
1268  const auto collation = parse_window_order_collation(order_keys_arr, cat, root_dag);
1269  const auto kind = parse_window_function_kind(op_name);
1270  const auto lower_bound =
1271  parse_window_bound(field(expr, "lower_bound"), cat, root_dag);
1272  const auto upper_bound =
1273  parse_window_bound(field(expr, "upper_bound"), cat, root_dag);
1274  bool is_rows = json_bool(field(expr, "is_rows"));
1275  ti.set_notnull(false);
1276  return std::make_unique<RexWindowFunctionOperator>(kind,
1277  operands,
1278  partition_keys,
1279  order_keys,
1280  collation,
1281  lower_bound,
1282  upper_bound,
1283  is_rows,
1284  ti);
1285  }
1286  return std::unique_ptr<RexOperator>(op == kFUNCTION
1287  ? new RexFunctionOperator(op_name, operands, ti)
1288  : new RexOperator(op, operands, ti));
1289 }
DEVICE auto upper_bound(ARGS &&...args)
Definition: gpu_enabled.h:123
SqlWindowFunctionKind parse_window_function_kind(const std::string &name)
Definition: RelAlgDag.cpp:1095
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1218
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:1162
std::vector< SortField > parse_window_order_collation(const rapidjson::Value &arr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1185
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:1065
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:1084
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:1198
#define CHECK(condition)
Definition: Logger.h:289

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

1357  {
1358  CHECK(expr.IsObject());
1359  if (expr.IsObject() && expr.HasMember("input")) {
1360  return std::unique_ptr<const RexScalar>(parse_abstract_input(expr));
1361  }
1362  if (expr.IsObject() && expr.HasMember("literal")) {
1363  return std::unique_ptr<const RexScalar>(parse_literal(expr));
1364  }
1365  if (expr.IsObject() && expr.HasMember("op")) {
1366  const auto op_str = json_str(field(expr, "op"));
1367  if (op_str == std::string("CASE")) {
1368  return std::unique_ptr<const RexScalar>(parse_case(expr, cat, root_dag));
1369  }
1370  if (op_str == std::string("$SCALAR_QUERY")) {
1371  return std::unique_ptr<const RexScalar>(parse_subquery(expr, cat, root_dag));
1372  }
1373  return std::unique_ptr<const RexScalar>(parse_operator(expr, cat, root_dag));
1374  }
1375  throw QueryNotSupported("Expression node " + json_node_to_string(expr) +
1376  " not supported");
1377 }
std::unique_ptr< RexOperator > parse_operator(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1246
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1218
std::string json_node_to_string(const rapidjson::Value &node) noexcept
Definition: RelAlgDag.cpp:962
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:973
std::unique_ptr< RexCase > parse_case(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1291
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:979
#define CHECK(condition)
Definition: Logger.h:289

+ 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 1173 of file RelAlgDag.cpp.

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

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

1173  {
1174  return json_str(field(collation, "direction")) == std::string("DESCENDING")
1177 }
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 1218 of file RelAlgDag.cpp.

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

Referenced by parse_operator(), and parse_scalar_expr().

1220  {
1221  const auto& operands = field(expr, "operands");
1222  CHECK(operands.IsArray());
1223  CHECK_GE(operands.Size(), unsigned(0));
1224  const auto& subquery_ast = field(expr, "subquery");
1225 
1226  auto subquery_dag = RelAlgDagBuilder::buildDagForSubquery(root_dag, subquery_ast, cat);
1227  const auto subquery_root_node = subquery_dag->getRootNodeShPtr();
1228  auto subquery = std::make_shared<RexSubQuery>(subquery_root_node);
1229  auto query_hint = subquery_dag->getQueryHint(subquery_dag->getRootNodeShPtr().get());
1230  root_dag.registerSubquery(subquery);
1231  const auto subquery_global_hint = subquery_dag->getGlobalHints();
1232  if (subquery_global_hint.isAnyQueryHintDelivered()) {
1233  // we need to propagate global query hint found in this subquery to its parent
1234  const auto new_global_hint = root_dag.getGlobalHints() || subquery_global_hint;
1235  root_dag.setGlobalQueryHints(new_global_hint);
1236  }
1237  const auto subquery_local_hint = subquery_dag->getQueryHint(subquery_root_node.get());
1238  if (subquery_local_hint) {
1239  // register local query hint of this subquery to its parent to correctly
1240  // enables them when executing this subquery
1241  root_dag.registerQueryHint(subquery_root_node.get(), *subquery_local_hint);
1242  }
1243  return subquery->deepCopy();
1244 }
void setGlobalQueryHints(const RegisteredQueryHint &global_hints)
Definition: RelAlgDag.h:2949
#define CHECK_GE(x, y)
Definition: Logger.h:302
void registerQueryHint(const RelAlgNode *node, const RegisteredQueryHint &query_hint)
Definition: RelAlgDag.h:2907
const RegisteredQueryHint & getGlobalHints() const
Definition: RelAlgDag.h:2947
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:2505
#define CHECK(condition)
Definition: Logger.h:289
static std::unique_ptr< RelAlgDag > buildDagForSubquery(RelAlgDag &root_dag, const rapidjson::Value &query_ast, const Catalog_Namespace::Catalog &cat)
Definition: RelAlgDag.cpp:3258

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

1065  {
1066  if (type_obj.IsArray()) {
1067  throw QueryNotSupported("Composite types are not currently supported.");
1068  }
1069  CHECK(type_obj.IsObject() && type_obj.MemberCount() >= 2)
1070  << json_node_to_string(type_obj);
1071  const auto type = to_sql_type(json_str(field(type_obj, "type")));
1072  const auto nullable = json_bool(field(type_obj, "nullable"));
1073  const auto precision_it = type_obj.FindMember("precision");
1074  const int precision =
1075  precision_it != type_obj.MemberEnd() ? json_i64(precision_it->value) : 0;
1076  const auto scale_it = type_obj.FindMember("scale");
1077  const int scale = scale_it != type_obj.MemberEnd() ? json_i64(scale_it->value) : 0;
1078  SQLTypeInfo ti(type, !nullable);
1079  ti.set_precision(precision);
1080  ti.set_scale(scale);
1081  return ti;
1082 }
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:962
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:289

+ 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 1198 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

1201  {
1202  CHECK(window_bound_obj.IsObject());
1204  window_bound.unbounded = json_bool(field(window_bound_obj, "unbounded"));
1205  window_bound.preceding = json_bool(field(window_bound_obj, "preceding"));
1206  window_bound.following = json_bool(field(window_bound_obj, "following"));
1207  window_bound.is_current_row = json_bool(field(window_bound_obj, "is_current_row"));
1208  const auto& offset_field = field(window_bound_obj, "offset");
1209  if (offset_field.IsObject()) {
1210  window_bound.bound_expr = parse_scalar_expr(offset_field, cat, root_dag);
1211  } else {
1212  CHECK(offset_field.IsNull());
1213  }
1214  window_bound.order_key = json_i64(field(window_bound_obj, "order_key"));
1215  return window_bound;
1216 }
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:1355
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:289

+ 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 1095 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

1095  {
1096  if (name == "ROW_NUMBER") {
1098  }
1099  if (name == "RANK") {
1101  }
1102  if (name == "DENSE_RANK") {
1104  }
1105  if (name == "PERCENT_RANK") {
1107  }
1108  if (name == "CUME_DIST") {
1110  }
1111  if (name == "NTILE") {
1113  }
1114  if (name == "LAG") {
1116  }
1117  if (name == "LAG_IN_FRAME") {
1119  }
1120  if (name == "LEAD") {
1122  }
1123  if (name == "LEAD_IN_FRAME") {
1125  }
1126  if (name == "FIRST_VALUE") {
1128  }
1129  if (name == "LAST_VALUE") {
1131  }
1132  if (name == "NTH_VALUE") {
1134  }
1135  if (name == "AVG") {
1137  }
1138  if (name == "MIN") {
1140  }
1141  if (name == "MAX") {
1143  }
1144  if (name == "SUM") {
1146  }
1147  if (name == "COUNT") {
1149  }
1150  if (name == "COUNT_IF") {
1152  }
1153  if (name == "SUM_IF") {
1155  }
1156  if (name == "$SUM0") {
1158  }
1159  throw std::runtime_error("Unsupported window function: " + name);
1160 }
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 1185 of file RelAlgDag.cpp.

References parse_nulls_position(), and parse_sort_direction().

Referenced by parse_operator().

1187  {
1188  std::vector<SortField> collation;
1189  size_t field_idx = 0;
1190  for (auto it = arr.Begin(); it != arr.End(); ++it, ++field_idx) {
1191  const auto sort_dir = parse_sort_direction(*it);
1192  const auto null_pos = parse_nulls_position(*it);
1193  collation.emplace_back(field_idx, sort_dir, null_pos);
1194  }
1195  return collation;
1196 }
NullSortedPosition parse_nulls_position(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1179
SortDirection parse_sort_direction(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1173

+ 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 1162 of file RelAlgDag.cpp.

References field(), and parse_scalar_expr().

Referenced by parse_operator().

1165  {
1166  std::vector<std::unique_ptr<const RexScalar>> exprs;
1167  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1168  exprs.emplace_back(parse_scalar_expr(field(*it, "field"), cat, root_dag));
1169  }
1170  return exprs;
1171 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1355
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 2325 of file RelAlgDag.cpp.

References CHECK.

Referenced by add_window_function_pre_project(), and separate_window_function_expressions().

2329  {
2330  auto delivered_hints = prev_node->getDeliveredHints();
2331  bool needs_propagate_hints = !delivered_hints->empty();
2332  if (needs_propagate_hints) {
2333  for (auto& kv : *delivered_hints) {
2334  new_node->addHint(kv.second);
2335  }
2336  auto prev_it = query_hints.find(prev_node->toHash());
2337  // query hint for the prev projection node should be registered
2338  CHECK(prev_it != query_hints.end());
2339  auto prev_hint_it = prev_it->second.find(prev_node->getId());
2340  CHECK(prev_hint_it != prev_it->second.end());
2341  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
2342  hint_map.emplace(new_node->getId(), prev_hint_it->second);
2343  query_hints.emplace(new_node->toHash(), hint_map);
2344  }
2345 }
#define CHECK(condition)
Definition: Logger.h:289

+ 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 637 of file RelAlgDag.cpp.

References CHECK.

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

Definition at line 710 of file RelAlgDag.cpp.

References CHECK, and CHECK_EQ.

Referenced by RelTableFunction::RelTableFunction(), and RelTableFunction::setTableFuncInputs().

713  {
714  CHECK_EQ(old_table_func_inputs.size(), new_table_func_inputs.size());
715  std::unordered_map<const Rex*, const Rex*> old_to_new_input;
716  for (size_t i = 0; i < old_table_func_inputs.size(); ++i) {
717  old_to_new_input.emplace(old_table_func_inputs[i].get(),
718  new_table_func_inputs[i].get());
719  }
720  for (auto& target : column_inputs) {
721  auto target_it = old_to_new_input.find(target);
722  CHECK(target_it != old_to_new_input.end());
723  target = target_it->second;
724  }
725 }
#define CHECK_EQ(x, y)
Definition: Logger.h:297
#define CHECK(condition)
Definition: Logger.h:289

+ Here is the caller graph for this function:

bool anonymous_namespace{RelAlgDag.cpp}::same_ignoring_notnull ( SQLTypeInfo  ti0,
SQLTypeInfo  ti1 
)

Definition at line 890 of file RelAlgDag.cpp.

References SQLTypeInfo::set_notnull().

Referenced by RelLogicalUnion::getCompatibleMetainfoTypes().

890  {
891  ti0.set_notnull({}); // Actual value doesn't matter
892  ti1.set_notnull({}); // as long as they are the same.
893  return ti0 == ti1;
894 }
void set_notnull(bool n)
Definition: sqltypes.h:497

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 2369 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().

2372  {
2373  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2374  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2375  const auto node = *node_itr;
2376  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2377  if (!window_func_project_node) {
2378  continue;
2379  }
2380 
2381  const auto prev_node_itr = std::prev(node_itr);
2382  const auto prev_node = *prev_node_itr;
2383  CHECK(prev_node);
2384 
2385  // map scalar expression index in the project node to window function ptr
2386  std::unordered_map<size_t, const RexScalar*> collected_window_func;
2387  WindowFunctionCollector collector(collected_window_func, false);
2388  // Iterate the target exprs of the project node and check for window function
2389  // expressions. If an embedded expression exists, collect it
2390  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2391  const auto scalar_rex = window_func_project_node->getProjectAt(i);
2392  if (is_window_function_operator(scalar_rex)) {
2393  // top level window function exprs are fine
2394  continue;
2395  }
2396  collector.visit(scalar_rex);
2397  }
2398 
2399  if (!collected_window_func.empty()) {
2400  // we have a nested window function expression
2401  std::unordered_set<size_t> collected_window_func_hash;
2402  // the current window function needs a set of new rex input which references
2403  // expressions in the newly introduced projection node
2404  std::vector<std::unique_ptr<const RexScalar>> new_rex_input_for_window_func;
2405  // a target projection expression of the newly created projection node
2406  std::vector<std::unique_ptr<const RexScalar>> new_scalar_expr_for_window_project;
2407  // a map between nested window function (hash val) and
2408  // its rex index stored in the `new_rex_input_for_window_func`
2409  std::unordered_map<size_t, size_t> window_func_to_new_rex_input_idx_map;
2410  // a map between RexInput of the current window function projection node (hash val)
2411  // and its corresponding new RexInput which is pushed down to the new projection
2412  // node
2413  std::unordered_map<size_t, std::unique_ptr<const RexInput>>
2414  new_rex_input_from_child_node;
2415  RexDeepCopyVisitor copier;
2416 
2417  std::vector<std::unique_ptr<const RexScalar>> dummy_scalar_exprs;
2418  std::vector<std::string> dummy_fields;
2419  std::vector<std::string> new_project_field_names;
2420  // create a new project node, it will contain window function expressions
2421  auto new_project =
2422  std::make_shared<RelProject>(dummy_scalar_exprs, dummy_fields, prev_node);
2423  // insert this new project node between the current window project node and its
2424  // child node
2425  node_list.insert(node_itr, new_project);
2426 
2427  // retrieve various information to replace expressions in the current window
2428  // function project node w/ considering scalar expressions in the new project node
2429  std::for_each(collected_window_func.begin(),
2430  collected_window_func.end(),
2431  [&new_project_field_names,
2432  &collected_window_func_hash,
2433  &new_rex_input_for_window_func,
2434  &new_scalar_expr_for_window_project,
2435  &copier,
2436  &new_project,
2437  &window_func_to_new_rex_input_idx_map](const auto& kv) {
2438  // compute window function expr's hash, and create a new rex_input
2439  // for it
2440  collected_window_func_hash.insert(kv.first);
2441 
2442  // map an old expression in the window function project node
2443  // to an index of the corresponding new RexInput
2444  const auto rex_idx = new_rex_input_for_window_func.size();
2445  window_func_to_new_rex_input_idx_map.emplace(kv.first, rex_idx);
2446 
2447  // create a new RexInput and make it as one of new expression of the
2448  // newly created project node
2449  new_rex_input_for_window_func.emplace_back(
2450  std::make_unique<const RexInput>(new_project.get(), rex_idx));
2451  new_scalar_expr_for_window_project.push_back(
2452  std::move(copier.visit(kv.second)));
2453  new_project_field_names.emplace_back("");
2454  });
2455  new_project->setExpressions(new_scalar_expr_for_window_project);
2456  new_project->setFields(std::move(new_project_field_names));
2457 
2458  auto window_func_scalar_exprs =
2459  window_func_project_node->getExpressionsAndRelease();
2460  RexWindowFuncReplacementVisitor replacer(collected_window_func_hash,
2461  new_rex_input_for_window_func,
2462  window_func_to_new_rex_input_idx_map,
2463  new_project.get(),
2464  new_rex_input_from_child_node);
2465  size_t rex_idx = 0;
2466  for (auto& scalar_expr : window_func_scalar_exprs) {
2467  // try to replace the old expressions in the window function project node
2468  // with expressions of the newly created project node
2469  auto new_parent_rex = replacer.visit(scalar_expr.get());
2470  window_func_scalar_exprs[rex_idx] = std::move(new_parent_rex);
2471  rex_idx++;
2472  }
2473  // Update the previous window project node
2474  window_func_project_node->setExpressions(window_func_scalar_exprs);
2475  window_func_project_node->replaceInput(prev_node, new_project);
2476  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2477  new_project->setPushedDownWindowExpr();
2478  }
2479  }
2480  nodes.assign(node_list.begin(), node_list.end());
2481 }
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:2325
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
#define CHECK(condition)
Definition: Logger.h:289

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void anonymous_namespace{RelAlgDag.cpp}::set_notnulls ( std::vector< TargetMetaInfo > *  tmis0,
std::vector< bool > const &  notnulls 
)

Definition at line 896 of file RelAlgDag.cpp.

References SQLTypeInfo::set_notnull().

Referenced by RelLogicalUnion::getCompatibleMetainfoTypes().

896  {
897  for (size_t j = 0; j < tmis0->size(); ++j) {
898  SQLTypeInfo ti = (*tmis0)[j].get_type_info();
899  SQLTypeInfo physical_ti = (*tmis0)[j].get_physical_type_info();
900  ti.set_notnull(notnulls[j]);
901  physical_ti.set_notnull(notnulls[j]);
902  (*tmis0)[j] = TargetMetaInfo((*tmis0)[j].get_resname(), ti, physical_ti);
903  }
904 }
void set_notnull(bool n)
Definition: sqltypes.h:497

+ 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 1313 of file RelAlgDag.cpp.

References CHECK.

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

1314  {
1315  CHECK(json_str_arr.IsArray());
1316  std::vector<std::string> fields;
1317  for (auto json_str_arr_it = json_str_arr.Begin(); json_str_arr_it != json_str_arr.End();
1318  ++json_str_arr_it) {
1319  CHECK(json_str_arr_it->IsString());
1320  fields.emplace_back(json_str_arr_it->GetString());
1321  }
1322  return fields;
1323 }
#define CHECK(condition)
Definition: Logger.h:289

+ 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 1379 of file RelAlgDag.cpp.

References ANTI, INNER, LEFT, and SEMI.

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

1379  {
1380  if (join_type_name == "inner") {
1381  return JoinType::INNER;
1382  }
1383  if (join_type_name == "left") {
1384  return JoinType::LEFT;
1385  }
1386  if (join_type_name == "semi") {
1387  return JoinType::SEMI;
1388  }
1389  if (join_type_name == "anti") {
1390  return JoinType::ANTI;
1391  }
1392  throw QueryNotSupported("Join type (" + join_type_name + ") not supported");
1393 }

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