MediaWiki REL1_31
populateArchiveRevId.php
Go to the documentation of this file.
1<?php
25
26require_once __DIR__ . '/Maintenance.php';
27
35 public function __construct() {
36 parent::__construct();
37 $this->addDescription( 'Populate ar_rev_id in pre-1.5 rows' );
38 $this->setBatchSize( 100 );
39 }
40
41 protected function getUpdateKey() {
42 return __CLASS__;
43 }
44
45 protected function doDBUpdates() {
46 $this->output( "Populating ar_rev_id...\n" );
47 $dbw = $this->getDB( DB_MASTER );
48
49 // Quick exit if there are no rows needing updates.
50 $any = $dbw->selectField(
51 'archive',
52 'ar_id',
53 [ 'ar_rev_id' => null ],
54 __METHOD__
55 );
56 if ( !$any ) {
57 $this->output( "Completed ar_rev_id population, 0 rows updated.\n" );
58 return true;
59 }
60
61 $rev = $this->makeDummyRevisionRow( $dbw );
62 $count = 0;
63 while ( true ) {
65
66 $arIds = $dbw->selectFieldValues(
67 'archive',
68 'ar_id',
69 [ 'ar_rev_id' => null ],
70 __METHOD__,
71 [ 'LIMIT' => $this->getBatchSize(), 'ORDER BY' => [ 'ar_id' ] ]
72 );
73 if ( !$arIds ) {
74 $this->output( "Completed ar_rev_id population, $count rows updated.\n" );
75 return true;
76 }
77
78 try {
79 $updates = $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) use ( $arIds, $rev ) {
80 // Create new rev_ids by inserting dummy rows into revision and then deleting them.
81 $dbw->insert( 'revision', array_fill( 0, count( $arIds ), $rev ), $fname );
82 $revIds = $dbw->selectFieldValues(
83 'revision',
84 'rev_id',
85 [ 'rev_timestamp' => $rev['rev_timestamp'] ],
86 $fname
87 );
88 if ( !is_array( $revIds ) ) {
89 throw new UnexpectedValueException( 'Failed to insert dummy revisions' );
90 }
91 if ( count( $revIds ) !== count( $arIds ) ) {
92 throw new UnexpectedValueException(
93 'Tried to insert ' . count( $arIds ) . ' dummy revisions, but found '
94 . count( $revIds ) . ' matching rows.'
95 );
96 }
97 $dbw->delete( 'revision', [ 'rev_id' => $revIds ], $fname );
98
99 return array_combine( $arIds, $revIds );
100 } );
101 } catch ( UnexpectedValueException $ex ) {
102 $this->fatalError( $ex->getMessage() );
103 }
104
105 foreach ( $updates as $arId => $revId ) {
106 $dbw->update(
107 'archive',
108 [ 'ar_rev_id' => $revId ],
109 [ 'ar_id' => $arId, 'ar_rev_id' => null ],
110 __METHOD__
111 );
112 $count += $dbw->affectedRows();
113 }
114
115 $min = min( array_keys( $updates ) );
116 $max = max( array_keys( $updates ) );
117 $this->output( " ... $min-$max\n" );
118 }
119 }
120
131 private function makeDummyRevisionRow( IDatabase $dbw ) {
132 $ts = $dbw->timestamp( '11111111111111' );
133 $mainPage = Title::newMainPage();
134 if ( !$mainPage ) {
135 $this->fatalError( 'Main page does not exist' );
136 }
137 $pageId = $mainPage->getArticleId();
138 if ( !$pageId ) {
139 $this->fatalError( $mainPage->getPrefixedText() . ' has no ID' );
140 }
141 $rev = $dbw->selectRow(
142 'revision',
143 '*',
144 [ 'rev_page' => $pageId ],
145 __METHOD__,
146 [ 'ORDER BY' => 'rev_timestamp ASC' ]
147 );
148 if ( !$rev ) {
149 $this->fatalError( $mainPage->getPrefixedText() . ' has no revisions' );
150 }
151 unset( $rev->rev_id );
152 $rev = (array)$rev;
153 $rev['rev_timestamp'] = $ts;
154 if ( isset( $rev['rev_user'] ) ) {
155 $rev['rev_user'] = 0;
156 $rev['rev_user_text'] = '0.0.0.0';
157 }
158 if ( isset( $rev['rev_comment'] ) ) {
159 $rev['rev_comment'] = 'Dummy row';
160 }
161
162 $any = $dbw->selectField(
163 'revision',
164 'rev_id',
165 [ 'rev_timestamp' => $ts ],
166 __METHOD__
167 );
168 if ( $any ) {
169 $this->fatalError( "... Why does your database contain a revision dated $ts?" );
170 }
171
172 return $rev;
173 }
174}
175
176$maintClass = "PopulateArchiveRevId";
177require_once RUN_MAINTENANCE_IF_MAIN;
wfWaitForSlaves( $ifWritesSince=null, $wiki=false, $cluster=false, $timeout=null)
Waits for the replica DBs to catch up to the master position.
if(defined( 'MW_SETUP_CALLBACK')) $fname
Customization point after all loading (constants, functions, classes, DefaultSettings,...
Definition Setup.php:112
Class for scripts that perform database maintenance and want to log the update in updatelog so we can...
getDB( $db, $groups=[], $wiki=false)
Returns a database to be used by current maintenance script.
getBatchSize()
Returns batch size.
addDescription( $text)
Set the description text.
setBatchSize( $s=0)
Set the batch size.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Maintenance script that populares archive.ar_rev_id in old rows.
doDBUpdates()
Do the actual work.
getUpdateKey()
Get the update key name to go in the update log table.
makeDummyRevisionRow(IDatabase $dbw)
Construct a dummy revision table row to use for reserving IDs.
__construct()
Default constructor.
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any and then calling output() to send it all. It could be easily changed to send incrementally if that becomes useful
the array() calling protocol came about after MediaWiki 1.4rc1.
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition hooks.txt:1777
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:38
selectRow( $table, $vars, $conds, $fname=__METHOD__, $options=[], $join_conds=[])
Single row SELECT wrapper.
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
selectField( $table, $var, $cond='', $fname=__METHOD__, $options=[], $join_conds=[])
A SELECT wrapper which returns a single field from a single result row.
require_once RUN_MAINTENANCE_IF_MAIN
const DB_MASTER
Definition defines.php:29