Hi!
Apparently I did forget something, and that's the patch itself :)
Thanks for Justin Pryzby for pointing this out.
Attaching the patch now.
Best regards,
Platon Pronko
On 2021-08-23 20:51, Platon Pronko wrote:
Hi!
Please find attached the patch implementing the proposed changes.
I hope I didn't forget anything (docs, tab completion, comments, etc),
if I did forget something please tell me and I'll fix it.
Best regards,
Platon Pronko
On 2021-08-08 01:18, Andrew Dunstan wrote:
On 8/7/21 10:56 AM, Platon Pronko wrote:
Hi!
I also find this annoying and would be happy to be rid of it.
Have you tried "\pset format wrapped"? Pavel suggested it, and it
solved most of the problem for me, for example.
Yes, but it changes the data line output. Ideally, you should be able
to modify these independently.
I agree, and I think this can be implemented, but I'm a bit afraid of
introducing an additional psql option (there's already quite a lot of
them).
I suspect primary PostgreSQL maintainers won't be happy with such an
approach.
I think I qualify as one of those ... :-)
Sorry, I'm new here, don't know who's who :)
No problem. Welcome! We're always very glad to see new contributors.
I'll start working on a new patch then. A couple questions about
specifics:
1. Can we add "expanded" in the option name, like
"xheader_expanded_width"?
I think adjusting the header row width doesn't make sense on any other
modes,
and placing that in the option name makes intent a bit clearer.
"xheader" was meant to be shorthand for "expanded output header"
2. What was "column" option in your original suggestion supposed to do?
("\pset xheader_width column|page|nnn")
It's meant to say don't print anything past the column spec, e.g.:
-[ RECORD 1 ]----+
n | 42
long_column_name | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-[ RECORD 2 ]----+
n | 210
long_column_name |
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3. Should we bother with using this option when in "\pset border 2" mode?
I can do it for consistency, but it will still look bad.
Probably not, but since I never use it I'll let others who do weigh in
on the subject.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index fcab5c0d51..8cffc18165 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2799,6 +2799,32 @@ lo_import 152801
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>xheader_width</literal></term>
+ <listitem>
+ <para>
+ Sets expanded header width to one of <literal>full</literal>,
+ <literal>column</literal>,
+ <literal>page</literal>,
+ or <replaceable class="parameter">integer value</replaceable>.
+ </para>
+
+ <para><literal>full</literal> is the default option - expanded header
+ is not truncated.
+ </para>
+
+ <para><literal>column</literal>: don't print header line past the first
+ column.
+ </para>
+
+ <para><literal>page</literal>: fit header line to terminal width.
+ </para>
+
+ <para><replaceable class="parameter">integer value</replaceable>: specify exact width of header line.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>fieldsep</literal></term>
<listitem>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 49d4c0e3ce..440b732d3c 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -4310,6 +4310,28 @@ 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 && pg_strcasecmp(value, "full") == 0)
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_FULL;
+ else if (value && pg_strcasecmp(value, "column") == 0)
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_COLUMN;
+ else if (value && pg_strcasecmp(value, "page") == 0)
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_PAGE;
+ else if (value) {
+ 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 an number specifying exact width.");
+ return false;
+ }
+ } else {
+ /* reset to default if value is empty */
+ popt->topt.expanded_header_width_type = PRINT_XHEADER_FULL;
+ }
+ }
+
/* field separator for CSV format */
else if (strcmp(param, "csv_fieldsep") == 0)
{
@@ -4502,6 +4524,19 @@ printPsetInfo(const char *param, printQueryOpt *popt)
printf(_("Expanded display is off.\n"));
}
+ /* show xheader width type */
+ 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)
{
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 064892bade..22c977d47d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -4115,13 +4115,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 d48fcc4a03..878cca02ef 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -1153,10 +1153,12 @@ cleanup:
static void
print_aligned_vertical_line(const printTextFormat *format,
+ const printTableOpt *topt,
const unsigned short opt_border,
unsigned long record,
unsigned int hwidth,
unsigned int dwidth,
+ int output_columns,
printTextRule pos,
FILE *fout)
{
@@ -1188,9 +1190,15 @@ 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 (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
@@ -1198,12 +1206,39 @@ 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 I've added this anyway 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);
}
@@ -1500,11 +1535,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(format, cont->opt, opt_border, 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(format, cont->opt, opt_border, 0, lhwidth,
+ dwidth, output_columns, pos, fout);
}
/* Format the header */
@@ -1690,8 +1726,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(format, cont->opt, opt_border, 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 27ccbd5119..9d65f58e04 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/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 37cf4b2f76..ff08826d5a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3422,6 +3422,7 @@ printTextFormat
printTextLineFormat
printTextLineWrap
printTextRule
+printXheaderWidthType
printfunc
priv_map
process_file_callback_t