Rework gnc_sql_append_guid_list_to_sql to eliminate GString and GList.

Which in turn forced rework of its users since the GString and GList were
passed-in parameters.
This commit is contained in:
John Ralls
2016-07-24 10:39:14 -07:00
parent cb464da599
commit 4b62deee42
15 changed files with 117 additions and 193 deletions

View File

@@ -625,7 +625,7 @@ GncSqlBackend::get_table_version(const std::string& table_name) const noexcept
*/
bool
GncSqlBackend::set_table_version (const std::string& table_name,
unsigned int version) noexcept
uint_t version) noexcept
{
g_return_val_if_fail (version > 0, false);
@@ -2069,33 +2069,23 @@ gnc_sql_execute_nonselect_sql (GncSqlBackend* be, const gchar* sql)
return be->execute_nonselect_statement (stmt);
}
guint
gnc_sql_append_guid_list_to_sql (GString* sql, GList* list, guint maxCount)
uint_t
gnc_sql_append_guids_to_sql (std::stringstream& sql, const InstanceVec& instances)
{
gchar guid_buf[GUID_ENCODING_LENGTH + 1];
gboolean first_guid = TRUE;
guint count;
char guid_buf[GUID_ENCODING_LENGTH + 1];
g_return_val_if_fail (sql != NULL, 0);
if (list == NULL) return 0;
for (count = 0; list != NULL && count < maxCount; list = list->next, count++)
for (auto inst : instances)
{
QofInstance* inst = QOF_INSTANCE (list->data);
(void)guid_to_string_buff (qof_instance_get_guid (inst), guid_buf);
if (!first_guid)
if (inst != *(instances.begin()))
{
(void)g_string_append (sql, ",");
sql << ",";
}
(void)g_string_append (sql, "'");
(void)g_string_append (sql, guid_buf);
(void)g_string_append (sql, "'");
first_guid = FALSE;
sql << "'" << guid_buf << "'";
}
return count;
return instances.size();
}
/* ================================================================= */
static PairVec

View File

@@ -50,13 +50,17 @@ extern "C"
#include <string>
#include <vector>
#include <memory>
#include <cstdint>
using uint_t = unsigned int;
struct GncSqlColumnInfo;
class GncSqlColumnTableEntry;
using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
using ColVec = std::vector<GncSqlColumnInfo>;
using StrVec = std::vector<std::string>;
using InstanceVec = std::vector<QofInstance*>;
using PairVec = std::vector<std::pair<std::string, std::string>>;
using VersionPair = std::pair<const std::string, unsigned int>;
using VersionVec = std::vector<VersionPair>;
@@ -98,7 +102,7 @@ public:
bool add_columns_to_table(const std::string& table_name,
const EntryVec& col_table) const noexcept;
unsigned int get_table_version(const std::string& table_name) const noexcept;
bool set_table_version (const std::string& table_name, unsigned int version) noexcept;
bool set_table_version (const std::string& table_name, uint_t version) noexcept;
QofBook* book() const noexcept { return m_book; }
bool pristine() const noexcept { return m_is_pristine_db; }
@@ -946,8 +950,8 @@ GncSqlStatementPtr gnc_sql_create_select_statement (GncSqlBackend* be,
* @param maxCount Max # of GUIDs to append
* @return Number of GUIDs appended
*/
guint gnc_sql_append_guid_list_to_sql (GString* str, GList* list,
guint maxCount);
uint_t gnc_sql_append_guids_to_sql (std::stringstream& sql,
const InstanceVec& instances);
/**
* Initializes DB table version information.

View File

@@ -240,22 +240,19 @@ GncSqlBillTermBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
GList* l_billterms_needing_parents = NULL;
for (auto row : *result)
{
auto pBillTerm =
load_single_billterm (be, row, &l_billterms_needing_parents);
if (pBillTerm != NULL)
list = g_list_append (list, pBillTerm);
if (pBillTerm != nullptr)
instances.push_back(QOF_INSTANCE(pBillTerm));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
/* While there are items on the list of billterms needing parents,
try to see if the parent has now been loaded. Theory says that if

View File

@@ -332,29 +332,23 @@ load_single_budget (GncSqlBackend* be, GncSqlRow& row)
void
GncSqlBudgetBackend::load_all (GncSqlBackend* be)
{
GList* list = NULL;
InstanceVec instances;
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, BUDGET_TABLE);
if (stmt != nullptr)
{
auto result = gnc_sql_execute_select_statement (be, stmt);
for (auto row : *result)
{
auto b = load_single_budget (be, row);
if (b != NULL)
{
list = g_list_prepend (list, b);
}
}
if (stmt == nullptr)
return;
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
auto result = gnc_sql_execute_select_statement (be, stmt);
for (auto row : *result)
{
auto b = load_single_budget (be, row);
if (b != nullptr)
instances.push_back(QOF_INSTANCE(b));
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */

View File

@@ -126,25 +126,19 @@ GncSqlCustomerBackend::load_all (GncSqlBackend* be)
{
g_return_if_fail (be != NULL);
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncCustomer* pCustomer = load_single_customer (be, row);
if (pCustomer != NULL)
{
list = g_list_append (list, pCustomer);
}
if (pCustomer != nullptr)
instances.push_back(QOF_INSTANCE(pCustomer));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */

View File

@@ -115,23 +115,17 @@ GncSqlEmployeeBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncEmployee* pEmployee = load_single_employee (be, row);
if (pEmployee != NULL)
{
list = g_list_append (list, pEmployee);
}
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
if (pEmployee != nullptr)
instances.push_back(QOF_INSTANCE(pEmployee));
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */

View File

@@ -196,22 +196,17 @@ GncSqlEntryBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncEntry* pEntry = load_single_entry (be, row);
if (pEntry != NULL)
{
list = g_list_append (list, pEntry);
}
if (pEntry != nullptr)
instances.push_back(QOF_INSTANCE(pEntry));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec(be, instances);
}
/* ================================================================= */

View File

@@ -135,22 +135,17 @@ GncSqlInvoiceBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncInvoice* pInvoice = load_single_invoice (be, row);
if (pInvoice != NULL)
{
list = g_list_append (list, pInvoice);
}
if (pInvoice != nullptr)
instances.push_back(QOF_INSTANCE(pInvoice));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */

View File

@@ -107,22 +107,17 @@ GncSqlJobBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncJob* pJob = load_single_job (be, row);
if (pJob != NULL)
{
list = g_list_append (list, pJob);
}
if (pJob != nullptr)
instances.push_back(QOF_INSTANCE(pJob));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */

View File

@@ -107,22 +107,17 @@ GncSqlOrderBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncOrder* pOrder = load_single_order (be, row);
if (pOrder != NULL)
{
list = g_list_append (list, pOrder);
}
if (pOrder != nullptr)
instances.push_back(QOF_INSTANCE(pOrder));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */

View File

@@ -127,7 +127,7 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
if (stmt == NULL) return;
auto result = gnc_sql_execute_select_statement (be, stmt);
SchedXactions* sxes;
GList* list = NULL;
InstanceVec instances;
sxes = gnc_book_get_schedxactions (be->book());
for (auto row : *result)
@@ -135,18 +135,15 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* be)
SchedXaction* sx;
sx = load_single_sx (be, row);
if (sx != NULL)
if (sx != nullptr)
{
gnc_sxes_add_sx (sxes, sx);
list = g_list_prepend (list, sx);
instances.push_back(QOF_INSTANCE(sx));
}
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}

View File

@@ -886,50 +886,39 @@ load_slot_for_list_item (GncSqlBackend* be, GncSqlRow& row,
}
void
gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list)
gnc_sql_slots_load_for_instancevec (GncSqlBackend* be, InstanceVec& instances)
{
QofCollection* coll;
GString* sql;
gboolean single_item;
std::stringstream sql;
g_return_if_fail (be != NULL);
// Ignore empty list
if (list == NULL) return;
if (instances.empty()) return;
coll = qof_instance_get_collection (QOF_INSTANCE (list->data));
coll = qof_instance_get_collection (instances[0]);
// Create the query for all slots for all items on the list
sql = g_string_sized_new (40 + (GUID_ENCODING_LENGTH + 3) * g_list_length (
list));
g_string_append_printf (sql, "SELECT * FROM %s WHERE %s ", TABLE_NAME,
obj_guid_col_table[0]->name());
if (g_list_length (list) != 1)
{
(void)g_string_append (sql, "IN (");
single_item = FALSE;
}
sql << "SELECT * FROM " << TABLE_NAME << " WHERE " <<
obj_guid_col_table[0]->name();
if (instances.size() != 1)
sql << " IN (";
else
{
(void)g_string_append (sql, "= ");
single_item = TRUE;
}
(void)gnc_sql_append_guid_list_to_sql (sql, list, G_MAXUINT);
if (!single_item)
{
(void)g_string_append (sql, ")");
}
sql << " = ";
gnc_sql_append_guids_to_sql (sql, instances);
if (instances.size() > 1)
sql << ")";
// Execute the query and load the slots
auto stmt = gnc_sql_create_statement_from_sql (be, sql->str);
auto stmt = be->create_statement_from_sql(sql.str());
if (stmt == nullptr)
{
PERR ("stmt == NULL, SQL = '%s'\n", sql->str);
(void)g_string_free (sql, TRUE);
PERR ("stmt == NULL, SQL = '%s'\n", sql.str().c_str());
return;
}
(void)g_string_free (sql, TRUE);
auto result = gnc_sql_execute_select_statement (be, stmt);
auto result = be->execute_select_statement (stmt);
for (auto row : *result)
load_slot_for_list_item (be, row, coll);
}

View File

@@ -64,14 +64,15 @@ gboolean gnc_sql_slots_delete (GncSqlBackend* be, const GncGUID* guid);
void gnc_sql_slots_load (GncSqlBackend* be, QofInstance* inst);
/**
* gnc_sql_slots_load_for_list - Loads slots for a list of objects from the db.
* Loading slots for a list of objects can be faster than loading for one object
* gnc_sql_slots_load_for_instancevec - Loads slots for a set of QofInstance*
* from the db. Loading slots for a set is faster than loading for one object
* at a time because fewer SQL queries are used.
*
* @param be SQL backend
* @param list List of objects
*/
void gnc_sql_slots_load_for_list (GncSqlBackend* be, GList* list);
void gnc_sql_slots_load_for_instancevec (GncSqlBackend* be,
InstanceVec& instances);
typedef QofInstance* (*BookLookupFn) (const GncGUID* guid,
const QofBook* book);

View File

@@ -258,40 +258,31 @@ load_single_split (GncSqlBackend* be, GncSqlRow& row)
}
static void
load_splits_for_tx_list (GncSqlBackend* be, GList* list)
load_splits_for_tx_list (GncSqlBackend* be, InstanceVec& transactions)
{
GString* sql;
g_return_if_fail (be != NULL);
if (list == NULL) return;
std::stringstream sql;
sql = g_string_sized_new (40 + (GUID_ENCODING_LENGTH + 3) * g_list_length (
list));
g_string_append_printf (sql, "SELECT * FROM %s WHERE %s IN (", SPLIT_TABLE,
tx_guid_col_table[0]->name());
(void)gnc_sql_append_guid_list_to_sql (sql, list, G_MAXUINT);
(void)g_string_append (sql, ")");
sql << "SELECT * FROM " << SPLIT_TABLE << " WHERE " <<
tx_guid_col_table[0]->name() << " IN (";
gnc_sql_append_guids_to_sql (sql, transactions);
sql << ")";
// Execute the query and load the splits
auto result = gnc_sql_execute_select_sql (be, sql->str);
GList* split_list = NULL;
auto stmt = be->create_statement_from_sql(sql.str());
auto result = be->execute_select_statement (stmt);
InstanceVec instances;
for (auto row : *result)
{
Split* s;
s = load_single_split (be, row);
if (s != NULL)
{
split_list = g_list_prepend (split_list, s);
}
Split* s = load_single_split (be, row);
if (s != nullptr)
instances.push_back(QOF_INSTANCE(s));
}
if (split_list != NULL)
{
gnc_sql_slots_load_for_list (be, split_list);
g_list_free (split_list);
}
(void)g_string_free (sql, TRUE);
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
static Transaction*
@@ -364,7 +355,6 @@ query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
if (result->begin() == result->end())
return;
GList* tx_list = NULL;
GList* node;
Transaction* tx;
#if LOAD_TRANSACTIONS_AS_NEEDED
@@ -383,30 +373,27 @@ query_transactions (GncSqlBackend* be, const GncSqlStatementPtr& stmt)
#endif
// Load the transactions
InstanceVec instances;
for (auto row : *result)
{
tx = load_single_tx (be, row);
if (tx != NULL)
if (tx != nullptr)
{
xaccTransScrubPostedDate (tx);
tx_list = g_list_prepend (tx_list, tx);
instances.push_back(QOF_INSTANCE(tx));
}
}
// Load all splits and slots for the transactions
if (tx_list != NULL)
if (!instances.empty())
{
gnc_sql_slots_load_for_list (be, tx_list);
load_splits_for_tx_list (be, tx_list);
gnc_sql_slots_load_for_instancevec (be, instances);
load_splits_for_tx_list (be, instances);
}
// Commit all of the transactions
for (node = tx_list; node != NULL; node = node->next)
{
Transaction* pTx = GNC_TRANSACTION (node->data);
xaccTransCommitEdit (pTx);
}
g_list_free (tx_list);
for (auto instance : instances)
xaccTransCommitEdit(GNC_TRANSACTION(instance));
#if LOAD_TRANSACTIONS_AS_NEEDED
// Update the account balances based on the loaded splits. If the end

View File

@@ -117,20 +117,17 @@ GncSqlVendorBackend::load_all (GncSqlBackend* be)
auto stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
auto result = gnc_sql_execute_select_statement (be, stmt);
GList* list = NULL;
InstanceVec instances;
for (auto row : *result)
{
GncVendor* pVendor = load_single_vendor (be, row);
if (pVendor != NULL)
list = g_list_append (list, pVendor);
if (pVendor != nullptr)
instances.push_back(QOF_INSTANCE(pVendor));
}
if (list != NULL)
{
gnc_sql_slots_load_for_list (be, list);
g_list_free (list);
}
if (!instances.empty())
gnc_sql_slots_load_for_instancevec (be, instances);
}
/* ================================================================= */