Skip to content

Instantly share code, notes, and snippets.

@multiplemonomials
Last active October 26, 2017 23:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save multiplemonomials/3b82de8bb114e85441b93f720c278d34 to your computer and use it in GitHub Desktop.
Save multiplemonomials/3b82de8bb114e85441b93f720c278d34 to your computer and use it in GitHub Desktop.
Wrapper around a Soci (SQL library for C++) statement that allows you to bind variables at execution time, and not before then. Helps you improve performance by making statements class variables.
//
// Created by Jamie on 5/12/2017.
//
#ifndef SOCI_LAZYSTATEMENT_H
#define SOCI_LAZYSTATEMENT_H
#include <soci/core/soci.h>
#include <soci/core/session.h>
/*
* With soci, sql statements have one HUGE problem:
* they must be bound to a variable at CONSTRUCTION time, and at EXECUTE time
* they suck in the value of that variable. So, even though the value isn't needed until later,
* it has to be available early on. So much for declaring statements as static and
* using them inside for loops.
* Bluh.
*
* Lazy statements allow you to just provide the type of the variable at
* construction time, and you apply the value at execute time.
*
* I've created 0-3 agument implementations, if you need more arguments, you can just copy-pase the lower
* argument versions and add another argument.
*/
namespace soci
{
template <typename ...Dummy> class lazy_statement; // base case, never instantiated!
// one argument version
template<typename param1_t>
class lazy_statement<param1_t>
{
param1_t param1;
statement _statement;
public:
lazy_statement(soci::session & session, std::string sql)
: param1(),
_statement((session.prepare << sql, use(param1)))
{
}
bool execute(param1_t value)
{
param1 = value;
return _statement.execute(true);
}
};
// two argument version
template<typename param1_t, typename param2_t>
class lazy_statement<param1_t, param2_t>
{
param1_t param1;
param2_t param2;
statement _statement;
public:
lazy_statement(soci::session & session, std::string sql)
: param1(),
param2(),
_statement((session.prepare << sql, use(param1), use(param2)))
{
}
bool execute(param1_t value1, param2_t value2)
{
param1 = value1;
param2 = value2;
return _statement.execute(true);
}
};
// three argument version
template<typename param1_t, typename param2_t, typename param3_t>
class lazy_statement<param1_t, param2_t, param3_t>
{
param1_t param1;
param2_t param2;
param3_t param3;
statement _statement;
public:
lazy_statement(soci::session & session, std::string sql)
: param1(),
param2(),
param3(),
_statement((session.prepare << sql, use(param1), use(param2), use(param3)))
{
}
bool execute(param1_t value1, param2_t value2, param3_t value3)
{
param1 = value1;
param2 = value2;
param3 = value3;
return _statement.execute(true);
}
};
}
#endif //SOCI_LAZYSTATEMENT_H
void Foo::addToDatabase(Bar& bar)
{
// this statement is only constructed once, which improves performance greatly vs constructing it each loop
// Or, you could put it in the class definition
soci::lazy_statement<std::string> barAddStatement(database, "INSERT INTO Baz(bar, barString) Values(:barid, :barString)");
for (std::string & barString)
{
barAddStatement.execute(bar.getId(), barString);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment