~singpolyma/biboumi

ref: d62ca9f87906be6f046fe9d07afb8bfb69c166e3 biboumi/src/database/update_query.hpp -rw-r--r-- 2.6 KiB
d62ca9f8 — louiz’ Use if constexpr to make things a lot more readable 5 years ago
                                                                                
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
7e64a2e3 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#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>
  void 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++;

            if (N < (sizeof...(T) - 1))
              this->body += ", ";
          }

        this->insert_col_name_and_value<N + 1>(columns);
      }
  }

  template <typename... T>
  void execute(DatabaseEngine& db, const std::tuple<T...>& columns)
  {
#ifdef DEBUG_SQL_QUERIES
      const auto timer = this->log_and_time();
#endif

    auto statement = db.prepare(this->body);
    this->bind_param(columns, *statement);
    this->bind_id(columns, *statement);

    statement->step();
  }

  template <int N=0, typename... T>
  void 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)>;

        if (!std::is_same<ColumnType, Id>::value)
          actual_bind(statement, column.value, index++);

        this->bind_param<N + 1>(columns, statement, index);
      }
  }

  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));
  }
};