diff -ru a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
--- a/doc/src/sgml/ref/psql-ref.sgml 2017-02-06 22:45:25.000000000 +0100
+++ b/doc/src/sgml/ref/psql-ref.sgml 2017-03-06 01:35:46.000000000 +0100
@@ -2326,7 +2326,8 @@
aligned, wrapped,
html, asciidoc,
latex (uses tabular),
- latex-longtable, or
+ latex-longtable,
+ rst, markdown, or
troff-ms.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
@@ -2354,7 +2355,8 @@
The html>, asciidoc>, latex>,
- latex-longtable, and troff-ms>
+ latex-longtable, troff-ms>,
+ and markdown> and rst>
formats put out tables that are intended to
be included in documents using the respective mark-up
language. They are not complete documents! This might not be
diff -ru a/src/bin/psql/command.c b/src/bin/psql/command.c
--- a/src/bin/psql/command.c 2017-02-06 22:45:25.000000000 +0100
+++ b/src/bin/psql/command.c 2017-03-06 03:27:07.000000000 +0100
@@ -2494,6 +2494,12 @@
case PRINT_TROFF_MS:
return "troff-ms";
break;
+ case PRINT_MARKDOWN:
+ return "markdown";
+ break;
+ case PRINT_RST:
+ return "rst";
+ break;
}
return "unknown";
}
@@ -2565,9 +2571,13 @@
popt->topt.format = PRINT_LATEX_LONGTABLE;
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
popt->topt.format = PRINT_TROFF_MS;
+ else if (pg_strncasecmp("markdown", value, vallen) == 0) /*markdown*/
+ popt->topt.format = PRINT_MARKDOWN;
+ else if (pg_strncasecmp("rst", value, vallen) == 0) /*rst*/
+ popt->topt.format = PRINT_RST;
else
{
- psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms\n");
+ psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms, markdown, rst\n");
return false;
}
diff -ru a/src/bin/psql/help.c b/src/bin/psql/help.c
--- a/src/bin/psql/help.c 2017-02-06 22:45:25.000000000 +0100
+++ b/src/bin/psql/help.c 2017-03-06 01:46:41.000000000 +0100
@@ -373,7 +373,7 @@
fprintf(output, _(" fieldsep field separator for unaligned output (default \"%s\")\n"), DEFAULT_FIELD_SEP);
fprintf(output, _(" fieldsep_zero set field separator for unaligned output to zero byte\n"));
fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n"));
- fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n"));
+ fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, asciidoc, rst, markdown ...]\n"));
fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n"));
fprintf(output, _(" null set the string to be printed in place of a null value\n"));
fprintf(output, _(" numericlocale enable or disable display of a locale-specific character to separate\n"
diff -ru a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
--- a/src/bin/psql/tab-complete.c 2017-02-06 22:45:25.000000000 +0100
+++ b/src/bin/psql/tab-complete.c 2017-03-06 00:57:11.000000000 +0100
@@ -3070,7 +3070,7 @@
{
static const char *const my_list[] =
{"unaligned", "aligned", "wrapped", "html", "asciidoc",
- "latex", "latex-longtable", "troff-ms", NULL};
+ "latex", "latex-longtable", "troff-ms", "markdown", "rst", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
diff -ru a/src/fe_utils/print.c b/src/fe_utils/print.c
--- a/src/fe_utils/print.c 2017-02-06 22:45:25.000000000 +0100
+++ b/src/fe_utils/print.c 2017-03-18 22:15:18.000000000 +0100
@@ -57,6 +57,48 @@
static printTableFooter default_footer_cell = {default_footer, NULL};
/* Line style control structures */
+const printTextFormat pg_markdown =
+{
+ "markdown",
+ {
+ {"", "", "", ""},
+ {"-", "|", "|", "|"},
+ {"", "", "", ""},
+ {"", "|", "|", "|"}
+ },
+ "|",
+ "|",
+ "|",
+ " ",
+ "+",
+ " ",
+ " ",
+ ".",
+ ".",
+ true
+};
+
+const printTextFormat pg_rst =
+{
+ "rst",
+ {
+ {"-", "+", "+", "+"},
+ {"=", "+", "+", "+"},
+ {"-", "+", "+", "+"},
+ {" ", "|", "|", "|"}
+ },
+ "|",
+ "|",
+ "|",
+ " ",
+ "+",
+ " ",
+ " ",
+ ".",
+ ".",
+ true
+};
+
const printTextFormat pg_asciiformat =
{
"ascii",
@@ -206,6 +248,7 @@
static void print_aligned_vertical(const printTableContent *cont,
FILE *fout, bool is_pager);
+static void skip_leading_spaces_print(const char *in, FILE *fout);
/* Count number of digits in integral part of number */
static int
@@ -575,6 +618,40 @@
fputc('\n', fout);
}
+/*
+ * skip leading spaces
+ */
+static void
+skip_leading_spaces_print(const char *in, FILE *fout)
+{
+ const char *p;
+ bool leading_space = true;
+ unsigned int spac; /**leading spaces*/
+ spac = 0;
+
+ for (p = in; *p; p++)
+ {
+ if (*p != ' ' && *p != '\n')
+ {
+ leading_space = false;
+ fputc(*p, fout);
+ }
+ else if (*p == '\n')
+ {
+ fputc(*p, fout);
+ leading_space = true;
+ }
+ else if (leading_space)
+ spac++; /*fputs(".", fout);*/
+ else
+ fputc(*p, fout);
+
+ }
+ if (spac != 0)
+ fprintf(fout, "%*s", spac, " ");
+
+}
+
/*
* Print pretty boxes around cells.
@@ -623,6 +700,12 @@
if (opt_border > 2)
opt_border = 2;
+ if (format == &pg_markdown)
+ opt_border = 2;
+
+ if (format == &pg_rst)
+ opt_border = 2;
+
if (cont->ncolumns > 0)
{
col_count = cont->ncolumns;
@@ -1053,9 +1136,13 @@
else /* Left aligned cell */
{
/* spaces second */
- fputnbytes(fout,
- (char *) (this_line->ptr + bytes_output[j]),
- bytes_to_output);
+ if (format != &pg_rst)
+ fputnbytes(fout,
+ (char *) (this_line->ptr + bytes_output[j]),
+ bytes_to_output);
+
+ else
+ skip_leading_spaces_print((char *) (this_line->ptr + bytes_output[j]), fout);
}
bytes_output[j] += bytes_to_output;
@@ -1124,13 +1211,20 @@
fputc('\n', fout);
} while (more_lines);
+
+ /* add line after every record */
+ if (opt_border == 2 && format == &pg_rst)
+ _print_horizontal_line(col_count, width_wrap, opt_border,
+ PRINT_RULE_BOTTOM, format, fout);
}
if (cont->opt->stop_table)
{
printTableFooter *footers = footers_with_default(cont);
- if (opt_border == 2 && !cancel_pressed)
+ /* dont add line after last row, because line is added after every row
+ **/
+ if ((opt_border == 2 && format != &pg_rst) && !cancel_pressed)
_print_horizontal_line(col_count, width_wrap, opt_border,
PRINT_RULE_BOTTOM, format, fout);
@@ -1138,6 +1232,12 @@
if (footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
+ /*add newline after table because rst needs empty line after table
+ */
+ if (format == &pg_rst || format == &pg_markdown)
+ {
+ fprintf(fout, "\n");
+ }
for (f = footers; f; f = f->next)
fprintf(fout, "%s\n", f->data);
@@ -1193,6 +1293,8 @@
{
if (opt_border == 0)
reclen = fprintf(fout, "* Record %lu", record);
+ else if (format == &pg_rst)
+ reclen = fprintf(fout, "**RECORD %lu**", record);
else
reclen = fprintf(fout, "[ RECORD %lu ]", record);
}
@@ -1258,6 +1360,10 @@
if (opt_border > 2)
opt_border = 2;
+ if (cont->opt->format == PRINT_RST) /*rst works only with border 2*/
+ opt_border = 2;
+
+
if (cont->cells[0] == NULL && cont->opt->start_table &&
cont->opt->stop_table)
{
@@ -1307,6 +1413,9 @@
hformatsize = fs;
}
+ if (format == &pg_rst)
+ hwidth = hwidth + 4; /*this broke print RECORD without pipe */
+
/* find longest data cell */
for (i = 0, ptr = cont->cells; *ptr; ptr++, i++)
{
@@ -1504,7 +1613,7 @@
if (cancel_pressed)
break;
- if (i == 0)
+ if (i == 0 || cont->opt->format == PRINT_RST)
pos = PRINT_RULE_TOP;
else
pos = PRINT_RULE_MIDDLE;
@@ -1519,9 +1628,19 @@
(format == &pg_asciiformat_old))
lhwidth++; /* for newline indicators */
- if (!opt_tuples_only)
+ if (!opt_tuples_only && cont->opt->format != PRINT_RST)
print_aligned_vertical_line(format, opt_border, record++,
lhwidth, dwidth, pos, fout);
+ else if (!opt_tuples_only && format == &pg_rst)
+ {
+ if (i ==0)
+ print_aligned_vertical_line(format, opt_border, 0, lhwidth,
+ dwidth, pos, fout);
+ print_aligned_vertical_line(format, opt_border, record++,
+ 0, lhwidth + dwidth, PRINT_RULE_DATA, fout); /* because need of only one column*/
+ print_aligned_vertical_line(format, opt_border, 0, lhwidth,
+ dwidth, pos, fout);
+ }
else if (i != 0 || !cont->opt->start_table || opt_border == 2)
print_aligned_vertical_line(format, opt_border, 0, lhwidth,
dwidth, pos, fout);
@@ -1565,9 +1684,18 @@
/*
* Header text
*/
- strlen_max_width(hlineptr[hline].ptr, &target_width,
- encoding);
- fprintf(fout, "%-s", hlineptr[hline].ptr);
+
+ if (format != &pg_rst)
+ strlen_max_width(hlineptr[hline].ptr, &target_width,
+ encoding);
+ else
+ strlen_max_width(hlineptr[hline].ptr, &target_width - 4,
+ encoding);
+
+ if (format != &pg_rst)
+ fprintf(fout, "%-s", hlineptr[hline].ptr);
+ else
+ fprintf(fout, "**%-s**", hlineptr[hline].ptr); /*header bold*/
/*
* Spacer
@@ -1641,8 +1769,12 @@
*/
bytes_to_output = strlen_max_width(dlineptr[dline].ptr + offset,
&target_width, encoding);
- fputnbytes(fout, (char *) (dlineptr[dline].ptr + offset),
- bytes_to_output);
+
+ if (format != &pg_rst)
+ fputnbytes(fout, (char *) (dlineptr[dline].ptr + offset),
+ bytes_to_output);
+ else
+ skip_leading_spaces_print((char *) (dlineptr[dline].ptr + offset), fout);
chars_to_output -= target_width;
offset += bytes_to_output;
@@ -1704,12 +1836,18 @@
else
fprintf(fout, "%*s %s\n", dwidth, "", dformat->rightvrule);
}
- }
+ /*if (opt_border == 2 && format == &pg_rst)
+ print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth,
+ PRINT_RULE_BOTTOM, fout); */
+ }
+ if (opt_border == 2 && format == &pg_rst)
+ print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth,
+ PRINT_RULE_BOTTOM, fout);
}
if (cont->opt->stop_table)
{
- if (opt_border == 2 && !cancel_pressed)
+ if (opt_border == 2 && !cancel_pressed && format != &pg_rst)
print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth,
PRINT_RULE_BOTTOM, fout);
@@ -3263,6 +3401,18 @@
else
print_troff_ms_text(cont, fout);
break;
+
+ case PRINT_RST:
+ if (cont->opt->expanded == 1)
+ print_aligned_vertical(cont, fout, false);
+ else
+ print_aligned_text(cont, fout, false);
+ break;
+
+ case PRINT_MARKDOWN:
+ print_aligned_text(cont, fout, false);
+ break;
+
default:
fprintf(stderr, _("invalid output format (internal error): %d"),
cont->opt->format);
@@ -3417,8 +3567,12 @@
* printTableOpt struct can be initialized to zeroes to get default
* behavior.
*/
- if (opt->line_style != NULL)
- return opt->line_style;
+ if (opt->format == PRINT_RST)
+ return &pg_rst;
+ else if (opt->format == PRINT_MARKDOWN)
+ return &pg_markdown;
+ else if (opt->line_style != NULL)
+ return opt->line_style;
else
return &pg_asciiformat;
}
diff -ru a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h
--- a/src/include/fe_utils/print.h 2017-02-06 22:45:25.000000000 +0100
+++ b/src/include/fe_utils/print.h 2017-03-05 18:28:04.000000000 +0100
@@ -33,7 +33,9 @@
PRINT_ASCIIDOC,
PRINT_LATEX,
PRINT_LATEX_LONGTABLE,
- PRINT_TROFF_MS
+ PRINT_TROFF_MS,
+ PRINT_MARKDOWN,
+ PRINT_RST
/* add your favourite output format here ... */
};
@@ -176,6 +178,8 @@
extern volatile bool cancel_pressed;
extern const printTextFormat pg_asciiformat;
+extern const printTextFormat pg_markdown; /*linestyle markdown*/
+extern const printTextFormat pg_rst; /*linestyle rst*/
extern const printTextFormat pg_asciiformat_old;
extern printTextFormat pg_utf8format; /* ideally would be const, but... */
diff -ru a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
--- a/src/test/regress/expected/psql.out 2017-02-06 22:45:25.000000000 +0100
+++ b/src/test/regress/expected/psql.out 2017-03-18 22:24:40.000000000 +0100
@@ -2714,3 +2714,102 @@
CONTEXT: PL/pgSQL function inline_code_block line 3 at RAISE
ERROR: bar
CONTEXT: PL/pgSQL function inline_code_block line 4 at RAISE
+prepare q AS VALUES(E'Elephant, kangaroo,\nsquirrel, gorilla', 121,
+(279./278.)::text, 0.1111, repeat('Hello ', 10))
+ , (E'goat, rhinoceros,\nmonkey, ape', 11121, (1279./1278.)::text, 5.1111,
+ repeat('xxxxxx ', 10))
+ , (E'donkey, cow, horse, tit,\neagle, whale,\naligator,
+ pelican,\ngrasshoper\npig\n\tbat', 14351, (12345./245.)::text, 345.11,
+ repeat('yyyyyy ', 10));
+\pset format rst
+execute q;
++--------------------------+---------+---------------------+---------+------------------------------------------------------------------------+
+| column1 | column2 | column3 | column4 | column5 |
++==========================+=========+=====================+=========+========================================================================+
+| Elephant, kangaroo, | 121 | 1.0035971223021583 | 0.1111 | Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello |
+| squirrel, gorilla | | | | |
++--------------------------+---------+---------------------+---------+------------------------------------------------------------------------+
+| goat, rhinoceros, | 11121 | 1.0007824726134585 | 5.1111 | xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx |
+| monkey, ape | | | | |
++--------------------------+---------+---------------------+---------+------------------------------------------------------------------------+
+| donkey, cow, horse, tit, | 14351 | 50.3877551020408163 | 345.11 | yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy |
+| eagle, whale, | | | | |
+| aligator, | | | | |
+| pelican, | | | | |
+| grasshoper | | | | |
+| pig | | | | |
+| bat | | | | |
++--------------------------+---------+---------------------+---------+------------------------------------------------------------------------+
+
+(3 rows)
+
+\pset format markdown
+execute q;
+
+| column1 | column2 | column3 | column4 | column5 |
+|--------------------------|---------|---------------------|---------|------------------------------------------------------------------------|
+| Elephant, kangaroo, | 121 | 1.0035971223021583 | 0.1111 | Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello |
+| squirrel, gorilla | | | | |
+| goat, rhinoceros, | 11121 | 1.0007824726134585 | 5.1111 | xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx |
+| monkey, ape | | | | |
+| donkey, cow, horse, tit, | 14351 | 50.3877551020408163 | 345.11 | yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy |
+| eagle, whale, | | | | |
+| aligator, | | | | |
+| pelican, | | | | |
+| grasshoper | | | | |
+| pig | | | | |
+| bat | | | | |
+
+
+(3 rows)
+
+\pset format rst
+\x
+execute q;
++-------------+------------------------------------------------------------------------+
+| **RECORD 1** |
++-------------+------------------------------------------------------------------------+
+| **column1** | Elephant, kangaroo, |
+| | squirrel, gorilla |
++-------------+------------------------------------------------------------------------+
+| **column2** | 121 |
++-------------+------------------------------------------------------------------------+
+| **column3** | 1.0035971223021583 |
++-------------+------------------------------------------------------------------------+
+| **column4** | 0.1111 |
++-------------+------------------------------------------------------------------------+
+| **column5** | Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello |
++-------------+------------------------------------------------------------------------+
+| **RECORD 2** |
++-------------+------------------------------------------------------------------------+
+| **column1** | goat, rhinoceros, |
+| | monkey, ape |
++-------------+------------------------------------------------------------------------+
+| **column2** | 11121 |
++-------------+------------------------------------------------------------------------+
+| **column3** | 1.0007824726134585 |
++-------------+------------------------------------------------------------------------+
+| **column4** | 5.1111 |
++-------------+------------------------------------------------------------------------+
+| **column5** | xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx |
++-------------+------------------------------------------------------------------------+
+| **RECORD 3** |
++-------------+------------------------------------------------------------------------+
+| **column1** | donkey, cow, horse, tit, |
+| | eagle, whale, |
+| | aligator, |
+| | pelican, |
+| | grasshoper |
+| | pig |
+| | bat |
++-------------+------------------------------------------------------------------------+
+| **column2** | 14351 |
++-------------+------------------------------------------------------------------------+
+| **column3** | 50.3877551020408163 |
++-------------+------------------------------------------------------------------------+
+| **column4** | 345.11 |
++-------------+------------------------------------------------------------------------+
+| **column5** | yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy yyyyyy |
++-------------+------------------------------------------------------------------------+
+
+deallocate q;
diff -ru a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
--- a/src/test/regress/sql/psql.sql 2017-02-06 22:45:25.000000000 +0100
+++ b/src/test/regress/sql/psql.sql 2017-03-18 22:21:54.000000000 +0100
@@ -379,3 +379,20 @@
raise notice 'foo';
raise exception 'bar';
end $$;
+
+prepare q AS VALUES(E'Elephant, kangaroo,\nsquirrel, gorilla', 121,
+(279./278.)::text, 0.1111, repeat('Hello ', 10))
+ , (E'goat, rhinoceros,\nmonkey, ape', 11121, (1279./1278.)::text, 5.1111,
+ repeat('xxxxxx ', 10))
+ , (E'donkey, cow, horse, tit,\neagle, whale,\naligator,
+ pelican,\ngrasshoper\npig\n\tbat', 14351, (12345./245.)::text, 345.11,
+ repeat('yyyyyy ', 10));
+
+\pset format rst
+execute q;
+\pset format markdown
+execute q;
+\pset format rst
+\x
+execute q;
+deallocate q;