From 829de424bb5a0c584ae06e607d2d2b94e6fc9bc3 Mon Sep 17 00:00:00 2001
From: Adrian Grucza <adrian.grucza@iress.com>
Date: Mon, 10 Jan 2022 12:33:20 +1100
Subject: [PATCH 2/2] Bug fix: SQLColAttribute returns wrong column name - In
 some circumstances it was returning a name from the previous result

---
 results.c                        |  4 ++
 test/expected/multistmt.out      | 83 +++++++++++++++++++++++++++++++++++-----
 test/src/catalogfunctions-test.c | 14 +++----
 test/src/common.c                | 45 +++++++++++++++++++---
 test/src/common.h                |  4 +-
 test/src/multistmt-test.c        | 15 +++++++-
 6 files changed, 140 insertions(+), 25 deletions(-)

diff --git a/results.c b/results.c
index ec89600..546edd2 100644
--- a/results.c
+++ b/results.c
@@ -630,6 +630,10 @@ MYLOG(DETAIL_LOG_LEVEL, "answering bookmark info\n");
 		ti = fi->ti;
 		field_type = getEffectiveOid(conn, fi);
 	}
+	else
+	{
+		fi = NULL;
+	}
 
 	MYLOG(0, "col %d field_type=%d fi,ti=%p,%p\n", col_idx, field_type, fi, ti);
 
diff --git a/test/expected/multistmt.out b/test/expected/multistmt.out
index 68a9e92..781a936 100644
--- a/test/expected/multistmt.out
+++ b/test/expected/multistmt.out
@@ -1,23 +1,86 @@
 connected
---1 Result set:
+--1
+Result set metadata:
+?column?: INTEGER(10) digits: 0, nullable
+Result set:
+?column?
 1
---2 Result set:
+--2
+Result set metadata:
+?column?: INTEGER(10) digits: 0, nullable
+Result set:
+?column?
 2
---1 Result set:
+--1
+Result set metadata:
+?column?: INTEGER(10) digits: 0, nullable
+Result set:
+?column?
 1
---2 Result set:
+--2
+Result set metadata:
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+Result set:
+?column?	?column?
 foo	bar
---3 Result set:
+--3
+Result set metadata:
+?column?: INTEGER(10) digits: 0, nullable
+Result set:
+?column?
 3
---4 Result set:
+--4
+Result set metadata:
+?column?: INTEGER(10) digits: 0, nullable
+Result set:
+?column?
 4
---1 Result set:
+--1
+Result set metadata:
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+Result set:
+?column?	?column?
 foo	bar
---2 Result set:
+--2
+Result set metadata:
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+Result set:
+?column?
 foobar
+--1
+Result set metadata:
+id: INTEGER(10) digits: 0, not nullable
+t: VARCHAR(20) digits: 0, nullable
+Result set:
+id	t
+1	foo
+2	bar
+3	foobar
+--2
+Result set metadata:
+t: VARCHAR(20) digits: 0, nullable
+result: INTEGER(10) digits: 0, nullable
+Result set:
+t	result
+foo	2
+bar	2
+foobar	2
 # of result cols: 3
---1 Result set:
+--1
+Result set metadata:
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+id: INTEGER(10) digits: 0, not nullable
+t: VARCHAR(20) digits: 0, nullable
+Result set:
+?column?	id	t
 first result set	1	foo
---2 Result set:
+--2
+Result set metadata:
+?column?: LONGVARCHAR(8190) digits: 0, nullable
+t: VARCHAR(20) digits: 0, nullable
+Result set:
+?column?	t
 second result set	bar
 disconnecting
diff --git a/test/src/catalogfunctions-test.c b/test/src/catalogfunctions-test.c
index b93ec69..ae1eb68 100644
--- a/test/src/catalogfunctions-test.c
+++ b/test/src/catalogfunctions-test.c
@@ -79,7 +79,7 @@ main(int argc, char **argv)
 	 * to get the OID in output, and this information looks to be
 	 * enough.
 	 */
-	print_result_series(hstmt, sql_column_ids, 6, -1);
+	print_result_series(hstmt, sql_column_ids, 6, -1, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 
@@ -187,7 +187,7 @@ main(int argc, char **argv)
 				 (SQLCHAR *) "set_byte", SQL_NTS,
 				 NULL, 0);
 	CHECK_STMT_RESULT(rc, "SQLProcedureColumns failed", hstmt);
-	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1);
+	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 	/*
@@ -199,7 +199,7 @@ main(int argc, char **argv)
 				 (SQLCHAR *) "getfoo", SQL_NTS,
 				 NULL, 0);
 	CHECK_STMT_RESULT(rc, "SQLProcedureColumns failed", hstmt);
-	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1);
+	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 	/*
@@ -211,7 +211,7 @@ main(int argc, char **argv)
 				 (SQLCHAR *) "getboo", SQL_NTS,
 				 NULL, 0);
 	CHECK_STMT_RESULT(rc, "SQLProcedureColumns failed", hstmt);
-	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1);
+	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 	/*
@@ -223,7 +223,7 @@ main(int argc, char **argv)
 				 (SQLCHAR *) "tbl_arg", SQL_NTS,
 				 NULL, 0);
 	CHECK_STMT_RESULT(rc, "SQLProcedureColumns failed", hstmt);
-	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1);
+	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 	/*
@@ -236,7 +236,7 @@ main(int argc, char **argv)
 				 (SQLCHAR *) "set_of", SQL_NTS,
 				 NULL, 0);
 	CHECK_STMT_RESULT(rc, "SQLProcedureColumns failed", hstmt);
-	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1);
+	print_result_series(hstmt, sql_pro_column_ids, sizeof(sql_pro_column_ids) / sizeof(sql_pro_column_ids[0]), -1, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 
@@ -248,7 +248,7 @@ main(int argc, char **argv)
 							(SQLCHAR *) "testtab1", SQL_NTS);
 	CHECK_STMT_RESULT(rc, "SQLTablePrivileges failed", hstmt);
 	print_result_meta(hstmt);
-	print_result_series(hstmt, sql_tab_privileges_ids, 6, 5);
+	print_result_series(hstmt, sql_tab_privileges_ids, 6, 5, FALSE);
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 
diff --git a/test/src/common.c b/test/src/common.c
index 076d7ff..656754c 100644
--- a/test/src/common.c
+++ b/test/src/common.c
@@ -297,12 +297,31 @@ invalidate_buf(char *buf, size_t len)
  * Print result only for the selected columns.
  */
 void
-print_result_series(HSTMT hstmt, SQLSMALLINT *colids, SQLSMALLINT numcols, SQLINTEGER rowcount)
+print_result_series(HSTMT hstmt, SQLSMALLINT *colids, SQLSMALLINT numcols, SQLINTEGER rowcount, BOOL printcolnames)
 {
 	SQLRETURN rc;
 	SQLINTEGER	rowc = 0;
+	char		buf[40];
+	int			i;
 
 	printf("Result set:\n");
+
+	if (printcolnames)
+	{
+		for (i = 1; i <= numcols; i++)
+		{
+			invalidate_buf(buf, sizeof(buf));
+			rc = SQLColAttribute(hstmt, i, SQL_DESC_LABEL, buf, sizeof(buf), NULL, NULL);
+			if (!SQL_SUCCEEDED(rc))
+			{
+				print_diag("SQLColAttribute failed", SQL_HANDLE_STMT, hstmt);
+				return;
+			}
+			printf("%s%s", (i > 1) ? "\t" : "", buf);
+		}
+		printf("\n");
+	}
+
 	while (rowcount <0 || rowc < rowcount)
 	{
 		rc = SQLFetch(hstmt);
@@ -310,8 +329,6 @@ print_result_series(HSTMT hstmt, SQLSMALLINT *colids, SQLSMALLINT numcols, SQLIN
 			break;
 		if (rc == SQL_SUCCESS)
 		{
-			char buf[40];
-			int i;
 			SQLLEN ind;
 
 			rowc++;
@@ -348,7 +365,7 @@ print_result_series(HSTMT hstmt, SQLSMALLINT *colids, SQLSMALLINT numcols, SQLIN
  * Print result on all the columns
  */
 void
-print_result(HSTMT hstmt)
+print_result_all(HSTMT hstmt, BOOL printcolnames)
 {
 	SQLRETURN rc;
 	SQLSMALLINT numcols, i;
@@ -364,6 +381,24 @@ print_result(HSTMT hstmt)
 	colids = (SQLSMALLINT *) malloc(numcols * sizeof(SQLSMALLINT));
 	for (i = 0; i < numcols; i++)
 		colids[i] = i + 1;
-	print_result_series(hstmt, colids, numcols, -1);
+	print_result_series(hstmt, colids, numcols, -1, printcolnames);
 	free(colids);
 }
+
+/*
+ * Print result on all the columns (without column names)
+ */
+void
+print_result(HSTMT hstmt)
+{
+	print_result_all(hstmt, FALSE);
+}
+
+/*
+ * Print result on all the columns (with column names)
+ */
+void
+print_result_with_column_names(HSTMT hstmt)
+{
+	print_result_all(hstmt, TRUE);
+}
diff --git a/test/src/common.h b/test/src/common.h
index 4794736..1e275c0 100644
--- a/test/src/common.h
+++ b/test/src/common.h
@@ -44,8 +44,10 @@ extern void print_result_meta_series(HSTMT hstmt,
 extern void print_result_series(HSTMT hstmt,
 								SQLSMALLINT *colids,
 								SQLSMALLINT numcols,
-								SQLINTEGER rowcount);
+								SQLINTEGER rowcount,
+								BOOL printcolnames);
 extern void print_result_meta(HSTMT hstmt);
 extern void print_result(HSTMT hstmt);
+extern void print_result_with_column_names(HSTMT hstmt);
 extern const char *datatype_str(SQLSMALLINT datatype);
 extern const char *nullable_str(SQLSMALLINT nullable);
diff --git a/test/src/multistmt-test.c b/test/src/multistmt-test.c
index 6a4236c..ac0d062 100644
--- a/test/src/multistmt-test.c
+++ b/test/src/multistmt-test.c
@@ -10,8 +10,10 @@ static void print_all_results(HSTMT hstmt)
 	int rc = SQL_SUCCESS;
 	for (i = 1; rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO; i++)
 	{
-		printf("--%d ", i);
-		print_result(hstmt);
+		/*** Verify column metadata/name and row data in each result ***/
+		printf("--%d\n", i);
+		print_result_meta(hstmt);
+		print_result_with_column_names(hstmt);
 
 		rc = SQLMoreResults(hstmt);
 	}
@@ -65,6 +67,15 @@ int main(int argc, char **argv)
 	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
 	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
 
+	/*** Different column name, type and source between results for the same column index ***/
+
+	rc = SQLExecDirect(hstmt, (SQLCHAR *) "SELECT id, t FROM testtab1; SELECT t, 2 result FROM testtab1", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
+	print_all_results(hstmt);
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
 	/*** Prepare/Execute a multi-statement with parameters ***/
 
 	rc = SQLPrepare(hstmt, (SQLCHAR *) "SELECT 'first result set', id, t FROM testtab1 WHERE t = ?; SELECT 'second result set', t FROM testtab1 WHERE t = ?", SQL_NTS);
-- 
2.13.0.windows.1

