Type type;
};
-template<typename Type>
-struct Distinct {
- Type value;
-};
-
-template<typename... Args>
-auto distinct(Args&&... args) -> decltype(Distinct<std::tuple<Args...>>())
-{
- return {std::tuple(args...)};
-}
-
} // namespace tsqb
} // namespace vist
template<typename... ColumnTypes>
T& select(ColumnTypes&&... cts);
- template<typename Type>
- T& select(Distinct<Type> distinct);
-
template<typename TableType>
T& selectAll(void);
T& where(Expr expr);
private:
- template<typename... ColumnTypes>
- T& selectInternal(bool distinct, ColumnTypes&& ...cts);
-
template<typename L, typename R>
std::string processWhere(condition::And<L,R>& expr);
template<typename T>
template<typename... ColumnTypes>
T& Crud<T>::select(ColumnTypes&&... cts)
-{
- return this->selectInternal(false, std::forward<ColumnTypes>(cts)...);
-}
-
-template<typename T>
-template<typename Type>
-T& Crud<T>::select(Distinct<Type> distinct)
-{
- return this->selectInternal(true, std::move(distinct.value));
-}
-
-template<typename T>
-T& Crud<T>::selectAll(void)
{
static_cast<T*>(this)->cache.clear();
+ auto columnNames = static_cast<T*>(this)->_getColumnNames(std::forward<ColumnTypes>(cts)...);
+ auto tableNames = static_cast<T*>(this)->_getTableNames(std::forward<ColumnTypes>(cts)...);
+
std::stringstream ss;
- ss << "SELECT * FROM " << static_cast<T*>(this)->name;
+ ss << "SELECT ";
+
+ std::size_t i = 0;
+ for (const auto& c : columnNames) {
+ ss << c;
+
+ if (i++ < columnNames.size() - 1)
+ ss << ", ";
+ }
+
+ ss << " FROM ";
+
+ i = 0;
+ for (const auto& t : tableNames) {
+ ss << t;
+
+ if (i++ < tableNames.size() - 1)
+ ss << ", ";
+ }
static_cast<T*>(this)->cache.emplace_back(ss.str());
}
template<typename T>
-template<typename TableType>
T& Crud<T>::selectAll(void)
{
static_cast<T*>(this)->cache.clear();
std::stringstream ss;
- auto tableName = static_cast<T*>(this)->getTableName(TableType());
- ss << "SELECT * FROM " << tableName;
+ ss << "SELECT * FROM " << static_cast<T*>(this)->name;
static_cast<T*>(this)->cache.emplace_back(ss.str());
}
template<typename T>
-template<typename... ColumnTypes>
-T& Crud<T>::selectInternal(bool distinct, ColumnTypes&& ...cts)
+template<typename TableType>
+T& Crud<T>::selectAll(void)
{
static_cast<T*>(this)->cache.clear();
- auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
-
- auto tuple = std::tuple(cts...);
- auto tableNames = static_cast<T*>(this)->getTableNames(std::move(tuple));
-
std::stringstream ss;
- ss << "SELECT ";
-
- if (distinct)
- ss << "DISTINCT ";
-
- std::size_t i = 0;
- for (const auto& c : columnNames) {
- ss << c;
-
- if (i++ < columnNames.size() - 1)
- ss << ", ";
- }
-
- ss << " FROM ";
-
- i = 0;
- for (const auto& t : tableNames) {
- ss << t;
-
- if (i++ < tableNames.size() - 1)
- ss << ", ";
- }
+ auto tableName = static_cast<T*>(this)->getTableName(TableType());
+ ss << "SELECT * FROM " << tableName;
static_cast<T*>(this)->cache.emplace_back(ss.str());
std::string getTableName(TableType&& type) const noexcept;
template<typename ColumnType>
std::string getColumnName(ColumnType&& type) const noexcept;
+ template<typename... Cs>
+ std::vector<std::string> _getTableNames(Cs&& ...columns) const noexcept;
+ template<typename... Cs>
+ std::vector<std::string> _getColumnNames(Cs&& ...columns) const noexcept;
+ template<typename ColumnType> // remove_cv or ref
+ std::string _getColumnName(ColumnType&& type) const noexcept;
std::vector<std::string> cache;
return std::vector<std::string>(names.begin(), names.end());
}
+template<typename... Tables>
+template<typename... Cs>
+std::vector<std::string> Database<Tables...>::_getTableNames(Cs&& ...columns) const noexcept
+{
+ std::set<std::string> names;
+
+ auto predicate = [this, &names](const auto& column) {
+ using ColumnType = std::remove_reference_t<decltype(column)>;
+ using TableType = typename ColumnType::Table;
+ auto name = this->getTableName(TableType());
+ if (!name.empty())
+ names.emplace(name);
+ };
+
+ auto closure = [&predicate](const auto&... iter) {
+ (predicate(iter), ...);
+ };
+
+ std::apply(closure, std::tuple(columns...));
+
+ return std::vector<std::string>(names.begin(), names.end());
+}
+
template<typename... Tables>
template<typename... Cs>
std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& ...columns) const noexcept
return names;
}
+template<typename... Tables>
+template<typename... Cs>
+std::vector<std::string> Database<Tables...>::_getColumnNames(Cs&& ...columns) const noexcept
+{
+ std::vector<std::string> names;
+ auto predicate = [this, &names](const auto& column) {
+ auto name = this->_getColumnName(column);
+ if (!name.empty())
+ names.emplace_back(name);
+ };
+
+ auto closure = [&predicate](const auto&... iter) {
+ (predicate(iter), ...);
+ };
+
+ std::apply(closure, std::tuple(columns...));
+
+ return names;
+}
+
template<typename... Tables>
template<typename Table>
std::string Database<Tables...>::getTableName(Table&& table) const noexcept
return name;
}
+template<typename... Tables>
+template<typename Column>
+std::string Database<Tables...>::_getColumnName(Column&& column) const noexcept
+{
+ using ColumnType = std::remove_reference_t<decltype(column)>;
+ using TableType = typename ColumnType::Table;
+ TableType table;
+
+ std::string name;
+ auto predicate = [&name, &table, &column](const auto& iter) {
+ if (iter.compare(table)) {
+ auto cname = iter._getColumnName(column);
+ name = iter.name + "." + cname;
+ }
+ };
+
+ auto closure = [&predicate](const auto&... iter) {
+ (predicate(iter), ...);
+ };
+
+ std::apply(closure, this->tables);
+
+ return name;
+}
+
template<typename... Tables>
std::size_t Database<Tables...>::size() const noexcept
{
/// Make first stuct type to table type
using Type = typename std::tuple_element<0, std::tuple<Columns...>>::type::Table;
- explicit Table(const std::string& name, Columns&& ...columns) :
+ explicit Table(const std::string& name, Columns ...columns) :
name(name), columns(columns...) {}
std::string getName(void) const noexcept;
std::vector<std::string> getColumnNames(Cs&& ...columns) const noexcept;
template<typename Column>
std::string getColumnName(const Column& column) const noexcept;
+ template<typename... Cs>
+ std::vector<std::string> _getTableNames(Cs&& ...) const noexcept;
+ template<typename... Cs>
+ std::vector<std::string> _getColumnNames(Cs&& ...columns) const noexcept;
+ template<typename Column>
+ std::string _getColumnName(const Column& column) const noexcept;
std::vector<std::string> cache;
return names;
}
+
+template<typename... Columns>
+template<typename... Cs>
+std::vector<std::string> Table<Columns...>::_getColumnNames(Cs&& ...columns) const noexcept
+{
+ std::vector<std::string> names;
+ auto predicate = [this, &names](const auto& type) {
+ auto name = this->_getColumnName(type);
+ if (!name.empty())
+ names.emplace_back(name);
+ };
+
+ auto closure = [&predicate](const auto&... iter) {
+ (predicate(iter), ...);
+ };
+
+ std::apply(closure, std::tuple(columns...));
+
+ return names;
+}
+
template<typename... Columns>
template<typename That>
std::string Table<Columns...>::getTableName(That&&) const noexcept
return name;
}
+template<typename... Columns>
+template<typename... Cs>
+std::vector<std::string> Table<Columns...>::_getTableNames(Cs&& ...) const noexcept
+{
+ return {this->name};
+}
+
+template<typename... Columns>
+template<typename Column>
+std::string Table<Columns...>::_getColumnName(const Column& column) const noexcept
+{
+ std::string name;
+ auto predicate = [&name, &column](const auto& iter) {
+ if (type::cast_compare(column.type, iter.type))
+ name = iter.name;
+ };
+
+ auto closure = [&predicate](const auto&... iter) {
+ (predicate(iter), ...);
+ };
+
+ std::apply(closure, this->columns);
+
+ return name;
+}
+
template<typename... Columns>
template<typename That>
bool Table<Columns...>::compare(const That& that) const noexcept
int column1;
std::string column2;
bool column3;
+
+ inline static Column Column1 = { "column1", &Table1::column1 };
+ inline static Column Column2 = { "column2", &Table1::column2 };
};
struct Table2 {
EXPECT_EQ(database.getTableName(Table1()), "table1");
EXPECT_EQ(database.getTableName(Table2()), "table2");
- EXPECT_EQ(database.getColumnName(&Table1::column1), "table1.column1");
+ EXPECT_EQ(database._getColumnName(Table1::Column1), "table1.column1");
EXPECT_EQ(database.getColumnName(&Table1::column2), "table1.column2");
EXPECT_EQ(database.getColumnName(&Table1::column3), "table1.column3");
TEST(QueryBuilderDatabaseTests, get_names)
{
+ {
+ auto columns = database._getColumnNames(Table1::Column1, Table1::Column2);
+ EXPECT_EQ(columns[0], "table1.column1");
+ EXPECT_EQ(columns[1], "table1.column2");
+ }
+
auto columns = database.getColumnNames(&Table1::column1, &Table2::column3);
auto tables = database.getTableNames(&Table1::column1, &Table2::column1, &Table2::column1);
if (columns.size() == 2 && tables.size() == 2) {
int uid;
std::string key;
int removable;
+
+ inline static Column Id = { "id", &Admin::id };
+ inline static Column Pkg = { "pkg", &Admin::pkg };
+ inline static Column Uid = { "uid", &Admin::uid };
+ inline static Column Key = { "key", &Admin::key };
+ inline static Column Removable = { "removable", &Admin::removable };
};
+static Table AdminTable { "admin", Admin::Id, Admin::Pkg,
+ Admin::Uid, Admin::Key, Admin::Removable };
+
struct ManagedPolicy {
int id;
int aid;
int pid;
int value;
+
+ inline static Column Id = { "id", &ManagedPolicy::id };
+ inline static Column Aid = { "aid", &ManagedPolicy::aid };
+ inline static Column Pid = { "pid", &ManagedPolicy::pid };
+ inline static Column Value = { "value", &ManagedPolicy::value };
};
+static Table ManagedPolicyTable { "managed_policy", ManagedPolicy::Id,
+ ManagedPolicy::Aid,
+ ManagedPolicy::Pid,
+ ManagedPolicy::Value };
+
struct PolicyDefinition {
int id;
int scope;
std::string name;
int ivalue;
+
+ inline static Column Id = { "id", &PolicyDefinition::id };
+ inline static Column Scope = { "scope", &PolicyDefinition::scope };
+ inline static Column Name = { "name", &PolicyDefinition::name };
+ inline static Column Ivalue = { "ivalue", &PolicyDefinition::ivalue };
};
+static Table PolicyDefinition { "policy_definition", PolicyDefinition::Id,
+ PolicyDefinition::Scope,
+ PolicyDefinition::Name,
+ PolicyDefinition::Ivalue };
+
Table admin { "admin", Column("id", &Admin::id),
Column("pkg", &Admin::pkg),
Column("uid", &Admin::uid),
TEST(QueryBuilderTsqbTests, SELECT)
{
- std::string select1 = admin.select(&Admin::id, &Admin::pkg, &Admin::uid, &Admin::key);
- std::string select2 = admin.select(&Admin::id, &Admin::uid, &Admin::key);
+ std::string select1 = AdminTable.select(Admin::Id, Admin::Pkg, Admin::Uid, Admin::Key);
+ std::string select2 = AdminTable.select(Admin::Id, Admin::Uid, Admin::Key);
EXPECT_EQ(select1, "SELECT id, pkg, uid, key FROM admin");
EXPECT_EQ(select2, "SELECT id, uid, key FROM admin");
TEST(QueryBuilderTsqbTests, SELECT_ALL)
{
- std::string select = admin.selectAll();
+ std::string select = AdminTable.selectAll();
EXPECT_EQ(select, "SELECT * FROM admin");
}
TEST(QueryBuilderTsqbTests, SELECT_WHERE)
{
- std::string select1 = admin.select(&Admin::uid, &Admin::key)
- .where(expr(&Admin::id) > 3);
+ std::string select1 = AdminTable.select(Admin::Uid, Admin::Key)
+ .where(expr(&Admin::id) > 3);
std::string select2 = admin.selectAll().where(expr(&Admin::uid) > 3);
std::string select3 = admin.selectAll().where(expr(&Admin::uid) > 3 &&
expr(&Admin::pkg) == "dpm");
EXPECT_EQ(select4, "SELECT * FROM admin WHERE uid > ? OR pkg = ?");
}
-TEST(QueryBuilderTsqbTests, SELECT_DISTINCT)
-{
- std::string select = admin.select(distinct(&Admin::uid, &Admin::key))
- .where(expr(&Admin::id) > 3);
-
- EXPECT_EQ(select, "SELECT DISTINCT uid, key FROM admin WHERE id > ?");
-}
-
TEST(QueryBuilderTsqbTests, UPDATE)
{
int uid = 0, id = 1;
TEST(QueryBuilderTsqbTests, MULTI_SELECT)
{
- std::string multiSelect1 = db.select(&Admin::uid, &Admin::key,
- &ManagedPolicy::id, &ManagedPolicy::value);
- std::string multiSelect2 = db.select(&Admin::uid, &Admin::key,
- &ManagedPolicy::id, &ManagedPolicy::value)
+ std::string multiSelect1 = db.select(Admin::Uid, Admin::Key,
+ ManagedPolicy::Id, ManagedPolicy::Value);
+ std::string multiSelect2 = db.select(Admin::Uid, Admin::Key,
+ ManagedPolicy::Id, ManagedPolicy::Value)
.where(expr(&Admin::uid) > 0 && expr(&ManagedPolicy::id) == 3);
EXPECT_EQ(multiSelect1, "SELECT admin.uid, admin.key, managed_policy.id, "
"WHERE admin.uid > ? AND managed_policy.id = ?");
}
+/*
TEST(QueryBuilderTsqbTests, JOIN)
{
- std::string join1 = db.select(&Admin::uid, &Admin::key)
+ std::string join1 = db.select(Admin::Uid, Admin::Key)
.join<PolicyDefinition>(condition::Join::LEFT_OUTER);
- std::string join2 = db.select(&Admin::uid, &Admin::key)
+ std::string join2 = db.select(Admin::Uid, Admin::Key)
.join<ManagedPolicy>(condition::Join::CROSS);
- std::string join3 = db.select(&ManagedPolicy::value)
+ std::string join3 = db.select(ManagedPolicy::Value)
.join<PolicyDefinition>()
.on(expr(&ManagedPolicy::pid) == expr(&PolicyDefinition::id))
.join<Admin>()
"INNER JOIN admin ON managed_policy.aid = admin.id "
"WHERE managed_policy.pid = ?");
}
+*/
int column1;
std::string column2;
bool column3;
+
+ inline static Column Column1 = { "column1", &Table1::column1 };
};
struct Table2 {
EXPECT_EQ(table1.getName(), "table1");
EXPECT_EQ(table2.name, "table2");
+ EXPECT_EQ(table1._getColumnName(Table1::Column1), "column1");
EXPECT_EQ(table1.getColumnName(&Table1::column1), "column1");
EXPECT_EQ(table1.getColumnName(&Table1::column2), "column2");
EXPECT_EQ(table1.getColumnName(&Table1::column3), "column3");