diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 1af8df6..3b26c7c 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -160,3 +160,6 @@ PQconnectStartParams      157
 PQping                    158
 PQpingParams              159
 PQlibVersion              160
+PQpgresult_malloc	  161
+PQpgresult_realloc	  162
+PQpgresult_free		  163
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 8e32b18..a574848 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -67,6 +67,15 @@ static int PQsendDescribe(PGconn *conn, char desc_type,
 			   const char *desc_target);
 static int	check_field_number(const PGresult *res, int field_num);
 
+/* ---
+ * malloc/realloc/free for PGResult is replasable for in-backend use
+ * Note that the events having the event id PGEVT_RESULTDESTROY won't
+ * fire when you free the memory blocks for PGresult without
+ * PQclear().
+ */
+void *(*PQpgresult_malloc)(size_t size) = malloc;
+void *(*PQpgresult_realloc)(void *ptr, size_t size) = realloc;
+void (*PQpgresult_free)(void *ptr) = free;
 
 /* ----------------
  * Space management for PGresult.
@@ -138,7 +147,7 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
 {
 	PGresult   *result;
 
-	result = (PGresult *) malloc(sizeof(PGresult));
+	result = (PGresult *) PQpgresult_malloc(sizeof(PGresult));
 	if (!result)
 		return NULL;
 
@@ -536,7 +545,8 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
 	 */
 	if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
 	{
-		block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
+		block =
+			(PGresult_data *) PQpgresult_malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
 		if (!block)
 			return NULL;
 		space = block->space + PGRESULT_BLOCK_OVERHEAD;
@@ -560,7 +570,7 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
 	}
 
 	/* Otherwise, start a new block. */
-	block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
+	block = (PGresult_data *) PQpgresult_malloc(PGRESULT_DATA_BLOCKSIZE);
 	if (!block)
 		return NULL;
 	block->next = res->curBlock;
@@ -662,12 +672,12 @@ PQclear(PGresult *res)
 	while ((block = res->curBlock) != NULL)
 	{
 		res->curBlock = block->next;
-		free(block);
+		PQpgresult_free(block);
 	}
 
 	/* Free the top-level tuple pointer array */
 	if (res->tuples)
-		free(res->tuples);
+		PQpgresult_free(res->tuples);
 
 	/* zero out the pointer fields to catch programming errors */
 	res->attDescs = NULL;
@@ -679,7 +689,7 @@ PQclear(PGresult *res)
 	/* res->curBlock was zeroed out earlier */
 
 	/* Free the PGresult structure itself */
-	free(res);
+	PQpgresult_free(res);
 }
 
 /*
@@ -844,10 +854,11 @@ pqAddTuple(PGresult *res, PGresAttValue *tup)
 
 		if (res->tuples == NULL)
 			newTuples = (PGresAttValue **)
-				malloc(newSize * sizeof(PGresAttValue *));
+				PQpgresult_malloc(newSize * sizeof(PGresAttValue *));
 		else
 			newTuples = (PGresAttValue **)
-				realloc(res->tuples, newSize * sizeof(PGresAttValue *));
+				PQpgresult_realloc(res->tuples,
+								 newSize * sizeof(PGresAttValue *));
 		if (!newTuples)
 			return FALSE;		/* malloc or realloc failed */
 		res->tupArrSize = newSize;
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index d13a5b9..c958df1 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -226,6 +226,14 @@ typedef struct pgresAttDesc
 } PGresAttDesc;
 
 /* ----------------
+ * malloc/realloc/free for PGResult is replasable for in-backend use
+ * ----------------
+ */
+extern void *(*PQpgresult_malloc)(size_t size);
+extern void *(*PQpgresult_realloc)(void *ptr, size_t size);
+extern void (*PQpgresult_free)(void *ptr);
+
+/* ----------------
  * Exported functions of libpq
  * ----------------
  */
