Improve psql's tabular display of wrapped-around data by inserting markers

in the formerly-always-blank columns just to left and right of the data.
Different marking is used for a line break caused by a newline in the data
than for a straight wraparound.  A newline break is signaled by a "+" in the
right margin column in ASCII mode, or a carriage return arrow in UNICODE mode.
Wraparound is signaled by a dot in the right margin as well as the following
left margin in ASCII mode, or an ellipsis symbol in the same places in UNICODE
mode.  "\pset linestyle old-ascii" is added to make the previous behavior
available if anyone really wants it.

In passing, this commit also cleans up a few regression test files that
had unintended spacing differences from the current actual output.

Roger Leigh, reviewed by Gabrielle Roth and other members of PDXPUG.
This commit is contained in:
Tom Lane 2009-11-22 05:20:41 +00:00
parent 93d3bac564
commit 1753337cf5
19 changed files with 374 additions and 260 deletions

View File

@ -6,21 +6,21 @@ SET bytea_output TO escape;
select armor(''); select armor('');
armor armor
----------------------------- -----------------------------
-----BEGIN PGP MESSAGE----- -----BEGIN PGP MESSAGE-----+
+
=twTO =twTO +
-----END PGP MESSAGE----- -----END PGP MESSAGE----- +
(1 row) (1 row)
select armor('test'); select armor('test');
armor armor
----------------------------- -----------------------------
-----BEGIN PGP MESSAGE----- -----BEGIN PGP MESSAGE-----+
+
dGVzdA== dGVzdA== +
=+G7Q =+G7Q +
-----END PGP MESSAGE----- -----END PGP MESSAGE----- +
(1 row) (1 row)
@ -40,12 +40,12 @@ select armor('0123456789abcdef0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef0123456789abcdef'); 0123456789abcdef0123456789abcdef0123456789abcdef');
armor armor
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-----BEGIN PGP MESSAGE----- -----BEGIN PGP MESSAGE----- +
+
MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmCjAxMjM0NTY3 MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmCjAxMjM0NTY3+
ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZg== ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZg== +
=JFw5 =JFw5 +
-----END PGP MESSAGE----- -----END PGP MESSAGE----- +
(1 row) (1 row)

View File

@ -742,8 +742,8 @@ select * from parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc
3 | ewri2 3 | ewri2
12 | 12 |
13 | <a href="qwe<qwe>"> 13 | <a href="qwe<qwe>">
12 | 12 | +
: |
19 | /usr/local/fff 19 | /usr/local/fff
12 | 12 |
19 | /awdf/dwqe/4325 19 | /awdf/dwqe/4325
@ -775,8 +775,8 @@ select * from parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc
20 | -4.2 20 | -4.2
12 | . 12 | .
22 | 234 22 | 234
12 | 12 | +
: |
12 | < 12 | <
1 | i 1 | i
12 | 12 |
@ -2330,8 +2330,8 @@ Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('sea&thousand&years')); ', to_tsquery('sea&thousand&years'));
headline headline
-------------------------------------------- --------------------------------------------
<b>sea</b> a <b>thousand</b> <b>years</b>, <b>sea</b> a <b>thousand</b> <b>years</b>,+
A <b>thousand</b> <b>years</b> to trace A <b>thousand</b> <b>years</b> to trace +
The granite features of this cliff The granite features of this cliff
(1 row) (1 row)
@ -2347,8 +2347,8 @@ Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('granite&sea')); ', to_tsquery('granite&sea'));
headline headline
------------------------------------------- -------------------------------------------
<b>sea</b> a thousand years, <b>sea</b> a thousand years, +
A thousand years to trace A thousand years to trace +
The <b>granite</b> features of this cliff The <b>granite</b> features of this cliff
(1 row) (1 row)
@ -2364,8 +2364,8 @@ Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('sea')); ', to_tsquery('sea'));
headline headline
------------------------------------ ------------------------------------
<b>sea</b> a thousand years, <b>sea</b> a thousand years, +
A thousand years to trace A thousand years to trace +
The granite features of this cliff The granite features of this cliff
(1 row) (1 row)
@ -2384,17 +2384,17 @@ ff-bg
to_tsquery('sea&foo'), 'HighlightAll=true'); to_tsquery('sea&foo'), 'HighlightAll=true');
headline headline
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
+
<html> <html> +
<!-- some comment --> <!-- some comment --> +
<body> <body> +
<b>Sea</b> view wow <u><b>foo</b> bar</u> <i>qq</i> <b>Sea</b> view wow <u><b>foo</b> bar</u> <i>qq</i> +
<a href="http://www.google.com/foo.bar.html" target="_blank">YES &nbsp;</a> <a href="http://www.google.com/foo.bar.html" target="_blank">YES &nbsp;</a>+
ff-bg ff-bg +
<script> <script> +
document.write(15); document.write(15); +
</script> </script> +
</body> </body> +
</html> </html>
(1 row) (1 row)

View File

@ -742,8 +742,8 @@ select * from parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc
3 | ewri2 3 | ewri2
12 | 12 |
13 | <a href="qwe<qwe>"> 13 | <a href="qwe<qwe>">
12 | 12 | +
: |
19 | /usr/local/fff 19 | /usr/local/fff
12 | 12 |
19 | /awdf/dwqe/4325 19 | /awdf/dwqe/4325
@ -775,8 +775,8 @@ select * from parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc
20 | -4.2 20 | -4.2
12 | . 12 | .
22 | 234 22 | 234
12 | 12 | +
: |
12 | < 12 | <
1 | i 1 | i
12 | 12 |
@ -2330,8 +2330,8 @@ Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('sea&thousand&years')); ', to_tsquery('sea&thousand&years'));
headline headline
-------------------------------------------- --------------------------------------------
<b>sea</b> a <b>thousand</b> <b>years</b>, <b>sea</b> a <b>thousand</b> <b>years</b>,+
A <b>thousand</b> <b>years</b> to trace A <b>thousand</b> <b>years</b> to trace +
The granite features of this cliff The granite features of this cliff
(1 row) (1 row)
@ -2347,8 +2347,8 @@ Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('granite&sea')); ', to_tsquery('granite&sea'));
headline headline
------------------------------------------- -------------------------------------------
<b>sea</b> a thousand years, <b>sea</b> a thousand years, +
A thousand years to trace A thousand years to trace +
The <b>granite</b> features of this cliff The <b>granite</b> features of this cliff
(1 row) (1 row)
@ -2364,8 +2364,8 @@ Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('sea')); ', to_tsquery('sea'));
headline headline
------------------------------------ ------------------------------------
<b>sea</b> a thousand years, <b>sea</b> a thousand years, +
A thousand years to trace A thousand years to trace +
The granite features of this cliff The granite features of this cliff
(1 row) (1 row)
@ -2384,17 +2384,17 @@ ff-bg
to_tsquery('sea&foo'), 'HighlightAll=true'); to_tsquery('sea&foo'), 'HighlightAll=true');
headline headline
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
+
<html> <html> +
<!-- some comment --> <!-- some comment --> +
<body> <body> +
<b>Sea</b> view wow <u><b>foo</b> bar</u> <i>qq</i> <b>Sea</b> view wow <u><b>foo</b> bar</u> <i>qq</i> +
<a href="http://www.google.com/foo.bar.html" target="_blank">YES &nbsp;</a> <a href="http://www.google.com/foo.bar.html" target="_blank">YES &nbsp;</a>+
ff-bg ff-bg +
<script> <script> +
document.write(15); document.write(15); +
</script> </script> +
</body> </body> +
</html> </html>
(1 row) (1 row)

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.232 2009/10/13 21:04:01 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.233 2009/11/22 05:20:41 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -1765,30 +1765,54 @@ lo_import 152801
<listitem> <listitem>
<para> <para>
Sets the border line drawing style to one Sets the border line drawing style to one
of <literal>ascii</literal> or <literal>unicode</literal>. of <literal>ascii</literal>, <literal>old-ascii</literal>
or <literal>unicode</literal>.
Unique abbreviations are allowed. (That would mean one Unique abbreviations are allowed. (That would mean one
letter is enough.) letter is enough.)
</para> </para>
<para> <para>
<quote>ASCII</quote> uses plain <acronym>ASCII</acronym> characters. <literal>ascii</literal> style uses plain <acronym>ASCII</acronym>
characters. Newlines in data are shown using
a <literal>+</literal> symbol in the right-hand margin.
When the data wraps from one line
to the next without a newline character, a dot (<literal>.</>)
is shown in the right-hand margin of the first line, and
again in the left-hand margin of the following line.
</para> </para>
<para> <para>
<quote>Unicode</quote> uses Unicode box-drawing characters. <literal>old-ascii</literal> style uses plain <acronym>ASCII</>
characters, using the formatting style used
in <productname>PostgreSQL</productname> 8.4 and earlier.
Newlines in data are shown using a <literal>:</literal>
symbol in place of the left-hand column separator.
When the data wraps from one line
to the next without a newline character, a <literal>;</>
symbol is used in place of the left-hand column separator.
</para>
<para>
<literal>unicode</literal> style uses Unicode box-drawing characters.
Newlines in data are shown using a carriage return symbol
in the right-hand margin. When the data wraps from one line
to the next without a newline character, an ellipsis symbol
is shown in the right-hand margin of the first line, and
again in the left-hand margin of the following line.
</para> </para>
<para> <para>
When the selected output format is one that draws lines or boxes When the selected output format is one that draws lines or boxes
around the data, this setting controls how the lines are drawn. around the data, this setting also determines the characters
with which the lines are drawn.
Plain <acronym>ASCII</acronym> characters work everywhere, but Plain <acronym>ASCII</acronym> characters work everywhere, but
Unicode characters look nicer on displays that recognize them. Unicode characters look nicer on displays that recognize them.
</para> </para>
<para> <para>
If this option has not been set, the default behavior is to If this option has not been set, the default behavior is to use
use Unicode characters if the client character set encoding <literal>unicode</literal> style if the client character set encoding
is UTF-8, otherwise <acronym>ASCII</acronym> characters. is UTF-8, otherwise <literal>ascii</literal> style.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2009, PostgreSQL Global Development Group * Copyright (c) 2000-2009, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.210 2009/10/13 21:04:01 tgl Exp $ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.211 2009/11/22 05:20:41 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "command.h" #include "command.h"
@ -1795,11 +1795,13 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
; ;
else if (pg_strncasecmp("ascii", value, vallen) == 0) else if (pg_strncasecmp("ascii", value, vallen) == 0)
popt->topt.line_style = &pg_asciiformat; popt->topt.line_style = &pg_asciiformat;
else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
popt->topt.line_style = &pg_asciiformat_old;
else if (pg_strncasecmp("unicode", value, vallen) == 0) else if (pg_strncasecmp("unicode", value, vallen) == 0)
popt->topt.line_style = &pg_utf8format; popt->topt.line_style = &pg_utf8format;
else else
{ {
psql_error("\\pset: allowed line styles are ascii, unicode\n"); psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
return false; return false;
} }

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2009, PostgreSQL Global Development Group * Copyright (c) 2000-2009, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.117 2009/10/13 21:04:01 tgl Exp $ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.118 2009/11/22 05:20:41 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
@ -54,9 +54,37 @@ const printTextFormat pg_asciiformat =
{ "-", "+", "+", "+" }, { "-", "+", "+", "+" },
{ "", "|", "|", "|" } { "", "|", "|", "|" }
}, },
"|",
"|",
"|",
" ",
"+",
" ",
"+",
".",
".",
true
};
const printTextFormat pg_asciiformat_old =
{
"old-ascii",
{
{ "-", "+", "+", "+" },
{ "-", "+", "+", "+" },
{ "-", "+", "+", "+" },
{ "", "|", "|", "|" }
},
":", ":",
";", ";",
" " " ",
"+",
" ",
" ",
" ",
" ",
" ",
false
}; };
const printTextFormat pg_utf8format = const printTextFormat pg_utf8format =
@ -72,12 +100,23 @@ const printTextFormat pg_utf8format =
/* N/A, │, │, │ */ /* N/A, │, │, │ */
{ "", "\342\224\202", "\342\224\202", "\342\224\202" } { "", "\342\224\202", "\342\224\202", "\342\224\202" }
}, },
/* ╎ */ /* │ */
"\342\225\216", "\342\224\202",
/* ┊ */ /* │ */
"\342\224\212", "\342\224\202",
/* ╷ */ /* │ */
"\342\225\267" "\342\224\202",
" ",
/* ↵ */
"\342\206\265",
" ",
/* ↵ */
"\342\206\265",
/* … */
"\342\200\246",
/* … */
"\342\200\246",
true
}; };
@ -476,6 +515,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
bool *header_done; /* Have all header lines been output? */ bool *header_done; /* Have all header lines been output? */
int *bytes_output; /* Bytes output for column value */ int *bytes_output; /* Bytes output for column value */
printTextLineWrap *wrap; /* Wrap status for each column */
int output_columns = 0; /* Width of interactive console */ int output_columns = 0; /* Width of interactive console */
bool is_pager = false; bool is_pager = false;
@ -499,6 +539,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
format_buf = pg_local_calloc(col_count, sizeof(*format_buf)); format_buf = pg_local_calloc(col_count, sizeof(*format_buf));
header_done = pg_local_calloc(col_count, sizeof(*header_done)); header_done = pg_local_calloc(col_count, sizeof(*header_done));
bytes_output = pg_local_calloc(col_count, sizeof(*bytes_output)); bytes_output = pg_local_calloc(col_count, sizeof(*bytes_output));
wrap = pg_local_calloc(col_count, sizeof(*wrap));
} }
else else
{ {
@ -513,6 +554,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
format_buf = NULL; format_buf = NULL;
header_done = NULL; header_done = NULL;
bytes_output = NULL; bytes_output = NULL;
wrap = NULL;
} }
/* scan all column headers, find maximum width and max max_nl_lines */ /* scan all column headers, find maximum width and max max_nl_lines */
@ -575,7 +617,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
/* adjust the total display width based on border style */ /* adjust the total display width based on border style */
if (opt_border == 0) if (opt_border == 0)
width_total = col_count - 1; width_total = col_count;
else if (opt_border == 1) else if (opt_border == 1)
width_total = col_count * 3 - 1; width_total = col_count * 3 - 1;
else else
@ -770,16 +812,18 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
while (more_col_wrapping) while (more_col_wrapping)
{ {
if (opt_border == 2) if (opt_border == 2)
fprintf(fout, "%s%c", dformat->leftvrule, fputs(dformat->leftvrule, fout);
curr_nl_line ? '+' : ' ');
else if (opt_border == 1)
fputc(curr_nl_line ? '+' : ' ', fout);
for (i = 0; i < cont->ncolumns; i++) for (i = 0; i < cont->ncolumns; i++)
{ {
struct lineptr *this_line = col_lineptrs[i] + curr_nl_line; struct lineptr *this_line = col_lineptrs[i] + curr_nl_line;
unsigned int nbspace; unsigned int nbspace;
if (opt_border != 0 ||
(format->wrap_right_border == false && i > 0))
fputs(curr_nl_line ? format->header_nl_left : " ",
fout);
if (!header_done[i]) if (!header_done[i])
{ {
nbspace = width_wrap[i] - this_line->width; nbspace = width_wrap[i] - this_line->width;
@ -796,21 +840,18 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
} }
else else
fprintf(fout, "%*s", width_wrap[i], ""); fprintf(fout, "%*s", width_wrap[i], "");
if (i < col_count - 1)
{ if (opt_border != 0 || format->wrap_right_border == true)
if (opt_border == 0) fputs(!header_done[i] ? format->header_nl_right : " ",
fputc(curr_nl_line ? '+' : ' ', fout); fout);
else
fprintf(fout, " %s%c", dformat->midvrule, if (opt_border != 0 && i < col_count - 1)
curr_nl_line ? '+' : ' '); fputs(dformat->midvrule, fout);
}
} }
curr_nl_line++; curr_nl_line++;
if (opt_border == 2) if (opt_border == 2)
fprintf(fout, " %s", dformat->rightvrule); fputs(dformat->rightvrule, fout);
else if (opt_border == 1)
fputc(' ', fout);
fputc('\n', fout); fputc('\n', fout);
} }
@ -861,9 +902,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
/* left border */ /* left border */
if (opt_border == 2) if (opt_border == 2)
fprintf(fout, "%s ", dformat->leftvrule); fputs(dformat->leftvrule, fout);
else if (opt_border == 1)
fputc(' ', fout);
/* for each column */ /* for each column */
for (j = 0; j < col_count; j++) for (j = 0; j < col_count; j++)
@ -874,6 +913,17 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
int chars_to_output = width_wrap[j]; int chars_to_output = width_wrap[j];
bool finalspaces = (opt_border == 2 || j < col_count - 1); bool finalspaces = (opt_border == 2 || j < col_count - 1);
/* Print left-hand wrap or newline mark */
if (opt_border != 0)
{
if (wrap[j] == PRINT_LINE_WRAP_WRAP)
fputs(format->wrap_left, fout);
else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE)
fputs(format->nl_left, fout);
else
fputc(' ', fout);
}
if (!this_line->ptr) if (!this_line->ptr)
{ {
/* Past newline lines so just pad for other columns */ /* Past newline lines so just pad for other columns */
@ -908,8 +958,6 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
/* spaces second */ /* spaces second */
fprintf(fout, "%.*s", bytes_to_output, fprintf(fout, "%.*s", bytes_to_output,
this_line->ptr + bytes_output[j]); this_line->ptr + bytes_output[j]);
if (finalspaces)
fprintf(fout, "%*s", width_wrap[j] - chars_to_output, "");
} }
bytes_output[j] += bytes_to_output; bytes_output[j] += bytes_to_output;
@ -927,29 +975,54 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
} }
} }
/* print a divider, if not the last column */ /* Determine next line's wrap status for this column */
if (j < col_count - 1) wrap[j] = PRINT_LINE_WRAP_NONE;
if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
{ {
if (opt_border == 0) if (bytes_output[j] != 0)
wrap[j] = PRINT_LINE_WRAP_WRAP;
else if (curr_nl_line[j] != 0)
wrap[j] = PRINT_LINE_WRAP_NEWLINE;
}
/*
* If left-aligned, pad out remaining space if needed (not
* last column, and/or wrap marks required).
*/
if (cont->aligns[j] != 'r') /* Left aligned cell */
{
if (finalspaces ||
wrap[j] == PRINT_LINE_WRAP_WRAP ||
wrap[j] == PRINT_LINE_WRAP_NEWLINE)
fprintf(fout, "%*s",
width_wrap[j] - chars_to_output, "");
}
/* Print right-hand wrap or newline mark */
if (wrap[j] == PRINT_LINE_WRAP_WRAP)
fputs(format->wrap_right, fout);
else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE)
fputs(format->nl_right, fout);
else if (opt_border == 2 || j < col_count - 1)
fputc(' ', fout); fputc(' ', fout);
/* Next value is beyond past newlines? */
/* Print column divider, if not the last column */
if (opt_border != 0 && j < col_count - 1)
{
if (wrap[j+1] == PRINT_LINE_WRAP_WRAP)
fputs(format->midvrule_wrap, fout);
else if (wrap[j+1] == PRINT_LINE_WRAP_NEWLINE)
fputs(format->midvrule_nl, fout);
else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL) else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL)
fprintf(fout, " %s ", format->midvrule_blank); fputs(format->midvrule_blank, fout);
/* In wrapping of value? */
else if (bytes_output[j + 1] != 0)
fprintf(fout, " %s ", format->midvrule_wrap);
/* After first newline value */
else if (curr_nl_line[j + 1] != 0)
fprintf(fout, " %s ", format->midvrule_cont);
/* Ordinary line */
else else
fprintf(fout, " %s ", dformat->midvrule); fputs(dformat->midvrule, fout);
} }
} }
/* end-of-row border */ /* end-of-row border */
if (opt_border == 2) if (opt_border == 2)
fprintf(fout, " %s", dformat->rightvrule); fputs(dformat->rightvrule, fout);
fputc('\n', fout); fputc('\n', fout);
} while (more_lines); } while (more_lines);
@ -1196,9 +1269,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
fprintf(fout, "%*s", hwidth, ""); fprintf(fout, "%*s", hwidth, "");
if (opt_border > 0) if (opt_border > 0)
fprintf(fout, " %s ", fprintf(fout, " %s ", dformat->midvrule);
(line_count == 0) ?
format->midvrule_cont : dformat->midvrule);
else else
fputc(' ', fout); fputc(' ', fout);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2009, PostgreSQL Global Development Group * Copyright (c) 2000-2009, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.41 2009/10/13 21:04:01 tgl Exp $ * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.42 2009/11/22 05:20:41 tgl Exp $
*/ */
#ifndef PRINT_H #ifndef PRINT_H
#define PRINT_H #define PRINT_H
@ -41,14 +41,30 @@ typedef enum printTextRule
PRINT_RULE_DATA /* data line (hrule is unused here) */ PRINT_RULE_DATA /* data line (hrule is unused here) */
} printTextRule; } printTextRule;
typedef enum printTextLineWrap
{
/* Line wrapping conditions */
PRINT_LINE_WRAP_NONE, /* No wrapping */
PRINT_LINE_WRAP_WRAP, /* Wraparound due to overlength line */
PRINT_LINE_WRAP_NEWLINE /* Newline in data */
} printTextLineWrap;
typedef struct printTextFormat typedef struct printTextFormat
{ {
/* A complete line style */ /* A complete line style */
const char *name; /* for display purposes */ const char *name; /* for display purposes */
printTextLineFormat lrule[4]; /* indexed by enum printTextRule */ printTextLineFormat lrule[4]; /* indexed by enum printTextRule */
const char *midvrule_cont; /* vertical line for continue after newline */ const char *midvrule_nl; /* vertical line for continue after newline */
const char *midvrule_wrap; /* vertical line for wrapped data */ const char *midvrule_wrap; /* vertical line for wrapped data */
const char *midvrule_blank; /* vertical line for blank data */ const char *midvrule_blank; /* vertical line for blank data */
const char *header_nl_left; /* left mark after newline */
const char *header_nl_right; /* right mark for newline */
const char *nl_left; /* left mark after newline */
const char *nl_right; /* right mark for newline */
const char *wrap_left; /* left mark after wrapped data */
const char *wrap_right; /* right mark for wrapped data */
bool wrap_right_border; /* use right-hand border for wrap marks
* when border=0? */
} printTextFormat; } printTextFormat;
typedef struct printTableOpt typedef struct printTableOpt
@ -125,6 +141,7 @@ typedef struct printQueryOpt
extern const printTextFormat pg_asciiformat; extern const printTextFormat pg_asciiformat;
extern const printTextFormat pg_asciiformat_old;
extern const printTextFormat pg_utf8format; extern const printTextFormat pg_utf8format;

View File

@ -71,9 +71,9 @@ RESET SESSION AUTHORIZATION;
Access privileges Access privileges
Schema | Name | Type | Access privileges | Column access privileges Schema | Name | Type | Access privileges | Column access privileges
--------+----------+-------+--------------------------------------------------+-------------------------- --------+----------+-------+--------------------------------------------------+--------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0 | public | deptest1 | table | regression_user0=arwdDxt/regression_user0 +|
: regression_user1=a*r*w*d*D*x*t*/regression_user0 | | | regression_user1=a*r*w*d*D*x*t*/regression_user0+|
: regression_user2=arwdDxt/regression_user1 | | | regression_user2=arwdDxt/regression_user1 |
(1 row) (1 row)
DROP OWNED BY regression_user1; DROP OWNED BY regression_user1;

View File

@ -366,14 +366,14 @@ GRANT USAGE ON FOREIGN SERVER s6 TO regress_test_role2 WITH GRANT OPTION;
List of foreign servers List of foreign servers
Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options
------+-------------------+----------------------+-----------------------------------------+--------+---------+------------------------------ ------+-------------------+----------------------+-----------------------------------------+--------+---------+------------------------------
s1 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user | | 1.0 | {servername=s1} s1 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 1.0 | {servername=s1}
: regress_test_role=U/foreign_data_user | | | regress_test_role=U/foreign_data_user | | |
s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b} s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b}
s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521} s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521}
s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b}
s5 | foreign_data_user | foo | | | 15.0 | s5 | foreign_data_user | foo | | | 15.0 |
s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user | | 16.0 | {host=a,dbname=b} s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | {host=a,dbname=b}
: regress_test_role2=U*/foreign_data_user | | | regress_test_role2=U*/foreign_data_user | | |
s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b}
s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db}
t1 | regress_test_role | foo | | | | t1 | regress_test_role | foo | | | |
@ -417,14 +417,14 @@ access to foreign-data wrapper foo
List of foreign servers List of foreign servers
Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options
------+-----------------------+----------------------+-----------------------------------------+--------+---------+--------------------------------- ------+-----------------------+----------------------+-----------------------------------------+--------+---------+---------------------------------
s1 | regress_test_indirect | foo | foreign_data_user=U/foreign_data_user | | 1.1 | {servername=s1} s1 | regress_test_indirect | foo | foreign_data_user=U/foreign_data_user +| | 1.1 | {servername=s1}
: regress_test_role=U/foreign_data_user | | | regress_test_role=U/foreign_data_user | | |
s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b} s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b}
s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521} s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521}
s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b}
s5 | foreign_data_user | foo | | | 15.0 | s5 | foreign_data_user | foo | | | 15.0 |
s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user | | 16.0 | {host=a,dbname=b} s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | {host=a,dbname=b}
: regress_test_role2=U*/foreign_data_user | | | regress_test_role2=U*/foreign_data_user | | |
s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b}
s8 | foreign_data_user | postgresql | | | | {dbname=db1,connect_timeout=30} s8 | foreign_data_user | postgresql | | | | {dbname=db1,connect_timeout=30}
t1 | regress_test_role | foo | | | | t1 | regress_test_role | foo | | | |

View File

@ -154,20 +154,20 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements
ORDER BY name; ORDER BY name;
name | statement | parameter_types name | statement | parameter_types
------+---------------------------------------------------------------------+-------------------------------------------------------- ------+---------------------------------------------------------------------+--------------------------------------------------------
q2 | PREPARE q2(text) AS | {text} q2 | PREPARE q2(text) AS +| {text}
: SELECT datname, datistemplate, datallowconn | SELECT datname, datistemplate, datallowconn +|
: FROM pg_database WHERE datname = $1; | FROM pg_database WHERE datname = $1; |
q3 | PREPARE q3(text, int, float, boolean, oid, smallint) AS | {text,integer,"double precision",boolean,oid,smallint} q3 | PREPARE q3(text, int, float, boolean, oid, smallint) AS +| {text,integer,"double precision",boolean,oid,smallint}
: SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR | SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR +|
: ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int) | ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int)+|
: ORDER BY unique1; | ORDER BY unique1; |
q5 | PREPARE q5(int, text) AS | {integer,text} q5 | PREPARE q5(int, text) AS +| {integer,text}
: SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 | SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +|
: ORDER BY unique1; | ORDER BY unique1; |
q6 | PREPARE q6 AS | {integer,name} q6 | PREPARE q6 AS +| {integer,name}
: SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; |
q7 | PREPARE q7(unknown) AS | {path} q7 | PREPARE q7(unknown) AS +| {path}
: SELECT * FROM road WHERE thepath = $1; | SELECT * FROM road WHERE thepath = $1; |
(5 rows) (5 rows)
-- test DEALLOCATE ALL; -- test DEALLOCATE ALL;

View File

@ -377,10 +377,10 @@ SELECT * FROM main_table ORDER BY a, b;
SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'modified_a'; SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'modified_a';
pg_get_triggerdef pg_get_triggerdef
-------------------------------------------------- --------------------------------------------------
CREATE TRIGGER modified_a CREATE TRIGGER modified_a +
BEFORE UPDATE OF a ON main_table BEFORE UPDATE OF a ON main_table +
FOR EACH ROW FOR EACH ROW +
WHEN (old.a <> new.a) WHEN (old.a <> new.a) +
EXECUTE PROCEDURE trigger_func('modified_a') EXECUTE PROCEDURE trigger_func('modified_a')
(1 row) (1 row)
@ -393,10 +393,10 @@ SELECT pg_get_triggerdef(oid, false) FROM pg_trigger WHERE tgrelid = 'main_table
SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'modified_any'; SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'modified_any';
pg_get_triggerdef pg_get_triggerdef
---------------------------------------------------- ----------------------------------------------------
CREATE TRIGGER modified_any CREATE TRIGGER modified_any +
BEFORE UPDATE OF a ON main_table BEFORE UPDATE OF a ON main_table +
FOR EACH ROW FOR EACH ROW +
WHEN (old.* IS DISTINCT FROM new.*) WHEN (old.* IS DISTINCT FROM new.*) +
EXECUTE PROCEDURE trigger_func('modified_any') EXECUTE PROCEDURE trigger_func('modified_any')
(1 row) (1 row)
@ -427,9 +427,9 @@ SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'main_table'::regc
SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'after_upd_a_b_row_trig'; SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'after_upd_a_b_row_trig';
pg_get_triggerdef pg_get_triggerdef
--------------------------------------------------------- ---------------------------------------------------------
CREATE TRIGGER after_upd_a_b_row_trig CREATE TRIGGER after_upd_a_b_row_trig +
AFTER UPDATE OF a, b ON main_table AFTER UPDATE OF a, b ON main_table +
FOR EACH ROW FOR EACH ROW +
EXECUTE PROCEDURE trigger_func('after_upd_a_b_row') EXECUTE PROCEDURE trigger_func('after_upd_a_b_row')
(1 row) (1 row)

View File

@ -344,8 +344,8 @@ SELECT * FROM ts_parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.w
3 | ewri2 3 | ewri2
12 | 12 |
13 | <a href="qwe<qwe>"> 13 | <a href="qwe<qwe>">
12 | 12 | +
: |
19 | /usr/local/fff 19 | /usr/local/fff
12 | 12 |
19 | /awdf/dwqe/4325 19 | /awdf/dwqe/4325
@ -377,8 +377,8 @@ SELECT * FROM ts_parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.w
20 | -4.2 20 | -4.2
12 | . 12 | .
22 | 234 22 | 234
12 | 12 | +
: |
12 | < 12 | <
1 | i 1 | i
12 | 12 |
@ -559,9 +559,9 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'paint&water')); ', to_tsquery('english', 'paint&water'));
ts_headline ts_headline
----------------------------------------- -----------------------------------------
<b>painted</b> Ocean. <b>painted</b> Ocean. +
<b>Water</b>, <b>water</b>, every where <b>Water</b>, <b>water</b>, every where+
And all the boards did shrink; And all the boards did shrink; +
<b>Water</b>, <b>water</b>, every <b>Water</b>, <b>water</b>, every
(1 row) (1 row)
@ -578,9 +578,9 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'breath&motion&water')); ', to_tsquery('english', 'breath&motion&water'));
ts_headline ts_headline
---------------------------------- ----------------------------------
<b>breath</b> nor <b>motion</b>, <b>breath</b> nor <b>motion</b>,+
As idle as a painted Ship As idle as a painted Ship +
Upon a painted Ocean. Upon a painted Ocean. +
<b>Water</b>, <b>water</b> <b>Water</b>, <b>water</b>
(1 row) (1 row)
@ -597,9 +597,9 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'ocean')); ', to_tsquery('english', 'ocean'));
ts_headline ts_headline
---------------------------------- ----------------------------------
<b>Ocean</b>. <b>Ocean</b>. +
Water, water, every where Water, water, every where +
And all the boards did shrink; And all the boards did shrink;+
Water, water, every where Water, water, every where
(1 row) (1 row)
@ -618,17 +618,17 @@ ff-bg
to_tsquery('english', 'sea&foo'), 'HighlightAll=true'); to_tsquery('english', 'sea&foo'), 'HighlightAll=true');
ts_headline ts_headline
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
+
<html> <html> +
<!-- some comment --> <!-- some comment --> +
<body> <body> +
<b>Sea</b> view wow <u><b>foo</b> bar</u> <i>qq</i> <b>Sea</b> view wow <u><b>foo</b> bar</u> <i>qq</i> +
<a href="http://www.google.com/foo.bar.html" target="_blank">YES &nbsp;</a> <a href="http://www.google.com/foo.bar.html" target="_blank">YES &nbsp;</a>+
ff-bg ff-bg +
<script> <script> +
document.write(15); document.write(15); +
</script> </script> +
</body> </body> +
</html> </html>
(1 row) (1 row)
@ -646,13 +646,13 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'ocean'), 'MaxFragments=1'); ', to_tsquery('english', 'ocean'), 'MaxFragments=1');
ts_headline ts_headline
------------------------------------ ------------------------------------
after day, after day, +
We stuck, nor breath nor motion, We stuck, nor breath nor motion,+
As idle as a painted Ship As idle as a painted Ship +
Upon a painted <b>Ocean</b>. Upon a painted <b>Ocean</b>. +
Water, water, every where Water, water, every where +
And all the boards did shrink; And all the boards did shrink; +
Water, water, every where, Water, water, every where, +
Nor any drop Nor any drop
(1 row) (1 row)
@ -670,13 +670,13 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'Coleridge & stuck'), 'MaxFragments=2'); ', to_tsquery('english', 'Coleridge & stuck'), 'MaxFragments=2');
ts_headline ts_headline
---------------------------------------------- ----------------------------------------------
after day, day after day, after day, day after day, +
We <b>stuck</b>, nor breath nor motion, We <b>stuck</b>, nor breath nor motion, +
As idle as a painted Ship As idle as a painted Ship +
Upon a painted Ocean. Upon a painted Ocean. +
Water, water, every where Water, water, every where +
And all the boards did shrink; And all the boards did shrink; +
Water, water, every where ... drop to drink. Water, water, every where ... drop to drink.+
S. T. <b>Coleridge</b> S. T. <b>Coleridge</b>
(1 row) (1 row)
@ -694,9 +694,9 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'ocean & seahorse'), 'MaxFragments=1'); ', to_tsquery('english', 'ocean & seahorse'), 'MaxFragments=1');
ts_headline ts_headline
------------------------------------ ------------------------------------
+
Day after day, day after day, Day after day, day after day, +
We stuck, nor breath nor motion, We stuck, nor breath nor motion,+
As idle as As idle as
(1 row) (1 row)
@ -714,13 +714,13 @@ S. T. Coleridge (1772-1834)
', to_tsquery('english', 'Coleridge & stuck'), 'MaxFragments=2,FragmentDelimiter=***'); ', to_tsquery('english', 'Coleridge & stuck'), 'MaxFragments=2,FragmentDelimiter=***');
ts_headline ts_headline
-------------------------------------------- --------------------------------------------
after day, day after day, after day, day after day, +
We <b>stuck</b>, nor breath nor motion, We <b>stuck</b>, nor breath nor motion, +
As idle as a painted Ship As idle as a painted Ship +
Upon a painted Ocean. Upon a painted Ocean. +
Water, water, every where Water, water, every where +
And all the boards did shrink; And all the boards did shrink; +
Water, water, every where***drop to drink. Water, water, every where***drop to drink.+
S. T. <b>Coleridge</b> S. T. <b>Coleridge</b>
(1 row) (1 row)

View File

@ -279,16 +279,16 @@ SELECT pg_get_viewdef('vsubdepartment'::regclass);
SELECT pg_get_viewdef('vsubdepartment'::regclass, true); SELECT pg_get_viewdef('vsubdepartment'::regclass, true);
pg_get_viewdef pg_get_viewdef
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------
WITH RECURSIVE subdepartment AS ( WITH RECURSIVE subdepartment AS ( +
SELECT department.id, department.parent_department, department.name SELECT department.id, department.parent_department, department.name+
FROM department FROM department +
WHERE department.name = 'A'::text WHERE department.name = 'A'::text +
UNION ALL UNION ALL +
SELECT d.id, d.parent_department, d.name SELECT d.id, d.parent_department, d.name +
FROM department d, subdepartment sd FROM department d, subdepartment sd +
WHERE d.parent_department = sd.id WHERE d.parent_department = sd.id +
) ) +
SELECT subdepartment.id, subdepartment.parent_department, subdepartment.name SELECT subdepartment.id, subdepartment.parent_department, subdepartment.name +
FROM subdepartment; FROM subdepartment;
(1 row) (1 row)