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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
#pragma once
#include <sqlite3.h>
#include <string>
#include <iostream>
#include <list>
#include <exception>
#include <memory>
namespace glGrib
{
namespace SQLiteDetail
{
class _sqlite3
{
public:
~_sqlite3 ()
{
if (data != nullptr)
sqlite3_close (data);
data = nullptr;
}
sqlite3 * data = nullptr;
};
typedef std::shared_ptr<_sqlite3> sqlite3_ptr;
class _sqlite3_stmt
{
public:
~_sqlite3_stmt ()
{
if (data != nullptr)
sqlite3_finalize (data);
data = nullptr;
}
sqlite3_stmt * data = nullptr;
};
typedef std::shared_ptr<_sqlite3_stmt> sqlite3_stmt_ptr;
void ok (sqlite3_ptr db, int rc);
void iset (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, const long int * t);
void iset (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, const int * t);
void iset (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, const float * t);
void iset (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, const char * t);
void iset (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, const std::string * t);
void isetList (sqlite3_ptr, sqlite3_stmt_ptr, int);
template <typename T, typename... Types>
void isetList (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, const T & t, Types... args)
{
iset (db, req, rank, t);
isetList (db, req, rank + 1, args...);
}
void oget (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, int * t);
void oget (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, float * t);
void oget (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, char * t);
void oget (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, std::string * t);
void ogetList (sqlite3_ptr, sqlite3_stmt_ptr, int);
template <typename T, typename... Types>
void ogetList (sqlite3_ptr db, sqlite3_stmt_ptr req, int rank, T t, Types... args)
{
if (rank >= sqlite3_column_count (req->data))
throw std::runtime_error (std::string ("Column out of bounds"));
oget (db, req, rank, t);
ogetList (db, req, rank + 1, args...);
}
};
class SQLite
{
public:
typedef SQLiteDetail::sqlite3_ptr sqlite3_ptr;
typedef SQLiteDetail::sqlite3_stmt_ptr sqlite3_stmt_ptr;
explicit SQLite (const std::string & file)
{
db = std::make_shared<SQLiteDetail::_sqlite3>();
if (sqlite3_open (file.c_str (), &db->data) != SQLITE_OK)
throw std::runtime_error (std::string ("Cannot open database ") + file);
}
class stmt
{
public:
stmt ()
{
req = std::make_shared<SQLiteDetail::_sqlite3_stmt>();
}
~stmt ()
{
}
void reset ()
{
SQLiteDetail::ok (db, sqlite3_reset (req->data));
}
template <typename... Types>
void bindall (Types... args)
{
SQLiteDetail::isetList (db, req, 0, args...);
}
template <typename... Types>
void execute (Types... args)
{
bindall (args...);
sqlite3_step (req->data);
}
template <typename... Types>
bool fetchRow (Types... args)
{
if (sqlite3_step (req->data) == SQLITE_ROW)
{
SQLiteDetail::ogetList (db, req, 0, args...);
return true;
}
return false;
}
template <typename T>
void bind (int rank, const T * t)
{
if (rank >= sqlite3_bind_parameter_count (req->data))
throw std::runtime_error (std::string ("Column out of bounds"));
SQLiteDetail::iset (db, req, rank, t);
}
private:
sqlite3_stmt_ptr req;
sqlite3_ptr db;
friend class SQLite;
};
const stmt prepare (const std::string & sql)
{
stmt st;
st.db = db;
SQLiteDetail::ok (db, sqlite3_prepare_v2 (db->data, sql.c_str (), -1, &st.req->data, 0));
return st;
}
void execute (const std::string & sql)
{
SQLiteDetail::ok (db, sqlite3_exec (db->data, sql.c_str (), 0, 0, 0));
}
~SQLite ()
{
close ();
}
void close ()
{
}
private:
sqlite3_ptr db;
};
}
|