Migrate to IReadableDatabase::newSelectQueryBuilder

Also use expression builder to avoid raw sql

Change-Id: I86da11d7e20a6c4890639aa22085424f3686d674
This commit is contained in:
Umherirrender 2024-05-02 21:10:54 +02:00
parent b4f94c094a
commit adbd669832

View file

@ -22,8 +22,11 @@ namespace MediaWiki\Extension\ReplaceText;
use MediaWiki\Config\Config;
use MediaWiki\Title\Title;
use Wikimedia\Rdbms\IConnectionProvider;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\IReadableDatabase;
use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\LikeValue;
use Wikimedia\Rdbms\SelectQueryBuilder;
class Search {
private Config $config;
@ -50,66 +53,58 @@ class Search {
$search, $namespaces, $category, $prefix, $pageLimit, $use_regex = false
) {
$dbr = $this->loadBalancer->getReplicaDatabase();
$tables = [ 'page', 'revision', 'text', 'slots', 'content' ];
$vars = [ 'page_id', 'page_namespace', 'page_title', 'old_text', 'slot_role_id' ];
$queryBuilder = $dbr->newSelectQueryBuilder()
->select( [ 'page_id', 'page_namespace', 'page_title', 'old_text', 'slot_role_id' ] )
->from( 'page' )
->join( 'revision', null, 'rev_id = page_latest' )
->join( 'slots', null, 'rev_id = slot_revision_id' )
->join( 'content', null, 'slot_content_id = content_id' )
->join( 'text', null, $dbr->buildIntegerCast( 'SUBSTR(content_address, 4)' ) . ' = old_id' );
if ( $use_regex ) {
$comparisonCond = self::regexCond( $dbr, 'old_text', $search );
$queryBuilder->where( self::regexCond( $dbr, 'old_text', $search ) );
} else {
$any = $dbr->anyString();
$comparisonCond = 'old_text ' . $dbr->buildLike( $any, $search, $any );
$queryBuilder->where( $dbr->expr( 'old_text', IExpression::LIKE, new LikeValue( $any, $search, $any ) ) );
}
$conds = [
$comparisonCond,
'page_namespace' => $namespaces,
'rev_id = page_latest',
'rev_id = slot_revision_id',
'slot_content_id = content_id',
$dbr->buildIntegerCast( 'SUBSTR(content_address, 4)' ) . ' = old_id'
];
$queryBuilder->andWhere( [ 'page_namespace' => $namespaces ] );
if ( $pageLimit === null || $pageLimit === '' ) {
$pageLimit = $this->config->get( 'ReplaceTextResultsLimit' );
}
self::categoryCondition( $category, $tables, $conds );
$this->prefixCondition( $prefix, $conds );
$options = [
'ORDER BY' => 'page_namespace, page_title',
'LIMIT' => $pageLimit
];
return $dbr->select( $tables, $vars, $conds, __METHOD__, $options );
self::categoryCondition( $category, $queryBuilder );
$this->prefixCondition( $prefix, $dbr, $queryBuilder );
return $queryBuilder->orderBy( [ 'page_namespace', 'page_title' ] )
->limit( $pageLimit )
->fetchResultSet();
}
/**
* @param string|null $category
* @param array &$tables
* @param array &$conds
* @param SelectQueryBuilder $queryBuilder
*/
public static function categoryCondition( $category, &$tables, &$conds ) {
public static function categoryCondition( $category, SelectQueryBuilder $queryBuilder ) {
if ( strval( $category ) !== '' ) {
$category = Title::newFromText( $category )->getDbKey();
$tables[] = 'categorylinks';
$conds[] = 'page_id = cl_from';
$conds['cl_to'] = $category;
$queryBuilder->join( 'categorylinks', null, 'page_id = cl_from' )
->where( [ 'cl_to' => $category ] );
}
}
/**
* @param string|null $prefix
* @param array &$conds
* @param IReadableDatabase $dbr
* @param SelectQueryBuilder $queryBuilder
*/
private function prefixCondition( $prefix, &$conds ) {
private function prefixCondition( $prefix, IReadableDatabase $dbr, SelectQueryBuilder $queryBuilder ) {
if ( strval( $prefix ) === '' ) {
return;
}
$dbr = $this->loadBalancer->getReplicaDatabase();
$title = Title::newFromText( $prefix );
if ( $title !== null ) {
$prefix = $title->getDbKey();
}
$any = $dbr->anyString();
// @phan-suppress-next-line PhanTypeMismatchArgumentNullable strval makes this non-null
$conds[] = 'page_title ' . $dbr->buildLike( $prefix, $any );
$queryBuilder->where( $dbr->expr( 'page_title', IExpression::LIKE, new LikeValue( $prefix, $any ) ) );
}
/**
@ -146,29 +141,25 @@ class Search {
$use_regex = false
) {
$dbr = $this->loadBalancer->getReplicaDatabase();
$tables = [ 'page' ];
$vars = [ 'page_title', 'page_namespace' ];
$queryBuilder = $dbr->newSelectQueryBuilder()
->select( [ 'page_title', 'page_namespace' ] )
->from( 'page' );
$str = str_replace( ' ', '_', $str );
if ( $use_regex ) {
$comparisonCond = self::regexCond( $dbr, 'page_title', $str );
$queryBuilder->where( self::regexCond( $dbr, 'page_title', $str ) );
} else {
$any = $dbr->anyString();
$comparisonCond = 'page_title ' . $dbr->buildLike( $any, $str, $any );
$queryBuilder->where( $dbr->expr( 'page_title', IExpression::LIKE, new LikeValue( $any, $str, $any ) ) );
}
$conds = [
$comparisonCond,
'page_namespace' => $namespaces,
];
$queryBuilder->andWhere( [ 'page_namespace' => $namespaces ] );
if ( $pageLimit === null || $pageLimit === '' ) {
$pageLimit = $this->config->get( 'ReplaceTextResultsLimit' );
}
self::categoryCondition( $category, $tables, $conds );
$this->prefixCondition( $prefix, $conds );
$sort = [ 'ORDER BY' => 'page_namespace, page_title', 'LIMIT' => $pageLimit ];
return $dbr->select( $tables, $vars, $conds, __METHOD__, $sort );
self::categoryCondition( $category, $queryBuilder );
$this->prefixCondition( $prefix, $dbr, $queryBuilder );
return $queryBuilder->orderBy( [ 'page_namespace', 'page_title' ] )
->limit( $pageLimit )
->fetchResultSet();
}
/**