MediaWiki master
populateRevisionLength.php
Go to the documentation of this file.
1<?php
24require_once __DIR__ . '/Maintenance.php';
25
34 public function __construct() {
35 parent::__construct();
36 $this->addDescription( 'Populates the rev_len and ar_len fields' );
37 $this->setBatchSize( 200 );
38 }
39
40 protected function getUpdateKey() {
41 return 'populate rev_len and ar_len';
42 }
43
44 public function doDBUpdates() {
45 $dbw = $this->getDB( DB_PRIMARY );
46 if ( !$dbw->tableExists( 'revision', __METHOD__ ) ) {
47 $this->fatalError( "revision table does not exist" );
48 } elseif ( !$dbw->tableExists( 'archive', __METHOD__ ) ) {
49 $this->fatalError( "archive table does not exist" );
50 } elseif ( !$dbw->fieldExists( 'revision', 'rev_len', __METHOD__ ) ) {
51 $this->output( "rev_len column does not exist\n\n", true );
52
53 return false;
54 }
55
56 $revisionStore = $this->getServiceContainer()->getRevisionStore();
57
58 $this->output( "Populating rev_len column\n" );
59 $rev = $this->doLenUpdates(
60 'revision',
61 'rev_id',
62 'rev',
63 $revisionStore->newSelectQueryBuilder( $this->getReplicaDB() )->joinComment()
64 );
65
66 $this->output( "Populating ar_len column\n" );
67 $ar = $this->doLenUpdates(
68 'archive',
69 'ar_id',
70 'ar',
71 $revisionStore->newArchiveSelectQueryBuilder( $this->getReplicaDB() )->joinComment()
72 );
73
74 $this->output( "rev_len and ar_len population complete "
75 . "[$rev revision rows, $ar archive rows].\n" );
76
77 return true;
78 }
79
87 protected function doLenUpdates( $table, $idCol, $prefix, $queryBuilder ) {
88 $dbr = $this->getReplicaDB();
89 $dbw = $this->getPrimaryDB();
90 $batchSize = $this->getBatchSize();
91 $start = $dbw->newSelectQueryBuilder()
92 ->select( "MIN($idCol)" )
93 ->from( $table )
94 ->caller( __METHOD__ )->fetchField();
95 $end = $dbw->newSelectQueryBuilder()
96 ->select( "MAX($idCol)" )
97 ->from( $table )
98 ->caller( __METHOD__ )->fetchField();
99 if ( !$start || !$end ) {
100 $this->output( "...$table table seems to be empty.\n" );
101
102 return 0;
103 }
104
105 # Do remaining chunks
106 $blockStart = intval( $start );
107 $blockEnd = intval( $start ) + $batchSize - 1;
108 $count = 0;
109
110 while ( $blockStart <= $end ) {
111 $this->output( "...doing $idCol from $blockStart to $blockEnd\n" );
112
113 $res = $queryBuilder
114 ->where( [
115 "$idCol >= $blockStart",
116 "$idCol <= $blockEnd",
117 $dbr->expr( "{$prefix}_len", '=', null )
118 ->orExpr(
119 $dbr->expr( "{$prefix}_len", '=', 0 )
120 // sha1( "" )
121 ->and( "{$prefix}_sha1", '!=', 'phoiac9h4m842xq45sp7s6u21eteeq1' )
122 ),
123 ] )
124 ->caller( __METHOD__ )->fetchResultSet();
125
126 if ( $res->numRows() > 0 ) {
127 $this->beginTransaction( $dbw, __METHOD__ );
128 # Go through and update rev_len from these rows.
129 foreach ( $res as $row ) {
130 if ( $this->upgradeRow( $row, $table, $idCol, $prefix ) ) {
131 $count++;
132 }
133 }
134 $this->commitTransaction( $dbw, __METHOD__ );
135 }
136
137 $blockStart += $batchSize;
138 $blockEnd += $batchSize;
139 }
140
141 return $count;
142 }
143
151 protected function upgradeRow( $row, $table, $idCol, $prefix ) {
152 $dbw = $this->getPrimaryDB();
153
154 $revFactory = $this->getServiceContainer()->getRevisionFactory();
155 if ( $table === 'archive' ) {
156 $revRecord = $revFactory->newRevisionFromArchiveRow( $row );
157 } else {
158 $revRecord = $revFactory->newRevisionFromRow( $row );
159 }
160
161 if ( !$revRecord ) {
162 # This should not happen, but sometimes does (T22757)
163 $id = $row->$idCol;
164 $this->output( "RevisionRecord of $table $id unavailable!\n" );
165
166 return false;
167 }
168
169 # Update the row...
170 $dbw->newUpdateQueryBuilder()
171 ->update( $table )
172 ->set( [ "{$prefix}_len" => $revRecord->getSize() ] )
173 ->where( [ $idCol => $row->$idCol ] )
174 ->caller( __METHOD__ )->execute();
175
176 return true;
177 }
178}
179
180$maintClass = PopulateRevisionLength::class;
181require_once RUN_MAINTENANCE_IF_MAIN;
getDB()
Class for scripts that perform database maintenance and want to log the update in updatelog so we can...
beginTransaction(IDatabase $dbw, $fname)
Begin a transaction on a DB.
commitTransaction(IDatabase $dbw, $fname)
Commit the transaction on a DB handle and wait for replica DBs to catch up.
output( $out, $channel=null)
Throw some output to the user.
getServiceContainer()
Returns the main service container.
getBatchSize()
Returns batch size.
addDescription( $text)
Set the description text.
setBatchSize( $s=0)
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Maintenance script that populates the rev_len and ar_len fields when they are NULL.
__construct()
Default constructor.
doDBUpdates()
Do the actual work.
upgradeRow( $row, $table, $idCol, $prefix)
getUpdateKey()
Get the update key name to go in the update log table.
doLenUpdates( $table, $idCol, $prefix, $queryBuilder)
const DB_PRIMARY
Definition defines.php:28