OmniSciDB  a5dc49c757
 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 2573 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 2653 of file RelAlgDag.cpp.

References anonymous_namespace{Utm.h}::a, CHECK, CHECK_EQ, CHECK_GT, RelAggregate::getGroupByCount(), kBOOLEAN, 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().

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

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

References CHECK_EQ, and disambiguate_rex().

Referenced by bind_inputs(), and create_compound().

1504  {
1505  CHECK_EQ(size_t(1), project_node->inputCount());
1506  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1507  for (size_t i = 0; i < project_node->size(); ++i) {
1508  const auto projected_expr = project_node->getProjectAt(i);
1509  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
1510  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
1511  } else {
1512  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
1513  }
1514  }
1515  project_node->setExpressions(disambiguated_exprs);
1516 }
#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:1478
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 1518 of file RelAlgDag.cpp.

References disambiguate_rex().

Referenced by bind_inputs().

1519  {
1520  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1521  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
1522  const auto target_expr = table_func_node->getTableFuncInputAt(i);
1523  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
1524  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
1525  } else {
1526  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
1527  }
1528  }
1529  table_func_node->setTableFuncInputs(std::move(disambiguated_exprs));
1530 }
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1478
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 2855 of file RelAlgDag.cpp.

References CHECK, and field().

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

2855  {
2856  const auto& inputs_json = field(node, "inputs");
2857  CHECK(inputs_json.IsArray() && !inputs_json.Size());
2858 }
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 2011 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().

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

References CHECK_NE.

Referenced by RelAlgDagBuilder::optimizeDag().

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

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

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

Referenced by disambiguate_rex().

1458  {
1459  std::vector<
1460  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
1461  disambiguated_expr_pair_list;
1462  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
1463  auto disambiguated_when = disambiguate_rex(rex_case->getWhen(i), ra_output);
1464  auto disambiguated_then = disambiguate_rex(rex_case->getThen(i), ra_output);
1465  disambiguated_expr_pair_list.emplace_back(std::move(disambiguated_when),
1466  std::move(disambiguated_then));
1467  }
1468  std::unique_ptr<const RexScalar> disambiguated_else{
1469  disambiguate_rex(rex_case->getElse(), ra_output)};
1470  return std::unique_ptr<const RexCase>(
1471  new RexCase(disambiguated_expr_pair_list, disambiguated_else));
1472 }
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:1478
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 1422 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

1424  {
1425  std::vector<std::unique_ptr<const RexScalar>> disambiguated_operands;
1426  for (size_t i = 0; i < rex_operator->size(); ++i) {
1427  auto operand = rex_operator->getOperand(i);
1428  if (dynamic_cast<const RexSubQuery*>(operand)) {
1429  disambiguated_operands.emplace_back(rex_operator->getOperandAndRelease(i));
1430  } else {
1431  disambiguated_operands.emplace_back(disambiguate_rex(operand, ra_output));
1432  }
1433  }
1434  const auto rex_window_function_operator =
1435  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
1436  if (rex_window_function_operator) {
1437  const auto& partition_keys = rex_window_function_operator->getPartitionKeys();
1438  std::vector<std::unique_ptr<const RexScalar>> disambiguated_partition_keys;
1439  for (const auto& partition_key : partition_keys) {
1440  disambiguated_partition_keys.emplace_back(
1441  disambiguate_rex(partition_key.get(), ra_output));
1442  }
1443  std::vector<std::unique_ptr<const RexScalar>> disambiguated_order_keys;
1444  const auto& order_keys = rex_window_function_operator->getOrderKeys();
1445  for (const auto& order_key : order_keys) {
1446  disambiguated_order_keys.emplace_back(disambiguate_rex(order_key.get(), ra_output));
1447  }
1448  return rex_window_function_operator->disambiguatedOperands(
1449  disambiguated_operands,
1450  disambiguated_partition_keys,
1451  disambiguated_order_keys,
1452  rex_window_function_operator->getCollation());
1453  }
1454  return rex_operator->getDisambiguated(disambiguated_operands);
1455 }
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:1478
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 1478 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().

1479  {
1480  const auto rex_abstract_input = dynamic_cast<const RexAbstractInput*>(rex_scalar);
1481  if (rex_abstract_input) {
1482  CHECK_LT(static_cast<size_t>(rex_abstract_input->getIndex()), ra_output.size());
1483  return std::unique_ptr<const RexInput>(
1484  new RexInput(ra_output[rex_abstract_input->getIndex()]));
1485  }
1486  const auto rex_operator = dynamic_cast<const RexOperator*>(rex_scalar);
1487  if (rex_operator) {
1488  return disambiguate_operator(rex_operator, ra_output);
1489  }
1490  const auto rex_case = dynamic_cast<const RexCase*>(rex_scalar);
1491  if (rex_case) {
1492  return disambiguate_case(rex_case, ra_output);
1493  }
1494  if (auto const rex_literal = dynamic_cast<const RexLiteral*>(rex_scalar)) {
1495  return rex_literal->deepCopy();
1496  } else if (auto const rex_subquery = dynamic_cast<const RexSubQuery*>(rex_scalar)) {
1497  return rex_subquery->deepCopy();
1498  } else {
1499  throw QueryNotSupported("Unable to disambiguate expression of type " +
1500  std::string(typeid(*rex_scalar).name()));
1501  }
1502 }
std::unique_ptr< const RexOperator > disambiguate_operator(const RexOperator *rex_operator, const RANodeOutput &ra_output) noexcept
Definition: RelAlgDag.cpp:1422
std::unique_ptr< const RexCase > disambiguate_case(const RexCase *rex_case, const RANodeOutput &ra_output)
Definition: RelAlgDag.cpp:1457
#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 2174 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

2174  {
2175  for (auto& node : nodes) {
2176  if (auto* proj_node = dynamic_cast<RelProject*>(node.get())) {
2177  if (proj_node->isSimple()) {
2178  if (auto child_proj_node =
2179  dynamic_cast<RelProject const*>(proj_node->getInput(0))) {
2180  std::vector<std::unique_ptr<RexScalar const>> scalar_exprs;
2181  RexDeepCopyVisitor copier;
2182  for (size_t i = 0; i < proj_node->size(); i++) {
2183  auto rex_abs_input =
2184  dynamic_cast<RexAbstractInput const*>(proj_node->getProjectAt(i));
2185  scalar_exprs.push_back(
2186  copier.visit(child_proj_node->getProjectAt(rex_abs_input->getIndex())));
2187  }
2188  CHECK_EQ(scalar_exprs.size(), proj_node->getFields().size());
2189  proj_node->setExpressions(scalar_exprs);
2190  proj_node->replaceInput(proj_node->getAndOwnInput(0),
2191  child_proj_node->getAndOwnInput(0));
2192  }
2193  }
2194  }
2195  }
2196 }
#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 2841 of file RelAlgDag.cpp.

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

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

2843  {
2844  const auto it = obj.FindMember(field);
2845  if (it == obj.MemberEnd()) {
2846  return default_val;
2847  }
2848  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
2849  CHECK_EQ(kDECIMAL, lit->getType());
2850  CHECK_EQ(unsigned(0), lit->getScale());
2851  CHECK_EQ(unsigned(0), lit->getTargetScale());
2852  return lit->getVal<int64_t>();
2853 }
#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 2861 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().

2861  {
2862  const auto& table_json = field(scan_ra, "table");
2863  CHECK(table_json.IsArray());
2864  CHECK_EQ(unsigned(2), table_json.Size());
2865  const auto cat =
2866  Catalog_Namespace::SysCatalog::instance().getCatalog(table_json[0].GetString());
2867  CHECK(cat);
2868  const auto td = cat->getMetadataForTable(table_json[1].GetString());
2869  CHECK(td);
2870  return {cat.get(), td};
2871 }
#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 2873 of file RelAlgDag.cpp.

References field(), and strings_from_json_array().

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

2873  {
2874  const auto& fields_json = field(scan_ra, "fieldNames");
2875  return strings_from_json_array(fields_json);
2876 }
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 2138 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().

2141  {
2142  std::list<std::shared_ptr<RelAlgNode>> node_list(nodes.begin(), nodes.end());
2143  bool replace_nodes = false;
2144  for (auto node_itr = node_list.begin(); node_itr != node_list.end(); ++node_itr) {
2145  auto node = *node_itr;
2146  if (auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node)) {
2147  std::vector<std::unique_ptr<const RexScalar>> scalar_exprs;
2148  std::vector<std::string> fields;
2149  std::shared_ptr<RelProject> new_project;
2150  CHECK_EQ(agg_node->getInputs().size(), size_t(1));
2151  CHECK_NE(*node_itr, *node_list.begin());
2152  const auto prev_node = *std::prev(node_itr);
2153  CHECK(prev_node);
2154  auto const input_node_ptr = agg_node->getAndOwnInput(0);
2155  if (auto join_node =
2156  std::dynamic_pointer_cast<RelLeftDeepInnerJoin const>(input_node_ptr)) {
2157  for (auto const* join_input_node : join_node->getInputs()) {
2158  create_rex_input_for_new_project_node(join_input_node, scalar_exprs, fields);
2159  }
2160  if (!scalar_exprs.empty()) {
2161  replace_nodes = true;
2162  new_project = std::make_shared<RelProject>(scalar_exprs, fields, join_node);
2163  agg_node->replaceInput(join_node, new_project);
2164  node_list.insert(node_itr, new_project);
2165  }
2166  }
2167  }
2168  }
2169  if (replace_nodes) {
2170  nodes.assign(node_list.begin(), node_list.end());
2171  }
2172 }
#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:2121
#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 1573 of file RelAlgDag.cpp.

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

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

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

References CHECK_EQ, and RelAlgNode::markAsNop().

Referenced by RelAlgDagBuilder::optimizeDag().

1625  {
1626  for (auto node : nodes) {
1627  const auto agg_node = std::dynamic_pointer_cast<RelAggregate>(node);
1628  if (!agg_node || agg_node->getAggExprsCount()) {
1629  continue;
1630  }
1631  CHECK_EQ(size_t(1), node->inputCount());
1632  const auto agg_input_node = dynamic_cast<const RelAggregate*>(node->getInput(0));
1633  if (agg_input_node && !agg_input_node->getAggExprsCount() &&
1634  agg_node->getGroupByCount() == agg_input_node->getGroupByCount()) {
1635  agg_node->markAsNop();
1636  }
1637  }
1638 }
#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:55
#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  std::string const node_str = json_node_to_string(expr);
1398  if (node_str.find("\"correl\":\"$cor") != std::string::npos) {
1399  throw QueryNotSupported("Unable to decorrelate one of the correlated subqueries.");
1400  }
1401  throw QueryNotSupported("Expression node " + node_str + " not supported");
1402 }
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:3369
#define CHECK_GE(x, y)
Definition: Logger.h:306
void registerQueryHint(const RelAlgNode *node, const RegisteredQueryHint &query_hint)
Definition: RelAlgDag.h:3327
const RegisteredQueryHint & getGlobalHints() const
Definition: RelAlgDag.h:3367
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:3378
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 2415 of file RelAlgDag.cpp.

References CHECK.

Referenced by add_window_function_pre_project(), and separate_window_function_expressions().

2419  {
2420  auto delivered_hints = prev_node->getDeliveredHints();
2421  bool needs_propagate_hints = !delivered_hints->empty();
2422  if (needs_propagate_hints) {
2423  for (auto& kv : *delivered_hints) {
2424  new_node->addHint(kv.second);
2425  }
2426  auto prev_it = query_hints.find(prev_node->toHash());
2427  // query hint for the prev projection node should be registered
2428  CHECK(prev_it != query_hints.end());
2429  auto prev_hint_it = prev_it->second.find(prev_node->getId());
2430  CHECK(prev_hint_it != prev_it->second.end());
2431  std::unordered_map<unsigned, RegisteredQueryHint> hint_map;
2432  hint_map.emplace(new_node->getId(), prev_hint_it->second);
2433  query_hints.emplace(new_node->toHash(), hint_map);
2434  }
2435 }
#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:477

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

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

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

References ANTI, INNER, LEFT, and SEMI.

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

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

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