Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit27da1a7

Browse files
committed
Improve psql's ability to select pager mode accurately.
We try to use the pager only when more than a screenful's worth ofdata is to be printed. However, the code in print.c that's concernedwith counting the number of lines that will be needed missed a lot ofedge cases:* While plain aligned mode accounted for embedded newlines in columnheaders and table cells, unaligned and vertical output modes did not.* In particular, since vertical mode repeats the headers for eachrecord, we need to account for embedded newlines in the headers foreach record.* Multi-line table titles were not accounted for.* tuples_only mode (where headers aren't printed) wasn't accountedfor.* Footers were accounted for as one line per footer, again missingthe possibility of multi-line footers. (In some cases such as"\d+" on a view, there can be many lines in a footer.) Also,we failed to account for the default footer.To fix, move the entire responsibility for counting lines intoIsPagerNeeded (or actually, into a new subroutine count_table_lines),and then expand the logic as appropriate. Also restructure to make itperhaps a bit easier to follow. It's still only completely accuratefor ALIGNED/WRAPPED/UNALIGNED formats, but the other formats are nottypically used with interactive output.Arrange to not run count_table_lines at all unless we will useits result, and teach it to quit early as soon as it's proventhat the output is long enough to require use of the pager.When dealing with large tables this should save a noticeableamount of time, since pg_wcssize() isn't exactly cheap.In passing, move the "flog" output step to the bottom of printTable(),rather than running it when we've already opened the pager in somemodes. In principle it shouldn't interfere with the pager becauseflog should always point to a non-interactive file; but it seems sillyto risk any interference, especially when the existing positioningseems to have been chosen with the aid of a dartboard.Also add a TAP test to exercise pager mode. Up to now, we have hadzero test coverage of these code paths, because they aren't reachedunless isatty(stdout). We do have the test infrastructure to improvethat situation, though. Following the lead of 010_tab_completion.pl,set up an interactive psql and feed it some test cases. To detectwhether it really did invoke the pager, point PSQL_PAGER to "wc -l".The test is skipped if that utility isn't available.Author: Erik Wienhold <ewie@ewie.name>Test-authored-by: Tom Lane <tgl@sss.pgh.pa.us>Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>Discussion:https://postgr.es/m/2dd2430f-dd20-4c89-97fd-242616a3d768@ewie.name
1 parent8c49a48 commit27da1a7

File tree

3 files changed

+382
-84
lines changed

3 files changed

+382
-84
lines changed

‎src/bin/psql/meson.build‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ tests += {
7777
't/001_basic.pl',
7878
't/010_tab_completion.pl',
7979
't/020_cancel.pl',
80+
't/030_pager.pl',
8081
],
8182
},
8283
}

‎src/bin/psql/t/030_pager.pl‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
# Copyright (c) 2021-2025, PostgreSQL Global Development Group
3+
4+
use strict;
5+
use warningsFATAL=>'all';
6+
7+
use PostgreSQL::Test::Cluster;
8+
use PostgreSQL::Test::Utils;
9+
use Test::More;
10+
use Data::Dumper;
11+
12+
# If we don't have IO::Pty, forget it, because IPC::Run depends on that
13+
# to support pty connections
14+
eval {require IO::Pty; };
15+
if ($@)
16+
{
17+
planskip_all=>'IO::Pty is needed to run this test';
18+
}
19+
20+
# Check that "wc -l" does what we expect, else forget it
21+
my$wcstdin ="foo bar\nbaz\n";
22+
my ($wcstdout,$wcstderr);
23+
my$result = IPC::Run::run ['wc','-l' ],
24+
'<'=> \$wcstdin,
25+
'>'=> \$wcstdout,
26+
'2>'=> \$wcstderr;
27+
chomp$wcstdout;
28+
if ($wcstdoutne'2' ||$wcstderrne'')
29+
{
30+
planskip_all=>'"wc -l" is needed to run this test';
31+
}
32+
33+
# We set up "wc -l" as the pager so we can tell whether psql used the pager
34+
$ENV{PSQL_PAGER} ="wc -l";
35+
36+
# start a new server
37+
my$node = PostgreSQL::Test::Cluster->new('main');
38+
$node->init;
39+
$node->start;
40+
41+
# fire up an interactive psql session
42+
my$h =$node->interactive_psql('postgres');
43+
44+
# set the pty's window size to known values
45+
# (requires undesirable chumminess with the innards of IPC::Run)
46+
formy$pty (values %{$h->{run}->{PTYS} })
47+
{
48+
$pty->set_winsize(24, 80);
49+
}
50+
51+
# Simple test case: type something and see if psql responds as expected
52+
subdo_command
53+
{
54+
my ($send,$pattern,$annotation) =@_;
55+
56+
# report test failures from caller location
57+
local$Test::Builder::Level =$Test::Builder::Level + 1;
58+
59+
# restart per-command timer
60+
$h->{timeout}->start($PostgreSQL::Test::Utils::timeout_default);
61+
62+
# send the data to be sent and wait for its result
63+
my$out =$h->query_until($pattern,$send);
64+
my$okay = ($out =~$pattern && !$h->{timeout}->is_expired);
65+
ok($okay,$annotation);
66+
# for debugging, log actual output if it didn't match
67+
local$Data::Dumper::Terse = 1;
68+
local$Data::Dumper::Useqq = 1;
69+
diag'Actual output was' . Dumper($out) ."Did not match\"$pattern\"\n"
70+
if !$okay;
71+
return;
72+
}
73+
74+
# Test invocation of the pager
75+
#
76+
# Note that interactive_psql starts psql with --no-align --tuples-only,
77+
# and that the output string will include psql's prompts and command echo.
78+
79+
do_command(
80+
"SELECT 'test' AS t FROM generate_series(1,23);\n",
81+
qr/^test\r?$/m,
82+
"execute SELECT query that needs no pagination");
83+
84+
do_command(
85+
"SELECT 'test' AS t FROM generate_series(1,24);\n",
86+
qr/^24\r?$/m,
87+
"execute SELECT query that needs pagination");
88+
89+
do_command(
90+
"\\pset expanded\nSELECT generate_series(1,20) as g;\n",
91+
qr/^39\r?$/m,
92+
"execute SELECT query that needs pagination in expanded mode");
93+
94+
do_command(
95+
"\\pset tuples_only off\n\\d+ information_schema.referential_constraints\n",
96+
qr/^\d+\r?$/m,
97+
"execute command with footer that needs pagination");
98+
99+
# send psql an explicit \q to shut it down, else pty won't close properly
100+
$h->quitordie"psql returned$?";
101+
102+
# done
103+
$node->stop;
104+
done_testing();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp