WordPress.org

Make WordPress Core

Ticket #2268: options-caches.diff

File options-caches.diff, 5.9 KB (added by markjaquith, 14 years ago)

Alloptions and Notoptions caching. Saves a query, and reduces cache misses to zero

  • wp-includes/cache.php

     
    193193                        }
    194194                } else
    195195                        if ('options' == $group) {
     196                                return; // disabled... handled in get_option() now
    196197                                $wpdb->hide_errors();
    197198                                if (!$options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'")) {
    198199                                        $options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options");
  • wp-includes/functions.php

     
    208208        if ( $pre )
    209209                return $pre;
    210210
    211         $value = wp_cache_get($setting, 'options');
     211        // prevent non-existent options from triggering multiple queries
     212        $notoptions = wp_cache_get('notoptions', 'options');
     213        if ( isset($notoptions[$setting]) )
     214                return false;
    212215
    213         if ( false === $value ) {
    214                 if ( defined('WP_INSTALLING') )
    215                         $wpdb->hide_errors();
    216                 $row = $wpdb->get_row("SELECT option_value FROM $wpdb->options WHERE option_name = '$setting' LIMIT 1");
    217                 if ( defined('WP_INSTALLING') )
    218                         $wpdb->show_errors();
     216        $alloptions = wp_cache_get('alloptions', 'options');
    219217
    220                 if( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values
    221                         $value = $row->option_value;
    222                         wp_cache_set($setting, $value, 'options');
    223                 } else {
    224                         return false;
     218        if ( !$alloptions ) {
     219                $wpdb->hide_errors();
     220                if ( !$alloptions_db = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'") )
     221                        $alloptions_db = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options");
     222                $wpdb->show_errors();
     223                $alloptions = array();
     224                foreach ( (array) $alloptions_db as $o )
     225                        $alloptions[$o->option_name] = $o->option_value;
     226                wp_cache_set('alloptions', $alloptions, 'options');
     227        }
     228
     229        if ( isset($alloptions[$setting]) ) {
     230                $value = $alloptions[$setting];
     231        } else {
     232                $value = wp_cache_get($setting, 'options');
     233
     234                if ( false === $value ) {
     235                        if ( defined('WP_INSTALLING') )
     236                                $wpdb->hide_errors();
     237                        $row = $wpdb->get_row("SELECT option_value FROM $wpdb->options WHERE option_name = '$setting' LIMIT 1");
     238                        if ( defined('WP_INSTALLING') )
     239                                $wpdb->show_errors();
     240
     241                        if( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values
     242                                $value = $row->option_value;
     243                                wp_cache_set($setting, $value, 'options');
     244                        } else { // option does not exist, so we must cache its non-existence
     245                                $notoptions[$setting] = true;
     246                                wp_cache_set('notoptions', $notoptions, 'options');
     247                                return false;
     248                        }
    225249                }
    226250        }
    227251
     
    235259        return apply_filters( 'option_' . $setting, maybe_unserialize($value) );
    236260}
    237261
     262function wp_protect_special_option($option) {
     263        $protected = array('alloptions', 'notoptions');
     264        if ( in_array($option, $protected) )
     265                die(sprintf(__('%s is a protected WP option and may not be modified'), wp_specialchars($option)));
     266}
     267
    238268function form_option($option) {
    239269        echo attribute_escape(get_option($option));
    240270}
     
    265295function update_option($option_name, $newvalue) {
    266296        global $wpdb;
    267297
     298        wp_protect_special_option($option_name);
     299
    268300        if ( is_string($newvalue) )
    269301                $newvalue = trim($newvalue);
    270302
     
    279311                return true;
    280312        }
    281313
     314        $notoptions = wp_cache_get('notoptions', 'options');
     315        if ( isset($notoptions[$option_name]) ) {
     316                unset($notoptions[$option_name]);
     317                wp_cache_set('notoptions', $notoptions, 'options');
     318        }
     319
    282320        $_newvalue = $newvalue;
    283321        $newvalue = maybe_serialize($newvalue);
    284322
    285         wp_cache_set($option_name, $newvalue, 'options');
     323        $alloptions = wp_cache_get('alloptions', 'options');
     324        if ( isset($alloptions[$option_name]) ) {
     325                $alloptions[$options_name] = $newvalue;
     326                wp_cache_set('alloptions', $alloptions, 'options');
     327        } else {
     328                wp_cache_set($option_name, $newvalue, 'options');
     329        }
    286330
    287331        $newvalue = $wpdb->escape($newvalue);
    288332        $option_name = $wpdb->escape($option_name);
     
    298342function add_option($name, $value = '', $description = '', $autoload = 'yes') {
    299343        global $wpdb;
    300344
    301         // Make sure the option doesn't already exist
    302         if ( false !== get_option($name) )
    303                 return;
     345        wp_protect_special_option($name);
    304346
     347        // Make sure the option doesn't already exist we can check the cache before we ask for a db query
     348        $notoptions = wp_cache_get('notoptions', 'options');
     349        if ( isset($notoptions[$name]) ) {
     350                unset($notoptions[$name]);
     351                wp_cache_set('notoptions', $notoptions, 'options');
     352        } elseif ( false !== get_option($name) ) {
     353                        return;
     354        }
     355
    305356        $value = maybe_serialize($value);
    306357
    307         wp_cache_set($name, $value, 'options');
     358        if ( 'yes' == $autoload ) {
     359                $alloptions = wp_cache_get('alloptions', 'options');
     360                $alloptions[$name] = $value;
     361                wp_cache_set('alloptions', $alloptions, 'options');
     362        } else {
     363                wp_cache_set($name, $value, 'options');
     364        }
    308365
    309366        $name = $wpdb->escape($name);
    310367        $value = $wpdb->escape($value);
     
    316373
    317374function delete_option($name) {
    318375        global $wpdb;
     376
     377        wp_protect_special_option($name);
     378
    319379        // Get the ID, if no ID then return
    320         $option_id = $wpdb->get_var("SELECT option_id FROM $wpdb->options WHERE option_name = '$name'");
    321         if ( !$option_id ) return false;
     380        $option = $wpdb->get_row("SELECT option_id, autoload FROM $wpdb->options WHERE option_name = '$name'");
     381        if ( !$option->option_id ) return false;
    322382        $wpdb->query("DELETE FROM $wpdb->options WHERE option_name = '$name'");
    323         wp_cache_delete($name, 'options');
     383        if ( 'yes' == $option->autoload ) {
     384                $alloptions = wp_cache_get('alloptions', 'options');
     385                if ( isset($alloptions[$name]) ) {
     386                        unset($alloptions[$name]);
     387                        wp_cache_set('alloptions', $alloptions, 'options');
     388                }
     389        } else {
     390                wp_cache_delete($name, 'options');
     391        }
    324392        return true;
    325393}
    326394