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:
Linas Vepstas 2001-06-03 07:41:07 +00:00
parent 9a44366d57
commit 23cb539270
7 changed files with 152 additions and 67 deletions

View File

@ -48,6 +48,7 @@
#include "Query.h" #include "Query.h"
#include "Transaction.h" #include "Transaction.h"
#include "gnc-book.h" #include "gnc-book.h"
#include "gnc-pricedb.h"
/* /*
* The book_begin() routine gives the backend a second initialization * The book_begin() routine gives the backend a second initialization
@ -157,6 +158,7 @@ struct _backend
int (*price_commit_edit) (Backend *, GNCPrice *); int (*price_commit_edit) (Backend *, GNCPrice *);
void (*run_query) (Backend *, Query *); void (*run_query) (Backend *, Query *);
void (*price_lookup) (Backend *, GNCPriceLookup *);
void (*sync) (Backend *, AccountGroup *); void (*sync) (Backend *, AccountGroup *);
void (*sync_price) (Backend *, GNCPriceDB *); void (*sync_price) (Backend *, GNCPriceDB *);

View File

@ -305,6 +305,7 @@ xmlendNew (void)
be->be.price_begin_edit = NULL; be->be.price_begin_edit = NULL;
be->be.price_commit_edit = NULL; be->be.price_commit_edit = NULL;
be->be.run_query = xmlbeRunQuery; be->be.run_query = xmlbeRunQuery;
be->be.price_lookup = NULL;
be->be.sync = NULL; be->be.sync = NULL;
be->be.sync_price = NULL; be->be.sync_price = NULL;
be->be.events_pending = NULL; be->be.events_pending = NULL;

View File

@ -56,6 +56,24 @@ struct _GNCPriceDB {
gboolean dirty; 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_mark_clean(GNCPriceDB *db);
void gnc_pricedb_substitute_commodity(GNCPriceDB *db, void gnc_pricedb_substitute_commodity(GNCPriceDB *db,

View File

@ -372,7 +372,7 @@ gnc_price_get_version(GNCPrice *p)
} }
/* ==================================================================== */ /* ==================================================================== */
/* setters */ /* price list manipulation functions */
static gint static gint
compare_prices_by_date(gconstpointer a, gconstpointer b) compare_prices_by_date(gconstpointer a, gconstpointer b)
@ -624,6 +624,7 @@ gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
} }
/* ==================================================================== */ /* ==================================================================== */
/* lookup/query functions */
GNCPrice * GNCPrice *
gnc_pricedb_lookup_latest(GNCPriceDB *db, gnc_pricedb_lookup_latest(GNCPriceDB *db,
@ -636,12 +637,23 @@ gnc_pricedb_lookup_latest(GNCPriceDB *db,
if(!db || !commodity || !currency) return NULL; 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); currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
if(!currency_hash) return NULL; if(!currency_hash) return NULL;
price_list = g_hash_table_lookup(currency_hash, currency); price_list = g_hash_table_lookup(currency_hash, currency);
if(!price_list) return NULL; 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; result = price_list->data;
gnc_price_ref(result); gnc_price_ref(result);
return result; return result;
@ -659,6 +671,15 @@ gnc_pricedb_get_prices(GNCPriceDB *db,
if(!db || !commodity || !currency) return NULL; 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); currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
if(!currency_hash) return NULL; if(!currency_hash) return NULL;
@ -685,6 +706,16 @@ gnc_pricedb_lookup_at_time(GNCPriceDB *db,
if(!db || !c || !currency) return NULL; 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); currency_hash = g_hash_table_lookup(db->commodity_hash, c);
if(!currency_hash) return NULL; if(!currency_hash) return NULL;
@ -704,6 +735,79 @@ gnc_pricedb_lookup_at_time(GNCPriceDB *db,
return result; 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(&current_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 /* gnc_pricedb_foreach_price infrastructure
*/ */
@ -842,72 +946,7 @@ gnc_pricedb_foreach_price(GNCPriceDB *db,
} }
/* ==================================================================== */ /* ==================================================================== */
/* commodity substitution */
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(&current_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
*/
typedef struct { typedef struct {
gnc_commodity *old_c; gnc_commodity *old_c;

View File

@ -108,6 +108,7 @@
*/ */
typedef struct _GNCPrice GNCPrice; typedef struct _GNCPrice GNCPrice;
typedef struct _GNCPriceLookup GNCPriceLookup;
/****************/ /****************/
/* constructors */ /* constructors */

View File

@ -101,6 +101,7 @@ static void rpcendEnable (RPCBackend *be)
be->be.price_begin_edit = be->snr.price_begin_edit; be->be.price_begin_edit = be->snr.price_begin_edit;
be->be.price_commit_edit = be->snr.price_commit_edit; be->be.price_commit_edit = be->snr.price_commit_edit;
be->be.run_query = be->snr.run_query; 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 = be->snr.sync;
be->be.sync_price = be->snr.sync_price; 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_begin_edit = be->be.price_begin_edit;
be->snr.price_commit_edit = be->be.price_commit_edit; be->snr.price_commit_edit = be->be.price_commit_edit;
be->snr.run_query = be->be.run_query; 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 = be->be.sync;
be->snr.sync_price = be->be.sync_price; 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_begin_edit = NULL;
be->be.price_commit_edit = NULL; be->be.price_commit_edit = NULL;
be->be.run_query = NULL; be->be.run_query = NULL;
be->be.price_lookup = NULL;
be->be.sync = NULL; be->be.sync = NULL;
be->be.sync_price = NULL; be->be.sync_price = NULL;
} }
@ -583,6 +586,11 @@ static int rpcend_price_commit_edit (Backend *bend, GNCPrice *pr)
return 0; return 0;
} }
static void rpcend_price_lookup (Backend *bend, GNCPriceLookup *q)
{
PERR ("not implemented");
}
static void rpcend_run_query (Backend *bend, Query *q) static void rpcend_run_query (Backend *bend, Query *q)
{ {
RPCBackend *be = (RPCBackend *)bend; 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_begin_edit = rpcend_price_begin_edit;
be->be.price_commit_edit = rpcend_price_commit_edit; be->be.price_commit_edit = rpcend_price_commit_edit;
be->be.run_query = rpcend_run_query; be->be.run_query = rpcend_run_query;
be->be.price_lookup = rpcend_price_lookup;
be->be.sync = rpcend_sync; be->be.sync = rpcend_sync;
be->be.sync_price = rpcend_sync_price; be->be.sync_price = rpcend_sync_price;
be->be.events_pending = rpcend_events_pending; be->be.events_pending = rpcend_events_pending;

View File

@ -1546,6 +1546,14 @@ pgendGetAllPrices (PGBackend *be, GNCPriceDB *prdb)
return prdb; return prdb;
} }
/* ============================================================= */
static void
pgendPriceLookup (Backend *be, GNCPriceLookup *look)
{
PERR ("not implemented, type=%d", look->type);
}
/* ============================================================= */ /* ============================================================= */
/* ============================================================= */ /* ============================================================= */
/* HIGHER LEVEL ROUTINES AND BACKEND PROPER */ /* 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_begin_edit = NULL;
be->be.price_commit_edit = NULL; be->be.price_commit_edit = NULL;
be->be.run_query = NULL; be->be.run_query = NULL;
be->be.price_lookup = NULL;
be->be.sync = pgendSyncSingleFile; be->be.sync = pgendSyncSingleFile;
be->be.sync_price = pgendSyncPriceDBSingleFile; be->be.sync_price = pgendSyncPriceDBSingleFile;
PWARN ("MODE_SINGLE_FILE is beta -- \n" 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_begin_edit = pgend_price_begin_edit;
be->be.price_commit_edit = pgend_price_commit_edit; be->be.price_commit_edit = pgend_price_commit_edit;
be->be.run_query = NULL; be->be.run_query = NULL;
be->be.price_lookup = NULL;
be->be.sync = pgendSync; be->be.sync = pgendSync;
be->be.sync_price = pgendSyncPriceDB; be->be.sync_price = pgendSyncPriceDB;
PWARN ("MODE_SINGLE_UPDATE is beta -- \n" 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_begin_edit = pgend_price_begin_edit;
be->be.price_commit_edit = pgend_price_commit_edit; be->be.price_commit_edit = pgend_price_commit_edit;
be->be.run_query = pgendRunQueryToCheckpoint; be->be.run_query = pgendRunQueryToCheckpoint;
be->be.price_lookup = pgendPriceLookup;
be->be.sync = pgendSync; be->be.sync = pgendSync;
be->be.sync_price = pgendSyncPriceDB; be->be.sync_price = pgendSyncPriceDB;
PWARN ("MODE_POLL is experimental -- you might corrupt your data\n"); 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_begin_edit = be->be.price_begin_edit;
be->snr.price_commit_edit = be->be.price_commit_edit; be->snr.price_commit_edit = be->be.price_commit_edit;
be->snr.run_query = be->be.run_query; 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 = be->be.sync;
be->snr.sync_price = be->be.sync_price; be->snr.sync_price = be->be.sync_price;
@ -2809,6 +2821,7 @@ pgendDisable (PGBackend *be)
be->be.price_begin_edit = NULL; be->be.price_begin_edit = NULL;
be->be.price_commit_edit = NULL; be->be.price_commit_edit = NULL;
be->be.run_query = NULL; be->be.run_query = NULL;
be->be.price_lookup = NULL;
be->be.sync = NULL; be->be.sync = NULL;
be->be.sync_price = 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_begin_edit = be->snr.price_begin_edit;
be->be.price_commit_edit = be->snr.price_commit_edit; be->be.price_commit_edit = be->snr.price_commit_edit;
be->be.run_query = be->snr.run_query; 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 = be->snr.sync;
be->be.sync_price = be->snr.sync_price; be->be.sync_price = be->snr.sync_price;
} }
@ -2870,6 +2884,7 @@ pgendInit (PGBackend *be)
be->be.price_begin_edit = NULL; be->be.price_begin_edit = NULL;
be->be.price_commit_edit = NULL; be->be.price_commit_edit = NULL;
be->be.run_query = NULL; be->be.run_query = NULL;
be->be.price_lookup = NULL;
be->be.sync = NULL; be->be.sync = NULL;
be->be.sync_price = NULL; be->be.sync_price = NULL;
be->be.events_pending = NULL; be->be.events_pending = NULL;