OmniSciDB  72c90bc290
 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, 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, 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, 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, RelAlgDag &root_dag)
 
RexWindowFunctionOperator::RexWindowBound parse_window_bound (const rapidjson::Value &window_bound_obj, RelAlgDag &root_dag)
 
std::unique_ptr< const
RexSubQuery
parse_subquery (const rapidjson::Value &expr, RelAlgDag &root_dag)
 
std::unique_ptr< RexOperatorparse_operator (const rapidjson::Value &expr, RelAlgDag &root_dag)
 
std::unique_ptr< RexCaseparse_case (const rapidjson::Value &expr, 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 handle_agg_over_join (std::vector< std::shared_ptr< RelAlgNode >> &nodes, std::unordered_map< size_t, std::unordered_map< unsigned, RegisteredQueryHint >> &query_hints)
 
void eliminate_redundant_projection (std::vector< std::shared_ptr< RelAlgNode >> &nodes)
 
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 std::pair< const
Catalog_Namespace::Catalog
*, const TableDescriptor * > 
getCatalogAndTableFromScanNode (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 2570 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 2650 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().

2654  {
2655  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2656  size_t project_node_counter{0};
2657  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2658  const auto node = *node_itr;
2659 
2660  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2661  if (!window_func_project_node) {
2662  continue;
2663  }
2664  project_node_counter++;
2665  if (!window_func_project_node->hasWindowFunctionExpr()) {
2666  // this projection node does not have a window function
2667  // expression -- skip to the next node in the DAG.
2668  continue;
2669  }
2670 
2671  const auto prev_node_itr = std::prev(node_itr);
2672  const auto prev_node = *prev_node_itr;
2673  CHECK(prev_node);
2674 
2675  auto filter_node = std::dynamic_pointer_cast<RelFilter>(prev_node);
2676  auto join_node = std::dynamic_pointer_cast<RelJoin>(prev_node);
2677 
2678  auto scan_node = std::dynamic_pointer_cast<RelScan>(prev_node);
2679  const bool has_multi_fragment_scan_input =
2680  (scan_node &&
2681  (scan_node->getNumShards() > 0 || scan_node->getNumFragments() > 1));
2682  auto const [has_generic_expr_in_window_func, needs_expr_pushdown] =
2683  need_pushdown_generic_expr(window_func_project_node.get());
2684 
2685  // We currently add a preceding project node in one of two conditions:
2686  // 1. always_add_project_if_first_project_is_window_expr = true, which
2687  // we currently only set for distributed, but could also be set to support
2688  // multi-frag window function inputs, either if we can detect that an input table
2689  // is multi-frag up front, or using a retry mechanism like we do for join filter
2690  // push down.
2691  // TODO(todd): Investigate a viable approach for the above.
2692  // 2. Regardless of #1, if the window function project node is preceded by a
2693  // filter node. This is required both for correctness and to avoid pulling
2694  // all source input columns into memory since non-coalesced filter node
2695  // inputs are currently not pruned or eliminated via dead column elimination.
2696  // Note that we expect any filter node followed by a project node to be coalesced
2697  // into a single compound node in RelAlgDag::coalesce_nodes, and that action
2698  // prunes unused inputs.
2699  // TODO(todd): Investigate whether the shotgun filter node issue affects other
2700  // query plans, i.e. filters before joins, and whether there is a more general
2701  // approach to solving this (will still need the preceding project node for
2702  // window functions preceded by filter nodes for correctness though)
2703  // 3. Similar to the above, when the window function project node is preceded
2704  // by a join node.
2705  // 4. when partition by / order by clauses have a general expression instead of
2706  // referencing column
2707 
2708  if (!((always_add_project_if_first_project_is_window_expr &&
2709  project_node_counter == 1) ||
2710  filter_node || join_node || has_multi_fragment_scan_input ||
2711  needs_expr_pushdown)) {
2712  continue;
2713  }
2714 
2715  if (needs_expr_pushdown || join_node) {
2716  // previous logic cannot cover join_node case well, so use the newly introduced
2717  // push-down expression logic to safely add pre_project node before processing
2718  // window function
2719  std::unordered_map<size_t, size_t> expr_offset_cache;
2720  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_for_new_project;
2721  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs_for_window_project;
2722  std::vector<std::string> fields_for_window_project;
2723  std::vector<std::string> fields_for_new_project;
2724 
2725  // step 0. create new project node with an empty scalar expr to rebind target
2726  // exprs
2727  std::vector<std::unique_ptr<const RexScalar>> dummy_scalar_exprs;
2728  std::vector<std::string> dummy_fields;
2729  auto new_project =
2730  std::make_shared<RelProject>(dummy_scalar_exprs, dummy_fields, prev_node);
2731 
2732  // step 1 - 2
2733  PushDownGenericExpressionInWindowFunction visitor(new_project,
2734  scalar_exprs_for_new_project,
2735  fields_for_new_project,
2736  expr_offset_cache);
2737  for (size_t i = 0; i < window_func_project_node->size(); ++i) {
2738  auto projected_target = window_func_project_node->getProjectAt(i);
2739  auto new_projection_target = visitor.visit(projected_target);
2740  scalar_exprs_for_window_project.emplace_back(
2741  std::move(new_projection_target.release()));
2742  }
2743  new_project->setExpressions(scalar_exprs_for_new_project);
2744  new_project->setFields(std::move(fields_for_new_project));
2745  bool has_groupby = false;
2746  auto aggregate = std::dynamic_pointer_cast<RelAggregate>(prev_node);
2747  if (aggregate) {
2748  has_groupby = aggregate->getGroupByCount() > 0;
2749  }
2750  // force rowwise output to prevent computing incorrect query result
2751  if (has_groupby && visitor.hasPartitionExpression()) {
2752  // we currently may compute incorrect result with columnar output when
2753  // 1) the window function has partition expression, and
2754  // 2) a parent node of the window function projection node has group by
2755  // expression todo (yoonmin) : relax this
2756  VLOG(1)
2757  << "Query output overridden to row-wise format due to presence of a window "
2758  "function with partition expression and group-by expression.";
2759  new_project->forceRowwiseOutput();
2760  } else if (has_generic_expr_in_window_func) {
2761  VLOG(1) << "Query output overridden to row-wise format due to presence of a "
2762  "generic expression as an input expression of the window "
2763  "function.";
2764  new_project->forceRowwiseOutput();
2765  } else if (visitor.hasCaseExprAsWindowOperand()) {
2766  VLOG(1)
2767  << "Query output overridden to row-wise format due to presence of a window "
2768  "function with a case statement as its operand.";
2769  new_project->forceRowwiseOutput();
2770  }
2771 
2772  // step 3. finalize
2773  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2774  new_project->setPushedDownWindowExpr();
2775  node_list.insert(node_itr, new_project);
2776  window_func_project_node->replaceInput(prev_node, new_project);
2777  window_func_project_node->setExpressions(scalar_exprs_for_window_project);
2778  } else {
2779  // only push rex_inputs listed in the window function down to a new project node
2780  RexInputSet inputs;
2781  RexInputCollector input_collector;
2782  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2783  auto new_inputs =
2784  input_collector.visit(window_func_project_node->getProjectAt(i));
2785  inputs.insert(new_inputs.begin(), new_inputs.end());
2786  }
2787 
2788  // Note: Technically not required since we are mapping old inputs to new input
2789  // indices, but makes the re-mapping of inputs easier to follow.
2790  std::vector<RexInput> sorted_inputs(inputs.begin(), inputs.end());
2791  std::sort(sorted_inputs.begin(),
2792  sorted_inputs.end(),
2793  [](const auto& a, const auto& b) { return a.getIndex() < b.getIndex(); });
2794 
2795  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs;
2796  std::vector<std::string> fields;
2797  std::unordered_map<unsigned, unsigned> old_index_to_new_index;
2798  for (auto& input : sorted_inputs) {
2799  CHECK_EQ(input.getSourceNode(), prev_node.get());
2800  CHECK(old_index_to_new_index
2801  .insert(std::make_pair(input.getIndex(), scalar_exprs.size()))
2802  .second);
2803  scalar_exprs.emplace_back(input.deepCopy());
2804  fields.emplace_back("");
2805  }
2806 
2807  auto new_project = std::make_shared<RelProject>(scalar_exprs, fields, prev_node);
2808  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2809  new_project->setPushedDownWindowExpr();
2810  node_list.insert(node_itr, new_project);
2811  window_func_project_node->replaceInput(
2812  prev_node, new_project, old_index_to_new_index);
2813  }
2814  }
2815  nodes.assign(node_list.begin(), node_list.end());
2816 }
const size_t getGroupByCount() const
Definition: RelAlgDag.h:1508
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::pair< bool, bool > need_pushdown_generic_expr(RelProject const *window_func_project_node)
Definition: RelAlgDag.cpp:2612
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:2412
constexpr double a
Definition: Utm.h:32
std::unordered_set< RexInput > RexInputSet
Definition: RelAlgDag.cpp:2570
#define CHECK(condition)
Definition: Logger.h:291
#define VLOG(n)
Definition: Logger.h:388

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

1529  {
1530  for (auto ra_node : nodes) {
1531  const auto filter_node = std::dynamic_pointer_cast<RelFilter>(ra_node);
1532  if (filter_node) {
1533  CHECK_EQ(size_t(1), filter_node->inputCount());
1534  auto disambiguated_condition = disambiguate_rex(
1535  filter_node->getCondition(), get_node_output(filter_node->getInput(0)));
1536  filter_node->setCondition(disambiguated_condition);
1537  continue;
1538  }
1539  const auto join_node = std::dynamic_pointer_cast<RelJoin>(ra_node);
1540  if (join_node) {
1541  CHECK_EQ(size_t(2), join_node->inputCount());
1542  auto disambiguated_condition =
1543  disambiguate_rex(join_node->getCondition(), get_node_output(join_node.get()));
1544  join_node->setCondition(disambiguated_condition);
1545  continue;
1546  }
1547  const auto project_node = std::dynamic_pointer_cast<RelProject>(ra_node);
1548  if (project_node) {
1549  bind_project_to_input(project_node.get(),
1550  get_node_output(project_node->getInput(0)));
1551  continue;
1552  }
1553  const auto table_func_node = std::dynamic_pointer_cast<RelTableFunction>(ra_node);
1554  if (table_func_node) {
1555  /*
1556  Collect all inputs from table function input (non-literal)
1557  arguments.
1558  */
1559  RANodeOutput input;
1560  input.reserve(table_func_node->inputCount());
1561  for (size_t i = 0; i < table_func_node->inputCount(); i++) {
1562  auto node_output = get_node_output(table_func_node->getInput(i));
1563  input.insert(input.end(), node_output.begin(), node_output.end());
1564  }
1565  bind_table_func_to_input(table_func_node.get(), input);
1566  }
1567  }
1568 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::vector< RexInput > RANodeOutput
Definition: RelAlgDag.h:3432
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1475
void bind_project_to_input(RelProject *project_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1501
void bind_table_func_to_input(RelTableFunction *table_func_node, const RANodeOutput &input) noexcept
Definition: RelAlgDag.cpp:1515
RANodeOutput get_node_output(const RelAlgNode *ra_node)
Definition: RelAlgDag.cpp:371

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

References CHECK_EQ, and disambiguate_rex().

Referenced by bind_inputs(), and create_compound().

1501  {
1502  CHECK_EQ(size_t(1), project_node->inputCount());
1503  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1504  for (size_t i = 0; i < project_node->size(); ++i) {
1505  const auto projected_expr = project_node->getProjectAt(i);
1506  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
1507  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
1508  } else {
1509  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
1510  }
1511  }
1512  project_node->setExpressions(disambiguated_exprs);
1513 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
size_t size() const override
Definition: RelAlgDag.h:1320
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1475
void setExpressions(std::vector< std::unique_ptr< const RexScalar >> &exprs) const
Definition: RelAlgDag.h:1300
const RexScalar * getProjectAtAndRelease(const size_t idx) const
Definition: RelAlgDag.h:1357
const RexScalar * getProjectAt(const size_t idx) const
Definition: RelAlgDag.h:1352
const size_t inputCount() const
Definition: RelAlgDag.h:875

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

References disambiguate_rex().

Referenced by bind_inputs().

1516  {
1517  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1518  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
1519  const auto target_expr = table_func_node->getTableFuncInputAt(i);
1520  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
1521  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
1522  } else {
1523  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
1524  }
1525  }
1526  table_func_node->setTableFuncInputs(std::move(disambiguated_exprs));
1527 }
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1475
const RexScalar * getTableFuncInputAtAndRelease(const size_t idx)
Definition: RelAlgDag.h:2571
size_t getTableFuncInputsSize() const
Definition: RelAlgDag.h:2560
void setTableFuncInputs(std::vector< std::unique_ptr< const RexScalar >> &&exprs)
Definition: RelAlgDag.cpp:730
const RexScalar * getTableFuncInputAt(const size_t idx) const
Definition: RelAlgDag.h:2566

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

References CHECK, and field().

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

2832  {
2833  const auto& inputs_json = field(node, "inputs");
2834  CHECK(inputs_json.IsArray() && !inputs_json.Size());
2835 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
#define CHECK(condition)
Definition: Logger.h:291

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

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

References CHECK_NE.

Referenced by RelAlgDagBuilder::optimizeDag().

1608  {
1609  // compute each rel node's hash value in advance to avoid inconsistency of their hash
1610  // values depending on the toHash's caller
1611  // specifically, we manipulate our logical query plan before retrieving query step
1612  // sequence but once we compute a hash value we cached it so there is no way to update
1613  // it after the plan has been changed starting from the top node, we compute the hash
1614  // value (top-down manner)
1615  std::for_each(
1616  nodes.rbegin(), nodes.rend(), [](const std::shared_ptr<RelAlgNode>& node) {
1617  auto node_hash = node->toHash();
1618  CHECK_NE(node_hash, static_cast<size_t>(0));
1619  });
1620 }
#define CHECK_NE(x, y)
Definition: Logger.h:302

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

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

References RexVisitorBase< T >::visit().

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

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

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

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

Referenced by disambiguate_rex().

1455  {
1456  std::vector<
1457  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1458  disambiguated_expr_pair_list;
1459  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1460  auto disambiguated_when = disambiguate_rex(rex_case->getWhen(i), ra_output);
1461  auto disambiguated_then = disambiguate_rex(rex_case->getThen(i), ra_output);
1462  disambiguated_expr_pair_list.emplace_back(std::move(disambiguated_when),
1463  std::move(disambiguated_then));
1464  }
1465  std::unique_ptr<const RexScalar> disambiguated_else{
1466  disambiguate_rex(rex_case->getElse(), ra_output)};
1467  return std::unique_ptr<const RexCase>(
1468  new RexCase(disambiguated_expr_pair_list, disambiguated_else));
1469 }
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:440
const RexScalar * getElse() const
Definition: RelAlgDag.h:445
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:435
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1475
size_t branchCount() const
Definition: RelAlgDag.h:433

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

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

Referenced by disambiguate_rex().

1421  {
1422  std::vector<std::unique_ptr<const RexScalar>> disambiguated_operands;
1423  for (size_t i = 0; i < rex_operator->size(); ++i) {
1424  auto operand = rex_operator->getOperand(i);
1425  if (dynamic_cast<const RexSubQuery*>(operand)) {
1426  disambiguated_operands.emplace_back(rex_operator->getOperandAndRelease(i));
1427  } else {
1428  disambiguated_operands.emplace_back(disambiguate_rex(operand, ra_output));
1429  }
1430  }
1431  const auto rex_window_function_operator =
1432  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
1433  if (rex_window_function_operator) {
1434  const auto& partition_keys = rex_window_function_operator->getPartitionKeys();
1435  std::vector<std::unique_ptr<const RexScalar>> disambiguated_partition_keys;
1436  for (const auto& partition_key : partition_keys) {
1437  disambiguated_partition_keys.emplace_back(
1438  disambiguate_rex(partition_key.get(), ra_output));
1439  }
1440  std::vector<std::unique_ptr<const RexScalar>> disambiguated_order_keys;
1441  const auto& order_keys = rex_window_function_operator->getOrderKeys();
1442  for (const auto& order_key : order_keys) {
1443  disambiguated_order_keys.emplace_back(disambiguate_rex(order_key.get(), ra_output));
1444  }
1445  return rex_window_function_operator->disambiguatedOperands(
1446  disambiguated_operands,
1447  disambiguated_partition_keys,
1448  disambiguated_order_keys,
1449  rex_window_function_operator->getCollation());
1450  }
1451  return rex_operator->getDisambiguated(disambiguated_operands);
1452 }
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
const RexScalar * getOperandAndRelease(const size_t idx) const
Definition: RelAlgDag.h:371
virtual std::unique_ptr< const RexOperator > getDisambiguated(std::vector< std::unique_ptr< const RexScalar >> &operands) const
Definition: RelAlgDag.h:359
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1475
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:643

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

1476  {
1477  const auto rex_abstract_input = dynamic_cast<const RexAbstractInput*>(rex_scalar);
1478  if (rex_abstract_input) {
1479  CHECK_LT(static_cast<size_t>(rex_abstract_input->getIndex()), ra_output.size());
1480  return std::unique_ptr<const RexInput>(
1481  new RexInput(ra_output[rex_abstract_input->getIndex()]));
1482  }
1483  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
1484  if (rex_operator) {
1485  return disambiguate_operator(rex_operator, ra_output);
1486  }
1487  const auto rex_case = dynamic_cast<const RexCase*>(rex_scalar);
1488  if (rex_case) {
1489  return disambiguate_case(rex_case, ra_output);
1490  }
1491  if (auto const rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar)) {
1492  return rex_literal->deepCopy();
1493  } else if (auto const rex_subquery = dynamic_cast<const RexSubQuery*>(rex_scalar)) {
1494  return rex_subquery->deepCopy();
1495  } else {
1496  throw QueryNotSupported("Unable to disambiguate expression of type " +
1497  std::string(typeid(*rex_scalar).name()));
1498  }
1499 }
std::unique_ptr< const RexOperator > disambiguate_operator(const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
Definition: RelAlgDag.cpp:1419
std::unique_ptr< const RexCase > disambiguate_case(const RexCase *rex_case, const RANodeOutput &ra_output)
Definition: RelAlgDag.cpp:1454
#define CHECK_LT(x, y)
Definition: Logger.h:303

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2171 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

2171  {
2172  for (auto& node : nodes) {
2173  if (auto* proj_node = dynamic_cast<RelProject*>(node.get())) {
2174  if (proj_node->isSimple()) {
2175  if (auto child_proj_node =
2176  dynamic_cast<RelProject const*>(proj_node->getInput(0))) {
2177  std::vector<std::unique_ptr<RexScalar const>> scalar_exprs;
2178  RexDeepCopyVisitor copier;
2179  for (size_t i = 0; i < proj_node->size(); i++) {
2180  auto rex_abs_input =
2181  dynamic_cast<RexAbstractInput const*>(proj_node->getProjectAt(i));
2182  scalar_exprs.push_back(
2183  copier.visit(child_proj_node->getProjectAt(rex_abs_input->getIndex())));
2184  }
2185  CHECK_EQ(scalar_exprs.size(), proj_node->getFields().size());
2186  proj_node->setExpressions(scalar_exprs);
2187  proj_node->replaceInput(proj_node->getAndOwnInput(0),
2188  child_proj_node->getAndOwnInput(0));
2189  }
2190  }
2191  }
2192  }
2193 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27

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

References CHECK, and CHECK_EQ.

Referenced by RelSort::hasEquivCollationOf().

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

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

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

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

2820  {
2821  const auto it = obj.FindMember(field);
2822  if (it == obj.MemberEnd()) {
2823  return default_val;
2824  }
2825  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
2826  CHECK_EQ(kDECIMAL, lit->getType());
2827  CHECK_EQ(unsigned(0), lit->getScale());
2828  CHECK_EQ(unsigned(0), lit->getTargetScale());
2829  return lit->getVal<int64_t>();
2830 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
std::unique_ptr< RexLiteral > parse_literal(const rapidjson::Value &expr)
Definition: RelAlgDag.cpp:995

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

const std::pair<const Catalog_Namespace::Catalog*, const TableDescriptor*> anonymous_namespace{RelAlgDag.cpp}::getCatalogAndTableFromScanNode ( const rapidjson::Value &  scan_ra)

Definition at line 2838 of file RelAlgDag.cpp.

References cat(), CHECK, CHECK_EQ, field(), Catalog_Namespace::SysCatalog::getCatalog(), and Catalog_Namespace::SysCatalog::instance().

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

2838  {
2839  const auto& table_json = field(scan_ra, "table");
2840  CHECK(table_json.IsArray());
2841  CHECK_EQ(unsigned(2), table_json.Size());
2842  const auto cat =
2843  Catalog_Namespace::SysCatalog::instance().getCatalog(table_json[0].GetString());
2844  CHECK(cat);
2845  const auto td = cat->getMetadataForTable(table_json[1].GetString());
2846  CHECK(td);
2847  return {cat.get(), td};
2848 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::string cat(Ts &&...args)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
static SysCatalog & instance()
Definition: SysCatalog.h:343
std::shared_ptr< Catalog > getCatalog(const std::string &dbName)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2850 of file RelAlgDag.cpp.

References field(), and strings_from_json_array().

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

2850  {
2851  const auto& fields_json = field(scan_ra, "fieldNames");
2852  return strings_from_json_array(fields_json);
2853 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
std::vector< std::string > strings_from_json_array(const rapidjson::Value &json_str_arr) noexcept
Definition: RelAlgDag.cpp:1336

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2135 of file RelAlgDag.cpp.

References CHECK, CHECK_EQ, CHECK_NE, and anonymous_namespace{RelAlgDag.cpp}::anonymous_namespace{RelAlgDag.cpp}::create_rex_input_for_new_project_node().

Referenced by RelAlgDagBuilder::optimizeDag().

2138  {
2139  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2140  bool replace_nodes = false;
2141  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2142  auto node = *node_itr;
2143  if (auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node)) {
2144  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs;
2145  std::vector<std::string> fields;
2146  std::shared_ptr<RelProject> new_project;
2147  CHECK_EQ(agg_node->getInputs().size(), size_t(1));
2148  CHECK_NE(*node_itr, *node_list.begin());
2149  const auto prev_node = *std::prev(node_itr);
2150  CHECK(prev_node);
2151  auto const input_node_ptr = agg_node->getAndOwnInput(0);
2152  if (auto join_node =
2153  std::dynamic_pointer_cast<RelLeftDeepInnerJoin const>(input_node_ptr)) {
2154  for (auto const* join_input_node : join_node->getInputs()) {
2155  create_rex_input_for_new_project_node(join_input_node, scalar_exprs, fields);
2156  }
2157  if (!scalar_exprs.empty()) {
2158  replace_nodes = true;
2159  new_project = std::make_shared<RelProject>(scalar_exprs, fields, join_node);
2160  agg_node->replaceInput(join_node, new_project);
2161  node_list.insert(node_itr, new_project);
2162  }
2163  }
2164  }
2165  }
2166  if (replace_nodes) {
2167  nodes.assign(node_list.begin(), node_list.end());
2168  }
2169 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
void create_rex_input_for_new_project_node(RelAlgNode const *node, std::vector< std::unique_ptr< const RexScalar >> &scalar_exprs, std::vector< std::string > &fields)
Definition: RelAlgDag.cpp:2118
#define CHECK_NE(x, y)
Definition: Logger.h:302
#define CHECK(condition)
Definition: Logger.h:291

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

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

Referenced by RelAlgExecutor::executeRelAlgStep(), and RelAlgDagBuilder::optimizeDag().

1571  {
1572  // query hint is delivered by the above three nodes
1573  // when a query block has top-sort node, a hint is registered to
1574  // one of the node which locates at the nearest from the sort node
1575  RegisteredQueryHint global_query_hint;
1576  for (auto node : nodes) {
1577  Hints* hint_delivered = nullptr;
1578  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1579  if (agg_node) {
1580  if (agg_node->hasDeliveredHint()) {
1581  hint_delivered = agg_node->getDeliveredHints();
1582  }
1583  }
1584  const auto project_node = std::dynamic_pointer_cast<RelProject>(node);
1585  if (project_node) {
1586  if (project_node->hasDeliveredHint()) {
1587  hint_delivered = project_node->getDeliveredHints();
1588  }
1589  }
1590  const auto compound_node = std::dynamic_pointer_cast<RelCompound>(node);
1591  if (compound_node) {
1592  if (compound_node->hasDeliveredHint()) {
1593  hint_delivered = compound_node->getDeliveredHints();
1594  }
1595  }
1596  if (hint_delivered && !hint_delivered->empty()) {
1597  rel_alg_dag.registerQueryHints(node, hint_delivered, global_query_hint);
1598  }
1599  }
1600  // the current rel_alg_dag may contain global query hints from the subquery
1601  // so we combine the current global hint we collected with the original one together
1602  // to propagate global query hints correctly
1603  const auto existing_global_query_hints = rel_alg_dag.getGlobalHints();
1604  const auto new_global_query_hints = existing_global_query_hints || global_query_hint;
1605  rel_alg_dag.setGlobalQueryHints(new_global_query_hints);
1606 }
void setGlobalQueryHints(const RegisteredQueryHint &global_hints)
Definition: RelAlgDag.h:3340
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1436
const RegisteredQueryHint & getGlobalHints() const
Definition: RelAlgDag.h:3338
Hints * getDeliveredHints()
Definition: RelAlgDag.h:1599
Hints * getDeliveredHints()
Definition: RelAlgDag.h:2159
std::unordered_map< QueryHint, ExplainedQueryHint > Hints
Definition: QueryHint.h:390
void registerQueryHints(std::shared_ptr< RelAlgNode > node, Hints *hints_delivered, RegisteredQueryHint &global_query_hint)
Definition: RelAlgDag.h:2842

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

References CHECK, and CHECK_GE.

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

1349  {
1350  CHECK(json_idx_arr.IsArray());
1351  std::vector<size_t> indices;
1352  for (auto json_idx_arr_it = json_idx_arr.Begin(); json_idx_arr_it != json_idx_arr.End();
1353  ++json_idx_arr_it) {
1354  CHECK(json_idx_arr_it->IsInt());
1355  CHECK_GE(json_idx_arr_it->GetInt(), 0);
1356  indices.emplace_back(json_idx_arr_it->GetInt());
1357  }
1358  return indices;
1359 }
#define CHECK_GE(x, y)
Definition: Logger.h:306
#define CHECK(condition)
Definition: Logger.h:291

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

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

Referenced by RelProject::isRenaming().

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

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

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

978  {
979  rapidjson::StringBuffer buffer;
980  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
981  node.Accept(writer);
982  return buffer.GetString();
983 }

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

References CHECK_EQ, and RelAlgNode::markAsNop().

Referenced by RelAlgDagBuilder::optimizeDag().

1622  {
1623  for (auto node : nodes) {
1624  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1625  if (!agg_node || agg_node->getAggExprsCount()) {
1626  continue;
1627  }
1628  CHECK_EQ(size_t(1), node->inputCount());
1629  const auto agg_input_node = dynamic_cast<const RelAggregate*>(node->getInput(0));
1630  if (agg_input_node && !agg_input_node->getAggExprsCount() &&
1631  agg_node->getGroupByCount() == agg_input_node->getGroupByCount()) {
1632  agg_node->markAsNop();
1633  }
1634  }
1635 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
void markAsNop()
Definition: RelAlgDag.h:925

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

References anonymous_namespace{Utm.h}::n.

Referenced by get_node_output().

96  {
97  std::vector<RexInput> outputs;
98  outputs.reserve(n);
99  for (size_t i = 0; i < n; ++i) {
100  outputs.emplace_back(node, i);
101  }
102  return outputs;
103 }
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 973 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().

973  {
974  const auto& id = field(ra_node, "id");
975  return std::stoi(json_str(id));
976 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33

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

References field(), and json_i64().

Referenced by parse_scalar_expr().

990  {
991  const auto& input = field(expr, "input");
992  return std::unique_ptr<RexAbstractInput>(new RexAbstractInput(json_i64(input)));
993 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:41

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

1361  {
1362  const auto agg_str = json_str(field(expr, "agg"));
1363  if (agg_str == "APPROX_QUANTILE") {
1364  LOG(INFO) << "APPROX_QUANTILE is deprecated. Please use APPROX_PERCENTILE instead.";
1365  }
1366  const auto agg = to_agg_kind(agg_str);
1367  const auto distinct = json_bool(field(expr, "distinct"));
1368  const auto agg_ti = parse_type(field(expr, "type"));
1369  const auto operands = indices_from_json_array(field(expr, "operands"));
1370  bool const allow_multiple_args =
1371  shared::is_any<kAPPROX_COUNT_DISTINCT, kAPPROX_QUANTILE, kSUM_IF>(agg);
1372  if (operands.size() > 1 && (operands.size() != 2 || !allow_multiple_args)) {
1373  throw QueryNotSupported("Multiple arguments for aggregates aren't supported");
1374  }
1375  return std::unique_ptr<const RexAgg>(new RexAgg(agg, distinct, agg_ti, operands));
1376 }
SQLAgg to_agg_kind(const std::string &agg_name)
#define LOG(tag)
Definition: Logger.h:285
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:51
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
std::vector< size_t > indices_from_json_array(const rapidjson::Value &json_idx_arr) noexcept
Definition: RelAlgDag.cpp:1348
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
Definition: RelAlgDag.cpp:1080

+ 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,
RelAlgDag root_dag 
)

Definition at line 1316 of file RelAlgDag.cpp.

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

Referenced by parse_scalar_expr().

1316  {
1317  const auto& operands = field(expr, "operands");
1318  CHECK(operands.IsArray());
1319  CHECK_GE(operands.Size(), unsigned(2));
1320  std::unique_ptr<const RexScalar> else_expr;
1321  std::vector<
1322  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1323  expr_pair_list;
1324  for (auto operands_it = operands.Begin(); operands_it != operands.End();) {
1325  auto when_expr = parse_scalar_expr(*operands_it++, root_dag);
1326  if (operands_it == operands.End()) {
1327  else_expr = std::move(when_expr);
1328  break;
1329  }
1330  auto then_expr = parse_scalar_expr(*operands_it++, root_dag);
1331  expr_pair_list.emplace_back(std::move(when_expr), std::move(then_expr));
1332  }
1333  return std::unique_ptr<RexCase>(new RexCase(expr_pair_list, else_expr));
1334 }
#define CHECK_GE(x, y)
Definition: Logger.h:306
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
#define CHECK(condition)
Definition: Logger.h:291
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1378

+ 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,
RelAlgDag root_dag 
)

Definition at line 1099 of file RelAlgDag.cpp.

References parse_scalar_expr().

Referenced by parse_operator().

1101  {
1102  std::vector<std::unique_ptr<const RexScalar>> exprs;
1103  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1104  exprs.emplace_back(parse_scalar_expr(*it, root_dag));
1105  }
1106  return exprs;
1107 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1378

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

995  {
996  CHECK(expr.IsObject());
997  const auto& literal = field(expr, "literal");
998  const auto type = to_sql_type(json_str(field(expr, "type")));
999  const auto target_type = to_sql_type(json_str(field(expr, "target_type")));
1000  const auto scale = json_i64(field(expr, "scale"));
1001  const auto precision = json_i64(field(expr, "precision"));
1002  const auto type_scale = json_i64(field(expr, "type_scale"));
1003  const auto type_precision = json_i64(field(expr, "type_precision"));
1004  if (literal.IsNull()) {
1005  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
1006  }
1007  switch (type) {
1008  case kINT:
1009  case kBIGINT:
1010  case kDECIMAL:
1011  case kINTERVAL_DAY_TIME:
1012  case kINTERVAL_YEAR_MONTH:
1013  case kTIME:
1014  case kTIMESTAMP:
1015  case kDATE:
1016  return std::unique_ptr<RexLiteral>(new RexLiteral(json_i64(literal),
1017  type,
1018  target_type,
1019  scale,
1020  precision,
1021  type_scale,
1022  type_precision));
1023  case kDOUBLE: {
1024  if (literal.IsDouble()) {
1025  return std::unique_ptr<RexLiteral>(new RexLiteral(json_double(literal),
1026  type,
1027  target_type,
1028  scale,
1029  precision,
1030  type_scale,
1031  type_precision));
1032  } else if (literal.IsInt64()) {
1033  return std::make_unique<RexLiteral>(static_cast<double>(literal.GetInt64()),
1034  type,
1035  target_type,
1036  scale,
1037  precision,
1038  type_scale,
1039  type_precision);
1040 
1041  } else if (literal.IsUint64()) {
1042  return std::make_unique<RexLiteral>(static_cast<double>(literal.GetUint64()),
1043  type,
1044  target_type,
1045  scale,
1046  precision,
1047  type_scale,
1048  type_precision);
1049  }
1050  UNREACHABLE() << "Unhandled type: " << literal.GetType();
1051  }
1052  case kTEXT:
1053  return std::unique_ptr<RexLiteral>(new RexLiteral(json_str(literal),
1054  type,
1055  target_type,
1056  scale,
1057  precision,
1058  type_scale,
1059  type_precision));
1060  case kBOOLEAN:
1061  return std::unique_ptr<RexLiteral>(new RexLiteral(json_bool(literal),
1062  type,
1063  target_type,
1064  scale,
1065  precision,
1066  type_scale,
1067  type_precision));
1068  case kNULLT:
1069  return std::unique_ptr<RexLiteral>(new RexLiteral(target_type));
1070  default:
1071  CHECK(false);
1072  }
1073  CHECK(false);
1074  return nullptr;
1075 }
SQLTypes to_sql_type(const std::string &type_name)
Definition: sqltypes.h:76
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:51
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
#define UNREACHABLE()
Definition: Logger.h:338
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:41
const double json_double(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:56
Definition: sqltypes.h:79
Definition: sqltypes.h:80
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72

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

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

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

1210  {
1211  return json_str(field(collation, "nulls")) == std::string("FIRST")
1214 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33

+ 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,
RelAlgDag root_dag 
)

Definition at line 1274 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().

1275  {
1276  const auto op_name = json_str(field(expr, "op"));
1277  const bool is_quantifier =
1278  op_name == std::string("PG_ANY") || op_name == std::string("PG_ALL");
1279  const auto op = is_quantifier ? kFUNCTION : to_sql_op(op_name);
1280  const auto& operators_json_arr = field(expr, "operands");
1281  CHECK(operators_json_arr.IsArray());
1282  auto operands = parse_expr_array(operators_json_arr, root_dag);
1283  const auto type_it = expr.FindMember("type");
1284  CHECK(type_it != expr.MemberEnd());
1285  auto ti = parse_type(type_it->value);
1286  if (op == kIN && expr.HasMember("subquery")) {
1287  auto subquery = parse_subquery(expr, root_dag);
1288  operands.emplace_back(std::move(subquery));
1289  }
1290  if (expr.FindMember("partition_keys") != expr.MemberEnd()) {
1291  const auto& partition_keys_arr = field(expr, "partition_keys");
1292  auto partition_keys = parse_expr_array(partition_keys_arr, root_dag);
1293  const auto& order_keys_arr = field(expr, "order_keys");
1294  auto order_keys = parse_window_order_exprs(order_keys_arr, root_dag);
1295  const auto collation = parse_window_order_collation(order_keys_arr, root_dag);
1296  const auto kind = parse_window_function_kind(op_name);
1297  const auto lower_bound = parse_window_bound(field(expr, "lower_bound"), root_dag);
1298  const auto upper_bound = parse_window_bound(field(expr, "upper_bound"), root_dag);
1299  bool is_rows = json_bool(field(expr, "is_rows"));
1300  ti.set_notnull(false);
1301  return std::make_unique<RexWindowFunctionOperator>(kind,
1302  operands,
1303  partition_keys,
1304  order_keys,
1305  collation,
1306  lower_bound,
1307  upper_bound,
1308  is_rows,
1309  ti);
1310  }
1311  return std::unique_ptr<RexOperator>(op == kFUNCTION
1312  ? new RexFunctionOperator(op_name, operands, ti)
1313  : new RexOperator(op, operands, ti));
1314 }
DEVICE auto upper_bound(ARGS &&...args)
Definition: gpu_enabled.h:123
std::vector< std::unique_ptr< const RexScalar > > parse_window_order_exprs(const rapidjson::Value &arr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1194
SqlWindowFunctionKind parse_window_function_kind(const std::string &name)
Definition: RelAlgDag.cpp:1109
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:51
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1247
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
SQLOps to_sql_op(const std::string &op_str)
SQLTypeInfo parse_type(const rapidjson::Value &type_obj)
Definition: RelAlgDag.cpp:1080
std::vector< SortField > parse_window_order_collation(const rapidjson::Value &arr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1216
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
std::vector< std::unique_ptr< const RexScalar > > parse_expr_array(const rapidjson::Value &arr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1099
Definition: sqldefs.h:52
#define CHECK(condition)
Definition: Logger.h:291
RexWindowFunctionOperator::RexWindowBound parse_window_bound(const rapidjson::Value &window_bound_obj, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1228

+ 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,
RelAlgDag root_dag 
)

Definition at line 1378 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().

1379  {
1380  CHECK(expr.IsObject());
1381  if (expr.IsObject() && expr.HasMember("input")) {
1382  return std::unique_ptr<const RexScalar>(parse_abstract_input(expr));
1383  }
1384  if (expr.IsObject() && expr.HasMember("literal")) {
1385  return std::unique_ptr<const RexScalar>(parse_literal(expr));
1386  }
1387  if (expr.IsObject() && expr.HasMember("op")) {
1388  const auto op_str = json_str(field(expr, "op"));
1389  if (op_str == std::string("CASE")) {
1390  return std::unique_ptr<const RexScalar>(parse_case(expr, root_dag));
1391  }
1392  if (op_str == std::string("$SCALAR_QUERY")) {
1393  return std::unique_ptr<const RexScalar>(parse_subquery(expr, root_dag));
1394  }
1395  return std::unique_ptr<const RexScalar>(parse_operator(expr, root_dag));
1396  }
1397  throw QueryNotSupported("Expression node " + json_node_to_string(expr) +
1398  " not supported");
1399 }
std::unique_ptr< RexCase > parse_case(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1316
std::string json_node_to_string(const rapidjson::Value &node) noexcept
Definition: RelAlgDag.cpp:978
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1247
std::unique_ptr< RexAbstractInput > parse_abstract_input(const rapidjson::Value &expr) noexcept
Definition: RelAlgDag.cpp:989
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
std::unique_ptr< RexOperator > parse_operator(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1274
std::unique_ptr< RexLiteral > parse_literal(const rapidjson::Value &expr)
Definition: RelAlgDag.cpp:995
#define CHECK(condition)
Definition: Logger.h:291

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

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

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

1204  {
1205  return json_str(field(collation, "direction")) == std::string("DESCENDING")
1208 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33

+ 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,
RelAlgDag root_dag 
)

Definition at line 1247 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().

1248  {
1249  const auto& operands = field(expr, "operands");
1250  CHECK(operands.IsArray());
1251  CHECK_GE(operands.Size(), unsigned(0));
1252  const auto& subquery_ast = field(expr, "subquery");
1253 
1254  auto subquery_dag = RelAlgDagBuilder::buildDagForSubquery(root_dag, subquery_ast);
1255  const auto subquery_root_node = subquery_dag->getRootNodeShPtr();
1256  auto subquery = std::make_shared<RexSubQuery>(subquery_root_node);
1257  auto query_hint = subquery_dag->getQueryHint(subquery_dag->getRootNodeShPtr().get());
1258  root_dag.registerSubquery(subquery);
1259  const auto subquery_global_hint = subquery_dag->getGlobalHints();
1260  if (subquery_global_hint.isAnyQueryHintDelivered()) {
1261  // we need to propagate global query hint found in this subquery to its parent
1262  const auto new_global_hint = root_dag.getGlobalHints() || subquery_global_hint;
1263  root_dag.setGlobalQueryHints(new_global_hint);
1264  }
1265  const auto subquery_local_hint = subquery_dag->getQueryHint(subquery_root_node.get());
1266  if (subquery_local_hint) {
1267  // register local query hint of this subquery to its parent to correctly
1268  // enables them when executing this subquery
1269  root_dag.registerQueryHint(subquery_root_node.get(), *subquery_local_hint);
1270  }
1271  return subquery->deepCopy();
1272 }
void setGlobalQueryHints(const RegisteredQueryHint &global_hints)
Definition: RelAlgDag.h:3340
#define CHECK_GE(x, y)
Definition: Logger.h:306
void registerQueryHint(const RelAlgNode *node, const RegisteredQueryHint &query_hint)
Definition: RelAlgDag.h:3298
const RegisteredQueryHint & getGlobalHints() const
Definition: RelAlgDag.h:3338
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
static std::unique_ptr< RelAlgDag > buildDagForSubquery(RelAlgDag &root_dag, const rapidjson::Value &query_ast)
Definition: RelAlgDag.cpp:3355
void registerSubquery(std::shared_ptr< RexSubQuery > subquery)
Definition: RelAlgDag.h:2830
#define CHECK(condition)
Definition: Logger.h:291

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

1080  {
1081  if (type_obj.IsArray()) {
1082  throw QueryNotSupported("Composite types are not currently supported.");
1083  }
1084  CHECK(type_obj.IsObject() && type_obj.MemberCount() >= 2)
1085  << json_node_to_string(type_obj);
1086  const auto type = to_sql_type(json_str(field(type_obj, "type")));
1087  const auto nullable = json_bool(field(type_obj, "nullable"));
1088  const auto precision_it = type_obj.FindMember("precision");
1089  const int precision =
1090  precision_it != type_obj.MemberEnd() ? json_i64(precision_it->value) : 0;
1091  const auto scale_it = type_obj.FindMember("scale");
1092  const int scale = scale_it != type_obj.MemberEnd() ? json_i64(scale_it->value) : 0;
1093  SQLTypeInfo ti(type, !nullable);
1094  ti.set_precision(precision);
1095  ti.set_scale(scale);
1096  return ti;
1097 }
SQLTypes to_sql_type(const std::string &type_name)
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:51
std::string json_node_to_string(const rapidjson::Value &node) noexcept
Definition: RelAlgDag.cpp:978
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:46
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:41
#define CHECK(condition)
Definition: Logger.h:291

+ 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,
RelAlgDag root_dag 
)

Definition at line 1228 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

1230  {
1231  CHECK(window_bound_obj.IsObject());
1233  window_bound.unbounded = json_bool(field(window_bound_obj, "unbounded"));
1234  window_bound.preceding = json_bool(field(window_bound_obj, "preceding"));
1235  window_bound.following = json_bool(field(window_bound_obj, "following"));
1236  window_bound.is_current_row = json_bool(field(window_bound_obj, "is_current_row"));
1237  const auto& offset_field = field(window_bound_obj, "offset");
1238  if (offset_field.IsObject()) {
1239  window_bound.bound_expr = parse_scalar_expr(offset_field, root_dag);
1240  } else {
1241  CHECK(offset_field.IsNull());
1242  }
1243  window_bound.order_key = json_i64(field(window_bound_obj, "order_key"));
1244  return window_bound;
1245 }
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:51
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:41
#define CHECK(condition)
Definition: Logger.h:291
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1378

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

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

Referenced by parse_operator().

1109  {
1110  if (name == "ROW_NUMBER") {
1112  }
1113  if (name == "RANK") {
1115  }
1116  if (name == "DENSE_RANK") {
1118  }
1119  if (name == "PERCENT_RANK") {
1121  }
1122  if (name == "CUME_DIST") {
1124  }
1125  if (name == "NTILE") {
1127  }
1128  if (name == "LAG") {
1130  }
1131  if (name == "LAG_IN_FRAME") {
1133  }
1134  if (name == "LEAD") {
1136  }
1137  if (name == "LEAD_IN_FRAME") {
1139  }
1140  if (name == "FIRST_VALUE") {
1142  }
1143  if (name == "LAST_VALUE") {
1145  }
1146  if (name == "NTH_VALUE") {
1148  }
1149  if (name == "NTH_VALUE_IN_FRAME") {
1151  }
1152  if (name == "FIRST_VALUE_IN_FRAME") {
1154  }
1155  if (name == "LAST_VALUE_IN_FRAME") {
1157  }
1158  if (name == "AVG") {
1160  }
1161  if (name == "MIN") {
1163  }
1164  if (name == "MAX") {
1166  }
1167  if (name == "SUM") {
1169  }
1170  if (name == "COUNT") {
1172  }
1173  if (name == "COUNT_IF") {
1175  }
1176  if (name == "SUM_IF") {
1178  }
1179  if (name == "$SUM0") {
1181  }
1182  if (name == "FORWARD_FILL") {
1184  }
1185  if (name == "BACKWARD_FILL") {
1187  }
1188  if (name == "CONDITIONAL_CHANGE_EVENT") {
1190  }
1191  throw std::runtime_error("Unsupported window function: " + name);
1192 }
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,
RelAlgDag root_dag 
)

Definition at line 1216 of file RelAlgDag.cpp.

References parse_nulls_position(), and parse_sort_direction().

Referenced by parse_operator().

1217  {
1218  std::vector<SortField> collation;
1219  size_t field_idx = 0;
1220  for (auto it = arr.Begin(); it != arr.End(); ++it, ++field_idx) {
1221  const auto sort_dir = parse_sort_direction(*it);
1222  const auto null_pos = parse_nulls_position(*it);
1223  collation.emplace_back(field_idx, sort_dir, null_pos);
1224  }
1225  return collation;
1226 }
NullSortedPosition parse_nulls_position(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1210
SortDirection parse_sort_direction(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1204

+ 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,
RelAlgDag root_dag 
)

Definition at line 1194 of file RelAlgDag.cpp.

References field(), and parse_scalar_expr().

Referenced by parse_operator().

1196  {
1197  std::vector<std::unique_ptr<const RexScalar>> exprs;
1198  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1199  exprs.emplace_back(parse_scalar_expr(field(*it, "field"), root_dag));
1200  }
1201  return exprs;
1202 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1378

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

References CHECK.

Referenced by add_window_function_pre_project(), and separate_window_function_expressions().

2416  {
2417  auto delivered_hints = prev_node->getDeliveredHints();
2418  bool needs_propagate_hints = !delivered_hints->empty();
2419  if (needs_propagate_hints) {
2420  for (auto& kv : *delivered_hints) {
2421  new_node->addHint(kv.second);
2422  }
2423  auto prev_it = query_hints.find(prev_node->toHash());
2424  // query hint for the prev projection node should be registered
2425  CHECK(prev_it != query_hints.end());
2426  auto prev_hint_it = prev_it->second.find(prev_node->getId());
2427  CHECK(prev_hint_it != prev_it->second.end());
2428  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
2429  hint_map.emplace(new_node->getId(), prev_hint_it->second);
2430  query_hints.emplace(new_node->toHash(), hint_map);
2431  }
2432 }
#define CHECK(condition)
Definition: Logger.h:291

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

References CHECK.

643  {
644  std::vector<const Rex*> target_exprs(target_exprs_old);
645  std::unordered_map<const Rex*, const Rex*> old_to_new_target(target_exprs.size());
646  for (size_t i = 0; i < agg_exprs_new.size(); ++i) {
647  old_to_new_target.emplace(agg_exprs_old[i].get(), agg_exprs_new[i].get());
648  }
649  for (size_t i = 0; i < scalar_sources_new.size(); ++i) {
650  old_to_new_target.emplace(scalar_sources_old[i].get(), scalar_sources_new[i].get());
651  }
652  for (auto& target : target_exprs) {
653  auto target_it = old_to_new_target.find(target);
654  CHECK(target_it != old_to_new_target.end());
655  target = target_it->second;
656  }
657  return target_exprs;
658 }
#define CHECK(condition)
Definition: Logger.h:291
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 711 of file RelAlgDag.cpp.

References CHECK, and CHECK_EQ.

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

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

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

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

2459  {
2460  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2461  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2462  const auto node = *node_itr;
2463  auto window_func_project_node = std::dynamic_pointer_cast<RelProject>(node);
2464  if (!window_func_project_node) {
2465  continue;
2466  }
2467 
2468  const auto prev_node_itr = std::prev(node_itr);
2469  const auto prev_node = *prev_node_itr;
2470  CHECK(prev_node);
2471 
2472  // map scalar expression index in the project node to window function ptr
2473  std::unordered_map<size_t, const RexScalar*> collected_window_func;
2474  WindowFunctionCollector collector(collected_window_func, false);
2475  // Iterate the target exprs of the project node and check for window function
2476  // expressions. If an embedded expression exists, collect it
2477  for (size_t i = 0; i < window_func_project_node->size(); i++) {
2478  const auto scalar_rex = window_func_project_node->getProjectAt(i);
2479  if (is_window_function_operator(scalar_rex)) {
2480  // top level window function exprs are fine
2481  continue;
2482  }
2483  collector.visit(scalar_rex);
2484  }
2485 
2486  if (!collected_window_func.empty()) {
2487  // we have a nested window function expression
2488  std::unordered_set<size_t> collected_window_func_hash;
2489  // the current window function needs a set of new rex input which references
2490  // expressions in the newly introduced projection node
2491  std::vector<std::unique_ptr<const RexScalar>> new_rex_input_for_window_func;
2492  // a target projection expression of the newly created projection node
2493  std::vector<std::unique_ptr<const RexScalar>> new_scalar_expr_for_window_project;
2494  // a map between nested window function (hash val) and
2495  // its rex index stored in the `new_rex_input_for_window_func`
2496  std::unordered_map<size_t, size_t> window_func_to_new_rex_input_idx_map;
2497  // a map between RexInput of the current window function projection node (hash
2498  // val) and its corresponding new RexInput which is pushed down to the new
2499  // projection node
2500  std::unordered_map<size_t, std::unique_ptr<const RexInput>>
2501  new_rex_input_from_child_node;
2502  RexDeepCopyVisitor copier;
2503 
2504  std::vector<std::unique_ptr<const RexScalar>> dummy_scalar_exprs;
2505  std::vector<std::string> dummy_fields;
2506  std::vector<std::string> new_project_field_names;
2507  // create a new project node, it will contain window function expressions
2508  auto new_project =
2509  std::make_shared<RelProject>(dummy_scalar_exprs, dummy_fields, prev_node);
2510  // insert this new project node between the current window project node and its
2511  // child node
2512  node_list.insert(node_itr, new_project);
2513 
2514  // retrieve various information to replace expressions in the current window
2515  // function project node w/ considering scalar expressions in the new project node
2516  std::for_each(collected_window_func.begin(),
2517  collected_window_func.end(),
2518  [&new_project_field_names,
2519  &collected_window_func_hash,
2520  &new_rex_input_for_window_func,
2521  &new_scalar_expr_for_window_project,
2522  &copier,
2523  &new_project,
2524  &window_func_to_new_rex_input_idx_map](const auto& kv) {
2525  // compute window function expr's hash, and create a new rex_input
2526  // for it
2527  collected_window_func_hash.insert(kv.first);
2528 
2529  // map an old expression in the window function project node
2530  // to an index of the corresponding new RexInput
2531  const auto rex_idx = new_rex_input_for_window_func.size();
2532  window_func_to_new_rex_input_idx_map.emplace(kv.first, rex_idx);
2533 
2534  // create a new RexInput and make it as one of new expression of
2535  // the newly created project node
2536  new_rex_input_for_window_func.emplace_back(
2537  std::make_unique<const RexInput>(new_project.get(), rex_idx));
2538  new_scalar_expr_for_window_project.push_back(
2539  std::move(copier.visit(kv.second)));
2540  new_project_field_names.emplace_back("");
2541  });
2542  new_project->setExpressions(new_scalar_expr_for_window_project);
2543  new_project->setFields(std::move(new_project_field_names));
2544 
2545  auto window_func_scalar_exprs =
2546  window_func_project_node->getExpressionsAndRelease();
2547  RexWindowFuncReplacementVisitor replacer(collected_window_func_hash,
2548  new_rex_input_for_window_func,
2549  window_func_to_new_rex_input_idx_map,
2550  new_project.get(),
2551  new_rex_input_from_child_node);
2552  size_t rex_idx = 0;
2553  for (auto& scalar_expr : window_func_scalar_exprs) {
2554  // try to replace the old expressions in the window function project node
2555  // with expressions of the newly created project node
2556  auto new_parent_rex = replacer.visit(scalar_expr.get());
2557  window_func_scalar_exprs[rex_idx] = std::move(new_parent_rex);
2558  rex_idx++;
2559  }
2560  // Update the previous window project node
2561  window_func_project_node->setExpressions(window_func_scalar_exprs);
2562  window_func_project_node->replaceInput(prev_node, new_project);
2563  propagate_hints_to_new_project(window_func_project_node, new_project, query_hints);
2564  new_project->setPushedDownWindowExpr();
2565  }
2566  }
2567  nodes.assign(node_list.begin(), node_list.end());
2568 }
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:2412
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
#define CHECK(condition)
Definition: Logger.h:291

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

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

References CHECK.

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

1337  {
1338  CHECK(json_str_arr.IsArray());
1339  std::vector<std::string> fields;
1340  for (auto json_str_arr_it = json_str_arr.Begin(); json_str_arr_it != json_str_arr.End();
1341  ++json_str_arr_it) {
1342  CHECK(json_str_arr_it->IsString());
1343  fields.emplace_back(json_str_arr_it->GetString());
1344  }
1345  return fields;
1346 }
#define CHECK(condition)
Definition: Logger.h:291

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

References ANTI, INNER, LEFT, and SEMI.

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

1401  {
1402  if (join_type_name == "inner") {
1403  return JoinType::INNER;
1404  }
1405  if (join_type_name == "left") {
1406  return JoinType::LEFT;
1407  }
1408  if (join_type_name == "semi") {
1409  return JoinType::SEMI;
1410  }
1411  if (join_type_name == "anti") {
1412  return JoinType::ANTI;
1413  }
1414  throw QueryNotSupported("Join type (" + join_type_name + ") not supported");
1415 }

+ Here is the caller graph for this function:

Variable Documentation

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

Definition at line 41 of file RelAlgDag.cpp.

Referenced by RelAlgNode::resetRelAlgFirstId().