Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #ifndef STATEMENT_H_
00009 #define STATEMENT_H_
00010
00011 #include <sqlite3.h>
00012 #include "Database.h"
00013 #include <vector>
00014 #include <cstdint>
00015 #include <tuple>
00016 #include <cassert>
00017
00018 namespace sqlite
00019 {
00020
00026 class Statement
00027 {
00028 private:
00029 template <class T>
00030 class ColType
00031 {
00032 public:
00033 T get_data(Statement& st, int col_index)
00034 {
00035 return T();
00036 }
00037 };
00038 friend Statement::ColType<double> coldouble();
00039 friend Statement::ColType<int> colint();
00040 friend Statement::ColType<int64_t> colint64();
00041 friend Statement::ColType<std::string> colstr();
00042
00043 template <class T>
00044 class BindWrap
00045 {
00046 };
00047
00048 public:
00052 Statement();
00058 Statement(std::string const& sql, Database& db);
00059 virtual ~Statement();
00060 Statement(Statement const&) = delete;
00061 Statement& operator=(Statement const&) = delete;
00062 Statement(Statement && other);
00063 Statement& operator=(Statement && other);
00064
00068 bool done();
00073 bool has_row();
00077 void step();
00078
00079
00085 void reset();
00090 void finalize();
00091
00097 double val_double(int col_index);
00103 int val_int(int col_index);
00109 int64_t val_int64(int col_index);
00115 std::string val_string(int col_index);
00116
00122 void bind_double(int param_index, double value);
00128 void bind_int(int param_index, int value);
00134 void bind_int64(int param_index, int64_t value);
00140 void bind_string(int param_index, std::string const& value);
00141
00147 template<typename... Args> std::tuple<Args...> get_row(ColType<Args>... types)
00148 {
00149 return get_row_internal(0, types...);
00150 }
00151
00157 template<typename... Args> std::vector<std::tuple<Args...> > get_remaining_rows(ColType<Args>... types)
00158 {
00159 std::vector<std::tuple<Args...> > ret;
00160 while (!done())
00161 {
00162 if (has_row())
00163 ret.push_back(get_row(types...));
00164 step();
00165 }
00166 return ret;
00167 }
00168
00174 template<typename... Args> void bind(Args... values)
00175 {
00176 bind_internal(1, values...);
00177 }
00178
00182 static ColType<int> colint;
00186 static ColType<double> coldouble;
00190 static ColType<int64_t> colint64;
00194 static ColType<std::string> colstring;
00195
00196 private:
00197 void reset_internal();
00198 void reset_nothrow();
00199 sqlite3_stmt* stmt;
00200 Database* db;
00201 void check_value_conditions(int col);
00202 int cols;
00203 bool hrow;
00204 bool dn;
00205
00206 std::tuple<> get_row_internal(int)
00207 {
00208 return std::tuple<>();
00209 }
00210 template<typename Head, typename... Tail> std::tuple<Head, Tail...> get_row_internal(int i, ColType<Head> h, ColType<Tail>... t)
00211 {
00212 std::tuple<Tail...> tail = get_row_internal(i + 1, t...);
00213 Head head = h.get_data(*this, i);
00214 return std::tuple_cat(std::make_tuple(head), tail);
00215 }
00216
00217 void bind_internal(int)
00218 {
00219 }
00220
00221 template<typename Head, typename... Tail> void bind_internal(int i, Head h, Tail... t)
00222 {
00223 BindWrap<Head> bw;
00224 bw.bind(i, h, *this);
00225 bind_internal(i + 1, t...);
00226 }
00227
00228 };
00229
00235 void execute_sql(std::string sql, Database& db);
00236
00244 template<typename... Args> std::vector<std::tuple<Args...> > query_sql(std::string sql, Database& db, Statement::ColType<Args>... types)
00245 {
00246 Statement st(sql, db);
00247 return st.get_remaining_rows(types...);
00248 }
00249
00250 template<>
00251 class Statement::ColType<int>
00252 {
00253 public:
00254 int get_data(Statement& st, int col_index)
00255 {
00256 return st.val_int(col_index);
00257 }
00258 };
00259
00260 template<>
00261 class Statement::ColType<double>
00262 {
00263 public:
00264 double get_data(Statement& st, int col_index)
00265 {
00266 return st.val_double(col_index);
00267 }
00268 };
00269
00270 template<>
00271 class Statement::ColType<int64_t>
00272 {
00273 public:
00274 int64_t get_data(Statement& st, int col_index)
00275 {
00276 return st.val_int64(col_index);
00277 }
00278 };
00279
00280 template<>
00281 class Statement::ColType<std::string>
00282 {
00283 public:
00284 std::string get_data(Statement& st, int col_index)
00285 {
00286 return st.val_string(col_index);
00287 }
00288 };
00289
00290 Statement::ColType<double> coldouble();
00291
00292 Statement::ColType<int> colint();
00293
00294 Statement::ColType<int64_t> colint64();
00295
00296 Statement::ColType<std::string> colstr();
00297
00298 template<>
00299 class Statement::BindWrap<int>
00300 {
00301 public:
00302 void bind(int index, int val, Statement& st)
00303 {
00304 st.bind_int(index, val);
00305 }
00306 };
00307
00308 template<>
00309 class Statement::BindWrap<int64_t>
00310 {
00311 public:
00312 void bind(int index, int64_t val, Statement& st)
00313 {
00314 st.bind_int64(index, val);
00315 }
00316 };
00317
00318 template<>
00319 class Statement::BindWrap<std::string>
00320 {
00321 public:
00322 void bind(int index, std::string const& val, Statement& st)
00323 {
00324 st.bind_string(index, val);
00325 }
00326 };
00327
00328 template<>
00329 class Statement::BindWrap<double>
00330 {
00331 public:
00332 void bind(int index, double val, Statement& st)
00333 {
00334 st.bind_double(index, val);
00335 }
00336 };
00337
00338 }
00339
00340 #endif