diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 59f8b03..434b1d6 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -748,6 +748,40 @@ exec_command(const char *cmd,
 		status = PSQL_CMD_SEND;
 	}
 
+	/* \gb means send query, get/produce results in binary */
+	else if (strcmp(cmd, "gb") == 0)
+	{
+		char	   *fname = psql_scan_slash_option(scan_state,
+												   OT_FILEPIPE, NULL, false);
+
+		if (!fname)
+			pset.gfname = NULL;
+		else
+		{
+			expand_tilde(&fname);
+			pset.gfname = pg_strdup(fname);
+		}
+		free(fname);
+		status = PSQL_CMD_SEND_BIN;
+	}
+
+	/* \gbn means send query, get/produce results in binary, and no separators */
+	else if (strcmp(cmd, "gbn") == 0)
+	{
+		char	   *fname = psql_scan_slash_option(scan_state,
+												   OT_FILEPIPE, NULL, false);
+
+		if (!fname)
+			pset.gfname = NULL;
+		else
+		{
+			expand_tilde(&fname);
+			pset.gfname = pg_strdup(fname);
+		}
+		free(fname);
+		status = PSQL_CMD_SEND_BIN_NS;
+	}
+
 	/* help */
 	else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
 	{
diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h
index 1b94e44..09a461b 100644
--- a/src/bin/psql/command.h
+++ b/src/bin/psql/command.h
@@ -16,6 +16,8 @@ typedef enum _backslashResult
 {
 	PSQL_CMD_UNKNOWN = 0,		/* not done parsing yet (internal only) */
 	PSQL_CMD_SEND,				/* query complete; send off */
+	PSQL_CMD_SEND_BIN,          /* same, but get/produce result in binary */
+	PSQL_CMD_SEND_BIN_NS,       /* same, but with no separators*/
 	PSQL_CMD_SKIP_LINE,			/* keep building query */
 	PSQL_CMD_TERMINATE,			/* quit program */
 	PSQL_CMD_NEWEDIT,			/* query buffer was changed (e.g., via \e) */
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 5fb0316..590d268 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -579,7 +579,9 @@ PrintNotifications(void)
  * Returns true if successful, false otherwise.
  */
 static bool
-PrintQueryTuples(const PGresult *results)
+PrintQueryTuples(const PGresult *results,
+				 bool binary,
+				 bool noseps)
 {
 	printQueryOpt my_popt = pset.popt;
 
@@ -600,7 +602,10 @@ PrintQueryTuples(const PGresult *results)
 			return false;
 		}
 
-		printQuery(results, &my_popt, pset.queryFout, pset.logfile);
+		if (!binary)
+			printQuery(results, &my_popt, pset.queryFout, pset.logfile);
+		else
+			printQueryBin(results, &my_popt, pset.queryFout, pset.logfile, noseps);
 
 		/* close file/pipe, restore old setting */
 		setQFout(NULL);
@@ -612,7 +617,12 @@ PrintQueryTuples(const PGresult *results)
 		pset.gfname = NULL;
 	}
 	else
-		printQuery(results, &my_popt, pset.queryFout, pset.logfile);
+	{
+		if (!binary)
+			printQuery(results, &my_popt, pset.queryFout, pset.logfile);
+		else
+			printQueryBin(results, &my_popt, pset.queryFout, pset.logfile, noseps);
+	}
 
 	return true;
 }
@@ -762,7 +772,9 @@ PrintQueryStatus(PGresult *results)
  * Returns true if the query executed successfully, false otherwise.
  */
 static bool
-PrintQueryResults(PGresult *results)
+PrintQueryResults(PGresult *results,
+				  bool binary,
+				  bool noseps)
 {
 	bool		success;
 	const char *cmdstatus;
@@ -774,7 +786,7 @@ PrintQueryResults(PGresult *results)
 	{
 		case PGRES_TUPLES_OK:
 			/* print the data ... */
-			success = PrintQueryTuples(results);
+			success = PrintQueryTuples(results, binary, noseps);
 			/* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
 			cmdstatus = PQcmdStatus(results);
 			if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
@@ -830,7 +842,9 @@ PrintQueryResults(PGresult *results)
  * Returns true if the query executed successfully, false otherwise.
  */
 bool
-SendQuery(const char *query)
+SendQuery(const char *query,
+		  bool binary,
+		  bool noseps)
 {
 	PGresult   *results;
 	PGTransactionStatusType transaction_status;
@@ -928,7 +942,10 @@ SendQuery(const char *query)
 		if (pset.timing)
 			INSTR_TIME_SET_CURRENT(before);
 
-		results = PQexec(pset.db, query);
+		if (! binary)
+			results = PQexec(pset.db, query);
+		else
+			results = PQexecParams(pset.db, query,0, NULL, NULL, NULL, NULL, 1);
 
 		/* these operations are included in the timing result: */
 		ResetCancelConn();
@@ -943,7 +960,7 @@ SendQuery(const char *query)
 
 		/* but printing results isn't: */
 		if (OK && results)
-			OK = PrintQueryResults(results);
+			OK = PrintQueryResults(results, binary, noseps);
 	}
 	else
 	{
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index f9f3b1f..0fb9ccc 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -47,7 +47,7 @@ extern void ResetCancelConn(void);
 
 extern PGresult *PSQLexec(const char *query, bool start_xact);
 
-extern bool SendQuery(const char *query);
+extern bool SendQuery(const char *query, bool binary, bool noseps);
 
 extern bool is_superuser(void);
 extern bool standard_strings(void);
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index a31d789..05e5b1f 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -316,7 +316,7 @@ do_copy(const char *args)
 	/* Run it like a user command, interposing the data source or sink. */
 	save_file = *override_file;
 	*override_file = copystream;
-	success = SendQuery(query.data);
+	success = SendQuery(query.data, false, false);
 	*override_file = save_file;
 	termPQExpBuffer(&query);
 
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index 6e31d5c..92a1ee1 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -254,7 +254,7 @@ MainLoop(FILE *source)
 				}
 
 				/* execute query */
-				success = SendQuery(query_buf->data);
+				success = SendQuery(query_buf->data, false, false);
 				slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
 
 				/* transfer query to previous_buf by pointer-swapping */
@@ -304,16 +304,20 @@ MainLoop(FILE *source)
 
 				success = slashCmdStatus != PSQL_CMD_ERROR;
 
-				if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
+				if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_SEND_BIN || 
+					 slashCmdStatus == PSQL_CMD_SEND_BIN_NS || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
 					query_buf->len == 0)
 				{
 					/* copy previous buffer to current for handling */
 					appendPQExpBufferStr(query_buf, previous_buf->data);
 				}
 
-				if (slashCmdStatus == PSQL_CMD_SEND)
+				if (slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_SEND_BIN || slashCmdStatus == PSQL_CMD_SEND_BIN_NS)
 				{
-					success = SendQuery(query_buf->data);
+					bool usebin = slashCmdStatus != PSQL_CMD_SEND;
+					bool noseps = slashCmdStatus == PSQL_CMD_SEND_BIN_NS;
+
+					success = SendQuery(query_buf->data, usebin, noseps);
 
 					/* transfer query to previous_buf by pointer-swapping */
 					{
@@ -384,7 +388,7 @@ MainLoop(FILE *source)
 			pg_send_history(history_buf);
 
 		/* execute query */
-		success = SendQuery(query_buf->data);
+		success = SendQuery(query_buf->data, false, false);
 
 		if (!success && die_on_error)
 			successResult = EXIT_USER;
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 466c255..e0c75bb 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2411,6 +2411,53 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
 }
 
 /*
+ * Use this to print query results when results are produced in binary
+ * rather than text.
+ *
+ */
+void
+printQueryBin(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog, bool noseps)
+{
+
+	int fields, rows, fld, row, flen;
+	char *val;
+
+	if (cancel_pressed)
+		return;
+
+	fields = PQnfields(result);
+	rows = PQntuples(result);
+
+	for (row = 0; row < rows; row++)
+	{
+		for (fld = 0; fld < fields; fld++)
+		{
+			if (! noseps && fld > 0)
+			{
+				if (opt->topt.fieldSep.separator_zero)
+					fputc(0, fout);
+				else
+					fprintf(fout, "%s", opt->topt.fieldSep.separator);
+			}
+			if (PQgetisnull(result,row,fld))
+				continue;
+			val = PQgetvalue(result,row,fld);
+			flen = PQgetlength(result,row,fld);
+			fwrite(val, flen, 1, fout);
+		}
+		if (!noseps)
+		{
+				if (opt->topt.recordSep.separator_zero)
+					fputc(0, fout);
+				else
+					fprintf(fout, "%s", opt->topt.recordSep.separator);			
+		}
+	}
+	
+
+}
+
+/*
  * Use this to print query results
  *
  * It calls printTable with all the things set straight.
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index 63ba4a5..18a613b 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -173,6 +173,8 @@ extern void printTableCleanup(printTableContent *const content);
 extern void printTable(const printTableContent *cont, FILE *fout, FILE *flog);
 extern void printQuery(const PGresult *result, const printQueryOpt *opt,
 		   FILE *fout, FILE *flog);
+extern void printQueryBin(const PGresult *result, const printQueryOpt *opt,
+		   FILE *fout, FILE *flog, bool noseps);
 
 extern void setDecimalLocale(void);
 extern const printTextFormat *get_line_style(const printTableOpt *opt);
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index a59f45b..296e5b0 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -317,7 +317,7 @@ main(int argc, char *argv[])
 		if (pset.echo == PSQL_ECHO_ALL)
 			puts(options.action_string);
 
-		successResult = SendQuery(options.action_string)
+		successResult = SendQuery(options.action_string, false, false)
 			? EXIT_SUCCESS : EXIT_FAILURE;
 	}
 
