GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-entry-sql.cpp
1/********************************************************************\
2 * gnc-entry-sql.c -- entry 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 "gncEntryP.h"
38#include "gncOrderP.h"
39#include "gncInvoiceP.h"
40#include "gncTaxTableP.h"
41
42#include "gnc-sql-connection.hpp"
43#include "gnc-sql-backend.hpp"
44#include "gnc-sql-object-backend.hpp"
45#include "gnc-sql-column-table-entry.hpp"
46#include "gnc-slots-sql.h"
47#include "gnc-bill-term-sql.h"
48#include "gnc-entry-sql.h"
49#include "gnc-invoice-sql.h"
50#include "gnc-order-sql.h"
51#include "gnc-tax-table-sql.h"
52
53#define _GNC_MOD_NAME GNC_ID_ENTRY
54
55static QofLogModule log_module = G_LOG_DOMAIN;
56
57#define TABLE_NAME "entries"
58#define TABLE_VERSION 4
59#define MAX_DESCRIPTION_LEN 2048
60#define MAX_ACTION_LEN 2048
61#define MAX_NOTES_LEN 2048
62#define MAX_DISCTYPE_LEN 2048
63#define MAX_DISCHOW_LEN 2048
64
65static void entry_set_invoice (gpointer pObject, gpointer val);
66static void entry_set_bill (gpointer pObject, gpointer val);
67
68static EntryVec col_table
69({
70 gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
71 gnc_sql_make_table_entry<CT_TIME>("date", 0, COL_NNUL, ENTRY_DATE,
72 true),
73 gnc_sql_make_table_entry<CT_TIME>("date_entered", 0, 0,
74 ENTRY_DATE_ENTERED, true),
75 gnc_sql_make_table_entry<CT_STRING>(
76 "description", MAX_DESCRIPTION_LEN, 0, "description"),
77 gnc_sql_make_table_entry<CT_STRING>("action", MAX_ACTION_LEN, 0,
78 ENTRY_ACTION, true),
79 gnc_sql_make_table_entry<CT_STRING>("notes", MAX_NOTES_LEN, 0, ENTRY_NOTES,
80 true),
81 gnc_sql_make_table_entry<CT_NUMERIC>("quantity", 0, 0, ENTRY_QTY,
82 true),
83 gnc_sql_make_table_entry<CT_ACCOUNTREF>("i_acct", 0, 0, ENTRY_IACCT,
84 true),
85 gnc_sql_make_table_entry<CT_NUMERIC>("i_price", 0, 0, ENTRY_IPRICE,
86 true),
87 gnc_sql_make_table_entry<CT_NUMERIC>("i_discount", 0, 0,
88 (QofAccessFunc)gncEntryGetInvDiscount,
89 (QofSetterFunc)gncEntrySetInvDiscount),
90 gnc_sql_make_table_entry<CT_INVOICEREF>("invoice", 0, 0,
91 (QofAccessFunc)gncEntryGetInvoice,
92 (QofSetterFunc)entry_set_invoice),
93 gnc_sql_make_table_entry<CT_STRING>("i_disc_type", MAX_DISCTYPE_LEN, 0,
94 ENTRY_INV_DISC_TYPE, true),
95 gnc_sql_make_table_entry<CT_STRING>("i_disc_how", MAX_DISCHOW_LEN, 0,
96 ENTRY_INV_DISC_HOW, true),
97 gnc_sql_make_table_entry<CT_BOOLEAN>("i_taxable", 0, 0, ENTRY_INV_TAXABLE,
98 true),
99 gnc_sql_make_table_entry<CT_BOOLEAN>("i_taxincluded", 0, 0,
100 ENTRY_INV_TAX_INC, true),
101 gnc_sql_make_table_entry<CT_TAXTABLEREF>("i_taxtable", 0, 0,
102 (QofAccessFunc)gncEntryGetInvTaxTable,
103 (QofSetterFunc)gncEntrySetInvTaxTable),
104 gnc_sql_make_table_entry<CT_ACCOUNTREF>("b_acct", 0, 0, ENTRY_BACCT,
105 true),
106 gnc_sql_make_table_entry<CT_NUMERIC>("b_price", 0, 0, ENTRY_BPRICE,
107 true),
108 gnc_sql_make_table_entry<CT_INVOICEREF>("bill", 0, 0,
109 (QofAccessFunc)gncEntryGetBill,
110 (QofSetterFunc)entry_set_bill),
111 gnc_sql_make_table_entry<CT_BOOLEAN>("b_taxable", 0, 0, ENTRY_BILL_TAXABLE,
112 true),
113 gnc_sql_make_table_entry<CT_BOOLEAN>("b_taxincluded", 0, 0,
114 ENTRY_BILL_TAX_INC, true),
115 gnc_sql_make_table_entry<CT_TAXTABLEREF>("b_taxtable", 0, 0,
116 (QofAccessFunc)gncEntryGetBillTaxTable,
117 (QofSetterFunc)gncEntrySetBillTaxTable),
118 gnc_sql_make_table_entry<CT_INT>("b_paytype", 0, 0,
119 (QofAccessFunc)gncEntryGetBillPayment,
120 (QofSetterFunc)gncEntrySetBillPayment),
121 gnc_sql_make_table_entry<CT_BOOLEAN>("billable", 0, 0, ENTRY_BILLABLE,
122 true),
123 gnc_sql_make_table_entry<CT_OWNERREF>("billto", 0, 0, ENTRY_BILLTO, true),
124 gnc_sql_make_table_entry<CT_ORDERREF>("order_guid", 0, 0,
125 (QofAccessFunc)gncEntryGetOrder,
126 (QofSetterFunc)gncEntrySetOrder),
127});
128
129GncSqlEntryBackend::GncSqlEntryBackend() :
130 GncSqlObjectBackend(TABLE_VERSION, GNC_ID_ENTRY,
131 TABLE_NAME, col_table) {}
132
133static void
134entry_set_invoice (gpointer pObject, gpointer val)
135{
136 GncEntry* entry;
137 GncInvoice* invoice;
138
139 g_return_if_fail (pObject != NULL);
140 g_return_if_fail (GNC_IS_ENTRY (pObject));
141 g_return_if_fail (val != NULL);
142 g_return_if_fail (GNC_IS_INVOICE (val));
143
144 entry = GNC_ENTRY (pObject);
145 invoice = GNC_INVOICE (val);
146
147 gncInvoiceAddEntry (invoice, entry);
148}
149
150static void
151entry_set_bill (gpointer pObject, gpointer val)
152{
153 GncEntry* entry;
154 GncInvoice* bill;
155
156 g_return_if_fail (pObject != NULL);
157 g_return_if_fail (GNC_IS_ENTRY (pObject));
158 g_return_if_fail (val != NULL);
159 g_return_if_fail (GNC_IS_INVOICE (val));
160
161 entry = GNC_ENTRY (pObject);
162 bill = GNC_INVOICE (val);
163
164 gncBillAddEntry (bill, entry);
165}
166
167static GncEntry*
168load_single_entry (GncSqlBackend* sql_be, GncSqlRow& row)
169{
170 const GncGUID* guid;
171 GncEntry* pEntry;
172
173 g_return_val_if_fail (sql_be != NULL, NULL);
174
175 guid = gnc_sql_load_guid (sql_be, row);
176 pEntry = gncEntryLookup (sql_be->book(), guid);
177 if (pEntry == NULL)
178 {
179 pEntry = gncEntryCreate (sql_be->book());
180 }
181 gnc_sql_load_object (sql_be, row, GNC_ID_ENTRY, pEntry, col_table);
182 qof_instance_mark_clean (QOF_INSTANCE (pEntry));
183
184 return pEntry;
185}
186
187/* Because gncEntryLookup has the arguments backwards: */
188static inline GncEntry*
189gnc_entry_lookup (const GncGUID *guid, const QofBook *book)
190{
191 QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_ENTRY, GncEntry);
192}
193
194void
196{
197 g_return_if_fail (sql_be != NULL);
198
199 std::string sql("SELECT * FROM " TABLE_NAME);
200 auto stmt = sql_be->create_statement_from_sql(sql);
201 auto result = sql_be->execute_select_statement(stmt);
202
203 for (auto row : *result)
204 load_single_entry (sql_be, row);
205
206 std::string pkey(col_table[0]->name());
207 sql = "SELECT DISTINCT ";
208 sql += pkey + " FROM " TABLE_NAME;
209 gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
210 (BookLookupFn)gnc_entry_lookup);
211}
212
213/* ================================================================= */
214void
216{
217 gint version;
218
219 g_return_if_fail (sql_be != NULL);
220
221 version = sql_be->get_table_version( TABLE_NAME);
222 if (version == 0)
223 {
224 sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
225 }
226 else if (version < TABLE_VERSION)
227 {
228 /* Upgrade:
229 1->2: 64 bit int handling
230 2->3: "entered" -> "date_entered", and it can be NULL
231 3->4: Use DATETIME instead of TIMESTAMP in MySQL
232 */
233 sql_be->upgrade_table(TABLE_NAME, col_table);
234 sql_be->set_table_version (TABLE_NAME, TABLE_VERSION);
235
236 PINFO ("Entries table upgraded from version %d to version %d\n", version,
237 TABLE_VERSION);
238 }
239}
240
241/* ================================================================= */
242static void
243write_single_entry (QofInstance* term_p, gpointer data_p)
244{
245 write_objects_t* s = (write_objects_t*)data_p;
246 GncEntry* entry = GNC_ENTRY (term_p);
247
248 g_return_if_fail (term_p != NULL);
249 g_return_if_fail (GNC_IS_ENTRY (term_p));
250 g_return_if_fail (data_p != NULL);
251
252 /* Only save if attached */
253 if (s->is_ok && (gncEntryGetOrder (entry) != NULL ||
254 gncEntryGetInvoice (entry) != NULL ||
255 gncEntryGetBill (entry) != NULL))
256 {
257 s->commit (term_p);
258 }
259}
260
261bool
263{
264 g_return_val_if_fail (sql_be != NULL, FALSE);
265 write_objects_t data{sql_be, true, this};
266
267 qof_object_foreach (GNC_ID_ENTRY, sql_be->book(), write_single_entry, &data);
268
269 return data.is_ok;
270}
271
272
273/* ========================== END OF FILE ===================== */
Main SQL backend structure.
uint_t get_table_version(const std::string &table_name) const noexcept
Returns the version number for a DB table.
bool create_table(const std::string &table_name, const EntryVec &col_table) const noexcept
Creates a table in the database.
GncSqlResultPtr execute_select_statement(const GncSqlStatementPtr &stmt) const noexcept
Executes an SQL SELECT statement and returns the result rows.
void upgrade_table(const std::string &table_name, const EntryVec &col_table) noexcept
Upgrades a table to a new structure.
bool set_table_version(const std::string &table_name, uint_t version) noexcept
Registers the version for a table.
void create_tables(GncSqlBackend *) override
Conditionally create or update a database table from m_col_table.
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.
Encapsulates per-class table schema with functions to load, create a table, commit a changed front-en...
Row of SQL Query results.
load and save accounts data to SQL
load and save entry data to SQL
load and save invoice data to SQL
load and save order data to SQL
load and save accounts data to SQL
load and save tax table 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:101
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition qofclass.h:123
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition qofclass.h:130
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
Call this function when adding an entry to a bill instead of an invoice.
Definition gncInvoice.c:719
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke the callback 'cb' on every instance ov a particular object type.
The type used to store guids in C.
Definition guid.h:75
QofBook reference.
Definition qofbook-p.hpp:47
Data-passing struct for callbacks to qof_object_foreach() used in GncSqlObjectBackend::write().