26 #include <sys/ioctl.h> 35 #include "catalog/pg_type_d.h" 114 const char *vertical_and_horizontal[2];
115 const char *up_and_horizontal[2];
116 const char *down_and_horizontal[2];
149 {
"\342\224\234",
"\342\225\237"},
151 {
"\342\224\244",
"\342\225\242"},
157 {
"\342\225\236",
"\342\225\240"},
159 {
"\342\225\241",
"\342\225\243"},
167 {
"\342\224\274",
"\342\225\252"},
169 {
"\342\224\264",
"\342\225\247"},
171 {
"\342\224\254",
"\342\225\244"},
177 {
"\342\225\253",
"\342\225\254"},
179 {
"\342\225\250",
"\342\225\251"},
181 {
"\342\225\245",
"\342\225\246"},
186 {
"\342\224\224",
"\342\224\202",
"\342\224\214",
"\342\224\200",
"\342\224\220",
"\342\224\230"},
188 {
"\342\225\232",
"\342\225\221",
"\342\225\224",
"\342\225\220",
"\342\225\227",
"\342\225\235"},
203 FILE **fout,
bool *is_pager);
206 FILE *fout,
bool is_pager);
214 if (my_str[0] ==
'-' || my_str[0] ==
'+')
217 return strspn(my_str,
"0123456789");
232 if (strchr(my_str,
'.') != NULL)
260 if (strspn(my_str,
"0123456789+-.eE") != strlen(my_str))
270 if (leading_digits == 0)
274 if (my_str[0] ==
'-' || my_str[0] ==
'+')
276 new_str[new_str_pos++] = my_str[0];
281 for (i = 0; i < int_len; i++)
284 if (i > 0 && --leading_digits == 0)
290 new_str[new_str_pos++] = my_str[
i];
294 if (my_str[i] ==
'.')
302 strcpy(&new_str[new_str_pos], &my_str[i]);
305 Assert(strlen(new_str) <= new_len);
349 unsigned long total_records;
353 ngettext(
"(%lu row)",
"(%lu rows)", total_records),
373 const char *
const *ptr;
374 bool need_recordsep =
false;
382 if (!opt_tuples_only && cont->
title)
384 fputs(cont->
title, fout);
389 if (!opt_tuples_only)
391 for (ptr = cont->
headers; *ptr; ptr++)
397 need_recordsep =
true;
402 need_recordsep =
true;
405 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
410 need_recordsep =
false;
419 need_recordsep =
true;
431 for (f = footers; f; f = f->
next)
436 need_recordsep =
false;
438 fputs(f->
data, fout);
439 need_recordsep =
true;
464 const char *
const *ptr;
465 bool need_recordsep =
false;
473 if (!opt_tuples_only && cont->
title)
475 fputs(cont->
title, fout);
476 need_recordsep =
true;
481 need_recordsep =
true;
484 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
491 need_recordsep =
false;
503 need_recordsep =
true;
517 fputs(f->
data, fout);
550 fputs(lformat->
hrule, fout);
551 else if (border == 2)
554 for (i = 0; i < ncolumns; i++)
556 for (j = 0; j < widths[
i]; j++)
557 fputs(lformat->
hrule, fout);
559 if (i < ncolumns - 1)
564 fprintf(fout,
"%s%s%s", lformat->
hrule,
571 else if (border == 1)
572 fputs(lformat->
hrule, fout);
586 unsigned short opt_border = cont->
opt->
border;
590 unsigned int col_count = 0,
596 unsigned int *width_header,
600 unsigned int *max_nl_lines,
603 unsigned char **format_buf;
604 unsigned int width_total;
605 unsigned int total_header_width;
606 unsigned int extra_row_output_lines = 0;
607 unsigned int extra_output_lines = 0;
609 const char *
const *ptr;
616 int output_columns = 0;
617 bool is_local_pager =
false;
628 width_header =
pg_malloc0(col_count *
sizeof(*width_header));
629 width_average =
pg_malloc0(col_count *
sizeof(*width_average));
630 max_width =
pg_malloc0(col_count *
sizeof(*max_width));
631 width_wrap =
pg_malloc0(col_count *
sizeof(*width_wrap));
632 max_nl_lines =
pg_malloc0(col_count *
sizeof(*max_nl_lines));
633 curr_nl_line =
pg_malloc0(col_count *
sizeof(*curr_nl_line));
634 col_lineptrs =
pg_malloc0(col_count *
sizeof(*col_lineptrs));
635 max_bytes =
pg_malloc0(col_count *
sizeof(*max_bytes));
636 format_buf =
pg_malloc0(col_count *
sizeof(*format_buf));
637 header_done =
pg_malloc0(col_count *
sizeof(*header_done));
638 bytes_output =
pg_malloc0(col_count *
sizeof(*bytes_output));
644 width_average = NULL;
658 for (i = 0; i < col_count; i++)
665 encoding, &width, &nl_lines, &bytes_required);
666 if (width > max_width[i])
668 if (nl_lines > max_nl_lines[i])
669 max_nl_lines[
i] = nl_lines;
670 if (bytes_required > max_bytes[i])
671 max_bytes[
i] = bytes_required;
672 if (nl_lines > extra_row_output_lines)
673 extra_row_output_lines = nl_lines;
678 extra_output_lines += extra_row_output_lines;
679 extra_row_output_lines = 0;
682 for (i = 0, ptr = cont->
cells; *ptr; ptr++, i++, cell_count++)
688 pg_wcssize((
const unsigned char *) *ptr, strlen(*ptr), encoding,
689 &width, &nl_lines, &bytes_required);
691 if (width > max_width[i % col_count])
692 max_width[i % col_count] =
width;
693 if (nl_lines > max_nl_lines[i % col_count])
694 max_nl_lines[i % col_count] = nl_lines;
695 if (bytes_required > max_bytes[i % col_count])
696 max_bytes[i % col_count] = bytes_required;
698 width_average[i % col_count] +=
width;
702 if (col_count != 0 && cell_count != 0)
704 int rows = cell_count / col_count;
706 for (i = 0; i < col_count; i++)
707 width_average[i] /= rows;
712 width_total = col_count;
713 else if (opt_border == 1)
714 width_total = col_count * 3 - ((col_count > 0) ? 1 : 0);
716 width_total = col_count * 3 + 1;
717 total_header_width = width_total;
719 for (i = 0; i < col_count; i++)
721 width_total += max_width[
i];
722 total_header_width += width_header[
i];
732 for (i = 0; i < col_count; i++)
735 col_lineptrs[
i] =
pg_malloc0((max_nl_lines[i] + 1) *
736 sizeof(**col_lineptrs));
740 col_lineptrs[
i]->
ptr = format_buf[
i];
744 for (i = 0; i < col_count; i++)
745 width_wrap[i] = max_width[i];
752 else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
759 struct winsize screen_size;
761 if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
762 output_columns = screen_size.ws_col;
776 if (output_columns > 0 && output_columns >= total_header_width)
779 while (width_total > output_columns)
781 double max_ratio = 0;
790 for (i = 0; i < col_count; i++)
792 if (width_average[i] && width_wrap[i] > width_header[i])
797 ratio = (double) width_wrap[i] / width_average[i] +
799 if (ratio > max_ratio)
812 width_wrap[worst_col]--;
825 (output_columns < total_header_width || output_columns < width_total))
832 if (!is_pager && fout == stdout && output_columns > 0 &&
833 (output_columns < total_header_width || output_columns < width_total))
836 is_pager = is_local_pager =
true;
840 if (!is_pager && fout == stdout)
843 for (i = 0, ptr = cont->
cells; *ptr; ptr++, cell_count++)
849 pg_wcssize((
const unsigned char *) *ptr, strlen(*ptr), encoding,
850 &width, &nl_lines, &bytes_required);
856 if (width > 0 && width_wrap[i])
858 unsigned int extra_lines;
861 extra_lines = ((width - 1) / width_wrap[i]) + nl_lines - 1;
862 if (extra_lines > extra_row_output_lines)
863 extra_row_output_lines = extra_lines;
867 if (++i >= col_count)
871 extra_output_lines += extra_row_output_lines;
872 extra_row_output_lines = 0;
875 IsPagerNeeded(cont, extra_output_lines,
false, &fout, &is_pager);
876 is_local_pager = is_pager;
883 if (cont->
title && !opt_tuples_only)
889 encoding, &width, &height, NULL);
890 if (width >= width_total)
892 fprintf(fout,
"%s\n", cont->
title);
895 fprintf(fout,
"%-*s%s\n", (width_total - width) / 2,
"",
900 if (!opt_tuples_only)
902 int more_col_wrapping;
909 for (i = 0; i < col_count; i++)
911 strlen(cont->
headers[i]), encoding,
912 col_lineptrs[i], max_nl_lines[i]);
914 more_col_wrapping = col_count;
916 memset(header_done,
false, col_count *
sizeof(
bool));
917 while (more_col_wrapping)
922 for (i = 0; i < cont->
ncolumns; i++)
924 struct lineptr *this_line = col_lineptrs[
i] + curr_nl_line;
925 unsigned int nbspace;
927 if (opt_border != 0 ||
934 nbspace = width_wrap[
i] - this_line->
width;
937 fprintf(fout,
"%-*s%s%-*s",
938 nbspace / 2,
"", this_line->
ptr, (nbspace + 1) / 2,
"");
940 if (!(this_line + 1)->ptr)
947 fprintf(fout,
"%*s", width_wrap[i],
"");
953 if (opt_border != 0 && col_count > 0 && i < col_count - 1)
969 for (i = 0, ptr = cont->
cells; *ptr; i += col_count, ptr += col_count)
979 for (j = 0; j < col_count; j++)
981 pg_wcsformat((
const unsigned char *) ptr[j], strlen(ptr[j]), encoding,
982 col_lineptrs[j], max_nl_lines[j]);
986 memset(bytes_output, 0, col_count *
sizeof(
int));
1002 for (j = 0; j < col_count; j++)
1005 struct lineptr *this_line = &col_lineptrs[j][curr_nl_line[j]];
1006 int bytes_to_output;
1007 int chars_to_output = width_wrap[j];
1008 bool finalspaces = (opt_border == 2 ||
1009 (col_count > 0 && j < col_count - 1));
1012 if (opt_border != 0)
1022 if (!this_line->
ptr)
1026 fprintf(fout,
"%*s", chars_to_output,
"");
1033 &chars_to_output, encoding);
1041 if (chars_to_output > width_wrap[j])
1042 chars_to_output = width_wrap[j];
1044 if (cont->
aligns[j] ==
'r')
1047 fprintf(fout,
"%*s", width_wrap[j] - chars_to_output,
"");
1049 (
char *) (this_line->
ptr + bytes_output[j]),
1056 (
char *) (this_line->
ptr + bytes_output[j]),
1060 bytes_output[j] += bytes_to_output;
1063 if (*(this_line->
ptr + bytes_output[j]) !=
'\0')
1069 if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
1071 bytes_output[j] = 0;
1077 if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
1079 if (bytes_output[j] != 0)
1081 else if (curr_nl_line[j] != 0)
1089 if (cont->
aligns[j] !=
'r')
1094 fprintf(fout,
"%*s",
1095 width_wrap[j] - chars_to_output,
"");
1103 else if (opt_border == 2 || (col_count > 0 && j < col_count - 1))
1107 if (opt_border != 0 && (col_count > 0 && j < col_count - 1))
1113 else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL)
1121 if (opt_border == 2)
1125 }
while (more_lines);
1141 for (f = footers; f; f = f->
next)
1142 fprintf(fout,
"%s\n", f->
data);
1150 for (i = 0; i < col_count; i++)
1152 free(col_lineptrs[i]);
1153 free(format_buf[i]);
1156 free(width_average);
1175 const unsigned short opt_border,
1176 unsigned long record,
1177 unsigned int hwidth,
1178 unsigned int dwidth,
1186 if (opt_border == 2)
1188 else if (opt_border == 1)
1189 fputs(lformat->
hrule, fout);
1193 if (opt_border == 0)
1194 reclen = fprintf(fout,
"* Record %lu", record);
1196 reclen = fprintf(fout,
"[ RECORD %lu ]", record);
1198 if (opt_border != 2)
1202 for (i = reclen; i < hwidth; i++)
1203 fputs(opt_border > 0 ? lformat->
hrule :
" ", fout);
1209 fputs(lformat->
hrule, fout);
1213 fputs(lformat->
hrule, fout);
1222 for (i = reclen; i < dwidth; i++)
1223 fputs(opt_border > 0 ? lformat->
hrule :
" ", fout);
1224 if (opt_border == 2)
1231 FILE *fout,
bool is_pager)
1234 unsigned short opt_border = cont->
opt->
border;
1239 const char *
const *
ptr;
1249 bool is_local_pager =
false,
1252 int output_columns = 0;
1269 for (f = footers; f; f = f->
next)
1270 fprintf(fout,
"%s\n", f->
data);
1286 is_local_pager = is_pager;
1290 for (i = 0; i < cont->
ncolumns; i++)
1297 encoding, &width, &height, &fs);
1300 if (height > hheight)
1305 if (fs > hformatsize)
1310 for (i = 0, ptr = cont->
cells; *ptr; ptr++, i++)
1316 pg_wcssize((
const unsigned char *) *ptr, strlen(*ptr), encoding,
1317 &width, &height, &fs);
1320 if (height > dheight)
1325 if (fs > dformatsize)
1333 dlineptr =
pg_malloc((
sizeof(*dlineptr)) * (dheight + 1));
1334 hlineptr =
pg_malloc((
sizeof(*hlineptr)) * (hheight + 1));
1342 if (!opt_tuples_only && cont->
title)
1343 fprintf(fout,
"%s\n", cont->
title);
1351 else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
1358 struct winsize screen_size;
1360 if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
1361 output_columns = screen_size.ws_col;
1371 unsigned int swidth,
1375 if (opt_border == 0)
1389 else if (opt_border == 1)
1398 if (hmultiline && (format == &pg_asciiformat_old))
1414 opt_border < 2 && format != &pg_asciiformat_old)
1418 if (!opt_tuples_only)
1420 if (cont->
nrows > 0)
1421 rwidth = 1 + (int) log10(cont->
nrows);
1422 if (opt_border == 0)
1424 else if (opt_border == 1)
1436 width = hwidth + swidth + dwidth;
1441 if (output_columns > 0)
1443 unsigned int min_width;
1446 min_width = hwidth + swidth + 3;
1448 if (min_width < rwidth)
1451 if (output_columns >= width)
1455 newdwidth = width - hwidth - swidth;
1457 else if (output_columns < min_width)
1460 newdwidth = min_width - hwidth - swidth;
1465 newdwidth = output_columns - hwidth - swidth;
1472 newdwidth = width - hwidth - swidth;
1479 if (newdwidth < dwidth && !dmultiline &&
1480 opt_border < 2 && format != &pg_asciiformat_old)
1493 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
1514 unsigned int lhwidth = hwidth;
1516 if ((opt_border < 2) &&
1518 (format == &pg_asciiformat_old))
1521 if (!opt_tuples_only)
1523 lhwidth, dwidth, pos, fout);
1532 encoding, hlineptr, hheight);
1534 pg_wcsformat((
const unsigned char *) *ptr, strlen(*ptr), encoding,
1542 dcomplete = hcomplete = 0;
1544 chars_to_output = dlineptr[dline].
width;
1545 while (!dcomplete || !hcomplete)
1548 if (opt_border == 2)
1549 fprintf(fout,
"%s", dformat->
leftvrule);
1554 int swidth = hwidth,
1555 target_width = hwidth;
1560 if ((opt_border == 2) ||
1561 (hmultiline && (format == &pg_asciiformat_old)))
1569 fprintf(fout,
"%-s", hlineptr[hline].ptr);
1574 swidth -= target_width;
1576 fprintf(fout,
"%*s", swidth,
" ");
1581 if (hlineptr[hline + 1].ptr)
1584 if ((opt_border > 0) ||
1585 (hmultiline && (format != &pg_asciiformat_old)))
1592 if ((opt_border > 0) ||
1593 (hmultiline && (format != &pg_asciiformat_old)))
1600 unsigned int swidth = hwidth + opt_border;
1602 if ((opt_border < 2) &&
1604 (format == &pg_asciiformat_old))
1607 if ((opt_border == 0) &&
1608 (format != &pg_asciiformat_old) &&
1612 fprintf(fout,
"%*s", swidth,
" ");
1620 else if (dline == 0)
1629 int target_width = dwidth,
1636 fputs(offset == 0 ?
" " : format->
wrap_left, fout);
1642 &target_width, encoding);
1643 fputnbytes(fout, (
char *) (dlineptr[dline].ptr + offset),
1646 chars_to_output -= target_width;
1647 offset += bytes_to_output;
1650 swidth -= target_width;
1652 if (chars_to_output)
1655 if ((opt_border > 1) ||
1656 (dmultiline && (format != &pg_asciiformat_old)))
1659 fprintf(fout,
"%*s", swidth,
" ");
1663 else if (dlineptr[dline + 1].ptr)
1666 if ((opt_border > 1) ||
1667 (dmultiline && (format != &pg_asciiformat_old)))
1670 fprintf(fout,
"%*s", swidth,
" ");
1675 chars_to_output = dlineptr[dline].
width;
1683 fprintf(fout,
"%*s", swidth,
" ");
1690 if (opt_border == 2)
1704 fprintf(fout,
"%*s %s\n", dwidth,
"", dformat->
rightvrule);
1723 fprintf(fout,
"%s\n", f->
data);
1748 bool leading_space =
true;
1750 for (p = in; *p; p++)
1755 fputs(
"&", fout);
1758 fputs(
"<", fout);
1761 fputs(
">", fout);
1764 fputs(
"<br />\n", fout);
1767 fputs(
""", fout);
1772 fputs(
" ", fout);
1780 leading_space =
false;
1789 unsigned short opt_border = cont->
opt->
border;
1792 const char *
const *ptr;
1799 fprintf(fout,
"<table border=\"%d\"", opt_border);
1801 fprintf(fout,
" %s", opt_table_attr);
1805 if (!opt_tuples_only && cont->
title)
1807 fputs(
" <caption>", fout);
1809 fputs(
"</caption>\n", fout);
1813 if (!opt_tuples_only)
1815 fputs(
" <tr>\n", fout);
1816 for (ptr = cont->
headers; *ptr; ptr++)
1818 fputs(
" <th align=\"center\">", fout);
1820 fputs(
"</th>\n", fout);
1822 fputs(
" </tr>\n", fout);
1827 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
1833 fputs(
" <tr valign=\"top\">\n", fout);
1836 fprintf(fout,
" <td align=\"%s\">", cont->
aligns[(i) % cont->
ncolumns] ==
'r' ?
"right" :
"left");
1838 if ((*ptr)[strspn(*ptr,
" \t")] ==
'\0')
1839 fputs(
" ", fout);
1843 fputs(
"</td>\n", fout);
1846 fputs(
" </tr>\n", fout);
1853 fputs(
"</table>\n", fout);
1861 for (f = footers; f; f = f->
next)
1864 fputs(
"<br />\n", fout);
1866 fputs(
"</p>", fout);
1878 unsigned short opt_border = cont->
opt->
border;
1882 const char *
const *ptr;
1889 fprintf(fout,
"<table border=\"%d\"", opt_border);
1891 fprintf(fout,
" %s", opt_table_attr);
1895 if (!opt_tuples_only && cont->
title)
1897 fputs(
" <caption>", fout);
1899 fputs(
"</caption>\n", fout);
1904 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
1910 if (!opt_tuples_only)
1912 "\n <tr><td colspan=\"2\" align=\"center\">Record %lu</td></tr>\n",
1915 fputs(
"\n <tr><td colspan=\"2\"> </td></tr>\n", fout);
1917 fputs(
" <tr valign=\"top\">\n" 1920 fputs(
"</th>\n", fout);
1922 fprintf(fout,
" <td align=\"%s\">", cont->
aligns[i % cont->
ncolumns] ==
'r' ?
"right" :
"left");
1924 if ((*ptr)[strspn(*ptr,
" \t")] ==
'\0')
1925 fputs(
" ", fout);
1929 fputs(
"</td>\n </tr>\n", fout);
1934 fputs(
"</table>\n", fout);
1945 fputs(
"<br />\n", fout);
1947 fputs(
"</p>", fout);
1964 for (p = in; *p; p++)
1981 unsigned short opt_border = cont->
opt->
border;
1983 const char *
const *ptr;
1994 if (!opt_tuples_only && cont->
title)
1997 fputs(cont->
title, fout);
2002 fprintf(fout,
"[%scols=\"", !opt_tuples_only ?
"options=\"header\"," :
"");
2003 for (i = 0; i < cont->
ncolumns; i++)
2007 fprintf(fout,
"%s", cont->
aligns[(i) % cont->
ncolumns] ==
'r' ?
">l" :
"<l");
2013 fputs(
",frame=\"none\",grid=\"none\"", fout);
2016 fputs(
",frame=\"none\"", fout);
2019 fputs(
",frame=\"all\",grid=\"all\"", fout);
2023 fputs(
"|====\n", fout);
2026 if (!opt_tuples_only)
2028 for (ptr = cont->
headers; *ptr; ptr++)
2040 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2053 if ((*ptr)[strspn(*ptr,
" \t")] ==
'\0')
2065 fputs(
"|====\n", fout);
2076 fputs(
"\n....\n", fout);
2077 for (f = footers; f; f = f->
next)
2079 fputs(f->
data, fout);
2082 fputs(
"....\n", fout);
2091 unsigned short opt_border = cont->
opt->
border;
2094 const char *
const *ptr;
2105 if (!opt_tuples_only && cont->
title)
2108 fputs(cont->
title, fout);
2113 fputs(
"[cols=\"h,l\"", fout);
2117 fputs(
",frame=\"none\",grid=\"none\"", fout);
2120 fputs(
",frame=\"none\"", fout);
2123 fputs(
",frame=\"all\",grid=\"all\"", fout);
2127 fputs(
"|====\n", fout);
2131 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2137 if (!opt_tuples_only)
2142 fputs(
"2+|\n", fout);
2148 fprintf(fout,
" %s|", cont->
aligns[i % cont->
ncolumns] ==
'r' ?
">l" :
"<l");
2150 if ((*ptr)[strspn(*ptr,
" \t")] ==
'\0')
2157 fputs(
"|====\n", fout);
2166 fputs(
"\n....\n", fout);
2169 fputs(f->
data, fout);
2172 fputs(
"....\n", fout);
2187 for (p = in; *p; p++)
2209 fputs(
"\\backslash", fout);
2212 fputs(
"\\\\", fout);
2224 unsigned short opt_border = cont->
opt->
border;
2226 const char *
const *ptr;
2237 if (!opt_tuples_only && cont->
title)
2239 fputs(
"\\begin{center}\n", fout);
2241 fputs(
"\n\\end{center}\n\n", fout);
2245 fputs(
"\\begin{tabular}{", fout);
2247 if (opt_border >= 2)
2249 for (i = 0; i < cont->
ncolumns; i++)
2251 fputc(*(cont->
aligns + i), fout);
2252 if (opt_border != 0 && i < cont->ncolumns - 1)
2255 if (opt_border >= 2)
2260 if (!opt_tuples_only && opt_border >= 2)
2261 fputs(
"\\hline\n", fout);
2264 if (!opt_tuples_only)
2266 for (i = 0, ptr = cont->
headers; i < cont->ncolumns; i++, ptr++)
2270 fputs(
"\\textit{", fout);
2274 fputs(
" \\\\\n", fout);
2275 fputs(
"\\hline\n", fout);
2280 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2286 fputs(
" \\\\\n", fout);
2287 if (opt_border == 3)
2288 fputs(
"\\hline\n", fout);
2300 if (opt_border == 2)
2301 fputs(
"\\hline\n", fout);
2303 fputs(
"\\end{tabular}\n\n\\noindent ", fout);
2310 for (f = footers; f; f = f->
next)
2313 fputs(
" \\\\\n", fout);
2326 unsigned short opt_border = cont->
opt->
border;
2329 const char *next_opt_table_attr_char = opt_table_attr;
2330 const char *last_opt_table_attr_char = NULL;
2331 const char *
const *ptr;
2342 fputs(
"\\begin{longtable}{", fout);
2344 if (opt_border >= 2)
2347 for (i = 0; i < cont->
ncolumns; i++)
2351 if (*(cont->
aligns + i) ==
'l' && opt_table_attr)
2353 #define LONGTABLE_WHITESPACE " \t\n" 2356 next_opt_table_attr_char += strspn(next_opt_table_attr_char,
2359 if (next_opt_table_attr_char[0] !=
'\0')
2362 fwrite(next_opt_table_attr_char, strcspn(next_opt_table_attr_char,
2364 last_opt_table_attr_char = next_opt_table_attr_char;
2365 next_opt_table_attr_char += strcspn(next_opt_table_attr_char,
2367 fputs(
"\\textwidth}", fout);
2370 else if (last_opt_table_attr_char != NULL)
2373 fwrite(last_opt_table_attr_char, strcspn(last_opt_table_attr_char,
2375 fputs(
"\\textwidth}", fout);
2381 fputc(*(cont->
aligns + i), fout);
2383 if (opt_border != 0 && i < cont->ncolumns - 1)
2387 if (opt_border >= 2)
2393 if (!opt_tuples_only)
2396 if (opt_border >= 2)
2397 fputs(
"\\toprule\n", fout);
2398 for (i = 0, ptr = cont->
headers; i < cont->ncolumns; i++, ptr++)
2402 fputs(
"\\small\\textbf{\\textit{", fout);
2406 fputs(
" \\\\\n", fout);
2407 fputs(
"\\midrule\n\\endfirsthead\n", fout);
2410 if (opt_border >= 2)
2411 fputs(
"\\toprule\n", fout);
2412 for (i = 0, ptr = cont->
headers; i < cont->ncolumns; i++, ptr++)
2416 fputs(
"\\small\\textbf{\\textit{", fout);
2420 fputs(
" \\\\\n", fout);
2422 if (opt_border != 3)
2423 fputs(
"\\midrule\n", fout);
2424 fputs(
"\\endhead\n", fout);
2427 if (!opt_tuples_only && cont->
title)
2430 if (opt_border == 2)
2431 fputs(
"\\bottomrule\n", fout);
2432 fputs(
"\\caption[", fout);
2434 fputs(
" (Continued)]{", fout);
2436 fputs(
"}\n\\endfoot\n", fout);
2437 if (opt_border == 2)
2438 fputs(
"\\bottomrule\n", fout);
2439 fputs(
"\\caption[", fout);
2443 fputs(
"}\n\\endlastfoot\n", fout);
2446 else if (opt_border >= 2)
2448 fputs(
"\\bottomrule\n\\endfoot\n", fout);
2449 fputs(
"\\bottomrule\n\\endlastfoot\n", fout);
2455 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2458 if (i != 0 && i % cont->
ncolumns != 0)
2459 fputs(
"\n&\n", fout);
2460 fputs(
"\\raggedright{", fout);
2465 fputs(
" \\tabularnewline\n", fout);
2466 if (opt_border == 3)
2467 fputs(
" \\hline\n", fout);
2474 fputs(
"\\end{longtable}\n", fout);
2482 unsigned short opt_border = cont->
opt->
border;
2485 const char *
const *ptr;
2496 if (!opt_tuples_only && cont->
title)
2498 fputs(
"\\begin{center}\n", fout);
2500 fputs(
"\n\\end{center}\n\n", fout);
2504 fputs(
"\\begin{tabular}{", fout);
2505 if (opt_border == 0)
2507 else if (opt_border == 1)
2509 else if (opt_border == 2)
2510 fputs(
"|c|l|", fout);
2515 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2522 if (!opt_tuples_only)
2524 if (opt_border == 2)
2526 fputs(
"\\hline\n", fout);
2527 fprintf(fout,
"\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++);
2530 fprintf(fout,
"\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++);
2532 if (opt_border >= 1)
2533 fputs(
"\\hline\n", fout);
2539 fputs(
" \\\\\n", fout);
2544 if (opt_border == 2)
2545 fputs(
"\\hline\n", fout);
2547 fputs(
"\\end{tabular}\n\n\\noindent ", fout);
2557 fputs(
" \\\\\n", fout);
2576 for (p = in; *p; p++)
2580 fputs(
"\\(rs", fout);
2592 unsigned short opt_border = cont->
opt->
border;
2594 const char *
const *ptr;
2605 if (!opt_tuples_only && cont->
title)
2607 fputs(
".LP\n.DS C\n", fout);
2609 fputs(
"\n.DE\n", fout);
2613 fputs(
".LP\n.TS\n", fout);
2614 if (opt_border == 2)
2615 fputs(
"center box;\n", fout);
2617 fputs(
"center;\n", fout);
2619 for (i = 0; i < cont->
ncolumns; i++)
2621 fputc(*(cont->
aligns + i), fout);
2622 if (opt_border > 0 && i < cont->ncolumns - 1)
2628 if (!opt_tuples_only)
2630 for (i = 0, ptr = cont->
headers; i < cont->ncolumns; i++, ptr++)
2634 fputs(
"\\fI", fout);
2636 fputs(
"\\fP", fout);
2638 fputs(
"\n_\n", fout);
2643 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2661 fputs(
".TE\n.DS L\n", fout);
2668 for (f = footers; f; f = f->
next)
2675 fputs(
".DE\n", fout);
2684 unsigned short opt_border = cont->
opt->
border;
2687 const char *
const *ptr;
2688 unsigned short current_format = 0;
2699 if (!opt_tuples_only && cont->
title)
2701 fputs(
".LP\n.DS C\n", fout);
2703 fputs(
"\n.DE\n", fout);
2707 fputs(
".LP\n.TS\n", fout);
2708 if (opt_border == 2)
2709 fputs(
"center box;\n", fout);
2711 fputs(
"center;\n", fout);
2714 if (opt_tuples_only)
2715 fputs(
"c l;\n", fout);
2721 for (i = 0, ptr = cont->
cells; *ptr; i++, ptr++)
2728 if (!opt_tuples_only)
2730 if (current_format != 1)
2732 if (opt_border == 2 && record > 1)
2734 if (current_format != 0)
2735 fputs(
".T&\n", fout);
2736 fputs(
"c s.\n", fout);
2739 fprintf(fout,
"\\fIRecord %lu\\fP\n", record++);
2741 if (opt_border >= 1)
2745 if (!opt_tuples_only)
2747 if (current_format != 2)
2749 if (current_format != 0)
2750 fputs(
".T&\n", fout);
2751 if (opt_border != 1)
2752 fputs(
"c l.\n", fout);
2754 fputs(
"c | l.\n", fout);
2768 fputs(
".TE\n.DS L\n", fout);
2782 fputs(
".DE\n", fout);
2854 if (topt && topt->
pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
2857 unsigned short int pager = topt->
pager;
2860 struct winsize screen_size;
2862 result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
2866 || (lines >= screen_size.ws_row && lines >= min_lines)
2870 const char *pagerprog;
2873 pagerprog = getenv(
"PSQL_PAGER");
2875 pagerprog = getenv(
"PAGER");
2881 if (strspn(pagerprog,
" \t\r\n") == strlen(pagerprog))
2885 pagerpipe = popen(pagerprog,
"w");
2904 if (pagerpipe && pagerpipe != stdout)
2915 fprintf(pagerpipe,
_(
"Interrupted\n"));
2934 const char *title,
const int ncolumns,
const int nrows)
2937 content->
title = title;
2939 content->
nrows = nrows;
2979 fprintf(stderr,
_(
"Cannot add header to table content: " 2980 "column count of %d exceeded.\n"),
2993 *content->
align = align;
3011 const bool translate,
const bool mustfree)
3019 fprintf(stderr,
_(
"Cannot add cell to table content: " 3020 "total cell count of %d exceeded.\n"),
3119 content->
opt = NULL;
3120 content->
title = NULL;
3122 content->
cells = NULL;
3125 content->
cell = NULL;
3126 content->
align = NULL;
3151 FILE **fout,
bool *is_pager)
3153 if (*fout == stdout)
3160 lines = cont->
nrows + 1;
3175 *is_pager = (*fout != stdout);
3191 FILE *fout,
bool is_pager, FILE *flog)
3193 bool is_local_pager =
false;
3207 is_local_pager = is_pager;
3268 fprintf(stderr,
_(
"invalid output format (internal error): %d"),
3288 FILE *fout,
bool is_pager, FILE *flog)
3305 for (i = 0; i < cont.
ncolumns; i++)
3313 for (r = 0; r < cont.
nrows; r++)
3315 for (c = 0; c < cont.
ncolumns; c++)
3318 bool mustfree =
false;
3343 for (footer = opt->
footers; *footer; footer++)
3380 struct lconv *extlconv;
3382 extlconv = localeconv();
3385 if (*extlconv->decimal_point)
3398 if (groupdigits <= 0 || groupdigits > 6)
3403 if (*extlconv->thousands_sep)
3436 popt->
name =
"unicode";
3487 unsigned char *start =
str;
3488 unsigned char *end = str + strlen((
char *) str);
3493 int char_width =
PQdsplen((
char *) str, encoding);
3501 if (*target_width < curr_width + char_width && curr_width != 0)
3504 curr_width += char_width;
3506 str +=
PQmblen((
char *) str, encoding);
3509 *target_width = curr_width;
static void print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
void printTableSetFooter(printTableContent *const content, const char *footer)
int PQnfields(const PGresult *res)
static void print_unaligned_vertical(const printTableContent *cont, FILE *fout)
static void latex_escaped_print(const char *in, FILE *fout)
static void asciidoc_escaped_print(const char *in, FILE *fout)
void pg_wcsformat(const unsigned char *pwcs, size_t len, int encoding, struct lineptr *lines, int count)
static void print_separator(struct separator sep, FILE *fout)
const printTextFormat * line_style
void printTableCleanup(printTableContent *const content)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
struct unicodeStyleBorderFormat unicodeStyleBorderFormat
struct unicodeStyleRowFormat unicodeStyleRowFormat
char * PQfname(const PGresult *res, int field_num)
void * pg_malloc(size_t size)
const char * midvrule_wrap
static const unicodeStyleFormat unicode_style
static printTableFooter * footers_with_default(const printTableContent *cont)
void disable_sigpipe_trap(void)
const char * header_nl_left
printTextFormat pg_utf8format
static void print_aligned_vertical_line(const printTextFormat *format, const unsigned short opt_border, unsigned long record, unsigned int hwidth, unsigned int dwidth, printTextRule pos, FILE *fout)
void ClosePager(FILE *pagerpipe)
const printTextFormat pg_asciiformat_old
int PQdsplen(const char *s, int encoding)
static void print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager)
static int integer_digits(const char *my_str)
static void print_aligned_vertical(const printTableContent *cont, FILE *fout, bool is_pager)
void set_sigpipe_trap_state(bool ignore)
unicode_linestyle unicode_header_linestyle
static void print_troff_ms_text(const printTableContent *cont, FILE *fout)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
printTextLineFormat lrule[4]
const printTableOpt * opt
int PQntuples(const PGresult *res)
unsigned long prior_records
const char * midvrule_blank
unicode_linestyle unicode_border_linestyle
Datum translate(PG_FUNCTION_ARGS)
const char * header_nl_right
void pg_wcssize(const unsigned char *pwcs, size_t len, int encoding, int *result_width, int *result_height, int *result_format_size)
volatile bool cancel_pressed
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded, FILE **fout, bool *is_pager)
unsigned short int border
unsigned short int expanded
static void print_html_text(const printTableContent *cont, FILE *fout)
FILE * PageOutput(int lines, const printTableOpt *topt)
static void print_latex_text(const printTableContent *cont, FILE *fout)
void * pg_malloc0(size_t size)
static void print_unaligned_text(const printTableContent *cont, FILE *fout)
unicode_linestyle unicode_column_linestyle
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
unsigned char * mbvalidate(unsigned char *pwcs, int encoding)
Oid PQftype(const PGresult *res, int field_num)
static void print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
struct unicodeStyleColumnFormat unicodeStyleColumnFormat
static void print_html_vertical(const printTableContent *cont, FILE *fout)
char * pg_strdup(const char *in)
#define LONGTABLE_WHITESPACE
static void _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, unsigned short border, printTextRule pos, const printTextFormat *format, FILE *fout)
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
void restore_sigpipe_trap(void)
char column_type_alignment(Oid ftype)
static bool always_ignore_sigpipe
struct unicodeStyleFormat unicodeStyleFormat
#define ngettext(s, p, n)
static void troff_ms_escaped_print(const char *in, FILE *fout)
void printTableAddFooter(printTableContent *const content, const char *footer)
static void cleanup(void)
static void print_latex_longtable_text(const printTableContent *cont, FILE *fout)
printTableFooter * footer
static printTableFooter default_footer_cell
static void print_asciidoc_text(const printTableContent *cont, FILE *fout)
pqsigfunc pqsignal(int signum, pqsigfunc handler)
struct separator fieldSep
const printTextFormat * get_line_style(const printTableOpt *opt)
static char * format_numeric_locale(const char *my_str)
#define Assert(condition)
void setDecimalLocale(void)
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
static void header(const char *fmt,...) pg_attribute_printf(1
printTableFooter * footers
static int strlen_max_width(unsigned char *str, int *target_width, int encoding)
static void fputnbytes(FILE *f, const char *str, size_t n)
static char * decimal_point
static void print_latex_vertical(const printTableContent *cont, FILE *fout)
void html_escaped_print(const char *in, FILE *fout)
void refresh_utf8format(const printTableOpt *opt)
static char * thousands_sep
const printTextFormat pg_asciiformat
struct separator recordSep
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
const bool * translate_columns
int PQmblen(const char *s, int encoding)
static int additional_numeric_locale_len(const char *my_str)
static char default_footer[100]