diff --git a/src/engine/sql/PostgresBackend.c b/src/engine/sql/PostgresBackend.c index 7eeae18aab..e01b7b1636 100644 --- a/src/engine/sql/PostgresBackend.c +++ b/src/engine/sql/PostgresBackend.c @@ -826,7 +826,6 @@ pgendStoreAllTransactions (PGBackend *be, AccountGroup *grp) static int pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) { - gnc_commodity *modity=NULL; char *pbuff; Transaction *trans; PGresult *result; @@ -836,6 +835,8 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) int i, j, nrows; int save_state = 1; GList *node, *db_splits=NULL, *engine_splits, *delete_splits=NULL; + gnc_commodity *currency = NULL; + gint64 trans_frac = 0; ENTER ("be=%p", be); if (!be || !trans_guid) return 0; @@ -914,6 +915,7 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) if (0 > engine_data_is_newer) { Timespec ts; + xaccTransBeginEdit (trans); if (do_set_guid) xaccTransSetGUID (trans, trans_guid); xaccTransSetNum (trans, DB_GET_VAL("num",j)); @@ -929,7 +931,8 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) * the reporting currency in an account. This hack will be * obsolete when reporting currencies are removed from the * account. */ - modity = gnc_string_to_commodity (DB_GET_VAL("currency",j)); + currency = gnc_string_to_commodity (DB_GET_VAL("currency",j)); + trans_frac = gnc_commodity_get_fraction (currency); #if 0 xaccTransSetCurrency (trans, gnc_string_to_commodity (DB_GET_VAL("currency",j))); @@ -990,7 +993,7 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) Split *s; GUID guid; Timespec ts; - gint64 num, denom; + gint64 num; gnc_numeric value, amount; /* --------------------------------------------- */ @@ -1013,14 +1016,8 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) (DB_GET_VAL("date_reconciled",j)); xaccSplitSetDateReconciledTS (s, &ts); - num = atoll (DB_GET_VAL("amountNum", j)); - denom = atoll (DB_GET_VAL("amountDenom", j)); - amount = gnc_numeric_create (num, denom); - xaccSplitSetShareAmount (s, amount); - - num = atoll (DB_GET_VAL("valueNum", j)); - denom = atoll (DB_GET_VAL("valueDenom", j)); - value = gnc_numeric_create (num, denom); + num = atoll (DB_GET_VAL("value", j)); + value = gnc_numeric_create (num, trans_frac); xaccSplitSetValue (s, value); xaccSplitSetReconcile (s, (DB_GET_VAL("reconciled", j))[0]); @@ -1042,6 +1039,14 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) } else { + gnc_commodity *modity; + gint64 acct_frac; + num = atoll (DB_GET_VAL("amount", j)); + modity = xaccAccountGetCommodity (acc); + acct_frac = gnc_commodity_get_fraction (modity); + amount = gnc_numeric_create (num, acct_frac); + xaccSplitSetShareAmount (s, amount); + xaccTransAppendSplit (trans, s); if (acc != previous_acc) @@ -1107,7 +1112,7 @@ pgendCopyTransactionToEngine (PGBackend *be, GUID *trans_guid) /* ------------------------------------------------- */ /* see note above as to why we do this set here ... */ - xaccTransSetCurrency (trans, modity); + xaccTransSetCurrency (trans, currency); xaccTransCommitEdit (trans); diff --git a/src/engine/sql/checkpoint.c b/src/engine/sql/checkpoint.c index c12b8c15f7..077588764b 100644 --- a/src/engine/sql/checkpoint.c +++ b/src/engine/sql/checkpoint.c @@ -87,7 +87,7 @@ pgendAccountRecomputeAllCheckpoints (PGBackend *be, const GUID *acct_guid) /* and now, fetch *all* of the splits in this account */ p = be->buff; *p = 0; - p = stpcpy (p, "SELECT gncEntry.amountNum AS amountNum, " + p = stpcpy (p, "SELECT gncEntry.amount AS amount, " " gncEntry.reconciled AS reconciled," " gncTransaction.date_posted AS date_posted " "FROM gncEntry, gncTransaction " @@ -156,7 +156,7 @@ pgendAccountRecomputeAllCheckpoints (PGBackend *be, const GUID *acct_guid) nsplits ++; /* accumulate balances */ - amt = atoll (DB_GET_VAL("amountNum",j)); + amt = atoll (DB_GET_VAL("amount",j)); recn = (DB_GET_VAL("reconciled",j))[0]; bp->balance += amt; if (NREC != recn) @@ -238,9 +238,9 @@ pgendAccountGetCheckpoint (PGBackend *be, Checkpoint *chk) p = guid_to_string_buff (chk->account_guid, p); p = stpcpy (p, "' AND commodity='"); p = stpcpy (p, chk->commodity); - p = stpcpy (p, "' AND date_xpoint <'"); + p = stpcpy (p, "' AND date_start <'"); p = gnc_timespec_to_iso8601_buff (chk->datetime, p); - p = stpcpy (p, "' ORDER BY date_xpoint DESC LIMIT 1;"); + p = stpcpy (p, "' ORDER BY date_start DESC LIMIT 1;"); SEND_QUERY (be,be->buff, ); i=0; nrows=0; diff --git a/src/engine/sql/design.txt b/src/engine/sql/design.txt index 1c7a8a3e0f..7f85375c3e 100644 --- a/src/engine/sql/design.txt +++ b/src/engine/sql/design.txt @@ -137,7 +137,74 @@ an hour newer/older than the others, leading to bad updates). Balances -------- -UPDATE tx - SET (balance )= (SELECT expr from .... WHERE ) -WHERE txdate between today - 7 and today +Account balances can be computed using advanced SQL statements. +The basic idea looks like this: + + UPDATE checkpoint + SET balance = (SELECT sum(expr) from .... WHERE + txdate between today - 7 and today) + +The above is not a valid SQL statement; below is one that actually +works. Note that this statement updates *all* checkpoints for the +indicated accountguid. + + UPDATE gnccheckpoint + SET balance = (SELECT sum(gncentry.valuenum) + FROM gncentry, gnctransaction + WHERE + gncentry.accountguid = gnccheckpoint.accountguid AND + gncentry.transguid = gnctransaction.transguid AND + gnctransaction.date_posted BETWEEN date_xpoint AND + date_xpoint + 360 ) + WHERE accountguid='111'; + +Its a better to create a function that does the computation: + + CREATE FUNCTION gncsubtotal (char(32), datetime, datetime) + RETURNS numeric + AS 'SELECT sum(gncentry.valuenum) + FROM gncentry, gnctransaction + WHERE + gncentry.accountguid = $1 AND + gncentry.transguid = gnctransaction.transguid AND + gnctransaction.date_posted BETWEEN $2 AND $3' + LANGUAGE 'sql'; + +and use it like this: + + UPDATE gnccheckpoint + SET balance = (gncsubtotal ('4c9cad7be044559705988c63ea7affc5', + date_xpoint, date_xpoint + 360 )) + WHERE accountguid='111'; + + +---------------------------- +nothing but junk below/test demo + +CREATE FUNCTION gncsubtotal (char(32), datetime, datetime, int8) + RETURNS numeric + AS 'SELECT $4 * sum(gncentry.valuenum numeric/ gncentry.valuedenom +numeric ) + FROM gncentry, gnctransaction + WHERE + gncentry.accountguid = $1 AND + gncentry.transguid = gnctransaction.transguid AND + gnctransaction.date_posted BETWEEN $2 AND $3' + LANGUAGE 'sql'; + + +UPDATE gnccheckpoint + SET balance = (SELECT sum(gncentry.valuenum) +FROM gncentry, gnctransaction +WHERE +gncentry.accountguid = '4c9cad7be044559705988c63ea7affc5' AND +gncentry.transguid = gnctransaction.transguid AND +gnctransaction.date_posted BETWEEN date_xpoint AND +date_xpoint + 360 ) +WHERE accountguid='111'; + + + +INSERT INTO gnccheckpoint (accountguid, date_xpoint, commodity, balance) +VALUES (111, '1997-01-01 12:00:00-05', 'FLOOP::GLOP', 0); diff --git a/src/engine/sql/table-create.sql b/src/engine/sql/table-create.sql index acd0952db0..ea859dac25 100644 --- a/src/engine/sql/table-create.sql +++ b/src/engine/sql/table-create.sql @@ -80,10 +80,8 @@ CREATE TABLE gncEntry ( action TEXT, reconciled CHAR DEFAULT 'n', date_reconciled DATETIME, - amountNum INT8 DEFAULT '0', - amountDenom INT4 DEFAULT '100', - valueNum INT8 DEFAULT '0', - valueDenom INT4 DEFAULT '100' + amount INT8 DEFAULT '0', + value INT8 DEFAULT '0' ); CREATE INDEX gncEntry_acc_idx ON gncEntry (accountGuid); @@ -98,13 +96,14 @@ CREATE INDEX gncEntry_trn_idx ON gncEntry (transGuid); CREATE TABLE gncCheckpoint ( accountGuid CHAR(32) NOT NULL, - date_xpoint DATETIME NOT NULL, + date_start DATETIME NOT NULL, +-- date_end DATETIME NOT NULL, commodity TEXT NOT NULL CHECK (commodity <>''), balance INT8 DEFAULT '0', cleared_balance INT8 DEFAULT '0', reconciled_balance INT8 DEFAULT '0', - PRIMARY KEY (accountGuid, date_xpoint, commodity) + PRIMARY KEY (accountGuid, date_start, commodity) ); -- The price table stores the price of 'commodity' valued diff --git a/src/engine/sql/table.m4 b/src/engine/sql/table.m4 index 66300ea6f5..2395367790 100644 --- a/src/engine/sql/table.m4 +++ b/src/engine/sql/table.m4 @@ -25,10 +25,8 @@ define(`split', `gncEntry, Split, Split, action, , char *, xaccSplitGetAction(ptr), reconciled, , char, xaccSplitGetReconcile(ptr), date_reconciled, , Timespec, xaccSplitRetDateReconciledTS(ptr), - amountNum, , int64, gnc_numeric_num(xaccSplitGetShareAmount(ptr)), - amountDenom, , int64, gnc_numeric_denom(xaccSplitGetShareAmount(ptr)), - valueNum, , int64, gnc_numeric_num(xaccSplitGetValue(ptr)), - valueDenom, , int64, gnc_numeric_denom(xaccSplitGetValue(ptr)), + amount, , int64, gnc_numeric_num(xaccSplitGetShareAmount(ptr)), + value, , int64, gnc_numeric_num(xaccSplitGetValue(ptr)), entryGUID, KEY, GUID *, xaccSplitGetGUID(ptr), ') @@ -65,7 +63,7 @@ define(`checkpoint', `gncCheckpoint, Checkpoint, Checkpoint, balance, , int64, ptr->balance, cleared_balance, , int64, ptr->cleared_balance, reconciled_balance, , int64, ptr->reconciled_balance, - date_xpoint, , Timespec, ptr->datetime, + date_start, , Timespec, ptr->datetime, commodity, , char *, ptr->commodity, accountGuid, , GUID *, ptr->account_guid, ')