LCOV - code coverage report
Current view: top level - libgnucash/backend/sql - gnc-bill-term-sql.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 32.7 % 113 37
Test Date: 2026-11-02 18:19:43 Functions: 43.8 % 16 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /********************************************************************\
       2              :  * gnc-bill-term-sql.c -- billing term sql backend                  *
       3              :  *                                                                  *
       4              :  * This program is free software; you can redistribute it and/or    *
       5              :  * modify it under the terms of the GNU General Public License as   *
       6              :  * published by the Free Software Foundation; either version 2 of   *
       7              :  * the License, or (at your option) any later version.              *
       8              :  *                                                                  *
       9              :  * This program is distributed in the hope that it will be useful,  *
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      12              :  * GNU General Public License for more details.                     *
      13              :  *                                                                  *
      14              :  * You should have received a copy of the GNU General Public License*
      15              :  * along with this program; if not, contact:                        *
      16              :  *                                                                  *
      17              :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      18              :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      19              :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      20              :  *                                                                  *
      21              : \********************************************************************/
      22              : 
      23              : /** @file gnc-bill-term-sql.c
      24              :  *  @brief load and save address data to SQL
      25              :  *  @author Copyright (c) 2007-2008 Phil Longstaff <plongstaff@rogers.com>
      26              :  *
      27              :  * This file implements the top-level QofBackend API for saving/
      28              :  * restoring data to/from an SQL database
      29              :  */
      30              : #include <guid.hpp>
      31              : #include <config.h>
      32              : 
      33              : #include <glib.h>
      34              : #include <stdlib.h>
      35              : #include <string.h>
      36              : 
      37              : #include "gncBillTermP.h"
      38              : #include "gncInvoice.h"
      39              : #include "qof.h"
      40              : 
      41              : #include <string>
      42              : #include <vector>
      43              : #include <algorithm>
      44              : 
      45              : #include "gnc-sql-connection.hpp"
      46              : #include "gnc-sql-backend.hpp"
      47              : #include "gnc-sql-object-backend.hpp"
      48              : #include "gnc-sql-column-table-entry.hpp"
      49              : #include "gnc-slots-sql.h"
      50              : #include "gnc-bill-term-sql.h"
      51              : 
      52              : #define _GNC_MOD_NAME   GNC_ID_BILLTERM
      53              : 
      54              : static QofLogModule log_module = G_LOG_DOMAIN;
      55              : 
      56              : #define MAX_NAME_LEN 2048
      57              : #define MAX_DESCRIPTION_LEN 2048
      58              : #define MAX_TYPE_LEN 2048
      59              : 
      60              : static void set_invisible (gpointer data, gboolean value);
      61              : static gpointer bt_get_parent (gpointer data);
      62              : static void bt_set_parent (gpointer data, gpointer value);
      63              : static void bt_set_parent_guid (gpointer data, gpointer value);
      64              : 
      65              : #define TABLE_NAME "billterms"
      66              : #define TABLE_VERSION 2
      67              : 
      68              : static EntryVec col_table
      69              : {
      70              :     gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
      71              :     gnc_sql_make_table_entry<CT_STRING>("name", MAX_NAME_LEN, COL_NNUL, "name"),
      72              :     gnc_sql_make_table_entry<CT_STRING>("description", MAX_DESCRIPTION_LEN,
      73              :                                         COL_NNUL, GNC_BILLTERM_DESC,
      74              :                                         true),
      75              :     gnc_sql_make_table_entry<CT_INT>("refcount", 0, COL_NNUL,
      76              :                                      (QofAccessFunc)gncBillTermGetRefcount,
      77              :                                      (QofSetterFunc)gncBillTermSetRefcount),
      78              :     gnc_sql_make_table_entry<CT_BOOLEAN>("invisible", 0, COL_NNUL,
      79              :                                          (QofAccessFunc)gncBillTermGetInvisible,
      80              :                                          (QofSetterFunc)set_invisible),
      81              :     gnc_sql_make_table_entry<CT_GUID>("parent", 0, 0,
      82              :                                       (QofAccessFunc)bt_get_parent,
      83              :                                       (QofSetterFunc)bt_set_parent),
      84              :     gnc_sql_make_table_entry<CT_STRING>("type", MAX_TYPE_LEN, COL_NNUL,
      85              :                                         GNC_BILLTERM_TYPE, true),
      86              :     gnc_sql_make_table_entry<CT_INT>("duedays", 0, 0, GNC_BILLTERM_DUEDAYS,
      87              :                                          true),
      88              :     gnc_sql_make_table_entry<CT_INT>("discountdays", 0, 0,
      89              :                                      GNC_BILLTERM_DISCDAYS, true),
      90              :     gnc_sql_make_table_entry<CT_NUMERIC>("discount", 0, 0,
      91              :                                          GNC_BILLTERM_DISCOUNT, true),
      92              :     gnc_sql_make_table_entry<CT_INT>("cutoff", 0, 0, GNC_BILLTERM_CUTOFF,
      93              :                                      true),
      94              : };
      95              : 
      96              : static EntryVec billterm_parent_col_table
      97              : {
      98              :     gnc_sql_make_table_entry<CT_GUID>("parent", 0, 0, nullptr,
      99              :                                        bt_set_parent_guid),
     100              : };
     101              : 
     102           15 : GncSqlBillTermBackend::GncSqlBillTermBackend() :
     103           30 :         GncSqlObjectBackend(TABLE_VERSION, GNC_ID_BILLTERM,
     104           75 :                             TABLE_NAME, col_table) {}
     105              : 
     106              : struct BillTermParentGuid
     107              : {
     108              :     GncBillTerm* billterm;
     109              :     GncGUID guid;
     110              :     bool have_guid;
     111              : };
     112              : 
     113              : using BillTermParentGuidPtr = BillTermParentGuid*;
     114              : using BillTermParentGuidVec = std::vector<BillTermParentGuidPtr>;
     115              : 
     116              : static void
     117            0 : set_invisible (gpointer data, gboolean value)
     118              : {
     119            0 :     GncBillTerm* term = GNC_BILLTERM (data);
     120              : 
     121            0 :     g_return_if_fail (term != NULL);
     122              : 
     123            0 :     if (value)
     124              :     {
     125            0 :         gncBillTermMakeInvisible (term);
     126              :     }
     127              : }
     128              : 
     129              : static  gpointer
     130            0 : bt_get_parent (gpointer pObject)
     131              : {
     132              :     const GncBillTerm* billterm;
     133              :     const GncBillTerm* pParent;
     134              :     const GncGUID* parent_guid;
     135              : 
     136            0 :     g_return_val_if_fail (pObject != NULL, NULL);
     137            0 :     g_return_val_if_fail (GNC_IS_BILLTERM (pObject), NULL);
     138              : 
     139            0 :     billterm = GNC_BILLTERM (pObject);
     140            0 :     pParent = gncBillTermGetParent (billterm);
     141            0 :     if (pParent == NULL)
     142              :     {
     143            0 :         parent_guid = NULL;
     144              :     }
     145              :     else
     146              :     {
     147            0 :         parent_guid = qof_instance_get_guid (QOF_INSTANCE (pParent));
     148              :     }
     149              : 
     150            0 :     return (gpointer)parent_guid;
     151              : }
     152              : 
     153              : static void
     154            0 : bt_set_parent (gpointer data, gpointer value)
     155              : {
     156              :     GncBillTerm* billterm;
     157              :     GncBillTerm* parent;
     158              :     QofBook* pBook;
     159            0 :     GncGUID* guid = (GncGUID*)value;
     160              : 
     161            0 :     g_return_if_fail (data != NULL);
     162            0 :     g_return_if_fail (GNC_IS_BILLTERM (data));
     163              : 
     164            0 :     billterm = GNC_BILLTERM (data);
     165            0 :     pBook = qof_instance_get_book (QOF_INSTANCE (billterm));
     166            0 :     if (guid != NULL)
     167              :     {
     168            0 :         parent = gncBillTermLookup (pBook, guid);
     169            0 :         if (parent != NULL)
     170              :         {
     171            0 :             gncBillTermSetParent (billterm, parent);
     172            0 :             gncBillTermSetChild (parent, billterm);
     173              :         }
     174              :     }
     175              : }
     176              : 
     177              : static void
     178            0 : bt_set_parent_guid (gpointer pObject,  gpointer pValue)
     179              : {
     180            0 :     g_return_if_fail (pObject != NULL);
     181            0 :     g_return_if_fail (pValue != NULL);
     182              : 
     183            0 :     auto s = static_cast<BillTermParentGuidPtr>(pObject);
     184            0 :     s->guid = *static_cast<GncGUID*>(pValue);
     185            0 :     s->have_guid = true;
     186              : }
     187              : 
     188              : static GncBillTerm*
     189            0 : load_single_billterm (GncSqlBackend* sql_be, GncSqlRow& row,
     190              :                       BillTermParentGuidVec& l_billterms_needing_parents)
     191              : {
     192            0 :     g_return_val_if_fail (sql_be != NULL, NULL);
     193              : 
     194            0 :     auto guid = gnc_sql_load_guid (sql_be, row);
     195            0 :     auto pBillTerm = gncBillTermLookup (sql_be->book(), guid);
     196            0 :     if (pBillTerm == nullptr)
     197              :     {
     198            0 :         pBillTerm = gncBillTermCreate (sql_be->book());
     199              :     }
     200            0 :     gnc_sql_load_object (sql_be, row, GNC_ID_BILLTERM, pBillTerm, col_table);
     201              : 
     202              :     /* If the billterm doesn't have a parent, it might be because it hasn't been
     203              :        loaded yet.  If so, add this billterm to the list of billterms with no
     204              :        parent, along with the parent GncGUID so that after they are all loaded,
     205              :        the parents can be fixed up. */
     206            0 :     if (gncBillTermGetParent (pBillTerm) == NULL)
     207              :     {
     208              :         BillTermParentGuid s;
     209              : 
     210            0 :         s.billterm = pBillTerm;
     211            0 :         s.have_guid = false;
     212            0 :         gnc_sql_load_object (sql_be, row, GNC_ID_BILLTERM, &s,
     213              :                              billterm_parent_col_table);
     214            0 :         if (s.have_guid)
     215            0 :             l_billterms_needing_parents.push_back(new BillTermParentGuid(s));
     216              : 
     217              :     }
     218              : 
     219            0 :     qof_instance_mark_clean (QOF_INSTANCE (pBillTerm));
     220              : 
     221            0 :     return pBillTerm;
     222              : }
     223              : 
     224              : /* Because gncBillTermLookup has the arguments backwards: */
     225              : static inline GncBillTerm*
     226            0 : gnc_billterm_lookup (const GncGUID *guid, const QofBook *book)
     227              : {
     228            0 :      QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_BILLTERM, GncBillTerm);
     229              : }
     230              : 
     231              : void
     232            7 : GncSqlBillTermBackend::load_all (GncSqlBackend* sql_be)
     233              : {
     234              : 
     235            7 :     g_return_if_fail (sql_be != NULL);
     236              : 
     237            7 :     std::string sql("SELECT * FROM " TABLE_NAME);
     238            7 :     auto stmt = sql_be->create_statement_from_sql(sql);
     239            7 :     auto result = sql_be->execute_select_statement(stmt);
     240            7 :     BillTermParentGuidVec l_billterms_needing_parents;
     241              : 
     242            7 :     for (auto row : *result)
     243              :     {
     244            0 :         load_single_billterm (sql_be, row, l_billterms_needing_parents);
     245            0 :     }
     246            7 :     delete result;
     247            7 :     std::string pkey(col_table[0]->name());
     248            7 :     sql = "SELECT DISTINCT ";
     249            7 :     sql += pkey + " FROM " TABLE_NAME;
     250            7 :     gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
     251              :                                          (BookLookupFn)gnc_billterm_lookup);
     252              : 
     253              :     /* While there are items on the list of billterms needing parents,
     254              :        try to see if the parent has now been loaded.  Theory says that if
     255              :        items are removed from the front and added to the back if the
     256              :        parent is still not available, then eventually, the list will
     257              :        shrink to size 0. */
     258            7 :     if (!l_billterms_needing_parents.empty())
     259              :     {
     260            0 :         bool progress_made = true;
     261            0 :         std::reverse(l_billterms_needing_parents.begin(),
     262              :                      l_billterms_needing_parents.end());
     263            0 :         auto end = l_billterms_needing_parents.end();
     264            0 :         while (progress_made)
     265              :         {
     266            0 :             progress_made = false;
     267            0 :             end = std::remove_if(l_billterms_needing_parents.begin(), end,
     268            0 :                                  [&](BillTermParentGuidPtr s)
     269              :                                  {
     270            0 :                                      auto pBook = qof_instance_get_book (QOF_INSTANCE (s->billterm));
     271            0 :                                      auto parent = gncBillTermLookup (pBook,
     272            0 :                                                                       &s->guid);
     273            0 :                                      if (parent != nullptr)
     274              :                                      {
     275            0 :                                          gncBillTermSetParent (s->billterm, parent);
     276            0 :                                          gncBillTermSetChild (parent, s->billterm);
     277            0 :                                          progress_made = true;
     278            0 :                                          delete s;
     279            0 :                                          return true;
     280              :                                      }
     281            0 :                                      return false;
     282              :                                  });
     283              :         }
     284              :     }
     285            7 : }
     286              : 
     287              : /* ================================================================= */
     288              : 
     289              : static void
     290            0 : do_save_billterm (QofInstance* inst, void* p2)
     291              : {
     292            0 :     auto data = static_cast<write_objects_t*>(p2);
     293            0 :     data->commit(inst);
     294            0 : }
     295              : 
     296              : bool
     297            6 : GncSqlBillTermBackend::write (GncSqlBackend* sql_be)
     298              : {
     299            6 :     g_return_val_if_fail (sql_be != NULL, FALSE);
     300              : 
     301            6 :     write_objects_t data {sql_be, true, this};
     302            6 :     qof_object_foreach (GNC_ID_BILLTERM, sql_be->book(), do_save_billterm, &data);
     303            6 :     return data.is_ok;
     304              : }
     305              : 
     306              : /* ================================================================= */
     307              : void
     308           13 : GncSqlBillTermBackend::create_tables (GncSqlBackend* sql_be)
     309              : {
     310              :     gint version;
     311              : 
     312           13 :     g_return_if_fail (sql_be != NULL);
     313              : 
     314           26 :     version = sql_be->get_table_version( TABLE_NAME);
     315           13 :     if (version == 0)
     316              :     {
     317           18 :         sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
     318              :     }
     319            7 :     else if (version < m_version)
     320              :     {
     321              :         /* Upgrade 64 bit int handling */
     322            0 :         sql_be->upgrade_table(TABLE_NAME, col_table);
     323            0 :         sql_be->set_table_version (TABLE_NAME, TABLE_VERSION);
     324              : 
     325            0 :         PINFO ("Billterms table upgraded from version 1 to version %d\n",
     326              :                TABLE_VERSION);
     327              :     }
     328              : }
     329              : 
     330              : /* ================================================================= */
     331              : 
     332              : template<> void
     333            3 : GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::load (const GncSqlBackend* sql_be,
     334              :                                                  GncSqlRow& row,
     335              :                                                  QofIdTypeConst obj_name,
     336              :                                                  gpointer pObject) const noexcept
     337              : {
     338            3 :     load_from_guid_ref(row, obj_name, pObject,
     339            0 :                        [sql_be](GncGUID* g){
     340            0 :                            return gncBillTermLookup(sql_be->book(), g);
     341              :                        });
     342            3 : }
     343              : 
     344              : template<> void
     345           18 : GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::add_to_table(ColVec& vec) const noexcept
     346              : {
     347           18 :     add_objectref_guid_to_table(vec);
     348           18 : }
     349              : 
     350              : template<> void
     351            3 : GncSqlColumnTableEntryImpl<CT_BILLTERMREF>::add_to_query(QofIdTypeConst obj_name,
     352              :                                                     const gpointer pObject,
     353              :                                                     PairVec& vec) const noexcept
     354              : {
     355            3 :     add_objectref_guid_to_query(obj_name, pObject, vec);
     356            3 : }
     357              : 
     358              : /* ========================== END OF FILE ===================== */
        

Generated by: LCOV version 2.0-1