]> granicus.if.org Git - postgresql/commitdiff
Fix behavior of printTable() and friends with externally-invoked pager.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 Dec 2015 23:20:33 +0000 (18:20 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 Dec 2015 23:20:41 +0000 (18:20 -0500)
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.

src/bin/psql/common.c
src/bin/psql/describe.c
src/bin/psql/large_obj.c
src/bin/psql/print.c
src/bin/psql/print.h
src/bin/scripts/createlang.c
src/bin/scripts/droplang.c

index 0e266a3e188a27b23e23d90d170f71f5b466ac65..3254a140b3a665c0e10b009373c83143b387cc3f 100644 (file)
@@ -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);
 
index 92ed6e297038a7a7b2a6013ed97fdc085d916bc5..a8acdc25ef686149116455f28a9799ff2c93ae79 100644 (file)
@@ -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;
index 621d6320597d5bb05b0ff080c418089a5e4fa6b7..35cfdb90ec6b835c5df4b7e3e05307034aaee050 100644 (file)
@@ -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;
index 97f9c2f1690ea67d2579e3b7944e1e60e7586a44..190f2bc5d854ecedab990204dd2bcafa12a74fbb 100644 (file)
@@ -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);
 }
 
index b0b6bf5251733df55f8f442ca78256b530b6f658..df514cffb0c770ae07bc63303ba8057de6c833bd 100644 (file)
@@ -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);
index 38cc20d9d4f160ed3897ee3807aa1e2007f6e638..87cd623d2512b23a3249b6c8d2c1319ced5c4ed0 100644 (file)
@@ -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);
index 502ec6475e8521012b0fbef92257b0b94dd71d04..fb4025ddf75338edd32cb7fbb36b30e36e82bfa2 100644 (file)
@@ -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);