diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 21dd772..729941f 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -171,3 +171,4 @@ PQsslAttributeNames       168
 PQsslAttribute            169
 PQsetErrorContextVisibility 170
 PQresultVerboseErrorMessage 171
+PQsetRowProcessor			172
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index b551875..1b3fbd8 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -1036,6 +1036,15 @@ pqRowProcessor(PGconn *conn, const char **errmsgp)
 	int			i;
 
 	/*
+	 * If we have a row processor set, just return the row processor.
+	 */
+	if (conn->row_processor_set)
+		return conn->row_processor(res, 
+								   columns, 
+								   nfields, 
+								   conn->row_processor_data); 
+
+	/*
 	 * In single-row mode, make a new PGresult that will hold just this one
 	 * row; the original conn->result is left unchanged so that it can be used
 	 * again as the template for future rows.
@@ -1391,6 +1400,11 @@ PQsendQueryStart(PGconn *conn)
 	/* reset single-row processing mode */
 	conn->singleRowMode = false;
 
+	/* Clean up the row processor */
+	conn->row_processor_set = false;
+	conn->row_processor = 0;
+	conn->row_processor_data = 0;
+
 	/* ready to send command message */
 	return true;
 }
@@ -1623,6 +1637,45 @@ PQsetSingleRowMode(PGconn *conn)
 }
 
 /*
+ * Sets a row processor, allowing the caller to bypass the standard
+ * pqRowProcessor with their own.
+ */
+int
+PQsetRowProcessor(PGconn *conn, PQrowProcessor rp, void *data)
+{
+	if (!conn)
+		return 0;
+
+	if (conn->asyncStatus != PGASYNC_BUSY)
+		return 0;
+
+	if (conn->result)
+		return 0;
+
+	/*
+	 * Setup the row processor
+	 */
+	conn->row_processor_set = true;
+	conn->row_processor = rp;
+	conn->row_processor_data = data;
+
+	return 1;
+}
+
+/*
+ * Clears the row processor
+ */
+int
+PQclearRowProcessor(PGconn *conn)
+{
+	conn->row_processor_set = false;
+	conn->row_processor = NULL;
+	conn->row_processor_data = NULL;
+
+	return 1;
+}
+
+/*
  * Consume any available input from the backend
  * 0 return: some kind of trouble
  * 1 return: no problem
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 1b53d0e..af32fff 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -241,6 +241,47 @@ typedef struct pgresAttDesc
 	int			atttypmod;		/* type-specific modifier info */
 } PGresAttDesc;
 
+/*
+ * Data for a single attribute of a single tuple
+ *
+ * We use char* for Attribute values.
+ *
+ * The value pointer always points to a null-terminated area; we add a
+ * null (zero) byte after whatever the backend sends us.  This is only
+ * particularly useful for text values ... with a binary value, the
+ * value might have embedded nulls, so the application can't use C string
+ * operators on it.  But we add a null anyway for consistency.
+ * Note that the value itself does not contain a length word.
+ *
+ * A NULL attribute is a special case in two ways: its len field is NULL_LEN
+ * and its value field points to null_field in the owning PGresult.  All the
+ * NULL attributes in a query result point to the same place (there's no need
+ * to store a null string separately for each one).
+ */
+
+#define PG_NULL_LEN		(-1)	/* pg_result len for NULL value */
+
+/* PGdataValue represents a data field value being passed to a row processor.
+ * It could be either text or binary data; text data is not zero-terminated.
+ * A SQL NULL is represented by len < 0; then value is still valid but there
+ * are no data bytes there.
+ */
+typedef struct pgDataValue
+{
+	int			len;			/* data length in bytes, or <0 if NULL */
+	const char *value;			/* data value, without zero-termination */
+} PGdataValue;
+
+/*
+ * When PQsetRowProcessor sets a PQrowProcessor, libpq will call the
+ * function for each row received from the back end.  It's the users
+ * responsibilty to COPY the data for each column to memory.  PQrowProcessor
+ * should return 1 in the event of an error and 0 for sucessfull processing.
+ */
+typedef int (*PQrowProcessor)(PGresult *res, const PGdataValue *cols,
+							  int col_count, void *data); 
+
+
 /* ----------------
  * Exported functions of libpq
  * ----------------
@@ -418,6 +459,8 @@ extern int PQsendQueryPrepared(PGconn *conn,
 					int resultFormat);
 extern int	PQsetSingleRowMode(PGconn *conn);
 extern PGresult *PQgetResult(PGconn *conn);
+extern int PQsetRowProcessor(PGconn *conn, PQrowProcessor rp, void *data); 
+extern int PQclearRowProcessor(PGconn *conn);
 
 /* Routines for managing an asynchronous query */
 extern int	PQisBusy(PGconn *conn);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 7289bd1..d4ce72d 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -281,16 +281,6 @@ typedef struct pgLobjfuncs
 	Oid			fn_lo_write;	/* OID of backend function LOwrite		*/
 } PGlobjfuncs;
 
-/* PGdataValue represents a data field value being passed to a row processor.
- * It could be either text or binary data; text data is not zero-terminated.
- * A SQL NULL is represented by len < 0; then value is still valid but there
- * are no data bytes there.
- */
-typedef struct pgDataValue
-{
-	int			len;			/* data length in bytes, or <0 if NULL */
-	const char *value;			/* data value, without zero-termination */
-} PGdataValue;
 
 typedef enum pg_conn_host_type
 {
@@ -389,6 +379,11 @@ struct pg_conn
 	char		copy_is_binary; /* 1 = copy binary, 0 = copy text */
 	int			copy_already_done;		/* # bytes already returned in COPY
 										 * OUT */
+
+	bool 		row_processor_set;
+	PQrowProcessor row_processor;		/* pqRowProcessor call row_processor if */
+	void 		*row_processor_data;	/* row_processor_set */
+
 	PGnotify   *notifyHead;		/* oldest unreported Notify msg */
 	PGnotify   *notifyTail;		/* newest unreported Notify msg */
 
