diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index a360d78..1af8df6 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -160,7 +160,3 @@ PQconnectStartParams      157
 PQping                    158
 PQpingParams              159
 PQlibVersion              160
-PQregisterTupleAdder	  161
-PQgetAsCstring		  162
-PQgetAddTupleParam	  163
-PQsetAddTupleErrMes	  164
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 437be26..50f3f83 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2692,7 +2692,6 @@ makeEmptyPGconn(void)
 	conn->allow_ssl_try = true;
 	conn->wait_ssl_try = false;
 #endif
-	conn->addTupleFunc = NULL;
 
 	/*
 	 * We try to send at least 8K at a time, which is the usual size of pipe
@@ -5065,10 +5064,3 @@ PQregisterThreadLock(pgthreadlock_t newhandler)
 
 	return prev;
 }
-
-void
-PQregisterTupleAdder(PGconn *conn, addTupleFunction func, void *param)
-{
-	conn->addTupleFunc = func;
-	conn->addTupleFuncParam = param;
-}
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index c8ec9bd..113aab0 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -48,6 +48,7 @@ char	   *const pgresStatus[] = {
 static int	static_client_encoding = PG_SQL_ASCII;
 static bool static_std_strings = false;
 
+
 static PGEvent *dupEvents(PGEvent *events, int count);
 static bool PQsendQueryStart(PGconn *conn);
 static int PQsendQueryGuts(PGconn *conn,
@@ -65,9 +66,7 @@ static PGresult *PQexecFinish(PGconn *conn);
 static int PQsendDescribe(PGconn *conn, char desc_type,
 			   const char *desc_target);
 static int	check_field_number(const PGresult *res, int field_num);
-static void *pqDefaultAddTupleFunc(PGresult *res, AddTupFunc func,
-								   int id, size_t len);
-static void *pqAddTuple(PGresult *res, PGresAttValue *tup);
+
 
 /* ----------------
  * Space management for PGresult.
@@ -161,9 +160,6 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
 	result->curBlock = NULL;
 	result->curOffset = 0;
 	result->spaceLeft = 0;
-	result->addTupleFunc = pqDefaultAddTupleFunc;
-	result->addTupleFuncParam = NULL;
-	result->addTupleFuncErrMes = NULL;
 
 	if (conn)
 	{
@@ -198,12 +194,6 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
 			}
 			result->nEvents = conn->nEvents;
 		}
-
-		if (conn->addTupleFunc)
-		{
-			result->addTupleFunc = conn->addTupleFunc;
-			result->addTupleFuncParam = conn->addTupleFuncParam;
-		}
 	}
 	else
 	{
@@ -497,33 +487,6 @@ PQresultAlloc(PGresult *res, size_t nBytes)
 	return pqResultAlloc(res, nBytes, TRUE);
 }
 
-void *
-pqDefaultAddTupleFunc(PGresult *res, AddTupFunc func, int id, size_t len)
-{
-	void *p;
-
-	switch (func)
-	{
-		case ADDTUP_ALLOC_TEXT:
-			return pqResultAlloc(res, len, TRUE);
-
-		case ADDTUP_ALLOC_BINARY:
-			p = pqResultAlloc(res, len, FALSE);
-
-			if (id == -1)
-				res->addTupleFuncParam = p;
-
-			return p;
-
-		case ADDTUP_ADD_TUPLE:
-			return pqAddTuple(res, res->addTupleFuncParam);
-
-		default:
-			/* Ignore */
-			break;
-	}
-	return NULL;
-}
 /*
  * pqResultAlloc -
  *		Allocate subsidiary storage for a PGresult.
@@ -867,9 +830,9 @@ pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
 /*
  * pqAddTuple
  *	  add a row pointer to the PGresult structure, growing it if necessary
- *	  Returns tup if OK, NULL if not enough memory to add the row.
+ *	  Returns TRUE if OK, FALSE if not enough memory to add the row
  */
-static void *
+int
 pqAddTuple(PGresult *res, PGresAttValue *tup)
 {
 	if (res->ntups >= res->tupArrSize)
@@ -895,13 +858,13 @@ pqAddTuple(PGresult *res, PGresAttValue *tup)
 			newTuples = (PGresAttValue **)
 				realloc(res->tuples, newSize * sizeof(PGresAttValue *));
 		if (!newTuples)
-			return NULL;		/* malloc or realloc failed */
+			return FALSE;		/* malloc or realloc failed */
 		res->tupArrSize = newSize;
 		res->tuples = newTuples;
 	}
 	res->tuples[res->ntups] = tup;
 	res->ntups++;
-	return tup;
+	return TRUE;
 }
 
 /*
@@ -2859,43 +2822,6 @@ PQgetisnull(const PGresult *res, int tup_num, int field_num)
 		return 0;
 }
 
-/* PQgetAsCString
- *	returns the field as C string.
- */
-char *
-PQgetAsCstring(PGresAttValue *attval)
-{
-	return attval->len == NULL_LEN ? NULL : attval->value;
-}
-
-/* PQgetAddTupleParam
- *	Get the pointer to the contextual parameter from PGresult which is
- *	registered to PGconn by PQregisterTupleAdder
- */
-void *
-PQgetAddTupleParam(const PGresult *res)
-{
-	if (!res)
-		return NULL;
-	return res->addTupleFuncParam;
-}
-
-/* PQsetAddTupleErrMes
- *	Set the error message pass back to the caller of addTupleFunc
- *  mes must be a malloc'ed memory block and it is released by the
- *  caller of addTupleFunc if set.
- *  You can replace the previous message by alternative mes, or clear
- *  it with NULL.
- */
-void
-PQsetAddTupleErrMes(PGresult *res, char *mes)
-{
-	/* Free existing message */
-	if (res->addTupleFuncErrMes)
-		free(res->addTupleFuncErrMes);
-	res->addTupleFuncErrMes = mes;
-}
-
 /* PQnparams:
  *	returns the number of input parameters of a prepared statement.
  */
diff --git a/src/interfaces/libpq/fe-protocol2.c b/src/interfaces/libpq/fe-protocol2.c
index c7f74ae..77c4d5a 100644
--- a/src/interfaces/libpq/fe-protocol2.c
+++ b/src/interfaces/libpq/fe-protocol2.c
@@ -733,10 +733,9 @@ getAnotherTuple(PGconn *conn, bool binary)
 	if (conn->curTuple == NULL)
 	{
 		conn->curTuple = (PGresAttValue *)
-			result->addTupleFunc(result, ADDTUP_ALLOC_BINARY, -1,
-								 nfields * sizeof(PGresAttValue));
+			pqResultAlloc(result, nfields * sizeof(PGresAttValue), TRUE);
 		if (conn->curTuple == NULL)
-			goto addTupleError;
+			goto outOfMemory;
 		MemSet(conn->curTuple, 0, nfields * sizeof(PGresAttValue));
 
 		/*
@@ -758,7 +757,7 @@ getAnotherTuple(PGconn *conn, bool binary)
 	{
 		bitmap = (char *) malloc(nbytes);
 		if (!bitmap)
-			goto addTupleError;
+			goto outOfMemory;
 	}
 
 	if (pqGetnchar(bitmap, nbytes, conn))
@@ -788,12 +787,9 @@ getAnotherTuple(PGconn *conn, bool binary)
 				vlen = 0;
 			if (tup[i].value == NULL)
 			{
-				AddTupFunc func =
-					(binary ? ADDTUP_ALLOC_BINARY : ADDTUP_ALLOC_TEXT);
-				tup[i].value =
-					(char *) result->addTupleFunc(result, func, i, vlen + 1);
+				tup[i].value = (char *) pqResultAlloc(result, vlen + 1, binary);
 				if (tup[i].value == NULL)
-					goto addTupleError;
+					goto outOfMemory;
 			}
 			tup[i].len = vlen;
 			/* read in the value */
@@ -816,9 +812,8 @@ getAnotherTuple(PGconn *conn, bool binary)
 	}
 
 	/* Success!  Store the completed tuple in the result */
-	if (!result->addTupleFunc(result, ADDTUP_ADD_TUPLE, 0, 0))
-		goto addTupleError;
-
+	if (!pqAddTuple(result, tup))
+		goto outOfMemory;
 	/* and reset for a new message */
 	conn->curTuple = NULL;
 
@@ -826,7 +821,7 @@ getAnotherTuple(PGconn *conn, bool binary)
 		free(bitmap);
 	return 0;
 
-addTupleError:
+outOfMemory:
 	/* Replace partially constructed result with an error result */
 
 	/*
@@ -834,21 +829,8 @@ addTupleError:
 	 * there's not enough memory to concatenate messages...
 	 */
 	pqClearAsyncResult(conn);
-	resetPQExpBuffer(&conn->errorMessage);
-
-	/*
-	 * If error message is passed from addTupleFunc, set it into
-	 * PGconn, assume out of memory if not.
-	 */
-	appendPQExpBufferStr(&conn->errorMessage,
-						 libpq_gettext(result->addTupleFuncErrMes ?
-									   result->addTupleFuncErrMes :
-									   "out of memory for query result\n"));
-	if (result->addTupleFuncErrMes)
-	{
-		free(result->addTupleFuncErrMes);
-		result->addTupleFuncErrMes = NULL;
-	}
+	printfPQExpBuffer(&conn->errorMessage,
+					  libpq_gettext("out of memory for query result\n"));
 
 	/*
 	 * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index d14b57a..45a84d8 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -634,10 +634,9 @@ getAnotherTuple(PGconn *conn, int msgLength)
 	if (conn->curTuple == NULL)
 	{
 		conn->curTuple = (PGresAttValue *)
-			result->addTupleFunc(result, ADDTUP_ALLOC_BINARY, -1,
-								 nfields * sizeof(PGresAttValue));
+			pqResultAlloc(result, nfields * sizeof(PGresAttValue), TRUE);
 		if (conn->curTuple == NULL)
-			goto addTupleError;
+			goto outOfMemory;
 		MemSet(conn->curTuple, 0, nfields * sizeof(PGresAttValue));
 	}
 	tup = conn->curTuple;
@@ -674,12 +673,11 @@ getAnotherTuple(PGconn *conn, int msgLength)
 			vlen = 0;
 		if (tup[i].value == NULL)
 		{
-			AddTupFunc func = (result->attDescs[i].format != 0 ?
-							   ADDTUP_ALLOC_BINARY : ADDTUP_ALLOC_TEXT);
-			tup[i].value =
-				(char *) result->addTupleFunc(result, func, i, vlen + 1);
+			bool		isbinary = (result->attDescs[i].format != 0);
+
+			tup[i].value = (char *) pqResultAlloc(result, vlen + 1, isbinary);
 			if (tup[i].value == NULL)
-				goto addTupleError;
+				goto outOfMemory;
 		}
 		tup[i].len = vlen;
 		/* read in the value */
@@ -691,36 +689,22 @@ getAnotherTuple(PGconn *conn, int msgLength)
 	}
 
 	/* Success!  Store the completed tuple in the result */
-	if (!result->addTupleFunc(result, ADDTUP_ADD_TUPLE, 0, 0))
-		goto addTupleError;
-
+	if (!pqAddTuple(result, tup))
+		goto outOfMemory;
 	/* and reset for a new message */
 	conn->curTuple = NULL;
 
 	return 0;
 
-addTupleError:
+outOfMemory:
 
 	/*
 	 * Replace partially constructed result with an error result. First
 	 * discard the old result to try to win back some memory.
 	 */
 	pqClearAsyncResult(conn);
-	resetPQExpBuffer(&conn->errorMessage);
-
-	/*
-	 * If error message is passed from addTupleFunc, set it into
-	 * PGconn, assume out of memory if not.
-	 */
-	appendPQExpBufferStr(&conn->errorMessage,
-						 libpq_gettext(result->addTupleFuncErrMes ?
-									   result->addTupleFuncErrMes : 
-									   "out of memory for query result\n"));
-	if (result->addTupleFuncErrMes)
-	{
-		free(result->addTupleFuncErrMes);
-		result->addTupleFuncErrMes = NULL;
-	}
+	printfPQExpBuffer(&conn->errorMessage,
+					  libpq_gettext("out of memory for query result\n"));
 	pqSaveErrorResult(conn);
 
 	/* Discard the failed message by pretending we read it */
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index bdce294..d13a5b9 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -116,16 +116,6 @@ typedef enum
 	PQPING_NO_ATTEMPT			/* connection not attempted (bad params) */
 } PGPing;
 
-/* AddTupFunc is one of the parameters of addTupleFunc that decides
- * the function of the addTupleFunction. See addTupleFunction for
- * details */
-typedef enum 
-{
-	ADDTUP_ALLOC_TEXT,          /* Returns non-aligned memory for text value */
-	ADDTUP_ALLOC_BINARY,        /* Returns aligned memory for binary value */
-	ADDTUP_ADD_TUPLE            /* Adds tuple data into tuple storage */
-} AddTupFunc;
-
 /* PGconn encapsulates a connection to the backend.
  * The contents of this struct are not supposed to be known to applications.
  */
@@ -235,12 +225,6 @@ typedef struct pgresAttDesc
 	int			atttypmod;		/* type-specific modifier info */
 } PGresAttDesc;
 
-typedef struct pgresAttValue
-{
-	int			len;			/* length in bytes of the value */
-	char	   *value;			/* actual value, plus terminating zero byte */
-} PGresAttValue;
-
 /* ----------------
  * Exported functions of libpq
  * ----------------
@@ -432,52 +416,6 @@ extern PGPing PQping(const char *conninfo);
 extern PGPing PQpingParams(const char *const * keywords,
 			 const char *const * values, int expand_dbname);
 
-/*
- * Typedef for tuple storage function.
- *
- * This function pointer is used for tuple storage function in
- * PGresult and PGconn.
- *
- * addTupleFunction is called for four types of function designated by
- * the enum AddTupFunc.
- *
- * id is the identifier for allocated memory block. The caller sets -1
- * for PGresAttValue array, and 0 to number of cols - 1 for each
- * column.
- *
- * ADDTUP_ALLOC_TEXT requests the size bytes memory block for a text
- * value which may not be alingned to the word boundary.
- *
- * ADDTUP_ALLOC_BINARY requests the size bytes memory block for a
- * binary value which is aligned to the word boundary.
- *
- * ADDTUP_ADD_TUPLE requests to add tuple data into storage, and
- * free the memory blocks allocated by this function if necessary.
- * id and size are ignored.
- *
- * This function must return non-NULL value for success and must
- * return NULL for failure and may set error message by
- * PQsetAddTupleErrMes in malloc'ed memory. Assumed by caller as out
- * of memory if the error message is NULL on failure. This function is
- * assumed not to throw any exception.
- */
-	typedef void *(*addTupleFunction)(PGresult *res, AddTupFunc func,
-									  int id, size_t size);
-
-/*
- * Register alternative tuple storage function to PGconn.
- * 
- * By registering this function, pg_result disables its own tuple
- * storage and calls it to append rows one by one.
- *
- * func is tuple store function. See addTupleFunction.
- * 
- * addTupFuncParam is contextual storage that can be get with
- * PQgetAddTupleParam in func.
- */
-extern void PQregisterTupleAdder(PGconn *conn, addTupleFunction func,
-								 void *addTupFuncParam);
-
 /* Force the write buffer to be written (or at least try) */
 extern int	PQflush(PGconn *conn);
 
@@ -516,9 +454,6 @@ extern char *PQcmdTuples(PGresult *res);
 extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
 extern int	PQgetlength(const PGresult *res, int tup_num, int field_num);
 extern int	PQgetisnull(const PGresult *res, int tup_num, int field_num);
-extern char *PQgetAsCstring(PGresAttValue *attdesc);
-extern void *PQgetAddTupleParam(const PGresult *res);
-extern void	PQsetAddTupleErrMes(PGresult *res, char *mes);
 extern int	PQnparams(const PGresult *res);
 extern Oid	PQparamtype(const PGresult *res, int param_num);
 
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 45e4c93..64dfcb2 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -134,6 +134,12 @@ typedef struct pgresParamDesc
 
 #define NULL_LEN		(-1)	/* pg_result len for NULL value */
 
+typedef struct pgresAttValue
+{
+	int			len;			/* length in bytes of the value */
+	char	   *value;			/* actual value, plus terminating zero byte */
+} PGresAttValue;
+
 /* Typedef for message-field list entries */
 typedef struct pgMessageField
 {
@@ -203,11 +209,6 @@ struct pg_result
 	PGresult_data *curBlock;	/* most recently allocated block */
 	int			curOffset;		/* start offset of free space in block */
 	int			spaceLeft;		/* number of free bytes remaining in block */
-
-	addTupleFunction addTupleFunc; /* Tuple storage function. See
-									* addTupleFunction for details. */
-	void *addTupleFuncParam;       /* Contextual parameter for addTupleFunc */
-	char *addTupleFuncErrMes;      /* Error message returned from addTupFunc */
 };
 
 /* PGAsyncStatusType defines the state of the query-execution state machine */
@@ -442,13 +443,6 @@ struct pg_conn
 
 	/* Buffer for receiving various parts of messages */
 	PQExpBufferData workBuffer; /* expansible string */
-
-    /* Tuple store function. The two fields below is copied to newly
-	 * created PGresult if addTupleFunc is not NULL. Use default
-	 * function if addTupleFunc is NULL. */
-	addTupleFunction addTupleFunc; /* Tuple storage function. See
-									* addTupleFunction for details. */
-	void *addTupleFuncParam;       /* Contextual parameter for addTupFunc */
 };
 
 /* PGcancel stores all data necessary to cancel a connection. A copy of this
@@ -513,6 +507,7 @@ extern void
 pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
 /* This lets gcc check the format string for consistency. */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
+extern int	pqAddTuple(PGresult *res, PGresAttValue *tup);
 extern void pqSaveMessageField(PGresult *res, char code,
 				   const char *value);
 extern void pqSaveParameterStatus(PGconn *conn, const char *name,
