summaryrefslogtreecommitdiff
path: root/src/database
diff options
context:
space:
mode:
Diffstat (limited to 'src/database')
-rw-r--r--src/database/index.hpp21
-rw-r--r--src/database/insert_query.hpp91
-rw-r--r--src/database/query.hpp41
-rw-r--r--src/database/row.hpp52
-rw-r--r--src/database/select_query.hpp77
-rw-r--r--src/database/table.hpp44
-rw-r--r--src/database/update_query.hpp51
7 files changed, 213 insertions, 164 deletions
diff --git a/src/database/index.hpp b/src/database/index.hpp
index 094a36a..30766ab 100644
--- a/src/database/index.hpp
+++ b/src/database/index.hpp
@@ -8,16 +8,19 @@
namespace
{
template <std::size_t N=0, typename... T>
-void add_column_name(std::string& out)
+typename std::enable_if<N == sizeof...(T), void>::type
+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;
- out += ColumnType::name;
- if (N != sizeof...(T) - 1)
- out += ",";
- add_column_name<N + 1, T...>(out);
- }
+ using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<std::tuple<T...>>()))>::type;
+ out += ColumnType::name;
+ if (N != sizeof...(T) - 1)
+ out += ",";
+ add_column_name<N+1, T...>(out);
}
}
diff --git a/src/database/insert_query.hpp b/src/database/insert_query.hpp
index ed1944f..04c098c 100644
--- a/src/database/insert_query.hpp
+++ b/src/database/insert_query.hpp
@@ -11,17 +11,20 @@
#include <tuple>
template <std::size_t N=0, typename... T>
-void update_autoincrement_id(std::tuple<T...>& columns, Statement& statement)
+typename std::enable_if<N < sizeof...(T), void>::type
+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;
- if (std::is_same<ColumnType, Id>::value)
- auto&& column = std::get<Id>(columns);
- update_autoincrement_id<N + 1>(columns, statement);
- }
+ using ColumnType = typename std::decay<decltype(std::get<N>(columns))>::type;
+ if (std::is_same<ColumnType, Id>::value)
+ auto&& column = std::get<Id>(columns);
+ 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
{
template <typename... T>
@@ -50,20 +53,23 @@ struct InsertQuery: public Query
}
template <int N=0, typename... T>
- void bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1)
{
- if constexpr(N < sizeof...(T))
- {
- auto&& column = std::get<N>(columns);
- using ColumnType = std::decay_t<decltype(column)>;
+ auto&& column = std::get<N>(columns);
+ using ColumnType = std::decay_t<decltype(column)>;
- if constexpr(!std::is_same<ColumnType, Id>::value)
- actual_bind(statement, column.value, index++);
+ if (!std::is_same<ColumnType, Id>::value)
+ 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>
void insert_values(const std::tuple<T...>& columns)
{
@@ -73,21 +79,23 @@ struct InsertQuery: public Query
}
template <int N=0, typename... T>
- void insert_value(const std::tuple<T...>& columns, int index=1)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ 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))>;
+
+ if (!std::is_same<ColumnType, Id>::value)
{
- using ColumnType = std::decay_t<decltype(std::get<N>(columns))>;
-
- if (!std::is_same<ColumnType, Id>::value)
- {
- this->body += "$" + std::to_string(index++);
- if (N != sizeof...(T) - 1)
- this->body += ", ";
- }
- this->insert_value<N + 1>(columns, index);
+ this->body += "$" + std::to_string(index++);
+ if (N != sizeof...(T) - 1)
+ this->body += ", ";
}
+ 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>
void insert_col_names(const std::tuple<T...>& columns)
@@ -98,21 +106,24 @@ struct InsertQuery: public Query
}
template <int N=0, typename... T>
- void insert_col_name(const std::tuple<T...>& columns)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ 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))>;
- if (!std::is_same<ColumnType, Id>::value)
- {
- this->body += ColumnType::name;
-
- if (N < (sizeof...(T) - 1))
- this->body += ", ";
- }
+ if (!std::is_same<ColumnType, Id>::value)
+ {
+ this->body += ColumnType::name;
- this->insert_col_name<N + 1>(columns);
+ if (N < (sizeof...(T) - 1))
+ this->body += ", ";
}
+
+ 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...>&)
+ {}
};
diff --git a/src/database/query.hpp b/src/database/query.hpp
index 2a2d2d4..1c4a5ff 100644
--- a/src/database/query.hpp
+++ b/src/database/query.hpp
@@ -13,12 +13,12 @@
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::optional<bool>& value, int index);
-template <typename T>
+template <typename T, typename std::enable_if_t<std::is_integral<T>::value>* = 0>
void actual_bind(Statement& statement, const T& value, int 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
#include <utils/scopetimer.hpp>
@@ -57,27 +57,38 @@ struct Query
#endif
};
-void actual_add_param(Query& query, const std::string& val);
-void actual_add_param(Query& query, const std::optional<bool>& val);
+template <typename ColumnType>
+void add_param(Query& query, const ColumnType& column)
+{
+ std::cout << "add_param<ColumnType>" << std::endl;
+ actual_add_param(query, column.value);
+}
+
template <typename T>
void actual_add_param(Query& query, const T& 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 std::string& str);
-template <typename T>
-Query& operator<<(Query& query, const T& i)
+template <typename Integer>
+typename std::enable_if<std::is_integral<Integer>::value, Query&>::type
+operator<<(Query& query, const Integer& i)
{
- if constexpr(std::is_integral<T>::value)
- {
- query.body += "$" + std::to_string(query.current_param++);
- actual_add_param(query, i);
- }
- else
- {
- query.body += T::name;
- }
+ query.body += "$" + std::to_string(query.current_param++);
+ actual_add_param(query, i);
return query;
}
+
diff --git a/src/database/row.hpp b/src/database/row.hpp
index 194a9c5..3703ff7 100644
--- a/src/database/row.hpp
+++ b/src/database/row.hpp
@@ -29,39 +29,41 @@ struct Row
return col.value;
}
- void save(std::unique_ptr<DatabaseEngine>& db)
+ template <bool Coucou=true>
+ void save(std::unique_ptr<DatabaseEngine>& db, typename std::enable_if<!is_one_of<Id, T...> && Coucou>::type* = nullptr)
{
- if constexpr(is_one_of<Id, T...>)
+ this->insert(*db);
+ }
+
+ 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);
+ if (id.value == Id::unset_value)
{
- const Id& id = std::get<Id>(this->columns);
- if (id.value == Id::unset_value)
- {
- this->insert(*db);
- if (db->last_inserted_rowid >= 0)
- std::get<Id>(this->columns).value = static_cast<Id::real_type>(db->last_inserted_rowid);
- }
- else
- this->update(*db);
+ this->insert(*db);
+ if (db->last_inserted_rowid >= 0)
+ std::get<Id>(this->columns).value = static_cast<Id::real_type>(db->last_inserted_rowid);
}
else
- this->insert(*db);
+ this->update(*db);
}
private:
- void insert(DatabaseEngine& db)
+ template <bool Coucou=true>
+ 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);
- // Ugly workaround for non portable stuff
- query.body += db.get_returning_id_sql_string(Id::name);
- query.execute(db, this->columns);
- }
- else
- {
- InsertQuery query(this->table_name, this->columns);
- query.execute(db, this->columns);
- }
+ InsertQuery query(this->table_name, this->columns);
+ // Ugly workaround for non portable stuff
+ query.body += db.get_returning_id_sql_string(Id::name);
+ query.execute(db, this->columns);
+ }
+
+ 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);
+ query.execute(db, this->columns);
}
void update(DatabaseEngine& db)
diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp
index f7496a4..cd9943c 100644
--- a/src/database/select_query.hpp
+++ b/src/database/select_query.hpp
@@ -15,37 +15,48 @@
using namespace std::string_literals;
template <typename T>
-auto extract_row_value(Statement& statement, const int i)
+typename std::enable_if<std::is_integral<T>::value, std::int64_t>::type
+extract_row_value(Statement& statement, const int i)
{
- if constexpr(std::is_integral<T>::value)
- return statement.get_column_int64(i);
- else if constexpr (std::is_same<std::string, T>::value)
- return statement.get_column_text(i);
- else if (std::is_same<std::optional<bool>, T>::value)
- {
- const auto integer = statement.get_column_int(i);
- if (integer > 0)
- return std::optional<bool>{true};
- else if (integer < 0)
- return std::optional<bool>{false};
- return std::optional<bool>{};
- }
+ return statement.get_column_int64(i);
+}
+
+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);
+}
+
+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);
+ if (integer > 0)
+ return true;
+ else if (integer < 0)
+ return false;
+ return std::nullopt;
}
template <std::size_t N=0, typename... T>
-void extract_row_values(Row<T...>& row, Statement& statement)
+typename std::enable_if<N < sizeof...(T), void>::type
+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);
- column.value = static_cast<decltype(column.value)>(extract_row_value<typename ColumnType::real_type>(statement, N));
+ auto&& column = std::get<N>(row.columns);
+ 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>
struct SelectQuery: public Query
{
@@ -58,21 +69,23 @@ struct SelectQuery: public Query
}
template <std::size_t N=0>
- void insert_col_name()
+ typename std::enable_if<N < sizeof...(T), void>::type
+ insert_col_name()
{
- if constexpr(N < sizeof...(T))
- {
- using ColumnsType = std::tuple<T...>;
- using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnsType>()))>::type;
+ using ColumnsType = std::tuple<T...>;
+ using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnsType>()))>::type;
- this->body += " " + std::string{ColumnType::name};
+ this->body += " " + std::string{ColumnType::name};
- if (N < (sizeof...(T) - 1))
- this->body += ", ";
+ if (N < (sizeof...(T) - 1))
+ 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()
{
diff --git a/src/database/table.hpp b/src/database/table.hpp
index eb68418..680e7cc 100644
--- a/src/database/table.hpp
+++ b/src/database/table.hpp
@@ -93,32 +93,36 @@ class Table
private:
template <std::size_t N=0>
- void add_column_if_not_exists(DatabaseEngine& db, const std::set<std::string>& existing_columns)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ 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;
- if (existing_columns.count(ColumnType::name) == 0)
- add_column_to_table<ColumnType>(db, this->name);
- add_column_if_not_exists<N + 1>(db, existing_columns);
- }
+ using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type;
+ if (existing_columns.count(ColumnType::name) == 0)
+ add_column_to_table<ColumnType>(db, this->name);
+ 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>
- void add_column_create(DatabaseEngine& db, std::string& str)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ 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;
- str += ColumnType::name;
- str += " ";
- str += ToSQLType<ColumnType>(db);
- if (N != sizeof...(T) - 1)
- str += ",";
-
- add_column_create<N + 1>(db, str);
- }
+ using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type;
+ str += ColumnType::name;
+ str += " ";
+ str += ToSQLType<ColumnType>(db);
+ if (N != sizeof...(T) - 1)
+ 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;
};
diff --git a/src/database/update_query.hpp b/src/database/update_query.hpp
index 0ee2bd9..a29ac3f 100644
--- a/src/database/update_query.hpp
+++ b/src/database/update_query.hpp
@@ -39,25 +39,27 @@ struct UpdateQuery: public Query
}
template <int N=0, typename... T>
- void insert_col_name_and_value(const std::tuple<T...>& columns)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ 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))>;
-
- if (!std::is_same<ColumnType, Id>::value)
- {
- this->body += ColumnType::name + "=$"s
- + std::to_string(this->current_param);
- this->current_param++;
+ using ColumnType = std::decay_t<decltype(std::get<N>(columns))>;
- if (N < (sizeof...(T) - 1))
- this->body += ", ";
- }
+ if (!std::is_same<ColumnType, Id>::value)
+ {
+ this->body += ColumnType::name + "=$"s + std::to_string(this->current_param);
+ this->current_param++;
- this->insert_col_name_and_value<N + 1>(columns);
+ if (N < (sizeof...(T) - 1))
+ this->body += ", ";
}
+
+ 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>
void execute(DatabaseEngine& db, const std::tuple<T...>& columns)
@@ -74,20 +76,23 @@ struct UpdateQuery: public Query
}
template <int N=0, typename... T>
- void bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1)
+ typename std::enable_if<N < sizeof...(T), void>::type
+ bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1)
{
- if constexpr(N < sizeof...(T))
- {
- auto&& column = std::get<N>(columns);
- using ColumnType = std::decay_t<decltype(column)>;
+ auto&& column = std::get<N>(columns);
+ using ColumnType = std::decay_t<decltype(column)>;
- if (!std::is_same<ColumnType, Id>::value)
- actual_bind(statement, column.value, index++);
+ if (!std::is_same<ColumnType, Id>::value)
+ 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>
void bind_id(const std::tuple<T...>& columns, Statement& statement)
{