Migrate another batch to use $db->expr instead of raw SQL

Bug: T210206
Change-Id: I327517fef250c24392565a26bbe7b296dc19508a
This commit is contained in:
Amir Sarabadani 2023-10-30 20:10:26 +01:00 committed by James D. Forrester
parent 9d3eae6684
commit 17589adcc4
22 changed files with 69 additions and 64 deletions

View file

@ -388,11 +388,17 @@ class CategoryViewer extends ContextSource {
# set in $wgCategoryCollation, pagination might go totally haywire.
$extraConds = [ 'cl_type' => $type ];
if ( isset( $this->from[$type] ) ) {
$extraConds[] = 'cl_sortkey >= '
. $dbr->addQuotes( $this->collation->getSortKey( $this->from[$type] ) );
$extraConds[] = $dbr->expr(
'cl_sortkey',
'>=',
$this->collation->getSortKey( $this->from[$type] )
);
} elseif ( isset( $this->until[$type] ) ) {
$extraConds[] = 'cl_sortkey < '
. $dbr->addQuotes( $this->collation->getSortKey( $this->until[$type] ) );
$extraConds[] = $dbr->expr(
'cl_sortkey',
'<',
$this->collation->getSortKey( $this->until[$type] )
);
$this->flip[$type] = true;
}

View file

@ -361,25 +361,17 @@ class HistoryAction extends FormlessAction {
[ $dirs, $oper ] = [ "DESC", "<=" ];
}
if ( $offset ) {
$offsets = [ "rev_timestamp $oper " . $dbr->addQuotes( $dbr->timestamp( $offset ) ) ];
} else {
$offsets = [];
}
$page_id = $this->getWikiPage()->getId();
$res = MediaWikiServices::getInstance()->getRevisionStore()->newSelectQueryBuilder( $dbr )
$queryBuilder = MediaWikiServices::getInstance()->getRevisionStore()->newSelectQueryBuilder( $dbr )
->joinComment()
->where( [ 'rev_page' => $page_id ] )
->andWhere( $offsets )
->where( [ 'rev_page' => $this->getWikiPage()->getId() ] )
->useIndex( [ 'revision' => 'rev_page_timestamp' ] )
->orderBy( [ 'rev_timestamp' ], $dirs )
->limit( $limit )
->caller( __METHOD__ )
->fetchResultSet();
->limit( $limit );
if ( $offset ) {
$queryBuilder->andWhere( $dbr->expr( 'rev_timestamp', $oper, $dbr->timestamp( $offset ) ) );
}
return $res;
return $queryBuilder->caller( __METHOD__ )->fetchResultSet();
}
/**

View file

@ -908,7 +908,7 @@ class InfoAction extends FormlessAction {
->select( 'COUNT(rev_page)' )
->from( 'revision' )
->where( [ 'rev_page' => $id ] )
->andWhere( [ "rev_timestamp >= " . $dbr->addQuotes( $threshold ) ] )
->andWhere( $dbr->expr( 'rev_timestamp', '>=', $threshold ) )
->caller( $fname )
->fetchField();
$result['recent_edits'] = $edits;

View file

@ -159,7 +159,9 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
if ( $params['prtype'] || $params['prexpiry'] != 'all' ) {
$this->addTables( 'page_restrictions' );
$this->addWhere( 'page_id=pr_page' );
$this->addWhere( "pr_expiry > {$db->addQuotes( $db->timestamp() )} OR pr_expiry IS NULL" );
$this->addWhere(
$db->expr( 'pr_expiry', '>', $db->timestamp() )->or( 'pr_expiry', '=', null )
);
if ( $params['prtype'] ) {
$this->addWhereFld( 'pr_type', $params['prtype'] );
@ -183,7 +185,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
if ( $params['prexpiry'] == 'indefinite' ) {
$this->addWhereFld( 'pr_expiry', [ $db->getInfinity(), null ] );
} elseif ( $params['prexpiry'] == 'definite' ) {
$this->addWhere( "pr_expiry != {$db->addQuotes( $db->getInfinity() )}" );
$this->addWhere( $db->expr( 'pr_expiry', '!=', $db->getInfinity() ) );
}
$this->addOption( 'DISTINCT' );

View file

@ -24,6 +24,7 @@ use MediaWiki\Linker\LinksMigration;
use MediaWiki\Title\Title;
use Wikimedia\ParamValidator\ParamValidator;
use Wikimedia\ParamValidator\TypeDef\IntegerDef;
use Wikimedia\Rdbms\OrExpressionGroup;
/**
* This is a three-in-one module to query:
@ -259,12 +260,15 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
foreach ( $this->redirTitles as $t ) {
$redirNs = $t->getNamespace();
$redirDBkey = $t->getDBkey();
$titleWhere[] = "{$this->bl_title} = " . $db->addQuotes( $redirDBkey ) .
( $this->hasNS ? " AND {$this->bl_ns} = {$redirNs}" : '' );
$expr = $db->expr( $this->bl_title, '=', $redirDBkey );
if ( $this->hasNS ) {
$expr = $expr->and( $this->bl_ns, '=', $redirNs );
}
$titleWhere[] = $expr;
$allRedirNs[$redirNs] = true;
$allRedirDBkey[$redirDBkey] = true;
}
$this->addWhere( $db->makeList( $titleWhere, LIST_OR ) );
$this->addWhere( new OrExpressionGroup( ...$titleWhere ) );
$this->addWhereFld( 'page_namespace', $this->params['namespace'] );
if ( count( $this->cont ) >= 6 ) {

View file

@ -28,6 +28,7 @@ use MediaWiki\MainConfigNames;
use MediaWiki\Title\Title;
use Wikimedia\ParamValidator\ParamValidator;
use Wikimedia\ParamValidator\TypeDef\IntegerDef;
use Wikimedia\Rdbms\OrExpressionGroup;
/**
* This implements prop=redirects, prop=linkshere, prop=catmembers,
@ -248,10 +249,10 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
$where = [];
foreach ( $titles as $t ) {
if ( $t->getNamespace() == $bl_namespace ) {
$where[] = "$bl_title = " . $db->addQuotes( $t->getDBkey() );
$where[] = $db->expr( $bl_title, '=', $t->getDBkey() );
}
}
$this->addWhere( $db->makeList( $where, LIST_OR ) );
$this->addWhere( new OrExpressionGroup( ...$where ) );
}
if ( $params['show'] !== null ) {
@ -262,7 +263,7 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
) {
$this->dieWithError( 'apierror-show' );
}
$this->addWhereIf( "rd_fragment != " . $db->addQuotes( '' ), isset( $show['fragment'] ) );
$this->addWhereIf( $db->expr( 'rd_fragment', '!=', '' ), isset( $show['fragment'] ) );
$this->addWhereIf( [ 'rd_fragment' => '' ], isset( $show['!fragment'] ) );
$this->addWhereIf( [ 'page_is_redirect' => 1 ], isset( $show['redirect'] ) );
$this->addWhereIf( [ 'page_is_redirect' => 0 ], isset( $show['!redirect'] ) );

View file

@ -329,11 +329,11 @@ abstract class ApiQueryBase extends ApiBase {
$db = $this->getDB();
if ( $start !== null ) {
$this->addWhere( $field . $after . $db->addQuotes( $start ) );
$this->addWhere( $db->expr( $field, $after, $start ) );
}
if ( $end !== null ) {
$this->addWhere( $field . $before . $db->addQuotes( $end ) );
$this->addWhere( $db->expr( $field, $before, $end ) );
}
if ( $sort ) {

View file

@ -20,6 +20,7 @@
use MediaWiki\Block\DatabaseBlock;
use MediaWiki\Permissions\Authority;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\IReadableDatabase;
/**
@ -95,7 +96,7 @@ trait ApiQueryBlockInfoTrait {
/**
* @see ApiQueryBase::addWhere
* @param string|array $conds
* @param string|array|IExpression $conds
*/
abstract protected function addWhere( $conds );

View file

@ -157,13 +157,10 @@ class ApiQueryBlocks extends ApiQueryBase {
// Extract the common prefix to any range block affecting this IP/CIDR
$prefix = substr( $lower, 0, $prefixLen + (int)floor( $cidrLimit / 4 ) );
$lower = $db->addQuotes( $lower );
$upper = $db->addQuotes( $upper );
$this->addWhere( [
'ipb_range_start' . $db->buildLike( $prefix, $db->anyString() ),
'ipb_range_start <= ' . $lower,
'ipb_range_end >= ' . $upper,
$db->expr( 'ipb_range_start', '<=', $lower ),
$db->expr( 'ipb_range_end', '>=', $upper ),
'ipb_auto' => 0
] );
}
@ -185,8 +182,7 @@ class ApiQueryBlocks extends ApiQueryBase {
$this->addWhereIf( 'ipb_user != 0 OR ipb_range_end > ipb_range_start', isset( $show['!ip'] ) );
$this->addWhereIf( 'ipb_user = 0 AND ipb_range_end = ipb_range_start', isset( $show['ip'] ) );
$this->addWhereIf( [ 'ipb_expiry' => $db->getInfinity() ], isset( $show['!temp'] ) );
$this->addWhereIf( 'ipb_expiry != ' .
$db->addQuotes( $db->getInfinity() ), isset( $show['temp'] ) );
$this->addWhereIf( $db->expr( 'ipb_expiry', '!=', $db->getInfinity() ), isset( $show['temp'] ) );
$this->addWhereIf( 'ipb_range_end = ipb_range_start', isset( $show['!range'] ) );
$this->addWhereIf( 'ipb_range_end > ipb_range_start', isset( $show['range'] ) );
}

View file

@ -70,8 +70,7 @@ class ApiQueryCategoryInfo extends ApiQueryBase {
$this->addWhere( [ 'cat_title' => $cattitles ] );
if ( $params['continue'] !== null ) {
$title = $this->getDB()->addQuotes( $params['continue'] );
$this->addWhere( "cat_title >= $title" );
$this->addWhere( $this->getDB()->expr( 'cat_title', '>=', $params['continue'] ) );
}
$this->addOption( 'ORDER BY', 'cat_title' );

View file

@ -181,7 +181,7 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
if ( $params['user'] !== null ) {
$this->addWhereFld( 'actor_name', $params['user'] );
} elseif ( $params['excludeuser'] !== null ) {
$this->addWhere( 'actor_name<>' . $db->addQuotes( $params['excludeuser'] ) );
$this->addWhere( $db->expr( 'actor_name', '!=', $params['excludeuser'] ) );
}
}

View file

@ -222,7 +222,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
// We already join on actor due to getArchiveQueryInfo()
$this->addWhereFld( 'actor_name', $params['user'] );
} elseif ( $params['excludeuser'] !== null ) {
$this->addWhere( 'actor_name<>' . $db->addQuotes( $params['excludeuser'] ) );
$this->addWhere( $db->expr( 'actor_name', '!=', $params['excludeuser'] ) );
}
if ( $params['user'] !== null || $params['excludeuser'] !== null ) {

View file

@ -163,8 +163,9 @@ class ApiQueryUsers extends ApiQueryBase {
$this->addJoinConds( [ 'user_groups' => [ 'JOIN', 'ug_user=user_id' ] ] );
$this->addFields( [ 'user_name' ] );
$this->addFields( [ 'ug_user', 'ug_group', 'ug_expiry' ] );
$this->addWhere( 'ug_expiry IS NULL OR ug_expiry >= ' .
$db->addQuotes( $db->timestamp() ) );
$this->addWhere(
$db->expr( 'ug_expiry', '=', null )->or( 'ug_expiry', '>=', $db->timestamp() )
);
$userGroupsRes = $this->select( __METHOD__ );
foreach ( $userGroupsRes as $row ) {

View file

@ -146,7 +146,10 @@ class JobQueueDB extends JobQueue {
try {
$count = $dbr->newSelectQueryBuilder()
->from( 'job' )
->where( [ 'job_cmd' => $this->type, "job_token != {$dbr->addQuotes( '' )}" ] )
->where( [
'job_cmd' => $this->type,
$dbr->expr( 'job_token', '!=', '' ),
] )
->caller( __METHOD__ )->fetchRowCount();
} catch ( DBError $e ) {
throw $this->getDBException( $e );
@ -182,7 +185,7 @@ class JobQueueDB extends JobQueue {
->where(
[
'job_cmd' => $this->type,
"job_token != {$dbr->addQuotes( '' )}",
$dbr->expr( 'job_token', '!=', '' ),
$dbr->expr( 'job_attempts', '>=', $this->maxTries ),
]
)
@ -729,7 +732,7 @@ class JobQueueDB extends JobQueue {
->where(
[
'job_cmd' => $this->type,
"job_token != {$dbw->addQuotes( '' )}", // was acquired
$dbw->expr( 'job_token', '!=', '' ), // was acquired
$dbw->expr( 'job_token_timestamp', '<', $claimCutoff ), // stale
$dbw->expr( 'job_attempts', '<', $this->maxTries ), // retries left
]
@ -752,7 +755,7 @@ class JobQueueDB extends JobQueue {
] )
->where( [
'job_id' => $ids,
"job_token != {$dbw->addQuotes( '' )}"
$dbw->expr( 'job_token', '!=', '' ),
] )
->caller( __METHOD__ )->execute();
@ -770,12 +773,12 @@ class JobQueueDB extends JobQueue {
->where(
[
'job_cmd' => $this->type,
"job_token != {$dbw->addQuotes( '' )}", // was acquired
$dbw->expr( 'job_token', '!=', '' ), // was acquired
$dbw->expr( 'job_token_timestamp', '<', $pruneCutoff ) // stale
]
);
if ( $this->claimTTL > 0 ) { // only prune jobs attempted too many times...
$qb->andWhere( "job_attempts >= {$dbw->addQuotes( $this->maxTries )}" );
$qb->andWhere( $dbw->expr( 'job_attempts', '>=', $this->maxTries ) );
}
// Get the IDs of jobs that are considered stale and should be removed. Selecting
// the IDs first means that the UPDATE can be done by primary key (less deadlocks).

View file

@ -100,8 +100,8 @@ class RenameUserJob extends Job {
}
# Bound by timestamp if given
if ( $timestampColumn !== null ) {
$conds[] = "$timestampColumn >= " . $dbw->addQuotes( $minTimestamp );
$conds[] = "$timestampColumn <= " . $dbw->addQuotes( $maxTimestamp );
$conds[] = $dbw->expr( $timestampColumn, '>=', $minTimestamp );
$conds[] = $dbw->expr( $timestampColumn, '<=', $maxTimestamp );
# Bound by unique key if given (B/C)
} elseif ( $uniqueKey !== null && $keyId !== null ) {
$conds[$uniqueKey] = $keyId;

View file

@ -584,7 +584,7 @@ class MergeHistory {
->select( 'MAX(rev_timestamp)' )
->from( 'revision' )
->where( [
'rev_timestamp <= ' . $this->dbw->addQuotes( $this->dbw->timestamp( $mwTimestamp ) ),
$this->dbw->expr( 'rev_timestamp', '<=', $this->dbw->timestamp( $mwTimestamp ) ),
'rev_page' => $this->source->getId()
] )
->caller( __METHOD__ )->fetchField();

View file

@ -230,7 +230,7 @@ class SpecialBlockList extends SpecialPage {
} elseif ( $hideTemp ) {
$conds['ipb_expiry'] = $db->getInfinity();
} elseif ( $hideIndef ) {
$conds[] = "ipb_expiry != " . $db->addQuotes( $db->getInfinity() );
$conds[] = $db->expr( 'ipb_expiry', '!=', $db->getInfinity() );
}
if ( $this->blockType === 'sitewide' ) {

View file

@ -942,8 +942,7 @@ class SpecialUndelete extends SpecialPage {
$out->setArticleBodyOnly( true );
$dbr = $this->dbProvider->getReplicaDatabase();
if ( $this->mHistoryOffset ) {
$encOffset = $dbr->addQuotes( $dbr->timestamp( $this->mHistoryOffset ) );
$extraConds = [ "ar_timestamp < $encOffset" ];
$extraConds = [ $dbr->expr( 'ar_timestamp', '<', $dbr->timestamp( $this->mHistoryOffset ) ) ];
} else {
$extraConds = [];
}

View file

@ -323,7 +323,7 @@ class SpecialUpload extends SpecialPage {
LogEventsList::showLogExtract( $delNotice, [ 'delete', 'move' ],
$desiredTitleObj,
'', [ 'lim' => 10,
'conds' => [ 'log_action != ' . $this->localRepo->getReplicaDB()->addQuotes( 'revision' ) ],
'conds' => [ $this->localRepo->getReplicaDB()->expr( 'log_action', '!=', 'revision' ) ],
'showIfEmpty' => false,
'msgKey' => [ 'upload-recreate-warning' ] ]
);

View file

@ -85,12 +85,12 @@ class SpecialWantedPages extends WantedQueryPage {
],
'conds' => [
'pg1.page_namespace' => null,
$blNamespace . ' NOT IN (' . $dbr->makeList( [ NS_USER, NS_USER_TALK ] ) . ')',
'pg2.page_namespace != ' . $dbr->addQuotes( NS_MEDIAWIKI ),
$dbr->expr( $blNamespace, '!=', [ NS_USER, NS_USER_TALK ] ),
$dbr->expr( 'pg2.page_namespace', '!=', NS_MEDIAWIKI ),
],
'options' => [
'HAVING' => [
'COUNT(*) > ' . $dbr->addQuotes( $count ),
$dbr->expr( 'COUNT(*)', '>', $count ),
'COUNT(*) > SUM(pg2.page_is_redirect)'
],
'GROUP BY' => [ $blNamespace, $blTitle ]

View file

@ -213,7 +213,7 @@ class MergeHistoryPager extends ReverseChronologicalPager {
->where( $this->mConds )
->andWhere( [
'rev_page' => $this->articleID,
"rev_timestamp < " . $dbr->addQuotes( $this->maxTimestamp )
$dbr->expr( 'rev_timestamp', '<', $this->maxTimestamp ),
] );
MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'revision' );

View file

@ -857,11 +857,12 @@ class UserGroupManager implements IDBAccessObject {
if ( $allowUpdate ) {
// Update the current row if its expiry does not match that of the loaded row
$conds[] = $expiry
? "ug_expiry IS NULL OR ug_expiry != {$dbw->addQuotes( $dbw->timestamp( $expiry ) )}"
: 'ug_expiry IS NOT NULL';
? $dbw->expr( 'ug_expiry', '=', null )
->or( 'ug_expiry', '!=', $dbw->timestamp( $expiry ) )
: $dbw->expr( 'ug_expiry', '!=', null );
} else {
// Update the current row if it is expired
$conds[] = "ug_expiry < {$dbw->addQuotes( $dbw->timestamp() )}";
$conds[] = $dbw->expr( 'ug_expiry', '<', $dbw->timestamp() );
}
$dbw->newUpdateQueryBuilder()
->update( 'user_groups' )