mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
with these patches, the sql backend is starting to work well.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3513 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
bb4dbf85dd
commit
eead62a8ce
@ -4,9 +4,8 @@
|
|||||||
*
|
*
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Implements the callbacks for the postgress backend.
|
* Implements the callbacks for the postgress backend.
|
||||||
* this is somewhat broken code.
|
* this is code kinda usually works.
|
||||||
* its a quick hack just to check things out.
|
* it needs review and design checking
|
||||||
* it needs extensive review and design checking
|
|
||||||
*
|
*
|
||||||
* HISTORY:
|
* HISTORY:
|
||||||
* Copyright (c) 2000, 2001 Linas Vepstas
|
* Copyright (c) 2000, 2001 Linas Vepstas
|
||||||
@ -24,6 +23,8 @@
|
|||||||
#include "BackendP.h"
|
#include "BackendP.h"
|
||||||
#include "Group.h"
|
#include "Group.h"
|
||||||
#include "gnc-book.h"
|
#include "gnc-book.h"
|
||||||
|
#include "gnc-commodity.h"
|
||||||
|
#include "gnc-engine.h"
|
||||||
#include "gnc-engine-util.h"
|
#include "gnc-engine-util.h"
|
||||||
#include "gnc-event.h"
|
#include "gnc-event.h"
|
||||||
#include "guid.h"
|
#include "guid.h"
|
||||||
@ -37,7 +38,6 @@
|
|||||||
|
|
||||||
static short module = MOD_BACKEND;
|
static short module = MOD_BACKEND;
|
||||||
|
|
||||||
|
|
||||||
static void pgendDisable (PGBackend *be);
|
static void pgendDisable (PGBackend *be);
|
||||||
static void pgendEnable (PGBackend *be);
|
static void pgendEnable (PGBackend *be);
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ static void pgendEnable (PGBackend *be);
|
|||||||
#define GET_DB_VAL(str,n) (PQgetvalue (result, n, PQfnumber (result, str)))
|
#define GET_DB_VAL(str,n) (PQgetvalue (result, n, PQfnumber (result, str)))
|
||||||
|
|
||||||
#define COMP_STR(sqlname,fun,ndiffs) { \
|
#define COMP_STR(sqlname,fun,ndiffs) { \
|
||||||
if (strcmp (GET_DB_VAL(sqlname,0),fun)) { \
|
if (null_strcmp (GET_DB_VAL(sqlname,0),fun)) { \
|
||||||
PINFO("%s sql='%s', eng='%s'", sqlname, \
|
PINFO("%s sql='%s', eng='%s'", sqlname, \
|
||||||
GET_DB_VAL (sqlname,0), fun); \
|
GET_DB_VAL (sqlname,0), fun); \
|
||||||
ndiffs++; \
|
ndiffs++; \
|
||||||
@ -143,7 +143,7 @@ static void pgendEnable (PGBackend *be);
|
|||||||
|
|
||||||
#define COMP_GUID(sqlname,fun, ndiffs) { \
|
#define COMP_GUID(sqlname,fun, ndiffs) { \
|
||||||
const char *tmp = guid_to_string(fun); \
|
const char *tmp = guid_to_string(fun); \
|
||||||
if (strcmp (GET_DB_VAL(sqlname,0),tmp)) { \
|
if (null_strcmp (GET_DB_VAL(sqlname,0),tmp)) { \
|
||||||
PINFO("%s sql='%s', eng='%s'", sqlname, \
|
PINFO("%s sql='%s', eng='%s'", sqlname, \
|
||||||
GET_DB_VAL(sqlname,0), tmp); \
|
GET_DB_VAL(sqlname,0), tmp); \
|
||||||
ndiffs++; \
|
ndiffs++; \
|
||||||
@ -177,6 +177,20 @@ static void pgendEnable (PGBackend *be);
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* a very special date comp */
|
||||||
|
#define COMP_NOW(sqlname,fun,ndiffs) { \
|
||||||
|
Timespec eng_time = xaccTransRetDateEnteredTS(ptr); \
|
||||||
|
Timespec sql_time = gnc_iso8601_to_timespec( \
|
||||||
|
GET_DB_VAL(sqlname,0)); \
|
||||||
|
if (eng_time.tv_sec != sql_time.tv_sec) { \
|
||||||
|
time_t tmp = eng_time.tv_sec; \
|
||||||
|
PINFO("%s sql='%s' eng=%s", sqlname, \
|
||||||
|
GET_DB_VAL(sqlname,0), ctime(&tmp)); \
|
||||||
|
ndiffs++; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define COMP_INT64(sqlname,fun,ndiffs) { \
|
#define COMP_INT64(sqlname,fun,ndiffs) { \
|
||||||
if (atoll (GET_DB_VAL(sqlname,0)) != fun) { \
|
if (atoll (GET_DB_VAL(sqlname,0)) != fun) { \
|
||||||
PINFO("%s sql='%s', eng='%lld'", sqlname, \
|
PINFO("%s sql='%s', eng='%lld'", sqlname, \
|
||||||
@ -184,10 +198,41 @@ static void pgendEnable (PGBackend *be);
|
|||||||
ndiffs++; \
|
ndiffs++; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define COMP_INT32(sqlname,fun,ndiffs) { \
|
||||||
|
if (atol (GET_DB_VAL(sqlname,0)) != fun) { \
|
||||||
|
PINFO("%s sql='%s', eng='%d'", sqlname, \
|
||||||
|
GET_DB_VAL (sqlname,0), fun); \
|
||||||
|
ndiffs++; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
||||||
#include "tmp.c"
|
#include "tmp.c"
|
||||||
|
|
||||||
|
/* ============================================================= */
|
||||||
|
/* This routine updates the commodity structure if needed, and/or
|
||||||
|
* stores it the first time if it hasn't yet been stored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
pgendStoreCommodityNoLock (PGBackend *be, const gnc_commodity *com)
|
||||||
|
{
|
||||||
|
gnc_commodity *commie = (gnc_commodity *) com;
|
||||||
|
int ndiffs;
|
||||||
|
if (!be || !com) return;
|
||||||
|
|
||||||
|
ndiffs = pgendCompareOnegnc_commodityOnly (be, commie);
|
||||||
|
|
||||||
|
/* update commodity if there are differences ... */
|
||||||
|
if (0<ndiffs) pgendStoreOnegnc_commodityOnly (be, commie, SQL_UPDATE);
|
||||||
|
/* insert commodity if it doesn't exist */
|
||||||
|
if (0>ndiffs) pgendStoreOnegnc_commodityOnly (be, commie, SQL_INSERT);
|
||||||
|
|
||||||
|
LEAVE(" ");
|
||||||
|
}
|
||||||
|
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
/* This routine updates the account structure if needed, and/or
|
/* This routine updates the account structure if needed, and/or
|
||||||
* stores it the first time if it hasn't yet been stored.
|
* stores it the first time if it hasn't yet been stored.
|
||||||
@ -200,6 +245,7 @@ static void
|
|||||||
pgendStoreAccountNoLock (PGBackend *be, Account *acct,
|
pgendStoreAccountNoLock (PGBackend *be, Account *acct,
|
||||||
gboolean do_mark)
|
gboolean do_mark)
|
||||||
{
|
{
|
||||||
|
const gnc_commodity *com;
|
||||||
int ndiffs;
|
int ndiffs;
|
||||||
|
|
||||||
if (!be || !acct) return;
|
if (!be || !acct) return;
|
||||||
@ -223,6 +269,11 @@ pgendStoreAccountNoLock (PGBackend *be, Account *acct,
|
|||||||
if (0<ndiffs) pgendStoreOneAccountOnly (be, acct, SQL_UPDATE);
|
if (0<ndiffs) pgendStoreOneAccountOnly (be, acct, SQL_UPDATE);
|
||||||
/* insert account if it doesn't exist */
|
/* insert account if it doesn't exist */
|
||||||
if (0>ndiffs) pgendStoreOneAccountOnly (be, acct, SQL_INSERT);
|
if (0>ndiffs) pgendStoreOneAccountOnly (be, acct, SQL_INSERT);
|
||||||
|
|
||||||
|
/* make sure the account's commodity is in the commodity table */
|
||||||
|
com = xaccAccountGetCurrency (acct);
|
||||||
|
pgendStoreCommodityNoLock (be, com);
|
||||||
|
|
||||||
LEAVE(" ");
|
LEAVE(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +447,8 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid)
|
|||||||
Account *acc, *previous_acc=NULL;
|
Account *acc, *previous_acc=NULL;
|
||||||
gboolean do_set_guid=FALSE;
|
gboolean do_set_guid=FALSE;
|
||||||
gboolean engine_data_is_newer = FALSE;
|
gboolean engine_data_is_newer = FALSE;
|
||||||
int i, nrows;
|
int i, j, nrows;
|
||||||
|
GList *node, *db_splits=NULL, *engine_splits, *delete_splits=NULL;
|
||||||
|
|
||||||
ENTER ("be=%p", be);
|
ENTER ("be=%p", be);
|
||||||
if (!be || !trans_guid) return;
|
if (!be || !trans_guid) return;
|
||||||
@ -428,10 +480,11 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid)
|
|||||||
do {
|
do {
|
||||||
GET_RESULTS (be->connection, result);
|
GET_RESULTS (be->connection, result);
|
||||||
{
|
{
|
||||||
int j=0, jrows;
|
int jrows;
|
||||||
int ncols = PQnfields (result);
|
int ncols = PQnfields (result);
|
||||||
jrows = PQntuples (result);
|
jrows = PQntuples (result);
|
||||||
nrows += jrows;
|
nrows += jrows;
|
||||||
|
j = 0;
|
||||||
PINFO ("query result %d has %d rows and %d cols",
|
PINFO ("query result %d has %d rows and %d cols",
|
||||||
i, nrows, ncols);
|
i, nrows, ncols);
|
||||||
|
|
||||||
@ -546,10 +599,6 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid)
|
|||||||
s = xaccMallocSplit();
|
s = xaccMallocSplit();
|
||||||
xaccSplitSetGUID(s, &guid);
|
xaccSplitSetGUID(s, &guid);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
PERR ("split already exists ... - implement me ..");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* next, restore some split data */
|
/* next, restore some split data */
|
||||||
/* hack alert - not all split fields handled */
|
/* hack alert - not all split fields handled */
|
||||||
@ -591,6 +640,11 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid)
|
|||||||
}
|
}
|
||||||
xaccAccountInsertSplit(acc, s);
|
xaccAccountInsertSplit(acc, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
/* finally tally them up; we use this below to clean
|
||||||
|
* out deleted splits */
|
||||||
|
db_splits = g_list_prepend (db_splits, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (result);
|
} while (result);
|
||||||
@ -598,6 +652,28 @@ pgendSyncTransaction (PGBackend *be, GUID *trans_guid)
|
|||||||
/* close out dangling edit session */
|
/* close out dangling edit session */
|
||||||
xaccAccountCommitEdit (previous_acc);
|
xaccAccountCommitEdit (previous_acc);
|
||||||
|
|
||||||
|
i=0; j=0;
|
||||||
|
engine_splits = xaccTransGetSplitList(trans);
|
||||||
|
for (node = engine_splits; node; node=node->next)
|
||||||
|
{
|
||||||
|
/* if not found, mark for deletion */
|
||||||
|
if (NULL == g_list_find (db_splits, node->data))
|
||||||
|
{
|
||||||
|
delete_splits = g_list_prepend (delete_splits, node->data);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
PINFO ("%d of %d splits marked for deletion", j, i);
|
||||||
|
|
||||||
|
/* now, delete them ... */
|
||||||
|
for (node=delete_splits; node; node=node->next)
|
||||||
|
{
|
||||||
|
xaccSplitDestroy ((Split *) node->data);
|
||||||
|
}
|
||||||
|
g_list_free (delete_splits);
|
||||||
|
g_list_free (db_splits);
|
||||||
|
|
||||||
xaccTransCommitEdit (trans);
|
xaccTransCommitEdit (trans);
|
||||||
|
|
||||||
/* reneable events to the backend and GUI */
|
/* reneable events to the backend and GUI */
|
||||||
@ -653,7 +729,7 @@ pgendGetAllAccounts (PGBackend *be)
|
|||||||
GUID guid;
|
GUID guid;
|
||||||
|
|
||||||
/* first, lets see if we've already got this one */
|
/* first, lets see if we've already got this one */
|
||||||
PINFO ("account GUID=%s\n", GET_DB_VAL("accountGUID",j));
|
PINFO ("account GUID=%s", GET_DB_VAL("accountGUID",j));
|
||||||
guid = nullguid; /* just in case the read fails ... */
|
guid = nullguid; /* just in case the read fails ... */
|
||||||
string_to_guid (GET_DB_VAL("accountGUID",j), &guid);
|
string_to_guid (GET_DB_VAL("accountGUID",j), &guid);
|
||||||
acc = (Account *) xaccLookupEntity (&guid, GNC_ID_ACCOUNT);
|
acc = (Account *) xaccLookupEntity (&guid, GNC_ID_ACCOUNT);
|
||||||
@ -668,8 +744,27 @@ pgendGetAllAccounts (PGBackend *be)
|
|||||||
xaccAccountSetDescription(acc, GET_DB_VAL("description",j));
|
xaccAccountSetDescription(acc, GET_DB_VAL("description",j));
|
||||||
xaccAccountSetCode(acc, GET_DB_VAL("accountCode",j));
|
xaccAccountSetCode(acc, GET_DB_VAL("accountCode",j));
|
||||||
xaccAccountSetType(acc, xaccAccountStringToEnum(GET_DB_VAL("type",j)));
|
xaccAccountSetType(acc, xaccAccountStringToEnum(GET_DB_VAL("type",j)));
|
||||||
|
|
||||||
|
/* hop through a couple of hoops for the commodity */
|
||||||
|
/* it would be nice to simplify this ... */
|
||||||
|
{
|
||||||
|
gnc_commodity_table *comtab;
|
||||||
|
gnc_commodity *com;
|
||||||
|
char *str, *name;
|
||||||
|
|
||||||
|
str = g_strdup(GET_DB_VAL("commodity",j));
|
||||||
|
name = strchr (str, ':');
|
||||||
|
*name = 0;
|
||||||
|
name += 2;
|
||||||
|
|
||||||
|
comtab = gnc_engine_commodities();
|
||||||
|
com = gnc_commodity_table_lookup(comtab, str, name);
|
||||||
|
xaccAccountSetCommodity(acc, com);
|
||||||
|
g_free (str);
|
||||||
|
}
|
||||||
|
|
||||||
/* try to find the parent account */
|
/* try to find the parent account */
|
||||||
PINFO ("parent GUID=%s\n", GET_DB_VAL("parentGUID",j));
|
PINFO ("parent GUID=%s", GET_DB_VAL("parentGUID",j));
|
||||||
guid = nullguid; /* just in case the read fails ... */
|
guid = nullguid; /* just in case the read fails ... */
|
||||||
string_to_guid (GET_DB_VAL("parentGUID",j), &guid);
|
string_to_guid (GET_DB_VAL("parentGUID",j), &guid);
|
||||||
if (guid_equal(xaccGUIDNULL(), &guid))
|
if (guid_equal(xaccGUIDNULL(), &guid))
|
||||||
@ -709,6 +804,31 @@ pgendGetAllAccounts (PGBackend *be)
|
|||||||
return topgrp;
|
return topgrp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================================= */
|
||||||
|
/* return TRUE if this appears to be a fresh, 'null' transaction */
|
||||||
|
/* it would be better is somehow we could get the gui to mark this
|
||||||
|
* as a fresh transaction, rather than having to scan a bunch of
|
||||||
|
* fields. But this is minor in the scheme of things.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_trans_empty (Transaction *trans)
|
||||||
|
{
|
||||||
|
Split *s;
|
||||||
|
if (!trans) return TRUE;
|
||||||
|
if (0 != (xaccTransGetDescription(trans))[0]) return FALSE;
|
||||||
|
if (0 != (xaccTransGetNum(trans))[0]) return FALSE;
|
||||||
|
if (1 != xaccTransCountSplits(trans)) return FALSE;
|
||||||
|
|
||||||
|
s = xaccTransGetSplit(trans, 0);
|
||||||
|
if (TRUE != gnc_numeric_zero_p(xaccSplitGetShareAmount(s))) return FALSE;
|
||||||
|
if (TRUE != gnc_numeric_zero_p(xaccSplitGetValue(s))) return FALSE;
|
||||||
|
if ('n' != xaccSplitGetReconcile(s)) return FALSE;
|
||||||
|
if (0 != (xaccSplitGetMemo(s))[0]) return FALSE;
|
||||||
|
if (0 != (xaccSplitGetAction(s))[0]) return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -729,37 +849,47 @@ pgend_trans_commit_edit (Backend * bend,
|
|||||||
"LOCK TABLE gncTransaction IN EXCLUSIVE MODE; "
|
"LOCK TABLE gncTransaction IN EXCLUSIVE MODE; "
|
||||||
"LOCK TABLE gncEntry IN EXCLUSIVE MODE; "
|
"LOCK TABLE gncEntry IN EXCLUSIVE MODE; "
|
||||||
"LOCK TABLE gncAccount IN EXCLUSIVE MODE; "
|
"LOCK TABLE gncAccount IN EXCLUSIVE MODE; "
|
||||||
|
"LOCK TABLE gncCommodity IN EXCLUSIVE MODE; "
|
||||||
);
|
);
|
||||||
SEND_QUERY (be,be->buff, 555);
|
SEND_QUERY (be,be->buff, 555);
|
||||||
FINISH_QUERY(be->connection);
|
FINISH_QUERY(be->connection);
|
||||||
|
|
||||||
/* See if the database is in the state that we last left it in.
|
/* Check to see if this is a 'new' transaction, or not.
|
||||||
* Basically, the database should contain the 'old transaction'.
|
* The hallmark of a 'new' transaction is that all the
|
||||||
* If it doesn't, then someone else has modified this transaction,
|
* fields are empty. If its new, then we just go ahead
|
||||||
* and thus, any further action on our part would be unsafe. It
|
* and commit. If its old, then we need some consistency
|
||||||
* would be best to spit this back at the GUI, and let a human
|
* checks.
|
||||||
* decide.
|
|
||||||
*/
|
*/
|
||||||
ndiffs = pgendCompareOneTransactionOnly (be, oldtrans);
|
if (FALSE == is_trans_empty (oldtrans))
|
||||||
if (ndiffs) rollback++;
|
{
|
||||||
|
/* See if the database is in the state that we last left it in.
|
||||||
/* be sure to check the old splits as well ... */
|
* Basically, the database should contain the 'old transaction'.
|
||||||
nsplits = xaccTransCountSplits (oldtrans);
|
* If it doesn't, then someone else has modified this transaction,
|
||||||
for (i=0; i<nsplits; i++) {
|
* and thus, any further action on our part would be unsafe. It
|
||||||
Split * s = xaccTransGetSplit (oldtrans, i);
|
* is recommended that this be spit back at the GUI, and let a
|
||||||
ndiffs = pgendCompareOneSplitOnly (be, s);
|
* human decide what to do next.
|
||||||
if (ndiffs) rollback++;
|
*/
|
||||||
|
ndiffs = pgendCompareOneTransactionOnly (be, oldtrans);
|
||||||
|
if (0 < ndiffs) rollback++;
|
||||||
|
|
||||||
|
/* be sure to check the old splits as well ... */
|
||||||
|
nsplits = xaccTransCountSplits (oldtrans);
|
||||||
|
for (i=0; i<nsplits; i++) {
|
||||||
|
Split * s = xaccTransGetSplit (oldtrans, i);
|
||||||
|
ndiffs = pgendCompareOneSplitOnly (be, s);
|
||||||
|
if (0 < ndiffs) rollback++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rollback) {
|
||||||
|
snprintf (be->buff, be->bufflen, "ROLLBACK;");
|
||||||
|
SEND_QUERY (be,be->buff,444);
|
||||||
|
FINISH_QUERY(be->connection);
|
||||||
|
|
||||||
|
LEAVE ("rolled back");
|
||||||
|
return 666; /* hack alert */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rollback) {
|
|
||||||
snprintf (be->buff, be->bufflen, "ROLLBACK;");
|
|
||||||
SEND_QUERY (be,be->buff,444);
|
|
||||||
FINISH_QUERY(be->connection);
|
|
||||||
|
|
||||||
LEAVE (" ");
|
|
||||||
return 666; /* hack alert */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we are here, we are good to go */
|
/* if we are here, we are good to go */
|
||||||
pgendStoreTransactionNoLock (be, trans, FALSE);
|
pgendStoreTransactionNoLock (be, trans, FALSE);
|
||||||
|
|
||||||
@ -767,7 +897,60 @@ pgend_trans_commit_edit (Backend * bend,
|
|||||||
SEND_QUERY (be,be->buff,333);
|
SEND_QUERY (be,be->buff,333);
|
||||||
FINISH_QUERY(be->connection);
|
FINISH_QUERY(be->connection);
|
||||||
|
|
||||||
LEAVE (" ");
|
/* hack alert -- the following code will get rid of that annoying
|
||||||
|
* message from the GUI about saving one's data. However, it doesn't
|
||||||
|
* do the right thing if the connection to the backend was ever lost.
|
||||||
|
* what should happen is the user should get a chance to
|
||||||
|
* resynchronize thier data with the backend, before quiting out.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Split * s = xaccTransGetSplit (trans, 0);
|
||||||
|
Account *acc = xaccSplitGetAccount (s);
|
||||||
|
AccountGroup *top = xaccGetAccountRoot (acc);
|
||||||
|
xaccGroupMarkSaved (top);
|
||||||
|
}
|
||||||
|
|
||||||
|
LEAVE ("commited");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================= */
|
||||||
|
|
||||||
|
static int
|
||||||
|
pgend_account_commit_edit (Backend * bend,
|
||||||
|
Account * acct)
|
||||||
|
{
|
||||||
|
PGBackend *be = (PGBackend *)bend;
|
||||||
|
|
||||||
|
ENTER ("be=%p, acct=%p", be, acct);
|
||||||
|
if (!be || !acct) return 1; /* hack alert hardcode literal */
|
||||||
|
|
||||||
|
/* lock it up so that we query and store atomically */
|
||||||
|
/* its not at all clear to me that this isn't rife with deadlocks. */
|
||||||
|
snprintf (be->buff, be->bufflen,
|
||||||
|
"BEGIN; "
|
||||||
|
"LOCK TABLE gncAccount IN EXCLUSIVE MODE; "
|
||||||
|
"LOCK TABLE gncCommodity IN EXCLUSIVE MODE; "
|
||||||
|
);
|
||||||
|
SEND_QUERY (be,be->buff, 555);
|
||||||
|
FINISH_QUERY(be->connection);
|
||||||
|
|
||||||
|
/* hack alert -- we aren't comparing old to new,
|
||||||
|
* i.e. not comparing version numbers, to see if
|
||||||
|
* we're clobbering someone elses changes. */
|
||||||
|
pgendStoreAccountNoLock (be, acct, FALSE);
|
||||||
|
|
||||||
|
snprintf (be->buff, be->bufflen, "COMMIT;");
|
||||||
|
SEND_QUERY (be,be->buff,333);
|
||||||
|
FINISH_QUERY(be->connection);
|
||||||
|
|
||||||
|
/* mark this up so that we don't get that annoying gui dialog
|
||||||
|
* about having to save to file. unfortunately,however, this
|
||||||
|
* is too liberal, and could screw up synchronization if we've lost
|
||||||
|
* contact with the back end at some point. So hack alert -- fix
|
||||||
|
* this. */
|
||||||
|
xaccGroupMarkSaved (xaccAccountGetParent(acct));
|
||||||
|
LEAVE ("commited");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -858,7 +1041,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid)
|
|||||||
g_free(url);
|
g_free(url);
|
||||||
|
|
||||||
/* handle localhost as a special case */
|
/* handle localhost as a special case */
|
||||||
if (!strcmp("localhost", be->hostname))
|
if (!safe_strcmp("localhost", be->hostname))
|
||||||
{
|
{
|
||||||
g_free (be->hostname);
|
g_free (be->hostname);
|
||||||
be->hostname = NULL;
|
be->hostname = NULL;
|
||||||
@ -882,7 +1065,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGCMD (PQtrace(be->connection, stderr));
|
// DEBUGCMD (PQtrace(be->connection, stderr));
|
||||||
|
|
||||||
/* set the datestyle to something we can parse */
|
/* set the datestyle to something we can parse */
|
||||||
snprintf (be->buff, be->bufflen, "SET DATESTYLE='ISO';");
|
snprintf (be->buff, be->bufflen, "SET DATESTYLE='ISO';");
|
||||||
@ -1032,7 +1215,7 @@ pgendEnable (PGBackend *be)
|
|||||||
PINFO("nest count=%d", be->nest_count);
|
PINFO("nest count=%d", be->nest_count);
|
||||||
if (be->nest_count) return;
|
if (be->nest_count) return;
|
||||||
be->be.account_begin_edit = NULL;
|
be->be.account_begin_edit = NULL;
|
||||||
be->be.account_commit_edit = NULL;
|
be->be.account_commit_edit = pgend_account_commit_edit;
|
||||||
be->be.trans_begin_edit = NULL;
|
be->be.trans_begin_edit = NULL;
|
||||||
be->be.trans_commit_edit = pgend_trans_commit_edit;
|
be->be.trans_commit_edit = pgend_trans_commit_edit;
|
||||||
be->be.trans_rollback_edit = NULL;
|
be->be.trans_rollback_edit = NULL;
|
||||||
|
@ -261,6 +261,14 @@ sqlBuild_Set_Int64 (sqlBuilder *b, const char *tag, gint64 nval)
|
|||||||
|
|
||||||
/* ================================================ */
|
/* ================================================ */
|
||||||
|
|
||||||
|
void
|
||||||
|
sqlBuild_Set_Int32 (sqlBuilder *b, const char *tag, gint32 nval)
|
||||||
|
{
|
||||||
|
sqlBuild_Set_Int64 (b, tag, (gint64) nval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================ */
|
||||||
|
|
||||||
void
|
void
|
||||||
sqlBuild_Where_Str (sqlBuilder *b, const char *tag, const char *val)
|
sqlBuild_Where_Str (sqlBuilder *b, const char *tag, const char *val)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +44,7 @@ void sqlBuild_Set_Char (sqlBuilder *b, const char *tag, char val);
|
|||||||
void sqlBuild_Set_GUID (sqlBuilder *b, const char *tag, const GUID *val);
|
void sqlBuild_Set_GUID (sqlBuilder *b, const char *tag, const GUID *val);
|
||||||
void sqlBuild_Set_Date (sqlBuilder *b, const char *tag, Timespec val);
|
void sqlBuild_Set_Date (sqlBuilder *b, const char *tag, Timespec val);
|
||||||
void sqlBuild_Set_Int64 (sqlBuilder *b, const char *tag, gint64 val);
|
void sqlBuild_Set_Int64 (sqlBuilder *b, const char *tag, gint64 val);
|
||||||
|
void sqlBuild_Set_Int32 (sqlBuilder *b, const char *tag, gint32 val);
|
||||||
|
|
||||||
|
|
||||||
/* build the update 'where' clause */
|
/* build the update 'where' clause */
|
||||||
|
@ -4,6 +4,17 @@
|
|||||||
-- these tables are hand-built, but maybe they should be
|
-- these tables are hand-built, but maybe they should be
|
||||||
-- autobuilt with the m4 macros ...
|
-- autobuilt with the m4 macros ...
|
||||||
|
|
||||||
|
-- Commodity structure
|
||||||
|
|
||||||
|
DROP TABLE gncCommodity;
|
||||||
|
CREATE TABLE gncCommodity (
|
||||||
|
commodity TEXT PRIMARY KEY,
|
||||||
|
fullname TEXT,
|
||||||
|
namespace TEXT,
|
||||||
|
mnemonic TEXT,
|
||||||
|
code TEXT,
|
||||||
|
fraction INT DEFAULT '100'
|
||||||
|
);
|
||||||
|
|
||||||
-- Account structure -- parentGUID points to parent account
|
-- Account structure -- parentGUID points to parent account
|
||||||
-- guid. There is no supports for Groups in this schema.
|
-- guid. There is no supports for Groups in this schema.
|
||||||
@ -22,7 +33,7 @@ CREATE TABLE gncAccount (
|
|||||||
description TEXT,
|
description TEXT,
|
||||||
notes TEXT,
|
notes TEXT,
|
||||||
type TEXT,
|
type TEXT,
|
||||||
currency TEXT
|
commodity TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CREATE INDEX gncAccount_pg_idx ON gncAccount (parentGuid);
|
-- CREATE INDEX gncAccount_pg_idx ON gncAccount (parentGuid);
|
||||||
@ -33,10 +44,11 @@ CREATE TABLE gncAccount (
|
|||||||
DROP TABLE gncTransaction;
|
DROP TABLE gncTransaction;
|
||||||
CREATE TABLE gncTransaction (
|
CREATE TABLE gncTransaction (
|
||||||
transGuid CHAR(32) PRIMARY KEY,
|
transGuid CHAR(32) PRIMARY KEY,
|
||||||
date_entered DATETIME,
|
date_entered DATETIME DEFAULT 'NOW',
|
||||||
date_posted DATETIME,
|
date_posted DATETIME,
|
||||||
num TEXT,
|
num TEXT,
|
||||||
description TEXT
|
description TEXT,
|
||||||
|
currency TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
-- a gncEntry is what we call 'Split' elsewhere in the engine
|
-- a gncEntry is what we call 'Split' elsewhere in the engine
|
||||||
@ -48,7 +60,7 @@ CREATE TABLE gncEntry (
|
|||||||
transGuid CHAR(32),
|
transGuid CHAR(32),
|
||||||
memo TEXT,
|
memo TEXT,
|
||||||
action TEXT,
|
action TEXT,
|
||||||
reconciled CHAR,
|
reconciled CHAR DEFAULT 'n',
|
||||||
date_reconciled DATETIME,
|
date_reconciled DATETIME,
|
||||||
amountNum INT8 DEFAULT '0',
|
amountNum INT8 DEFAULT '0',
|
||||||
amountDenom INT8 DEFAULT '100',
|
amountDenom INT8 DEFAULT '100',
|
||||||
|
@ -11,6 +11,7 @@ define(`account', `gncAccount, Account,
|
|||||||
description, , char *, xaccAccountGetDescription(ptr),
|
description, , char *, xaccAccountGetDescription(ptr),
|
||||||
notes, , char *, xaccAccountGetNotes(ptr),
|
notes, , char *, xaccAccountGetNotes(ptr),
|
||||||
type, , char *, xaccAccountTypeEnumAsString(xaccAccountGetType(ptr)),
|
type, , char *, xaccAccountTypeEnumAsString(xaccAccountGetType(ptr)),
|
||||||
|
commodity, , char *, gnc_commodity_get_unique_name(xaccAccountGetCommodity(ptr)),
|
||||||
parentGUID, , GUID *, xaccAccountGetGUID(xaccAccountGetParentAccount(ptr)),
|
parentGUID, , GUID *, xaccAccountGetGUID(xaccAccountGetParentAccount(ptr)),
|
||||||
accountGUID, KEY, GUID *, xaccAccountGetGUID(ptr),
|
accountGUID, KEY, GUID *, xaccAccountGetGUID(ptr),
|
||||||
')
|
')
|
||||||
@ -40,11 +41,23 @@ define(`split', `gncEntry, Split,
|
|||||||
define(`transaction', `gncTransaction, Transaction,
|
define(`transaction', `gncTransaction, Transaction,
|
||||||
num, , char *, xaccTransGetNum(ptr),
|
num, , char *, xaccTransGetNum(ptr),
|
||||||
description, , char *, xaccTransGetDescription(ptr),
|
description, , char *, xaccTransGetDescription(ptr),
|
||||||
date_entered, , char *, "CURRENT",
|
currency, , char *, gnc_commodity_get_unique_name(xaccTransGetCurrency(ptr)),
|
||||||
|
date_entered, , now, "NOW",
|
||||||
date_posted, , Timespec, xaccTransRetDatePostedTS(ptr),
|
date_posted, , Timespec, xaccTransRetDatePostedTS(ptr),
|
||||||
transGUID, KEY, GUID *, xaccTransGetGUID(ptr),
|
transGUID, KEY, GUID *, xaccTransGetGUID(ptr),
|
||||||
')
|
')
|
||||||
|
|
||||||
|
|
||||||
|
define(`modity', `gncCommodity, gnc_commodity,
|
||||||
|
namespace, , char *, gnc_commodity_get_namespace(ptr),
|
||||||
|
fullname, , char *, gnc_commodity_get_fullname(ptr),
|
||||||
|
mnemonic, , char *, gnc_commodity_get_mnemonic(ptr),
|
||||||
|
code, , char *, gnc_commodity_get_exchange_code(ptr),
|
||||||
|
fraction, , int32, gnc_commodity_get_fraction(ptr),
|
||||||
|
commodity, KEY, char *, gnc_commodity_get_unique_name(ptr),
|
||||||
|
')
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------- */
|
/* ------------------------------------------------------- */
|
||||||
/* symbolic names for the table accessors */
|
/* symbolic names for the table accessors */
|
||||||
define(`tablename', $1)
|
define(`tablename', $1)
|
||||||
@ -54,7 +67,7 @@ define(`firstrec', `shift(shift($@))')
|
|||||||
define(`nextrec', `shift(shift(shift(shift($@))))')
|
define(`nextrec', `shift(shift(shift(shift($@))))')
|
||||||
|
|
||||||
/* -------- */
|
/* -------- */
|
||||||
/* macros that use teh sql builder to build a query */
|
/* macros that use the sql builder to build a query */
|
||||||
|
|
||||||
define(`sql_setter', `ifelse($2, `KEY',
|
define(`sql_setter', `ifelse($2, `KEY',
|
||||||
`ifelse($1, `char *', sqlBuild_Where_Str,
|
`ifelse($1, `char *', sqlBuild_Where_Str,
|
||||||
@ -62,6 +75,8 @@ define(`sql_setter', `ifelse($2, `KEY',
|
|||||||
|
|
||||||
$2, ,
|
$2, ,
|
||||||
`ifelse($1, `char *', sqlBuild_Set_Str,
|
`ifelse($1, `char *', sqlBuild_Set_Str,
|
||||||
|
$1, `now', sqlBuild_Set_Str,
|
||||||
|
$1, `int32', sqlBuild_Set_Int32,
|
||||||
$1, `int64', sqlBuild_Set_Int64,
|
$1, `int64', sqlBuild_Set_Int64,
|
||||||
$1, `GUID *', sqlBuild_Set_GUID,
|
$1, `GUID *', sqlBuild_Set_GUID,
|
||||||
$1, `Timespec', sqlBuild_Set_Date,
|
$1, `Timespec', sqlBuild_Set_Date,
|
||||||
@ -80,6 +95,8 @@ define(`set_fields', `set_fields_r(firstrec($@))')
|
|||||||
/* macros to compare a query result */
|
/* macros to compare a query result */
|
||||||
|
|
||||||
define(`cmp_value', `ifelse($1, `char *', COMP_STR,
|
define(`cmp_value', `ifelse($1, `char *', COMP_STR,
|
||||||
|
$1, `now', COMP_NOW,
|
||||||
|
$1, `int32', COMP_INT32,
|
||||||
$1, `int64', COMP_INT64,
|
$1, `int64', COMP_INT64,
|
||||||
$1, `GUID *', COMP_GUID,
|
$1, `GUID *', COMP_GUID,
|
||||||
$1, `Timespec', COMP_DATE,
|
$1, `Timespec', COMP_DATE,
|
||||||
@ -180,7 +197,9 @@ divert
|
|||||||
store_one_only(account)
|
store_one_only(account)
|
||||||
store_one_only(transaction)
|
store_one_only(transaction)
|
||||||
store_one_only(split)
|
store_one_only(split)
|
||||||
|
store_one_only(modity)
|
||||||
|
|
||||||
compare_one_only(account)
|
compare_one_only(account)
|
||||||
compare_one_only(transaction)
|
compare_one_only(transaction)
|
||||||
compare_one_only(split)
|
compare_one_only(split)
|
||||||
|
compare_one_only(modity)
|
||||||
|
Loading…
Reference in New Issue
Block a user