From 30b201b01a60f8c88ac3d043d942c562d491fdb8 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Fri, 15 Mar 2013 11:51:12 +0200
Subject: [PATCH 1/1] Avoid multiple evaluation in some macros.

There was at least one real bug caused by the multiple evaluation of 2nd
argument to SC_set_result(). SC_pre_execute() passed QR_Constructor() call
as the 2nd argument, so we ended up creating extra result sets that were
leaked.
---
 statement.c |   35 +++++++++++++++++++++++++++++++++++
 statement.h |   33 +++------------------------------
 2 files changed, 38 insertions(+), 30 deletions(-)

diff --git a/statement.c b/statement.c
index a0543f5..697d142 100644
--- a/statement.c
+++ b/statement.c
@@ -522,6 +522,41 @@ SC_Destructor(StatementClass *self)
 	return TRUE;
 }
 
+void
+SC_init_Result(StatementClass *self)
+{
+	self->result = self->curres = NULL;
+	self->curr_param_result = 0;
+	mylog("SC_init_Result(%x)", self);
+}
+
+void
+SC_set_Result(StatementClass *self, QResultClass *res)
+{
+	if (res != self->result)
+	{
+		mylog("SC_set_Result(%x, %x)", self, res);
+		QR_Destructor(self->result);
+		self->result = self->curres = res;
+		if (NULL != res)
+			self->curr_param_result = 1;
+	}
+}
+
+void
+SC_forget_unnamed(StatementClass *self)
+{
+	if (PREPARED_TEMPORARILY == self->prepared)
+	{
+		SC_set_prepared(self, ONCE_DESCRIBED);
+		if (FALSE && !SC_IsExecuting(self))
+		{
+			QResultClass	*res = SC_get_Curres(self);
+			if (NULL != res && !res->dataFilled && !QR_is_fetching_tuples(res))
+				SC_set_Result(self, NULL);
+		}
+	}
+}
 
 /*
  *	Free parameters and free the memory from the
diff --git a/statement.h b/statement.h
index cb21911..21785ae 100644
--- a/statement.h
+++ b/statement.h
@@ -285,23 +285,8 @@ struct StatementClass_
 };
 
 #define SC_get_conn(a)	  (a->hdbc)
-#define SC_init_Result(a) \
-do { \
-	a->result = a->curres = NULL; \
-	a->curr_param_result = 0; \
-	mylog("SC_init_Result(%x)", a); \
-} while (0)
-#define SC_set_Result(a, b) \
-do { \
-	if (b != a->result) \
-	{ \
-		mylog("SC_set_Result(%x, %x)", a, b); \
-		QR_Destructor(a->result); \
-		a->result = a->curres = b; \
-		if (NULL != b) \
-			a->curr_param_result = 1; \
-	} \
-} while (0)
+void SC_init_Result(StatementClass *self);
+void SC_set_Result(StatementClass *self, QResultClass *res);
 #define SC_get_Result(a)  (a->result)
 #define SC_set_Curres(a, b)  (a->curres = b)
 #define SC_get_Curres(a)  (a->curres)
@@ -435,19 +420,7 @@ enum
 #define SC_started_rbpoint(a)	((a->rbonerr & (1L << 4)) != 0)
 #define SC_unref_CC_error(a)	((a->ref_CC_error) = FALSE)
 #define SC_ref_CC_error(a)	((a->ref_CC_error) = TRUE)
-#define SC_forget_unnamed(a) \
-do { \
-	if (PREPARED_TEMPORARILY == (a)->prepared) \
-	{ \
-		SC_set_prepared(a, ONCE_DESCRIBED); \
-		if (FALSE && !SC_IsExecuting((a))) \
-		{ \
-			QResultClass	*res = SC_get_Curres((a)); \
-			if (NULL != res && !res->dataFilled && !QR_is_fetching_tuples(res)) \
-				SC_set_Result((a), NULL); \
-		} \
-	} \
-} while (0)
+void SC_forget_unnamed(StatementClass *self);
 #define SC_can_parse_statement(a) (STMT_TYPE_SELECT == (a)->statement_type)
 #define SC_may_use_cursor(a) (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type)
 #define SC_may_fetch_rows(a) (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type)
-- 
1.7.10.4

