Skip to content

Commit 125ed68

Browse files
committed
Restore psql's former behavior that padding spaces to the right of the last
output column are not emitted. (That change already caused more noise in the regression test output files than I would like.) Provide some needed editorial help for comments, clean up code formatting.
1 parent 2cabe2d commit 125ed68

File tree

1 file changed

+73
-55
lines changed

1 file changed

+73
-55
lines changed

src/bin/psql/print.c

Lines changed: 73 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.98 2008/05/08 17:04:26 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.99 2008/05/10 03:31:58 tgl Exp $
77
*/
88
#include "postgres_fe.h"
99

@@ -28,8 +28,6 @@
2828

2929
#include "mbprint.h"
3030

31-
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
32-
3331
/*
3432
* We define the cancel_pressed flag in this file, rather than common.c where
3533
* it naturally belongs, because this file is also used by non-psql programs
@@ -45,6 +43,9 @@ static char *decimal_point;
4543
static char *grouping;
4644
static char *thousands_sep;
4745

46+
/* Local functions */
47+
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
48+
4849

4950
static void *
5051
pg_local_malloc(size_t size)
@@ -400,7 +401,7 @@ _print_horizontal_line(const unsigned int col_count, const unsigned int *widths,
400401

401402

402403
/*
403-
* Prety pretty boxes around cells.
404+
* Print pretty boxes around cells.
404405
*/
405406
static void
406407
print_aligned_text(const char *title, const char *const * headers,
@@ -411,7 +412,7 @@ print_aligned_text(const char *title, const char *const * headers,
411412
bool opt_tuples_only = opt->tuples_only;
412413
bool opt_numeric_locale = opt->numericLocale;
413414
int encoding = opt->encoding;
414-
unsigned short int opt_border = opt->border;
415+
unsigned short opt_border = opt->border;
415416

416417
unsigned int col_count = 0, cell_count = 0;
417418

@@ -483,7 +484,8 @@ print_aligned_text(const char *title, const char *const * headers,
483484
nl_lines,
484485
bytes_required;
485486

486-
pg_wcssize((unsigned char *) headers[i], strlen(headers[i]), encoding, &width, &nl_lines, &bytes_required);
487+
pg_wcssize((unsigned char *) headers[i], strlen(headers[i]), encoding,
488+
&width, &nl_lines, &bytes_required);
487489
if (width > max_width[i])
488490
max_width[i] = width;
489491
if (nl_lines > max_nl_lines[i])
@@ -502,7 +504,8 @@ print_aligned_text(const char *title, const char *const * headers,
502504
bytes_required;
503505

504506
/* Get width, ignore nl_lines */
505-
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding, &width, &nl_lines, &bytes_required);
507+
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
508+
&width, &nl_lines, &bytes_required);
506509
if (opt_numeric_locale && opt_align[i % col_count] == 'r')
507510
{
508511
width += additional_numeric_locale_len(*ptr);
@@ -567,12 +570,14 @@ print_aligned_text(const char *title, const char *const * headers,
567570

568571
if (opt->format == PRINT_WRAPPED)
569572
{
570-
/* Get terminal width */
573+
/*
574+
* Choose target output width: \pset columns, or $COLUMNS, or ioctl
575+
*/
571576
if (opt->columns > 0)
572577
output_columns = opt->columns;
573578
else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
574579
{
575-
if (opt->env_columns)
580+
if (opt->env_columns > 0)
576581
output_columns = opt->env_columns;
577582
#ifdef TIOCGWINSZ
578583
else
@@ -586,11 +591,11 @@ print_aligned_text(const char *title, const char *const * headers,
586591
}
587592

588593
/*
589-
* Optional optimized word wrap. Shrink columns with a high max/avg ratio.
590-
* Slighly bias against wider columns. (Increases chance a narrow column
591-
* will fit in its cell.)
592-
* If available columns is positive...
593-
* and greater than the width of the unshrinkable column headers
594+
* Optional optimized word wrap. Shrink columns with a high max/avg
595+
* ratio. Slighly bias against wider columns. (Increases chance a
596+
* narrow column will fit in its cell.) If available columns is
597+
* positive... and greater than the width of the unshrinkable column
598+
* headers
594599
*/
595600
if (output_columns > 0 && output_columns >= total_header_width)
596601
{
@@ -610,10 +615,11 @@ print_aligned_text(const char *title, const char *const * headers,
610615
{
611616
if (width_average[i] && width_wrap[i] > width_header[i])
612617
{
613-
/* Penalize wide columns by +1% of their width (0.01) */
614-
double ratio = (double)width_wrap[i] / width_average[i] +
615-
max_width[i] * 0.01;
618+
/* Penalize wide columns by 1% of their width */
619+
double ratio;
616620

621+
ratio = (double) width_wrap[i] / width_average[i] +
622+
max_width[i] * 0.01;
617623
if (ratio > max_ratio)
618624
{
619625
max_ratio = ratio;
@@ -641,7 +647,8 @@ print_aligned_text(const char *title, const char *const * headers,
641647
{
642648
int width, height;
643649

644-
pg_wcssize((unsigned char *) title, strlen(title), encoding, &width, &height, NULL);
650+
pg_wcssize((unsigned char *) title, strlen(title), encoding,
651+
&width, &height, NULL);
645652
if (width >= width_total)
646653
fprintf(fout, "%s\n", title); /* Aligned */
647654
else
@@ -723,21 +730,22 @@ print_aligned_text(const char *title, const char *const * headers,
723730
break;
724731

725732
/*
726-
* Format each cell. Format again, it is a numeric formatting locale
733+
* Format each cell. Format again, if it's a numeric formatting locale
727734
* (e.g. 123,456 vs. 123456)
728735
*/
729736
for (j = 0; j < col_count; j++)
730737
{
731-
pg_wcsformat((unsigned char *) ptr[j], strlen(ptr[j]), encoding, col_lineptrs[j], max_nl_lines[j]);
738+
pg_wcsformat((unsigned char *) ptr[j], strlen(ptr[j]), encoding,
739+
col_lineptrs[j], max_nl_lines[j]);
732740
curr_nl_line[j] = 0;
733741

734742
if (opt_numeric_locale && opt_align[j % col_count] == 'r')
735743
{
736744
char *my_cell;
737745

738746
my_cell = format_numeric_locale((char *) col_lineptrs[j]->ptr);
739-
strcpy((char *) col_lineptrs[j]->ptr, my_cell); /* Buffer IS large
740-
* enough... now */
747+
/* Buffer IS large enough... now */
748+
strcpy((char *) col_lineptrs[j]->ptr, my_cell);
741749
free(my_cell);
742750
}
743751
}
@@ -764,16 +772,22 @@ print_aligned_text(const char *title, const char *const * headers,
764772
{
765773
/* We have a valid array element, so index it */
766774
struct lineptr *this_line = &col_lineptrs[j][curr_nl_line[j]];
767-
int bytes_to_output, chars_to_output = width_wrap[j];
775+
int bytes_to_output;
776+
int chars_to_output = width_wrap[j];
777+
bool finalspaces = (opt_border == 2 || j < col_count - 1);
768778

769-
/* Past newline lines so pad for other columns */
770779
if (!this_line->ptr)
771-
fprintf(fout, "%*s", width_wrap[j], "");
780+
{
781+
/* Past newline lines so just pad for other columns */
782+
if (finalspaces)
783+
fprintf(fout, "%*s", chars_to_output, "");
784+
}
772785
else
773786
{
774-
/* Get strlen() of the width_wrap character */
775-
bytes_to_output = strlen_max_width(this_line->ptr +
776-
bytes_output[j], &chars_to_output, encoding);
787+
/* Get strlen() of the characters up to width_wrap */
788+
bytes_to_output =
789+
strlen_max_width(this_line->ptr + bytes_output[j],
790+
&chars_to_output, encoding);
777791

778792
/*
779793
* If we exceeded width_wrap, it means the display width
@@ -796,13 +810,14 @@ print_aligned_text(const char *title, const char *const * headers,
796810
/* spaces second */
797811
fprintf(fout, "%.*s", bytes_to_output,
798812
this_line->ptr + bytes_output[j]);
799-
fprintf(fout, "%*s", width_wrap[j] - chars_to_output, "");
813+
if (finalspaces)
814+
fprintf(fout, "%*s", width_wrap[j] - chars_to_output, "");
800815
}
801816

802817
bytes_output[j] += bytes_to_output;
803818

804819
/* Do we have more text to wrap? */
805-
if (*(this_line->ptr + bytes_output[j]) != 0)
820+
if (*(this_line->ptr + bytes_output[j]) != '\0')
806821
more_lines = true;
807822
else
808823
{
@@ -814,8 +829,8 @@ print_aligned_text(const char *title, const char *const * headers,
814829
}
815830
}
816831

817-
/* print a divider, middle columns only */
818-
if ((j + 1) % col_count)
832+
/* print a divider, if not the last column */
833+
if (j < col_count - 1)
819834
{
820835
if (opt_border == 0)
821836
fputc(' ', fout);
@@ -832,10 +847,9 @@ print_aligned_text(const char *title, const char *const * headers,
832847
/* Ordinary line */
833848
fputs(" | ", fout);
834849
}
835-
836850
}
837851

838-
/* end of row border */
852+
/* end-of-row border */
839853
if (opt_border == 2)
840854
fputs(" |", fout);
841855
fputc('\n', fout);
@@ -887,7 +901,7 @@ print_aligned_vertical(const char *title, const char *const * headers,
887901
{
888902
bool opt_tuples_only = opt->tuples_only;
889903
bool opt_numeric_locale = opt->numericLocale;
890-
unsigned short int opt_border = opt->border;
904+
unsigned short opt_border = opt->border;
891905
int encoding = opt->encoding;
892906
unsigned int col_count = 0;
893907
unsigned long record = opt->prior_records + 1;
@@ -927,7 +941,8 @@ print_aligned_vertical(const char *title, const char *const * headers,
927941
height,
928942
fs;
929943

930-
pg_wcssize((unsigned char *) headers[i], strlen(headers[i]), encoding, &width, &height, &fs);
944+
pg_wcssize((unsigned char *) headers[i], strlen(headers[i]), encoding,
945+
&width, &height, &fs);
931946
if (width > hwidth)
932947
hwidth = width;
933948
if (height > hheight)
@@ -953,7 +968,8 @@ print_aligned_vertical(const char *title, const char *const * headers,
953968
else
954969
numeric_locale_len = 0;
955970

956-
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding, &width, &height, &fs);
971+
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
972+
&width, &height, &fs);
957973
width += numeric_locale_len;
958974
if (width > dwidth)
959975
dwidth = width;
@@ -1041,9 +1057,11 @@ print_aligned_vertical(const char *title, const char *const * headers,
10411057

10421058
/* Format the header */
10431059
pg_wcsformat((unsigned char *) headers[i % col_count],
1044-
strlen(headers[i % col_count]), encoding, hlineptr, hheight);
1060+
strlen(headers[i % col_count]),
1061+
encoding, hlineptr, hheight);
10451062
/* Format the data */
1046-
pg_wcsformat((unsigned char *) *ptr, strlen(*ptr), encoding, dlineptr, dheight);
1063+
pg_wcsformat((unsigned char *) *ptr, strlen(*ptr), encoding,
1064+
dlineptr, dheight);
10471065

10481066
line_count = 0;
10491067
dcomplete = hcomplete = 0;
@@ -1182,7 +1200,7 @@ print_html_text(const char *title, const char *const * headers,
11821200
{
11831201
bool opt_tuples_only = opt->tuples_only;
11841202
bool opt_numeric_locale = opt->numericLocale;
1185-
unsigned short int opt_border = opt->border;
1203+
unsigned short opt_border = opt->border;
11861204
const char *opt_table_attr = opt->tableAttr;
11871205
unsigned int col_count = 0;
11881206
unsigned int i;
@@ -1283,7 +1301,7 @@ print_html_vertical(const char *title, const char *const * headers,
12831301
{
12841302
bool opt_tuples_only = opt->tuples_only;
12851303
bool opt_numeric_locale = opt->numericLocale;
1286-
unsigned short int opt_border = opt->border;
1304+
unsigned short opt_border = opt->border;
12871305
const char *opt_table_attr = opt->tableAttr;
12881306
unsigned int col_count = 0;
12891307
unsigned long record = opt->prior_records + 1;
@@ -1421,7 +1439,7 @@ print_latex_text(const char *title, const char *const * headers,
14211439
{
14221440
bool opt_tuples_only = opt->tuples_only;
14231441
bool opt_numeric_locale = opt->numericLocale;
1424-
unsigned short int opt_border = opt->border;
1442+
unsigned short opt_border = opt->border;
14251443
unsigned int col_count = 0;
14261444
unsigned int i;
14271445
const char *const * ptr;
@@ -1534,7 +1552,7 @@ print_latex_vertical(const char *title, const char *const * headers,
15341552
{
15351553
bool opt_tuples_only = opt->tuples_only;
15361554
bool opt_numeric_locale = opt->numericLocale;
1537-
unsigned short int opt_border = opt->border;
1555+
unsigned short opt_border = opt->border;
15381556
unsigned int col_count = 0;
15391557
unsigned long record = opt->prior_records + 1;
15401558
unsigned int i;
@@ -1661,7 +1679,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
16611679
{
16621680
bool opt_tuples_only = opt->tuples_only;
16631681
bool opt_numeric_locale = opt->numericLocale;
1664-
unsigned short int opt_border = opt->border;
1682+
unsigned short opt_border = opt->border;
16651683
unsigned int col_count = 0;
16661684
unsigned int i;
16671685
const char *const * ptr;
@@ -1764,7 +1782,7 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
17641782
{
17651783
bool opt_tuples_only = opt->tuples_only;
17661784
bool opt_numeric_locale = opt->numericLocale;
1767-
unsigned short int opt_border = opt->border;
1785+
unsigned short opt_border = opt->border;
17681786
unsigned int col_count = 0;
17691787
unsigned long record = opt->prior_records + 1;
17701788
unsigned int i;
@@ -1970,7 +1988,7 @@ printTable(const char *title,
19701988
static const char *default_footer[] = {NULL};
19711989
FILE *output;
19721990
bool is_pager = false;
1973-
1991+
19741992
if (cancel_pressed)
19751993
return;
19761994

@@ -2216,36 +2234,36 @@ setDecimalLocale(void)
22162234
}
22172235

22182236
/*
2219-
* Returns the byte length to the end of the specified character
2220-
* and number of display characters processed (useful if the string
2221-
* is shorter then dpylen).
2237+
* Compute the byte distance to the end of the string or *target_width
2238+
* display character positions, whichever comes first. Update *target_width
2239+
* to be the number of display character positions actually filled.
22222240
*/
22232241
static int
22242242
strlen_max_width(unsigned char *str, int *target_width, int encoding)
22252243
{
22262244
unsigned char *start = str;
2245+
unsigned char *end = str + strlen((char *) str);
22272246
int curr_width = 0;
22282247

2229-
while (*str && curr_width < *target_width)
2248+
while (str < end)
22302249
{
22312250
int char_width = PQdsplen((char *) str, encoding);
22322251

22332252
/*
22342253
* If the display width of the new character causes
22352254
* the string to exceed its target width, skip it
22362255
* and return. However, if this is the first character
2237-
* of the string (*width == 0), we have to accept it.
2256+
* of the string (curr_width == 0), we have to accept it.
22382257
*/
2239-
if (*target_width - curr_width < char_width && curr_width != 0)
2258+
if (*target_width < curr_width + char_width && curr_width != 0)
22402259
break;
2241-
2242-
str += PQmblen((char *)str, encoding);
22432260

22442261
curr_width += char_width;
2262+
2263+
str += PQmblen((char *) str, encoding);
22452264
}
22462265

22472266
*target_width = curr_width;
22482267

2249-
/* last byte */
22502268
return str - start;
22512269
}

0 commit comments

Comments
 (0)