diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index e0c46a5427bcb..be0bbbc919b25 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -613,6 +613,8 @@ public function next(): bool {} final class mysqli_sql_exception extends RuntimeException { protected string $sqlstate = "00000"; + + public function getSqlState(): string {} } /** @refcount 1 */ diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 4cd285e347f47..a0168a51c7a98 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e9f4dd04e7d01864c38033bcaf5e03b63e191deb */ + * Stub hash: 78662c05cd463735a8a4101c0357fd0d2698d48e */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) @@ -720,6 +720,9 @@ ZEND_END_ARG_INFO() #define arginfo_class_mysqli_warning_next arginfo_mysqli_thread_safe +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_mysqli_sql_exception_getSqlState, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(mysqli_affected_rows); ZEND_FUNCTION(mysqli_autocommit); @@ -842,6 +845,7 @@ ZEND_METHOD(mysqli_result, getIterator); ZEND_METHOD(mysqli_stmt, __construct); ZEND_METHOD(mysqli_warning, __construct); ZEND_METHOD(mysqli_warning, next); +ZEND_METHOD(mysqli_sql_exception, getSqlState); static const zend_function_entry ext_functions[] = { @@ -1083,6 +1087,7 @@ static const zend_function_entry class_mysqli_warning_methods[] = { static const zend_function_entry class_mysqli_sql_exception_methods[] = { + ZEND_ME(mysqli_sql_exception, getSqlState, arginfo_class_mysqli_sql_exception_getSqlState, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/mysqli/mysqli_exception.c b/ext/mysqli/mysqli_exception.c index 3bc80807a7e98..3d15881863e24 100644 --- a/ext/mysqli/mysqli_exception.c +++ b/ext/mysqli/mysqli_exception.c @@ -63,3 +63,17 @@ void php_mysqli_throw_sql_exception(char *sqlstate, int errorno, char *format, . zend_throw_exception_object(&sql_ex); } + +PHP_METHOD(mysqli_sql_exception, getSqlState) +{ + zval *prop; + zval rv; + + ZEND_PARSE_PARAMETERS_NONE(); + + prop = zend_read_property(mysqli_exception_class_entry, Z_OBJ_P(ZEND_THIS), "sqlstate", sizeof("sqlstate")-1, 1, &rv); + ZVAL_DEREF(prop); + zend_string *str = zval_get_string(prop); + + RETURN_STR(str); +} diff --git a/ext/mysqli/tests/gh7746.phpt b/ext/mysqli/tests/gh7746.phpt new file mode 100644 index 0000000000000..18fdb03451377 --- /dev/null +++ b/ext/mysqli/tests/gh7746.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #GH-7746 mysqli_sql_exception->sqlstate is inaccessible +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- +query("stuff"); +} catch (mysqli_sql_exception $exception) { + var_dump($exception->getSqlState()); +} + +?> +--EXPECT-- +string(5) "42000"