From: Platon Pronko <platon7pronko@gmail.com>
To: Andrew Dunstan <andrew@dunslane.net>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Cc: Justin Pryzby <pryzby@telsasoft.com>
Subject: Re: very long record lines in expanded psql output
Date: Mon, 23 Aug 2021 21:00:22 +0300
Message-ID: <7f3ef168-0958-a33d-6911-bda8999c30c2@gmail.com> (raw)
In-Reply-To: <aae2bfe7-e07f-bb11-5d5a-529e76e0f317@gmail.com>
References: <f03d38a3-db96-a56e-d1bc-dbbc80bbde4d@gmail.com>
<CAFj8pRBJ8bcTga9qTYG_v25BfeCB=4+GNc1rbf94qex_3C_e-A@mail.gmail.com>
<998a8549-f808-a349-bae6-9f44d07e050d@dunslane.net>
<d5280c71-b11b-b0fc-f57d-5033a9197406@gmail.com>
<bf64d7b0-413d-1501-00b2-992491b865b0@dunslane.net>
<4e8b9a10-95aa-aecf-01a1-cbc24d643465@gmail.com>
<66d23848-9f73-abc9-2fbb-3b8abfbb2fce@dunslane.net>
<0efd52b9-450a-7636-fb75-663bc2d81b34@gmail.com>
<92258bb8-8b9d-8f70-6f34-b5499215204c@dunslane.net>
<aae2bfe7-e07f-bb11-5d5a-529e76e0f317@gmail.com>
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
>>
Attachments:fix-header-lines-in-expanded-output.patch (text/x-patch, 9.7K) downloaddiff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgmlindex 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.cindex 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.cindex 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.cindex 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.hindex 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.listindex 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: platon7pronko@gmail.com, andrew@dunslane.net, pgsql-hackers@lists.postgresql.org, pryzby@telsasoft.com
Subject: Re: very long record lines in expanded psql output
In-Reply-To: <7f3ef168-0958-a33d-6911-bda8999c30c2@gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox