diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 9ce4c6165bd8b..f29b4ca973cc6 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(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); PDO_CONSTRUCT_CHECK; @@ -712,11 +710,18 @@ 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); + if (EG(exception)) { + RETURN_THROWS(); + } + } + 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..b507af8914628 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 Traversable|array, stdClass given array ( 0 => 1, 1 => 1,