mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Add test for session_preload_libraries and parameter permissions checks.
We weren't exercising the session_preload_libraries option in any meaningful way. auto_explain is a good testbed for doing so, since it's one of the primary use-cases for session_preload_libraries. Hence, adjust its TAP test to load the library via session_preload_libraries not shared_preload_libraries. While at it, feed test-specific settings to the backend via PGOPTIONS rather than tediously rewriting postgresql.conf. Also, since auto_explain has some PGC_SUSET parameters, we can use it to provide a test case for the permissions-checking bug just fixed by commitb35617de3
. Back-patch to v15 so that we have coverage for the permissions issue in that branch too. To do that, I back-patched the refactoring recently done by commit550bc0a6c
. Dagfinn Ilmari Mannsåker and Tom Lane Discussion: https://postgr.es/m/CABwTF4VEpwTHhRQ+q5MiC5ucngN-whN-PdcKeufX7eLSoAfbZA@mail.gmail.com
This commit is contained in:
@ -8,50 +8,141 @@ use PostgreSQL::Test::Cluster;
|
||||
use PostgreSQL::Test::Utils;
|
||||
use Test::More;
|
||||
|
||||
# Runs the specified query and returns the emitted server log.
|
||||
# params is an optional hash mapping GUC names to values;
|
||||
# any such settings are transmitted to the backend via PGOPTIONS.
|
||||
sub query_log
|
||||
{
|
||||
my ($node, $sql, $params) = @_;
|
||||
$params ||= {};
|
||||
|
||||
local $ENV{PGOPTIONS} = join " ",
|
||||
map { "-c $_=$params->{$_}" } keys %$params;
|
||||
|
||||
my $log = $node->logfile();
|
||||
my $offset = -s $log;
|
||||
|
||||
$node->safe_psql("postgres", $sql);
|
||||
|
||||
return slurp_file($log, $offset);
|
||||
}
|
||||
|
||||
my $node = PostgreSQL::Test::Cluster->new('main');
|
||||
$node->init;
|
||||
$node->append_conf('postgresql.conf',
|
||||
"shared_preload_libraries = 'auto_explain'");
|
||||
"session_preload_libraries = 'auto_explain'");
|
||||
$node->append_conf('postgresql.conf', "auto_explain.log_min_duration = 0");
|
||||
$node->append_conf('postgresql.conf', "auto_explain.log_analyze = on");
|
||||
$node->start;
|
||||
|
||||
# run a couple of queries
|
||||
$node->safe_psql("postgres", "SELECT * FROM pg_class;");
|
||||
$node->safe_psql("postgres",
|
||||
"SELECT * FROM pg_proc WHERE proname = 'int4pl';");
|
||||
# Simple query.
|
||||
my $log_contents = query_log($node, "SELECT * FROM pg_class;");
|
||||
|
||||
# emit some json too
|
||||
$node->append_conf('postgresql.conf', "auto_explain.log_format = json");
|
||||
$node->reload;
|
||||
$node->safe_psql("postgres", "SELECT * FROM pg_proc;");
|
||||
$node->safe_psql("postgres",
|
||||
"SELECT * FROM pg_class WHERE relname = 'pg_class';");
|
||||
like(
|
||||
$log_contents,
|
||||
qr/Query Text: SELECT \* FROM pg_class;/,
|
||||
"query text logged, text mode");
|
||||
|
||||
$node->stop('fast');
|
||||
|
||||
my $log = $node->logfile();
|
||||
|
||||
my $log_contents = slurp_file($log);
|
||||
unlike(
|
||||
$log_contents,
|
||||
qr/Query Parameters:/,
|
||||
"no query parameters logged when none, text mode");
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/Seq Scan on pg_class/,
|
||||
"sequential scan logged, text mode");
|
||||
|
||||
# Prepared query.
|
||||
$log_contents = query_log($node,
|
||||
q{PREPARE get_proc(name) AS SELECT * FROM pg_proc WHERE proname = $1; EXECUTE get_proc('int4pl');}
|
||||
);
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/Query Text: PREPARE get_proc\(name\) AS SELECT \* FROM pg_proc WHERE proname = \$1;/,
|
||||
"prepared query text logged, text mode");
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/Index Scan using pg_proc_proname_args_nsp_index on pg_proc/,
|
||||
"index scan logged, text mode");
|
||||
|
||||
|
||||
# JSON format.
|
||||
$log_contents = query_log(
|
||||
$node,
|
||||
"SELECT * FROM pg_class;",
|
||||
{ "auto_explain.log_format" => "json" });
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/"Node Type": "Seq Scan"[^}]*"Relation Name": "pg_proc"/s,
|
||||
qr/"Query Text": "SELECT \* FROM pg_class;"/,
|
||||
"query text logged, json mode");
|
||||
|
||||
unlike(
|
||||
$log_contents,
|
||||
qr/"Query Parameters":/,
|
||||
"query parameters not logged when none, json mode");
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/"Node Type": "Seq Scan"[^}]*"Relation Name": "pg_class"/s,
|
||||
"sequential scan logged, json mode");
|
||||
|
||||
# Prepared query in JSON format.
|
||||
$log_contents = query_log(
|
||||
$node,
|
||||
q{PREPARE get_class(name) AS SELECT * FROM pg_class WHERE relname = $1; EXECUTE get_class('pg_class');},
|
||||
{ "auto_explain.log_format" => "json" });
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/"Query Text": "PREPARE get_class\(name\) AS SELECT \* FROM pg_class WHERE relname = \$1;"/,
|
||||
"prepared query text logged, json mode");
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/"Node Type": "Index Scan"[^}]*"Index Name": "pg_class_relname_nsp_index"/s,
|
||||
"index scan logged, json mode");
|
||||
|
||||
# Check that PGC_SUSET parameters can be set by non-superuser if granted,
|
||||
# otherwise not
|
||||
|
||||
$node->safe_psql(
|
||||
"postgres", q{
|
||||
CREATE USER regress_user1;
|
||||
GRANT SET ON PARAMETER auto_explain.log_format TO regress_user1;
|
||||
});
|
||||
|
||||
$ENV{PGUSER} = "regress_user1";
|
||||
|
||||
$log_contents = query_log(
|
||||
$node,
|
||||
"SELECT * FROM pg_database;",
|
||||
{ "auto_explain.log_format" => "json" });
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/"Query Text": "SELECT \* FROM pg_database;"/,
|
||||
"query text logged, json mode selected by non-superuser");
|
||||
|
||||
$log_contents = query_log(
|
||||
$node,
|
||||
"SELECT * FROM pg_database;",
|
||||
{ "auto_explain.log_level" => "log" });
|
||||
|
||||
like(
|
||||
$log_contents,
|
||||
qr/WARNING: permission denied to set parameter "auto_explain\.log_level"/,
|
||||
"permission failure logged");
|
||||
|
||||
$ENV{PGUSER} = undef;
|
||||
|
||||
$node->safe_psql(
|
||||
"postgres", q{
|
||||
REVOKE SET ON PARAMETER auto_explain.log_format FROM regress_user1;
|
||||
DROP USER regress_user1;
|
||||
});
|
||||
|
||||
done_testing();
|
||||
|
Reference in New Issue
Block a user