Line data Source code
1 : /********************************************************************
2 : * gnc-price-sql.c: load and save data to SQL *
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 : /** @file gnc-price-sql.c
22 : * @brief load and save data to SQL
23 : * @author Copyright (c) 2006-2009 Phil Longstaff <plongstaff@rogers.com>
24 : *
25 : * This file implements the top-level QofBackend API for saving/
26 : * restoring data to/from an SQL db
27 : */
28 : #include <glib.h>
29 :
30 : #include <config.h>
31 :
32 : #include "qof.h"
33 : #include "gnc-pricedb.h"
34 :
35 : #if defined( S_SPLINT_S )
36 : #include "splint-defs.h"
37 : #endif
38 :
39 : #include "gnc-sql-connection.hpp"
40 : #include "gnc-sql-backend.hpp"
41 : #include "gnc-sql-object-backend.hpp"
42 : #include "gnc-sql-column-table-entry.hpp"
43 : #include "gnc-commodity-sql.h"
44 : #include "gnc-price-sql.h"
45 : #include "gnc-slots-sql.h"
46 :
47 :
48 : static QofLogModule log_module = G_LOG_DOMAIN;
49 :
50 : #define TABLE_NAME "prices"
51 : #define TABLE_VERSION 3
52 :
53 : #define PRICE_MAX_SOURCE_LEN 2048
54 : #define PRICE_MAX_TYPE_LEN 2048
55 :
56 : static const EntryVec col_table
57 : ({
58 : gnc_sql_make_table_entry<CT_GUID>("guid", 0, COL_NNUL | COL_PKEY, "guid"),
59 : gnc_sql_make_table_entry<CT_COMMODITYREF>("commodity_guid", 0, COL_NNUL,
60 : "commodity"),
61 : gnc_sql_make_table_entry<CT_COMMODITYREF>("currency_guid", 0, COL_NNUL,
62 : "currency"),
63 : gnc_sql_make_table_entry<CT_TIME>("date", 0, COL_NNUL, "date"),
64 : gnc_sql_make_table_entry<CT_STRING>("source", PRICE_MAX_SOURCE_LEN, 0,
65 : "source"),
66 : gnc_sql_make_table_entry<CT_STRING>("type", PRICE_MAX_TYPE_LEN, 0, "type"),
67 : gnc_sql_make_table_entry<CT_NUMERIC>("value", 0, COL_NNUL, "value")
68 : });
69 :
70 15 : GncSqlPriceBackend::GncSqlPriceBackend() :
71 30 : GncSqlObjectBackend(TABLE_VERSION, GNC_ID_PRICE,
72 75 : TABLE_NAME, col_table) {}
73 :
74 : /* ================================================================= */
75 :
76 : static GNCPrice*
77 0 : load_single_price (GncSqlBackend* sql_be, GncSqlRow& row)
78 : {
79 : GNCPrice* pPrice;
80 :
81 0 : g_return_val_if_fail (sql_be != NULL, NULL);
82 :
83 0 : pPrice = gnc_price_create (sql_be->book());
84 :
85 0 : gnc_price_begin_edit (pPrice);
86 0 : gnc_sql_load_object (sql_be, row, GNC_ID_PRICE, pPrice, col_table);
87 0 : gnc_price_commit_edit (pPrice);
88 :
89 0 : return pPrice;
90 : }
91 :
92 : void
93 7 : GncSqlPriceBackend::load_all (GncSqlBackend* sql_be)
94 : {
95 : QofBook* pBook;
96 : GNCPriceDB* pPriceDB;
97 :
98 14 : g_return_if_fail (sql_be != NULL);
99 :
100 7 : pBook = sql_be->book();
101 7 : pPriceDB = gnc_pricedb_get_db (pBook);
102 7 : std::string sql("SELECT * FROM " TABLE_NAME);
103 7 : auto stmt = sql_be->create_statement_from_sql(sql);
104 7 : if (stmt != nullptr)
105 : {
106 7 : auto result = sql_be->execute_select_statement(stmt);
107 7 : if (result->begin() == result->end())
108 7 : return;
109 :
110 : GNCPrice* pPrice;
111 :
112 0 : gnc_pricedb_set_bulk_update (pPriceDB, TRUE);
113 0 : for (auto row : *result)
114 : {
115 0 : pPrice = load_single_price (sql_be, row);
116 :
117 0 : if (pPrice != NULL)
118 : {
119 0 : (void)gnc_pricedb_add_price (pPriceDB, pPrice);
120 0 : gnc_price_unref (pPrice);
121 : }
122 0 : }
123 0 : gnc_pricedb_set_bulk_update (pPriceDB, FALSE);
124 0 : std::string pkey(col_table[0]->name());
125 0 : sql = "SELECT DISTINCT ";
126 0 : sql += pkey + " FROM " TABLE_NAME;
127 0 : gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
128 : (BookLookupFn)gnc_price_lookup);
129 0 : }
130 14 : }
131 :
132 : /* ================================================================= */
133 : void
134 13 : GncSqlPriceBackend::create_tables (GncSqlBackend* sql_be)
135 : {
136 : gint version;
137 :
138 13 : g_return_if_fail (sql_be != NULL);
139 :
140 26 : version = sql_be->get_table_version( TABLE_NAME);
141 13 : if (version == 0)
142 : {
143 18 : (void)sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
144 : }
145 7 : else if (version < m_version)
146 : {
147 : /*
148 : 1->2: Upgrade 64 bit int handling
149 : 2->3: Use DATETIME instead of TIMESTAMP in MySQL
150 : */
151 0 : sql_be->upgrade_table(TABLE_NAME, col_table);
152 0 : sql_be->set_table_version (TABLE_NAME, TABLE_VERSION);
153 :
154 0 : PINFO ("Prices table upgraded from version 1 to version %d\n", TABLE_VERSION);
155 : }
156 : }
157 :
158 : /* ================================================================= */
159 :
160 : bool
161 0 : GncSqlPriceBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
162 : {
163 0 : GNCPrice* pPrice = GNC_PRICE (inst);
164 : E_DB_OPERATION op;
165 : gboolean is_infant;
166 0 : gboolean is_ok = TRUE;
167 :
168 0 : g_return_val_if_fail (sql_be != NULL, FALSE);
169 0 : g_return_val_if_fail (inst != NULL, FALSE);
170 0 : g_return_val_if_fail (GNC_IS_PRICE (inst), FALSE);
171 :
172 0 : is_infant = qof_instance_get_infant (inst);
173 0 : if (qof_instance_get_destroying (inst))
174 : {
175 0 : op = OP_DB_DELETE;
176 : }
177 0 : else if (sql_be->pristine() || is_infant)
178 : {
179 0 : op = OP_DB_INSERT;
180 : }
181 : else
182 : {
183 0 : op = OP_DB_UPDATE;
184 : }
185 :
186 0 : if (op != OP_DB_DELETE)
187 : {
188 : /* Ensure commodity and currency are in the db */
189 0 : (void)sql_be->save_commodity(gnc_price_get_commodity(pPrice));
190 0 : is_ok = sql_be->save_commodity(gnc_price_get_currency(pPrice));
191 : }
192 :
193 0 : if (is_ok)
194 : {
195 0 : is_ok = sql_be->do_db_operation(op, TABLE_NAME, GNC_ID_PRICE, pPrice,
196 : col_table);
197 : }
198 :
199 0 : return is_ok;
200 : }
201 :
202 : static gboolean
203 0 : write_price (GNCPrice* p, gpointer data)
204 : {
205 0 : auto s = reinterpret_cast<write_objects_t*>(data);
206 :
207 0 : g_return_val_if_fail (p != NULL, FALSE);
208 0 : g_return_val_if_fail (data != NULL, FALSE);
209 :
210 0 : if (s->is_ok && gnc_price_get_source (p) != PRICE_SOURCE_TEMP)
211 : {
212 0 : s->commit (QOF_INSTANCE(p));
213 : }
214 :
215 0 : return s->is_ok;
216 : }
217 :
218 : bool
219 6 : GncSqlPriceBackend::write (GncSqlBackend* sql_be)
220 : {
221 6 : g_return_val_if_fail (sql_be != NULL, FALSE);
222 6 : write_objects_t data{sql_be, true, this};
223 :
224 6 : auto priceDB = gnc_pricedb_get_db (sql_be->book());
225 6 : return gnc_pricedb_foreach_price (priceDB, write_price, &data, TRUE);
226 : }
227 :
228 : /* ========================== END OF FILE ===================== */
|