Use expression builder to avoid raw sql via BETWEEN operator

Replace BETWEEN with >= and <= operator

Change-Id: Ic21b6f4cc11c773c967d9d4c5f20e762c2ff9629
This commit is contained in:
Umherirrender 2024-04-21 14:24:21 +02:00
parent 401c78b10e
commit fea5c2f687
15 changed files with 67 additions and 36 deletions

View file

@ -244,9 +244,7 @@ class ApiQueryUserContribs extends ApiQueryBase {
$res = $dbSecondary->newSelectQueryBuilder()
->select( 'ipc_hex' )
->from( 'ip_changes' )
->where( [ 'ipc_hex BETWEEN ' . $dbSecondary->addQuotes( $start ) .
' AND ' . $dbSecondary->addQuotes( $end )
] )
->where( $dbSecondary->expr( 'ipc_hex', '>=', $start )->and( 'ipc_hex', '<=', $end ) )
->groupBy( 'ipc_hex' )
->orderBy( 'ipc_hex', $sort )
->limit( $limit )

View file

@ -50,6 +50,7 @@ use stdClass;
use Wikimedia\IPUtils;
use Wikimedia\Rdbms\FakeResultWrapper;
use Wikimedia\Rdbms\IConnectionProvider;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\IReadableDatabase;
use Wikimedia\Rdbms\IResultWrapper;
@ -457,7 +458,7 @@ class ContribsPager extends RangeChronologicalPager {
* Get SQL conditions for an IP range, if applicable
* @param IReadableDatabase $db
* @param string $ip The IP address or CIDR
* @return string|false SQL for valid IP ranges, false if invalid
* @return IExpression|false SQL for valid IP ranges, false if invalid
*/
private function getIpRangeConds( $db, $ip ) {
// First make sure it is a valid range and they are not outside the CIDR limit
@ -467,7 +468,7 @@ class ContribsPager extends RangeChronologicalPager {
[ $start, $end ] = IPUtils::parseRange( $ip );
return 'ipc_hex BETWEEN ' . $db->addQuotes( $start ) . ' AND ' . $db->addQuotes( $end );
return $db->expr( 'ipc_hex', '>=', $start )->and( 'ipc_hex', '<=', $end );
}
/**

View file

@ -69,7 +69,7 @@ class MigrateExternallinks extends LoggedUpdateMaintenance {
private function handleBatch( $lowId ) {
$batchSize = $this->getBatchSize();
// BETWEEN is inclusive, let's subtract one.
// range is inclusive, let's subtract one.
$highId = $lowId + $batchSize - 1;
$dbw = $this->getPrimaryDB();
$updated = 0;
@ -78,7 +78,8 @@ class MigrateExternallinks extends LoggedUpdateMaintenance {
->from( 'externallinks' )
->where( [
'el_to_domain_index' => '',
"el_id BETWEEN $lowId AND $highId"
$dbw->expr( 'el_id', '>=', $lowId ),
$dbw->expr( 'el_id', '<=', $highId ),
] )
->limit( $batchSize )
->caller( __METHOD__ )

View file

@ -90,7 +90,7 @@ class MigrateLinksTable extends LoggedUpdateMaintenance {
$batchSize = $this->getBatchSize();
$targetColumn = $mapping[$table]['target_id'];
$pageIdColumn = $mapping[$table]['page_id'];
// BETWEEN is inclusive, let's subtract one.
// range is inclusive, let's subtract one.
$highPageId = $lowPageId + $batchSize - 1;
$dbw = $this->getPrimaryDB();
$updated = 0;
@ -101,7 +101,8 @@ class MigrateLinksTable extends LoggedUpdateMaintenance {
->from( $table )
->where( [
$targetColumn => [ null, 0 ],
"$pageIdColumn BETWEEN $lowPageId AND $highPageId"
$dbw->expr( $pageIdColumn, '>=', $lowPageId ),
$dbw->expr( $pageIdColumn, '<=', $highPageId ),
] )
->limit( 1 )
->caller( __METHOD__ )
@ -123,7 +124,8 @@ class MigrateLinksTable extends LoggedUpdateMaintenance {
$targetColumn => [ null, 0 ],
$mapping[$table]['ns'] => $ns,
$mapping[$table]['title'] => $titleString,
"$pageIdColumn BETWEEN $lowPageId AND $highPageId"
$dbw->expr( $pageIdColumn, '>=', $lowPageId ),
$dbw->expr( $pageIdColumn, '<=', $highPageId ),
] )
->caller( __METHOD__ )->execute();
$updatedInThisBatch = $dbw->affectedRows();

View file

@ -74,7 +74,8 @@ class MigrateUserGroup extends Maintenance {
->set( [ 'ug_group' => $newGroup ] )
->where( [
'ug_group' => $oldGroup,
"ug_user BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd
$dbw->expr( 'ug_user', '>=', (int)$blockStart ),
$dbw->expr( 'ug_user', '<=', (int)$blockEnd ),
] )
->caller( __METHOD__ )->execute();
$affected += $dbw->affectedRows();
@ -86,7 +87,8 @@ class MigrateUserGroup extends Maintenance {
->deleteFrom( 'user_groups' )
->where( [
'ug_group' => $oldGroup,
"ug_user BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd
$dbw->expr( 'ug_user', '>=', (int)$blockStart ),
$dbw->expr( 'ug_user', '<=', (int)$blockEnd ),
] )
->caller( __METHOD__ )->execute();
$affected += $dbw->affectedRows();
@ -101,7 +103,8 @@ class MigrateUserGroup extends Maintenance {
->from( 'user_groups' )
->where( [
'ug_group' => $newGroup,
"ug_user BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd
$dbw->expr( 'ug_user', '>=', (int)$blockStart ),
$dbw->expr( 'ug_user', '<=', (int)$blockEnd ),
] )
->caller( __METHOD__ )->fetchResultSet();
if ( $res !== false ) {

View file

@ -74,7 +74,10 @@ class PopulateBacklinkNamespace extends LoggedUpdateMaintenance {
$res = $db->newSelectQueryBuilder()
->select( [ 'page_id', 'page_namespace' ] )
->from( 'page' )
->where( "page_id BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd )
->where( [
$db->expr( 'page_id', '>=', (int)$blockStart ),
$db->expr( 'page_id', '<=', (int)$blockEnd ),
] )
->caller( __METHOD__ )->fetchResultSet();
foreach ( $res as $row ) {
$db->newUpdateQueryBuilder()

View file

@ -100,7 +100,11 @@ TEXT
$rows = $dbr->select(
[ 'revision' ] + $actorQuery['tables'],
[ 'rev_id', 'rev_timestamp', 'rev_user_text' => $actorQuery['fields']['rev_user_text'] ],
[ "rev_id BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd, $revUserIsAnon ],
[
$dbr->expr( 'rev_id', '>=', (int)$blockStart ),
$dbr->expr( 'rev_id', '<=', (int)$blockEnd ),
$revUserIsAnon
],
__METHOD__,
[],
$actorQuery['joins']

View file

@ -106,11 +106,11 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
while ( $blockEnd <= $end ) {
$this->output( "...doing $idCol from $blockStart to $blockEnd\n" );
$cond = "$idCol BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd .
" AND $idCol IS NOT NULL AND {$prefix}_sha1 = ''";
$res = $queryBuilder->where( $cond )
->caller( __METHOD__ )->fetchResultSet();
$res = $queryBuilder->where( [
$db->expr( $idCol, '>=', (int)$blockStart )->and( $idCol, '<=', (int)$blockEnd ),
$db->expr( $idCol, '!=', null ),
"{$prefix}_sha1" => '',
] )->caller( __METHOD__ )->fetchResultSet();
$this->beginTransaction( $db, __METHOD__ );
foreach ( $res as $row ) {

View file

@ -126,7 +126,10 @@ class RebuildFileCache extends Maintenance {
->from( 'page' )
->useIndex( 'PRIMARY' )
->where( $where )
->andWhere( [ "page_id BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd ] )
->andWhere( [
$dbr->expr( 'page_id', '>=', (int)$blockStart ),
$dbr->expr( 'page_id', '<=', (int)$blockEnd ),
] )
->orderBy( 'page_id', SelectQueryBuilder::SORT_ASC )
->caller( __METHOD__ )->fetchResultSet();

View file

@ -101,8 +101,10 @@ class RebuildTextIndex extends Maintenance {
}
$end = $n + self::RTI_CHUNK_SIZE - 1;
$queryBuilder = clone $queryBuilderTemplate;
$res = $queryBuilder->where( [ "page_id BETWEEN $n AND $end", 'page_latest = rev_id' ] )
->caller( __METHOD__ )->fetchResultSet();
$res = $queryBuilder->where( [
$dbw->expr( 'page_id', '>=', $n )->and( 'page_id', '<=', $end ),
'page_latest = rev_id'
] )->caller( __METHOD__ )->fetchResultSet();
foreach ( $res as $s ) {

View file

@ -23,6 +23,7 @@ use MediaWiki\Linker\LinkTarget;
use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Title\Title;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\IReadableDatabase;
use Wikimedia\Rdbms\SelectQueryBuilder;
@ -359,7 +360,7 @@ class RefreshLinks extends Maintenance {
}
/**
* Build a SQL expression for a closed interval (i.e. BETWEEN).
* Build a SQL expression for a closed interval.
*
* By specifying a null $start or $end, it is also possible to create
* half-bounded or unbounded intervals using this function.
@ -368,17 +369,17 @@ class RefreshLinks extends Maintenance {
* @param string $var Field name
* @param mixed $start First value to include or null
* @param mixed $end Last value to include or null
* @return string
* @return IExpression
*/
private static function intervalCond( IReadableDatabase $db, $var, $start, $end ) {
if ( $start === null && $end === null ) {
return "$var IS NOT NULL";
return $db->expr( $var, '!=', null );
} elseif ( $end === null ) {
return "$var >= " . $db->addQuotes( $start );
return $db->expr( $var, '>=', $start );
} elseif ( $start === null ) {
return "$var <= " . $db->addQuotes( $end );
return $db->expr( $var, '<=', $end );
} else {
return "$var BETWEEN " . $db->addQuotes( $start ) . ' AND ' . $db->addQuotes( $end );
return $db->expr( $var, '>=', $start )->and( $var, '<=', $end );
}
}

View file

@ -98,7 +98,10 @@ class CheckStorage extends Maintenance {
->select( [ 'slot_revision_id', 'content_address' ] )
->from( 'slots' )
->join( 'content', null, 'content_id = slot_content_id' )
->where( [ "slot_revision_id BETWEEN $chunkStart AND $chunkEnd" ] )
->where( [
$dbr->expr( 'slot_revision_id', '>=', $chunkStart ),
$dbr->expr( 'slot_revision_id', '<=', $chunkEnd ),
] )
->caller( __METHOD__ )->fetchResultSet();
/** @var \MediaWiki\Storage\SqlBlobStore $blobStore */
$blobStore = $this->getServiceContainer()->getBlobStore();

View file

@ -20,6 +20,8 @@
*/
use MediaWiki\Storage\SqlBlobStore;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\LikeValue;
require_once __DIR__ . '/moveToExternal.php';
@ -31,9 +33,12 @@ class FixLegacyEncoding extends MoveToExternal {
protected function getConditions( $blockStart, $blockEnd, $dbr ) {
return [
"old_id BETWEEN $blockStart AND $blockEnd",
'old_flags NOT ' . $dbr->buildLike( $dbr->anyString(), 'utf-8', $dbr->anyString() ),
'old_flags NOT ' . $dbr->buildLike( $dbr->anyString(), 'utf8', $dbr->anyString() ),
$dbr->expr( 'old_id', '>=', $blockStart ),
$dbr->expr( 'old_id', '<=', $blockEnd ),
$dbr->expr( 'old_flags', IExpression::NOT_LIKE,
new LikeValue( $dbr->anyString(), 'utf-8', $dbr->anyString() ) ),
$dbr->expr( 'old_flags', IExpression::NOT_LIKE,
new LikeValue( $dbr->anyString(), 'utf8', $dbr->anyString() ) ),
];
}

View file

@ -25,6 +25,8 @@ use MediaWiki\MainConfigNames;
use MediaWiki\Maintenance\UndoLog;
use MediaWiki\Storage\SqlBlobStore;
use Wikimedia\AtEase\AtEase;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\LikeValue;
require_once __DIR__ . '/../Maintenance.php';
@ -320,8 +322,10 @@ class MoveToExternal extends Maintenance {
protected function getConditions( $blockStart, $blockEnd, $dbr ) {
return [
"old_id BETWEEN $blockStart AND $blockEnd",
'old_flags NOT ' . $dbr->buildLike( $dbr->anyString(), 'external', $dbr->anyString() ),
$dbr->expr( 'old_id', '>=', $blockStart ),
$dbr->expr( 'old_id', '>=', $blockEnd ),
$dbr->expr( 'old_flags', IExpression::NOT_LIKE,
new LikeValue( $dbr->anyString(), 'external', $dbr->anyString() ) ),
];
}

View file

@ -106,7 +106,8 @@ class UpdateSearchIndex extends Maintenance {
->join( 'page', null, 'rc_cur_id=page_id AND rc_this_oldid=page_latest' )
->where( [
$dbw->expr( 'rc_type', '!=', RC_LOG ),
'rc_timestamp BETWEEN ' . $dbw->addQuotes( $start ) . ' AND ' . $dbw->addQuotes( $end )
$dbw->expr( 'rc_timestamp', '>=', $start ),
$dbw->expr( 'rc_timestamp', '<=', $end ),
] )
->caller( __METHOD__ )->fetchResultSet();