Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  001_basic.pl

  Sprache: Shell
 


# Copyright (c) 2021-2025, PostgreSQL Global Development Group

use strict;
use warnings FATAL => 'all';
use locale;

use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;

program_help_ok('psql');
program_version_ok('psql');
program_options_handling_ok('psql');

# Execute a psql command and check its output.
sub psql_like
{
 local $Test::Builder::Level = $Test::Builder::Level + 1;

 my ($node, $sql, $expected_stdout, $test_name) = @_;

 my ($ret, $stdout, $stderr) = $node->psql('postgres', $sql);

 is($ret, 0"$test_name: exit code 0");
 is($stderr, ''"$test_name: no stderr");
 like($stdout, $expected_stdout, "$test_name: matches");

 return;
}

# Execute a psql command and check that it fails and check the stderr.
sub psql_fails_like
{
 local $Test::Builder::Level = $Test::Builder::Level + 1;

 my ($node, $sql, $expected_stderr, $test_name, $replication) = @_;

 # Use the context of a WAL sender, if requested by the caller.
 $replication = '' unless defined($replication);

 my ($ret, $stdout, $stderr) =
   $node->psql('postgres', $sql, replication => $replication);

 isnt($ret, 0"$test_name: exit code not 0");
 like($stderr, $expected_stderr, "$test_name: matches");

 return;
}

# test --help=foo, analogous to program_help_ok()
foreach my $arg (qw(commands variables))
{
 my ($stdout, $stderr);
 my $result;

 $result = IPC::Run::run [ 'psql'"--help=$arg" ],
   '>' => \$stdout,
   '2>' => \$stderr;
 ok($result, "psql --help=$arg exit code 0");
 isnt($stdout, ''"psql --help=$arg goes to stdout");
 is($stderr, ''"psql --help=$arg nothing to stderr");
}

my $node = PostgreSQL::Test::Cluster->new('main');
$node->init(extra => [ '--locale=C''--encoding=UTF8' ]);
$node->append_conf(
 'postgresql.conf', q{
wal_level = 'logical'
max_replication_slots = 4
max_wal_senders = 4
});
$node->start;

psql_like($node, '\copyright', qr/Copyright/, '\copyright');
psql_like($node, '\help', qr/ALTER/, '\help without arguments');
psql_like($node, '\help SELECT', qr/SELECT/, '\help with argument');

# Test clean handling of unsupported replication command responses
psql_fails_like(
 $node,
 'START_REPLICATION 0/0',
 qr/unexpected PQresultStatus: 8$/,
 'handling of unexpected PQresultStatus''database');

# test \timing
psql_like(
 $node,
 '\timing on
SELECT 1',
 qr/^1$
^Time: \d+[.,]\d\d\d ms/m,
 '\timing with successful query');

# test \timing with query that fails
{
 my ($ret, $stdout, $stderr) =
   $node->psql('postgres'"\\timing on\nSELECT error");
 isnt($ret, 0'\timing with query error: query failed');
 like(
  $stdout,
  qr/^Time: \d+[.,]\d\d\d ms/m,
  '\timing with query error: timing output appears');
 unlike(
  $stdout,
  qr/^Time: 0[.,]000 ms/m,
  '\timing with query error: timing was updated');
}

# test that ENCODING variable is set and that it is updated when
# client encoding is changed
psql_like(
 $node,
 '\echo :ENCODING
set client_encoding = LATIN1;
\echo :ENCODING',
 qr/^UTF8$
^LATIN1$/m,
 'ENCODING variable is set and updated');

# test LISTEN/NOTIFY
psql_like(
 $node,
 'LISTEN foo;
NOTIFY foo;',
 qr/^Asynchronous notification "foo" received from server process with PID \d+\.$/,
 'notification');

psql_like(
 $node,
 "LISTEN foo;
NOTIFY foo, 'bar';",
 qr/^Asynchronous notification "foo" with payload "bar" received from server process with PID \d+\.$/,
 'notification with payload');

# test behavior and output on server crash
my ($ret, $out, $err) = $node->psql('postgres',
  "SELECT 'before' AS running;\n"
   . "SELECT pg_terminate_backend(pg_backend_pid());\n"
   . "SELECT 'AFTER' AS not_running;\n");

is($ret, 2'server crash: psql exit code');
like($out, qr/before/, 'server crash: output before crash');
ok($out !~ qr/AFTER/, 'server crash: no output after crash');
is( $err,
 'psql:<stdin>:2: FATAL:  terminating connection due to administrator command
psql:<stdin>:2: server closed the connection unexpectedly
 This probably means the server terminated abnormally
 before or while processing the request.
psql:<stdin>:2: error: connection to server was lost',
 'server crash: error message');

# test \errverbose
#
# (This is not in the regular regression tests because the output
# contains the source code location and we don't want to have to
# update that every time it changes.)

psql_like(
 $node,
 'SELECT 1;
\errverbose',
 qr/^1\nThere is no previous error\.$/,
 '\errverbose with no previous error');

# There are three main ways to run a query that might affect
# \errverbose: The normal way, piecemeal retrieval using FETCH_COUNT,
# and using \gdesc.  Test them all.

like(
 (   $node->psql(
   'postgres',
   "SELECT error;\n\\errverbose",
   on_error_stop => 0))[2],
 qr/\A^psql:<stdin>:1: ERROR:  .*$
^LINE 1: SELECT error;$
^ *^.*$
^psql:<stdin>:2: error: ERROR:  [0-9A-Z]{5}: .*$
^LINE 1: SELECT error;$
^ *^.*$
^LOCATION: .*$/m,
 '\errverbose after normal query with error');

like(
 (   $node->psql(
   'postgres',
   "\\set FETCH_COUNT 1\nSELECT error;\n\\errverbose",
   on_error_stop => 0))[2],
 qr/\A^psql:<stdin>:2: ERROR:  .*$
^LINE 1: SELECT error;$
^ *^.*$
^psql:<stdin>:3: error: ERROR:  [0-9A-Z]{5}: .*$
^LINE 1: SELECT error;$
^ *^.*$
^LOCATION: .*$/m,
 '\errverbose after FETCH_COUNT query with error');

like(
 (   $node->psql(
   'postgres',
   "SELECT error\\gdesc\n\\errverbose",
   on_error_stop => 0))[2],
 qr/\A^psql:<stdin>:1: ERROR:  .*$
^LINE 1: SELECT error$
^ *^.*$
^psql:<stdin>:2: error: ERROR:  [0-9A-Z]{5}: .*$
^LINE 1: SELECT error$
^ *^.*$
^LOCATION: .*$/m,
 '\errverbose after \gdesc with error');

# Check behavior when using multiple -c and -f switches.
# Note that we cannot test backend-side errors as tests are unstable in this
# case: IPC::Run can complain about a SIGPIPE if psql quits before reading a
# query result.
my $tempdir = PostgreSQL::Test::Utils::tempdir;
$node->safe_psql('postgres'"CREATE TABLE tab_psql_single (a int);");

# Tests with ON_ERROR_STOP.
$node->command_ok(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--set' => 'ON_ERROR_STOP=1',
  '--command' => 'INSERT INTO tab_psql_single VALUES (1)',
  '--command' => 'INSERT INTO tab_psql_single VALUES (2)',
 ],
 'ON_ERROR_STOP, --single-transaction and multiple -c switches');
my $row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '2',
 '--single-transaction commits transaction, ON_ERROR_STOP and multiple -c switches'
);

$node->command_fails(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--set' => 'ON_ERROR_STOP=1',
  '--command' => 'INSERT INTO tab_psql_single VALUES (3)',
  '--command' => "\\copy tab_psql_single FROM '$tempdir/nonexistent'"
 ],
 'ON_ERROR_STOP, --single-transaction and multiple -c switches, error');
$row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '2',
 'client-side error rolls back transaction, ON_ERROR_STOP and multiple -c switches'
);

# Tests mixing files and commands.
my $copy_sql_file = "$tempdir/tab_copy.sql";
my $insert_sql_file = "$tempdir/tab_insert.sql";
append_to_file($copy_sql_file,
 "\\copy tab_psql_single FROM '$tempdir/nonexistent';");
append_to_file($insert_sql_file, 'INSERT INTO tab_psql_single VALUES (4);');
$node->command_ok(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--set' => 'ON_ERROR_STOP=1',
  '--file' => $insert_sql_file,
  '--file' => $insert_sql_file
 ],
 'ON_ERROR_STOP, --single-transaction and multiple -f switches');
$row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '4',
 '--single-transaction commits transaction, ON_ERROR_STOP and multiple -f switches'
);

$node->command_fails(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--set' => 'ON_ERROR_STOP=1',
  '--file' => $insert_sql_file,
  '--file' => $copy_sql_file
 ],
 'ON_ERROR_STOP, --single-transaction and multiple -f switches, error');
$row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '4',
 'client-side error rolls back transaction, ON_ERROR_STOP and multiple -f switches'
);

# Tests without ON_ERROR_STOP.
# The last switch fails on \copy.  The command returns a failure and the
# transaction commits.
$node->command_fails(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--file' => $insert_sql_file,
  '--file' => $insert_sql_file,
  '--command' => "\\copy tab_psql_single FROM '$tempdir/nonexistent'"
 ],
 'no ON_ERROR_STOP, --single-transaction and multiple -f/-c switches');
$row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '6',
 'client-side error commits transaction, no ON_ERROR_STOP and multiple -f/-c switches'
);

# The last switch fails on \copy coming from an input file.  The command
# returns a success and the transaction commits.
$node->command_ok(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--file' => $insert_sql_file,
  '--file' => $insert_sql_file,
  '--file' => $copy_sql_file
 ],
 'no ON_ERROR_STOP, --single-transaction and multiple -f switches');
$row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '8',
 'client-side error commits transaction, no ON_ERROR_STOP and multiple -f switches'
);

# The last switch makes the command return a success, and the contents of
# the transaction commit even if there is a failure in-between.
$node->command_ok(
 [
  'psql',
  '--no-psqlrc',
  '--single-transaction',
  '--command' => 'INSERT INTO tab_psql_single VALUES (5)',
  '--file' => $copy_sql_file,
  '--command' => 'INSERT INTO tab_psql_single VALUES (6)'
 ],
 'no ON_ERROR_STOP, --single-transaction and multiple -c switches');
$row_count =
  $node->safe_psql('postgres''SELECT count(*) FROM tab_psql_single');
is($row_count, '10',
 'client-side error commits transaction, no ON_ERROR_STOP and multiple -c switches'
);

# Test \copy from with DEFAULT option
$node->safe_psql(
 'postgres',
 "CREATE TABLE copy_default (
  id integer PRIMARY KEY,
  text_value text NOT NULL DEFAULT 'test',
  ts_value timestamp without time zone NOT NULL DEFAULT '2022-07-05'
 )"
);

my $copy_default_sql_file = "$tempdir/copy_default.csv";
append_to_file($copy_default_sql_file, "1,value,2022-07-04\n");
append_to_file($copy_default_sql_file, "2,placeholder,2022-07-03\n");
append_to_file($copy_default_sql_file, "3,placeholder,placeholder\n");

psql_like(
 $node,
 "\\copy copy_default from $copy_default_sql_file with (format 'csv', default 'placeholder');
 SELECT * FROM copy_default",
 qr/1\|value\|2022-07-04 00:00:00
2|test|2022-07-03 00:00:00
3|test|2022-07-05 00:00:00/,
 '\copy from with DEFAULT');

# Check \watch
# Note: the interval value is parsed with locale-aware strtod()
psql_like(
 $node, sprintf('SELECT 1 \watch c=3 i=%g'0.01),
 qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.01');

# Sub-millisecond wait works, equivalent to 0.
psql_like(
 $node, sprintf('SELECT 1 \watch c=3 i=%g'0.0001),
 qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.0001');

# Test zero interval
psql_like(
 $node, '\set WATCH_INTERVAL 0
SELECT 1 \watch c=3',
 qr/1\n1\n1/, '\watch with 3 iterations, interval of 0');

# Check \watch minimum row count
psql_fails_like(
 $node,
 'SELECT 3 \watch m=x',
 qr/incorrect minimum row count/,
 '\watch, invalid minimum row setting');

psql_fails_like(
 $node,
 'SELECT 3 \watch m=1 min_rows=2',
 qr/minimum row count specified more than once/,
 '\watch, minimum rows is specified more than once');

psql_like(
 $node,
 sprintf(
  q{with x as (
  select now()-backend_start AS howlong
  from pg_stat_activity
  where pid = pg_backend_pid()
   ) select 123 from x where howlong < '2 seconds' \watch i=%g m=2}, 0.5),
 qr/^123$/,
 '\watch, 2 minimum rows');

# Check \watch errors
psql_fails_like(
 $node,
 'SELECT 1 \watch -10',
 qr/incorrect interval value "-10"/,
 '\watch, negative interval');
psql_fails_like(
 $node,
 'SELECT 1 \watch 10ab',
 qr/incorrect interval value "10ab"/,
 '\watch, incorrect interval');
psql_fails_like(
 $node,
 'SELECT 1 \watch 10e400',
 qr/incorrect interval value "10e400"/,
 '\watch, out-of-range interval');
psql_fails_like(
 $node,
 'SELECT 1 \watch 1 1',
 qr/interval value is specified more than once/,
 '\watch, interval value is specified more than once');
psql_fails_like(
 $node,
 'SELECT 1 \watch c=1 c=1',
 qr/iteration count is specified more than once/,
 '\watch, iteration count is specified more than once');

# Check WATCH_INTERVAL
psql_like(
 $node,
 '\echo :WATCH_INTERVAL
\set WATCH_INTERVAL 10
\echo :WATCH_INTERVAL
\unset WATCH_INTERVAL
\echo :WATCH_INTERVAL',
 qr/^2$
^10$
^2$/m,
 'WATCH_INTERVAL variable is set and updated');
psql_fails_like(
 $node,
 '\set WATCH_INTERVAL 1e500',
 qr/is out of range/,
 'WATCH_INTERVAL variable is out of range');

# Test \g output piped into a program.
# The program is perl -pe '' to simply copy the input to the output.
my $g_file = "$tempdir/g_file_1.out";
my $perlbin = $^X;
$perlbin =~ s!\\!/!g if $PostgreSQL::Test::Utils::windows_os;
my $pipe_cmd = "$perlbin -pe '' >$g_file";

psql_like($node, "SELECT 'one' \\g | $pipe_cmd", qr//, "one command \\g");
my $c1 = slurp_file($g_file);
like($c1, qr/one/);

psql_like($node, "SELECT 'two' \\; SELECT 'three' \\g | $pipe_cmd",
 qr//, "two commands \\g");
my $c2 = slurp_file($g_file);
like($c2, qr/two.*three/s);


psql_like(
 $node,
 "\\set SHOW_ALL_RESULTS 0\nSELECT 'four' \\; SELECT 'five' \\g | $pipe_cmd",
 qr//,
 "two commands \\g with only last result");
my $c3 = slurp_file($g_file);
like($c3, qr/five/);
unlike($c3, qr/four/);

psql_like($node, "copy (values ('foo'),('bar')) to stdout \\g | $pipe_cmd",
 qr//, "copy output passed to \\g pipe");
my $c4 = slurp_file($g_file);
like($c4, qr/foo.*bar/s);

# Test COPY within pipelines.  These abort the connection from
# the frontend so they cannot be tested via SQL.
$node->safe_psql('postgres''CREATE TABLE psql_pipeline()');
my $log_location = -s $node->logfile;
psql_fails_like(
 $node,
 qq{\\startpipeline
COPY psql_pipeline FROM STDIN;
SELECT 'val1';
\\syncpipeline
\\endpipeline},
 qr/COPY in a pipeline is not supported, aborting connection/,
 'COPY FROM in pipeline: fails');
$node->wait_for_log(
 qr/FATAL: .*terminating connection because protocol synchronization was lost/,
 $log_location);

# Remove \syncpipeline here.
psql_fails_like(
 $node,
 qq{\\startpipeline
COPY psql_pipeline TO STDOUT;
SELECT 'val1';
\\endpipeline},
 qr/COPY in a pipeline is not supported, aborting connection/,
 'COPY TO in pipeline: fails');

psql_fails_like(
 $node,
 qq{\\startpipeline
\\copy psql_pipeline from stdin;
SELECT 'val1';
\\syncpipeline
\\endpipeline},
 qr/COPY in a pipeline is not supported, aborting connection/,
 '\copy from in pipeline: fails');

# Sync attempt after a COPY TO/FROM.
psql_fails_like(
 $node,
 qq{\\startpipeline
\\copy psql_pipeline to stdout;
\\syncpipeline
\\endpipeline},
 qr/COPY in a pipeline is not supported, aborting connection/,
 '\copy to in pipeline: fails');

psql_fails_like(
 $node,
 qq{\\restrict test
\\! should_fail},
 qr/backslash commands are restricted; only \\unrestrict is allowed/,
 'meta-command in restrict mode fails');

done_testing();

Messung V0.5 in Prozent
C=92 H=72 G=82

¤ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet am  2026-08-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002