mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
* Matthew Vanecek's patch:
The attached patch contains some immediate bug fixes for the SQL back end, and it adds and error message string + accessor/mutator to Backend. Also, in xaccAccountCommitEdit(), added the use of PWARN_GUI to display the error message. The bug fixes in the SQL backend involved converting the *_QUERY macros to functions. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7485 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
d4f97ce2d9
commit
c2bfd78517
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
2002-11-16 Derek Atkins <derek@ihtfp.com>
|
||||
|
||||
* Matthew Vanecek's patch:
|
||||
|
||||
The attached patch contains some immediate bug fixes for the SQL
|
||||
back end, and it adds and error message string + accessor/mutator
|
||||
to Backend. Also, in xaccAccountCommitEdit(), added the use of
|
||||
PWARN_GUI to display the error message.
|
||||
|
||||
The bug fixes in the SQL backend involved converting the *_QUERY
|
||||
macros to functions.
|
||||
|
||||
2002-11-15 Joshua Sled <jsled@asynchronous.org>
|
||||
|
||||
* src/gnome/window-register.c (gnc_register_delete_cb): Change the
|
||||
|
14
m4/ChangeLog
14
m4/ChangeLog
@ -1,3 +1,17 @@
|
||||
2002-11-16 gettextize <bug-gnu-gettext@gnu.org>
|
||||
|
||||
* codeset.m4: New file, from gettext-0.11.1.
|
||||
* gettext.m4: New file, from gettext-0.11.1.
|
||||
* glibc21.m4: New file, from gettext-0.11.1.
|
||||
* iconv.m4: New file, from gettext-0.11.1.
|
||||
* isc-posix.m4: New file, from gettext-0.11.1.
|
||||
* lcmessage.m4: New file, from gettext-0.11.1.
|
||||
* lib-ld.m4: New file, from gettext-0.11.1.
|
||||
* lib-link.m4: New file, from gettext-0.11.1.
|
||||
* lib-prefix.m4: New file, from gettext-0.11.1.
|
||||
* progtest.m4: New file, from gettext-0.11.1.
|
||||
* Makefile.am (EXTRA_DIST): Add the new files.
|
||||
|
||||
2002-05-13 gettextize <bug-gnu-gettext@gnu.org>
|
||||
|
||||
* codeset.m4: New file, from gettext-0.11.1.
|
||||
|
@ -22,7 +22,8 @@ libgncmod_backend_postgres_la_SOURCES = \
|
||||
price.c \
|
||||
txn.c \
|
||||
txnmass.c \
|
||||
upgrade.c
|
||||
upgrade.c \
|
||||
putil.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
PostgresBackend.h \
|
||||
|
@ -70,10 +70,10 @@
|
||||
#include "txnmass.h"
|
||||
#include "upgrade.h"
|
||||
|
||||
#include "putil.h"
|
||||
|
||||
static short module = MOD_BACKEND;
|
||||
|
||||
#include "putil.h"
|
||||
|
||||
static void pgendInit (PGBackend *be);
|
||||
|
||||
static const char * pgendSessionGetMode (PGBackend *be);
|
||||
@ -1127,7 +1127,6 @@ pgendSessionGetMode (PGBackend *be)
|
||||
return "POLL";
|
||||
case MODE_EVENT:
|
||||
return "EVENT";
|
||||
default:
|
||||
}
|
||||
return "ERROR";
|
||||
}
|
||||
|
@ -49,10 +49,10 @@
|
||||
#include "PostgresBackend.h"
|
||||
#include "price.h"
|
||||
|
||||
#include "putil.h"
|
||||
|
||||
static short module = MOD_BACKEND;
|
||||
|
||||
#include "putil.h"
|
||||
|
||||
/* ============================================================= */
|
||||
/* ============================================================= */
|
||||
/* ACCOUNT AND GROUP STUFF */
|
||||
@ -577,6 +577,7 @@ pgend_account_commit_edit (Backend * bend,
|
||||
{
|
||||
AccountGroup *parent;
|
||||
char *p;
|
||||
GNCBackendError err;
|
||||
PGBackend *be = (PGBackend *)bend;
|
||||
|
||||
ENTER ("be=%p, acct=%p", be, acct);
|
||||
@ -624,15 +625,18 @@ pgend_account_commit_edit (Backend * bend,
|
||||
if (acct->do_free)
|
||||
{
|
||||
const GUID *guid = xaccAccountGetGUID(acct);
|
||||
pgendStoreAuditAccount (be, acct, SQL_DELETE);
|
||||
pgendKVPDelete (be, acct->idata);
|
||||
|
||||
p = be->buff; *p = 0;
|
||||
p = stpcpy (p, "DELETE FROM gncAccount WHERE accountGuid='");
|
||||
p = guid_to_string_buff (guid, p);
|
||||
p = stpcpy (p, "';");
|
||||
SEND_QUERY (be,be->buff,);
|
||||
FINISH_QUERY(be->connection);
|
||||
err = sendQuery (be,be->buff);
|
||||
if (err == ERR_BACKEND_NO_ERR) {
|
||||
err = finishQuery(be);
|
||||
if (err > 0) /* if the number of rows deleted is 0 */
|
||||
pgendStoreAuditAccount (be, acct, SQL_DELETE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
106
src/backend/postgres/putil.c
Normal file
106
src/backend/postgres/putil.c
Normal file
@ -0,0 +1,106 @@
|
||||
/********************************************************************\
|
||||
* putil.c -- utility macros for the postgres backend *
|
||||
* *
|
||||
* 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 *
|
||||
\********************************************************************/
|
||||
|
||||
/*
|
||||
* FILE:
|
||||
* putil.c
|
||||
*
|
||||
* FUNCTION:
|
||||
* Postgres backend utility macros
|
||||
*
|
||||
* HISTORY:
|
||||
* Copyright (c) 2002 Matthew Vanecek <mevanecek@yahoo.com>
|
||||
*
|
||||
*/
|
||||
|
||||
static short module = MOD_BACKEND;
|
||||
|
||||
#include "putil.h"
|
||||
|
||||
/* ============================================================= */
|
||||
/* The sendQuery function sends the sql statement off to the server.
|
||||
* It performs a minimal check to see that the send succeeded. The
|
||||
* return value indicates success or failure of the send.
|
||||
*/
|
||||
int sendQuery(PGBackend *be,char * buff) {
|
||||
int rc = 0;
|
||||
|
||||
ENTER(" ");
|
||||
if (NULL == be->connection) return ERR_BACKEND_CONN_LOST;
|
||||
PINFO("Connectionn is %p", be->connection);
|
||||
PINFO ("sending query %s", buff);
|
||||
rc = PQsendQuery (be->connection, buff);
|
||||
if (!rc) {
|
||||
gchar * msg = (gchar *)PQerrorMessage(be->connection);
|
||||
PERR("send query failed:\n"
|
||||
"\t%s", msg);
|
||||
xaccBackendSetMessage(&be->be, msg);
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_SERVER_ERR);
|
||||
return ERR_BACKEND_SERVER_ERR;
|
||||
}
|
||||
LEAVE("PQsendQuery rc = %d", rc);
|
||||
return ERR_BACKEND_NO_ERR;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* The finishQuery function makes sure that the previously sent
|
||||
* query completed with no errors. It assumes that the query
|
||||
* does not produce any results; if it did those results are
|
||||
* discarded (only error conditions are checked for). The number of
|
||||
* rows affected by the query is returned.
|
||||
*/
|
||||
|
||||
int finishQuery(PGBackend *be) {
|
||||
int i=0;
|
||||
PGresult *result;
|
||||
|
||||
ENTER(" ");
|
||||
/* complete/commit the transaction, check the status */
|
||||
PINFO("Connection is %p", be->connection);
|
||||
do {
|
||||
int x;
|
||||
ExecStatusType status;
|
||||
result = PQgetResult(be->connection);
|
||||
if (!result) {
|
||||
PINFO("Result is (null)");
|
||||
break;
|
||||
}
|
||||
|
||||
status = PQresultStatus(result);
|
||||
x = atoi(PQcmdTuples(result));
|
||||
PINFO("Result status: %s, rows affected: %d, by %s",
|
||||
PQresStatus(status), x, PQcmdStatus(result));
|
||||
i += x;
|
||||
|
||||
if (PGRES_COMMAND_OK != status) {
|
||||
gchar * msg = (gchar *)PQerrorMessage(be->connection);
|
||||
PERR("finish query failed:\n\t%s", msg);
|
||||
PQclear(result);
|
||||
xaccBackendSetMessage(&be->be, msg);
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_SERVER_ERR);
|
||||
break;
|
||||
}
|
||||
PQclear(result);
|
||||
} while (result);
|
||||
|
||||
LEAVE("%d rows affected by SQL statement", i);
|
||||
return i;
|
||||
}
|
@ -68,6 +68,9 @@ gpointer pgendGetResults (PGBackend *be,
|
||||
*/
|
||||
gnc_commodity * gnc_string_to_commodity (const char *str, GNCBook *book);
|
||||
|
||||
int sendQuery(PGBackend *be,char * buff);
|
||||
int finishQuery(PGBackend *be);
|
||||
|
||||
/* hack alert -- calling PQfinish() on error is quite harsh, since
|
||||
* all subsequent sql queries will fail. On the other hand, killing
|
||||
* anything that follows *is* a way of minimizing data corruption
|
||||
@ -89,12 +92,11 @@ gnc_commodity * gnc_string_to_commodity (const char *str, GNCBook *book);
|
||||
rc = PQsendQuery (be->connection, buff); \
|
||||
if (!rc) \
|
||||
{ \
|
||||
gchar * msg = (gchar *)PQerrorMessage(be->connection); \
|
||||
/* hack alert -- we need kinder, gentler error handling */\
|
||||
PERR("send query failed:\n" \
|
||||
"\t%s", PQerrorMessage(be->connection)); \
|
||||
PQfinish (be->connection); \
|
||||
be->connection = NULL; \
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_CONN_LOST); \
|
||||
PERR("send query failed:\n\t%s", msg); \
|
||||
xaccBackendSetMessage (&be->be, msg); \
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_SERVER_ERR); \
|
||||
return retval; \
|
||||
} \
|
||||
}
|
||||
@ -112,6 +114,7 @@ gnc_commodity * gnc_string_to_commodity (const char *str, GNCBook *book);
|
||||
PGresult *result; \
|
||||
/* complete/commit the transaction, check the status */ \
|
||||
do { \
|
||||
gchar *msg = NULL; \
|
||||
ExecStatusType status; \
|
||||
result = PQgetResult((conn)); \
|
||||
if (!result) break; \
|
||||
@ -121,9 +124,8 @@ gnc_commodity * gnc_string_to_commodity (const char *str, GNCBook *book);
|
||||
PERR("finish query failed:\n" \
|
||||
"\t%s", PQerrorMessage((conn))); \
|
||||
PQclear(result); \
|
||||
PQfinish ((conn)); \
|
||||
be->connection = NULL; \
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_CONN_LOST); \
|
||||
xaccBackendSetMessage (&be->be, msg); \
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_SERVER_ERR); \
|
||||
break; \
|
||||
} \
|
||||
PQclear(result); \
|
||||
|
@ -474,13 +474,20 @@ xaccAccountCommitEdit (Account *acc)
|
||||
|
||||
if (ERR_BACKEND_NO_ERR != errcode)
|
||||
{
|
||||
char * err;
|
||||
/* destroys must be rolled back as well ... ??? */
|
||||
acc->do_free = FALSE;
|
||||
/* XXX hack alert FIXME implement account rollback */
|
||||
PERR (" backend asked engine to rollback, but this isn't"
|
||||
" handled yet. Return code=%d", errcode);
|
||||
err = xaccBackendGetMessage(be);
|
||||
PWARN_GUI("Error occurred while saving Account:\n%d: %s",
|
||||
xaccBackendGetError(be), err);
|
||||
|
||||
/* push error back onto the stack */
|
||||
xaccBackendSetError (be, errcode);
|
||||
xaccBackendSetMessage (be, err);
|
||||
g_free(err);
|
||||
}
|
||||
}
|
||||
acc->core_dirty = FALSE;
|
||||
|
@ -22,7 +22,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "Account.h"
|
||||
@ -35,6 +35,7 @@
|
||||
#include "gnc-pricedb.h"
|
||||
#include "gnc-pricedb-p.h"
|
||||
#include "TransactionP.h"
|
||||
#include "messages.h"
|
||||
|
||||
/* static short module = MOD_ENGINE; */
|
||||
|
||||
@ -64,6 +65,45 @@ xaccBackendGetError (Backend *be)
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
xaccBackendSetMessage (Backend *be, const char *format, ...) {
|
||||
va_list args;
|
||||
char * buffer;
|
||||
|
||||
if (!be) return;
|
||||
|
||||
va_start(args, format);
|
||||
buffer = (char *)g_strdup_vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
/* If there's already something here, free it */
|
||||
if (be->error_msg) g_free(be->error_msg);
|
||||
|
||||
be->error_msg = buffer;
|
||||
}
|
||||
|
||||
/* This should always return a valid char * */
|
||||
char *
|
||||
xaccBackendGetMessage (Backend *be) {
|
||||
char * msg;
|
||||
|
||||
if (!be) return g_strdup(_("ERR_BACKEND_NO_BACKEND"));
|
||||
if (!be->error_msg) return g_strdup(_("No error message"));
|
||||
|
||||
/*
|
||||
* Just return the contents of the error_msg and then set it to
|
||||
* NULL. This is necessary, because the Backends don't seem to
|
||||
* have a destroy_backend function to take care if freeing stuff
|
||||
* up. The calling function should free the copy.
|
||||
* Also, this is consistent with the xaccBackendGetError() popping.
|
||||
*/
|
||||
|
||||
msg = be->error_msg;
|
||||
be->error_msg = NULL;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* Fetch the backend *
|
||||
\********************************************************************/
|
||||
@ -123,7 +163,8 @@ xaccInitBackend(Backend *be)
|
||||
be->process_events = NULL;
|
||||
|
||||
be->last_err = ERR_BACKEND_NO_ERR;
|
||||
|
||||
if (be->error_msg) g_free (be->error_msg);
|
||||
be->error_msg = NULL;
|
||||
be->percentage = NULL;
|
||||
|
||||
be->export = NULL;
|
||||
|
@ -257,6 +257,7 @@ struct backend_s
|
||||
GNCBePercentageFunc percentage;
|
||||
|
||||
GNCBackendError last_err;
|
||||
char * error_msg;
|
||||
|
||||
/* Export should really _NOT_ be here, but is left here for now */
|
||||
void (*export) (Backend *, GNCBook *);
|
||||
@ -268,10 +269,18 @@ struct backend_s
|
||||
*
|
||||
* The xaccBackendGetError() routine pops an error code off the error
|
||||
* stack.
|
||||
*
|
||||
* The xaccBackendSetMessage() assigns a string to the backend error
|
||||
* message.
|
||||
*
|
||||
* The xaccBackendGetMessage() pops the error message string from
|
||||
* the Backend. This string should be freed with g_free().
|
||||
*/
|
||||
|
||||
void xaccBackendSetError (Backend *be, GNCBackendError err);
|
||||
GNCBackendError xaccBackendGetError (Backend *be);
|
||||
void xaccBackendSetMessage(Backend *be, const char *format, ...);
|
||||
char * xaccBackendGetMessage(Backend *be);
|
||||
|
||||
/*
|
||||
* The xaccGetAccountBackend() subroutine will find the
|
||||
|
@ -320,6 +320,31 @@ gnc_session_load_backend(GNCSession * session, char * backend_name)
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static void
|
||||
gnc_session_destroy_backend (GNCSession *session)
|
||||
{
|
||||
g_return_if_fail (session);
|
||||
|
||||
if (session->backend)
|
||||
{
|
||||
/* clear any error message */
|
||||
char * msg = xaccBackendGetMessage (session->backend);
|
||||
g_free (msg);
|
||||
|
||||
/* Then destroy the backend */
|
||||
if (session->backend->destroy_backend)
|
||||
{
|
||||
session->backend->destroy_backend(session->backend);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(session->backend);
|
||||
}
|
||||
}
|
||||
|
||||
session->backend = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_session_begin (GNCSession *session, const char * book_id,
|
||||
gboolean ignore_lock, gboolean create_if_nonexistent)
|
||||
@ -365,16 +390,7 @@ gnc_session_begin (GNCSession *session, const char * book_id,
|
||||
PINFO ("logpath=%s", session->logpath ? session->logpath : "(null)");
|
||||
|
||||
/* destroy the old backend */
|
||||
if (session->backend && session->backend->destroy_backend)
|
||||
{
|
||||
session->backend->destroy_backend(session->backend);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(session->backend);
|
||||
}
|
||||
|
||||
session->backend = NULL;
|
||||
gnc_session_destroy_backend(session);
|
||||
|
||||
/* check to see if this is a type we know how to handle */
|
||||
if (!g_strncasecmp(book_id, "file:", 5) ||
|
||||
@ -719,14 +735,7 @@ gnc_session_destroy (GNCSession *session)
|
||||
gnc_session_end (session);
|
||||
|
||||
/* destroy the backend */
|
||||
if (session->backend && session->backend->destroy_backend)
|
||||
{
|
||||
session->backend->destroy_backend(session->backend);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(session->backend);
|
||||
}
|
||||
gnc_session_destroy_backend(session);
|
||||
|
||||
for (node=session->books; node; node=node->next)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user