3838#include "php_globals.h"
3939#include "zend_exceptions.h"
4040#include "zend_attributes.h"
41+ #include "zend_interfaces.h"
4142#include "php_network.h"
4243
4344#ifdef HAVE_PGSQL
@@ -3357,6 +3358,29 @@ PHP_FUNCTION(pg_copy_to)
33573358}
33583359/* }}} */
33593360
3361+ static zend_result pgsql_copy_from_query (PGconn * pgsql , PGresult * pgsql_result , zval * value )
3362+ {
3363+ zend_string * tmp = zval_try_get_string (value );
3364+ if (UNEXPECTED (!tmp )) {
3365+ return FAILURE ;
3366+ }
3367+ zend_string * zquery = zend_string_alloc (ZSTR_LEN (tmp ) + 1 , false);
3368+ memcpy (ZSTR_VAL (zquery ), ZSTR_VAL (tmp ), ZSTR_LEN (tmp ) + 1 );
3369+ ZSTR_LEN (zquery ) = ZSTR_LEN (tmp );
3370+ if (ZSTR_LEN (tmp ) > 0 && ZSTR_VAL (zquery )[ZSTR_LEN (tmp )] != '\n' ) {
3371+ ZSTR_VAL (zquery )[ZSTR_LEN (tmp )] = '\n' ;
3372+ ZSTR_LEN (zquery ) ++ ;
3373+ }
3374+ if (PQputCopyData (pgsql , ZSTR_VAL (zquery ), ZSTR_LEN (zquery )) != 1 ) {
3375+ zend_string_release_ex (zquery , false);
3376+ zend_string_release (tmp );
3377+ return FAILURE ;
3378+ }
3379+ zend_string_release_ex (zquery , false);
3380+ zend_string_release (tmp );
3381+ return SUCCESS ;
3382+ }
3383+
33603384/* {{{ Copy table from array */
33613385PHP_FUNCTION (pg_copy_from )
33623386{
@@ -3376,7 +3400,7 @@ PHP_FUNCTION(pg_copy_from)
33763400 ZEND_PARSE_PARAMETERS_START (3 , 5 )
33773401 Z_PARAM_OBJECT_OF_CLASS (pgsql_link , pgsql_link_ce )
33783402 Z_PARAM_PATH_STR (table_name )
3379- Z_PARAM_ARRAY (pg_rows )
3403+ Z_PARAM_ITERABLE (pg_rows )
33803404 Z_PARAM_OPTIONAL
33813405 Z_PARAM_STR (pg_delimiter )
33823406 Z_PARAM_STRING (pg_null_as , pg_null_as_len )
@@ -3417,38 +3441,44 @@ PHP_FUNCTION(pg_copy_from)
34173441 switch (status ) {
34183442 case PGRES_COPY_IN :
34193443 if (pgsql_result ) {
3420- int command_failed = 0 ;
34213444 PQclear (pgsql_result );
3422- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pg_rows ), value ) {
3423- zend_string * tmp = zval_try_get_string (value );
3424- if (UNEXPECTED (!tmp )) {
3425- return ;
3426- }
3427- zend_string * zquery = zend_string_alloc (ZSTR_LEN (tmp ) + 1 , false);
3428- memcpy (ZSTR_VAL (zquery ), ZSTR_VAL (tmp ), ZSTR_LEN (tmp ) + 1 );
3429- ZSTR_LEN (zquery ) = ZSTR_LEN (tmp );
3430- if (ZSTR_LEN (tmp ) > 0 && ZSTR_VAL (zquery )[ZSTR_LEN (tmp )] != '\n' ) {
3431- ZSTR_VAL (zquery )[ZSTR_LEN (tmp )] = '\n' ;
3432- ZSTR_LEN (zquery ) ++ ;
3445+ bool command_failed = false;
3446+ if (Z_TYPE_P (pg_rows ) == IS_ARRAY ) {
3447+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pg_rows ), value ) {
3448+ if (pgsql_copy_from_query (pgsql , pgsql_result , value ) == FAILURE ) {
3449+ PHP_PQ_ERROR ("copy failed: %s" , pgsql );
3450+ RETURN_FALSE ;
3451+ }
3452+ } ZEND_HASH_FOREACH_END ();
3453+ } else {
3454+ zend_object_iterator * iter = Z_OBJCE_P (pg_rows )-> get_iterator (Z_OBJCE_P (pg_rows ), pg_rows , 0 );
3455+ if (UNEXPECTED (EG (exception ) || iter == NULL )) {
3456+ RETURN_THROWS ();
34333457 }
3434- if (PQputCopyData (pgsql , ZSTR_VAL (zquery ), ZSTR_LEN (zquery )) != 1 ) {
3435- zend_string_release_ex (zquery , false);
3436- zend_string_release (tmp );
3437- PHP_PQ_ERROR ("copy failed: %s" , pgsql );
3438- RETURN_FALSE ;
3458+
3459+ if (iter -> funcs -> rewind ) {
3460+ iter -> funcs -> rewind (iter );
34393461 }
3440- zend_string_release_ex (zquery , false);
3441- zend_string_release (tmp );
3442- } ZEND_HASH_FOREACH_END ();
34433462
3463+ while (iter -> funcs -> valid (iter ) == SUCCESS && EG (exception ) == NULL ) {
3464+ zval * value = iter -> funcs -> get_current_data (iter );
3465+ if (pgsql_copy_from_query (pgsql , pgsql_result , value ) == FAILURE ) {
3466+ zend_iterator_dtor (iter );
3467+ PHP_PQ_ERROR ("copy failed: %s" , pgsql );
3468+ RETURN_FALSE ;
3469+ }
3470+ iter -> funcs -> move_forward (iter );
3471+ }
3472+ zend_iterator_dtor (iter );
3473+ }
34443474 if (PQputCopyEnd (pgsql , NULL ) != 1 ) {
34453475 PHP_PQ_ERROR ("putcopyend failed: %s" , pgsql );
34463476 RETURN_FALSE ;
34473477 }
34483478 while ((pgsql_result = PQgetResult (pgsql ))) {
34493479 if (PGRES_COMMAND_OK != PQresultStatus (pgsql_result )) {
34503480 PHP_PQ_ERROR ("Copy command failed: %s" , pgsql );
3451- command_failed = 1 ;
3481+ command_failed = true ;
34523482 }
34533483 PQclear (pgsql_result );
34543484 }
0 commit comments