/* See the copyright notice (COPYRIGHT) in this directory. */

/*
 * NAME
 *	pg_begin_tran ()- start a multistatement transaction
 *	pg_commit()	- end a transaction, saving changes
 *	pg_rollback()	- end a transaction, discarding changes
 *	pg_savepoint()	- no effect for Postgres, here for GDI compatibility
 *
 * SYNOPSIS
 *
 *	#include "libgendb.h"
 *	#include "gdi_postgres.h"
 *
 * DESCRIPTION
 *	This file contains functions for POSTGRES transaction management.
 *
 *	For now, we track transaction state in the vendor conn.  This
 *	could be perilous since we might not know all the conditions under
 *	which a transaction might be automatically aborted.
 *
 * DIAGNOSTICS
 *	Functions which return pointers will return NULL if an error
 *	occurred.  Functions which return a non-negative int will return 
 *	-1 if an error occurred.
 *
 * FILES
 *	pg_tran.c (this file)
 *
 * AUTHOR
 *	Jean Anderson
 */
#ifndef	lint
static char SccsId[] = "@(#)pg_tran.c	16.2 8/7/93 Copyright (c) 1992-1993 Science Applications International Corporation";
#endif

#include "gdi_postgres.h"

/*
 * pg_begin_tran ()
 *
 * Begin a POSTGRES database transaction.
 *
 * Public
 */

dbStatus
pg_begin_tran (conn, channo, tran_name)
dbConn	*conn;		/* We track transactions in the vendor conn */
int     channo;		/* not used for POSTGRES */
char	*tran_name;	/* not used for POSTGRES */
{
	char *r="pg_begin_tran";
	char *res;

	if ((conn == NULL) || (conn->vendor_conn == NULL))
	{
		gdi_error_app (conn, GDI_NOCONNECT,
			"pg_begin_tran: Not connected to database");
		return (GDI_FAILURE);
	}

	if ( PG_TRAN(conn) == FALSE)
	{
		PG_TRAN(conn) = TRUE;

	        if (conn->debug == GDI_DEBUG_VERBOSE)
                     fprintf(stderr, "%16s: starting transaction \n", r);

		res = (char *) PQexec("begin");
		if( pg_error(conn, GDI_NOT_USED, res, "pg_begin_tran")
			!= GDI_SUCCESS)
			return(GDI_FAILURE);

	}
	else if (conn->debug == GDI_DEBUG_VERBOSE)
                fprintf(stderr, "%16s: a transaction is already live.\n", r);

	return (GDI_SUCCESS);
}

/*
 * pg_commit ()
 *
 * Commit an POSTGRES database transaction.
 *
 * Public
 */

dbStatus
pg_commit (conn, channo)
dbConn	*conn;
int     channo;	/* Note: channo is ignored; not application to POSTGRES */
{
	char *r="pg_commit";
	char *res;

	if ((conn == NULL) || (conn->vendor_conn == NULL))
	{
		gdi_error_app (conn, GDI_NOCONNECT,
			"pg_commit: Not connected to database");
		return (GDI_FAILURE);
	}

		/* Only end a transaction if one is alive */
	if( PG_TRAN(conn) == TRUE )
	{
		PG_TRAN(conn) = FALSE;

	        if (conn->debug == GDI_DEBUG_VERBOSE)
                     fprintf(stderr, "%16s: committing transaction\n", r);

		res=PQexec("end");
		if( pg_error(conn, GDI_NOT_USED, res, "pg_commit") 
			!= GDI_SUCCESS)
			return(GDI_FAILURE);
	}
	else if (conn->debug == GDI_DEBUG_VERBOSE)
		fprintf(stderr, "%16s: no transaction to commit.\n", r);

	return (GDI_SUCCESS);
}

/*
 * pg_rollback ()
 *
 * Rollback an POSTGRES database transaction.
 *
 * Public
 */

dbStatus
pg_rollback (conn, channo)
dbConn	*conn;
int	channo;
{
	char *r="pg_rollback";
	char *res;
	if ((conn == NULL) || (conn->vendor_conn == NULL))
	{
		gdi_error_app (conn, GDI_NOCONNECT,
			"pg_rollback: Not connected to database");
		return (GDI_FAILURE);
	}

	if ( PG_TRAN(conn) == TRUE )
	{
                /* If the abort fails, it means there isn't a transaction
                 * so we still want to set transaction false.
                 */

		PG_TRAN(conn) = FALSE;

	        if (conn->debug == GDI_DEBUG_VERBOSE)
                     fprintf(stderr, "%16s: aborting transaction\n", r);

		res=PQexec("abort");
		if( pg_error(conn, GDI_NOT_USED, res, "pg_rollback")
			!= GDI_SUCCESS)
			return(GDI_FAILURE);

	}
	else if (conn->debug == GDI_DEBUG_VERBOSE)
		fprintf(stderr, "%16s: no transaction to abort.\n", r);
     
	return (GDI_SUCCESS);
}


/*
 * pg_savepoint ()
 *
 * Dummy placeholder for GDI compatibility; gets ignored.
 *
 * Public
 */

dbStatus
pg_savepoint (conn, channo, sname)
dbConn	*conn;
int	channo;
char	*sname;
{
	fprintf(stderr, "pg_savepoint: %s\n", PG_NA_S);
	return (GDI_SUCCESS);
}
