column.h
Go to the documentation of this file.
1 #ifndef cetlib_sqlite_column_h
2 #define cetlib_sqlite_column_h
3 
4 // ===================================================================
5 // column<T, Constraints...>
6 //
7 // SQLite tables are composed of columns that are specified in SQLite
8 // as (e.g):
9 //
10 // CREATE TABLE workers(FirstName TEXT, LastName TEXT);
11 //
12 // where the fields in parentheses denote two columns with the names
13 // 'FirstName' and 'LastName', both of which are of the type 'TEXT'.
14 //
15 // The column template allows a user to specify a column using native
16 // C++ types. For example, the above SQLite statement can be achieved
17 // and executed in C++ using the create_table command:
18 //
19 // cet::sqlite::create_table(db,
20 // "workers",
21 // column<string>{"FirstName"},
22 // column<string>{"LastName"});
23 //
24 // Column constraints are also allowed (e.g.):
25 //
26 // column<int, primary_key, autoincrement>{"id"}
27 //
28 // See the notes in cetlib/sqlite/detail/column_constraint.h.
29 // ===================================================================
30 
32 
33 #include <array>
34 #include <string>
35 #include <tuple>
36 #include <utility>
37 
38 namespace cet::sqlite {
39  template <size_t N>
40  using name_array = std::array<std::string, N>;
41 
42  class column_base {
43  public:
44  column_base(std::string const& n) : name_{n} {}
45  auto const&
46  name() const
47  {
48  return name_;
49  }
50 
51  private:
53  };
54 
55  // column<T> is a containing struct that knows its C++ type (T)
56  // and the sqlite translation (sqlite_type()). There is no
57  // implementation for the general case; the template must be
58  // specialized for each supported type.
59  template <typename T, typename... Constraints>
60  struct column;
61 
62  // IMPROVEMENT: The specializations can be improved by some
63  // template metaprogramming and using the std::is_arithmetic and
64  // std::is_floating_point type traits.
65  template <typename... Constraints>
66  struct column<double, Constraints...> : column_base {
68  using type = double;
70  sqlite_type() const
71  {
72  return " numeric";
73  }
74  };
75 
76  template <typename... Constraints>
77  struct column<float, Constraints...> : column_base {
79  using type = float;
81  sqlite_type() const
82  {
83  return " numeric";
84  }
85  };
86 
87  template <typename... Constraints>
88  struct column<int, Constraints...> : column_base {
90  using type = int;
92  sqlite_type() const
93  {
94  return " integer";
95  }
96  };
97 
98  template <typename... Constraints>
99  struct column<long, Constraints...> : column_base {
101  using type = long;
103  sqlite_type() const
104  {
105  return " integer";
106  }
107  };
108 
109  template <typename... Constraints>
110  struct column<long long, Constraints...> : column_base {
112  using type = long long;
114  sqlite_type() const
115  {
116  return " integer";
117  }
118  };
119 
120  template <typename... Constraints>
121  struct column<unsigned int, Constraints...> : column_base {
123  using type = int;
125  sqlite_type() const
126  {
127  return " integer";
128  }
129  };
130 
131  template <typename... Constraints>
132  struct column<unsigned long, Constraints...> : column_base {
134  using type = long;
136  sqlite_type() const
137  {
138  return " integer";
139  }
140  };
141 
142  template <typename... Constraints>
143  struct column<unsigned long long, Constraints...> : column_base {
145  using type = long long;
147  sqlite_type() const
148  {
149  return " integer";
150  }
151  };
152 
153  template <typename... Constraints>
154  struct column<std::string, Constraints...> : column_base {
156  using type = std::string;
158  sqlite_type() const
159  {
160  return " text";
161  }
162  };
163 
164  //=============================================================================
165  // A permissive_column type is used in the context of an Ntuple so
166  // that the following constructs are allowed:
167  //
168  // Ntuple<int, double, string> // has identical semantics to...
169  // Ntuple<column<int>, column<double>, column<string>>
170  //
171  // The benefit is that if a user wants to specify a constraint for
172  // a given column, the way to do that in the context of the Ntuple
173  // is for the user to specify (e.g.) column<int, primary_key> for
174  // the relevant column, but not be required to use column<...> for
175  // all others (e.g.):
176  //
177  // Ntuple<column<int, primary_key>, double, string>;
178 
179  template <typename T, typename... Constraints>
180  struct permissive_column : column<T, Constraints...> {
181  using column<T, Constraints...>::column;
182  using element_type = T;
183  };
184 
185  template <typename T, typename... Constraints>
186  struct permissive_column<column<T, Constraints...>>
187  : permissive_column<T, Constraints...> {
188  using permissive_column<T, Constraints...>::permissive_column;
189  };
190 
191 } // cet::sqlite
192 
193 #endif /* cetlib_sqlite_column_h */
194 
195 // Local Variables:
196 // mode: c++
197 // End:
auto const & name() const
Definition: column.h:46
column_base(std::string const &n)
Definition: column.h:44
std::string string
Definition: nybbler.cc:12
STL namespace.
std::string sqlite_type() const
Definition: column.h:92
std::void_t< T > n
std::string name_
Definition: column.h:52
std::vector< std::string > column
std::array< std::string, N > name_array
Definition: column.h:40