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:
@ -21,6 +21,14 @@ Database::Database(const std::string &username, const std::string &host, const s
|
|||||||
LOG << "opened MYSQL connection" << std::endl;
|
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) {
|
MYSQL_RES* Database::query(char const *query, bool get_result) {
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::lock_guard<boost::mutex> guard(m_handle_lock);
|
boost::lock_guard<boost::mutex> guard(m_handle_lock);
|
||||||
@ -67,6 +75,43 @@ MYSQL_RES* Database::query_stream(char const *query)
|
|||||||
return res;
|
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()
|
my_ulonglong Database::affected_rows()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -24,13 +24,15 @@ namespace fail {
|
|||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::mutex m_handle_lock;
|
boost::mutex m_handle_lock;
|
||||||
#endif
|
#endif
|
||||||
|
std::string m_insertquery;
|
||||||
|
std::vector<std::string> m_insertquery_values;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor that connects instantly to the database
|
* Constructor that connects instantly to the database
|
||||||
*/
|
*/
|
||||||
Database(const std::string &username, const std::string &host, const std::string &database);
|
Database(const std::string &username, const std::string &host, const std::string &database);
|
||||||
~Database() { mysql_close(handle); }
|
~Database();
|
||||||
|
|
||||||
struct Variant {
|
struct Variant {
|
||||||
int id;
|
int id;
|
||||||
@ -80,6 +82,12 @@ namespace fail {
|
|||||||
*/
|
*/
|
||||||
MYSQL_RES *query_stream(char const *query);
|
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
|
* How many rows were affected by the last query
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user