diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 905f8ea871601..4d72cdebec8aa 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -174,6 +174,9 @@ static void pgsql_link_free(pgsql_link_handle *link) link->conn = NULL; zend_string_release(link->hash); + if (link->notices) { + zend_hash_destroy(link->notices); + } } static void pgsql_link_free_obj(zend_object *obj) @@ -310,26 +313,28 @@ static void _close_pgsql_plink(zend_resource *rsrc) PGG(num_links)--; } -static void _php_pgsql_notice_handler(void *resource_id, const char *message) +static void _php_pgsql_notice_handler(void *link, const char *message) { - zval *notices; + HashTable *notices, tmp_notices; zval tmp; - char *trimed_message; - size_t trimed_message_len; + char *trimmed_message; + size_t trimmed_message_len; if (! PGG(ignore_notices)) { - notices = zend_hash_index_find(&PGG(notices), (zend_ulong)resource_id); + notices = ((pgsql_link_handle *) link)->notices; if (!notices) { - array_init(&tmp); - notices = &tmp; - zend_hash_index_update(&PGG(notices), (zend_ulong)resource_id, notices); + zend_hash_init(&tmp_notices, 1, NULL, ZVAL_PTR_DTOR, 0); + notices = &tmp_notices; } - trimed_message = _php_pgsql_trim_message(message, &trimed_message_len); + trimmed_message = _php_pgsql_trim_message(message, &trimmed_message_len); if (PGG(log_notices)) { - php_error_docref(NULL, E_NOTICE, "%s", trimed_message); + php_error_docref(NULL, E_NOTICE, "%s", trimmed_message); } - add_next_index_stringl(notices, trimed_message, trimed_message_len); - efree(trimed_message); + + ZVAL_STRINGL(&tmp, trimmed_message, trimmed_message_len); + zend_hash_next_index_insert(notices, &tmp); + efree(trimmed_message); + zval_ptr_dtor(&tmp); } } @@ -409,7 +414,6 @@ static PHP_GINIT_FUNCTION(pgsql) #endif memset(pgsql_globals, 0, sizeof(zend_pgsql_globals)); /* Initialize notice message hash at MINIT only */ - zend_hash_init(&pgsql_globals->notices, 0, NULL, ZVAL_PTR_DTOR, 1); zend_hash_init(&pgsql_globals->regular_list, 0, NULL, ZVAL_PTR_DTOR, 1); } @@ -581,7 +585,6 @@ PHP_MINIT_FUNCTION(pgsql) PHP_MSHUTDOWN_FUNCTION(pgsql) { UNREGISTER_INI_ENTRIES(); - zend_hash_destroy(&PGG(notices)); zend_hash_destroy(&PGG(regular_list)); return SUCCESS; @@ -597,7 +600,6 @@ PHP_RINIT_FUNCTION(pgsql) PHP_RSHUTDOWN_FUNCTION(pgsql) { /* clean up notice messages */ - zend_hash_clean(&PGG(notices)); zend_hash_clean(&PGG(regular_list)); /* clean up persistent connection */ zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions); @@ -716,6 +718,8 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) object_init_ex(return_value, pgsql_link_ce); link = Z_PGSQL_LINK_P(return_value); link->conn = pgsql; + link->hash = zend_string_copy(str.s); + link->notices = NULL; } else { /* Non persistent connection */ zval *index_ptr, new_index_ptr; @@ -762,6 +766,7 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) link = Z_PGSQL_LINK_P(return_value); link->conn = pgsql; link->hash = zend_string_copy(str.s); + link->notices = NULL; /* add it to the hash */ ZVAL_COPY(&new_index_ptr, return_value); @@ -776,9 +781,9 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) } /* set notice processor */ if (! PGG(ignore_notices) && Z_TYPE_P(return_value) == IS_OBJECT) { - PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void*)(zend_uintptr_t)Z_OBJ_P(return_value)->handle); + PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, link); } - php_pgsql_set_default_link(pgsql_link_from_obj(Z_OBJ_P(return_value))); + php_pgsql_set_default_link(link); cleanup: smart_str_free(&str); @@ -1497,7 +1502,8 @@ PHP_FUNCTION(pg_affected_rows) PHP_FUNCTION(pg_last_notice) { zval *pgsql_link = NULL; - zval *notice, *notices; + zval *notice; + HashTable *notices; pgsql_link_handle *link; zend_long option = PGSQL_NOTICE_LAST; @@ -1508,12 +1514,12 @@ PHP_FUNCTION(pg_last_notice) link = Z_PGSQL_LINK_P(pgsql_link); CHECK_PGSQL_LINK(link); - notices = zend_hash_index_find(&PGG(notices), (zend_ulong) Z_OBJ_P(pgsql_link)->handle); + notices = link->notices; switch (option) { case PGSQL_NOTICE_LAST: if (notices) { - zend_hash_internal_pointer_end(Z_ARRVAL_P(notices)); - if ((notice = zend_hash_get_current_data(Z_ARRVAL_P(notices))) == NULL) { + zend_hash_internal_pointer_end(notices); + if ((notice = zend_hash_get_current_data(notices)) == NULL) { RETURN_EMPTY_STRING(); } RETURN_COPY(notice); @@ -1523,7 +1529,7 @@ PHP_FUNCTION(pg_last_notice) break; case PGSQL_NOTICE_ALL: if (notices) { - RETURN_COPY(notices); + RETURN_ARR(zend_array_dup(notices)); } else { array_init(return_value); return; @@ -1531,7 +1537,7 @@ PHP_FUNCTION(pg_last_notice) break; case PGSQL_NOTICE_CLEAR: if (notices) { - zend_hash_clean(&PGG(notices)); + zend_hash_clean(link->notices); } RETURN_TRUE; break; diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h index 5b73c7af28440..eda16446670e6 100644 --- a/ext/pgsql/php_pgsql.h +++ b/ext/pgsql/php_pgsql.h @@ -147,6 +147,7 @@ typedef enum _php_pgsql_data_type { typedef struct pgsql_link_handle { PGconn *conn; zend_string *hash; + HashTable *notices; zend_object std; } pgsql_link_handle; @@ -186,7 +187,6 @@ ZEND_BEGIN_MODULE_GLOBALS(pgsql) zend_long allow_persistent; zend_long auto_reset_persistent; int ignore_notices,log_notices; - HashTable notices; /* notice message for each connection */ pgsql_link_handle *default_link; /* default link when connection is omitted */ HashTable regular_list; /* connection list */ ZEND_END_MODULE_GLOBALS(pgsql)