summaryrefslogtreecommitdiff
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.c148
1 files changed, 120 insertions, 28 deletions
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 1ad04783d0c..97f6f1e665c 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -3,11 +3,15 @@
*
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.86 2006/06/07 22:24:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.87 2006/06/14 16:49:02 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.
*/
-#include "postgres_fe.h"
+#include "postgres.h"
#include "common.h"
#include "print.h"
+#include "catalog/pg_type.h"
#include <math.h>
#include <signal.h>
@@ -28,6 +32,17 @@
#include "mbprint.h"
+/*
+ * We define the cancel_pressed flag in this file, rather than common.c where
+ * it naturally belongs, because this file is also used by non-psql programs
+ * (see the bin/scripts/ directory). In those programs cancel_pressed will
+ * never become set and will have no effect.
+ *
+ * Note: print.c's general strategy for when to check cancel_pressed is to do
+ * so at completion of each row of output.
+ */
+volatile bool cancel_pressed = false;
+
static char *decimal_point;
static char *grouping;
static char *thousands_sep;
@@ -171,6 +186,9 @@ print_unaligned_text(const char *title, const char *const * headers,
const char *const * ptr;
bool need_recordsep = false;
+ if (cancel_pressed)
+ return;
+
if (!opt_fieldsep)
opt_fieldsep = "";
if (!opt_recordsep)
@@ -202,6 +220,8 @@ print_unaligned_text(const char *title, const char *const * headers,
{
fputs(opt_recordsep, fout);
need_recordsep = false;
+ if (cancel_pressed)
+ break;
}
if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
{
@@ -222,7 +242,7 @@ print_unaligned_text(const char *title, const char *const * headers,
/* print footers */
- if (!opt_tuples_only && footers)
+ if (!opt_tuples_only && footers && !cancel_pressed)
for (ptr = footers; *ptr; ptr++)
{
if (need_recordsep)
@@ -252,6 +272,9 @@ print_unaligned_vertical(const char *title, const char *const * headers,
unsigned int i;
const char *const * ptr;
+ if (cancel_pressed)
+ return;
+
if (!opt_fieldsep)
opt_fieldsep = "";
if (!opt_recordsep)
@@ -273,6 +296,8 @@ print_unaligned_vertical(const char *title, const char *const * headers,
fputs(opt_recordsep, fout);
if (i % col_count == 0)
fputs(opt_recordsep, fout); /* another one */
+ if (cancel_pressed)
+ break;
}
fputs(headers[i % col_count], fout);
@@ -289,7 +314,7 @@ print_unaligned_vertical(const char *title, const char *const * headers,
}
/* print footers */
- if (!opt_tuples_only && footers && *footers)
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
fputs(opt_recordsep, fout);
for (ptr = footers; *ptr; ptr++)
@@ -369,6 +394,9 @@ print_aligned_text(const char *title, const char *const * headers,
int *complete; /* Array remembering which columns have completed output */
+ if (cancel_pressed)
+ return;
+
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
@@ -543,7 +571,6 @@ print_aligned_text(const char *title, const char *const * headers,
fputc('\n', fout);
}
-
_print_horizontal_line(col_count, widths, opt_border, fout);
}
@@ -553,7 +580,10 @@ print_aligned_text(const char *title, const char *const * headers,
int j;
int cols_todo = col_count;
int line_count; /* Number of lines output so far in row */
-
+
+ if (cancel_pressed)
+ break;
+
for (j = 0; j < col_count; j++)
pg_wcsformat((unsigned char*)ptr[j], strlen(ptr[j]), encoding, col_lineptrs[j], heights[j]);
@@ -630,11 +660,11 @@ print_aligned_text(const char *title, const char *const * headers,
}
}
- if (opt_border == 2)
+ if (opt_border == 2 && !cancel_pressed)
_print_horizontal_line(col_count, widths, opt_border, fout);
/* print footers */
- if (footers && !opt_tuples_only)
+ if (footers && !opt_tuples_only && !cancel_pressed)
for (ptr = footers; *ptr; ptr++)
fprintf(fout, "%s\n", *ptr);
@@ -681,6 +711,9 @@ print_aligned_vertical(const char *title, const char *const * headers,
char *divider;
unsigned int cell_count = 0;
struct lineptr *hlineptr, *dlineptr;
+
+ if (cancel_pressed)
+ return;
if (cells[0] == NULL)
{
@@ -764,6 +797,8 @@ print_aligned_vertical(const char *title, const char *const * headers,
if (i % col_count == 0)
{
+ if (cancel_pressed)
+ break;
if (!opt_tuples_only)
{
char *record_str = pg_local_malloc(32);
@@ -860,12 +895,12 @@ print_aligned_vertical(const char *title, const char *const * headers,
}
}
- if (opt_border == 2)
+ if (opt_border == 2 && !cancel_pressed)
fprintf(fout, "%s\n", divider);
/* print footers */
- if (!opt_tuples_only && footers && *footers)
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
if (opt_border < 2)
fputc('\n', fout);
@@ -943,6 +978,9 @@ print_html_text(const char *title, const char *const * headers,
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);
@@ -976,7 +1014,11 @@ print_html_text(const char *title, const char *const * headers,
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (i % col_count == 0)
+ {
+ if (cancel_pressed)
+ break;
fputs(" <tr valign=\"top\">\n", fout);
+ }
fprintf(fout, " <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
/* is string only whitespace? */
@@ -1002,7 +1044,7 @@ print_html_text(const char *title, const char *const * headers,
/* print footers */
- if (!opt_tuples_only && footers && *footers)
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
@@ -1029,6 +1071,9 @@ print_html_vertical(const char *title, const char *const * headers,
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);
@@ -1051,6 +1096,8 @@ print_html_vertical(const char *title, const char *const * headers,
{
if (i % col_count == 0)
{
+ if (cancel_pressed)
+ break;
if (!opt_tuples_only)
fprintf(fout, "\n <tr><td colspan=\"2\" align=\"center\">Record %d</td></tr>\n", record++);
else
@@ -1081,7 +1128,7 @@ print_html_vertical(const char *title, const char *const * headers,
fputs("</table>\n", fout);
/* print footers */
- if (!opt_tuples_only && footers && *footers)
+ if (!opt_tuples_only && footers && *footers && !cancel_pressed)
{
fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
@@ -1151,6 +1198,8 @@ print_latex_text(const char *title, const char *const * headers,
unsigned int i;
const char *const * ptr;
+ if (cancel_pressed)
+ return;
/* print title */
if (!opt_tuples_only && title)
@@ -1216,7 +1265,11 @@ print_latex_text(const char *title, const char *const * headers,
latex_escaped_print(*ptr, fout);
if ((i + 1) % col_count == 0)
+ {
fputs(" \\\\\n", fout);
+ if (cancel_pressed)
+ break;
+ }
else
fputs(" & ", fout);
}
@@ -1229,7 +1282,7 @@ print_latex_text(const char *title, const char *const * headers,
/* print footers */
- if (footers && !opt_tuples_only)
+ if (footers && !opt_tuples_only && !cancel_pressed)
for (ptr = footers; *ptr; ptr++)
{
latex_escaped_print(*ptr, fout);
@@ -1255,6 +1308,9 @@ print_latex_vertical(const char *title, const char *const * headers,
(void) opt_align; /* currently unused parameter */
+ if (cancel_pressed)
+ return;
+
/* print title */
if (!opt_tuples_only && title)
{
@@ -1285,6 +1341,8 @@ print_latex_vertical(const char *title, const char *const * headers,
/* new record */
if (i % col_count == 0)
{
+ if (cancel_pressed)
+ break;
if (!opt_tuples_only)
{
if (opt_border == 2)
@@ -1313,7 +1371,7 @@ print_latex_vertical(const char *title, const char *const * headers,
/* print footers */
- if (footers && !opt_tuples_only)
+ if (footers && !opt_tuples_only && !cancel_pressed)
for (ptr = footers; *ptr; ptr++)
{
if (opt_numeric_locale)
@@ -1367,6 +1425,8 @@ print_troff_ms_text(const char *title, const char *const * headers,
unsigned int i;
const char *const * ptr;
+ if (cancel_pressed)
+ return;
/* print title */
if (!opt_tuples_only && title)
@@ -1425,7 +1485,11 @@ print_troff_ms_text(const char *title, const char *const * headers,
troff_ms_escaped_print(*ptr, fout);
if ((i + 1) % col_count == 0)
+ {
fputc('\n', fout);
+ if (cancel_pressed)
+ break;
+ }
else
fputc('\t', fout);
}
@@ -1435,7 +1499,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
/* print footers */
- if (footers && !opt_tuples_only)
+ if (footers && !opt_tuples_only && !cancel_pressed)
for (ptr = footers; *ptr; ptr++)
{
troff_ms_escaped_print(*ptr, fout);
@@ -1462,6 +1526,9 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
(void) opt_align; /* currently unused parameter */
+ if (cancel_pressed)
+ return;
+
/* print title */
if (!opt_tuples_only && title)
{
@@ -1491,6 +1558,8 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
/* new record */
if (i % col_count == 0)
{
+ if (cancel_pressed)
+ break;
if (!opt_tuples_only)
{
if (current_format != 1)
@@ -1542,7 +1611,7 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
/* print footers */
- if (footers && !opt_tuples_only)
+ if (footers && !opt_tuples_only && !cancel_pressed)
for (ptr = footers; *ptr; ptr++)
{
troff_ms_escaped_print(*ptr, fout);
@@ -1618,6 +1687,9 @@ printTable(const char *title,
FILE *output;
bool use_expanded;
+ if (cancel_pressed)
+ return;
+
if (opt->format == PRINT_NOTHING)
return;
@@ -1731,6 +1803,17 @@ printTable(const char *title,
/* 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);
@@ -1751,6 +1834,9 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
char *align;
int i;
+ if (cancel_pressed)
+ return;
+
/* extract headers */
nfields = PQnfields(result);
@@ -1798,18 +1884,24 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
{
Oid ftype = PQftype(result, i);
- if (ftype == 20 || /* int8 */
- ftype == 21 || /* int2 */
- ftype == 23 || /* int4 */
- (ftype >= 26 && ftype <= 30) || /* ?id */
- ftype == 700 || /* float4 */
- ftype == 701 || /* float8 */
- ftype == 790 || /* money */
- ftype == 1700 /* numeric */
- )
- align[i] = 'r';
- else
- align[i] = 'l';
+ switch (ftype)
+ {
+ case INT2OID:
+ case INT4OID:
+ case INT8OID:
+ case FLOAT4OID:
+ case FLOAT8OID:
+ case NUMERICOID:
+ case OIDOID:
+ case XIDOID:
+ case CIDOID:
+ case CASHOID:
+ align[i] = 'r';
+ break;
+ default:
+ align[i] = 'l';
+ break;
+ }
}
/* call table printer */