GnuCash  5.6-150-g038405b370+
gnc-sql-column-table-entry.cpp
1 /********************************************************************
2  * gnc-sql-column-table-entry.cpp: Implement GncSqlColumnTableEntry *
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 #include <config.h>
25 #include <qof.h>
26 #include <sstream>
27 #include <iomanip>
28 #include <cstdint>
29 #include <gnc-datetime.hpp>
30 #include "gnc-sql-backend.hpp"
31 #include "gnc-sql-object-backend.hpp"
32 #include "gnc-sql-column-table-entry.hpp"
33 #include "gnc-sql-result.hpp"
34 
35 static QofLogModule log_module = G_LOG_DOMAIN;
36 
37 /* ================================================================= */
38 static gpointer
39 get_autoinc_id (void* object, const QofParam* param)
40 {
41  // Just need a 0 to force a new autoinc value
42  return (gpointer)0;
43 }
44 
45 static void
46 set_autoinc_id (void* object, void* item)
47 {
48  // Nowhere to put the ID
49 }
50 
51 
54 {
55  QofAccessFunc getter;
56 
57  g_return_val_if_fail (obj_name != NULL, NULL);
58 
59  if (m_flags & COL_AUTOINC)
60  {
61  getter = get_autoinc_id;
62  }
63  else if (m_qof_param_name != NULL)
64  {
65  getter = qof_class_get_parameter_getter (obj_name, m_qof_param_name);
66  }
67  else
68  {
69  getter = m_getter;
70  }
71 
72  return getter;
73 }
74 
77 {
78  QofSetterFunc setter = nullptr;
79  if (m_flags & COL_AUTOINC)
80  {
81  setter = set_autoinc_id;
82  }
83  else if (m_qof_param_name != nullptr)
84  {
85  g_assert (obj_name != NULL);
86  setter = qof_class_get_parameter_setter (obj_name, m_qof_param_name);
87  }
88  else
89  {
90  setter = m_setter;
91  }
92  return setter;
93 }
94 
95 void
97  const void* pObject,
98  PairVec& vec) const noexcept
99 {
100  auto inst = get_row_value_from_object<QofInstance*>(obj_name, pObject);
101  if (inst == nullptr) return;
102  auto guid = qof_instance_get_guid (inst);
103  if (guid != nullptr) {
104  gchar *guid_s = guid_to_string(guid);
105  vec.emplace_back (std::make_pair (std::string{m_col_name}, quote_string(guid_s)));
106  g_free(guid_s);
107  }
108 }
109 
110 void
112 {
113  GncSqlColumnInfo info{*this, BCT_STRING, GUID_ENCODING_LENGTH, FALSE};
114  vec.emplace_back(std::move(info));
115 }
116 
117 
118 /* ----------------------------------------------------------------- */
119 template<> void
121  GncSqlRow& row,
122  QofIdTypeConst obj_name,
123  gpointer pObject) const noexcept
124 {
125  g_return_if_fail (pObject != NULL);
126  g_return_if_fail (m_gobj_param_name != NULL || get_setter(obj_name) != NULL);
127 
128  auto s = row.get_string_at_col (m_col_name);
129  if (s)
130  set_parameter(pObject, s->c_str(), get_setter(obj_name), m_gobj_param_name);
131 }
132 
133 template<> void
135 {
136  GncSqlColumnInfo info{*this, BCT_STRING, m_size, TRUE};
137  vec.emplace_back(std::move(info));
138 }
139 
140 /* char is unusual in that we get a pointer but don't deref it to pass
141  * it to operator<<().
142  */
143 template<> void
145  const gpointer pObject,
146  PairVec& vec) const noexcept
147 {
148  auto s = get_row_value_from_object<char*>(obj_name, pObject);
149 
150  if (s != nullptr)
151  {
152  std::ostringstream stream;
153  stream << s;
154  vec.emplace_back (std::make_pair (std::string{m_col_name},
155  quote_string(stream.str())));
156  return;
157  }
158 }
159 
160 /* ----------------------------------------------------------------- */
161 typedef gint (*IntAccessFunc) (const gpointer);
162 typedef void (*IntSetterFunc) (const gpointer, gint);
163 
164 template<> void
166  GncSqlRow& row,
167  QofIdTypeConst obj_name,
168  gpointer pObject) const noexcept
169 {
170 
171  g_return_if_fail (pObject != NULL);
172  g_return_if_fail (m_gobj_param_name != NULL || get_setter(obj_name) != NULL);
173 
174  auto val = row.get_int_at_col(m_col_name);
175  if (val)
176  set_parameter(pObject, *val,
177  reinterpret_cast<IntSetterFunc>(get_setter(obj_name)),
178  m_gobj_param_name);
179 }
180 
181 template<> void
183 {
184  GncSqlColumnInfo info{*this, BCT_INT, 0, FALSE};
185  vec.emplace_back(std::move(info));
186 }
187 
188 template<> void
190  const gpointer pObject,
191  PairVec& vec) const noexcept
192 {
193  add_value_to_vec<int>(obj_name, pObject, vec);
194 }
195 
196 /* ----------------------------------------------------------------- */
197 typedef gboolean (*BooleanAccessFunc) (const gpointer);
198 typedef void (*BooleanSetterFunc) (const gpointer, gboolean);
199 
200 template<> void
202  GncSqlRow& row,
203  QofIdTypeConst obj_name,
204  gpointer pObject)
205  const noexcept
206 {
207  g_return_if_fail (pObject != NULL);
208  g_return_if_fail (m_gobj_param_name != NULL || get_setter(obj_name) != NULL);
209 
210  auto val = row.get_int_at_col (m_col_name);
211  if (val)
212  set_parameter(pObject, static_cast<int>(*val),
213  reinterpret_cast<BooleanSetterFunc>(get_setter(obj_name)),
214  m_gobj_param_name);
215 }
216 
217 template<> void
219 {
220  GncSqlColumnInfo info{*this, BCT_INT, 0, FALSE};
221  vec.emplace_back(std::move(info));
222 }
223 
224 template<> void
226  const gpointer pObject,
227  PairVec& vec) const noexcept
228 {
229  add_value_to_vec<int>(obj_name, pObject, vec);
230 }
231 
232 /* ----------------------------------------------------------------- */
233 typedef gint64 (*Int64AccessFunc) (const gpointer);
234 typedef void (*Int64SetterFunc) (const gpointer, gint64);
235 
236 template<> void
238  GncSqlRow& row,
239  QofIdTypeConst obj_name,
240  gpointer pObject)
241  const noexcept
242 {
243  g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
244 
245  auto val = row.get_int_at_col (m_col_name);
246  if (val)
247  set_parameter(pObject, *val,
248  reinterpret_cast<Int64SetterFunc>(get_setter(obj_name)),
249  m_gobj_param_name);
250 }
251 
252 template<> void
254 {
255 
256  GncSqlColumnInfo info{*this, BCT_INT64, 0, FALSE};
257  vec.emplace_back(std::move(info));
258 }
259 
260 template<> void
262  const gpointer pObject,
263  PairVec& vec) const noexcept
264 {
265  add_value_to_vec<int64_t>(obj_name, pObject, vec);
266 }
267 /* ----------------------------------------------------------------- */
268 
269 template<> void
271  GncSqlRow& row,
272  QofIdTypeConst obj_name,
273  gpointer pObject)
274  const noexcept
275 {
276  g_return_if_fail (pObject != NULL);
277  g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
278  double val{0.0};
279 
280  if (auto int_val{row.get_int_at_col(m_col_name)})
281  val = static_cast<decltype(val)>(*int_val);
282  else if (auto float_val{row.get_float_at_col(m_col_name)})
283  val = static_cast<decltype(val)>(*float_val);
284  else if (auto double_val{row.get_double_at_col(m_col_name)})
285  val = *double_val;
286 
287  set_parameter(pObject, val, get_setter(obj_name), m_gobj_param_name);
288 }
289 
290 template<> void
292 {
293  GncSqlColumnInfo info{*this, BCT_DOUBLE, 0, FALSE};
294  vec.emplace_back(std::move(info));
295 }
296 
297 template<> void
299  const gpointer pObject,
300  PairVec& vec) const noexcept
301 {
302  add_value_to_vec<double*>(obj_name, pObject, vec);
303 }
304 
305 /* ----------------------------------------------------------------- */
306 
307 template<> void
309  GncSqlRow& row,
310  QofIdTypeConst obj_name,
311  gpointer pObject)
312  const noexcept
313 {
314 
315  GncGUID guid;
316 
317  g_return_if_fail (pObject != NULL);
318  g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
319 
320  auto strval{row.get_string_at_col(m_col_name)};
321  if (strval && string_to_guid (strval->c_str(), &guid))
322  set_parameter(pObject, &guid, get_setter(obj_name), m_gobj_param_name);
323 }
324 
325 template<> void
327 {
328  GncSqlColumnInfo info{*this, BCT_STRING, GUID_ENCODING_LENGTH, FALSE};
329  vec.emplace_back(std::move(info));
330 }
331 
332 template<> void
334  const gpointer pObject,
335  PairVec& vec) const noexcept
336 {
337  auto s = get_row_value_from_object<GncGUID*>(obj_name, pObject);
338 
339  if (s != nullptr)
340  {
341  gchar *guid_s = guid_to_string(s);
342  vec.emplace_back (std::make_pair (std::string{m_col_name}, quote_string(guid_s)));
343  g_free(guid_s);
344  return;
345  }
346 }
347 /* ----------------------------------------------------------------- */
348 typedef time64 (*Time64AccessFunc) (const gpointer);
349 typedef void (*Time64SetterFunc) (const gpointer, time64);
350 constexpr int TIME_COL_SIZE = 4 + 3 + 3 + 3 + 3 + 3;
351 
352 template<> void
354  GncSqlRow& row,
355  QofIdTypeConst obj_name,
356  gpointer pObject)
357  const noexcept
358 {
359  time64 t{0};
360  g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
361  auto strval = row.get_string_at_col(m_col_name);
362  if (strval)
363  {
364  if (!strval->empty())
365  try
366  {
367  GncDateTime time(*strval);
368  t = static_cast<time64>(time);
369  }
370  catch (const std::invalid_argument& err)
371  {
372  PWARN("An invalid date %s was found in your database."
373  "It has been set to 1 January 1970.",
374  strval->c_str());
375  }
376  }
377  else
378  {
379  if (auto time64val = row.get_time64_at_col (m_col_name))
380  t = *time64val;
381  }
382 
383  if (m_gobj_param_name != nullptr)
384  {
385  Time64 t64{t};
386  set_parameter(pObject, &t64, m_gobj_param_name);
387  }
388  else
389  {
390  set_parameter(pObject, t,
391  reinterpret_cast<Time64SetterFunc>(get_setter(obj_name)),
392  nullptr);
393  }
394 }
395 
396 template<> void
398 {
399 
400  GncSqlColumnInfo info{*this, BCT_DATETIME, TIME_COL_SIZE, FALSE};
401  vec.emplace_back(std::move(info));
402 }
403 
404 template<> void
406  const gpointer pObject,
407  PairVec& vec) const noexcept
408 {
409  /* We still can't use get_row_value_from_object because while g_value could
410  * contentedly store a time64 in an int64, KVP wouldn't be able to tell them
411  * apart, so we have the struct Time64 hack, see engine/gnc-date.c.
412  */
413  time64 t64;
414  if (m_gobj_param_name != nullptr)
415  {
416  Time64* t;
417  g_object_get (pObject, m_gobj_param_name, &t, nullptr);
418  t64 = t->t;
419  }
420  else
421  {
422  auto getter = (Time64AccessFunc)get_getter (obj_name);
423  g_return_if_fail(getter != nullptr);
424  t64 = (*getter)(pObject);
425  }
426  if (t64 > MINTIME && t64 < MAXTIME)
427  {
428  GncDateTime time(t64);
429  std::string timestr("'");
430  timestr += time.format_iso8601() + "'";
431  vec.emplace_back (std::make_pair (std::string{m_col_name}, timestr));
432  }
433  else
434  {
435  vec.emplace_back (std::make_pair (std::string{m_col_name},
436  "NULL"));
437  }
438 }
439 
440 /* ----------------------------------------------------------------- */
441 #define DATE_COL_SIZE 8
442 
443 template<> void
445  GncSqlRow& row,
446  QofIdTypeConst obj_name,
447  gpointer pObject) const noexcept
448 {
449  g_return_if_fail (pObject != NULL);
450  g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
451  if (row.is_col_null(m_col_name))
452  return;
453  GDate date;
454  g_date_clear (&date, 1);
455 
456  auto strval{row.get_string_at_col(m_col_name)};
457  if (strval)
458  {
459  if (strval->empty())
460  return;
461  auto year = static_cast<GDateYear>(stoi (strval->substr (0,4)));
462  auto month = static_cast<GDateMonth>(stoi (strval->substr (4,2)));
463  auto day = static_cast<GDateDay>(stoi (strval->substr (6,2)));
464 
465  if (year != 0 || month != 0 || day != (GDateDay)0)
466  g_date_set_dmy(&date, day, month, year);
467  }
468  else
469  {
470  auto timeval = row.get_time64_at_col(m_col_name);
471  if (!timeval)
472  return;
473  /* time64_to_gdate applies the tz, and gdates are saved
474  * as ymd, so we don't want that.
475  */
476  auto time = *timeval;
477  auto tm = gnc_gmtime(&time);
478  g_date_set_dmy(&date, tm->tm_mday,
479  static_cast<GDateMonth>(tm->tm_mon + 1),
480  tm->tm_year + 1900);
481  free(tm);
482  }
483 
484  set_parameter(pObject, &date, get_setter(obj_name), m_gobj_param_name);
485 }
486 
487 template<> void
489 {
490  GncSqlColumnInfo info{*this, BCT_DATE, DATE_COL_SIZE, FALSE};
491  vec.emplace_back(std::move(info));
492 }
493 
494 template<> void
496  const gpointer pObject,
497  PairVec& vec) const noexcept
498 {
499  GDate *date = get_row_value_from_object<GDate*>(obj_name, pObject);
500 
501  if (date && g_date_valid (date))
502  {
503  std::ostringstream buf;
504  buf << std::setfill ('0') << std::setw (4) << g_date_get_year (date) <<
505  std::setw (2) << g_date_get_month (date) <<
506  std::setw (2) << static_cast<int>(g_date_get_day (date));
507  vec.emplace_back (std::make_pair (std::string{m_col_name},
508  quote_string(buf.str())));
509  return;
510  }
511 }
512 
513 /* ----------------------------------------------------------------- */
514 typedef gnc_numeric (*NumericGetterFunc) (const gpointer);
515 typedef void (*NumericSetterFunc) (gpointer, gnc_numeric);
516 
517 static const EntryVec numeric_col_table =
518 {
519  gnc_sql_make_table_entry<CT_INT64>("num", 0, COL_NNUL, "guid"),
520  gnc_sql_make_table_entry<CT_INT64>("denom", 0, COL_NNUL, "guid")
521 };
522 
523 template <>
524 void set_parameter<gpointer, gnc_numeric>(gpointer object,
525  gnc_numeric item,
526  const char* property)
527 {
528  qof_instance_increase_editlevel(object);
529  g_object_set(object, property, &item, nullptr);
530  qof_instance_decrease_editlevel(object);
531 };
532 
533 template<> void
535  GncSqlRow& row,
536  QofIdTypeConst obj_name,
537  gpointer pObject) const noexcept
538 {
539 
540 
541  g_return_if_fail (pObject != NULL);
542  g_return_if_fail (m_gobj_param_name != nullptr || get_setter(obj_name) != nullptr);
543 
544  auto buf = g_strdup_printf ("%s_num", m_col_name);
545  auto num = row.get_int_at_col (buf);
546  g_free (buf);
547  buf = g_strdup_printf ("%s_denom", m_col_name);
548  auto denom = row.get_int_at_col (buf);
549  g_free (buf);
550 
551  if (num && denom)
552  {
553  auto n = gnc_numeric_create (*num, *denom);
554  set_parameter(pObject, n,
555  reinterpret_cast<NumericSetterFunc>(get_setter(obj_name)),
556  m_gobj_param_name);
557  }
558 }
559 
560 template<> void
562 {
563 
564  for (auto const& subtable_row : numeric_col_table)
565  {
566  gchar* buf = g_strdup_printf("%s_%s", m_col_name,
567  subtable_row->m_col_name);
568  GncSqlColumnInfo info(buf, BCT_INT64, 0, false, false,
569  m_flags & COL_PKEY, m_flags & COL_NNUL);
570  g_free (buf);
571  vec.emplace_back(std::move(info));
572  }
573 }
574 
575 template<> void
577  const gpointer pObject,
578  PairVec& vec) const noexcept
579 {
580 /* We can't use get_row_value_from_object for the same reason as time64. */
581  NumericGetterFunc getter;
582  gnc_numeric n;
583 
584  g_return_if_fail (obj_name != NULL);
585  g_return_if_fail (pObject != NULL);
586 
587  if (m_gobj_param_name != nullptr)
588  {
589  gnc_numeric* s;
590  g_object_get (pObject, m_gobj_param_name, &s, NULL);
591  n = *s;
592  }
593  else
594  {
595  getter = reinterpret_cast<NumericGetterFunc>(get_getter (obj_name));
596  if (getter != NULL)
597  {
598  n = (*getter) (pObject);
599  }
600  else
601  {
602  n = gnc_numeric_zero ();
603  }
604  }
605 
606  std::ostringstream buf;
607  std::string num_col{m_col_name};
608  std::string denom_col{m_col_name};
609  num_col += "_num";
610  denom_col += "_denom";
611  buf << gnc_numeric_num (n);
612  vec.emplace_back (std::make_pair (num_col, buf.str ()));
613  buf.str ("");
614  buf << gnc_numeric_denom (n);
615  vec.emplace_back (denom_col, buf.str ());
616 }
617 
618 static void
619 _retrieve_guid_ (gpointer pObject, gpointer pValue)
620 {
621  GncGUID* pGuid = (GncGUID*)pObject;
622  GncGUID* guid = (GncGUID*)pValue;
623 
624  g_return_if_fail (pObject != NULL);
625  g_return_if_fail (pValue != NULL);
626 
627  *pGuid = *guid;
628 }
629 
630 // Table to retrieve just the guid
631 static EntryVec guid_table
632 {
633  gnc_sql_make_table_entry<CT_GUID>("guid", 0, 0, nullptr, _retrieve_guid_)
634 };
635 
636 const GncGUID*
637 gnc_sql_load_guid (const GncSqlBackend* sql_be, GncSqlRow& row)
638 {
639  static GncGUID guid;
640 
641  g_return_val_if_fail (sql_be != NULL, NULL);
642 
643  gnc_sql_load_object (sql_be, row, NULL, &guid, guid_table);
644 
645  return &guid;
646 }
647 
648 void
649 gnc_sql_load_object (const GncSqlBackend* sql_be, GncSqlRow& row,
650  QofIdTypeConst obj_name, gpointer pObject,
651  const EntryVec& table)
652 {
653  g_return_if_fail (sql_be != NULL);
654  g_return_if_fail (pObject != NULL);
655 
656  for (auto const& table_row : table)
657  {
658  table_row->load (sql_be, row, obj_name, pObject);
659  }
660 }
661 
662 uint_t
663 gnc_sql_append_guids_to_sql (std::stringstream& sql,
664  const InstanceVec& instances)
665 {
666  char guid_buf[GUID_ENCODING_LENGTH + 1];
667 
668  for (auto inst : instances)
669  {
670  (void)guid_to_string_buff (qof_instance_get_guid (inst), guid_buf);
671 
672  if (inst != *(instances.begin()))
673  {
674  sql << ",";
675  }
676  sql << "'" << guid_buf << "'";
677  }
678 
679  return instances.size();
680 }
681 
682 /* This is necessary for 64-bit builds because g++ complains
683  * that reinterpret_casting a void* (64 bits) to an int (32 bits)
684  * loses precision, so we have to explicitly dispose of the precision.
685  * FIXME: We shouldn't be storing ints in ptrs in the first place.
686  */
687 #ifdef __LP64__
688 template <> int
689 GncSqlColumnTableEntry::get_row_value_from_object<int>(QofIdTypeConst obj_name,
690  const void* pObject,
691  std::false_type) const
692 {
693  g_return_val_if_fail(obj_name != nullptr && pObject != nullptr, 0);
694  int result = 0;
695  if (m_gobj_param_name != nullptr)
696  g_object_get(const_cast<void*>(pObject), m_gobj_param_name, &result,
697  nullptr);
698  else
699  {
700  QofAccessFunc getter = get_getter(obj_name);
701  if (getter != nullptr)
702  {
703  auto value = ((getter)(const_cast<void*>(pObject), nullptr));
704  result = reinterpret_cast<uint64_t>(value) &
705  UINT64_C(0x00000000FFFFFFFF);
706  }
707  }
708  return result;
709 }
710 #endif
information required to create a column in a table.
QofSetterFunc get_setter(QofIdTypeConst obj_name) const noexcept
Retrieve the setter function depending on whether it&#39;s an auto-increment field, a QofClass getter...
GnuCash DateTime class.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
const gchar * QofIdTypeConst
QofIdTypeConst declaration.
Definition: qofid.h:82
void add_objectref_guid_to_query(QofIdTypeConst obj_name, const void *pObject, PairVec &vec) const noexcept
Adds a name/guid std::pair to a PairVec for creating a query.
gboolean string_to_guid(const gchar *string, GncGUID *guid)
Given a string, replace the given guid with the parsed one unless the given value is null...
void add_to_query(QofIdTypeConst obj_name, void *pObject, PairVec &vec) const noexcept override
Add a pair of the table column heading and object&#39;s value&#39;s string representation to a PairVec; used ...
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition: guid.cpp:173
QofAccessFunc qof_class_get_parameter_getter(QofIdTypeConst obj_name, const char *parameter)
Return the object&#39;s parameter getter function.
Definition: qofclass.cpp:156
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:185
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void load(const GncSqlBackend *sql_be, GncSqlRow &row, QofIdTypeConst obj_name, void *pObject) const noexcept override
Load a value into an object from the database row.
Row of SQL Query results.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition: guid.h:84
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition: qofclass.h:178
gchar * guid_to_string(const GncGUID *guid)
The guid_to_string() routine returns a null-terminated string encoding of the id. ...
Definition: guid.cpp:164
struct tm * gnc_gmtime(const time64 *secs)
fill out a time struct from a 64-bit time value
Definition: gnc-date.cpp:177
void add_to_table(ColVec &vec) const noexcept override
Add a GncSqlColumnInfo structure for the column type to a ColVec.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
void add_objectref_guid_to_table(ColVec &vec) const noexcept
Adds a column info structure for an object reference GncGUID to a ColVec.
QofSetterFunc qof_class_get_parameter_setter(QofIdTypeConst obj_name, const char *parameter)
Return the object&#39;s parameter setter function.
Definition: qofclass.cpp:172
The type used to store guids in C.
Definition: guid.h:75
Main SQL backend structure.
QofAccessFunc get_getter(QofIdTypeConst obj_name) const noexcept
Retrieve the getter function depending on whether it&#39;s an auto-increment field, a QofClass getter...