From 9c50a0047fcaaa2e9d85620418c71132461ac550 Mon Sep 17 00:00:00 2001
From: Hiroshi Inoue <inoue@tpf.co.jp>
Date: Wed, 20 Jun 2001 07:06:40 +0000
Subject: [PATCH] Change the driver so that large error messages are returned
 by multiple SQLError calls.

---
 src/interfaces/odbc/environ.c   | 40 ++++++++++++++++++++++++++++++---
 src/interfaces/odbc/statement.c | 10 ++++++++-
 src/interfaces/odbc/statement.h |  2 ++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/src/interfaces/odbc/environ.c b/src/interfaces/odbc/environ.c
index 5a6b6b11a3b..506ca5cf7ba 100644
--- a/src/interfaces/odbc/environ.c
+++ b/src/interfaces/odbc/environ.c
@@ -91,12 +91,16 @@ SQLError(
 	char	   *msg;
 	int			status;
 
-	mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u\n", henv, hdbc, hstmt);
+	mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u <%d>\n", henv, hdbc, hstmt, cbErrorMsgMax);
 
+	if (cbErrorMsgMax < 0)
+		return SQL_ERROR;
 	if (SQL_NULL_HSTMT != hstmt)
 	{
 		/* CC: return an error of a hstmt  */
 		StatementClass *stmt = (StatementClass *) hstmt;
+		SWORD	msglen;
+		BOOL	once_again = FALSE;
 
 		if (SC_get_error(stmt, &status, &msg))
 		{
@@ -112,8 +116,18 @@ SQLError(
 
 				return SQL_NO_DATA_FOUND;
 			}
+			msglen = (SWORD) strlen(msg);
 			if (NULL != pcbErrorMsg)
-				*pcbErrorMsg = (SWORD) strlen(msg);
+			{
+				*pcbErrorMsg = msglen;
+				if (cbErrorMsgMax == 0)
+					once_again = TRUE;
+				else if (msglen >= cbErrorMsgMax)
+				{
+					once_again = TRUE;
+					*pcbErrorMsg = cbErrorMsgMax - 1;
+				}
+			}
 
 			if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
 				strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
@@ -238,7 +252,27 @@ SQLError(
 			return SQL_NO_DATA_FOUND;
 		}
 
-		return SQL_SUCCESS;
+		if (once_again)
+		{
+			int	outlen;
+			stmt->errornumber = status;
+			if (cbErrorMsgMax > 0)
+				outlen = *pcbErrorMsg;
+			else
+				outlen = 0;
+			if (!stmt->errormsg_malloced || !stmt->errormsg)
+			{
+				stmt->errormsg = malloc(msglen - outlen + 1);
+				stmt->errormsg_malloced = TRUE;
+			}
+			memmove(stmt->errormsg, msg + outlen, msglen - outlen + 1);
+		}
+		else if (stmt->errormsg_malloced)
+			SC_clear_error(stmt);
+		if (cbErrorMsgMax == 0)
+			return SQL_SUCCESS_WITH_INFO;
+		else
+			return SQL_SUCCESS;
 	}
 	else if (SQL_NULL_HDBC != hdbc)
 	{
diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c
index ba6ca3efbd4..fd77eee6d6c 100644
--- a/src/interfaces/odbc/statement.c
+++ b/src/interfaces/odbc/statement.c
@@ -248,6 +248,7 @@ SC_Constructor(void)
 		rv->errormsg = NULL;
 		rv->errornumber = 0;
 		rv->errormsg_created = FALSE;
+		rv->errormsg_malloced = FALSE;
 
 		rv->statement = NULL;
 		rv->stmt_with_params = NULL;
@@ -530,9 +531,12 @@ SC_recycle_statement(StatementClass *self)
 	self->bind_row = 0;
 	self->last_fetch_count = 0;
 
+	if (self->errormsg_malloced && self->errormsg)
+		free(self->errormsg);
 	self->errormsg = NULL;
 	self->errornumber = 0;
 	self->errormsg_created = FALSE;
+	self->errormsg_malloced = FALSE;
 
 	self->lobj_fd = -1;
 
@@ -610,9 +614,12 @@ SC_unbind_cols(StatementClass *self)
 void
 SC_clear_error(StatementClass *self)
 {
+	if (self->errormsg_malloced && self->errormsg)
+		free(self->errormsg);
 	self->errornumber = 0;
 	self->errormsg = NULL;
 	self->errormsg_created = FALSE;
+	self->errormsg_malloced = FALSE;
 }
 
 
@@ -675,7 +682,8 @@ SC_get_error(StatementClass *self, int *number, char **message)
 	{
 		*number = self->errornumber;
 		*message = self->errormsg;
-		self->errormsg = NULL;
+		if (!self->errormsg_malloced)
+			self->errormsg = NULL;
 	}
 
 	rv = (self->errornumber != 0);
diff --git a/src/interfaces/odbc/statement.h b/src/interfaces/odbc/statement.h
index fe0b4a0b720..3f2fef5db7d 100644
--- a/src/interfaces/odbc/statement.h
+++ b/src/interfaces/odbc/statement.h
@@ -218,6 +218,8 @@ struct StatementClass_
 	char		pre_executing;	/* This statement is prematurely executing */
 	char		inaccurate_result;		/* Current status is PREMATURE but
 										 * result is inaccurate */
+	char		errormsg_malloced;		/* Current status is PREMATURE but
+										 * result is inaccurate */
 };
 
 #define SC_get_conn(a)	  (a->hdbc)
-- 
GitLab