Convert numerous DB queries to use QueryBuilders
Bug: T344971 Change-Id: Ia727b513a6bfcaa5a0b13977a6789aa879ad2f0b
This commit is contained in:
parent
59213059de
commit
b98f33cdac
12 changed files with 274 additions and 264 deletions
|
|
@ -499,7 +499,7 @@ class SelectQueryBuilder extends JoinGroupBase {
|
|||
*
|
||||
* @param string[]|string $fields The field or list of fields to order by.
|
||||
* @param string|null $direction self::SORT_ASC or self::SORT_DESC.
|
||||
* If this is null then $fields is assumed to optionally contain ASC or DESC
|
||||
* If this is null, then $fields is assumed to optionally contain ASC or DESC
|
||||
* after each field name.
|
||||
* @return $this
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
use MediaWiki\User\ActorMigration;
|
||||
use MediaWiki\User\User;
|
||||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
|
@ -52,28 +51,32 @@ class FixUserRegistration extends Maintenance {
|
|||
->orderBy( 'user_id' )
|
||||
->limit( $this->getBatchSize() )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
foreach ( $res as $row ) {
|
||||
$id = $row->user_id;
|
||||
$lastId = $id;
|
||||
|
||||
// Get first edit time
|
||||
$actorQuery = ActorMigration::newMigration()
|
||||
->getWhere( $dbw, 'rev_user', User::newFromId( $id ) );
|
||||
$timestamp = $dbw->selectField(
|
||||
[ 'revision' ] + $actorQuery['tables'],
|
||||
'MIN(rev_timestamp)',
|
||||
$actorQuery['conds'],
|
||||
__METHOD__,
|
||||
[],
|
||||
$actorQuery['joins']
|
||||
);
|
||||
$actorStore = \MediaWiki\MediaWikiServices::getInstance()->getActorStore();
|
||||
$userIdentity = $actorStore->getUserIdentityByUserId( $id );
|
||||
if ( !$userIdentity ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$timestamp = $dbw->newSelectQueryBuilder()
|
||||
->select( 'MIN(rev_timestamp)' )
|
||||
->from( 'revision' )
|
||||
->where( [ 'rev_actor' => $userIdentity->getId() ] )
|
||||
->caller( __METHOD__ )->fetchField();
|
||||
|
||||
// Update
|
||||
if ( $timestamp !== null ) {
|
||||
$dbw->update(
|
||||
'user',
|
||||
[ 'user_registration' => $timestamp ],
|
||||
[ 'user_id' => $id ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'user' )
|
||||
->set( [ 'user_registration' => $timestamp ] )
|
||||
->where( [ 'user_id' => $id ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
$user = User::newFromId( $id );
|
||||
$user->invalidateCache();
|
||||
$this->output( "Set registration for #$id to $timestamp\n" );
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
||||
use MediaWiki\User\ActorMigration;
|
||||
use MediaWiki\WikiMap\WikiMap;
|
||||
|
||||
class InitEditCount extends Maintenance {
|
||||
|
|
@ -51,8 +50,6 @@ class InitEditCount extends Maintenance {
|
|||
$backgroundMode = $lb->hasReplicaServers();
|
||||
}
|
||||
|
||||
$actorQuery = ActorMigration::newMigration()->getJoin( 'rev_user' );
|
||||
|
||||
if ( $backgroundMode ) {
|
||||
$this->output( "Using replication-friendly background mode...\n" );
|
||||
|
||||
|
|
@ -68,21 +65,21 @@ class InitEditCount extends Maintenance {
|
|||
for ( $min = 0; $min <= $lastUser; $min += $chunkSize ) {
|
||||
$max = $min + $chunkSize;
|
||||
|
||||
$revUser = $actorQuery['fields']['rev_user'];
|
||||
$result = $dbr->select(
|
||||
[ 'user', 'rev' => [ 'revision' ] + $actorQuery['tables'] ],
|
||||
[ 'user_id', 'user_editcount' => "COUNT($revUser)" ],
|
||||
"user_id > $min AND user_id <= $max",
|
||||
__METHOD__,
|
||||
[ 'GROUP BY' => 'user_id' ],
|
||||
[ 'rev' => [ 'LEFT JOIN', "user_id = $revUser" ] ] + $actorQuery['joins']
|
||||
);
|
||||
$result = $dbr->newSelectQueryBuilder()
|
||||
->select( [ 'user_id', 'user_editcount' => "COUNT(actor_rev_user.actor_user)" ] )
|
||||
->from( 'user' )
|
||||
->leftJoin( 'revision', 'rev', "user_id = actor_rev_user.actor_user" )
|
||||
->join( 'actor', 'actor_rev_user', 'actor_rev_user.actor_id = rev_actor' )
|
||||
->where( "user_id > $min AND user_id <= $max" )
|
||||
->groupBy( 'user_id' )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
foreach ( $result as $row ) {
|
||||
$dbw->update( 'user',
|
||||
[ 'user_editcount' => $row->user_editcount ],
|
||||
[ 'user_id' => $row->user_id ],
|
||||
__METHOD__ );
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'user' )
|
||||
->set( [ 'user_editcount' => $row->user_editcount ] )
|
||||
->where( [ 'user_id' => $row->user_id ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
++$migrated;
|
||||
}
|
||||
|
||||
|
|
@ -101,14 +98,13 @@ class InitEditCount extends Maintenance {
|
|||
$this->output( "Using single-query mode...\n" );
|
||||
|
||||
$user = $dbw->tableName( 'user' );
|
||||
$subquery = $dbw->selectSQLText(
|
||||
[ 'revision' ] + $actorQuery['tables'],
|
||||
[ 'COUNT(*)' ],
|
||||
[ 'user_id = ' . $actorQuery['fields']['rev_user'] ],
|
||||
__METHOD__,
|
||||
[],
|
||||
$actorQuery['joins']
|
||||
);
|
||||
$subquery = $dbw->newSelectQueryBuilder()
|
||||
->select( 'COUNT(*)' )
|
||||
->from( 'revision' )
|
||||
->join( 'actor', 'actor_rev_user', 'actor_rev_user.actor_id = rev_actor' )
|
||||
->where( 'user_id = actor_rev_user.actor_user' )
|
||||
->caller( __METHOD__ )->getSQL();
|
||||
|
||||
$dbw->query( "UPDATE $user SET user_editcount=($subquery)", __METHOD__ );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance {
|
|||
'revision',
|
||||
'rev_id',
|
||||
'rev',
|
||||
$revisionStore->getQueryInfo()
|
||||
$revisionStore->newSelectQueryBuilder( $this->getDB( DB_REPLICA ) )->joinComment()
|
||||
);
|
||||
|
||||
$this->output( "Populating ar_len column\n" );
|
||||
|
|
@ -70,7 +70,7 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance {
|
|||
'archive',
|
||||
'ar_id',
|
||||
'ar',
|
||||
$revisionStore->getArchiveQueryInfo()
|
||||
$revisionStore->newArchiveSelectQueryBuilder( $this->getDB( DB_REPLICA ) )->joinComment()
|
||||
);
|
||||
|
||||
$this->output( "rev_len and ar_len population complete "
|
||||
|
|
@ -83,10 +83,10 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance {
|
|||
* @param string $table
|
||||
* @param string $idCol
|
||||
* @param string $prefix
|
||||
* @param array $queryInfo
|
||||
* @param \Wikimedia\Rdbms\SelectQueryBuilder $queryBuilder should use a replica db
|
||||
* @return int
|
||||
*/
|
||||
protected function doLenUpdates( $table, $idCol, $prefix, $queryInfo ) {
|
||||
protected function doLenUpdates( $table, $idCol, $prefix, $queryBuilder ) {
|
||||
$dbr = $this->getDB( DB_REPLICA );
|
||||
$dbw = $this->getDB( DB_PRIMARY );
|
||||
$batchSize = $this->getBatchSize();
|
||||
|
|
@ -111,10 +111,9 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance {
|
|||
|
||||
while ( $blockStart <= $end ) {
|
||||
$this->output( "...doing $idCol from $blockStart to $blockEnd\n" );
|
||||
$res = $dbr->select(
|
||||
$queryInfo['tables'],
|
||||
$queryInfo['fields'],
|
||||
[
|
||||
|
||||
$res = $queryBuilder
|
||||
->where( [
|
||||
"$idCol >= $blockStart",
|
||||
"$idCol <= $blockEnd",
|
||||
$dbr->makeList( [
|
||||
|
|
@ -125,11 +124,8 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance {
|
|||
"{$prefix}_sha1 != " . $dbr->addQuotes( 'phoiac9h4m842xq45sp7s6u21eteeq1' ),
|
||||
], IDatabase::LIST_AND )
|
||||
], IDatabase::LIST_OR )
|
||||
],
|
||||
__METHOD__,
|
||||
[],
|
||||
$queryInfo['joins']
|
||||
);
|
||||
] )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
if ( $res->numRows() > 0 ) {
|
||||
$this->beginTransaction( $dbw, __METHOD__ );
|
||||
|
|
@ -175,11 +171,11 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance {
|
|||
}
|
||||
|
||||
# Update the row...
|
||||
$dbw->update( $table,
|
||||
[ "{$prefix}_len" => $revRecord->getSize() ],
|
||||
[ $idCol => $row->$idCol ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( $table )
|
||||
->set( [ "{$prefix}_len" => $revRecord->getSize() ] )
|
||||
->where( [ $idCol => $row->$idCol ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,12 +57,14 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
|
|||
|
||||
$this->output( "Populating rev_sha1 column\n" );
|
||||
$rc = $this->doSha1Updates( $revStore, 'revision', 'rev_id',
|
||||
$revStore->getQueryInfo(), 'rev'
|
||||
$revStore->newSelectQueryBuilder( $this->getDB( DB_PRIMARY ) )->joinComment(),
|
||||
'rev'
|
||||
);
|
||||
|
||||
$this->output( "Populating ar_sha1 column\n" );
|
||||
$ac = $this->doSha1Updates( $revStore, 'archive', 'ar_rev_id',
|
||||
$revStore->getArchiveQueryInfo(), 'ar'
|
||||
$revStore->newArchiveSelectQueryBuilder( $this->getDB( DB_PRIMARY ) )->joinComment(),
|
||||
'ar'
|
||||
);
|
||||
|
||||
$this->output( "rev_sha1 and ar_sha1 population complete "
|
||||
|
|
@ -75,11 +77,11 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
|
|||
* @param MediaWiki\Revision\RevisionStore $revStore
|
||||
* @param string $table
|
||||
* @param string $idCol
|
||||
* @param array $queryInfo
|
||||
* @param \Wikimedia\Rdbms\SelectQueryBuilder $queryBuilder should use a primary db
|
||||
* @param string $prefix
|
||||
* @return int Rows changed
|
||||
*/
|
||||
protected function doSha1Updates( $revStore, $table, $idCol, $queryInfo, $prefix ) {
|
||||
protected function doSha1Updates( $revStore, $table, $idCol, $queryBuilder, $prefix ) {
|
||||
$db = $this->getDB( DB_PRIMARY );
|
||||
$batchSize = $this->getBatchSize();
|
||||
$start = $db->newSelectQueryBuilder()
|
||||
|
|
@ -106,9 +108,9 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
|
|||
|
||||
$cond = "$idCol BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd .
|
||||
" AND $idCol IS NOT NULL AND {$prefix}_sha1 = ''";
|
||||
$res = $db->select(
|
||||
$queryInfo['tables'], $queryInfo['fields'], $cond, __METHOD__, [], $queryInfo['joins']
|
||||
);
|
||||
|
||||
$res = $queryBuilder->where( $cond )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
$this->beginTransaction( $db, __METHOD__ );
|
||||
foreach ( $res as $row ) {
|
||||
|
|
@ -147,11 +149,11 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
|
|||
return false; // T24624? T22757?
|
||||
}
|
||||
|
||||
$db->update( $table,
|
||||
[ "{$prefix}_sha1" => $sha1 ],
|
||||
[ $idCol => $row->$idCol ],
|
||||
__METHOD__
|
||||
);
|
||||
$db->newUpdateQueryBuilder()
|
||||
->update( $table )
|
||||
->set( [ "{$prefix}_sha1" => $sha1 ] )
|
||||
->where( [ $idCol => $row->$idCol ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
* @license GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
use MediaWiki\User\ActorMigration;
|
||||
use MediaWiki\User\User;
|
||||
use Wikimedia\IPUtils;
|
||||
|
||||
|
|
@ -75,7 +74,7 @@ class ReassignEdits extends Maintenance {
|
|||
* @param User &$to User to assign edits to
|
||||
* @param bool $updateRC Update the recent changes table
|
||||
* @param bool $report Don't change things; just echo numbers
|
||||
* @return int Number of entries changed, or that would be changed
|
||||
* @return int The number of entries changed, or that would be changed
|
||||
*/
|
||||
private function doReassignEdits( &$from, &$to, $updateRC = false, $report = false ) {
|
||||
$dbw = $this->getDB( DB_PRIMARY );
|
||||
|
|
@ -85,15 +84,14 @@ class ReassignEdits extends Maintenance {
|
|||
|
||||
# Count things
|
||||
$this->output( "Checking current edits..." );
|
||||
$revQueryInfo = ActorMigration::newMigration()->getWhere( $dbw, 'rev_user', $from );
|
||||
$revisionRows = $dbw->selectRowCount(
|
||||
[ 'revision' ] + $revQueryInfo['tables'],
|
||||
'*',
|
||||
$revQueryInfo['conds'],
|
||||
__METHOD__,
|
||||
[],
|
||||
$revQueryInfo['joins']
|
||||
);
|
||||
|
||||
$revisionRows = $dbw->newSelectQueryBuilder()
|
||||
->select( '*' )
|
||||
->from( 'revision' )
|
||||
->where( [ 'rev_actor' => $fromActorId ] )
|
||||
->caller( __METHOD__ )
|
||||
->fetchRowCount();
|
||||
|
||||
$this->output( "found {$revisionRows}.\n" );
|
||||
|
||||
$this->output( "Checking deleted edits..." );
|
||||
|
|
@ -126,32 +124,37 @@ class ReassignEdits extends Maintenance {
|
|||
if ( $revisionRows ) {
|
||||
# Reassign edits
|
||||
$this->output( "Reassigning current edits..." );
|
||||
$dbw->update(
|
||||
'revision',
|
||||
[ 'rev_actor' => $toActorId ],
|
||||
[ 'rev_actor' => $fromActorId ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'revision' )
|
||||
->set( [ 'rev_actor' => $toActorId ] )
|
||||
->where( [ 'rev_actor' => $fromActorId ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
|
||||
if ( $archiveRows ) {
|
||||
$this->output( "Reassigning deleted edits..." );
|
||||
$dbw->update( 'archive',
|
||||
[ 'ar_actor' => $toActorId ],
|
||||
[ 'ar_actor' => $fromActorId ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'archive' )
|
||||
->set( [ 'ar_actor' => $toActorId ] )
|
||||
->where( [ 'ar_actor' => $fromActorId ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
# Update recent changes if required
|
||||
if ( $recentChangesRows ) {
|
||||
$this->output( "Updating recent changes..." );
|
||||
$dbw->update( 'recentchanges',
|
||||
[ 'rc_actor' => $toActorId ],
|
||||
[ 'rc_actor' => $fromActorId ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'recentchanges' )
|
||||
->set( [ 'rc_actor' => $toActorId ] )
|
||||
->where( [ 'rc_actor' => $fromActorId ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
|
||||
|
|
@ -159,14 +162,11 @@ class ReassignEdits extends Maintenance {
|
|||
# ip_changes. No update needed, as $to cannot be an IP.
|
||||
if ( !$from->isRegistered() ) {
|
||||
$this->output( "Deleting ip_changes..." );
|
||||
$dbw->delete(
|
||||
'ip_changes',
|
||||
[
|
||||
'ipc_hex' => IPUtils::toHex( $from->getName() )
|
||||
],
|
||||
__METHOD__
|
||||
);
|
||||
$this->output( "done.\n" );
|
||||
|
||||
$dbw->newDeleteQueryBuilder()
|
||||
->deleteFrom( 'ip_changes' )
|
||||
->where( [ 'ipc_hex' => IPUtils::toHex( $from->getName() ) ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
||||
use MediaWiki\User\ActorMigration;
|
||||
use Wikimedia\Rdbms\IDatabase;
|
||||
use Wikimedia\Rdbms\SelectQueryBuilder;
|
||||
|
||||
/**
|
||||
* Maintenance script that rebuilds recent changes from scratch.
|
||||
|
|
@ -109,36 +109,46 @@ class RebuildRecentchanges extends Maintenance {
|
|||
->andWhere( [ 'rc_timestamp < ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffTo ) ) ] )
|
||||
->caller( __METHOD__ )->fetchFieldValues();
|
||||
foreach ( array_chunk( $rcids, $this->getBatchSize() ) as $rcidBatch ) {
|
||||
$dbw->delete( 'recentchanges', [ 'rc_id' => $rcidBatch ], __METHOD__ );
|
||||
$dbw->newDeleteQueryBuilder()
|
||||
->deleteFrom( 'recentchanges' )
|
||||
->where( [ 'rc_id' => $rcidBatch ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
$this->waitForReplication();
|
||||
}
|
||||
|
||||
$this->output( "Loading from page and revision tables...\n" );
|
||||
|
||||
$commentQuery = $commentStore->getJoin( 'rev_comment' );
|
||||
$actorQuery = ActorMigration::newMigration()->getJoin( 'rev_user' );
|
||||
$res = $dbw->select(
|
||||
[ 'revision', 'page' ] + $commentQuery['tables'] + $actorQuery['tables'],
|
||||
[
|
||||
'rev_timestamp',
|
||||
'rev_minor_edit',
|
||||
'rev_id',
|
||||
'rev_deleted',
|
||||
'page_namespace',
|
||||
'page_title',
|
||||
'page_is_new',
|
||||
'page_id'
|
||||
] + $commentQuery['fields'] + $actorQuery['fields'],
|
||||
[
|
||||
'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffFrom ) ),
|
||||
'rev_timestamp < ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffTo ) )
|
||||
],
|
||||
__METHOD__,
|
||||
[ 'ORDER BY' => 'rev_timestamp DESC' ],
|
||||
[
|
||||
'page' => [ 'JOIN', 'rev_page=page_id' ],
|
||||
] + $commentQuery['joins'] + $actorQuery['joins']
|
||||
);
|
||||
$res = $dbw->newSelectQueryBuilder()
|
||||
->select(
|
||||
[
|
||||
'rev_timestamp',
|
||||
'rev_minor_edit',
|
||||
'rev_id',
|
||||
'rev_deleted',
|
||||
'page_namespace',
|
||||
'page_title',
|
||||
'page_is_new',
|
||||
'page_id',
|
||||
'rev_comment_text' => 'comment_rev_comment.comment_text',
|
||||
'rev_comment_data' => 'comment_rev_comment.comment_data',
|
||||
'rev_comment_cid' => 'comment_rev_comment.comment_id',
|
||||
'rev_user' => 'actor_rev_user.actor_user',
|
||||
'rev_user_text' => 'actor_rev_user.actor_name',
|
||||
'rev_actor' => 'rev_actor',
|
||||
]
|
||||
)
|
||||
->from( 'revision' )
|
||||
->join( 'page', null, 'rev_page=page_id' )
|
||||
->join( 'comment', 'comment_rev_comment', 'comment_rev_comment.comment_id = rev_comment_id' )
|
||||
->join( 'actor', 'actor_rev_user', 'actor_rev_user.actor_id = rev_actor' )
|
||||
->where(
|
||||
[
|
||||
'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffFrom ) ),
|
||||
'rev_timestamp < ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffTo ) )
|
||||
]
|
||||
)
|
||||
->orderBy( 'rev_timestamp', SelectQueryBuilder::SORT_DESC )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
$this->output( "Inserting from page and revision tables...\n" );
|
||||
$inserted = 0;
|
||||
|
|
@ -165,12 +175,11 @@ class RebuildRecentchanges extends Maintenance {
|
|||
);
|
||||
|
||||
$rcid = $dbw->insertId();
|
||||
$dbw->update(
|
||||
'change_tag',
|
||||
[ 'ct_rc_id' => $rcid ],
|
||||
[ 'ct_rev_id' => $row->rev_id ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'change_tag' )
|
||||
->set( [ 'ct_rc_id' => $rcid ] )
|
||||
->where( [ 'ct_rev_id' => $row->rev_id ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
if ( ( ++$inserted % $this->getBatchSize() ) == 0 ) {
|
||||
$this->waitForReplication();
|
||||
|
|
@ -236,23 +245,23 @@ class RebuildRecentchanges extends Maintenance {
|
|||
->where( [ 'rev_id' => $row->rc_this_oldid ] )
|
||||
->caller( __METHOD__ )->fetchField();
|
||||
|
||||
$dbw->update(
|
||||
'recentchanges',
|
||||
[
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'recentchanges' )
|
||||
->set( [
|
||||
'rc_last_oldid' => $lastOldId,
|
||||
'rc_new' => $new,
|
||||
'rc_type' => $new ? RC_NEW : RC_EDIT,
|
||||
'rc_source' => $new === 1 ? RecentChange::SRC_NEW : RecentChange::SRC_EDIT,
|
||||
'rc_old_len' => $lastSize,
|
||||
'rc_new_len' => $size,
|
||||
],
|
||||
[
|
||||
] )
|
||||
->where( [
|
||||
'rc_cur_id' => $lastCurId,
|
||||
'rc_this_oldid' => $row->rc_this_oldid,
|
||||
'rc_timestamp' => $row->rc_timestamp // index usage
|
||||
],
|
||||
__METHOD__
|
||||
);
|
||||
// index usage
|
||||
'rc_timestamp' => $row->rc_timestamp,
|
||||
] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
$lastOldId = intval( $row->rc_this_oldid );
|
||||
$lastSize = $size;
|
||||
|
|
@ -272,37 +281,44 @@ class RebuildRecentchanges extends Maintenance {
|
|||
|
||||
$dbw = $this->getDB( DB_PRIMARY );
|
||||
$commentStore = $this->getServiceContainer()->getCommentStore();
|
||||
$nonRCLogs = array_merge( array_keys( $wgLogRestrictions ),
|
||||
$nonRCLogs = array_merge(
|
||||
array_keys( $wgLogRestrictions ),
|
||||
array_keys( $wgFilterLogTypes ),
|
||||
[ 'create' ] );
|
||||
[ 'create' ]
|
||||
);
|
||||
|
||||
$this->output( "Loading from user and logging tables...\n" );
|
||||
|
||||
$commentQuery = $commentStore->getJoin( 'log_comment' );
|
||||
$res = $dbw->select(
|
||||
[ 'logging' ] + $commentQuery['tables'],
|
||||
[
|
||||
'log_timestamp',
|
||||
'log_actor',
|
||||
'log_namespace',
|
||||
'log_title',
|
||||
'log_page',
|
||||
'log_type',
|
||||
'log_action',
|
||||
'log_id',
|
||||
'log_params',
|
||||
'log_deleted'
|
||||
] + $commentQuery['fields'],
|
||||
[
|
||||
'log_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffFrom ) ),
|
||||
'log_timestamp < ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffTo ) ),
|
||||
// Some logs don't go in RC since they are private, or are included in the filterable log types.
|
||||
'log_type' => array_diff( LogPage::validTypes(), $nonRCLogs ),
|
||||
],
|
||||
__METHOD__,
|
||||
[ 'ORDER BY' => [ 'log_timestamp DESC', 'log_id DESC' ] ],
|
||||
$commentQuery['joins']
|
||||
);
|
||||
$res = $dbw->newSelectQueryBuilder()
|
||||
->select(
|
||||
[
|
||||
'log_timestamp',
|
||||
'log_actor',
|
||||
'log_namespace',
|
||||
'log_title',
|
||||
'log_page',
|
||||
'log_type',
|
||||
'log_action',
|
||||
'log_id',
|
||||
'log_params',
|
||||
'log_deleted',
|
||||
'log_comment_text' => 'comment_log_comment.comment_text',
|
||||
'log_comment_data' => 'comment_log_comment.comment_data',
|
||||
'log_comment_cid' => 'comment_log_comment.comment_id',
|
||||
]
|
||||
)
|
||||
->from( 'logging' )
|
||||
->join( 'comment', 'comment_log_comment', 'comment_log_comment.comment_id = log_comment_id' )
|
||||
->where(
|
||||
[
|
||||
'log_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffFrom ) ),
|
||||
'log_timestamp < ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffTo ) ),
|
||||
// Some logs don't go in RC since they are private, or are included in the filterable log types.
|
||||
'log_type' => array_diff( LogPage::validTypes(), $nonRCLogs ),
|
||||
]
|
||||
)
|
||||
->orderBy( [ 'log_timestamp DESC', 'log_id DESC' ] )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
$field = $dbw->fieldInfo( 'recentchanges', 'rc_cur_id' );
|
||||
|
||||
|
|
@ -337,12 +353,11 @@ class RebuildRecentchanges extends Maintenance {
|
|||
);
|
||||
|
||||
$rcid = $dbw->insertId();
|
||||
$dbw->update(
|
||||
'change_tag',
|
||||
[ 'ct_rc_id' => $rcid ],
|
||||
[ 'ct_log_id' => $row->log_id ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'change_tag' )
|
||||
->set( [ 'ct_rc_id' => $rcid ] )
|
||||
->where( [ 'ct_log_id' => $row->log_id ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
if ( ( ++$inserted % $this->getBatchSize() ) == 0 ) {
|
||||
$this->waitForReplication();
|
||||
|
|
@ -402,12 +417,11 @@ class RebuildRecentchanges extends Maintenance {
|
|||
$rcids = $this->findRcIdsWithGroups( $dbw, $botgroups );
|
||||
|
||||
foreach ( array_chunk( $rcids, $this->getBatchSize() ) as $rcidBatch ) {
|
||||
$dbw->update(
|
||||
'recentchanges',
|
||||
[ 'rc_bot' => 1 ],
|
||||
[ 'rc_id' => $rcidBatch ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'recentchanges' )
|
||||
->set( [ 'rc_bot' => 1 ] )
|
||||
->where( [ 'rc_id' => $rcidBatch ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
$this->waitForReplication();
|
||||
}
|
||||
}
|
||||
|
|
@ -430,12 +444,11 @@ class RebuildRecentchanges extends Maintenance {
|
|||
|
||||
$rcids = $this->findRcIdsWithGroups( $dbw, $autopatrolgroups, $conds );
|
||||
foreach ( array_chunk( $rcids, $this->getBatchSize() ) as $rcidBatch ) {
|
||||
$dbw->update(
|
||||
'recentchanges',
|
||||
[ 'rc_patrolled' => 2 ],
|
||||
[ 'rc_id' => $rcidBatch ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'recentchanges' )
|
||||
->set( [ 'rc_patrolled' => 2 ] )
|
||||
->where( [ 'rc_id' => $rcidBatch ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
$this->waitForReplication();
|
||||
}
|
||||
}
|
||||
|
|
@ -468,19 +481,17 @@ class RebuildRecentchanges extends Maintenance {
|
|||
$log_id = $row->ls_log_id;
|
||||
|
||||
// Mark the logging row as having an associated rev id
|
||||
$dbw->update(
|
||||
'recentchanges',
|
||||
/*SET*/ [ 'rc_this_oldid' => $rev_id ],
|
||||
/*WHERE*/ [ 'rc_logid' => $log_id ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newUpdateQueryBuilder()
|
||||
->update( 'recentchanges' )
|
||||
->set( [ 'rc_this_oldid' => $rev_id ] )
|
||||
->where( [ 'rc_logid' => $log_id ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
// Delete the revision row
|
||||
$dbw->delete(
|
||||
'recentchanges',
|
||||
/*WHERE*/ [ 'rc_this_oldid' => $rev_id, 'rc_logid' => 0 ],
|
||||
__METHOD__
|
||||
);
|
||||
$dbw->newDeleteQueryBuilder()
|
||||
->deleteFrom( 'recentchanges' )
|
||||
->where( [ 'rc_this_oldid' => $rev_id, 'rc_logid' => 0 ] )
|
||||
->caller( __METHOD__ )->execute();
|
||||
|
||||
if ( ( ++$updates % $this->getBatchSize() ) == 0 ) {
|
||||
$this->waitForReplication();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
|
||||
use MediaWiki\Title\Title;
|
||||
use MediaWiki\User\ActorMigration;
|
||||
use MediaWiki\User\User;
|
||||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
|
@ -114,16 +113,14 @@ class RollbackEdits extends Maintenance {
|
|||
private function getRollbackTitles( $user ) {
|
||||
$dbr = $this->getDB( DB_REPLICA );
|
||||
$titles = [];
|
||||
$actorQuery = ActorMigration::newMigration()
|
||||
->getWhere( $dbr, 'rev_user', User::newFromName( $user, false ) );
|
||||
$results = $dbr->select(
|
||||
[ 'page', 'revision' ] + $actorQuery['tables'],
|
||||
[ 'page_namespace', 'page_title' ],
|
||||
$actorQuery['conds'],
|
||||
__METHOD__,
|
||||
[],
|
||||
[ 'revision' => [ 'JOIN', 'page_latest = rev_id' ] ] + $actorQuery['joins']
|
||||
);
|
||||
|
||||
$results = $dbr->newSelectQueryBuilder()
|
||||
->select( [ 'page_namespace', 'page_title' ] )
|
||||
->from( 'page' )
|
||||
->join( 'revision', null, 'page_latest = rev_id' )
|
||||
->join( 'actor', null, 'rev_actor = actor_id' )
|
||||
->where( [ 'actor_name' => $user ] )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
foreach ( $results as $row ) {
|
||||
$titles[] = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
||||
use Wikimedia\Rdbms\IDatabase;
|
||||
use Wikimedia\Rdbms\Platform\ISQLPlatform;
|
||||
|
||||
/**
|
||||
* Maintenance script to run a database query in batches and wait for replica DBs.
|
||||
|
|
@ -71,14 +71,21 @@ class RunBatchedQuery extends Maintenance {
|
|||
$this->output( "Batch $n: " );
|
||||
$n++;
|
||||
|
||||
// Note that the update conditions do not rely on atomicity of the
|
||||
// Note that the update conditions do not rely on the atomicity of the
|
||||
// SELECT query in order to guarantee that all rows are updated. The
|
||||
// results of the SELECT are merely a partitioning hint. Simultaneous
|
||||
// updates merely result in the wrong number of rows being updated
|
||||
// in a batch.
|
||||
|
||||
$res = $dbw->select( $table, $key, $selectConds, __METHOD__,
|
||||
[ 'ORDER BY' => $key, 'LIMIT' => $batchSize ] );
|
||||
$res = $dbw->newSelectQueryBuilder()
|
||||
->select( $key )
|
||||
->from( $table )
|
||||
->where( $selectConds )
|
||||
->orderBy( $key )
|
||||
->limit( $batchSize )
|
||||
->caller( __METHOD__ )
|
||||
->fetchResultSet();
|
||||
|
||||
if ( $res->numRows() ) {
|
||||
$res->seek( $res->numRows() - 1 );
|
||||
$row = $res->fetchObject();
|
||||
|
|
@ -95,7 +102,7 @@ class RunBatchedQuery extends Maintenance {
|
|||
|
||||
$query = "UPDATE " . $dbw->tableName( $table ) .
|
||||
" SET " . $set .
|
||||
" WHERE " . $dbw->makeList( $updateConds, IDatabase::LIST_AND );
|
||||
" WHERE " . $dbw->makeList( $updateConds, ISQLPlatform::LIST_AND );
|
||||
|
||||
$dbw->query( $query, __METHOD__ );
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ class CompressOld extends Maintenance {
|
|||
$pageConds[] = 'page_namespace<>0';
|
||||
}
|
||||
if ( $queryExtra ) {
|
||||
$pageConds[] = $queryExtra;
|
||||
$pageConds[] = $queryExtra;
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
@ -268,11 +268,23 @@ class CompressOld extends Maintenance {
|
|||
# Don't compress object type entities, because that might produce data loss when
|
||||
# overwriting bulk storage concat rows. Don't compress external references, because
|
||||
# the script doesn't yet delete rows from external storage.
|
||||
$conds = [
|
||||
'old_flags NOT ' . $dbr->buildLike( $dbr->anyString(), 'object', $dbr->anyString() )
|
||||
. ' AND old_flags NOT '
|
||||
. $dbr->buildLike( $dbr->anyString(), 'external', $dbr->anyString() )
|
||||
];
|
||||
$slotRoleStore = $this->getServiceContainer()->getSlotRoleStore();
|
||||
$queryBuilderTemplate = $dbw->newSelectQueryBuilder()
|
||||
->select( [ 'rev_id', 'old_id', 'old_flags', 'old_text' ] )
|
||||
->forUpdate()
|
||||
->from( 'revision' )
|
||||
->join( 'slots', null, 'rev_id=slot_revision_id' )
|
||||
->join( 'content', null, 'content_id=slot_content_id' )
|
||||
->join( 'text', null, 'SUBSTRING(content_address, 4)=old_id' )
|
||||
->where(
|
||||
'old_flags NOT ' . $dbr->buildLike( $dbr->anyString(), 'object', $dbr->anyString() )
|
||||
. ' AND old_flags NOT '
|
||||
. $dbr->buildLike( $dbr->anyString(), 'external', $dbr->anyString() )
|
||||
)
|
||||
->andWhere( [
|
||||
'slot_role_id' => $slotRoleStore->getId( SlotRecord::MAIN ),
|
||||
'SUBSTRING(content_address, 1, 3)=' . $dbr->addQuotes( 'tt:' ),
|
||||
] );
|
||||
|
||||
if ( $beginDate ) {
|
||||
if ( !preg_match( '/^\d{14}$/', $beginDate ) ) {
|
||||
|
|
@ -280,7 +292,7 @@ class CompressOld extends Maintenance {
|
|||
|
||||
return false;
|
||||
}
|
||||
$conds[] = "rev_timestamp>'" . $beginDate . "'";
|
||||
$queryBuilderTemplate->andWhere( "rev_timestamp>'" . $beginDate . "'" );
|
||||
}
|
||||
if ( $endDate ) {
|
||||
if ( !preg_match( '/^\d{14}$/', $endDate ) ) {
|
||||
|
|
@ -288,27 +300,9 @@ class CompressOld extends Maintenance {
|
|||
|
||||
return false;
|
||||
}
|
||||
$conds[] = "rev_timestamp<'" . $endDate . "'";
|
||||
$queryBuilderTemplate->andWhere( "rev_timestamp<'" . $endDate . "'" );
|
||||
}
|
||||
|
||||
$slotRoleStore = $this->getServiceContainer()->getSlotRoleStore();
|
||||
$tables = [ 'revision', 'slots', 'content', 'text' ];
|
||||
$conds = array_merge( [
|
||||
'rev_id=slot_revision_id',
|
||||
'slot_role_id=' . $slotRoleStore->getId( SlotRecord::MAIN ),
|
||||
'content_id=slot_content_id',
|
||||
'SUBSTRING(content_address, 1, 3)=' . $dbr->addQuotes( 'tt:' ),
|
||||
'SUBSTRING(content_address, 4)=old_id',
|
||||
], $conds );
|
||||
|
||||
$fields = [ 'rev_id', 'old_id', 'old_flags', 'old_text' ];
|
||||
$revLoadOptions = 'FOR UPDATE';
|
||||
|
||||
# Don't work with current revisions
|
||||
# Don't lock the page table for update either -- TS 2006-04-04
|
||||
# $tables[] = 'page';
|
||||
# $conds[] = 'page_id=rev_page AND rev_id != page_latest';
|
||||
|
||||
for ( $pageId = $startId; $pageId <= $maxPageId; $pageId++ ) {
|
||||
$this->waitForReplication();
|
||||
|
||||
|
|
@ -332,17 +326,17 @@ class CompressOld extends Maintenance {
|
|||
$this->output( "$pageId\t" . $titleObj->getPrefixedDBkey() . " " );
|
||||
|
||||
# Load revisions
|
||||
$revRes = $dbw->select( $tables, $fields,
|
||||
array_merge( [
|
||||
$queryBuilder = clone $queryBuilderTemplate;
|
||||
$revRes = $queryBuilder->where(
|
||||
[
|
||||
'rev_page' => $pageRow->page_id,
|
||||
# Don't operate on the current revision
|
||||
# Use < instead of <> in case the current revision has changed
|
||||
# since the page select, which wasn't locking
|
||||
// Don't operate on the current revision
|
||||
// Use < instead of <> in case the current revision has changed
|
||||
// since the page select, which wasn't locking
|
||||
'rev_timestamp < ' . (int)$pageRow->rev_timestamp
|
||||
], $conds ),
|
||||
__METHOD__,
|
||||
$revLoadOptions
|
||||
);
|
||||
] )
|
||||
->caller( __METHOD__ )->fetchResultSet();
|
||||
|
||||
$revs = [];
|
||||
foreach ( $revRes as $revRow ) {
|
||||
$revs[] = $revRow;
|
||||
|
|
|
|||
|
|
@ -334,12 +334,11 @@ class RecompressTracked {
|
|||
if ( $this->noCount ) {
|
||||
$numPages = '[unknown]';
|
||||
} else {
|
||||
$numPages = $dbr->selectField( 'blob_tracking',
|
||||
'COUNT(DISTINCT bt_page)',
|
||||
# A condition is required so that this query uses the index
|
||||
[ 'bt_moved' => 0 ],
|
||||
__METHOD__
|
||||
);
|
||||
$numPages = $dbr->newSelectQueryBuilder()
|
||||
->select( 'COUNT(DISTINCT bt_page)' )
|
||||
->from( 'blob_tracking' )
|
||||
->where( [ 'bt_moved' => 0 ] )
|
||||
->caller( __METHOD__ )->fetchField();
|
||||
}
|
||||
if ( $this->copyOnly ) {
|
||||
$this->info( "Copying pages..." );
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\SiteStats\SiteStats;
|
||||
use Wikimedia\Rdbms\IDatabase;
|
||||
use Wikimedia\Rdbms\Platform\ISQLPlatform;
|
||||
|
||||
/**
|
||||
* @group Database
|
||||
|
|
@ -42,10 +42,15 @@ class SiteStatsTest extends MediaWikiIntegrationTestCase {
|
|||
* @covers MediaWiki\SiteStats\SiteStats
|
||||
*/
|
||||
public function testInit() {
|
||||
$this->db->delete( 'site_stats', IDatabase::ALL_ROWS, __METHOD__ );
|
||||
$this->db->delete( 'site_stats', ISQLPlatform::ALL_ROWS, __METHOD__ );
|
||||
SiteStats::unload();
|
||||
|
||||
SiteStats::edits();
|
||||
$this->assertNotFalse( $this->db->selectRow( 'site_stats', '1', IDatabase::ALL_ROWS, __METHOD__ ) );
|
||||
$row = $this->db->newSelectQueryBuilder()
|
||||
->select( '1' )
|
||||
->from( 'site_stats' )
|
||||
->caller( __METHOD__ )->fetchRow();
|
||||
|
||||
$this->assertNotFalse( $row );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue