diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 84683f62b1c8..80e6ee21b108 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -3099,6 +3099,30 @@ SELECT $1 \parse stmt1
+
+ display_false
+
+
+ Sets the string to be printed in place of a false value.
+ The default is to print f, as that is the value
+ transmitted by the server. For readability,
+ \pset display_false 'false' is recommended.
+
+
+
+
+
+ display_true
+
+
+ Sets the string to be printed in place of a true value.
+ The default is to print t, as that is the value
+ transmitted by the server. For readability,
+ \pset display_true 'true' is recommended.
+
+
+
+
expanded (or x)
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index cc602087db24..f7454daf6ed7 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2709,7 +2709,8 @@ exec_command_pset(PsqlScanState scan_state, bool active_branch)
int i;
static const char *const my_list[] = {
- "border", "columns", "csv_fieldsep", "expanded", "fieldsep",
+ "border", "columns", "csv_fieldsep",
+ "display_false", "display_true", "expanded", "fieldsep",
"fieldsep_zero", "footer", "format", "linestyle", "null",
"numericlocale", "pager", "pager_min_lines",
"recordsep", "recordsep_zero",
@@ -5300,6 +5301,26 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
}
}
+ /* 'false' display */
+ else if (strcmp(param, "display_false") == 0)
+ {
+ if (value)
+ {
+ free(popt->falsePrint);
+ popt->falsePrint = pg_strdup(value);
+ }
+ }
+
+ /* 'true' display */
+ else if (strcmp(param, "display_true") == 0)
+ {
+ if (value)
+ {
+ free(popt->truePrint);
+ popt->truePrint = pg_strdup(value);
+ }
+ }
+
/* field separator for unaligned text */
else if (strcmp(param, "fieldsep") == 0)
{
@@ -5474,6 +5495,20 @@ printPsetInfo(const char *param, printQueryOpt *popt)
popt->topt.csvFieldSep);
}
+ /* show boolean 'false' display */
+ else if (strcmp(param, "display_false") == 0)
+ {
+ printf(_("Boolean false display is \"%s\".\n"),
+ popt->falsePrint ? popt->falsePrint : "f");
+ }
+
+ /* show boolean 'true' display */
+ else if (strcmp(param, "display_true") == 0)
+ {
+ printf(_("Boolean true display is \"%s\".\n"),
+ popt->truePrint ? popt->truePrint : "t");
+ }
+
/* show field separator for unaligned text */
else if (strcmp(param, "fieldsep") == 0)
{
@@ -5743,6 +5778,12 @@ pset_value_string(const char *param, printQueryOpt *popt)
return psprintf("%d", popt->topt.columns);
else if (strcmp(param, "csv_fieldsep") == 0)
return pset_quoted_string(popt->topt.csvFieldSep);
+ else if (strcmp(param, "display_false") == 0)
+ return pset_quoted_string(popt->falsePrint ?
+ popt->falsePrint : "f");
+ else if (strcmp(param, "display_true") == 0)
+ return pset_quoted_string(popt->truePrint ?
+ popt->truePrint : "t");
else if (strcmp(param, "expanded") == 0)
return pstrdup(popt->topt.expanded == 2
? "auto"
diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c
index 73847d3d6b3e..4d97ad2ddeb7 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -3775,6 +3775,10 @@ printQuery(const PGresult *result, const printQueryOpt *opt,
if (PQgetisnull(result, r, c))
cell = opt->nullPrint ? opt->nullPrint : "";
+ else if (PQftype(result, c) == BOOLOID)
+ cell = (PQgetvalue(result, r, c)[0] == 't' ?
+ (opt->truePrint ? opt->truePrint : "t") :
+ (opt->falsePrint ? opt->falsePrint : "f"));
else
{
cell = PQgetvalue(result, r, c);
diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h
index c99c2ee1a31a..6a6fc7e132c2 100644
--- a/src/include/fe_utils/print.h
+++ b/src/include/fe_utils/print.h
@@ -184,6 +184,8 @@ typedef struct printQueryOpt
{
printTableOpt topt; /* the options above */
char *nullPrint; /* how to print null entities */
+ char *truePrint; /* how to print boolean true values */
+ char *falsePrint; /* how to print boolean false values */
char *title; /* override title */
char **footers; /* override footer (default is "(xx rows)") */
bool translate_header; /* do gettext on column headers */
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index fa8984ffe0da..c8f3932edf09 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -445,6 +445,8 @@ environment value
border 1
columns 0
csv_fieldsep ','
+display_false 'f'
+display_true 't'
expanded off
fieldsep '|'
fieldsep_zero off
@@ -464,6 +466,36 @@ unicode_border_linestyle single
unicode_column_linestyle single
unicode_header_linestyle single
xheader_width full
+-- test the simple display substitution settings
+prepare q as select null as n, true as t, false as f;
+\pset null '(null)'
+\pset display_true 'true'
+\pset display_false 'false'
+execute q;
+ n | t | f
+--------+------+-------
+ (null) | true | false
+(1 row)
+
+\pset null
+\pset display_true
+\pset display_false
+execute q;
+ n | t | f
+--------+------+-------
+ (null) | true | false
+(1 row)
+
+\pset null ''
+\pset display_true 't'
+\pset display_false 'f'
+execute q;
+ n | t | f
+---+---+---
+ | t | f
+(1 row)
+
+deallocate q;
-- test multi-line headers, wrapping, and newline indicators
-- in aligned, unaligned, and wrapped formats
prepare q as select array_to_string(array_agg(repeat('x',2*n)),E'\n') as "ab
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index f064e4f54560..dcdbd4fc0209 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -219,6 +219,22 @@ select 'drop table gexec_test', 'select ''2000-01-01''::date as party_over'
-- show all pset options
\pset
+-- test the simple display substitution settings
+prepare q as select null as n, true as t, false as f;
+\pset null '(null)'
+\pset display_true 'true'
+\pset display_false 'false'
+execute q;
+\pset null
+\pset display_true
+\pset display_false
+execute q;
+\pset null ''
+\pset display_true 't'
+\pset display_false 'f'
+execute q;
+deallocate q;
+
-- test multi-line headers, wrapping, and newline indicators
-- in aligned, unaligned, and wrapped formats
prepare q as select array_to_string(array_agg(repeat('x',2*n)),E'\n') as "ab