Branch data 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 : 10 : GncSqlPriceBackend::GncSqlPriceBackend() :
71 : : GncSqlObjectBackend(TABLE_VERSION, GNC_ID_PRICE,
72 : 10 : 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 : 5 : GncSqlPriceBackend::load_all (GncSqlBackend* sql_be)
94 : : {
95 : : QofBook* pBook;
96 : : GNCPriceDB* pPriceDB;
97 : :
98 : 10 : g_return_if_fail (sql_be != NULL);
99 : :
100 : 5 : pBook = sql_be->book();
101 : 5 : pPriceDB = gnc_pricedb_get_db (pBook);
102 : 5 : std::string sql("SELECT * FROM " TABLE_NAME);
103 : 5 : auto stmt = sql_be->create_statement_from_sql(sql);
104 : 5 : if (stmt != nullptr)
105 : : {
106 : 5 : auto result = sql_be->execute_select_statement(stmt);
107 : 5 : if (result->begin() == result->end())
108 : 5 : 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 : 10 : }
131 : :
132 : : /* ================================================================= */
133 : : void
134 : 10 : GncSqlPriceBackend::create_tables (GncSqlBackend* sql_be)
135 : : {
136 : : gint version;
137 : :
138 : 10 : g_return_if_fail (sql_be != NULL);
139 : :
140 : 10 : version = sql_be->get_table_version( TABLE_NAME);
141 : 10 : if (version == 0)
142 : : {
143 : 5 : (void)sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
144 : : }
145 : 5 : 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 : 5 : GncSqlPriceBackend::write (GncSqlBackend* sql_be)
220 : : {
221 : 5 : g_return_val_if_fail (sql_be != NULL, FALSE);
222 : 5 : write_objects_t data{sql_be, true, this};
223 : :
224 : 5 : auto priceDB = gnc_pricedb_get_db (sql_be->book());
225 : 5 : return gnc_pricedb_foreach_price (priceDB, write_price, &data, TRUE);
226 : : }
227 : :
228 : : /* ========================== END OF FILE ===================== */
|