PostgreSQL: Fix Special:ActiveUsers GROUP BY query
[lhc/web/wiklou.git] / includes / specials / SpecialActiveusers.php
index 07e1be1..0caf6b4 100644 (file)
@@ -115,15 +115,23 @@ class ActiveUsersPager extends UsersPager {
                        ) . ')';
                }
 
+               if ( $dbr->implicitGroupby() ) {
+                       $options = array( 'GROUP BY' => array( 'qcc_title' ) );
+               } else {
+                       $options = array( 'GROUP BY' => array( 'user_name', 'user_id', 'qcc_title' ) );
+               }
+
                return array(
                        'tables' => array( 'querycachetwo', 'user', 'recentchanges' ),
                        'fields' => array( 'user_name', 'user_id', 'recentedits' => 'COUNT(*)', 'qcc_title' ),
-                       'options' => array( 'GROUP BY' => array( 'qcc_title' ) ),
+                       'options' => $options,
                        'conds' => $conds
                );
        }
 
        function doBatchLookups() {
+               parent::doBatchLookups();
+
                $uids = array();
                foreach ( $this->mResult as $row ) {
                        $uids[] = $row->user_id;
@@ -172,7 +180,8 @@ class ActiveUsersPager extends UsersPager {
                // Note: This is a different loop than for user rights,
                // because we're reusing it to build the group links
                // at the same time
-               foreach ( $user->getGroups() as $group ) {
+               $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache );
+               foreach ( $groups_list as $group ) {
                        if ( in_array( $group, $this->hideGroups ) ) {
                                return '';
                        }
@@ -259,7 +268,7 @@ class SpecialActiveUsers extends SpecialPage {
                        array( 'activeusers-intro', $this->getLanguage()->formatNum( $days ) ) );
 
                // Occasionally merge in new updates
-               $seconds = min( self::mergeActiveUsers( 600, $days ), $days * 86400 );
+               $seconds = min( self::mergeActiveUsers( 300, $days ), $days * 86400 );
                // Mention the level of staleness
                $out->addWikiMsg( 'cachedspecial-viewing-cached-ttl',
                        $this->getLanguage()->formatDuration( $seconds ) );
@@ -314,10 +323,10 @@ class SpecialActiveUsers extends SpecialPage {
        }
 
        /**
-        * @param DatabaseBase $dbw Passed in from updateSpecialPages.php
+        * @param IDatabase $dbw Passed in from updateSpecialPages.php
         * @return void
         */
-       public static function cacheUpdate( DatabaseBase $dbw ) {
+       public static function cacheUpdate( IDatabase $dbw ) {
                global $wgActiveUserDays;
 
                self::doQueryCacheUpdate( $dbw, $wgActiveUserDays, $wgActiveUserDays * 86400 );
@@ -326,12 +335,12 @@ class SpecialActiveUsers extends SpecialPage {
        /**
         * Update the query cache as needed
         *
-        * @param DatabaseBase $dbw
+        * @param IDatabase $dbw
         * @param int $days How many days user must be idle before he is considered inactive
         * @param int $window Maximum time range of new data to scan (in seconds)
         * @return int|bool UNIX timestamp the cache is now up-to-date as of (false on error)
         */
-       protected static function doQueryCacheUpdate( DatabaseBase $dbw, $days, $window ) {
+       protected static function doQueryCacheUpdate( IDatabase $dbw, $days, $window ) {
                $dbw->startAtomic( __METHOD__ );
 
                $lockKey = wfWikiID() . '-activeusers';
@@ -339,21 +348,19 @@ class SpecialActiveUsers extends SpecialPage {
                        return false; // exclusive update (avoids duplicate entries)
                }
 
-               $now = time();
+               $nowUnix = time();
+               // Get the last-updated timestamp for the cache
                $cTime = $dbw->selectField( 'querycache_info',
                        'qci_timestamp',
                        array( 'qci_type' => 'activeusers' )
                );
                $cTimeUnix = $cTime ? wfTimestamp( TS_UNIX, $cTime ) : 1;
-               // If a transaction was already started, it might have an old
-               // snapshot, so kludge the timestamp range a few seconds back.
-               $cTimeUnix -= 5;
 
                // Pick the date range to fetch from. This is normally from the last
                // update to till the present time, but has a limited window for sanity.
                // If the window is limited, multiple runs are need to fully populate it.
-               $sTimestamp = max( $cTimeUnix, $now - $days * 86400 );
-               $eTimestamp = min( $sTimestamp + $window, $now );
+               $sTimestamp = max( $cTimeUnix, $nowUnix - $days * 86400 );
+               $eTimestamp = min( $sTimestamp + $window, $nowUnix );
 
                // Get all the users active since the last update
                $res = $dbw->select(
@@ -381,7 +388,7 @@ class SpecialActiveUsers extends SpecialPage {
                $dbw->delete( 'querycachetwo',
                        array(
                                'qcc_type' => 'activeusers',
-                               'qcc_value < ' . $dbw->addQuotes( $now - $days * 86400 ) // TS_UNIX
+                               'qcc_value < ' . $dbw->addQuotes( $nowUnix - $days * 86400 ) // TS_UNIX
                        ),
                        __METHOD__
                );
@@ -425,11 +432,15 @@ class SpecialActiveUsers extends SpecialPage {
                        }
                }
 
+               // If a transaction was already started, it might have an old
+               // snapshot, so kludge the timestamp range back as needed.
+               $asOfTimestamp = min( $eTimestamp, (int)$dbw->trxTimestamp() );
+
                // Touch the data freshness timestamp
                $dbw->replace( 'querycache_info',
                        array( 'qci_type' ),
                        array( 'qci_type' => 'activeusers',
-                               'qci_timestamp' => $dbw->timestamp( $eTimestamp ) ), // not always $now
+                               'qci_timestamp' => $dbw->timestamp( $asOfTimestamp ) ), // not always $now
                        __METHOD__
                );