db: handle multi-row INSERTs

Several database implementations, including, e.g., MySQL and PostgreSQL,
allow multiple rows to be INSERTed at once.  At least for MySQL this
improves INSERT speed significantly.

Change-Id: Ic223f7915053f30b0cb00c567310f3e780c9fa59
This commit is contained in:
Horst Schirmeier
2013-07-16 12:13:50 +02:00
parent cbbd0ec764
commit 470d455e34
2 changed files with 54 additions and 1 deletions

View File

@ -21,6 +21,14 @@ Database::Database(const std::string &username, const std::string &host, const s
LOG << "opened MYSQL connection" << std::endl;
}
Database::~Database()
{
// flush cached INSERTs if available
insert_multiple();
mysql_close(handle);
}
MYSQL_RES* Database::query(char const *query, bool get_result) {
#ifndef __puma
boost::lock_guard<boost::mutex> guard(m_handle_lock);
@ -67,6 +75,43 @@ MYSQL_RES* Database::query_stream(char const *query)
return res;
}
bool Database::insert_multiple(char const *insertquery, char const *values)
{
// different insertquery, but still cached values?
if (insertquery && m_insertquery != insertquery && m_insertquery_values.size() > 0) {
// flush cache
insert_multiple();
} else if (!insertquery && m_insertquery.size() == 0) {
// don't know how to INSERT, no insertquery available!
return false;
}
if (insertquery) {
m_insertquery = insertquery;
}
if (values) {
m_insertquery_values.push_back(values);
}
if ((!values && m_insertquery_values.size() > 0) || m_insertquery_values.size() >= 32) {
std::stringstream sql;
sql << m_insertquery;
bool first = true;
for (std::vector<std::string>::const_iterator it = m_insertquery_values.begin();
it != m_insertquery_values.end(); ++it) {
if (!first) {
sql << ",";
}
first = false;
sql << *it;
}
m_insertquery_values.clear();
return query(sql.str().c_str());
}
return true;
}
my_ulonglong Database::affected_rows()
{

View File

@ -24,13 +24,15 @@ namespace fail {
#ifndef __puma
boost::mutex m_handle_lock;
#endif
std::string m_insertquery;
std::vector<std::string> m_insertquery_values;
public:
/**
* Constructor that connects instantly to the database
*/
Database(const std::string &username, const std::string &host, const std::string &database);
~Database() { mysql_close(handle); }
~Database();
struct Variant {
int id;
@ -80,6 +82,12 @@ namespace fail {
*/
MYSQL_RES *query_stream(char const *query);
/**
* Caches multiple value tuples to combine into multi-value INSERTs.
* Call without parameters to flush the cache.
*/
bool insert_multiple(char const *insertquery = 0, char const *values = 0);
/**
* How many rows were affected by the last query
*/