mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-05 16:09:21 +02:00
Fix behavior of printTable() and friends with externally-invoked pager.
The formatting modes that depend on knowledge of the terminal window width did not work right when printing a query result that's been fetched in sections (as a result of FETCH_SIZE). ExecQueryUsingCursor() would force use of the pager as soon as there's more than one result section, and then print.c would see an output file pointer that's not stdout and incorrectly conclude that the terminal window width isn't relevant. This has been broken all along for non-expanded "wrapped" output format, and as of 9.5 the issue affects expanded mode as well. The problem also caused "\pset expanded auto" mode to invariably *not* switch to expanded output in a segmented result, which seems to me to be exactly backwards. To fix, we need to pass down an "is_pager" flag to inform the print.c subroutines that some calling level has already replaced stdout with a pager pipe, so they should (a) not do that again and (b) nonetheless honor the window size. (Notably, this makes the first is_pager test in print_aligned_text() not be dead code anymore.) This patch is a bit invasive because there are so many existing calls of printQuery()/printTable(), but fortunately all but a couple can just pass "false" for the added parameter. Back-patch to 9.5 but no further. Given the lack of field complaints, it's not clear that we should change the behavior in stable branches. Also, the API change for printQuery()/printTable() might possibly break third-party code, again something we don't like to do in stable branches. However, it's not quite too late to do this in 9.5, and with the larger scope of the problem there, it seems worth doing.
This commit is contained in:
parent
e9986a811c
commit
375a3b3397
@ -9,6 +9,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h> /* for write() */
|
||||
@ -537,7 +538,7 @@ PSQLexecWatch(const char *query, const printQueryOpt *opt)
|
||||
switch (PQresultStatus(res))
|
||||
{
|
||||
case PGRES_TUPLES_OK:
|
||||
printQuery(res, opt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, opt, pset.queryFout, false, pset.logfile);
|
||||
break;
|
||||
|
||||
case PGRES_COMMAND_OK:
|
||||
@ -624,7 +625,7 @@ PrintQueryTuples(const PGresult *results)
|
||||
return false;
|
||||
}
|
||||
|
||||
printQuery(results, &my_popt, pset.queryFout, pset.logfile);
|
||||
printQuery(results, &my_popt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
/* close file/pipe, restore old setting */
|
||||
setQFout(NULL);
|
||||
@ -633,7 +634,7 @@ PrintQueryTuples(const PGresult *results)
|
||||
pset.queryFoutPipe = queryFoutPipe_copy;
|
||||
}
|
||||
else
|
||||
printQuery(results, &my_popt, pset.queryFout, pset.logfile);
|
||||
printQuery(results, &my_popt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1336,11 +1337,11 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
|
||||
* If query requires multiple result sets, hack to ensure that
|
||||
* only one pager instance is used for the whole mess
|
||||
*/
|
||||
pset.queryFout = PageOutput(100000, &(my_popt.topt));
|
||||
pset.queryFout = PageOutput(INT_MAX, &(my_popt.topt));
|
||||
did_pager = true;
|
||||
}
|
||||
|
||||
printQuery(results, &my_popt, pset.queryFout, pset.logfile);
|
||||
printQuery(results, &my_popt, pset.queryFout, did_pager, pset.logfile);
|
||||
|
||||
PQclear(results);
|
||||
|
||||
|
@ -123,7 +123,7 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.title = _("List of aggregate functions");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -204,7 +204,7 @@ describeTablespaces(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of tablespaces");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -469,7 +469,7 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -585,7 +585,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.title = _("List of data types");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -660,7 +660,7 @@ describeOperators(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.title = _("List of operators");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -731,7 +731,7 @@ listAllDbs(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of databases");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -847,7 +847,7 @@ permissionsList(const char *pattern)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
termPQExpBuffer(&buf);
|
||||
PQclear(res);
|
||||
@ -921,7 +921,7 @@ listDefaultACLs(const char *pattern)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
termPQExpBuffer(&buf);
|
||||
PQclear(res);
|
||||
@ -1117,7 +1117,7 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -1260,7 +1260,7 @@ describeOneTableDetails(const char *schemaname,
|
||||
{
|
||||
printfPQExpBuffer(&buf,
|
||||
"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
|
||||
"c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
|
||||
"c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
|
||||
"c.relhasoids, %s, c.reltablespace, "
|
||||
"CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
|
||||
"c.relpersistence, c.relreplident\n"
|
||||
@ -2546,8 +2546,7 @@ describeOneTableDetails(const char *schemaname,
|
||||
printTableAddFooter(&cont, buf.data);
|
||||
}
|
||||
|
||||
printTable(&cont, pset.queryFout, pset.logfile);
|
||||
printTableCleanup(&cont);
|
||||
printTable(&cont, pset.queryFout, false, pset.logfile);
|
||||
|
||||
retval = true;
|
||||
|
||||
@ -2791,7 +2790,7 @@ describeRoles(const char *pattern, bool verbose)
|
||||
}
|
||||
termPQExpBuffer(&buf);
|
||||
|
||||
printTable(&cont, pset.queryFout, pset.logfile);
|
||||
printTable(&cont, pset.queryFout, false, pset.logfile);
|
||||
printTableCleanup(&cont);
|
||||
|
||||
for (i = 0; i < nrows; i++)
|
||||
@ -2865,7 +2864,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2)
|
||||
myopt.title = _("List of settings");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
@ -3029,7 +3028,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
@ -3105,7 +3104,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.title = _("List of languages");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3192,7 +3191,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.title = _("List of domains");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3268,7 +3267,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3334,7 +3333,7 @@ listEventTriggers(const char *pattern, bool verbose)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3433,7 +3432,7 @@ listCasts(const char *pattern, bool verbose)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3509,7 +3508,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3566,7 +3565,7 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
|
||||
myopt.title = _("List of schemas");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3623,7 +3622,7 @@ listTSParsers(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of text search parsers");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3769,7 +3768,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
|
||||
myopt.translate_columns = translate_columns;
|
||||
myopt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
|
||||
@ -3801,7 +3800,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
|
||||
myopt.translate_columns = NULL;
|
||||
myopt.n_translate_columns = 0;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3869,7 +3868,7 @@ listTSDictionaries(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of text search dictionaries");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3937,7 +3936,7 @@ listTSTemplates(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of text search templates");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -3994,7 +3993,7 @@ listTSConfigs(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of text search configurations");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -4132,7 +4131,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
|
||||
myopt.topt.default_footer = false;
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
termPQExpBuffer(&title);
|
||||
|
||||
@ -4215,7 +4214,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of foreign-data wrappers");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -4294,7 +4293,7 @@ listForeignServers(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of foreign servers");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -4352,7 +4351,7 @@ listUserMappings(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of user mappings");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -4426,7 +4425,7 @@ listForeignTables(const char *pattern, bool verbose)
|
||||
myopt.title = _("List of foreign tables");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -4480,7 +4479,7 @@ listExtensions(const char *pattern)
|
||||
myopt.title = _("List of installed extensions");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -4587,7 +4586,7 @@ listOneExtensionContents(const char *extname, const char *oid)
|
||||
myopt.title = title;
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
|
@ -308,7 +308,7 @@ do_lo_list(void)
|
||||
myopt.title = _("Large objects");
|
||||
myopt.translate_header = true;
|
||||
|
||||
printQuery(res, &myopt, pset.queryFout, pset.logfile);
|
||||
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
|
@ -191,10 +191,11 @@ const unicodeStyleFormat unicode_style = {
|
||||
|
||||
/* Local functions */
|
||||
static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
|
||||
static void IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expanded,
|
||||
static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded,
|
||||
FILE **fout, bool *is_pager);
|
||||
|
||||
static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
|
||||
static void print_aligned_vertical(const printTableContent *cont,
|
||||
FILE *fout, bool is_pager);
|
||||
|
||||
|
||||
/* Count number of digits in integral part of number */
|
||||
@ -570,7 +571,7 @@ _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
|
||||
* Print pretty boxes around cells.
|
||||
*/
|
||||
static void
|
||||
print_aligned_text(const printTableContent *cont, FILE *fout)
|
||||
print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager)
|
||||
{
|
||||
bool opt_tuples_only = cont->opt->tuples_only;
|
||||
int encoding = cont->opt->encoding;
|
||||
@ -605,7 +606,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
||||
int *bytes_output; /* Bytes output for column value */
|
||||
printTextLineWrap *wrap; /* Wrap status for each column */
|
||||
int output_columns = 0; /* Width of interactive console */
|
||||
bool is_pager = false;
|
||||
bool is_local_pager = false;
|
||||
|
||||
if (cancel_pressed)
|
||||
return;
|
||||
@ -813,7 +814,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
||||
if (cont->opt->expanded == 2 && output_columns > 0 &&
|
||||
(output_columns < total_header_width || output_columns < width_total))
|
||||
{
|
||||
print_aligned_vertical(cont, fout);
|
||||
print_aligned_vertical(cont, fout, is_pager);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -822,11 +823,11 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
||||
(output_columns < total_header_width || output_columns < width_total))
|
||||
{
|
||||
fout = PageOutput(INT_MAX, cont->opt); /* force pager */
|
||||
is_pager = true;
|
||||
is_pager = is_local_pager = true;
|
||||
}
|
||||
|
||||
/* Check if newlines or our wrapping now need the pager */
|
||||
if (!is_pager)
|
||||
if (!is_pager && fout == stdout)
|
||||
{
|
||||
/* scan all cells, find maximum width, compute cell_count */
|
||||
for (i = 0, ptr = cont->cells; *ptr; ptr++, cell_count++)
|
||||
@ -862,6 +863,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
|
||||
}
|
||||
}
|
||||
IsPagerNeeded(cont, extra_output_lines, false, &fout, &is_pager);
|
||||
is_local_pager = is_pager;
|
||||
}
|
||||
|
||||
/* time to output */
|
||||
@ -1153,7 +1155,7 @@ cleanup:
|
||||
free(bytes_output);
|
||||
free(wrap);
|
||||
|
||||
if (is_pager)
|
||||
if (is_local_pager)
|
||||
ClosePager(fout);
|
||||
}
|
||||
|
||||
@ -1215,7 +1217,8 @@ print_aligned_vertical_line(const printTextFormat *format,
|
||||
}
|
||||
|
||||
static void
|
||||
print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
||||
print_aligned_vertical(const printTableContent *cont,
|
||||
FILE *fout, bool is_pager)
|
||||
{
|
||||
bool opt_tuples_only = cont->opt->tuples_only;
|
||||
unsigned short opt_border = cont->opt->border;
|
||||
@ -1233,7 +1236,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
||||
dformatsize = 0;
|
||||
struct lineptr *hlineptr,
|
||||
*dlineptr;
|
||||
bool is_pager = false,
|
||||
bool is_local_pager = false,
|
||||
hmultiline = false,
|
||||
dmultiline = false;
|
||||
int output_columns = 0; /* Width of interactive console */
|
||||
@ -1267,7 +1270,11 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
||||
* get here via print_aligned_text() in expanded auto mode, and so we have
|
||||
* to recalculate the pager requirement based on vertical output.
|
||||
*/
|
||||
IsPagerNeeded(cont, 0, true, &fout, &is_pager);
|
||||
if (!is_pager)
|
||||
{
|
||||
IsPagerNeeded(cont, 0, true, &fout, &is_pager);
|
||||
is_local_pager = is_pager;
|
||||
}
|
||||
|
||||
/* Find the maximum dimensions for the headers */
|
||||
for (i = 0; i < cont->ncolumns; i++)
|
||||
@ -1714,7 +1721,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
|
||||
free(hlineptr);
|
||||
free(dlineptr);
|
||||
|
||||
if (is_pager)
|
||||
if (is_local_pager)
|
||||
ClosePager(fout);
|
||||
}
|
||||
|
||||
@ -3075,8 +3082,8 @@ printTableCleanup(printTableContent *const content)
|
||||
* Setup pager if required
|
||||
*/
|
||||
static void
|
||||
IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expanded, FILE **fout,
|
||||
bool *is_pager)
|
||||
IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded,
|
||||
FILE **fout, bool *is_pager)
|
||||
{
|
||||
if (*fout == stdout)
|
||||
{
|
||||
@ -3107,12 +3114,18 @@ IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expande
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this to print just any table in the supported formats.
|
||||
* Use this to print any table in the supported formats.
|
||||
*
|
||||
* cont: table data and formatting options
|
||||
* fout: where to print to
|
||||
* is_pager: true if caller has already redirected fout to be a pager pipe
|
||||
* flog: if not null, also print the table there (for --log-file option)
|
||||
*/
|
||||
void
|
||||
printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
printTable(const printTableContent *cont,
|
||||
FILE *fout, bool is_pager, FILE *flog)
|
||||
{
|
||||
bool is_pager = false;
|
||||
bool is_local_pager = false;
|
||||
|
||||
if (cancel_pressed)
|
||||
return;
|
||||
@ -3120,15 +3133,19 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
if (cont->opt->format == PRINT_NOTHING)
|
||||
return;
|
||||
|
||||
/* print_aligned_*() handles the pager themselves */
|
||||
if (cont->opt->format != PRINT_ALIGNED &&
|
||||
/* print_aligned_*() handle the pager themselves */
|
||||
if (!is_pager &&
|
||||
cont->opt->format != PRINT_ALIGNED &&
|
||||
cont->opt->format != PRINT_WRAPPED)
|
||||
{
|
||||
IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
|
||||
is_local_pager = is_pager;
|
||||
}
|
||||
|
||||
/* print the stuff */
|
||||
|
||||
if (flog)
|
||||
print_aligned_text(cont, flog);
|
||||
print_aligned_text(cont, flog, false);
|
||||
|
||||
switch (cont->opt->format)
|
||||
{
|
||||
@ -3140,10 +3157,17 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
break;
|
||||
case PRINT_ALIGNED:
|
||||
case PRINT_WRAPPED:
|
||||
if (cont->opt->expanded == 1)
|
||||
print_aligned_vertical(cont, fout);
|
||||
|
||||
/*
|
||||
* In expanded-auto mode, force vertical if a pager is passed in;
|
||||
* else we may make different decisions for different hunks of the
|
||||
* query result.
|
||||
*/
|
||||
if (cont->opt->expanded == 1 ||
|
||||
(cont->opt->expanded == 2 && is_pager))
|
||||
print_aligned_vertical(cont, fout, is_pager);
|
||||
else
|
||||
print_aligned_text(cont, fout);
|
||||
print_aligned_text(cont, fout, is_pager);
|
||||
break;
|
||||
case PRINT_HTML:
|
||||
if (cont->opt->expanded == 1)
|
||||
@ -3181,17 +3205,22 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (is_pager)
|
||||
if (is_local_pager)
|
||||
ClosePager(fout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this to print query results
|
||||
*
|
||||
* It calls printTable with all the things set straight.
|
||||
* result: result of a successful query
|
||||
* opt: formatting options
|
||||
* fout: where to print to
|
||||
* is_pager: true if caller has already redirected fout to be a pager pipe
|
||||
* flog: if not null, also print the data there (for --log-file option)
|
||||
*/
|
||||
void
|
||||
printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog)
|
||||
printQuery(const PGresult *result, const printQueryOpt *opt,
|
||||
FILE *fout, bool is_pager, FILE *flog)
|
||||
{
|
||||
printTableContent cont;
|
||||
int i,
|
||||
@ -3271,7 +3300,7 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
|
||||
printTableAddFooter(&cont, *footer);
|
||||
}
|
||||
|
||||
printTable(&cont, fout, flog);
|
||||
printTable(&cont, fout, is_pager, flog);
|
||||
printTableCleanup(&cont);
|
||||
}
|
||||
|
||||
|
@ -184,9 +184,10 @@ extern void printTableAddFooter(printTableContent *const content,
|
||||
extern void printTableSetFooter(printTableContent *const content,
|
||||
const char *footer);
|
||||
extern void printTableCleanup(printTableContent *const content);
|
||||
extern void printTable(const printTableContent *cont, FILE *fout, FILE *flog);
|
||||
extern void printTable(const printTableContent *cont,
|
||||
FILE *fout, bool is_pager, FILE *flog);
|
||||
extern void printQuery(const PGresult *result, const printQueryOpt *opt,
|
||||
FILE *fout, FILE *flog);
|
||||
FILE *fout, bool is_pager, FILE *flog);
|
||||
|
||||
extern void setDecimalLocale(void);
|
||||
extern const printTextFormat *get_line_style(const printTableOpt *opt);
|
||||
|
@ -162,7 +162,7 @@ main(int argc, char *argv[])
|
||||
popt.translate_columns = translate_columns;
|
||||
popt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(result, &popt, stdout, NULL);
|
||||
printQuery(result, &popt, stdout, false, NULL);
|
||||
|
||||
PQfinish(conn);
|
||||
exit(0);
|
||||
|
@ -161,7 +161,7 @@ main(int argc, char *argv[])
|
||||
popt.translate_columns = translate_columns;
|
||||
popt.n_translate_columns = lengthof(translate_columns);
|
||||
|
||||
printQuery(result, &popt, stdout, NULL);
|
||||
printQuery(result, &popt, stdout, false, NULL);
|
||||
|
||||
PQfinish(conn);
|
||||
exit(0);
|
||||
|
Loading…
Reference in New Issue
Block a user