I have managed to make a library to help me making request to SqlLite library, specially those related with BLOB files.
The problem came because I feel that the implementation can be improved, but I do not have enought knoledge to achieve it. Any help with this couple of issues:
Some functions can be called using a SQL statement as a c-pure string or a std::string. Both of them finally calls the same function final implementation. The problem cames by an unambiguos call to template function if I try to remove the '_' for function declaration and calling (please see source code). I understand this is a minor isssue, but I wonder if is there any way to achieve it.
I have try to use the same code for requests using files to load a BLOB in DB, and for requests not using BLOBS. The diference is that first ones uses files streams as parameters, and second ones do not have any stream parameter. SqlLite force to call an specific function to executute the sql statement, so I need to use a "if consexpr..." conditional clause to separate the case with 0 arguments from the case the 1 or more stream arguments.
Source code is presented ahead:
#include <string>
#include <sstream>
#include <utility>
class sqlite3 {};
class sqlite3_stmt {};
void sqlite3_step(sqlite3_stmt*) {}
sqlite3* db;
//Auxiliary BLOB functions
template<typename T>
bool sqlite3_blob(sqlite3_stmt*, const T& data, int col);
template<>
bool sqlite3_blob<std::ostringstream>(sqlite3_stmt* statement, const std::ostringstream& data, int col)
{
//std::string buffer{ data.str() };
return true;
}
//sqlite3 automatization request
template<typename... Args, std::size_t... Is>
constexpr bool sqlite3_request_(sqlite3* db, const char* sql, Args&&... args, std::index_sequence<Is...>)
{
sqlite3_stmt* statement{};
(sqlite3_blob(statement, std::forward<Args>(args), Is + 1), ...);
if constexpr (sizeof...(Args) == 0) sqlite3_step(statement);//Horrible conditional statement. Is there any way of getting rid of it???
return true;
}
template<typename... Args>
constexpr bool sqlite3_request(sqlite3* db, const char* sql, Args&&... args)
{
return sqlite3_request_<Args...>(db, sql, std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args)>{});//Need to change the name because calling function is not able to unambiguosly called the right on
}
//For std::string arguments:
template<typename... Args>
constexpr bool sqlite3_request(sqlite3* db, const std::string& sql, Args&&... args)//args contain loading data for blobs, if any
{
return sqlite3_request_<Args...>(db, sql.c_str(), std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args)>{});// Possible to improve? Unambiguos calling to function if '_' eliminated in function calling and declaration
}
int main()
{
const std::ostringstream data;
std::string sql = "INSERT INTO scenarios(file) VALUES(?);";//file is a BLOB field
sqlite3_request(db, sql, data);
}
Please note the I have clean and mock all SqlLite functions. This is not a question about SqlLite but about improving templates style.
Also, here it is a coliru link http://coliru.stacked-crooked.com/a/ec8e8bf65f451b20
to stated source code.