Use expression builder instead of raw sql

Bug: T361023
Change-Id: Ibf1c93ddbf8f680e8fb9442816f6fed94a069c0a
This commit is contained in:
Umherirrender 2024-07-22 22:39:25 +02:00
parent c09c0dfa85
commit 9a107e6b03
27 changed files with 62 additions and 54 deletions

View file

@ -620,7 +620,7 @@ class PageHistoryCountHandler extends SimpleHandler {
->from( 'revision' )
->where( [
'rev_page' => $pageId,
'rev_minor_edit != 0',
$dbr->expr( 'rev_minor_edit', '!=', 0 ),
$dbr->bitAnd( 'rev_deleted', RevisionRecord::DELETED_TEXT ) . " = 0"
] )
->limit( self::COUNT_LIMITS['minor'] + 1 ); // extra to detect truncation

View file

@ -64,7 +64,7 @@ class RevisionSelectQueryBuilder extends SelectQueryBuilder {
->leftJoin(
'user',
null,
[ "actor_rev_user.actor_user != 0", "user_id = actor_rev_user.actor_user" ]
[ $this->db->expr( 'actor_rev_user.actor_user', '!=', 0 ), "user_id = actor_rev_user.actor_user" ]
);
return $this;

View file

@ -2809,7 +2809,7 @@ class RevisionStore implements RevisionFactory, RevisionLookup, LoggerAwareInter
->select( 'rev_id' )
->from( 'revision' )
->where( [ 'rev_page' => $rev->getPageId( $this->wikiId ) ] )
->andWhere( 'rev_id < ' . $rev->getId( $this->wikiId ) )
->andWhere( $db->expr( 'rev_id', '<', $rev->getId( $this->wikiId ) ) )
->orderBy( 'rev_id DESC' )
->caller( __METHOD__ )->fetchField();
}

View file

@ -209,6 +209,7 @@ class HistoryAction extends FormlessAction {
true
);
$dbr = $services->getConnectionProvider()->getReplicaDatabase();
// Fail nicely if article doesn't exist.
if ( !$this->getWikiPage()->exists() ) {
$send404Code = $config->get( MainConfigNames::Send404Code );
@ -217,8 +218,6 @@ class HistoryAction extends FormlessAction {
}
$out->addWikiMsg( 'nohistory' );
$dbr = $services->getConnectionProvider()->getReplicaDatabase();
# show deletion/move log if there is an entry
LogEventsList::showLogExtract(
$out,
@ -242,7 +241,7 @@ class HistoryAction extends FormlessAction {
* Option to show only revisions that have been (partially) hidden via RevisionDelete
*/
if ( $request->getBool( 'deleted' ) ) {
$conds = [ 'rev_deleted != 0' ];
$conds = [ $dbr->expr( 'rev_deleted', '!=', 0 ) ];
} else {
$conds = [];
}

View file

@ -194,7 +194,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
}
if ( $params['witheditsonly'] ) {
$this->addWhere( 'user_editcount > 0' );
$this->addWhere( $db->expr( 'user_editcount', '>', 0 ) );
}
$this->addDeletedUserFilter();

View file

@ -32,6 +32,7 @@ use Wikimedia\IPUtils;
use Wikimedia\ParamValidator\ParamValidator;
use Wikimedia\ParamValidator\TypeDef\IntegerDef;
use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\RawSQLExpression;
/**
* Query module to enumerate all user blocks
@ -227,9 +228,12 @@ class ApiQueryBlocks extends ApiQueryBase {
}
$this->addWhereIf( [ 'bt_user' => 0 ], isset( $show['!account'] ) );
$this->addWhereIf( 'bt_user != 0', isset( $show['account'] ) );
$this->addWhereIf( 'bt_user != 0 OR bt_range_end > bt_range_start', isset( $show['!ip'] ) );
$this->addWhereIf( 'bt_user = 0 AND bt_range_end = bt_range_start', isset( $show['ip'] ) );
$this->addWhereIf( $db->expr( 'bt_user', '!=', 0 ), isset( $show['account'] ) );
$this->addWhereIf(
$db->expr( 'bt_user', '!=', 0 )->orExpr( new RawSQLExpression( 'bt_range_end > bt_range_start' ) ),
isset( $show['!ip'] )
);
$this->addWhereIf( [ 'bt_user' => 0, 'bt_range_end = bt_range_start' ], isset( $show['ip'] ) );
$this->addWhereIf( [ 'bl_expiry' => $db->getInfinity() ], isset( $show['!temp'] ) );
$this->addWhereIf( $db->expr( 'bl_expiry', '!=', $db->getInfinity() ), isset( $show['temp'] ) );
$this->addWhereIf( 'bt_range_end = bt_range_start', isset( $show['!range'] ) );

View file

@ -117,7 +117,7 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
'pp_propname' => 'hiddencat' ] ]
] );
if ( isset( $show['hidden'] ) ) {
$this->addWhere( [ 'pp_propname IS NOT NULL' ] );
$this->addWhere( $this->getDB()->expr( 'pp_propname', '!=', null ) );
} elseif ( isset( $show['!hidden'] ) ) {
$this->addWhere( [ 'pp_propname' => null ] );
}

View file

@ -201,9 +201,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
/* Add additional conditions to query depending upon parameters. */
$this->addWhereIf( [ 'rc_minor' => 0 ], isset( $show['!minor'] ) );
$this->addWhereIf( 'rc_minor != 0', isset( $show['minor'] ) );
$this->addWhereIf( $db->expr( 'rc_minor', '!=', 0 ), isset( $show['minor'] ) );
$this->addWhereIf( [ 'rc_bot' => 0 ], isset( $show['!bot'] ) );
$this->addWhereIf( 'rc_bot != 0', isset( $show['bot'] ) );
$this->addWhereIf( $db->expr( 'rc_bot', '!=', 0 ), isset( $show['bot'] ) );
if ( isset( $show['anon'] ) || isset( $show['!anon'] ) ) {
$this->addTables( 'actor', 'actor' );
$this->addJoinConds( [ 'actor' => [ 'JOIN', 'actor_id=rc_actor' ] ] );
@ -211,11 +211,11 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
[ 'actor_user' => null ], isset( $show['anon'] )
);
$this->addWhereIf(
'actor_user IS NOT NULL', isset( $show['!anon'] )
$db->expr( 'actor_user', '!=', null ), isset( $show['!anon'] )
);
}
$this->addWhereIf( [ 'rc_patrolled' => 0 ], isset( $show['!patrolled'] ) );
$this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
$this->addWhereIf( $db->expr( 'rc_patrolled', '!=', 0 ), isset( $show['patrolled'] ) );
$this->addWhereIf( [ 'page_is_redirect' => 1 ], isset( $show['redirect'] ) );
if ( isset( $show['unpatrolled'] ) ) {
@ -229,7 +229,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
}
$this->addWhereIf(
'rc_patrolled != ' . RecentChange::PRC_AUTOPATROLLED,
$db->expr( 'rc_patrolled', '!=', RecentChange::PRC_AUTOPATROLLED ),
isset( $show['!autopatrolled'] )
);
$this->addWhereIf(
@ -400,12 +400,12 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
// 2. otherwise if the content of a slot is different to the content of its parent slot,
// then the content of the slot has been changed in this revision
// (probably by a revert)
$this->addWhere(
'slot.slot_origin = slot.slot_revision_id OR ' .
'slot.slot_content_id != parent_slot.slot_content_id OR ' .
'(slot.slot_content_id IS NULL AND parent_slot.slot_content_id IS NOT NULL) OR ' .
'(slot.slot_content_id IS NOT NULL AND parent_slot.slot_content_id IS NULL)'
);
$this->addWhere( $db->orExpr( [
new RawSQLExpression( 'slot.slot_origin = slot.slot_revision_id' ),
new RawSQLExpression( 'slot.slot_content_id != parent_slot.slot_content_id' ),
$db->expr( 'slot.slot_content_id', '=', null )->and( 'parent_slot.slot_content_id', '!=', null ),
$db->expr( 'slot.slot_content_id', '!=', null )->and( 'parent_slot.slot_content_id', '=', null ),
] ) );
// Only include changes that touch page content (i.e. RC_NEW, RC_EDIT)
$changeTypes = RecentChange::parseToRCType(
array_intersect( $params['type'], [ 'new', 'edit' ] )

View file

@ -473,17 +473,17 @@ class ApiQueryUserContribs extends ApiQueryBase {
}
$this->addWhereIf( [ 'rev_minor_edit' => 0 ], isset( $show['!minor'] ) );
$this->addWhereIf( 'rev_minor_edit != 0', isset( $show['minor'] ) );
$this->addWhereIf( $db->expr( 'rev_minor_edit', '!=', 0 ), isset( $show['minor'] ) );
$this->addWhereIf(
[ 'rc_patrolled' => RecentChange::PRC_UNPATROLLED ],
isset( $show['!patrolled'] )
);
$this->addWhereIf(
'rc_patrolled != ' . RecentChange::PRC_UNPATROLLED,
$db->expr( 'rc_patrolled', '!=', RecentChange::PRC_UNPATROLLED ),
isset( $show['patrolled'] )
);
$this->addWhereIf(
'rc_patrolled != ' . RecentChange::PRC_AUTOPATROLLED,
$db->expr( 'rc_patrolled', '!=', RecentChange::PRC_AUTOPATROLLED ),
isset( $show['!autopatrolled'] )
);
$this->addWhereIf(
@ -492,7 +492,7 @@ class ApiQueryUserContribs extends ApiQueryBase {
);
$this->addWhereIf( $idField . ' != page_latest', isset( $show['!top'] ) );
$this->addWhereIf( $idField . ' = page_latest', isset( $show['top'] ) );
$this->addWhereIf( 'rev_parent_id != 0', isset( $show['!new'] ) );
$this->addWhereIf( $db->expr( 'rev_parent_id', '!=', 0 ), isset( $show['!new'] ) );
$this->addWhereIf( [ 'rev_parent_id' => 0 ], isset( $show['new'] ) );
}
$this->addOption( 'LIMIT', $limit + 1 );

View file

@ -108,7 +108,7 @@ class LinksDeletionUpdate extends LinksUpdate implements EnqueueableDataUpdate {
$rcIdsForPage = $dbw->newSelectQueryBuilder()
->select( 'rc_id' )
->from( 'recentchanges' )
->where( [ 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ] )
->where( [ $dbw->expr( 'rc_type', '!=', RC_LOG ), 'rc_cur_id' => $id ] )
->caller( __METHOD__ )->fetchFieldValues();
// T98706: delete by PK to avoid lock contention with RC delete log insertions

View file

@ -86,7 +86,7 @@ class UserEditCountUpdate implements DeferrableUpdate, MergeableUpdate {
'user_editcount+' . (int)$info->getIncrement()
)
] )
->where( [ 'user_id' => $userId, 'user_editcount IS NOT NULL' ] )
->where( [ 'user_id' => $userId, $dbw->expr( 'user_editcount', '!=', null ) ] )
->caller( $fname )->execute();
// Lazy initialization check...
if ( $dbw->affectedRows() == 0 ) {

View file

@ -621,7 +621,8 @@ class JobQueueDB extends JobQueue {
* @return Iterator<RunnableJob>
*/
public function getAllAcquiredJobs() {
return $this->getJobIterator( [ 'job_cmd' => $this->getType(), "job_token > ''" ] );
$dbr = $this->getReplicaDB();
return $this->getJobIterator( [ 'job_cmd' => $this->getType(), $dbr->expr( 'job_token', '>', '' ) ] );
}
/**
@ -629,10 +630,11 @@ class JobQueueDB extends JobQueue {
* @return Iterator<RunnableJob>
*/
public function getAllAbandonedJobs() {
$dbr = $this->getReplicaDB();
return $this->getJobIterator( [
'job_cmd' => $this->getType(),
"job_token > ''",
"job_attempts >= " . intval( $this->maxTries )
$dbr->expr( 'job_token', '>', '' ),
$dbr->expr( 'job_attempts', '>=', intval( $this->maxTries ) ),
] );
}

View file

@ -620,7 +620,7 @@ class MessageCache implements LoggerAwareInterface {
->select( [ 'page_title', 'page_latest' ] )
->from( 'page' )
->where( $conds )
->andWhere( [ 'page_len > ' . intval( $this->maxEntrySize ) ] )
->andWhere( $dbr->expr( 'page_len', '>', intval( $this->maxEntrySize ) ) )
->caller( __METHOD__ . "($code)-big" )->fetchResultSet();
foreach ( $res as $row ) {
// Include entries/stubs for all keys in $mostused in adaptive mode

View file

@ -134,7 +134,7 @@ class RevisionDeleteUser {
$dbw->newUpdateQueryBuilder()
->update( 'recentchanges' )
->set( self::buildSetBitDeletedField( 'rc_deleted', $op, $delAction, $dbw ) )
->where( [ 'rc_namespace' => NS_USER, 'rc_title' => $userDbKey, 'rc_logid > 0' ] )
->where( [ 'rc_namespace' => NS_USER, 'rc_title' => $userDbKey, $dbw->expr( 'rc_logid', '>', 0 ) ] )
->caller( __METHOD__ )->execute();
return true;

View file

@ -344,7 +344,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
'queryCallable' => static function ( string $specialClassName, IContextSource $ctx,
IReadableDatabase $dbr, &$tables, &$fields, &$conds, &$query_options, &$join_conds
) {
$conds[] = 'rc_minor = 0';
$conds[] = $dbr->expr( 'rc_minor', '=', 0 );
},
'cssClassSuffix' => 'minor',
'isRowApplicableCallable' => static function ( IContextSource $ctx, RecentChange $rc ) {
@ -359,7 +359,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
'queryCallable' => static function ( string $specialClassName, IContextSource $ctx,
IReadableDatabase $dbr, &$tables, &$fields, &$conds, &$query_options, &$join_conds
) {
$conds[] = 'rc_minor = 1';
$conds[] = $dbr->expr( 'rc_minor', '=', 1 );
},
'cssClassSuffix' => 'major',
'isRowApplicableCallable' => static function ( IContextSource $ctx, RecentChange $rc ) {
@ -515,7 +515,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
'queryCallable' => static function ( string $specialClassName, IContextSource $ctx,
IReadableDatabase $dbr, &$tables, &$fields, &$conds, &$query_options, &$join_conds
) {
$conds[] = 'rc_patrolled != ' . RecentChange::PRC_UNPATROLLED;
$conds[] = $dbr->expr( 'rc_patrolled', '!=', RecentChange::PRC_UNPATROLLED );
},
'isReplacedInStructuredUi' => true,
],

View file

@ -125,7 +125,7 @@ class SpecialAutoblockList extends SpecialPage {
*/
protected function getBlockListPager() {
$conds = [
'bl_parent_block_id IS NOT NULL',
$this->dbProvider->getReplicaDatabase()->expr( 'bl_parent_block_id', '!=', null ),
];
# Is the user allowed to see hidden blocks?
if ( !$this->getAuthority()->isAllowed( 'hideuser' ) ) {

View file

@ -220,9 +220,9 @@ class SpecialBlockList extends SpecialPage {
&& in_array( 'rangeblocks', $this->options )
) {
// Simpler conditions for only user blocks (T360864)
$conds[] = "bt_user IS NOT NULL";
$conds[] = $db->expr( 'bt_user', '!=', null );
} elseif ( in_array( 'addressblocks', $this->options ) ) {
$conds[] = "bt_user IS NOT NULL OR bt_range_start IS NOT NULL";
$conds[] = $db->expr( 'bt_user', '!=', null )->or( 'bt_range_start', '!=', null );
} elseif ( in_array( 'rangeblocks', $this->options ) ) {
$conds['bt_range_start'] = null;
}

View file

@ -92,7 +92,7 @@ class SpecialBrokenRedirects extends QueryPage {
'conds' => [
// Exclude pages that don't exist locally as wiki pages, but aren't "broken" either: special
// pages and interwiki links.
'rd_namespace >= 0',
$dbr->expr( 'rd_namespace', '>=', 0 ),
'rd_interwiki' => '',
'p2.page_namespace' => null,
],

View file

@ -84,7 +84,7 @@ class SpecialFewestRevisions extends QueryPage {
'conds' => [
'page_namespace' => $this->namespaceInfo->getContentNamespaces(),
'page_id = rev_page',
'page_is_redirect = 0',
'page_is_redirect' => 0,
],
'options' => [
'GROUP BY' => [ 'page_namespace', 'page_title' ]

View file

@ -67,12 +67,13 @@ class SpecialMostLinkedCategories extends QueryPage {
}
public function getQueryInfo() {
$dbr = $this->getDatabaseProvider()->getReplicaDatabase();
return [
'tables' => [ 'category' ],
'fields' => [ 'title' => 'cat_title',
'namespace' => NS_CATEGORY,
'value' => 'cat_pages' ],
'conds' => [ 'cat_pages > 0' ],
'conds' => [ $dbr->expr( 'cat_pages', '>', 0 ) ],
];
}

View file

@ -173,7 +173,7 @@ class SpecialRandomPage extends SpecialPage {
* causes anyway. Trust me, I'm a mathematician. :)
*/
if ( !$row ) {
$row = $this->selectRandomPageFromDB( "0", __METHOD__ );
$row = $this->selectRandomPageFromDB( 0, __METHOD__ );
}
if ( $row ) {
@ -184,12 +184,13 @@ class SpecialRandomPage extends SpecialPage {
}
protected function getQueryInfo( $randstr ) {
$dbr = $this->dbProvider->getReplicaDatabase();
$redirect = $this->isRedirect() ? 1 : 0;
$tables = [ 'page' ];
$conds = array_merge( [
'page_namespace' => $this->namespaces,
'page_is_redirect' => $redirect,
'page_random >= ' . $randstr
$dbr->expr( 'page_random', '>=', $randstr ),
], $this->extra );
$joinConds = [];

View file

@ -120,10 +120,11 @@ class NewPagesPager extends ReverseChronologicalPager {
$size = abs( intval( $this->opts->getValue( 'size' ) ) );
if ( $size > 0 ) {
$db = $this->getDatabase();
if ( $this->opts->getValue( 'size-mode' ) === 'max' ) {
$conds[] = 'page_len <= ' . $size;
$conds[] = $db->expr( 'page_len', '<=', $size );
} else {
$conds[] = 'page_len >= ' . $size;
$conds[] = $db->expr( 'page_len', '>=', $size );
}
}

View file

@ -310,10 +310,10 @@ class ProtectedPagesPager extends TablePager {
$conds['pr_expiry'] = [ $dbr->getInfinity(), null ];
}
if ( $this->cascadeonly ) {
$conds[] = 'pr_cascade = 1';
$conds['pr_cascade'] = 1;
}
if ( $this->noredirect ) {
$conds[] = 'page_is_redirect = 0';
$conds['page_is_redirect'] = 0;
}
if ( $this->level ) {

View file

@ -216,7 +216,7 @@ class UsersPager extends AlphabeticPager {
if ( $this->creationSort ) {
$userIdentity = $this->userIdentityLookup->getUserIdentityByName( $this->requestedUser );
if ( $userIdentity && $userIdentity->isRegistered() ) {
$conds[] = 'user_id >= ' . $userIdentity->getId();
$conds[] = $dbr->expr( 'user_id', '>=', $userIdentity->getId() );
}
} else {
$conds[] = $dbr->expr( 'user_name', '>=', $this->requestedUser );
@ -224,7 +224,7 @@ class UsersPager extends AlphabeticPager {
}
if ( $this->editsOnly ) {
$conds[] = 'user_editcount > 0';
$conds[] = $dbr->expr( 'user_editcount', '>', 0 );
}
$options['GROUP BY'] = $this->creationSort ? 'user_id' : 'user_name';

View file

@ -2938,7 +2938,7 @@ class Title implements Stringable, LinkTarget, PageIdentity {
->select( '1' )
->forUpdate()
->from( 'revision' )
->where( [ 'rev_page' => $this->mArticleID, 'rev_id != ' . (int)$this->mLatestID ] )
->where( [ 'rev_page' => $this->mArticleID, $dbw->expr( 'rev_id', '!=', (int)$this->mLatestID ) ] )
->caller( __METHOD__ )->fetchField();
} else {
$isSingleRevRedirect = false;

View file

@ -927,7 +927,7 @@ class User implements Stringable, Authority, UserIdentity, UserEmailContact {
->limit( min( 5000, $limit ) );
if ( $after !== null ) {
$queryBuilder->andWhere( 'ug_user > ' . (int)$after );
$queryBuilder->andWhere( $dbr->expr( 'ug_user', '>', (int)$after ) );
}
$ids = $queryBuilder->caller( __METHOD__ )->fetchFieldValues() ?: [];

View file

@ -475,7 +475,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
public function testRcHideminorFilter() {
$this->assertConditions(
[ # expected
"rc_minor = 0",
'rc_minor = 0',
],
[
'hideminor' => 1,
@ -487,7 +487,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
public function testRcHidemajorFilter() {
$this->assertConditions(
[ # expected
"rc_minor = 1",
'rc_minor = 1',
],
[
'hidemajor' => 1,