GnuCash 2.3.0
Files | Typedefs | Functions
Price Database
GnuCash Engine: Core, Non-GUI Accounting Functions

Files

file  gnc-pricedb.h
 

a simple price database for gnucash


Typedefs

typedef struct gnc_price_db_s GNCPriceDB

Functions

GNCPriceDBgnc_pricedb_get_db (QofBook *book)
GNCPriceDBgnc_collection_get_pricedb (QofCollection *col)
void gnc_pricedb_destroy (GNCPriceDB *db)
void gnc_pricedb_begin_edit (GNCPriceDB *)
void gnc_pricedb_commit_edit (GNCPriceDB *)
void gnc_pricedb_set_bulk_update (GNCPriceDB *db, gboolean bulk_update)
gboolean gnc_pricedb_add_price (GNCPriceDB *db, GNCPrice *p)
gboolean gnc_pricedb_remove_price (GNCPriceDB *db, GNCPrice *p)
gboolean gnc_pricedb_remove_old_prices (GNCPriceDB *db, Timespec cutoff, const gboolean delete_user, gboolean delete_last)
GNCPricegnc_pricedb_lookup_latest (GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency)
PriceList * gnc_pricedb_lookup_latest_any_currency (GNCPriceDB *db, const gnc_commodity *commodity)
gboolean gnc_pricedb_has_prices (GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency)
PriceList * gnc_pricedb_get_prices (GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency)
PriceList * gnc_pricedb_lookup_at_time (GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency, Timespec t)
PriceList * gnc_pricedb_lookup_day (GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency, Timespec t)
GNCPricegnc_pricedb_lookup_nearest_in_time (GNCPriceDB *db, const gnc_commodity *c, const gnc_commodity *currency, Timespec t)
PriceList * gnc_pricedb_lookup_nearest_in_time_any_currency (GNCPriceDB *db, const gnc_commodity *c, Timespec t)
GNCPricegnc_pricedb_lookup_latest_before (GNCPriceDB *db, gnc_commodity *c, gnc_commodity *currency, Timespec t)
PriceList * gnc_pricedb_lookup_latest_before_any_currency (GNCPriceDB *db, gnc_commodity *c, Timespec t)
gnc_numeric gnc_pricedb_convert_balance_latest_price (GNCPriceDB *pdb, gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency)
gnc_numeric gnc_pricedb_convert_balance_nearest_price (GNCPriceDB *pdb, gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency, Timespec t)
gboolean gnc_pricedb_foreach_price (GNCPriceDB *db, gboolean(*f)(GNCPrice *p, gpointer user_data), gpointer user_data, gboolean stable_order)
guint gnc_pricedb_get_num_prices (GNCPriceDB *db)
gboolean gnc_pricedb_equal (GNCPriceDB *db1, GNCPriceDB *db2)

Internal/Debugging

void gnc_pricedb_print_contents (GNCPriceDB *db, FILE *f)

Price Parameter Names

For use with QofQuery

#define PRICE_COMMODITY   "price-commodity"
#define PRICE_CURRENCY   "price-currency"
#define PRICE_DATE   "price-date"
#define PRICE_SOURCE   "price-source"
#define PRICE_TYPE   "price-type"
#define PRICE_VALUE   "price-value"

Detailed Description

The PriceDB is intended to be a database of price quotes, or more specifically, a database of GNCPrices. For the time being, it is still a fairly simple database supporting only fairly simple queries. It is expected that new queries will be added as needed, and that there is some advantage to delaying complex queries for now in the hope that we get a real DB implementation before they're really needed.

Every QofBook contains a GNCPriceDB, accessible via gnc_pricedb_get_db.

Warning:
The PriceDB does not currently use the object system used elsewhere in the GnuCash Engine, i.e. it does not use GUISD's, Entities and Collections. It should. In particular, this means that currently prices cannot be queried with the same mechanism as everything else.

Whenever a you store a price in the pricedb, the pricedb adds its own reference to the price, so you can safely unref that price after inserting it into the DB if you're finished with it otherwise.

Similarly, when the pricedb returns a price to you, either singly, or in a price list, the price will have had a ref added for you, so you only need to unref the price(s) when you're finished with it/them.


Typedef Documentation

typedef struct gnc_price_db_s GNCPriceDB

Data type

Definition at line 281 of file gnc-pricedb.h.


Function Documentation

GNCPriceDB* gnc_collection_get_pricedb ( QofCollection col)
Todo:
Collections of prices are not destroyed fully.
gnc_pricedb_destroy does not clean up properly because gnc_pricedb_create reports an existing PriceDB after running gnc_pricedb_destroy. To change the pricedb, we need to destroy and recreate the book. Yuk.

Definition at line 854 of file gnc-pricedb.c.

{
    if (!col) return NULL;
    return qof_collection_get_data (col);
}
gboolean gnc_pricedb_add_price ( GNCPriceDB db,
GNCPrice p 
)

gnc_pricedb_add_price - add a price to the pricedb, you may drop your reference to the price (i.e. call unref) after this succeeds, whenever you're finished with the price.

Definition at line 1040 of file gnc-pricedb.c.

{
    if (!db || !p) return FALSE;

    ENTER ("db=%p, pr=%p dirty=%d destroying=%d",
           db, p, qof_instance_get_dirty_flag(p),
           qof_instance_get_destroying(p));

    if (FALSE == add_price(db, p))
    {
        LEAVE (" failed to add price");
        return FALSE;
    }

    gnc_pricedb_begin_edit(db);
    qof_instance_set_dirty(&db->inst);
    gnc_pricedb_commit_edit(db);

    LEAVE ("db=%p, pr=%p dirty=%d destroying=%d",
           db, p, qof_instance_get_dirty_flag(p),
           qof_instance_get_destroying(p));

    return TRUE;
}
void gnc_pricedb_begin_edit ( GNCPriceDB )

Used for editing the pricedb en-mass

Definition at line 347 of file gnc-pricedb.c.

{
    qof_begin_edit(&pdb->inst);
}
gnc_numeric gnc_pricedb_convert_balance_latest_price ( GNCPriceDB pdb,
gnc_numeric  balance,
const gnc_commodity balance_currency,
const gnc_commodity new_currency 
)

gnc_pricedb_convert_balance_latest_price - Convert a balance from one currency to another.

Definition at line 2050 of file gnc-pricedb.c.

{
    GNCPrice *price, *currency_price;
    GList *price_list, *list_helper;
    gnc_numeric currency_price_value;
    gnc_commodity *intermediate_currency;

    if (gnc_numeric_zero_p (balance) ||
            gnc_commodity_equiv (balance_currency, new_currency))
        return balance;

    /* Look for a direct price. */
    price = gnc_pricedb_lookup_latest (pdb, balance_currency, new_currency);
    if (price)
    {
        balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
                                   gnc_commodity_get_fraction (new_currency),
                                   GNC_HOW_RND_ROUND_HALF_UP);
        gnc_price_unref (price);
        return balance;
    }

    /* Look for a price of the new currency in the balance currency and use
     * the reciprocal if we find it
     */
    price = gnc_pricedb_lookup_latest (pdb, new_currency, balance_currency);
    if (price)
    {
        balance = gnc_numeric_div (balance, gnc_price_get_value (price),
                                   gnc_commodity_get_fraction (new_currency),
                                   GNC_HOW_RND_ROUND_HALF_UP);
        gnc_price_unref (price);
        return balance;
    }

    /*
     * no direct price found, try if we find a price in another currency
     * and convert in two stages
     */
    price_list = gnc_pricedb_lookup_latest_any_currency(pdb, balance_currency);
    if (!price_list)
    {
        balance =  gnc_numeric_zero ();
        return balance;
    }

    list_helper = price_list;
    currency_price_value = gnc_numeric_zero();

    do
    {
        price = (GNCPrice *)(list_helper->data);

        intermediate_currency = gnc_price_get_currency(price);
        currency_price = gnc_pricedb_lookup_latest(pdb, intermediate_currency,
                         new_currency);
        if (currency_price)
        {
            currency_price_value = gnc_price_get_value(currency_price);
            gnc_price_unref(currency_price);
        }
        else
        {
            currency_price = gnc_pricedb_lookup_latest(pdb, new_currency,
                             intermediate_currency);
            if (currency_price)
            {
                /* here we need the reciprocal */
                currency_price_value = gnc_numeric_div(gnc_numeric_create(1, 1),
                                                       gnc_price_get_value(currency_price),
                                                       GNC_DENOM_AUTO,
                                                       GNC_HOW_DENOM_EXACT | GNC_HOW_RND_NEVER);
                gnc_price_unref(currency_price);
            }
        }

        list_helper = list_helper->next;
    }
    while ((list_helper != NULL) &&
            (gnc_numeric_zero_p(currency_price_value)));

    balance = gnc_numeric_mul (balance, currency_price_value,
                               GNC_DENOM_AUTO,
                               GNC_HOW_DENOM_EXACT | GNC_HOW_RND_NEVER);
    balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
                               gnc_commodity_get_fraction (new_currency),
                               GNC_HOW_RND_ROUND_HALF_UP);

    gnc_price_list_destroy(price_list);
    return balance;
}
gnc_numeric gnc_pricedb_convert_balance_nearest_price ( GNCPriceDB pdb,
gnc_numeric  balance,
const gnc_commodity balance_currency,
const gnc_commodity new_currency,
Timespec  t 
)

gnc_pricedb_convert_balance_nearest_price - Convert a balance from one currency to another.

Definition at line 2146 of file gnc-pricedb.c.

{
    GNCPrice *price, *currency_price;
    GList *price_list, *list_helper;
    gnc_numeric currency_price_value;
    gnc_commodity *intermediate_currency;

    if (gnc_numeric_zero_p (balance) ||
            gnc_commodity_equiv (balance_currency, new_currency))
        return balance;

    /* Look for a direct price. */
    price = gnc_pricedb_lookup_nearest_in_time (pdb, balance_currency, new_currency, t);
    if (price)
    {
        balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
                                   gnc_commodity_get_fraction (new_currency),
                                   GNC_HOW_RND_ROUND_HALF_UP);
        gnc_price_unref (price);
        return balance;
    }

    /* Look for a price of the new currency in the balance currency and use
     * the reciprocal if we find it
     */
    price = gnc_pricedb_lookup_nearest_in_time (pdb, new_currency, balance_currency, t);
    if (price)
    {
        balance = gnc_numeric_div (balance, gnc_price_get_value (price),
                                   gnc_commodity_get_fraction (new_currency),
                                   GNC_HOW_RND_ROUND_HALF_UP);
        gnc_price_unref (price);
        return balance;
    }

    /*
     * no direct price found, try if we find a price in another currency
     * and convert in two stages
     */
    price_list = gnc_pricedb_lookup_nearest_in_time_any_currency(pdb, balance_currency, t);
    if (!price_list)
    {
        balance =  gnc_numeric_zero ();
        return balance;
    }

    list_helper = price_list;
    currency_price_value = gnc_numeric_zero();

    do
    {
        price = (GNCPrice *)(list_helper->data);

        intermediate_currency = gnc_price_get_currency(price);
        currency_price = gnc_pricedb_lookup_nearest_in_time(pdb, intermediate_currency,
                         new_currency, t);
        if (currency_price)
        {
            currency_price_value = gnc_price_get_value(currency_price);
            gnc_price_unref(currency_price);
        }
        else
        {
            currency_price = gnc_pricedb_lookup_nearest_in_time(pdb, new_currency,
                             intermediate_currency, t);
            if (currency_price)
            {
                /* here we need the reciprocal */
                currency_price_value = gnc_numeric_div(gnc_numeric_create(1, 1),
                                                       gnc_price_get_value(currency_price),
                                                       gnc_commodity_get_fraction (new_currency),
                                                       GNC_HOW_RND_ROUND_HALF_UP);
                gnc_price_unref(currency_price);
            }
        }

        list_helper = list_helper->next;
    }
    while ((list_helper != NULL) &&
            (gnc_numeric_zero_p(currency_price_value)));

    balance = gnc_numeric_mul (balance, currency_price_value,
                               gnc_commodity_get_fraction (new_currency),
                               GNC_HOW_RND_ROUND_HALF_UP);

    balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
                               gnc_commodity_get_fraction (new_currency),
                               GNC_HOW_RND_ROUND_HALF_UP);

    gnc_price_list_destroy(price_list);
    return balance;
}
void gnc_pricedb_destroy ( GNCPriceDB db)

gnc_pricedb_destroy - destroy the given pricedb and unref all of the prices it contains. This may not deallocate all of those prices. Other code may still be holding references to them.

Definition at line 817 of file gnc-pricedb.c.

{
    if (!db) return;
    if (db->commodity_hash)
    {
        g_hash_table_foreach (db->commodity_hash,
                              destroy_pricedb_commodity_hash_data,
                              NULL);
    }
    g_hash_table_destroy (db->commodity_hash);
    db->commodity_hash = NULL;
    /* qof_instance_release (&db->inst); */
    g_object_unref(db);
}
gboolean gnc_pricedb_equal ( GNCPriceDB db1,
GNCPriceDB db2 
)

gnc_pricedb_equal - test equality of two pricedbs

Definition at line 938 of file gnc-pricedb.c.

{
    GNCPriceDBEqualData equal_data;

    if (db1 == db2) return TRUE;

    if (!db1 || !db2)
    {
        PWARN ("one is NULL");
        return FALSE;
    }

    equal_data.equal = TRUE;
    equal_data.db2 = db2;

    g_hash_table_foreach (db1->commodity_hash,
                          pricedb_equal_foreach_currencies_hash,
                          &equal_data);

    return equal_data.equal;
}
gboolean gnc_pricedb_foreach_price ( GNCPriceDB db,
gboolean(*)(GNCPrice *p, gpointer user_data)  f,
gpointer  user_data,
gboolean  stable_order 
)

gnc_pricedb_foreach_price - call f once for each price in db, until and unless f returns FALSE. If stable_order is not FALSE, make sure the ordering of the traversal is stable (i.e. the same order every time given the same db contents -- stable traversals may be less efficient).

Definition at line 2381 of file gnc-pricedb.c.

{
    ENTER ("db=%p f=%p", db, f);
    if (stable_order)
    {
        LEAVE (" stable order found");
        return stable_price_traversal(db, f, user_data);
    }
    LEAVE (" use unstable order");
    return unstable_price_traversal(db, f, user_data);
}
GNCPriceDB* gnc_pricedb_get_db ( QofBook book)

return the pricedb associated with the book

Definition at line 861 of file gnc-pricedb.c.

{
    QofCollection *col;

    if (!book) return NULL;
    col = qof_book_get_collection (book, GNC_ID_PRICEDB);
    return gnc_collection_get_pricedb (col);
}
guint gnc_pricedb_get_num_prices ( GNCPriceDB db)

gnc_pricedb_get_num_prices - return the number of prices in the database.

Definition at line 883 of file gnc-pricedb.c.

{
    guint count;

    if (!db) return 0;

    count = 0;

    gnc_pricedb_foreach_price(db, num_prices_helper, &count, FALSE);

    return count;
}
PriceList* gnc_pricedb_get_prices ( GNCPriceDB db,
const gnc_commodity commodity,
const gnc_commodity currency 
)

gnc_pricedb_get_prices - return all the prices for a given commodity in the given currency. Returns NULL on failure. The result is a GNCPrice list (see above).

Definition at line 1466 of file gnc-pricedb.c.

{
    GList *price_list;
    GList *result;
    GList *node;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;

    if (!db || !commodity) return NULL;
    ENTER ("db=%p commodity=%p currency=%p", db, commodity, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_ALL;
        pl.prdb = db;
        pl.commodity = commodity;
        pl.currency = currency;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    if (currency)
    {
        price_list = g_hash_table_lookup(currency_hash, currency);
        if (!price_list)
        {
            LEAVE (" no price list");
            return NULL;
        }
        result = g_list_copy (price_list);
    }
    else
    {
        result = NULL;
        g_hash_table_foreach(currency_hash, hash_values_helper, (gpointer)&result);
    }
    for (node = result; node; node = node->next)
        gnc_price_ref (node->data);

    LEAVE (" ");
    return result;
}
gboolean gnc_pricedb_has_prices ( GNCPriceDB db,
const gnc_commodity commodity,
const gnc_commodity currency 
)

gnc_pricedb_has_prices - return an indication of whether or not there are any prices for a given commodity in the given currency. Returns TRUE if there are prices, FALSE otherwise.

Definition at line 1415 of file gnc-pricedb.c.

{
    GList *price_list;
    GHashTable *currency_hash;
    gint size;
    QofBook *book;
    QofBackend *be;

    if (!db || !commodity) return FALSE;
    ENTER ("db=%p commodity=%p currency=%p", db, commodity, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (book && be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_ALL;
        pl.prdb = db;
        pl.commodity = commodity;
        pl.currency = currency;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
    if (!currency_hash)
    {
        LEAVE("no, no currency_hash table");
        return FALSE;
    }

    if (currency)
    {
        price_list = g_hash_table_lookup(currency_hash, currency);
        if (price_list)
        {
            LEAVE("yes");
            return TRUE;
        }
        LEAVE("no, no price list");
        return FALSE;
    }

    size = g_hash_table_size (currency_hash);
    LEAVE("%s", size > 0 ? "yes" : "no");
    return size > 0;
}
PriceList* gnc_pricedb_lookup_at_time ( GNCPriceDB db,
const gnc_commodity commodity,
const gnc_commodity currency,
Timespec  t 
)

gnc_pricedb_lookup_at_time - return all prices that match the given commodity, currency, and timespec. Prices will be returned as a GNCPrice list (see above).

Definition at line 1609 of file gnc-pricedb.c.

{
    GList *price_list;
    GList *result = NULL;
    GList *item = NULL;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;

    if (!db || !c || !currency) return NULL;
    ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_AT_TIME;
        pl.prdb = db;
        pl.commodity = c;
        pl.currency = currency;
        pl.date = t;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    price_list = g_hash_table_lookup(currency_hash, currency);
    if (!price_list)
    {
        LEAVE (" no price list");
        return NULL;
    }

    item = price_list;
    while (item)
    {
        GNCPrice *p = item->data;
        Timespec price_time = gnc_price_get_time(p);
        if (timespec_equal(&price_time, &t))
        {
            result = g_list_prepend(result, p);
            gnc_price_ref(p);
        }
        item = item->next;
    }
    LEAVE (" ");
    return result;
}
PriceList* gnc_pricedb_lookup_day ( GNCPriceDB db,
const gnc_commodity commodity,
const gnc_commodity currency,
Timespec  t 
)

gnc_pricedb_lookup_day - return all prices that match the given commodity, currency, and timespec. Prices will be returned as a GNCPrice list (see above).

Definition at line 1523 of file gnc-pricedb.c.

{
    GList *price_list;
    GList *result = NULL;
    GList *item = NULL;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;

    if (!db || !c || !currency) return NULL;
    ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
    /* Convert to noon local time. */
    t = timespecCanonicalDayTime(t);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_AT_TIME;
        pl.prdb = db;
        pl.commodity = c;
        pl.currency = currency;
        pl.date = t;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    price_list = g_hash_table_lookup(currency_hash, currency);
    if (!price_list)
    {
        LEAVE (" no price list");
        return NULL;
    }

    item = price_list;
    while (item)
    {
        GNCPrice *p = item->data;
        Timespec price_time = timespecCanonicalDayTime(gnc_price_get_time(p));
        if (timespec_equal(&price_time, &t))
        {
            result = g_list_prepend(result, p);
            gnc_price_ref(p);
        }
        item = item->next;
    }
    LEAVE (" ");
    return result;
}
GNCPrice* gnc_pricedb_lookup_latest ( GNCPriceDB db,
const gnc_commodity commodity,
const gnc_commodity currency 
)

gnc_pricedb_lookup_latest - find the most recent price for the given commodity in the given currency. Returns NULL on failure.

Definition at line 1296 of file gnc-pricedb.c.

{
    GList *price_list;
    GNCPrice *result;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;

    if (!db || !commodity || !currency) return NULL;
    ENTER ("db=%p commodity=%p currency=%p", db, commodity, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_LATEST;
        pl.prdb = db;
        pl.commodity = commodity;
        pl.currency = currency;
        (be->price_lookup) (be, &pl);
    }
#endif

    currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    price_list = g_hash_table_lookup(currency_hash, currency);
    if (!price_list)
    {
        LEAVE (" no 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);
    LEAVE(" ");
    return result;
}
PriceList* gnc_pricedb_lookup_latest_any_currency ( GNCPriceDB db,
const gnc_commodity commodity 
)

gnc_pricedb_lookup_latest_any_currency - find the most recent prices for the given commodity in any available currency. Prices will be returned as a GNCPrice list (see above).

Definition at line 1360 of file gnc-pricedb.c.

{
    GList *result;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;

    result = NULL;

    if (!db || !commodity) return NULL;
    ENTER ("db=%p commodity=%p", db, commodity);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_LATEST;
        pl.prdb = db;
        pl.commodity = commodity;
        pl.currency = NULL;  /* can the backend handle this??? */
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    g_hash_table_foreach(currency_hash, lookup_latest, &result);

    if (!result)
    {
        LEAVE (" ");
        return NULL;
    }

    result = g_list_sort(result, compare_prices_by_date);

    LEAVE(" ");
    return result;
}
GNCPrice* gnc_pricedb_lookup_latest_before ( GNCPriceDB db,
gnc_commodity c,
gnc_commodity currency,
Timespec  t 
)

gnc_pricedb_lookup_latest_before - return the latest price for the given commodity in the given currency up to and including time t.

Definition at line 1790 of file gnc-pricedb.c.

{
    GList *price_list;
    GNCPrice *current_price = NULL;
    /*  GNCPrice *next_price = NULL;
        GNCPrice *result = NULL;*/
    GList *item = NULL;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;
    Timespec price_time;

    if (!db || !c || !currency) return NULL;
    ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_LATEST_BEFORE;
        pl.prdb = db;
        pl.commodity = c;
        pl.currency = currency;
        pl.date = t;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
    if (!currency_hash)
    {
        LEAVE ("no currency hash");
        return NULL;
    }

    price_list = g_hash_table_lookup(currency_hash, currency);
    if (!price_list)
    {
        LEAVE ("no price list");
        return NULL;
    }

    item = price_list;
    do
    {
        price_time = gnc_price_get_time (item->data);
        if (timespec_cmp(&price_time, &t) <= 0)
            current_price = item->data;
        item = item->next;
    }
    while (timespec_cmp(&price_time, &t) > 0 && item);
    gnc_price_ref(current_price);
    LEAVE (" ");
    return current_price;
}
PriceList* gnc_pricedb_lookup_latest_before_any_currency ( GNCPriceDB db,
gnc_commodity c,
Timespec  t 
)

gnc_pricedb_lookup_latest_before_any_currency - return recent prices that match the given commodity up to and including time t in any available currency. Prices will be returned as a GNCPrice list (see above).

Definition at line 1996 of file gnc-pricedb.c.

{
    GList *result = NULL;
    GHashTable *currency_hash;
    GNCPriceLookupHelper lookup_helper;
    QofBook *book;
    QofBackend *be;

    if (!db || !c) return NULL;
    ENTER ("db=%p commodity=%p", db, c);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_LATEST_BEFORE;
        pl.prdb = db;
        pl.commodity = c;
        pl.currency = NULL;  /* can the backend handle this??? */
        pl.date = t;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    lookup_helper.return_list = &result;
    lookup_helper.time = t;
    g_hash_table_foreach(currency_hash, lookup_latest_before, &lookup_helper);

    if (!result)
    {
        LEAVE (" ");
        return NULL;
    }

    result = g_list_sort(result, compare_prices_by_date);

    LEAVE (" ");
    return result;
}
GNCPrice* gnc_pricedb_lookup_nearest_in_time ( GNCPriceDB db,
const gnc_commodity c,
const gnc_commodity currency,
Timespec  t 
)

gnc_pricedb_lookup_nearest_in_time - return the price for the given commodity in the given currency nearest to the given time t.

Definition at line 1691 of file gnc-pricedb.c.

{
    GList *price_list;
    GNCPrice *current_price = NULL;
    GNCPrice *next_price = NULL;
    GNCPrice *result = NULL;
    GList *item = NULL;
    GHashTable *currency_hash;
    QofBook *book;
    QofBackend *be;

    if (!db || !c || !currency) return NULL;
    ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_NEAREST_IN_TIME;
        pl.prdb = db;
        pl.commodity = c;
        pl.currency = currency;
        pl.date = t;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
    if (!currency_hash)
    {
        LEAVE ("no currency hash");
        return NULL;
    }

    price_list = g_hash_table_lookup(currency_hash, currency);
    if (!price_list)
    {
        LEAVE ("no 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);

            /* Choose the price that is closest to the given time. In case of
             * a tie, prefer the older price since it actually existed at the
             * time. (This also fixes bug #541970.) */
            if (timespec_cmp(&abs_current, &abs_next) < 0)
            {
                result = current_price;
            }
            else
            {
                result = next_price;
            }
        }
    }

    gnc_price_ref(result);
    LEAVE (" ");
    return result;
}
PriceList* gnc_pricedb_lookup_nearest_in_time_any_currency ( GNCPriceDB db,
const gnc_commodity c,
Timespec  t 
)

gnc_pricedb_lookup_nearest_in_time_any_currency - return all prices that match the given commodity and timespec in any available currency. Prices will be returned as a GNCPrice list (see above).

Definition at line 1945 of file gnc-pricedb.c.

{
    GList *result = NULL;
    GHashTable *currency_hash;
    GNCPriceLookupHelper lookup_helper;
    QofBook *book;
    QofBackend *be;

    if (!db || !c) return NULL;
    ENTER ("db=%p commodity=%p", db, c);
    book = qof_instance_get_book(&db->inst);
    be = qof_book_get_backend(book);
#ifdef GNUCASH_MAJOR_VERSION
    if (be && be->price_lookup)
    {
        GNCPriceLookup pl;
        pl.type = LOOKUP_NEAREST_IN_TIME;
        pl.prdb = db;
        pl.commodity = c;
        pl.currency = NULL;  /* can the backend handle this??? */
        pl.date = t;
        (be->price_lookup) (be, &pl);
    }
#endif
    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
    if (!currency_hash)
    {
        LEAVE (" no currency hash");
        return NULL;
    }

    lookup_helper.return_list = &result;
    lookup_helper.time = t;
    g_hash_table_foreach(currency_hash, lookup_nearest, &lookup_helper);

    if (!result)
    {
        LEAVE (" ");
        return NULL;
    }

    result = g_list_sort(result, compare_prices_by_date);

    LEAVE (" ");
    return result;
}
void gnc_pricedb_print_contents ( GNCPriceDB db,
FILE *  f 
)

This simple function can be useful for debugging the pricedb code

Definition at line 2517 of file gnc-pricedb.c.

{
    if (!db)
    {
        PERR("NULL PriceDB\n");
        return;
    }
    if (!f)
    {
        PERR("NULL FILE*\n");
        return;
    }

    fprintf(f, "<gnc:pricedb>\n");
    gnc_pricedb_foreach_price(db, print_pricedb_adapter, f, FALSE);
    fprintf(f, "</gnc:pricedb>\n");
}
gboolean gnc_pricedb_remove_price ( GNCPriceDB db,
GNCPrice p 
)

gnc_pricedb_remove_price - removes the given price, p, from the pricedb. Returns TRUE if successful, FALSE otherwise.

Definition at line 1147 of file gnc-pricedb.c.

{
    gboolean rc;
    if (!db || !p) return FALSE;
    ENTER ("db=%p, pr=%p dirty=%d destroying=%d",
           db, p, qof_instance_get_dirty_flag(p),
           qof_instance_get_destroying(p));

    gnc_price_ref(p);
    rc = remove_price (db, p, TRUE);
    gnc_pricedb_begin_edit(db);
    qof_instance_set_dirty(&db->inst);
    gnc_pricedb_commit_edit(db);

    /* invoke the backend to delete this price */
    gnc_price_begin_edit (p);
    qof_instance_set_destroying(p, TRUE);
    gnc_price_commit_edit (p);
    p->db = NULL;
    gnc_price_unref(p);
    LEAVE ("db=%p, pr=%p", db, p);
    return rc;
}
void gnc_pricedb_set_bulk_update ( GNCPriceDB db,
gboolean  bulk_update 
)

Indicate whether or not the database is in the middle of a bulk update. Setting this flag will disable checks for duplicate entries.

Definition at line 833 of file gnc-pricedb.c.

{
    db->bulk_update = bulk_update;
}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines