Options, Meta APIs: Improve logic to avoid unnecessary database writes in `update_option()`.
Prior to this change, a strict comparison between the old and new database value could lead to a false negative, since database values are generally stored as strings. For example, passing an integer to `update_option()` would almost always result in an update given any existing database value for that option would be that number cast to a string. This changeset adjusts the logic to perform an intentional "loose-y" comparison by casting the values to strings. Extensive coverage previously added in [56648] provides additional confidence that this does not introduce any backward compatibility issues. Props mukesh27, costdev, spacedmonkey, joemcgill, flixos90, nacin, atimmer, duck_, boonebgorges. Fixes #22192. Built from https://develop.svn.wordpress.org/trunk@56681 git-svn-id: http://core.svn.wordpress.org/trunk@56193 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
28af9eafb0
commit
bfbcb02444
|
@ -776,21 +776,23 @@ function update_option( $option, $value, $autoload = null ) {
|
||||||
*/
|
*/
|
||||||
$value = apply_filters( 'pre_update_option', $value, $option, $old_value );
|
$value = apply_filters( 'pre_update_option', $value, $option, $old_value );
|
||||||
|
|
||||||
|
/** This filter is documented in wp-includes/option.php */
|
||||||
|
$default_value = apply_filters( "default_option_{$option}", false, $option, false );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the new and old values are the same, no need to update.
|
* If the new and old values are the same, no need to update.
|
||||||
*
|
*
|
||||||
* Unserialized values will be adequate in most cases. If the unserialized
|
* An exception applies when no value is set in the database, i.e. the old value is the default.
|
||||||
* data differs, the (maybe) serialized data is checked to avoid
|
* In that case, the new value should always be added as it may be intentional to store it rather than relying on the default.
|
||||||
* unnecessary database calls for otherwise identical object instances.
|
|
||||||
*
|
*
|
||||||
* See https://core.trac.wordpress.org/ticket/38903
|
* See https://core.trac.wordpress.org/ticket/38903 and https://core.trac.wordpress.org/ticket/22192.
|
||||||
*/
|
*/
|
||||||
if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
|
if ( $old_value !== $default_value && _is_equal_database_value( $old_value, $value ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This filter is documented in wp-includes/option.php */
|
if ( $old_value === $default_value ) {
|
||||||
if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
|
|
||||||
// Default setting for new options is 'yes'.
|
// Default setting for new options is 'yes'.
|
||||||
if ( null === $autoload ) {
|
if ( null === $autoload ) {
|
||||||
$autoload = 'yes';
|
$autoload = 'yes';
|
||||||
|
@ -2887,3 +2889,40 @@ function filter_default_option( $default_value, $option, $passed_default ) {
|
||||||
|
|
||||||
return $registered[ $option ]['default'];
|
return $registered[ $option ]['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether two values will be equal when stored in the database.
|
||||||
|
*
|
||||||
|
* @since 6.4.0
|
||||||
|
* @access private
|
||||||
|
*
|
||||||
|
* @param mixed $old_value The old value to compare.
|
||||||
|
* @param mixed $new_value The new value to compare.
|
||||||
|
* @return bool True if the values are equal, false otherwise.
|
||||||
|
*/
|
||||||
|
function _is_equal_database_value( $old_value, $new_value ) {
|
||||||
|
$values = array(
|
||||||
|
'old' => $old_value,
|
||||||
|
'new' => $new_value,
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ( $values as $_key => &$_value ) {
|
||||||
|
// Cast scalars or null to a string so type discrepancies don't result in cache misses.
|
||||||
|
if ( null === $_value || is_scalar( $_value ) ) {
|
||||||
|
$_value = (string) $_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $values['old'] === $values['new'] ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unserialized values will be adequate in most cases. If the unserialized
|
||||||
|
* data differs, the (maybe) serialized data is checked to avoid
|
||||||
|
* unnecessary database calls for otherwise identical object instances.
|
||||||
|
*
|
||||||
|
* See https://core.trac.wordpress.org/ticket/38903
|
||||||
|
*/
|
||||||
|
return maybe_serialize( $old_value ) === maybe_serialize( $new_value );
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '6.4-alpha-56680';
|
$wp_version = '6.4-alpha-56681';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue