diff --git a/src/engine/sql/Makefile b/src/engine/sql/Makefile index 82df637811..300f2f6466 100644 --- a/src/engine/sql/Makefile +++ b/src/engine/sql/Makefile @@ -1,3 +1,56 @@ +# Generated automatically from Makefile.in by configure. +# Makefile -- makefile for xacc/src/engine/sql +# Copyright (C) 1997 Robin Clark +# Copyright (C) 1998 Linas Vepstas +# Copyright (C) 1998 Rob Browning +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, contact: +# +# Free Software Foundation Voice: +1-617-542-5942 +# 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +# Boston, MA 02111-1307, USA gnu@gnu.org + +include ../../../Makefile.init + +INCLPATH = -I. \ + -I.. \ + -I../.. \ + -I../../.. \ + -I../guid \ + -I/usr/include + +# add the -fpic flag to generate relocatable position independent code +# for the engine so that in can be used in a shared module (e.g. a perl module) +CFLAGS = -g -O2 ${INCLPATH} -fpic +LIBS = -lpq + +###################################################################### +# See Makefile.common for information about these variables. +INDEP_SRCS := PostgresBackend.c + +###################################################################### + +all: default + +# This inclusion must come after the first target, and after the +# definitions of *_SRCS, etc., but before the usage of *_OBJS. +include ../../../Makefile.common + +default: ${OBJS} + + +.PHONY: all default demo: demo.c diff --git a/src/engine/sql/PostgresBackend.c b/src/engine/sql/PostgresBackend.c new file mode 100644 index 0000000000..310968d744 --- /dev/null +++ b/src/engine/sql/PostgresBackend.c @@ -0,0 +1,261 @@ +/* + * 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. + * + */ + +#include +#include +#include + +#include "BackendP.h" +#include "Group.h" +#include "Session.h" +#include "guid.h" +#include "util.h" + +#include "PostgresBackend.h" + +static short module = MOD_BACKEND; + +/* hack alert -- this is the query buffer, it might be too small. + we need to make it dynamic sized */ +#define QBUFSIZE 16350 + +/* ============================================================= */ + +#define FLUSH(conn) { \ + PGresult *result; \ + /* complete/commit the transaction, check the status */ \ + do { \ + ExecStatusType status; \ + result = PQgetResult((conn)); \ + if (!result) break; \ + PINFO ("got result\n"); \ + status = PQresultStatus(result); \ + if (PGRES_COMMAND_OK != status) { \ + PERR("bad status\n"); \ + PQclear(result); \ + PQfinish ((conn)); \ + } \ + PQclear(result); \ + } while (result); \ +} + +/* ============================================================= */ +/* This routine stores the indicated group structure into the database. + * It does *not* chase pointers, traverse the tree, etc. + */ + +static void +pgendStoreOneGroupOnly (PGBackend *be, AccountGroup *grp) +{ + Account *parent; + const GUID *parent_guid, *grp_guid; + char buff[QBUFSIZE]; + int i, nacc, rc; + + ENTER ("be=%p, grp=%p\n", be, grp); + if (!be || !grp) return; + + grp_guid = xaccGroupGetGUID (grp); + parent = xaccGroupGetParentAccount(grp); + parent_guid = xaccAccountGetGUID (parent); + nacc = xaccGroupGetNumAccounts(grp); + + for (i=0; iconnection, buff); + if (!rc) + { + PERR("send query failed:\n" + "\t%s", PQerrorMessage(be->connection)); + PQfinish (be->connection); + return; + } + + /* complete/commit the transaction, check the status */ + FLUSH(be->connection); + } + + LEAVE ("\n"); +} + +/* ============================================================= */ +/* this routine stores the indicated split in the database + */ + +static void +pgendStoreSplit (PGBackend *be, Split *split) +{ + Timespec ts; + char buff[QBUFSIZE]; + int rc; + + ENTER ("be=%p, split=%p\n", be, split); + if (!be || !split) return; + + /* hack alert date is not stored ... */ + xaccSplitGetDateReconciledTS (split, &ts); + + /* hack alert -- values should be escaped so that no '' apear in them */ + snprintf (buff, QBUFSIZE, + "INSERT INTO gncEntry " + "(entryGuid, accountGuid, transGuid, memo, action," + "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))), + xaccSplitGetMemo(split), + xaccSplitGetAction(split), + xaccSplitGetReconcile(split), + xaccSplitGetShareAmount(split), + xaccSplitGetSharePrice(split) + ); + rc = PQsendQuery (be->connection, buff); + if (!rc) + { + PERR("send query failed:\n" + "\t%s", PQerrorMessage(be->connection)); + PQfinish (be->connection); + return; + } + + /* complete/commit the transaction, check the status */ + FLUSH(be->connection); + + LEAVE ("\n"); +} + +/* ============================================================= */ +/* this routine fills in the structure pointed at by split + * with data sucked out of the database + */ + +static void +pgendGetSplit (PGBackend *be, Split *split, GUID *guid) +{ + int rc; + + ENTER ("be=%p, split=%p\n", be, split); + if (!be || !split || !guid) return; + + rc = PQsendQuery (be->connection, "SELECT * FROM gncEntry;"); + if (!rc) + { + PERR("send query failed:\n" + "\t%s", PQerrorMessage(be->connection)); + PQfinish (be->connection); + return; + } + + + LEAVE ("\n"); + +} + +/* ============================================================= */ + +AccountGroup * +pgend_session_begin (Session *sess, const char * sessionid) +{ + PGBackend *be; + + ENTER("sessionid=%s\n", sessionid); + /* connect to a bogus database ... */ + /* hack alert -- clean this up ... */ + be->dbName = strdup ("gnc_bogus"); + be->connection = PQsetdbLogin (NULL, NULL, NULL, NULL, be->dbName, NULL, NULL); + + /* check the conmnection status */ + if (CONNECTION_BAD == PQstatus(be->connection)) + { + PERR("Connection to database '%s' failed:\n" + "\t%s", + be->dbName, PQerrorMessage(be->connection)); + PQfinish (be->connection); + return NULL; + } + + DEBUGCMD (PQtrace(be->connection, stderr)); + + LEAVE("\n"); + return NULL; +} + +/* ============================================================= */ + +int +pgend_trans_commit_edit (Backend * bend, Transaction * trans) +{ + PGBackend *be = (PGBackend *)bend; + int i, nsplits; + int rc; + + ENTER ("be=%p, trans=%p\n", be, trans); + if (!be || !trans) return 1; /* hack alert hardcode literal */ + + nsplits = xaccTransCountSplits (trans); + for (i=0; iconnection, "SELECT * FROM gncAccount;"); + if (!rc) + { + PERR("send query failed:\n" + "\t%s", PQerrorMessage(be->connection)); + PQfinish (be->connection); + return 2; /* hack alert hardcode literal */ + } +#endif + + + LEAVE ("\n"); +} + +/* ============================================================= */ + +Backend * +pgendNew (void) +{ + PGBackend *be; + + be = (PGBackend *) malloc (sizeof (PGBackend)); + + /* generic backend handlers */ + be->be.session_begin = pgend_session_begin; + be->be.session_end = NULL; + + be->be.account_begin_edit = NULL; + be->be.account_commit_edit = NULL; + be->be.trans_begin_edit = NULL; + be->be.trans_commit_edit = pgend_trans_commit_edit; + be->be.trans_rollback_edit= NULL; + + /* postgres specific data */ + be->dbName = NULL; + be->connection = NULL; + + return (Backend *) be; +} + +/* ======================== END OF FILE ======================== */ diff --git a/src/engine/sql/PostgresBackend.h b/src/engine/sql/PostgresBackend.h new file mode 100644 index 0000000000..ea33190cee --- /dev/null +++ b/src/engine/sql/PostgresBackend.h @@ -0,0 +1,26 @@ +/* + * PostgressBackend.h + * + * Implements the callbacks for the postgress backend. + * + */ + + +#include +#include "BackendP.h" + +typedef struct _pgend PGBackend; + +struct _pgend { + Backend be; + + /* postgres-specific conection data */ + char * dbName; + PGconn * connection; +}; + +/* + * pgendNew creates a new postgress backend + */ +Backend * pgendNew (void); + diff --git a/src/engine/sql/gnc-init.sql b/src/engine/sql/gnc-init.sql index bb6cbdc6d9..3f6e64114e 100644 --- a/src/engine/sql/gnc-init.sql +++ b/src/engine/sql/gnc-init.sql @@ -1,10 +1,18 @@ --- these tables roughly mirror the c structs in TransactionP.h and --- AccountP.h +-- these tables roughly mirror the c structs in +-- TransactionP.h, AccountP.h and GroupP.h + +-- each child of a group will have its own record. +DROP TABLE gncGroup; +CREATE TABLE gncGroup ( + groupGuid CHAR(32), + parentGuid CHAR(32), + childGuid CHAR(32) +); DROP TABLE gncAccount; CREATE TABLE gncAccount ( - accountGuid CHAR(16) PRIMARY KEY, + accountGuid CHAR(32) PRIMARY KEY, accountName VARCHAR(40) DEFAULT 'xoxo', accountCode VARCHAR(8), description VARCHAR(120), @@ -25,11 +33,12 @@ INSERT INTO gncaccount (accountguid,accountName,description) values DROP TABLE gncEntry; CREATE TABLE gncEntry ( - entryGuid CHAR(16) PRIMARY KEY, - accountGuid CHAR(16), - transGuid CHAR(16), + entryGuid CHAR(32) PRIMARY KEY, + accountGuid CHAR(32), + transGuid CHAR(32), memo VARCHAR(20), action VARCHAR(20), + reconciled CHAR, date_reconciled DATETIME, amount FLOAT8 DEFAULT '0.0', share_price FLOAT8 DEFAULT '0.0' @@ -37,7 +46,7 @@ CREATE TABLE gncEntry ( DROP TABLE gncTransaction; CREATE TABLE gncTransaction ( - transGuid CHAR(16) PRIMARY KEY, + transGuid CHAR(32) PRIMARY KEY, date_entered DATETIME, date_posted DATETIME, num VARCHAR(8),