mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
more database backend modifications
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2334 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -341,7 +341,7 @@ xaccSessionBeginFile (Session *sess, const char * filefrag)
|
||||
#ifdef SQLHACK
|
||||
/* for testing the sql, just a hack, remove later ... */
|
||||
/* this should never ever appear here ... */
|
||||
xaccSessionBeginSQL (sess, "gnc_bogus");
|
||||
xaccSessionBeginSQL (sess, "postgres://localhost/gnc_bogus");
|
||||
#endif
|
||||
|
||||
return (sess->topgroup);
|
||||
|
||||
@@ -139,7 +139,7 @@ static short module = MOD_BACKEND;
|
||||
*/
|
||||
|
||||
static void
|
||||
pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp)
|
||||
pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp, int update)
|
||||
{
|
||||
Account *parent;
|
||||
const char *parent_guid, *grp_guid;
|
||||
@@ -153,33 +153,89 @@ pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp)
|
||||
parent_guid = guid_to_string(xaccAccountGetGUID (parent));
|
||||
nacc = xaccGroupGetNumAccounts(grp);
|
||||
|
||||
for (i=0; i<nacc; i++) {
|
||||
Account *acc = xaccGroupGetAccount(grp, i);
|
||||
const char * acc_guid = guid_to_string(xaccAccountGetGUID (acc));
|
||||
|
||||
if (update) {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"UPDATE gncGroup SET "
|
||||
"parentGuid ='%s' "
|
||||
"WHERE"
|
||||
"groupGuid='%s';",
|
||||
parent_guid,
|
||||
grp_guid
|
||||
);
|
||||
} else {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"INSERT INTO gncGroup "
|
||||
"(groupGuid, parentGuid, childGuid)"
|
||||
"(groupGuid, parentGuid)"
|
||||
" values "
|
||||
"('%s', '%s', '%s');",
|
||||
"('%s', '%s');",
|
||||
grp_guid,
|
||||
parent_guid,
|
||||
acc_guid
|
||||
parent_guid
|
||||
);
|
||||
|
||||
free ((char *) acc_guid);
|
||||
SEND_QUERY(be);
|
||||
|
||||
/* complete/commit the transaction, check the status */
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
free ((char *) grp_guid);
|
||||
free ((char *) parent_guid);
|
||||
|
||||
SEND_QUERY(be);
|
||||
|
||||
/* complete/commit the transaction, check the status */
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
LEAVE ("\n");
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* this routine routine returns non-zero if the indicated group
|
||||
* differs from that in the SQL database.
|
||||
* this routine grabs no locks.
|
||||
*/
|
||||
|
||||
static int
|
||||
pgendCompareOneGroupOnly (PGBackend *be, AccountGroup *grp)
|
||||
{
|
||||
const char *grp_guid;
|
||||
PGresult *result;
|
||||
int i=0, nrows=0, ndiffs=0;
|
||||
|
||||
ENTER ("be=%p, grp=%p\n", be, grp);
|
||||
if (!be || !grp) return;
|
||||
|
||||
grp_guid = guid_to_string(xaccGroupGetGUID (grp));
|
||||
|
||||
/* try to find this group in the database */
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"SELECT parentGuid "
|
||||
"FROM gncGroup "
|
||||
"WHERE groupGuid = '%s';",
|
||||
grp_guid
|
||||
);
|
||||
free ((char *) grp_guid);
|
||||
|
||||
/* hack alert -- if error occurs here, what is the return value ???? */
|
||||
SEND_QUERY (be);
|
||||
|
||||
i=0; nrows=0;
|
||||
do {
|
||||
GET_RESULTS (be->connection, result);
|
||||
IF_ONE_ROW (result, nrows, i) {
|
||||
|
||||
/* compared queried values to input values */
|
||||
COMP_GUID ("parentGuid",
|
||||
xaccAccountGetGUID (xaccGroupGetParentAccount(grp)), ndiffs);
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
i++;
|
||||
} while (result);
|
||||
|
||||
if (0 == nrows) ndiffs = -1;
|
||||
|
||||
LEAVE ("\n");
|
||||
return ndiffs;
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine stores the indicated account structure into the database.
|
||||
* It does *not* chase pointers, traverse the tree, etc.
|
||||
@@ -528,8 +584,9 @@ pgendCompareOneSplitOnly (PGBackend *be, Split *split)
|
||||
xaccTransGetGUID (xaccSplitGetParent(split)), ndiffs);
|
||||
|
||||
/* hack alert -- need to also compare recconcile flag, amount, and price */
|
||||
PINFO ("recn=%s amt=%s price=%s\n", GETV("reconciled"), GETV("amount"),
|
||||
GETV("share_price"));
|
||||
PINFO ("recn=%s amt=%s price=%s\n", GET_DB_VAL("reconciled"),
|
||||
GET_DB_VAL("amount"),
|
||||
GET_DB_VAL("share_price"));
|
||||
/*
|
||||
xaccSplitGetReconcile(split),
|
||||
xaccSplitGetShareAmount(split),
|
||||
@@ -549,9 +606,12 @@ GETV("share_price"));
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine traverses the account structure and stores/updates
|
||||
* it in the database. If checks the account parents as well,
|
||||
* updating those.
|
||||
/* This routine updates the account structure if needed, and/or
|
||||
* stores it the first time if it hasn't yet been stored.
|
||||
* Note that it sets a mark to avoid excessive recursion:
|
||||
* This routine shouldn't be used outside of locks,
|
||||
where the recursion prevention clears the marks ...
|
||||
ah hell. this is a bad idea maybe ....
|
||||
*/
|
||||
|
||||
static void
|
||||
@@ -561,11 +621,14 @@ pgendStoreAccount (PGBackend *be, Account *acct)
|
||||
|
||||
if (!be || !acct) return;
|
||||
|
||||
/* hack alert -- because this query is potentially quite
|
||||
heavy-hitting to the database, and also because it will probably be
|
||||
performed redundantly, we should use a check-flag to mark this accountas
|
||||
having been checked already. The check-flag should be zeroed after
|
||||
things get unlocked */
|
||||
/* Check to see if we've processed this account recently.
|
||||
* If so, then return. The goal here is to avoid excess
|
||||
* hits to the database, leading to poor performance.
|
||||
* Note that this marking makes this routine unsafe to use
|
||||
* outside a lock (since we never clear the mark)
|
||||
*/
|
||||
if (xaccAccountGetMark (acct)) return;
|
||||
xaccAccountSetMark (acct, 1);
|
||||
|
||||
ndiffs = pgendCompareOneAccountOnly (be, acct);
|
||||
|
||||
@@ -574,8 +637,6 @@ things get unlocked */
|
||||
/* insert account if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneAccountOnly (be, acct, 0);
|
||||
|
||||
/* hack alert -- walk over tree of parents, children */
|
||||
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
@@ -592,12 +653,12 @@ pgendStoreTransaction (PGBackend *be, Transaction *trans)
|
||||
|
||||
if (!be || !trans) return;
|
||||
|
||||
ndiffs = pgendCompareOneTransOnly (be, trans);
|
||||
ndiffs = pgendCompareOneTransactionOnly (be, trans);
|
||||
|
||||
/* update transaction if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneTransOnly (be, trans, 1);
|
||||
if (0<ndiffs) pgendStoreOneTransactionOnly (be, trans, 1);
|
||||
/* insert trans if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneTransOnly (be, trans, 0);
|
||||
if (0>ndiffs) pgendStoreOneTransactionOnly (be, trans, 0);
|
||||
|
||||
/* walk over the list of splits */
|
||||
nsplits = xaccTransCountSplits (trans);
|
||||
@@ -625,6 +686,11 @@ pgendStoreTransaction (PGBackend *be, Transaction *trans)
|
||||
static int
|
||||
traverse_cb (Transaction *trans, void *cb_data)
|
||||
{
|
||||
/* clear marks .. is this a good thing to do here ???
|
||||
* hack alert rexaminte this issue .. */
|
||||
Split * s = xaccTransGetSplit (trans, 0);
|
||||
Account * acc = xaccSplitGetAccount (s);
|
||||
xaccClearMark (acc, 0);
|
||||
pgendStoreTransaction ((PGBackend *) cb_data, trans);
|
||||
return 0;
|
||||
}
|
||||
@@ -632,12 +698,16 @@ traverse_cb (Transaction *trans, void *cb_data)
|
||||
static void
|
||||
pgendStoreGroupNoLock (PGBackend *be, AccountGroup *grp)
|
||||
{
|
||||
int i, nacc;
|
||||
int i, nacc, ndiffs;
|
||||
|
||||
if (!be || !grp) return;
|
||||
|
||||
/* first, store the top-group */
|
||||
pgendStoreOneGroupOnly (be, grp);
|
||||
ndiffs = pgendCompareOneGroupOnly (be, grp);
|
||||
/* update group if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneGroupOnly (be, grp, 1);
|
||||
/* insert group if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneGroupOnly (be, grp, 0);
|
||||
|
||||
/* next, walk the account tree, and store subaccounts */
|
||||
nacc = xaccGroupGetNumAccounts(grp);
|
||||
@@ -670,6 +740,10 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp)
|
||||
SEND_QUERY (be);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
/* clear the account marks; useful later to avoid recurision
|
||||
* during account consistency checks. */
|
||||
xaccClearMarkDownGr (grp, 0);
|
||||
|
||||
/* reset the write flags. We use this to amek sure we don't
|
||||
* get caught in infinite recursion */
|
||||
xaccGroupBeginStagedTransactionTraversals(grp);
|
||||
@@ -678,6 +752,8 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp)
|
||||
/* recursively walk transactions */
|
||||
xaccGroupStagedTransactionTraversal (grp, 1, traverse_cb, be);
|
||||
|
||||
xaccClearMarkDownGr (grp, 0);
|
||||
|
||||
snprintf (be->buff, be->bufflen, "COMMIT;");
|
||||
SEND_QUERY (be);
|
||||
FINISH_QUERY(be->connection);
|
||||
@@ -687,6 +763,7 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp)
|
||||
/* this routine fills in the structure pointed at by split
|
||||
* with data sucked out of the database. It does only that
|
||||
* one split,
|
||||
* hack alert unfinished, incom[plete
|
||||
*/
|
||||
|
||||
static void
|
||||
@@ -724,7 +801,10 @@ pgend_session_begin (Session *sess, const char * sessionid)
|
||||
ENTER("sessionid=%s\n", sessionid);
|
||||
/* connect to a bogus database ... */
|
||||
/* hack alert -- we should be parsing the sessionid for the
|
||||
* hostname, port number, db name, etc... clean this up ... */
|
||||
* hostname, port number, db name, etc... clean this up ...
|
||||
* format should be something like
|
||||
* postgres://some.host.com:portno/db_name
|
||||
*/
|
||||
be->dbName = strdup ("gnc_bogus");
|
||||
be->connection = PQsetdbLogin (NULL, NULL, NULL, NULL, be->dbName, NULL, NULL);
|
||||
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
-- each child of a group will have its own record.
|
||||
DROP TABLE gncGroup;
|
||||
CREATE TABLE gncGroup (
|
||||
groupGuid CHAR(32),
|
||||
parentGuid CHAR(32),
|
||||
childGuid CHAR(32)
|
||||
groupGuid CHAR(32) PRIMARY KEY,
|
||||
parentGuid CHAR(32)
|
||||
);
|
||||
|
||||
-- hack alert -- docref ??
|
||||
|
||||
Reference in New Issue
Block a user