aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/print.c')
-rw-r--r--src/bin/psql/print.c969
1 files changed, 528 insertions, 441 deletions
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 68c675c06f8..2dcf964a8a9 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -3,13 +3,10 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.99 2008/05/10 03:31:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.100 2008/05/12 22:59:58 alvherre Exp $
*/
#include "postgres_fe.h"
-#include "print.h"
-#include "catalog/pg_type.h"
-
#include <math.h>
#include <signal.h>
#include <unistd.h>
@@ -24,9 +21,12 @@
#include <locale.h>
+#include "catalog/pg_type.h"
#include "pqsignal.h"
+#include "common.h"
#include "mbprint.h"
+#include "print.h"
/*
* We define the cancel_pressed flag in this file, rather than common.c where
@@ -175,16 +175,12 @@ format_numeric_locale(const char *my_str)
static void
-print_unaligned_text(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_unaligned_text(const printTableContent *cont, FILE *fout)
{
- const char *opt_fieldsep = opt->fieldSep;
- const char *opt_recordsep = opt->recordSep;
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned int col_count = 0;
+ const char *opt_fieldsep = cont->opt->fieldSep;
+ const char *opt_recordsep = cont->opt->recordSep;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
unsigned int i;
const char *const * ptr;
bool need_recordsep = false;
@@ -197,22 +193,18 @@ print_unaligned_text(const char *title, const char *const * headers,
if (!opt_recordsep)
opt_recordsep = "";
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
- fprintf(fout, "%s%s", title, opt_recordsep);
+ if (!opt_tuples_only && cont->title)
+ fprintf(fout, "%s%s", cont->title, opt_recordsep);
/* print headers */
if (!opt_tuples_only)
{
- for (ptr = headers; *ptr; ptr++)
+ for (ptr = cont->headers; *ptr; ptr++)
{
- if (ptr != headers)
+ if (ptr != cont->headers)
fputs(opt_fieldsep, fout);
fputs(*ptr, fout);
}
@@ -224,7 +216,7 @@ print_unaligned_text(const char *title, const char *const * headers,
need_recordsep = true;
/* print cells */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
if (need_recordsep)
{
@@ -233,7 +225,7 @@ print_unaligned_text(const char *title, const char *const * headers,
if (cancel_pressed)
break;
}
- if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
+ if (cont->aligns[i % cont->ncolumns] == 'r' && opt_numeric_locale)
{
char *my_cell = format_numeric_locale(*ptr);
@@ -243,27 +235,30 @@ print_unaligned_text(const char *title, const char *const * headers,
else
fputs(*ptr, fout);
- if ((i + 1) % col_count)
+ if ((i + 1) % cont->ncolumns)
fputs(opt_fieldsep, fout);
else
need_recordsep = true;
}
/* print footers */
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
- if (!opt_tuples_only && footers && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ for (f = cont->footers; f; f = f->next)
{
if (need_recordsep)
{
fputs(opt_recordsep, fout);
need_recordsep = false;
}
- fputs(*ptr, fout);
+ fputs(f->data, fout);
need_recordsep = true;
}
-
+ }
/* the last record needs to be concluded with a newline */
if (need_recordsep)
fputc('\n', fout);
@@ -272,16 +267,12 @@ print_unaligned_text(const char *title, const char *const * headers,
static void
-print_unaligned_vertical(const char *title, const char *const * headers,
- const char *const * cells,
- const char *const * footers, const char *opt_align,
- const printTableOpt *opt, FILE *fout)
+print_unaligned_vertical(const printTableContent *cont, FILE *fout)
{
- const char *opt_fieldsep = opt->fieldSep;
- const char *opt_recordsep = opt->recordSep;
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned int col_count = 0;
+ const char *opt_fieldsep = cont->opt->fieldSep;
+ const char *opt_recordsep = cont->opt->recordSep;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
unsigned int i;
const char *const * ptr;
bool need_recordsep = false;
@@ -294,16 +285,12 @@ print_unaligned_vertical(const char *title, const char *const * headers,
if (!opt_recordsep)
opt_recordsep = "";
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
- fputs(title, fout);
+ fputs(cont->title, fout);
need_recordsep = true;
}
}
@@ -312,7 +299,7 @@ print_unaligned_vertical(const char *title, const char *const * headers,
need_recordsep = true;
/* print records */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
if (need_recordsep)
{
@@ -324,9 +311,9 @@ print_unaligned_vertical(const char *title, const char *const * headers,
break;
}
- fputs(headers[i % col_count], fout);
+ fputs(cont->headers[i % cont->ncolumns], fout);
fputs(opt_fieldsep, fout);
- if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
+ if (cont->aligns[i % cont->ncolumns] == 'r' && opt_numeric_locale)
{
char *my_cell = format_numeric_locale(*ptr);
@@ -336,22 +323,24 @@ print_unaligned_vertical(const char *title, const char *const * headers,
else
fputs(*ptr, fout);
- if ((i + 1) % col_count)
+ if ((i + 1) % cont->ncolumns)
fputs(opt_recordsep, fout);
else
need_recordsep = true;
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
/* print footers */
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
{
+ printTableFooter *f;
+
fputs(opt_recordsep, fout);
- for (ptr = footers; *ptr; ptr++)
+ for (f = cont->footers; f; f = f->next)
{
fputs(opt_recordsep, fout);
- fputs(*ptr, fout);
+ fputs(f->data, fout);
}
}
@@ -367,7 +356,8 @@ print_unaligned_vertical(const char *title, const char *const * headers,
/* draw "line" */
static void
-_print_horizontal_line(const unsigned int col_count, const unsigned int *widths, unsigned short border, FILE *fout)
+_print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
+ unsigned short border, FILE *fout)
{
unsigned int i,
j;
@@ -377,12 +367,12 @@ _print_horizontal_line(const unsigned int col_count, const unsigned int *widths,
else if (border == 2)
fputs("+-", fout);
- for (i = 0; i < col_count; i++)
+ for (i = 0; i < ncolumns; i++)
{
for (j = 0; j < widths[i]; j++)
fputc('-', fout);
- if (i < col_count - 1)
+ if (i < ncolumns - 1)
{
if (border == 0)
fputc(' ', fout);
@@ -404,15 +394,12 @@ _print_horizontal_line(const unsigned int col_count, const unsigned int *widths,
* Print pretty boxes around cells.
*/
static void
-print_aligned_text(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- bool is_pager, FILE *fout)
+print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- int encoding = opt->encoding;
- unsigned short opt_border = opt->border;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ int encoding = cont->opt->encoding;
+ unsigned short opt_border = cont->opt->border;
unsigned int col_count = 0, cell_count = 0;
@@ -444,12 +431,9 @@ print_aligned_text(const char *title, const char *const * headers,
if (opt_border > 2)
opt_border = 2;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (col_count > 0)
+ if (cont->ncolumns > 0)
{
+ col_count = cont->ncolumns;
width_header = pg_local_calloc(col_count, sizeof(*width_header));
width_average = pg_local_calloc(col_count, sizeof(*width_average));
max_width = pg_local_calloc(col_count, sizeof(*max_width));
@@ -484,8 +468,8 @@ print_aligned_text(const char *title, const char *const * headers,
nl_lines,
bytes_required;
- pg_wcssize((unsigned char *) headers[i], strlen(headers[i]), encoding,
- &width, &nl_lines, &bytes_required);
+ pg_wcssize((unsigned char *) cont->headers[i], strlen(cont->headers[i]),
+ encoding, &width, &nl_lines, &bytes_required);
if (width > max_width[i])
max_width[i] = width;
if (nl_lines > max_nl_lines[i])
@@ -497,7 +481,7 @@ print_aligned_text(const char *title, const char *const * headers,
}
/* scan all cells, find maximum width, compute cell_count */
- for (i = 0, ptr = cells; *ptr; ptr++, i++, cell_count++)
+ for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
{
int width,
nl_lines,
@@ -506,7 +490,7 @@ print_aligned_text(const char *title, const char *const * headers,
/* Get width, ignore nl_lines */
pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
&width, &nl_lines, &bytes_required);
- if (opt_numeric_locale && opt_align[i % col_count] == 'r')
+ if (opt_numeric_locale && cont->aligns[i % col_count] == 'r')
{
width += additional_numeric_locale_len(*ptr);
bytes_required += additional_numeric_locale_len(*ptr);
@@ -568,17 +552,17 @@ print_aligned_text(const char *title, const char *const * headers,
for (i = 0; i < col_count; i++)
width_wrap[i] = max_width[i];
- if (opt->format == PRINT_WRAPPED)
+ if (cont->opt->format == PRINT_WRAPPED)
{
/*
* Choose target output width: \pset columns, or $COLUMNS, or ioctl
*/
- if (opt->columns > 0)
- output_columns = opt->columns;
+ if (cont->opt->columns > 0)
+ output_columns = cont->opt->columns;
else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
{
- if (opt->env_columns > 0)
- output_columns = opt->env_columns;
+ if (cont->opt->env_columns > 0)
+ output_columns = cont->opt->env_columns;
#ifdef TIOCGWINSZ
else
{
@@ -640,19 +624,22 @@ print_aligned_text(const char *title, const char *const * headers,
}
/* time to output */
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (title && !opt_tuples_only)
+ if (cont->title && !opt_tuples_only)
{
int width, height;
- pg_wcssize((unsigned char *) title, strlen(title), encoding,
- &width, &height, NULL);
+ pg_wcssize((unsigned char *) cont->title, strlen(cont->title),
+ encoding, &width, &height, NULL);
if (width >= width_total)
- fprintf(fout, "%s\n", title); /* Aligned */
+ /* Aligned */
+ fprintf(fout, "%s\n", cont->title);
else
- fprintf(fout, "%-*s%s\n", (width_total - width) / 2, "", title); /* Centered */
+ /* Centered */
+ fprintf(fout, "%-*s%s\n", (width_total - width) / 2, "",
+ cont->title);
}
/* print headers */
@@ -665,8 +652,9 @@ print_aligned_text(const char *title, const char *const * headers,
_print_horizontal_line(col_count, width_wrap, opt_border, fout);
for (i = 0; i < col_count; i++)
- pg_wcsformat((unsigned char *) headers[i], strlen(headers[i]),
- encoding, col_lineptrs[i], max_nl_lines[i]);
+ pg_wcsformat((unsigned char *) cont->headers[i],
+ strlen(cont->headers[i]), encoding,
+ col_lineptrs[i], max_nl_lines[i]);
more_col_wrapping = col_count;
curr_nl_line = 0;
@@ -678,7 +666,7 @@ print_aligned_text(const char *title, const char *const * headers,
else if (opt_border == 1)
fputc(curr_nl_line ? '+' : ' ', fout);
- for (i = 0; i < col_count; i++)
+ for (i = 0; i < cont->ncolumns; i++)
{
unsigned int nbspace;
@@ -722,7 +710,7 @@ print_aligned_text(const char *title, const char *const * headers,
}
/* print cells, one loop per row */
- for (i = 0, ptr = cells; *ptr; i += col_count, ptr += col_count)
+ for (i = 0, ptr = cont->cells; *ptr; i += col_count, ptr += col_count)
{
bool more_lines;
@@ -739,7 +727,7 @@ print_aligned_text(const char *title, const char *const * headers,
col_lineptrs[j], max_nl_lines[j]);
curr_nl_line[j] = 0;
- if (opt_numeric_locale && opt_align[j % col_count] == 'r')
+ if (opt_numeric_locale && cont->aligns[j % col_count] == 'r')
{
char *my_cell;
@@ -798,7 +786,7 @@ print_aligned_text(const char *title, const char *const * headers,
if (chars_to_output > width_wrap[j])
chars_to_output = width_wrap[j];
- if (opt_align[j] == 'r') /* Right aligned cell */
+ if (cont->aligns[j] == 'r') /* Right aligned cell */
{
/* spaces first */
fprintf(fout, "%*s", width_wrap[j] - chars_to_output, "");
@@ -857,15 +845,19 @@ print_aligned_text(const char *title, const char *const * headers,
} while (more_lines);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
if (opt_border == 2 && !cancel_pressed)
_print_horizontal_line(col_count, width_wrap, opt_border, fout);
/* print footers */
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
+ if (cont->footers && !opt_tuples_only && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ for (f = cont->footers; f; f = f->next)
+ fprintf(fout, "%s\n", f->data);
+ }
/*
* for some reason MinGW (and MSVC) outputs an extra newline, so this
@@ -894,17 +886,13 @@ print_aligned_text(const char *title, const char *const * headers,
static void
-print_aligned_vertical(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_aligned_vertical(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- int encoding = opt->encoding;
- unsigned int col_count = 0;
- unsigned long record = opt->prior_records + 1;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
+ int encoding = cont->opt->encoding;
+ unsigned long record = cont->opt->prior_records + 1;
const char *const * ptr;
unsigned int i,
hwidth = 0,
@@ -914,7 +902,6 @@ print_aligned_vertical(const char *title, const char *const * headers,
hformatsize = 0,
dformatsize = 0;
char *divider;
- unsigned int cell_count = 0;
struct lineptr *hlineptr,
*dlineptr;
@@ -924,25 +911,22 @@ print_aligned_vertical(const char *title, const char *const * headers,
if (opt_border > 2)
opt_border = 2;
- if (cells[0] == NULL && opt->start_table && opt->stop_table)
+ if (cont->cells[0] == NULL && cont->opt->start_table &&
+ cont->opt->stop_table)
{
fprintf(fout, _("(No rows)\n"));
return;
}
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
/* Find the maximum dimensions for the headers */
- for (i = 0; i < col_count; i++)
+ for (i = 0; i < cont->ncolumns; i++)
{
int width,
height,
fs;
- pg_wcssize((unsigned char *) headers[i], strlen(headers[i]), encoding,
- &width, &height, &fs);
+ pg_wcssize((unsigned char *) cont->headers[i], strlen(cont->headers[i]),
+ encoding, &width, &height, &fs);
if (width > hwidth)
hwidth = width;
if (height > hheight)
@@ -951,19 +935,15 @@ print_aligned_vertical(const char *title, const char *const * headers,
hformatsize = fs;
}
- /* Count cells, find their lengths */
- for (ptr = cells; *ptr; ptr++)
- cell_count++;
-
/* find longest data cell */
- for (i = 0, ptr = cells; *ptr; ptr++, i++)
+ for (i = 0, ptr = cont->cells; *ptr; ptr++, i++)
{
int numeric_locale_len;
int width,
height,
fs;
- if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
+ if (cont->aligns[i % cont->ncolumns] == 'r' && opt_numeric_locale)
numeric_locale_len = additional_numeric_locale_len(*ptr);
else
numeric_locale_len = 0;
@@ -1005,21 +985,21 @@ print_aligned_vertical(const char *title, const char *const * headers,
if (opt_border == 2)
strcat(divider, "-+");
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
- fprintf(fout, "%s\n", title);
+ if (!opt_tuples_only && cont->title)
+ fprintf(fout, "%s\n", cont->title);
}
/* print records */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
int line_count,
dcomplete,
hcomplete;
- if (i % col_count == 0)
+ if (i % cont->ncolumns == 0)
{
if (cancel_pressed)
break;
@@ -1038,26 +1018,20 @@ print_aligned_vertical(const char *title, const char *const * headers,
fprintf(fout, "%.*s%s\n", opt_border, divider, record_str);
else
{
- char *div_copy = strdup(divider);
-
- if (!div_copy)
- {
- fprintf(stderr, _("out of memory\n"));
- exit(EXIT_FAILURE);
- }
+ char *div_copy = pg_strdup(divider);
strncpy(div_copy + opt_border, record_str, record_str_len);
fprintf(fout, "%s\n", div_copy);
free(div_copy);
}
}
- else if (i != 0 || !opt->start_table || opt_border == 2)
+ else if (i != 0 || !cont->opt->start_table || opt_border == 2)
fprintf(fout, "%s\n", divider);
}
/* Format the header */
- pg_wcsformat((unsigned char *) headers[i % col_count],
- strlen(headers[i % col_count]),
+ pg_wcsformat((unsigned char *) cont->headers[i % cont->ncolumns],
+ strlen(cont->headers[i % cont->ncolumns]),
encoding, hlineptr, hheight);
/* Format the data */
pg_wcsformat((unsigned char *) *ptr, strlen(*ptr), encoding,
@@ -1087,7 +1061,7 @@ print_aligned_vertical(const char *title, const char *const * headers,
if (!dcomplete)
{
- if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
+ if (cont->aligns[i % cont->ncolumns] == 'r' && opt_numeric_locale)
{
char *my_cell = format_numeric_locale((char *) dlineptr[line_count].ptr);
@@ -1121,18 +1095,20 @@ print_aligned_vertical(const char *title, const char *const * headers,
}
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
if (opt_border == 2 && !cancel_pressed)
fprintf(fout, "%s\n", divider);
/* print footers */
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
{
+ printTableFooter *f;
+
if (opt_border < 2)
fputc('\n', fout);
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
+ for (f = cont->footers; f; f = f->next)
+ fprintf(fout, "%s\n", f->data);
}
fputc('\n', fout);
@@ -1193,27 +1169,19 @@ html_escaped_print(const char *in, FILE *fout)
static void
-print_html_text(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_html_text(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- const char *opt_table_attr = opt->tableAttr;
- unsigned int col_count = 0;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
+ const char *opt_table_attr = cont->opt->tableAttr;
unsigned int i;
const char *const * ptr;
if (cancel_pressed)
return;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
@@ -1221,10 +1189,10 @@ print_html_text(const char *title, const char *const * headers,
fputs(">\n", fout);
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
fputs(" <caption>", fout);
- html_escaped_print(title, fout);
+ html_escaped_print(cont->title, fout);
fputs("</caption>\n", fout);
}
@@ -1232,7 +1200,7 @@ print_html_text(const char *title, const char *const * headers,
if (!opt_tuples_only)
{
fputs(" <tr>\n", fout);
- for (ptr = headers; *ptr; ptr++)
+ for (ptr = cont->headers; *ptr; ptr++)
{
fputs(" <th align=\"center\">", fout);
html_escaped_print(*ptr, fout);
@@ -1243,20 +1211,20 @@ print_html_text(const char *title, const char *const * headers,
}
/* print cells */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
- if (i % col_count == 0)
+ if (i % cont->ncolumns == 0)
{
if (cancel_pressed)
break;
fputs(" <tr valign=\"top\">\n", fout);
}
- fprintf(fout, " <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
+ fprintf(fout, " <td align=\"%s\">", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left");
/* is string only whitespace? */
if ((*ptr)[strspn(*ptr, " \t")] == '\0')
fputs("&nbsp; ", fout);
- else if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
+ else if (cont->aligns[i % cont->ncolumns] == 'r' && opt_numeric_locale)
{
char *my_cell = format_numeric_locale(*ptr);
@@ -1268,21 +1236,23 @@ print_html_text(const char *title, const char *const * headers,
fputs("</td>\n", fout);
- if ((i + 1) % col_count == 0)
+ if ((i + 1) % cont->ncolumns == 0)
fputs(" </tr>\n", fout);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
fputs("</table>\n", fout);
/* print footers */
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
{
+ printTableFooter *f;
+
fputs("<p>", fout);
- for (ptr = footers; *ptr; ptr++)
+ for (f = cont->footers; f; f = f->next)
{
- html_escaped_print(*ptr, fout);
+ html_escaped_print(f->data, fout);
fputs("<br />\n", fout);
}
fputs("</p>", fout);
@@ -1294,28 +1264,20 @@ print_html_text(const char *title, const char *const * headers,
static void
-print_html_vertical(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_html_vertical(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- const char *opt_table_attr = opt->tableAttr;
- unsigned int col_count = 0;
- unsigned long record = opt->prior_records + 1;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
+ const char *opt_table_attr = cont->opt->tableAttr;
+ unsigned long record = cont->opt->prior_records + 1;
unsigned int i;
const char *const * ptr;
if (cancel_pressed)
return;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
@@ -1323,18 +1285,18 @@ print_html_vertical(const char *title, const char *const * headers,
fputs(">\n", fout);
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
fputs(" <caption>", fout);
- html_escaped_print(title, fout);
+ html_escaped_print(cont->title, fout);
fputs("</caption>\n", fout);
}
}
/* print records */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
- if (i % col_count == 0)
+ if (i % cont->ncolumns == 0)
{
if (cancel_pressed)
break;
@@ -1347,14 +1309,14 @@ print_html_vertical(const char *title, const char *const * headers,
}
fputs(" <tr valign=\"top\">\n"
" <th>", fout);
- html_escaped_print(headers[i % col_count], fout);
+ html_escaped_print(cont->headers[i % cont->ncolumns], fout);
fputs("</th>\n", fout);
- fprintf(fout, " <td align=\"%s\">", opt_align[i % col_count] == 'r' ? "right" : "left");
+ fprintf(fout, " <td align=\"%s\">", cont->aligns[i % cont->ncolumns] == 'r' ? "right" : "left");
/* is string only whitespace? */
if ((*ptr)[strspn(*ptr, " \t")] == '\0')
fputs("&nbsp; ", fout);
- else if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
+ else if (cont->aligns[i % cont->ncolumns] == 'r' && opt_numeric_locale)
{
char *my_cell = format_numeric_locale(*ptr);
@@ -1367,17 +1329,19 @@ print_html_vertical(const char *title, const char *const * headers,
fputs("</td>\n </tr>\n", fout);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
fputs("</table>\n", fout);
/* print footers */
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
{
+ printTableFooter *f;
+
fputs("<p>", fout);
- for (ptr = footers; *ptr; ptr++)
+ for (f = cont->footers; f; f = f->next)
{
- html_escaped_print(*ptr, fout);
+ html_escaped_print(f->data, fout);
fputs("<br />\n", fout);
}
fputs("</p>", fout);
@@ -1432,15 +1396,11 @@ latex_escaped_print(const char *in, FILE *fout)
static void
-print_latex_text(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_latex_text(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- unsigned int col_count = 0;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
unsigned int i;
const char *const * ptr;
@@ -1450,17 +1410,13 @@ print_latex_text(const char *title, const char *const * headers,
if (opt_border > 2)
opt_border = 2;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
fputs("\\begin{center}\n", fout);
- latex_escaped_print(title, fout);
+ latex_escaped_print(cont->title, fout);
fputs("\n\\end{center}\n\n", fout);
}
@@ -1469,10 +1425,10 @@ print_latex_text(const char *title, const char *const * headers,
if (opt_border == 2)
fputs("| ", fout);
- for (i = 0; i < col_count; i++)
+ for (i = 0; i < cont->ncolumns; i++)
{
- fputc(*(opt_align + i), fout);
- if (opt_border != 0 && i < col_count - 1)
+ fputc(*(cont->aligns + i), fout);
+ if (opt_border != 0 && i < cont->ncolumns - 1)
fputs(" | ", fout);
}
if (opt_border == 2)
@@ -1486,7 +1442,7 @@ print_latex_text(const char *title, const char *const * headers,
/* print headers */
if (!opt_tuples_only)
{
- for (i = 0, ptr = headers; i < col_count; i++, ptr++)
+ for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
{
if (i != 0)
fputs(" & ", fout);
@@ -1500,7 +1456,7 @@ print_latex_text(const char *title, const char *const * headers,
}
/* print cells */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
if (opt_numeric_locale)
{
@@ -1512,7 +1468,7 @@ print_latex_text(const char *title, const char *const * headers,
else
latex_escaped_print(*ptr, fout);
- if ((i + 1) % col_count == 0)
+ if ((i + 1) % cont->ncolumns == 0)
{
fputs(" \\\\\n", fout);
if (cancel_pressed)
@@ -1522,7 +1478,7 @@ print_latex_text(const char *title, const char *const * headers,
fputs(" & ", fout);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
if (opt_border == 2)
fputs("\\hline\n", fout);
@@ -1530,11 +1486,13 @@ print_latex_text(const char *title, const char *const * headers,
fputs("\\end{tabular}\n\n\\noindent ", fout);
/* print footers */
- if (footers && !opt_tuples_only && !cancel_pressed)
+ if (cont->footers && !opt_tuples_only && !cancel_pressed)
{
- for (ptr = footers; *ptr; ptr++)
+ printTableFooter *f;
+
+ for (f = cont->footers; f; f = f->next)
{
- latex_escaped_print(*ptr, fout);
+ latex_escaped_print(f->data, fout);
fputs(" \\\\\n", fout);
}
}
@@ -1545,38 +1503,28 @@ print_latex_text(const char *title, const char *const * headers,
static void
-print_latex_vertical(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_latex_vertical(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- unsigned int col_count = 0;
- unsigned long record = opt->prior_records + 1;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
unsigned int i;
const char *const * ptr;
- (void) opt_align; /* currently unused parameter */
-
if (cancel_pressed)
return;
if (opt_border > 2)
opt_border = 2;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
fputs("\\begin{center}\n", fout);
- latex_escaped_print(title, fout);
+ latex_escaped_print(cont->title, fout);
fputs("\n\\end{center}\n\n", fout);
}
@@ -1592,10 +1540,10 @@ print_latex_vertical(const char *title, const char *const * headers,
}
/* print records */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
/* new record */
- if (i % col_count == 0)
+ if (i % cont->ncolumns == 0)
{
if (cancel_pressed)
break;
@@ -1613,13 +1561,13 @@ print_latex_vertical(const char *title, const char *const * headers,
fputs("\\hline\n", fout);
}
- latex_escaped_print(headers[i % col_count], fout);
+ latex_escaped_print(cont->headers[i % cont->ncolumns], fout);
fputs(" & ", fout);
latex_escaped_print(*ptr, fout);
fputs(" \\\\\n", fout);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
if (opt_border == 2)
fputs("\\hline\n", fout);
@@ -1627,19 +1575,21 @@ print_latex_vertical(const char *title, const char *const * headers,
fputs("\\end{tabular}\n\n\\noindent ", fout);
/* print footers */
- if (footers && !opt_tuples_only && !cancel_pressed)
+ if (cont->footers && !opt_tuples_only && !cancel_pressed)
{
- for (ptr = footers; *ptr; ptr++)
+ printTableFooter *f;
+
+ for (f = cont->footers; f; f = f->next)
{
if (opt_numeric_locale)
{
- char *my_cell = format_numeric_locale(*ptr);
+ char *my_cell = format_numeric_locale(f->data);
latex_escaped_print(my_cell, fout);
free(my_cell);
}
else
- latex_escaped_print(*ptr, fout);
+ latex_escaped_print(f->data, fout);
fputs(" \\\\\n", fout);
}
}
@@ -1672,15 +1622,11 @@ troff_ms_escaped_print(const char *in, FILE *fout)
static void
-print_troff_ms_text(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_troff_ms_text(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- unsigned int col_count = 0;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
unsigned int i;
const char *const * ptr;
@@ -1690,17 +1636,13 @@ print_troff_ms_text(const char *title, const char *const * headers,
if (opt_border > 2)
opt_border = 2;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
fputs(".LP\n.DS C\n", fout);
- troff_ms_escaped_print(title, fout);
+ troff_ms_escaped_print(cont->title, fout);
fputs("\n.DE\n", fout);
}
@@ -1711,10 +1653,10 @@ print_troff_ms_text(const char *title, const char *const * headers,
else
fputs("center;\n", fout);
- for (i = 0; i < col_count; i++)
+ for (i = 0; i < cont->ncolumns; i++)
{
- fputc(*(opt_align + i), fout);
- if (opt_border > 0 && i < col_count - 1)
+ fputc(*(cont->aligns + i), fout);
+ if (opt_border > 0 && i < cont->ncolumns - 1)
fputs(" | ", fout);
}
fputs(".\n", fout);
@@ -1722,7 +1664,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
/* print headers */
if (!opt_tuples_only)
{
- for (i = 0, ptr = headers; i < col_count; i++, ptr++)
+ for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
{
if (i != 0)
fputc('\t', fout);
@@ -1735,7 +1677,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
}
/* print cells */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
if (opt_numeric_locale)
{
@@ -1747,7 +1689,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
else
troff_ms_escaped_print(*ptr, fout);
- if ((i + 1) % col_count == 0)
+ if ((i + 1) % cont->ncolumns == 0)
{
fputc('\n', fout);
if (cancel_pressed)
@@ -1757,17 +1699,21 @@ print_troff_ms_text(const char *title, const char *const * headers,
fputc('\t', fout);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
fputs(".TE\n.DS L\n", fout);
/* print footers */
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
+ if (cont->footers && !opt_tuples_only && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ for (f = cont->footers; f; f = f->next)
{
- troff_ms_escaped_print(*ptr, fout);
+ troff_ms_escaped_print(f->data, fout);
fputc('\n', fout);
}
+ }
fputs(".DE\n", fout);
}
@@ -1775,39 +1721,29 @@ print_troff_ms_text(const char *title, const char *const * headers,
static void
-print_troff_ms_vertical(const char *title, const char *const * headers,
- const char *const * cells, const char *const * footers,
- const char *opt_align, const printTableOpt *opt,
- FILE *fout)
+print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
{
- bool opt_tuples_only = opt->tuples_only;
- bool opt_numeric_locale = opt->numericLocale;
- unsigned short opt_border = opt->border;
- unsigned int col_count = 0;
- unsigned long record = opt->prior_records + 1;
+ bool opt_tuples_only = cont->opt->tuples_only;
+ bool opt_numeric_locale = cont->opt->numericLocale;
+ unsigned short opt_border = cont->opt->border;
+ unsigned long record = cont->opt->prior_records + 1;
unsigned int i;
const char *const * ptr;
unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
- (void) opt_align; /* currently unused parameter */
-
if (cancel_pressed)
return;
if (opt_border > 2)
opt_border = 2;
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- if (opt->start_table)
+ if (cont->opt->start_table)
{
/* print title */
- if (!opt_tuples_only && title)
+ if (!opt_tuples_only && cont->title)
{
fputs(".LP\n.DS C\n", fout);
- troff_ms_escaped_print(title, fout);
+ troff_ms_escaped_print(cont->title, fout);
fputs("\n.DE\n", fout);
}
@@ -1826,10 +1762,10 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
current_format = 2; /* assume tuples printed already */
/* print records */
- for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
{
/* new record */
- if (i % col_count == 0)
+ if (i % cont->ncolumns == 0)
{
if (cancel_pressed)
break;
@@ -1864,7 +1800,7 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
}
}
- troff_ms_escaped_print(headers[i % col_count], fout);
+ troff_ms_escaped_print(cont->headers[i % cont->ncolumns], fout);
fputc('\t', fout);
if (opt_numeric_locale)
{
@@ -1879,17 +1815,21 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
fputc('\n', fout);
}
- if (opt->stop_table)
+ if (cont->opt->stop_table)
{
fputs(".TE\n.DS L\n", fout);
/* print footers */
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
+ if (cont->footers && !opt_tuples_only && !cancel_pressed)
+ {
+ printTableFooter *f;
+
+ for (f = cont->footers; f; f = f->next)
{
- troff_ms_escaped_print(*ptr, fout);
+ troff_ms_escaped_print(f->data, fout);
fputc('\n', fout);
}
+ }
fputs(".DE\n", fout);
}
@@ -1976,53 +1916,239 @@ ClosePager(FILE *pagerpipe)
}
}
+/*
+ * Initialise a table contents struct.
+ *
+ * Must be called before any other printTable method is used.
+ *
+ * If you call this, you must call printTableCleanup once you're done with the
+ * table.
+ */
+void
+printTableInit(printTableContent *const content, const printTableOpt *opt,
+ const char *title, int ncolumns, int nrows)
+{
+ content->opt = opt;
+ content->title = title;
+ content->ncolumns = ncolumns;
+ content->nrows = nrows;
+
+ content->headers = pg_local_calloc(ncolumns + 1,
+ sizeof(*content->headers));
+
+ content->cells = pg_local_calloc(ncolumns * nrows + 1,
+ sizeof(*content->cells));
+
+ content->footers = NULL;
+
+ content->aligns = pg_local_calloc(ncolumns + 1,
+ sizeof(*content->align));
+
+ content->header = content->headers;
+ content->cell = content->cells;
+ content->footer = content->footers;
+ content->align = content->aligns;
+}
+/*
+ * Add a header to the table.
+ *
+ * Headers are not duplicated; you must ensure that the header string is
+ * available for the lifetime of the printTableContent struct.
+ *
+ * If translate is true, the function will pass the header through gettext.
+ * Otherwise, the header will not be translated.
+ *
+ * align is either 'l' or 'r', and specifies the alignment for cells in this
+ * column.
+ */
void
-printTable(const char *title,
- const char *const * headers,
- const char *const * cells,
- const char *const * footers,
- const char *align,
- const printTableOpt *opt, FILE *fout, FILE *flog)
+printTableAddHeader(printTableContent *const content, const char *header,
+ bool translate, char align)
+{
+#ifndef ENABLE_NLS
+ (void) translate; /* unused parameter */
+#endif
+
+ if (content->header >= content->headers + content->ncolumns)
+ {
+ fprintf(stderr, _("Cannot add header to table content: "
+ "column count of %d exceeded.\n"),
+ content->ncolumns);
+ exit(EXIT_FAILURE);
+ }
+
+ *content->header = (char *) mbvalidate((unsigned char *) header,
+ content->opt->encoding);
+#ifdef ENABLE_NLS
+ if (translate)
+ *content->header = _(*content->header);
+#endif
+ content->header++;
+
+ *content->align = align;
+ content->align++;
+}
+
+/*
+ * Add a cell to the table.
+ *
+ * Cells are not duplicated; you must ensure that the cell string is available
+ * for the lifetime of the printTableContent struct.
+ *
+ * If translate is true, the function will pass the cell through gettext.
+ * Otherwise, the cell will not be translated.
+ */
+void
+printTableAddCell(printTableContent *const content, const char *cell,
+ bool translate)
+{
+#ifndef ENABLE_NLS
+ (void) translate; /* unused parameter */
+#endif
+
+ if (content->cell >= content->cells + (content->ncolumns * content->nrows))
+ {
+ fprintf(stderr, _("Cannot add cell to table content: "
+ "total cell count of %d exceeded.\n"),
+ content->ncolumns * content->nrows);
+ exit(EXIT_FAILURE);
+ }
+
+ *content->cell = (char *) mbvalidate((unsigned char *) cell,
+ content->opt->encoding);
+
+#ifdef ENABLE_NLS
+ if (translate)
+ *content->header = _(*content->header);
+#endif
+ content->cell++;
+}
+
+/*
+ * Add a footer to the table.
+ *
+ * Footers are added as elements of a singly-linked list, and the content is
+ * strdup'd, so there is no need to keep the original footer string around.
+ *
+ * Footers are never translated by the function. If you want the footer
+ * translated you must do so yourself, before calling printTableAddFooter. The
+ * reason this works differently to headers and cells is that footers tend to
+ * be made of up individually translated components, rather than being
+ * translated as a whole.
+ */
+void
+printTableAddFooter(printTableContent *const content, const char *footer)
+{
+ printTableFooter *f;
+
+ f = pg_local_calloc(1, sizeof(*f));
+ f->data = pg_strdup(footer);
+
+ if (content->footers == NULL)
+ content->footers = f;
+ else
+ content->footer->next = f;
+
+ content->footer = f;
+}
+
+/*
+ * Change the content of the last-added footer.
+ *
+ * The current contents of the last-added footer are freed, and replaced by the
+ * content given in *footer. If there was no previous footer, add a new one.
+ *
+ * The content is strdup'd, so there is no need to keep the original string
+ * around.
+ */
+void
+printTableSetFooter(printTableContent *const content, const char *footer)
+{
+ if (content->footers != NULL)
+ {
+ free(content->footer->data);
+ content->footer->data = pg_strdup(footer);
+ }
+ else
+ printTableAddFooter(content, footer);
+}
+
+/*
+ * Free all memory allocated to this struct.
+ *
+ * Once this has been called, the struct is unusable unless you pass it to
+ * printTableInit() again.
+ */
+void
+printTableCleanup(printTableContent *content)
+{
+ free(content->headers);
+ free(content->cells);
+ free(content->aligns);
+
+ content->opt = NULL;
+ content->title = NULL;
+ content->headers = NULL;
+ content->cells = NULL;
+ content->aligns = NULL;
+ content->header = NULL;
+ content->cell = NULL;
+ content->align = NULL;
+
+ if (content->footers)
+ {
+ for (content->footer = content->footers; content->footer;)
+ {
+ printTableFooter *f;
+
+ f = content->footer;
+ content->footer = f->next;
+ free(f->data);
+ free(f);
+ }
+ }
+ content->footers = NULL;
+ content->footer = NULL;
+}
+
+/*
+ * Use this to print just any table in the supported formats.
+ */
+void
+printTable(const printTableContent *cont, FILE *fout, FILE *flog)
{
- static const char *default_footer[] = {NULL};
FILE *output;
bool is_pager = false;
-
+
if (cancel_pressed)
return;
- if (opt->format == PRINT_NOTHING)
+ if (cont->opt->format == PRINT_NOTHING)
return;
- if (!footers)
- footers = default_footer;
-
if (fout == stdout)
{
- int col_count = 0,
- row_count = 0,
- lines;
- const char *const * ptr;
-
- /* rough estimate of columns and rows */
- if (headers)
- for (ptr = headers; *ptr; ptr++)
- col_count++;
- if (cells)
- for (ptr = cells; *ptr; ptr++)
- row_count++;
- if (col_count > 0)
- row_count /= col_count;
-
- if (opt->expanded)
- lines = (col_count + 1) * row_count;
+ int lines;
+
+ if (cont->opt->expanded)
+ lines = (cont->ncolumns + 1) * cont->nrows;
else
- lines = row_count + 1;
- if (footers && !opt->tuples_only)
- for (ptr = footers; *ptr; ptr++)
+ lines = cont->nrows + 1;
+
+ if (!cont->opt->tuples_only)
+ {
+ printTableFooter *f;
+
+ /*
+ * FIXME -- this is slightly bogus: it counts the number of
+ * footers, not the number of lines in them.
+ */
+ for (f = cont->footers; f; f = f->next)
lines++;
- output = PageOutput(lines, opt->pager);
+ }
+
+ output = PageOutput(lines, cont->opt->pager);
is_pager = (output != fout);
}
else
@@ -2031,54 +2157,44 @@ printTable(const char *title,
/* print the stuff */
if (flog)
- print_aligned_text(title, headers, cells, footers, align,
- opt, is_pager, flog);
+ print_aligned_text(cont, is_pager, flog);
- switch (opt->format)
+ switch (cont->opt->format)
{
case PRINT_UNALIGNED:
- if (opt->expanded)
- print_unaligned_vertical(title, headers, cells, footers, align,
- opt, output);
+ if (cont->opt->expanded)
+ print_unaligned_vertical(cont, output);
else
- print_unaligned_text(title, headers, cells, footers, align,
- opt, output);
+ print_unaligned_text(cont, output);
break;
case PRINT_ALIGNED:
case PRINT_WRAPPED:
- if (opt->expanded)
- print_aligned_vertical(title, headers, cells, footers, align,
- opt, output);
+ if (cont->opt->expanded)
+ print_aligned_vertical(cont, output);
else
- print_aligned_text(title, headers, cells, footers, align,
- opt, is_pager, output);
+ print_aligned_text(cont, is_pager, output);
break;
case PRINT_HTML:
- if (opt->expanded)
- print_html_vertical(title, headers, cells, footers, align,
- opt, output);
+ if (cont->opt->expanded)
+ print_html_vertical(cont, output);
else
- print_html_text(title, headers, cells, footers, align,
- opt, output);
+ print_html_text(cont, output);
break;
case PRINT_LATEX:
- if (opt->expanded)
- print_latex_vertical(title, headers, cells, footers, align,
- opt, output);
+ if (cont->opt->expanded)
+ print_latex_vertical(cont, output);
else
- print_latex_text(title, headers, cells, footers, align,
- opt, output);
+ print_latex_text(cont, output);
break;
case PRINT_TROFF_MS:
- if (opt->expanded)
- print_troff_ms_vertical(title, headers, cells, footers, align,
- opt, output);
+ if (cont->opt->expanded)
+ print_troff_ms_vertical(cont, output);
else
- print_troff_ms_text(title, headers, cells, footers, align,
- opt, output);
+ print_troff_ms_text(cont, output);
break;
default:
- fprintf(stderr, _("invalid output format (internal error): %d"), opt->format);
+ fprintf(stderr, _("invalid output format (internal error): %d"),
+ cont->opt->format);
exit(EXIT_FAILURE);
}
@@ -2086,17 +2202,15 @@ printTable(const char *title,
ClosePager(output);
}
-
+/*
+ * Use this to print query results
+ *
+ * It calls printTable with all the things set straight.
+ */
void
printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog)
{
- int ntuples;
- int nfields;
- int ncells;
- const char **headers;
- const char **cells;
- char **footers;
- char *align;
+ printTableContent cont;
int i,
r,
c;
@@ -2104,71 +2218,12 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
if (cancel_pressed)
return;
- /* extract headers */
- ntuples = PQntuples(result);
- nfields = PQnfields(result);
-
- headers = pg_local_calloc(nfields + 1, sizeof(*headers));
-
- for (i = 0; i < nfields; i++)
- {
- headers[i] = (char *) mbvalidate((unsigned char *) PQfname(result, i),
- opt->topt.encoding);
-#ifdef ENABLE_NLS
- if (opt->trans_headers)
- headers[i] = _(headers[i]);
-#endif
- }
-
- /* set cells */
- ncells = ntuples * nfields;
- cells = pg_local_calloc(ncells + 1, sizeof(*cells));
-
- i = 0;
- for (r = 0; r < ntuples; r++)
- {
- for (c = 0; c < nfields; c++)
- {
- if (PQgetisnull(result, r, c))
- cells[i] = opt->nullPrint ? opt->nullPrint : "";
- else
- {
- cells[i] = (char *)
- mbvalidate((unsigned char *) PQgetvalue(result, r, c),
- opt->topt.encoding);
-#ifdef ENABLE_NLS
- if (opt->trans_columns && opt->trans_columns[c])
- cells[i] = _(cells[i]);
-#endif
- }
- i++;
- }
- }
-
- /* set footers */
+ printTableInit(&cont, &opt->topt, opt->title,
+ PQnfields(result), PQntuples(result));
- if (opt->footers)
- footers = opt->footers;
- else if (!opt->topt.expanded && opt->default_footer)
- {
- unsigned long total_records;
-
- footers = pg_local_calloc(2, sizeof(*footers));
- footers[0] = pg_local_malloc(100);
- total_records = opt->topt.prior_records + ntuples;
- if (total_records == 1)
- snprintf(footers[0], 100, _("(1 row)"));
- else
- snprintf(footers[0], 100, _("(%lu rows)"), total_records);
- }
- else
- footers = NULL;
-
- /* set alignment */
- align = pg_local_calloc(nfields + 1, sizeof(*align));
-
- for (i = 0; i < nfields; i++)
+ for (i = 0; i < cont.ncolumns; i++)
{
+ char align;
Oid ftype = PQftype(result, i);
switch (ftype)
@@ -2183,27 +2238,59 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
case XIDOID:
case CIDOID:
case CASHOID:
- align[i] = 'r';
+ align = 'r';
break;
default:
- align[i] = 'l';
+ align = 'l';
break;
}
+
+ printTableAddHeader(&cont, PQfname(result, i),
+ opt->trans_headers, align);
}
- /* call table printer */
- printTable(opt->title, headers, cells,
- (const char *const *) footers,
- align, &opt->topt, fout, flog);
+ /* set cells */
+ for (r = 0; r < cont.nrows; r++)
+ {
+ for (c = 0; c < cont.ncolumns; c++)
+ {
+ char *cell;
+ bool translate;
+
+ if (PQgetisnull(result, r, c))
+ cell = opt->nullPrint ? opt->nullPrint : "";
+ else
+ cell = PQgetvalue(result, r, c);
+
+ translate = (opt->trans_columns && opt->trans_columns[c]);
+ printTableAddCell(&cont, cell, translate);
+ }
+ }
- free(headers);
- free(cells);
- if (footers && !opt->footers)
+ /* set footers */
+ if (opt->footers)
+ {
+ char **footer;
+
+ for (footer = opt->footers; *footer; footer++)
+ printTableAddFooter(&cont, *footer);
+ }
+ else if (!opt->topt.expanded && opt->default_footer)
{
- free(footers[0]);
- free(footers);
+ unsigned long total_records;
+ char default_footer[100];
+
+ total_records = opt->topt.prior_records + cont.nrows;
+ if (total_records == 1)
+ snprintf(default_footer, 100, _("(1 row)"));
+ else
+ snprintf(default_footer, 100, _("(%lu rows)"), total_records);
+
+ printTableAddFooter(&cont, default_footer);
}
- free(align);
+
+ printTable(&cont, fout, flog);
+ printTableCleanup(&cont);
}
@@ -2215,17 +2302,17 @@ setDecimalLocale(void)
extlconv = localeconv();
if (*extlconv->decimal_point)
- decimal_point = strdup(extlconv->decimal_point);
+ decimal_point = pg_strdup(extlconv->decimal_point);
else
decimal_point = "."; /* SQL output standard */
if (*extlconv->grouping && atoi(extlconv->grouping) > 0)
- grouping = strdup(extlconv->grouping);
+ grouping = pg_strdup(extlconv->grouping);
else
grouping = "3"; /* most common */
/* similar code exists in formatting.c */
if (*extlconv->thousands_sep)
- thousands_sep = strdup(extlconv->thousands_sep);
+ thousands_sep = pg_strdup(extlconv->thousands_sep);
/* Make sure thousands separator doesn't match decimal point symbol. */
else if (strcmp(decimal_point, ",") != 0)
thousands_sep = ",";