WordPress Quotes Collection patch update

This is an update to the WordPress Quotes Collection plugin, which uses “ORDER BY RAND().” This is a Bad Idea, but there is a better way that isn’t too ugly. This is a partial fix. A complete fix involves a helper table and a database trigger, which I am just too lazy to maintain as a branch of an uncommented PHP script.

The problem: If you have a very large number of quotes, and use the “random” feature, your quotes collection plugin is eating randomness very rapidly for each page load. This is bad.

The solution: This patch replaces the quotescollection_get_quote()  function with a random function that retrieves exactly one random number per fetch. It has only been tested in my configuration, with Quotes Collection 1.5.1:

function quotescollection_get_quote($condition = '', $random = 1, $current = 0)
{
    global $wpdb;
    $sql = "SELECT quote_id, quote, author, source
        FROM " . $wpdb->prefix . "quotescollection";
    if(!$random) {
        if ($condition)
            $sql .= $condition;
        if($current)
            $sql .= " AND quote_id < {$current}";
        $sql .= " ORDER BY quote_id DESC";
    }
    else {
                // Select random id. Conserves randomness, but will be less random if you
                // delete quotes.
                // See: http://jan.kneschke.de/projects/mysql/order-by-rand/
        $sql .= " JOIN (SELECT CEIL(RAND() * (SELECT MAX(quote_id)
                                FROM " . $wpdb->prefix . "quotescollection )) AS id)
                               AS myrand";

        if ($condition) {
            $sql .= $condition;
            $sql .= " AND ";
        }
        else {
            $sql .= " WHERE ";
        }

                $sql .= "quote_id >= myrand.id";
        // This random method requires LIMIT 1, which is appended below already
    }

    $sql .= " LIMIT 1";
    $random_quote = $wpdb->get_row($sql, ARRAY_A);
    if ( empty($random_quote) ) {
        if(!$random && $current)
            return quotescollection_get_quote($condition, 0, 0);
        else
            return 0;
    }
    else
        return $random_quote;
}

My previous random fix used count(*) which I have now discovered can be just as slow, for entirely different reasons. So I won’t be doing that again. :)

Peace, love, and high quality randomness to you all.

Leave a Reply

You must be logged in to post a comment.