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