38
38
#include "php_globals.h"
39
39
#include "zend_exceptions.h"
40
40
#include "zend_attributes.h"
41
+ #include "zend_interfaces.h"
41
42
#include "php_network.h"
42
43
43
44
#ifdef HAVE_PGSQL
@@ -3357,6 +3358,29 @@ PHP_FUNCTION(pg_copy_to)
3357
3358
}
3358
3359
/* }}} */
3359
3360
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
+
3360
3384
/* {{{ Copy table from array */
3361
3385
PHP_FUNCTION (pg_copy_from )
3362
3386
{
@@ -3376,7 +3400,7 @@ PHP_FUNCTION(pg_copy_from)
3376
3400
ZEND_PARSE_PARAMETERS_START (3 , 5 )
3377
3401
Z_PARAM_OBJECT_OF_CLASS (pgsql_link , pgsql_link_ce )
3378
3402
Z_PARAM_PATH_STR (table_name )
3379
- Z_PARAM_ARRAY (pg_rows )
3403
+ Z_PARAM_ARRAY_OR_OBJECT (pg_rows )
3380
3404
Z_PARAM_OPTIONAL
3381
3405
Z_PARAM_STR (pg_delimiter )
3382
3406
Z_PARAM_STRING (pg_null_as , pg_null_as_len )
@@ -3392,6 +3416,10 @@ PHP_FUNCTION(pg_copy_from)
3392
3416
zend_argument_value_error (4 , "must be one character" );
3393
3417
RETURN_THROWS ();
3394
3418
}
3419
+ if (Z_TYPE_P (pg_rows ) == IS_OBJECT && !instanceof_function (Z_OBJCE_P (pg_rows ), zend_ce_traversable )) {
3420
+ zend_argument_type_error (3 , "must be of type Traversable" );
3421
+ RETURN_THROWS ();
3422
+ }
3395
3423
if (!pg_null_as ) {
3396
3424
pg_null_as = estrdup ("\\\\N" );
3397
3425
pg_null_as_free = true;
@@ -3417,38 +3445,40 @@ PHP_FUNCTION(pg_copy_from)
3417
3445
switch (status ) {
3418
3446
case PGRES_COPY_IN :
3419
3447
if (pgsql_result ) {
3420
- int command_failed = 0 ;
3421
3448
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 ) ++ ;
3433
- }
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 ;
3449
+ bool command_failed = false;
3450
+ if (Z_TYPE_P (pg_rows ) == IS_ARRAY ) {
3451
+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pg_rows ), value ) {
3452
+ if (pgsql_copy_from_query (pgsql , pgsql_result , value ) == FAILURE ) {
3453
+ PHP_PQ_ERROR ("copy failed: %s" , pgsql );
3454
+ RETURN_FALSE ;
3455
+ }
3456
+ } ZEND_HASH_FOREACH_END ();
3457
+ } else {
3458
+ zend_object_iterator * iter = Z_OBJ_P (pg_rows )-> ce -> get_iterator (Z_OBJCE_P (pg_rows ), pg_rows , 0 );
3459
+ if (UNEXPECTED (EG (exception ) || iter == NULL )) {
3460
+ RETURN_THROWS ();
3439
3461
}
3440
- zend_string_release_ex (zquery , false);
3441
- zend_string_release (tmp );
3442
- } ZEND_HASH_FOREACH_END ();
3443
3462
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
+ }
3444
3474
if (PQputCopyEnd (pgsql , NULL ) != 1 ) {
3445
3475
PHP_PQ_ERROR ("putcopyend failed: %s" , pgsql );
3446
3476
RETURN_FALSE ;
3447
3477
}
3448
3478
while ((pgsql_result = PQgetResult (pgsql ))) {
3449
3479
if (PGRES_COMMAND_OK != PQresultStatus (pgsql_result )) {
3450
3480
PHP_PQ_ERROR ("Copy command failed: %s" , pgsql );
3451
- command_failed = 1 ;
3481
+ command_failed = true ;
3452
3482
}
3453
3483
PQclear (pgsql_result );
3454
3484
}
0 commit comments