From 76d38cb0c693985f8a2473e1bcd2ff093aebfe62 Mon Sep 17 00:00:00 2001
From: Hiroshi Inoue <inoue@tpf.co.jp>
Date: Tue, 19 Jun 2001 02:17:06 +0000
Subject: [PATCH] Changed the error handling as follows. 1) ERRORs cause an
 SQL_ERROR and the SQLSTATE='S1000'. 2) NOTICEs cause an SQL_SUCCESS_WITH_INFO
 and the succeeding    SQLError() returns the NOTICE message.

---
 src/interfaces/odbc/connection.c | 60 ++++++++++++++++++++++----------
 src/interfaces/odbc/socket.c     |  6 ++--
 src/interfaces/odbc/socket.h     |  2 +-
 src/interfaces/odbc/statement.c  | 11 +++---
 4 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c
index c853cdb79ba..90fc132b981 100644
--- a/src/interfaces/odbc/connection.c
+++ b/src/interfaces/odbc/connection.c
@@ -916,6 +916,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 	int			id;
 	SocketClass *sock = self->sock;
 	int		maxlen;
+	BOOL		msg_truncated;
 
 	/* ERROR_MSG_LENGTH is suffcient */
 	static char msgbuffer[ERROR_MSG_LENGTH + 1];
@@ -1004,6 +1005,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 					self->errormsg = "No response from backend while receiving a portal query command";
 					mylog("send_query: 'C' - %s\n", self->errormsg);
 					CC_set_no_trans(self);
+					if (res)
+						QR_Destructor(res);
 					return NULL;
 				}
 				else
@@ -1018,7 +1021,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 					mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
 
 					/* Only save the first command */
-					QR_set_status(res, PGRES_COMMAND_OK);
+					if (QR_command_successful(res))
+						QR_set_status(res, PGRES_COMMAND_OK);
 					QR_set_command(res, cmdbuffer);
 
 					/*
@@ -1049,11 +1053,16 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 								qlog("Command response: '%s'\n", cmdbuffer);
 								break;
 							case 'N':
-								SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+								msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+								if (QR_command_successful(res))
+									QR_set_status(res, PGRES_NONFATAL_ERROR);
+								QR_set_notice(res, cmdbuffer);	/* will dup this string */
 								qlog("NOTICE from backend during clear: '%s'\n", cmdbuffer);
+								while (msg_truncated)
+									msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 								break;
 							case 'E':
-								SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+								msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 								qlog("ERROR from backend during clear: '%s'\n", cmdbuffer);
 
 								/*
@@ -1071,8 +1080,10 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 								}
 								else
 									self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
-								QR_set_status(res, PGRES_NONFATAL_ERROR);
+								QR_set_status(res, PGRES_FATAL_ERROR);
 								QR_set_aborted(res, TRUE);
+								while (msg_truncated)
+									msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 								break;
 						}
 					}
@@ -1088,14 +1099,17 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 			case 'Z':			/* Backend is ready for new query (6.4) */
 				break;
 			case 'N':			/* NOTICE: */
-				SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-
-				res = QR_Constructor();
-				QR_set_status(res, PGRES_NONFATAL_ERROR);
+				msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+				if (!res)
+					res = QR_Constructor();
+				if (QR_command_successful(res))
+					QR_set_status(res, PGRES_NONFATAL_ERROR);
 				QR_set_notice(res, cmdbuffer);	/* will dup this string */
 
 				mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
 				qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
+				while (msg_truncated)
+					msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 
 				continue;		/* dont return a result -- continue
 								 * reading */
@@ -1107,20 +1121,22 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 				{
 					self->errornumber = CONNECTION_BACKEND_CRAZY;
 					self->errormsg = "Unexpected protocol character from backend (send_query - I)";
-					res = QR_Constructor();
+					if (!res)
+						res = QR_Constructor();
 					QR_set_status(res, PGRES_FATAL_ERROR);
 					return res;
 				}
 				else
 				{
 					/* We return the empty query */
-					res = QR_Constructor();
+					if (!res)
+						res = QR_Constructor();
 					QR_set_status(res, PGRES_EMPTY_QUERY);
 					return res;
 				}
 				break;
 			case 'E':
-				SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+				msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
 
 				/* Remove a newline */
 				if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer) - 1] == '\n')
@@ -1132,20 +1148,22 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 				qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
 
 				/* We should report that an error occured. Zoltan */
-				res = QR_Constructor();
+				if (!res)
+					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
 				{
 					self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
-					QR_set_status(res, PGRES_NONFATAL_ERROR);
 				}
+				QR_set_status(res, PGRES_FATAL_ERROR);
 				QR_set_aborted(res, TRUE);
+				while (msg_truncated)
+					msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 
 				return res;		/* instead of NULL. Zoltan */
 
@@ -1188,12 +1206,16 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 
 				return result_in;
 			case 'D':			/* Copy in command began successfully */
-				res = QR_Constructor();
-				QR_set_status(res, PGRES_COPY_IN);
+				if (!res)
+					res = QR_Constructor();
+				if (QR_command_successful(res))
+					QR_set_status(res, PGRES_COPY_IN);
 				return res;
 			case 'B':			/* Copy out command began successfully */
-				res = QR_Constructor();
-				QR_set_status(res, PGRES_COPY_OUT);
+				if (!res)
+					res = QR_Constructor();
+				if (QR_command_successful(res))
+					QR_set_status(res, PGRES_COPY_OUT);
 				return res;
 			default:
 				self->errornumber = CONNECTION_BACKEND_CRAZY;
@@ -1201,6 +1223,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 				CC_set_no_trans(self);
 
 				mylog("send_query: error - %s\n", self->errormsg);
+				if (res)
+					QR_Destructor(res);
 				return NULL;
 		}
 	}
diff --git a/src/interfaces/odbc/socket.c b/src/interfaces/odbc/socket.c
index 650ec9ecb00..de695058b9c 100644
--- a/src/interfaces/odbc/socket.c
+++ b/src/interfaces/odbc/socket.c
@@ -195,17 +195,19 @@ SOCK_put_n_char(SocketClass *self, char *buffer, int len)
 /*
  *	bufsize must include room for the null terminator
  *	will read at most bufsize-1 characters + null.
+ *	returns TRUE if truncation occurs.
  */
-void
+BOOL
 SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
 {
 	register int lf = 0;
 
 	for (lf = 0; lf < bufsize; lf++)
 		if (!(buffer[lf] = SOCK_get_next_byte(self)))
-			return;
+			return FALSE;
 
 	buffer[bufsize - 1] = '\0';
+	return TRUE;
 }
 
 
diff --git a/src/interfaces/odbc/socket.h b/src/interfaces/odbc/socket.h
index 67391767384..b4a55e57db6 100644
--- a/src/interfaces/odbc/socket.h
+++ b/src/interfaces/odbc/socket.h
@@ -86,7 +86,7 @@ void		SOCK_Destructor(SocketClass *self);
 char		SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname);
 void		SOCK_get_n_char(SocketClass *self, char *buffer, int len);
 void		SOCK_put_n_char(SocketClass *self, char *buffer, int len);
-void		SOCK_get_string(SocketClass *self, char *buffer, int bufsize);
+BOOL		SOCK_get_string(SocketClass *self, char *buffer, int bufsize);
 void		SOCK_put_string(SocketClass *self, char *string);
 int			SOCK_get_int(SocketClass *self, short len);
 void		SOCK_put_int(SocketClass *self, int value, short len);
diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c
index 83dd58ba8f2..ba6ca3efbd4 100644
--- a/src/interfaces/odbc/statement.c
+++ b/src/interfaces/odbc/statement.c
@@ -652,6 +652,8 @@ SC_create_errormsg(StatementClass *self)
 			sprintf(&msg[pos], ";\n%s", sock->errormsg);
 		}
 	}
+	if (!msg[0] && res && QR_get_notice(res))
+		return QR_get_notice(res);
 
 	return msg;
 }
@@ -1044,14 +1046,11 @@ SC_execute(StatementClass *self)
 
 	if (self->errornumber == STMT_OK)
 		return SQL_SUCCESS;
-
+	else if (self->errornumber == STMT_INFO_ONLY)
+		return SQL_SUCCESS_WITH_INFO;
 	else
 	{
-		/* Modified, 2000-04-29, Zoltan */
-		if (self->errornumber == STMT_INFO_ONLY)
-			self->errormsg = "Error while executing the query (non-fatal)";
-		else
-			self->errormsg = "Unknown error";
+		self->errormsg = "Error while executing the query";
 		SC_log_error(func, "", self);
 		return SQL_ERROR;
 	}
-- 
GitLab