Commit d62ca9f8 authored by louiz’'s avatar louiz’

Use if constexpr to make things a lot more readable

parent ba879a88
...@@ -8,19 +8,16 @@ ...@@ -8,19 +8,16 @@
namespace namespace
{ {
template <std::size_t N=0, typename... T> template <std::size_t N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type void add_column_name(std::string& out)
add_column_name(std::string&)
{ }
template <std::size_t N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type
add_column_name(std::string& out)
{ {
if constexpr(N < sizeof...(T))
{
using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<std::tuple<T...>>()))>::type; using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<std::tuple<T...>>()))>::type;
out += ColumnType::name; out += ColumnType::name;
if (N != sizeof...(T) - 1) if (N != sizeof...(T) - 1)
out += ","; out += ",";
add_column_name<N+1, T...>(out); add_column_name<N + 1, T...>(out);
}
} }
} }
......
...@@ -11,20 +11,17 @@ ...@@ -11,20 +11,17 @@
#include <tuple> #include <tuple>
template <std::size_t N=0, typename... T> template <std::size_t N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void update_autoincrement_id(std::tuple<T...>& columns, Statement& statement)
update_autoincrement_id(std::tuple<T...>& columns, Statement& statement)
{ {
if constexpr(N < sizeof...(T))
{
using ColumnType = typename std::decay<decltype(std::get<N>(columns))>::type; using ColumnType = typename std::decay<decltype(std::get<N>(columns))>::type;
if (std::is_same<ColumnType, Id>::value) if (std::is_same<ColumnType, Id>::value)
auto&& column = std::get<Id>(columns); auto&& column = std::get<Id>(columns);
update_autoincrement_id<N+1>(columns, statement); update_autoincrement_id<N + 1>(columns, statement);
}
} }
template <std::size_t N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
update_autoincrement_id(std::tuple<T...>&, Statement&)
{}
struct InsertQuery: public Query struct InsertQuery: public Query
{ {
template <typename... T> template <typename... T>
...@@ -53,22 +50,19 @@ struct InsertQuery: public Query ...@@ -53,22 +50,19 @@ struct InsertQuery: public Query
} }
template <int N=0, typename... T> template <int N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1)
bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1) {
if constexpr(N < sizeof...(T))
{ {
auto&& column = std::get<N>(columns); auto&& column = std::get<N>(columns);
using ColumnType = std::decay_t<decltype(column)>; using ColumnType = std::decay_t<decltype(column)>;
if (!std::is_same<ColumnType, Id>::value) if constexpr(!std::is_same<ColumnType, Id>::value)
actual_bind(statement, column.value, index++); actual_bind(statement, column.value, index++);
this->bind_param<N+1>(columns, statement, index); this->bind_param<N + 1>(columns, statement, index);
}
} }
template <int N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
bind_param(const std::tuple<T...>&, Statement&, int)
{}
template <typename... T> template <typename... T>
void insert_values(const std::tuple<T...>& columns) void insert_values(const std::tuple<T...>& columns)
...@@ -79,8 +73,9 @@ struct InsertQuery: public Query ...@@ -79,8 +73,9 @@ struct InsertQuery: public Query
} }
template <int N=0, typename... T> template <int N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void insert_value(const std::tuple<T...>& columns, int index=1)
insert_value(const std::tuple<T...>& columns, int index=1) {
if constexpr(N < sizeof...(T))
{ {
using ColumnType = std::decay_t<decltype(std::get<N>(columns))>; using ColumnType = std::decay_t<decltype(std::get<N>(columns))>;
...@@ -90,12 +85,9 @@ struct InsertQuery: public Query ...@@ -90,12 +85,9 @@ struct InsertQuery: public Query
if (N != sizeof...(T) - 1) if (N != sizeof...(T) - 1)
this->body += ", "; this->body += ", ";
} }
this->insert_value<N+1>(columns, index); this->insert_value<N + 1>(columns, index);
}
} }
template <int N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
insert_value(const std::tuple<T...>&, const int)
{ }
template <typename... T> template <typename... T>
void insert_col_names(const std::tuple<T...>& columns) void insert_col_names(const std::tuple<T...>& columns)
...@@ -106,8 +98,9 @@ struct InsertQuery: public Query ...@@ -106,8 +98,9 @@ struct InsertQuery: public Query
} }
template <int N=0, typename... T> template <int N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void insert_col_name(const std::tuple<T...>& columns)
insert_col_name(const std::tuple<T...>& columns) {
if constexpr(N < sizeof...(T))
{ {
using ColumnType = std::decay_t<decltype(std::get<N>(columns))>; using ColumnType = std::decay_t<decltype(std::get<N>(columns))>;
...@@ -119,11 +112,7 @@ struct InsertQuery: public Query ...@@ -119,11 +112,7 @@ struct InsertQuery: public Query
this->body += ", "; this->body += ", ";
} }
this->insert_col_name<N+1>(columns); this->insert_col_name<N + 1>(columns);
}
} }
template <int N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
insert_col_name(const std::tuple<T...>&)
{}
}; };
...@@ -13,12 +13,12 @@ ...@@ -13,12 +13,12 @@
void actual_bind(Statement& statement, const std::string& value, int index); void actual_bind(Statement& statement, const std::string& value, int index);
void actual_bind(Statement& statement, const std::int64_t& value, int index); void actual_bind(Statement& statement, const std::int64_t& value, int index);
template <typename T, typename std::enable_if_t<std::is_integral<T>::value>* = 0> void actual_bind(Statement& statement, const std::optional<bool>& value, int index);
template <typename T>
void actual_bind(Statement& statement, const T& value, int index) void actual_bind(Statement& statement, const T& value, int index)
{ {
actual_bind(statement, static_cast<std::int64_t>(value), index); actual_bind(statement, static_cast<std::int64_t>(value), index);
} }
void actual_bind(Statement& statement, const std::optional<bool>& value, int index);
#ifdef DEBUG_SQL_QUERIES #ifdef DEBUG_SQL_QUERIES
#include <utils/scopetimer.hpp> #include <utils/scopetimer.hpp>
...@@ -57,38 +57,27 @@ struct Query ...@@ -57,38 +57,27 @@ struct Query
#endif #endif
}; };
template <typename ColumnType> void actual_add_param(Query& query, const std::string& val);
void add_param(Query& query, const ColumnType& column) void actual_add_param(Query& query, const std::optional<bool>& val);
{
std::cout << "add_param<ColumnType>" << std::endl;
actual_add_param(query, column.value);
}
template <typename T> template <typename T>
void actual_add_param(Query& query, const T& val) void actual_add_param(Query& query, const T& val)
{ {
query.params.push_back(std::to_string(val)); query.params.push_back(std::to_string(val));
} }
void actual_add_param(Query& query, const std::string& val);
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, Query&>::type
operator<<(Query& query, const T&)
{
query.body += T::name;
return query;
}
void actual_add_param(Query& query, const std::optional<bool>& val);
Query& operator<<(Query& query, const char* str); Query& operator<<(Query& query, const char* str);
Query& operator<<(Query& query, const std::string& str); Query& operator<<(Query& query, const std::string& str);
template <typename Integer> template <typename T>
typename std::enable_if<std::is_integral<Integer>::value, Query&>::type Query& operator<<(Query& query, const T& i)
operator<<(Query& query, const Integer& i)
{ {
if constexpr(std::is_integral<T>::value)
{
query.body += "$" + std::to_string(query.current_param++); query.body += "$" + std::to_string(query.current_param++);
actual_add_param(query, i); actual_add_param(query, i);
}
else
{
query.body += T::name;
}
return query; return query;
} }
...@@ -29,14 +29,9 @@ struct Row ...@@ -29,14 +29,9 @@ struct Row
return col.value; return col.value;
} }
template <bool Coucou=true> void save(std::unique_ptr<DatabaseEngine>& db)
void save(std::unique_ptr<DatabaseEngine>& db, typename std::enable_if<!is_one_of<Id, T...> && Coucou>::type* = nullptr)
{ {
this->insert(*db); if constexpr(is_one_of<Id, T...>)
}
template <bool Coucou=true>
void save(std::unique_ptr<DatabaseEngine>& db, typename std::enable_if<is_one_of<Id, T...> && Coucou>::type* = nullptr)
{ {
const Id& id = std::get<Id>(this->columns); const Id& id = std::get<Id>(this->columns);
if (id.value == Id::unset_value) if (id.value == Id::unset_value)
...@@ -48,23 +43,26 @@ struct Row ...@@ -48,23 +43,26 @@ struct Row
else else
this->update(*db); this->update(*db);
} }
else
this->insert(*db);
}
private: private:
template <bool Coucou=true> void insert(DatabaseEngine& db)
void insert(DatabaseEngine& db, typename std::enable_if<is_one_of<Id, T...> && Coucou>::type* = nullptr) {
if constexpr(is_one_of<Id, T...>)
{ {
InsertQuery query(this->table_name, this->columns); InsertQuery query(this->table_name, this->columns);
// Ugly workaround for non portable stuff // Ugly workaround for non portable stuff
query.body += db.get_returning_id_sql_string(Id::name); query.body += db.get_returning_id_sql_string(Id::name);
query.execute(db, this->columns); query.execute(db, this->columns);
} }
else
template <bool Coucou=true>
void insert(DatabaseEngine& db, typename std::enable_if<!is_one_of<Id, T...> && Coucou>::type* = nullptr)
{ {
InsertQuery query(this->table_name, this->columns); InsertQuery query(this->table_name, this->columns);
query.execute(db, this->columns); query.execute(db, this->columns);
} }
}
void update(DatabaseEngine& db) void update(DatabaseEngine& db)
{ {
......
...@@ -15,48 +15,37 @@ ...@@ -15,48 +15,37 @@
using namespace std::string_literals; using namespace std::string_literals;
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, std::int64_t>::type auto extract_row_value(Statement& statement, const int i)
extract_row_value(Statement& statement, const int i)
{ {
if constexpr(std::is_integral<T>::value)
return statement.get_column_int64(i); return statement.get_column_int64(i);
} else if constexpr (std::is_same<std::string, T>::value)
template <typename T>
typename std::enable_if<std::is_same<std::string, T>::value, T>::type
extract_row_value(Statement& statement, const int i)
{
return statement.get_column_text(i); return statement.get_column_text(i);
} else if (std::is_same<std::optional<bool>, T>::value)
{
template <typename T>
typename std::enable_if<std::is_same<std::optional<bool>, T>::value, T>::type
extract_row_value(Statement& statement, const int i)
{
const auto integer = statement.get_column_int(i); const auto integer = statement.get_column_int(i);
if (integer > 0) if (integer > 0)
return true; return std::optional<bool>{true};
else if (integer < 0) else if (integer < 0)
return false; return std::optional<bool>{false};
return std::nullopt; return std::optional<bool>{};
}
} }
template <std::size_t N=0, typename... T> template <std::size_t N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void extract_row_values(Row<T...>& row, Statement& statement)
extract_row_values(Row<T...>& row, Statement& statement)
{ {
if constexpr(N < sizeof...(T))
{
using ColumnType = typename std::remove_reference<decltype(std::get<N>(row.columns))>::type; using ColumnType = typename std::remove_reference<decltype(std::get<N>(row.columns))>::type;
auto&& column = std::get<N>(row.columns); auto&& column = std::get<N>(row.columns);
column.value = static_cast<decltype(column.value)>(extract_row_value<typename ColumnType::real_type>(statement, N)); column.value = static_cast<decltype(column.value)>(extract_row_value<typename ColumnType::real_type>(statement, N));
extract_row_values<N+1>(row, statement); extract_row_values<N + 1>(row, statement);
}
} }
template <std::size_t N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
extract_row_values(Row<T...>&, Statement&)
{}
template <typename... T> template <typename... T>
struct SelectQuery: public Query struct SelectQuery: public Query
{ {
...@@ -69,8 +58,9 @@ struct SelectQuery: public Query ...@@ -69,8 +58,9 @@ struct SelectQuery: public Query
} }
template <std::size_t N=0> template <std::size_t N=0>
typename std::enable_if<N < sizeof...(T), void>::type void insert_col_name()
insert_col_name() {
if constexpr(N < sizeof...(T))
{ {
using ColumnsType = std::tuple<T...>; using ColumnsType = std::tuple<T...>;
using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnsType>()))>::type; using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnsType>()))>::type;
...@@ -80,12 +70,9 @@ struct SelectQuery: public Query ...@@ -80,12 +70,9 @@ struct SelectQuery: public Query
if (N < (sizeof...(T) - 1)) if (N < (sizeof...(T) - 1))
this->body += ", "; this->body += ", ";
this->insert_col_name<N+1>(); this->insert_col_name<N + 1>();
}
} }
template <std::size_t N=0>
typename std::enable_if<N == sizeof...(T), void>::type
insert_col_name()
{}
SelectQuery& where() SelectQuery& where()
{ {
......
...@@ -93,22 +93,21 @@ class Table ...@@ -93,22 +93,21 @@ class Table
private: private:
template <std::size_t N=0> template <std::size_t N=0>
typename std::enable_if<N < sizeof...(T), void>::type void add_column_if_not_exists(DatabaseEngine& db, const std::set<std::string>& existing_columns)
add_column_if_not_exists(DatabaseEngine& db, const std::set<std::string>& existing_columns) {
if constexpr(N < sizeof...(T))
{ {
using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type; using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type;
if (existing_columns.count(ColumnType::name) == 0) if (existing_columns.count(ColumnType::name) == 0)
add_column_to_table<ColumnType>(db, this->name); add_column_to_table<ColumnType>(db, this->name);
add_column_if_not_exists<N+1>(db, existing_columns); add_column_if_not_exists<N + 1>(db, existing_columns);
}
} }
template <std::size_t N=0>
typename std::enable_if<N == sizeof...(T), void>::type
add_column_if_not_exists(DatabaseEngine&, const std::set<std::string>&)
{}
template <std::size_t N=0> template <std::size_t N=0>
typename std::enable_if<N < sizeof...(T), void>::type void add_column_create(DatabaseEngine& db, std::string& str)
add_column_create(DatabaseEngine& db, std::string& str) {
if constexpr(N < sizeof...(T))
{ {
using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type; using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type;
str += ColumnType::name; str += ColumnType::name;
...@@ -117,12 +116,9 @@ class Table ...@@ -117,12 +116,9 @@ class Table
if (N != sizeof...(T) - 1) if (N != sizeof...(T) - 1)
str += ","; str += ",";
add_column_create<N+1>(db, str); add_column_create<N + 1>(db, str);
}
} }
template <std::size_t N=0>
typename std::enable_if<N == sizeof...(T), void>::type
add_column_create(DatabaseEngine&, std::string&)
{ }
const std::string name; const std::string name;
}; };
...@@ -39,27 +39,25 @@ struct UpdateQuery: public Query ...@@ -39,27 +39,25 @@ struct UpdateQuery: public Query
} }
template <int N=0, typename... T> template <int N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void insert_col_name_and_value(const std::tuple<T...>& columns)
insert_col_name_and_value(const std::tuple<T...>& columns) {
if constexpr(N < sizeof...(T))
{ {
using ColumnType = std::decay_t<decltype(std::get<N>(columns))>; using ColumnType = std::decay_t<decltype(std::get<N>(columns))>;
if (!std::is_same<ColumnType, Id>::value) if (!std::is_same<ColumnType, Id>::value)
{ {
this->body += ColumnType::name + "=$"s + std::to_string(this->current_param); this->body += ColumnType::name + "=$"s
+ std::to_string(this->current_param);
this->current_param++; this->current_param++;
if (N < (sizeof...(T) - 1)) if (N < (sizeof...(T) - 1))
this->body += ", "; this->body += ", ";
} }
this->insert_col_name_and_value<N+1>(columns); this->insert_col_name_and_value<N + 1>(columns);
}
} }
template <int N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
insert_col_name_and_value(const std::tuple<T...>&)
{}
template <typename... T> template <typename... T>
void execute(DatabaseEngine& db, const std::tuple<T...>& columns) void execute(DatabaseEngine& db, const std::tuple<T...>& columns)
...@@ -76,8 +74,9 @@ struct UpdateQuery: public Query ...@@ -76,8 +74,9 @@ struct UpdateQuery: public Query
} }
template <int N=0, typename... T> template <int N=0, typename... T>
typename std::enable_if<N < sizeof...(T), void>::type void bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1)
bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1) {
if constexpr(N < sizeof...(T))
{ {
auto&& column = std::get<N>(columns); auto&& column = std::get<N>(columns);
using ColumnType = std::decay_t<decltype(column)>; using ColumnType = std::decay_t<decltype(column)>;
...@@ -85,13 +84,9 @@ struct UpdateQuery: public Query ...@@ -85,13 +84,9 @@ struct UpdateQuery: public Query
if (!std::is_same<ColumnType, Id>::value) if (!std::is_same<ColumnType, Id>::value)
actual_bind(statement, column.value, index++); actual_bind(statement, column.value, index++);
this->bind_param<N+1>(columns, statement, index); this->bind_param<N + 1>(columns, statement, index);
}
} }
template <int N=0, typename... T>
typename std::enable_if<N == sizeof...(T), void>::type
bind_param(const std::tuple<T...>&, Statement&, int)
{}
template <typename... T> template <typename... T>
void bind_id(const std::tuple<T...>& columns, Statement& statement) void bind_id(const std::tuple<T...>& columns, Statement& statement)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment