Branch data 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 : 10 : GncSqlEntryBackend::GncSqlEntryBackend() :
130 : : GncSqlObjectBackend(TABLE_VERSION, GNC_ID_ENTRY,
131 : 10 : 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 : 5 : GncSqlEntryBackend::load_all (GncSqlBackend* sql_be)
196 : : {
197 : 5 : g_return_if_fail (sql_be != NULL);
198 : :
199 : 5 : std::string sql("SELECT * FROM " TABLE_NAME);
200 : 5 : auto stmt = sql_be->create_statement_from_sql(sql);
201 : 5 : auto result = sql_be->execute_select_statement(stmt);
202 : :
203 : 6 : for (auto row : *result)
204 : 6 : load_single_entry (sql_be, row);
205 : :
206 : 5 : std::string pkey(col_table[0]->name());
207 : 5 : sql = "SELECT DISTINCT ";
208 : 5 : sql += pkey + " FROM " TABLE_NAME;
209 : 5 : gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
210 : : (BookLookupFn)gnc_entry_lookup);
211 : 5 : }
212 : :
213 : : /* ================================================================= */
214 : : void
215 : 10 : GncSqlEntryBackend::create_tables (GncSqlBackend* sql_be)
216 : : {
217 : : gint version;
218 : :
219 : 10 : g_return_if_fail (sql_be != NULL);
220 : :
221 : 10 : version = sql_be->get_table_version( TABLE_NAME);
222 : 10 : if (version == 0)
223 : : {
224 : 5 : sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
225 : : }
226 : 5 : 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 : 5 : GncSqlEntryBackend::write (GncSqlBackend* sql_be)
263 : : {
264 : 5 : g_return_val_if_fail (sql_be != NULL, FALSE);
265 : 5 : write_objects_t data{sql_be, true, this};
266 : :
267 : 5 : qof_object_foreach (GNC_ID_ENTRY, sql_be->book(), write_single_entry, &data);
268 : :
269 : 5 : return data.is_ok;
270 : : }
271 : :
272 : :
273 : : /* ========================== END OF FILE ===================== */
|