From 8c36aa3373b02111b7031522273693c05d3e37e7 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Wed, 12 Apr 2017 11:38:20 -0400 Subject: [PATCH] ApiQueryLinks: Avoid MySQL order-by bug MySQL (and MariaDB) have a strange bug where it will often get confused and insist on filesorting if a field that is constant in the WHERE clause is also present in ORDER BY. We've worked around this in several places in the API, and in fact it was done in this very module in r34720 and r37250. But when r67450 added the pltitles and tltemplates parameters, it didn't adjust the logic for avoiding the DB bug. This does that now. Change-Id: I9f37f8812a94cdd088d3940da43d1046ebd455d6 --- includes/api/ApiQueryLinks.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/includes/api/ApiQueryLinks.php b/includes/api/ApiQueryLinks.php index 2f75e76343..508bdf3f9d 100644 --- a/includes/api/ApiQueryLinks.php +++ b/includes/api/ApiQueryLinks.php @@ -87,25 +87,34 @@ class ApiQueryLinks extends ApiQueryGeneratorBase { $this->addTables( $this->table ); $this->addWhereFld( $this->prefix . '_from', array_keys( $this->getPageSet()->getGoodTitles() ) ); - $this->addWhereFld( $this->prefix . '_namespace', $params['namespace'] ); + $multiNS = true; + $multiTitle = true; if ( $params[$this->titlesParam] ) { + // Filter the titles in PHP so our ORDER BY bug avoidance below works right. + $filterNS = $params['namespace'] ? array_flip( $params['namespace'] ) : false; + $lb = new LinkBatch; foreach ( $params[$this->titlesParam] as $t ) { $title = Title::newFromText( $t ); if ( !$title ) { $this->addWarning( [ 'apiwarn-invalidtitle', wfEscapeWikiText( $t ) ] ); - } else { + } elseif ( !$filterNS || isset( $filterNS[$title->getNamespace()] ) ) { $lb->addObj( $title ); } } $cond = $lb->constructSet( $this->prefix, $this->getDB() ); if ( $cond ) { $this->addWhere( $cond ); + $multiNS = count( $lb->data ) !== 1; + $multiTitle = count( call_user_func_array( 'array_merge', $lb->data ) ) !== 1; } else { // No titles so no results return; } + } elseif ( $params['namespace'] ) { + $this->addWhereFld( $this->prefix . '_namespace', $params['namespace'] ); + $multiNS = count( $params['namespace'] ) !== 1; } if ( !is_null( $params['continue'] ) ) { @@ -134,12 +143,15 @@ class ApiQueryLinks extends ApiQueryGeneratorBase { if ( count( $this->getPageSet()->getGoodTitles() ) != 1 ) { $order[] = $this->prefix . '_from' . $sort; } - if ( count( $params['namespace'] ) != 1 ) { + if ( $multiNS ) { $order[] = $this->prefix . '_namespace' . $sort; } - - $order[] = $this->prefix . '_title' . $sort; - $this->addOption( 'ORDER BY', $order ); + if ( $multiTitle ) { + $order[] = $this->prefix . '_title' . $sort; + } + if ( $order ) { + $this->addOption( 'ORDER BY', $order ); + } $this->addOption( 'LIMIT', $params['limit'] + 1 ); $res = $this->select( __METHOD__ ); -- 2.20.1