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); }
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); } }
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(); }
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); }
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); }
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(); }
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()); }
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; } }