From c404d91c0bf15442a3dc38644263a05e258c3c52 Mon Sep 17 00:00:00 2001
From: "Thomas G. Lockhart" <lockhart@fourpalms.org>
Date: Wed, 25 Oct 2000 14:15:49 +0000
Subject: [PATCH] From Zoltan Kovacs back in April (sorry for the delay
 Zoltan!):

I modified the current ODBC driver for

* referential integrity error reporting,
* SELECT in transactions and
* disabling autocommit.

I tested these changes with Borland C++ Builder -> ODBCExpress ->
WinODBC driver (DLL) -> Postgres 7.0beta1 and Borland C++ Builder -> BDE ->
WinODBC driver (DLL) -> Postgres 7.0beta1. The patch is based on snapshot of
22th April (I don't think that someone has modified it since that: Byron
hasn't gave any sign of living for about a month and I didn't find any
comments about the ODBC driver on the list).
---
 src/interfaces/odbc/connection.c | 23 +++++++++++++++++++++--
 src/interfaces/odbc/options.c    |  9 +++++++++
 src/interfaces/odbc/statement.c  | 23 +++++++++++++++++------
 3 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c
index e3d444997ec..d5b0d12dffe 100644
--- a/src/interfaces/odbc/connection.c
+++ b/src/interfaces/odbc/connection.c
@@ -947,6 +947,19 @@ char cmdbuffer[MAX_MESSAGE_LEN+1];	/* QR_set_command() dups this string so dont
 					case 'E':
 						SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 						qlog("ERROR from backend during clear: '%s'\n", cmdbuffer);
+						/* We must report this type of error as well
+						   (practically for reference integrity violation
+						   error reporting, from PostgreSQL 7.0).
+						   (Zoltan Kovacs, 04/26/2000)
+						*/
+						self->errormsg = cmdbuffer;
+						if ( ! strncmp(self->errormsg, "FATAL", 5)) {
+						    self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
+						    CC_set_no_trans(self);
+						    }
+						else 
+						    self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
+						QR_set_status(res, PGRES_NONFATAL_ERROR);
 						break;
 					}
 				}
@@ -1001,14 +1014,20 @@ char cmdbuffer[MAX_MESSAGE_LEN+1];	/* QR_set_command() dups this string so dont
 			mylog("send_query: 'E' - %s\n", self->errormsg);
 			qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
 
+			/* We should report that an error occured. Zoltan */
+			res = QR_Constructor();
+
 			if ( ! strncmp(self->errormsg, "FATAL", 5)) {
 				self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
 				CC_set_no_trans(self);
+				QR_set_status(res, PGRES_FATAL_ERROR);
 			}
-			else
+			else {
 				self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
+				QR_set_status(res, PGRES_NONFATAL_ERROR);
+			}
 
-			return NULL;
+			return res; /* instead of NULL. Zoltan */
 
 		case 'P' : /* get the Portal name */
 			SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
diff --git a/src/interfaces/odbc/options.c b/src/interfaces/odbc/options.c
index eb67dd590fa..217f063338e 100644
--- a/src/interfaces/odbc/options.c
+++ b/src/interfaces/odbc/options.c
@@ -330,6 +330,15 @@ int i;
 		switch(vParam) {
 		case SQL_AUTOCOMMIT_OFF:
 			CC_set_autocommit_off(conn);
+		/* The following two lines are new.
+		   With this modification the SELECT statements
+		   are also included in the transactions.
+		   Error handling should be written, 
+		   this is missing yet, see
+		   SC_execute in statement.c for details. Zoltan
+		*/    
+			CC_send_query(conn,"BEGIN",NULL);
+			CC_set_in_trans(conn);
 			break;
 
 		case SQL_AUTOCOMMIT_ON:
diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c
index 95c9e8986e7..0fac4d6bc08 100644
--- a/src/interfaces/odbc/statement.c
+++ b/src/interfaces/odbc/statement.c
@@ -748,8 +748,14 @@ QueryInfo qi;
 	/*	Begin a transaction if one is not already in progress */
 	/*	The reason is because we can't use declare/fetch cursors without
 		starting a transaction first.
+
+		A transaction should be begun if and only if
+		we use declare/fetch and the statement is SELECT.
+		We assume that the Postgres backend has an autocommit
+		feature as default. (Zoltan Kovacs, 04/26/2000)
 	*/
-	if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
+	// if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
+	if ( ! self->internal && ! CC_is_in_trans(conn) && globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) {
 
 		mylog("   about to begin a transaction on statement = %u\n", self);
 		res = CC_send_query(conn, "BEGIN", NULL);
@@ -826,11 +832,14 @@ QueryInfo qi;
 		self->result = CC_send_query(conn, self->stmt_with_params, NULL);
 
 		/*	If we are in autocommit, we must send the commit. */
-		if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
+		/*	No, we shouldn't. Postgres backend does the
+			autocommit if neccessary. (Zoltan, 04/26/2000)
+		*/
+/*		if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
 	    res = CC_send_query(conn, "COMMIT", NULL);
 	    QR_Destructor(res);
 	    CC_set_no_trans(conn);
-		}
+		}*/		
 
 	}
 
@@ -889,10 +898,12 @@ QueryInfo qi;
 	if (self->errornumber == STMT_OK)
 		return SQL_SUCCESS;
 
-	else if (self->errornumber == STMT_INFO_ONLY)
-		return SQL_SUCCESS_WITH_INFO;
-
 	else {
+		// Modified, 04/29/2000, Zoltan
+		if (self->errornumber == STMT_INFO_ONLY)
+		    self->errormsg = "Error while executing the query (non-fatal)";
+		else
+		    self->errormsg = "Unknown error";
 		SC_log_error(func, "", self);
 		return SQL_ERROR;
 	}
-- 
GitLab