root/software/sqlite_poc/DBManager.h @ 7b498bcd
| 88cf406f | David Sorber | #include <cassert>
|
||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
| 143a60e7 | David Sorber | #include <sqlite3.h>
|
||
// Helper function prototypes
|
||||
void get_value(int64_t& val, int idx, sqlite3_stmt* stmt);
|
||||
void get_value(double& val, int idx, sqlite3_stmt* stmt);
|
||||
void get_value(std::string& val, int idx, sqlite3_stmt* stmt);
|
||||
| 258a530e | David Sorber | void get_value(bool& val, int idx, sqlite3_stmt* stmt);
|
||
| 88cf406f | David Sorber | |||
| 6e4119a4 | David Sorber | template<size_t I>
|
||
struct builder_impl
|
||||
| 88cf406f | David Sorber | {
|
||
| 143a60e7 | David Sorber | template<typename T>
|
||
static void set_values_helper(T& tup, sqlite3_stmt* stmt)
|
||||
| 88cf406f | David Sorber | {
|
||
| 143a60e7 | David Sorber | // Assign the "current" value
|
||
get_value(std::get<I - 1>(tup), I - 1, stmt);
|
||||
// Recurse to the next value in the tuple
|
||||
builder_impl<I - 1>::set_values_helper(tup, stmt);
|
||||
| 88cf406f | David Sorber | }
|
||
};
|
||||
| 143a60e7 | David Sorber | |||
template<>
|
||||
| 6e4119a4 | David Sorber | struct builder_impl<0>
|
||
| 88cf406f | David Sorber | {
|
||
| 143a60e7 | David Sorber | template<typename T>
|
||
static void set_values_helper(T& tup, sqlite3_stmt* stmt)
|
||||
{
|
||||
// Stop recursing
|
||||
return;
|
||||
| 6e4119a4 | David Sorber | }
|
||
| 88cf406f | David Sorber | };
|
||
| 6e4119a4 | David Sorber | |||
| 143a60e7 | David Sorber | template <typename... Ts>
|
||
void set_values(std::tuple<Ts...>& tup, sqlite3_stmt* stmt)
|
||||
| 6e4119a4 | David Sorber | {
|
||
| 143a60e7 | David Sorber | builder_impl<sizeof...(Ts)>::set_values_helper(tup, stmt);
|
||
| 88cf406f | David Sorber | }
|
||
| 6e4119a4 | David Sorber | |||
| 88cf406f | David Sorber | class DBManager
|
||
{
|
||||
public:
|
||||
| 143a60e7 | David Sorber | |||
| 88cf406f | David Sorber | // Constructor
|
||
DBManager(const std::string& db_path);
|
||||
| 143a60e7 | David Sorber | |||
| 88cf406f | David Sorber | // Destructor
|
||
~DBManager();
|
||||
| 143a60e7 | David Sorber | |||
// Execute query template function
|
||||
| 6e4119a4 | David Sorber | template<typename... T>
|
||
std::vector<std::tuple<T...>*>* execute_query(
|
||||
| 88cf406f | David Sorber | const std::string& sql_statement,
|
||
int& return_code)
|
||||
{
|
||||
sqlite3_stmt* sqlite_statement;
|
||||
| 143a60e7 | David Sorber | |||
| 88cf406f | David Sorber | // Prepare the sqlite statement
|
||
| 143a60e7 | David Sorber | return_code = sqlite3_prepare_v2(db, sql_statement.c_str(), -1,
|
||
| 88cf406f | David Sorber | &sqlite_statement, nullptr);
|
||
if (return_code != SQLITE_OK)
|
||||
{
|
||||
return nullptr;
|
||||
| 143a60e7 | David Sorber | }
|
||
auto output_vector = new std::vector<std::tuple<T...>*>();
|
||||
| 88cf406f | David Sorber | // Iterate until we've collected all the output
|
||
| 6e4119a4 | David Sorber | int step_return = 0;
|
||
while ((step_return = sqlite3_step(sqlite_statement)) != SQLITE_DONE)
|
||||
| 88cf406f | David Sorber | {
|
||
| 143a60e7 | David Sorber | // Create a new result row
|
||
| 6e4119a4 | David Sorber | auto result_row = new std::tuple<T...>();
|
||
| 143a60e7 | David Sorber | |||
// Now populate the result row using some neato variadic
|
||||
// template function magic NOTE: a small amount of black magic
|
||||
// is in use here; animal sacrifices not necessary
|
||||
set_values(*result_row, sqlite_statement);
|
||||
// Add the result row to our vector of output rows
|
||||
| 6e4119a4 | David Sorber | output_vector->push_back(result_row);
|
||
| 88cf406f | David Sorber | }
|
||
| 143a60e7 | David Sorber | |||
| 30f264c2 | David Sorber | sqlite3_finalize(sqlite_statement);
|
||
| 88cf406f | David Sorber | return output_vector;
|
||
}
|
||||
| 143a60e7 | David Sorber | |||
| 88cf406f | David Sorber | private:
|
||
| 143a60e7 | David Sorber | |||
| 88cf406f | David Sorber | sqlite3 *db;
|
||
};
|