gnucash master: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sat Apr 14 19:46:09 EDT 2018


Updated	 via  https://github.com/Gnucash/gnucash/commit/4a4e7a9a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5e807a0e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8a3889d0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/044583d7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/40a266fc (commit)
	 via  https://github.com/Gnucash/gnucash/commit/51851965 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4ba77f7b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a04fd573 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4e3bf5a5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/f680823d (commit)
	 via  https://github.com/Gnucash/gnucash/commit/01420adb (commit)
	 via  https://github.com/Gnucash/gnucash/commit/e90a662a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b7396611 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9b643574 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/e4d0ad9d (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a39ba167 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/dcfc1280 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6093e597 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8db11465 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1ee2c083 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b02e4a7c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4acc5a23 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/2d9021ca (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d273a330 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/73ffcaa8 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3a44b368 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3a46088c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a8c17c20 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d567ee10 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/7321c995 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/10f8f6a7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/e2535abb (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c9fd6832 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/805094d5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/dd28f4ed (commit)
	 via  https://github.com/Gnucash/gnucash/commit/48db9939 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9094f6e5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/61141051 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/e81b2ccc (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4a97269e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/85cc574d (commit)
	 via  https://github.com/Gnucash/gnucash/commit/16ba1e39 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b5ac8591 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/868489b1 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b1915a0b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cdeee960 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6810c2a6 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9319858b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/655803a1 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c3f528b8 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c05aeb85 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/192a3c3d (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8bfbc779 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/facd26c0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8975158a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5af11ced (commit)
	 via  https://github.com/Gnucash/gnucash/commit/aea33ca5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/34c46444 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a909f802 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/434dd952 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0a3f2dd3 (commit)
	from  https://github.com/Gnucash/gnucash/commit/ba3bf37d (commit)



commit 4a4e7a9a7b543f51dbfd37e726bf72c12c4fee4c
Merge: ba3bf37 5e807a0
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Apr 14 16:45:52 2018 -0700

    Merge branch 'maint'


commit 5e807a0e18f7ac90158f6ee4dac0920545fde7cc
Merge: 8a3889d 868489b
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Apr 14 16:39:38 2018 -0700

    Merge branch 'maint' into unstable


commit 8a3889d0883a43bbee7f1517aedb18b531596a59
Merge: 40a266f 044583d
Author: John Ralls <john at localhost.localdomain>
Date:   Sat Apr 14 16:31:16 2018 -0700

    Merge Chirs Lam's Bug 795064 - Enable subtotal-only if... into unstable.


commit 044583d72f407f17f0949c377a763ee2fa96d47e
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Wed Apr 11 08:31:24 2018 +0800

    Bug 795064 - Enable subtotal-only if either sortkeys are dates
    
    This will allow 'show subtotals only' if sortkeys are date-types. This
    allows, for example, prime-sortkey=date, yearly. sec-sortkey=date,
    monthly.

diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index cb2dbc3..6dbb894 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -630,7 +630,9 @@ tags within description, notes or memo. ")
         (gnc-option-db-set-option-selectable-by-name
          options pagename-sorting optname-show-subtotals-only
          (or (and prime-sortkey-subtotal-enabled prime-sortkey-subtotal-true)
-             (and sec-sortkey-subtotal-enabled sec-sortkey-subtotal-true)))
+             (and sec-sortkey-subtotal-enabled sec-sortkey-subtotal-true)
+             prime-date-sortingtype-enabled
+             sec-date-sortingtype-enabled))
 
         (gnc-option-db-set-option-selectable-by-name
          options pagename-sorting optname-show-informal-headers

commit 40a266fc62921e95420cad6bb7c6246bca8e3c97
Author: John Ralls <john at localhost.localdomain>
Date:   Sat Apr 14 16:03:04 2018 -0700

    One more catch-by-value error.

diff --git a/libgnucash/engine/test/gtest-gnc-numeric.cpp b/libgnucash/engine/test/gtest-gnc-numeric.cpp
index 8326071..f6ba3f1 100644
--- a/libgnucash/engine/test/gtest-gnc-numeric.cpp
+++ b/libgnucash/engine/test/gtest-gnc-numeric.cpp
@@ -223,7 +223,7 @@ TEST(gncnumeric_stream, output_stream)
         else
             EXPECT_EQ("123\xe2\x80\xaf""456", output.str());
     }
-    catch (std::runtime_error)
+    catch (std::runtime_error& err)
     {
         output.imbue(std::locale("fr_FR"));
         output.str("");

commit 518519654cb6c41bf3bd0ad8913e5357d8314b8d
Merge: 4ba77f7 0a3f2dd
Author: John Ralls <john at localhost.localdomain>
Date:   Sat Apr 14 15:52:26 2018 -0700

    Merge Bill Nottingham's 'gmock-trial' into unstable.


commit 4ba77f7b09effb6c3d9aa749ccc3bdcda6e9df39
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Apr 14 13:11:23 2018 -0700

    Remove another gnc_pop_locale().

diff --git a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp
index 3a4e495..a686fa4 100644
--- a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp
+++ b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp
@@ -147,7 +147,6 @@ GncDbiSqlResult::IteratorImpl::get_string_at_col(const char* col) const
     auto strval = dbi_result_get_string(m_inst->m_dbi_result, col);
     if (strval == nullptr)
     {
-        gnc_pop_locale (LC_NUMERIC);
         throw (std::invalid_argument{"Column empty."});
     }
     auto retval =  std::string{strval};

commit a04fd573efca43e432085fc92aecf9f2067063d5
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Apr 14 12:33:00 2018 -0700

    Bug 792105 - Startup takes several minutes
    
    set/get_locale are apparently very expensive on Mingw64, and setting
    the C locale for extracting a string is unnecessary.
    
    Unfortunately the released version of libdbi still uses strtod so
    setting the C locale *is* still necessary for retrieving floats
    and doubles and for passing queries.
    
    Thanks to Mkubat for the diagnosis.

diff --git a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp
index 61f1664..3a4e495 100644
--- a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp
+++ b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp
@@ -144,7 +144,6 @@ GncDbiSqlResult::IteratorImpl::get_string_at_col(const char* col) const
     auto attrs = dbi_result_get_field_attribs (m_inst->m_dbi_result, col);
     if(type != DBI_TYPE_STRING)
         throw (std::invalid_argument{"Requested string from non-string column."});
-    gnc_push_locale (LC_NUMERIC, "C");
     auto strval = dbi_result_get_string(m_inst->m_dbi_result, col);
     if (strval == nullptr)
     {
@@ -152,7 +151,6 @@ GncDbiSqlResult::IteratorImpl::get_string_at_col(const char* col) const
         throw (std::invalid_argument{"Column empty."});
     }
     auto retval =  std::string{strval};
-    gnc_pop_locale (LC_NUMERIC);
     return retval;
 }
 time64

commit 4e3bf5a5cbaebe40ed58e16a4c574f49cc87c747
Author: Geert Janssens <janssens-geert at telenet.be>
Date:   Mon Mar 21 11:30:44 2016 +0100

    Bug 118391 - Long currency names untranslated
    
    Fix for Win32

diff --git a/gnucash/gnucash-bin.c b/gnucash/gnucash-bin.c
index 248ffaa..51525ec 100644
--- a/gnucash/gnucash-bin.c
+++ b/gnucash/gnucash-bin.c
@@ -775,7 +775,9 @@ main(int argc, char ** argv)
     {
         gchar *localedir = gnc_path_get_localedir();
         bindtextdomain(GETTEXT_PACKAGE, localedir);
-        textdomain(GETTEXT_PACKAGE);
+	bindtextdomain("iso_4217", localedir); // For win32 to find currency name translations
+	bind_textdomain_codeset("iso_4217", "UTF-8");
+	textdomain(GETTEXT_PACKAGE);
         bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
         g_free(localedir);
     }

commit f680823dbfff5cc90c98139c755c727f2f19d4cb
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Apr 13 14:02:57 2018 -0700

    Bug 795039 - Crash on startup using Technicolor Style sheet in report
    
    The mingw-w64 toolchain bizarrely substitutes scm_to_locale_string()
    for scm_to_utf8_string(). This results in latin1 (yeah, "locale" is
    a lie) instead of utf8 which causes an assertion in
    g_utf8_collate_key().
    
    Perhaps equally bizarre, the compiler doesn't make the substitution
    with scm_to_utf8_stringn(), so use that instead.

diff --git a/libgnucash/app-utils/gnc-ui-util.c b/libgnucash/app-utils/gnc-ui-util.c
index c4e3a86..5fa6430 100644
--- a/libgnucash/app-utils/gnc-ui-util.c
+++ b/libgnucash/app-utils/gnc-ui-util.c
@@ -590,13 +590,13 @@ gnc_ui_account_get_tax_info_string (const Account *account)
             {
                 gchar *form = NULL;
 
-                /* Note: using scm_to_utf8_string directly here instead
+                /* Note: using scm_to_utf8_stringn directly here instead
                    of our wrapper gnc_scm_to_utf8_string. 'form' should
                    be freed with 'free' instead of 'g_free'. This will
                    be taken care of automatically during scm_dynwind_end,
                    because we inform guile of this memory allocation via
                    scm_dynwind_free a little further. */
-                form = scm_to_utf8_string (form_scm);
+                form = scm_to_utf8_stringn (form_scm, NULL);
                 if (!form)
                 {
                     if (tax_related)
diff --git a/libgnucash/core-utils/gnc-guile-utils.c b/libgnucash/core-utils/gnc-guile-utils.c
index e86fe9f..99e46d7 100644
--- a/libgnucash/core-utils/gnc-guile-utils.c
+++ b/libgnucash/core-utils/gnc-guile-utils.c
@@ -43,7 +43,7 @@ gchar *gnc_scm_to_utf8_string(SCM scm_string)
         gchar* s;
         char * str;
 
-        str = scm_to_utf8_string(scm_string);
+        str = scm_to_utf8_stringn(scm_string, NULL);
         s = g_strdup(str);
         free (str);
         return s;

commit 01420adb9989f49a0413b4a9bbf34494623a5443
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Mar 24 16:30:34 2018 -0700

    Bug 772776 - VERY large queries (over 11000 fields in IN clause) slow...
    
    down GnuCash
    
    Replace with joins or subqueries. Affords a 20% speedup on Windows.

diff --git a/libgnucash/backend/sql/gnc-slots-sql.cpp b/libgnucash/backend/sql/gnc-slots-sql.cpp
index ab2d6e4..ca719f3 100644
--- a/libgnucash/backend/sql/gnc-slots-sql.cpp
+++ b/libgnucash/backend/sql/gnc-slots-sql.cpp
@@ -821,44 +821,6 @@ load_slot_for_list_item (GncSqlBackend* sql_be, GncSqlRow& row,
 
 }
 
-void
-gnc_sql_slots_load_for_instancevec (GncSqlBackend* sql_be, InstanceVec& instances)
-{
-    QofCollection* coll;
-    std::stringstream sql;
-
-    g_return_if_fail (sql_be != NULL);
-
-    // Ignore empty list
-    if (instances.empty()) return;
-
-    coll = qof_instance_get_collection (instances[0]);
-
-    // Create the query for all slots for all items on the list
-
-    sql << "SELECT * FROM " << TABLE_NAME << " WHERE " <<
-                            obj_guid_col_table[0]->name();
-    if (instances.size() != 1)
-        sql << " IN (";
-    else
-        sql << " = ";
-
-    gnc_sql_append_guids_to_sql (sql, instances);
-    if (instances.size() > 1)
-        sql << ")";
-
-    // Execute the query and load the slots
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
-    if (stmt == nullptr)
-    {
-        PERR ("stmt == NULL, SQL = '%s'\n", sql.str().c_str());
-        return;
-    }
-    auto result = sql_be->execute_select_statement (stmt);
-    for (auto row : *result)
-        load_slot_for_list_item (sql_be, row, coll);
-}
-
 static void
 load_slot_for_book_object (GncSqlBackend* sql_be, GncSqlRow& row,
                            BookLookupFn lookup_fn)
diff --git a/libgnucash/backend/sql/gnc-slots-sql.h b/libgnucash/backend/sql/gnc-slots-sql.h
index 0cdf3a6..b7b9891 100644
--- a/libgnucash/backend/sql/gnc-slots-sql.h
+++ b/libgnucash/backend/sql/gnc-slots-sql.h
@@ -76,17 +76,6 @@ gboolean gnc_sql_slots_delete (GncSqlBackend* sql_be, const GncGUID* guid);
  */
 void gnc_sql_slots_load (GncSqlBackend* sql_be, QofInstance* inst);
 
-/**
- * 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 sql_be SQL backend
- * @param list List of objects
- */
-void gnc_sql_slots_load_for_instancevec (GncSqlBackend* sql_be,
-                                         InstanceVec& instances);
-
 typedef QofInstance* (*BookLookupFn) (const GncGUID* guid,
                                       const QofBook* book);
 
diff --git a/libgnucash/backend/sql/gnc-sql-backend.cpp b/libgnucash/backend/sql/gnc-sql-backend.cpp
index 1a8af92..536b76b 100644
--- a/libgnucash/backend/sql/gnc-sql-backend.cpp
+++ b/libgnucash/backend/sql/gnc-sql-backend.cpp
@@ -510,19 +510,19 @@ GncSqlBackend::sync(QofBook* book)
 void
 GncSqlBackend::begin(QofInstance* inst)
 {
-    g_return_if_fail (inst != NULL);
+    //g_return_if_fail (inst != NULL);
 
-    ENTER (" ");
-    LEAVE ("");
+    //ENTER (" ");
+    //LEAVE ("");
 }
 
 void
 GncSqlBackend::rollback(QofInstance* inst)
 {
-    g_return_if_fail (inst != NULL);
+    //g_return_if_fail (inst != NULL);
 
-    ENTER (" ");
-    LEAVE ("");
+    //ENTER (" ");
+    //LEAVE ("");
 }
 
 void
diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp
index 5d94e69..ca8cb97 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp
@@ -247,52 +247,36 @@ load_single_split (GncSqlBackend* sql_be, GncSqlRow& row)
     }
     return pSplit;
 }
-
-static void
-load_splits_for_sql_subquery (GncSqlBackend* sql_be, std::string subquery)
-{
-    g_return_if_fail (sql_be != NULL);
-    const std::string sskey(tx_guid_col_table[0]->name());
-    std::string sql("SELECT * FROM " SPLIT_TABLE " WHERE ");
-    sql += sskey + " IN (" + subquery + ")";
-    auto stmt = sql_be->create_statement_from_sql(sql);
-    auto result = sql_be->execute_select_statement(stmt);
-    for (auto row : *result)
-        load_single_split (sql_be, row);
-    const std::string spkey(split_col_table[0]->name());
-    std::string sub_subquery("SELECT DISTINCT ");
-    sub_subquery += spkey + " FROM " SPLIT_TABLE " WHERE " + sskey +
-        " IN (" + subquery + ")";
-    gnc_sql_slots_load_for_sql_subquery(sql_be, sub_subquery,
-                                        (BookLookupFn)xaccSplitLookup);
-}
-
 static void
-load_splits_for_tx_list (GncSqlBackend* sql_be, InstanceVec& transactions)
+load_splits_for_transactions (GncSqlBackend* sql_be, std::string selector)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
+    const std::string spkey(split_col_table[0]->name());
+    const std::string sskey(tx_guid_col_table[0]->name());
+    const std::string tpkey(tx_col_table[0]->name());
 
-    sql << "SELECT * FROM " << SPLIT_TABLE << " WHERE " <<
-        tx_guid_col_table[0]->name() << " IN (";
-    gnc_sql_append_guids_to_sql (sql, transactions);
-    sql << ")";
+    std::string sql("SELECT ");
+    if (selector.empty())
+    {
+	sql += SPLIT_TABLE ".* FROM " SPLIT_TABLE " INNER JOIN "
+	    TRANSACTION_TABLE " WHERE " SPLIT_TABLE "." + sskey + " = "
+	    TRANSACTION_TABLE "." + tpkey;
+	selector = "(SELECT DISTINCT " + tpkey + " FROM " TRANSACTION_TABLE ")";
+    }
+    else
+	sql += " * FROM " SPLIT_TABLE " WHERE " + sskey + " IN " + selector;
 
     // Execute the query and load the splits
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement (stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         Split* s = load_single_split (sql_be, row);
-        if (s != nullptr)
-            instances.push_back(QOF_INSTANCE(s));
-    }
-
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    sql = "SELECT DISTINCT ";
+    sql += spkey + " FROM " SPLIT_TABLE " WHERE " + sskey + " IN " + selector;
+    gnc_sql_slots_load_for_sql_subquery(sql_be, sql,
+					(BookLookupFn)xaccSplitLookup);
 }
 
 static  Transaction*
@@ -356,19 +340,30 @@ typedef struct
  * @param stmt SQL statement
  */
 static void
-query_transactions (GncSqlBackend* sql_be, const GncSqlStatementPtr& stmt)
+query_transactions (GncSqlBackend* sql_be, std::string selector)
 {
     g_return_if_fail (sql_be != NULL);
-    g_return_if_fail (stmt != NULL);
 
+    const std::string tpkey(tx_col_table[0]->name());
+    std::string sql("SELECT * FROM " TRANSACTION_TABLE);
+
+    if (!selector.empty() && selector[0] == '(')
+	sql += " WHERE " + tpkey + " IN " + selector;
+    else if (!selector.empty()) // plain condition
+	sql += " WHERE " + selector;
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
     if (result->begin() == result->end())
+    {
+	PINFO("Query %s returned no results", sql.c_str());
         return;
-
+    }
+    
     Transaction* tx;
 
     // Load the transactions
     InstanceVec instances;
+    instances.reserve(result->size());
     for (auto row : *result)
     {
         tx = load_single_tx (sql_be, row);
@@ -382,8 +377,15 @@ query_transactions (GncSqlBackend* sql_be, const GncSqlStatementPtr& stmt)
     // Load all splits and slots for the transactions
     if (!instances.empty())
     {
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
-        load_splits_for_tx_list (sql_be, instances);
+	const std::string tpkey(tx_col_table[0]->name());
+	if (selector.empty())
+	{
+	    selector = "(SELECT DISTINCT ";
+	    selector += tpkey + " FROM " TRANSACTION_TABLE +")";
+	}
+        load_splits_for_transactions (sql_be, selector);
+        gnc_sql_slots_load_for_sql_subquery (sql_be, selector,
+					     (BookLookupFn)xaccTransLookup);
     }
 
     // Commit all of the transactions
@@ -691,16 +693,15 @@ void gnc_sql_transaction_load_tx_for_account (GncSqlBackend* sql_be,
     g_return_if_fail (account != NULL);
 
     guid = qof_instance_get_guid (QOF_INSTANCE (account));
-    (void)guid_to_string_buff (guid, guid_buf);
-    query_sql = g_strdup_printf (
-                    "SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND s.account_guid ='%s'",
-                    TRANSACTION_TABLE, SPLIT_TABLE, guid_buf);
-    auto stmt = sql_be->create_statement_from_sql(query_sql);
-    g_free (query_sql);
-    if (stmt != nullptr)
-    {
-        query_transactions (sql_be, stmt);
-    }
+
+    const std::string tpkey(tx_col_table[0]->name());    //guid
+    const std::string spkey(split_col_table[0]->name()); //guid
+    const std::string stkey(split_col_table[1]->name()); //txn_guid
+    const std::string sakey(split_col_table[2]->name()); //account_guid
+    std::string sql("(SELECT DISTINCT ");
+    sql += stkey + " FROM " SPLIT_TABLE " WHERE " + sakey + " = '";
+    sql += gnc::GUID(*guid).to_string() + "')";
+    query_transactions (sql_be, sql);
 }
 
 /**
@@ -713,44 +714,7 @@ void
 GncSqlTransBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
-
-    std::string query_sql("SELECT * FROM " TRANSACTION_TABLE);
-    auto stmt = sql_be->create_statement_from_sql(query_sql);
-
-    if (stmt != nullptr)
-    {
-        auto result = sql_be->execute_select_statement(stmt);
-        if (result->begin() == result->end())
-            return;
-
-        Transaction* tx;
-
-        // Load the transactions
-        InstanceVec instances;
-        instances.reserve(result->size());
-        for (auto row : *result)
-        {
-            tx = load_single_tx (sql_be, row);
-            if (tx != nullptr)
-            {
-                xaccTransScrubPostedDate (tx);
-                instances.push_back(QOF_INSTANCE(tx));
-            }
-        }
-        if (instances.empty())
-            return;
-        const std::string tpkey(tx_col_table[0]->name());
-        std::string subquery("SELECT DISTINCT ");
-        subquery += tpkey + " FROM " TRANSACTION_TABLE;
-        gnc_sql_slots_load_for_sql_subquery (sql_be, subquery,
-                                             (BookLookupFn)xaccTransLookup);
-        load_splits_for_sql_subquery (sql_be, subquery);
-
-        // Commit all of the transactions
-        for (auto instance : instances)
-            xaccTransCommitEdit(GNC_TRANSACTION(instance));
-
-    }
+    query_transactions (sql_be, "");
 }
 
 static void
@@ -995,12 +959,11 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* sql_be,
             tx = xaccTransLookup (&guid, sql_be->book());
 
         // If the transaction is not found, try loading it
+	std::string tpkey(tx_col_table[0]->name());
         if (tx == nullptr)
         {
-            auto buf = std::string{"SELECT * FROM "} + TRANSACTION_TABLE +
-                                       " WHERE guid='" + val + "'";
-            auto stmt = sql_be->create_statement_from_sql (buf);
-            query_transactions ((GncSqlBackend*)sql_be, stmt);
+	    std::string sql = tpkey + " = '" + val + "'";
+            query_transactions ((GncSqlBackend*)sql_be, sql);
             tx = xaccTransLookup (&guid, sql_be->book());
         }
 
diff --git a/libgnucash/engine/TransLog.c b/libgnucash/engine/TransLog.c
index 7584bc0..b88d982 100644
--- a/libgnucash/engine/TransLog.c
+++ b/libgnucash/engine/TransLog.c
@@ -230,7 +230,7 @@ xaccTransWriteLog (Transaction *trans, char flag)
 
     if (!gen_logs)
     {
-	 PINFO ("Attempt to write disabled transaction log");
+         PINFO ("Attempt to write disabled transaction log");
 	 return;
     }
     if (!trans_log) return;

commit e90a662a20299d5cbd649cc855cb491a3d9dc228
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Mar 26 16:59:49 2018 -0700

    Use subquery instead of instancevec GncSqlTransBackend::load_all.

diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp
index 6013aaa..5d94e69 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp
@@ -249,6 +249,25 @@ load_single_split (GncSqlBackend* sql_be, GncSqlRow& row)
 }
 
 static void
+load_splits_for_sql_subquery (GncSqlBackend* sql_be, std::string subquery)
+{
+    g_return_if_fail (sql_be != NULL);
+    const std::string sskey(tx_guid_col_table[0]->name());
+    std::string sql("SELECT * FROM " SPLIT_TABLE " WHERE ");
+    sql += sskey + " IN (" + subquery + ")";
+    auto stmt = sql_be->create_statement_from_sql(sql);
+    auto result = sql_be->execute_select_statement(stmt);
+    for (auto row : *result)
+        load_single_split (sql_be, row);
+    const std::string spkey(split_col_table[0]->name());
+    std::string sub_subquery("SELECT DISTINCT ");
+    sub_subquery += spkey + " FROM " SPLIT_TABLE " WHERE " + sskey +
+        " IN (" + subquery + ")";
+    gnc_sql_slots_load_for_sql_subquery(sql_be, sub_subquery,
+                                        (BookLookupFn)xaccSplitLookup);
+}
+
+static void
 load_splits_for_tx_list (GncSqlBackend* sql_be, InstanceVec& transactions)
 {
     g_return_if_fail (sql_be != NULL);
@@ -695,12 +714,42 @@ GncSqlTransBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    auto query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
+    std::string query_sql("SELECT * FROM " TRANSACTION_TABLE);
     auto stmt = sql_be->create_statement_from_sql(query_sql);
-    g_free (query_sql);
+
     if (stmt != nullptr)
     {
-        query_transactions (sql_be, stmt);
+        auto result = sql_be->execute_select_statement(stmt);
+        if (result->begin() == result->end())
+            return;
+
+        Transaction* tx;
+
+        // Load the transactions
+        InstanceVec instances;
+        instances.reserve(result->size());
+        for (auto row : *result)
+        {
+            tx = load_single_tx (sql_be, row);
+            if (tx != nullptr)
+            {
+                xaccTransScrubPostedDate (tx);
+                instances.push_back(QOF_INSTANCE(tx));
+            }
+        }
+        if (instances.empty())
+            return;
+        const std::string tpkey(tx_col_table[0]->name());
+        std::string subquery("SELECT DISTINCT ");
+        subquery += tpkey + " FROM " TRANSACTION_TABLE;
+        gnc_sql_slots_load_for_sql_subquery (sql_be, subquery,
+                                             (BookLookupFn)xaccTransLookup);
+        load_splits_for_sql_subquery (sql_be, subquery);
+
+        // Commit all of the transactions
+        for (auto instance : instances)
+            xaccTransCommitEdit(GNC_TRANSACTION(instance));
+
     }
 }
 

commit b739661171edad92c678b5bbf6e5814c34518a24
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Mar 25 10:19:44 2018 -0700

    Remove functions marked G_UNUSED.
    
    More noise reduction.

diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp
index e54728c..6013aaa 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp
@@ -872,199 +872,6 @@ typedef struct
     gboolean has_been_run;
 } split_query_info_t;
 
-#define TX_GUID_CHECK 0
-
-G_GNUC_UNUSED static  gpointer
-compile_split_query (GncSqlBackend* sql_be, QofQuery* query)
-{
-    split_query_info_t* query_info = NULL;
-    gchar* query_sql;
-
-    g_return_val_if_fail (sql_be != NULL, NULL);
-    g_return_val_if_fail (query != NULL, NULL);
-
-    query_info = static_cast<decltype (query_info)> (
-                     g_malloc (sizeof (split_query_info_t)));
-    g_assert (query_info != NULL);
-    query_info->has_been_run = FALSE;
-
-    if (qof_query_has_terms (query))
-    {
-        GList* orterms = qof_query_get_terms (query);
-        GList* orTerm;
-        std::stringstream sql;
-        gboolean need_OR = FALSE;
-
-        for (orTerm = orterms; orTerm != NULL; orTerm = orTerm->next)
-        {
-            GList* andterms = (GList*)orTerm->data;
-            GList* andTerm;
-            gboolean need_AND = FALSE;
-#if TX_GUID_CHECK
-            gboolean has_tx_guid_check = FALSE;
-#endif
-            if (need_OR)
-            {
-                sql << " OR ";
-            }
-            sql << "(";
-            for (andTerm = andterms; andTerm != NULL; andTerm = andTerm->next)
-            {
-                QofQueryTerm* term;
-                GSList* paramPath;
-                gboolean unknownPath = FALSE;
-
-                term = (QofQueryTerm*)andTerm->data;
-                paramPath = qof_query_term_get_param_path (term);
-                const char* path = static_cast<decltype (path)> (paramPath->data);
-                const char* next_path =
-                    static_cast<decltype (next_path)> (paramPath->next->data);
-                if (strcmp (path, QOF_PARAM_BOOK) == 0) continue;
-
-#if SIMPLE_QUERY_COMPILATION
-                if (strcmp (path, SPLIT_ACCOUNT) != 0 ||
-                    strcmp (next_path, QOF_PARAM_GUID) != 0) continue;
-#endif
-
-                if (need_AND) sql<< " AND ";
-
-                if (strcmp (path, SPLIT_ACCOUNT) == 0 &&
-                    strcmp (next_path, QOF_PARAM_GUID) == 0)
-                {
-                    convert_query_term_to_sql (sql_be, "s.account_guid", term,
-                                               sql);
-#if SIMPLE_QUERY_COMPILATION
-                    goto done_compiling_query;
-#endif
-
-                }
-                else if (strcmp (path, SPLIT_RECONCILE) == 0)
-                {
-                    convert_query_term_to_sql (sql_be, "s.reconcile_state",
-                                               term, sql);
-
-                }
-                else if (strcmp (path, SPLIT_TRANS) == 0)
-                {
-#if TX_GUID_CHECK
-                    if (!has_tx_guid_check)
-                    {
-                        sql << "(splits.tx_guid = transactions.guid) AND ");
-                        has_tx_guid_check = TRUE;
-                    }
-#endif
-                    if (strcmp (next_path, TRANS_DATE_POSTED) == 0)
-                    {
-                        convert_query_term_to_sql (sql_be, "t.post_date", term,
-                                                   sql);
-                    }
-                    else if (strcmp (next_path, TRANS_DESCRIPTION) == 0)
-                    {
-                        convert_query_term_to_sql (sql_be, "t.description",
-                                                   term, sql);
-                    }
-                    else
-                    {
-                        unknownPath = TRUE;
-                    }
-
-                }
-                else if (strcmp (path, SPLIT_VALUE) == 0)
-                {
-                    convert_query_term_to_sql (sql_be,
-                                               "s.value_num/s.value_denom",
-                                               term, sql);
-                }
-                else
-                {
-                    unknownPath = TRUE;
-                }
-
-                if (unknownPath)
-                {
-                    std::stringstream name;
-                    name << static_cast<char*>(paramPath->data);
-                    for (;paramPath->next != NULL; paramPath = paramPath->next)
-                    {
-                        next_path =
-                            static_cast<decltype (next_path)>(paramPath->next->data);
-                        name << "." << next_path;
-                    }
-                    PERR ("Unknown SPLIT query field: %s\n",
-                          name.str().c_str());
-                }
-                need_AND = TRUE;
-            }
-
-            /* If the last char in the string is a '(', then for some reason, there were
-               no terms added to the SQL.  If so, remove it and ignore the OR term. */
-        if (!sql.str().empty() && sql.str().back() == '(')
-            {
-                sql.str().erase(sql.str().back());
-                need_OR = FALSE;
-            }
-            else
-            {
-                sql << ")";
-                need_OR = TRUE;
-            }
-        }
-
-#if SIMPLE_QUERY_COMPILATION
-done_compiling_query:
-#endif
-    if (!sql.str().empty())
-        {
-#if SIMPLE_QUERY_COMPILATION
-            sql<< ")";
-#endif
-            query_sql = g_strdup_printf (
-                            "SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND %s",
-                            TRANSACTION_TABLE, SPLIT_TABLE, sql.str().c_str());
-        }
-        else
-        {
-            query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
-        }
-        query_info->stmt = sql_be->create_statement_from_sql(query_sql);
-        g_free (query_sql);
-
-    }
-    else
-    {
-        query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
-        query_info->stmt = sql_be->create_statement_from_sql(query_sql);
-        g_free (query_sql);
-    }
-
-    return query_info;
-}
-
-G_GNUC_UNUSED static void
-run_split_query (GncSqlBackend* sql_be, gpointer pQuery)
-{
-    split_query_info_t* query_info = (split_query_info_t*)pQuery;
-
-    g_return_if_fail (sql_be != NULL);
-    g_return_if_fail (pQuery != NULL);
-
-    if (!query_info->has_been_run)
-    {
-        query_transactions (sql_be, query_info->stmt);
-        query_info->has_been_run = TRUE;
-        query_info->stmt = nullptr;
-    }
-}
-
-G_GNUC_UNUSED static void
-free_split_query (GncSqlBackend* sql_be, gpointer pQuery)
-{
-    g_return_if_fail (sql_be != NULL);
-    g_return_if_fail (pQuery != NULL);
-
-    g_free (pQuery);
-}
-
 /* ----------------------------------------------------------------- */
 typedef struct
 {
@@ -1118,22 +925,6 @@ static const EntryVec acct_balances_col_table
                                          (QofSetterFunc)set_acct_bal_balance),
 };
 
-G_GNUC_UNUSED static  single_acct_balance_t*
-load_single_acct_balances (const GncSqlBackend* sql_be, GncSqlRow& row)
-{
-    single_acct_balance_t* bal = NULL;
-
-    g_return_val_if_fail (sql_be != NULL, NULL);
-
-    bal = static_cast<decltype (bal)> (g_malloc (sizeof (single_acct_balance_t)));
-    g_assert (bal != NULL);
-
-    bal->sql_be = sql_be;
-    gnc_sql_load_object (sql_be, row, NULL, bal, acct_balances_col_table);
-
-    return bal;
-}
-
 /* ----------------------------------------------------------------- */
 template<> void
 GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* sql_be,

commit 9b643574274c5f13093c6b4d3add25a6fc0f309f
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Mar 24 18:16:00 2018 -0700

    Remove LOAD_TRANSACTIONS_AS_NEEDED from SQL backend.
    
    We're not ready for that and until we are it's just noise.

diff --git a/libgnucash/backend/sql/gnc-account-sql.cpp b/libgnucash/backend/sql/gnc-account-sql.cpp
index e926b0d..f80370b 100644
--- a/libgnucash/backend/sql/gnc-account-sql.cpp
+++ b/libgnucash/backend/sql/gnc-account-sql.cpp
@@ -273,27 +273,6 @@ GncSqlAccountBackend::load_all (GncSqlBackend* sql_be)
 			     });
     }
 
-#if LOAD_TRANSACTIONS_AS_NEEDED
-    /* Load starting balances */
-    auto bal_slist = gnc_sql_get_account_balances_slist (sql_be);
-    for (auto bal = bal_slist; bal != NULL; bal = bal->next)
-    {
-        acct_balances_t* balances = (acct_balances_t*)bal->data;
-
-        qof_instance_increase_editlevel (balances->acct);
-        g_object_set (balances->acct,
-                      "start-balance", &balances->balance,
-                      "start-cleared-balance", &balances->cleared_balance,
-                      "start-reconciled-balance", &balances->reconciled_balance,
-                      NULL);
-
-        qof_instance_decrease_editlevel (balances->acct);
-    }
-    if (bal_slist != NULL)
-    {
-        g_slist_free (bal_slist);
-    }
-#endif
     LEAVE ("");
 }
 
diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp
index 8f92178..e54728c 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp
@@ -64,7 +64,6 @@ extern "C"
 #include "gnc-slots-sql.h"
 
 #define SIMPLE_QUERY_COMPILATION 1
-#define LOAD_TRANSACTIONS_AS_NEEDED 0
 
 static QofLogModule log_module = G_LOG_DOMAIN;
 
@@ -264,13 +263,17 @@ load_splits_for_tx_list (GncSqlBackend* sql_be, InstanceVec& transactions)
     // Execute the query and load the splits
     auto stmt = sql_be->create_statement_from_sql(sql.str());
     auto result = sql_be->execute_select_statement (stmt);
+    InstanceVec instances;
 
     for (auto row : *result)
+    {
         Split* s = load_single_split (sql_be, row);
-    sql = "SELECT DISTINCT ";
-    sql += spkey + " FROM " SPLIT_TABLE " WHERE " + sskey + " IN " + selector;
-    gnc_sql_slots_load_for_sql_subquery(sql_be, sql,
-					(BookLookupFn)xaccSplitLookup);
+        if (s != nullptr)
+            instances.push_back(QOF_INSTANCE(s));
+    }
+
+    if (!instances.empty())
+        gnc_sql_slots_load_for_instancevec (sql_be, instances);
 }
 
 static  Transaction*
@@ -344,19 +347,6 @@ query_transactions (GncSqlBackend* sql_be, const GncSqlStatementPtr& stmt)
         return;
 
     Transaction* tx;
-#if LOAD_TRANSACTIONS_AS_NEEDED
-    GSList* bal_list = NULL;
-    Account* root = gnc_book_get_root_account (sql_be->book());
-
-    qof_event_suspend ();
-    xaccAccountBeginEdit (root);
-
-    // Save the start/ending balances (balance, cleared and reconciled) for
-    // every account.
-    gnc_account_foreach_descendant (gnc_book_get_root_account (sql_be->primary_book),
-                                    save_account_balances,
-                                    &bal_list);
-#endif
 
     // Load the transactions
     InstanceVec instances;
@@ -381,71 +371,9 @@ query_transactions (GncSqlBackend* sql_be, const GncSqlStatementPtr& stmt)
     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
-    // balance has changed, update the start balance so that the end
-    // balance is the same as it was before the splits were loaded.
-    // Repeat for cleared and reconciled balances.
-    for (auto nextbal = bal_list; nextbal != NULL; nextbal = nextbal->next)
-    {
-        full_acct_balances_t* balns = (full_acct_balances_t*)nextbal->data;
-        gnc_numeric* pnew_end_bal;
-        gnc_numeric* pnew_end_c_bal;
-        gnc_numeric* pnew_end_r_bal;
-        gnc_numeric adj;
-
-        g_object_get (balns->acc,
-                      "end-balance", &pnew_end_bal,
-                      "end-cleared-balance", &pnew_end_c_bal,
-                      "end-reconciled-balance", &pnew_end_r_bal,
-                      NULL);
-
-        qof_instance_increase_editlevel (balns - acc);
-        if (!gnc_numeric_eq (*pnew_end_bal, balns->end_bal))
-        {
-            adj = gnc_numeric_sub (balns->end_bal, *pnew_end_bal,
-                                   GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            balns->start_bal = gnc_numeric_add (balns->start_bal, adj,
-                                                GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            g_object_set (balns->acc, "start-balance", &balns->start_bal, NULL);
-            qof_instance_decrease_editlevel (balns - acc);
-        }
-        if (!gnc_numeric_eq (*pnew_end_c_bal, balns->end_cleared_bal))
-        {
-            adj = gnc_numeric_sub (balns->end_cleared_bal, *pnew_end_c_bal,
-                                   GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            balns->start_cleared_bal = gnc_numeric_add (balns->start_cleared_bal, adj,
-                                                        GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            g_object_set (balns->acc, "start-cleared-balance", &balns->start_cleared_bal,
-                          NULL);
-        }
-        if (!gnc_numeric_eq (*pnew_end_r_bal, balns->end_reconciled_bal))
-        {
-            adj = gnc_numeric_sub (balns->end_reconciled_bal, *pnew_end_r_bal,
-                                   GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            balns->start_reconciled_bal = gnc_numeric_add (balns->start_reconciled_bal,
-                                                           adj,
-                                                           GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            g_object_set (balns->acc, "start-reconciled-balance",
-                          &balns->start_reconciled_bal, NULL);
-        }
-        qof_instance_decrease_editlevel (balns - acc);
-        xaccAccountRecomputeBalance (balns->acc);
-        g_free (pnew_end_bal);
-        g_free (pnew_end_c_bal);
-        g_free (pnew_end_r_bal);
-        g_free (balns);
-    }
-    if (bal_list != NULL)
-    {
-        g_slist_free (bal_list);
-    }
-
-    xaccAccountCommitEdit (root);
-    qof_event_resume ();
-#endif
 }
 
+
 /* ================================================================= */
 /**
  * Creates the transaction and split tables.
@@ -1206,89 +1134,6 @@ load_single_acct_balances (const GncSqlBackend* sql_be, GncSqlRow& row)
     return bal;
 }
 
-GSList*
-gnc_sql_get_account_balances_slist (GncSqlBackend* sql_be)
-{
-#if LOAD_TRANSACTIONS_AS_NEEDED
-    gchar* buf;
-    GSList* bal_slist = NULL;
-
-    g_return_val_if_fail (sql_be != NULL, NULL);
-
-    buf = g_strdup_printf ("SELECT account_guid, reconcile_state, sum(quantity_num) as quantity_num, quantity_denom FROM %s GROUP BY account_guid, reconcile_state, quantity_denom ORDER BY account_guid, reconcile_state",
-                           SPLIT_TABLE);
-    auto stmt = sql_be->create_statement_from_sql(buf);
-    g_assert (stmt != nullptr);
-    g_free (buf);
-    auto result = sql_be->execute_select_statement(stmt);
-    acct_balances_t* bal = NULL;
-
-    for (auto row : *result)
-    {
-        single_acct_balance_t* single_bal;
-
-        // Get the next reconcile state balance and merge with other balances
-        single_bal = load_single_acct_balances (sql_be, row);
-        if (single_bal != NULL)
-        {
-            if (bal != NULL && bal->acct != single_bal->acct)
-            {
-                bal->cleared_balance = gnc_numeric_add (bal->cleared_balance,
-                                                        bal->reconciled_balance,
-                                                        GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-                bal->balance = gnc_numeric_add (bal->balance, bal->cleared_balance,
-                                                GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-                bal_slist = g_slist_append (bal_slist, bal);
-                bal = NULL;
-            }
-            if (bal == NULL)
-            {
-                bal = g_malloc ((gsize)sizeof (acct_balances_t));
-                g_assert (bal != NULL);
-
-                bal->acct = single_bal->acct;
-                bal->balance = gnc_numeric_zero ();
-                bal->cleared_balance = gnc_numeric_zero ();
-                bal->reconciled_balance = gnc_numeric_zero ();
-            }
-            if (single_bal->reconcile_state == 'n')
-            {
-                bal->balance = gnc_numeric_add (bal->balance, single_bal->balance,
-                                                GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            }
-            else if (single_bal->reconcile_state == 'c')
-            {
-                bal->cleared_balance = gnc_numeric_add (bal->cleared_balance,
-                                                        single_bal->balance,
-                                                        GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            }
-            else if (single_bal->reconcile_state == 'y')
-            {
-                bal->reconciled_balance = gnc_numeric_add (bal->reconciled_balance,
-                                                           single_bal->balance,
-                                                           GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-            }
-            g_free (single_bal);
-        }
-    }
-
-    // Add the final balance
-    if (bal != NULL)
-    {
-        bal->cleared_balance = gnc_numeric_add (bal->cleared_balance,
-                                                bal->reconciled_balance,
-                                                GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-        bal->balance = gnc_numeric_add (bal->balance, bal->cleared_balance,
-                                        GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
-        bal_slist = g_slist_append (bal_slist, bal);
-    }
-
-    return bal_slist;
-#else
-    return NULL;
-#endif
-}
-
 /* ----------------------------------------------------------------- */
 template<> void
 GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* sql_be,
diff --git a/libgnucash/backend/sql/gnc-transaction-sql.h b/libgnucash/backend/sql/gnc-transaction-sql.h
index f1b11cd..78d35b2 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.h
+++ b/libgnucash/backend/sql/gnc-transaction-sql.h
@@ -69,13 +69,5 @@ typedef struct
     gnc_numeric reconciled_balance;
 } acct_balances_t;
 
-/**
- * Returns a list of acct_balances_t structures, one for each account which
- * has splits.
- *
- * @param sql_be SQL backend
- * @return GSList of acct_balances_t structures
- */
-GSList* gnc_sql_get_account_balances_slist (GncSqlBackend* sql_be);
 
 #endif /* GNC_TRANSACTION_SQL_H */

commit e4d0ad9ddaecd18467433568b474f391d70496b9
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Mar 24 17:55:03 2018 -0700

    Reduce use of gnc_sql_slots_load_for_instancevec.

diff --git a/libgnucash/backend/sql/gnc-account-sql.cpp b/libgnucash/backend/sql/gnc-account-sql.cpp
index f0113ed..e926b0d 100644
--- a/libgnucash/backend/sql/gnc-account-sql.cpp
+++ b/libgnucash/backend/sql/gnc-account-sql.cpp
@@ -220,16 +220,14 @@ GncSqlAccountBackend::load_all (GncSqlBackend* sql_be)
 
     pBook = sql_be->book();
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
     for (auto row : *result)
         load_single_account (sql_be, row, l_accounts_needing_parents);
 
-    sql.str("");
-    sql << "SELECT DISTINCT guid FROM " << TABLE_NAME;
-    gnc_sql_slots_load_for_sql_subquery (sql_be, sql.str().c_str(),
+    sql = "SELECT DISTINCT guid FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
                                          (BookLookupFn)xaccAccountLookup);
 
     /* While there are items on the list of accounts needing parents,
diff --git a/libgnucash/backend/sql/gnc-bill-term-sql.cpp b/libgnucash/backend/sql/gnc-bill-term-sql.cpp
index ae813d8..31b4445 100644
--- a/libgnucash/backend/sql/gnc-bill-term-sql.cpp
+++ b/libgnucash/backend/sql/gnc-bill-term-sql.cpp
@@ -224,30 +224,35 @@ load_single_billterm (GncSqlBackend* sql_be, GncSqlRow& row,
     return pBillTerm;
 }
 
+/* Because gncBillTermLookup has the arguments backwards: */
+static inline GncBillTerm*
+gnc_billterm_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_BILLTERM, GncBillTerm);
+}
+
 void
 GncSqlBillTermBackend::load_all (GncSqlBackend* sql_be)
 {
 
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
     BillTermParentGuidVec l_billterms_needing_parents;
 
     for (auto row : *result)
     {
         auto pBillTerm =
             load_single_billterm (sql_be, row, l_billterms_needing_parents);
-        if (pBillTerm != nullptr)
-            instances.push_back(QOF_INSTANCE(pBillTerm));
     }
     delete result;
-
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_billterm_lookup);
 
     /* 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
diff --git a/libgnucash/backend/sql/gnc-budget-sql.cpp b/libgnucash/backend/sql/gnc-budget-sql.cpp
index 9ad5fba..826e56d 100644
--- a/libgnucash/backend/sql/gnc-budget-sql.cpp
+++ b/libgnucash/backend/sql/gnc-budget-sql.cpp
@@ -327,22 +327,19 @@ load_single_budget (GncSqlBackend* sql_be, GncSqlRow& row)
 void
 GncSqlBudgetBackend::load_all (GncSqlBackend* sql_be)
 {
-    InstanceVec instances;
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << BUDGET_TABLE;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " BUDGET_TABLE);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
     for (auto row : *result)
-    {
         auto b = load_single_budget (sql_be, row);
-        if (b != nullptr)
-            instances.push_back(QOF_INSTANCE(b));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " BUDGET_TABLE;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_budget_lookup);
 }
 
 /* ================================================================= */
diff --git a/libgnucash/backend/sql/gnc-commodity-sql.cpp b/libgnucash/backend/sql/gnc-commodity-sql.cpp
index 451b55a..32689d3 100644
--- a/libgnucash/backend/sql/gnc-commodity-sql.cpp
+++ b/libgnucash/backend/sql/gnc-commodity-sql.cpp
@@ -142,9 +142,8 @@ GncSqlCommodityBackend::load_all (GncSqlBackend* sql_be)
     gnc_commodity_table* pTable;
 
     pTable = gnc_commodity_table_get_table (sql_be->book());
-    std::stringstream sql;
-    sql << "SELECT * FROM " << COMMODITIES_TABLE;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " COMMODITIES_TABLE);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
 
     for (auto row : *result)
@@ -162,11 +161,12 @@ GncSqlCommodityBackend::load_all (GncSqlBackend* sql_be)
             qof_instance_set_guid (QOF_INSTANCE (pCommodity), &guid);
         }
 
-        auto sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", COMMODITIES_TABLE);
-        gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
-                                             (BookLookupFn)gnc_commodity_find_commodity_by_guid);
-        g_free (sql);
     }
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " COMMODITIES_TABLE;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_commodity_find_commodity_by_guid);
 }
 /* ================================================================= */
 static gboolean
diff --git a/libgnucash/backend/sql/gnc-customer-sql.cpp b/libgnucash/backend/sql/gnc-customer-sql.cpp
index de713eb..d4c2bfa 100644
--- a/libgnucash/backend/sql/gnc-customer-sql.cpp
+++ b/libgnucash/backend/sql/gnc-customer-sql.cpp
@@ -117,26 +117,30 @@ load_single_customer (GncSqlBackend* sql_be, GncSqlRow& row)
     return pCustomer;
 }
 
+/* Because gncCustomerLookup has the arguments backwards: */
+static inline GncCustomer*
+gnc_customer_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_CUSTOMER, GncCustomer);
+}
+
 void
 GncSqlCustomerBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         GncCustomer* pCustomer = load_single_customer (sql_be, row);
-        if (pCustomer != nullptr)
-            instances.push_back(QOF_INSTANCE(pCustomer));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_customer_lookup);
 }
 
 /* ================================================================= */
diff --git a/libgnucash/backend/sql/gnc-employee-sql.cpp b/libgnucash/backend/sql/gnc-employee-sql.cpp
index 79c6346..afa0e90 100644
--- a/libgnucash/backend/sql/gnc-employee-sql.cpp
+++ b/libgnucash/backend/sql/gnc-employee-sql.cpp
@@ -101,30 +101,33 @@ load_single_employee (GncSqlBackend* sql_be, GncSqlRow& row)
 
     return pEmployee;
 }
+/* Because gncCustomerLookup has the arguments backwards: */
+static inline GncEmployee*
+gnc_employee_lookup (const GncGUID *guid, const QofBook *book)
+{
+    QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_EMPLOYEE, GncEmployee);
+}
 
 void
 GncSqlEmployeeBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
 
-    InstanceVec instances;
-
     for (auto row : *result)
-    {
         GncEmployee* pEmployee = load_single_employee (sql_be, row);
-        if (pEmployee != nullptr)
-            instances.push_back(QOF_INSTANCE(pEmployee));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_employee_lookup);
 }
 
+
 /* ================================================================= */
 void
 GncSqlEmployeeBackend::create_tables (GncSqlBackend* sql_be)
diff --git a/libgnucash/backend/sql/gnc-entry-sql.cpp b/libgnucash/backend/sql/gnc-entry-sql.cpp
index 764ffa4..f68e210 100644
--- a/libgnucash/backend/sql/gnc-entry-sql.cpp
+++ b/libgnucash/backend/sql/gnc-entry-sql.cpp
@@ -186,26 +186,30 @@ load_single_entry (GncSqlBackend* sql_be, GncSqlRow& row)
     return pEntry;
 }
 
+/* Because gncEntryLookup has the arguments backwards: */
+static inline GncEntry*
+gnc_entry_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_ENTRY, GncEntry);
+}
+
 void
 GncSqlEntryBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         GncEntry* pEntry = load_single_entry (sql_be, row);
-        if (pEntry != nullptr)
-            instances.push_back(QOF_INSTANCE(pEntry));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec(sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_entry_lookup);
 }
 
 /* ================================================================= */
diff --git a/libgnucash/backend/sql/gnc-invoice-sql.cpp b/libgnucash/backend/sql/gnc-invoice-sql.cpp
index e0cc87a..29a18fd 100644
--- a/libgnucash/backend/sql/gnc-invoice-sql.cpp
+++ b/libgnucash/backend/sql/gnc-invoice-sql.cpp
@@ -124,26 +124,30 @@ load_single_invoice (GncSqlBackend* sql_be, GncSqlRow& row)
     return pInvoice;
 }
 
+/* Because gncInvoiceLookup has the arguments backwards: */
+static inline GncInvoice*
+gnc_invoice_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_INVOICE, GncInvoice);
+}
+
 void
 GncSqlInvoiceBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         GncInvoice* pInvoice = load_single_invoice (sql_be, row);
-        if (pInvoice != nullptr)
-            instances.push_back(QOF_INSTANCE(pInvoice));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_invoice_lookup);
 }
 
 /* ================================================================= */
diff --git a/libgnucash/backend/sql/gnc-job-sql.cpp b/libgnucash/backend/sql/gnc-job-sql.cpp
index dd4d9f5..48e17aa 100644
--- a/libgnucash/backend/sql/gnc-job-sql.cpp
+++ b/libgnucash/backend/sql/gnc-job-sql.cpp
@@ -96,26 +96,30 @@ load_single_job (GncSqlBackend* sql_be, GncSqlRow& row)
     return pJob;
 }
 
+/* Because gncJobLookup has the arguments backwards: */
+static inline GncJob*
+gnc_job_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_JOB, GncJob);
+}
+
 void
 GncSqlJobBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         GncJob* pJob = load_single_job (sql_be, row);
-        if (pJob != nullptr)
-            instances.push_back(QOF_INSTANCE(pJob));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_job_lookup);
 }
 
 /* ================================================================= */
diff --git a/libgnucash/backend/sql/gnc-order-sql.cpp b/libgnucash/backend/sql/gnc-order-sql.cpp
index b870a22..50cde38 100644
--- a/libgnucash/backend/sql/gnc-order-sql.cpp
+++ b/libgnucash/backend/sql/gnc-order-sql.cpp
@@ -98,26 +98,30 @@ load_single_order (GncSqlBackend* sql_be, GncSqlRow& row)
     return pOrder;
 }
 
+/* Because gncOrderLookup has the arguments backwards: */
+static inline GncOrder*
+gnc_order_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_ORDER, GncOrder);
+}
+
 void
 GncSqlOrderBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         GncOrder* pOrder = load_single_order (sql_be, row);
-        if (pOrder != nullptr)
-            instances.push_back(QOF_INSTANCE(pOrder));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_order_lookup);
 }
 
 /* ================================================================= */
diff --git a/libgnucash/backend/sql/gnc-price-sql.cpp b/libgnucash/backend/sql/gnc-price-sql.cpp
index 85c440c..6a12872 100644
--- a/libgnucash/backend/sql/gnc-price-sql.cpp
+++ b/libgnucash/backend/sql/gnc-price-sql.cpp
@@ -102,9 +102,8 @@ GncSqlPriceBackend::load_all (GncSqlBackend* sql_be)
 
     pBook = sql_be->book();
     pPriceDB = gnc_pricedb_get_db (pBook);
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     if (stmt != nullptr)
     {
         auto result = sql_be->execute_select_statement(stmt);
@@ -112,7 +111,6 @@ GncSqlPriceBackend::load_all (GncSqlBackend* sql_be)
             return;
 
         GNCPrice* pPrice;
-        gchar* sql;
 
         gnc_pricedb_set_bulk_update (pPriceDB, TRUE);
         for (auto row : *result)
@@ -126,10 +124,11 @@ GncSqlPriceBackend::load_all (GncSqlBackend* sql_be)
             }
         }
         gnc_pricedb_set_bulk_update (pPriceDB, FALSE);
-
-        sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", TABLE_NAME);
-        gnc_sql_slots_load_for_sql_subquery (sql_be, sql, (BookLookupFn)gnc_price_lookup);
-        g_free (sql);
+	std::string pkey(col_table[0]->name());
+        sql = "SELECT DISTINCT ";
+	sql += pkey + " FROM " TABLE_NAME;
+        gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					     (BookLookupFn)gnc_price_lookup);
     }
 }
 
diff --git a/libgnucash/backend/sql/gnc-schedxaction-sql.cpp b/libgnucash/backend/sql/gnc-schedxaction-sql.cpp
index f7909fd..c883a92 100644
--- a/libgnucash/backend/sql/gnc-schedxaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-schedxaction-sql.cpp
@@ -115,18 +115,23 @@ load_single_sx (GncSqlBackend* sql_be, GncSqlRow& row)
     return pSx;
 }
 
+/* Because SchedXaction doesn't define a lookup function: */
+static inline SchedXaction*
+gnc_sx_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_SCHEDXACTION, SchedXaction);
+}
+
 void
 GncSqlSchedXactionBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << SCHEDXACTION_TABLE;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
-    if (stmt == NULL) return;
+    std::string sql("SELECT * FROM " SCHEDXACTION_TABLE);
+    auto stmt = sql_be->create_statement_from_sql(sql);
+    if (stmt == nullptr) return;
     auto result = sql_be->execute_select_statement(stmt);
     SchedXactions* sxes;
-    InstanceVec instances;
     sxes = gnc_book_get_schedxactions (sql_be->book());
 
     for (auto row : *result)
@@ -135,14 +140,13 @@ GncSqlSchedXactionBackend::load_all (GncSqlBackend* sql_be)
 
         sx = load_single_sx (sql_be, row);
         if (sx != nullptr)
-        {
             gnc_sxes_add_sx (sxes, sx);
-            instances.push_back(QOF_INSTANCE(sx));
-        }
     }
-
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " SCHEDXACTION_TABLE;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_sx_lookup);
 }
 
 
diff --git a/libgnucash/backend/sql/gnc-slots-sql.cpp b/libgnucash/backend/sql/gnc-slots-sql.cpp
index ca26617..ab2d6e4 100644
--- a/libgnucash/backend/sql/gnc-slots-sql.cpp
+++ b/libgnucash/backend/sql/gnc-slots-sql.cpp
@@ -766,19 +766,15 @@ gnc_sql_slots_load (GncSqlBackend* sql_be, QofInstance* inst)
 static void
 slots_load_info (slot_info_t* pInfo)
 {
-    gchar guid_buf[GUID_ENCODING_LENGTH + 1];
-
     g_return_if_fail (pInfo != NULL);
     g_return_if_fail (pInfo->be != NULL);
     g_return_if_fail (pInfo->guid != NULL);
     g_return_if_fail (pInfo->pKvpFrame != NULL);
 
-    (void)guid_to_string_buff (pInfo->guid, guid_buf);
-
-    std::stringstream buf;
-    buf << "SELECT * FROM " << TABLE_NAME <<
-        " WHERE obj_guid='" << guid_buf << "'";
-    auto stmt = pInfo->be->create_statement_from_sql (buf.str());
+    gnc::GUID guid(*pInfo->guid);
+    std::string sql("SELECT * FROM " TABLE_NAME " WHERE obj_guid='");
+    sql += guid.to_string() + "'";
+    auto stmt = pInfo->be->create_statement_from_sql(sql);
     if (stmt != nullptr)
     {
         auto result = pInfo->be->execute_select_statement (stmt);
@@ -897,29 +893,25 @@ load_slot_for_book_object (GncSqlBackend* sql_be, GncSqlRow& row,
  * @param lookup_fn Lookup function
  */
 void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* sql_be,
-                                          const gchar* subquery,
+                                          const std::string subquery,
                                           BookLookupFn lookup_fn)
 {
-    gchar* sql;
-
     g_return_if_fail (sql_be != NULL);
 
     // Ignore empty subquery
-    if (subquery == NULL) return;
+    if (subquery.empty()) return;
 
-    sql = g_strdup_printf ("SELECT * FROM %s WHERE %s IN (%s)",
-                           TABLE_NAME, obj_guid_col_table[0]->name(),
-                           subquery);
+    std::string pkey(obj_guid_col_table[0]->name());
+    std::string sql("SELECT * FROM " TABLE_NAME " WHERE ");
+    sql += pkey + " IN (" + subquery + ")";
 
     // Execute the query and load the slots
     auto stmt = sql_be->create_statement_from_sql(sql);
     if (stmt == nullptr)
     {
-        PERR ("stmt == NULL, SQL = '%s'\n", sql);
-        g_free (sql);
+        PERR ("stmt == NULL, SQL = '%s'\n", sql.c_str());
         return;
     }
-    g_free (sql);
     auto result = sql_be->execute_select_statement(stmt);
     for (auto row : *result)
         load_slot_for_book_object (sql_be, row, lookup_fn);
diff --git a/libgnucash/backend/sql/gnc-slots-sql.h b/libgnucash/backend/sql/gnc-slots-sql.h
index 56ef2e5..0cdf3a6 100644
--- a/libgnucash/backend/sql/gnc-slots-sql.h
+++ b/libgnucash/backend/sql/gnc-slots-sql.h
@@ -100,7 +100,7 @@ typedef QofInstance* (*BookLookupFn) (const GncGUID* guid,
  * @param lookup_fn Lookup function to get the right object from the book
  */
 void gnc_sql_slots_load_for_sql_subquery (GncSqlBackend* sql_be,
-                                          const gchar* subquery,
+                                          const std::string subquery,
                                           BookLookupFn lookup_fn);
 
 void gnc_sql_init_slots_handler (void);
diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp
index c8ddd1e..8f92178 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp
@@ -264,17 +264,13 @@ load_splits_for_tx_list (GncSqlBackend* sql_be, InstanceVec& transactions)
     // Execute the query and load the splits
     auto stmt = sql_be->create_statement_from_sql(sql.str());
     auto result = sql_be->execute_select_statement (stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         Split* s = load_single_split (sql_be, row);
-        if (s != nullptr)
-            instances.push_back(QOF_INSTANCE(s));
-    }
-
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    sql = "SELECT DISTINCT ";
+    sql += spkey + " FROM " SPLIT_TABLE " WHERE " + sskey + " IN " + selector;
+    gnc_sql_slots_load_for_sql_subquery(sql_be, sql,
+					(BookLookupFn)xaccSplitLookup);
 }
 
 static  Transaction*
diff --git a/libgnucash/backend/sql/gnc-vendor-sql.cpp b/libgnucash/backend/sql/gnc-vendor-sql.cpp
index ae60b3a..a73c29c 100644
--- a/libgnucash/backend/sql/gnc-vendor-sql.cpp
+++ b/libgnucash/backend/sql/gnc-vendor-sql.cpp
@@ -106,26 +106,30 @@ load_single_vendor (GncSqlBackend* sql_be, GncSqlRow& row)
     return pVendor;
 }
 
+/* Because gncVendorLookup has the arguments backwards: */
+static inline GncVendor*
+gnc_vendor_lookup (const GncGUID *guid, const QofBook *book)
+{
+     QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_VENDOR, GncVendor);
+}
+
 void
 GncSqlVendorBackend::load_all (GncSqlBackend* sql_be)
 {
     g_return_if_fail (sql_be != NULL);
 
-    std::stringstream sql;
-    sql << "SELECT * FROM " << TABLE_NAME;
-    auto stmt = sql_be->create_statement_from_sql(sql.str());
+    std::string sql("SELECT * FROM " TABLE_NAME);
+    auto stmt = sql_be->create_statement_from_sql(sql);
     auto result = sql_be->execute_select_statement(stmt);
-    InstanceVec instances;
 
     for (auto row : *result)
-    {
         GncVendor* pVendor = load_single_vendor (sql_be, row);
-        if (pVendor != nullptr)
-            instances.push_back(QOF_INSTANCE(pVendor));
-    }
 
-    if (!instances.empty())
-        gnc_sql_slots_load_for_instancevec (sql_be, instances);
+    std::string pkey(col_table[0]->name());
+    sql = "SELECT DISTINCT ";
+    sql += pkey + " FROM " TABLE_NAME;
+    gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
+					 (BookLookupFn)gnc_vendor_lookup);
 }
 
 /* ================================================================= */

commit a39ba1672af5eecdb457f606d1b9fc27a6316140
Merge: dcfc128 8db1146
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 18:59:26 2018 +0200

    Merge branch 'unstable-tr-fix' of https://github.com/christopherlam/gnucash into unstable


commit dcfc1280bdf13623b79c639ff8735c6c3fa7f85d
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 18:46:26 2018 +0200

    Base invoice posted status on the presence of a posted transaction rather than a posted account
    
    Bills and invoices that are posted and subsequently unposted again still store their
    posted account internally as a convenience to the user (upon reposting the old
    account will be offered by default) so it's not a reliable test for the posted state.
    The posted transaction on the other hand is guaranteed to only exist when the invoice is
    posted. This should fix a slew of small and perhaps larger side effects, such as
    a posted bill still appearing as editable, critical warnings when creating new bills/invoices
    and so on.

diff --git a/libgnucash/engine/gncInvoice.c b/libgnucash/engine/gncInvoice.c
index 35b7f9f..592363f 100644
--- a/libgnucash/engine/gncInvoice.c
+++ b/libgnucash/engine/gncInvoice.c
@@ -1859,7 +1859,7 @@ gncInvoiceApplyPayment (const GncInvoice *invoice, Transaction *txn,
 gboolean gncInvoiceIsPosted (const GncInvoice *invoice)
 {
     if (!invoice) return FALSE;
-    return GNC_IS_ACCOUNT(gncInvoiceGetPostedAcc(invoice));
+    return GNC_IS_TRANSACTION(gncInvoiceGetPostedTxn(invoice));
 }
 
 gboolean gncInvoiceIsPaid (const GncInvoice *invoice)

commit 6093e5978f34eba8cda437745186fcc7f5ae68c4
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 18:39:18 2018 +0200

    Bug 794767 - Dates default to 01/01/1970

diff --git a/gnucash/gnome/dialog-invoice.c b/gnucash/gnome/dialog-invoice.c
index 187972b..043666f 100644
--- a/gnucash/gnome/dialog-invoice.c
+++ b/gnucash/gnome/dialog-invoice.c
@@ -1764,7 +1764,7 @@ gnc_invoice_update_window (InvoiceWindow *iw, GtkWidget *widget)
                                           gncInvoiceGetActive (invoice));
 
         time = gncInvoiceGetDateOpened (invoice);
-        if (!time)
+        if (time == INT64_MAX)
         {
             gnc_date_edit_set_time (GNC_DATE_EDIT (iw->opened_date),
                                     gnc_time (NULL));

commit 8db114658be024fa894fbca4fb1f71d1b2a6975c
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat Apr 14 22:43:19 2018 +0800

    html-font: add default font family
    
    Windows ships with GTK2 in which the default font styles are named
    "Sans" "Sans Bold" "Sans Normal" etc. There is no "Sans" font in
    Windows; I vote to add a default "Sans-Serif" font-family which is
    valid CSS. This ensures exported reports are shown as intended.

diff --git a/gnucash/report/report-system/html-fonts.scm b/gnucash/report/report-system/html-fonts.scm
index 8ad15bd..fee9af9 100644
--- a/gnucash/report/report-system/html-fonts.scm
+++ b/gnucash/report/report-system/html-fonts.scm
@@ -68,7 +68,7 @@
 		))))
 	(set! font-family font-name)
 	(set! result (string-append
-		"font-family: " font-family "; "
+		"font-family: " font-family ", Sans-Serif; "
 		"font-size: " font-size "pt; "
 		(if font-style (string-append "font-style: " font-style "; ") "")
 		(if font-weight (string-append "font-weight: " font-weight "; ") "")))

commit 1ee2c08306af8b480b5a706854c4557139400c76
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat Apr 14 22:13:21 2018 +0800

    GSTR: close br tag; add  empty lines to empty-report-message
    
    This will be useful for unit testing, and for displaying
    gnc:render-options-changed.

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index ed61412..2cd7b7e 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -43,14 +43,15 @@
  authorities. From <i>Edit report options</i> above, choose your Business Income and Business Expense accounts.
  Each transaction may contain, in addition to the accounts payable/receivable or bank accounts,
  a split to a tax account, e.g. Income:Sales -$1000, Liability:GST on Sales -$100, Asset:Bank $1100.")
-   "<br><br>"
+   "<br/><br/>"
    (_ "These tax accounts can either be populated using the standard register, or from Business Invoices and Bills
  which will require Business > Sales Tax Tables to be set up correctly. Please see the documentation.")
-   "<br><br>"
+   "<br/><br/>"
    (_ "From the Report Options, you will need to select the accounts which will \
 hold the GST/VAT taxes collected or paid. These accounts must contain splits which document the \
 monies which are wholly sent or claimed from tax authorities during periodic GST/VAT returns. These \
-accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")))
+accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
+   "<br/><br/>"))
 
 (define (income-gst-statement-renderer rpt)
   (trep-renderer rpt

commit b02e4a7c148d84b3ab702d81fb86ff9170f134bb
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat Apr 14 22:00:12 2018 +0800

    GSTR: bugfix individual tax on sales should be negated
    
    The GST-on-sales relates to income, therefore should be negated.

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index 8143dd3..ed61412 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -216,7 +216,7 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
                        (lambda (a) ""))))
      (if (opt-val gnc:pagename-display (N_ "Individual tax columns"))
          (map (lambda (acc) (vector (xaccAccountGetName acc)
-                                    (account-adder acc)
+                                    (account-adder-neg acc)
                                     #t #t #f
                                     (lambda (a) "")))
               accounts-tax-collected)

commit 4acc5a23f5e4e04ac3815a8d1b6465cd37b72152
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Apr 13 21:28:25 2018 +0800

    TR: instead of hand-crafting html-string, use html-table API
    
    Using html-table API seems more robust than hand-crafting HTML.

diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index 4f3a680..cb2dbc3 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -1668,45 +1668,30 @@ tags within description, notes or memo. ")
   (set! grid (grid-del grid row col))           ;we simply delete old data stored at row/col and 
   (set! grid (cons (vector row col data) grid)) ;add again. this is fine because the grid should
   grid)                                         ;never have duplicate data in the trep.
-(define (grid->html grid list-of-rows list-of-cols)
-  (define (cell->html cell)
-    (if (pair? cell)
-        (string-append "<td class=\"number-cell\">"
-                       (string-join (map gnc:monetary->string
-                                         (vector-ref (car cell) 2))
-                                    "<br/>\n")
-                       "</td>\n")
-        "<td></td>\n"))
-  (define (row->html row list-of-cols)
-    (string-append "<tr><td>"
-                   (if (eq? row 'row-total)
-                       (_ "Grand Total")
-                       (cdr row))
-                   "</td>\n"
-                   (string-join (map
-                                 (lambda (col) (cell->html (grid-get grid row col)))
-                                 list-of-cols) "")
-                   (cell->html (grid-get grid row 'col-total))
-                   "</tr>\n"))
-  (string-append "<table class=\"summary-table\"><caption>"
-                 optname-grid
-                 "</caption><thead><tr>"
-                 "<th></th>\n"
-                 (string-join (map (lambda (col)
-                                     (string-append "<th class=\"column-heading-right\">"
-                                                    (cdr col)
-                                                    "</th>\n")) list-of-cols) "")
-                 "<th class=\"column-heading-right\">"
-                 (_ "Total")
-                 "</th>\n</tr>\n</thead><tbody>"
-                 (string-join (map (lambda (row)
-                                     (row->html row list-of-cols))
-                                   list-of-rows) "")
-                 (if (memq 'row-total (grid-rows grid))
-                     (row->html 'row-total list-of-cols)
-                     "")
-                 "</tbody></table>\n"))
-
+(define (grid->html-table grid list-of-rows list-of-cols)
+  (define (make-table-cell row col)
+    (let ((cell (grid-get grid row col)))
+      (if (pair? cell)
+          (gnc:make-html-table-cell/markup "number-cell" (car (vector-ref (car cell) 2)))
+          "")))
+  (define (make-row row)
+    (append
+     (list (if (eq? row 'row-total) (_ "Grand Total") (cdr row)))
+     (map (lambda (col) (make-table-cell row col))
+          list-of-cols)
+     (list (make-table-cell row 'col-total))))
+  (let ((table (gnc:make-html-table)))
+    (gnc:html-table-set-caption! table optname-grid)
+    (gnc:html-table-set-col-headers! table (append (list "") (map cdr list-of-cols) (list (_ "Total"))))
+    (gnc:html-table-set-style! table "th"
+                               'attribute (list "class" "column-heading-right"))
+    (for-each
+     (lambda (row)
+       (gnc:html-table-append-row! table (make-row row)))
+     list-of-rows)
+    (if (memq 'row-total (grid-rows grid))
+        (gnc:html-table-append-row! table (make-row 'row-total)))
+    table))
 
 ;; ;;;;;;;;;;;;;;;;;;;;
 ;; Here comes the renderer function for this report.
@@ -1962,7 +1947,7 @@ tags within description, notes or memo. ")
                            (list-of-rows (stable-sort! (delete 'row-total (grid-rows grid)) generic<?))
                            (list-of-cols (stable-sort! (delete 'col-total (grid-cols grid)) generic<?)))
                       (gnc:html-document-add-object!
-                       document (grid->html grid list-of-rows list-of-cols))))
+                       document (grid->html-table grid list-of-rows list-of-cols))))
 
                 (if (eq? infobox-display 'always)
                     (gnc:html-document-add-object!

commit 2d9021ca424706e0a317c276f94efa20a32d335a
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Wed Apr 11 07:01:57 2018 +0800

    TR: catch invalid regex
    
    This commit prevents report crashing when either Account or
    Transaction Matcher strings are invalid POSIX regular expressions and
    called with make-regexp.

diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index c773cc1..4f3a680 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -1747,11 +1747,13 @@ tags within description, notes or memo. ")
   (let* ((document (gnc:make-html-document))
          (account-matcher (opt-val pagename-filter optname-account-matcher))
          (account-matcher-regexp (and (opt-val pagename-filter optname-account-matcher-regex)
-                                      (make-regexp account-matcher)))
+                                      (catch 'regular-expression-syntax
+                                        (lambda () (make-regexp account-matcher))
+                                        (const 'invalid-regex))))
          (c_account_0 (opt-val gnc:pagename-accounts optname-accounts))
          (c_account_1 (filter
                        (lambda (acc)
-                         (if account-matcher-regexp
+                         (if (regexp? account-matcher-regexp)
                              (regexp-exec account-matcher-regexp (gnc-account-get-full-name acc))
                              (string-contains (gnc-account-get-full-name acc) account-matcher)))
                        c_account_0))
@@ -1765,7 +1767,9 @@ tags within description, notes or memo. ")
                     (opt-val gnc:pagename-general optname-enddate))))
          (transaction-matcher (opt-val pagename-filter optname-transaction-matcher))
          (transaction-matcher-regexp (and (opt-val pagename-filter optname-transaction-matcher-regex)
-                                          (make-regexp transaction-matcher)))
+                                          (catch 'regular-expression-syntax
+                                            (lambda () (make-regexp transaction-matcher))
+                                            (const 'invalid-regex))))
          (reconcile-status-filter (keylist-get-info reconcile-status-list
                                                     (opt-val pagename-filter optname-reconcile-status)
                                                     'filter-types))
@@ -1838,7 +1842,9 @@ tags within description, notes or memo. ")
       (generic-less? X Y 'date 'none #t))
 
 
-    (if (or (null? c_account_1) (and-map not c_account_1))
+    (if (or (or (null? c_account_1) (and-map not c_account_1))
+            (eq? account-matcher-regexp 'invalid-regex)
+            (eq? transaction-matcher-regexp 'invalid-regex))
 
         ;; error condition: no accounts specified or obtained after filtering
         (begin

commit d273a3304e0ab88e258f6904cce6cfa0380cb383
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat Mar 3 23:01:33 2018 +0800

    TR: convert Reconcile Status Filter to QofQuery
    
    I presume QofQuery based in C is faster than scheme filtering. No
    saved-reports incompatibility is expected.

diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index 03e2478..c773cc1 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -321,6 +321,10 @@ in the Options panel."))
                 (cons 'tip (_ "Show both (and include void transactions in totals)."))))))
 
 (define reconcile-status-list
+  ;; 'filter-types must be either #f (i.e. disable reconcile filter)
+  ;; or a value defined as defined in Query.c
+  ;; e.g. CLEARED-NO for unreconciled
+  ;;      (logior CLEARED-NO CLEARED-CLEARED) for unreconciled & cleared
   (list
    (cons 'all
          (list
@@ -332,19 +336,19 @@ in the Options panel."))
          (list
           (cons 'text (_ "Unreconciled"))
           (cons 'tip (_ "Unreconciled only"))
-          (cons 'filter-types (list #\n))))
+          (cons 'filter-types CLEARED-NO)))
 
    (cons 'cleared
          (list
           (cons 'text (_ "Cleared"))
           (cons 'tip (_ "Cleared only"))
-          (cons 'filter-types (list #\c))))
+          (cons 'filter-types CLEARED-CLEARED)))
 
    (cons 'reconciled
          (list
           (cons 'text (_ "Reconciled"))
           (cons 'tip (_ "Reconciled only"))
-          (cons 'filter-types (list #\y))))))
+          (cons 'filter-types CLEARED-RECONCILED)))))
 
 
 (define ascending-list
@@ -1865,6 +1869,8 @@ tags within description, notes or memo. ")
             ((non-void-only) (gnc:query-set-match-non-voids-only! query (gnc-get-current-book)))
             ((void-only)     (gnc:query-set-match-voids-only! query (gnc-get-current-book)))
             (else #f))
+          (if reconcile-status-filter
+              (xaccQueryAddClearedMatch query reconcile-status-filter QOF-QUERY-AND))
           (if (not custom-sort?)
               (begin
                 (qof-query-set-sort-order query
@@ -1892,7 +1898,6 @@ tags within description, notes or memo. ")
           ;; - include/exclude splits to/from selected accounts
           ;; - substring/regex matcher for Transaction Description/Notes/Memo
           ;; - custom-split-filter, a split->bool function for derived reports
-          ;; - by reconcile status
           (set! splits (filter
                         (lambda (split)
                           (let* ((trans (xaccSplitGetParent split))
@@ -1910,9 +1915,7 @@ tags within description, notes or memo. ")
                                      (match? (xaccSplitGetMemo split)))
                                  (or (not custom-split-filter)     ; #f = ignore custom-split-filter
                                      (custom-split-filter split))
-                                 (or (not reconcile-status-filter) ; #f = ignore reconcile-status-filter
-                                     (memv (xaccSplitGetReconcile split)
-                                           reconcile-status-filter)))))
+                                 )))
                         splits))
 
           (if (null? splits)

commit 73ffcaa81e645d574e2b4c7b0429bd3b7e0e885f
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat Mar 31 11:16:47 2018 +0800

    TR: refactor add-subtotal-row
    
    This commit refactors add-subtotal-row to use a named let. This avoids
    set! calls, and is more idiomatic scheme.

diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index 1feee34..03e2478 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -1290,52 +1290,38 @@ tags within description, notes or memo. ")
               (addto! row-contents (gnc:make-html-table-cell/size/markup 1 (+ right-indent width-left-columns) "total-label-cell" string))))
 
         (define (add-columns commodity)
-          (let ((start-dual-column? #f)
-                (dual-subtotal #f))
-            (for-each (lambda (column merge-entry)
-                        (let* ((mon (retrieve-commodity column commodity))
-                               (column-amount (and mon (gnc:gnc-monetary-amount mon)))
-                               (merge? merge-entry))
-                          (if merge?
-                              ;; We're merging. If a subtotal exists, store
-                              ;; it in dual-subtotal. Do NOT add column to row.
-                              (begin
-                                (set! dual-subtotal column-amount)
-                                (set! start-dual-column? #t))
-                              (if start-dual-column?
-                                  (begin
-                                    ;; We've completed merging. Add the negated
-                                    ;; column amount and add the columns to row.
-                                    (if column-amount
-                                        (set! dual-subtotal
-                                          (- (or dual-subtotal 0) column-amount)))
-                                    (cond ((not dual-subtotal)
-                                           (addto! row-contents "")
-                                           (addto! row-contents ""))
-                                          ((positive? dual-subtotal)
-                                           (addto! row-contents
-                                                   (gnc:make-html-table-cell/markup
-                                                    "total-number-cell"
-                                                    (gnc:make-gnc-monetary
-                                                     commodity
-                                                     dual-subtotal)))
-                                           (addto! row-contents ""))
-                                          (else
-                                           (addto! row-contents "")
-                                           (addto! row-contents
-                                                   (gnc:make-html-table-cell/markup
-                                                    "total-number-cell"
-                                                    (gnc:make-gnc-monetary
-                                                     commodity
-                                                     (- dual-subtotal))))))
-                                    (set! start-dual-column? #f)
-                                    (set! dual-subtotal #f))
-                                  ;; Default; not merging/completed merge. Just
-                                  ;; display monetary amount
-                                  (addto! row-contents
-                                          (gnc:make-html-table-cell/markup "total-number-cell" mon))))))
-                      columns
-                      merge-list)))
+          (let loop ((merging? #f)
+                     (last-column #f)
+                     (columns columns)
+                     (merge-list merge-list))
+            (if (not (null? columns))
+                (let* ((mon (retrieve-commodity (car columns) commodity))
+                       (this-column (and mon (gnc:gnc-monetary-amount mon))))
+                  (if (car merge-list)
+                      ;; We're merging. If a subtotal exists, send to next loop iteration.
+                      (loop #t
+                            this-column
+                            (cdr columns)
+                            (cdr merge-list))
+                      (begin
+                        (if merging?
+                            ;; We're completing merge. Display debit-credit in correct column.
+                            (let* ((sum (and (or last-column this-column)
+                                             (- (or last-column 0) (or this-column 0))))
+                                   (sum-table-cell (and sum (gnc:make-html-table-cell/markup
+                                                             "total-number-cell"
+                                                             (gnc:make-gnc-monetary
+                                                              commodity (abs sum)))))
+                                   (debit-col (and sum (positive? sum) sum-table-cell))
+                                   (credit-col (and sum (not (positive? sum)) sum-table-cell)))
+                              (addto! row-contents (or debit-col ""))
+                              (addto! row-contents (or credit-col "")))
+                            ;; Default; not merging nor completed merge. Display monetary amount
+                            (addto! row-contents (gnc:make-html-table-cell/markup "total-number-cell" mon)))
+                        (loop #f
+                              #f
+                              (cdr columns)
+                              (cdr merge-list))))))))
 
         ;; we only wish to add the first column into the grid.
         (if (pair? columns)

commit 3a44b368d46e350a90671450529364c508a22a74
Merge: 3a46088 34c4644
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 17:36:09 2018 +0200

    Merge branch 'unstable' of https://github.com/Abschiedsstein/gnucash into unstable


commit 3a46088ca8eed6e6539a1fc7922ce86010684c3e
Merge: a8c17c2 c9fd683
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 17:23:21 2018 +0200

    Merge branch 'fixes2' of https://github.com/Bob-IT/gnucash into unstable


commit a8c17c2078bbd2dc901fc8d3f88ee326f4759b86
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 12:05:30 2018 +0200

    Bug 795155 - CSV import does not distinguish between deposit and withdrawal

diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
index db16b7f..7c4246d 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
@@ -624,7 +624,7 @@ void GncPreSplit::create_split (Transaction* trans)
     if (m_withdrawal)
         withdrawal = *m_withdrawal;
 
-    amount = deposit + withdrawal;
+    amount = deposit - withdrawal;
 
     /* Add a split with the cumulative amount value. */
     trans_add_split (trans, account, amount, m_action, m_memo, m_rec_state, m_rec_date, m_price);

commit d567ee104923b4e567d7369cb545107186473fe8
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 11:48:11 2018 +0200

    Bug 769686 - Notes not imported when using update and reconcile in import transactions from CSV

diff --git a/gnucash/import-export/import-backend.c b/gnucash/import-export/import-backend.c
index 83a013c..e538563 100644
--- a/gnucash/import-export/import-backend.c
+++ b/gnucash/import-export/import-backend.c
@@ -982,6 +982,10 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
                                     xaccTransGetDescription(
                                         gnc_import_TransInfo_get_trans(trans_info)));
 
+            xaccTransSetNotes(selected_match->trans,
+                                    xaccTransGetNotes(
+                                        gnc_import_TransInfo_get_trans(trans_info)));
+
             if (xaccSplitGetReconcile(selected_match->split) == NREC)
             {
                 xaccSplitSetReconcile(selected_match->split, CREC);

commit 7321c995b4ec73574255ba55f5e1ce50fe7e9d25
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 12:01:32 2018 +0200

    csv-impport - Allow empty amount fields
    
    Treat empty amount fields as 0. This is necessary for example in the case the
    csv import file has both a deposit and a withdrawal column.
    
    Note this issue was masked by the bug fixed in the previus commit.

diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
index 650f4e9..db16b7f 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
@@ -102,7 +102,11 @@ GncTransPropType sanitize_trans_prop (GncTransPropType prop, bool multi_split)
  */
 GncNumeric parse_amount (const std::string &str, int currency_format)
 {
-    /* If a cell is empty or just spaces return invalid amount */
+    /* An empty field is treated as zero */
+    if (str.empty())
+        return GncNumeric{};
+
+    /* Strings otherwise containing not digits will be considered invalid */
     if(!boost::regex_search(str, boost::regex("[0-9]")))
         throw std::invalid_argument (_("Value doesn't appear to contain a valid number."));
 

commit 10f8f6a7507d3b46eea82255166894024fc0fc70
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 11:27:06 2018 +0200

    Bug 795082 - CSV import crashes if a transaction's 'Account' field is empty and no default Account set

diff --git a/gnucash/import-export/csv-imp/gnc-import-tx.cpp b/gnucash/import-export/csv-imp/gnc-import-tx.cpp
index 8dd940e..34d68b7 100644
--- a/gnucash/import-export/csv-imp/gnc-import-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-import-tx.cpp
@@ -790,17 +790,14 @@ void GncTxImport::update_pre_split_props (uint32_t row, uint32_t col, GncTransPr
         return; /* Only deal with split related properties. */
 
     auto split_props = std::get<PL_PRESPLIT>(m_parsed_lines[row]);
-    auto value = std::string();
 
-    if (col < std::get<PL_INPUT>(m_parsed_lines[row]).size())
-        value = std::get<PL_INPUT>(m_parsed_lines[row]).at(col);
-
-    if (value.empty())
+    if (col == std::get<PL_INPUT>(m_parsed_lines[row]).size())
         split_props->reset (prop_type);
     else
     {
         try
         {
+            auto value = std::get<PL_INPUT>(m_parsed_lines[row]).at(col);
             split_props->set(prop_type, value);
         }
         catch (const std::exception& e)

commit e2535abb954334bda7292699110acf4111abc988
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Sat Apr 14 08:17:34 2018 +0200

    Remove reference to GTEST_DISABLE, it no longer exists
    
    The google test framework is a required dependency.

diff --git a/cmake/README_CMAKE.txt b/cmake/README_CMAKE.txt
index 4d936ed..8d2ce15 100644
--- a/cmake/README_CMAKE.txt
+++ b/cmake/README_CMAKE.txt
@@ -3,8 +3,9 @@ Using CMake to build GnuCash
 
 == Intro
 
-As part of his CuteCash work, Christian Stimming added support for
-using http://www.cmake.org[CMake] to build the part of GnuCash that
+As part of his CuteCash experiment (now removed from the repository),
+Christian Stimming added support for using
+http://www.cmake.org[CMake] to build the part of GnuCash that
 went into CuteCash. This work extends the use of CMake to cover all of
 GnuCash proper such that GnuCash itself can be fully compiled with
 CMake.
@@ -123,8 +124,7 @@ Then decide what cmake command line options you will need:
 
  * Google Test will work without setting options in most Linux distros, but if
    it doesn't you may need to set GMOCK_ROOT or GTEST_ROOT to the root of the
-   respective sources. Set GTEST_DISABLE to prevent Google Test based tests from
-   running.
+   respective sources.
 
 Some examples:
 

commit c9fd6832b83a1f93a4895144a1144c6a44b06913
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 03:57:39 2018 +0100

    Bug 795142 - Unable to enter account codes in business sheets
    
    In Bills, Invoices and Expense vouchers you can not enter an account
    code in an account field like you can on a normal register, enable this.

diff --git a/gnucash/register/ledger-core/gncEntryLedger.c b/gnucash/register/ledger-core/gncEntryLedger.c
index 91d0736..645e809 100644
--- a/gnucash/register/ledger-core/gncEntryLedger.c
+++ b/gnucash/register/ledger-core/gncEntryLedger.c
@@ -92,6 +92,8 @@ gnc_entry_ledger_get_account_by_name (GncEntryLedger *ledger, BasicCell * bcell,
 
     /* Find the account */
     account = gnc_account_lookup_for_register (gnc_get_current_root_account (), name);
+    if (!account)
+        account = gnc_account_lookup_by_code (gnc_get_current_root_account(), name);
 
     if (!account)
     {
@@ -116,13 +118,16 @@ gnc_entry_ledger_get_account_by_name (GncEntryLedger *ledger, BasicCell * bcell,
         if (!account)
             return NULL;
         *isnew = TRUE;
-
-        /* Now have a new account. Update the cell with the name as created. */
-        account_name = gnc_get_account_name_for_register (account);
+    }
+    
+    /* Now have a new account. Update the cell with the name as created. */
+    account_name = gnc_get_account_name_for_register (account);
+    if (g_strcmp0(account_name, gnc_basic_cell_get_value(bcell)))
+    {
         gnc_combo_cell_set_value (cell, account_name);
         gnc_basic_cell_set_changed (&cell->cell, TRUE);
-        g_free (account_name);
     }
+    g_free (account_name);
 
     /* See if the account (either old or new) is a placeholder. */
     if (xaccAccountGetPlaceholder (account))

commit 805094d570c9416dd810a459d4a639d39d38108e
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 03:56:14 2018 +0100

    Remove trailing spaces and replace tabs with spaces
    
    Remove trailing spaces and replace tabs with spaces in the reconcile
    source files.

diff --git a/gnucash/gnome-utils/gnc-query-view.c b/gnucash/gnome-utils/gnc-query-view.c
index 0e53a8e..78dbe3b 100644
--- a/gnucash/gnome-utils/gnc-query-view.c
+++ b/gnucash/gnome-utils/gnc-query-view.c
@@ -46,7 +46,7 @@ typedef struct _GNCQueryViewPriv GNCQueryViewPriv;
 struct _GNCQueryViewPriv
 {
     const QofParam *get_guid;
-    gint	    component_id;
+    gint        component_id;
 };
 
 #define GNC_QUERY_VIEW_GET_PRIVATE(o)  \
@@ -82,14 +82,14 @@ gnc_query_view_get_type (void)
     {
         GTypeInfo type_info =
         {
-            sizeof(GNCQueryViewClass),          /* class_size */
-            NULL,   				/* base_init */
-            NULL,				/* base_finalize */
+            sizeof(GNCQueryViewClass), /* class_size */
+            NULL,                      /* base_init */
+            NULL,                      /* base_finalize */
             (GClassInitFunc)gnc_query_view_class_init,
-            NULL,				/* class_finalize */
-            NULL,				/* class_data */
-            sizeof (GNCQueryView),		/* */
-            0,				        /* n_preallocs */
+            NULL,                      /* class_finalize */
+            NULL,                      /* class_data */
+            sizeof (GNCQueryView),     /* */
+            0,                         /* n_preallocs */
             (GInstanceInitFunc)gnc_query_view_init,
         };
 
@@ -366,13 +366,13 @@ gnc_query_view_init_view (GNCQueryView *qview)
         if (((GNCSearchParam *) param)->passive)
             gtk_tree_view_column_set_clickable (col, FALSE);
         else
-	{
+        {
             gtk_tree_view_column_set_clickable (col, TRUE);
             /* Add sortable columns */
             gtk_tree_view_column_set_sort_column_id (col, i+1);
             gtk_tree_sortable_set_sort_func (sortable, i+1, sort_iter_compare_func,
                                     GINT_TO_POINTER (i+1), NULL);
-	}
+        }
 
         type = gnc_search_param_get_param_type (((GNCSearchParam *) param));
 
@@ -525,7 +525,7 @@ gnc_query_view_double_click_cb (GtkTreeView       *view,
 
     model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
 
-    if (gtk_tree_model_get_iter (model, &iter, path)) 
+    if (gtk_tree_model_get_iter (model, &iter, path))
         gtk_tree_model_get (model, &iter, 0, &entry, -1);
 
     qview->selected_entry = entry;
@@ -557,7 +557,7 @@ gnc_query_view_toggled_cb (GtkCellRendererToggle *cell_renderer,
 
     treepath = gtk_tree_path_new_from_string (path);
 
-    if (gtk_tree_model_get_iter(model, &iter, treepath)) 
+    if (gtk_tree_model_get_iter(model, &iter, treepath))
     {
         gtk_tree_model_get (model, &iter, 0, &entry, -1);
         indices = gtk_tree_path_get_indices (treepath);
@@ -711,7 +711,7 @@ gnc_query_view_refresh (GNCQueryView *qview)
  *   sets the sorting order of entries in the view                  *
  *                                                                  *
  * Args: qview      - view to change the sort order for             *
- *	 new_column - is this a new column (so should we set the    *
+ *   new_column - is this a new column (so should we set the    *
  *                    query sort order or just set the 'increasing' *
  * Returns: nothing                                                 *
 \********************************************************************/
@@ -833,7 +833,8 @@ gnc_query_view_fill (GNCQueryView *qview)
 
                 if (qview->numeric_abs)
                     value = gnc_numeric_abs (value);
-                gtk_list_store_set (GTK_LIST_STORE (model), &iter, i + 1, xaccPrintAmount (value, gnc_default_print_info (FALSE)), -1);
+                gtk_list_store_set (GTK_LIST_STORE (model), &iter, i + 1,
+                     xaccPrintAmount (value, gnc_default_print_info (FALSE)), -1);
             }
             else
             {
diff --git a/gnucash/gnome/reconcile-view.c b/gnucash/gnome/reconcile-view.c
index 70e310d..a4e7404 100644
--- a/gnucash/gnome/reconcile-view.c
+++ b/gnucash/gnome/reconcile-view.c
@@ -1,7 +1,7 @@
 /********************************************************************\
  * reconcile-view.c -- A view of accounts to be reconciled for      *
  *                     GnuCash.                                     *
- * Copyright (C) 1998,1999 Jeremy Collins	                    *
+ * Copyright (C) 1998,1999 Jeremy Collins                           *
  * Copyright (C) 1998-2000 Linas Vepstas                            *
  * Copyright (C) 2012 Robert Fewell                                 *
  *                                                                  *
@@ -65,7 +65,7 @@ static void gnc_reconcile_view_double_click_entry (GNCQueryView *qview, gpointer
 static void gnc_reconcile_view_row_selected (GNCQueryView *qview, gpointer item, gpointer user_data);
 static gboolean gnc_reconcile_view_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
 static gboolean gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y, gboolean keyboard_mode,
-					 GtkTooltip* tooltip, gpointer* user_data);
+                     GtkTooltip* tooltip, gpointer* user_data);
 
 GType
 gnc_reconcile_view_get_type (void)
@@ -97,7 +97,7 @@ gnc_reconcile_view_get_type (void)
 
 static gboolean
 gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y,
-	gboolean keyboard_mode, GtkTooltip *tooltip, gpointer *user_data)
+    gboolean keyboard_mode, GtkTooltip *tooltip, gpointer *user_data)
 {
     GtkTreeModel* model;
     GtkTreeIter iter;
@@ -108,7 +108,7 @@ gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y,
         GtkTreeViewColumn *col;
         GList *cols;
         gint col_pos, col_width;
-	gchar* desc_text = NULL;
+        gchar* desc_text = NULL;
 
         /* Are we in keyboard tooltip mode, displays tooltip below/above treeview CTRL+F1 */
         if (keyboard_mode == FALSE)
@@ -170,7 +170,6 @@ gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y,
                 device_manager = gdk_display_get_device_manager (gdk_window_get_display (parent_window));
                 pointer = gdk_device_manager_get_client_pointer (device_manager);
 #endif
-
                 gdk_window_get_device_position (parent_window, pointer, &cur_x, &cur_y, NULL);
 
                 gdk_window_get_origin (parent_window, &root_x, &root_y);
@@ -189,7 +188,7 @@ gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y,
                 }
                 g_list_free (win_list);
 
-	        gtk_tooltip_set_text (tooltip, desc_text);
+                gtk_tooltip_set_text (tooltip, desc_text);
 
                 if (GTK_IS_WINDOW (tip_win))
                 {
@@ -214,7 +213,6 @@ gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y,
                     monitor_num = gdk_screen_get_monitor_at_point (screen, x, y);
                     gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
 #endif
-
                     if (x + requisition.width > monitor.x + monitor.width)
                         x -= x - (monitor.x + monitor.width) + requisition.width;
                     else if (x < monitor.x)
@@ -226,9 +224,9 @@ gnc_reconcile_view_tooltip_cb (GNCQueryView *qview, gint x, gint y,
                     gtk_window_move (tip_win, x, y);
                 }
             }
-	    gtk_tooltip_set_text (tooltip, desc_text);
+            gtk_tooltip_set_text (tooltip, desc_text);
             g_free (desc_text);
-	    return TRUE;
+            return TRUE;
         }
     }
     return FALSE;
@@ -365,8 +363,8 @@ gnc_reconcile_view_new (Account *account, GNCReconcileViewType type,
             g_assert (recn == NREC || recn == CREC);
 
             if (recn == CREC &&
-		gnc_difftime (trans_date, statement_date_day_end) <= 0)
-		g_hash_table_insert (view->reconciled, split, split);
+        gnc_difftime (trans_date, statement_date_day_end) <= 0)
+        g_hash_table_insert (view->reconciled, split, split);
         }
     }
 
@@ -675,7 +673,7 @@ gnc_reconcile_view_set_list ( GNCReconcileView  *view, gboolean reconcile)
 }
 
 
-gint 
+gint
 gnc_reconcile_view_num_selected (GNCReconcileView  *view )
 {
     GNCQueryView      *qview = GNC_QUERY_VIEW(view);
@@ -950,7 +948,7 @@ gnc_reconcile_view_postpone (GNCReconcileView *view)
         // Don't change splits past reconciliation date that haven't been
         // set to be reconciled
         if (gnc_difftime (view->statement_date,
-			  xaccTransGetDate (xaccSplitGetParent (entry))) >= 0 ||
+              xaccTransGetDate (xaccSplitGetParent (entry))) >= 0 ||
                 g_hash_table_lookup (view->reconciled, entry))
         {
             recn = g_hash_table_lookup (view->reconciled, entry) ? CREC : NREC;
@@ -994,4 +992,3 @@ gnc_reconcile_view_changed (GNCReconcileView *view)
 
     return g_hash_table_size (view->reconciled) != 0;
 }
-
diff --git a/gnucash/gnome/window-reconcile.c b/gnucash/gnome/window-reconcile.c
index 5c849bc..8405a32 100644
--- a/gnucash/gnome/window-reconcile.c
+++ b/gnucash/gnome/window-reconcile.c
@@ -131,12 +131,12 @@ typedef struct _startRecnWindowData
  */
 #define account_type_has_auto_interest_charge(type)  (((type) == ACCT_TYPE_CREDIT) || \
                                                       ((type) == ACCT_TYPE_LIABILITY) ||\
-						      ((type) == ACCT_TYPE_PAYABLE))
+                              ((type) == ACCT_TYPE_PAYABLE))
 
 #define account_type_has_auto_interest_payment(type) (((type) == ACCT_TYPE_BANK)  || \
                                                       ((type) == ACCT_TYPE_ASSET) || \
                                                       ((type) == ACCT_TYPE_MUTUAL) || \
-						      ((type) == ACCT_TYPE_RECEIVABLE))
+                              ((type) == ACCT_TYPE_RECEIVABLE))
 
 #define account_type_has_auto_interest_xfer(type) \
   (  account_type_has_auto_interest_charge(type) || \
@@ -480,7 +480,8 @@ recnInterestXferWindow( startRecnWindowData *data)
 {
     gchar *title;
 
-    if ( !account_type_has_auto_interest_xfer( data->account_type ) ) return;
+    if ( !account_type_has_auto_interest_xfer( data->account_type ) )
+        return;
 
     /* get a normal transfer dialog... */
     data->xferData = gnc_xfer_dialog( GTK_WIDGET(data->startRecnWindow),

commit dd28f4ed4f95d1630180a9a836e0ae5bcde8d1e7
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 03:23:57 2018 +0100

    Remove the set transient parent setting for Reconcile window
    
    The Reconcile option is already a window so it is not necessary to set
    this value which allows the jump to transaction to work properly.

diff --git a/gnucash/gnome/window-reconcile.c b/gnucash/gnome/window-reconcile.c
index 2581d50..5c849bc 100644
--- a/gnucash/gnome/window-reconcile.c
+++ b/gnucash/gnome/window-reconcile.c
@@ -1662,7 +1662,7 @@ recnWindow (GtkWidget *parent, Account *account)
             enable_subaccounts))
         return NULL;
 
-    return recnWindowWithBalance (parent, account, new_ending, statement_date);
+    return recnWindowWithBalance (account, new_ending, statement_date);
 }
 
 
@@ -1682,15 +1682,14 @@ recnWindow_add_widget (GtkUIManager *merge,
  *   Opens up the window to reconcile an account, but with ending
  *   balance and statement date already given.
  *
- * Args:   parent         - The parent widget of the new window
- *         account        - The account to reconcile
+ * Args:   account        - The account to reconcile
  *         new_ending     - The amount for ending balance
  *         statement_date - The date of the statement
  * Return: recnData - the instance of this RecnWindow
 \********************************************************************/
 RecnWindow *
-recnWindowWithBalance (GtkWidget *parent, Account *account,
-                       gnc_numeric new_ending, time64 statement_date)
+recnWindowWithBalance (Account *account, gnc_numeric new_ending,
+                       time64 statement_date)
 {
     RecnWindow *recnData;
     GtkWidget *statusbar;
@@ -1924,8 +1923,6 @@ recnWindowWithBalance (GtkWidget *parent, Account *account,
 
     /* Allow resize */
     gtk_window_set_resizable(GTK_WINDOW(recnData->window), TRUE);
-    gtk_window_set_transient_for(GTK_WINDOW(recnData->window),
-                                 GTK_WINDOW (parent));
     gtk_widget_show_all(recnData->window);
 
     gnc_reconcile_window_set_titles(recnData);
diff --git a/gnucash/gnome/window-reconcile.h b/gnucash/gnome/window-reconcile.h
index 26dc8ad..0516140 100644
--- a/gnucash/gnome/window-reconcile.h
+++ b/gnucash/gnome/window-reconcile.h
@@ -52,14 +52,12 @@ RecnWindow *recnWindow (GtkWidget *parent, Account *account);
  *   Opens up the window to reconcile an account, but with ending
  *   balance and statement date already given.
  *
- * Args:   parent         - The parent widget of the new window
- *         account        - The account to reconcile
+ * Args:   account        - The account to reconcile
  *         new_ending     - The amount for ending balance
  *         statement_date - The date of the statement
  * Return: recnData - the instance of this RecnWindow
 \********************************************************************/
-RecnWindow *recnWindowWithBalance (GtkWidget *parent,
-                                   Account *account,
+RecnWindow *recnWindowWithBalance (Account *account,
                                    gnc_numeric new_ending,
                                    time64 statement_date);
 
diff --git a/gnucash/import-export/aqb/gnc-ab-utils.c b/gnucash/import-export/aqb/gnc-ab-utils.c
index 549fd28..03d6539 100644
--- a/gnucash/import-export/aqb/gnc-ab-utils.c
+++ b/gnucash/import-export/aqb/gnc-ab-utils.c
@@ -1060,7 +1060,7 @@ bal_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data)
 
     /* Show reconciliation window */
     if (show_recn_window)
-        recnWindowWithBalance(data->parent, gnc_acc, value, booked_tt);
+        recnWindowWithBalance(gnc_acc, value, booked_tt);
 
     return NULL;
 }

commit 48db993932c6c5e9dde862fe5074544737db8f78
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 03:22:51 2018 +0100

    Align the reconcile column titles to that of the values

diff --git a/gnucash/gnome-utils/gnc-query-view.c b/gnucash/gnome-utils/gnc-query-view.c
index aef5b6f..0e53a8e 100644
--- a/gnucash/gnome-utils/gnc-query-view.c
+++ b/gnucash/gnome-utils/gnc-query-view.c
@@ -350,6 +350,9 @@ gnc_query_view_init_view (GNCQueryView *qview)
         else if (((GNCSearchParam *) param)->justify == GTK_JUSTIFY_RIGHT)
             algn = 1.0;
 
+        /* Set the column title alignment to that of the column */
+        gtk_tree_view_column_set_alignment (col, algn);
+
         /* Set column resizable */
         if (((GNCSearchParam *) param)->non_resizeable)
         {

commit 9094f6e5a9ae4ef3e2e05fcdefbdaaf593975469
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 03:18:49 2018 +0100

    Bug 795101 - Scrollbar floats and covers toggle buttons
    
    When the scrollbar appears for the reconcile windows it can float above
    the reconcile toggle button which make it difficult to toggle. Move this
    column to the start which has the advantage of aligning the amount
    column above the Total value.

diff --git a/gnucash/gnome/reconcile-view.c b/gnucash/gnome/reconcile-view.c
index 99829f9..70e310d 100644
--- a/gnucash/gnome/reconcile-view.c
+++ b/gnucash/gnome/reconcile-view.c
@@ -262,7 +262,7 @@ gnc_reconcile_view_construct (GNCReconcileView *view, Query *query)
     gnc_query_view_set_numerics (qview, TRUE, inv_sort);
 
     /* Set the description field to have spare space */
-    col = gtk_tree_view_get_column (GTK_TREE_VIEW (qview), 2);
+    col = gtk_tree_view_get_column (GTK_TREE_VIEW (qview), 3);
     gtk_tree_view_column_set_expand (col, TRUE);
 
     /* Get the renderer of the description column and set ellipsize value */
@@ -310,8 +310,8 @@ gnc_reconcile_view_new (Account *account, GNCReconcileViewType type,
 
     /* Create the list store with 6 columns and add to treeview,
        column 0 will be a pointer to the entry */
-    liststore = gtk_list_store_new (6, G_TYPE_POINTER, G_TYPE_STRING, 
-                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN );
+    liststore = gtk_list_store_new (6, G_TYPE_POINTER, G_TYPE_BOOLEAN,
+                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
     gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (liststore));
     g_object_unref (liststore);
 
@@ -389,14 +389,6 @@ gnc_reconcile_view_init (GNCReconcileView *view)
     view->account = NULL;
     view->sibling = NULL;
 
-    param = gnc_search_param_simple_new();
-    gnc_search_param_set_param_fcn (param, QOF_TYPE_BOOLEAN,
-                                    gnc_reconcile_view_is_reconciled, view);
-    gnc_search_param_set_title ((GNCSearchParam *) param, _("Reconciled:R") + 11);
-    gnc_search_param_set_justify ((GNCSearchParam *) param, GTK_JUSTIFY_CENTER);
-    gnc_search_param_set_passive ((GNCSearchParam *) param, TRUE);
-    gnc_search_param_set_non_resizeable ((GNCSearchParam *) param, TRUE);
-    columns = g_list_prepend (columns, param);
     columns = gnc_search_param_prepend_with_justify (columns, _("Amount"),
               GTK_JUSTIFY_RIGHT,
               NULL, GNC_ID_SPLIT,
@@ -416,6 +408,15 @@ gnc_reconcile_view_init (GNCReconcileView *view)
     columns = gnc_search_param_prepend (columns, _("Date"), NULL, GNC_ID_SPLIT,
                                         SPLIT_TRANS, TRANS_DATE_POSTED, NULL);
 
+    param = gnc_search_param_simple_new();
+    gnc_search_param_set_param_fcn (param, QOF_TYPE_BOOLEAN,
+                                    gnc_reconcile_view_is_reconciled, view);
+    gnc_search_param_set_title ((GNCSearchParam *) param, _("Reconciled:R") + 11);
+    gnc_search_param_set_justify ((GNCSearchParam *) param, GTK_JUSTIFY_CENTER);
+    gnc_search_param_set_passive ((GNCSearchParam *) param, TRUE);
+    gnc_search_param_set_non_resizeable ((GNCSearchParam *) param, TRUE);
+    columns = g_list_prepend (columns, param);
+
     view->column_list = columns;
 }
 
@@ -546,8 +547,8 @@ gnc_reconcile_view_toggle_children (Account *account, GNCReconcileView *view, Sp
             if(pointer == other_split)
             {
                 gboolean toggled;
-                gtk_tree_model_get (model, &iter, 5, &toggled, -1);
-                gtk_list_store_set (GTK_LIST_STORE (model), &iter, 5, !toggled, -1);
+                gtk_tree_model_get (model, &iter, 1, &toggled, -1);
+                gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, !toggled, -1);
                 break;
             }
 
@@ -661,9 +662,9 @@ gnc_reconcile_view_set_list ( GNCReconcileView  *view, gboolean reconcile)
         {
             /* now iter is a valid row iterator */
             gtk_tree_model_get (model, &iter, 0, &entry, -1);
-            gtk_tree_model_get (model, &iter, 5, &toggled, -1);
+            gtk_tree_model_get (model, &iter, 1, &toggled, -1);
 
-            gtk_list_store_set (GTK_LIST_STORE (model), &iter, 5, reconcile, -1);
+            gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, reconcile, -1);
 
             if(reconcile != toggled)
                 gnc_reconcile_view_toggle (view, entry);
@@ -710,7 +711,7 @@ gnc_reconcile_view_set_toggle (GNCReconcileView  *view)
         if(gtk_tree_model_get_iter(model, &iter, node->data))
         {
             /* now iter is a valid row iterator */
-            gtk_tree_model_get (model, &iter, 5, &toggled, -1);
+            gtk_tree_model_get (model, &iter, 1, &toggled, -1);
 
             if(toggled)
                 num_toggled++;
diff --git a/gnucash/gnome/window-reconcile.c b/gnucash/gnome/window-reconcile.c
index d080647..2581d50 100644
--- a/gnucash/gnome/window-reconcile.c
+++ b/gnucash/gnome/window-reconcile.c
@@ -1185,6 +1185,12 @@ gnc_reconcile_window_create_view_box(Account *account,
     gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
+#if GTK_CHECK_VERSION(3,12,0)
+    gtk_widget_set_margin_end (GTK_WIDGET(hbox), 10);
+#else
+    gtk_widget_set_margin_right (GTK_WIDGET(hbox), 10);
+#endif
+
     label = gtk_label_new(_("Total:"));
     gnc_label_set_alignment(label, 1.0, 0.5);
     gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);

commit 6114105115de5accaa49ab589b2985fd4a31ca93
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 00:09:34 2018 +0100

    Save the tab label width so we do not have to get it again

diff --git a/gnucash/gnome-utils/gnc-main-window.c b/gnucash/gnome-utils/gnc-main-window.c
index 2a15582..c50a413 100644
--- a/gnucash/gnome-utils/gnc-main-window.c
+++ b/gnucash/gnome-utils/gnc-main-window.c
@@ -2046,9 +2046,10 @@ gnc_main_window_set_tab_ellipsize (GtkWidget *label, gint tab_width)
 
     if (tab_width != 0)
     {
-        if (g_utf8_strlen (lab_text, -1) < tab_width)
+        gint text_length = g_utf8_strlen (lab_text, -1);
+        if (text_length < tab_width)
         {
-            gtk_label_set_width_chars (GTK_LABEL(label), strlen (lab_text));
+            gtk_label_set_width_chars (GTK_LABEL(label), text_length);
             gtk_label_set_ellipsize (GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
         }
         else

commit e81b2ccca3a97781f14951b60b6fc4c5712ed94b
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat Apr 14 00:05:25 2018 +0100

    Date Format dialog flashes up when file/properties used
    
    When you select the File/Properties dialog, in the construction of that
    a 'Date Format' dialog flashes up while the date component is moved to
    the properties dialog. Can mainly be seen on Windows so remove the
    visible setting in glade file.

diff --git a/gnucash/gtkbuilder/gnc-date-format.glade b/gnucash/gtkbuilder/gnc-date-format.glade
index b51369c..5b02e29 100644
--- a/gnucash/gtkbuilder/gnc-date-format.glade
+++ b/gnucash/gtkbuilder/gnc-date-format.glade
@@ -35,7 +35,6 @@
     </data>
   </object>
   <object class="GtkWindow" id="gnc_date_format_window">
-    <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="title" translatable="yes">Date Format</property>
     <property name="resizable">False</property>

commit 4a97269e4b0ea9afc213b7f6fb839895eb65f599
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Apr 12 15:16:29 2018 -0700

    Correct a g_log_level in test_gnc_pricedb_lookup_day.

diff --git a/libgnucash/engine/test/utest-gnc-pricedb.c b/libgnucash/engine/test/utest-gnc-pricedb.c
index 34824a3..345a34d 100644
--- a/libgnucash/engine/test/utest-gnc-pricedb.c
+++ b/libgnucash/engine/test/utest-gnc-pricedb.c
@@ -1070,7 +1070,7 @@ static void
 test_gnc_pricedb_lookup_day (PriceDBFixture *fixture, gconstpointer pData)
 {
     gchar *msg1 = "[gnc_dmy2timespec_internal()] Date computation error from Y-M-D 12-11-18: Year is out of valid range: 1400..10000";
-    gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+    gint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
     gchar *logdomain = "qof.engine";
     TestErrorStruct check = {loglevel, logdomain, msg1, 0};
     GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);

commit 85cc574d5071d945bb6174b4ffa5f30037592842
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Apr 12 15:15:33 2018 -0700

    Prevent throw in gnc-pricedb.
    
    If a price lookup is given an invalid time64/timespec (i.e. INT64_MAX)
    then just return NULL instead of trying to find the nearest price.

diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c
index 186f697..62e3111 100644
--- a/libgnucash/engine/gnc-pricedb.c
+++ b/libgnucash/engine/gnc-pricedb.c
@@ -2348,6 +2348,7 @@ lookup_nearest_in_time(GNCPriceDB *db,
     GList *item = NULL;
 
     if (!db || !c || !currency) return NULL;
+    if (t.tv_sec == INT64_MAX) return NULL;
     ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
     price_list = pricedb_get_prices_internal (db, c, currency, TRUE);
     if (!price_list) return NULL;

commit 16ba1e39b13f90beb9f17afd32474e766480ff2d
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Apr 12 15:12:14 2018 -0700

    Bug 795080 - Some dates reset to 01/01/1970
    
    An odd corner case: BST apparently came off of DST at 23:00 26 Oct 2014,
    so midnight that day was ambiguous about being DST or not; that causes
    the local_date_time constructor to throw in spite of the tm.is_dst element
    being 0 (meaning pick standard time).
    
    Instead of just failing in that case, try constructing a local_date_time
    three hours later then adjust it back three hours. If *that* doesn't work
    then throw a std::invalid argument.

diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp
index 0c43372..d0958de 100644
--- a/libgnucash/engine/gnc-datetime.cpp
+++ b/libgnucash/engine/gnc-datetime.cpp
@@ -158,12 +158,12 @@ LDT_from_unix_local(const time64 time)
 static LDT
 LDT_from_struct_tm(const struct tm tm)
 {
+    auto tdate = boost::gregorian::date_from_tm(tm);
+    auto tdur = boost::posix_time::time_duration(tm.tm_hour, tm.tm_min,
+                                                 tm.tm_sec, 0);
+    auto tz = tzp.get(tdate.year());
     try
     {
-        auto tdate = boost::gregorian::date_from_tm(tm);
-        auto tdur = boost::posix_time::time_duration(tm.tm_hour, tm.tm_min,
-                                                     tm.tm_sec, 0);
-        auto tz = tzp.get(tdate.year());
         LDT ldt(tdate, tdur, tz, LDTBase::EXCEPTION_ON_ERROR);
         return ldt;
     }
@@ -177,7 +177,18 @@ LDT_from_struct_tm(const struct tm tm)
     }
     catch(boost::local_time::ambiguous_result&)
     {
-        throw(std::invalid_argument("Struct tm can resolve to more than one time."));
+        /* We plunked down in the middle of a DST change. Try constructing the
+         * LDT three hours later to get a valid result then back up those three
+         * hours to have the time we want.
+         */
+        using boost::posix_time::hours;
+        auto hour = tm.tm_hour;
+        tdur += hours(3);
+        LDT ldt(tdate, tdur, tz, LDTBase::NOT_DATE_TIME_ON_ERROR);
+        if (ldt.is_special())
+            throw(std::invalid_argument("Couldn't create a valid datetime."));
+        ldt -= hours(3);
+        return ldt;
     }
 }
 

commit b5ac8591fcbf71c8a6a14caa707e055c49ed96a3
Merge: 6810c2a 8bfbc77
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Tue Apr 10 19:11:13 2018 +0200

    Merge branch 'fixes' of https://github.com/Bob-IT/gnucash into unstable


commit 868489b1c4f9b1f64fe61130e6ae28b4bad16f22
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Apr 10 09:52:02 2018 -0700

    Fix typo.

diff --git a/src/backend/dbi/gnc-backend-dbi.c b/src/backend/dbi/gnc-backend-dbi.c
index 29bd82d..824486a 100644
--- a/src/backend/dbi/gnc-backend-dbi.c
+++ b/src/backend/dbi/gnc-backend-dbi.c
@@ -3327,7 +3327,7 @@ conn_test_dbi_library( dbi_conn conn )
     memset( doublestr, 0, sizeof(doublestr));
 
     result = dbi_conn_query (conn, "DROP TABLE IF EXISTS numtest;");
-    result = dbi_conn_query (con, "CREATE TEMPORARY TABLE numtest "
+    result = dbi_conn_query (conn, "CREATE TEMPORARY TABLE numtest "
                              "( test_int BIGINT, test_unsigned BIGINT,"
                              " test_double FLOAT8 )");
     if ( result == NULL )

commit b1915a0b89396446f0bf2fb6c78bed32eab3ee08
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Apr 10 09:34:06 2018 -0700

    Bug 795049 - GnuCash 2.6.20-1 (Fedora Linux package) is unable to open...
    
    MariaDB.
    MariaDB (and probably MySQL) doesn't accept two queries in a single
    command.

diff --git a/src/backend/dbi/gnc-backend-dbi.c b/src/backend/dbi/gnc-backend-dbi.c
index 5708f78..29bd82d 100644
--- a/src/backend/dbi/gnc-backend-dbi.c
+++ b/src/backend/dbi/gnc-backend-dbi.c
@@ -3326,10 +3326,10 @@ conn_test_dbi_library( dbi_conn conn )
     GncDbiTestResult retval = GNC_DBI_PASS;
     memset( doublestr, 0, sizeof(doublestr));
 
-    result = dbi_conn_query( conn, "DROP TABLE IF EXISTS numtest;"
-                             "CREATE TEMPORARY TABLE numtest "
+    result = dbi_conn_query (conn, "DROP TABLE IF EXISTS numtest;");
+    result = dbi_conn_query (con, "CREATE TEMPORARY TABLE numtest "
                              "( test_int BIGINT, test_unsigned BIGINT,"
-                             " test_double FLOAT8 )" );
+                             " test_double FLOAT8 )");
     if ( result == NULL )
     {
         PWARN("Test_DBI_Library: Create table failed");

commit cdeee96074211ee8a16f2cf666398525def81341
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Apr 10 09:30:58 2018 -0700

    Revert "Bug 795049 - GnuCash 2.6.20-1 (Fedora Linux package) is unable to open..."
    
    This reverts commit aea33ca515aceb4f63a5cbc8165d4ec93f245d0c because
    it doesn't fix the problem, just tests that the problem is only on
    MySQL/MariaDB.

diff --git a/src/backend/dbi/test/test-backend-dbi-basic.c b/src/backend/dbi/test/test-backend-dbi-basic.c
index 4a55a62..386a2c3 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.c
+++ b/src/backend/dbi/test/test-backend-dbi-basic.c
@@ -666,15 +666,15 @@ test_suite_gnc_backend_dbi (void)
     }
     if (g_list_find_custom (drivers, "sqlite3", (GCompareFunc)g_strcmp0))
         create_dbi_test_suite ("sqlite3", "sqlite3");
+    if (strlen (TEST_MYSQL_URL) > 0 &&
+            g_list_find_custom (drivers, "mysql", (GCompareFunc)g_strcmp0))
+        create_dbi_test_suite ("mysql", TEST_MYSQL_URL);
     if (strlen (TEST_PGSQL_URL) > 0 &&
             g_list_find_custom (drivers, "pgsql", (GCompareFunc)g_strcmp0))
     {
         g_setenv ("PGOPTIONS", "-c client_min_messages=WARNING", FALSE);
         create_dbi_test_suite ("postgres", TEST_PGSQL_URL);
     }
-    if (strlen (TEST_MYSQL_URL) > 0 &&
-            g_list_find_custom (drivers, "mysql", (GCompareFunc)g_strcmp0))
-        create_dbi_test_suite ("mysql", TEST_MYSQL_URL);
 
     GNC_TEST_ADD_FUNC( suitename, "adjust sql options string localtime", 
         test_adjust_sql_options_string );

commit 6810c2a689113a23f5de6d169f515c76dbdb34f4
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Tue Apr 10 10:06:34 2018 +0200

    Fix typo

diff --git a/README.dependencies b/README.dependencies
index 0b16ca7..43237b2 100644
--- a/README.dependencies
+++ b/README.dependencies
@@ -67,7 +67,7 @@ Libraries/Deps
   guile			2.2.0 or 2.0.0
   libxml2		2.5.10
   gettext               0.19.6                  Can use older if you pass
-                                                -DALLOW_OLD_CMAKE to cmake;
+                                                -DALLOW_OLD_GETTEXT to cmake;
                                                 doesn't include all file types
                                                 when building gnucash.pot.
   libxslt, including xsltproc

commit 9319858b9697a8bf7ebad09be5235f8811baa64e
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Apr 9 15:30:36 2018 -0700

    Release 2.6.21

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 52bc5af..7a44f55 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@ ENABLE_TESTING()
 # Version number of gnucash
 SET (GNUCASH_MAJOR_VERSION 2)
 SET (GNUCASH_MINOR_VERSION 6)
-SET (GNUCASH_MICRO_VERSION 20)
+SET (GNUCASH_MICRO_VERSION 21)
 SET (GNUCASH_NANO_VERSION 0)
 SET (VERSION "${GNUCASH_MAJOR_VERSION}.${GNUCASH_MINOR_VERSION}.${GNUCASH_MICRO_VERSION}")
 SET (GNUCASH_LATEST_STABLE_SERIES 2.6)
diff --git a/NEWS b/NEWS
index fbeea52..de89e20 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,15 @@
 Version history:
 ------- -------
+2.6.21 - 10 April 2018
+This is the final, final release in the 2.6. stable series. After 2.6.20's release astute users quickly reported two significant bugs:
+    Bug 795049 - GnuCash 2.6.20-1 (Fedora Linux package) is unable to open
+                 MariaDB database.
+    Bug 795068 - src/optional/python-bindings missing several files.
+
+We also noticed that src/quotes/README had a note about the
+gnc-value-portfolio script that was removed because it required Yahoo!
+quotes. That note has also been removed.
+
 2.6.20 - 1 April 2018
 This is the final release in the 2.6 stable series.
 The following bugs are fixed:
diff --git a/configure.ac b/configure.ac
index 9905267..b337b12 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@ dnl Process this file with autoconf to produce a configure script.
 
 # Autoconf initialization
 AC_PREREQ(2.60)
-AC_INIT([GnuCash], [2.6.20], [https://bugzilla.gnome.org/page.cgi?id=browse.html&product=GnuCash], , [http://www.gnucash.org/])
+AC_INIT([GnuCash], [2.6.21], [https://bugzilla.gnome.org/page.cgi?id=browse.html&product=GnuCash], , [http://www.gnucash.org/])
 AC_CONFIG_HEADERS(config.h)
 AC_CONFIG_SRCDIR(src/engine/Transaction.h)
 AC_CONFIG_MACRO_DIR([macros])

commit 655803a1ca839bcc2c0065eecc31cd1a0995beb1
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Apr 9 15:23:40 2018 -0700

    Remove reference to the deleted gnc-value-portfolio script from README.

diff --git a/src/quotes/README b/src/quotes/README
index 9c9fccb..36b5140 100644
--- a/src/quotes/README
+++ b/src/quotes/README
@@ -25,9 +25,3 @@ gnc-fq-update.in:
   Source file for gnc-fq-update which is a perl script that updates
   Finance::Quote from CPAN.
 
-gnc-value-portfolio:
-
-  A stand-alone perl script for updating and printing the value of a
-  portfolio.  To use this script, edit the first few lines at the top
-  of the file to indicate your portfolio and purchase price.
-  (from Christopher B. Browne, cbbrowne at hex.net)

commit c3f528b80c6cccdf9c139dc0f63a96ef513a0e62
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Apr 9 15:17:32 2018 -0700

    Bug 795068 - src/optional/python-bindings missing several files

diff --git a/src/optional/python-bindings/CMakeLists.txt b/src/optional/python-bindings/CMakeLists.txt
index e87c194..96d92a1 100644
--- a/src/optional/python-bindings/CMakeLists.txt
+++ b/src/optional/python-bindings/CMakeLists.txt
@@ -1,7 +1,9 @@
 ADD_SUBDIRECTORY(example_scripts)
 ADD_SUBDIRECTORY(tests)
 
-IF (BUILDING_FROM_VCS)
+  SET(PYEXEC_FILES  __init__.py function_class.py gnucash_business.py gnucash_core.py)
+
+  IF (BUILDING_FROM_VCS)
   SET(SWIG_FILES ${CMAKE_CURRENT_SOURCE_DIR}/gnucash_core.i ${CMAKE_CURRENT_SOURCE_DIR}/timespec.i)
   SET(GNUCASH_CORE_C_INCLUDES
     ${CMAKE_BINARY_DIR}/src/config.h
@@ -63,8 +65,6 @@ IF(WITH_PYTHON)
     ${PYTHON_INCLUDE_DIRS}
   )
 
-  SET(PYEXEC_FILES  __init__.py function_class.py gnucash_business.py gnucash_core.py)
-
   ADD_LIBRARY(gnucash_core_c MODULE ${SWIG_GNUCASH_CORE_C})
   TARGET_INCLUDE_DIRECTORIES(gnucash_core_c PRIVATE ${gnucash_core_c_INCLUDE_DIRS})
 

commit c05aeb85ec19b6aa50772a63fd1983f8fc429acd
Merge: 192a3c3 434dd95
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Apr 9 15:12:56 2018 -0700

    Merge Bill Nottingham's exception type fix into unstable.


commit 192a3c3d2b18e5440c9faa4942d577adf1aeb0c0
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Apr 9 15:10:25 2018 -0700

    Set GNC_VCS at build time instead of when making the tarball.
    
    Because the tarball is always made from a VCS repo.

diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index fc31390..39481d2 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -59,6 +59,10 @@ ADD_DEPENDENCIES (gnucash gnucash-manpage)
 
 TARGET_COMPILE_DEFINITIONS(gnucash PRIVATE -DG_LOG_DOMAIN=\"gnc.bin\")
 
+if (BUILDING_FROM_VCS)
+  TARGET_COMPILE_DEFINITIONS(gncmod-gnome-utils PRIVATE -DGNC_VCS=\"git\")
+endif (BUILDING_FROM_VCS)
+
 TARGET_LINK_LIBRARIES (gnucash
    gncmod-ledger-core gncmod-report-gnome gnc-gnome gncmod-gnome-utils gncmod-app-utils
    gncmod-engine gnc-module gnc-core-utils gncmod-report-system
diff --git a/gnucash/gnome-utils/CMakeLists.txt b/gnucash/gnome-utils/CMakeLists.txt
index 855d684..c947189 100644
--- a/gnucash/gnome-utils/CMakeLists.txt
+++ b/gnucash/gnome-utils/CMakeLists.txt
@@ -215,7 +215,11 @@ TARGET_LINK_LIBRARIES(gncmod-gnome-utils gncmod-app-utils gncmod-engine gnc-back
      ${CMAKE_DL_LIBS} ${GTK3_LDFLAGS} ${GTK_MAC_LDFLAGS})
 
 TARGET_COMPILE_DEFINITIONS(gncmod-gnome-utils PUBLIC ${GTK_MAC_CFLAGS_OTHER}
-    PRIVATE -DG_LOG_DOMAIN=\"gnc.gui\")
+  PRIVATE -DG_LOG_DOMAIN=\"gnc.gui\")
+
+if (BUILDING_FROM_VCS)
+  TARGET_COMPILE_DEFINITIONS(gncmod-gnome-utils PRIVATE -DGNC_VCS=\"git\")
+endif (BUILDING_FROM_VCS)
 
 IF (MAC_INTEGRATION)
   TARGET_COMPILE_OPTIONS(gncmod-gnome-utils PRIVATE ${OSX_EXTRA_COMPILE_FLAGS})
diff --git a/libgnucash/core-utils/CMakeLists.txt b/libgnucash/core-utils/CMakeLists.txt
index befab78..98641fb 100644
--- a/libgnucash/core-utils/CMakeLists.txt
+++ b/libgnucash/core-utils/CMakeLists.txt
@@ -54,7 +54,6 @@ SET (GNC_VERSION_H_IN
 #ifndef GNC_VERSION_H
 #define GNC_VERSION_H
 
-#define GNC_VCS \"git\"
 #include \"gnc-vcs-info.h\"
 #endif
 ")

commit 8bfbc7791ee4c76537ef16afd4f336c6c914b745
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Apr 9 19:03:39 2018 +0100

    Bug 794953 - Ellipsize on short tab labels
    
    Correct error on when to ellipsize tab labels. Also as this is used in
    two places separate out this to new function so it is not duplicated.

diff --git a/gnucash/gnome-utils/gnc-main-window.c b/gnucash/gnome-utils/gnc-main-window.c
index b77b56a..2a15582 100644
--- a/gnucash/gnome-utils/gnc-main-window.c
+++ b/gnucash/gnome-utils/gnc-main-window.c
@@ -2028,11 +2028,46 @@ gnc_main_window_update_tab_color (gpointer gsettings, gchar *pref, gpointer user
 }
 
 
+/** Set the tab label ellipsize value. The special check for a zero
+ *  value handles the case where a user hasn't set a tab width and
+ *  the preference default isn't detected.
+ *
+ *  @internal
+ *
+ *  @param label GtkLabel for the tab.
+ *
+ *  @param tab_width Tab width the user has set in preferences.
+ *
+ */
+static void
+gnc_main_window_set_tab_ellipsize (GtkWidget *label, gint tab_width)
+{
+    const gchar *lab_text = gtk_label_get_text (GTK_LABEL(label));
+
+    if (tab_width != 0)
+    {
+        if (g_utf8_strlen (lab_text, -1) < tab_width)
+        {
+            gtk_label_set_width_chars (GTK_LABEL(label), strlen (lab_text));
+            gtk_label_set_ellipsize (GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
+        }
+        else
+        {
+            gtk_label_set_width_chars (GTK_LABEL(label), tab_width);
+            gtk_label_set_ellipsize (GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
+        }
+    }
+    else
+    {
+        gtk_label_set_width_chars (GTK_LABEL(label), 15);
+        gtk_label_set_ellipsize (GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
+    }
+}
+
+
 /** Update the width of the label in the tab of a notebook page.  This
- *  function adjusts both the width and the ellipsize mode so that the tab
- *  label looks correct.  The special check for a zero value handles the
- *  case where a user hasn't set a tab width and the preference default isn't
- *  detected.
+ *  function adjusts both the width and the ellipsize mode so that the
+ *  tab label looks correct.
  *
  *  @internal
  *
@@ -2046,7 +2081,6 @@ gnc_main_window_update_tab_width_one_page (GncPluginPage *page,
 {
     gint *new_value = user_data;
     GtkWidget *label;
-    const gchar *lab_text;
 
     ENTER("page %p, visible %d", page, *new_value);
     label = g_object_get_data(G_OBJECT (page), PLUGIN_PAGE_TAB_LABEL);
@@ -2055,23 +2089,7 @@ gnc_main_window_update_tab_width_one_page (GncPluginPage *page,
         LEAVE("no label");
         return;
     }
-
-    lab_text = gtk_label_get_text (GTK_LABEL(label));
-
-    if (*new_value != 0)
-    {
-        if (g_utf8_strlen (lab_text, -1) < *new_value)
-            gtk_label_set_width_chars (GTK_LABEL(label), strlen (lab_text));
-        else
-            gtk_label_set_width_chars (GTK_LABEL(label), *new_value);
-
-        gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
-    }
-    else
-    {
-        gtk_label_set_width_chars (GTK_LABEL(label), 15);
-        gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
-    }
+    gnc_main_window_set_tab_ellipsize (label, *new_value);
     LEAVE(" ");
 }
 
@@ -2940,15 +2958,8 @@ gnc_main_window_open_page (GncMainWindow *window,
     label = gtk_label_new (lab_text);
     g_object_set_data (G_OBJECT (page), PLUGIN_PAGE_TAB_LABEL, label);
 
-    if (width != 0)
-    {
-        if (g_utf8_strlen (lab_text, -1) < width)
-            gtk_label_set_width_chars (GTK_LABEL(label), strlen (lab_text));
-        else
-            gtk_label_set_width_chars (GTK_LABEL(label), width);
+    gnc_main_window_set_tab_ellipsize (label, width);
 
-        gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
-    }
     gtk_widget_show (label);
 
     tab_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);

commit facd26c0ef18ef016392d13e9f09a86d966815f4
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Apr 9 15:15:25 2018 +0100

    Bug 794994 - Display Alphavantage key in full
    
    Set the entry to expand so all the space is used to display.

diff --git a/gnucash/gtkbuilder/dialog-preferences.glade b/gnucash/gtkbuilder/dialog-preferences.glade
index abd3429..092f822 100644
--- a/gnucash/gtkbuilder/dialog-preferences.glade
+++ b/gnucash/gtkbuilder/dialog-preferences.glade
@@ -3280,6 +3280,7 @@ many months before the current month:</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="tooltip_text" translatable="yes">To retrieve online quotes from Alphavantage, this key needs to be set. A key can be retrieved from the Alpha Vantage website.</property>
+                    <property name="hexpand">True</property>
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
@@ -3316,5 +3317,8 @@ many months before the current month:</property>
       <action-widget response="-11">helpbutton2</action-widget>
       <action-widget response="-7">closebutton2</action-widget>
     </action-widgets>
+    <child>
+      <placeholder/>
+    </child>
   </object>
 </interface>

commit 8975158ac64af4d0a0236ba1cea9e7fd040766f0
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Apr 9 15:13:29 2018 +0100

    If there are no prices in the db, critical errors are flagged
    
    When dialog transfer is used between two commodities and there are no
    prices in the db a critical error is logged. Test for price object
    being NULL before retrieving the price for the error message.

diff --git a/gnucash/gnome-utils/dialog-transfer.c b/gnucash/gnome-utils/dialog-transfer.c
index 13204f0..89a4bd9 100644
--- a/gnucash/gnome-utils/dialog-transfer.c
+++ b/gnucash/gnome-utils/dialog-transfer.c
@@ -272,6 +272,16 @@ lookup_price(PriceReq *pr, PriceDate pd)
             prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->from, pr->to);
             break;
     }
+
+    if (!prc) //no price found
+    {
+        PINFO("No price Found for %s, %s",
+              gnc_commodity_get_mnemonic(pr->from),
+              gnc_commodity_get_mnemonic(pr->to));
+        pr->price = NULL;
+        return FALSE;
+    }
+
     if (gnc_commodity_equiv(gnc_price_get_currency(prc), pr->from))
     {
         pr->reverse = TRUE;
@@ -279,7 +289,6 @@ lookup_price(PriceReq *pr, PriceDate pd)
               gnc_commodity_get_mnemonic(pr->to),
               gnc_numeric_to_double(gnc_price_get_value(prc)),
               gnc_commodity_get_mnemonic(pr->from));
-
     }
     else
     {
@@ -288,8 +297,6 @@ lookup_price(PriceReq *pr, PriceDate pd)
               gnc_numeric_to_double(gnc_price_get_value(prc)),
               gnc_commodity_get_mnemonic(pr->to));
     }
-    if (!prc)
-        return FALSE;
     pr->price = prc;
     return TRUE;
 }
@@ -1639,7 +1646,7 @@ new_price(XferDialog *xferData, Timespec ts)
     PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
           gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
     gnc_price_unref (price);
-}    
+}
 
 static void
 create_price(XferDialog *xferData, Timespec ts)

commit 5af11ced47f4fd640b0fa7b9b34ee8d6f4d18c6e
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Apr 9 15:10:02 2018 +0100

    Invalid cast for parent of transfer dialog
    
    Trying to cast from SplitRegister to GtkWidget.

diff --git a/gnucash/register/ledger-core/split-register-control.c b/gnucash/register/ledger-core/split-register-control.c
index 235befa..fe14cd2 100644
--- a/gnucash/register/ledger-core/split-register-control.c
+++ b/gnucash/register/ledger-core/split-register-control.c
@@ -1250,7 +1250,7 @@ gnc_split_register_xfer_dialog(SplitRegister *reg, Transaction *txn,
     cur = reg->table->current_cursor;
 
     /* Create the exchange rate dialog. */
-    xfer = gnc_xfer_dialog(GTK_WIDGET (reg), NULL);
+    xfer = gnc_xfer_dialog(gnc_split_register_get_parent (reg), NULL);
     g_return_val_if_fail(xfer, NULL);
 
     /* Set the description. */

commit aea33ca515aceb4f63a5cbc8165d4ec93f245d0c
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Apr 8 15:20:55 2018 -0700

    Bug 795049 - GnuCash 2.6.20-1 (Fedora Linux package) is unable to open...
    
    MariaDB database.

diff --git a/src/backend/dbi/test/test-backend-dbi-basic.c b/src/backend/dbi/test/test-backend-dbi-basic.c
index 386a2c3..4a55a62 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.c
+++ b/src/backend/dbi/test/test-backend-dbi-basic.c
@@ -666,15 +666,15 @@ test_suite_gnc_backend_dbi (void)
     }
     if (g_list_find_custom (drivers, "sqlite3", (GCompareFunc)g_strcmp0))
         create_dbi_test_suite ("sqlite3", "sqlite3");
-    if (strlen (TEST_MYSQL_URL) > 0 &&
-            g_list_find_custom (drivers, "mysql", (GCompareFunc)g_strcmp0))
-        create_dbi_test_suite ("mysql", TEST_MYSQL_URL);
     if (strlen (TEST_PGSQL_URL) > 0 &&
             g_list_find_custom (drivers, "pgsql", (GCompareFunc)g_strcmp0))
     {
         g_setenv ("PGOPTIONS", "-c client_min_messages=WARNING", FALSE);
         create_dbi_test_suite ("postgres", TEST_PGSQL_URL);
     }
+    if (strlen (TEST_MYSQL_URL) > 0 &&
+            g_list_find_custom (drivers, "mysql", (GCompareFunc)g_strcmp0))
+        create_dbi_test_suite ("mysql", TEST_MYSQL_URL);
 
     GNC_TEST_ADD_FUNC( suitename, "adjust sql options string localtime", 
         test_adjust_sql_options_string );

commit 34c464446ae9e1664a2dd7823fbecddae7bca5c2
Author: Henrik tom Wörden <henrik at trineo.org>
Date:   Sat Apr 7 12:21:51 2018 +0200

    MAINT: removed reference to README.git
    
    The reference was inappropriate as README.git no longer contains
    information on how to build gnucash.

diff --git a/README b/README
index cddc552..d018e72 100644
--- a/README
+++ b/README
@@ -189,8 +189,7 @@ Building & Installing
 ---------------------
 
 GnuCash uses CMake to handle the build process. Details are available
-in cmake/README_CMAKE.txt (If you are building directly from Git, read
-the README.git file for more instructions.)
+in cmake/README_CMAKE.txt
 
 Prior to building GnuCash, you will have to obtain and install the
 following packages:

commit a909f802defc326a397cd65febda39c181c43e91
Author: Henrik tom Wörden <henrik at trineo.org>
Date:   Sat Apr 7 12:20:58 2018 +0200

    FIX: Corrected typos

diff --git a/common/cmake_modules/GncAddSwigCommand.cmake b/common/cmake_modules/GncAddSwigCommand.cmake
index c6de5de..fa4f09d 100644
--- a/common/cmake_modules/GncAddSwigCommand.cmake
+++ b/common/cmake_modules/GncAddSwigCommand.cmake
@@ -14,7 +14,7 @@
 #   when building from git, it points to the actually generated file
 #   however when building from a tarball, it will point to the version from the tarball instead
 # - _output is the name of the wrapper file to generate (or to look up in the tarball)
-# - input it the swig interface file (*.i) to generate this wrapper from
+# - _input is the swig interface file (*.i) to generate this wrapper from
 # Any additional parameters will be used as dependencies for this wrapper target
 macro (gnc_add_swig_guile_command _target _out_var _output _input)
 
@@ -55,7 +55,7 @@ endmacro (gnc_add_swig_guile_command)
 # - _py_out_var is the same but for the python module that's generated together with the wrapper
 # - _output is the name of the wrapper file to generate (or to look up in the tarball)
 # - _py_output is the name of the python module associated with this wrapper
-# - input it the swig interface file (*.i) to generate this wrapper from
+# - _input is the swig interface file (*.i) to generate this wrapper from
 # Any additional parameters will be used as dependencies for this wrapper target
 macro (gnc_add_swig_python_command _target _out_var _py_out_var _output _py_output _input)
 

commit 434dd9520c1c74c38dae8a737b2045ee28adc1e1
Author: Bill Nottingham <notting at splat.cc>
Date:   Tue Apr 3 22:02:44 2018 -0400

    Adjust catch syntax to avoid GCC8 warnings.

diff --git a/libgnucash/backend/sql/gnc-address-sql.cpp b/libgnucash/backend/sql/gnc-address-sql.cpp
index 4445bef..e3c18ca 100644
--- a/libgnucash/backend/sql/gnc-address-sql.cpp
+++ b/libgnucash/backend/sql/gnc-address-sql.cpp
@@ -98,7 +98,7 @@ GncSqlColumnTableEntryImpl<CT_ADDRESS>::load (const GncSqlBackend* sql_be,
             set_parameter (addr, val.c_str(), sub_setter,
                            subtable_row->m_gobj_param_name);
         }
-        catch (std::invalid_argument)
+        catch (std::invalid_argument&)
         {
             return;
         }
diff --git a/libgnucash/backend/sql/gnc-owner-sql.cpp b/libgnucash/backend/sql/gnc-owner-sql.cpp
index 2e862b2..c2f2990 100644
--- a/libgnucash/backend/sql/gnc-owner-sql.cpp
+++ b/libgnucash/backend/sql/gnc-owner-sql.cpp
@@ -73,7 +73,7 @@ GncSqlColumnTableEntryImpl<CT_OWNERREF>::load (const GncSqlBackend* sql_be,
         if (string_to_guid (val.c_str(), &guid))
             pGuid = &guid;
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         return;
     }
diff --git a/libgnucash/backend/sql/gnc-slots-sql.cpp b/libgnucash/backend/sql/gnc-slots-sql.cpp
index 7f579c1..ca26617 100644
--- a/libgnucash/backend/sql/gnc-slots-sql.cpp
+++ b/libgnucash/backend/sql/gnc-slots-sql.cpp
@@ -703,7 +703,7 @@ gnc_sql_slots_delete (GncSqlBackend* sql_be, const GncGUID* guid)
                 if (string_to_guid (val.c_str(), &child_guid))
                     gnc_sql_slots_delete (sql_be, &child_guid);
             }
-            catch (std::invalid_argument)
+            catch (std::invalid_argument&)
             {
                 continue;
             }
diff --git a/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp b/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp
index 09d6f3a..81e1938 100644
--- a/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp
+++ b/libgnucash/backend/sql/gnc-sql-column-table-entry.cpp
@@ -130,7 +130,7 @@ GncSqlColumnTableEntryImpl<CT_STRING>::load (const GncSqlBackend* sql_be,
         auto s = row.get_string_at_col (m_col_name);
         set_parameter(pObject, s.c_str(), get_setter(obj_name), m_gobj_param_name);
     }
-    catch (std::invalid_argument) {}
+    catch (std::invalid_argument&) {}
 }
 
 template<> void
@@ -279,19 +279,19 @@ GncSqlColumnTableEntryImpl<CT_DOUBLE>::load (const GncSqlBackend* sql_be,
     {
         val = static_cast<double>(row.get_int_at_col(m_col_name));
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         try
         {
             val = static_cast<double>(row.get_float_at_col(m_col_name));
         }
-        catch (std::invalid_argument)
+        catch (std::invalid_argument&)
         {
             try
             {
                 val = row.get_double_at_col(m_col_name);
             }
-            catch (std::invalid_argument)
+            catch (std::invalid_argument&)
             {
                 val = 0.0;
             }
@@ -336,7 +336,7 @@ GncSqlColumnTableEntryImpl<CT_GUID>::load (const GncSqlBackend* sql_be,
     {
         str = row.get_string_at_col(m_col_name);
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         return;
     }
@@ -391,7 +391,7 @@ GncSqlColumnTableEntryImpl<CT_TIMESPEC>::load (const GncSqlBackend* sql_be,
         auto val = row.get_time64_at_col(m_col_name);
         timespecFromTime64 (&ts, val);
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         try
         {
@@ -399,7 +399,7 @@ GncSqlColumnTableEntryImpl<CT_TIMESPEC>::load (const GncSqlBackend* sql_be,
             GncDateTime time(val);
             ts.tv_sec = static_cast<time64>(time);
         }
-        catch (std::invalid_argument)
+        catch (std::invalid_argument&)
         {
             return;
         }
@@ -471,7 +471,7 @@ GncSqlColumnTableEntryImpl<CT_TIME64>::load (const GncSqlBackend* sql_be,
     {
         t = row.get_time64_at_col (m_col_name);
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         try
         {
@@ -479,7 +479,7 @@ GncSqlColumnTableEntryImpl<CT_TIME64>::load (const GncSqlBackend* sql_be,
             GncDateTime time(val);
             t = static_cast<time64>(time);
         }
-        catch (std::invalid_argument)
+        catch (std::invalid_argument&)
         {
             return;
         }
@@ -543,7 +543,7 @@ GncSqlColumnTableEntryImpl<CT_GDATE>::load (const GncSqlBackend* sql_be,
                        tm->tm_year + 1900);
         free(tm);
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         try
         {
@@ -557,7 +557,7 @@ GncSqlColumnTableEntryImpl<CT_GDATE>::load (const GncSqlBackend* sql_be,
                 g_date_set_dmy(&date, day, month, year);
 
         }
-        catch (std::invalid_argument)
+        catch (std::invalid_argument&)
         {
             return;
         }
@@ -622,7 +622,7 @@ GncSqlColumnTableEntryImpl<CT_NUMERIC>::load (const GncSqlBackend* sql_be,
         n = gnc_numeric_create (num, denom);
         g_free (buf);
     }
-    catch (std::invalid_argument)
+    catch (std::invalid_argument&)
     {
         return;
     }
diff --git a/libgnucash/backend/sql/gnc-sql-column-table-entry.hpp b/libgnucash/backend/sql/gnc-sql-column-table-entry.hpp
index a98801a..0465589 100644
--- a/libgnucash/backend/sql/gnc-sql-column-table-entry.hpp
+++ b/libgnucash/backend/sql/gnc-sql-column-table-entry.hpp
@@ -199,7 +199,7 @@ public:
                                        m_gobj_param_name);
                 }
             }
-            catch (std::invalid_argument) {}
+            catch (std::invalid_argument&) {}
         }
 
 
diff --git a/libgnucash/backend/sql/gnc-transaction-sql.cpp b/libgnucash/backend/sql/gnc-transaction-sql.cpp
index 266d356..c8ddd1e 100644
--- a/libgnucash/backend/sql/gnc-transaction-sql.cpp
+++ b/libgnucash/backend/sql/gnc-transaction-sql.cpp
@@ -1326,7 +1326,7 @@ GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* sql_be,
         if (tx != nullptr)
             set_parameter (pObject, tx, get_setter(obj_name), m_gobj_param_name);
     }
-    catch (std::invalid_argument) {}
+    catch (std::invalid_argument&) {}
 }
 
 template<> void
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 6f63fcb..94078e7 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -5442,7 +5442,7 @@ gnc_account_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
     gnc::GUID guid;
     try {
         guid = gnc::GUID::from_string(best.account_guid);
-    } catch (gnc::guid_syntax_exception) {
+    } catch (gnc::guid_syntax_exception&) {
         return nullptr;
     }
     auto account = xaccAccountLookup (reinterpret_cast<GncGUID*>(&guid), imap->book);
diff --git a/libgnucash/engine/gnc-date.cpp b/libgnucash/engine/gnc-date.cpp
index f4c0cf7..1b37ede 100644
--- a/libgnucash/engine/gnc-date.cpp
+++ b/libgnucash/engine/gnc-date.cpp
@@ -120,7 +120,7 @@ gnc_localtime_r (const time64 *secs, struct tm* time)
         *time = static_cast<struct tm>(GncDateTime(*secs));
         return time;
     }
-    catch(std::invalid_argument)
+    catch(std::invalid_argument&)
     {
         return NULL;
     }
@@ -194,7 +194,7 @@ gnc_gmtime (const time64 *secs)
         *time = gncdt.utc_tm();
         return time;
     }
-    catch(std::invalid_argument)
+    catch(std::invalid_argument&)
     {
         return NULL;
     }
@@ -211,7 +211,7 @@ gnc_mktime (struct tm* time)
         *time = static_cast<struct tm>(gncdt);
         return static_cast<time64>(gncdt);
     }
-    catch(std::invalid_argument)
+    catch(std::invalid_argument&)
     {
         return 0;
     }
@@ -232,7 +232,7 @@ gnc_timegm (struct tm* time)
 #endif
         return static_cast<time64>(gncdt) - gncdt.offset();
     }
-    catch(std::invalid_argument)
+    catch(std::invalid_argument&)
     {
         return 0;
     }
diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp
index e86d47e..6aa463c 100644
--- a/libgnucash/engine/gnc-datetime.cpp
+++ b/libgnucash/engine/gnc-datetime.cpp
@@ -149,7 +149,7 @@ LDT_from_unix_local(const time64 time)
         auto tz = tzp.get(temp.date().year());
         return LDT(temp, tz);
     }
-    catch(boost::gregorian::bad_year)
+    catch(boost::gregorian::bad_year&)
     {
         throw(std::invalid_argument("Time value is outside the supported year range."));
     }
@@ -167,15 +167,15 @@ LDT_from_struct_tm(const struct tm tm)
         LDT ldt(tdate, tdur, tz, LDTBase::EXCEPTION_ON_ERROR);
         return ldt;
     }
-    catch(boost::gregorian::bad_year)
+    catch(boost::gregorian::bad_year&)
     {
         throw(std::invalid_argument("Time value is outside the supported year range."));
     }
-    catch(boost::local_time::time_label_invalid)
+    catch(boost::local_time::time_label_invalid&)
     {
         throw(std::invalid_argument("Struct tm does not resolve to a valid time."));
     }
-    catch(boost::local_time::ambiguous_result)
+    catch(boost::local_time::ambiguous_result&)
     {
         throw(std::invalid_argument("Struct tm can resolve to more than one time."));
     }
@@ -256,7 +256,7 @@ GncDateTimeImpl::GncDateTimeImpl(const GncDateImpl& date, DayPart part) :
                 m_time -= hours(offset.hours() - 11);
         }
     }
-    catch(boost::gregorian::bad_year)
+    catch(boost::gregorian::bad_year&)
     {
         throw(std::invalid_argument("Time value is outside the supported year range."));
     }
@@ -298,7 +298,7 @@ GncDateTimeImpl::GncDateTimeImpl(std::string str) :
         m_time = LDT(pdt.date(), pdt.time_of_day(), tzptr,
                          LDTBase::NOT_DATE_TIME_ON_ERROR);
     }
-    catch(boost::gregorian::bad_year)
+    catch(boost::gregorian::bad_year&)
     {
         throw(std::invalid_argument("The date string was outside of the supported year range."));
     }
diff --git a/libgnucash/engine/gnc-rational.cpp b/libgnucash/engine/gnc-rational.cpp
index c534b8b..33f2741 100644
--- a/libgnucash/engine/gnc-rational.cpp
+++ b/libgnucash/engine/gnc-rational.cpp
@@ -69,7 +69,7 @@ GncRational::operator gnc_numeric () const noexcept
     {
         return {static_cast<int64_t>(m_num), static_cast<int64_t>(m_den)};
     }
-    catch (std::overflow_error)
+    catch (std::overflow_error&)
     {
         return gnc_numeric_error (GNC_ERROR_OVERFLOW);
     }

commit 0a3f2dd3ef7dc16e4d2de2eebdadbca23c0b98e3
Author: Bill Nottingham <notting at splat.cc>
Date:   Tue Apr 3 21:59:50 2018 -0400

    Allow building against a shared libgmock (an option in gtest-1.8.0).

diff --git a/common/cmake_modules/GncAddTest.cmake b/common/cmake_modules/GncAddTest.cmake
index 9c7863c..47fc988 100644
--- a/common/cmake_modules/GncAddTest.cmake
+++ b/common/cmake_modules/GncAddTest.cmake
@@ -149,6 +149,8 @@ FUNCTION(GNC_GTEST_CONFIGURE)
   FIND_PATH(GMOCK_INCLUDE_DIR gmock/gmock.h
     PATHS ${GMOCK_ROOT}/include /usr/include)
   unset(GMOCK_SRC_DIR CACHE)
+  FIND_LIBRARY(GMOCK_SHARED_LIB gmock)
+  FIND_LIBRARY(GMOCK_MAIN_LIB gmock_main)
   FIND_PATH(GMOCK_SRC_DIR src/gmock-all.cc
     PATHS ${GMOCK_ROOT} /usr/src/gmock)
   if (GMOCK_SRC_DIR)
@@ -160,10 +162,15 @@ FUNCTION(GNC_GTEST_CONFIGURE)
       SET(GMOCK_MAIN_SRC_DIR "${GMOCK_SRC_DIR}")
     endif()
   endif()
-  if (GMOCK_INCLUDE_DIR AND GMOCK_SRC_DIR)
+  if (GMOCK_INCLUDE_DIR AND (GMOCK_SHARED_LIB OR GMOCK_SRC_DIR))
     SET(GMOCK_FOUND YES PARENT_SCOPE)
-    SET(GMOCK_SRC "${GMOCK_MAIN_SRC_DIR}/gmock-all.cc" PARENT_SCOPE)
-    SET(GMOCK_LIB "${CMAKE_BINARY_DIR}/common/test-core/libgmock.a" PARENT_SCOPE)
+    IF(GMOCK_SHARED_LIB)
+      SET(GMOCK_LIB "${GMOCK_SHARED_LIB};${GMOCK_MAIN_LIB}" PARENT_SCOPE)
+      UNSET(GMOCK_SRC_DIR CACHE)
+    ELSE()
+      SET(GMOCK_SRC "${GMOCK_MAIN_SRC_DIR}/gmock-all.cc" PARENT_SCOPE)
+      SET(GMOCK_LIB "${CMAKE_BINARY_DIR}/common/test-core/libgmock.a" PARENT_SCOPE)
+    ENDIF()
   ELSE()
     MESSAGE(FATAL_ERROR "GMOCK not found. Please install it or set GMOCK_ROOT")
   ENDIF()
diff --git a/common/test-core/CMakeLists.txt b/common/test-core/CMakeLists.txt
index ce4ed3a..5281565 100644
--- a/common/test-core/CMakeLists.txt
+++ b/common/test-core/CMakeLists.txt
@@ -75,13 +75,15 @@ IF(NOT GTEST_SHARED_LIB)
   ENDIF()
   TARGET_INCLUDE_DIRECTORIES(gtest PUBLIC ${GTEST_INCLUDE_DIR} ${GTEST_SRC_DIR})
 ENDIF()
-SET (lib_gmock_SOURCES ${GMOCK_SRC})
-ADD_LIBRARY(gmock STATIC  ${lib_gmock_SOURCES})
-IF (APPLE)
-  TARGET_COMPILE_OPTIONS(gmock PRIVATE -Wno-missing-prototypes)
-ELSE()
-  TARGET_COMPILE_OPTIONS(gmock PRIVATE -Wno-missing-declarations)
+IF(NOT GMOCK_SHARED_LIB)
+  SET (lib_gmock_SOURCES ${GMOCK_SRC})
+  ADD_LIBRARY(gmock STATIC  ${lib_gmock_SOURCES})
+  IF (APPLE)
+    TARGET_COMPILE_OPTIONS(gmock PRIVATE -Wno-missing-prototypes)
+  ELSE()
+    TARGET_COMPILE_OPTIONS(gmock PRIVATE -Wno-missing-declarations)
+  ENDIF()
+  TARGET_INCLUDE_DIRECTORIES(gmock PUBLIC
+    ${GTEST_INCLUDE_DIR} ${GTEST_SRC_DIR}
+    ${GMOCK_INCLUDE_DIR} ${GMOCK_SRC_DIR})
 ENDIF()
-TARGET_INCLUDE_DIRECTORIES(gmock PUBLIC
-  ${GTEST_INCLUDE_DIR} ${GTEST_SRC_DIR}
-  ${GMOCK_INCLUDE_DIR} ${GMOCK_SRC_DIR})



Summary of changes:
 README                                             |   3 +-
 README.dependencies                                |   2 +-
 cmake/README_CMAKE.txt                             |   8 +-
 common/cmake_modules/GncAddSwigCommand.cmake       |   4 +-
 common/cmake_modules/GncAddTest.cmake              |  13 +-
 common/test-core/CMakeLists.txt                    |  20 +-
 gnucash/CMakeLists.txt                             |   4 +
 gnucash/gnome-utils/CMakeLists.txt                 |   6 +-
 gnucash/gnome-utils/dialog-transfer.c              |  15 +-
 gnucash/gnome-utils/gnc-main-window.c              |  72 ++--
 gnucash/gnome-utils/gnc-query-view.c               |  32 +-
 gnucash/gnome/dialog-invoice.c                     |   2 +-
 gnucash/gnome/reconcile-view.c                     |  58 ++-
 gnucash/gnome/window-reconcile.c                   |  24 +-
 gnucash/gnome/window-reconcile.h                   |   6 +-
 gnucash/gnucash-bin.c                              |   4 +-
 gnucash/gtkbuilder/dialog-preferences.glade        |   4 +
 gnucash/gtkbuilder/gnc-date-format.glade           |   1 -
 gnucash/import-export/aqb/gnc-ab-utils.c           |   2 +-
 gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp |   8 +-
 gnucash/import-export/csv-imp/gnc-import-tx.cpp    |   7 +-
 gnucash/import-export/import-backend.c             |   4 +
 gnucash/register/ledger-core/gncEntryLedger.c      |  13 +-
 .../register/ledger-core/split-register-control.c  |   2 +-
 gnucash/report/report-system/html-fonts.scm        |   2 +-
 .../standard-reports/income-gst-statement.scm      |   9 +-
 gnucash/report/standard-reports/transaction.scm    | 178 ++++----
 libgnucash/app-utils/gnc-ui-util.c                 |   4 +-
 libgnucash/backend/dbi/gnc-dbisqlresult.cpp        |   3 -
 libgnucash/backend/sql/gnc-account-sql.cpp         |  31 +-
 libgnucash/backend/sql/gnc-address-sql.cpp         |   2 +-
 libgnucash/backend/sql/gnc-bill-term-sql.cpp       |  23 +-
 libgnucash/backend/sql/gnc-budget-sql.cpp          |  17 +-
 libgnucash/backend/sql/gnc-commodity-sql.cpp       |  14 +-
 libgnucash/backend/sql/gnc-customer-sql.cpp        |  24 +-
 libgnucash/backend/sql/gnc-employee-sql.cpp        |  25 +-
 libgnucash/backend/sql/gnc-entry-sql.cpp           |  24 +-
 libgnucash/backend/sql/gnc-invoice-sql.cpp         |  24 +-
 libgnucash/backend/sql/gnc-job-sql.cpp             |  24 +-
 libgnucash/backend/sql/gnc-order-sql.cpp           |  24 +-
 libgnucash/backend/sql/gnc-owner-sql.cpp           |   2 +-
 libgnucash/backend/sql/gnc-price-sql.cpp           |  15 +-
 libgnucash/backend/sql/gnc-schedxaction-sql.cpp    |  26 +-
 libgnucash/backend/sql/gnc-slots-sql.cpp           |  68 +--
 libgnucash/backend/sql/gnc-slots-sql.h             |  13 +-
 libgnucash/backend/sql/gnc-sql-backend.cpp         |  12 +-
 .../backend/sql/gnc-sql-column-table-entry.cpp     |  24 +-
 .../backend/sql/gnc-sql-column-table-entry.hpp     |   2 +-
 libgnucash/backend/sql/gnc-transaction-sql.cpp     | 470 +++------------------
 libgnucash/backend/sql/gnc-transaction-sql.h       |   8 -
 libgnucash/backend/sql/gnc-vendor-sql.cpp          |  24 +-
 libgnucash/core-utils/CMakeLists.txt               |   1 -
 libgnucash/core-utils/gnc-guile-utils.c            |   2 +-
 libgnucash/engine/Account.cpp                      |   2 +-
 libgnucash/engine/TransLog.c                       |   2 +-
 libgnucash/engine/gnc-date.cpp                     |   8 +-
 libgnucash/engine/gnc-datetime.cpp                 |  33 +-
 libgnucash/engine/gnc-pricedb.c                    |   1 +
 libgnucash/engine/gnc-rational.cpp                 |   2 +-
 libgnucash/engine/gncInvoice.c                     |   2 +-
 libgnucash/engine/test/gtest-gnc-numeric.cpp       |   2 +-
 libgnucash/engine/test/utest-gnc-pricedb.c         |   2 +-
 62 files changed, 548 insertions(+), 915 deletions(-)



More information about the gnucash-changes mailing list