Re: very long record lines in expanded psql output

2021-10-03 Thread Platon Pronko

Hi,

+   pg_log_error("\\pset: allowed xheader_width values are full
(default), column, page, or an number specifying exact width.");

  an number specifying -> a number specifying

Cheers



Fixed, attaching the updated patch. Thank you!

Best regards,
Platon Pronkodiff --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
   
   
 
+  
+  xheader_width
+  
+  
+  Sets expanded header width to one of full,
+  column,
+  page,
+  or integer value.
+  
+
+  full is the default option - expanded header
+  is not truncated.
+  
+
+  column: don't print header line past the first
+  column.
+  
+
+  page: fit header line to terminal width.
+  
+
+  integer value: specify exact width of header line.
+  
+  
+  
+
   
   fieldsep
   
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 49d4c0e3ce..801810aba9 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 a 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 =

Re: very long record lines in expanded psql output

2021-10-03 Thread Platon Pronko

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 Pronkodiff --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
   
   
 
+  
+  xheader_width
+  
+  
+  Sets expanded header width to one of full,
+  column,
+  page,
+  or integer value.
+  
+
+  full is the default option - expanded header
+  is not truncated.
+  
+
+  column: don't print header line past the first
+  column.
+  
+
+  page: fit header line to terminal width.
+  
+
+  integer value: specify exact width of header line.
+  
+  
+  
+
   
   fieldsep
   
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&quo

Re: very long record lines in expanded psql output

2021-09-23 Thread Platon Pronko

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.

Best regards,
Platon Pronko




Re: very long record lines in expanded psql output

2021-08-23 Thread Platon Pronko

Hi!

Done, here's the link: https://commitfest.postgresql.org/34/3295/

Best regards,
Platon Pronko

On 2021-08-23 21:14, Andrew Dunstan wrote:


On 8/23/21 2:00 PM, Platon Pronko wrote:

Hi!

Apparently I did forget something, and that's the patch itself :)
Thanks for Justin Pryzby for pointing this out.

Attaching the patch now.




Please add it to the commitfest, the next one starts in about a week.


cheers


andrew

--
Andrew Dunstan
EDB: https://www.enterprisedb.com






Re: very long record lines in expanded psql output

2021-08-23 Thread Platon Pronko

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 | xx
-[ RECORD 2 ]+
n    | 210
long_column_name | 
xx




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
   
   
 
+  
+  xheader_width
+  
+  
+  Sets expanded header width to one of full,
+  column,
+  page,
+  or integer value.
+  
+
+  full is the default option - expanded header
+  is not truncated.
+  
+
+  column: don't print header line past the first
+  column.
+  
+
+  page: fit header line to terminal width.
+  
+
+  integer value: specify exact width of header line.
+  
+  
+  
+
   
   fieldsep
   
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)
 

Re: very long record lines in expanded psql output

2021-08-23 Thread Platon Pronko

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 | xx
-[ RECORD 2 ]+
n| 210
long_column_name | 
xx




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






Re: very long record lines in expanded psql output

2021-08-07 Thread Platon Pronko

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 :)

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.

2. What was "column" option in your original suggestion supposed to do?
("\pset xheader_width column|page|nnn")

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.

Best regards,
Platon Pronko




Re: very long record lines in expanded psql output

2021-08-05 Thread Platon Pronko

it can be a fully new format - designed for simple copy from terminal. Some
like

== record: 10 ==
 proname 
left
 prosrc  
$lalalal
ewqrwqerw
ewqrwqerqrewq
$
===



no, it was proposed for psql


How is this better than "copy (...) to stdout"? E.g.:

$ copy (select * from pg_class limit 1) to stdout;
2619pg_statistic11  12016   0   10  2   26190   
18  402 18  2840t   f   p   r   31  0   
f   f   f   f   f   t   n   f0  478 1   
{postgres=arwdDxt/postgres} \N  \N

You can still copy the necessary parts (using mouse selection) -
seems that it achieves the the same goal.

Best regards,
Platon Pronko




Re: very long record lines in expanded psql output

2021-08-05 Thread Platon Pronko

Hi!


I don't think that would be a good idea. If somebody really just needs to
copy,
then wrapping the query in "copy (...) to stdout" already works nicely,
no need to create a special mode just for that.



It is working well, but it is copy to file, not copy to clipboard.


Maybe I misunderstood - are you suggesting this a special mode in pspg? I 
thought
that you were suggesting to implement a mode in psql, something like
"\pset format_for_clipboard".
 

I think the question was more about being able to copy in an ad-hoc way,
in the middle of scrolling trough "normal" output.


I understand your motivation, but I don't feel a significant benefit to
increase the complexity of the main format (more, when it breaks pspg,
without possibility to fix it). but it can depend on usual data, and it is
true, so when I use pspg, I don't use extended mode too often.


To clarify: I'm not suggesting my patch anymore - it definitely breaks pspg and 
this
is completely unacceptable.
We're just discussing the possible alternate solutions, I think.

Best regards,
Platon Pronko




Re: very long record lines in expanded psql output

2021-08-05 Thread Platon Pronko

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.



it can be a fully new format - designed for simple copy from terminal. Some
like

== record: 10 ==
 proname 
left
 prosrc  
$lalalal
ewqrwqerw
ewqrwqerqrewq
$
===


I don't think that would be a good idea. If somebody really just needs to copy,
then wrapping the query in "copy (...) to stdout" already works nicely,
no need to create a special mode just for that.
I think the question was more about being able to copy in an ad-hoc way,
in the middle of scrolling trough "normal" output.

Best regards,
Platon Pronko




Re: very long record lines in expanded psql output

2021-08-05 Thread Platon Pronko

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.

Best regards,
Platon Pronko




Re: very long record lines in expanded psql output

2021-08-05 Thread Platon Pronko

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.

Best regards,
Platon Pronko




very long record lines in expanded psql output

2021-08-05 Thread Platon Pronko

In expanded mode psql calculates the width of the longest field in all the 
output rows,
and prints the header line according to it. This often results in record header 
wrapping
over several lines (see example below).

This huge record header is printed the same way before each record, even if all 
the fields
in current record are small and fit into terminal width. This often leads to 
situations
when record header occupies the entirety of the screen, for all records, even 
though there are
only a few records with huge fields in a record set.

Maybe we can avoid making the header line longer than terminal width for \pset 
border 0
and \pset border 1? We already have terminal width calculated. Please see 
attached a patch
with the proposed implementation.

Example output before the modification, in a terminal with a 100-column width:

$ psql template1 -c "\x on" -c "\pset border 1;" -c "select n, repeat('x', n) as 
long_column_name from unnest(array[42,210]) as n"
Expanded display is on.
Border style is 1.
─[ RECORD 1 
]┬──

─
n│ 42
long_column_name │ xx
─[ RECORD 2 
]┼──

─
n│ 210
long_column_name │ 
x

x

And here's the same command after the patch:

$ psql template1 -c "\x on" -c "\pset border 1;" -c "select n, repeat('x', n) as 
long_column_name from unnest(array[42,210]) as n"
Expanded display is on.
Border style is 1.
─[ RECORD 1 
]┬──
n│ 42
long_column_name │ xx
─[ RECORD 2 
]┼──
n│ 210
long_column_name │ 
x
xxxxxxxx
x

Best regards,
Platon Pronko
diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c
index d48fcc4a03..9483d0d852 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -1157,6 +1157,7 @@ print_aligned_vertical_line(const printTextFormat *format,
 			unsigned long record,
 			unsigned int hwidth,
 			unsigned int dwidth,
+			int output_columns,
 			printTextRule pos,
 			FILE *fout)
 {
@@ -1200,6 +1201,14 @@ print_aligned_vertical_line(const printTextFormat *format,
 	}
 	if (reclen < 0)
 		reclen = 0;
+
+	if (output_columns > 0) {
+		if (opt_border == 0)
+			dwidth = Min(dwidth, output_columns - hwidth);
+		if (opt_border == 1)
+			dwidth = Min(dwidth, output_columns - hwidth - 3);
+	}
+
 	for (i = reclen; i < dwidth; i++)
 		fputs(opt_border > 0 ? lformat->hrule : " ", fout);
 	if (opt_border == 2)
@@ -1501,10 +1510,11 @@ print_aligned_vertical(const printTableContent *cont,
 
 			if (!opt_tuples_only)
 print_aligned_vertical_line(format, opt_border, record++,
-			lhwidth, dwidth, pos, fout);
+			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);
+			dwidth, output_columns, pos, fout);
 		}
 
 		/* Format the header */
@@ -1691,7 +1701,7 @@ print_aligned_vertical(const printTableContent *cont,
 	{
 		if (opt_border == 2 && !cancel_pressed)
 			print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth,
-		PRINT_RULE_BOTTOM, fout);
+		output_columns, PRINT_RULE_BOTTOM, fout);
 
 		/* print footers */
 		if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)