ApiQueryRevisions: Restore use of rvstartid/rvendid as a tiebreaker
authorBrad Jorsch <bjorsch@wikimedia.org>
Mon, 8 May 2017 18:18:03 +0000 (14:18 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Mon, 8 May 2017 18:34:13 +0000 (14:34 -0400)
If rvstartid/rvendid are used with revisions that have the same
timestamp, we should omit any revisions with the same timestamp but
out-of-range IDs.

Bug: T163532
Change-Id: I6ba5e0724945668dad55eec0d09cb7d3fe08e347

includes/api/ApiQueryRevisions.php

index 3e077c3..b0a8468 100644 (file)
@@ -259,12 +259,34 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                                        $p = $this->encodeParamName( 'endid' );
                                        $this->dieWithError( [ 'apierror-revisions-badid', $p ], "badid_$p" );
                                }
+
+                               if ( $params['start'] !== null ) {
+                                       $op = ( $params['dir'] === 'newer' ? '>' : '<' );
+                                       $ts = $db->addQuotes( $db->timestampOrNull( $params['start'] ) );
+                                       if ( $params['startid'] !== null ) {
+                                               $this->addWhere( "rev_timestamp $op $ts OR "
+                                                       . "rev_timestamp = $ts AND rev_id $op= " . intval( $params['startid'] ) );
+                                       } else {
+                                               $this->addWhere( "rev_timestamp $op= $ts" );
+                                       }
+                               }
+                               if ( $params['end'] !== null ) {
+                                       $op = ( $params['dir'] === 'newer' ? '<' : '>' ); // Yes, opposite of the above
+                                       $ts = $db->addQuotes( $db->timestampOrNull( $params['end'] ) );
+                                       if ( $params['endid'] !== null ) {
+                                               $this->addWhere( "rev_timestamp $op $ts OR "
+                                                       . "rev_timestamp = $ts AND rev_id $op= " . intval( $params['endid'] ) );
+                                       } else {
+                                               $this->addWhere( "rev_timestamp $op= $ts" );
+                                       }
+                               }
+                       } else {
+                               $this->addTimestampWhereRange( 'rev_timestamp', $params['dir'],
+                                       $params['start'], $params['end'] );
                        }
 
-                       $this->addTimestampWhereRange( 'rev_timestamp', $params['dir'],
-                               $params['start'], $params['end'] );
-                       // Dummy to add rev_id to ORDER BY
-                       $this->addWhereRange( 'rev_id', $params['dir'], null, null );
+                       $sort = ( $params['dir'] === 'newer' ? '' : 'DESC' );
+                       $this->addOption( 'ORDER BY', [ "rev_timestamp $sort", "rev_id $sort" ] );
 
                        // There is only one ID, use it
                        $ids = array_keys( $pageSet->getGoodTitles() );