diff --git a/src/include/utils/innerjoin.h b/src/include/utils/innerjoin.h new file mode 100644 index 0000000..754982e --- /dev/null +++ b/src/include/utils/innerjoin.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +namespace buzzdb { +namespace utils { + +class Table : public std::vector> { +public: + Table() : std::vector>() {} + Table(std::initializer_list> list) + : std::vector>(list) {} + + friend std::ostream &operator<<(std::ostream &os, const Table &table); +}; + +class InnerJoin { +public: + InnerJoin(Table &left, Table &right, size_t left_attr_index, + size_t right_attr_index); + ~InnerJoin(); + + friend std::ostream &operator<<(std::ostream &os, const Table &table); + + Table joined_table; + +private: + std::unordered_map> hashmap; +}; + +} // namespace utils +} // namespace buzzdb \ No newline at end of file diff --git a/src/utils/innerjoin.cc b/src/utils/innerjoin.cc new file mode 100644 index 0000000..34ee2cc --- /dev/null +++ b/src/utils/innerjoin.cc @@ -0,0 +1,39 @@ +#include "../include/utils/innerjoin.h" +#include +#include +#include + +#define UNUSED(p) ((void)(p)) + +namespace buzzdb { +namespace utils { +InnerJoin::InnerJoin(Table &left, Table &right, size_t left_attr_index, + size_t right_attr_index) { + for (size_t i = 0; i < left.size(); i++) { + hashmap[left[i][left_attr_index]] = left[i]; + } + + for (auto &tuple : right) { + if (hashmap.find(tuple[right_attr_index]) != hashmap.end()) { + std::vector row = hashmap[tuple[right_attr_index]]; + row.insert(row.end(), tuple.begin(), tuple.end()); + + joined_table.push_back(row); + } + } +} + +InnerJoin::~InnerJoin() {} + +std::ostream &operator<<(std::ostream &os, const buzzdb::utils::Table &table) { + for (size_t i = 0; i < table.size(); i++) { + for (size_t j = 0; j < table[i].size(); j++) { + os << table[i][j] << '\t'; + } + os << std::endl; + } + return os; +} + +} // namespace utils +} // namespace buzzdb \ No newline at end of file diff --git a/test/unit/utils/innerjoin_test.cc b/test/unit/utils/innerjoin_test.cc new file mode 100644 index 0000000..ed6426b --- /dev/null +++ b/test/unit/utils/innerjoin_test.cc @@ -0,0 +1,48 @@ +#include "utils/innerjoin.h" +#include +#include +#include +#include + +namespace { +using buzzdb::utils::InnerJoin; +using buzzdb::utils::Table; + +Table relation_students{ + // ID, Name, Age, Major + {"1", "Alice", "19", "CS"}, {"2", "Jonah", "20", "EE"}, + {"3", "Charlie", "19", "CS"}, {"4", "David", "22", "EE"}, + {"5", "Eve", "18", "CS"}, +}; + +Table relation_grades{ + // ID, Course, Grade + {"1", "CS101", "A"}, + {"1", "EE200", "B"}, + {"2", "CS101", "C"}, + {"4", "EE200", "B"}, +}; + +TEST(AlgorithmTest, InnerJoin) { + const Table expected_table = Table{ + // ID, Name, Age, Major, ID, Course, Grade + {"1", "Alice", "19", "CS", "1", "CS101", "A"}, + {"1", "Alice", "19", "CS", "1", "EE200", "B"}, + {"2", "Jonah", "20", "EE", "2", "CS101", "C"}, + {"4", "David", "22", "EE", "4", "EE200", "B"}, + }; + + InnerJoin join{relation_students, relation_grades, 0, 0}; + + EXPECT_EQ(join.joined_table, expected_table); + + std::cout << "Expected table:" << std::endl << expected_table << std::endl; + std::cout << "Joined table:" << std::endl << join.joined_table << std::endl; +} + +} // namespace + +int main(int argc, char *argv[]) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}