Branch data 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 : 1070 : quote_string(const std::string& str)
91 : : {
92 : 1070 : 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 : 1070 : if (str.empty()) return "''";
97 : 877 : std::string retval;
98 : 877 : retval.reserve(str.length() + 2);
99 : 877 : retval.insert(0, 1, '\'');
100 : 17881 : for (auto c = str.begin(); c != str.end(); ++c)
101 : : {
102 : 17004 : if (*c == '\'')
103 : 2 : retval += *c;
104 : 17004 : retval += *c;
105 : : }
106 : 877 : retval += '\'';
107 : 877 : return retval;
108 : 877 : }
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 : 13452 : 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 : 13452 : QofSetterFunc set = nullptr) :
135 : 13452 : m_col_name{name}, m_col_type{type}, m_size{s},
136 : 13452 : m_flags{static_cast<ColumnFlags>(f)},
137 : 13452 : m_gobj_param_name{gobj_name}, m_qof_param_name{qof_name}, m_getter{get},
138 : 13452 : m_setter{set} {}
139 : 13452 : 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 : 2033 : 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 : 108 : 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 : 108 : g_return_if_fail (pObject != NULL);
189 : :
190 : : GncGUID guid;
191 : 108 : auto val = row.get_string_at_col (m_col_name);
192 : 108 : if (!val)
193 : : {
194 : 0 : DEBUG("set parameter: No string in column %s.", m_col_name);
195 : 0 : return;
196 : : }
197 : :
198 : 108 : if (string_to_guid (val->c_str(), &guid))
199 : : {
200 : 70 : auto target = get_ref(&guid);
201 : 70 : if (target != nullptr)
202 : 70 : set_parameter (pObject, target, get_setter(obj_name),
203 : 70 : 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 : 38 : if (val->empty())
211 : 38 : 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 : 108 : }
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 : 13452 : 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 : 13452 : GncSqlColumnTableEntry (name, type, s, f, gobj_name,qof_name, get, set)
277 : 13452 : {}
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 : 472 : gnc_sql_make_table_entry(const char* name, unsigned int s, int f)
292 : : {
293 : 472 : return std::make_shared<GncSqlColumnTableEntryImpl<Type>>(name, Type, s, f);
294 : : }
295 : :
296 : : template <GncSqlObjectType Type>
297 : : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
298 : 6667 : 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 : 6667 : f, param);
303 : : }
304 : :
305 : : class is_qof : public std::true_type {};
306 : :
307 : : template <GncSqlObjectType Type>
308 : : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
309 : 2596 : 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 : 5192 : f, nullptr,
314 : 2596 : param);
315 : : }
316 : :
317 : : template <GncSqlObjectType Type>
318 : : std::shared_ptr<GncSqlColumnTableEntryImpl<Type>>
319 : 3658 : 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 : 3658 : name, Type, s, f, nullptr, nullptr, get, set);
324 : : }
325 : :
326 : :
327 : : template <typename T> T
328 : 1784 : GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
329 : : const void* pObject) const
330 : : {
331 : 3568 : return get_row_value_from_object<T>(obj_name, pObject,
332 : 1784 : std::is_pointer<T>());
333 : : }
334 : :
335 : : template <typename T> T
336 : 1353 : GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
337 : : const void* pObject,
338 : : std::true_type) const
339 : : {
340 : 1353 : g_return_val_if_fail(obj_name != nullptr && pObject != nullptr, nullptr);
341 : 1353 : T result = nullptr;
342 : 1353 : if (m_gobj_param_name != nullptr)
343 : 664 : g_object_get(const_cast<void*>(pObject), m_gobj_param_name,
344 : : &result, nullptr);
345 : : else
346 : : {
347 : 689 : QofAccessFunc getter = get_getter(obj_name);
348 : 689 : if (getter != nullptr)
349 : 689 : result = reinterpret_cast<T>((getter)(const_cast<void*>(pObject),
350 : : nullptr));
351 : : }
352 : 1353 : return result;
353 : : }
354 : :
355 : : template <typename T> T
356 : 67 : GncSqlColumnTableEntry::get_row_value_from_object(QofIdTypeConst obj_name,
357 : : const void* pObject,
358 : : std::false_type) const
359 : : {
360 : 67 : g_return_val_if_fail(obj_name != nullptr && pObject != nullptr,
361 : : static_cast<T>(0));
362 : 67 : T result = static_cast<T>(0);
363 : 67 : if (m_gobj_param_name != nullptr)
364 : 2 : g_object_get(const_cast<void*>(pObject), m_gobj_param_name,
365 : : &result, nullptr);
366 : : else
367 : : {
368 : 65 : QofAccessFunc getter = get_getter(obj_name);
369 : 65 : if (getter != nullptr)
370 : 65 : result = reinterpret_cast<T>((getter)(const_cast<void*>(pObject),
371 : : nullptr));
372 : : }
373 : 67 : return result;
374 : : }
375 : :
376 : : template <typename T> void
377 : 496 : GncSqlColumnTableEntry::add_value_to_vec(QofIdTypeConst obj_name,
378 : : const void* pObject,
379 : : PairVec& vec) const
380 : : {
381 : 496 : add_value_to_vec<T>(obj_name, pObject, vec, std::is_pointer<T>());
382 : 496 : }
383 : :
384 : : template <typename T> void
385 : : GncSqlColumnTableEntry::add_value_to_vec(QofIdTypeConst obj_name,
386 : : const void* pObject,
387 : : PairVec& vec, std::true_type) const
388 : : {
389 : : T s = get_row_value_from_object<T>(obj_name, pObject);
390 : :
391 : : if (s != nullptr)
392 : : {
393 : : std::ostringstream stream;
394 : : stream << *s;
395 : : vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
396 : : return;
397 : : }
398 : : }
399 : :
400 : : template <> inline void
401 : 65 : GncSqlColumnTableEntry::add_value_to_vec<double*>(QofIdTypeConst obj_name,
402 : : const void* pObject,
403 : : PairVec& vec, std::true_type) const
404 : : {
405 : 65 : double* s = get_row_value_from_object<double*>(obj_name, pObject);
406 : :
407 : 65 : if (s != nullptr)
408 : : {
409 : 3 : std::ostringstream stream;
410 : 3 : stream << std::setprecision(12) << std::fixed << *s;
411 : 3 : vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
412 : 3 : return;
413 : 3 : }
414 : : }
415 : :
416 : : template <typename T> void
417 : 431 : GncSqlColumnTableEntry::add_value_to_vec(QofIdTypeConst obj_name,
418 : : const void* pObject,
419 : : PairVec& vec, std::false_type) const
420 : : {
421 : 431 : T s = get_row_value_from_object<T>(obj_name, pObject);
422 : :
423 : 431 : std::ostringstream stream;
424 : 431 : stream << s;
425 : 431 : vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
426 : 862 : return;
427 : 431 : }
428 : :
429 : : template <> inline void
430 : : GncSqlColumnTableEntry::add_value_to_vec<double>(QofIdTypeConst obj_name,
431 : : const void* pObject,
432 : : PairVec& vec, std::false_type) const
433 : : {
434 : : double s = *get_row_value_from_object<double*>(obj_name, pObject);
435 : :
436 : : std::ostringstream stream;
437 : : stream << std::setprecision(12) << std::fixed << s;
438 : : vec.emplace_back(std::make_pair(std::string{m_col_name}, stream.str()));
439 : : return;
440 : : }
441 : :
442 : : /**
443 : : * Load an arbitrary object from a result row.
444 : : *
445 : : * @param sql_be: GncSqlBackend*, pass-through to the implementation loader.
446 : : * @param row: The GncSqlResult
447 : : * @param obj_name: The object-name with which to retrieve the setter func.
448 : : * @param pObject: The target object being loaded.
449 : : * @param table: The table description to interpret the row.
450 : : */
451 : : void gnc_sql_load_object (const GncSqlBackend* sql_be, GncSqlRow& row,
452 : : QofIdTypeConst obj_name, gpointer pObject,
453 : : const EntryVec& table);
454 : : /**
455 : : * Create a GncGUID from a guid stored in a row.
456 : : *
457 : : * @param sql_be: The active GncSqlBackend. Pass-throug to gnc_sql_load_object.
458 : : * @param row: The GncSqlResult row.
459 : : */
460 : : const GncGUID*
461 : : gnc_sql_load_guid (const GncSqlBackend* sql_be, GncSqlRow& row);
462 : :
463 : : /**
464 : : * Append the GUIDs of QofInstances to a SQL query.
465 : : *
466 : : * @param sql: The SQL Query in progress to which the GncGUIDS should be appended.
467 : : * @param instances: The QofInstances
468 : : * @return The number of instances
469 : : */
470 : : uint_t gnc_sql_append_guids_to_sql (std::stringstream& sql,
471 : : const InstanceVec& instances);
472 : :
473 : : /**
474 : : * information required to create a column in a table.
475 : : */
476 : : struct GncSqlColumnInfo
477 : : {
478 : 370 : GncSqlColumnInfo (std::string&& name, GncSqlBasicColumnType type,
479 : : unsigned int size = 0, bool unicode = false,
480 : : bool autoinc = false, bool primary = false,
481 : 370 : bool not_null = false) :
482 : 370 : m_name{name}, m_type{type}, m_size{size}, m_unicode{unicode},
483 : 370 : m_autoinc{autoinc}, m_primary_key{primary}, m_not_null{not_null}
484 : 370 : {}
485 : 890 : GncSqlColumnInfo(const GncSqlColumnTableEntry& e, GncSqlBasicColumnType t,
486 : 890 : unsigned int size = 0, bool unicode = true) :
487 : 890 : m_name{e.m_col_name}, m_type{t}, m_size{size}, m_unicode{unicode},
488 : 890 : m_autoinc(e.m_flags & COL_AUTOINC),
489 : 890 : m_primary_key(e.m_flags & COL_PKEY),
490 : 890 : m_not_null(e.m_flags & COL_NNUL) {}
491 : : std::string m_name; /**< Column name */
492 : : GncSqlBasicColumnType m_type; /**< Column basic type */
493 : : unsigned int m_size; /**< Column size (string types) */
494 : : bool m_unicode; /**< Column is unicode (string types) */
495 : : bool m_autoinc; /**< Column is autoinc (int type) */
496 : : bool m_primary_key; /**< Column is the primary key */
497 : : bool m_not_null; /**< Column forbids NULL values */
498 : : };
499 : :
500 : 0 : inline bool operator==(const GncSqlColumnInfo& l,
501 : : const GncSqlColumnInfo& r)
502 : : {
503 : 0 : return l.m_name == r.m_name && l.m_type == r.m_type;
504 : : }
505 : :
506 : 0 : inline bool operator!=(const GncSqlColumnInfo& l,
507 : : const GncSqlColumnInfo& r)
508 : : {
509 : 0 : return !(l == r);
510 : : }
511 : :
512 : : /**
513 : : * Set an object property with a setter function.
514 : : * @param pObject void* to the object being set.
515 : : * @param item the value to be set in the property.
516 : : * @param setter The function to set the property.
517 : : * The void* is an obvious wart occasioned by the fact that we're using GLists
518 : : * to hold objects. As the rewrite progresses we'll replace that with another
519 : : * template parameter.
520 : : */
521 : : template <typename T, typename P, typename F>
522 : 331 : void set_parameter(T object, P item, F& setter)
523 : : {
524 : 331 : (*setter)(object, item);
525 : 331 : }
526 : :
527 : : template <typename T, typename P>
528 : 450 : void set_parameter(T object, P item, QofSetterFunc setter, std::true_type)
529 : : {
530 : 450 : (*setter)(object, (void*)item);
531 : 450 : }
532 : :
533 : : template <typename T, typename P>
534 : 58 : void set_parameter(T object, P item, QofSetterFunc setter, std::false_type)
535 : : {
536 : 58 : (*setter)(object, (void*)(&item));
537 : 58 : }
538 : :
539 : : template <typename T, typename P>
540 : 508 : void set_parameter(T object, P item, QofSetterFunc setter)
541 : : {
542 : 508 : set_parameter(object, item, setter, std::is_pointer<P>());
543 : 508 : }
544 : :
545 : : /**
546 : : * Set an object property with g_object_set.
547 : : * @param pObject void* to the object being set.
548 : : * @param item the value to set in the property.
549 : : * @param property the property name.
550 : : * The void* is an obvious wart. So is g_object_set, partly because it's GObject
551 : : * but mostly because it works off of string comparisons.
552 : : */
553 : : template <typename T, typename P>
554 : 628 : void set_parameter(T object, P item, const char* property)
555 : : {
556 : : // Properly use qof_begin_edit and qof_commit_edit{_part2}
557 : : // here. This is needed to reset the infant state of objects
558 : : // when loading them initially from sql. Failing to do so
559 : : // could prevent future editing of these objects
560 : : // Example of this is https://bugs.gnucash.org/show_bug.cgi?id=795944
561 : 628 : qof_begin_edit(QOF_INSTANCE(object));
562 : 628 : g_object_set(object, property, item, nullptr);
563 : 628 : if (!qof_commit_edit(QOF_INSTANCE(object))) return;
564 : : // FIXME I can't use object specific callbacks in generic code
565 : : // so for now these will silently fail. As the GObject based method
566 : : // of setting qof objects should go away eventually I won't bother
567 : : // finding a proper solution for this.
568 : 173 : qof_commit_edit_part2(QOF_INSTANCE(object), nullptr, nullptr, nullptr);
569 : : };
570 : :
571 : : /**
572 : : * Set an object property with either a g_object_set or a setter.
573 : : *
574 : : * See previous templates for the parameter meanings. This is clunky but fits in
575 : : * the current architecture for refactoring.
576 : : */
577 : : template <typename T, typename P, typename F>
578 : 1469 : void set_parameter(T object, P item, F setter, const char* property)
579 : : {
580 : 1469 : if (property)
581 : 630 : set_parameter(object, item, property);
582 : : else
583 : 839 : set_parameter(object, item, setter);
584 : 1469 : }
585 : :
586 : : #endif //__GNC_SQL_COLUMN_TABLE_ENTRY_HPP__
|