LCOV - code coverage report
Current view: top level - libgnucash/backend/sql - gnc-sql-column-table-entry.hpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 92.3 % 117 108
Test Date: 2026-11-02 18:19:43 Functions: 85.5 % 172 147
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /***********************************************************************\
       2              :  * gnc-sql-column-table-entry.hpp: Column Specification for SQL Table. *
       3              :  *                                                                     *
       4              :  * Copyright 2016 John Ralls <jralls@ceridwen.us>                      *
       5              :  *                                                                     *
       6              :  * This program is free software; you can redistribute it and/or       *
       7              :  * modify it under the terms of the GNU General Public License as      *
       8              :  * published by the Free Software Foundation; either version 2 of      *
       9              :  * the License, or (at your option) any later version.                 *
      10              :  *                                                                     *
      11              :  * This program is distributed in the hope that it will be useful,     *
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
      14              :  * GNU General Public License for more details.                        *
      15              :  *                                                                     *
      16              :  * You should have received a copy of the GNU General Public License   *
      17              :  * along with this program; if not, contact:                           *
      18              :  *                                                                     *
      19              :  * Free Software Foundation           Voice:  +1-617-542-5942          *
      20              :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652          *
      21              :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                      *
      22              : \***********************************************************************/
      23              : 
      24              : #ifndef __GNC_SQL_COLUMN_TABLE_ENTRY_HPP__
      25              : #define __GNC_SQL_COLUMN_TABLE_ENTRY_HPP__
      26              : 
      27              : #include <qof.h>
      28              : #include <memory>
      29              : #include <vector>
      30              : #include <iostream>
      31              : #include <iomanip>
      32              : 
      33              : #include "gnc-sql-result.hpp"
      34              : 
      35              : struct GncSqlColumnInfo;
      36              : using ColVec = std::vector<GncSqlColumnInfo>;
      37              : using PairVec = std::vector<std::pair<std::string, std::string>>;
      38              : using InstanceVec = std::vector<QofInstance*>;
      39              : using uint_t = unsigned int;
      40              : class GncSqlBackend;
      41              : 
      42              : /**
      43              :  * Basic column type
      44              :  */
      45              : typedef enum
      46              : {
      47              :     BCT_STRING,
      48              :     BCT_INT,
      49              :     BCT_INT64,
      50              :     BCT_DATE,
      51              :     BCT_DOUBLE,
      52              :     BCT_DATETIME
      53              : } GncSqlBasicColumnType;
      54              : 
      55              : enum ColumnFlags : int
      56              : {
      57              :     COL_NO_FLAG = 0,
      58              :     COL_PKEY = 0x01,    /**< The column is a primary key */
      59              :     COL_NNUL = 0x02,    /**< The column may not contain a NULL value */
      60              :     COL_UNIQUE = 0x04,  /**< The column must contain unique values */
      61              :     COL_AUTOINC = 0x08  /**< The column is an auto-incrementing int */
      62              : };
      63              : 
      64              : // Type for conversion of db row to object.
      65              : enum GncSqlObjectType
      66              : {
      67              :     CT_STRING,
      68              :     CT_GUID,
      69              :     CT_INT,
      70              :     CT_INT64,
      71              :     CT_TIME,
      72              :     CT_GDATE,
      73              :     CT_NUMERIC,
      74              :     CT_DOUBLE,
      75              :     CT_BOOLEAN,
      76              :     CT_ACCOUNTREF,
      77              :     CT_BUDGETREF,
      78              :     CT_COMMODITYREF,
      79              :     CT_LOTREF,
      80              :     CT_TXREF,
      81              :     CT_ADDRESS,
      82              :     CT_BILLTERMREF,
      83              :     CT_INVOICEREF,
      84              :     CT_ORDERREF,
      85              :     CT_OWNERREF,
      86              :     CT_TAXTABLEREF
      87              : };
      88              : 
      89              : static inline std::string
      90         1207 : quote_string(const std::string& str)
      91              : {
      92         1207 :     if (str == "NULL" || str == "null") return "NULL";
      93              :     /* FIXME: This is here because transactions.num has a NULL
      94              :      * constraint, which is dumb; it's often empty.
      95              :      */
      96         1645 :     if (str.empty()) return "''";
      97          988 :     std::string retval;
      98          988 :     retval.reserve(str.length() + 2);
      99          988 :     retval.insert(0, 1, '\'');
     100        40652 :     for (auto c = str.begin(); c != str.end(); ++c)
     101              :     {
     102        19338 :         if (*c == '\'')
     103            2 :             retval += *c;
     104        19338 :         retval += *c;
     105              :     }
     106          988 :     retval += '\'';
     107          988 :     return retval;
     108          988 : }
     109              : 
     110              : /**
     111              :  * Contains all of the information required to copy information between an
     112              :  * object and the database for a specific object property.
     113              :  *
     114              :  * If an entry contains a gobj_param_name value, this string is used as the
     115              :  * property name for a call to g_object_get() or g_object_set().  If the
     116              :  * gobj_param_name value is NULL but qof_param_name is not NULL, this value
     117              :  * is used as the parameter name for a call to
     118              :  * qof_class_get_parameter_getter().  If both of these values are NULL, getter
     119              :  * and setter are the addresses of routines to return or set the parameter
     120              :  * value, respectively.
     121              :  *
     122              :  * The database description for an object consists of an array of
     123              :  * GncSqlColumnTableEntry objects, with a final member having col_name == NULL.
     124              :  */
     125              : 
     126              : class GncSqlColumnTableEntry
     127              : {
     128              : public:
     129         2736 :     GncSqlColumnTableEntry (const char* name, const GncSqlObjectType type,
     130              :                             unsigned int s,
     131              :                             int f, const char* gobj_name = nullptr,
     132              :                             const char* qof_name = nullptr,
     133              :                             QofAccessFunc get = nullptr,
     134         2736 :                             QofSetterFunc set = nullptr) :
     135         2736 :         m_col_name{name}, m_col_type{type}, m_size{s},
     136         2736 :         m_flags{static_cast<ColumnFlags>(f)},
     137         2736 :         m_gobj_param_name{gobj_name}, m_qof_param_name{qof_name}, m_getter{get},
     138         2736 :         m_setter{set} {}
     139         2736 :     virtual ~GncSqlColumnTableEntry() = default;
     140              : 
     141              :     /**
     142              :      * Load a value into an object from the database row.
     143              :      */
     144              :     virtual void load(const GncSqlBackend* sql_be, GncSqlRow& row,
     145              :                       QofIdTypeConst obj_name, void* pObject) const noexcept = 0;
     146              :     /**
     147              :      * Add a GncSqlColumnInfo structure for the column type to a
     148              :      * ColVec.
     149              :      */
     150              :     virtual void add_to_table(ColVec& vec) const noexcept = 0;
     151              :     /**
     152              :      * Add a pair of the table column heading and object's value's string
     153              :      * representation to a PairVec; used for constructing WHERE clauses and
     154              :      * UPDATE statements.
     155              :      */
     156              :     virtual void add_to_query(QofIdTypeConst obj_name,
     157              :                               void* pObject, PairVec& vec) const noexcept = 0;
     158              :     /**
     159              :      * Retrieve the getter function depending on whether it's an auto-increment
     160              :      * field, a QofClass getter, or a function passed to the constructor.
     161              :      */
     162              :     QofAccessFunc get_getter(QofIdTypeConst obj_name) const noexcept;
     163              :     /**
     164              :      * Retrieve the setter function depending on whether it's an auto-increment
     165              :      * field, a QofClass getter, or a function passed to the constructor.
     166              :      */
     167              :     QofSetterFunc get_setter(QofIdTypeConst obj_name) const noexcept;
     168              :     /**
     169              :      * Retrieve the field name so that we don't need to make
     170              :      * create_single_col_select_statement and friend.
     171              :      */
     172            0 :     const char* name() const noexcept { return m_col_name; }
     173              :     /**
     174              :      * Report if the entry is an auto-increment field.
     175              :      */
     176         2299 :     bool is_autoincr() const noexcept { return m_flags & COL_AUTOINC; }
     177              :     /* On the other hand, our implementation class and GncSqlColumnInfo need to
     178              :      * be able to read our member variables.
     179              :      */
     180              :     template<GncSqlObjectType Otype> friend class GncSqlColumnTableEntryImpl;
     181              :     friend struct GncSqlColumnInfo;
     182          129 :     template<typename T> void load_from_guid_ref(GncSqlRow& row,
     183              :                                                  QofIdTypeConst obj_name,
     184              :                                                  void* pObject, T get_ref)
     185              :         const noexcept
     186              :     {
     187              :         static QofLogModule log_module = G_LOG_DOMAIN;
     188          129 :         g_return_if_fail (pObject != NULL);
     189              : 
     190              :         GncGUID guid;
     191          129 :         auto val = row.get_string_at_col (m_col_name);
     192          129 :         if (!val)
     193              :         {
     194            0 :             DEBUG("set parameter: No string in column %s.", m_col_name);
     195            0 :             return;
     196              :         }
     197              : 
     198          129 :         if (string_to_guid (val->c_str(), &guid))
     199              :         {
     200           82 :             auto target = get_ref(&guid);
     201           82 :             if (target != nullptr)
     202           82 :                 set_parameter (pObject, target, get_setter(obj_name),
     203           82 :                                m_gobj_param_name);
     204              :             else
     205            0 :                 DEBUG("GUID %s returned null %s reference.",
     206              :                       val->c_str(), m_gobj_param_name);
     207              :         }
     208              :         else
     209              :         {
     210           47 :             if (val->empty())
     211           47 :                 DEBUG("Can't load empty guid string for column %s", m_col_name);
     212              :             else
     213            0 :                 DEBUG("Invalid GUID %s for column %s", val->c_str(), m_col_name);
     214              :         }
     215          129 :     }
     216              : 
     217              : 
     218              : protected:
     219              :     template <typename T> T
     220              :     get_row_value_from_object(QofIdTypeConst obj_name, const void* pObject) const;
     221              :     template <typename T> void
     222              :     add_value_to_vec(QofIdTypeConst obj_name,
     223              :                      const void* pObject, PairVec& vec) const;
     224              : /**
     225              :  * Adds a name/guid std::pair to a PairVec for creating a query.
     226              :  *
     227              :  * @param sql_be SQL backend struct
     228              :  * @param obj_name QOF object type name
     229              :  * @param pObject Object
     230              :  * @param pList List
     231              :  */
     232              :     void add_objectref_guid_to_query (QofIdTypeConst obj_name,
     233              :                                       const void* pObject,
     234              :                                       PairVec& vec) const noexcept;
     235              : /**
     236              :  * Adds a column info structure for an object reference GncGUID to a ColVec.
     237              :  *
     238              :  * @param sql_be SQL backend struct
     239              :  * @param pList List
     240              :  */
     241              :     void add_objectref_guid_to_table (ColVec& vec) const noexcept;
     242              : private:
     243              :     const char* m_col_name = nullptr;        /**< Column name */
     244              :     const GncSqlObjectType m_col_type;        /**< Column type */
     245              :     unsigned int m_size;       /**< Column size in bytes, for string columns */
     246              :     ColumnFlags m_flags;           /**< Column flags */
     247              :     const char* m_gobj_param_name = nullptr; /**< If non-null, g_object param name */
     248              :     const char* m_qof_param_name = nullptr;  /**< If non-null, qof parameter name */
     249              :     QofAccessFunc m_getter;        /**< General access function */
     250              :     QofSetterFunc m_setter;        /**< General setter function */
     251              :     template <typename T> T get_row_value_from_object(QofIdTypeConst obj_name,
     252              :                                                       const void* pObject,
     253              :                                                       std::true_type) const;
     254              :     template <typename T> T get_row_value_from_object(QofIdTypeConst obj_name,
     255              :                                                       const void* pObject,
     256              :                                                       std::false_type) const;
     257              :     template <typename T> void add_value_to_vec(QofIdTypeConst obj_name,
     258              :                                                 const void* pObject,
     259              :                                                 PairVec& vec, std::true_type) const;
     260              :     template <typename T> void add_value_to_vec(QofIdTypeConst obj_name,
     261              :                                                 const void* pObject,
     262              :                                                 PairVec& vec, std::false_type) const;
     263              : 
     264              : };
     265              : 
     266              : template <GncSqlObjectType Type>
     267              : class GncSqlColumnTableEntryImpl final : public GncSqlColumnTableEntry
     268              : {
     269              : public:
     270         2736 :     GncSqlColumnTableEntryImpl (const char* name, const GncSqlObjectType type,
     271              :                                 unsigned int s,
     272              :                                 int f, const char* gobj_name = nullptr,
     273              :                                 const char* qof_name = nullptr,
     274              :                                 QofAccessFunc get = nullptr,
     275              :                                 QofSetterFunc set = nullptr) :
     276         2736 :         GncSqlColumnTableEntry (name, type, s, f, gobj_name,qof_name, get, set)
     277         2736 :         {}
     278              : 
     279              :     void load(const GncSqlBackend* sql_be, GncSqlRow& row,  QofIdTypeConst obj_name,
     280              :               void* pObject) const noexcept override;
     281              :     void add_to_table(ColVec& vec) const noexcept override;
     282              :     void add_to_query(QofIdTypeConst obj_name, void* pObject, PairVec& vec)
     283              :         const noexcept override;
     284              : };
     285              : 
     286              : using GncSqlColumnTableEntryPtr = std::shared_ptr<GncSqlColumnTableEntry>;
     287              : using EntryVec = std::vector<GncSqlColumnTableEntryPtr>;
     288              : 
     289              : template <GncSqlObjectType Type>
     290              : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
     291           96 : gnc_sql_make_table_entry(const char* name, unsigned int s, int f)
     292              : {
     293           96 :     return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s, f);
     294              : }
     295              : 
     296              : template <GncSqlObjectType Type>
     297              : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
     298         1356 : gnc_sql_make_table_entry(const char* name, unsigned int s, int f,
     299              :                          const char* param)
     300              : {
     301              :     return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s,
     302         1356 :                                                               f, param);
     303              : }
     304              : 
     305              : class is_qof : public std::true_type {};
     306              : 
     307              : template <GncSqlObjectType Type>
     308              : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
     309          528 : gnc_sql_make_table_entry(const char* name, unsigned int s, int f,
     310              :                          const char* param, bool qofp)
     311              : {
     312              :     return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s,
     313         1056 :                                                               f, nullptr,
     314          528 :                                                               param);
     315              : }
     316              : 
     317              : template <GncSqlObjectType Type>
     318              : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
     319          744 : gnc_sql_make_table_entry(const char* name, unsigned int s, int f,
     320              :                          QofAccessFunc get, QofSetterFunc set)
     321              : {
     322              :     return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(
     323          744 :         name, Type, s, f, nullptr, nullptr, get, set);
     324              : }
     325              : 
     326              : 
     327              : template <typename T> T
     328         1934 : GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
     329              :                                                   const void* pObject) const
     330              : {
     331         3868 :     return get_row_value_from_object<T>(obj_name, pObject,
     332         1934 :                                         std::is_pointer<T>());
     333              : }
     334              : 
     335              : template <typename T> T
     336         1532 : GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
     337              :                                                   const void* pObject,
     338              :                                                   std::true_type) const
     339              : {
     340         1532 :     g_return_val_if_fail(obj_name != nullptr && pObject != nullptr, nullptr);
     341         1532 :     T result = nullptr;
     342         1532 :     if (m_gobj_param_name != nullptr)
     343          747 :         g_object_get(const_cast<void*>(pObject), m_gobj_param_name,
     344              :                      &result, nullptr);
     345              :     else
     346              :     {
     347          785 :         QofAccessFunc getter = get_getter(obj_name);
     348          785 :         if (getter != nullptr)
     349          785 :             result = reinterpret_cast<T>((getter)(const_cast<void*>(pObject),
     350              :                                                   nullptr));
     351              :     }
     352         1532 :     return result;
     353              : }
     354              : 
     355              : template <typename T> T
     356              : GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
     357              :                                                   const void* pObject,
     358              :                                                   std::false_type) const
     359              : {
     360              :     g_return_val_if_fail(obj_name != nullptr && pObject != nullptr,
     361              :                          static_cast<T>(0));
     362              :     T result = static_cast<T>(0);
     363              :     if (m_gobj_param_name != nullptr)
     364              :         g_object_get(const_cast<void*>(pObject), m_gobj_param_name,
     365              :                      &result, nullptr);
     366              :     else
     367              :     {
     368              :         QofAccessFunc getter = get_getter(obj_name);
     369              :         if (getter != nullptr)
     370              :         {
     371              :             result = static_cast<T>(reinterpret_cast<intptr_t>((getter)(const_cast<void*>(pObject),
     372              :                                                                          nullptr)));
     373              :         }
     374              :     }
     375              :     return result;
     376              : }
     377              : 
     378              : template <typename T> void
     379          554 : GncSqlColumnTableEntry::add_value_to_vec(QofIdTypeConst obj_name,
     380              :                                          const void* pObject,
     381              :                                          PairVec& vec) const
     382              : {
     383          554 :     add_value_to_vec<T>(obj_name, pObject, vec, std::is_pointer<T>());
     384          554 : }
     385              : 
     386              : template <typename T> void
     387              : GncSqlColumnTableEntry::add_value_to_vec(QofIdTypeConst obj_name,
     388              :                                          const void* pObject,
     389              :                                          PairVec& vec, std::true_type) const
     390              : {
     391              :     T s = get_row_value_from_object<T>(obj_name, pObject);
     392              : 
     393              :     if (s != nullptr)
     394              :     {
     395              :         std::ostringstream stream;
     396              :         stream << *s;
     397              :         vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
     398              :         return;
     399              :     }
     400              : }
     401              : 
     402              : template <> inline  void
     403           75 : GncSqlColumnTableEntry::add_value_to_vec<double*>(QofIdTypeConst obj_name,
     404              :                                          const void* pObject,
     405              :                                          PairVec& vec, std::true_type) const
     406              : {
     407           75 :     double* s = get_row_value_from_object<double*>(obj_name, pObject);
     408              : 
     409           75 :     if (s != nullptr)
     410              :     {
     411            4 :         std::ostringstream stream;
     412            4 :         stream << std::setprecision(12) << std::fixed << *s;
     413           12 :         vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
     414            4 :         return;
     415            4 :     }
     416              : }
     417              : 
     418              : template <typename T> void
     419          479 : GncSqlColumnTableEntry::add_value_to_vec(QofIdTypeConst obj_name,
     420              :                                          const void* pObject,
     421              :                                          PairVec& vec, std::false_type) const
     422              : {
     423          479 :     T s = get_row_value_from_object<T>(obj_name, pObject);
     424              : 
     425          479 :     std::ostringstream stream;
     426          479 :     stream << s;
     427         1437 :     vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
     428          958 :     return;
     429          479 : }
     430              : 
     431              : template <> inline void
     432              : GncSqlColumnTableEntry::add_value_to_vec<double>(QofIdTypeConst obj_name,
     433              :                                          const void* pObject,
     434              :                                          PairVec& vec, std::false_type) const
     435              : {
     436              :     double s = *get_row_value_from_object<double*>(obj_name, pObject);
     437              : 
     438              :     std::ostringstream stream;
     439              :     stream << std::setprecision(12) << std::fixed << s;
     440              :     vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
     441              :     return;
     442              : }
     443              : 
     444              : /**
     445              :  * Load an arbitrary object from a result row.
     446              :  *
     447              :  * @param sql_be: GncSqlBackend*, pass-through to the implementation loader.
     448              :  * @param row: The GncSqlResult
     449              :  * @param obj_name: The object-name with which to retrieve the setter func.
     450              :  * @param pObject: The target object being loaded.
     451              :  * @param table: The table description to interpret the row.
     452              :  */
     453              : void gnc_sql_load_object (const GncSqlBackend* sql_be, GncSqlRow& row,
     454              :                           QofIdTypeConst obj_name, gpointer pObject,
     455              :                           const EntryVec& table);
     456              : /**
     457              :  * Create a GncGUID from a guid stored in a row.
     458              :  *
     459              :  * @param sql_be: The active GncSqlBackend. Pass-throug to gnc_sql_load_object.
     460              :  * @param row: The GncSqlResult row.
     461              :  */
     462              : const GncGUID*
     463              : gnc_sql_load_guid (const GncSqlBackend* sql_be, GncSqlRow& row);
     464              : 
     465              : /**
     466              :  * Append the GUIDs of QofInstances to a SQL query.
     467              :  *
     468              :  * @param sql: The SQL Query in progress to which the GncGUIDS should be appended.
     469              :  * @param instances: The QofInstances
     470              :  * @return The number of instances
     471              :  */
     472              : uint_t gnc_sql_append_guids_to_sql (std::stringstream& sql,
     473              :                                     const InstanceVec& instances);
     474              : 
     475              : /**
     476              :  *  information required to create a column in a table.
     477              :  */
     478              : struct GncSqlColumnInfo
     479              : {
     480          444 :     GncSqlColumnInfo (std::string&& name, GncSqlBasicColumnType type,
     481              :                       unsigned int size = 0, bool unicode = false,
     482              :                       bool autoinc = false, bool primary = false,
     483          444 :                       bool not_null = false) :
     484          444 :         m_name{name}, m_type{type}, m_size{size}, m_unicode{unicode},
     485          444 :         m_autoinc{autoinc}, m_primary_key{primary}, m_not_null{not_null}
     486          444 :         {}
     487         1068 :     GncSqlColumnInfo(const GncSqlColumnTableEntry& e, GncSqlBasicColumnType t,
     488         1068 :                      unsigned int size = 0, bool unicode = true) :
     489         2136 :         m_name{e.m_col_name}, m_type{t}, m_size{size}, m_unicode{unicode},
     490         1068 :         m_autoinc(e.m_flags & COL_AUTOINC),
     491         1068 :         m_primary_key(e.m_flags & COL_PKEY),
     492         1068 :         m_not_null(e.m_flags & COL_NNUL) {}
     493              :     std::string m_name; /**< Column name */
     494              :     GncSqlBasicColumnType m_type; /**< Column basic type */
     495              :     unsigned int m_size; /**< Column size (string types) */
     496              :     bool m_unicode; /**< Column is unicode (string types) */
     497              :     bool m_autoinc; /**< Column is autoinc (int type) */
     498              :     bool m_primary_key; /**< Column is the primary key */
     499              :     bool m_not_null; /**< Column forbids NULL values */
     500              : };
     501              : 
     502            0 : inline bool operator==(const GncSqlColumnInfo& l,
     503              :                        const GncSqlColumnInfo& r)
     504              : {
     505            0 :     return l.m_name == r.m_name && l.m_type == r.m_type;
     506              : }
     507              : 
     508            0 : inline bool operator!=(const GncSqlColumnInfo& l,
     509              :                        const GncSqlColumnInfo& r)
     510              : {
     511            0 :     return !(l == r);
     512              : }
     513              : 
     514              : /**
     515              :  * Set an object property with a setter function.
     516              :  * @param pObject void* to the object being set.
     517              :  * @param item the value to be set in the property.
     518              :  * @param setter The function to set the property.
     519              :  * The void* is an obvious wart occasioned by the fact that we're using GLists
     520              :  * to hold objects. As the rewrite progresses we'll replace that with another
     521              :  * template parameter.
     522              :  */
     523              : template <typename T, typename P, typename F>
     524          411 : void set_parameter(T object, P item, F& setter)
     525              : {
     526          411 :     (*setter)(object, item);
     527          411 : }
     528              : 
     529              : template <typename T, typename P>
     530          558 : void set_parameter(T object, P item, QofSetterFunc setter, std::true_type)
     531              : {
     532          558 :     (*setter)(object, (void*)item);
     533          558 : }
     534              : 
     535              : template <typename T, typename P>
     536           74 : void set_parameter(T object, P item, QofSetterFunc setter, std::false_type)
     537              : {
     538           74 :     (*setter)(object, (void*)(&item));
     539           74 : }
     540              : 
     541              : template <typename T, typename P>
     542          632 : void set_parameter(T object, P item, QofSetterFunc setter)
     543              : {
     544          632 :     set_parameter(object, item, setter, std::is_pointer<P>());
     545          632 : }
     546              : 
     547              : /**
     548              :  * Set an object property with g_object_set.
     549              :  * @param pObject void* to the object being set.
     550              :  * @param item the value to set in the property.
     551              :  * @param property the property name.
     552              :  * The void* is an obvious wart. So is g_object_set, partly because it's GObject
     553              :  * but mostly because it works off of string comparisons.
     554              :  */
     555              : template <typename T, typename P>
     556          760 : void set_parameter(T object, P item, const char* property)
     557              : {
     558              :     // Properly use qof_begin_edit and qof_commit_edit{_part2}
     559              :     // here. This is needed to reset the infant state of objects
     560              :     // when loading them initially from sql. Failing to do so
     561              :     // could prevent future editing of these objects
     562              :     // Example of this is https://bugs.gnucash.org/show_bug.cgi?id=795944
     563          760 :     qof_begin_edit(QOF_INSTANCE(object));
     564          760 :     g_object_set(object, property, item, nullptr);
     565          760 :     if (!qof_commit_edit(QOF_INSTANCE(object))) return;
     566              :     // FIXME I can't use object specific callbacks in generic code
     567              :     // so for now these will silently fail. As the GObject based method
     568              :     // of setting qof objects should go away eventually I won't bother
     569              :     // finding a proper solution for this.
     570          203 :     qof_commit_edit_part2(QOF_INSTANCE(object), nullptr, nullptr, nullptr);
     571              : };
     572              : 
     573              : /**
     574              :  * Set an object property with either a g_object_set or a setter.
     575              :  *
     576              :  * See previous templates for the parameter meanings. This is clunky but fits in
     577              :  * the current architecture for refactoring.
     578              :  */
     579              : template <typename T, typename P, typename F>
     580         1804 : void set_parameter(T object, P item, F setter, const char* property)
     581              : {
     582         1804 :     if (property)
     583          761 :         set_parameter(object, item, property);
     584              :     else
     585         1043 :         set_parameter(object, item, setter);
     586         1804 : }
     587              : 
     588              : #endif //__GNC_SQL_COLUMN_TABLE_ENTRY_HPP__
        

Generated by: LCOV version 2.0-1