~singpolyma/biboumi

ref: 4bd7b6981bb49dd4111c908aaa34c34f677171f4 biboumi/src/database/update_query.hpp -rw-r--r-- 3.0 KiB
4bd7b698 — louiz’ Refactor that fixes a compilation issue in Release mode 5 years ago
                                                                                
0168b96b louiz’
4bd7b698 louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
d62ca9f8 louiz’
d0e3c71b louiz’
d62ca9f8 louiz’
d0e3c71b louiz’
0168b96b louiz’
7e64a2e3 louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
d0e3c71b louiz’
0168b96b louiz’
4bd7b698 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#pragma once

#include <database/engine.hpp>
#include <database/query.hpp>
#include <database/row.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)
  {
#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>
  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));
  }
};

template <typename... T>
void update(Row<T...>& row, DatabaseEngine& db)
{
  UpdateQuery query(row.table_name, row.columns);

  query.execute(db, row.columns);
}