* src/backend/postgres/txn.c: fix bugs restoring one transaction

from database.

* src/backend/postgres/putil.h: add EXEC_QUERY

* src/backend/postgres/price.h: add pgendGetCommodity

* src/backend/postgres/price.c: add pgendGetCommodity


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6391 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas
2001-12-19 11:39:57 +00:00
parent 5b18193b14
commit ee1d594ca4
4 changed files with 174 additions and 93 deletions

View File

@@ -57,22 +57,22 @@ static short module = MOD_BACKEND;
static gpointer
get_commodities_cb (PGBackend *be, PGresult *result, int j, gpointer data)
{
gnc_commodity_table *comtab = (gnc_commodity_table *) data;
gnc_commodity_table *comtab = data;
gnc_commodity *com;
/* first, lets see if we've already got this one */
com = gnc_commodity_table_lookup(comtab,
DB_GET_VAL("namespace",j), DB_GET_VAL("mnemonic",j));
DB_GET_VAL("namespace",j),
DB_GET_VAL("mnemonic",j));
if (com) return comtab;
/* no we don't ... restore it */
com = gnc_commodity_new (
DB_GET_VAL("fullname",j),
DB_GET_VAL("namespace",j),
DB_GET_VAL("mnemonic",j),
DB_GET_VAL("code",j),
atoi(DB_GET_VAL("fraction",j)));
com = gnc_commodity_new (DB_GET_VAL("fullname",j),
DB_GET_VAL("namespace",j),
DB_GET_VAL("mnemonic",j),
DB_GET_VAL("code",j),
atoi(DB_GET_VAL("fraction",j)));
gnc_commodity_table_insert (comtab, com);
return comtab;
@@ -101,6 +101,38 @@ pgendGetAllCommodities (PGBackend *be)
LEAVE (" ");
}
void
pgendGetCommodity (PGBackend *be, const char * unique_name)
{
gnc_commodity_table *comtab;
sqlEscape *escape;
char *p;
if (!be || !unique_name) return;
ENTER ("be=%p, conn=%p", be, be->connection);
comtab = gnc_book_get_commodity_table (be->book);
if (!comtab) {
PERR ("can't get commodity table");
return;
}
escape = sqlEscape_new ();
/* Get them ALL */
p = be->buff;
p = stpcpy (p, "SELECT * FROM gncCommodity WHERE gncCommodity.commodity='");
p = stpcpy (p, sqlEscapeString (escape, unique_name));
p = stpcpy (p, "';");
SEND_QUERY (be, be->buff, );
pgendGetResults (be, get_commodities_cb, comtab);
sqlEscape_destroy (escape);
LEAVE (" ");
}
/* ============================================================= */
/* ============================================================= */

View File

@@ -27,6 +27,7 @@
#include "PostgresBackend.h"
void pgendGetAllCommodities (PGBackend *be);
void pgendGetCommodity (PGBackend *be, const char * unique_name);
void pgendStorePriceDB (PGBackend *be, GNCPriceDB *prdb);
void pgendStorePriceDBNoLock (PGBackend *be, GNCPriceDB *prdb);
GNCPriceDB * pgendGetAllPrices (PGBackend *be, GNCPriceDB *prdb);

View File

@@ -154,6 +154,32 @@ gnc_commodity * gnc_string_to_commodity (const char *str, GNCBook *book);
} \
}
/* --------------------------------------------------------------- */
/* The EXEC_QUERY macro executes a query and returns the results
* and makes sure that no errors occured. Results are left
* in the result buffer.
*/
#define EXEC_QUERY(conn,buff,result) \
{ \
ExecStatusType status = 0; \
result = PQexec (conn, buff); \
if (result) \
status = PQresultStatus(result); \
if (!result || \
((PGRES_COMMAND_OK != status) && \
(PGRES_TUPLES_OK != status))) \
{ \
PERR("failed to get result to query:\n" \
"\t%s", PQerrorMessage((conn))); \
if (result) \
PQclear (result); \
result = NULL; \
PQfinish (conn); \
be->connection = NULL; \
xaccBackendSetError (&be->be, ERR_BACKEND_SERVER_ERR); \
} \
}
/* --------------------------------------------------------------- */
/* 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

View File

@@ -43,9 +43,10 @@
#include "Transaction.h"
#include "TransactionP.h"
#include "PostgresBackend.h"
#include "checkpoint.h"
#include "kvp-sql.h"
#include "PostgresBackend.h"
#include "price.h"
#include "txn.h"
#include "putil.h"
@@ -570,7 +571,7 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
PGresult *result;
gboolean do_set_guid=FALSE;
int engine_data_is_newer = 0;
int i, j, nrows;
int j;
GList *node, *engine_splits;
ENTER ("be=%p", be);
@@ -604,96 +605,102 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
/* build the sql query to get the transaction */
pbuff = be->buff;
pbuff[0] = 0;
pbuff = stpcpy (pbuff,
"SELECT * FROM gncTransaction WHERE transGuid='");
pbuff = stpcpy (pbuff, "SELECT * FROM gncTransaction WHERE transGuid='");
pbuff = guid_to_string_buff(trans_guid, pbuff);
pbuff = stpcpy (pbuff, "';");
SEND_QUERY (be,be->buff, 0);
i=0; nrows=0;
do {
GET_RESULTS (be->connection, result);
{
int jrows;
int ncols = PQnfields (result);
jrows = PQntuples (result);
nrows += jrows;
PINFO ("query result %d has %d rows and %d cols",
i, nrows, ncols);
EXEC_QUERY (be->connection, be->buff, result);
if (!result)
return 0;
j = 0;
if (0 == nrows)
{
PQclear (result);
/* I beleive its a programming error to get this case.
* Print a warning for now... */
PERR ("no such transaction in the database. This is unexpected ...\n");
xaccBackendSetError (&be->be, ERR_SQL_MISSING_DATA);
pgendEnable(be);
gnc_engine_resume_events();
return 0;
{
int ncols = PQnfields (result);
int nrows = PQntuples (result);
PINFO ("query result has %d rows and %d cols", nrows, ncols);
j = 0;
if (0 == nrows)
{
PQclear (result);
/* I beleive its a programming error to get this case.
* Print a warning for now... */
PERR ("no such transaction in the database. This is unexpected ...\n");
xaccBackendSetError (&be->be, ERR_SQL_MISSING_DATA);
pgendEnable(be);
gnc_engine_resume_events();
return 0;
}
if (1 < nrows)
{
/* since the guid is primary key, this error is totally
* and completely impossible, theoretically ... */
PERR ("!!!!!!!!!!!SQL database is corrupt!!!!!!!\n"
"too many transactions with GUID=%s\n",
guid_to_string (trans_guid));
xaccBackendSetError (&be->be, ERR_BACKEND_DATA_CORRUPT);
pgendEnable(be);
gnc_engine_resume_events();
return 0;
}
/* First order of business is to determine whose data is
* newer: the engine cache, or the database. If the
* database has newer stuff, we update the engine. If the
* engine is equal or newer, we do nothing in this routine.
* Of course, we know the database has newer data if this
* transaction doesn't exist in the engine yet.
*/
if (!do_set_guid)
{
gint32 db_version, cache_version;
db_version = atoi (DB_GET_VAL("version",j));
cache_version = xaccTransGetVersion (trans);
if (db_version == cache_version) {
engine_data_is_newer = 0;
} else
if (db_version < cache_version) {
engine_data_is_newer = +1;
} else {
engine_data_is_newer = -1;
}
}
if (1 < nrows)
{
/* since the guid is primary key, this error is totally
* and completely impossible, theoretically ... */
PERR ("!!!!!!!!!!!SQL database is corrupt!!!!!!!\n"
"too many transactions with GUID=%s\n",
guid_to_string (trans_guid));
if (jrows != nrows) xaccTransCommitEdit (trans);
xaccBackendSetError (&be->be, ERR_BACKEND_DATA_CORRUPT);
pgendEnable(be);
gnc_engine_resume_events();
return 0;
}
/* if the DB data is newer, copy it to engine */
if (0 > engine_data_is_newer)
{
Timespec ts;
gnc_commodity *currency;
/* First order of business is to determine whose data is
* newer: the engine cache, or the database. If the
* database has newer stuff, we update the engine. If the
* engine is equal or newer, we do nothing in this routine.
* Of course, we know the database has newer data if this
* transaction doesn't exist in the engine yet.
*/
if (!do_set_guid)
{
gint32 db_version, cache_version;
db_version = atoi (DB_GET_VAL("version",j));
cache_version = xaccTransGetVersion (trans);
if (db_version == cache_version) {
engine_data_is_newer = 0;
} else
if (db_version < cache_version) {
engine_data_is_newer = +1;
} else {
engine_data_is_newer = -1;
}
}
currency = gnc_string_to_commodity (DB_GET_VAL("currency",j), be->book);
if (!currency)
{
pgendGetCommodity (be, DB_GET_VAL("currency",j));
currency = gnc_string_to_commodity (DB_GET_VAL("currency",j),
be->book);
}
/* if the DB data is newer, copy it to engine */
if (0 > engine_data_is_newer)
{
Timespec ts;
gnc_commodity *currency;
if (!currency)
{
PERR ("currency not found: %s", DB_GET_VAL("currency",j));
}
xaccTransBeginEdit (trans);
if (do_set_guid) xaccTransSetGUID (trans, trans_guid);
xaccTransSetNum (trans, DB_GET_VAL("num",j));
xaccTransSetDescription (trans, DB_GET_VAL("description",j));
ts = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_posted",j));
xaccTransSetDatePostedTS (trans, &ts);
ts = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_entered",j));
xaccTransSetDateEnteredTS (trans, &ts);
xaccTransSetVersion (trans, atoi(DB_GET_VAL("version",j)));
currency = gnc_string_to_commodity (DB_GET_VAL("currency",j),
be->book);
xaccTransSetCurrency (trans, currency);
trans->idata = atoi(DB_GET_VAL("iguid",j));
}
}
PQclear (result);
i++;
} while (result);
xaccTransBeginEdit (trans);
if (do_set_guid) xaccTransSetGUID (trans, trans_guid);
xaccTransSetNum (trans, DB_GET_VAL("num",j));
xaccTransSetDescription (trans, DB_GET_VAL("description",j));
ts = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_posted",j));
xaccTransSetDatePostedTS (trans, &ts);
ts = gnc_iso8601_to_timespec_local (DB_GET_VAL("date_entered",j));
xaccTransSetDateEnteredTS (trans, &ts);
xaccTransSetVersion (trans, atoi(DB_GET_VAL("version",j)));
xaccTransSetCurrency (trans, currency);
trans->idata = atoi(DB_GET_VAL("iguid",j));
}
}
PQclear (result);
/* set timestamp as 'recent' for this data */
trans->version_check = be->version_check;
@@ -718,6 +725,12 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
if (0 != trans->idata)
{
if (!kvp_frame_is_empty (trans->kvp_data))
{
kvp_frame_delete (trans->kvp_data);
trans->kvp_data = kvp_frame_new ();
}
trans->kvp_data = pgendKVPFetch (be, trans->idata, trans->kvp_data);
}
@@ -727,6 +740,12 @@ pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid)
Split *s = node->data;
if (0 != s->idata)
{
if (!kvp_frame_is_empty (s->kvp_data))
{
kvp_frame_delete (s->kvp_data);
s->kvp_data = kvp_frame_new ();
}
s->kvp_data = pgendKVPFetch (be, s->idata, s->kvp_data);
}
}
@@ -890,7 +909,9 @@ pgend_trans_commit_edit (Backend * bend,
* and crashes. We've fixed the bugs, but ...
*/
char buf[80];
gnc_timespec_to_iso8601_buff (xaccTransRetDatePostedTS (trans), buf);
gnc_timespec_to_iso8601_buff (xaccTransRetDatePostedTS (trans),
buf);
PERR ("The impossible has happened, and thats not good!\n"
"\tThe SQL database contains an active transaction that\n"
"\talso appears in the audit trail as deleted !!\n"
@@ -945,7 +966,8 @@ pgend_trans_commit_edit (Backend * bend,
{
Split *s = (Split *) node->data;
Account *acc = xaccSplitGetAccount (s);
pgendAccountRecomputeOneCheckpoint (be, acc, trans->orig->date_posted);
pgendAccountRecomputeOneCheckpoint (be, acc,
trans->orig->date_posted);
}
/* set checkpoints for the new accounts */