summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2022-07-25 14:24:50 -0400
committerAndrew Dunstan <andrew@dunslane.net>2022-07-25 14:25:02 -0400
commita45388d6e0984abb02074f0300cd9c5cbda13848 (patch)
tree95689aab9fda59493f9f119f9e45b5f22f0d4fab
parentb35617de37870756bdb0e00ffc0a42441e56eefa (diff)
downloadpostgresql-a45388d6e0984abb02074f0300cd9c5cbda13848.tar.gz
Add xheader_width pset option to psql
The setting controls tha maximum length of the header line in expanded format output. Possible settings are full, column, page, or an integer. the default is full, the current behaviour, and in this case the header line is the length of the widest line of output. column causes the header to be truncated to the width of the first column, page causes it to be truncated to the width of the terminal page, and an integer causes it to be truncated to that value. If the full value is less than the page or integer value no truncation occurs. If given without an argument this option prints its current setting. Platon Pronko, somewhat modified by me. Discussion: https://postgr.es/m/f03d38a3-db96-a56e-d1bc-dbbc80bbde4d@gmail.com
-rw-r--r--doc/src/sgml/ref/psql-ref.sgml33
-rw-r--r--src/bin/psql/command.c54
-rw-r--r--src/bin/psql/tab-complete.c5
-rw-r--r--src/fe_utils/print.c77
-rw-r--r--src/include/fe_utils/print.h11
-rw-r--r--src/test/regress/expected/psql.out1
-rw-r--r--src/tools/pgindent/typedefs.list1
7 files changed, 164 insertions, 18 deletions
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 65bb0a6a3f..a95ddd60ee 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2843,6 +2843,39 @@ lo_import 152801
</varlistentry>
<varlistentry>
+ <term><literal>xheader_width</literal></term>
+ <listitem>
+ <para>
+ Sets the maximum width of the header for expanded output to one of
+ <literal>full</literal> (the default value),
+ <literal>column</literal>, <literal>page</literal>, or an
+ <replaceable class="parameter">integer value</replaceable>.
+ </para>
+
+ <para>
+ <literal>full</literal>: the expanded header is not truncated,
+ and will be as wide as the widest output
+ line.
+ </para>
+
+ <para>
+ <literal>column</literal>: truncate the header line at the
+ width of the first column.
+ </para>
+
+ <para>
+ <literal>page</literal>: truncate the the header line at the terminal
+ width.
+ </para>
+
+ <para>
+ <replaceable class="parameter">integer value</replaceable>: specify
+ the exact maximum width of the header line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>fieldsep</literal></term>
<listitem>
<para>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index cac98804ab..a81bd3307b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -2244,6 +2244,7 @@ exec_command_pset(PsqlScanState scan_state, bool active_branch)
"unicode_border_linestyle",
"unicode_column_linestyle",
"unicode_header_linestyle",
+ "xheader_width",
NULL
};
@@ -4369,6 +4370,29 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.expanded = !popt->topt.expanded;
}
+ /* header line width in expanded mode */
+ else if (strcmp(param, "xheader_width") == 0)
+ {
+ if (! value)
+ ;
+ else if (pg_strcasecmp(value, "full") == 0)
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_FULL;
+ else if (pg_strcasecmp(value, "column") == 0)
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_COLUMN;
+ else if (pg_strcasecmp(value, "page") == 0)
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_PAGE;
+ else
+ {
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_EXACT_WIDTH;
+ popt->topt.expanded_header_exact_width = atoi(value);
+ if (popt->topt.expanded_header_exact_width == 0)
+ {
+ pg_log_error("\\pset: allowed xheader_width values are full (default), column, page, or a number specifying the exact width.");
+ return false;
+ }
+ }
+ }
+
/* field separator for CSV format */
else if (strcmp(param, "csv_fieldsep") == 0)
{
@@ -4561,6 +4585,19 @@ printPsetInfo(const char *param, printQueryOpt *popt)
printf(_("Expanded display is off.\n"));
}
+ /* show xheader width value */
+ else if (strcmp(param, "xheader_width") == 0)
+ {
+ if (popt->topt.expanded_header_width_type == PRINT_XHEADER_FULL)
+ printf(_("Expanded header width is 'full'.\n"));
+ else if (popt->topt.expanded_header_width_type == PRINT_XHEADER_COLUMN)
+ printf(_("Expanded header width is 'column'.\n"));
+ else if (popt->topt.expanded_header_width_type == PRINT_XHEADER_PAGE)
+ printf(_("Expanded header width is 'page'.\n"));
+ else if (popt->topt.expanded_header_width_type == PRINT_XHEADER_EXACT_WIDTH)
+ printf(_("Expanded header width is %d.\n"), popt->topt.expanded_header_exact_width);
+ }
+
/* show field separator for CSV format */
else if (strcmp(param, "csv_fieldsep") == 0)
{
@@ -4881,6 +4918,23 @@ pset_value_string(const char *param, printQueryOpt *popt)
return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
else if (strcmp(param, "unicode_header_linestyle") == 0)
return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
+ else if (strcmp(param, "xheader_width") == 0)
+ {
+ if (popt->topt.expanded_header_width_type == PRINT_XHEADER_FULL)
+ return(pstrdup("full"));
+ else if (popt->topt.expanded_header_width_type == PRINT_XHEADER_COLUMN)
+ return(pstrdup("column"));
+ else if (popt->topt.expanded_header_width_type == PRINT_XHEADER_PAGE)
+ return(pstrdup("page"));
+ else
+ {
+ /* must be PRINT_XHEADER_EXACT_WIDTH */
+ char wbuff[32];
+ snprintf(wbuff, sizeof(wbuff), "%d",
+ popt->topt.expanded_header_exact_width);
+ return pstrdup(wbuff);
+ }
+ }
else
return pstrdup("ERROR");
}
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 5f06768085..f265e043e9 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -4654,13 +4654,16 @@ psql_completion(const char *text, int start, int end)
"tableattr", "title", "tuples_only",
"unicode_border_linestyle",
"unicode_column_linestyle",
- "unicode_header_linestyle");
+ "unicode_header_linestyle",
+ "xheader_width");
else if (TailMatchesCS("\\pset", MatchAny))
{
if (TailMatchesCS("format"))
COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
"latex-longtable", "troff-ms", "unaligned",
"wrapped");
+ else if (TailMatchesCS("xheader_width"))
+ COMPLETE_WITH_CS("full", "column", "page");
else if (TailMatchesCS("linestyle"))
COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
else if (TailMatchesCS("pager"))
diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c
index fe676a971b..a48c919697 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -1222,15 +1222,16 @@ cleanup:
static void
-print_aligned_vertical_line(const printTextFormat *format,
- const unsigned short opt_border,
+print_aligned_vertical_line(const printTableOpt *topt,
unsigned long record,
unsigned int hwidth,
unsigned int dwidth,
+ int output_columns,
printTextRule pos,
FILE *fout)
{
- const printTextLineFormat *lformat = &format->lrule[pos];
+ const printTextLineFormat *lformat = &get_line_style(topt)->lrule[pos];
+ const unsigned short opt_border = topt->border;
unsigned int i;
int reclen = 0;
@@ -1259,8 +1260,18 @@ print_aligned_vertical_line(const printTextFormat *format,
if (reclen-- <= 0)
fputs(lformat->hrule, fout);
if (reclen-- <= 0)
- fputs(lformat->midvrule, fout);
- if (reclen-- <= 0)
+ {
+ if (topt->expanded_header_width_type == PRINT_XHEADER_COLUMN)
+ {
+ fputs(lformat->rightvrule, fout);
+ }
+ else
+ {
+ fputs(lformat->midvrule, fout);
+ }
+ }
+ if (reclen-- <= 0
+ && topt->expanded_header_width_type != PRINT_XHEADER_COLUMN)
fputs(lformat->hrule, fout);
}
else
@@ -1268,12 +1279,43 @@ print_aligned_vertical_line(const printTextFormat *format,
if (reclen-- <= 0)
fputc(' ', fout);
}
- if (reclen < 0)
- reclen = 0;
- for (i = reclen; i < dwidth; i++)
- fputs(opt_border > 0 ? lformat->hrule : " ", fout);
- if (opt_border == 2)
- fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
+
+ if (topt->expanded_header_width_type != PRINT_XHEADER_COLUMN)
+ {
+ if (topt->expanded_header_width_type == PRINT_XHEADER_PAGE
+ || topt->expanded_header_width_type == PRINT_XHEADER_EXACT_WIDTH)
+ {
+ if (topt->expanded_header_width_type == PRINT_XHEADER_EXACT_WIDTH)
+ {
+ output_columns = topt->expanded_header_exact_width;
+ }
+ if (output_columns > 0)
+ {
+ if (opt_border == 0)
+ dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth)));
+ if (opt_border == 1)
+ dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth - 3)));
+ /*
+ * Handling the xheader width for border=2 doesn't make
+ * much sense because this format has an additional
+ * right border, but keep this for consistency.
+ */
+ if (opt_border == 2)
+ dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth - 7)));
+ }
+ }
+
+ if (reclen < 0)
+ reclen = 0;
+ if (dwidth < reclen)
+ dwidth = reclen;
+
+ for (i = reclen; i < dwidth; i++)
+ fputs(opt_border > 0 ? lformat->hrule : " ", fout);
+ if (opt_border == 2)
+ fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
+ }
+
fputc('\n', fout);
}
@@ -1570,11 +1612,12 @@ print_aligned_vertical(const printTableContent *cont,
lhwidth++; /* for newline indicators */
if (!opt_tuples_only)
- print_aligned_vertical_line(format, opt_border, record++,
- lhwidth, dwidth, pos, fout);
+ print_aligned_vertical_line(cont->opt, record++,
+ lhwidth, dwidth, output_columns,
+ pos, fout);
else if (i != 0 || !cont->opt->start_table || opt_border == 2)
- print_aligned_vertical_line(format, opt_border, 0, lhwidth,
- dwidth, pos, fout);
+ print_aligned_vertical_line(cont->opt, 0, lhwidth,
+ dwidth, output_columns, pos, fout);
}
/* Format the header */
@@ -1760,8 +1803,8 @@ print_aligned_vertical(const printTableContent *cont,
if (cont->opt->stop_table)
{
if (opt_border == 2 && !cancel_pressed)
- print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth,
- PRINT_RULE_BOTTOM, fout);
+ print_aligned_vertical_line(cont->opt, 0, hwidth, dwidth,
+ output_columns, PRINT_RULE_BOTTOM, fout);
/* print footers */
if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h
index bb2f1bf4e6..b8dbfa5f54 100644
--- a/src/include/fe_utils/print.h
+++ b/src/include/fe_utils/print.h
@@ -66,6 +66,15 @@ typedef enum printTextLineWrap
PRINT_LINE_WRAP_NEWLINE /* Newline in data */
} printTextLineWrap;
+typedef enum printXheaderWidthType
+{
+ /* Expanded header line width variants */
+ PRINT_XHEADER_FULL, /* do not truncate header line (this is the default) */
+ PRINT_XHEADER_COLUMN, /* only print header line above the first column */
+ PRINT_XHEADER_PAGE, /* header line must not be longer than terminal width */
+ PRINT_XHEADER_EXACT_WIDTH, /* explicitly specified width */
+} printXheaderWidthType;
+
typedef struct printTextFormat
{
/* A complete line style */
@@ -101,6 +110,8 @@ typedef struct printTableOpt
enum printFormat format; /* see enum above */
unsigned short int expanded; /* expanded/vertical output (if supported
* by output format); 0=no, 1=yes, 2=auto */
+ printXheaderWidthType expanded_header_width_type; /* width type for header line in expanded mode */
+ int expanded_header_exact_width; /* explicit width for header line in expanded mode */
unsigned short int border; /* Print a border around the table. 0=none,
* 1=dividing lines, 2=full */
unsigned short int pager; /* use pager for output (if to stdout and
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 60acbd1241..a7f5700edc 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -317,6 +317,7 @@ tuples_only off
unicode_border_linestyle single
unicode_column_linestyle single
unicode_header_linestyle single
+xheader_width full
-- 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/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 34a76ceb60..60709ddc98 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3569,6 +3569,7 @@ printTextFormat
printTextLineFormat
printTextLineWrap
printTextRule
+printXheaderWidthType
printfunc
priv_map
process_file_callback_t