~singpolyma/biboumi

ref: d62ca9f87906be6f046fe9d07afb8bfb69c166e3 biboumi/src/database/insert_query.hpp -rw-r--r-- 3.0 KiB
d62ca9f8 — louiz’ Use if constexpr to make things a lot more readable 5 years ago
                                                                                
50cadf3d louiz’
9defd0cc louiz’
50cadf3d louiz’
0168b96b louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
50cadf3d louiz’
0168b96b louiz’
50cadf3d louiz’
0168b96b louiz’
50cadf3d louiz’
0168b96b louiz’
50cadf3d louiz’
7e64a2e3 louiz’
0168b96b louiz’
50cadf3d louiz’
5834dd53 louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
50cadf3d louiz’
5834dd53 louiz’
50cadf3d louiz’
5834dd53 louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
0168b96b louiz’
50cadf3d louiz’
5834dd53 louiz’
0168b96b louiz’
50cadf3d louiz’
5834dd53 louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
50cadf3d louiz’
d62ca9f8 louiz’
0168b96b louiz’
d62ca9f8 louiz’
50cadf3d 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
114
115
116
117
118
#pragma once

#include <database/statement.hpp>
#include <database/column.hpp>
#include <database/query.hpp>
#include <logger/logger.hpp>

#include <type_traits>
#include <vector>
#include <string>
#include <tuple>

template <std::size_t N=0, typename... T>
void 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);
    }
}

struct InsertQuery: public Query
{
  template <typename... T>
  InsertQuery(const std::string& name, const std::tuple<T...>& columns):
      Query("INSERT INTO ")
  {
    this->body += name;
    this->insert_col_names(columns);
    this->insert_values(columns);
  }

  template <typename... T>
  void execute(DatabaseEngine& db, 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);

    if (statement->step() != StepResult::Error)
      db.extract_last_insert_rowid(*statement);
    else
      log_error("Failed to extract the rowid from the last INSERT");
  }

  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 constexpr(!std::is_same<ColumnType, Id>::value)
          actual_bind(statement, column.value, index++);

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

  template <typename... T>
  void insert_values(const std::tuple<T...>& columns)
  {
    this->body += "VALUES (";
    this->insert_value(columns);
    this->body += ")";
  }

  template <int N=0, typename... T>
  void 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)
          {
            this->body += "$" + std::to_string(index++);
            if (N != sizeof...(T) - 1)
              this->body += ", ";
          }
        this->insert_value<N + 1>(columns, index);
      }
  }

  template <typename... T>
  void insert_col_names(const std::tuple<T...>& columns)
  {
    this->body += " (";
    this->insert_col_name(columns);
    this->body += ")";
  }

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

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

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