@@ -273,6 +273,8 @@ static void pgsql_lob_free_obj(zend_object *obj)
273273
274274/* Compatibility definitions */
275275
276+ static inline zend_result build_tablename (smart_str * querystr , PGconn * pg_link , const zend_string * table );
277+
276278static zend_string * _php_pgsql_trim_message (const char * message )
277279{
278280 size_t i = strlen (message );
@@ -3347,9 +3349,8 @@ PHP_FUNCTION(pg_copy_to)
33473349 pgsql_link_handle * link ;
33483350 zend_string * table_name ;
33493351 zend_string * pg_delimiter = NULL ;
3350- char * pg_null_as = "\\\\N" ;
3351- size_t pg_null_as_len = 0 ;
3352- char * query ;
3352+ char * pg_null_as = "\\N" ;
3353+ size_t pg_null_as_len = sizeof ("\\N" ) - 1 ;
33533354 PGconn * pgsql ;
33543355 PGresult * pgsql_result ;
33553356 ExecStatusType status ;
@@ -3373,14 +3374,44 @@ PHP_FUNCTION(pg_copy_to)
33733374 zend_argument_value_error (3 , "must be one character" );
33743375 RETURN_THROWS ();
33753376 }
3377+ smart_str querystr = {0 };
3378+ smart_str_appends (& querystr , "COPY " );
3379+ if (ZSTR_LEN (table_name ) > 0 && ZSTR_VAL (table_name )[0 ] == '(' ) {
3380+ smart_str_appendc (& querystr , '(' );
3381+ smart_str_append (& querystr , table_name );
3382+ smart_str_appendc (& querystr , ')' );
3383+ } else if (build_tablename (& querystr , pgsql , table_name ) == FAILURE ) {
3384+ smart_str_free (& querystr );
3385+ RETURN_FALSE ;
3386+ }
33763387
3377- spprintf (& query , 0 , "COPY %s TO STDOUT DELIMITER E'%c' NULL AS E'%s'" , ZSTR_VAL (table_name ), * ZSTR_VAL (pg_delimiter ), pg_null_as );
3388+ char * escaped_delimiter = PQescapeLiteral (pgsql , ZSTR_VAL (pg_delimiter ), 1 );
3389+ if (!escaped_delimiter ) {
3390+ zend_string * msgbuf = _php_pgsql_trim_message (PQerrorMessage (pgsql ));
3391+ php_error_docref (NULL , E_WARNING , "Failed to escape delimiter '%c': %s" , * ZSTR_VAL (pg_delimiter ), ZSTR_VAL (msgbuf ));
3392+ zend_string_release (msgbuf );
3393+ smart_str_free (& querystr );
3394+ RETURN_FALSE ;
3395+ }
3396+ char * escaped_null_as = PQescapeLiteral (pgsql , pg_null_as , pg_null_as_len );
3397+ if (!escaped_null_as ) {
3398+ zend_string * msgbuf = _php_pgsql_trim_message (PQerrorMessage (pgsql ));
3399+ php_error_docref (NULL , E_WARNING , "Failed to escape null_as '%s': %s" , pg_null_as , ZSTR_VAL (msgbuf ));
3400+ zend_string_release (msgbuf );
3401+ PQfreemem (escaped_delimiter );
3402+ smart_str_free (& querystr );
3403+ RETURN_FALSE ;
3404+ }
3405+ smart_str_append_printf (& querystr , " TO STDOUT DELIMITER %s NULL AS %s" , escaped_delimiter , escaped_null_as );
3406+ smart_str_0 (& querystr );
3407+ PQfreemem (escaped_delimiter );
3408+ PQfreemem (escaped_null_as );
33783409
33793410 while ((pgsql_result = PQgetResult (pgsql ))) {
33803411 PQclear (pgsql_result );
33813412 }
3382- pgsql_result = PQexec (pgsql , query );
3383- efree ( query );
3413+ pgsql_result = PQexec (pgsql , ZSTR_VAL ( querystr . s ) );
3414+ smart_str_free ( & querystr );
33843415
33853416 if (pgsql_result ) {
33863417 status = PQresultStatus (pgsql_result );
@@ -3462,9 +3493,8 @@ PHP_FUNCTION(pg_copy_from)
34623493 zval * value ;
34633494 zend_string * table_name ;
34643495 zend_string * pg_delimiter = NULL ;
3465- char * pg_null_as = "\\\\N" ;
3466- size_t pg_null_as_len ;
3467- char * query ;
3496+ char * pg_null_as = "\\N" ;
3497+ size_t pg_null_as_len = sizeof ("\\N" ) - 1 ;
34683498 PGconn * pgsql ;
34693499 PGresult * pgsql_result ;
34703500 ExecStatusType status ;
@@ -3488,14 +3518,41 @@ PHP_FUNCTION(pg_copy_from)
34883518 zend_argument_value_error (4 , "must be one character" );
34893519 RETURN_THROWS ();
34903520 }
3521+ smart_str querystr = {0 };
3522+ smart_str_appends (& querystr , "COPY " );
3523+ if (build_tablename (& querystr , pgsql , table_name ) == FAILURE ) {
3524+ smart_str_free (& querystr );
3525+ RETURN_FALSE ;
3526+ }
3527+
3528+ char * escaped_delimiter = PQescapeLiteral (pgsql , ZSTR_VAL (pg_delimiter ), 1 );
3529+ if (!escaped_delimiter ) {
3530+ zend_string * msgbuf = _php_pgsql_trim_message (PQerrorMessage (pgsql ));
3531+ php_error_docref (NULL , E_WARNING , "Failed to escape delimiter '%c': %s" , * ZSTR_VAL (pg_delimiter ), ZSTR_VAL (msgbuf ));
3532+ zend_string_release (msgbuf );
3533+ smart_str_free (& querystr );
3534+ RETURN_FALSE ;
3535+ }
3536+ char * escaped_null_as = PQescapeLiteral (pgsql , pg_null_as , pg_null_as_len );
3537+ if (!escaped_null_as ) {
3538+ zend_string * msgbuf = _php_pgsql_trim_message (PQerrorMessage (pgsql ));
3539+ php_error_docref (NULL , E_WARNING , "Failed to escape null_as '%s': %s" , pg_null_as , ZSTR_VAL (msgbuf ));
3540+ zend_string_release (msgbuf );
3541+ PQfreemem (escaped_delimiter );
3542+ smart_str_free (& querystr );
3543+ RETURN_FALSE ;
3544+ }
3545+ smart_str_append_printf (& querystr , " FROM STDIN DELIMITER %s NULL AS %s" , escaped_delimiter , escaped_null_as );
3546+ smart_str_0 (& querystr );
3547+ PQfreemem (escaped_delimiter );
3548+ PQfreemem (escaped_null_as );
34913549
3492- spprintf (& query , 0 , "COPY %s FROM STDIN DELIMITER E'%c' NULL AS E'%s'" , ZSTR_VAL (table_name ), * ZSTR_VAL (pg_delimiter ), pg_null_as );
34933550 while ((pgsql_result = PQgetResult (pgsql ))) {
34943551 PQclear (pgsql_result );
34953552 }
3496- pgsql_result = PQexec (pgsql , query );
3553+ pgsql_result = PQexec (pgsql , ZSTR_VAL ( querystr . s ) );
34973554
3498- efree ( query );
3555+ smart_str_free ( & querystr );
34993556
35003557 if (pgsql_result ) {
35013558 status = PQresultStatus (pgsql_result );
@@ -5574,7 +5631,9 @@ static inline zend_result build_tablename(smart_str *querystr, PGconn *pg_link,
55745631 } else {
55755632 char * escaped = PQescapeIdentifier (pg_link , ZSTR_VAL (table ), len );
55765633 if (escaped == NULL ) {
5577- php_error_docref (NULL , E_NOTICE , "Failed to escape table name '%s'" , ZSTR_VAL (table ));
5634+ zend_string * msgbuf = _php_pgsql_trim_message (PQerrorMessage (pg_link ));
5635+ php_error_docref (NULL , E_WARNING , "Failed to escape table name '%s': %s" , ZSTR_VAL (table ), ZSTR_VAL (msgbuf ));
5636+ zend_string_release (msgbuf );
55785637 return FAILURE ;
55795638 }
55805639 smart_str_appends (querystr , escaped );
@@ -5590,7 +5649,9 @@ static inline zend_result build_tablename(smart_str *querystr, PGconn *pg_link,
55905649 } else {
55915650 char * escaped = PQescapeIdentifier (pg_link , after_dot , len );
55925651 if (escaped == NULL ) {
5593- php_error_docref (NULL , E_NOTICE , "Failed to escape table name '%s'" , ZSTR_VAL (table ));
5652+ zend_string * msgbuf = _php_pgsql_trim_message (PQerrorMessage (pg_link ));
5653+ php_error_docref (NULL , E_WARNING , "Failed to escape table name '%s': %s" , ZSTR_VAL (table ), ZSTR_VAL (msgbuf ));
5654+ zend_string_release (msgbuf );
55945655 return FAILURE ;
55955656 }
55965657 smart_str_appendc (querystr , '.' );
0 commit comments