~singpolyma/biboumi

ref: d7427fc9ca4c06fda458e4951559f57163d90b94 biboumi/src/database/update_query.hpp -rw-r--r-- 2.8 KiB
d7427fc9 — louiz’ Re-connect to postgresql when the connection is lost 5 years ago
                                                                                
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’
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
#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)
  {
#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));
  }
};