GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-price-sql.cpp
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\********************************************************************/
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
48static 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
56static 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
70GncSqlPriceBackend::GncSqlPriceBackend() :
71 GncSqlObjectBackend(TABLE_VERSION, GNC_ID_PRICE,
72 TABLE_NAME, col_table) {}
73
74/* ================================================================= */
75
76static GNCPrice*
77load_single_price (GncSqlBackend* sql_be, GncSqlRow& row)
78{
79 GNCPrice* pPrice;
80
81 g_return_val_if_fail (sql_be != NULL, NULL);
82
83 pPrice = gnc_price_create (sql_be->book());
84
85 gnc_price_begin_edit (pPrice);
86 gnc_sql_load_object (sql_be, row, GNC_ID_PRICE, pPrice, col_table);
87 gnc_price_commit_edit (pPrice);
88
89 return pPrice;
90}
91
92void
94{
95 QofBook* pBook;
96 GNCPriceDB* pPriceDB;
97
98 g_return_if_fail (sql_be != NULL);
99
100 pBook = sql_be->book();
101 pPriceDB = gnc_pricedb_get_db (pBook);
102 std::string sql("SELECT * FROM " TABLE_NAME);
103 auto stmt = sql_be->create_statement_from_sql(sql);
104 if (stmt != nullptr)
105 {
106 auto result = sql_be->execute_select_statement(stmt);
107 if (result->begin() == result->end())
108 return;
109
110 GNCPrice* pPrice;
111
112 gnc_pricedb_set_bulk_update (pPriceDB, TRUE);
113 for (auto row : *result)
114 {
115 pPrice = load_single_price (sql_be, row);
116
117 if (pPrice != NULL)
118 {
119 (void)gnc_pricedb_add_price (pPriceDB, pPrice);
120 gnc_price_unref (pPrice);
121 }
122 }
123 gnc_pricedb_set_bulk_update (pPriceDB, FALSE);
124 std::string pkey(col_table[0]->name());
125 sql = "SELECT DISTINCT ";
126 sql += pkey + " FROM " TABLE_NAME;
127 gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
128 (BookLookupFn)gnc_price_lookup);
129 }
130}
131
132/* ================================================================= */
133void
135{
136 gint version;
137
138 g_return_if_fail (sql_be != NULL);
139
140 version = sql_be->get_table_version( TABLE_NAME);
141 if (version == 0)
142 {
143 (void)sql_be->create_table(TABLE_NAME, TABLE_VERSION, col_table);
144 }
145 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 sql_be->upgrade_table(TABLE_NAME, col_table);
152 sql_be->set_table_version (TABLE_NAME, TABLE_VERSION);
153
154 PINFO ("Prices table upgraded from version 1 to version %d\n", TABLE_VERSION);
155 }
156}
157
158/* ================================================================= */
159
160bool
162{
163 GNCPrice* pPrice = GNC_PRICE (inst);
164 E_DB_OPERATION op;
165 gboolean is_infant;
166 gboolean is_ok = TRUE;
167
168 g_return_val_if_fail (sql_be != NULL, FALSE);
169 g_return_val_if_fail (inst != NULL, FALSE);
170 g_return_val_if_fail (GNC_IS_PRICE (inst), FALSE);
171
172 is_infant = qof_instance_get_infant (inst);
174 {
175 op = OP_DB_DELETE;
176 }
177 else if (sql_be->pristine() || is_infant)
178 {
179 op = OP_DB_INSERT;
180 }
181 else
182 {
183 op = OP_DB_UPDATE;
184 }
185
186 if (op != OP_DB_DELETE)
187 {
188 /* Ensure commodity and currency are in the db */
189 (void)sql_be->save_commodity(gnc_price_get_commodity(pPrice));
190 is_ok = sql_be->save_commodity(gnc_price_get_currency(pPrice));
191 }
192
193 if (is_ok)
194 {
195 is_ok = sql_be->do_db_operation(op, TABLE_NAME, GNC_ID_PRICE, pPrice,
196 col_table);
197 }
198
199 return is_ok;
200}
201
202static gboolean
203write_price (GNCPrice* p, gpointer data)
204{
205 auto s = reinterpret_cast<write_objects_t*>(data);
206
207 g_return_val_if_fail (p != NULL, FALSE);
208 g_return_val_if_fail (data != NULL, FALSE);
209
210 if (s->is_ok && gnc_price_get_source (p) != PRICE_SOURCE_TEMP)
211 {
212 s->commit (QOF_INSTANCE(p));
213 }
214
215 return s->is_ok;
216}
217
218bool
220{
221 g_return_val_if_fail (sql_be != NULL, FALSE);
222 write_objects_t data{sql_be, true, this};
223
224 auto priceDB = gnc_pricedb_get_db (sql_be->book());
225 return gnc_pricedb_foreach_price (priceDB, write_price, &data, TRUE);
226}
227
228/* ========================== 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 do_db_operation(E_DB_OPERATION op, const char *table_name, QofIdTypeConst obj_name, gpointer pObject, const EntryVec &table) const noexcept
Performs an operation on the database.
bool save_commodity(gnc_commodity *comm) noexcept
Ensure that a commodity referenced in another object is in fact saved in the database.
bool set_table_version(const std::string &table_name, uint_t version) noexcept
Registers the version for a table.
Encapsulates per-class table schema with functions to load, create a table, commit a changed front-en...
bool commit(GncSqlBackend *sql_be, QofInstance *inst) override
UPDATE/INSERT a single instance of m_type_name into the database.
void load_all(GncSqlBackend *) override
Load all objects of m_type in the database into memory.
void create_tables(GncSqlBackend *) override
Conditionally create or update a database table from m_col_table.
bool write(GncSqlBackend *) override
Write all objects of m_type_name to the database.
Row of SQL Query results.
load and save data to SQL
load and save data to SQL
a simple price database for gnucash
load and save accounts data to SQL
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
void gnc_pricedb_set_bulk_update(GNCPriceDB *db, gboolean bulk_update)
Set flag to indicate whether duplication checks should be performed.
gboolean gnc_pricedb_foreach_price(GNCPriceDB *db, GncPriceForeachFunc f, gpointer user_data, gboolean stable_order)
Call a GncPriceForeachFunction once for each price in db, until the function returns FALSE.
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Return the pricedb associated with the book.
gboolean gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p)
Add a price to the pricedb.
GNCPrice * gnc_price_create(QofBook *book)
gnc_price_create - returns a newly allocated and initialized price with a reference count of 1.
void gnc_price_unref(GNCPrice *p)
gnc_price_unref - indicate you're finished with a price (i.e.
QofBook reference.
Definition qofbook-p.hpp:47
Data-passing struct for callbacks to qof_object_foreach() used in GncSqlObjectBackend::write().