Skip to content

Commit 6a9061e

Browse files
committed
Fix GH-9344: pgsql pipeline mode proposal.
Adding pg_enter_pipeline_mode, pg_exit_pipeline_mode, pg_pipeline_sync and pg_pipeline_status. Close GH-10868
1 parent 732d92c commit 6a9061e

File tree

5 files changed

+249
-1
lines changed

5 files changed

+249
-1
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ PHP NEWS
118118
- PGSQL:
119119
. pg_fetch_object raises a ValueError instead of an Exception.
120120
(David Carlier)
121+
. Added GH-9344, pipeline mode support. (David Carlier)
121122

122123
- Phar:
123124
. Fix memory leak in phar_rename_archive(). (stkeke)

ext/pgsql/pgsql.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5798,4 +5798,66 @@ PHP_FUNCTION(pg_select)
57985798
}
57995799
/* }}} */
58005800

5801+
#ifdef LIBPQ_HAS_PIPELINING
5802+
PHP_FUNCTION(pg_enter_pipeline_mode)
5803+
{
5804+
zval *pgsql_link;
5805+
pgsql_link_handle *pgsql_handle;
5806+
5807+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pgsql_link, pgsql_link_ce) == FAILURE) {
5808+
RETURN_THROWS();
5809+
}
5810+
5811+
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
5812+
CHECK_PGSQL_LINK(pgsql_handle);
5813+
5814+
RETURN_BOOL(PQenterPipelineMode(pgsql_handle->conn));
5815+
}
5816+
5817+
PHP_FUNCTION(pg_exit_pipeline_mode)
5818+
{
5819+
zval *pgsql_link;
5820+
pgsql_link_handle *pgsql_handle;
5821+
5822+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pgsql_link, pgsql_link_ce) == FAILURE) {
5823+
RETURN_THROWS();
5824+
}
5825+
5826+
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
5827+
CHECK_PGSQL_LINK(pgsql_handle);
5828+
5829+
RETURN_BOOL(PQexitPipelineMode(pgsql_handle->conn));
5830+
}
5831+
5832+
PHP_FUNCTION(pg_pipeline_sync)
5833+
{
5834+
zval *pgsql_link;
5835+
pgsql_link_handle *pgsql_handle;
5836+
5837+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pgsql_link, pgsql_link_ce) == FAILURE) {
5838+
RETURN_THROWS();
5839+
}
5840+
5841+
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
5842+
CHECK_PGSQL_LINK(pgsql_handle);
5843+
5844+
RETURN_BOOL(PQpipelineSync(pgsql_handle->conn));
5845+
}
5846+
5847+
PHP_FUNCTION(pg_pipeline_status)
5848+
{
5849+
zval *pgsql_link;
5850+
pgsql_link_handle *pgsql_handle;
5851+
5852+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pgsql_link, pgsql_link_ce) == FAILURE) {
5853+
RETURN_THROWS();
5854+
}
5855+
5856+
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
5857+
CHECK_PGSQL_LINK(pgsql_handle);
5858+
5859+
RETURN_LONG(PQpipelineStatus(pgsql_handle->conn));
5860+
}
5861+
#endif
5862+
58015863
#endif

ext/pgsql/pgsql.stub.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,29 @@
413413
*/
414414
const PGSQL_DML_STRING = UNKNOWN;
415415

416+
#ifdef LIBPQ_HAS_PIPELINING
417+
/**
418+
* @var int
419+
* @cvalue PGRES_PIPELINE_SYNC
420+
*/
421+
const PGSQL_PIPELINE_SYNC = UNKNOWN;
422+
/**
423+
* @var int
424+
* @cvalue PQ_PIPELINE_ON
425+
*/
426+
const PGSQL_PIPELINE_ON = UNKNOWN;
427+
/**
428+
* @var int
429+
* @cvalue PQ_PIPELINE_OFF
430+
*/
431+
const PGSQL_PIPELINE_OFF = UNKNOWN;
432+
/**
433+
* @var int
434+
* @cvalue PQ_PIPELINE_ABORTED
435+
*/
436+
const PGSQL_PIPELINE_ABORTED = UNKNOWN;
437+
#endif
438+
416439
function pg_connect(string $connection_string, int $flags = 0): PgSql\Connection|false {}
417440

418441
function pg_pconnect(string $connection_string, int $flags = 0): PgSql\Connection|false {}
@@ -894,6 +917,13 @@ function pg_delete(PgSql\Connection $connection, string $table_name, array $cond
894917
* @refcount 1
895918
*/
896919
function pg_select(PgSql\Connection $connection, string $table_name, array $conditions, int $flags = PGSQL_DML_EXEC, int $mode = PGSQL_ASSOC): array|string|false {}
920+
921+
#ifdef LIBPQ_HAS_PIPELINING
922+
function pg_enter_pipeline_mode(PgSql\Connection $connection): bool {}
923+
function pg_exit_pipeline_mode(PgSql\Connection $connection): bool {}
924+
function pg_pipeline_sync(PgSql\Connection $connection): bool {}
925+
function pg_pipeline_status(PgSql\Connection $connection): int {}
926+
#endif
897927
}
898928

899929
namespace PgSql {

ext/pgsql/pgsql_arginfo.h

Lines changed: 57 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/pgsql/tests/pg_pipeline_sync.phpt

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
--TEST--
2+
PostgreSQL pipeline mode
3+
--EXTENSIONS--
4+
pgsql
5+
--SKIPIF--
6+
<?php
7+
include("skipif.inc");
8+
if (!defined('PGSQL_PIPELINE_SYNC') || !function_exists('pg_send_query_params')) {
9+
die('skip pipeline mode not available');
10+
}
11+
?>
12+
--FILE--
13+
<?php
14+
15+
include('config.inc');
16+
include('nonblocking.inc');
17+
18+
if (!$db = pg_connect($conn_str, PGSQL_CONNECT_ASYNC)) {
19+
die("pg_connect() error");
20+
} elseif (pg_connection_status($db) === PGSQL_CONNECTION_BAD) {
21+
die("pg_connect() error");
22+
} elseif ($db_socket = pg_socket($db)) {
23+
stream_set_blocking($db_socket, FALSE);
24+
} else {
25+
die("pg_socket() error");
26+
}
27+
28+
while (true) {
29+
switch ($status = pg_connect_poll($db)) {
30+
case PGSQL_POLLING_READING:
31+
nb_is_readable($db_socket);
32+
break;
33+
case PGSQL_POLLING_WRITING:
34+
nb_is_writable($db_socket);
35+
break;
36+
case PGSQL_POLLING_FAILED:
37+
die("async connection failed");
38+
case PGSQL_POLLING_OK:
39+
break 2;
40+
default:
41+
die("unknown poll status");
42+
}
43+
}
44+
45+
if (!pg_enter_pipeline_mode($db)) {
46+
die('pg_enter_pipeline_mode{}');
47+
}
48+
49+
if (!pg_send_query_params($db, "select $1 as index, now() + ($1||' day')::interval as time", array(1))) {
50+
die('pg_send_query_params failed');
51+
}
52+
53+
if (!pg_pipeline_sync($db)) {
54+
die('pg_pipeline_sync failed');
55+
}
56+
57+
if (pg_pipeline_status($db) !== PGSQL_PIPELINE_ON) {
58+
die('pg_pipeline_status failed');
59+
}
60+
61+
if (!($result = pg_get_result($db))) {
62+
die('pg_get_result');
63+
}
64+
65+
if (pg_result_status($result) !== PGSQL_TUPLES_OK) {
66+
die('pg_result_status failed');
67+
}
68+
69+
if (pg_num_rows($result) == -1) {
70+
die('pg_num_rows failed');
71+
}
72+
73+
if (!pg_fetch_row($result, null)) {
74+
die('pg_fetch_row failed');
75+
}
76+
77+
pg_free_result($result);
78+
79+
if (pg_get_result($db) !== false) {
80+
die('pg_get_result failed');
81+
}
82+
83+
if (($result = pg_get_result($db)) !== false) {
84+
if (pg_result_status($result) !== PGSQL_PIPELINE_SYNC) {
85+
die('pg_result_status failed');
86+
}
87+
}
88+
89+
if (!pg_exit_pipeline_mode($db)) {
90+
die('pg_exit_pipeline_mode failed');
91+
}
92+
93+
echo "OK";
94+
95+
pg_close($db);
96+
97+
?>
98+
--EXPECT--
99+
OK

0 commit comments

Comments
 (0)