* (bug 2018) Fix deletion for new schema, make work on MySQL 3 again
authorBrion Vibber <brion@users.mediawiki.org>
Sun, 1 May 2005 08:07:25 +0000 (08:07 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Sun, 1 May 2005 08:07:25 +0000 (08:07 +0000)
The archive table now has an ar_text_id field which points at the
text record containing the deleted revision's text. Older archive
records containing self-contained text are still supported and
will be restored by adding a new revision.

For now, revision and page records are still removed on deletion,
but text records are left intact. This will keep block compression
and immutable alternate storage backends working relatively cleanly.
A rev_deleted flag field is reserved in revision for further future
changes but that won't happen in the 1.5 timeframe.

There is no longer a delete-on-join which was present in earlier
1.5 revisions, so deletion should work on MySQL 3.x again.

includes/Article.php
includes/SpecialUndelete.php
maintenance/archives/patch-archive-text_id.sql [new file with mode: 0644]
maintenance/tables.sql
maintenance/updaters.inc

index 2012d7f..df05074 100644 (file)
@@ -1727,33 +1727,39 @@ class Article {
                # Client and file cache invalidation
                Title::touchArray( $linksTo );
 
-               # Move article and history to the "archive" table
 
-               $dbw->insertSelect( 'archive', array( 'page','revision', 'text' ),
+               // For now, shunt the revision data into the archive table.
+               // Text is *not* removed from the text table; bulk storage
+               // is left intact to avoid breaking block-compression or
+               // immutable storage schemes.
+               //
+               // For backwards compatibility, note that some older archive
+               // table entries will have ar_text and ar_flags fields still.
+               //
+               // In the future, we may keep revisions and mark them with
+               // the rev_deleted field, which is reserved for this purpose.
+               $dbw->insertSelect( 'archive', array( 'page', 'revision' ),
                        array(
                                'ar_namespace'  => 'page_namespace',
                                'ar_title'      => 'page_title',
-                               'ar_text'       => 'old_text',
                                'ar_comment'    => 'rev_comment',
                                'ar_user'       => 'rev_user',
                                'ar_user_text'  => 'rev_user_text',
                                'ar_timestamp'  => 'rev_timestamp',
                                'ar_minor_edit' => 'rev_minor_edit',
-                               'ar_flags'      => 'old_flags',
                                'ar_rev_id'     => 'rev_id',
+                               'ar_text_id'    => 'rev_text_id',
                        ), array(
-                               'page_namespace' => $ns,
-                               'page_title' => $t,
-                               'page_id = rev_page AND old_id = rev_id'
+                               'page_id' => $id,
+                               'page_id = rev_page'
                        ), $fname
                );
-
+               
                # Now that it's safely backed up, delete it
-
-               $dbw->deleteJoin( 'text', 'revision', 'old_id', 'rev_id', array( "rev_page = {$id}" ), $fname );
                $dbw->delete( 'revision', array( 'rev_page' => $id ), $fname );
                $dbw->delete( 'page', array( 'page_id' => $id ), $fname);
+               
+               # Clean up recentchanges entries...
                $dbw->delete( 'recentchanges', array( 'rc_namespace' => $ns, 'rc_title' => $t ), $fname );
 
                # Finally, clean up the link tables
index ab078d2..dd6262a 100644 (file)
@@ -73,13 +73,26 @@ class PageArchive {
         * @return string
         */
        function getRevisionText( $timestamp ) {
+               $fname = 'PageArchive::getRevisionText';
                $dbr =& wfGetDB( DB_SLAVE );
                $row = $dbr->selectRow( 'archive',
-                       array( 'ar_text', 'ar_flags' ),
+                       array( 'ar_text', 'ar_flags', 'ar_text_id' ),
                        array( 'ar_namespace' => $this->title->getNamespace(),
                               'ar_title' => $this->title->getDbkey(),
-                              'ar_timestamp' => $dbr->timestamp( $timestamp ) ) );
-               return Revision::getRevisionText( $row, "ar_" );
+                              'ar_timestamp' => $dbr->timestamp( $timestamp ) ),
+                       $fname );
+               if( is_null( $row->ar_text_id ) ) {
+                       // An old row from MediaWiki 1.4 or previous.
+                       // Text is embedded in this row in classic compression format.
+                       return Revision::getRevisionText( $row, "ar_" );
+               } else {
+                       // New-style: keyed to the text storage backend.
+                       $text = $dbr->selectRow( 'text',
+                               array( 'old_text', 'old_flags' ),
+                               array( 'old_id' => $row->ar_text_id ),
+                               $fname );
+                       return Revision::getRevisionText( $text );
+               }
        }
        
        /**
@@ -189,7 +202,8 @@ class PageArchive {
                                'ar_user_text',
                                'ar_timestamp',
                                'ar_minor_edit',
-                               'ar_flags' ),
+                               'ar_flags',
+                               'ar_text_id' ),
                        /* WHERE */ array(
                                'ar_namespace' => $this->title->getNamespace(),
                                'ar_title'     => $this->title->getDBkey(),
@@ -209,6 +223,7 @@ class PageArchive {
                                'user_text'  => $row->ar_user_text,
                                'timestamp'  => $row->ar_timestamp,
                                'minor_edit' => $row->ar_minor_edit,
+                               'text_id'    => $row->ar_text_id,
                                ) );
                        $revision->insertOn( $dbw );
                }
diff --git a/maintenance/archives/patch-archive-text_id.sql b/maintenance/archives/patch-archive-text_id.sql
new file mode 100644 (file)
index 0000000..f59715f
--- /dev/null
@@ -0,0 +1,14 @@
+-- New field in archive table to preserve text source IDs across undeletion.
+--
+-- Older entries containing NULL in this field will contain text in the
+-- ar_text and ar_flags fields, and will cause the (re)creation of a new
+-- text record upon undeletion.
+--
+-- Newer ones will reference a text.old_id with this field, and the existing
+-- entries will be used as-is; only a revision record need be created.
+--
+-- Added 2005-05-01
+
+ALTER TABLE /*$wgDBprefix*/archive
+  ADD
+    ar_text_id int(8) unsigned;
index 114549a..0d5da0d 100644 (file)
@@ -108,6 +108,7 @@ CREATE TABLE /*$wgDBprefix*/archive (
   ar_minor_edit tinyint(1) NOT NULL default '0',
   ar_flags tinyblob NOT NULL default '',
   ar_rev_id int(8) unsigned,
+  ar_text_id int(8) unsigned,
   
   KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp)
 );
index 27f9f2d..48b70d1 100644 (file)
@@ -36,6 +36,7 @@ $wgNewFields = array(
        array( 'group',         'group_rights',     'patch-userlevels-rights.sql' ),
        array( 'logging',       'log_params',       'patch-log_params.sql' ),
        array( 'archive',       'ar_rev_id',        'patch-archive-rev_id.sql' ),
+       array( 'archive',       'ar_text_id',       'patch-archive-text_id.sql' ),
        array( 'page',          'page_len',         'patch-page_len.sql' ),
        array( 'revision',      'rev_deleted',      'patch-rev_deleted.sql' ),
        array( 'image',         'img_width',        'patch-img_width.sql' ),