/** * @brief Create a physical tile for the given logical tile * @param source_tile Source tile from which the physical tile is created * @return a logical tile wrapper for the created physical tile */ LogicalTile *MaterializationExecutor::Physify(LogicalTile *source_tile) { std::unique_ptr<catalog::Schema> source_tile_schema( source_tile->GetPhysicalSchema()); const int num_tuples = source_tile->GetTupleCount(); const catalog::Schema *output_schema; std::unordered_map<oid_t, oid_t> old_to_new_cols; auto node = GetRawNode(); // Create a default identity mapping node if we did not get one if (node == nullptr) { assert(source_tile_schema.get()); output_schema = source_tile_schema.get(); old_to_new_cols = BuildIdentityMapping(output_schema); } // Else use the mapping in the given plan node else { const planner::MaterializationPlan &node = GetPlanNode<planner::MaterializationPlan>(); if (node.GetSchema()) { output_schema = node.GetSchema(); old_to_new_cols = node.old_to_new_cols(); } else { output_schema = source_tile_schema.get(); old_to_new_cols = BuildIdentityMapping(output_schema); } } // Generate mappings. std::unordered_map<storage::Tile *, std::vector<oid_t>> tile_to_cols; GenerateTileToColMap(old_to_new_cols, source_tile, tile_to_cols); // Create new physical tile. std::shared_ptr<storage::Tile> dest_tile( storage::TileFactory::GetTempTile(*output_schema, num_tuples)); // Proceed to materialize logical tile by physical tile at a time. MaterializeByTiles(source_tile, old_to_new_cols, tile_to_cols, dest_tile.get()); // Wrap physical tile in logical tile. return LogicalTileFactory::WrapTiles({dest_tile}); }
/** * @brief Creates materialized physical tile from logical tile and wraps it * in a new logical tile. * * @return true on success, false otherwise. */ bool MaterializationExecutor::DExecute() { // Retrieve child tile. const bool success = children_[0]->Execute(); if (!success) { return false; } std::unique_ptr<LogicalTile> source_tile(children_[0]->GetOutput()); LogicalTile *output_tile = nullptr; // Check the number of tuples in input logical tile // If none, then just return false const int num_tuples = source_tile->GetTupleCount(); if (num_tuples == 0) { return false; } auto node = GetRawNode(); bool physify_flag = true; // by default, we create a physical tile if (node != nullptr) { const planner::MaterializationPlan &node = GetPlanNode<planner::MaterializationPlan>(); physify_flag = node.GetPhysifyFlag(); } if (physify_flag) { /* create a physical tile and a logical tile wrapper to be the output */ output_tile = Physify(source_tile.get()); } else { /* just pass thru the underlying logical tile */ output_tile = source_tile.release(); } SetOutput(output_tile); return true; }
/** * @brief Creates logical tile from tile group and applies scan predicate. * @return true on success, false otherwise. */ bool SeqScanExecutor::DExecute() { // Scanning over a logical tile. if (children_.size() == 1 && // There will be a child node on the create index scenario, // but we don't want to use this execution flow !(GetRawNode()->GetChildren().size() > 0 && GetRawNode()->GetChildren()[0].get()->GetPlanNodeType() == PlanNodeType::CREATE && ((planner::CreatePlan *)GetRawNode()->GetChildren()[0].get()) ->GetCreateType() == CreateType::INDEX)) { // FIXME Check all requirements for children_.size() == 0 case. LOG_TRACE("Seq Scan executor :: 1 child "); PELOTON_ASSERT(target_table_ == nullptr); PELOTON_ASSERT(column_ids_.size() == 0); while (children_[0]->Execute()) { std::unique_ptr<LogicalTile> tile(children_[0]->GetOutput()); if (predicate_ != nullptr) { // Invalidate tuples that don't satisfy the predicate. for (oid_t tuple_id : *tile) { ContainerTuple<LogicalTile> tuple(tile.get(), tuple_id); auto eval = predicate_->Evaluate(&tuple, nullptr, executor_context_); if (eval.IsFalse()) { // if (predicate_->Evaluate(&tuple, nullptr, executor_context_) // .IsFalse()) { tile->RemoveVisibility(tuple_id); } } } if (0 == tile->GetTupleCount()) { // Avoid returning empty tiles continue; } /* Hopefully we needn't do projections here */ SetOutput(tile.release()); return true; } return false; } // Scanning a table else if (children_.size() == 0 || // If we are creating an index, there will be a child (children_.size() == 1 && // This check is only needed to pass seq_scan_test // unless it is possible to add a executor child // without a corresponding plan. GetRawNode()->GetChildren().size() > 0 && // Check if the plan is what we actually expect. GetRawNode()->GetChildren()[0].get()->GetPlanNodeType() == PlanNodeType::CREATE && // If it is, confirm it is for indexes ((planner::CreatePlan *)GetRawNode()->GetChildren()[0].get()) ->GetCreateType() == CreateType::INDEX)) { LOG_TRACE("Seq Scan executor :: 0 child "); PELOTON_ASSERT(target_table_ != nullptr); PELOTON_ASSERT(column_ids_.size() > 0); if (children_.size() > 0 && !index_done_) { children_[0]->Execute(); // This stops continuous executions due to // a parent and avoids multiple creations // of the same index. index_done_ = true; } concurrency::TransactionManager &transaction_manager = concurrency::TransactionManagerFactory::GetInstance(); bool acquire_owner = GetPlanNode<planner::AbstractScan>().IsForUpdate(); auto current_txn = executor_context_->GetTransaction(); // Retrieve next tile group. while (current_tile_group_offset_ < table_tile_group_count_) { auto tile_group = target_table_->GetTileGroup(current_tile_group_offset_++); auto tile_group_header = tile_group->GetHeader(); oid_t active_tuple_count = tile_group->GetNextTupleSlot(); // Construct position list by looping through tile group // and applying the predicate. std::vector<oid_t> position_list; for (oid_t tuple_id = 0; tuple_id < active_tuple_count; tuple_id++) { ItemPointer location(tile_group->GetTileGroupId(), tuple_id); auto visibility = transaction_manager.IsVisible( current_txn, tile_group_header, tuple_id); // check transaction visibility if (visibility == VisibilityType::OK) { // if the tuple is visible, then perform predicate evaluation. if (predicate_ == nullptr) { position_list.push_back(tuple_id); auto res = transaction_manager.PerformRead(current_txn, location, acquire_owner); if (!res) { transaction_manager.SetTransactionResult(current_txn, ResultType::FAILURE); return res; } } else { ContainerTuple<storage::TileGroup> tuple(tile_group.get(), tuple_id); LOG_TRACE("Evaluate predicate for a tuple"); auto eval = predicate_->Evaluate(&tuple, nullptr, executor_context_); LOG_TRACE("Evaluation result: %s", eval.GetInfo().c_str()); if (eval.IsTrue()) { position_list.push_back(tuple_id); auto res = transaction_manager.PerformRead(current_txn, location, acquire_owner); if (!res) { transaction_manager.SetTransactionResult(current_txn, ResultType::FAILURE); return res; } else { LOG_TRACE("Sequential Scan Predicate Satisfied"); } } } } } // Don't return empty tiles if (position_list.size() == 0) { continue; } // Construct logical tile. std::unique_ptr<LogicalTile> logical_tile(LogicalTileFactory::GetTile()); logical_tile->AddColumns(tile_group, column_ids_); logical_tile->AddPositionList(std::move(position_list)); LOG_TRACE("Information %s", logical_tile->GetInfo().c_str()); SetOutput(logical_tile.release()); return true; } } return false; }