diff --git a/repertory/repertory_test/src/database_test.cpp b/repertory/repertory_test/src/database_test.cpp index e336e030..996a88b1 100644 --- a/repertory/repertory_test/src/database_test.cpp +++ b/repertory/repertory_test/src/database_test.cpp @@ -27,6 +27,7 @@ #include "database/db_select.hpp" #include "database/db_update.hpp" #include "utils/path.hpp" +#include namespace repertory { class database_test : public ::testing::Test { @@ -260,4 +261,159 @@ TEST_F(database_test, insert_or_replace_and_delete) { common_delete(*db3.get()); } + +struct comp_t final { + std::string column_name; + std::string comparison; + db::db_types_t data; +}; + +template struct next_t final { + std::string action; + w_t &parent; + w_t next{&parent}; + + using group_func_t = std::function; + + [[nodiscard]] auto column(std::string column_name) -> c_t { + return next.column(column_name); + } + + [[nodiscard]] auto dump() const -> std::string { return parent.dump(); } + + [[nodiscard]] auto group(group_func_t func) -> wn_t { + return next.group(std::move(func)); + } +}; + +template struct where_next_t final { + w_t &owner; + w_t &parent; + + using next_t = next_t; + + [[nodiscard]] auto and_() -> next_t { + owner.actions.emplace_back(next_t{"AND", parent}); + return std::get(*std::prev(owner.actions.end())); + } + + [[nodiscard]] auto dump() const -> std::string { return parent.dump(); } + + [[nodiscard]] auto or_() -> next_t { + owner.actions.emplace_back(next_t{"OR", parent}); + return std::get(*std::prev(owner.actions.end())); + } +}; + +template struct comp_next_t final { + w_t &owner; + w_t &parent; + std::string column_name; + + using where_next_t = where_next_t; + + [[nodiscard]] auto create(std::string op, db::db_types_t value) { + owner.actions.emplace_back(comp_t{column_name, op, value}); + return where_next_t{owner, parent}; + } + + [[nodiscard]] auto equals(db::db_types_t value) -> where_next_t { + return create("=", value); + }; + + [[nodiscard]] auto gt(db::db_types_t value) -> where_next_t { + return create(">", value); + } + + [[nodiscard]] auto gte(db::db_types_t value) -> where_next_t { + return create(">=", value); + } + + [[nodiscard]] auto like(db::db_types_t value) -> where_next_t { + return create("LIKE", value); + } + + [[nodiscard]] auto lt(db::db_types_t value) -> where_next_t { + return create("<", value); + } + + [[nodiscard]] auto lte(db::db_types_t value) -> where_next_t { + return create("<=", value); + } + + [[nodiscard]] auto not_equals(db::db_types_t value) -> where_next_t { + return create("!=", value); + }; +}; + +struct where_t final { + where_t *parent{this}; + + using comp_next_t = comp_next_t; + using where_next_t = where_next_t; + using next_t = next_t; + + using group_func_t = std::function; + + using action_t = std::variant; + + std::vector actions{}; + + [[nodiscard]] auto column(std::string column_name) -> comp_next_t { + return comp_next_t{ + *this, + *parent, + column_name, + }; + } + + [[nodiscard]] auto dump() const -> std::string { + std::stringstream ss; + ss << '('; + for (auto &&action : actions) { + std::visit(overloaded{ + [&ss](const comp_t &comp) { + ss << comp.column_name << comp.comparison << '?'; + }, + [&ss](const next_t &next) { + ss << ' ' << next.action << ' ' << next.next.dump(); + }, + [&ss](const where_t &where) { ss << where.dump(); }, + }, + action); + } + ss << ')'; + + return ss.str(); + } + + [[nodiscard]] auto group(group_func_t func) -> where_next_t { + where_t where{parent}; + func(where); + + actions.push_back(std::move(where)); + return where_next_t{ + std::get(*std::prev(actions.end())), + *parent, + }; + } +}; + +TEST(database, groups) { + // "(s=a and r=t)" + auto str = + where_t().column("s").equals("a").and_().column("r").equals("t").dump(); + std::cout << str << std::endl; + // "((s=a and r=t) OR (s=c or s=x))" + // auto str = where_t() + // .group([](where_t &where) { + // where.column("s").equals("a").and_().column("r").equals("t"); + // }) + // .or_() + // .group([](where_t &where) { + // where.column("s").equals("c").or_().column("s").equals("x"); + // }) + // .dump(); + // std::cout << str << std::endl; +} } // namespace repertory