Commit b6a7492c authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen
Browse files

Allow arbitrary number of parameters to bind when executing a request

parent 17a66f61
......@@ -48,7 +48,7 @@ const std::vector<std::shared_ptr<IAlbumTrack>>& Album::tracks()
{
m_tracks = new std::vector<std::shared_ptr<IAlbumTrack>>;
const char* req = "SELECT * FROM AlbumTrack WHERE id_album = ?";
SqliteTools::fetchAll<AlbumTrack>( m_dbConnection, req, m_id, *m_tracks );
SqliteTools::fetchAll<AlbumTrack>( m_dbConnection, req, *m_tracks, m_id );
}
return *m_tracks;
}
......
......@@ -91,7 +91,7 @@ std::vector<std::shared_ptr<ILabel> > File::labels()
static const std::string req = "SELECT l.* FROM " + policy::LabelTable::Name + " l "
"LEFT JOIN LabelFileRelation lfr ON lfr.id_label = l.id_label "
"WHERE lfr.id_file = ?";
SqliteTools::fetchAll<Label>( m_dbConnection, req.c_str(), m_id, labels );
SqliteTools::fetchAll<Label>( m_dbConnection, req.c_str(), labels, m_id );
return labels;
}
......
......@@ -44,7 +44,7 @@ std::vector<FilePtr>& Label::files()
static const std::string req = "SELECT f.* FROM " + policy::FileTable::Name + " f "
"LEFT JOIN LabelFileRelation lfr ON lfr.id_file = f.id_file "
"WHERE lfr.id_label = ?";
SqliteTools::fetchAll<File>( m_dbConnection, req.c_str(), m_id, *m_files );
SqliteTools::fetchAll<File>( m_dbConnection, req.c_str(), *m_files, m_id );
}
return *m_files;
}
......
......@@ -8,12 +8,6 @@
#include <vector>
#include <iostream>
template <typename T>
struct TypeHelper
{
static const T Default = {};
};
// Have a base case for integral type only
// Use specialization to define other cases, and fail for the rest.
template <typename T>
......@@ -55,21 +49,14 @@ class SqliteTools
* @param results A reference to the result vector. All existing elements will
* be discarded.
*/
template <typename IMPL, typename INTF, typename KEYTYPE>
static bool fetchAll( sqlite3* dbConnection, const char* req, const KEYTYPE& foreignKey, std::vector<std::shared_ptr<INTF> >& results)
template <typename IMPL, typename INTF, typename... Args>
static bool fetchAll( sqlite3* dbConnection, const char* req, std::vector<std::shared_ptr<INTF> >& results, const Args&... args )
{
results.clear();
sqlite3_stmt* stmt;
int res = sqlite3_prepare_v2( dbConnection, req, -1, &stmt, NULL );
if ( res != SQLITE_OK )
{
std::cerr << "Failed to execute request: " << req << std::endl;
std::cerr << sqlite3_errmsg( dbConnection ) << std::endl;
sqlite3_stmt* stmt = executeRequest( dbConnection, req, args...);
if ( stmt == nullptr )
return false;
}
if ( foreignKey != TypeHelper<KEYTYPE>::Default )
Traits<KEYTYPE>::Bind( stmt, 1, foreignKey );
res = sqlite3_step( stmt );
int res = sqlite3_step( stmt );
while ( res == SQLITE_ROW )
{
auto row = IMPL::load( dbConnection, stmt );
......@@ -80,33 +67,47 @@ class SqliteTools
return true;
}
template <typename IMPL, typename INTF>
static bool fetchAll( sqlite3* dbConnection, const char* req, std::vector<std::shared_ptr<INTF> >& results)
template <typename T, typename... Args>
static std::shared_ptr<T> fetchOne( sqlite3* dbConnection, const char* req, const Args&... args )
{
std::shared_ptr<T> result;
sqlite3_stmt *stmt = executeRequest( dbConnection, req, args... );
if ( stmt == nullptr )
return false;
if ( sqlite3_step( stmt ) != SQLITE_ROW )
return result;
result = T::load( dbConnection, stmt );
sqlite3_finalize( stmt );
return result;
}
template <typename... Args>
static sqlite3_stmt* executeRequest( sqlite3* dbConnection, const char* req, const Args&... args )
{
return fetchAll<IMPL, INTF>( dbConnection, req, 0, results );
return _executeRequest<1>( dbConnection, req, args... );
}
template <typename T, typename KEYTYPE>
static std::shared_ptr<T> fetchOne( sqlite3* dbConnection, const char* req, const KEYTYPE& toBind )
private:
template <unsigned int>
static sqlite3_stmt* _executeRequest( sqlite3* dbConnection, const char* req )
{
std::shared_ptr<T> result;
sqlite3_stmt *stmt;
sqlite3_stmt* stmt = nullptr;
int res = sqlite3_prepare_v2( dbConnection, req, -1, &stmt, NULL );
if ( res != SQLITE_OK )
{
std::cerr << "Failed to execute request: " << req << std::endl;
std::cerr << sqlite3_errmsg( dbConnection ) << std::endl;
return result;
}
Traits<KEYTYPE>::Bind( stmt, 1, toBind );
if ( sqlite3_step( stmt ) != SQLITE_ROW )
return result;
result = T::load( dbConnection, stmt );
sqlite3_finalize( stmt );
return result;
return stmt;
}
template <unsigned int COLIDX, typename T, typename... Args>
static sqlite3_stmt* _executeRequest( sqlite3* dbConnection, const char* req, const T& arg, const Args&... args )
{
sqlite3_stmt* stmt = _executeRequest<COLIDX + 1>( dbConnection, req, args... );
Traits<T>::Bind( stmt, COLIDX, arg );
return stmt;
}
};
#endif // SQLITETOOLS_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment