Run GenderCache for api query modules using ApiQueryBase::addTitleInfo

When converting a Title object into a string for user or user talk
namespace the gender information are needed.

This patch set improves performance on wikis with gender distinction
like dewiki or ruwiki by combining the fetch of the information into one
query and avoids a query per unique user name.
It also avoids false results for request with apihighlimit, because the
apihighlimit with 5000 is higher than the query max limit of the
GenderCache with 1000

Bug: T200238
Change-Id: Ibe0561b210dbeb654117dad777e839640f51b4e4
This commit is contained in:
Umherirrender 2019-10-10 19:44:04 +02:00
parent 650868fa48
commit 731d9f748e
19 changed files with 134 additions and 4 deletions

View file

@ -316,6 +316,11 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
$this->addOption( 'ORDER BY', $orderby );
$res = $this->select( __METHOD__ );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__, 'ar' );
}
$pageMap = []; // Maps ns&title to array index
$count = 0;
$nextIndex = 0;

View file

@ -20,6 +20,8 @@
* @file
*/
use MediaWiki\MediaWikiServices;
/**
* Query module to enumerate links from all pages together.
*
@ -183,6 +185,20 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
$res = $this->select( __METHOD__ );
// Get gender information
if ( $res->numRows() && $resultPageSet === null ) {
$services = MediaWikiServices::getInstance();
if ( $services->getNamespaceInfo()->hasGenderDistinction( $namespace ) ) {
$users = [];
foreach ( $res as $row ) {
$users[] = $row->pl_title;
}
if ( $users !== [] ) {
$services->getGenderCache()->doQuery( $users, __METHOD__ );
}
}
}
$pageids = [];
$titles = [];
$count = 0;

View file

@ -188,6 +188,11 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase {
$hookData = [];
$res = $this->select( __METHOD__, [], $hookData );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$pageMap = []; // Maps rev_page to array index
$count = 0;
$nextIndex = 0;

View file

@ -170,6 +170,11 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
$this->addOption( 'STRAIGHT_JOIN' );
$res = $this->select( __METHOD__ );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$count = 0;
foreach ( $res as $row ) {
if ( ++$count > $this->params['limit'] ) {
@ -288,6 +293,11 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
$this->addOption( 'USE INDEX', [ 'page' => 'PRIMARY' ] );
$res = $this->select( __METHOD__ );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$count = 0;
foreach ( $res as $row ) {
$ns = $this->hasNS ? $row->{$this->bl_ns} : NS_FILE;

View file

@ -286,7 +286,9 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
$res = $this->select( __METHOD__ );
if ( is_null( $resultPageSet ) ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
if ( $fld_title ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$count = 0;
foreach ( $res as $row ) {

View file

@ -587,6 +587,10 @@ abstract class ApiQueryBase extends ApiBase {
}
$services = MediaWikiServices::getInstance();
if ( !$services->getContentLanguage()->needsGenderDistinction() ) {
return;
}
$nsInfo = $services->getNamespaceInfo();
$namespaceField = $fieldPrefix . '_namespace';
$titleField = $fieldPrefix . '_title';

View file

@ -199,6 +199,9 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
$extraConds[] = $contWhere;
}
$res = $this->select( __METHOD__, [ 'where' => $extraConds ] );
if ( $type === 'page' && $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$rows = array_merge( $rows, iterator_to_array( $res ) );
if ( count( $rows ) >= $limit + 1 ) {
break;
@ -210,6 +213,9 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
// No need to worry about per-type queries because we
// aren't sorting or filtering by type anyway
$res = $this->select( __METHOD__ );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$rows = iterator_to_array( $res );
}

View file

@ -137,6 +137,11 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
$res = $this->select( __METHOD__ );
$result = $this->getResult();
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$count = 0;
foreach ( $res as $row ) {
if ( ++$count > $limit ) {

View file

@ -115,6 +115,11 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
$count = 0;
$result = $this->getResult();
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
foreach ( $res as $row ) {
if ( ++$count > $params['limit'] ) {
// We've reached the one extra which shows that there are

View file

@ -115,6 +115,11 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
$count = 0;
$result = $this->getResult();
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
foreach ( $res as $row ) {
if ( ++$count > $params['limit'] ) {
// We've reached the one extra which shows that there are

View file

@ -153,6 +153,8 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
$res = $this->select( __METHOD__ );
if ( is_null( $resultPageSet ) ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__, 'pl' );
$count = 0;
foreach ( $res as $row ) {
if ( ++$count > $params['limit'] ) {

View file

@ -251,6 +251,11 @@ class ApiQueryLogEvents extends ApiQueryBase {
$count = 0;
$res = $this->select( __METHOD__ );
if ( $this->fld_title ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__, 'log' );
}
$result = $this->getResult();
foreach ( $res as $row ) {
if ( ++$count > $limit ) {

View file

@ -87,7 +87,13 @@ class ApiQueryPagesWithProp extends ApiQueryGeneratorBase {
$result = $this->getResult();
$count = 0;
foreach ( $this->select( __METHOD__ ) as $row ) {
$res = $this->select( __METHOD__ );
if ( $fld_title && $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
foreach ( $res as $row ) {
if ( ++$count > $limit ) {
// We've reached the one extra which shows that there are
// additional pages to be had. Stop here...

View file

@ -98,6 +98,10 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
$this->addOption( 'LIMIT', $params['limit'] + 1 );
$res = $this->select( __METHOD__ );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__, 'pt' );
}
$count = 0;
$result = $this->getResult();

View file

@ -87,6 +87,11 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
$path = [ 'query', $this->getModuleName() ];
$res = $this->select( __METHOD__ );
if ( $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
$count = 0;
foreach ( $res as $row ) {
if ( $count++ >= $limit ) {

View file

@ -418,6 +418,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
/* Perform the actual query. */
$res = $this->select( __METHOD__, [], $hookData );
if ( $this->fld_title && $resultPageSet === null ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__, 'rc' );
}
$revids = [];
$titles = [];

View file

@ -223,6 +223,10 @@ class ApiQueryUserContribs extends ApiQueryBase {
$this->prepareQuery( $users, $limit - $count );
$res = $this->select( __METHOD__, [], $hookData );
if ( $this->fld_title ) {
$this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
}
if ( $this->fld_sizediff ) {
$revIds = [];
foreach ( $res as $row ) {

View file

@ -178,9 +178,27 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
] );
$ids = [];
$watchedItemQuery = MediaWikiServices::getInstance()->getWatchedItemQueryService();
$services = MediaWikiServices::getInstance();
$watchedItemQuery = $services->getWatchedItemQueryService();
$items = $watchedItemQuery->getWatchedItemsWithRecentChangeInfo( $wlowner, $options, $startFrom );
// Get gender information
if ( $items !== [] && $resultPageSet === null && $this->fld_title &&
$services->getContentLanguage()->needsGenderDistinction()
) {
$nsInfo = $services->getNamespaceInfo();
$usernames = [];
foreach ( $items as list( $watchedItem, $recentChangeInfo ) ) {
$linkTarget = $watchedItem->getLinkTarget();
if ( $nsInfo->hasGenderDistinction( $linkTarget->getNamespace() ) ) {
$usernames[] = $linkTarget->getText();
}
}
if ( $usernames !== [] ) {
$services->getGenderCache()->doQuery( $usernames, __METHOD__ );
}
}
foreach ( $items as list( $watchedItem, $recentChangeInfo ) ) {
/** @var WatchedItem $watchedItem */
if ( is_null( $resultPageSet ) ) {

View file

@ -97,8 +97,27 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
$titles = [];
$count = 0;
$items = MediaWikiServices::getInstance()->getWatchedItemQueryService()
$services = MediaWikiServices::getInstance();
$items = $services->getWatchedItemQueryService()
->getWatchedItemsForUser( $user, $options );
// Get gender information
if ( $items !== [] && $resultPageSet === null &&
$services->getContentLanguage()->needsGenderDistinction()
) {
$nsInfo = $services->getNamespaceInfo();
$usernames = [];
foreach ( $items as $item ) {
$linkTarget = $item->getLinkTarget();
if ( $nsInfo->hasGenderDistinction( $linkTarget->getNamespace() ) ) {
$usernames[] = $linkTarget->getText();
}
}
if ( $usernames !== [] ) {
$services->getGenderCache()->doQuery( $usernames, __METHOD__ );
}
}
foreach ( $items as $item ) {
$ns = $item->getLinkTarget()->getNamespace();
$dbKey = $item->getLinkTarget()->getDBkey();