34#include "Recurrence.h"
37#if defined( S_SPLINT_S )
38#include "splint-defs.h"
41#include "gnc-sql-connection.hpp"
42#include "gnc-sql-backend.hpp"
43#include "gnc-sql-object-backend.hpp"
44#include "gnc-sql-column-table-entry.hpp"
49#define BUDGET_TABLE "budgets"
50#define TABLE_VERSION 1
51#define AMOUNTS_TABLE "budget_amounts"
52#define AMOUNTS_TABLE_VERSION 1
54[[maybe_unused]]
static QofLogModule log_module = G_LOG_DOMAIN;
56#define BUDGET_MAX_NAME_LEN 2048
57#define BUDGET_MAX_DESCRIPTION_LEN 2048
59static const EntryVec col_table
61 gnc_sql_make_table_entry<CT_GUID>(
62 "guid", 0, COL_NNUL | COL_PKEY,
"guid"),
63 gnc_sql_make_table_entry<CT_STRING>(
64 "name", BUDGET_MAX_NAME_LEN, COL_NNUL,
"name"),
65 gnc_sql_make_table_entry<CT_STRING>(
66 "description", BUDGET_MAX_DESCRIPTION_LEN, 0,
"description"),
67 gnc_sql_make_table_entry<CT_INT>(
68 "num_periods", 0, COL_NNUL,
"num_periods"),
72static void set_budget (gpointer pObj, gpointer val);
74static void set_account (gpointer pObj, gpointer val);
75static gint get_period_num (gpointer pObj);
76static void set_period_num (gpointer pObj, gpointer val);
77static gnc_numeric get_amount (gpointer pObj);
78static void set_amount (gpointer pObj, gnc_numeric value);
80GncSqlBudgetBackend::GncSqlBudgetBackend() :
82 BUDGET_TABLE, col_table) {}
91static const EntryVec budget_amounts_col_table
93 gnc_sql_make_table_entry<CT_INT>(
94 "id", 0, COL_NNUL | COL_PKEY | COL_AUTOINC),
95 gnc_sql_make_table_entry<CT_BUDGETREF>(
"budget_guid", 0, COL_NNUL,
98 gnc_sql_make_table_entry<CT_ACCOUNTREF>(
"account_guid", 0, COL_NNUL,
101 gnc_sql_make_table_entry<CT_INT>(
"period_num", 0, COL_NNUL,
104 gnc_sql_make_table_entry<CT_NUMERIC>(
"amount", 0, COL_NNUL,
111get_budget (gpointer pObj)
115 g_return_val_if_fail (pObj != NULL, NULL);
117 return QOF_INSTANCE (info->budget);
121set_budget (gpointer pObj, gpointer val)
126get_account (gpointer pObj)
130 g_return_val_if_fail (pObj != NULL, NULL);
132 return QOF_INSTANCE (info->account);
136set_account (gpointer pObj, gpointer val)
140 g_return_if_fail (pObj != NULL);
141 g_return_if_fail (val != NULL);
142 g_return_if_fail (GNC_IS_ACCOUNT (val));
144 info->account = GNC_ACCOUNT (val);
148get_period_num (gpointer pObj)
152 g_return_val_if_fail (pObj != NULL, 0);
154 return info->period_num;
158set_period_num (gpointer pObj, gpointer val)
162 g_return_if_fail (pObj != NULL);
164 info->period_num = GPOINTER_TO_UINT (val);
168get_amount (gpointer pObj)
172 g_return_val_if_fail (pObj != NULL, gnc_numeric_zero ());
174 return gnc_budget_get_account_period_value (info->budget, info->account,
179set_amount (gpointer pObj, gnc_numeric value)
183 g_return_if_fail (pObj != NULL);
185 gnc_budget_set_account_period_value (info->budget, info->account,
186 info->period_num, value);
197load_budget_amounts (
GncSqlBackend* sql_be, GncBudget* budget)
201 g_return_if_fail (sql_be != NULL);
202 g_return_if_fail (budget != NULL);
206 auto sql = g_strdup_printf (
"SELECT * FROM %s WHERE budget_guid='%s'",
207 AMOUNTS_TABLE, guid_buf);
208 auto stmt = sql_be->create_statement_from_sql(sql);
215 for (
auto row : *result)
216 gnc_sql_load_object (sql_be, row, NULL, &info, budget_amounts_col_table);
227delete_budget_amounts (
GncSqlBackend* sql_be, GncBudget* budget)
231 g_return_val_if_fail (sql_be != NULL, FALSE);
232 g_return_val_if_fail (budget != NULL, FALSE);
236 std::stringstream sql;
237 sql <<
"DELETE FROM " << AMOUNTS_TABLE <<
" WHERE budget_guid='"<<
239 auto stmt = sql_be->create_statement_from_sql(sql.str());
240 sql_be->execute_nonselect_statement(stmt);
252save_budget_amounts (
GncSqlBackend* sql_be, GncBudget* budget)
258 gboolean is_ok = TRUE;
260 g_return_val_if_fail (sql_be != NULL, FALSE);
261 g_return_val_if_fail (budget != NULL, FALSE);
264 delete_budget_amounts (sql_be, budget);
266 info.budget = budget;
267 num_periods = gnc_budget_get_num_periods (budget);
270 for (node = descendants; node != NULL && is_ok; node = g_list_next (node))
274 info.account = GNC_ACCOUNT (node->data);
275 for (i = 0; i < num_periods && is_ok; i++)
277 if (gnc_budget_is_account_period_value_set (budget, info.account, i))
282 budget_amounts_col_table);
286 g_list_free (descendants);
295 GncBudget* pBudget = NULL;
298 g_return_val_if_fail (sql_be != NULL, NULL);
300 guid = gnc_sql_load_guid (sql_be, row);
303 pBudget = gnc_budget_lookup (guid, sql_be->book());
310 gnc_budget_begin_edit (pBudget);
311 gnc_sql_load_object (sql_be, row, GNC_ID_BUDGET, pBudget, col_table);
312 load_budget_amounts (sql_be, pBudget);
313 r = gnc_sql_recurrence_load (sql_be, gnc_budget_get_guid (pBudget));
316 gnc_budget_set_recurrence (pBudget, r);
319 gnc_budget_commit_edit (pBudget);
327 g_return_if_fail (sql_be != NULL);
329 std::string sql(
"SELECT * FROM " BUDGET_TABLE);
330 auto stmt = sql_be->create_statement_from_sql(sql);
332 for (
auto row : *result)
333 load_single_budget (sql_be, row);
335 std::string pkey(col_table[0]->name());
336 sql =
"SELECT DISTINCT ";
337 sql += pkey +
" FROM " BUDGET_TABLE;
338 gnc_sql_slots_load_for_sql_subquery (sql_be, sql,
339 (BookLookupFn)gnc_budget_lookup);
348 g_return_if_fail (sql_be != NULL);
353 (void)sql_be->
create_table(BUDGET_TABLE, TABLE_VERSION, col_table);
359 (void)sql_be->
create_table(AMOUNTS_TABLE, AMOUNTS_TABLE_VERSION,
360 budget_amounts_col_table);
368 GncBudget* pBudget = GNC_BUDGET (inst);
374 g_return_val_if_fail (sql_be != NULL, FALSE);
375 g_return_val_if_fail (inst != NULL, FALSE);
376 g_return_val_if_fail (GNC_IS_BUDGET (inst), FALSE);
378 is_infant = qof_instance_get_infant (inst);
383 else if (sql_be->pristine() || is_infant)
391 is_ok = sql_be->
do_db_operation(op, BUDGET_TABLE, GNC_ID_BUDGET, pBudget,
400 is_ok = save_budget_amounts (sql_be, pBudget);
403 is_ok = gnc_sql_recurrence_save (sql_be, guid,
404 gnc_budget_get_recurrence (pBudget));
408 is_ok = gnc_sql_slots_save (sql_be, guid, is_infant, inst);
413 is_ok = delete_budget_amounts (sql_be, pBudget);
416 is_ok = gnc_sql_recurrence_delete (sql_be, guid);
420 (void)gnc_sql_slots_delete (sql_be, guid);
435 s->is_ok = s->obe->commit (s->be, inst);
444 g_return_val_if_fail (sql_be != NULL, FALSE);
460 gpointer pObject)
const noexcept
462 load_from_guid_ref(row, obj_name, pObject,
464 return gnc_budget_lookup (g, sql_be->book());
471 add_objectref_guid_to_table(vec);
476 const gpointer pObject,
477 PairVec& vec)
const noexcept
479 add_objectref_guid_to_query(obj_name, pObject, vec);
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.
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.
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 commit(GncSqlBackend *sql_be, QofInstance *inst) override
UPDATE/INSERT a single instance of m_type_name into the database.
bool write(GncSqlBackend *) override
Write all objects of m_type_name to the database.
void add_to_query(QofIdTypeConst obj_name, void *pObject, PairVec &vec) const noexcept override
Add a pair of the table column heading and object's value's string representation to a PairVec; used ...
void add_to_table(ColVec &vec) const noexcept override
Add a GncSqlColumnInfo structure for the column type to a ColVec.
void load(const GncSqlBackend *sql_be, GncSqlRow &row, QofIdTypeConst obj_name, void *pObject) const noexcept override
Load a value into an object from the database row.
Encapsulates per-class table schema with functions to load, create a table, commit a changed front-en...
Row of SQL Query results.
load and save data to SQL
load and save accounts data to SQL
load and save accounts data to SQL
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
void(* QofInstanceForeachCB)(QofInstance *, gpointer user_data)
Callback type for qof_collection_foreach.
const gchar * QofIdTypeConst
QofIdTypeConst declaration.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
GncBudget * gnc_budget_new(QofBook *book)
Creates and initializes a Budget.
The type used to store guids in C.
Data-passing struct for callbacks to qof_object_foreach() used in GncSqlObjectBackend::write().