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

Namespaces

 anonymous_namespace{RelAlgDag.cpp}
 

Classes

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

Typedefs

using RexInputSet = std::unordered_set< RexInput >
 

Functions

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

Variables

const unsigned FIRST_RA_NODE_ID = 1
 

Typedef Documentation

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

Definition at line 2374 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 2403 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1391 of file RelAlgDag.cpp.

References CHECK_EQ, and disambiguate_rex().

Referenced by bind_inputs(), and create_compound().

1391  {
1392  CHECK_EQ(size_t(1), project_node->inputCount());
1393  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1394  for (size_t i = 0; i < project_node->size(); ++i) {
1395  const auto projected_expr = project_node->getProjectAt(i);
1396  if (dynamic_cast<const RexSubQuery*>(projected_expr)) {
1397  disambiguated_exprs.emplace_back(project_node->getProjectAtAndRelease(i));
1398  } else {
1399  disambiguated_exprs.emplace_back(disambiguate_rex(projected_expr, input));
1400  }
1401  }
1402  project_node->setExpressions(disambiguated_exprs);
1403 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
size_t size() const override
Definition: RelAlgDag.h:1068
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1365
void setExpressions(std::vector< std::unique_ptr< const RexScalar >> &exprs) const
Definition: RelAlgDag.h:1048
const RexScalar * getProjectAtAndRelease(const size_t idx) const
Definition: RelAlgDag.h:1075
const RexScalar * getProjectAt(const size_t idx) const
Definition: RelAlgDag.h:1070
const size_t inputCount() const
Definition: RelAlgDag.h:824

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1405 of file RelAlgDag.cpp.

References disambiguate_rex().

Referenced by bind_inputs().

1406  {
1407  std::vector<std::unique_ptr<const RexScalar>> disambiguated_exprs;
1408  for (size_t i = 0; i < table_func_node->getTableFuncInputsSize(); ++i) {
1409  const auto target_expr = table_func_node->getTableFuncInputAt(i);
1410  if (dynamic_cast<const RexSubQuery*>(target_expr)) {
1411  disambiguated_exprs.emplace_back(table_func_node->getTableFuncInputAtAndRelease(i));
1412  } else {
1413  disambiguated_exprs.emplace_back(disambiguate_rex(target_expr, input));
1414  }
1415  }
1416  table_func_node->setTableFuncInputs(disambiguated_exprs);
1417 }
std::unique_ptr< const RexScalar > disambiguate_rex(const RexScalar *, const RANodeOutput &)
Definition: RelAlgDag.cpp:1365
const RexScalar * getTableFuncInputAtAndRelease(const size_t idx)
Definition: RelAlgDag.h:2090
size_t getTableFuncInputsSize() const
Definition: RelAlgDag.h:2079
void setTableFuncInputs(std::vector< std::unique_ptr< const RexScalar >> &exprs)
Definition: RelAlgDag.h:2095
const RexScalar * getTableFuncInputAt(const size_t idx) const
Definition: RelAlgDag.h:2085

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

References CHECK, and field().

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

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

References CHECK_NE.

Referenced by RelAlgDagBuilder::optimizeDag().

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

+ Here is the caller graph for this function:

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

Definition at line 615 of file RelAlgDag.cpp.

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

Definition at line 625 of file RelAlgDag.cpp.

References RexVisitorBase< T >::visit().

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

+ Here is the call graph for this function:

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1344 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1309 of file RelAlgDag.cpp.

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

Referenced by disambiguate_rex().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 740 of file RelAlgDag.cpp.

References CHECK, and CHECK_EQ.

Referenced by RelSort::hasEquivCollationOf().

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

+ Here is the caller graph for this function:

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

Definition at line 2587 of file RelAlgDag.cpp.

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

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

2589  {
2590  const auto it = obj.FindMember(field);
2591  if (it == obj.MemberEnd()) {
2592  return default_val;
2593  }
2594  std::unique_ptr<RexLiteral> lit(parse_literal(it->value));
2595  CHECK_EQ(kDECIMAL, lit->getType());
2596  CHECK_EQ(unsigned(0), lit->getScale());
2597  CHECK_EQ(unsigned(0), lit->getTargetScale());
2598  return lit->getVal<int64_t>();
2599 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::unique_ptr< RexLiteral > parse_literal(const rapidjson::Value &expr)
Definition: RelAlgDag.cpp:921

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2616 of file RelAlgDag.cpp.

References field(), and strings_from_json_array().

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

2616  {
2617  const auto& fields_json = field(scan_ra, "fieldNames");
2618  return strings_from_json_array(fields_json);
2619 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::vector< std::string > strings_from_json_array(const rapidjson::Value &json_str_arr) noexcept
Definition: RelAlgDag.cpp:1226

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2606 of file RelAlgDag.cpp.

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1460 of file RelAlgDag.cpp.

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

Referenced by RelAlgDagBuilder::optimizeDag().

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

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

References CHECK, and CHECK_GE.

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

1239  {
1240  CHECK(json_idx_arr.IsArray());
1241  std::vector<size_t> indices;
1242  for (auto json_idx_arr_it = json_idx_arr.Begin(); json_idx_arr_it != json_idx_arr.End();
1243  ++json_idx_arr_it) {
1244  CHECK(json_idx_arr_it->IsInt());
1245  CHECK_GE(json_idx_arr_it->GetInt(), 0);
1246  indices.emplace_back(json_idx_arr_it->GetInt());
1247  }
1248  return indices;
1249 }
#define CHECK_GE(x, y)
Definition: Logger.h:235
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the caller graph for this function:

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

Definition at line 469 of file RelAlgDag.cpp.

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

Referenced by RelProject::isRenaming().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 904 of file RelAlgDag.cpp.

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

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

+ Here is the caller graph for this function:

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

Definition at line 1507 of file RelAlgDag.cpp.

References CHECK_EQ, and RelAlgNode::markAsNop().

Referenced by RelAlgDagBuilder::optimizeDag().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 95 of file RelAlgDag.cpp.

References anonymous_namespace{Utm.h}::n.

Referenced by get_node_output().

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

+ Here is the caller graph for this function:

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

Definition at line 899 of file RelAlgDag.cpp.

References field(), and json_str().

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

899  {
900  const auto& id = field(ra_node, "id");
901  return std::stoi(json_str(id));
902 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 915 of file RelAlgDag.cpp.

References field(), and json_i64().

Referenced by parse_scalar_expr().

916  {
917  const auto& input = field(expr, "input");
918  return std::unique_ptr<RexAbstractInput>(new RexAbstractInput(json_i64(input)));
919 }
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1251 of file RelAlgDag.cpp.

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1204 of file RelAlgDag.cpp.

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

Referenced by parse_scalar_expr().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1026 of file RelAlgDag.cpp.

References parse_scalar_expr().

Referenced by parse_operator().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 921 of file RelAlgDag.cpp.

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

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

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

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

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

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

1106  {
1107  return json_str(field(collation, "nulls")) == std::string("FIRST")
1110 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

1269  {
1270  CHECK(expr.IsObject());
1271  if (expr.IsObject() && expr.HasMember("input")) {
1272  return std::unique_ptr<const RexScalar>(parse_abstract_input(expr));
1273  }
1274  if (expr.IsObject() && expr.HasMember("literal")) {
1275  return std::unique_ptr<const RexScalar>(parse_literal(expr));
1276  }
1277  if (expr.IsObject() && expr.HasMember("op")) {
1278  const auto op_str = json_str(field(expr, "op"));
1279  if (op_str == std::string("CASE")) {
1280  return std::unique_ptr<const RexScalar>(parse_case(expr, cat, root_dag));
1281  }
1282  if (op_str == std::string("$SCALAR_QUERY")) {
1283  return std::unique_ptr<const RexScalar>(parse_subquery(expr, cat, root_dag));
1284  }
1285  return std::unique_ptr<const RexScalar>(parse_operator(expr, cat, root_dag));
1286  }
1287  throw QueryNotSupported("Expression node " + json_node_to_string(expr) +
1288  " not supported");
1289 }
std::unique_ptr< RexOperator > parse_operator(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1159
std::unique_ptr< const RexSubQuery > parse_subquery(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1145
std::string json_node_to_string(const rapidjson::Value &node) noexcept
Definition: RelAlgDag.cpp:904
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
std::unique_ptr< RexAbstractInput > parse_abstract_input(const rapidjson::Value &expr) noexcept
Definition: RelAlgDag.cpp:915
std::unique_ptr< RexCase > parse_case(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1204
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::unique_ptr< RexLiteral > parse_literal(const rapidjson::Value &expr)
Definition: RelAlgDag.cpp:921
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1100 of file RelAlgDag.cpp.

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

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

1100  {
1101  return json_str(field(collation, "direction")) == std::string("DESCENDING")
1104 }
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1145 of file RelAlgDag.cpp.

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

Referenced by parse_operator(), and parse_scalar_expr().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1007 of file RelAlgDag.cpp.

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1125 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

1128  {
1129  CHECK(window_bound_obj.IsObject());
1131  window_bound.unbounded = json_bool(field(window_bound_obj, "unbounded"));
1132  window_bound.preceding = json_bool(field(window_bound_obj, "preceding"));
1133  window_bound.following = json_bool(field(window_bound_obj, "following"));
1134  window_bound.is_current_row = json_bool(field(window_bound_obj, "is_current_row"));
1135  const auto& offset_field = field(window_bound_obj, "offset");
1136  if (offset_field.IsObject()) {
1137  window_bound.bound_expr = parse_scalar_expr(offset_field, cat, root_dag);
1138  } else {
1139  CHECK(offset_field.IsNull());
1140  }
1141  window_bound.order_key = json_i64(field(window_bound_obj, "order_key"));
1142  return window_bound;
1143 }
const bool json_bool(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:49
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1267
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
const int64_t json_i64(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:39
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1037 of file RelAlgDag.cpp.

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

Referenced by parse_operator().

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

+ Here is the caller graph for this function:

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

Definition at line 1112 of file RelAlgDag.cpp.

References parse_nulls_position(), and parse_sort_direction().

Referenced by parse_operator().

1114  {
1115  std::vector<SortField> collation;
1116  size_t field_idx = 0;
1117  for (auto it = arr.Begin(); it != arr.End(); ++it, ++field_idx) {
1118  const auto sort_dir = parse_sort_direction(*it);
1119  const auto null_pos = parse_nulls_position(*it);
1120  collation.emplace_back(field_idx, sort_dir, null_pos);
1121  }
1122  return collation;
1123 }
NullSortedPosition parse_nulls_position(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1106
SortDirection parse_sort_direction(const rapidjson::Value &collation)
Definition: RelAlgDag.cpp:1100

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1089 of file RelAlgDag.cpp.

References field(), and parse_scalar_expr().

Referenced by parse_operator().

1092  {
1093  std::vector<std::unique_ptr<const RexScalar>> exprs;
1094  for (auto it = arr.Begin(); it != arr.End(); ++it) {
1095  exprs.emplace_back(parse_scalar_expr(field(*it, "field"), cat, root_dag));
1096  }
1097  return exprs;
1098 }
std::unique_ptr< const RexScalar > parse_scalar_expr(const rapidjson::Value &expr, const Catalog_Namespace::Catalog &cat, RelAlgDag &root_dag)
Definition: RelAlgDag.cpp:1267
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 2217 of file RelAlgDag.cpp.

References CHECK.

Referenced by add_window_function_pre_project(), and separate_window_function_expressions().

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

+ Here is the caller graph for this function:

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

Definition at line 636 of file RelAlgDag.cpp.

References CHECK.

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

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 1226 of file RelAlgDag.cpp.

References CHECK.

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

1227  {
1228  CHECK(json_str_arr.IsArray());
1229  std::vector<std::string> fields;
1230  for (auto json_str_arr_it = json_str_arr.Begin(); json_str_arr_it != json_str_arr.End();
1231  ++json_str_arr_it) {
1232  CHECK(json_str_arr_it->IsString());
1233  fields.emplace_back(json_str_arr_it->GetString());
1234  }
1235  return fields;
1236 }
#define CHECK(condition)
Definition: Logger.h:222

+ Here is the caller graph for this function:

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

Definition at line 1291 of file RelAlgDag.cpp.

References ANTI, INNER, LEFT, and SEMI.

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

1291  {
1292  if (join_type_name == "inner") {
1293  return JoinType::INNER;
1294  }
1295  if (join_type_name == "left") {
1296  return JoinType::LEFT;
1297  }
1298  if (join_type_name == "semi") {
1299  return JoinType::SEMI;
1300  }
1301  if (join_type_name == "anti") {
1302  return JoinType::ANTI;
1303  }
1304  throw QueryNotSupported("Join type (" + join_type_name + ") not supported");
1305 }

+ Here is the caller graph for this function:

Variable Documentation

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

Definition at line 40 of file RelAlgDag.cpp.

Referenced by RelAlgNode::resetRelAlgFirstId().