Decouple revision.rev_id from text.old_id
authorBrion Vibber <brion@users.mediawiki.org>
Mon, 28 Mar 2005 10:47:12 +0000 (10:47 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Mon, 28 Mar 2005 10:47:12 +0000 (10:47 +0000)
* This will allow the backend text storage to use different id numbers
* Revisions noting metadata changes can be added to history without duplicating text
  (implemented for page move)

This changes the revision table schema and requires running update.php
or maintenance/archives/patch-rev_text_id.sql on existing test wikis.
PostgreSQL table defs are still not in sync, so not updated.

includes/MessageCache.php
includes/Revision.php
includes/SearchMySQL3.php
includes/SearchMySQL4.php
includes/Title.php
maintenance/archives/patch-rev_text_id.sql [new file with mode: 0644]
maintenance/tables.sql
maintenance/updaters.inc

index 2627f09..7a0616c 100755 (executable)
@@ -144,9 +144,9 @@ class MessageCache
                                $conditions['page_title']=MessageCacheHints::get();
                        }
                }
-               $res = $dbr->select( array( 'page', 'text' ),
+               $res = $dbr->select( array( 'page', 'revision', 'text' ),
                        array( 'page_title', 'old_text', 'old_flags' ),
-                       'page_is_redirect=0 AND page_namespace = '.NS_MEDIAWIKI.' AND page_latest = old_id',
+                       'page_is_redirect=0 AND page_namespace='.NS_MEDIAWIKI.' AND page_latest=rev_id AND rev_text_id=old_id',
                        $fname
                );
 
index 3d9cedd..02d7c52 100644 (file)
@@ -165,6 +165,7 @@ class Revision {
                               'page_latest',
                               'rev_id',
                               'rev_page',
+                              'rev_text_id',
                               'rev_comment',
                               'rev_user_text',
                               'rev_user',
@@ -183,6 +184,7 @@ class Revision {
                if( is_object( $row ) ) {
                        $this->mId        = IntVal( $row->rev_id );
                        $this->mPage      = IntVal( $row->rev_page );
+                       $this->mTextId    = IntVal( $row->rev_text_id );
                        $this->mComment   =         $row->rev_comment;
                        $this->mUserText  =         $row->rev_user_text;
                        $this->mUser      = IntVal( $row->rev_user );
@@ -204,6 +206,7 @@ class Revision {
                        
                        $this->mId        = isset( $row['id']         ) ? IntVal( $row['id']         ) : null;
                        $this->mPage      = isset( $row['page']       ) ? IntVal( $row['page']       ) : null;
+                       $this->mTextId    = isset( $row['text_id']    ) ? IntVal( $row['text_id']    ) : null;
                        $this->mComment   = isset( $row['comment']    ) ? StrVal( $row['comment']    ) : null;
                        $this->mUserText  = isset( $row['user_text']  ) ? StrVal( $row['user_text']  ) : $wgUser->getName();
                        $this->mUser      = isset( $row['user']       ) ? IntVal( $row['user']       ) : $wgUser->getId();
@@ -229,6 +232,13 @@ class Revision {
                return $this->mId;
        }
        
+       /**
+        * @return int
+        */
+       function getTextId() {
+               return $this->mTextId;
+       }
+       
        /**
         * Returns the title of the page associated with this entry.
         * @return Title
@@ -433,23 +443,27 @@ class Revision {
                $flags = Revision::compressRevisionText( $mungedText );
                
                # Record the text to the text table
-               $old_id = isset( $this->mId )
-                       ? $this->mId
-                       : $dbw->nextSequenceValue( 'text_old_id_val' );
-               $dbw->insert( 'text',
-                       array(
-                               'old_id'    => $old_id,
-                               'old_text'  => $mungedText,
-                               'old_flags' => $flags,
-                       ), $fname
-               );
-               $revisionId = $dbw->insertId();
+               if( !isset( $this->mTextId ) ) {
+                       $old_id = $dbw->nextSequenceValue( 'text_old_id_val' );
+                       $dbw->insert( 'text',
+                               array(
+                                       'old_id'    => $old_id,
+                                       'old_text'  => $mungedText,
+                                       'old_flags' => $flags,
+                               ), $fname
+                       );
+                       $this->mTextId = $dbw->insertId();
+               }
                
                # Record the edit in revisions
+               $rev_id = isset( $this->mId )
+                       ? $this->mId
+                       : $dbw->nextSequenceValue( 'rev_rev_id_val' );
                $dbw->insert( 'revision',
                        array(
-                               'rev_id'         => $revisionId,
+                               'rev_id'         => $rev_id,
                                'rev_page'       => $this->mPage,
+                               'rev_text_id'    => $this->mTextId,
                                'rev_comment'    => $this->mComment,
                                'rev_minor_edit' => $this->mMinorEdit ? 1 : 0,
                                'rev_user'       => $this->mUser,
@@ -458,10 +472,10 @@ class Revision {
                        ), $fname
                );
                
-               $this->mId = $revisionId;
+               $this->mId = $dbw->insertId();
                
                wfProfileOut( $fname );
-               return $revisionId;
+               return $this->mId;
        }
        
        /**
@@ -478,7 +492,7 @@ class Revision {
                $dbr =& wfGetDB( DB_SLAVE );
                $row = $dbr->selectRow( 'text',
                        array( 'old_text', 'old_flags' ),
-                       array( 'old_id' => $this->getId() ),
+                       array( 'old_id' => $this->getTextId() ),
                        $fname);
                
                $text = Revision::getRevisionText( $row );
@@ -486,5 +500,48 @@ class Revision {
                
                return $text;
        }
+
+       /**
+        * Create a new null-revision for insertion into a page's
+        * history. This will not re-save the text, but simply refer
+        * to the text from the previous version.
+        *
+        * Such revisions can for instance identify page rename
+        * operations and other such meta-modifications.
+        *
+        * @param Database $dbw
+        * @param int      $pageId ID number of the page to read from
+        * @param string   $summary
+        * @param bool     $minor
+        * @return Revision
+        */
+       function &newNullRevision( &$dbw, $pageId, $summary, $minor ) {
+               $fname = 'Revision::newNullRevision';
+               wfProfileIn( $fname );
+               
+               $current = $dbw->selectRow(
+                       array( 'page', 'revision' ),
+                       array( 'page_latest', 'rev_text_id' ),
+                       array(
+                               'page_id' => $pageId,
+                               'page_latest=rev_id',
+                               ),
+                       $fname );
+               
+               if( $current ) {
+                       $revision = new Revision( array(
+                               'page'       => $pageId,
+                               'comment'    => $summary,
+                               'minor_edit' => $minor,
+                               'text_id'    => $current->rev_text_id,
+                               ) );
+               } else {
+                       $revision = null;
+               }
+               
+               wfProfileOut( $fname );
+               return $revision;
+       }
+       
 }
 ?>
\ No newline at end of file
index bd2a0ed..948c97b 100644 (file)
@@ -82,12 +82,13 @@ class SearchMySQL3 extends SearchEngine {
 
        function queryMain( $filteredTerm, $fulltext ) {
                $match = $this->parseQuery( $filteredTerm, $fulltext );
-               $page = $this->db->tableName( 'page' );
-               $text = $this->db->tableName( 'text' );
+               $page        = $this->db->tableName( 'page' );
+               $revision    = $this->db->tableName( 'revision' );
+               $text        = $this->db->tableName( 'text' );
                $searchindex = $this->db->tableName( 'searchindex' );
                return 'SELECT page_id, page_namespace, page_title, old_flags, old_text ' .
-                       "FROM $page,$text,$searchindex " .
-                       'WHERE page_id=si_page AND page_latest=old_id AND ' . $match;
+                       "FROM $page,$revision,$text,$searchindex " .
+                       'WHERE page_id=si_page AND page_latest=rev_id AND rev_text_id=old_id AND ' . $match;
        }
 
        function update( $id, $title, $text ) {
index 6847ac1..20bbfbc 100644 (file)
@@ -81,12 +81,13 @@ class SearchMySQL4 extends SearchEngine {
        /** @todo document */
        function queryMain( $filteredTerm, $fulltext ) {
                $match = $this->parseQuery( $filteredTerm, $fulltext );
-               $page = $this->db->tableName( 'page' );
-               $text = $this->db->tableName( 'text' );
+               $page        = $this->db->tableName( 'page' );
+               $revision    = $this->db->tableName( 'revision' );
+               $text        = $this->db->tableName( 'text' );
                $searchindex = $this->db->tableName( 'searchindex' );
                return 'SELECT page_id, page_namespace, page_title, old_flags, old_text ' .
-                       "FROM $page,$text,$searchindex " .
-                       'WHERE page_id=si_page AND page_latest=old_id AND ' . $match;
+                       "FROM $page,$revision,$text,$searchindex " .
+                       'WHERE page_id=si_page AND page_latest=rev_id AND rev_text_id=old_id AND ' . $match;
        }
 
        /** @todo document */
index 4fb3dc2..dc9e743 100644 (file)
@@ -1502,12 +1502,19 @@ class Title {
                # a conflict on the unique namespace+title index...
                $dbw->delete( 'page', array( 'page_id' => $newid ), $fname );
                
+               # Save a null revision in the page's history notifying of the move
+               $nullRevision = Revision::newNullRevision( $dbw, $oldid,
+                       wfMsg( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() ),
+                       true );
+               $nullRevId = $nullRevision->insertOn( $dbw );
+               
                # Change the name of the target page:
                $dbw->update( 'page',
                        /* SET */ array( 
-                               'page_touched' => $dbw->timestamp($now), 
+                               'page_touched'   => $dbw->timestamp($now), 
                                'page_namespace' => $nt->getNamespace(),
-                               'page_title' => $nt->getDBkey()
+                               'page_title'     => $nt->getDBkey(),
+                               'page_latest'    => $nullRevId,
                        ), 
                        /* WHERE */ array( 'page_id' => $oldid ),
                        $fname
@@ -1610,12 +1617,19 @@ class Title {
                wfSeedRandom();
                $rand = wfRandom();
 
+               # Save a null revision in the page's history notifying of the move
+               $nullRevision = Revision::newNullRevision( $dbw, $oldid,
+                       wfMsg( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() ),
+                       true );
+               $nullRevId = $nullRevision->insertOn( $dbw );
+               
                # Rename cur entry
                $dbw->update( 'page',
                        /* SET */ array(
-                               'page_touched' => $now,
+                               'page_touched'   => $now,
                                'page_namespace' => $nt->getNamespace(),
-                               'page_title' => $nt->getDBkey()
+                               'page_title'     => $nt->getDBkey(),
+                               'page_latest'    => $nullRevId,
                        ),
                        /* WHERE */ array( 'page_id' => $oldid ),
                        $fname
@@ -1685,9 +1699,9 @@ class Title {
 
                # Is it a redirect?
                $id  = $nt->getArticleID();
-               $obj = $dbw->selectRow( array( 'page', 'text') ,
-                       array( 'page_is_redirect','old_text' ), 
-                       array( 'page_id' => $id, 'page_latest=old_id' ),
+               $obj = $dbw->selectRow( array( 'page', 'revision', 'text'),
+                       array( 'page_is_redirect','old_text' ),
+                       array( 'page_id' => $id, 'page_latest=rev_id', 'rev_text_id=old_id' ),
                        $fname, 'FOR UPDATE' );
 
                if ( !$obj || 0 == $obj->page_is_redirect ) { 
diff --git a/maintenance/archives/patch-rev_text_id.sql b/maintenance/archives/patch-rev_text_id.sql
new file mode 100644 (file)
index 0000000..44ef438
--- /dev/null
@@ -0,0 +1,17 @@
+--
+-- Adds rev_text_id field to revision table.
+-- This is a key to text.old_id, so that revisions can be stored
+-- for non-save operations without duplicating text, and so that
+-- a back-end storage system can provide its own numbering system
+-- if necessary.
+--
+-- rev.rev_id and text.old_id are no longer assumed to be the same.
+--
+-- 2005-03-28
+--
+
+ALTER TABLE /*$wgDBprefix*/revision
+  ADD rev_text_id int(8) unsigned NOT NULL;
+
+UPDATE /*$wgDBprefix*/revision
+  SET rev_text_id=rev_id;
index 4e0651f..15cda2b 100644 (file)
@@ -64,6 +64,7 @@ CREATE TABLE /*$wgDBprefix*/page (
 CREATE TABLE /*$wgDBprefix*/revision (
   rev_id int(8) unsigned NOT NULL auto_increment,
   rev_page int(8) unsigned NOT NULL,
+  rev_text_id int(8) unsigned NOT NULL,
   rev_comment tinyblob NOT NULL default '',
   rev_user int(5) unsigned NOT NULL default '0',
   rev_user_text varchar(255) binary NOT NULL default '',
index 6bd12a4..b388c3f 100644 (file)
@@ -421,6 +421,18 @@ function do_inverse_timestamp() {
        }
 }
 
+function do_text_id() {
+       global $wgDatabase;
+       if( $wgDatabase->fieldExists( 'revision', 'rev_text_id' ) ) {
+               echo "...rev_text_id already in place.\n";
+       } else {
+               echo "Adding rev_text_id field... ";
+               dbsource( 'maintenance/archives/patch-rev_text_id.sql', $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+
 function do_all_updates() {
        global $wgNewTables, $wgNewFields;
        
@@ -452,6 +464,7 @@ function do_all_updates() {
        
        do_schema_restructuring(); flush();
        do_inverse_timestamp(); flush();
+       do_text_id(); flush();
 
        initialiseMessages(); flush();
 }