3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
18 * @ingroup Maintenance
21 require_once( "Maintenance.php" );
23 class InitEditCount
extends Maintenance
{
24 public function __construct() {
25 parent
::__construct();
26 $this->addOption( 'quick', 'Force the update to be done in a single query' );
27 $this->addOption( 'background', 'Force replication-friendly mode; may be inefficient but
28 avoids locking tables or lagging slaves with large updates;
29 calculates counts on a slave if possible.
31 Background mode will be automatically used if the server is MySQL 4.0
32 (which does not support subqueries) or if multiple servers are listed
33 in $wgDBservers, usually indicating a replication environment.' );
34 $this->mDescription
= "Batch-recalculate user_editcount fields from the revision table";
37 public function execute() {
38 $dbw = wfGetDB( DB_MASTER
);
39 $user = $dbw->tableName( 'user' );
40 $revision = $dbw->tableName( 'revision' );
42 $dbver = $dbw->getServerVersion();
45 $backgroundMode = count( $wgDBservers ) > 1 ||
46 ($dbw instanceof DatabaseMySql
&& version_compare( $dbver, '4.1' ) < 0);
48 if( $this->hasOption('background') ) {
49 $backgroundMode = true;
50 } elseif( $this->hasOption('quick') ) {
51 $backgroundMode = false;
54 if( $backgroundMode ) {
55 $this->output( "Using replication-friendly background mode...\n" );
57 $dbr = wfGetDB( DB_SLAVE
);
59 $lastUser = $dbr->selectField( 'user', 'MAX(user_id)', '', __METHOD__
);
61 $start = microtime( true );
63 for( $min = 0; $min <= $lastUser; $min +
= $chunkSize ) {
64 $max = $min +
$chunkSize;
65 $result = $dbr->query(
68 COUNT(rev_user) AS user_editcount
70 LEFT OUTER JOIN $revision ON user_id=rev_user
71 WHERE user_id > $min AND user_id <= $max
75 while( $row = $dbr->fetchObject( $result ) ) {
77 array( 'user_editcount' => $row->user_editcount
),
78 array( 'user_id' => $row->user_id
),
82 $dbr->freeResult( $result );
84 $delta = microtime( true ) - $start;
85 $rate = ($delta == 0.0) ?
0.0 : $migrated / $delta;
86 $this->output( sprintf( "%s %d (%0.1f%%) done in %0.1f secs (%0.3f accounts/sec).\n",
89 min( $max, $lastUser ) / $lastUser * 100.0,
93 wfWaitForSlaves( 10 );
96 // Subselect should work on modern MySQLs etc
97 $this->output( "Using single-query mode...\n" );
98 $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)";
102 $this->output( "Done!\n" );
106 $maintClass = "InitEditCount";
107 require_once( DO_MAINTENANCE
);