diff --git a/src/engine/sql/PostgresBackend.c b/src/engine/sql/PostgresBackend.c index 9896d91ea6..68bee1d5e3 100644 --- a/src/engine/sql/PostgresBackend.c +++ b/src/engine/sql/PostgresBackend.c @@ -2,8 +2,9 @@ * PostgressBackend.c * * Implements the callbacks for the postgress backend. - * this is some seriously broken, poorly designed code. - * its meant to be a quiick hack just ot check things out. + * this is somewhat seriously broken, poorly designed code. + * its meant to be a quick hack just ot check things out. + * it needs extensive review and design checking * */ @@ -64,19 +65,20 @@ static void pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp) { Account *parent; - const GUID *parent_guid, *grp_guid; + const char *parent_guid, *grp_guid; int i, nacc; ENTER ("be=%p, grp=%p\n", be, grp); if (!be || !grp) return; - grp_guid = xaccGroupGetGUID (grp); + grp_guid = guid_to_string(xaccGroupGetGUID (grp)); parent = xaccGroupGetParentAccount(grp); - parent_guid = xaccAccountGetGUID (parent); + parent_guid = guid_to_string(xaccAccountGetGUID (parent)); nacc = xaccGroupGetNumAccounts(grp); for (i=0; ibuff, be->bufflen, @@ -84,16 +86,19 @@ pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp) "(groupGuid, parentGuid, childGuid)" " values " "('%s', '%s', '%s');", - guid_to_string(grp_guid), - guid_to_string(parent_guid), - guid_to_string(xaccAccountGetGUID (acc)) + grp_guid, + parent_guid, + acc_guid ); + free ((char *) acc_guid); SEND_QUERY(be); /* complete/commit the transaction, check the status */ FLUSH(be->connection); } + free ((char *) grp_guid); + free ((char *) parent_guid); LEAVE ("\n"); } @@ -107,10 +112,14 @@ pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp) static void pgendStoreOneAccountOnly (PGBackend *be, Account *acct) { - + const char *acct_guid, *parent_guid, *child_guid; ENTER ("be=%p, acct=%p\n", be, acct); if (!be || !acct) return; + acct_guid = guid_to_string(xaccAccountGetGUID (acct)); + parent_guid = guid_to_string(xaccGroupGetGUID (xaccAccountGetParent(acct))); + child_guid = guid_to_string(xaccGroupGetGUID (xaccAccountGetChildren(acct))); + /* hack alert -- values should be escaped so that no '' apear in them */ snprintf (be->buff, be->bufflen, "INSERT INTO gncAccount " @@ -120,9 +129,9 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct) " values " "('%s', '%s', '%s', '%s', '%s', '%s', '%s', " "%d, '%s', '%s');", - guid_to_string(xaccAccountGetGUID (acct)), - guid_to_string(xaccGroupGetGUID (xaccAccountGetParent(acct))), - guid_to_string(xaccGroupGetGUID (xaccAccountGetChildren(acct))), + acct_guid, + parent_guid, + child_guid, xaccAccountGetName (acct), xaccAccountGetCode (acct), xaccAccountGetDescription (acct), @@ -131,6 +140,9 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct) xaccAccountGetCurrency (acct), xaccAccountGetSecurity (acct) ); + free ((char *) acct_guid); + free ((char *) parent_guid); + free ((char *) child_guid); SEND_QUERY (be); @@ -149,21 +161,25 @@ pgendStoreOneAccountOnly (PGBackend *be, Account *acct) static void pgendStoreOneTransactionOnly (PGBackend *be, Transaction *trans) { + const char * trans_guid; ENTER ("be=%p, trans=%p\n", be, trans); if (!be || !trans) return; + trans_guid = guid_to_string(xaccTransGetGUID (trans)); /* hack alert -- values should be escaped so that no '' apear in them */ snprintf (be->buff, be->bufflen, "INSERT INTO gncTransaction " "(transGuid, num, description)" " values " "('%s', '%s', '%s');", - guid_to_string(xaccTransGetGUID (trans)), + trans_guid, xaccTransGetNum (trans), xaccTransGetDescription (trans) ); + free ((char *) trans_guid); + SEND_QUERY (be); /* complete/commit the transaction, check the status */ @@ -180,10 +196,15 @@ static void pgendStoreOneSplitOnly (PGBackend *be, Split *split) { Timespec ts; + const char *split_guid, *acct_guid, *trans_guid; ENTER ("be=%p, split=%p\n", be, split); if (!be || !split) return; + split_guid = guid_to_string(xaccSplitGetGUID (split)); + acct_guid = guid_to_string(xaccAccountGetGUID (xaccSplitGetAccount(split))); + trans_guid = guid_to_string(xaccTransGetGUID (xaccSplitGetParent(split))); + /* hack alert date is not stored ... */ xaccSplitGetDateReconciledTS (split, &ts); @@ -194,15 +215,18 @@ pgendStoreOneSplitOnly (PGBackend *be, Split *split) "reconciled, amount, share_price)" " values " "('%s', '%s', '%s', '%s', '%s', '%c', %g, %g);", - guid_to_string(xaccSplitGetGUID (split)), - guid_to_string(xaccAccountGetGUID (xaccSplitGetAccount(split))), - guid_to_string(xaccTransGetGUID (xaccSplitGetParent(split))), + split_guid, + acct_guid, + trans_guid, xaccSplitGetMemo(split), xaccSplitGetAction(split), xaccSplitGetReconcile(split), xaccSplitGetShareAmount(split), xaccSplitGetSharePrice(split) ); + free ((char *) split_guid); + free ((char *) acct_guid); + free ((char *) trans_guid); SEND_QUERY (be); @@ -212,6 +236,106 @@ pgendStoreOneSplitOnly (PGBackend *be, Split *split) LEAVE ("\n"); } +/* ============================================================= */ +/* this routine routine returns non-zero if the indicated split + * differs fropm that in the SQL database. + * this routine grabs no locks. + */ + +static int +pgendCompareOneSplitOnly (PGBackend *be, Split *split) +{ + const char *split_guid; + PGresult *result; + int i, nrows, ncols, ndiffs=0; + + ENTER ("be=%p, split=%p\n", be, split); + if (!be || !split) return; + + split_guid = guid_to_string(xaccSplitGetGUID (split)); + + /* try to find this split in the database */ + /* hack alert -- values should be escaped so that no '' apear in them */ + snprintf (be->buff, be->bufflen, + "SELECT accountGuid, transGuid, memo, action, " + "reconciled, amount, share_price " + "FROM gncEntry " + "WHERE entryGuid = '%s';", + split_guid + ); + free ((char *) split_guid); + + 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); } + + /* compared queried values to input values */ + COMP ("memo", xaccSplitGetMemo(split)); + COMP ("action", xaccSplitGetAction(split)); + GCOMP ("accountGuid", + xaccAccountGetGUID (xaccSplitGetAccount(split))); + GCOMP ("transGuid", + xaccTransGetGUID (xaccSplitGetParent(split))); + +PINFO ("recn=%s amt=%s price=%s\n", GETV("reconciled"), GETV("amount"), +GETV("share_price")); + } + + PQclear (result); + i++; + } while (result); + + if (0 == nrows) ndiffs = -1; + +/* + xaccSplitGetReconcile(split), + xaccSplitGetShareAmount(split), + xaccSplitGetSharePrice(split) +*/ + + + LEAVE ("\n"); + return ndiffs; +} + /* ============================================================= */ /* This routine traverses the group structure and stores it into * the database. The NoLock version doesn't lock up the tables. @@ -228,9 +352,11 @@ traverse_cb (Transaction *trans, void *cb_data) pgendStoreOneTransactionOnly (be, trans); /* walk over the list of splits */ - nsplits = xaccTransGetNumSplits (trans); + nsplits = xaccTransCountSplits (trans); for (i=0; idbName = strdup ("gnc_bogus"); be->connection = PQsetdbLogin (NULL, NULL, NULL, NULL, be->dbName, NULL, NULL); @@ -365,6 +493,8 @@ pgend_trans_commit_edit (Backend * bend, Transaction * trans) nsplits = xaccTransCountSplits (trans); for (i=0; i