From: Brad Jorsch Date: Thu, 11 Dec 2014 15:56:36 +0000 (-0500) Subject: API: Avoid MySQL filesort with list=allpages&apfilterlanglinks=withlanglinks X-Git-Tag: 1.31.0-rc.0~12913 X-Git-Url: https://git.cyclocoop.org/%28%28?a=commitdiff_plain;h=c394cdc04dd1ee4058a90c09630f0dee7f70026f;p=lhc%2Fweb%2Fwiklou.git API: Avoid MySQL filesort with list=allpages&apfilterlanglinks=withlanglinks I'm not sure whether r44584 didn't go far enough or if MySQL's behavior has changed since 2008, but MySQL is now filesorting when a constant-in-WHERE field is included in GROUP BY. If all our supported databases used the 1999 SQL standard rules for GROUP BY[1] this would be an easy fix. But PostgreSQL before 9.1 uses the older 1992 rules.[2] And then there's Oracle and MSSQL, which aren't listed as supported[1] but are still in the code. Simplest thing to do is probably to check if we're on MySQL, Sqlite, or Postgres >= 9.1 and use the 1999 rules, and otherwise use the older rules. [1]: Basically "any non-aggregate field in the SELECT must be functionally dependent on the grouped-by fields", meaning if you include the primary key you're good. [2]: Basically "any non-aggregate field in the SELECT must be in the GROUP BY". [3]: https://www.mediawiki.org/wiki/Manual:Installation_requirements#Database_server Bug: T78276 Change-Id: I80b515bb06d194b146897155b318a3d1c908e8b6 --- diff --git a/includes/api/ApiQueryAllPages.php b/includes/api/ApiQueryAllPages.php index a85c9c9361..e243593b1b 100644 --- a/includes/api/ApiQueryAllPages.php +++ b/includes/api/ApiQueryAllPages.php @@ -168,9 +168,23 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase { $this->addTables( 'langlinks' ); $this->addWhere( 'page_id=ll_from' ); $this->addOption( 'STRAIGHT_JOIN' ); - // We have to GROUP BY all selected fields to stop - // PostgreSQL from whining - $this->addOption( 'GROUP BY', $selectFields ); + + // MySQL filesorts if we use a GROUP BY that works with the rules + // in the 1992 SQL standard (it doesn't like having the + // constant-in-WHERE page_namespace column in there). Using the + // 1999 rules works fine, but that breaks other DBs. Sigh. + /// @todo Once we drop support for 1992-rule DBs, we can simplify this. + $dbType = $db->getType(); + if ( $dbType === 'mysql' || $dbType === 'sqlite' || + $dbType === 'postgres' && $db->getServerVersion() >= 9.1 + ) { + // 1999 rules, or screw-the-rules + $this->addOption( 'GROUP BY', array( 'page_title', 'page_id' ) ); + } else { + // 1992 rules + $this->addOption( 'GROUP BY', $selectFields ); + } + $forceNameTitleIndex = false; }