From 9051f5f8fceb019c751d1ebcad8ad554f8f59561 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 1 Oct 2024 20:15:37 +0100 Subject: [PATCH 1/3] Fix GH-15893: Pdo\Pgsql backport fixes from GH-16124 --- ext/pdo_pgsql/pgsql_driver.c | 6 +++++- ext/pdo_pgsql/tests/copy_from_iterator.phpt | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 9ce4c6165bd8b..100bba3e709f2 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -712,11 +712,15 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS) } } ZEND_HASH_FOREACH_END(); } else { - iter = Z_OBJ_P(pg_rows)->ce->get_iterator(Z_OBJCE_P(pg_rows), pg_rows, 0); + iter = Z_OBJCE_P(pg_rows)->get_iterator(Z_OBJCE_P(pg_rows), pg_rows, 0); if (iter == NULL || EG(exception)) { RETURN_THROWS(); } + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + } + for (; iter->funcs->valid(iter) == SUCCESS && EG(exception) == NULL; iter->funcs->move_forward(iter)) { tmp = iter->funcs->get_current_data(iter); if (!_pdo_pgsql_send_copy_data(H, tmp)) { diff --git a/ext/pdo_pgsql/tests/copy_from_iterator.phpt b/ext/pdo_pgsql/tests/copy_from_iterator.phpt index 62a8dfe92e5fd..6bd0422413457 100644 --- a/ext/pdo_pgsql/tests/copy_from_iterator.phpt +++ b/ext/pdo_pgsql/tests/copy_from_iterator.phpt @@ -42,6 +42,12 @@ $iterator = new class implements Iterator{ } }; +try { + $db->pgsqlCopyFromArray('test_copy_from_traversable',new stdClass()); +} catch (\TypeError $e) { + echo $e->getMessage() . PHP_EOL; +} + $db->pgsqlCopyFromArray('test_copy_from_traversable',$iterator); $stmt = $db->query("select * from test_copy_from_traversable order by 1"); @@ -56,6 +62,7 @@ $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->query('DROP TABLE IF EXISTS test_copy_from_traversable CASCADE'); ?> --EXPECT-- +PDO::pgsqlCopyFromArray(): Argument #2 ($rows) must be of type array or Traversable array ( 0 => 1, 1 => 1, From fd7cb5216c52dff2ff027dae64b74a90acc34946 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 2 Oct 2024 12:20:22 +0100 Subject: [PATCH 2/3] ZPP -> fZPP --- ext/pdo_pgsql/pgsql_driver.c | 18 ++++++++---------- ext/pdo_pgsql/tests/copy_from_iterator.phpt | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 100bba3e709f2..acaf9a023f718 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -657,16 +657,14 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS) PGresult *pgsql_result; ExecStatusType status; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sA|sss!", - &table_name, &table_name_len, &pg_rows, - &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) { - RETURN_THROWS(); - } - - if ((Z_TYPE_P(pg_rows) != IS_ARRAY && !instanceof_function(Z_OBJCE_P(pg_rows), zend_ce_traversable))) { - zend_argument_type_error(2, "must be of type array or Traversable"); - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 5) + Z_PARAM_STRING(table_name, table_name_len) + Z_PARAM_ITERABLE(pg_rows) + Z_PARAM_OPTIONAL + Z_PARAM_STRING(pg_delim, pg_delim_len) + Z_PARAM_STRING_OR_NULL(pg_null_as, pg_null_as_len) + Z_PARAM_STRING(pg_fields, pg_fields_len) + ZEND_PARSE_PARAMETERS_END(); dbh = Z_PDO_DBH_P(ZEND_THIS); PDO_CONSTRUCT_CHECK; diff --git a/ext/pdo_pgsql/tests/copy_from_iterator.phpt b/ext/pdo_pgsql/tests/copy_from_iterator.phpt index 6bd0422413457..b507af8914628 100644 --- a/ext/pdo_pgsql/tests/copy_from_iterator.phpt +++ b/ext/pdo_pgsql/tests/copy_from_iterator.phpt @@ -62,7 +62,7 @@ $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->query('DROP TABLE IF EXISTS test_copy_from_traversable CASCADE'); ?> --EXPECT-- -PDO::pgsqlCopyFromArray(): Argument #2 ($rows) must be of type array or Traversable +PDO::pgsqlCopyFromArray(): Argument #2 ($rows) must be of type Traversable|array, stdClass given array ( 0 => 1, 1 => 1, From d2a991809ccb114c320913d5bc9c4cdf95d66eed Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 3 Oct 2024 12:26:49 +0100 Subject: [PATCH 3/3] changes from feedback --- ext/pdo_pgsql/pgsql_driver.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index acaf9a023f718..f29b4ca973cc6 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -662,8 +662,8 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS) Z_PARAM_ITERABLE(pg_rows) Z_PARAM_OPTIONAL Z_PARAM_STRING(pg_delim, pg_delim_len) - Z_PARAM_STRING_OR_NULL(pg_null_as, pg_null_as_len) - Z_PARAM_STRING(pg_fields, pg_fields_len) + Z_PARAM_STRING(pg_null_as, pg_null_as_len) + Z_PARAM_STRING_OR_NULL(pg_fields, pg_fields_len) ZEND_PARSE_PARAMETERS_END(); dbh = Z_PDO_DBH_P(ZEND_THIS); @@ -717,6 +717,9 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS) if (iter->funcs->rewind) { iter->funcs->rewind(iter); + if (EG(exception)) { + RETURN_THROWS(); + } } for (; iter->funcs->valid(iter) == SUCCESS && EG(exception) == NULL; iter->funcs->move_forward(iter)) {