Skip to content

Commit 564914a

Browse files
committed
ext/pgsql: adding postgresql 17 new libpq wrapper call.
pg_set_chunked_rows_size to allow to fetch results in chunk of max N rows. close GH-14571
1 parent 12f9b89 commit 564914a

File tree

7 files changed

+112
-8
lines changed

7 files changed

+112
-8
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ PHP NEWS
214214
the end of the COPY. (David Carlier)
215215
. Added pg_socket_poll to poll on the connection. (David Carlier)
216216
. Added pg_jit to get infos on server JIT support. (David Carlier)
217+
. Added pg_set_chunked_rows_size to fetch results per chunk. (David Carlier)
217218

218219
- Phar:
219220
. Fixed bug GH-12532 (PharData created from zip has incorrect timestamp).

UPGRADING

+2
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ PHP 8.4 UPGRADE NOTES
562562
. Added pg_socket_poll to check if there is any read and/or write events
563563
with an optional timeout.
564564
. Added pg_jit to get informations on the server JIT support.
565+
. Added pg_set_chunked_rows_size to allow to fetch results in chunk of
566+
max N rows.
565567

566568
- Sodium:
567569
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()

ext/pgsql/config.m4

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ if test "$PHP_PGSQL" != "no"; then
7070
AC_CHECK_LIB(pq, PQresultMemorySize, AC_DEFINE(HAVE_PG_RESULT_MEMORY_SIZE,1,[PostgreSQL 12 or later]))
7171
AC_CHECK_LIB(pq, PQchangePassword, AC_DEFINE(HAVE_PG_CHANGE_PASSWORD,1,[PostgreSQL 17 or later]))
7272
AC_CHECK_LIB(pq, PQsocketPoll, AC_DEFINE(HAVE_PG_SOCKET_POLL,1,[PostgreSQL 17 or later]))
73+
AC_CHECK_LIB(pq, PQsetChunkedRowsMode, AC_DEFINE(HAVE_PG_SET_CHUNKED_ROWS_SIZE,1,[PostgreSQL 17 or later]))
7374

7475
dnl Available since PostgreSQL 12.
7576
AC_CACHE_CHECK([if PGVerbosity enum has PQERRORS_SQLSTATE],

ext/pgsql/pgsql.c

+31-7
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@
4040
#include "php_globals.h"
4141
#include "zend_exceptions.h"
4242
#include "zend_attributes.h"
43-
#if !defined(HAVE_PG_SOCKET_POLL)
4443
#include "php_network.h"
45-
#endif
4644

4745
#ifdef HAVE_PGSQL
4846

@@ -935,16 +933,16 @@ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type
935933
array_init(return_value);
936934
res = PQexec(pgsql, "SHOW jit_provider");
937935
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
938-
add_assoc_null(return_value, "jit_provider");
936+
add_assoc_null(return_value, "jit_provider");
939937
} else {
940-
add_assoc_string(return_value, "jit_provider", PQgetvalue(res, 0, 0));
938+
add_assoc_string(return_value, "jit_provider", PQgetvalue(res, 0, 0));
941939
}
942940
PQclear(res);
943941
res = PQexec(pgsql, "SHOW jit");
944942
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
945-
add_assoc_null(return_value, "jit");
943+
add_assoc_null(return_value, "jit");
946944
} else {
947-
add_assoc_string(return_value, "jit", PQgetvalue(res, 0, 0));
945+
add_assoc_string(return_value, "jit", PQgetvalue(res, 0, 0));
948946
}
949947
PQclear(res);
950948
return;
@@ -4346,7 +4344,7 @@ static int php_pgsql_fd_cast(php_stream *stream, int cast_as, void **ret) /* {{{
43464344
}
43474345

43484346
if (ret) {
4349-
*(php_socket_t *)ret = fd_number;
4347+
*(php_socket_t *)ret = fd_number;
43504348
}
43514349
}
43524350
return SUCCESS;
@@ -6248,3 +6246,29 @@ PHP_FUNCTION(pg_socket_poll)
62486246

62496247
RETURN_LONG((zend_long)PQsocketPoll(socket, (int)read, (int)write, (int)ts));
62506248
}
6249+
6250+
#if defined(HAVE_PG_SET_CHUNKED_ROWS_SIZE)
6251+
PHP_FUNCTION(pg_set_chunked_rows_size)
6252+
{
6253+
zval *pgsql_link;
6254+
pgsql_link_handle *link;
6255+
zend_long size;
6256+
6257+
ZEND_PARSE_PARAMETERS_START(2, 2)
6258+
Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce)
6259+
Z_PARAM_LONG(size)
6260+
ZEND_PARSE_PARAMETERS_END();
6261+
6262+
if (size < 1 || size > INT_MAX) {
6263+
zend_argument_value_error(2, "must be between 1 and %d", INT_MAX);
6264+
RETURN_THROWS();
6265+
}
6266+
6267+
link = Z_PGSQL_LINK_P(pgsql_link);
6268+
CHECK_PGSQL_LINK(link);
6269+
6270+
/** can still fail if it is not allowed e.g. already fetched results **/
6271+
6272+
RETURN_BOOL(PQsetChunkedRowsMode(link->conn, (int)size) == 1);
6273+
}
6274+
#endif

ext/pgsql/pgsql.stub.php

+11
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@
245245
* @cvalue PGRES_TUPLES_OK
246246
*/
247247
const PGSQL_TUPLES_OK = UNKNOWN;
248+
#ifdef HAVE_PG_SET_CHUNKED_ROWS_SIZE
249+
/**
250+
* @var int
251+
* @cvalue PGRES_TUPLES_CHUNK
252+
*/
253+
const PGSQL_TUPLES_CHUNK = UNKNOWN;
254+
#endif
248255
/**
249256
* @var int
250257
* @cvalue PGRES_COPY_OUT
@@ -963,6 +970,10 @@ function pg_put_copy_end(PgSql\Connection $connection, ?string $error = null): i
963970
* @param resource $socket
964971
*/
965972
function pg_socket_poll($socket, int $read, int $write, int $timeout = -1): int {}
973+
974+
#ifdef HAVE_PG_SET_CHUNKED_ROWS_SIZE
975+
function pg_set_chunked_rows_size(Pgsql\Connection $connection, int $size): bool {}
976+
#endif
966977
}
967978

968979
namespace PgSql {

ext/pgsql/pgsql_arginfo.h

+17-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
PostgreSQL pg_set_chunked_rows_size
3+
--EXTENSIONS--
4+
pgsql
5+
--SKIPIF--
6+
<?php
7+
include("inc/skipif.inc");
8+
if (!function_exists("pg_set_chunked_rows_size")) die("skip pg_set_chunked_rows_size unsupported");
9+
?>
10+
--FILE--
11+
<?php
12+
13+
include('inc/config.inc');
14+
$table_name = "test_chunked_rows_size";
15+
16+
$conn = pg_connect($conn_str);
17+
pg_query($conn, "CREATE TABLE {$table_name} (num int, str text)");
18+
19+
for ($i = 0; $i < 10; $i ++)
20+
pg_query($conn, "INSERT INTO {$table_name} DEFAULT VALUES");
21+
22+
var_dump(pg_send_query($conn, "SELECT * FROM ".$table_name.";"));
23+
try {
24+
pg_set_chunked_rows_size($conn, -1);
25+
} catch (\ValueError $e) {
26+
echo $e->getMessage() . PHP_EOL;
27+
}
28+
29+
var_dump(pg_set_chunked_rows_size($conn, 1));
30+
$result = pg_get_result($conn);
31+
var_dump(pg_result_status($result) === PGSQL_TUPLES_CHUNK);
32+
var_dump(pg_num_rows($result));
33+
var_dump(pg_set_chunked_rows_size($conn, 10));
34+
?>
35+
--CLEAN--
36+
<?php
37+
include('inc/config.inc');
38+
$table_name = "test_chunked_rows_size";
39+
40+
$conn = pg_connect($conn_str);
41+
pg_query($conn, "DROP TABLE IF EXISTS {$table_name}");
42+
?>
43+
--EXPECTF--
44+
bool(true)
45+
pg_set_chunked_rows_size(): Argument #2 ($size) must be between 1 and %d
46+
bool(true)
47+
bool(true)
48+
int(1)
49+
bool(false)

0 commit comments

Comments
 (0)