MediaWiki
REL1_24
|
00001 <?php 00026 require_once __DIR__ . '/Maintenance.php'; 00027 00034 class PopulateParentId extends LoggedUpdateMaintenance { 00035 public function __construct() { 00036 parent::__construct(); 00037 $this->mDescription = "Populates rev_parent_id"; 00038 } 00039 00040 protected function getUpdateKey() { 00041 return 'populate rev_parent_id'; 00042 } 00043 00044 protected function updateSkippedMessage() { 00045 return 'rev_parent_id column of revision table already populated.'; 00046 } 00047 00048 protected function doDBUpdates() { 00049 $db = wfGetDB( DB_MASTER ); 00050 if ( !$db->tableExists( 'revision' ) ) { 00051 $this->error( "revision table does not exist" ); 00052 00053 return false; 00054 } 00055 $this->output( "Populating rev_parent_id column\n" ); 00056 $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ ); 00057 $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ ); 00058 if ( is_null( $start ) || is_null( $end ) ) { 00059 $this->output( "...revision table seems to be empty, nothing to do.\n" ); 00060 00061 return true; 00062 } 00063 # Do remaining chunk 00064 $blockStart = intval( $start ); 00065 $blockEnd = intval( $start ) + $this->mBatchSize - 1; 00066 $count = 0; 00067 $changed = 0; 00068 while ( $blockStart <= $end ) { 00069 $this->output( "...doing rev_id from $blockStart to $blockEnd\n" ); 00070 $cond = "rev_id BETWEEN $blockStart AND $blockEnd"; 00071 $res = $db->select( 'revision', 00072 array( 'rev_id', 'rev_page', 'rev_timestamp', 'rev_parent_id' ), 00073 array( $cond, 'rev_parent_id' => null ), __METHOD__ ); 00074 # Go through and update rev_parent_id from these rows. 00075 # Assume that the previous revision of the title was 00076 # the original previous revision of the title when the 00077 # edit was made... 00078 foreach ( $res as $row ) { 00079 # First, check rows with the same timestamp other than this one 00080 # with a smaller rev ID. The highest ID "wins". This avoids loops 00081 # as timestamp can only decrease and never loops with IDs (from parent to parent) 00082 $previousID = $db->selectField( 'revision', 'rev_id', 00083 array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $row->rev_timestamp, 00084 "rev_id < " . intval( $row->rev_id ) ), 00085 __METHOD__, 00086 array( 'ORDER BY' => 'rev_id DESC' ) ); 00087 # If there are none, check the the highest ID with a lower timestamp 00088 if ( !$previousID ) { 00089 # Get the highest older timestamp 00090 $lastTimestamp = $db->selectField( 00091 'revision', 00092 'rev_timestamp', 00093 array( 00094 'rev_page' => $row->rev_page, 00095 "rev_timestamp < " . $db->addQuotes( $row->rev_timestamp ) 00096 ), 00097 __METHOD__, 00098 array( 'ORDER BY' => 'rev_timestamp DESC' ) 00099 ); 00100 # If there is one, let the highest rev ID win 00101 if ( $lastTimestamp ) { 00102 $previousID = $db->selectField( 'revision', 'rev_id', 00103 array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $lastTimestamp ), 00104 __METHOD__, 00105 array( 'ORDER BY' => 'rev_id DESC' ) ); 00106 } 00107 } 00108 $previousID = intval( $previousID ); 00109 if ( $previousID != $row->rev_parent_id ) { 00110 $changed++; 00111 } 00112 # Update the row... 00113 $db->update( 'revision', 00114 array( 'rev_parent_id' => $previousID ), 00115 array( 'rev_id' => $row->rev_id ), 00116 __METHOD__ ); 00117 $count++; 00118 } 00119 $blockStart += $this->mBatchSize; 00120 $blockEnd += $this->mBatchSize; 00121 wfWaitForSlaves(); 00122 } 00123 $this->output( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" ); 00124 00125 return true; 00126 } 00127 } 00128 00129 $maintClass = "PopulateParentId"; 00130 require_once RUN_MAINTENANCE_IF_MAIN;