diff options
Diffstat (limited to 'src/database/update_query.hpp')
-rw-r--r-- | src/database/update_query.hpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/database/update_query.hpp b/src/database/update_query.hpp new file mode 100644 index 0000000..32befc0 --- /dev/null +++ b/src/database/update_query.hpp @@ -0,0 +1,100 @@ +#pragma once + +#include <database/query.hpp> +#include <database/engine.hpp> + +using namespace std::string_literals; + +template <class T, class... Tuple> +struct Index; + +template <class T, class... Types> +struct Index<T, std::tuple<T, Types...>> +{ + static const std::size_t value = 0; +}; + +template <class T, class U, class... Types> +struct Index<T, std::tuple<U, Types...>> +{ + static const std::size_t value = Index<T, std::tuple<Types...>>::value + 1; +}; + +struct UpdateQuery: public Query +{ + template <typename... T> + UpdateQuery(const std::string& name, const std::tuple<T...>& columns): + Query("UPDATE ") + { + this->body += name; + this->insert_col_names_and_values(columns); + } + + template <typename... T> + void insert_col_names_and_values(const std::tuple<T...>& columns) + { + this->body += " SET "; + this->insert_col_name_and_value(columns); + this->body += " WHERE "s + Id::name + "=$" + std::to_string(this->current_param); + } + + template <int N=0, typename... T> + typename std::enable_if<N < sizeof...(T), void>::type + insert_col_name_and_value(const std::tuple<T...>& columns) + { + 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++; + + 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) + { + auto statement = db.prepare(this->body); + this->bind_param(columns, *statement); + this->bind_id(columns, *statement); + + statement->step(); + } + + template <int N=0, typename... T> + typename std::enable_if<N < sizeof...(T), void>::type + bind_param(const std::tuple<T...>& columns, Statement& statement, int index=1) + { + 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++); + + 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) + { + static constexpr auto index = Index<Id, std::tuple<T...>>::value; + auto&& value = std::get<index>(columns); + + actual_bind(statement, value.value, sizeof...(T)); + } +}; |