Line data Source code
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 :
23 : /** @file gnc-entry-sql.c
24 : * @brief load and save address data to SQL
25 : * @author Copyright (c) 2007-2008 Phil Longstaff <plongstaff@rogers.com>
26 : *
27 : * This file implements the top-level QofBackend API for saving/
28 : * restoring data to/from an SQL database
29 : */
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 :
55 : static 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 :
65 : static void entry_set_invoice (gpointer pObject, gpointer val);
66 : static void entry_set_bill (gpointer pObject, gpointer val);
67 :
68 : static 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 :
129 15 : GncSqlEntryBackend::GncSqlEntryBackend() :
130 30 : GncSqlObjectBackend(TABLE_VERSION, GNC_ID_ENTRY,
131 75 : TABLE_NAME, col_table) {}
132 :
133 : static void
134 0 : entry_set_invoice (gpointer pObject, gpointer val)
135 : {
136 : GncEntry* entry;
137 : GncInvoice* invoice;
138 :
139 0 : g_return_if_fail (pObject != NULL);
140 0 : g_return_if_fail (GNC_IS_ENTRY (pObject));
141 0 : g_return_if_fail (val != NULL);
142 0 : g_return_if_fail (GNC_IS_INVOICE (val));
143 :
144 0 : entry = GNC_ENTRY (pObject);
145 0 : invoice = GNC_INVOICE (val);
146 :
147 0 : gncInvoiceAddEntry (invoice, entry);
148 : }
149 :
150 : static void
151 1 : entry_set_bill (gpointer pObject, gpointer val)
152 : {
153 : GncEntry* entry;
154 : GncInvoice* bill;
155 :
156 1 : g_return_if_fail (pObject != NULL);
157 1 : g_return_if_fail (GNC_IS_ENTRY (pObject));
158 1 : g_return_if_fail (val != NULL);
159 1 : g_return_if_fail (GNC_IS_INVOICE (val));
160 :
161 1 : entry = GNC_ENTRY (pObject);
162 1 : bill = GNC_INVOICE (val);
163 :
164 1 : gncBillAddEntry (bill, entry);
165 : }
166 :
167 : static GncEntry*
168 1 : load_single_entry (GncSqlBackend* sql_be, GncSqlRow& row)
169 : {
170 : const GncGUID* guid;
171 : GncEntry* pEntry;
172 :
173 1 : g_return_val_if_fail (sql_be != NULL, NULL);
174 :
175 1 : guid = gnc_sql_load_guid (sql_be, row);
176 1 : pEntry = gncEntryLookup (sql_be->book(), guid);
177 1 : if (pEntry == NULL)
178 : {
179 1 : pEntry = gncEntryCreate (sql_be->book());
180 : }
181 1 : gnc_sql_load_object (sql_be, row, GNC_ID_ENTRY, pEntry, col_table);
182 1 : qof_instance_mark_clean (QOF_INSTANCE (pEntry));
183 :
184 1 : return pEntry;
185 : }
186 :
187 : /* Because gncEntryLookup has the arguments backwards: */
188 : static inline GncEntry*
189 0 : gnc_entry_lookup (const GncGUID *guid, const QofBook *book)
190 : {
191 0 : QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_ENTRY, GncEntry);
192 : }
193 :
194 : void
195 7 : GncSqlEntryBackend::load_all (GncSqlBackend* sql_be)
196 : {
197 7 : g_return_if_fail (sql_be != NULL);
198 :
199 7 : std::string sql("SELECT * FROM " TABLE_NAME);
200 7 : auto stmt = sql_be->create_statement_from_sql(sql);
201 7 : auto result = sql_be->execute_select_statement(stmt);
202 :
203 8 : for (auto row : *result)
204 8 : load_single_entry (sql_be, row);
205 :
206 7 : std::string pkey(col_table[0]->name());
207 7 : sql = "SELECT DISTINCT ";
208 7 : sql += pkey + " FROM " TABLE_NAME;
209 7 : gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
210 : (BookLookupFn)gnc_entry_lookup);
211 7 : }
212 :
213 : /* ================================================================= */
214 : void
215 13 : GncSqlEntryBackend::create_tables (GncSqlBackend* sql_be)
216 : {
217 : gint version;
218 :
219 13 : g_return_if_fail (sql_be != NULL);
220 :
221 26 : version = sql_be->get_table_version( TABLE_NAME);
222 13 : if (version == 0)
223 : {
224 18 : sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
225 : }
226 7 : 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 0 : sql_be->upgrade_table(TABLE_NAME, col_table);
234 0 : sql_be->set_table_version (TABLE_NAME, TABLE_VERSION);
235 :
236 0 : PINFO ("Entries table upgraded from version %d to version %d\n", version,
237 : TABLE_VERSION);
238 : }
239 : }
240 :
241 : /* ================================================================= */
242 : static void
243 1 : write_single_entry (QofInstance* term_p, gpointer data_p)
244 : {
245 1 : write_objects_t* s = (write_objects_t*)data_p;
246 1 : GncEntry* entry = GNC_ENTRY (term_p);
247 :
248 1 : g_return_if_fail (term_p != NULL);
249 1 : g_return_if_fail (GNC_IS_ENTRY (term_p));
250 1 : g_return_if_fail (data_p != NULL);
251 :
252 : /* Only save if attached */
253 2 : if (s->is_ok && (gncEntryGetOrder (entry) != NULL ||
254 1 : gncEntryGetInvoice (entry) != NULL ||
255 1 : gncEntryGetBill (entry) != NULL))
256 : {
257 1 : s->commit (term_p);
258 : }
259 : }
260 :
261 : bool
262 6 : GncSqlEntryBackend::write (GncSqlBackend* sql_be)
263 : {
264 6 : g_return_val_if_fail (sql_be != NULL, FALSE);
265 6 : write_objects_t data{sql_be, true, this};
266 :
267 6 : qof_object_foreach (GNC_ID_ENTRY, sql_be->book(), write_single_entry, &data);
268 :
269 6 : return data.is_ok;
270 : }
271 :
272 :
273 : /* ========================== END OF FILE ===================== */
|