mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
add more update handling
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2332 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
19d7265ab1
commit
2590d21bcc
@ -23,8 +23,12 @@
|
||||
static short module = MOD_BACKEND;
|
||||
|
||||
/* ============================================================= */
|
||||
/* The SEND_QUERY macro sends the sql statement off to the server.
|
||||
* It performs a minimal check to see that the send succeeded.
|
||||
*/
|
||||
|
||||
#define SEND_QUERY(be) { \
|
||||
#define SEND_QUERY(be) \
|
||||
{ \
|
||||
int rc; \
|
||||
rc = PQsendQuery (be->connection, be->buff); \
|
||||
if (!rc) \
|
||||
@ -37,7 +41,15 @@ static short module = MOD_BACKEND;
|
||||
} \
|
||||
}
|
||||
|
||||
#define FLUSH(conn) { \
|
||||
/* --------------------------------------------------------------- */
|
||||
/* The FINISH_QUERY macro makes sure that the previously sent
|
||||
* query complete with no errors. It assumes that the query
|
||||
* is does not produce any results; if it did, those results are
|
||||
* discarded (only error conditions are checked for).
|
||||
*/
|
||||
|
||||
#define FINISH_QUERY(conn) \
|
||||
{ \
|
||||
PGresult *result; \
|
||||
/* complete/commit the transaction, check the status */ \
|
||||
do { \
|
||||
@ -55,6 +67,71 @@ static short module = MOD_BACKEND;
|
||||
} while (result); \
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* The GET_RESULTS macro grabs the result of an sSQL query off the
|
||||
* wire, and makes sure that no errors occured. Results are left
|
||||
* in the result buffer.
|
||||
*/
|
||||
#define GET_RESULTS(conn,result) \
|
||||
{ \
|
||||
ExecStatusType status; \
|
||||
result = PQgetResult (conn); \
|
||||
if (!result) break; \
|
||||
status = PQresultStatus(result); \
|
||||
if ((PGRES_COMMAND_OK != status) && \
|
||||
(PGRES_TUPLES_OK != status)) \
|
||||
{ \
|
||||
PERR ("failed to get result to query\n"); \
|
||||
PQclear (result); \
|
||||
/* hack alert need gentler, kinder error recovery */ \
|
||||
PQfinish (conn); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* The IF_ONE_ROW macro counts the number of rows returned by
|
||||
* a query, reports an error if there is more than one row, and
|
||||
* conditionally executes a block for the first row.
|
||||
*/
|
||||
|
||||
#define IF_ONE_ROW(result,nrows,loopcounter) \
|
||||
{ \
|
||||
int ncols = PQnfields (result); \
|
||||
nrows += PQntuples (result); \
|
||||
PINFO ("query result %d has %d rows and %d cols\n", \
|
||||
loopcounter, nrows, ncols); \
|
||||
} \
|
||||
if (1 < nrows) { \
|
||||
PERR ("unexpected duplicate records\n"); \
|
||||
break; \
|
||||
} else if (1 == nrows)
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* Some utility macros for comparing values returned from the
|
||||
* database to values in the engine structs.
|
||||
*/
|
||||
|
||||
#define GET_DB_VAL(str) (PQgetvalue (result, 0, PQfnumber (result, str)))
|
||||
|
||||
#define COMP_STR(sqlname,fun,ndiffs) { \
|
||||
if (strcmp (GET_DB_VAL(sqlname),fun)) { \
|
||||
PINFO("%s sql='%s', eng='%s'\n", sqlname, \
|
||||
GET_DB_VAL (sqlname), fun); \
|
||||
ndiffs++; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COMP_GUID(sqlname,fun, ndiffs) { \
|
||||
const char *tmp = guid_to_string(fun); \
|
||||
if (strcmp (GET_DB_VAL(sqlname),tmp)) { \
|
||||
PINFO("%s sql='%s', eng='%s'\n", sqlname, \
|
||||
GET_DB_VAL(sqlname), tmp); \
|
||||
ndiffs++; \
|
||||
} \
|
||||
free ((char *) tmp); \
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine stores the indicated group structure into the database.
|
||||
* It does *not* chase pointers, traverse the tree, etc.
|
||||
@ -95,7 +172,7 @@ pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp)
|
||||
SEND_QUERY(be);
|
||||
|
||||
/* complete/commit the transaction, check the status */
|
||||
FLUSH(be->connection);
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
free ((char *) grp_guid);
|
||||
free ((char *) parent_guid);
|
||||
@ -110,7 +187,7 @@ pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp)
|
||||
*/
|
||||
|
||||
static void
|
||||
pgendStoreOneAccountOnly (PGBackend *be, Account *acct)
|
||||
pgendStoreOneAccountOnly (PGBackend *be, Account *acct, int update)
|
||||
{
|
||||
const char *acct_guid, *parent_guid, *child_guid;
|
||||
ENTER ("be=%p, acct=%p\n", be, acct);
|
||||
@ -120,6 +197,26 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct)
|
||||
parent_guid = guid_to_string(xaccGroupGetGUID (xaccAccountGetParent(acct)));
|
||||
child_guid = guid_to_string(xaccGroupGetGUID (xaccAccountGetChildren(acct)));
|
||||
|
||||
if (update) {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"UPDATE gncAccount SET "
|
||||
"parentGuid='%s', childrenGuid='%s', "
|
||||
"accountName='%s', accountCode='%s', description='%s', "
|
||||
"notes='%s', type=%d, currency='%s', security='%s' "
|
||||
"WHERE accountGuid='%s';",
|
||||
parent_guid,
|
||||
child_guid,
|
||||
xaccAccountGetName (acct),
|
||||
xaccAccountGetCode (acct),
|
||||
xaccAccountGetDescription (acct),
|
||||
xaccAccountGetNotes (acct),
|
||||
xaccAccountGetType (acct),
|
||||
xaccAccountGetCurrency (acct),
|
||||
xaccAccountGetSecurity (acct),
|
||||
acct_guid
|
||||
);
|
||||
} else {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"INSERT INTO gncAccount "
|
||||
@ -140,6 +237,7 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct)
|
||||
xaccAccountGetCurrency (acct),
|
||||
xaccAccountGetSecurity (acct)
|
||||
);
|
||||
}
|
||||
free ((char *) acct_guid);
|
||||
free ((char *) parent_guid);
|
||||
free ((char *) child_guid);
|
||||
@ -147,11 +245,75 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct)
|
||||
SEND_QUERY (be);
|
||||
|
||||
/* complete/commit the transaction, check the status */
|
||||
FLUSH(be->connection);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
LEAVE ("\n");
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* this routine routine returns non-zero if the indicated acount
|
||||
* differs from that in the SQL database.
|
||||
* this routine grabs no locks.
|
||||
*/
|
||||
|
||||
static int
|
||||
pgendCompareOneAccountOnly (PGBackend *be, Account *acct)
|
||||
{
|
||||
const char *acct_guid;
|
||||
PGresult *result;
|
||||
int i=0, nrows=0, ndiffs=0;
|
||||
|
||||
ENTER ("be=%p, acct=%p\n", be, acct);
|
||||
if (!be || !acct) return;
|
||||
|
||||
acct_guid = guid_to_string(xaccAccountGetGUID (acct));
|
||||
|
||||
/* try to find this account in the database */
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"SELECT parentGuid, childrenGuid, accountName, accountCode, "
|
||||
"description, notes, type, currency, security "
|
||||
"FROM gncAccount "
|
||||
"WHERE accountGuid = '%s';",
|
||||
acct_guid
|
||||
);
|
||||
free ((char *) acct_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_STR ("accountName", xaccAccountGetName(acct), ndiffs);
|
||||
COMP_STR ("description", xaccAccountGetDescription(acct), ndiffs);
|
||||
COMP_STR ("notes", xaccAccountGetNotes(acct), ndiffs);
|
||||
COMP_STR ("currency", xaccAccountGetCurrency(acct), ndiffs);
|
||||
COMP_STR ("security", xaccAccountGetSecurity(acct), ndiffs);
|
||||
|
||||
COMP_GUID ("parentGuid",
|
||||
xaccGroupGetGUID (xaccAccountGetParent(acct)), ndiffs);
|
||||
COMP_GUID ("childrenGuid",
|
||||
xaccGroupGetGUID (xaccAccountGetChildren(acct)), ndiffs);
|
||||
|
||||
/* hack alert -- need to also do the account type */
|
||||
/* hack alert -- need to also do additional acct info for
|
||||
the specialty account types */
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
i++;
|
||||
} while (result);
|
||||
|
||||
if (0 == nrows) ndiffs = -1;
|
||||
|
||||
LEAVE ("\n");
|
||||
return ndiffs;
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine stores the indicated transaction structure into the database.
|
||||
* It does *not* chase pointers, traverse the tree, etc.
|
||||
@ -159,7 +321,7 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct)
|
||||
*/
|
||||
|
||||
static void
|
||||
pgendStoreOneTransactionOnly (PGBackend *be, Transaction *trans)
|
||||
pgendStoreOneTransactionOnly (PGBackend *be, Transaction *trans, int update)
|
||||
{
|
||||
const char * trans_guid;
|
||||
|
||||
@ -167,6 +329,18 @@ pgendStoreOneTransactionOnly (PGBackend *be, Transaction *trans)
|
||||
if (!be || !trans) return;
|
||||
|
||||
trans_guid = guid_to_string(xaccTransGetGUID (trans));
|
||||
|
||||
if (update) {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"UPDATE gncTransaction SET "
|
||||
"num='%s', description='%s' "
|
||||
"WHERE transGuid='%s';",
|
||||
xaccTransGetNum (trans),
|
||||
xaccTransGetDescription (trans),
|
||||
trans_guid
|
||||
);
|
||||
} else {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"INSERT INTO gncTransaction "
|
||||
@ -177,17 +351,71 @@ pgendStoreOneTransactionOnly (PGBackend *be, Transaction *trans)
|
||||
xaccTransGetNum (trans),
|
||||
xaccTransGetDescription (trans)
|
||||
);
|
||||
}
|
||||
|
||||
free ((char *) trans_guid);
|
||||
|
||||
SEND_QUERY (be);
|
||||
|
||||
/* complete/commit the transaction, check the status */
|
||||
FLUSH(be->connection);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
LEAVE ("\n");
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* this routine routine returns non-zero if the indicated transaction
|
||||
* differs from that in the SQL database.
|
||||
* this routine grabs no locks.
|
||||
*/
|
||||
|
||||
static int
|
||||
pgendCompareOneTransactionOnly (PGBackend *be, Transaction *trans)
|
||||
{
|
||||
const char *trans_guid;
|
||||
PGresult *result;
|
||||
int i=0, nrows=0, ndiffs=0;
|
||||
|
||||
ENTER ("be=%p, trans=%p\n", be, trans);
|
||||
if (!be || !trans) return;
|
||||
|
||||
trans_guid = guid_to_string(xaccTransGetGUID (trans));
|
||||
|
||||
/* try to find this transaction in the database */
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"SELECT transGuid, date_entered, date_posted, num, description "
|
||||
"FROM gncTransaction "
|
||||
"WHERE transGuid = '%s';",
|
||||
trans_guid
|
||||
);
|
||||
free ((char *) trans_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_STR ("num", xaccTransGetNum(trans), ndiffs);
|
||||
COMP_STR ("description", xaccTransGetDescription(trans), ndiffs);
|
||||
|
||||
/* hack alert -- need to also do the dates */
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
i++;
|
||||
} while (result);
|
||||
|
||||
if (0 == nrows) ndiffs = -1;
|
||||
|
||||
LEAVE ("\n");
|
||||
return ndiffs;
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* this routine stores the indicated split in the database
|
||||
*/
|
||||
@ -211,7 +439,7 @@ pgendStoreOneSplitOnly (PGBackend *be, Split *split, int update)
|
||||
if (update) {
|
||||
/* hack alert -- values should be escaped so that no '' apear in them */
|
||||
snprintf (be->buff, be->bufflen,
|
||||
"UPDATE gncEntry SET"
|
||||
"UPDATE gncEntry SET "
|
||||
"accountGuid='%s', transGuid='%s', memo='%s', action='%s', "
|
||||
"reconciled='%c', amount=%g, share_price=%g "
|
||||
"WHERE entryGuid='%s';",
|
||||
@ -249,14 +477,14 @@ pgendStoreOneSplitOnly (PGBackend *be, Split *split, int update)
|
||||
SEND_QUERY (be);
|
||||
|
||||
/* complete/commit the transaction, check the status */
|
||||
FLUSH(be->connection);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
LEAVE ("\n");
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* this routine routine returns non-zero if the indicated split
|
||||
* differs fropm that in the SQL database.
|
||||
* differs from that in the SQL database.
|
||||
* this routine grabs no locks.
|
||||
*/
|
||||
|
||||
@ -265,7 +493,7 @@ pgendCompareOneSplitOnly (PGBackend *be, Split *split)
|
||||
{
|
||||
const char *split_guid;
|
||||
PGresult *result;
|
||||
int i, nrows, ncols, ndiffs=0;
|
||||
int i=0, nrows=0, ndiffs=0;
|
||||
|
||||
ENTER ("be=%p, split=%p\n", be, split);
|
||||
if (!be || !split) return;
|
||||
@ -283,58 +511,31 @@ pgendCompareOneSplitOnly (PGBackend *be, Split *split)
|
||||
);
|
||||
free ((char *) split_guid);
|
||||
|
||||
/* hack alert -- if error occurs here, what is the return value ???? */
|
||||
SEND_QUERY (be);
|
||||
|
||||
i=0; nrows=0;
|
||||
do {
|
||||
ExecStatusType status;
|
||||
|
||||
result = PQgetResult (be->connection);
|
||||
if (!result) break;
|
||||
|
||||
status = PQresultStatus(result);
|
||||
|
||||
if ((PGRES_COMMAND_OK != status) &&
|
||||
(PGRES_TUPLES_OK != status))
|
||||
{
|
||||
PERR ("failed to get result to query\n");
|
||||
PQclear (result);
|
||||
/* hack alert need gentler, kinder error recovery */
|
||||
PQfinish (be->connection);
|
||||
break;
|
||||
}
|
||||
|
||||
nrows += PQntuples (result);
|
||||
ncols = PQnfields (result);
|
||||
|
||||
PINFO ("query result %d has %d rows and %d cols\n",
|
||||
i, nrows, ncols);
|
||||
if (1 < nrows) {
|
||||
PERR ("unexpected duplicate records\n");
|
||||
break;
|
||||
} else if (1 == nrows) {
|
||||
|
||||
#define GETV(str) (PQgetvalue (result, 0, PQfnumber (result, str)))
|
||||
#define COMP(sqlname,fun) if (strcmp (GETV(sqlname),fun)) { \
|
||||
PINFO("%s sql='%s', split='%s'\n", sqlname, GETV(sqlname), fun); \
|
||||
ndiffs++; }
|
||||
#define GCOMP(sqlname,fun) { \
|
||||
const char *tmp = guid_to_string(fun); \
|
||||
if (strcmp (GETV(sqlname),tmp)) { \
|
||||
PINFO("%s sql='%s', split='%s'\n", sqlname, GETV(sqlname), tmp); \
|
||||
ndiffs++; } \
|
||||
free ((char *) tmp); }
|
||||
GET_RESULTS (be->connection, result);
|
||||
IF_ONE_ROW (result, nrows, i) {
|
||||
|
||||
/* compared queried values to input values */
|
||||
COMP ("memo", xaccSplitGetMemo(split));
|
||||
COMP ("action", xaccSplitGetAction(split));
|
||||
GCOMP ("accountGuid",
|
||||
xaccAccountGetGUID (xaccSplitGetAccount(split)));
|
||||
GCOMP ("transGuid",
|
||||
xaccTransGetGUID (xaccSplitGetParent(split)));
|
||||
COMP_STR ("memo", xaccSplitGetMemo(split), ndiffs);
|
||||
COMP_STR ("action", xaccSplitGetAction(split), ndiffs);
|
||||
COMP_GUID ("accountGuid",
|
||||
xaccAccountGetGUID (xaccSplitGetAccount(split)), ndiffs);
|
||||
COMP_GUID ("transGuid",
|
||||
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"));
|
||||
/*
|
||||
xaccSplitGetReconcile(split),
|
||||
xaccSplitGetShareAmount(split),
|
||||
xaccSplitGetSharePrice(split)
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
@ -343,17 +544,79 @@ GETV("share_price"));
|
||||
|
||||
if (0 == nrows) ndiffs = -1;
|
||||
|
||||
/*
|
||||
xaccSplitGetReconcile(split),
|
||||
xaccSplitGetShareAmount(split),
|
||||
xaccSplitGetSharePrice(split)
|
||||
*/
|
||||
|
||||
|
||||
LEAVE ("\n");
|
||||
return ndiffs;
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine traverses the account structure and stores/updates
|
||||
* it in the database. If checks the account parents as well,
|
||||
* updating those.
|
||||
*/
|
||||
|
||||
static void
|
||||
pgendStoreAccount (PGBackend *be, Account *acct)
|
||||
{
|
||||
int i, ndiffs, nsplits;
|
||||
|
||||
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 */
|
||||
|
||||
ndiffs = pgendCompareOneAccountOnly (be, acct);
|
||||
|
||||
/* update account if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneAccountOnly (be, acct, 1);
|
||||
/* insert account if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneAccountOnly (be, acct, 0);
|
||||
|
||||
/* hack alert -- walk over tree of parents, children */
|
||||
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine traverses the transaction structure and stores/updates
|
||||
* it in the database. If checks the transaction splits as well,
|
||||
* updating those. Finally, it makes sure that each account is present
|
||||
* as well.
|
||||
*/
|
||||
|
||||
static void
|
||||
pgendStoreTransaction (PGBackend *be, Transaction *trans)
|
||||
{
|
||||
int i, ndiffs, nsplits;
|
||||
|
||||
if (!be || !trans) return;
|
||||
|
||||
ndiffs = pgendCompareOneTransOnly (be, trans);
|
||||
|
||||
/* update transaction if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneTransOnly (be, trans, 1);
|
||||
/* insert trans if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneTransOnly (be, trans, 0);
|
||||
|
||||
/* walk over the list of splits */
|
||||
nsplits = xaccTransCountSplits (trans);
|
||||
for (i=0; i<nsplits; i++) {
|
||||
Split * s = xaccTransGetSplit (trans, i);
|
||||
Account *acct = xaccSplitGetAccount (s);
|
||||
|
||||
ndiffs = pgendCompareOneSplitOnly (be, s);
|
||||
/* update split if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneSplitOnly (be, s, 1);
|
||||
/* insert split if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneSplitOnly (be, s, 0);
|
||||
|
||||
/* check to see if the account that this split references is in
|
||||
* storage; if not, add it */
|
||||
pgendStoreAccount (be, acct);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine traverses the group structure and stores it into
|
||||
* the database. The NoLock version doesn't lock up the tables.
|
||||
@ -362,24 +625,7 @@ GETV("share_price"));
|
||||
static int
|
||||
traverse_cb (Transaction *trans, void *cb_data)
|
||||
{
|
||||
PGBackend *be = (PGBackend *) cb_data;
|
||||
int i, nsplits;
|
||||
|
||||
if (!be || !trans) return;
|
||||
|
||||
pgendStoreOneTransactionOnly (be, trans);
|
||||
|
||||
/* walk over the list of splits */
|
||||
nsplits = xaccTransCountSplits (trans);
|
||||
for (i=0; i<nsplits; i++) {
|
||||
Split * s = xaccTransGetSplit (trans, i);
|
||||
int ndiffs = pgendCompareOneSplitOnly (be, s);
|
||||
/* update split if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneSplitOnly (be, s, 1);
|
||||
/* insert split if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneSplitOnly (be, s, 0);
|
||||
}
|
||||
|
||||
pgendStoreTransaction ((PGBackend *) cb_data, trans);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -399,7 +645,12 @@ pgendStoreGroupNoLock (PGBackend *be, AccountGroup *grp)
|
||||
for (i=0; i<nacc; i++) {
|
||||
AccountGroup *subgrp;
|
||||
Account *acc = xaccGroupGetAccount(grp, i);
|
||||
pgendStoreOneAccountOnly (be, acc);
|
||||
|
||||
int ndiffs = pgendCompareOneAccountOnly (be, acc);
|
||||
/* update account if there are differences ... */
|
||||
if (0<ndiffs) pgendStoreOneAccountOnly (be, acc, 1);
|
||||
/* insert account if it doesn't exist */
|
||||
if (0>ndiffs) pgendStoreOneAccountOnly (be, acc, 0);
|
||||
|
||||
/* recursively walk to child accounts */
|
||||
subgrp = xaccAccountGetChildren (acc);
|
||||
@ -417,7 +668,7 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp)
|
||||
/* lock it up so that we store atomically */
|
||||
snprintf (be->buff, be->bufflen, "BEGIN;");
|
||||
SEND_QUERY (be);
|
||||
FLUSH(be->connection);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
/* reset the write flags. We use this to amek sure we don't
|
||||
* get caught in infinite recursion */
|
||||
@ -429,7 +680,7 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp)
|
||||
|
||||
snprintf (be->buff, be->bufflen, "COMMIT;");
|
||||
SEND_QUERY (be);
|
||||
FLUSH(be->connection);
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
|
Loading…
Reference in New Issue
Block a user