Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ PHP NEWS
. Fixed bug GH-20051 (apache2 shutdowns when restart is requested during
preloading). (Arnaud, welcomycozyhom)

- PDO_PGSQL:
. Clear session-local state disconnect-equivalent processing.
(KentarouTakeda)

- Phar:
. Support reference values in Phar::mungServer(). (ndossche)
. Invalid values now throw in Phar::mungServer() instead of being silently
Expand Down
16 changes: 15 additions & 1 deletion ext/pdo_pgsql/pgsql_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,20 @@ static const zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, i
}
}

static void pdo_pgsql_request_shutdown(pdo_dbh_t *dbh)
{
PGresult *res;
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;

if(H->server) {
res = PQexec(H->server, "DISCARD ALL");

if(res) {
PQclear(res);
}
}
}

static bool pdo_pgsql_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
{
bool bval;
Expand Down Expand Up @@ -1383,7 +1397,7 @@ static const struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_get_attribute,
pdo_pgsql_check_liveness, /* check_liveness */
pdo_pgsql_get_driver_methods, /* get_driver_methods */
NULL,
pdo_pgsql_request_shutdown,
pgsql_handle_in_transaction,
NULL, /* get_gc */
pdo_pgsql_scanner
Expand Down
55 changes: 55 additions & 0 deletions ext/pdo_pgsql/tests/session_state_reset.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--TEST--
Persistent connections: session state reset when performing disconnect-equivalent processing (general case)
--EXTENSIONS--
pdo_pgsql
--SKIPIF--
<?php
require __DIR__ . '/config.inc';
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
putenv('PDOTEST_ATTR='.serialize([PDO::ATTR_PERSISTENT => true]));

require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';

$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt');

$pid1 = (int)$pdo1
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

$defaultValue = (int)$pdo1
->query('show log_min_duration_statement;')
->fetchColumn(0);

$setValue = $defaultValue + 1;

$pdo1->exec("set log_min_duration_statement = {$setValue};");

$pdo1 = null;

$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt');

$pid2 = (int)$pdo2
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

assert($pid1 === $pid2);

$expectedValue = (int)$pdo2
->query('show log_min_duration_statement;')
->fetchColumn(0);

echo "defaultValue: {$defaultValue}\n";
echo "setValue: {$setValue}\n";
echo "expectedValue: {$expectedValue}\n";
echo "expected value should be reset to default: " . (($expectedValue === $defaultValue) ? 'success' : 'failure') . "\n";

?>
--EXPECTF--
defaultValue: %i
setValue: %d
expectedValue: %i
expected value should be reset to default: success
51 changes: 51 additions & 0 deletions ext/pdo_pgsql/tests/session_state_reset_advisory_lock.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
--TEST--
Persistent connections: session state reset when performing disconnect-equivalent processing (advisory lock case)
--EXTENSIONS--
pdo_pgsql
--SKIPIF--
<?php
require __DIR__ . '/config.inc';
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
putenv('PDOTEST_ATTR='.serialize([PDO::ATTR_PERSISTENT => true]));

require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';

$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt');

$pid1 = (int)$pdo1
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

$lockResult1 = (bool)$pdo1
->query('select pg_try_advisory_lock(42)::int;')
->fetchColumn(0);

$pdo1 = null;

$dsn = getenv('PDO_PGSQL_TEST_DSN');
$dsn .= ';';
putenv('PDO_PGSQL_TEST_DSN='.$dsn);

$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt');

$pid2 = (int)$pdo2
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

assert($pid1 !== $pid2);

$lockResult2 = (bool)$pdo2
->query('select pg_try_advisory_lock(42)::int;')
->fetchColumn(0);

echo "lock1: " . ($lockResult1 ? 'success' : 'failure') . "\n";
echo "lock2: " . ($lockResult2 ? 'success' : 'failure') . "\n";

?>
--EXPECT--
lock1: success
lock2: success
52 changes: 52 additions & 0 deletions ext/pdo_pgsql/tests/session_state_reset_after_interrupted.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--TEST--
Persistent connections: session state reset after backend termination (interrupted case)
--EXTENSIONS--
pdo_pgsql
--SKIPIF--
<?php
require __DIR__ . '/config.inc';
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
putenv('PDOTEST_ATTR='.serialize([PDO::ATTR_PERSISTENT => true]));

require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';

$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt');

$pid1 = (int)$pdo1
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

$pid1 = (int)$pdo1
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

$dsn = getenv('PDO_PGSQL_TEST_DSN');
$dsn .= ';';
putenv('PDO_PGSQL_TEST_DSN='.$dsn);

$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt');

$pid2 = (int)$pdo2
->query('select pg_backend_pid()::int;')
->fetchColumn(0);

assert($pid1 !== $pid2);

$terminateResult = (bool)$pdo2
->query("select pg_terminate_backend({$pid1})::int")
->fetchColumn(0);

// Disconnect after being terminated by another connection
$pdo1 = null;

echo 'pid of pdo1: ' . $pid1 . "\n";
echo 'terminate result of pdo1 by pdo2: ' . ($terminateResult ? 'success' : 'failure') . "\n";

?>
--EXPECTF--
pid of pdo1: %d
terminate result of pdo1 by pdo2: success