diff --git a/NEWS b/NEWS index 808f3ed8061..7034346b847 100644 --- a/NEWS +++ b/NEWS @@ -141,6 +141,8 @@ PHP NEWS . pg_trace new PGSQL_TRACE_SUPPRESS_TIMESTAMPS/PGSQL_TRACE_REGRESS_MODE contants support. (David Carlier) . pg_set_error_verbosity adding PGSQL_ERRORS_STATE constant. (David Carlier) + . pg_convert/pg_insert E_WARNING on type errors had been converted to + ValueError/TypeError exceptions. (David Carlier) - Phar: . Fix memory leak in phar_rename_archive(). (stkeke) diff --git a/UPGRADING b/UPGRADING index 79f86cb148d..53ac565428e 100644 --- a/UPGRADING +++ b/UPGRADING @@ -146,6 +146,8 @@ PHP 8.3 UPGRADE NOTES . pg_fetch_object now raises a ValueError instead of an Exception when the constructor_args argument is non empty with the class not having constructor. . pg_insert now raises a ValueError instead of a WARNING when the table specified is invalid. + . pg_insert and pg_convert raises a ValueError or a TypeError instead of a WARNING when the + value/type of a field does not match properly with a PostGreSQL's type. - Standard: . E_NOTICEs emitted by unserialize() have been promoted to E_WARNING. diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 14488ca6157..d7215f3a9ba 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -4529,7 +4529,6 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * data_type = php_pgsql_get_data_type(Z_STR_P(type)); } - /* TODO: Should E_NOTICE be converted to type error if PHP type cannot be converted to field type? */ switch(data_type) { case PG_BOOL: @@ -4554,7 +4553,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * ZVAL_STRINGL(&new_val, "'f'", sizeof("'f'")-1); } else { - php_error_docref(NULL, E_NOTICE, "Detected invalid value (%s) for PostgreSQL %s field (%s)", Z_STRVAL_P(val), Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_value_error("%s(): Field \"%s\" must be of type bool, invalid PostgreSQL string boolean value \"%s\" given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(val)); err = 1; } } @@ -4586,7 +4585,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects string, null, long or boolelan value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null|int|bool, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4630,7 +4629,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for pgsql '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type int|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4679,7 +4678,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type %s|int|null, %s given", get_active_function_name(), (data_type == PG_MONEY ? "money" : "float"), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4740,7 +4739,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4782,7 +4781,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type int|null, %s given", get_active_function_name(), ZSTR_VAL(field), zend_zval_value_name(val)); } break; @@ -4801,7 +4800,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * at all though and let the server side to handle it.*/ if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 0) == FAILURE && php_pgsql_convert_match(Z_STR_P(val), REGEX1, sizeof(REGEX1)-1, 0) == FAILURE) { - err = 1; + err = 2; } else { ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val))); @@ -4820,7 +4819,11 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL or IPv4 or IPv6 address string for '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + if (err == 2) { + zend_value_error("%s(): Field \"%s\" must be a valid IPv4 or IPv6 address string, \"%s\" given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(val)); + } else { + zend_type_error("%s(): Field \"%s\" must be of type string|null, given %s", get_active_function_name(), ZSTR_VAL(field), zend_zval_value_name(val)); + } } break; @@ -4854,7 +4857,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4886,7 +4889,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4918,7 +4921,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -4996,7 +4999,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; case PG_BYTEA: @@ -5037,7 +5040,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; @@ -5068,7 +5071,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - php_error_docref(NULL, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); } break; diff --git a/ext/pgsql/tests/bug71998.phpt b/ext/pgsql/tests/bug71998.phpt index 854c4e42274..96fc58ff827 100644 --- a/ext/pgsql/tests/bug71998.phpt +++ b/ext/pgsql/tests/bug71998.phpt @@ -57,7 +57,13 @@ $i = 0; $errors = 0; foreach ($ips as $ip) { $data = array("id" => ++$i, "remote_addr" => $ip); - $r = @pg_insert($db, 'tmp_statistics', $data); + $r = true; + try { + @pg_insert($db, 'tmp_statistics', $data); + } catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; + $r = false; + } if (!$r && in_array($ip, $bad)) { $errors++; @@ -79,6 +85,13 @@ pg_close($db); ?> --EXPECT-- +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "256.257.258.259" given +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "fe08::7:8interface" given +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "schnitzel" given +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "10002.3.4" given +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "1.2.3.4.5" given +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "256.0.0.0" given +pg_insert(): Field "remote_addr" must be a valid IPv4 or IPv6 address string, "260.0.0.0" given array(2) { [0]=> string(1) "1" diff --git a/ext/pgsql/tests/bug77047.phpt b/ext/pgsql/tests/bug77047.phpt index 50a4d61e7b5..8995050677b 100644 --- a/ext/pgsql/tests/bug77047.phpt +++ b/ext/pgsql/tests/bug77047.phpt @@ -19,10 +19,18 @@ pg_query($db, "CREATE TABLE bug77047 ( t TIME WITHOUT TIME ZONE )"); -pg_insert($db, "bug77047", array("t" => "13:31")); +try { + pg_insert($db, "bug77047", array("t" => "13:31")); +} catch (\TypeError $e) { + echo $e->getMessage(); +} pg_insert($db, "bug77047", array("t" => "13:31:13")); pg_insert($db, "bug77047", array("t" => "1:2:3")); -pg_insert($db, "bug77047", array("t" => "xyz")); +try { + pg_insert($db, "bug77047", array("t" => "xyz")); +} catch (\TypeError $e) { + echo $e->getMessage() . PHP_EOL; +} pg_insert($db, "bug77047", array("t" => NULL)); pg_insert($db, "bug77047", array("t" => "")); @@ -33,10 +41,9 @@ while (false !== ($row = pg_fetch_row($res))) { ?> --EXPECTF-- -Notice: pg_insert(): Expects NULL or string for PostgreSQL time field (t) in %s on line %d +pg_insert(): Field "t" must be of type string|null, time given string(8) "13:31:00" string(8) "13:31:13" string(8) "01:02:03" NULL NULL -