php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #78621
Patch pgsqlSetNoticeCallback.8.diff revision 2021-03-11 17:35 UTC by guillaume-php at outters dot eu
Patch pgsqlSetNoticeCallback.7.diff revision 2019-10-02 05:05 UTC by guillaume-php at outters dot eu

Patch pgsqlSetNoticeCallback.8.diff for PDO PgSQL Bug #78621

Patch version 2021-03-11 17:35 UTC

Return to Bug #78621 | Download this patch
Patch Revisions:

Developer: guillaume-php@outters.eu

diff -ruw ext/pdo_pgsql/pgsql_driver.stub.php ext/pdo_pgsql/pgsql_driver.stub.php
--- ext/pdo_pgsql/pgsql_driver.stub.php	2021-03-09 07:46:54.779841000 +0100
+++ ext/pdo_pgsql/pgsql_driver.stub.php	2021-03-09 07:52:52.415093000 +0100
@@ -30,4 +30,10 @@
 
     /** @return int */
     public function pgsqlGetPid() {}
+
+	/**
+     * @param callable|null $callback
+     * @return bool
+     */
+    public function pgsqlSetNoticeCallback($callback) {}
 }
diff -ruw ext/pdo_pgsql/pgsql_driver_arginfo.h ext/pdo_pgsql/pgsql_driver_arginfo.h
--- ext/pdo_pgsql/pgsql_driver_arginfo.h	2015-09-01 22:09:37.000000000 +0200
+++ ext/pdo_pgsql/pgsql_driver_arginfo.h	2019-10-01 05:18:31.085807000 +0200
@@ -45,6 +45,10 @@
 
 #define arginfo_class_PDO_PGSql_Ext_pgsqlGetPid arginfo_class_PDO_PGSql_Ext_pgsqlLOBCreate
 
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_PDO_PGSql_Ext_pgsqlSetNoticeCallback, 0, 1, _IS_BOOL, 0)
+	ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 1)
+ZEND_END_ARG_INFO()
+
 
 ZEND_METHOD(PDO_PGSql_Ext, pgsqlCopyFromArray);
 ZEND_METHOD(PDO_PGSql_Ext, pgsqlCopyFromFile);
@@ -55,6 +59,7 @@
 ZEND_METHOD(PDO_PGSql_Ext, pgsqlLOBUnlink);
 ZEND_METHOD(PDO_PGSql_Ext, pgsqlGetNotify);
 ZEND_METHOD(PDO_PGSql_Ext, pgsqlGetPid);
+ZEND_METHOD(PDO_PGSql_Ext, pgsqlSetNoticeCallback);
 
 
 static const zend_function_entry class_PDO_PGSql_Ext_methods[] = {
@@ -67,5 +72,6 @@
 	ZEND_ME(PDO_PGSql_Ext, pgsqlLOBUnlink, arginfo_class_PDO_PGSql_Ext_pgsqlLOBUnlink, ZEND_ACC_PUBLIC)
 	ZEND_ME(PDO_PGSql_Ext, pgsqlGetNotify, arginfo_class_PDO_PGSql_Ext_pgsqlGetNotify, ZEND_ACC_PUBLIC)
 	ZEND_ME(PDO_PGSql_Ext, pgsqlGetPid, arginfo_class_PDO_PGSql_Ext_pgsqlGetPid, ZEND_ACC_PUBLIC)
+	ZEND_ME(PDO_PGSql_Ext, pgsqlSetNoticeCallback, arginfo_class_PDO_PGSql_Ext_pgsqlSetNoticeCallback, ZEND_ACC_PUBLIC)
 	ZEND_FE_END
 };
diff -ruw ext/pdo_pgsql/pgsql_driver.c ext/pdo_pgsql/pgsql_driver.c
--- ext/pdo_pgsql/pgsql_driver.c	2015-09-01 22:09:37.000000000 +0200
+++ ext/pdo_pgsql/pgsql_driver.c	2019-10-01 05:18:31.085807000 +0200
@@ -103,7 +103,23 @@
 
 static void _pdo_pgsql_notice(pdo_dbh_t *dbh, const char *message) /* {{{ */
 {
-/*	pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; */
+	int ret;
+	zval zarg;
+	zval retval;
+	pdo_pgsql_fci * fc;
+	if ((fc = ((pdo_pgsql_db_handle *)dbh->driver_data)->notice_callback)) {
+		ZVAL_STRINGL(&zarg, (char *) message, strlen(message));
+		fc->fci.param_count = 1;
+		fc->fci.params = &zarg;
+		fc->fci.retval = &retval;
+		if ((ret = zend_call_function(&fc->fci, &fc->fcc)) != FAILURE) {
+			zval_ptr_dtor(&retval);
+		}
+		zval_ptr_dtor(&zarg);
+		if (ret == FAILURE) {
+			pdo_raise_impl_error(dbh, NULL, "HY000", "could not call user-supplied function");
+		}
+	}
 }
 /* }}} */
 
@@ -125,6 +141,16 @@
 }
 /* }}} */
 
+static void pdo_pgsql_cleanup_notice_callback(pdo_pgsql_db_handle *H) /* {{{ */
+{
+	if (H->notice_callback) {
+		zval_ptr_dtor(&H->notice_callback->fci.function_name);
+		efree(H->notice_callback);
+		H->notice_callback = NULL;
+	}
+}
+/* }}} */
+
 /* {{{ pdo_pgsql_create_lob_stream */
 static ssize_t pgsql_lob_write(php_stream *stream, const char *buf, size_t count)
 {
@@ -207,6 +233,7 @@
 {
 	pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
 	if (H) {
+		pdo_pgsql_cleanup_notice_callback(H);
 		if (H->server) {
 			PQfinish(H->server);
 			H->server = NULL;
@@ -1140,6 +1167,53 @@
 }
 /* }}} */
 
+/* {{{ proto bool PDO::pgsqlSetNoticeCallback(mixed callback)
+   Sets a callback to receive DB notices (after client_min_messages has been set) */
+PHP_METHOD(PDO_PGSql_Ext, pgsqlSetNoticeCallback)
+{
+	zval *callback;
+	zend_string *cbname;
+	pdo_dbh_t *dbh;
+	pdo_pgsql_db_handle *H;
+	pdo_pgsql_fci *fc;
+
+	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "z", &callback)) {
+		RETURN_FALSE;
+	}
+	
+	dbh = Z_PDO_DBH_P(getThis());
+	PDO_CONSTRUCT_CHECK;
+	
+	H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+	if (Z_TYPE_P(callback) == IS_NULL) {
+		pdo_pgsql_cleanup_notice_callback(H);
+		RETURN_TRUE;
+	} else {
+		if (!(fc = H->notice_callback)) {
+			fc = (pdo_pgsql_fci*)ecalloc(1, sizeof(pdo_pgsql_fci));
+		} else {
+			zval_ptr_dtor(&fc->fci.function_name);
+			memcpy(&fc->fcc, &empty_fcall_info_cache, sizeof(fc->fcc));
+		}
+
+		if (FAILURE == zend_fcall_info_init(callback, 0, &fc->fci, &fc->fcc, &cbname, NULL)) {
+			php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
+			zend_string_release_ex(cbname, 0);
+			efree(fc);
+			H->notice_callback = NULL;
+			RETURN_FALSE;
+		}
+		Z_TRY_ADDREF_P(&fc->fci.function_name);
+		zend_string_release_ex(cbname, 0);
+
+		H->notice_callback = fc;
+
+		RETURN_TRUE;
+	}
+}
+/* }}} */
+
 static const zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, int kind)
 {
 	switch (kind) {
@@ -1248,7 +1322,7 @@
 		goto cleanup;
 	}
 
-	PQsetNoticeProcessor(H->server, (void(*)(void*,const char*))_pdo_pgsql_notice, (void *)&dbh);
+	PQsetNoticeProcessor(H->server, (void(*)(void*,const char*))_pdo_pgsql_notice, (void *)dbh);
 
 	H->attached = 1;
 	H->pgoid = -1;
diff -ruw ext/pdo_pgsql/php_pdo_pgsql_int.h ext/pdo_pgsql/php_pdo_pgsql_int.h
--- ext/pdo_pgsql/php_pdo_pgsql_int.h	2015-09-01 22:09:37.000000000 +0200
+++ ext/pdo_pgsql/php_pdo_pgsql_int.h	2019-10-01 05:18:31.085743000 +0200
@@ -32,6 +32,11 @@
 	char *errmsg;
 } pdo_pgsql_error_info;
 
+typedef struct {
+	zend_fcall_info fci;
+	zend_fcall_info_cache fcc;
+} pdo_pgsql_fci;
+
 /* stuff we use in a pgsql database handle */
 typedef struct {
 	PGconn		*server;
@@ -45,6 +50,7 @@
 	zend_bool       emulate_prepares;
 	zend_bool       disable_native_prepares; /* deprecated since 5.6 */
 	zend_bool       disable_prepares;
+	pdo_pgsql_fci * notice_callback;
 } pdo_pgsql_db_handle;
 
 typedef struct {
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 17:01:28 2024 UTC