Skip to content

Commit

Permalink
ext/pgsql: adding pg_close_stmt.
Browse files Browse the repository at this point in the history
up to postgresql 17, when done with a prepared statement, we could
release it with DEALLOCATE sql command which is fine ; until we want
to implement a cache solution based on statement ids.

Since PostgreSQL 17, PQclosePrepared uses internally the `close` protocol
allowing to reuse the statement name while still freeing it.
Since the close protocol implementation had been added on libpq within
this release, no way to reimplement it.

close GH-14584
  • Loading branch information
devnexen committed Sep 29, 2024
1 parent 291eef2 commit 1da352c
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 1 deletion.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ PHP NEWS
Pdo\Pgsql::prepare(…, [ PDO::ATTR_PREFETCH => 0 ]) make fetch() lazy
instead of storing the whole result set in memory (Guillaume Outters)

- PGSQL:
. Added pg_close_stmt to close a prepared statement while allowing
its name to be reused. (David Carlier)

- Random:
. Moves from /dev/urandom usage to arc4random_buf on Haiku. (David Carlier)

Expand Down
5 changes: 5 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ PHP 8.5 UPGRADE NOTES
6. New Functions
========================================

- PGSQL@
. pg_close_stmt offers an alternative way to close a prepared
statement from the DEALLOCATE sql command in that we can reuse
its name afterwards.

========================================
7. New Classes and Interfaces
========================================
Expand Down
3 changes: 3 additions & 0 deletions ext/pgsql/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ if test "$PHP_PGSQL" != "no"; then
[Define to 1 if libpq has the 'PQsetChunkedRowsMode' function (PostgreSQL
17 or later).])],,
[$PGSQL_LIBS])
PHP_CHECK_LIBRARY([pq], [PQclosePrepared],
[AC_DEFINE([HAVE_PG_CLOSE_STMT], [1], [PostgreSQL 17 or later])],,
[$PGSQL_LIBS])

old_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $PGSQL_CFLAGS"
Expand Down
36 changes: 36 additions & 0 deletions ext/pgsql/pgsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -6256,3 +6256,39 @@ PHP_FUNCTION(pg_set_chunked_rows_size)
RETURN_BOOL(PQsetChunkedRowsMode(link->conn, (int)size) == 1);
}
#endif

#if defined(HAVE_PG_CLOSE_STMT)
PHP_FUNCTION(pg_close_stmt)
{
zval *pgsql_link;
pgsql_link_handle *link;
PGresult *pgsql_result;
zend_string *stmt;

ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce)
Z_PARAM_STR(stmt)
ZEND_PARSE_PARAMETERS_END();

if (ZSTR_LEN(stmt) == 0) {
zend_argument_value_error(2, "cannot be empty");
RETURN_THROWS();
}

link = Z_PGSQL_LINK_P(pgsql_link);
CHECK_PGSQL_LINK(link);

pgsql_result = PQclosePrepared(link->conn, ZSTR_VAL(stmt));

if (PQresultStatus(pgsql_result) != PGRES_COMMAND_OK) {
RETURN_FALSE;
} else {
pgsql_result_handle *pg_handle;
object_init_ex(return_value, pgsql_result_ce);
pg_handle = Z_PGSQL_RESULT_P(return_value);
pg_handle->conn = link->conn;
pg_handle->result = pgsql_result;
pg_handle->row = 0;
}
}
#endif
3 changes: 3 additions & 0 deletions ext/pgsql/pgsql.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,9 @@ function pg_socket_poll($socket, int $read, int $write, int $timeout = -1): int
#ifdef HAVE_PG_SET_CHUNKED_ROWS_SIZE
function pg_set_chunked_rows_size(Pgsql\Connection $connection, int $size): bool {}
#endif
#ifdef HAVE_PG_CLOSE_STMT
function pg_close_stmt(Pgsql\Connection $connection, string $statement_name): Pgsql\Result|false {}
#endif
}

namespace PgSql {
Expand Down
15 changes: 14 additions & 1 deletion ext/pgsql/pgsql_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions ext/pgsql/tests/pg_close_stmt.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
PostgreSQL pg_close_stmt
--EXTENSIONS--
pgsql
--SKIPIF--
<?php include("inc/skipif.inc");
if (!function_exists("pg_close_stmt")) die("skip pg_close_stmt unsupported");
?>
--FILE--
<?php
include('inc/config.inc');


$query = 'SELECT $1::text IS NULL;';
$params_null = [null];

$db = pg_connect($conn_str);
$res = pg_prepare($db, 'test', $query);

$res = pg_execute($db, 'test', $params_null);
$res = pg_close_stmt($db, 'test');
var_dump($res !== false);
var_dump(pg_result_status($res) === PGSQL_COMMAND_OK);
pg_prepare($db, 'test', $query);
$res = pg_execute($db, 'test', $params_null);
pg_free_result($res);

pg_close($db);

?>
--EXPECT--
bool(true)
bool(true)

0 comments on commit 1da352c

Please sign in to comment.