diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index e520cdf3ba..457a59eeab 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2020,6 +2020,19 @@ CREATE INDEX
+
+ \graw[+] [ filename ]
+ \graw[+] [ |command ]
+
+
+ \graw is equivalent to \g, but
+ forces unaligned output mode for this query. When +
+ is appended, column names are also displayed.
+
+
+
+
+
\gset [ prefix ]
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 8cc4de3878..b3461291eb 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -332,7 +332,8 @@ exec_command(const char *cmd,
status = exec_command_errverbose(scan_state, active_branch);
else if (strcmp(cmd, "f") == 0)
status = exec_command_f(scan_state, active_branch);
- else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
+ else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0 ||
+ strcmp(cmd, "graw") == 0 || strcmp(cmd, "graw+") == 0)
status = exec_command_g(scan_state, active_branch, cmd);
else if (strcmp(cmd, "gdesc") == 0)
status = exec_command_gdesc(scan_state, active_branch);
@@ -1232,6 +1233,7 @@ exec_command_f(PsqlScanState scan_state, bool active_branch)
/*
* \g [filename] -- send query, optionally with output to file/pipe
+ * \graw [filename] -- same as \g with raw format
* \gx [filename] -- same as \g, with expanded mode forced
*/
static backslashResult
@@ -1254,6 +1256,10 @@ exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
free(fname);
if (strcmp(cmd, "gx") == 0)
pset.g_expanded = true;
+ else if (strcmp(cmd, "graw") == 0)
+ pset.g_raw = true;
+ else if (strcmp(cmd, "graw+") == 0)
+ pset.g_raw_header = true;
status = PSQL_CMD_SEND;
}
else
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 7a91a44b2b..9f7ef51dfb 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -865,6 +865,14 @@ PrintQueryTuples(const PGresult *results)
if (pset.g_expanded)
my_popt.topt.expanded = 1;
+ /* one-shot raw output requested by \raw and \graw+ */
+ else if (pset.g_raw || pset.g_raw_header)
+ {
+ my_popt.topt.format = PRINT_UNALIGNED;
+ my_popt.topt.tuples_only = true;
+ my_popt.topt.force_column_header = pset.g_raw_header;
+ }
+
/* write output to \g argument, if any */
if (pset.gfname)
{
@@ -1517,6 +1525,10 @@ sendquery_cleanup:
/* reset \gx's expanded-mode flag */
pset.g_expanded = false;
+ /* reset \graw flags */
+ pset.g_raw = false;
+ pset.g_raw_header = false;
+
/* reset \gset trigger */
if (pset.gset_prefix)
{
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index a926c40b9b..e573711434 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -167,7 +167,7 @@ slashUsage(unsigned short int pager)
* Use "psql --help=commands | wc" to count correctly. It's okay to count
* the USE_READLINE line even in builds without that.
*/
- output = PageOutput(125, pager ? &(pset.popt.topt) : NULL);
+ output = PageOutput(126, pager ? &(pset.popt.topt) : NULL);
fprintf(output, _("General\n"));
fprintf(output, _(" \\copyright show PostgreSQL usage and distribution terms\n"));
@@ -176,6 +176,7 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\g [FILE] or ; execute query (and send results to file or |pipe)\n"));
fprintf(output, _(" \\gdesc describe result of query, without executing it\n"));
fprintf(output, _(" \\gexec execute query, then execute each value in its result\n"));
+ fprintf(output, _(" \\graw[+] [FILE] as \\g, but forces unaligned raw output mode\n"));
fprintf(output, _(" \\gset [PREFIX] execute query and store results in psql variables\n"));
fprintf(output, _(" \\gx [FILE] as \\g, but forces expanded output mode\n"));
fprintf(output, _(" \\q quit psql\n"));
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 96338c3197..7a8d2cef86 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -92,6 +92,8 @@ typedef struct _psqlSettings
char *gfname; /* one-shot file output argument for \g */
bool g_expanded; /* one-shot expanded output requested via \gx */
+ bool g_raw; /* one-shot raw format for \graw */
+ bool g_raw_header; /* one-shot show header for \graw+ */
char *gset_prefix; /* one-shot prefix argument for \gset */
bool gdesc_flag; /* one-shot request to describe query results */
bool gexec_flag; /* one-shot request to execute query results */
diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c
index 8af5bbe97e..48a0f64e6a 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -369,6 +369,7 @@ static void
print_unaligned_text(const printTableContent *cont, FILE *fout)
{
bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_force_column_header = cont->opt->force_column_header;
unsigned int i;
const char *const *ptr;
bool need_recordsep = false;
@@ -386,7 +387,7 @@ print_unaligned_text(const printTableContent *cont, FILE *fout)
}
/* print headers */
- if (!opt_tuples_only)
+ if (!opt_tuples_only || opt_force_column_header)
{
for (ptr = cont->headers; *ptr; ptr++)
{
diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h
index 36b89e7d57..e6dd3888e0 100644
--- a/src/include/fe_utils/print.h
+++ b/src/include/fe_utils/print.h
@@ -108,6 +108,7 @@ typedef struct printTableOpt
bool start_table; /* print start decoration, eg */
bool stop_table; /* print stop decoration, eg
*/
bool default_footer; /* allow "(xx rows)" default footer */
+ bool force_column_header; /* print column header in raw mode */
unsigned long prior_records; /* start offset for record counters */
const printTextFormat *line_style; /* line style (NULL for default) */
struct separator fieldSep; /* field separator for unaligned text mode */
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 3818cfea7e..a5b8226b16 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -3243,3 +3243,10 @@ last error message: division by zero
\echo 'last error code:' :LAST_ERROR_SQLSTATE
last error code: 22012
\unset FETCH_COUNT
+-- \graw
+\pset fieldsep ,
+SELECT 1 AS a, 2 AS b \graw
+1,2
+SELECT 1 AS a, 2 AS b \graw+
+a,b
+1,2
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index b45da9bb8d..4e2944d0d0 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -688,3 +688,8 @@ select 1/(15-unique2) from tenk1 order by unique2 limit 19;
\echo 'last error code:' :LAST_ERROR_SQLSTATE
\unset FETCH_COUNT
+
+-- \graw
+\pset fieldsep ,
+SELECT 1 AS a, 2 AS b \graw
+SELECT 1 AS a, 2 AS b \graw+