summaryrefslogtreecommitdiff
path: root/src/database/table.hpp
blob: 163b97f0a08208e363ad6e7725b86c8f39711222 (plain)
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
#pragma once

#include <database/select_query.hpp>
#include <database/type_to_sql.hpp>
#include <logger/logger.hpp>
#include <database/row.hpp>

#include <algorithm>
#include <string>

template <typename... T>
class Table
{
  static_assert(sizeof...(T) > 0, "Table cannot be empty");
  using ColumnTypes = std::tuple<T...>;

 public:
  using RowType = Row<T...>;

  Table(std::string name):
      name(std::move(name))
  {}

  void create(sqlite3* db)
  {
    std::string res{"CREATE TABLE IF NOT EXISTS "};
    res += this->name;
    res += " (\n";
    this->add_column_create<0>(res);
    res += ")";

    log_debug(res);

    char* error;
    const auto result = sqlite3_exec(db, res.data(), nullptr, nullptr, &error);
    log_debug("result: ", +result);
    if (result != SQLITE_OK)
      {
        log_error("Error executing query: ", error);
        sqlite3_free(error);
      }
  }

  RowType row()
  {
    return {this->name};
  }

  SelectQuery<T...> select()
  {
    SelectQuery<T...> select(this->name);
    return select;
  }

  const std::string& get_name() const
  {
    return this->name;
  }

 private:
  template <std::size_t N>
  typename std::enable_if<N < sizeof...(T), void>::type
  add_column_create(std::string& str)
  {
    using ColumnType = typename std::remove_reference<decltype(std::get<N>(std::declval<ColumnTypes>()))>::type;
    using RealType = typename ColumnType::real_type;
    str += ColumnType::name;
    str += " ";
    str += TypeToSQLType<RealType>::type;
    str += " "s + ColumnType::options;
    if (N != sizeof...(T) - 1)
      str += ",";
    str += "\n";

    add_column_create<N+1>(str);
  }

  template <std::size_t N>
  typename std::enable_if<N == sizeof...(T), void>::type
  add_column_create(std::string&)
  { }

  const std::string name;
};