mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
add callbacks for pricedb queries
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4390 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
9a44366d57
commit
23cb539270
@ -48,6 +48,7 @@
|
||||
#include "Query.h"
|
||||
#include "Transaction.h"
|
||||
#include "gnc-book.h"
|
||||
#include "gnc-pricedb.h"
|
||||
|
||||
/*
|
||||
* The book_begin() routine gives the backend a second initialization
|
||||
@ -157,6 +158,7 @@ struct _backend
|
||||
int (*price_commit_edit) (Backend *, GNCPrice *);
|
||||
|
||||
void (*run_query) (Backend *, Query *);
|
||||
void (*price_lookup) (Backend *, GNCPriceLookup *);
|
||||
void (*sync) (Backend *, AccountGroup *);
|
||||
void (*sync_price) (Backend *, GNCPriceDB *);
|
||||
|
||||
|
@ -305,6 +305,7 @@ xmlendNew (void)
|
||||
be->be.price_begin_edit = NULL;
|
||||
be->be.price_commit_edit = NULL;
|
||||
be->be.run_query = xmlbeRunQuery;
|
||||
be->be.price_lookup = NULL;
|
||||
be->be.sync = NULL;
|
||||
be->be.sync_price = NULL;
|
||||
be->be.events_pending = NULL;
|
||||
|
@ -56,6 +56,24 @@ struct _GNCPriceDB {
|
||||
gboolean dirty;
|
||||
};
|
||||
|
||||
/* These structs define the kind of price lookup being done
|
||||
* so that it can be passed to the backend. This is a rather
|
||||
* cheesy, low-brow interface. It could stand improvement.
|
||||
*/
|
||||
typedef enum {
|
||||
LOOKUP_LATEST = 1,
|
||||
LOOKUP_ALL,
|
||||
LOOKUP_AT_TIME,
|
||||
LOOKUP_NEAREST_IN_TIME
|
||||
} PriceLookupType;
|
||||
|
||||
|
||||
struct _GNCPriceLookup {
|
||||
PriceLookupType type;
|
||||
gnc_commodity *commodity;
|
||||
gnc_commodity *currency;
|
||||
Timespec date;
|
||||
};
|
||||
|
||||
void gnc_pricedb_mark_clean(GNCPriceDB *db);
|
||||
void gnc_pricedb_substitute_commodity(GNCPriceDB *db,
|
||||
|
@ -372,7 +372,7 @@ gnc_price_get_version(GNCPrice *p)
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* setters */
|
||||
/* price list manipulation functions */
|
||||
|
||||
static gint
|
||||
compare_prices_by_date(gconstpointer a, gconstpointer b)
|
||||
@ -624,6 +624,7 @@ gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* lookup/query functions */
|
||||
|
||||
GNCPrice *
|
||||
gnc_pricedb_lookup_latest(GNCPriceDB *db,
|
||||
@ -636,12 +637,23 @@ gnc_pricedb_lookup_latest(GNCPriceDB *db,
|
||||
|
||||
if(!db || !commodity || !currency) return NULL;
|
||||
|
||||
if (db->backend && db->backend->price_lookup)
|
||||
{
|
||||
GNCPriceLookup pl;
|
||||
pl.type = LOOKUP_LATEST;
|
||||
pl.commodity = commodity;
|
||||
pl.currency = currency;
|
||||
(db->backend->price_lookup) (db->backend, &pl);
|
||||
}
|
||||
|
||||
currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
|
||||
if(!currency_hash) return NULL;
|
||||
|
||||
price_list = g_hash_table_lookup(currency_hash, currency);
|
||||
if(!price_list) return NULL;
|
||||
|
||||
/* This works magically because prices are inserted in date-sorted order,
|
||||
* and the latest date always comes first. So return the first in the list. */
|
||||
result = price_list->data;
|
||||
gnc_price_ref(result);
|
||||
return result;
|
||||
@ -659,6 +671,15 @@ gnc_pricedb_get_prices(GNCPriceDB *db,
|
||||
|
||||
if(!db || !commodity || !currency) return NULL;
|
||||
|
||||
if (db->backend && db->backend->price_lookup)
|
||||
{
|
||||
GNCPriceLookup pl;
|
||||
pl.type = LOOKUP_ALL;
|
||||
pl.commodity = commodity;
|
||||
pl.currency = currency;
|
||||
(db->backend->price_lookup) (db->backend, &pl);
|
||||
}
|
||||
|
||||
currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
|
||||
if(!currency_hash) return NULL;
|
||||
|
||||
@ -685,6 +706,16 @@ gnc_pricedb_lookup_at_time(GNCPriceDB *db,
|
||||
|
||||
if(!db || !c || !currency) return NULL;
|
||||
|
||||
if (db->backend && db->backend->price_lookup)
|
||||
{
|
||||
GNCPriceLookup pl;
|
||||
pl.type = LOOKUP_AT_TIME;
|
||||
pl.commodity = c;
|
||||
pl.currency = currency;
|
||||
pl.date = t;
|
||||
(db->backend->price_lookup) (db->backend, &pl);
|
||||
}
|
||||
|
||||
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
|
||||
if(!currency_hash) return NULL;
|
||||
|
||||
@ -704,6 +735,79 @@ gnc_pricedb_lookup_at_time(GNCPriceDB *db,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
GNCPrice *
|
||||
gnc_pricedb_lookup_nearest_in_time(GNCPriceDB *db,
|
||||
gnc_commodity *c,
|
||||
gnc_commodity *currency,
|
||||
Timespec t)
|
||||
{
|
||||
GList *price_list;
|
||||
GNCPrice *current_price = NULL;
|
||||
GNCPrice *next_price = NULL;
|
||||
GNCPrice *result = NULL;
|
||||
GList *item = NULL;
|
||||
GHashTable *currency_hash;
|
||||
|
||||
if(!db || !c || !currency) return NULL;
|
||||
|
||||
if (db->backend && db->backend->price_lookup)
|
||||
{
|
||||
GNCPriceLookup pl;
|
||||
pl.type = LOOKUP_NEAREST_IN_TIME;
|
||||
pl.commodity = c;
|
||||
pl.currency = currency;
|
||||
pl.date = t;
|
||||
(db->backend->price_lookup) (db->backend, &pl);
|
||||
}
|
||||
|
||||
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
|
||||
if(!currency_hash) return NULL;
|
||||
|
||||
price_list = g_hash_table_lookup(currency_hash, currency);
|
||||
if(!price_list) return NULL;
|
||||
|
||||
item = price_list;
|
||||
|
||||
/* default answer */
|
||||
current_price = item->data;
|
||||
|
||||
/* find the first candidate past the one we want. Remember that
|
||||
prices are in most-recent-first order. */
|
||||
while (!next_price && item) {
|
||||
GNCPrice *p = item->data;
|
||||
Timespec price_time = gnc_price_get_time(p);
|
||||
if (timespec_cmp(&price_time, &t) <= 0) {
|
||||
next_price = item->data;
|
||||
break;
|
||||
}
|
||||
current_price = item->data;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
if (current_price) {
|
||||
if (!next_price) {
|
||||
result = current_price;
|
||||
} else {
|
||||
Timespec current_t = gnc_price_get_time(current_price);
|
||||
Timespec next_t = gnc_price_get_time(next_price);
|
||||
Timespec diff_current = timespec_diff(¤t_t, &t);
|
||||
Timespec diff_next = timespec_diff(&next_t, &t);
|
||||
Timespec abs_current = timespec_abs(&diff_current);
|
||||
Timespec abs_next = timespec_abs(&diff_next);
|
||||
|
||||
if (timespec_cmp(&abs_current, &abs_next) <= 0) {
|
||||
result = current_price;
|
||||
} else {
|
||||
result = next_price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gnc_price_ref(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* gnc_pricedb_foreach_price infrastructure
|
||||
*/
|
||||
@ -842,72 +946,7 @@ gnc_pricedb_foreach_price(GNCPriceDB *db,
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
GNCPrice *
|
||||
gnc_pricedb_lookup_nearest_in_time(GNCPriceDB *db,
|
||||
gnc_commodity *c,
|
||||
gnc_commodity *currency,
|
||||
Timespec t)
|
||||
{
|
||||
GList *price_list;
|
||||
GNCPrice *current_price = NULL;
|
||||
GNCPrice *next_price = NULL;
|
||||
GNCPrice *result = NULL;
|
||||
GList *item = NULL;
|
||||
GHashTable *currency_hash;
|
||||
|
||||
if(!db || !c || !currency) return NULL;
|
||||
|
||||
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
|
||||
if(!currency_hash) return NULL;
|
||||
|
||||
price_list = g_hash_table_lookup(currency_hash, currency);
|
||||
if(!price_list) return NULL;
|
||||
|
||||
item = price_list;
|
||||
|
||||
/* default answer */
|
||||
current_price = item->data;
|
||||
|
||||
/* find the first candidate past the one we want. Remember that
|
||||
prices are in most-recent-first order. */
|
||||
while (!next_price && item) {
|
||||
GNCPrice *p = item->data;
|
||||
Timespec price_time = gnc_price_get_time(p);
|
||||
if (timespec_cmp(&price_time, &t) <= 0) {
|
||||
next_price = item->data;
|
||||
break;
|
||||
}
|
||||
current_price = item->data;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
if (current_price) {
|
||||
if (!next_price) {
|
||||
result = current_price;
|
||||
} else {
|
||||
Timespec current_t = gnc_price_get_time(current_price);
|
||||
Timespec next_t = gnc_price_get_time(next_price);
|
||||
Timespec diff_current = timespec_diff(¤t_t, &t);
|
||||
Timespec diff_next = timespec_diff(&next_t, &t);
|
||||
Timespec abs_current = timespec_abs(&diff_current);
|
||||
Timespec abs_next = timespec_abs(&diff_next);
|
||||
|
||||
if (timespec_cmp(&abs_current, &abs_next) <= 0) {
|
||||
result = current_price;
|
||||
} else {
|
||||
result = next_price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gnc_price_ref(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* commodity substitution
|
||||
*/
|
||||
/* commodity substitution */
|
||||
|
||||
typedef struct {
|
||||
gnc_commodity *old_c;
|
||||
|
@ -108,6 +108,7 @@
|
||||
*/
|
||||
|
||||
typedef struct _GNCPrice GNCPrice;
|
||||
typedef struct _GNCPriceLookup GNCPriceLookup;
|
||||
|
||||
/****************/
|
||||
/* constructors */
|
||||
|
@ -101,6 +101,7 @@ static void rpcendEnable (RPCBackend *be)
|
||||
be->be.price_begin_edit = be->snr.price_begin_edit;
|
||||
be->be.price_commit_edit = be->snr.price_commit_edit;
|
||||
be->be.run_query = be->snr.run_query;
|
||||
be->be.price_lookup = be->snr.price_lookup;
|
||||
be->be.sync = be->snr.sync;
|
||||
be->be.sync_price = be->snr.sync_price;
|
||||
}
|
||||
@ -123,6 +124,7 @@ static void rpcendDisable (RPCBackend *be)
|
||||
be->snr.price_begin_edit = be->be.price_begin_edit;
|
||||
be->snr.price_commit_edit = be->be.price_commit_edit;
|
||||
be->snr.run_query = be->be.run_query;
|
||||
be->snr.price_lookup = be->be.price_lookup;
|
||||
be->snr.sync = be->be.sync;
|
||||
be->snr.sync_price = be->be.sync_price;
|
||||
|
||||
@ -135,6 +137,7 @@ static void rpcendDisable (RPCBackend *be)
|
||||
be->be.price_begin_edit = NULL;
|
||||
be->be.price_commit_edit = NULL;
|
||||
be->be.run_query = NULL;
|
||||
be->be.price_lookup = NULL;
|
||||
be->be.sync = NULL;
|
||||
be->be.sync_price = NULL;
|
||||
}
|
||||
@ -583,6 +586,11 @@ static int rpcend_price_commit_edit (Backend *bend, GNCPrice *pr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rpcend_price_lookup (Backend *bend, GNCPriceLookup *q)
|
||||
{
|
||||
PERR ("not implemented");
|
||||
}
|
||||
|
||||
static void rpcend_run_query (Backend *bend, Query *q)
|
||||
{
|
||||
RPCBackend *be = (RPCBackend *)bend;
|
||||
@ -928,6 +936,7 @@ static void rpcend_book_begin (GNCBook *book, const char *book_id,
|
||||
be->be.price_begin_edit = rpcend_price_begin_edit;
|
||||
be->be.price_commit_edit = rpcend_price_commit_edit;
|
||||
be->be.run_query = rpcend_run_query;
|
||||
be->be.price_lookup = rpcend_price_lookup;
|
||||
be->be.sync = rpcend_sync;
|
||||
be->be.sync_price = rpcend_sync_price;
|
||||
be->be.events_pending = rpcend_events_pending;
|
||||
|
@ -1546,6 +1546,14 @@ pgendGetAllPrices (PGBackend *be, GNCPriceDB *prdb)
|
||||
return prdb;
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
|
||||
static void
|
||||
pgendPriceLookup (Backend *be, GNCPriceLookup *look)
|
||||
{
|
||||
PERR ("not implemented, type=%d", look->type);
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* ============================================================= */
|
||||
/* HIGHER LEVEL ROUTINES AND BACKEND PROPER */
|
||||
@ -2720,6 +2728,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
be->be.price_begin_edit = NULL;
|
||||
be->be.price_commit_edit = NULL;
|
||||
be->be.run_query = NULL;
|
||||
be->be.price_lookup = NULL;
|
||||
be->be.sync = pgendSyncSingleFile;
|
||||
be->be.sync_price = pgendSyncPriceDBSingleFile;
|
||||
PWARN ("MODE_SINGLE_FILE is beta -- \n"
|
||||
@ -2739,6 +2748,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
be->be.price_begin_edit = pgend_price_begin_edit;
|
||||
be->be.price_commit_edit = pgend_price_commit_edit;
|
||||
be->be.run_query = NULL;
|
||||
be->be.price_lookup = NULL;
|
||||
be->be.sync = pgendSync;
|
||||
be->be.sync_price = pgendSyncPriceDB;
|
||||
PWARN ("MODE_SINGLE_UPDATE is beta -- \n"
|
||||
@ -2757,6 +2767,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
be->be.price_begin_edit = pgend_price_begin_edit;
|
||||
be->be.price_commit_edit = pgend_price_commit_edit;
|
||||
be->be.run_query = pgendRunQueryToCheckpoint;
|
||||
be->be.price_lookup = pgendPriceLookup;
|
||||
be->be.sync = pgendSync;
|
||||
be->be.sync_price = pgendSyncPriceDB;
|
||||
PWARN ("MODE_POLL is experimental -- you might corrupt your data\n");
|
||||
@ -2798,6 +2809,7 @@ pgendDisable (PGBackend *be)
|
||||
be->snr.price_begin_edit = be->be.price_begin_edit;
|
||||
be->snr.price_commit_edit = be->be.price_commit_edit;
|
||||
be->snr.run_query = be->be.run_query;
|
||||
be->snr.price_lookup = be->be.price_lookup;
|
||||
be->snr.sync = be->be.sync;
|
||||
be->snr.sync_price = be->be.sync_price;
|
||||
|
||||
@ -2809,6 +2821,7 @@ pgendDisable (PGBackend *be)
|
||||
be->be.price_begin_edit = NULL;
|
||||
be->be.price_commit_edit = NULL;
|
||||
be->be.run_query = NULL;
|
||||
be->be.price_lookup = NULL;
|
||||
be->be.sync = NULL;
|
||||
be->be.sync_price = NULL;
|
||||
}
|
||||
@ -2835,6 +2848,7 @@ pgendEnable (PGBackend *be)
|
||||
be->be.price_begin_edit = be->snr.price_begin_edit;
|
||||
be->be.price_commit_edit = be->snr.price_commit_edit;
|
||||
be->be.run_query = be->snr.run_query;
|
||||
be->be.price_lookup = be->snr.price_lookup;
|
||||
be->be.sync = be->snr.sync;
|
||||
be->be.sync_price = be->snr.sync_price;
|
||||
}
|
||||
@ -2870,6 +2884,7 @@ pgendInit (PGBackend *be)
|
||||
be->be.price_begin_edit = NULL;
|
||||
be->be.price_commit_edit = NULL;
|
||||
be->be.run_query = NULL;
|
||||
be->be.price_lookup = NULL;
|
||||
be->be.sync = NULL;
|
||||
be->be.sync_price = NULL;
|
||||
be->be.events_pending = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user