*
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.126 2006/08/29 15:19:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.127 2006/08/29 22:25:07 tgl Exp $
*/
#include "postgres_fe.h"
#include "common.h"
#include "command.h"
#include "copy.h"
#include "mb/pg_wchar.h"
+#include "mbprint.h"
/* Workarounds for Windows */
#endif
+static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
static bool command_no_begin(const char *query);
+static bool is_select_command(const char *query);
/*
* "Safe" wrapper around strdup()
* AcceptResult
*
* Checks whether a result is valid, giving an error message if necessary;
- * resets cancelConn as needed, and ensures that the connection to the backend
- * is still up.
+ * and ensures that the connection to the backend is still up.
*
* Returns true for valid result, false for error state.
*/
static bool
-AcceptResult(const PGresult *result, const char *query)
+AcceptResult(const PGresult *result)
{
bool OK = true;
- ResetCancelConn();
-
if (!result)
OK = false;
else
res = PQexec(pset.db, query);
- if (!AcceptResult(res, query) && res)
+ ResetCancelConn();
+
+ if (!AcceptResult(res))
{
PQclear(res);
res = NULL;
/* write output to \g argument, if any */
if (pset.gfname)
{
+ /* keep this code in sync with ExecQueryUsingCursor */
FILE *queryFout_copy = pset.queryFout;
bool queryFoutPipe_copy = pset.queryFoutPipe;
SendQuery(const char *query)
{
PGresult *results;
- TimevalStruct before,
- after;
+ PGTransactionStatusType transaction_status;
+ double elapsed_msec = 0;
bool OK,
on_error_rollback_savepoint = false;
- PGTransactionStatusType transaction_status;
static bool on_error_rollback_warning = false;
if (!pset.db)
}
}
- if (pset.timing)
- GETTIMEOFDAY(&before);
+ if (pset.fetch_count <= 0 || !is_select_command(query))
+ {
+ /* Default fetch-it-all-and-print mode */
+ TimevalStruct before,
+ after;
- results = PQexec(pset.db, query);
+ if (pset.timing)
+ GETTIMEOFDAY(&before);
- /* these operations are included in the timing result: */
- OK = (AcceptResult(results, query) && ProcessCopyResult(results));
+ results = PQexec(pset.db, query);
- if (pset.timing)
- GETTIMEOFDAY(&after);
+ /* these operations are included in the timing result: */
+ ResetCancelConn();
+ OK = (AcceptResult(results) && ProcessCopyResult(results));
- /* but printing results isn't: */
- if (OK)
- OK = PrintQueryResults(results);
+ if (pset.timing)
+ {
+ GETTIMEOFDAY(&after);
+ elapsed_msec = DIFF_MSEC(&after, &before);
+ }
+
+ /* but printing results isn't: */
+ if (OK)
+ OK = PrintQueryResults(results);
+ }
+ else
+ {
+ /* Fetch-in-segments mode */
+ OK = ExecQueryUsingCursor(query, &elapsed_msec);
+ ResetCancelConn();
+ results = NULL; /* PQclear(NULL) does nothing */
+ }
/* If we made a temporary savepoint, possibly release/rollback */
if (on_error_rollback_savepoint)
* the user did RELEASE or ROLLBACK, our savepoint is gone. If
* they issued a SAVEPOINT, releasing ours would remove theirs.
*/
- if (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
- strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
- strcmp(PQcmdStatus(results), "ROLLBACK") == 0)
+ if (results &&
+ (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
+ strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
+ strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
svptres = NULL;
else
svptres = PQexec(pset.db, "RELEASE pg_psql_temporary_savepoint");
/* Possible microtiming output */
if (OK && pset.timing)
- printf(_("Time: %.3f ms\n"), DIFF_MSEC(&after, &before));
+ printf(_("Time: %.3f ms\n"), elapsed_msec);
/* check for events that may occur during query execution */
}
+/*
+ * ExecQueryUsingCursor: run a SELECT-like query using a cursor
+ *
+ * This feature allows result sets larger than RAM to be dealt with.
+ *
+ * Returns true if the query executed successfully, false otherwise.
+ *
+ * If pset.timing is on, total query time (exclusive of result-printing) is
+ * stored into *elapsed_msec.
+ */
+static bool
+ExecQueryUsingCursor(const char *query, double *elapsed_msec)
+{
+ bool OK = true;
+ PGresult *results;
+ PQExpBufferData buf;
+ printQueryOpt my_popt = pset.popt;
+ FILE *queryFout_copy = pset.queryFout;
+ bool queryFoutPipe_copy = pset.queryFoutPipe;
+ bool started_txn = false;
+ bool did_pager = false;
+ int ntuples;
+ char fetch_cmd[64];
+ TimevalStruct before,
+ after;
+
+ *elapsed_msec = 0;
+
+ /* initialize print options for partial table output */
+ my_popt.topt.start_table = true;
+ my_popt.topt.stop_table = false;
+ my_popt.topt.prior_records = 0;
+
+ if (pset.timing)
+ GETTIMEOFDAY(&before);
+
+ /* if we're not in a transaction, start one */
+ if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
+ {
+ results = PQexec(pset.db, "BEGIN");
+ OK = AcceptResult(results) &&
+ (PQresultStatus(results) == PGRES_COMMAND_OK);
+ PQclear(results);
+ if (!OK)
+ return false;
+ started_txn = true;
+ }
+
+ /* Send DECLARE CURSOR */
+ initPQExpBuffer(&buf);
+ appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s",
+ query);
+
+ results = PQexec(pset.db, buf.data);
+ OK = AcceptResult(results) &&
+ (PQresultStatus(results) == PGRES_COMMAND_OK);
+ PQclear(results);
+ termPQExpBuffer(&buf);
+ if (!OK)
+ goto cleanup;
+
+ if (pset.timing)
+ {
+ GETTIMEOFDAY(&after);
+ *elapsed_msec += DIFF_MSEC(&after, &before);
+ }
+
+ snprintf(fetch_cmd, sizeof(fetch_cmd),
+ "FETCH FORWARD %d FROM _psql_cursor",
+ pset.fetch_count);
+
+ /* prepare to write output to \g argument, if any */
+ if (pset.gfname)
+ {
+ /* keep this code in sync with PrintQueryTuples */
+ pset.queryFout = stdout; /* so it doesn't get closed */
+
+ /* open file/pipe */
+ if (!setQFout(pset.gfname))
+ {
+ pset.queryFout = queryFout_copy;
+ pset.queryFoutPipe = queryFoutPipe_copy;
+ OK = false;
+ goto cleanup;
+ }
+ }
+
+ for (;;)
+ {
+ if (pset.timing)
+ GETTIMEOFDAY(&before);
+
+ /* get FETCH_COUNT tuples at a time */
+ results = PQexec(pset.db, fetch_cmd);
+ OK = AcceptResult(results) &&
+ (PQresultStatus(results) == PGRES_TUPLES_OK);
+
+ if (pset.timing)
+ {
+ GETTIMEOFDAY(&after);
+ *elapsed_msec += DIFF_MSEC(&after, &before);
+ }
+
+ if (!OK)
+ {
+ PQclear(results);
+ break;
+ }
+
+ ntuples = PQntuples(results);
+
+ if (ntuples < pset.fetch_count)
+ {
+ /* this is the last result set, so allow footer decoration */
+ my_popt.topt.stop_table = true;
+ }
+ else if (pset.queryFout == stdout && !did_pager)
+ {
+ /*
+ * If query requires multiple result sets, hack to ensure that
+ * only one pager instance is used for the whole mess
+ */
+ pset.queryFout = PageOutput(100000, my_popt.topt.pager);
+ did_pager = true;
+ }
+
+ printQuery(results, &my_popt, pset.queryFout, pset.logfile);
+
+ /* after the first result set, disallow header decoration */
+ my_popt.topt.start_table = false;
+ my_popt.topt.prior_records += ntuples;
+
+ PQclear(results);
+
+ if (ntuples < pset.fetch_count || cancel_pressed)
+ break;
+ }
+
+ /* close \g argument file/pipe, restore old setting */
+ if (pset.gfname)
+ {
+ /* keep this code in sync with PrintQueryTuples */
+ setQFout(NULL);
+
+ pset.queryFout = queryFout_copy;
+ pset.queryFoutPipe = queryFoutPipe_copy;
+
+ free(pset.gfname);
+ pset.gfname = NULL;
+ }
+ else if (did_pager)
+ {
+ ClosePager(pset.queryFout);
+ pset.queryFout = queryFout_copy;
+ pset.queryFoutPipe = queryFoutPipe_copy;
+ }
+
+cleanup:
+ if (pset.timing)
+ GETTIMEOFDAY(&before);
+
+ /*
+ * We try to close the cursor on either success or failure, but on
+ * failure ignore the result (it's probably just a bleat about
+ * being in an aborted transaction)
+ */
+ results = PQexec(pset.db, "CLOSE _psql_cursor");
+ if (OK)
+ {
+ OK = AcceptResult(results) &&
+ (PQresultStatus(results) == PGRES_COMMAND_OK);
+ }
+ PQclear(results);
+
+ if (started_txn)
+ {
+ results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK");
+ OK &= AcceptResult(results) &&
+ (PQresultStatus(results) == PGRES_COMMAND_OK);
+ PQclear(results);
+ }
+
+ if (pset.timing)
+ {
+ GETTIMEOFDAY(&after);
+ *elapsed_msec += DIFF_MSEC(&after, &before);
+ }
+
+ return OK;
+}
+
+
/*
* Advance the given char pointer over white space and SQL comments.
*/
}
+/*
+ * Check whether the specified command is a SELECT (or VALUES).
+ */
+static bool
+is_select_command(const char *query)
+{
+ int wordlen;
+
+ /*
+ * First advance over any whitespace, comments and left parentheses.
+ */
+ for (;;)
+ {
+ query = skip_white_space(query);
+ if (query[0] == '(')
+ query++;
+ else
+ break;
+ }
+
+ /*
+ * Check word length (since "selectx" is not "select").
+ */
+ wordlen = 0;
+ while (isalpha((unsigned char) query[wordlen]))
+ wordlen += PQmblen(&query[wordlen], pset.encoding);
+
+ if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0)
+ return true;
+
+ if (wordlen == 6 && pg_strncasecmp(query, "values", 6) == 0)
+ return true;
+
+ return false;
+}
+
+
/*
* Test if the current user is a database superuser.
*
*
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.88 2006/07/14 14:52:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.89 2006/08/29 22:25:07 tgl Exp $
*
* Note: we include postgres.h not postgres_fe.h so that we can include
* catalog/pg_type.h, and thereby have access to INT4OID and similar macros.
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 char *opt_fieldsep,
- const char *opt_recordsep, bool opt_tuples_only,
- bool opt_numeric_locale, FILE *fout)
+ const char *opt_align, const printTableOpt *opt,
+ 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;
unsigned int i;
const char *const * ptr;
if (!opt_recordsep)
opt_recordsep = "";
- /* print title */
- if (!opt_tuples_only && title)
- fprintf(fout, "%s%s", title, opt_recordsep);
-
- /* print headers and count columns */
+ /* count columns */
for (ptr = headers; *ptr; ptr++)
- {
col_count++;
+
+ if (opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && title)
+ fprintf(fout, "%s%s", title, opt_recordsep);
+
+ /* print headers */
if (!opt_tuples_only)
{
- if (col_count > 1)
- fputs(opt_fieldsep, fout);
- fputs(*ptr, fout);
+ for (ptr = headers; *ptr; ptr++)
+ {
+ if (ptr != headers)
+ fputs(opt_fieldsep, fout);
+ fputs(*ptr, fout);
+ }
+ need_recordsep = true;
}
}
- if (!opt_tuples_only)
+ else /* assume continuing printout */
need_recordsep = true;
/* print cells */
- i = 0;
- for (ptr = cells; *ptr; ptr++)
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (need_recordsep)
{
fputs(opt_fieldsep, fout);
else
need_recordsep = true;
- i++;
}
/* print footers */
-
- if (!opt_tuples_only && footers && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
- {
- if (need_recordsep)
+ if (opt->stop_table)
+ {
+ if (!opt_tuples_only && footers && !cancel_pressed)
+ for (ptr = footers; *ptr; ptr++)
{
- fputs(opt_recordsep, fout);
- need_recordsep = false;
+ if (need_recordsep)
+ {
+ fputs(opt_recordsep, fout);
+ need_recordsep = false;
+ }
+ fputs(*ptr, fout);
+ need_recordsep = true;
}
- fputs(*ptr, fout);
- need_recordsep = true;
- }
- /* the last record needs to be concluded with a newline */
- if (need_recordsep)
- fputc('\n', fout);
+ /* the last record needs to be concluded with a newline */
+ if (need_recordsep)
+ fputc('\n', fout);
+ }
}
-
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 char *opt_fieldsep, const char *opt_recordsep,
- bool opt_tuples_only, bool opt_numeric_locale, FILE *fout)
+ const printTableOpt *opt, 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;
unsigned int i;
const char *const * ptr;
+ bool need_recordsep = false;
if (cancel_pressed)
return;
if (!opt_recordsep)
opt_recordsep = "";
- /* print title */
- if (!opt_tuples_only && title)
- fputs(title, fout);
-
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
+ if (opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs(title, fout);
+ need_recordsep = true;
+ }
+ }
+ else /* assume continuing printout */
+ need_recordsep = true;
+
/* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
- if (i != 0 || (!opt_tuples_only && title))
+ if (need_recordsep)
{
+ /* record separator is 2 occurrences of recordsep in this mode */
+ fputs(opt_recordsep, fout);
fputs(opt_recordsep, fout);
- if (i % col_count == 0)
- fputs(opt_recordsep, fout); /* another one */
+ need_recordsep = false;
if (cancel_pressed)
break;
}
}
else
fputs(*ptr, fout);
+
+ if ((i + 1) % col_count)
+ fputs(opt_recordsep, fout);
+ else
+ need_recordsep = true;
}
- /* print footers */
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (opt->stop_table)
{
- fputs(opt_recordsep, fout);
- for (ptr = footers; *ptr; ptr++)
+ /* print footers */
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
fputs(opt_recordsep, fout);
- fputs(*ptr, fout);
+ for (ptr = footers; *ptr; ptr++)
+ {
+ fputs(opt_recordsep, fout);
+ fputs(*ptr, fout);
+ }
}
- }
- fputc('\n', fout);
+ fputc('\n', fout);
+ }
}
-
/********************/
/* Aligned text */
/********************/
}
-
static void
print_aligned_text(const char *title, const char *const * headers,
const char *const * cells, const char *const * footers,
- const char *opt_align, bool opt_tuples_only, bool opt_numeric_locale,
- unsigned short int opt_border, int encoding,
+ const char *opt_align, const printTableOpt *opt,
FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
+ int encoding = opt->encoding;
unsigned int col_count = 0;
unsigned int cell_count = 0;
unsigned int i;
if (cancel_pressed)
return;
+ if (opt_border > 2)
+ opt_border = 2;
+
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
format_space = pg_local_calloc(col_count, sizeof(*format_space));
format_buf = pg_local_calloc(col_count, sizeof(*format_buf));
complete = pg_local_calloc(col_count, sizeof(*complete));
-
}
else
{
}
else
lineptr_list = NULL;
-
- /* print title */
- if (title && !opt_tuples_only)
- {
- /* Get width & height */
- int height;
- pg_wcssize((unsigned char *)title, strlen(title), encoding, &tmp, &height, NULL);
- if (tmp >= total_w)
- fprintf(fout, "%s\n", title);
- else
- fprintf(fout, "%-*s%s\n", (total_w - tmp) / 2, "", title);
- }
- /* print headers */
- if (!opt_tuples_only)
+ if (opt->start_table)
{
- int cols_todo;
- int line_count;
-
- if (opt_border == 2)
- _print_horizontal_line(col_count, widths, opt_border, fout);
+ /* print title */
+ if (title && !opt_tuples_only)
+ {
+ /* Get width & height */
+ int height;
+ pg_wcssize((unsigned char *)title, strlen(title), encoding, &tmp, &height, NULL);
+ if (tmp >= total_w)
+ fprintf(fout, "%s\n", title);
+ else
+ fprintf(fout, "%-*s%s\n", (total_w - tmp) / 2, "", title);
+ }
- for (i = 0; i < col_count; i++)
- pg_wcsformat((unsigned char *)headers[i], strlen(headers[i]), encoding, col_lineptrs[i], heights[i]);
-
- cols_todo = col_count;
- line_count = 0;
- memset(complete, 0, col_count*sizeof(int));
- while (cols_todo)
+ /* print headers */
+ if (!opt_tuples_only)
{
+ int cols_todo;
+ int line_count;
+
if (opt_border == 2)
- fprintf(fout, "|%c", line_count ? '+' : ' ');
- else if (opt_border == 1)
- fputc(line_count ? '+' : ' ', fout);
+ _print_horizontal_line(col_count, widths, opt_border, fout);
for (i = 0; i < col_count; i++)
+ pg_wcsformat((unsigned char *)headers[i], strlen(headers[i]), encoding, col_lineptrs[i], heights[i]);
+
+ cols_todo = col_count;
+ line_count = 0;
+ memset(complete, 0, col_count*sizeof(int));
+ while (cols_todo)
{
- unsigned int nbspace;
+ if (opt_border == 2)
+ fprintf(fout, "|%c", line_count ? '+' : ' ');
+ else if (opt_border == 1)
+ fputc(line_count ? '+' : ' ', fout);
- struct lineptr *this_line = col_lineptrs[i] + line_count;
- if (!complete[i])
+ for (i = 0; i < col_count; i++)
{
- nbspace = widths[i] - this_line->width;
-
- /* centered */
- fprintf(fout, "%-*s%s%-*s",
- nbspace / 2, "", this_line->ptr, (nbspace + 1) / 2, "");
+ unsigned int nbspace;
- if (line_count == (heights[i]-1) || !(this_line+1)->ptr)
+ struct lineptr *this_line = col_lineptrs[i] + line_count;
+ if (!complete[i])
{
- cols_todo--;
- complete[i] = 1;
+ nbspace = widths[i] - this_line->width;
+
+ /* centered */
+ fprintf(fout, "%-*s%s%-*s",
+ nbspace / 2, "", this_line->ptr, (nbspace + 1) / 2, "");
+
+ if (line_count == (heights[i]-1) || !(this_line+1)->ptr)
+ {
+ cols_todo--;
+ complete[i] = 1;
+ }
}
- }
- else
- fprintf(fout, "%*s", widths[i], "");
- if (i < col_count - 1)
- {
- if (opt_border == 0)
- fputc(line_count ? '+' : ' ', fout);
else
- fprintf(fout, " |%c", line_count ? '+' : ' ');
+ fprintf(fout, "%*s", widths[i], "");
+ if (i < col_count - 1)
+ {
+ if (opt_border == 0)
+ fputc(line_count ? '+' : ' ', fout);
+ else
+ fprintf(fout, " |%c", line_count ? '+' : ' ');
+ }
}
+ line_count++;
+
+ if (opt_border == 2)
+ fputs(" |", fout);
+ else if (opt_border == 1)
+ fputc(' ', fout);;
+ fputc('\n', fout);
}
- line_count++;
- if (opt_border == 2)
- fputs(" |", fout);
- else if (opt_border == 1)
- fputc(' ', fout);;
- fputc('\n', fout);
+ _print_horizontal_line(col_count, widths, opt_border, fout);
}
-
- _print_horizontal_line(col_count, widths, opt_border, fout);
}
/* print cells */
}
}
- if (opt_border == 2 && !cancel_pressed)
- _print_horizontal_line(col_count, widths, opt_border, fout);
+ if (opt->stop_table)
+ {
+ if (opt_border == 2 && !cancel_pressed)
+ _print_horizontal_line(col_count, widths, opt_border, fout);
- /* print footers */
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
+ /* print footers */
+ if (footers && !opt_tuples_only && !cancel_pressed)
+ for (ptr = footers; *ptr; ptr++)
+ fprintf(fout, "%s\n", *ptr);
+ /*
+ * for some reason MinGW (and MSVC) outputs an extra newline,
+ * so this suppresses it
+ */
#ifndef WIN32
-
- /*
- * for some reason MinGW (and MSVC) outputs an extra newline, so this supresses it
- */
- fputc('\n', fout);
+ fputc('\n', fout);
#endif
+ }
/* clean up */
free(widths);
}
-
static void
print_aligned_vertical(const char *title, const char *const * headers,
const char *const * cells, const char *const * footers,
- const char *opt_align, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
- int encoding, FILE *fout)
+ const char *opt_align, const printTableOpt *opt,
+ FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
+ int encoding = opt->encoding;
unsigned int col_count = 0;
- unsigned int record = 1;
+ unsigned long record = opt->prior_records + 1;
const char *const * ptr;
unsigned int i,
hwidth = 0,
if (cancel_pressed)
return;
+
+ if (opt_border > 2)
+ opt_border = 2;
- if (cells[0] == NULL)
+ if (cells[0] == NULL && opt->start_table && opt->stop_table)
{
fprintf(fout, _("(No rows)\n"));
return;
}
- /* count headers and find longest one */
+ /* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
dlineptr->ptr = pg_local_malloc(dformatsize);
hlineptr->ptr = pg_local_malloc(hformatsize);
-
- /* print title */
- if (!opt_tuples_only && title)
- fprintf(fout, "%s\n", title);
/* make horizontal border */
divider = pg_local_malloc(hwidth + dwidth + 10);
if (opt_border == 2)
strcat(divider, "-+");
+ if (opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && title)
+ fprintf(fout, "%s\n", title);
+ }
+
/* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
break;
if (!opt_tuples_only)
{
- char *record_str = pg_local_malloc(32);
+ char record_str[64];
size_t record_str_len;
if (opt_border == 0)
- snprintf(record_str, 32, "* Record %d", record++);
+ snprintf(record_str, 64, "* Record %lu", record++);
else
- snprintf(record_str, 32, "[ RECORD %d ]", record++);
+ snprintf(record_str, 64, "[ RECORD %lu ]", record++);
record_str_len = strlen(record_str);
if (record_str_len + opt_border > strlen(divider))
fprintf(fout, "%s\n", div_copy);
free(div_copy);
}
- free(record_str);
}
- else if (i != 0 || opt_border == 2)
+ else if (i != 0 || !opt->start_table || opt_border == 2)
fprintf(fout, "%s\n", divider);
}
}
}
- if (opt_border == 2 && !cancel_pressed)
- fprintf(fout, "%s\n", divider);
+ if (opt->stop_table)
+ {
+ if (opt_border == 2 && !cancel_pressed)
+ fprintf(fout, "%s\n", divider);
- /* print footers */
+ /* print footers */
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ {
+ if (opt_border < 2)
+ fputc('\n', fout);
+ for (ptr = footers; *ptr; ptr++)
+ fprintf(fout, "%s\n", *ptr);
+ }
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
- {
- if (opt_border < 2)
- fputc('\n', fout);
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
+ fputc('\n', fout);
}
- fputc('\n', fout);
free(divider);
free(hlineptr->ptr);
free(dlineptr->ptr);
}
-
-
-
/**********************/
/* HTML printing ******/
/**********************/
}
-
static void
print_html_text(const char *title, const char *const * headers,
const char *const * cells, const char *const * footers,
- const char *opt_align, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
- const char *opt_table_attr, FILE *fout)
+ const char *opt_align, const printTableOpt *opt,
+ FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
+ const char *opt_table_attr = opt->tableAttr;
unsigned int col_count = 0;
unsigned int i;
const char *const * ptr;
if (cancel_pressed)
return;
- fprintf(fout, "<table border=\"%d\"", opt_border);
- if (opt_table_attr)
- fprintf(fout, " %s", opt_table_attr);
- fputs(">\n", fout);
+ /* count columns */
+ for (ptr = headers; *ptr; ptr++)
+ col_count++;
- /* print title */
- if (!opt_tuples_only && title)
+ if (opt->start_table)
{
- fputs(" <caption>", fout);
- html_escaped_print(title, fout);
- fputs("</caption>\n", fout);
- }
+ fprintf(fout, "<table border=\"%d\"", opt_border);
+ if (opt_table_attr)
+ fprintf(fout, " %s", opt_table_attr);
+ fputs(">\n", fout);
- /* print headers and count columns */
- if (!opt_tuples_only)
- fputs(" <tr>\n", fout);
- for (i = 0, ptr = headers; *ptr; i++, ptr++)
- {
- col_count++;
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs(" <caption>", fout);
+ html_escaped_print(title, fout);
+ fputs("</caption>\n", fout);
+ }
+
+ /* print headers */
if (!opt_tuples_only)
{
- fputs(" <th align=\"center\">", fout);
- html_escaped_print(*ptr, fout);
- fputs("</th>\n", fout);
+ fputs(" <tr>\n", fout);
+ for (ptr = headers; *ptr; ptr++)
+ {
+ fputs(" <th align=\"center\">", fout);
+ html_escaped_print(*ptr, fout);
+ fputs("</th>\n", fout);
+ }
+ fputs(" </tr>\n", fout);
}
}
- if (!opt_tuples_only)
- fputs(" </tr>\n", fout);
/* print cells */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
fputs(" </tr>\n", fout);
}
- fputs("</table>\n", fout);
-
- /* print footers */
-
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (opt->stop_table)
{
- fputs("<p>", fout);
- for (ptr = footers; *ptr; ptr++)
+ fputs("</table>\n", fout);
+
+ /* print footers */
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
- html_escaped_print(*ptr, fout);
- fputs("<br />\n", fout);
+ fputs("<p>", fout);
+ for (ptr = footers; *ptr; ptr++)
+ {
+ html_escaped_print(*ptr, fout);
+ fputs("<br />\n", fout);
+ }
+ fputs("</p>", fout);
}
- fputs("</p>", fout);
+
+ fputc('\n', fout);
}
- fputc('\n', fout);
}
-
static void
print_html_vertical(const char *title, const char *const * headers,
const char *const * cells, const char *const * footers,
- const char *opt_align, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
- const char *opt_table_attr, FILE *fout)
+ const char *opt_align, const printTableOpt *opt,
+ FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
+ const char *opt_table_attr = opt->tableAttr;
unsigned int col_count = 0;
+ unsigned long record = opt->prior_records + 1;
unsigned int i;
- unsigned int record = 1;
const char *const * ptr;
if (cancel_pressed)
return;
- fprintf(fout, "<table border=\"%d\"", opt_border);
- if (opt_table_attr)
- fprintf(fout, " %s", opt_table_attr);
- fputs(">\n", fout);
-
- /* print title */
- if (!opt_tuples_only && title)
- {
- fputs(" <caption>", fout);
- html_escaped_print(title, fout);
- fputs("</caption>\n", fout);
- }
-
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
+ if (opt->start_table)
+ {
+ fprintf(fout, "<table border=\"%d\"", opt_border);
+ if (opt_table_attr)
+ fprintf(fout, " %s", opt_table_attr);
+ fputs(">\n", fout);
+
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs(" <caption>", fout);
+ html_escaped_print(title, fout);
+ fputs("</caption>\n", fout);
+ }
+ }
+
/* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (cancel_pressed)
break;
if (!opt_tuples_only)
- fprintf(fout, "\n <tr><td colspan=\"2\" align=\"center\">Record %d</td></tr>\n", record++);
+ fprintf(fout,
+ "\n <tr><td colspan=\"2\" align=\"center\">Record %lu</td></tr>\n",
+ record++);
else
fputs("\n <tr><td colspan=\"2\"> </td></tr>\n", fout);
}
fputs("</td>\n </tr>\n", fout);
}
- fputs("</table>\n", fout);
-
- /* print footers */
- if (!opt_tuples_only && footers && *footers && !cancel_pressed)
+ if (opt->stop_table)
{
- fputs("<p>", fout);
- for (ptr = footers; *ptr; ptr++)
+ fputs("</table>\n", fout);
+
+ /* print footers */
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
- html_escaped_print(*ptr, fout);
- fputs("<br />\n", fout);
+ fputs("<p>", fout);
+ for (ptr = footers; *ptr; ptr++)
+ {
+ html_escaped_print(*ptr, fout);
+ fputs("<br />\n", fout);
+ }
+ fputs("</p>", fout);
}
- fputs("</p>", fout);
+
+ fputc('\n', fout);
}
- fputc('\n', fout);
}
-
/*************************/
-/* LaTeX */
+/* LaTeX */
/*************************/
}
-
static void
print_latex_text(const char *title, const char *const * headers,
const char *const * cells, const char *const * footers,
- const char *opt_align, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
+ const char *opt_align, const printTableOpt *opt,
FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
unsigned int col_count = 0;
unsigned int i;
const char *const * ptr;
if (cancel_pressed)
return;
- /* print title */
- if (!opt_tuples_only && title)
- {
- fputs("\\begin{center}\n", fout);
- latex_escaped_print(title, fout);
- fputs("\n\\end{center}\n\n", fout);
- }
+ if (opt_border > 2)
+ opt_border = 2;
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
- /* begin environment and set alignments and borders */
- fputs("\\begin{tabular}{", fout);
-
- if (opt_border == 2)
- fputs("| ", fout);
- for (i = 0; i < col_count; i++)
+ if (opt->start_table)
{
- fputc(*(opt_align + i), fout);
- if (opt_border != 0 && i < col_count - 1)
- fputs(" | ", fout);
- }
- if (opt_border == 2)
- fputs(" |", fout);
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs("\\begin{center}\n", fout);
+ latex_escaped_print(title, fout);
+ fputs("\n\\end{center}\n\n", fout);
+ }
- fputs("}\n", fout);
+ /* begin environment and set alignments and borders */
+ fputs("\\begin{tabular}{", fout);
- if (!opt_tuples_only && opt_border == 2)
- fputs("\\hline\n", fout);
+ if (opt_border == 2)
+ fputs("| ", fout);
+ for (i = 0; i < col_count; i++)
+ {
+ fputc(*(opt_align + i), fout);
+ if (opt_border != 0 && i < col_count - 1)
+ fputs(" | ", fout);
+ }
+ if (opt_border == 2)
+ fputs(" |", fout);
- /* print headers and count columns */
- for (i = 0, ptr = headers; i < col_count; i++, ptr++)
- {
+ fputs("}\n", fout);
+
+ if (!opt_tuples_only && opt_border == 2)
+ fputs("\\hline\n", fout);
+
+ /* print headers */
if (!opt_tuples_only)
{
- if (i != 0)
- fputs(" & ", fout);
- fputs("\\textit{", fout);
- latex_escaped_print(*ptr, fout);
- fputc('}', fout);
+ for (i = 0, ptr = headers; i < col_count; i++, ptr++)
+ {
+ if (i != 0)
+ fputs(" & ", fout);
+ fputs("\\textit{", fout);
+ latex_escaped_print(*ptr, fout);
+ fputc('}', fout);
+ }
+ fputs(" \\\\\n", fout);
+ fputs("\\hline\n", fout);
}
}
- if (!opt_tuples_only)
- {
- fputs(" \\\\\n", fout);
- fputs("\\hline\n", fout);
- }
-
/* print cells */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
fputs(" & ", fout);
}
- if (opt_border == 2)
- fputs("\\hline\n", fout);
-
- fputs("\\end{tabular}\n\n\\noindent ", fout);
-
+ if (opt->stop_table)
+ {
+ if (opt_border == 2)
+ fputs("\\hline\n", fout);
- /* print footers */
+ fputs("\\end{tabular}\n\n\\noindent ", fout);
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
+ /* print footers */
+ if (footers && !opt_tuples_only && !cancel_pressed)
{
- latex_escaped_print(*ptr, fout);
- fputs(" \\\\\n", fout);
+ for (ptr = footers; *ptr; ptr++)
+ {
+ latex_escaped_print(*ptr, fout);
+ fputs(" \\\\\n", fout);
+ }
}
- fputc('\n', fout);
+ fputc('\n', fout);
+ }
}
-
static void
print_latex_vertical(const char *title, const char *const * headers,
const char *const * cells, const char *const * footers,
- const char *opt_align, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
+ const char *opt_align, const printTableOpt *opt,
FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
unsigned int col_count = 0;
+ unsigned long record = opt->prior_records + 1;
unsigned int i;
const char *const * ptr;
- unsigned int record = 1;
(void) opt_align; /* currently unused parameter */
if (cancel_pressed)
return;
- /* print title */
- if (!opt_tuples_only && title)
- {
- fputs("\\begin{center}\n", fout);
- latex_escaped_print(title, fout);
- fputs("\n\\end{center}\n\n", fout);
- }
-
- /* begin environment and set alignments and borders */
- fputs("\\begin{tabular}{", fout);
- if (opt_border == 0)
- fputs("cl", fout);
- else if (opt_border == 1)
- fputs("c|l", fout);
- else if (opt_border == 2)
- fputs("|c|l|", fout);
- fputs("}\n", fout);
-
+ if (opt_border > 2)
+ opt_border = 2;
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
+ if (opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs("\\begin{center}\n", fout);
+ latex_escaped_print(title, fout);
+ fputs("\n\\end{center}\n\n", fout);
+ }
+
+ /* begin environment and set alignments and borders */
+ fputs("\\begin{tabular}{", fout);
+ if (opt_border == 0)
+ fputs("cl", fout);
+ else if (opt_border == 1)
+ fputs("c|l", fout);
+ else if (opt_border == 2)
+ fputs("|c|l|", fout);
+ fputs("}\n", fout);
+ }
/* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
if (opt_border == 2)
{
fputs("\\hline\n", fout);
- fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %d}} \\\\\n", record++);
+ fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++);
}
else
- fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %d}} \\\\\n", record++);
+ fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++);
}
if (opt_border >= 1)
fputs("\\hline\n", fout);
fputs(" \\\\\n", fout);
}
- if (opt_border == 2)
- fputs("\\hline\n", fout);
-
- fputs("\\end{tabular}\n\n\\noindent ", fout);
-
+ if (opt->stop_table)
+ {
+ if (opt_border == 2)
+ fputs("\\hline\n", fout);
- /* print footers */
+ fputs("\\end{tabular}\n\n\\noindent ", fout);
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
+ /* print footers */
+ if (footers && !opt_tuples_only && !cancel_pressed)
{
- if (opt_numeric_locale)
+ for (ptr = footers; *ptr; ptr++)
{
- char *my_cell = format_numeric_locale(*ptr);
+ if (opt_numeric_locale)
+ {
+ char *my_cell = format_numeric_locale(*ptr);
- latex_escaped_print(my_cell, fout);
- free(my_cell);
+ latex_escaped_print(my_cell, fout);
+ free(my_cell);
+ }
+ else
+ latex_escaped_print(*ptr, fout);
+ fputs(" \\\\\n", fout);
}
- else
- latex_escaped_print(*ptr, fout);
- fputs(" \\\\\n", fout);
}
- fputc('\n', fout);
+ fputc('\n', fout);
+ }
}
-
/*************************/
/* Troff -ms */
/*************************/
}
-
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, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
+ const char *opt_align, const printTableOpt *opt,
FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
unsigned int col_count = 0;
unsigned int i;
const char *const * ptr;
if (cancel_pressed)
return;
- /* print title */
- if (!opt_tuples_only && title)
- {
- fputs(".LP\n.DS C\n", fout);
- troff_ms_escaped_print(title, fout);
- fputs("\n.DE\n", fout);
- }
+ if (opt_border > 2)
+ opt_border = 2;
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
- /* begin environment and set alignments and borders */
- fputs(".LP\n.TS\n", fout);
- if (opt_border == 2)
- fputs("center box;\n", fout);
- else
- fputs("center;\n", fout);
-
- for (i = 0; i < col_count; i++)
+ if (opt->start_table)
{
- fputc(*(opt_align + i), fout);
- if (opt_border > 0 && i < col_count - 1)
- fputs(" | ", fout);
- }
- fputs(".\n", fout);
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs(".LP\n.DS C\n", fout);
+ troff_ms_escaped_print(title, fout);
+ fputs("\n.DE\n", fout);
+ }
- /* print headers and count columns */
- for (i = 0, ptr = headers; i < col_count; i++, ptr++)
- {
+ /* begin environment and set alignments and borders */
+ fputs(".LP\n.TS\n", fout);
+ if (opt_border == 2)
+ fputs("center box;\n", fout);
+ else
+ fputs("center;\n", fout);
+
+ for (i = 0; i < col_count; i++)
+ {
+ fputc(*(opt_align + i), fout);
+ if (opt_border > 0 && i < col_count - 1)
+ fputs(" | ", fout);
+ }
+ fputs(".\n", fout);
+
+ /* print headers */
if (!opt_tuples_only)
{
- if (i != 0)
- fputc('\t', fout);
- fputs("\\fI", fout);
- troff_ms_escaped_print(*ptr, fout);
- fputs("\\fP", fout);
+ for (i = 0, ptr = headers; i < col_count; i++, ptr++)
+ {
+ if (i != 0)
+ fputc('\t', fout);
+ fputs("\\fI", fout);
+ troff_ms_escaped_print(*ptr, fout);
+ fputs("\\fP", fout);
+ }
+ fputs("\n_\n", fout);
}
}
- if (!opt_tuples_only)
- fputs("\n_\n", fout);
-
/* print cells */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
fputc('\t', fout);
}
- fputs(".TE\n.DS L\n", fout);
-
-
- /* print footers */
+ if (opt->stop_table)
+ {
+ fputs(".TE\n.DS L\n", fout);
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
- {
- troff_ms_escaped_print(*ptr, fout);
- fputc('\n', fout);
- }
+ /* print footers */
+ if (footers && !opt_tuples_only && !cancel_pressed)
+ for (ptr = footers; *ptr; ptr++)
+ {
+ troff_ms_escaped_print(*ptr, fout);
+ fputc('\n', fout);
+ }
- fputs(".DE\n", fout);
+ fputs(".DE\n", fout);
+ }
}
-
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, bool opt_tuples_only,
- bool opt_numeric_locale, unsigned short int opt_border,
+ const char *const * cells, const char *const * footers,
+ const char *opt_align, const printTableOpt *opt,
FILE *fout)
{
+ bool opt_tuples_only = opt->tuples_only;
+ bool opt_numeric_locale = opt->numericLocale;
+ unsigned short int opt_border = opt->border;
unsigned int col_count = 0;
+ unsigned long record = opt->prior_records + 1;
unsigned int i;
const char *const * ptr;
- unsigned int record = 1;
unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
(void) opt_align; /* currently unused parameter */
if (cancel_pressed)
return;
- /* print title */
- if (!opt_tuples_only && title)
- {
- fputs(".LP\n.DS C\n", fout);
- troff_ms_escaped_print(title, fout);
- fputs("\n.DE\n", fout);
- }
-
- /* begin environment and set alignments and borders */
- fputs(".LP\n.TS\n", fout);
- if (opt_border == 2)
- fputs("center box;\n", fout);
- else
- fputs("center;\n", fout);
-
- /* basic format */
- if (opt_tuples_only)
- fputs("c l;\n", fout);
+ if (opt_border > 2)
+ opt_border = 2;
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
+ if (opt->start_table)
+ {
+ /* print title */
+ if (!opt_tuples_only && title)
+ {
+ fputs(".LP\n.DS C\n", fout);
+ troff_ms_escaped_print(title, fout);
+ fputs("\n.DE\n", fout);
+ }
+
+ /* begin environment and set alignments and borders */
+ fputs(".LP\n.TS\n", fout);
+ if (opt_border == 2)
+ fputs("center box;\n", fout);
+ else
+ fputs("center;\n", fout);
+
+ /* basic format */
+ if (opt_tuples_only)
+ fputs("c l;\n", fout);
+ }
+ else
+ current_format = 2; /* assume tuples printed already */
+
/* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
{
if (current_format != 1)
{
- if (opt_border == 2 && i > 0)
+ if (opt_border == 2 && record > 1)
fputs("_\n", fout);
if (current_format != 0)
fputs(".T&\n", fout);
fputs("c s.\n", fout);
current_format = 1;
}
- fprintf(fout, "\\fIRecord %d\\fP\n", record++);
+ fprintf(fout, "\\fIRecord %lu\\fP\n", record++);
}
if (opt_border >= 1)
fputs("_\n", fout);
fputc('\n', fout);
}
- fputs(".TE\n.DS L\n", fout);
-
-
- /* print footers */
+ if (opt->stop_table)
+ {
+ fputs(".TE\n.DS L\n", fout);
- if (footers && !opt_tuples_only && !cancel_pressed)
- for (ptr = footers; *ptr; ptr++)
- {
- troff_ms_escaped_print(*ptr, fout);
- fputc('\n', fout);
- }
+ /* print footers */
+ if (footers && !opt_tuples_only && !cancel_pressed)
+ for (ptr = footers; *ptr; ptr++)
+ {
+ troff_ms_escaped_print(*ptr, fout);
+ fputc('\n', fout);
+ }
- fputs(".DE\n", fout);
+ fputs(".DE\n", fout);
+ }
}
-
/********************************/
/* Public functions */
/********************************/
)
{
const char *pagerprog;
+ FILE *pagerpipe;
#ifdef TIOCGWINSZ
int result;
#ifndef WIN32
pqsignal(SIGPIPE, SIG_IGN);
#endif
- return popen(pagerprog, "w");
+ pagerpipe = popen(pagerprog, "w");
+ if (pagerpipe)
+ return pagerpipe;
#ifdef TIOCGWINSZ
}
#endif
return stdout;
}
+/*
+ * ClosePager
+ *
+ * Close previously opened pager pipe, if any
+ */
+void
+ClosePager(FILE *pagerpipe)
+{
+ if (pagerpipe && pagerpipe != stdout)
+ {
+ /*
+ * If printing was canceled midstream, warn about it.
+ *
+ * Some pagers like less use Ctrl-C as part of their command
+ * set. Even so, we abort our processing and warn the user
+ * what we did. If the pager quit as a result of the
+ * SIGINT, this message won't go anywhere ...
+ */
+ if (cancel_pressed)
+ fprintf(pagerpipe, _("Interrupted\n"));
+
+ pclose(pagerpipe);
+#ifndef WIN32
+ pqsignal(SIGPIPE, SIG_DFL);
+#endif
+ }
+}
void
const char *align,
const printTableOpt *opt, FILE *fout, FILE *flog)
{
- const char *default_footer[] = {NULL};
- unsigned short int border = opt->border;
+ static const char *default_footer[] = {NULL};
FILE *output;
- bool use_expanded;
if (cancel_pressed)
return;
if (!footers)
footers = default_footer;
- if (opt->format != PRINT_HTML && border > 2)
- border = 2;
-
- /*
- * We only want to display the results in "expanded" format if this is a
- * normal (user-submitted) query, not a table we're printing for a slash
- * command.
- */
- if (opt->expanded)
- use_expanded = true;
- else
- use_expanded = false;
-
if (fout == stdout)
{
int col_count = 0,
/* print the stuff */
if (flog)
- print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, opt->numericLocale, border, opt->encoding, flog);
+ print_aligned_text(title, headers, cells, footers, align,
+ opt, flog);
switch (opt->format)
{
case PRINT_UNALIGNED:
- if (use_expanded)
+ if (opt->expanded)
print_unaligned_vertical(title, headers, cells, footers, align,
- opt->fieldSep, opt->recordSep,
- opt->tuples_only, opt->numericLocale, output);
+ opt, output);
else
print_unaligned_text(title, headers, cells, footers, align,
- opt->fieldSep, opt->recordSep,
- opt->tuples_only, opt->numericLocale, output);
+ opt, output);
break;
case PRINT_ALIGNED:
- if (use_expanded)
+ if (opt->expanded)
print_aligned_vertical(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale, border,
- opt->encoding, output);
+ opt, output);
else
print_aligned_text(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale,
- border, opt->encoding, output);
+ opt, output);
break;
case PRINT_HTML:
- if (use_expanded)
+ if (opt->expanded)
print_html_vertical(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale,
- border, opt->tableAttr, output);
+ opt, output);
else
- print_html_text(title, headers, cells, footers,
- align, opt->tuples_only, opt->numericLocale, border,
- opt->tableAttr, output);
+ print_html_text(title, headers, cells, footers, align,
+ opt, output);
break;
case PRINT_LATEX:
- if (use_expanded)
+ if (opt->expanded)
print_latex_vertical(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale,
- border, output);
+ opt, output);
else
print_latex_text(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale,
- border, output);
+ opt, output);
break;
case PRINT_TROFF_MS:
- if (use_expanded)
+ if (opt->expanded)
print_troff_ms_vertical(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale,
- border, output);
+ opt, output);
else
print_troff_ms_text(title, headers, cells, footers, align,
- opt->tuples_only, opt->numericLocale,
- border, output);
+ opt, output);
break;
default:
fprintf(stderr, _("invalid output format (internal error): %d"), opt->format);
}
/* Only close if we used the pager */
- if (fout == stdout && output != stdout)
- {
- /*
- * If printing was canceled midstream, warn about it.
- *
- * Some pagers like less use Ctrl-C as part of their command
- * set. Even so, we abort our processing and warn the user
- * what we did. If the pager quit as a result of the
- * SIGINT, this message won't go anywhere ...
- */
- if (cancel_pressed)
- fprintf(output, _("Interrupted\n"));
-
- pclose(output);
-#ifndef WIN32
- pqsignal(SIGPIPE, SIG_DFL);
-#endif
- }
+ if (output != fout)
+ ClosePager(output);
}
-
void
printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog)
{
footers = opt->footers;
else if (!opt->topt.expanded && opt->default_footer)
{
- footers = pg_local_calloc(2, sizeof(*footers));
+ unsigned long total_records;
+ footers = pg_local_calloc(2, sizeof(*footers));
footers[0] = pg_local_malloc(100);
- if (PQntuples(result) == 1)
+ total_records = opt->topt.prior_records + PQntuples(result);
+ if (total_records == 1)
snprintf(footers[0], 100, _("(1 row)"));
else
- snprintf(footers[0], 100, _("(%d rows)"), PQntuples(result));
+ snprintf(footers[0], 100, _("(%lu rows)"), total_records);
}
else
footers = NULL;