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:
Linas Vepstas 2001-01-21 20:48:38 +00:00
parent bb4dbf85dd
commit eead62a8ce
5 changed files with 271 additions and 48 deletions

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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 */

View File

@ -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',

View File

@ -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)