TEST_F(ProjectionTests, BasicTest) { MockExecutor child_executor; EXPECT_CALL(child_executor, DInit()).WillOnce(Return(true)); EXPECT_CALL(child_executor, DExecute()) .WillOnce(Return(true)) .WillOnce(Return(false)); size_t tile_size = 5; // Create a table and wrap it in logical tile auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); std::unique_ptr<storage::DataTable> data_table( ExecutorTestsUtil::CreateTable(tile_size)); ExecutorTestsUtil::PopulateTable(txn, data_table.get(), tile_size, false, false, false); txn_manager.CommitTransaction(); std::unique_ptr<executor::LogicalTile> source_logical_tile1( executor::LogicalTileFactory::WrapTileGroup(data_table->GetTileGroup(0))); EXPECT_CALL(child_executor, GetOutput()) .WillOnce(Return(source_logical_tile1.release())); // Create the plan node planner::ProjectInfo::TargetList target_list; planner::ProjectInfo::DirectMapList direct_map_list; ///////////////////////////////////////////////////////// // PROJECTION 0 ///////////////////////////////////////////////////////// // construct schema std::vector<catalog::Column> columns; auto orig_schema = data_table.get()->GetSchema(); columns.push_back(orig_schema->GetColumn(0)); std::shared_ptr<const catalog::Schema> schema(new catalog::Schema(columns)); // direct map planner::ProjectInfo::DirectMap direct_map = std::make_pair(0, std::make_pair(0, 0)); direct_map_list.push_back(direct_map); std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(target_list), std::move(direct_map_list))); planner::ProjectionPlan node(std::move(project_info), schema); // Create and set up executor executor::ProjectionExecutor executor(&node, nullptr); executor.AddChild(&child_executor); RunTest(executor, 1); }
// FIXME: Should remove when the simple_optimizer tears down // Initializes the update plan without adding any child nodes and // retrieves column ids for the child scan plan. void UpdatePlan::BuildInitialUpdatePlan( const parser::UpdateStatement *parse_tree, std::vector<oid_t> &column_ids) { LOG_TRACE("Creating an Update Plan"); auto t_ref = parse_tree->table; auto table_name = std::string(t_ref->GetTableName()); auto database_name = t_ref->GetDatabaseName(); LOG_TRACE("Update database %s table %s", database_name, table_name.c_str()); target_table_ = catalog::Catalog::GetInstance()->GetTableWithName( database_name, table_name); PL_ASSERT(target_table_ != nullptr); for (auto update_clause : *parse_tree->updates) { updates_.push_back(update_clause->Copy()); } TargetList tlist; DirectMapList dmlist; oid_t col_id; auto schema = target_table_->GetSchema(); for (auto update : updates_) { // get oid_t of the column and push it to the vector; col_id = schema->GetColumnID(std::string(update->column)); column_ids.push_back(col_id); auto *update_expr = update->value->Copy(); expression::ExpressionUtil::TransformExpression(target_table_->GetSchema(), update_expr); planner::DerivedAttribute attribute{update_expr}; attribute.attribute_info.name = update->column; tlist.emplace_back(col_id, attribute); } auto &schema_columns = schema->GetColumns(); for (uint i = 0; i < schema_columns.size(); i++) { bool is_in_target_list = false; for (auto col_id : column_ids) { if (schema_columns[i].column_name == schema_columns[col_id].column_name) { is_in_target_list = true; break; } } if (is_in_target_list == false) dmlist.emplace_back(i, std::pair<oid_t, oid_t>(0, i)); } std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(tlist), std::move(dmlist))); project_info_ = std::move(project_info); if (parse_tree->where != nullptr) where_ = parse_tree->where->Copy(); else where_ = nullptr; expression::ExpressionUtil::TransformExpression(target_table_->GetSchema(), where_); }
bool TransactionTestsUtil::ExecuteUpdateByValue(concurrency::Transaction *txn, storage::DataTable *table, int old_value, int new_value) { std::unique_ptr<executor::ExecutorContext> context( new executor::ExecutorContext(txn)); Value update_val = ValueFactory::GetIntegerValue(new_value); // ProjectInfo planner::ProjectInfo::TargetList target_list; planner::ProjectInfo::DirectMapList direct_map_list; target_list.emplace_back( 1, expression::ExpressionUtil::ConstantValueFactory(update_val)); direct_map_list.emplace_back(0, std::pair<oid_t, oid_t>(0, 0)); // Update plan std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(target_list), std::move(direct_map_list))); planner::UpdatePlan update_node(table, std::move(project_info)); executor::UpdateExecutor update_executor(&update_node, context.get()); // Predicate auto tup_val_exp = new expression::TupleValueExpression(0, 1); auto const_val_exp = new expression::ConstantValueExpression( ValueFactory::GetIntegerValue(old_value)); auto predicate = new expression::ComparisonExpression<expression::CmpEq>( EXPRESSION_TYPE_COMPARE_EQUAL, tup_val_exp, const_val_exp); // Seq scan std::vector<oid_t> column_ids = {0, 1}; std::unique_ptr<planner::SeqScanPlan> seq_scan_node( new planner::SeqScanPlan(table, predicate, column_ids)); executor::SeqScanExecutor seq_scan_executor(seq_scan_node.get(), context.get()); update_node.AddChild(std::move(seq_scan_node)); update_executor.AddChild(&seq_scan_executor); EXPECT_TRUE(update_executor.Init()); return update_executor.Execute(); }
bool TransactionTestsUtil::ExecuteUpdate(concurrency::Transaction *transaction, storage::DataTable *table, int id, int value) { std::unique_ptr<executor::ExecutorContext> context( new executor::ExecutorContext(transaction)); Value update_val = ValueFactory::GetIntegerValue(value); // ProjectInfo planner::ProjectInfo::TargetList target_list; planner::ProjectInfo::DirectMapList direct_map_list; target_list.emplace_back( 1, expression::ExpressionUtil::ConstantValueFactory(update_val)); direct_map_list.emplace_back(0, std::pair<oid_t, oid_t>(0, 0)); // Update plan std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(target_list), std::move(direct_map_list))); planner::UpdatePlan update_node(table, std::move(project_info)); executor::UpdateExecutor update_executor(&update_node, context.get()); // Predicate auto predicate = MakePredicate(id); // Seq scan std::vector<oid_t> column_ids = {0}; std::unique_ptr<planner::SeqScanPlan> seq_scan_node( new planner::SeqScanPlan(table, predicate, column_ids)); executor::SeqScanExecutor seq_scan_executor(seq_scan_node.get(), context.get()); update_node.AddChild(std::move(seq_scan_node)); update_executor.AddChild(&seq_scan_executor); EXPECT_TRUE(update_executor.Init()); return update_executor.Execute(); }
TEST_F(ProjectionTests, BasicTargetTest) { MockExecutor child_executor; EXPECT_CALL(child_executor, DInit()).WillOnce(Return(true)); EXPECT_CALL(child_executor, DExecute()) .WillOnce(Return(true)) .WillOnce(Return(false)); size_t tile_size = 5; // Create a table and wrap it in logical tile auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); std::unique_ptr<storage::DataTable> data_table( TestingExecutorUtil::CreateTable(tile_size)); TestingExecutorUtil::PopulateTable(data_table.get(), tile_size, false, false, false, txn); txn_manager.CommitTransaction(txn); std::unique_ptr<executor::LogicalTile> source_logical_tile1( executor::LogicalTileFactory::WrapTileGroup(data_table->GetTileGroup(0))); EXPECT_CALL(child_executor, GetOutput()) .WillOnce(Return(source_logical_tile1.release())); // Create the plan node TargetList target_list; DirectMapList direct_map_list; ///////////////////////////////////////////////////////// // PROJECTION 0, TARGET 0 + 20 ///////////////////////////////////////////////////////// // construct schema std::vector<catalog::Column> columns; auto orig_schema = data_table.get()->GetSchema(); columns.push_back(orig_schema->GetColumn(0)); columns.push_back(orig_schema->GetColumn(0)); std::shared_ptr<const catalog::Schema> schema(new catalog::Schema(columns)); // direct map DirectMap direct_map = std::make_pair(0, std::make_pair(0, 0)); direct_map_list.push_back(direct_map); // target list auto const_val = new expression::ConstantValueExpression( type::ValueFactory::GetIntegerValue(20)); auto tuple_value_expr = expression::ExpressionUtil::TupleValueFactory(type::Type::INTEGER, 0, 0); expression::AbstractExpression *expr = expression::ExpressionUtil::OperatorFactory(ExpressionType::OPERATOR_PLUS, type::Type::INTEGER, tuple_value_expr, const_val); Target target = std::make_pair(1, expr); target_list.push_back(target); std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(target_list), std::move(direct_map_list))); planner::ProjectionPlan node(std::move(project_info), schema); // Create and set up executor executor::ProjectionExecutor executor(&node, nullptr); executor.AddChild(&child_executor); RunTest(executor, 1); }
/** * @brief Convert a Postgres NestLoop into a Peloton SeqScanNode. * @return Pointer to the constructed AbstractPlanNode. */ const planner::AbstractPlan *PlanTransformer::TransformNestLoop( const NestLoopPlanState *nl_plan_state) { PelotonJoinType peloton_join_type = PlanTransformer::TransformJoinType(nl_plan_state->jointype); NestLoop *nl = nl_plan_state->nl; if (peloton_join_type == JOIN_TYPE_INVALID) { LOG_ERROR("unsupported join type: %d", nl_plan_state->jointype); return nullptr; } expression::AbstractExpression *join_filter = ExprTransformer::TransformExpr( reinterpret_cast<ExprState *>(nl_plan_state->joinqual)); expression::AbstractExpression *plan_filter = ExprTransformer::TransformExpr( reinterpret_cast<ExprState *>(nl_plan_state->qual)); expression::AbstractExpression *predicate = nullptr; if (join_filter && plan_filter) { predicate = expression::ExpressionUtil::ConjunctionFactory( EXPRESSION_TYPE_CONJUNCTION_AND, join_filter, plan_filter); } else if (join_filter) { predicate = join_filter; } else { predicate = plan_filter; } // TODO: do we need to consider target list here? // Transform project info std::unique_ptr<const planner::ProjectInfo> project_info(nullptr); project_info.reset(BuildProjectInfo(nl_plan_state->ps_ProjInfo)); LOG_INFO("%s", project_info.get()->Debug().c_str()); planner::AbstractPlan *result = nullptr; planner::NestedLoopJoinPlan *plan_node = nullptr; auto project_schema = SchemaTransformer::GetSchemaFromTupleDesc( nl_plan_state->tts_tupleDescriptor); if (project_info.get()->isNonTrivial()) { // we have non-trivial projection LOG_INFO("We have non-trivial projection"); result = new planner::ProjectionPlan(project_info.release(), project_schema); plan_node = new planner::NestedLoopJoinPlan(peloton_join_type, predicate, nullptr, project_schema, nl); result->AddChild(plan_node); } else { LOG_INFO("We have direct mapping projection"); plan_node = new planner::NestedLoopJoinPlan(peloton_join_type, predicate, project_info.release(), project_schema, nl); result = plan_node; } const planner::AbstractPlan *outer = PlanTransformer::TransformPlan(outerAbstractPlanState(nl_plan_state)); const planner::AbstractPlan *inner = PlanTransformer::TransformPlan(innerAbstractPlanState(nl_plan_state)); /* Add the children nodes */ plan_node->AddChild(outer); plan_node->AddChild(inner); LOG_INFO("Finishing mapping Nested loop join, JoinType: %d", nl_plan_state->jointype); return result; }
/** * @brief Convert a Postgres HashState into a Peloton HashPlanNode * @return Pointer to the constructed AbstractPlan */ std::unique_ptr<planner::AbstractPlan> PlanTransformer::TransformHashJoin( const HashJoinPlanState *hj_plan_state) { std::unique_ptr<planner::AbstractPlan> result; PelotonJoinType join_type = PlanTransformer::TransformJoinType(hj_plan_state->jointype); if (join_type == JOIN_TYPE_INVALID) { LOG_ERROR("unsupported join type: %d", hj_plan_state->jointype); return nullptr; } LOG_INFO("Handle hash join with join type: %d", join_type); /* std::vector<planner::HashJoinPlan::JoinClause> join_clauses( BuildHashJoinClauses(mj_plan_state->mj_Clauses, mj_plan_state->mj_NumClauses); */ expression::AbstractExpression *join_filter = ExprTransformer::TransformExpr( reinterpret_cast<ExprState *>(hj_plan_state->joinqual)); expression::AbstractExpression *plan_filter = ExprTransformer::TransformExpr( reinterpret_cast<ExprState *>(hj_plan_state->qual)); std::unique_ptr<const expression::AbstractExpression> predicate(nullptr); if (join_filter && plan_filter) { predicate.reset(expression::ExpressionUtil::ConjunctionFactory( EXPRESSION_TYPE_CONJUNCTION_AND, join_filter, plan_filter)); } else if (join_filter) { predicate.reset(join_filter); } else { predicate.reset(plan_filter); } /* Transform project info */ std::unique_ptr<const planner::ProjectInfo> project_info(nullptr); project_info.reset(BuildProjectInfoFromTLSkipJunk(hj_plan_state->targetlist)); if (project_info.get() != nullptr) { LOG_INFO("%s", project_info.get()->Debug().c_str()); } else { LOG_INFO("empty projection info"); } std::shared_ptr<const catalog::Schema> project_schema( SchemaTransformer::GetSchemaFromTupleDesc( hj_plan_state->tts_tupleDescriptor)); std::vector<oid_t> outer_hashkeys = BuildColumnListFromExpStateList(hj_plan_state->outer_hashkeys); bool non_trivial = (project_info.get() != nullptr && project_info.get()->isNonTrivial()); if (non_trivial) { // we have non-trivial projection LOG_INFO("We have non-trivial projection"); result = std::unique_ptr<planner::AbstractPlan>( new planner::ProjectionPlan(std::move(project_info), project_schema)); // set project_info to nullptr project_info.reset(); } else { LOG_INFO("We have direct mapping projection"); } std::unique_ptr<planner::HashJoinPlan> plan_node(new planner::HashJoinPlan( join_type, std::move(predicate), std::move(project_info), project_schema, outer_hashkeys)); std::unique_ptr<planner::AbstractPlan> outer{std::move( PlanTransformer::TransformPlan(outerAbstractPlanState(hj_plan_state)))}; std::unique_ptr<planner::AbstractPlan> inner{std::move( PlanTransformer::TransformPlan(innerAbstractPlanState(hj_plan_state)))}; /* Add the children nodes */ plan_node->AddChild(std::move(outer)); plan_node->AddChild(std::move(inner)); if (non_trivial) { result->AddChild(std::move(plan_node)); } else { result.reset(plan_node.release()); } LOG_INFO("Finishing mapping Hash join, JoinType: %d", join_type); return result; }
bool RunUpdate() { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); ///////////////////////////////////////////////////////// // INDEX SCAN + PREDICATE ///////////////////////////////////////////////////////// std::unique_ptr<executor::ExecutorContext> context( new executor::ExecutorContext(txn)); // Column ids to be added to logical tile after scan. std::vector<oid_t> column_ids; oid_t column_count = state.column_count + 1; for (oid_t col_itr = 0; col_itr < column_count; col_itr++) { column_ids.push_back(col_itr); } // Create and set up index scan executor std::vector<oid_t> key_column_ids; std::vector<ExpressionType> expr_types; std::vector<Value> values; std::vector<expression::AbstractExpression *> runtime_keys; auto tuple_count = state.scale_factor * DEFAULT_TUPLES_PER_TILEGROUP; auto lookup_key = rand() % tuple_count; key_column_ids.push_back(0); expr_types.push_back(ExpressionType::EXPRESSION_TYPE_COMPARE_EQUAL); values.push_back(ValueFactory::GetIntegerValue(lookup_key)); auto ycsb_pkey_index = user_table->GetIndexWithOid(user_table_pkey_index_oid); planner::IndexScanPlan::IndexScanDesc index_scan_desc( ycsb_pkey_index, key_column_ids, expr_types, values, runtime_keys); // Create plan node. auto predicate = nullptr; planner::IndexScanPlan index_scan_node(user_table, predicate, column_ids, index_scan_desc); // Run the executor executor::IndexScanExecutor index_scan_executor(&index_scan_node, context.get()); ///////////////////////////////////////////////////////// // UPDATE ///////////////////////////////////////////////////////// planner::ProjectInfo::TargetList target_list; planner::ProjectInfo::DirectMapList direct_map_list; // Update the second attribute for (oid_t col_itr = 0; col_itr < column_count; col_itr++) { if (col_itr != 1) { direct_map_list.emplace_back(col_itr, std::pair<oid_t, oid_t>(0, col_itr)); } } std::string update_raw_value(ycsb_field_length - 1, 'u'); Value update_val = ValueFactory::GetStringValue(update_raw_value); target_list.emplace_back( 1, expression::ExpressionUtil::ConstantValueFactory(update_val)); std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(target_list), std::move(direct_map_list))); planner::UpdatePlan update_node(user_table, std::move(project_info)); executor::UpdateExecutor update_executor(&update_node, context.get()); update_executor.AddChild(&index_scan_executor); ///////////////////////////////////////////////////////// // EXECUTE ///////////////////////////////////////////////////////// std::vector<executor::AbstractExecutor *> executors; executors.push_back(&update_executor); ExecuteTest(executors); Result result = txn_manager.CommitTransaction(); if (result == Result::RESULT_SUCCESS) { return true; } else { assert(result == Result::RESULT_ABORTED || result == Result::RESULT_FAILURE); return false; } }
bool RunMixed(ZipfDistribution &zipf, FastRandom &rng) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); concurrency::Transaction *txn = txn_manager.BeginTransaction(); std::unique_ptr<executor::ExecutorContext> context( new executor::ExecutorContext(txn)); // Column ids to be added to logical tile. std::vector<oid_t> column_ids; oid_t column_count = state.column_count + 1; // read all the attributes in a tuple. for (oid_t col_itr = 0; col_itr < column_count; col_itr++) { column_ids.push_back(col_itr); } // Create and set up index scan executor std::vector<oid_t> key_column_ids; std::vector<ExpressionType> expr_types; key_column_ids.push_back(0); expr_types.push_back(ExpressionType::EXPRESSION_TYPE_COMPARE_EQUAL); std::vector<expression::AbstractExpression *> runtime_keys; for (int i = 0; i < state.operation_count; i++) { auto rng_val = rng.NextUniform(); if (rng_val < state.update_ratio) { ///////////////////////////////////////////////////////// // PERFORM UPDATE ///////////////////////////////////////////////////////// // set up parameter values std::vector<type::Value > values; auto lookup_key = zipf.GetNextNumber(); values.push_back(type::ValueFactory::GetIntegerValue(lookup_key).Copy()); auto ycsb_pkey_index = user_table->GetIndexWithOid(user_table_pkey_index_oid); planner::IndexScanPlan::IndexScanDesc index_scan_desc( ycsb_pkey_index, key_column_ids, expr_types, values, runtime_keys); // Create plan node. auto predicate = nullptr; planner::IndexScanPlan index_scan_node(user_table, predicate, column_ids, index_scan_desc); // Run the executor executor::IndexScanExecutor index_scan_executor(&index_scan_node, context.get()); TargetList target_list; DirectMapList direct_map_list; // update multiple attributes for (oid_t col_itr = 0; col_itr < column_count; col_itr++) { if (col_itr == 1) { if (state.string_mode == true) { std::string update_raw_value(100, 'a'); type::Value update_val = type::ValueFactory::GetVarcharValue(update_raw_value).Copy(); target_list.emplace_back( col_itr, expression::ExpressionUtil::ConstantValueFactory(update_val)); } else { int update_raw_value = 1; type::Value update_val = type::ValueFactory::GetIntegerValue(update_raw_value).Copy(); target_list.emplace_back( col_itr, expression::ExpressionUtil::ConstantValueFactory(update_val)); } } else { direct_map_list.emplace_back(col_itr, std::pair<oid_t, oid_t>(0, col_itr)); } } std::unique_ptr<const planner::ProjectInfo> project_info( new planner::ProjectInfo(std::move(target_list), std::move(direct_map_list))); planner::UpdatePlan update_node(user_table, std::move(project_info)); executor::UpdateExecutor update_executor(&update_node, context.get()); update_executor.AddChild(&index_scan_executor); ExecuteUpdate(&update_executor); if (txn->GetResult() != Result::RESULT_SUCCESS) { txn_manager.AbortTransaction(txn); return false; } } else { ///////////////////////////////////////////////////////// // PERFORM READ ///////////////////////////////////////////////////////// // set up parameter values std::vector<type::Value > values; auto lookup_key = zipf.GetNextNumber(); values.push_back(type::ValueFactory::GetIntegerValue(lookup_key).Copy()); auto ycsb_pkey_index = user_table->GetIndexWithOid(user_table_pkey_index_oid); planner::IndexScanPlan::IndexScanDesc index_scan_desc( ycsb_pkey_index, key_column_ids, expr_types, values, runtime_keys); // Create plan node. auto predicate = nullptr; planner::IndexScanPlan index_scan_node(user_table, predicate, column_ids, index_scan_desc); // Run the executor executor::IndexScanExecutor index_scan_executor(&index_scan_node, context.get()); ExecuteRead(&index_scan_executor); if (txn->GetResult() != Result::RESULT_SUCCESS) { txn_manager.AbortTransaction(txn); return false; } } } // transaction passed execution. PL_ASSERT(txn->GetResult() == Result::RESULT_SUCCESS); auto result = txn_manager.CommitTransaction(txn); if (result == Result::RESULT_SUCCESS) { return true; } else { // transaction failed commitment. PL_ASSERT(result == Result::RESULT_ABORTED || result == Result::RESULT_FAILURE); return false; } }
/** * @brief Convert a Postgres HashState into a Peloton HashPlanNode * @return Pointer to the constructed AbstractPlan */ const planner::AbstractPlan *PlanTransformer::TransformHashJoin( const HashJoinPlanState *hj_plan_state) { planner::AbstractPlan *result = nullptr; planner::HashJoinPlan *plan_node = nullptr; PelotonJoinType join_type = PlanTransformer::TransformJoinType(hj_plan_state->jointype); if (join_type == JOIN_TYPE_INVALID) { LOG_ERROR("unsupported join type: %d", hj_plan_state->jointype); return nullptr; } LOG_INFO("Handle hash join with join type: %d", join_type); /* std::vector<planner::HashJoinPlan::JoinClause> join_clauses( BuildHashJoinClauses(mj_plan_state->mj_Clauses, mj_plan_state->mj_NumClauses); */ expression::AbstractExpression *join_filter = ExprTransformer::TransformExpr( reinterpret_cast<ExprState *>(hj_plan_state->joinqual)); expression::AbstractExpression *plan_filter = ExprTransformer::TransformExpr( reinterpret_cast<ExprState *>(hj_plan_state->qual)); expression::AbstractExpression *predicate = nullptr; if (join_filter && plan_filter) { predicate = expression::ExpressionUtil::ConjunctionFactory( EXPRESSION_TYPE_CONJUNCTION_AND, join_filter, plan_filter); } else if (join_filter) { predicate = join_filter; } else { predicate = plan_filter; } /* Transform project info */ std::unique_ptr<const planner::ProjectInfo> project_info(nullptr); project_info.reset(BuildProjectInfoFromTLSkipJunk(hj_plan_state->targetlist)); LOG_INFO("%s", project_info.get()->Debug().c_str()); auto project_schema = SchemaTransformer::GetSchemaFromTupleDesc( hj_plan_state->tts_tupleDescriptor); std::vector<oid_t> outer_hashkeys = BuildColumnListFromExpStateList(hj_plan_state->outer_hashkeys); if (project_info.get()->isNonTrivial()) { // we have non-trivial projection LOG_INFO("We have non-trivial projection"); result = new planner::ProjectionPlan(project_info.release(), project_schema); plan_node = new planner::HashJoinPlan(join_type, predicate, nullptr, project_schema, outer_hashkeys); result->AddChild(plan_node); } else { LOG_INFO("We have direct mapping projection"); plan_node = new planner::HashJoinPlan(join_type, predicate, project_info.release(), project_schema, outer_hashkeys); result = plan_node; } const planner::AbstractPlan *outer = PlanTransformer::TransformPlan(outerAbstractPlanState(hj_plan_state)); const planner::AbstractPlan *inner = PlanTransformer::TransformPlan(innerAbstractPlanState(hj_plan_state)); /* Add the children nodes */ plan_node->AddChild(outer); plan_node->AddChild(inner); LOG_INFO("Finishing mapping Hash join, JoinType: %d", join_type); return result; }