[Bug 24782]: fix API paging for recentchanges
authordaniel <daniel.kinzler@wikimedia.de>
Wed, 5 Sep 2012 18:09:19 +0000 (20:09 +0200)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 5 Mar 2013 19:35:23 +0000 (19:35 +0000)
Combine timestampt and rcid to form a uniformely increasing unique ID for paging.

The patch was originally submitted by Sam Reed, I fixed it up a bit.

Change-Id: Icc43b62ffa7f70f2eba36e9a07141b0ef2e02aa8

includes/api/ApiQueryRecentChanges.php

index 6acca67..24849bd 100644 (file)
@@ -149,6 +149,26 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                $this->addTables( 'recentchanges' );
                $index = array( 'recentchanges' => 'rc_timestamp' ); // May change
                $this->addTimestampWhereRange( 'rc_timestamp', $params['dir'], $params['start'], $params['end'] );
+
+               if ( !is_null( $params['continue'] ) ) {
+                       $cont = explode( '|', $params['continue'] );
+                       if ( count( $cont ) != 2 ) {
+                               $this->dieUsage( 'Invalid continue param. You should pass the ' .
+                                                               'original value returned by the previous query', '_badcontinue' );
+                       }
+
+                       $timestamp = $this->getDB()->addQuotes( wfTimestamp( TS_MW, $cont[0] ) );
+                       $id = intval( $cont[1] );
+                       $op = $params['dir'] == 'descending' ? '<' : '>';
+
+                       $this->addWhere(
+                               "rc_timestamp $op $timestamp OR " .
+                               "(rc_timestamp = $timestamp AND " .
+                               "rc_id <= $id)"
+                       );
+               }
+
+
                $this->addWhereFld( 'rc_namespace', $params['namespace'] );
                $this->addWhereFld( 'rc_deleted', 0 );
 
@@ -229,8 +249,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
                        }
 
+                       $this->addFields( 'rc_id' );
                        /* Add fields to our query if they are specified as a needed parameter. */
-                       $this->addFieldsIf( array( 'rc_id', 'rc_this_oldid', 'rc_last_oldid' ), $this->fld_ids );
+                       $this->addFieldsIf( array( 'rc_this_oldid', 'rc_last_oldid' ), $this->fld_ids );
                        $this->addFieldsIf( 'rc_comment', $this->fld_comment || $this->fld_parsedcomment );
                        $this->addFieldsIf( 'rc_user', $this->fld_user );
                        $this->addFieldsIf( 'rc_user_text', $this->fld_user || $this->fld_userid );
@@ -281,7 +302,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                foreach ( $res as $row ) {
                        if ( ++ $count > $params['limit'] ) {
                                // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) );
+                               $this->setContinueEnumParameter( 'continue', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) . '|' . $row->rc_id );
                                break;
                        }
 
@@ -295,7 +316,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                }
                                $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
                                if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) );
+                                       $this->setContinueEnumParameter( 'continue', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) . '|' . $row->rc_id );
                                        break;
                                }
                        } else {
@@ -584,6 +605,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                )
                        ),
                        'toponly' => false,
+                       'continue' => null,
                );
        }
 
@@ -621,6 +643,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        'limit' => 'How many total changes to return',
                        'tag' => 'Only list changes tagged with this tag',
                        'toponly' => 'Only list changes which are the latest revision',
+                       'continue' => 'When more results are available, use this to continue',
                );
        }