Пример #1
0
std::vector<std::vector<Value>>
ExecuteTest(executor::AbstractExecutor* executor) {
  time_point_ start, end;
  bool status = false;

  // Run all the executors
  status = executor->Init();
  if (status == false) {
    throw Exception("Init failed");
  }

  std::vector<std::vector<Value>> logical_tile_values;

  // Execute stuff
  while (executor->Execute() == true) {
    std::unique_ptr<executor::LogicalTile> result_tile(
        executor->GetOutput());

    if(result_tile == nullptr)
      break;

    auto column_count = result_tile->GetColumnCount();

    for (oid_t tuple_id : *result_tile) {
      expression::ContainerTuple<executor::LogicalTile> cur_tuple(result_tile.get(),
                                                                  tuple_id);
      std::vector<Value> tuple_values;
      for (oid_t column_itr = 0; column_itr < column_count; column_itr++){
        auto value = cur_tuple.GetValue(column_itr);
        tuple_values.push_back(value);
      }

      // Move the tuple list
      logical_tile_values.push_back(std::move(tuple_values));
    }
  }

  return std::move(logical_tile_values);
}
Пример #2
0
void Table::build_keys( vector<string> key_list )
{
  // construct file pat
  string path( "./data/" );
  path.append( name );
  path.append( ".tbl" );

  ifstream fs( path.c_str() );
  if ( !fs.is_open() )
  {
    cout << path << endl;
    cerr << "ERROR: file does not exist in Table::build_keys(). " << endl;
    return;
  }

  for ( int i = 0; i < key_list.size(); i++ )
  {
    if( has_index_file( key_list[i] ) )
    {
      build_key_from_file( key_list[i] );
      continue;
    }


    int pos = get_col_pos( key_list[i] );
    
    streampos offset = 0;

    BTree * btree = new BTree ( 5, 6 );
    string line;
    getline( fs, line ); // get rid of the first line

    offset = fs.tellg(); 
    while ( getline ( fs, line ) && line.size() > 0)
    {
      // to ignore the deleted lines
      //cout << line << endl;
      if( line[0] == '@' )
      {
        //cout << line << endl;
        offset = fs.tellg();
        continue;
      }

      string entry = get_entry( line, pos );

      if ( is_number ( entry ) ) 
      {
        Tuple cur_tuple( atoi( entry.c_str() ),  offset );
        btree->insert( cur_tuple );
      }
      else 
      {
        Tuple cur_tuple( entry.c_str() ,  offset );
        btree->insert( cur_tuple );
      }
      offset = fs.tellg();
    }

    keys.insert( pair<string, BTree*>( key_list[i], btree )  );
    fs.clear();
    fs.seekg( fs.beg );

    BTreeNode * node = btree->get_first();
    dump_tree( key_list[i], node );
  }

  fs.close();
}
/**
 * @brief Creates logical tile(s) wrapping the results of aggregation.
 * @return true on success, false otherwise.
 */
bool AggregateExecutor::DExecute() {
  // Already performed the aggregation
  if (done) {
    if (result_itr == INVALID_OID || result_itr == result.size()) {
      return false;
    } else {
      // Return appropriate tile and go to next tile
      SetOutput(result[result_itr]);
      result_itr++;
      return true;
    }
  }

  // Grab info from plan node
  const planner::AggregatePlan &node = GetPlanNode<planner::AggregatePlan>();

  // Get an aggregator
  std::unique_ptr<AbstractAggregator> aggregator(nullptr);

  // Get input tiles and aggregate them
  while (children_[0]->Execute() == true) {
    std::unique_ptr<LogicalTile> tile(children_[0]->GetOutput());

    if (nullptr == aggregator.get()) {
      // Initialize the aggregator
      switch (node.GetAggregateStrategy()) {
        case AGGREGATE_TYPE_HASH:
          LOG_TRACE("Use HashAggregator");
          aggregator.reset(new HashAggregator(
              &node, output_table, executor_context_, tile->GetColumnCount()));
          break;
        case AGGREGATE_TYPE_SORTED:
          LOG_TRACE("Use SortedAggregator");
          aggregator.reset(new SortedAggregator(
              &node, output_table, executor_context_, tile->GetColumnCount()));
          break;
        case AGGREGATE_TYPE_PLAIN:
          LOG_TRACE("Use PlainAggregator");
          aggregator.reset(
              new PlainAggregator(&node, output_table, executor_context_));
          break;
        default:
          LOG_ERROR("Invalid aggregate type. Return.");
          return false;
      }
    }

    LOG_TRACE("Looping over tile..");

    for (oid_t tuple_id : *tile) {
      std::unique_ptr<expression::ContainerTuple<LogicalTile>> cur_tuple(
          new expression::ContainerTuple<LogicalTile>(tile.get(), tuple_id));

      if (aggregator->Advance(cur_tuple.get()) == false) {
        return false;
      }
    }
    LOG_TRACE("Finished processing logical tile");
  }

  LOG_TRACE("Finalizing..");
  if (!aggregator.get() || !aggregator->Finalize()) {
    // If there's no tuples and no group-by, count() aggregations should return
    // 0 according to the test in MySQL.
    // TODO: We only checked whether all AggTerms are counts here. If there're
    // mixed terms, we should return 0 for counts and null for others.
    bool all_count_aggs = true;
    for (oid_t aggno = 0; aggno < node.GetUniqueAggTerms().size(); aggno++) {
      auto agg_type = node.GetUniqueAggTerms()[aggno].aggtype;
      if (agg_type != EXPRESSION_TYPE_AGGREGATE_COUNT &&
          agg_type != EXPRESSION_TYPE_AGGREGATE_COUNT_STAR)
        all_count_aggs = false;
    }

    // If there's no tuples in the table and only if no group-by in the
    // query,
    // we should return a NULL tuple
    // this is required by SQL
    if (!aggregator.get() && node.GetGroupbyColIds().empty()) {
      LOG_TRACE(
          "No tuples received and no group-by. Should insert a NULL tuple "
          "here.");
      std::unique_ptr<storage::Tuple> tuple(
          new storage::Tuple(output_table->GetSchema(), true));
      if (all_count_aggs == true) {
        tuple->SetAllZeros();
      } else {
        tuple->SetAllNulls();
      }
      auto location = output_table->InsertTuple(tuple.get());
      PL_ASSERT(location.block != INVALID_OID);

      auto &manager = catalog::Manager::GetInstance();
      auto tile_group_header =
          manager.GetTileGroup(location.block)->GetHeader();
      tile_group_header->SetTransactionId(location.offset, INITIAL_TXN_ID);

    } else {
      done = true;
      return false;
    }
  }

  // Transform output table into result
  auto tile_group_count = output_table->GetTileGroupCount();

  if (tile_group_count == 0) return false;

  for (oid_t tile_group_itr = 0; tile_group_itr < tile_group_count;
       tile_group_itr++) {
    auto tile_group = output_table->GetTileGroup(tile_group_itr);

    // Get the logical tiles corresponding to the given tile group
    auto logical_tile = LogicalTileFactory::WrapTileGroup(tile_group);

    result.push_back(logical_tile);
  }

  done = true;
  LOG_TRACE("Result tiles : %lu ", result.size());

  SetOutput(result[result_itr]);
  result_itr++;

  return true;
}
Пример #4
0
/**
 * @brief Adds a column to the logical tile, using the position lists.
 * @return true on success, false otherwise.
 */
bool InsertExecutor::DExecute() {
  if (done_) return false;

  assert(!done_);
  assert(executor_context_ != nullptr);

  const planner::InsertPlan &node = GetPlanNode<planner::InsertPlan>();
  storage::DataTable *target_table_ = node.GetTable();
  oid_t bulk_insert_count = node.GetBulkInsertCount();
  assert(target_table_);

  auto transaction_ = executor_context_->GetTransaction();
  auto executor_pool = executor_context_->GetExecutorContextPool();

  // Inserting a logical tile.
  if (children_.size() == 1) {
    LOG_INFO("Insert executor :: 1 child \n");

    if (!children_[0]->Execute()) {
      return false;
    }

    std::unique_ptr<LogicalTile> logical_tile(children_[0]->GetOutput());
    assert(logical_tile.get() != nullptr);
    auto target_table_schema = target_table_->GetSchema();
    auto column_count = target_table_schema->GetColumnCount();

    std::unique_ptr<storage::Tuple> tuple(
        new storage::Tuple(target_table_schema, true));

    // Go over the logical tile
    for (oid_t tuple_id : *logical_tile) {
      expression::ContainerTuple<LogicalTile> cur_tuple(logical_tile.get(),
                                                        tuple_id);

      // Materialize the logical tile tuple
      for (oid_t column_itr = 0; column_itr < column_count; column_itr++)
        tuple->SetValue(column_itr, cur_tuple.GetValue(column_itr),
                        executor_pool);

      peloton::ItemPointer location =
          target_table_->InsertTuple(transaction_, tuple.get());
      if (location.block == INVALID_OID) {
        transaction_->SetResult(peloton::Result::RESULT_FAILURE);
        return false;
      }
      transaction_->RecordInsert(location);

      executor_context_->num_processed += 1;  // insert one
    }

    return true;
  }
  // Inserting a collection of tuples from plan node
  else if (children_.size() == 0) {
    LOG_INFO("Insert executor :: 0 child \n");

    // Extract expressions from plan node and construct the tuple.
    // For now we just handle a single tuple
    auto schema = target_table_->GetSchema();
    std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(schema, true));
    auto project_info = node.GetProjectInfo();

    // There should be no direct maps
    assert(project_info);
    assert(project_info->GetDirectMapList().size() == 0);

    for (auto target : project_info->GetTargetList()) {
      peloton::Value value =
          target.second->Evaluate(nullptr, nullptr, executor_context_);
      tuple->SetValue(target.first, value, executor_pool);
    }

    // Bulk Insert Mode
    for (oid_t insert_itr = 0; insert_itr < bulk_insert_count; insert_itr++) {
      // Carry out insertion
      ItemPointer location =
          target_table_->InsertTuple(transaction_, tuple.get());
      LOG_INFO("Inserted into location: %lu, %lu", location.block,
               location.offset);

      if (location.block == INVALID_OID) {
        LOG_INFO("Failed to Insert. Set txn failure.");
        transaction_->SetResult(peloton::Result::RESULT_FAILURE);
        return false;
      }
      transaction_->RecordInsert(location);

      // Logging
      {
        auto &log_manager = logging::LogManager::GetInstance();

        if (log_manager.IsInLoggingMode()) {
          auto logger = log_manager.GetBackendLogger();
          auto record = logger->GetTupleRecord(
              LOGRECORD_TYPE_TUPLE_INSERT, transaction_->GetTransactionId(),
              target_table_->GetOid(), location, INVALID_ITEMPOINTER,
              tuple.get());

          logger->Log(record);
        }
      }
    }

    executor_context_->num_processed += 1;  // insert one
    done_ = true;
    return true;
  }

  return true;
}
Пример #5
0
/**
 * @brief Creates logical tile(s) wrapping the results of aggregation.
 * @return true on success, false otherwise.
 */
bool AggregateExecutor::DExecute() {
  // Already performed the aggregation
  if (done) {
    if (result_itr == INVALID_OID || result_itr == result.size()) {
      return false;
    } else {
      // Return appropriate tile and go to next tile
      SetOutput(result[result_itr]);
      result_itr++;
      return true;
    }
  }

  // Grab info from plan node
  const planner::AggregatePlan &node = GetPlanNode<planner::AggregatePlan>();

  // Get an aggregator
  std::unique_ptr<AbstractAggregator> aggregator(nullptr);

  // Get input tiles and aggregate them
  while (children_[0]->Execute() == true) {
    std::unique_ptr<LogicalTile> tile(children_[0]->GetOutput());

    if (nullptr == aggregator.get()) {
      // Initialize the aggregator
      switch (node.GetAggregateStrategy()) {
        case AGGREGATE_TYPE_HASH:
          LOG_INFO("Use HashAggregator\n");
          aggregator.reset(new HashAggregator(
              &node, output_table, executor_context_, tile->GetColumnCount()));
          break;
        case AGGREGATE_TYPE_SORTED:
          LOG_INFO("Use SortedAggregator\n");
          aggregator.reset(new SortedAggregator(
              &node, output_table, executor_context_, tile->GetColumnCount()));
          break;
        case AGGREGATE_TYPE_PLAIN:
          LOG_INFO("Use PlainAggregator\n");
          aggregator.reset(
              new PlainAggregator(&node, output_table, executor_context_));
          break;
        default:
          LOG_ERROR("Invalid aggregate type. Return.\n");
          return false;
      }
    }

    LOG_INFO("Looping over tile..");

    for (oid_t tuple_id : *tile) {
      std::unique_ptr<expression::ContainerTuple<LogicalTile>> cur_tuple(
          new expression::ContainerTuple<LogicalTile>(tile.get(), tuple_id));

      if (aggregator->Advance(cur_tuple.get()) == false) {
        return false;
      }
    }
    LOG_TRACE("Finished processing logical tile");
  }

  LOG_INFO("Finalizing..");
  if (!aggregator.get() || !aggregator->Finalize()) {
    // If there's no tuples in the table and only if no group-by in the query,
    // we should return a NULL tuple
    // this is required by SQL
    if (!aggregator.get() && node.GetGroupbyColIds().empty()) {
      LOG_INFO(
          "No tuples received and no group-by. Should insert a NULL tuple "
          "here.");
      std::unique_ptr<storage::Tuple> tuple(
          new storage::Tuple(output_table->GetSchema(), true));
      tuple->SetAllNulls();
      output_table->InsertTuple(executor_context_->GetTransaction(),
                                tuple.get());
    } else {
      done = true;
      return false;
    }
  }

  // Transform output table into result
  auto tile_group_count = output_table->GetTileGroupCount();

  if (tile_group_count == 0) return false;

  for (oid_t tile_group_itr = 0; tile_group_itr < tile_group_count;
       tile_group_itr++) {
    auto tile_group = output_table->GetTileGroup(tile_group_itr);

    // Get the logical tiles corresponding to the given tile group
    auto logical_tile = LogicalTileFactory::WrapTileGroup(tile_group);

    result.push_back(logical_tile);
  }

  done = true;
  LOG_INFO("Result tiles : %lu \n", result.size());

  SetOutput(result[result_itr]);
  result_itr++;

  return true;
}
Пример #6
0
/**
 * @brief Adds a column to the logical tile, using the position lists.
 * @return true on success, false otherwise.
 */
bool InsertExecutor::DExecute() {
  if (done_) return false;

  PELOTON_ASSERT(!done_);
  PELOTON_ASSERT(executor_context_ != nullptr);

  const planner::InsertPlan &node = GetPlanNode<planner::InsertPlan>();
  storage::DataTable *target_table = node.GetTable();
  oid_t bulk_insert_count = node.GetBulkInsertCount();

  auto &transaction_manager =
      concurrency::TransactionManagerFactory::GetInstance();

  auto current_txn = executor_context_->GetTransaction();

  if (!target_table) {
    transaction_manager.SetTransactionResult(current_txn,
                                             peloton::ResultType::FAILURE);
    return false;
  }

  LOG_TRACE("Number of tuples in table before insert: %lu",
            target_table->GetTupleCount());
  auto executor_pool = executor_context_->GetPool();

  trigger::TriggerList *trigger_list = target_table->GetTriggerList();
  if (trigger_list != nullptr) {
    LOG_TRACE("size of trigger list in target table: %d",
              trigger_list->GetTriggerListSize());
    if (trigger_list->HasTriggerType(TriggerType::BEFORE_INSERT_STATEMENT)) {
      LOG_TRACE("target table has per-statement-before-insert triggers!");
      trigger_list->ExecTriggers(TriggerType::BEFORE_INSERT_STATEMENT,
                                 current_txn);
    }
  }

  // Inserting a logical tile.
  if (children_.size() == 1) {
    if (!children_[0]->Execute()) {
      return false;
    }

    std::unique_ptr<LogicalTile> logical_tile(children_[0]->GetOutput());

    // FIXME: Wrong? What if the result of select is nothing? Michael
    PELOTON_ASSERT(logical_tile.get() != nullptr);

    auto target_table_schema = target_table->GetSchema();
    auto column_count = target_table_schema->GetColumnCount();

    std::unique_ptr<storage::Tuple> tuple(
        new storage::Tuple(target_table_schema, true));

    // Go over the logical tile
    for (oid_t tuple_id : *logical_tile) {
      ContainerTuple<LogicalTile> cur_tuple(logical_tile.get(), tuple_id);

      // Materialize the logical tile tuple
      for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
        type::Value val = (cur_tuple.GetValue(column_itr));
        tuple->SetValue(column_itr, val, executor_pool);
      }

      // insert tuple into the table.
      ItemPointer *index_entry_ptr = nullptr;
      peloton::ItemPointer location =
          target_table->InsertTuple(tuple.get(), current_txn, &index_entry_ptr);

      // it is possible that some concurrent transactions have inserted the same
      // tuple.
      // in this case, abort the transaction.
      if (location.block == INVALID_OID) {
        transaction_manager.SetTransactionResult(current_txn,
                                                 peloton::ResultType::FAILURE);
        return false;
      }

      transaction_manager.PerformInsert(current_txn, location, index_entry_ptr);

      executor_context_->num_processed += 1;  // insert one
    }

    // execute after-insert-statement triggers and
    // record on-commit-insert-statement triggers into current transaction
    if (trigger_list != nullptr) {
      LOG_TRACE("size of trigger list in target table: %d",
                trigger_list->GetTriggerListSize());
      if (trigger_list->HasTriggerType(TriggerType::AFTER_INSERT_STATEMENT)) {
        LOG_TRACE("target table has per-statement-after-insert triggers!");
        trigger_list->ExecTriggers(TriggerType::AFTER_INSERT_STATEMENT,
                                   current_txn);
      }
      if (trigger_list->HasTriggerType(
              TriggerType::ON_COMMIT_INSERT_STATEMENT)) {
        LOG_TRACE("target table has per-statement-on-commit-insert triggers!");
        trigger_list->ExecTriggers(TriggerType::ON_COMMIT_INSERT_STATEMENT,
                                   current_txn);
      }
    }
    return true;
  }
  // Inserting a collection of tuples from plan node
  else if (children_.size() == 0) {
    // Extract expressions from plan node and construct the tuple.
    // For now we just handle a single tuple
    auto schema = target_table->GetSchema();
    auto project_info = node.GetProjectInfo();
    auto tuple = node.GetTuple(0);
    std::unique_ptr<storage::Tuple> storage_tuple;

    // Check if this is not a raw tuple
    if (project_info) {
      // Otherwise, there must exist a project info
      PELOTON_ASSERT(project_info);
      // There should be no direct maps
      PELOTON_ASSERT(project_info->GetDirectMapList().size() == 0);

      storage_tuple.reset(new storage::Tuple(schema, true));

      for (auto target : project_info->GetTargetList()) {
        auto value =
            target.second.expr->Evaluate(nullptr, nullptr, executor_context_);
        storage_tuple->SetValue(target.first, value, executor_pool);
      }

      // Set tuple to point to temporary project tuple
      tuple = storage_tuple.get();
    }

    // Bulk Insert Mode
    for (oid_t insert_itr = 0; insert_itr < bulk_insert_count; insert_itr++) {
      // if we are doing a bulk insert from values not project_info

      if (!project_info) {
        tuple = node.GetTuple(insert_itr);

        if (tuple == nullptr) {
          storage_tuple.reset(new storage::Tuple(schema, true));

          // read from values
          uint32_t num_columns = schema->GetColumnCount();
          for (uint32_t col_id = 0; col_id < num_columns; col_id++) {
            auto value = node.GetValue(col_id + insert_itr * num_columns);
            storage_tuple->SetValue(col_id, value, executor_pool);
          }

          // Set tuple to point to temporary project tuple
          tuple = storage_tuple.get();
        }
      }

      trigger::TriggerList *trigger_list = target_table->GetTriggerList();

      auto new_tuple = tuple;
      if (trigger_list != nullptr) {
        LOG_TRACE("size of trigger list in target table: %d",
                  trigger_list->GetTriggerListSize());
        if (trigger_list->HasTriggerType(TriggerType::BEFORE_INSERT_ROW)) {
          LOG_TRACE("target table has per-row-before-insert triggers!");
          LOG_TRACE("address of the origin tuple before firing triggers: 0x%lx",
                    long(tuple));
          trigger_list->ExecTriggers(TriggerType::BEFORE_INSERT_ROW,
                                     current_txn,
                                     const_cast<storage::Tuple *>(tuple),
                                     executor_context_, nullptr, &new_tuple);
          LOG_TRACE("address of the new tuple after firing triggers: 0x%lx",
                    long(new_tuple));
        }
      }

      if (new_tuple == nullptr) {
        // trigger doesn't allow this tuple to be inserted
        LOG_TRACE("this tuple is rejected by trigger");
        continue;
      }

      // Carry out insertion
      ItemPointer *index_entry_ptr = nullptr;
      ItemPointer location =
          target_table->InsertTuple(new_tuple, current_txn, &index_entry_ptr);
      if (new_tuple->GetColumnCount() > 2) {
        type::Value val = (new_tuple->GetValue(2));
        LOG_TRACE("value: %s", val.GetInfo().c_str());
      }

      if (location.block == INVALID_OID) {
        LOG_TRACE("Failed to Insert. Set txn failure.");
        transaction_manager.SetTransactionResult(current_txn,
                                                 ResultType::FAILURE);
        return false;
      }

      transaction_manager.PerformInsert(current_txn, location, index_entry_ptr);

      LOG_TRACE("Number of tuples in table after insert: %lu",
                target_table->GetTupleCount());

      executor_context_->num_processed += 1;  // insert one

      // execute after-insert-row triggers and
      // record on-commit-insert-row triggers into current transaction
      new_tuple = tuple;
      if (trigger_list != nullptr) {
        LOG_TRACE("size of trigger list in target table: %d",
                  trigger_list->GetTriggerListSize());
        if (trigger_list->HasTriggerType(TriggerType::AFTER_INSERT_ROW)) {
          LOG_TRACE("target table has per-row-after-insert triggers!");
          LOG_TRACE("address of the origin tuple before firing triggers: 0x%lx",
                    long(tuple));
          trigger_list->ExecTriggers(TriggerType::AFTER_INSERT_ROW, current_txn,
                                     const_cast<storage::Tuple *>(tuple),
                                     executor_context_, nullptr, &new_tuple);
          LOG_TRACE("address of the new tuple after firing triggers: 0x%lx",
                    long(new_tuple));
        }
        if (trigger_list->HasTriggerType(TriggerType::ON_COMMIT_INSERT_ROW)) {
          LOG_TRACE("target table has per-row-on-commit-insert triggers!");
          LOG_TRACE("address of the origin tuple before firing triggers: 0x%lx",
                    long(tuple));
          trigger_list->ExecTriggers(TriggerType::ON_COMMIT_INSERT_ROW,
                                     current_txn,
                                     const_cast<storage::Tuple *>(tuple),
                                     executor_context_, nullptr, &new_tuple);
          LOG_TRACE("address of the new tuple after firing triggers: 0x%lx",
                    long(new_tuple));
        }
      }
    }
    // execute after-insert-statement triggers and
    // record on-commit-insert-statement triggers into current transaction
    trigger_list = target_table->GetTriggerList();
    if (trigger_list != nullptr) {
      LOG_TRACE("size of trigger list in target table: %d",
                trigger_list->GetTriggerListSize());
      if (trigger_list->HasTriggerType(TriggerType::AFTER_INSERT_STATEMENT)) {
        LOG_TRACE("target table has per-statement-after-insert triggers!");
        trigger_list->ExecTriggers(TriggerType::AFTER_INSERT_STATEMENT,
                                   current_txn);
      }
      if (trigger_list->HasTriggerType(
              TriggerType::ON_COMMIT_INSERT_STATEMENT)) {
        LOG_TRACE("target table has per-statement-on-commit-insert triggers!");
        trigger_list->ExecTriggers(TriggerType::ON_COMMIT_INSERT_STATEMENT,
                                   current_txn);
      }
    }
    done_ = true;
    return true;
  }
  return true;
}
Пример #7
0
/**
 * @brief Build a executor tree and execute it.
 * Use std::vector<Value> as params to make it more elegant for networking
 * Before ExecutePlan, a node first receives value list, so we should pass
 * value list directly rather than passing Postgres's ParamListInfo
 * @return status of execution.
 */
peloton_status PlanExecutor::ExecutePlan(const planner::AbstractPlan *plan,
                                         const std::vector<Value> &params,
                                         TupleDesc tuple_desc) {
  peloton_status p_status;

  if (plan == nullptr) return p_status;

  LOG_TRACE("PlanExecutor Start ");

  bool status;
  bool init_failure = false;
  bool single_statement_txn = false;
  List *slots = NULL;

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = peloton::concurrency::current_txn;
  // This happens for single statement queries in PG
  if (txn == nullptr) {
    single_statement_txn = true;
    txn = txn_manager.BeginTransaction();
  }
  PL_ASSERT(txn);

  LOG_TRACE("Txn ID = %lu ", txn->GetTransactionId());
  LOG_TRACE("Building the executor tree");

  // Use const std::vector<Value> &params to make it more elegant for network
  std::unique_ptr<executor::ExecutorContext> executor_context(
  BuildExecutorContext(params, txn));
  //auto executor_context = BuildExecutorContext(param_list, txn);

  // Build the executor tree
  std::unique_ptr<executor::AbstractExecutor> executor_tree(
      BuildExecutorTree(nullptr, plan, executor_context.get()));

  LOG_TRACE("Initializing the executor tree");

  // Initialize the executor tree
  status = executor_tree->Init();

  // Abort and cleanup
  if (status == false) {
    init_failure = true;
    txn->SetResult(Result::RESULT_FAILURE);
    goto cleanup;
  }

  LOG_TRACE("Running the executor tree");

  // Execute the tree until we get result tiles from root node
  for (;;) {
    status = executor_tree->Execute();

    // Stop
    if (status == false) {
      break;
    }

    std::unique_ptr<executor::LogicalTile> logical_tile(
        executor_tree->GetOutput());

    // Some executors don't return logical tiles (e.g., Update).
    if (logical_tile.get() == nullptr) {
      continue;
    }

    // Go over the logical tile
    for (oid_t tuple_id : *logical_tile) {
      expression::ContainerTuple<executor::LogicalTile> cur_tuple(
          logical_tile.get(), tuple_id);

      auto slot = TupleTransformer::GetPostgresTuple(&cur_tuple, tuple_desc);

      if (slot != nullptr) {
        slots = lappend(slots, slot);
      }
    }
  }

  // Set the result
  p_status.m_processed = executor_context->num_processed;
  p_status.m_result_slots = slots;

// final cleanup
cleanup:

  LOG_TRACE("About to commit: single stmt: %d, init_failure: %d, status: %d",
            single_statement_txn, init_failure, txn->GetResult());

  // should we commit or abort ?
  if (single_statement_txn == true || init_failure == true) {
    auto status = txn->GetResult();
    switch (status) {
      case Result::RESULT_SUCCESS:
        // Commit
        p_status.m_result = txn_manager.CommitTransaction();

        break;

      case Result::RESULT_FAILURE:
      default:
        // Abort
        p_status.m_result = txn_manager.AbortTransaction();
    }
  }

  // clean up executor tree
  CleanExecutorTree(executor_tree.get());

  return p_status;
}
Пример #8
0
void SimpleCheckpoint::Scan(storage::DataTable *target_table,
                            oid_t database_oid) {
  auto schema = target_table->GetSchema();
  PL_ASSERT(schema);
  std::vector<oid_t> column_ids;
  column_ids.resize(schema->GetColumnCount());
  std::iota(column_ids.begin(), column_ids.end(), 0);

  oid_t current_tile_group_offset = START_OID;
  auto table_tile_group_count = target_table->GetTileGroupCount();
  CheckpointTileScanner scanner;

  // TODO scan assigned tile in multi-thread checkpoint
  while (current_tile_group_offset < table_tile_group_count) {
    // Retrieve a tile group
    auto tile_group = target_table->GetTileGroup(current_tile_group_offset);

    // Retrieve a logical tile
    std::unique_ptr<executor::LogicalTile> logical_tile(
        scanner.Scan(tile_group, column_ids, start_commit_id_));

    // Empty result
    if (!logical_tile) {
      current_tile_group_offset++;
      continue;
    }

    auto tile_group_id = logical_tile->GetColumnInfo(0)
                             .base_tile->GetTileGroup()
                             ->GetTileGroupId();

    // Go over the logical tile
    for (oid_t tuple_id : *logical_tile) {
      expression::ContainerTuple<executor::LogicalTile> cur_tuple(
          logical_tile.get(), tuple_id);

      // Logging
      {
        // construct a physical tuple from the logical tuple
        std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(schema, true));
        for (auto column_id : column_ids) {
          tuple->SetValue(column_id, cur_tuple.GetValue(column_id),
                          this->pool.get());
        }
        ItemPointer location(tile_group_id, tuple_id);
        // TODO is it possible to avoid `new` for checkpoint?
        std::shared_ptr<LogRecord> record(logger_->GetTupleRecord(
            LOGRECORD_TYPE_TUPLE_INSERT, INITIAL_TXN_ID, target_table->GetOid(),
            database_oid, location, INVALID_ITEMPOINTER, tuple.get()));
        PL_ASSERT(record);
        CopySerializeOutput output_buffer;
        record->Serialize(output_buffer);
        LOG_TRACE("Insert a new record for checkpoint (%u, %u)", tile_group_id,
                  tuple_id);
        records_.push_back(record);
      }
    }
    // persist to file once per tile
    Persist();
    current_tile_group_offset++;
  }
}