mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Add "\pset linestyle ascii/unicode" option to psql, allowing our traditional
ASCII-art style of table output to be upgraded to use Unicode box drawing characters if desired. By default, psql will use the Unicode characters whenever client_encoding is UTF8. The patch forces linestyle=ascii in pg_regress usage, ensuring we don't break the regression tests in Unicode locales. Roger Leigh
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.231 2009/10/08 16:34:00 alvherre Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.232 2009/10/13 21:04:01 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -1760,6 +1760,39 @@ lo_import 152801
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>linestyle</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets the border line drawing style to one
|
||||||
|
of <literal>ascii</literal> or <literal>unicode</literal>.
|
||||||
|
Unique abbreviations are allowed. (That would mean one
|
||||||
|
letter is enough.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<quote>ASCII</quote> uses plain <acronym>ASCII</acronym> characters.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<quote>Unicode</quote> uses Unicode box-drawing characters.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When the selected output format is one that draws lines or boxes
|
||||||
|
around the data, this setting controls how the lines are drawn.
|
||||||
|
Plain <acronym>ASCII</acronym> characters work everywhere, but
|
||||||
|
Unicode characters look nicer on displays that recognize them.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If this option has not been set, the default behavior is to
|
||||||
|
use Unicode characters if the client character set encoding
|
||||||
|
is UTF-8, otherwise <acronym>ASCII</acronym> characters.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>expanded</literal> (or <literal>x</literal>)</term>
|
<term><literal>expanded</literal> (or <literal>x</literal>)</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -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.209 2009/10/07 22:14:24 alvherre Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.210 2009/10/13 21:04:01 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -1788,6 +1788,26 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
|
|||||||
printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
|
printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set table line style */
|
||||||
|
else if (strcmp(param, "linestyle") == 0)
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
;
|
||||||
|
else if (pg_strncasecmp("ascii", value, vallen) == 0)
|
||||||
|
popt->topt.line_style = &pg_asciiformat;
|
||||||
|
else if (pg_strncasecmp("unicode", value, vallen) == 0)
|
||||||
|
popt->topt.line_style = &pg_utf8format;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psql_error("\\pset: allowed line styles are ascii, unicode\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("Line style is %s.\n"),
|
||||||
|
get_line_style(&popt->topt)->name);
|
||||||
|
}
|
||||||
|
|
||||||
/* set border style/width */
|
/* set border style/width */
|
||||||
else if (strcmp(param, "border") == 0)
|
else if (strcmp(param, "border") == 0)
|
||||||
{
|
{
|
||||||
|
@ -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/mbprint.c,v 1.35 2009/06/11 14:49:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/mbprint.c,v 1.36 2009/10/13 21:04:01 tgl Exp $
|
||||||
*
|
*
|
||||||
* XXX this file does not really belong in psql/. Perhaps move to libpq?
|
* XXX this file does not really belong in psql/. Perhaps move to libpq?
|
||||||
* It also seems that the mbvalidate function is redundant with existing
|
* It also seems that the mbvalidate function is redundant with existing
|
||||||
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
typedef unsigned int pg_wchar;
|
typedef unsigned int pg_wchar;
|
||||||
|
|
||||||
static int
|
int
|
||||||
get_utf8_id(void)
|
pg_get_utf8_id(void)
|
||||||
{
|
{
|
||||||
static int utf8_id = -1;
|
static int utf8_id = -1;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ get_utf8_id(void)
|
|||||||
return utf8_id;
|
return utf8_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PG_UTF8 get_utf8_id()
|
#define PG_UTF8 pg_get_utf8_id()
|
||||||
|
|
||||||
|
|
||||||
static pg_wchar
|
static pg_wchar
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $PostgreSQL: pgsql/src/bin/psql/mbprint.h,v 1.13 2009/06/11 14:49:08 momjian Exp $ */
|
/* $PostgreSQL: pgsql/src/bin/psql/mbprint.h,v 1.14 2009/10/13 21:04:01 tgl Exp $ */
|
||||||
#ifndef MBPRINT_H
|
#ifndef MBPRINT_H
|
||||||
#define MBPRINT_H
|
#define MBPRINT_H
|
||||||
|
|
||||||
@ -9,8 +9,8 @@ struct lineptr
|
|||||||
int width;
|
int width;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int pg_get_utf8_id(void);
|
||||||
extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding);
|
extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding);
|
||||||
|
|
||||||
extern int pg_wcswidth(const unsigned char *pwcs, size_t len, int encoding);
|
extern int pg_wcswidth(const unsigned char *pwcs, size_t len, int encoding);
|
||||||
extern void pg_wcsformat(unsigned char *pwcs, size_t len, int encoding, struct lineptr * lines, int count);
|
extern void pg_wcsformat(unsigned char *pwcs, size_t len, int encoding, struct lineptr * lines, int count);
|
||||||
extern void pg_wcssize(unsigned char *pwcs, size_t len, int encoding,
|
extern void pg_wcssize(unsigned char *pwcs, size_t len, int encoding,
|
||||||
|
@ -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.116 2009/06/12 16:17:29 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.117 2009/10/13 21:04:01 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -44,6 +44,43 @@ static char *decimal_point;
|
|||||||
static char *grouping;
|
static char *grouping;
|
||||||
static char *thousands_sep;
|
static char *thousands_sep;
|
||||||
|
|
||||||
|
/* Line style control structures */
|
||||||
|
const printTextFormat pg_asciiformat =
|
||||||
|
{
|
||||||
|
"ascii",
|
||||||
|
{
|
||||||
|
{ "-", "+", "+", "+" },
|
||||||
|
{ "-", "+", "+", "+" },
|
||||||
|
{ "-", "+", "+", "+" },
|
||||||
|
{ "", "|", "|", "|" }
|
||||||
|
},
|
||||||
|
":",
|
||||||
|
";",
|
||||||
|
" "
|
||||||
|
};
|
||||||
|
|
||||||
|
const printTextFormat pg_utf8format =
|
||||||
|
{
|
||||||
|
"unicode",
|
||||||
|
{
|
||||||
|
/* ─, ┌, ┬, ┐ */
|
||||||
|
{ "\342\224\200", "\342\224\214", "\342\224\254", "\342\224\220" },
|
||||||
|
/* ─, ├, ┼, ┤ */
|
||||||
|
{ "\342\224\200", "\342\224\234", "\342\224\274", "\342\224\244" },
|
||||||
|
/* ─, └, ┴, ┘ */
|
||||||
|
{ "\342\224\200", "\342\224\224", "\342\224\264", "\342\224\230" },
|
||||||
|
/* N/A, │, │, │ */
|
||||||
|
{ "", "\342\224\202", "\342\224\202", "\342\224\202" }
|
||||||
|
},
|
||||||
|
/* ╎ */
|
||||||
|
"\342\225\216",
|
||||||
|
/* ┊ */
|
||||||
|
"\342\224\212",
|
||||||
|
/* ╷ */
|
||||||
|
"\342\225\267"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Local functions */
|
/* Local functions */
|
||||||
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
|
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
|
||||||
static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
|
static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
|
||||||
@ -116,7 +153,10 @@ strlen_with_numeric_locale(const char *my_str)
|
|||||||
return strlen(my_str) + additional_numeric_locale_len(my_str);
|
return strlen(my_str) + additional_numeric_locale_len(my_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the appropriately formatted string in a new allocated block, caller must free */
|
/*
|
||||||
|
* Returns the appropriately formatted string in a new allocated block,
|
||||||
|
* caller must free
|
||||||
|
*/
|
||||||
static char *
|
static char *
|
||||||
format_numeric_locale(const char *my_str)
|
format_numeric_locale(const char *my_str)
|
||||||
{
|
{
|
||||||
@ -172,6 +212,7 @@ format_numeric_locale(const char *my_str)
|
|||||||
return new_str;
|
return new_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
/* Unaligned text */
|
/* Unaligned text */
|
||||||
/*************************/
|
/*************************/
|
||||||
@ -360,34 +401,38 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
/* draw "line" */
|
/* draw "line" */
|
||||||
static void
|
static void
|
||||||
_print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
|
_print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
|
||||||
unsigned short border, FILE *fout)
|
unsigned short border, printTextRule pos,
|
||||||
|
const printTextFormat *format,
|
||||||
|
FILE *fout)
|
||||||
{
|
{
|
||||||
|
const printTextLineFormat *lformat = &format->lrule[pos];
|
||||||
unsigned int i,
|
unsigned int i,
|
||||||
j;
|
j;
|
||||||
|
|
||||||
if (border == 1)
|
if (border == 1)
|
||||||
fputc('-', fout);
|
fputs(lformat->hrule, fout);
|
||||||
else if (border == 2)
|
else if (border == 2)
|
||||||
fputs("+-", fout);
|
fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
|
||||||
|
|
||||||
for (i = 0; i < ncolumns; i++)
|
for (i = 0; i < ncolumns; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < widths[i]; j++)
|
for (j = 0; j < widths[i]; j++)
|
||||||
fputc('-', fout);
|
fputs(lformat->hrule, fout);
|
||||||
|
|
||||||
if (i < ncolumns - 1)
|
if (i < ncolumns - 1)
|
||||||
{
|
{
|
||||||
if (border == 0)
|
if (border == 0)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
else
|
else
|
||||||
fputs("-+-", fout);
|
fprintf(fout, "%s%s%s", lformat->hrule,
|
||||||
|
lformat->midvrule, lformat->hrule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (border == 2)
|
if (border == 2)
|
||||||
fputs("-+", fout);
|
fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
|
||||||
else if (border == 1)
|
else if (border == 1)
|
||||||
fputc('-', fout);
|
fputs(lformat->hrule, fout);
|
||||||
|
|
||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
}
|
}
|
||||||
@ -403,6 +448,8 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
bool opt_numeric_locale = cont->opt->numericLocale;
|
bool opt_numeric_locale = cont->opt->numericLocale;
|
||||||
int encoding = cont->opt->encoding;
|
int encoding = cont->opt->encoding;
|
||||||
unsigned short opt_border = cont->opt->border;
|
unsigned short opt_border = cont->opt->border;
|
||||||
|
const printTextFormat *format = get_line_style(cont->opt);
|
||||||
|
const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA];
|
||||||
|
|
||||||
unsigned int col_count = 0,
|
unsigned int col_count = 0,
|
||||||
cell_count = 0;
|
cell_count = 0;
|
||||||
@ -709,7 +756,8 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
int curr_nl_line;
|
int curr_nl_line;
|
||||||
|
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
_print_horizontal_line(col_count, width_wrap, opt_border, fout);
|
_print_horizontal_line(col_count, width_wrap, opt_border,
|
||||||
|
PRINT_RULE_TOP, format, fout);
|
||||||
|
|
||||||
for (i = 0; i < col_count; i++)
|
for (i = 0; i < col_count; i++)
|
||||||
pg_wcsformat((unsigned char *) cont->headers[i],
|
pg_wcsformat((unsigned char *) cont->headers[i],
|
||||||
@ -722,15 +770,15 @@ 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, "|%c", curr_nl_line ? '+' : ' ');
|
fprintf(fout, "%s%c", dformat->leftvrule,
|
||||||
|
curr_nl_line ? '+' : ' ');
|
||||||
else if (opt_border == 1)
|
else if (opt_border == 1)
|
||||||
fputc(curr_nl_line ? '+' : ' ', fout);
|
fputc(curr_nl_line ? '+' : ' ', fout);
|
||||||
|
|
||||||
for (i = 0; i < cont->ncolumns; i++)
|
for (i = 0; i < cont->ncolumns; i++)
|
||||||
{
|
{
|
||||||
unsigned int nbspace;
|
|
||||||
|
|
||||||
struct lineptr *this_line = col_lineptrs[i] + curr_nl_line;
|
struct lineptr *this_line = col_lineptrs[i] + curr_nl_line;
|
||||||
|
unsigned int nbspace;
|
||||||
|
|
||||||
if (!header_done[i])
|
if (!header_done[i])
|
||||||
{
|
{
|
||||||
@ -753,19 +801,21 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
if (opt_border == 0)
|
if (opt_border == 0)
|
||||||
fputc(curr_nl_line ? '+' : ' ', fout);
|
fputc(curr_nl_line ? '+' : ' ', fout);
|
||||||
else
|
else
|
||||||
fprintf(fout, " |%c", curr_nl_line ? '+' : ' ');
|
fprintf(fout, " %s%c", dformat->midvrule,
|
||||||
|
curr_nl_line ? '+' : ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
curr_nl_line++;
|
curr_nl_line++;
|
||||||
|
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs(" |", fout);
|
fprintf(fout, " %s", dformat->rightvrule);
|
||||||
else if (opt_border == 1)
|
else if (opt_border == 1)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
}
|
}
|
||||||
|
|
||||||
_print_horizontal_line(col_count, width_wrap, opt_border, fout);
|
_print_horizontal_line(col_count, width_wrap, opt_border,
|
||||||
|
PRINT_RULE_MIDDLE, format, fout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +861,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
|
|
||||||
/* left border */
|
/* left border */
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs("| ", fout);
|
fprintf(fout, "%s ", dformat->leftvrule);
|
||||||
else if (opt_border == 1)
|
else if (opt_border == 1)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
|
|
||||||
@ -884,22 +934,22 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
/* Next value is beyond past newlines? */
|
/* Next value is beyond past newlines? */
|
||||||
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)
|
||||||
fputs(" ", fout);
|
fprintf(fout, " %s ", format->midvrule_blank);
|
||||||
/* In wrapping of value? */
|
/* In wrapping of value? */
|
||||||
else if (bytes_output[j + 1] != 0)
|
else if (bytes_output[j + 1] != 0)
|
||||||
fputs(" ; ", fout);
|
fprintf(fout, " %s ", format->midvrule_wrap);
|
||||||
/* After first newline value */
|
/* After first newline value */
|
||||||
else if (curr_nl_line[j + 1] != 0)
|
else if (curr_nl_line[j + 1] != 0)
|
||||||
fputs(" : ", fout);
|
fprintf(fout, " %s ", format->midvrule_cont);
|
||||||
|
/* Ordinary line */
|
||||||
else
|
else
|
||||||
/* Ordinary line */
|
fprintf(fout, " %s ", dformat->midvrule);
|
||||||
fputs(" | ", fout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end-of-row border */
|
/* end-of-row border */
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs(" |", fout);
|
fprintf(fout, " %s", dformat->rightvrule);
|
||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
|
|
||||||
} while (more_lines);
|
} while (more_lines);
|
||||||
@ -908,7 +958,8 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
if (cont->opt->stop_table)
|
if (cont->opt->stop_table)
|
||||||
{
|
{
|
||||||
if (opt_border == 2 && !cancel_pressed)
|
if (opt_border == 2 && !cancel_pressed)
|
||||||
_print_horizontal_line(col_count, width_wrap, opt_border, fout);
|
_print_horizontal_line(col_count, width_wrap, opt_border,
|
||||||
|
PRINT_RULE_BOTTOM, format, fout);
|
||||||
|
|
||||||
/* print footers */
|
/* print footers */
|
||||||
if (cont->footers && !opt_tuples_only && !cancel_pressed)
|
if (cont->footers && !opt_tuples_only && !cancel_pressed)
|
||||||
@ -942,12 +993,71 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_aligned_vertical_line(const printTableContent *cont,
|
||||||
|
unsigned long record,
|
||||||
|
unsigned int hwidth,
|
||||||
|
unsigned int dwidth,
|
||||||
|
printTextRule pos,
|
||||||
|
FILE *fout)
|
||||||
|
{
|
||||||
|
const printTextFormat *format = get_line_style(cont->opt);
|
||||||
|
const printTextLineFormat *lformat = &format->lrule[pos];
|
||||||
|
unsigned short opt_border = cont->opt->border;
|
||||||
|
unsigned int i;
|
||||||
|
int reclen = 0;
|
||||||
|
|
||||||
|
if (opt_border == 2)
|
||||||
|
fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
|
||||||
|
else if (opt_border == 1)
|
||||||
|
fputs(lformat->hrule, fout);
|
||||||
|
|
||||||
|
if (record)
|
||||||
|
{
|
||||||
|
if (opt_border == 0)
|
||||||
|
reclen = fprintf(fout, "* Record %lu", record);
|
||||||
|
else
|
||||||
|
reclen = fprintf(fout, "[ RECORD %lu ]", record);
|
||||||
|
}
|
||||||
|
if (opt_border != 2)
|
||||||
|
reclen++;
|
||||||
|
if (reclen < 0)
|
||||||
|
reclen = 0;
|
||||||
|
for (i = reclen; i < hwidth; i++)
|
||||||
|
fputs(opt_border > 0 ? lformat->hrule : " ", fout);
|
||||||
|
reclen -= hwidth;
|
||||||
|
|
||||||
|
if (opt_border > 0)
|
||||||
|
{
|
||||||
|
if (reclen-- <= 0)
|
||||||
|
fputs(lformat->hrule, fout);
|
||||||
|
if (reclen-- <= 0)
|
||||||
|
fputs(lformat->midvrule, fout);
|
||||||
|
if (reclen-- <= 0)
|
||||||
|
fputs(lformat->hrule, fout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (reclen-- <= 0)
|
||||||
|
fputc(' ', fout);
|
||||||
|
}
|
||||||
|
if (reclen < 0)
|
||||||
|
reclen = 0;
|
||||||
|
for (i = reclen; i < dwidth; i++)
|
||||||
|
fputs(opt_border > 0 ? lformat->hrule : " ", fout);
|
||||||
|
if (opt_border == 2)
|
||||||
|
fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
|
||||||
|
fputc('\n', fout);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
||||||
{
|
{
|
||||||
bool opt_tuples_only = cont->opt->tuples_only;
|
bool opt_tuples_only = cont->opt->tuples_only;
|
||||||
bool opt_numeric_locale = cont->opt->numericLocale;
|
bool opt_numeric_locale = cont->opt->numericLocale;
|
||||||
unsigned short opt_border = cont->opt->border;
|
unsigned short opt_border = cont->opt->border;
|
||||||
|
const printTextFormat *format = get_line_style(cont->opt);
|
||||||
|
const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA];
|
||||||
int encoding = cont->opt->encoding;
|
int encoding = cont->opt->encoding;
|
||||||
unsigned long record = cont->opt->prior_records + 1;
|
unsigned long record = cont->opt->prior_records + 1;
|
||||||
const char *const * ptr;
|
const char *const * ptr;
|
||||||
@ -958,7 +1068,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
dheight = 1,
|
dheight = 1,
|
||||||
hformatsize = 0,
|
hformatsize = 0,
|
||||||
dformatsize = 0;
|
dformatsize = 0;
|
||||||
char *divider;
|
|
||||||
struct lineptr *hlineptr,
|
struct lineptr *hlineptr,
|
||||||
*dlineptr;
|
*dlineptr;
|
||||||
|
|
||||||
@ -1026,22 +1135,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
dlineptr->ptr = pg_local_malloc(dformatsize);
|
dlineptr->ptr = pg_local_malloc(dformatsize);
|
||||||
hlineptr->ptr = pg_local_malloc(hformatsize);
|
hlineptr->ptr = pg_local_malloc(hformatsize);
|
||||||
|
|
||||||
/* make horizontal border */
|
|
||||||
divider = pg_local_malloc(hwidth + dwidth + 10);
|
|
||||||
divider[0] = '\0';
|
|
||||||
if (opt_border == 2)
|
|
||||||
strcat(divider, "+-");
|
|
||||||
for (i = 0; i < hwidth; i++)
|
|
||||||
strcat(divider, opt_border > 0 ? "-" : " ");
|
|
||||||
if (opt_border > 0)
|
|
||||||
strcat(divider, "-+-");
|
|
||||||
else
|
|
||||||
strcat(divider, " ");
|
|
||||||
for (i = 0; i < dwidth; i++)
|
|
||||||
strcat(divider, opt_border > 0 ? "-" : " ");
|
|
||||||
if (opt_border == 2)
|
|
||||||
strcat(divider, "-+");
|
|
||||||
|
|
||||||
if (cont->opt->start_table)
|
if (cont->opt->start_table)
|
||||||
{
|
{
|
||||||
/* print title */
|
/* print title */
|
||||||
@ -1052,38 +1145,29 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
/* print records */
|
/* print records */
|
||||||
for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
|
for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
|
||||||
{
|
{
|
||||||
|
printTextRule pos;
|
||||||
int line_count,
|
int line_count,
|
||||||
dcomplete,
|
dcomplete,
|
||||||
hcomplete;
|
hcomplete;
|
||||||
|
|
||||||
|
if (cancel_pressed)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
pos = PRINT_RULE_TOP;
|
||||||
|
else if (!(*(ptr+1)))
|
||||||
|
pos = PRINT_RULE_BOTTOM;
|
||||||
|
else
|
||||||
|
pos = PRINT_RULE_MIDDLE;
|
||||||
|
|
||||||
if (i % cont->ncolumns == 0)
|
if (i % cont->ncolumns == 0)
|
||||||
{
|
{
|
||||||
if (cancel_pressed)
|
|
||||||
break;
|
|
||||||
if (!opt_tuples_only)
|
if (!opt_tuples_only)
|
||||||
{
|
print_aligned_vertical_line(cont, record++, hwidth, dwidth,
|
||||||
char record_str[64];
|
pos, fout);
|
||||||
size_t record_str_len;
|
|
||||||
|
|
||||||
if (opt_border == 0)
|
|
||||||
snprintf(record_str, 64, "* Record %lu", record++);
|
|
||||||
else
|
|
||||||
snprintf(record_str, 64, "[ RECORD %lu ]", record++);
|
|
||||||
record_str_len = strlen(record_str);
|
|
||||||
|
|
||||||
if (record_str_len + opt_border > strlen(divider))
|
|
||||||
fprintf(fout, "%.*s%s\n", opt_border, divider, record_str);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *div_copy = pg_strdup(divider);
|
|
||||||
|
|
||||||
strncpy(div_copy + opt_border, record_str, record_str_len);
|
|
||||||
fprintf(fout, "%s\n", div_copy);
|
|
||||||
free(div_copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (i != 0 || !cont->opt->start_table || opt_border == 2)
|
else if (i != 0 || !cont->opt->start_table || opt_border == 2)
|
||||||
fprintf(fout, "%s\n", divider);
|
print_aligned_vertical_line(cont, 0, hwidth, dwidth,
|
||||||
|
pos, fout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Format the header */
|
/* Format the header */
|
||||||
@ -1099,7 +1183,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
while (!dcomplete || !hcomplete)
|
while (!dcomplete || !hcomplete)
|
||||||
{
|
{
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs("| ", fout);
|
fprintf(fout, "%s ", dformat->leftvrule);
|
||||||
if (!hcomplete)
|
if (!hcomplete)
|
||||||
{
|
{
|
||||||
fprintf(fout, "%-s%*s", hlineptr[line_count].ptr,
|
fprintf(fout, "%-s%*s", hlineptr[line_count].ptr,
|
||||||
@ -1112,9 +1196,11 @@ 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, " %c ", (line_count == 0) ? '|' : ':');
|
fprintf(fout, " %s ",
|
||||||
|
(line_count == 0) ?
|
||||||
|
format->midvrule_cont : dformat->midvrule);
|
||||||
else
|
else
|
||||||
fputs(" ", fout);
|
fputc(' ', fout);
|
||||||
|
|
||||||
if (!dcomplete)
|
if (!dcomplete)
|
||||||
{
|
{
|
||||||
@ -1125,8 +1211,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
if (opt_border < 2)
|
if (opt_border < 2)
|
||||||
fprintf(fout, "%s\n", my_cell);
|
fprintf(fout, "%s\n", my_cell);
|
||||||
else
|
else
|
||||||
fprintf(fout, "%-s%*s |\n", my_cell,
|
fprintf(fout, "%-s%*s %s\n", my_cell,
|
||||||
(int) (dwidth - strlen(my_cell)), "");
|
(int) (dwidth - strlen(my_cell)), "",
|
||||||
|
dformat->rightvrule);
|
||||||
free(my_cell);
|
free(my_cell);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1134,8 +1221,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
if (opt_border < 2)
|
if (opt_border < 2)
|
||||||
fprintf(fout, "%s\n", dlineptr[line_count].ptr);
|
fprintf(fout, "%s\n", dlineptr[line_count].ptr);
|
||||||
else
|
else
|
||||||
fprintf(fout, "%-s%*s |\n", dlineptr[line_count].ptr,
|
fprintf(fout, "%-s%*s %s\n", dlineptr[line_count].ptr,
|
||||||
dwidth - dlineptr[line_count].width, "");
|
dwidth - dlineptr[line_count].width, "",
|
||||||
|
dformat->rightvrule);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dlineptr[line_count + 1].ptr)
|
if (!dlineptr[line_count + 1].ptr)
|
||||||
@ -1146,7 +1234,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
if (opt_border < 2)
|
if (opt_border < 2)
|
||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
else
|
else
|
||||||
fprintf(fout, "%*s |\n", dwidth, "");
|
fprintf(fout, "%*s %s\n", dwidth, "", dformat->rightvrule);
|
||||||
}
|
}
|
||||||
line_count++;
|
line_count++;
|
||||||
}
|
}
|
||||||
@ -1155,7 +1243,8 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
if (cont->opt->stop_table)
|
if (cont->opt->stop_table)
|
||||||
{
|
{
|
||||||
if (opt_border == 2 && !cancel_pressed)
|
if (opt_border == 2 && !cancel_pressed)
|
||||||
fprintf(fout, "%s\n", divider);
|
print_aligned_vertical_line(cont, 0, hwidth, dwidth,
|
||||||
|
PRINT_RULE_BOTTOM, fout);
|
||||||
|
|
||||||
/* print footers */
|
/* print footers */
|
||||||
if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
|
if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
|
||||||
@ -1171,7 +1260,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
|||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(divider);
|
|
||||||
free(hlineptr->ptr);
|
free(hlineptr->ptr);
|
||||||
free(dlineptr->ptr);
|
free(dlineptr->ptr);
|
||||||
free(hlineptr);
|
free(hlineptr);
|
||||||
@ -2387,6 +2475,18 @@ setDecimalLocale(void)
|
|||||||
thousands_sep = ".";
|
thousands_sep = ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get selected or default line style */
|
||||||
|
const printTextFormat *
|
||||||
|
get_line_style(const printTableOpt *opt)
|
||||||
|
{
|
||||||
|
if (opt->line_style != NULL)
|
||||||
|
return opt->line_style;
|
||||||
|
else if (opt->encoding == pg_get_utf8_id())
|
||||||
|
return &pg_utf8format;
|
||||||
|
else
|
||||||
|
return &pg_asciiformat;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the byte distance to the end of the string or *target_width
|
* Compute the byte distance to the end of the string or *target_width
|
||||||
* display character positions, whichever comes first. Update *target_width
|
* display character positions, whichever comes first. Update *target_width
|
||||||
|
@ -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.40 2009/06/11 14:49:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.41 2009/10/13 21:04:01 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef PRINT_H
|
#ifndef PRINT_H
|
||||||
#define PRINT_H
|
#define PRINT_H
|
||||||
@ -23,10 +23,37 @@ enum printFormat
|
|||||||
/* add your favourite output format here ... */
|
/* add your favourite output format here ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct printTextLineFormat
|
||||||
|
{
|
||||||
|
/* Line drawing characters to be used in various contexts */
|
||||||
|
const char *hrule; /* horizontal line character */
|
||||||
|
const char *leftvrule; /* left vertical line (+horizontal) */
|
||||||
|
const char *midvrule; /* intra-column vertical line (+horizontal) */
|
||||||
|
const char *rightvrule; /* right vertical line (+horizontal) */
|
||||||
|
} printTextLineFormat;
|
||||||
|
|
||||||
|
typedef enum printTextRule
|
||||||
|
{
|
||||||
|
/* Additional context for selecting line drawing characters */
|
||||||
|
PRINT_RULE_TOP, /* top horizontal line */
|
||||||
|
PRINT_RULE_MIDDLE, /* intra-data horizontal line */
|
||||||
|
PRINT_RULE_BOTTOM, /* bottom horizontal line */
|
||||||
|
PRINT_RULE_DATA /* data line (hrule is unused here) */
|
||||||
|
} printTextRule;
|
||||||
|
|
||||||
|
typedef struct printTextFormat
|
||||||
|
{
|
||||||
|
/* A complete line style */
|
||||||
|
const char *name; /* for display purposes */
|
||||||
|
printTextLineFormat lrule[4]; /* indexed by enum printTextRule */
|
||||||
|
const char *midvrule_cont; /* vertical line for continue after newline */
|
||||||
|
const char *midvrule_wrap; /* vertical line for wrapped data */
|
||||||
|
const char *midvrule_blank; /* vertical line for blank data */
|
||||||
|
} printTextFormat;
|
||||||
|
|
||||||
typedef struct printTableOpt
|
typedef struct printTableOpt
|
||||||
{
|
{
|
||||||
enum printFormat format; /* one of the above */
|
enum printFormat format; /* see enum above */
|
||||||
bool expanded; /* expanded/vertical output (if supported by
|
bool expanded; /* expanded/vertical output (if supported by
|
||||||
* output format) */
|
* output format) */
|
||||||
unsigned short int border; /* Print a border around the table. 0=none,
|
unsigned short int border; /* Print a border around the table. 0=none,
|
||||||
@ -37,6 +64,7 @@ typedef struct printTableOpt
|
|||||||
bool start_table; /* print start decoration, eg <table> */
|
bool start_table; /* print start decoration, eg <table> */
|
||||||
bool stop_table; /* print stop decoration, eg </table> */
|
bool stop_table; /* print stop decoration, eg </table> */
|
||||||
unsigned long prior_records; /* start offset for record counters */
|
unsigned long prior_records; /* start offset for record counters */
|
||||||
|
const printTextFormat *line_style; /* line style (NULL for default) */
|
||||||
char *fieldSep; /* field separator for unaligned text mode */
|
char *fieldSep; /* field separator for unaligned text mode */
|
||||||
char *recordSep; /* record separator for unaligned text mode */
|
char *recordSep; /* record separator for unaligned text mode */
|
||||||
bool numericLocale; /* locale-aware numeric units separator and
|
bool numericLocale; /* locale-aware numeric units separator and
|
||||||
@ -96,6 +124,10 @@ typedef struct printQueryOpt
|
|||||||
} printQueryOpt;
|
} printQueryOpt;
|
||||||
|
|
||||||
|
|
||||||
|
extern const printTextFormat pg_asciiformat;
|
||||||
|
extern const printTextFormat pg_utf8format;
|
||||||
|
|
||||||
|
|
||||||
extern FILE *PageOutput(int lines, unsigned short int pager);
|
extern FILE *PageOutput(int lines, unsigned short int pager);
|
||||||
extern void ClosePager(FILE *pagerpipe);
|
extern void ClosePager(FILE *pagerpipe);
|
||||||
|
|
||||||
@ -118,6 +150,7 @@ extern void printQuery(const PGresult *result, const printQueryOpt *opt,
|
|||||||
FILE *fout, FILE *flog);
|
FILE *fout, FILE *flog);
|
||||||
|
|
||||||
extern void setDecimalLocale(void);
|
extern void setDecimalLocale(void);
|
||||||
|
extern const printTextFormat *get_line_style(const printTableOpt *opt);
|
||||||
|
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
#define DEFAULT_PAGER "more"
|
#define DEFAULT_PAGER "more"
|
||||||
|
@ -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/tab-complete.c,v 1.186 2009/10/08 16:34:01 alvherre Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.187 2009/10/13 21:04:01 tgl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
@ -2264,8 +2264,8 @@ psql_completion(char *text, int start, int end)
|
|||||||
{
|
{
|
||||||
static const char *const my_list[] =
|
static const char *const my_list[] =
|
||||||
{"format", "border", "expanded",
|
{"format", "border", "expanded",
|
||||||
"null", "fieldsep", "tuples_only", "title", "tableattr", "pager",
|
"null", "fieldsep", "tuples_only", "title", "tableattr",
|
||||||
"recordsep", NULL};
|
"linestyle", "pager", "recordsep", NULL};
|
||||||
|
|
||||||
COMPLETE_WITH_LIST(my_list);
|
COMPLETE_WITH_LIST(my_list);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/test/regress/pg_regress_main.c,v 1.6 2009/06/11 14:49:15 momjian Exp $
|
* $PostgreSQL: pgsql/src/test/regress/pg_regress_main.c,v 1.7 2009/10/13 21:04:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -59,7 +59,7 @@ psql_start_test(const char *testname,
|
|||||||
add_stringlist_item(expectfiles, expectfile);
|
add_stringlist_item(expectfiles, expectfile);
|
||||||
|
|
||||||
snprintf(psql_cmd, sizeof(psql_cmd),
|
snprintf(psql_cmd, sizeof(psql_cmd),
|
||||||
SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
|
SYSTEMQUOTE "\"%s%spsql\" -X -a -q -P linestyle=ascii -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
|
||||||
psqldir ? psqldir : "",
|
psqldir ? psqldir : "",
|
||||||
psqldir ? "/" : "",
|
psqldir ? "/" : "",
|
||||||
dblist->str,
|
dblist->str,
|
||||||
|
Reference in New Issue
Block a user