GnuCash  5.6-150-g038405b370+
gnc-customer-sql.cpp
1 /********************************************************************\
2  * gnc-customer-sql.c -- customer sql backend *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU General Public License as *
6  * published by the Free Software Foundation; either version 2 of *
7  * the License, or (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact: *
16  * *
17  * Free Software Foundation Voice: +1-617-542-5942 *
18  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19  * Boston, MA 02110-1301, USA gnu@gnu.org *
20  * *
21 \********************************************************************/
22 
30 #include <glib.h>
31 
32 #include <config.h>
33 
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "gncBillTermP.h"
38 #include "gncCustomerP.h"
39 #include "gncTaxTableP.h"
40 
41 #include "gnc-sql-connection.hpp"
42 #include "gnc-sql-backend.hpp"
43 #include "gnc-sql-object-backend.hpp"
44 #include "gnc-sql-column-table-entry.hpp"
45 #include "gnc-slots-sql.h"
46 #include "gnc-customer-sql.h"
47 #include "gnc-bill-term-sql.h"
48 #include "gnc-tax-table-sql.h"
49 
50 #define _GNC_MOD_NAME GNC_ID_CUSTOMER
51 
52 static QofLogModule log_module = G_LOG_DOMAIN;
53 
54 #define TABLE_NAME "customers"
55 #define TABLE_VERSION 2
56 
57 #define MAX_NAME_LEN 2048
58 #define MAX_ID_LEN 2048
59 #define MAX_NOTES_LEN 2048
60 
61 static EntryVec col_table
62 ({
63  gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid" ),
64  gnc_sql_make_table_entry<CT_STRING>("name", MAX_NAME_LEN, COL_NNUL, "name"),
65  gnc_sql_make_table_entry<CT_STRING>("id", MAX_ID_LEN, COL_NNUL,
66  CUSTOMER_ID, true),
67  gnc_sql_make_table_entry<CT_STRING>("notes", MAX_NOTES_LEN, COL_NNUL,
68  CUSTOMER_NOTES, true),
69  gnc_sql_make_table_entry<CT_BOOLEAN>("active", 0, COL_NNUL,
70  QOF_PARAM_ACTIVE, true),
71  gnc_sql_make_table_entry<CT_NUMERIC>("discount", 0, COL_NNUL,
72  CUSTOMER_DISCOUNT, true),
73  gnc_sql_make_table_entry<CT_NUMERIC>("credit", 0, COL_NNUL,
74  CUSTOMER_CREDIT, true),
75  gnc_sql_make_table_entry<CT_COMMODITYREF>("currency", 0, COL_NNUL,
76  (QofAccessFunc)gncCustomerGetCurrency,
77  (QofSetterFunc)gncCustomerSetCurrency),
78  gnc_sql_make_table_entry<CT_BOOLEAN>("tax_override", 0, COL_NNUL,
79  CUSTOMER_TT_OVER, true),
80  gnc_sql_make_table_entry<CT_ADDRESS>("addr", 0, 0, CUSTOMER_ADDR,
81  true),
82  gnc_sql_make_table_entry<CT_ADDRESS>("shipaddr", 0, 0, CUSTOMER_SHIPADDR,
83  true),
84  gnc_sql_make_table_entry<CT_BILLTERMREF>("terms", 0, 0, CUSTOMER_TERMS,
85  true),
86  gnc_sql_make_table_entry<CT_INT>("tax_included", 0, 0,
87  (QofAccessFunc)gncCustomerGetTaxIncluded,
88  (QofSetterFunc)gncCustomerSetTaxIncluded),
89  gnc_sql_make_table_entry<CT_TAXTABLEREF>("taxtable", 0, 0,
90  (QofAccessFunc)gncCustomerGetTaxTable,
91  (QofSetterFunc)gncCustomerSetTaxTable),
92 });
93 
94 GncSqlCustomerBackend::GncSqlCustomerBackend() :
95  GncSqlObjectBackend(TABLE_VERSION, GNC_ID_CUSTOMER,
96  TABLE_NAME, col_table) {}
97 
98 static GncCustomer*
99 load_single_customer (GncSqlBackend* sql_be, GncSqlRow& row)
100 {
101  const GncGUID* guid;
102  GncCustomer* pCustomer;
103 
104  g_return_val_if_fail (sql_be != NULL, NULL);
105 
106  guid = gnc_sql_load_guid (sql_be, row);
107  pCustomer = gncCustomerLookup (sql_be->book(), guid);
108  if (pCustomer == NULL)
109  {
110  pCustomer = gncCustomerCreate (sql_be->book());
111  }
112  gnc_sql_load_object (sql_be, row, GNC_ID_CUSTOMER, pCustomer, col_table);
113  qof_instance_mark_clean (QOF_INSTANCE (pCustomer));
114 
115  return pCustomer;
116 }
117 
118 /* Because gncCustomerLookup has the arguments backwards: */
119 static inline GncCustomer*
120 gnc_customer_lookup (const GncGUID *guid, const QofBook *book)
121 {
122  QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_CUSTOMER, GncCustomer);
123 }
124 
125 void
127 {
128  g_return_if_fail (sql_be != NULL);
129 
130  std::string sql("SELECT * FROM " TABLE_NAME);
131  auto stmt = sql_be->create_statement_from_sql(sql);
132  auto result = sql_be->execute_select_statement(stmt);
133 
134  for (auto row : *result)
135  load_single_customer (sql_be, row);
136 
137  std::string pkey(col_table[0]->name());
138  sql = "SELECT DISTINCT ";
139  sql += pkey + " FROM " TABLE_NAME;
141  (BookLookupFn)gnc_customer_lookup);
142 }
143 
144 /* ================================================================= */
145 void
147 {
148  gint version;
149 
150  g_return_if_fail (sql_be != NULL);
151 
152  version = sql_be->get_table_version( TABLE_NAME);
153  if (version == 0)
154  {
155  sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
156  }
157  else if (version < m_version)
158  {
159  /* Upgrade 64 bit int handling */
160  sql_be->upgrade_table(TABLE_NAME, col_table);
161  sql_be->set_table_version (TABLE_NAME, TABLE_VERSION);
162 
163  PINFO ("Customers table upgraded from version 1 to version %d\n",
164  TABLE_VERSION);
165  }
166 }
167 
168 /* ================================================================= */
169 static gboolean
170 customer_should_be_saved (GncCustomer* customer)
171 {
172  const char* id;
173 
174  g_return_val_if_fail (customer != NULL, FALSE);
175 
176  /* Make sure this is a valid customer before we save it -- should have an ID */
177  id = gncCustomerGetID (customer);
178  if (id == NULL || *id == '\0')
179  {
180  return FALSE;
181  }
182 
183  return TRUE;
184 }
185 
186 static void
187 write_single_customer (QofInstance* term_p, gpointer data_p)
188 {
189  auto data = reinterpret_cast<write_objects_t*>(data_p);
190 
191  g_return_if_fail (term_p != NULL);
192  g_return_if_fail (GNC_IS_CUSTOMER (term_p));
193  g_return_if_fail (data_p != NULL);
194 
195  if (customer_should_be_saved (GNC_CUSTOMER (term_p)))
196  {
197  data->commit (term_p);
198  }
199 }
200 
201 bool
203 {
204  write_objects_t data;
205 
206  g_return_val_if_fail (sql_be != NULL, FALSE);
207 
208  data.be = sql_be;
209  data.is_ok = TRUE;
210  data.obe = this;
211  qof_object_foreach (GNC_ID_CUSTOMER, sql_be->book(), write_single_customer,
212  (gpointer)&data);
213  return data.is_ok;
214 }
215 
216 /* ========================== END OF FILE ===================== */
bool create_table(const std::string &table_name, const EntryVec &col_table) const noexcept
Creates a table in the database.
bool set_table_version(const std::string &table_name, uint_t version) noexcept
Registers the version for a table.
GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr &stmt) const noexcept
Executes an SQL SELECT statement and returns the result rows.
void gnc_sql_slots_load_for_sql_subquery(GncSqlBackend *sql_be, const std::string subquery, BookLookupFn lookup_fn)
gnc_sql_slots_load_for_sql_subquery - Loads slots for all objects whose guid is supplied by a subquer...
void create_tables(GncSqlBackend *) override
Conditionally create or update a database table from m_col_table.
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
load and save accounts data to SQL
load and save customer data to SQL
#define QOF_BOOK_RETURN_ENTITY(book, guid, e_type, c_type)
Encapsulates all the information about a dataset manipulated by QOF.
Definition: qofbook.h:186
load and save accounts data to SQL
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:185
Row of SQL Query results.
void upgrade_table(const std::string &table_name, const EntryVec &col_table) noexcept
Upgrades a table to a new structure.
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke the callback &#39;cb&#39; on every instance ov a particular object type.
Definition: qofobject.cpp:185
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition: qofclass.h:178
Encapsulates per-class table schema with functions to load, create a table, commit a changed front-en...
credit, discount and shipaddr are unique to GncCustomer id, name, notes, terms, addr, currency, taxtable, taxtable_override taxincluded, active and jobs are identical to ::GncVendor.
Data-passing struct for callbacks to qof_object_foreach() used in GncSqlObjectBackend::write().
void load_all(GncSqlBackend *) override
Load all objects of m_type in the database into memory.
bool write(GncSqlBackend *) override
Write all objects of m_type_name to the database.
The type used to store guids in C.
Definition: guid.h:75
uint_t get_table_version(const std::string &table_name) const noexcept
Returns the version number for a DB table.
Main SQL backend structure.
load and save tax table data to SQL