Skip to content

Commit 6389800

Browse files
degtyaryovdevnexen
authored andcommitted
Fix GH-9344: pgsql pipeline mode proposal.
Adding pg_send_flush_request. Fix freeze after next execute pg_send_* on PQgetResult in _php_pgsql_link_has_results. Set nonblocking for pipelining mode. No flush client buffer in pg_send_* for pipelining mode. Close GH-12644
1 parent 677db1b commit 6389800

File tree

6 files changed

+195
-50
lines changed

6 files changed

+195
-50
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ PHP NEWS
4444
. Fixed bug GH-11374 (Backport upstream fix, Different preg_match result
4545
with -d pcre.jit=0). (mvorisek)
4646

47+
- PGSQL:
48+
. Fixed pipeline mode GH-9344. (degtyaryov)
49+
4750
- SOAP:
4851
. Fix potential crash with an edge case of persistent encoders. (nielsdos)
4952
. Fixed bug #75306 (Memleak in SoapClient). (nielsdos)

UPGRADING

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ PHP 8.3 UPGRADE NOTES
432432
in error messages (with libpq >= 9.6).
433433
. Added pg_enter_pipeline_mode().
434434
. Added pg_exit_pipeline_mode().
435+
. Added pg_send_flush_request().
435436
. Added pg_pipeline_sync().
436437
. Added pg_pipeline_status().
437438

ext/pgsql/pgsql.c

Lines changed: 135 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3595,6 +3595,9 @@ PHP_FUNCTION(pg_send_query)
35953595
char *query;
35963596
size_t len;
35973597
PGconn *pgsql;
3598+
#ifdef LIBPQ_HAS_PIPELINING
3599+
bool is_pipeline_mode;
3600+
#endif
35983601
int is_non_blocking;
35993602
int ret;
36003603

@@ -3606,23 +3609,40 @@ PHP_FUNCTION(pg_send_query)
36063609
CHECK_PGSQL_LINK(link);
36073610
pgsql = link->conn;
36083611

3609-
is_non_blocking = PQisnonblocking(pgsql);
3612+
#ifdef LIBPQ_HAS_PIPELINING
3613+
is_pipeline_mode = (PQpipelineStatus(pgsql) == PQ_PIPELINE_ON);
3614+
if (is_pipeline_mode) {
3615+
is_non_blocking = 1;
3616+
} else {
3617+
#endif
3618+
is_non_blocking = PQisnonblocking(pgsql);
36103619

3611-
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3612-
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3613-
RETURN_FALSE;
3614-
}
3620+
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3621+
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3622+
RETURN_FALSE;
3623+
}
36153624

3616-
if (_php_pgsql_link_has_results(pgsql)) {
3617-
php_error_docref(NULL, E_NOTICE,
3618-
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3625+
if (_php_pgsql_link_has_results(pgsql)) {
3626+
php_error_docref(NULL, E_NOTICE,
3627+
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3628+
}
3629+
#ifdef LIBPQ_HAS_PIPELINING
36193630
}
3631+
#endif
36203632

36213633
if (is_non_blocking) {
36223634
if (!PQsendQuery(pgsql, query)) {
36233635
RETURN_FALSE;
36243636
}
3625-
ret = PQflush(pgsql);
3637+
#ifdef LIBPQ_HAS_PIPELINING
3638+
if (is_pipeline_mode) {
3639+
ret = 0;
3640+
} else {
3641+
#endif
3642+
ret = PQflush(pgsql);
3643+
#ifdef LIBPQ_HAS_PIPELINING
3644+
}
3645+
#endif
36263646
} else {
36273647
if (!PQsendQuery(pgsql, query)) {
36283648
if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
@@ -3667,6 +3687,9 @@ PHP_FUNCTION(pg_send_query_params)
36673687
char *query;
36683688
size_t query_len;
36693689
PGconn *pgsql;
3690+
#ifdef LIBPQ_HAS_PIPELINING
3691+
bool is_pipeline_mode;
3692+
#endif
36703693
int is_non_blocking;
36713694
int ret;
36723695

@@ -3678,17 +3701,26 @@ PHP_FUNCTION(pg_send_query_params)
36783701
CHECK_PGSQL_LINK(link);
36793702
pgsql = link->conn;
36803703

3681-
is_non_blocking = PQisnonblocking(pgsql);
3704+
#ifdef LIBPQ_HAS_PIPELINING
3705+
is_pipeline_mode = (PQpipelineStatus(pgsql) == PQ_PIPELINE_ON);
3706+
if (is_pipeline_mode) {
3707+
is_non_blocking = 1;
3708+
} else {
3709+
#endif
3710+
is_non_blocking = PQisnonblocking(pgsql);
36823711

3683-
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3684-
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3685-
RETURN_FALSE;
3686-
}
3712+
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3713+
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3714+
RETURN_FALSE;
3715+
}
36873716

3688-
if (_php_pgsql_link_has_results(pgsql)) {
3689-
php_error_docref(NULL, E_NOTICE,
3690-
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3717+
if (_php_pgsql_link_has_results(pgsql)) {
3718+
php_error_docref(NULL, E_NOTICE,
3719+
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3720+
}
3721+
#ifdef LIBPQ_HAS_PIPELINING
36913722
}
3723+
#endif
36923724

36933725
num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
36943726
if (num_params > 0) {
@@ -3727,7 +3759,15 @@ PHP_FUNCTION(pg_send_query_params)
37273759
}
37283760

37293761
if (is_non_blocking) {
3730-
ret = PQflush(pgsql);
3762+
#ifdef LIBPQ_HAS_PIPELINING
3763+
if (is_pipeline_mode) {
3764+
ret = 0;
3765+
} else {
3766+
#endif
3767+
ret = PQflush(pgsql);
3768+
#ifdef LIBPQ_HAS_PIPELINING
3769+
}
3770+
#endif
37313771
} else {
37323772
/* Wait to finish sending buffer */
37333773
while ((ret = PQflush(pgsql))) {
@@ -3761,6 +3801,9 @@ PHP_FUNCTION(pg_send_prepare)
37613801
char *query, *stmtname;
37623802
size_t stmtname_len, query_len;
37633803
PGconn *pgsql;
3804+
#ifdef LIBPQ_HAS_PIPELINING
3805+
bool is_pipeline_mode;
3806+
#endif
37643807
int is_non_blocking;
37653808
int ret;
37663809

@@ -3772,17 +3815,26 @@ PHP_FUNCTION(pg_send_prepare)
37723815
CHECK_PGSQL_LINK(link);
37733816
pgsql = link->conn;
37743817

3775-
is_non_blocking = PQisnonblocking(pgsql);
3818+
#ifdef LIBPQ_HAS_PIPELINING
3819+
is_pipeline_mode = (PQpipelineStatus(pgsql) == PQ_PIPELINE_ON);
3820+
if (is_pipeline_mode) {
3821+
is_non_blocking = 1;
3822+
} else {
3823+
#endif
3824+
is_non_blocking = PQisnonblocking(pgsql);
37763825

3777-
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3778-
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3779-
RETURN_FALSE;
3780-
}
3826+
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3827+
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3828+
RETURN_FALSE;
3829+
}
37813830

3782-
if (_php_pgsql_link_has_results(pgsql)) {
3783-
php_error_docref(NULL, E_NOTICE,
3784-
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3831+
if (_php_pgsql_link_has_results(pgsql)) {
3832+
php_error_docref(NULL, E_NOTICE,
3833+
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3834+
}
3835+
#ifdef LIBPQ_HAS_PIPELINING
37853836
}
3837+
#endif
37863838

37873839
if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
37883840
if (is_non_blocking) {
@@ -3798,7 +3850,15 @@ PHP_FUNCTION(pg_send_prepare)
37983850
}
37993851

38003852
if (is_non_blocking) {
3801-
ret = PQflush(pgsql);
3853+
#ifdef LIBPQ_HAS_PIPELINING
3854+
if (is_pipeline_mode) {
3855+
ret = 0;
3856+
} else {
3857+
#endif
3858+
ret = PQflush(pgsql);
3859+
#ifdef LIBPQ_HAS_PIPELINING
3860+
}
3861+
#endif
38023862
} else {
38033863
/* Wait to finish sending buffer */
38043864
while ((ret = PQflush(pgsql))) {
@@ -3834,6 +3894,9 @@ PHP_FUNCTION(pg_send_execute)
38343894
char *stmtname;
38353895
size_t stmtname_len;
38363896
PGconn *pgsql;
3897+
#ifdef LIBPQ_HAS_PIPELINING
3898+
bool is_pipeline_mode;
3899+
#endif
38373900
int is_non_blocking;
38383901
int ret;
38393902

@@ -3845,17 +3908,26 @@ PHP_FUNCTION(pg_send_execute)
38453908
CHECK_PGSQL_LINK(link);
38463909
pgsql = link->conn;
38473910

3848-
is_non_blocking = PQisnonblocking(pgsql);
3911+
#ifdef LIBPQ_HAS_PIPELINING
3912+
is_pipeline_mode = (PQpipelineStatus(pgsql) == PQ_PIPELINE_ON);
3913+
if (is_pipeline_mode) {
3914+
is_non_blocking = 1;
3915+
} else {
3916+
#endif
3917+
is_non_blocking = PQisnonblocking(pgsql);
38493918

3850-
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3851-
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3852-
RETURN_FALSE;
3853-
}
3919+
if (is_non_blocking == 0 && PQsetnonblocking(pgsql, 1) == -1) {
3920+
php_error_docref(NULL, E_NOTICE, "Cannot set connection to nonblocking mode");
3921+
RETURN_FALSE;
3922+
}
38543923

3855-
if (_php_pgsql_link_has_results(pgsql)) {
3856-
php_error_docref(NULL, E_NOTICE,
3857-
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3924+
if (_php_pgsql_link_has_results(pgsql)) {
3925+
php_error_docref(NULL, E_NOTICE,
3926+
"There are results on this connection. Call pg_get_result() until it returns FALSE");
3927+
}
3928+
#ifdef LIBPQ_HAS_PIPELINING
38583929
}
3930+
#endif
38593931

38603932
num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
38613933
if (num_params > 0) {
@@ -3896,7 +3968,15 @@ PHP_FUNCTION(pg_send_execute)
38963968
}
38973969

38983970
if (is_non_blocking) {
3899-
ret = PQflush(pgsql);
3971+
#ifdef LIBPQ_HAS_PIPELINING
3972+
if (is_pipeline_mode) {
3973+
ret = 0;
3974+
} else {
3975+
#endif
3976+
ret = PQflush(pgsql);
3977+
#ifdef LIBPQ_HAS_PIPELINING
3978+
}
3979+
#endif
39003980
} else {
39013981
/* Wait to finish sending buffer */
39023982
while ((ret = PQflush(pgsql))) {
@@ -5891,6 +5971,8 @@ PHP_FUNCTION(pg_enter_pipeline_mode)
58915971
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
58925972
CHECK_PGSQL_LINK(pgsql_handle);
58935973

5974+
PQsetnonblocking(pgsql_handle->conn, 1);
5975+
58945976
RETURN_BOOL(PQenterPipelineMode(pgsql_handle->conn));
58955977
}
58965978

@@ -5906,9 +5988,26 @@ PHP_FUNCTION(pg_exit_pipeline_mode)
59065988
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
59075989
CHECK_PGSQL_LINK(pgsql_handle);
59085990

5991+
PQsetnonblocking(pgsql_handle->conn, 0);
5992+
59095993
RETURN_BOOL(PQexitPipelineMode(pgsql_handle->conn));
59105994
}
59115995

5996+
PHP_FUNCTION(pg_send_flush_request)
5997+
{
5998+
zval *pgsql_link;
5999+
pgsql_link_handle *pgsql_handle;
6000+
6001+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pgsql_link, pgsql_link_ce) == FAILURE) {
6002+
RETURN_THROWS();
6003+
}
6004+
6005+
pgsql_handle = Z_PGSQL_LINK_P(pgsql_link);
6006+
CHECK_PGSQL_LINK(pgsql_handle);
6007+
6008+
RETURN_BOOL(PQsendFlushRequest(pgsql_handle->conn));
6009+
}
6010+
59126011
PHP_FUNCTION(pg_pipeline_sync)
59136012
{
59146013
zval *pgsql_link;

ext/pgsql/pgsql.stub.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ function pg_select(PgSql\Connection $connection, string $table_name, array $cond
966966
#ifdef LIBPQ_HAS_PIPELINING
967967
function pg_enter_pipeline_mode(PgSql\Connection $connection): bool {}
968968
function pg_exit_pipeline_mode(PgSql\Connection $connection): bool {}
969+
function pg_send_flush_request(PgSql\Connection $connection): bool {}
969970
function pg_pipeline_sync(PgSql\Connection $connection): bool {}
970971
function pg_pipeline_status(PgSql\Connection $connection): int {}
971972
#endif

ext/pgsql/pgsql_arginfo.h

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

0 commit comments

Comments
 (0)