TEST_F(TileGroupIteratorTests, BasicTest) {
  const int tuples_per_tilegroup = TESTS_TUPLES_PER_TILEGROUP;
  const int expected_tilegroup_count = 5;
  const int allocated_tilegroup_count = 6;
  const int tuple_count = tuples_per_tilegroup * expected_tilegroup_count;

  // Create a table and wrap it in logical tiles
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  txn_manager.BeginTransaction();
  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuples_per_tilegroup, false));
  ExecutorTestsUtil::PopulateTable(data_table.get(), tuple_count, false, false,
                                   true);
  txn_manager.CommitTransaction();

  storage::TileGroupIterator tile_group_itr(data_table.get());
  std::shared_ptr<storage::TileGroup> tile_group_ptr;
  int actual_tile_group_count = 0;
  while (tile_group_itr.Next(tile_group_ptr)) {
    if (tile_group_ptr.get() != nullptr) {
      actual_tile_group_count += 1;
    }
  }  // WHILE

  EXPECT_EQ(allocated_tilegroup_count, actual_tile_group_count);
}
示例#2
0
TEST_F(LoaderTests, LoadingTest) {
  // We are going to simply load tile groups concurrently in this test
  oid_t tuples_per_tilegroup = DEFAULT_TUPLES_PER_TILEGROUP;
  bool build_indexes = false;

  // Control the scale
  oid_t loader_threads_count = 2;
  oid_t tilegroup_count_per_loader = 10;

  // Each tuple size ~40 B.
  oid_t tuple_size = 41;

  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuples_per_tilegroup, build_indexes));

  auto testing_pool = TestingHarness::GetInstance().GetTestingPool();

  LaunchParallelTest(loader_threads_count, InsertTuple, data_table.get(),
                     testing_pool, tilegroup_count_per_loader);

  auto expected_tile_group_count =
      loader_threads_count * tilegroup_count_per_loader;
  auto bytes_to_megabytes_converter = (1024 * 1024);

  EXPECT_EQ(data_table->GetTileGroupCount(), expected_tile_group_count);

  LOG_INFO("Dataset size : %lu MB \n",
           (expected_tile_group_count * tuples_per_tilegroup * tuple_size) /
           bytes_to_megabytes_converter);
}
TEST_F(ConstraintsTests, CombinedPrimaryKeyTest) {
  // First, generate the table with index
  // this table has 10 rows:
  //  int(primary)  int(primary)
  //  0             0
  //  1             1
  //  2             2
  //  .....
  //  9             9

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

  {
    std::unique_ptr<storage::DataTable> data_table(
        TransactionTestsUtil::CreateCombinedPrimaryKeyTable());
    // Test1: insert 2 tuple with duplicated primary key
    // txn1: insert (0, 1) -- success
    // txn0 commit
    // txn1: insert (1, 1) -- fail
    // txn1 commit
    TransactionScheduler scheduler(2, data_table.get(), &txn_manager);
    scheduler.Txn(0).Insert(0, 1);
    scheduler.Txn(0).Commit();
    scheduler.Txn(1).Insert(1, 1);
    scheduler.Txn(1).Commit();

    scheduler.Run();

    EXPECT_TRUE(RESULT_SUCCESS == scheduler.schedules[0].txn_result);
    EXPECT_TRUE(RESULT_ABORTED == scheduler.schedules[1].txn_result);
  }
}
示例#4
0
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);
}
TEST_F(ConstraintsTests, NOTNULLTest) {
  // First, generate the table with index
  // this table has 15 rows:
  //  int(primary)  int   double  var(22) (unique)
  //  0             1     2       "3"
  //  10            11    12      "13"
  //  20            21    22      "23"
  //  .....
  //  140           141   142     "143"

  std::unique_ptr<storage::DataTable> data_table(
      ConstraintsTestsUtil::CreateAndPopulateTable());

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

  // begin this transaction
  auto txn = txn_manager.BeginTransaction();

  // Test1: insert a tuple with column 1 = null
  bool hasException = false;
  try {
    ConstraintsTestsUtil::ExecuteInsert(
        txn, data_table.get(), ValueFactory::GetNullValue(),
        ValueFactory::GetIntegerValue(
            ConstraintsTestsUtil::PopulatedValue(15, 1)),
        ValueFactory::GetIntegerValue(
            ConstraintsTestsUtil::PopulatedValue(15, 2)),
        ValueFactory::GetStringValue(
            std::to_string(ConstraintsTestsUtil::PopulatedValue(15, 3))));

  } catch (ConstraintException e) {
    hasException = true;
  }
  EXPECT_TRUE(hasException);

  // Test2: insert a legal tuple
  hasException = false;
  try {
    ConstraintsTestsUtil::ExecuteInsert(
        txn, data_table.get(), ValueFactory::GetIntegerValue(
                                   ConstraintsTestsUtil::PopulatedValue(15, 0)),
        ValueFactory::GetIntegerValue(
            ConstraintsTestsUtil::PopulatedValue(15, 1)),
        ValueFactory::GetIntegerValue(
            ConstraintsTestsUtil::PopulatedValue(15, 2)),
        ValueFactory::GetStringValue(
            std::to_string(ConstraintsTestsUtil::PopulatedValue(15, 3))));
  } catch (ConstraintException e) {
    hasException = true;
  }
  EXPECT_FALSE(hasException);

  // commit this transaction
  txn_manager.CommitTransaction();
}
示例#6
0
TEST_F(LoaderTests, LoadingTest) {
  // We are going to simply load tile groups concurrently in this test
  // WARNING: This test may potentially run for a long time if
  // TEST_TUPLES_PER_TILEGROUP is large, consider rewrite the test or hard
  // code the number of tuples per tile group in this test
  oid_t tuples_per_tilegroup = TEST_TUPLES_PER_TILEGROUP;
  bool build_indexes = false;

  // Control the scale
  oid_t loader_threads_count = 1;
  oid_t tilegroup_count_per_loader = 1002;

  // Each tuple size ~40 B.
  UNUSED_ATTRIBUTE oid_t tuple_size = 41;

  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuples_per_tilegroup, build_indexes));

  auto testing_pool = TestingHarness::GetInstance().GetTestingPool();

  LaunchParallelTest(loader_threads_count, InsertTuple, data_table.get(),
                     testing_pool, tilegroup_count_per_loader);

  auto expected_tile_group_count = 0;

  int total_tuple_count = loader_threads_count * tilegroup_count_per_loader * TEST_TUPLES_PER_TILEGROUP;
  int max_cached_tuple_count = TEST_TUPLES_PER_TILEGROUP * storage::DataTable::active_tilegroup_count_;
  int max_unfill_cached_tuple_count = (TEST_TUPLES_PER_TILEGROUP - 1) * storage::DataTable::active_tilegroup_count_;

  if (total_tuple_count - max_cached_tuple_count <= 0) {
    if (total_tuple_count <= max_unfill_cached_tuple_count) {
      expected_tile_group_count = storage::DataTable::active_tilegroup_count_;
    } else {
      expected_tile_group_count = storage::DataTable::active_tilegroup_count_ + total_tuple_count - max_unfill_cached_tuple_count; 
    }
  } else {
    int filled_tile_group_count = total_tuple_count / max_cached_tuple_count * storage::DataTable::active_tilegroup_count_;
    
    if (total_tuple_count - filled_tile_group_count * TEST_TUPLES_PER_TILEGROUP - max_unfill_cached_tuple_count <= 0) {
      expected_tile_group_count = filled_tile_group_count + storage::DataTable::active_tilegroup_count_;
    } else {
      expected_tile_group_count = filled_tile_group_count + storage::DataTable::active_tilegroup_count_ + (total_tuple_count - filled_tile_group_count - max_unfill_cached_tuple_count); 
    }
  }

  UNUSED_ATTRIBUTE auto bytes_to_megabytes_converter = (1024 * 1024);

  EXPECT_EQ(data_table->GetTileGroupCount(), expected_tile_group_count);

  LOG_INFO("Dataset size : %u MB \n",
           (expected_tile_group_count * tuples_per_tilegroup * tuple_size) /
               bytes_to_megabytes_converter);
}
示例#7
0
TEST_F(InsertTests, LoadingTest) {
  // We are going to simply load tile groups concurrently in this test
  // WARNING: This test may potentially run for a long time if
  // TEST_TUPLES_PER_TILEGROUP is large, consider rewrite the test or hard
  // code the number of tuples per tile group in this test
  oid_t tuples_per_tilegroup = TEST_TUPLES_PER_TILEGROUP;
  bool build_indexes = false;

  // Control the scale
  oid_t loader_threads_count = 1;
  oid_t tilegroup_count_per_loader = 1;

  // Each tuple size ~40 B.
  oid_t tuple_size = 41;

  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuples_per_tilegroup, build_indexes));

  auto testing_pool = TestingHarness::GetInstance().GetTestingPool();

  Timer<> timer;

  timer.Start();

  LaunchParallelTest(loader_threads_count, InsertTuple, data_table.get(),
                     testing_pool, tilegroup_count_per_loader);

  timer.Stop();
  auto duration = timer.GetDuration();

  LOG_INFO("Duration: %.2lf", duration);

  //EXPECT_LE(duration, 0.2);

  auto expected_tile_group_count =
      loader_threads_count * tilegroup_count_per_loader + 1;
  auto bytes_to_megabytes_converter = (1024 * 1024);

  EXPECT_EQ(data_table->GetTileGroupCount(), expected_tile_group_count);

  LOG_INFO("Dataset size : %u MB \n",
           (expected_tile_group_count * tuples_per_tilegroup * tuple_size) /
               bytes_to_megabytes_converter);
}
TEST_F(DataTableTests, TransformTileGroupTest) {
  const int tuple_count = TESTS_TUPLES_PER_TILEGROUP;

  // Create a table and wrap it in logical tiles
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuple_count, false));
  ExecutorTestsUtil::PopulateTable(data_table.get(), tuple_count, false, false,
                                   true, txn);
  txn_manager.CommitTransaction(txn);

  // Create the new column map
  storage::column_map_type column_map;
  column_map[0] = std::make_pair(0, 0);
  column_map[1] = std::make_pair(0, 1);
  column_map[2] = std::make_pair(1, 0);
  column_map[3] = std::make_pair(1, 1);

  auto theta = 0.0;

  // Transform the tile group
  data_table->TransformTileGroup(0, theta);

  // Create the another column map
  column_map[0] = std::make_pair(0, 0);
  column_map[1] = std::make_pair(0, 1);
  column_map[2] = std::make_pair(0, 2);
  column_map[3] = std::make_pair(1, 0);

  // Transform the tile group
  data_table->TransformTileGroup(0, theta);

  // Create the another column map
  column_map[0] = std::make_pair(0, 0);
  column_map[1] = std::make_pair(1, 0);
  column_map[2] = std::make_pair(1, 1);
  column_map[3] = std::make_pair(1, 2);

  // Transform the tile group
  data_table->TransformTileGroup(0, theta);
}
TEST(TileGroupIteratorTests, BasicTest) {
  const int tuples_per_tilegroup = TESTS_TUPLES_PER_TILEGROUP;
  const int expected_tilegroup_count = 5;
  const int tuple_count = tuples_per_tilegroup * expected_tilegroup_count;

  // Create a table and wrap it in logical tiles
  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuples_per_tilegroup, false));
  ExecutorTestsUtil::PopulateTable(data_table.get(), tuple_count, false, false,
                                   true);

  storage::TileGroupIterator tile_group_itr(data_table.get());
  std::shared_ptr<storage::TileGroup> tile_group_ptr;
  int actual_tile_group_count = 0;
  while (tile_group_itr.Next(tile_group_ptr)) {
    if (tile_group_ptr.get() != nullptr) {
      actual_tile_group_count += 1;
    }
  }  // WHILE

  EXPECT_EQ(expected_tilegroup_count, actual_tile_group_count);
}
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);
}
示例#11
0
TEST_F(IndexTunerTests, BasicTest) {

  const int tuple_count = TESTS_TUPLES_PER_TILEGROUP;

  // Create a table and populate it
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<storage::DataTable> data_table(
      TestingExecutorUtil::CreateTable(tuple_count, false));
  TestingExecutorUtil::PopulateTable(data_table.get(), tuple_count, false, false,
                                   true, txn);
  txn_manager.CommitTransaction(txn);

  // Check column count
  oid_t column_count = data_table->GetSchema()->GetColumnCount();
  EXPECT_EQ(column_count, 4);

  // Index tuner
  tuning::IndexTuner &index_tuner = tuning::IndexTuner::GetInstance();

  // Attach table to index tuner
  index_tuner.AddTable(data_table.get());

  // Check old index count
  auto old_index_count = data_table->GetIndexCount();
  EXPECT_TRUE(old_index_count == 0);
  LOG_INFO("Index Count: %u", old_index_count);

  // Start index tuner
  index_tuner.Start();

  std::vector<double> columns_accessed(column_count, 0);
  double sample_weight;

  UniformGenerator generator;
  for (int sample_itr = 0; sample_itr < 10000; sample_itr++) {
    auto rng_val = generator.GetSample();

    if (rng_val < 0.6) {
      columns_accessed = {0, 1, 2};
      sample_weight = 100;
    } else if (rng_val < 0.9) {
      columns_accessed = {0, 2};
      sample_weight = 10;
    } else {
      columns_accessed = {0, 1};
      sample_weight = 10;
    }

    // Create a table access sample
    // Indicates the columns present in predicate, query weight, and selectivity
    tuning::Sample sample(columns_accessed,
                         sample_weight,
                         tuning::SampleType::ACCESS);

    // Collect index sample in table
    data_table->RecordIndexSample(sample);

    // Periodically sleep a bit
    // Index tuner thread will process the index samples periodically,
    // and materialize the appropriate ad-hoc indexes
    if(sample_itr % 100 == 0 ){
      std::this_thread::sleep_for(std::chrono::microseconds(10000));
    }
  }

  // Wait for tuner to build indexes
  sleep(5);

  // Stop index tuner
  index_tuner.Stop();

  // Detach all tables from index tuner
  index_tuner.ClearTables();

  // Check new index count
  auto new_index_count = data_table->GetIndexCount();
  LOG_INFO("Index Count: %u", new_index_count);

  EXPECT_TRUE(new_index_count != old_index_count);
  EXPECT_TRUE(new_index_count == 3);

  // Check candidate indices to ensure that
  // all the ad-hoc indexes are materialized
  std::vector<std::set<oid_t>> candidate_indices;
  candidate_indices.push_back({0, 1, 2});
  candidate_indices.push_back({0, 2});
  candidate_indices.push_back({0, 1});

  for (auto candidate_index : candidate_indices) {
    bool candidate_index_found = false;
    oid_t index_itr;
    for (index_itr = 0; index_itr < new_index_count; index_itr++) {
      // Check attributes
      auto index_attrs = data_table->GetIndexAttrs(index_itr);
      if (index_attrs != candidate_index) {
        continue;
      }
      // Exact match
      candidate_index_found = true;
      break;
    }

    EXPECT_TRUE(candidate_index_found);
  }

}
// Index scan of table with index predicate.
TEST_F(IndexScanTests, IndexPredicateTest) {
  // First, generate the table with index
  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateAndPopulateTable());

  // Column ids to be added to logical tile after scan.
  std::vector<oid_t> column_ids({0, 1, 3});

  //===--------------------------------------------------------------------===//
  // ATTR 0 <= 110
  //===--------------------------------------------------------------------===//

  auto index = data_table->GetIndex(0);
  std::vector<oid_t> key_column_ids;
  std::vector<ExpressionType> expr_types;
  std::vector<Value> values;
  std::vector<expression::AbstractExpression *> runtime_keys;

  key_column_ids.push_back(0);
  expr_types.push_back(
      ExpressionType::EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO);
  values.push_back(ValueFactory::GetIntegerValue(110));

  // Create index scan desc

  planner::IndexScanPlan::IndexScanDesc index_scan_desc(
      index, key_column_ids, expr_types, values, runtime_keys);

  expression::AbstractExpression *predicate = nullptr;

  // Create plan node.
  planner::IndexScanPlan node(data_table.get(), predicate, column_ids,
                              index_scan_desc);

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));

  // Run the executor
  executor::IndexScanExecutor executor(&node, context.get());
  int expected_num_tiles = 3;

  EXPECT_TRUE(executor.Init());

  std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

  for (int i = 0; i < expected_num_tiles; i++) {
    EXPECT_TRUE(executor.Execute());
    std::unique_ptr<executor::LogicalTile> result_tile(executor.GetOutput());
    EXPECT_THAT(result_tile, NotNull());
    result_tiles.emplace_back(result_tile.release());
  }

  EXPECT_FALSE(executor.Execute());
  EXPECT_EQ(result_tiles.size(), expected_num_tiles);
  EXPECT_EQ(result_tiles[0].get()->GetTupleCount(), 5);
  EXPECT_EQ(result_tiles[1].get()->GetTupleCount(), 5);
  EXPECT_EQ(result_tiles[2].get()->GetTupleCount(), 2);

  txn_manager.CommitTransaction();
}
示例#13
0
TEST(AggregateTests, PlainSumCountDistinctTest) {
  /*
   * SELECT SUM(a), COUNT(b), COUNT(DISTINCT b) from table
   */
  const int tuple_count = TESTS_TUPLES_PER_TILEGROUP;

  // Create a table and wrap it in logical tiles
  auto &txn_manager = concurrency::TransactionManager::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  auto txn_id = txn->GetTransactionId();

  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuple_count, false));
  ExecutorTestsUtil::PopulateTable(txn, data_table.get(),
                                   2 * tuple_count, false,
                                   true, true);
  txn_manager.CommitTransaction();

  std::unique_ptr<executor::LogicalTile> source_logical_tile1(
      executor::LogicalTileFactory::WrapTileGroup(data_table->GetTileGroup(0),
                                                  txn_id));

  std::unique_ptr<executor::LogicalTile> source_logical_tile2(
      executor::LogicalTileFactory::WrapTileGroup(data_table->GetTileGroup(1),
                                                  txn_id));

  // (1-5) Setup plan node

  // 1) Set up group-by columns
  std::vector<oid_t> group_by_columns;

  // 2) Set up project info
  planner::ProjectInfo::DirectMapList direct_map_list = {
      {0, {1, 0}}, {1, {1, 1}}, {2, {1, 2}}};

  auto proj_info = new planner::ProjectInfo(planner::ProjectInfo::TargetList(),
                                            std::move(direct_map_list));

  // 3) Set up unique aggregates
  std::vector<planner::AggregatePlan::AggTerm> agg_terms;
  planner::AggregatePlan::AggTerm sumA(EXPRESSION_TYPE_AGGREGATE_SUM,
                                       expression::TupleValueFactory(0, 0),
                                       false);
  planner::AggregatePlan::AggTerm countB(EXPRESSION_TYPE_AGGREGATE_COUNT,
                                         expression::TupleValueFactory(0, 1),
                                         false);  // Flag distinct
  planner::AggregatePlan::AggTerm countDistinctB(
      EXPRESSION_TYPE_AGGREGATE_COUNT, expression::TupleValueFactory(0, 1),
      true);  // Flag distinct
  agg_terms.push_back(sumA);
  agg_terms.push_back(countB);
  agg_terms.push_back(countDistinctB);

  // 4) Set up predicate (empty)
  expression::AbstractExpression* predicate = nullptr;

  // 5) Create output table schema
  auto data_table_schema = data_table.get()->GetSchema();
  std::vector<oid_t> set = {0, 1, 1};
  std::vector<catalog::Column> columns;
  for (auto column_index : set) {
    columns.push_back(data_table_schema->GetColumn(column_index));
  }
  auto output_table_schema = new catalog::Schema(columns);

  // OK) Create the plan node
  planner::AggregatePlan node(proj_info, predicate, std::move(agg_terms),
                              std::move(group_by_columns), output_table_schema,
                              AGGREGATE_TYPE_PLAIN);

  // Create and set up executor
  auto txn2 = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn2));

  executor::AggregateExecutor executor(&node, context.get());
  MockExecutor child_executor;
  executor.AddChild(&child_executor);

  EXPECT_CALL(child_executor, DInit()).WillOnce(Return(true));

  EXPECT_CALL(child_executor, DExecute())
      .WillOnce(Return(true))
      .WillOnce(Return(true))
      .WillOnce(Return(false));

  EXPECT_CALL(child_executor, GetOutput())
      .WillOnce(Return(source_logical_tile1.release()))
      .WillOnce(Return(source_logical_tile2.release()));

  EXPECT_TRUE(executor.Init());

  EXPECT_TRUE(executor.Execute());

  txn_manager.CommitTransaction();

  /* Verify result */
  std::unique_ptr<executor::LogicalTile> result_tile(executor.GetOutput());
  EXPECT_TRUE(result_tile.get() != nullptr);
  EXPECT_TRUE(result_tile->GetValue(0, 0)
                  .OpEquals(ValueFactory::GetIntegerValue(50))
                  .IsTrue());
  EXPECT_TRUE(result_tile->GetValue(0, 1)
                  .OpEquals(ValueFactory::GetIntegerValue(10))
                  .IsTrue());

  EXPECT_TRUE(result_tile->GetValue(0, 2)
                  .OpLessThanOrEqual(ValueFactory::GetIntegerValue(3))
                  .IsTrue());
}
示例#14
0
TEST(AggregateTests, HashDistinctTest) {
  /*
   * SELECT d, a, b, c FROM table GROUP BY a, b, c, d;
   */

  const int tuple_count = TESTS_TUPLES_PER_TILEGROUP;

  // Create a table and wrap it in logical tiles
  auto &txn_manager = concurrency::TransactionManager::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  auto txn_id = txn->GetTransactionId();
  std::unique_ptr<storage::DataTable> data_table(
      ExecutorTestsUtil::CreateTable(tuple_count, false));
  ExecutorTestsUtil::PopulateTable(txn, data_table.get(),
                                   2 * tuple_count, false,
                                   true,
                                   true);  // let it be random
  txn_manager.CommitTransaction();

  std::unique_ptr<executor::LogicalTile> source_logical_tile1(
      executor::LogicalTileFactory::WrapTileGroup(data_table->GetTileGroup(0),
                                                  txn_id));

  std::unique_ptr<executor::LogicalTile> source_logical_tile2(
      executor::LogicalTileFactory::WrapTileGroup(data_table->GetTileGroup(1),
                                                  txn_id));

  // (1-5) Setup plan node

  // 1) Set up group-by columns
  std::vector<oid_t> group_by_columns = {0, 1, 2, 3};

  // 2) Set up project info
  planner::ProjectInfo::DirectMapList direct_map_list = {
      {0, {0, 3}}, {1, {0, 0}}, {2, {0, 1}}, {3, {0, 2}}};
  auto proj_info = new planner::ProjectInfo(planner::ProjectInfo::TargetList(),
                                            std::move(direct_map_list));

  // 3) Set up unique aggregates (empty)
  std::vector<planner::AggregatePlan::AggTerm> agg_terms;

  // 4) Set up predicate (empty)
  expression::AbstractExpression* predicate = nullptr;

  // 5) Create output table schema
  auto data_table_schema = data_table.get()->GetSchema();
  std::vector<oid_t> set = {3, 0, 1, 2};
  std::vector<catalog::Column> columns;
  for (auto column_index : set) {
    columns.push_back(data_table_schema->GetColumn(column_index));
  }

  auto output_table_schema = new catalog::Schema(columns);

  // OK) Create the plan node
  planner::AggregatePlan node(proj_info, predicate, std::move(agg_terms),
                              std::move(group_by_columns), output_table_schema,
                              AGGREGATE_TYPE_HASH);

  // Create and set up executor
  auto txn2 = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn2));

  executor::AggregateExecutor executor(&node, context.get());
  MockExecutor child_executor;
  executor.AddChild(&child_executor);

  EXPECT_CALL(child_executor, DInit()).WillOnce(Return(true));

  EXPECT_CALL(child_executor, DExecute())
      .WillOnce(Return(true))
      .WillOnce(Return(true))
      .WillOnce(Return(false));

  EXPECT_CALL(child_executor, GetOutput())
      .WillOnce(Return(source_logical_tile1.release()))
      .WillOnce(Return(source_logical_tile2.release()));

  EXPECT_TRUE(executor.Init());

  EXPECT_TRUE(executor.Execute());
  txn_manager.CommitTransaction();

  /* Verify result */
  std::unique_ptr<executor::LogicalTile> result_tile(executor.GetOutput());
  EXPECT_TRUE(result_tile.get() != nullptr);

  for (auto tuple_id : *result_tile) {
    int colA = ValuePeeker::PeekAsInteger(result_tile->GetValue(tuple_id, 1));
    (void)colA;
  }
}