SQLiteXX  0.1.0
 All Classes Namespaces Files Functions Enumerations Enumerator
Functions.h
1 #ifndef __SQLITEXX_SQLITE_FUNCTIONS_H__
2 #define __SQLITEXX_SQLITE_FUNCTIONS_H__
3 
4 #include "Blob.h"
5 #include "Value.h"
6 
7 #include <sqlite3.h>
8 
9 #include <functional>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 namespace sqlite {
15  template<std::size_t N>
16  struct placeholder_template {
17  static placeholder_template pt;
18  };
19 
20  template<std::size_t N>
21  placeholder_template<N> placeholder_template<N>::pt;
22 }
23 
24 namespace std {
25  template<std::size_t N>
26  struct is_placeholder<sqlite::placeholder_template<N> > : std::integral_constant<std::size_t, N> {
27  };
28 }
29 
30 namespace sqlite
31 {
32  enum class textencoding: int {
33  utf8 = SQLITE_UTF8,
34  utf16le = SQLITE_UTF16LE,
35  utf16be = SQLITE_UTF16BE,
36  utf16 = SQLITE_UTF16,
37  };
38 
42  inline void return_result(sqlite3_context *context, int value) {
43  sqlite3_result_int(context, value);
44  }
45 
46  inline void return_result(sqlite3_context *context, int64_t value) {
47  sqlite3_result_int64(context, value);
48  }
49 
50  inline void return_result(sqlite3_context *context, double value) {
51  sqlite3_result_double(context, value);
52  }
53 
54  inline void return_result(sqlite3_context *context, const std::string &value) {
55  sqlite3_result_text(context, value.c_str(), value.size(), SQLITE_TRANSIENT);
56  }
57 
58  inline void return_result(sqlite3_context *context, const std::u16string &value) {
59  sqlite3_result_text16(context, value.c_str(), value.size() * sizeof(char16_t), SQLITE_TRANSIENT);
60  }
61 
62  inline void return_result(sqlite3_context *context, const value &value) {
63  sqlite3_result_value(context, value.handle());
64  }
65 
66  inline void return_result(sqlite3_context *context, const blob &value) {
67  sqlite3_result_blob(context, value.data(), value.size(), SQLITE_TRANSIENT);
68  }
69 
70  template <typename T>
71  struct function_traits : public function_traits<decltype(&T::operator())>
72  {};
73 
74  template <typename C, typename R, typename... Args>
75  struct function_traits<R(C::*)(Args...)> {
76  typedef std::function<R(Args...)> f_type;
77  static const size_t nargs = sizeof...(Args);
78 
79  typedef R result_type;
80 
81  template<size_t i>
82  struct arg
83  {
84  typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
85  };
86  };
87 
88  template <typename C, typename R, typename... Args>
89  struct function_traits<R(C::*)(Args...) const> {
90  typedef std::function<R(Args...)> f_type;
91  static const size_t nargs = sizeof...(Args);
92 
93  typedef R result_type;
94 
95  template<size_t i>
96  struct arg
97  {
98  typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
99  };
100  };
101 
102  template <typename R, typename... Args>
103  struct function_traits<R(*)(Args...)> {
104  typedef std::function<R(Args...)> f_type;
105  static const size_t nargs = sizeof...(Args);
106 
107  typedef R result_type;
108 
109  template<size_t i>
110  struct arg
111  {
112  typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
113  };
114  };
115 
116  template <typename R, typename... Args>
117  struct function_traits<R(&)(Args...)> {
118  typedef std::function<R(Args...)> f_type;
119  static const size_t nargs = sizeof...(Args);
120 
121  typedef R result_type;
122 
123  template<size_t i>
124  struct arg
125  {
126  typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
127  };
128  };
129 
130  template <typename T>
131  struct SQLiteFunctionTraits : public SQLiteFunctionTraits<decltype(&T::operator())>
132  {};
133 
134  template <typename C, typename R>
135  struct SQLiteFunctionTraits<R(C::*)(const std::vector<value> &)> {
136  typedef std::function<R(const std::vector<value> &)> f_type;
137  };
138 
139  template <typename C, typename R>
140  struct SQLiteFunctionTraits<R(C::*)(const std::vector<value> &) const> {
141  typedef std::function<R(const std::vector<value> &)> f_type;
142  };
143 
144  template <typename R>
145  struct SQLiteFunctionTraits<R(*)(const std::vector<value> &)> {
146  typedef std::function<R(const std::vector<value> &)> f_type;
147  };
148 
149  template <typename R>
150  struct SQLiteFunctionTraits<R(&)(const std::vector<value> &)> {
151  typedef std::function<R(const std::vector<value> &)> f_type;
152  };
153 
154  template <typename T>
155  struct collation_traits : public collation_traits<decltype(&T::operator())>
156  {};
157 
158  template <typename C>
159  struct collation_traits<int(C::*)(const std::string&, const std::string&)> {
160  typedef std::function<int(const std::string&, const std::string&)> f_type;
161  };
162 
163  template <typename C>
164  struct collation_traits<int(C::*)(const std::string&, const std::string&) const> {
165  typedef std::function<int(const std::string&, const std::string&)> f_type;
166  };
167 
168  template <>
169  struct collation_traits<int(*)(const std::string&, const std::string&)> {
170  typedef std::function<int(const std::string&, const std::string&)> f_type;
171  };
172 
173  template <>
174  struct collation_traits<int(&)(const std::string&, const std::string&)> {
175  typedef std::function<int(const std::string&, const std::string&)> f_type;
176  };
177 
178  template<typename T>
179  typename std::remove_reference<T>::type get(sqlite3_value **values, const std::size_t index) {
180  return value(values[index]);
181  }
182 
183  template<typename F, typename C, std::size_t... Is>
184  typename function_traits<F>::f_type
185  bind_class_method(F method, C* classObject, std::index_sequence<Is...>) {
186  return std::bind(method, classObject, placeholder_template<Is+1>::pt...);
187  }
188 
189  template<typename F, typename C>
190  typename function_traits<F>::f_type
191  bind_class_method(F method, C* classObject) {
192  return bind_class_method(method, classObject, std::make_index_sequence<function_traits<F>::nargs>{});
193  }
194 
195  template<typename R, typename... Args, std::size_t... Is>
196  R invoke(std::function<R(Args...)> func, sqlite3_value **values, std::index_sequence<Is...>) {
197  // So there is no warnings when no arguments are given to function.
198  (void)values;
199 
200  return func(get<typename function_traits<decltype(func)>::template arg<Is>::type>(values, Is) ...);
201  }
202 
203  template<typename R, typename... Args>
204  R invoke(std::function<R(Args...)> func, sqlite3_value **values) {
205  return invoke(func, values, std::index_sequence_for<Args...>{});
206  }
207 
208  template <typename F>
209  void internal_scalar_function(sqlite3_context* context, int argc, sqlite3_value **values) {
210  // This argument is needed so this function can be used in the
211  // SQLite create function interface. Adding this line so no warning is generated
212  (void)argc;
213  F* userScalarFunction = static_cast<F*>(sqlite3_user_data(context));
214  assert(userScalarFunction != 0);
215 
216  try {
217  auto result = invoke(*userScalarFunction, values);
218  return_result(context, result);
219  } catch (const std::bad_alloc&) {
220  sqlite3_result_error_nomem(context);
221  } catch (const sqlite::exception& e) {
222  sqlite3_result_error(context, e.what(), e.errcode);
223  } catch (const std::exception& e) {
224  sqlite3_result_error(context, e.what(), SQLITE_ABORT);
225  } catch (...) {
226  sqlite3_result_error_code(context, SQLITE_ABORT);
227  }
228  }
229 
230  template <typename F>
231  void internal_general_scalar_function(sqlite3_context* context, int argc, sqlite3_value **values) {
232  F* userScalarFunction = static_cast<F*>(sqlite3_user_data(context));
233  assert(userScalarFunction != 0);
234 
235  try {
236  std::vector<value> argValues;
237  for (int i = 0; i < argc; ++i) {
238  argValues.push_back(value(values[i]));
239  }
240 
241  auto result = (*userScalarFunction)(argValues);
242  return_result(context, result);
243  } catch (const std::bad_alloc&) {
244  sqlite3_result_error_nomem(context);
245  } catch (const sqlite::exception& e) {
246  sqlite3_result_error(context, e.what(), e.errcode);
247  } catch (const std::exception& e) {
248  sqlite3_result_error(context, e.what(), SQLITE_ABORT);
249  } catch (...) {
250  sqlite3_result_error_code(context, SQLITE_ABORT);
251  }
252  }
253 
254  template <typename F>
255  int internal_collation_function(void* context, int bytes1, const void* string_bytes1, int bytes2, const void* string_bytes2) {
256  F* userCollationFunction = static_cast<F*>(context);
257  assert(userCollationFunction != 0);
258 
259  const std::string string1(static_cast<const char*>(string_bytes1), bytes1);
260  const std::string string2(static_cast<const char*>(string_bytes2), bytes2);
261 
262  int result = (*userCollationFunction)(string1, string2);
263  return result;
264  }
265 
266 
267  template<typename Call>
268  void internal_delete(void *user_data) {
269  Call *callback = static_cast<Call *>(user_data);
270  assert(callback != 0);
271 
272  delete callback;
273  }
274 
275  template<typename T>
276  class aggregate_wrapper {
277  public:
278  aggregate_wrapper() :
279  m_implementation()
280  {}
281 
282  void step(sqlite3_context* context, int argc, sqlite3_value **values) {
283  (void)context;
284  (void)argc;
285  invoke(bind_class_method(&T::step, &m_implementation), values);
286  }
287 
288  void finalize(sqlite3_context* context) {
289  return_result(context, m_implementation.finalize());
290  }
291 
292  void reset() {
293  m_implementation = T();
294  }
295 
296  private:
297  T m_implementation;
298  };
299 
300  template <typename T>
301  void internal_step(sqlite3_context* context, int argc, sqlite3_value **values) {
302  T* wrapper = static_cast<T*>(sqlite3_user_data(context));
303  assert(wrapper != 0);
304 
305  try {
306  wrapper->step(context, argc, values);
307  } catch (const std::bad_alloc&) {
308  sqlite3_result_error_nomem(context);
309  } catch (const sqlite::exception& e) {
310  sqlite3_result_error(context, e.what(), e.errcode);
311  } catch (const std::exception& e) {
312  sqlite3_result_error(context, e.what(), SQLITE_ABORT);
313  } catch (...) {
314  sqlite3_result_error_code(context, SQLITE_ABORT);
315  }
316  }
317 
318  template <typename T>
319  void internal_final(sqlite3_context* context) {
320  T* wrapper = static_cast<T*>(sqlite3_user_data(context));
321  assert(wrapper != 0);
322 
323  try {
324  wrapper->finalize(context);
325  wrapper->reset();
326  } catch (const std::bad_alloc&) {
327  sqlite3_result_error_nomem(context);
328  } catch (const sqlite::exception& e) {
329  sqlite3_result_error(context, e.what(), e.errcode);
330  } catch (const std::exception& e) {
331  sqlite3_result_error(context, e.what(), SQLITE_ABORT);
332  } catch (...) {
333  sqlite3_result_error_code(context, SQLITE_ABORT);
334  }
335  }
336 
337  template <typename T>
338  void internal_dispose(void *user_data) {
339  T* wrapper = static_cast<T *>(user_data);
340  assert(wrapper != 0);
341 
342  delete wrapper;
343  }
344 }
345 
346 #endif
A SQLite dynamically typed value object, aka "sqlite3_value".
Definition: Value.h:27
Encapsulation of the error code and message from SQLite3, based on std::runtime_error.
Definition: Exception.h:14
void return_result(sqlite3_context *context, int value)
Helpers for setting result of scalar functions.
Definition: Functions.h:42