Project

General

Profile

Download (2.57 KB) Statistics
| Branch: | Tag: | Revision:
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
88cf406f David Sorber
return output_vector;
}
143a60e7 David Sorber
88cf406f David Sorber
private:
143a60e7 David Sorber
88cf406f David Sorber
sqlite3 *db;
};