Anomie has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/349501 )

Change subject: Have Title::get(Next|Previous)RevisionID sort by timestamp
......................................................................

Have Title::get(Next|Previous)RevisionID sort by timestamp

Revision IDs are usually increasing as timestamp increases, but not
always. Callers almost certainly want next/previous timestamp when the
two differ.

This also takes care of a minor bug in the nearby getFirstRevision()
where it'll choose an arbitrary tied revision ID if there were multiple
revisions made in the same second.

Bug: T163532
Bug: T159319
Change-Id: Iab2060a0ad5e45edbaa0ff36e863cb014b8e876f
---
M includes/Title.php
1 file changed, 47 insertions(+), 31 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/01/349501/1

diff --git a/includes/Title.php b/includes/Title.php
index dd6aaef..8366719 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -3994,29 +3994,52 @@
        }
 
        /**
-        * Get the revision ID of the previous revision
-        *
+        * Get next/previous revision ID relative to another revision ID
         * @param int $revId Revision ID. Get the revision that was before this 
one.
         * @param int $flags Title::GAID_FOR_UPDATE
-        * @return int|bool Old revision ID, or false if none exists
+        * @param string $dir 'next' or 'prev'
+        * @return int|bool New revision ID, or false if none exists
         */
-       public function getPreviousRevisionID( $revId, $flags = 0 ) {
-               /* This function and getNextRevisionID have bad performance when
-                  used on a page with many revisions on mysql. An explicit 
extended
-                  primary key may help in some cases, if the PRIMARY KEY is 
banned:
-                  T159319 */
+       private function getRelativeRevisionID( $revId, $flags, $dir ) {
+               $revId = (int)$revId;
+               if ( $dir === 'next' ) {
+                       $op = '>';
+                       $sort = 'ASC';
+               } elseif ( $dir === 'prev' ) {
+                       $op = '<';
+                       $sort = 'DESC';
+               } else {
+                       throw new InvalidArgumentException( '$dir must be 
"next" or "prev"' );
+               }
+
                if ( $flags & self::GAID_FOR_UPDATE ) {
                        $db = wfGetDB( DB_MASTER );
                } else {
                        $db = wfGetDB( DB_REPLICA, 'contributions' );
                }
+
+               // Intentionally not caring if the specified revision belongs 
to this
+               // page. We only care about the timestamp.
+               $ts = $db->selectField( 'revision', 'rev_timestamp', [ 'rev_id' 
=> $revId ], __METHOD__ );
+               if ( $ts === false ) {
+                       $ts = $db->selectField( 'archive', 'ar_timestamp', [ 
'ar_rev_id' => $revId ], __METHOD__ );
+                       if ( $ts === false ) {
+                               // Or should this throw an 
InvalidArgumentException or something?
+                               return false;
+                       }
+               }
+               $ts = $db->addQuotes( $ts );
+
                $revId = $db->selectField( 'revision', 'rev_id',
                        [
                                'rev_page' => $this->getArticleID( $flags ),
-                               'rev_id < ' . intval( $revId )
+                               "rev_timestamp $op $ts OR (rev_timestamp = $ts 
AND rev_id $op $revId)"
                        ],
                        __METHOD__,
-                       [ 'ORDER BY' => 'rev_id DESC', 'IGNORE INDEX' => 
'PRIMARY' ]
+                       [
+                               'ORDER BY' => "rev_timestamp $sort, rev_id 
$sort",
+                               'IGNORE INDEX' => 'rev_timestamp', // Probably 
needed for T159319
+                       ]
                );
 
                if ( $revId === false ) {
@@ -4027,6 +4050,17 @@
        }
 
        /**
+        * Get the revision ID of the previous revision
+        *
+        * @param int $revId Revision ID. Get the revision that was before this 
one.
+        * @param int $flags Title::GAID_FOR_UPDATE
+        * @return int|bool Old revision ID, or false if none exists
+        */
+       public function getPreviousRevisionID( $revId, $flags = 0 ) {
+               return $this->getRelativeRevisionID( $revId, $flags, 'prev' );
+       }
+
+       /**
         * Get the revision ID of the next revision
         *
         * @param int $revId Revision ID. Get the revision that was after this 
one.
@@ -4034,25 +4068,7 @@
         * @return int|bool Next revision ID, or false if none exists
         */
        public function getNextRevisionID( $revId, $flags = 0 ) {
-               if ( $flags & self::GAID_FOR_UPDATE ) {
-                       $db = wfGetDB( DB_MASTER );
-               } else {
-                       $db = wfGetDB( DB_REPLICA, 'contributions' );
-               }
-               $revId = $db->selectField( 'revision', 'rev_id',
-                       [
-                               'rev_page' => $this->getArticleID( $flags ),
-                               'rev_id > ' . intval( $revId )
-                       ],
-                       __METHOD__,
-                       [ 'ORDER BY' => 'rev_id', 'IGNORE INDEX' => 'PRIMARY' ]
-               );
-
-               if ( $revId === false ) {
-                       return false;
-               } else {
-                       return intval( $revId );
-               }
+               return $this->getRelativeRevisionID( $revId, $flags, 'next' );
        }
 
        /**
@@ -4069,8 +4085,8 @@
                                [ 'rev_page' => $pageId ],
                                __METHOD__,
                                [
-                                       'ORDER BY' => 'rev_timestamp ASC',
-                                       'IGNORE INDEX' => 'rev_timestamp'
+                                       'ORDER BY' => 'rev_timestamp ASC, 
rev_id ASC',
+                                       'IGNORE INDEX' => 'rev_timestamp', // 
See T159319
                                ]
                        );
                        if ( $row ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/349501
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iab2060a0ad5e45edbaa0ff36e863cb014b8e876f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to