mirror of
https://github.com/Gnucash/gnucash.git
synced 2026-09-03 20:53:02 -05:00
The postgress single-user mode should now be more-or-less 'beta'
with this patch; multi-user mode is still highly experimental. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3591 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -11,11 +11,13 @@ libgnc_postgres_la_SOURCES = \
|
||||
|
||||
EXTRA_DIST = \
|
||||
builder.h \
|
||||
design.txt \
|
||||
PostgresBackend.h \
|
||||
README \
|
||||
demo.c \
|
||||
gnc-init.sh \
|
||||
gnc-init.sql
|
||||
table.m4 \
|
||||
table-create.sql \
|
||||
table-drop.sql \
|
||||
demo.c
|
||||
|
||||
INCLUDES = -I.. -I/usr/lib/glib/include
|
||||
|
||||
@@ -23,8 +25,18 @@ LDFLAGS= -lpq
|
||||
|
||||
# Some of the required C files are built with the m4 pre-processor
|
||||
|
||||
PostgresBackend.o: autogen.c
|
||||
PostgresBackend.lo: autogen.c
|
||||
PostgresBackend.o: autogen.c table-create.c table-drop.c
|
||||
PostgresBackend.lo: autogen.c table-create.c table-drop.c
|
||||
|
||||
autogen.c: table.m4
|
||||
m4 table.m4 > autogen.c
|
||||
|
||||
table-drop.c: table-drop.sql
|
||||
echo \" > table-drop.c
|
||||
cat table-drop.sql >> table-drop.c
|
||||
echo \" >> table-drop.c
|
||||
|
||||
table-create.c: table-create.sql
|
||||
echo \" > table-create.c
|
||||
cat table-create.sql >> table-create.c
|
||||
echo \" >> table-create.c
|
||||
|
||||
@@ -314,6 +314,14 @@ gnc_string_to_commodity (const char *str)
|
||||
|
||||
#include "autogen.c"
|
||||
|
||||
static const char *table_create_str =
|
||||
#include "table-create.c"
|
||||
;
|
||||
|
||||
static const char *table_drop_str =
|
||||
#include "table-drop.c"
|
||||
;
|
||||
|
||||
/* ============================================================= */
|
||||
/* This routine updates the account structure if needed, and/or
|
||||
* stores it the first time if it hasn't yet been stored.
|
||||
@@ -1969,12 +1977,14 @@ pgend_book_load_single (Backend *bend)
|
||||
/* ============================================================= */
|
||||
|
||||
static void
|
||||
pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
gboolean ignore_lock, gboolean create_new_db)
|
||||
{
|
||||
int really_do_create = 0;
|
||||
int rc;
|
||||
PGBackend *be;
|
||||
char *url, *start, *end;
|
||||
char * bufp;
|
||||
char *bufp;
|
||||
|
||||
if (!sess) return;
|
||||
be = (PGBackend *) xaccGNCBookGetBackend (sess);
|
||||
@@ -1998,7 +2008,11 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
*
|
||||
*/
|
||||
|
||||
if (strncmp (sessionid, "postgres://", 11)) return;
|
||||
if (strncmp (sessionid, "postgres://", 11))
|
||||
{
|
||||
xaccBackendSetError (&be->be, ERR_SQL_BAD_LOCATION);
|
||||
return;
|
||||
}
|
||||
url = g_strdup(sessionid);
|
||||
start = url + 11;
|
||||
end = strchr (start, ':');
|
||||
@@ -2021,7 +2035,12 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
be->hostname = g_strdup (start);
|
||||
}
|
||||
start = end+1;
|
||||
if (0x0 == *start) { g_free(url); return; }
|
||||
if (0x0 == *start)
|
||||
{
|
||||
xaccBackendSetError (&be->be, ERR_SQL_BAD_LOCATION);
|
||||
g_free(url);
|
||||
return;
|
||||
}
|
||||
|
||||
/* chop of trailing url-encoded junk, if present */
|
||||
end = strchr (start, '?');
|
||||
@@ -2053,8 +2072,88 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
be->dbName, PQerrorMessage(be->connection));
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
xaccBackendSetError (&be->be, ERR_SQL_CANT_CONNECT);
|
||||
return;
|
||||
|
||||
/* OK, this part is convoluted.
|
||||
* I wish that postgres returned usable error codes.
|
||||
* Alas, it does not, so we guess the true error.
|
||||
* If the host is 'localhost', and we couldn't connect,
|
||||
* then we assume that its because the database doesn't
|
||||
* exist (although this might also happen if the database
|
||||
* existed, but the user supplied a bad username/password)
|
||||
*/
|
||||
if (NULL == be->hostname)
|
||||
{
|
||||
if (create_new_db) {
|
||||
really_do_create = TRUE;
|
||||
} else {
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_NO_SUCH_DB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xaccBackendSetError (&be->be, ERR_SQL_CANT_CONNECT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (really_do_create)
|
||||
{
|
||||
char * p;
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
NULL, /* trace/debug options */
|
||||
NULL, /* file or tty for debug output */
|
||||
"gnucash",
|
||||
NULL, /* login */
|
||||
NULL); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PERR("Can't connect to database 'gnucash':\n"
|
||||
"\t%s",
|
||||
PQerrorMessage(be->connection));
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
xaccBackendSetError (&be->be, ERR_SQL_CANT_CONNECT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* create the database */
|
||||
p = be->buff; *p =0;
|
||||
p = stpcpy (p, "CREATE DATABASE ");
|
||||
p = stpcpy (p, be->dbName);
|
||||
p = stpcpy (p, ";");
|
||||
SEND_QUERY (be,be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
PQfinish (be->connection);
|
||||
|
||||
/* now connect to the newly created database */
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
NULL, /* trace/debug options */
|
||||
NULL, /* file or tty for debug output */
|
||||
be->dbName,
|
||||
NULL, /* login */
|
||||
NULL); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PERR("Can't connect to the newly created database '%s':\n"
|
||||
"\t%s",
|
||||
be->dbName,
|
||||
PQerrorMessage(be->connection));
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
xaccBackendSetError (&be->be, ERR_SQL_CANT_CONNECT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* finally, create all the tables and indexes */
|
||||
SEND_QUERY (be,table_create_str, );
|
||||
FINISH_QUERY(be->connection);
|
||||
}
|
||||
|
||||
// DEBUGCMD (PQtrace(be->connection, stderr));
|
||||
@@ -2088,7 +2187,8 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
be->be.trans_rollback_edit = NULL;
|
||||
be->be.run_query = NULL;
|
||||
be->be.sync = pgendSyncSingleFile;
|
||||
PWARN ("MODE_SINGLE_FILE is experimental");
|
||||
PWARN ("MODE_SINGLE_FILE is beta -- we've fixed all known \n"
|
||||
"bugs but that doesn't mean there aren't any!\n");
|
||||
break;
|
||||
|
||||
case MODE_SINGLE_UPDATE:
|
||||
@@ -2101,7 +2201,8 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
be->be.trans_rollback_edit = NULL;
|
||||
be->be.run_query = NULL;
|
||||
be->be.sync = pgendSync;
|
||||
PWARN ("MODE_SINGLE_UPDATE is experimental");
|
||||
PWARN ("MODE_SINGLE_UPDATE is beta -- we've fixed all known \n"
|
||||
"bugs but that doesn't mean there aren't any!\n");
|
||||
break;
|
||||
|
||||
case MODE_POLL:
|
||||
@@ -2114,7 +2215,7 @@ pgend_session_begin (GNCBook *sess, const char * sessionid, int ignore_lock)
|
||||
be->be.trans_rollback_edit = NULL;
|
||||
be->be.run_query = pgendRunQuery;
|
||||
be->be.sync = pgendSync;
|
||||
PWARN ("MODE_EVENT is experimental");
|
||||
PWARN ("MODE_POLL is experimental -- you will corrupt your data\n");
|
||||
break;
|
||||
|
||||
case MODE_EVENT:
|
||||
|
||||
+49
-35
@@ -1,54 +1,67 @@
|
||||
|
||||
This directory contains experimental code for sql/postgres
|
||||
support. The code 'functions' and does many things but is still
|
||||
missing an assortment of features, and may be buggy and crash a lot.
|
||||
This directory contains code for SQL/postgres support. The
|
||||
SQL backend can be used in several modes. The single-user modes
|
||||
are more-or-less beta: they work, but haven't been well tested.
|
||||
The multi-user code is experimental: it still has a variety of
|
||||
problems.
|
||||
|
||||
|
||||
|
||||
postgres install instructions
|
||||
-----------------------------
|
||||
1) Install postgresql server, client and devel packages.
|
||||
2) if installed from redhat, then running /etc/rc.d/init.d/postgresql
|
||||
will setup and initialize all first-time setup & config.
|
||||
will setup and initialize basic postgres first-time setup & config.
|
||||
3) as root, su - postgres then run 'createuser' to add your user id
|
||||
|
||||
Gnucash-specific install steps
|
||||
------------------------------
|
||||
A) install the m4 macro processor if you don't already have it.
|
||||
B) run the script gnc-init.sh
|
||||
This script will automatically create the needed tables
|
||||
4) (don't set a password on your postgres db name, yet, gnucash doesn't
|
||||
have a GUI to ask for your password yet)
|
||||
5) as yourself (i.e. your unix login), run 'createdb gnucash'
|
||||
|
||||
|
||||
|
||||
|
||||
To Bo Done
|
||||
To Be Done
|
||||
----------
|
||||
-- bug: transaction memo in double line mode is lost.
|
||||
-- create database if it don't exist; provide user dialog for this.
|
||||
Core bugs/features that still need work:
|
||||
|
||||
-- allow user to enter url in gui dialog
|
||||
-- handle kvp frames
|
||||
-- implement account commit edit (actually, the check&rollback part)
|
||||
-- fix excessive use of account commit by engine
|
||||
-- provide support for more query types in gncquery.c
|
||||
-- optimize for quantity of sql traffic -- there's a lot of it,
|
||||
much of it proably un-needed.
|
||||
|
||||
-- Implement account and transaction deletion. Deleting an account or
|
||||
-- bug: Implement account and transaction deletion. Deleting an account or
|
||||
transaction doesn't remove it from the database.
|
||||
(done with split delete)
|
||||
|
||||
-- Implement logging history in the sql server. i.e. save the old
|
||||
-- bug: transaction memo in double line mode is lost.
|
||||
|
||||
-- bug/feature: the 'save as' semantics are ... unexpected, if
|
||||
the database already exists and has data in it ...
|
||||
|
||||
-- bug: group sync doesn't pull in newer data from the db ...
|
||||
|
||||
-- allow user to enter URL in GUI dialog
|
||||
|
||||
-- Implement GUI to ask user for username/password to log onto the
|
||||
server.
|
||||
|
||||
-- handle kvp frames
|
||||
|
||||
To Be Done, Part II
|
||||
-------------------
|
||||
This list only affects the multi-user and advanced/optional features.
|
||||
|
||||
-- implement account commit edit (actually, the check&rollback part)
|
||||
-- fix excessive use of account commit by engine
|
||||
-- provide support for more query types in gncquery.c
|
||||
-- optimize for quantity of SQL traffic -- there's a lot of it,
|
||||
much of it probably un-needed.
|
||||
|
||||
-- Implement logging history in the SQL server. i.e. save the old
|
||||
copies of stuff in log tables. Make the username part of the
|
||||
logging scheme.
|
||||
|
||||
-- Implement gui to ask user for username/password to log onto the
|
||||
server.
|
||||
|
||||
-- let all attached client receive update events via sql LISTEN/NOTIFY
|
||||
-- let all attached client receive update events via SQL LISTEN/NOTIFY
|
||||
events.
|
||||
|
||||
-- Implement various advanced database features, such as checking the
|
||||
user's permission to view/edit account by account ... (hmmm this
|
||||
done by the dbadmin... using sql commands... which means if user
|
||||
done by the dbadmin... using SQL commands... which means if user
|
||||
tries to write to something they're not allowed to write to,
|
||||
then they should be bounced back.
|
||||
|
||||
@@ -56,32 +69,33 @@ To Bo Done
|
||||
should be like CVS: multiple nearly-simultaneous writers are allowed;
|
||||
however, only one wins, and others are kicked back. The losers know
|
||||
themselves because they are trying to update info of the wrong
|
||||
version. But right now, version is not done everyehwere, nor is it
|
||||
done uniformely:
|
||||
version. But right now, version is not done everywhere, nor is it
|
||||
done uniformly:
|
||||
-- pgend_transaction_commit does it correctly.
|
||||
-- pgTransactionSync does not, it clobbers.
|
||||
-- pgend_account_commit clobbers.
|
||||
-- pgendAccountGroupSync is unfinished.
|
||||
I'm not sure how critical this all is; with a small number of users
|
||||
it shouldn'tbe a prblem. With a huge number of users, each editing
|
||||
it shouldn't be a problem. With a huge number of users, each editing
|
||||
the same transaction (unlikely!?) then there is risk of clobbered
|
||||
data, but so what?
|
||||
|
||||
-- fix rollback bug in gui. If backend tells engine to rollback,
|
||||
(e.g. on a new transaction), the gui still shows traces, instead
|
||||
-- fix rollback bug in GUI. If backend tells engine to rollback,
|
||||
(e.g. on a new transaction), the GUI still shows traces, instead
|
||||
of kicking back.
|
||||
This is a symptom of a lack of kick-back detection in gui.
|
||||
This is a symptom of a lack of kick-back detection in GUI.
|
||||
-- finish implementing pgendAccountGroupSync
|
||||
|
||||
-- store account balances in database. This will be tricky ...
|
||||
-- split query gets hard ...
|
||||
-- use aggregates ??
|
||||
|
||||
-- review multiuser operation for correctness
|
||||
|
||||
-- fix caching in the face of lost contact to the backend. If the
|
||||
backend can't contact its server, then we should just save up caches,
|
||||
and then when contact with backend re-established, we should spit
|
||||
them out. But right now, this is brroken. In particular,
|
||||
them out. But right now, this is broken. In particular,
|
||||
the use of xaccGrouparkSaved screws up some status bits ...
|
||||
|
||||
-- review & match up against docs at
|
||||
|
||||
Reference in New Issue
Block a user