On 2021-09-24 14:42, Andrew Dunstan wrote:
On 9/24/21 12:49 AM, Platon Pronko wrote:
On 2021-09-23 22:28, Andrew Dunstan wrote:
2. It would possibly be better to pass the relevant parts of the options
to print_aligned_vertical_line() rather than the whole options
structure. It feels odd to pass both that and opt_border.
What do you think about doing it the other way around - passing only
whole
options structure? That way we will roll 4 parameters (opt_border,
printTextFormat,
and two xheader ones) into only one argument.
This increases code coupling a bit, but I'm not sure if that's
relevant here.
Sure, as long as it doesn't result in duplicated computation.
Hi!
Please find attached the updated patch - with fixed braces and
adjusted parameters to print_aligned_vertical_line().
Best regards,
Platon Pronko
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 14e0a4dbe3..78d27caefa 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..ebba14d082 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -4310,6 +4310,32 @@ 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 +4528,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 5cd5838668..e3e3bdc709 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -4168,13 +4168,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..1e94772b8b 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -1152,15 +1152,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;
@@ -1189,8 +1190,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
@@ -1198,12 +1209,41 @@ 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 +1540,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 */
@@ -1690,8 +1731,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 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 cb5b5ec74c..2bccb3406c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3425,6 +3425,7 @@ printTextFormat
printTextLineFormat
printTextLineWrap
printTextRule
+printXheaderWidthType
printfunc
priv_map
process_file_callback_t