API:
authorRoan Kattouw <catrope@users.mediawiki.org>
Thu, 8 May 2008 12:33:20 +0000 (12:33 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Thu, 8 May 2008 12:33:20 +0000 (12:33 +0000)
* Added ApiQueryBase::addJoin() which provides a cleaner interface to construct JOIN queries. Behind the scenes this still uses the old, ugly way, but it'll be easy to rewrite when/if the Database class gets its own function for JOINs
* Used addJoin() in query modules where necessary
* Removed FORCE INDEX (rc_timestamp) from ApiQueryRecentchanges: it's nigh impossible to integrate with addJoin() and it doesn't seem to be necessary anyway (my MySQL instance automatically chooses rc_timestamp)

includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryAllpages.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryUserContributions.php
includes/api/ApiQueryUsers.php

index 4c6914b..71ea288 100644 (file)
@@ -54,7 +54,6 @@ class ApiQueryAllUsers extends ApiQueryBase {
                }
 
                $limit = $params['limit'];
-               $tables = $db->tableName('user');
 
                if( !is_null( $params['from'] ) )
                        $this->addWhere( 'user_name >= ' . $db->addQuotes( self::keyToTitle( $params['from'] ) ) );
@@ -64,21 +63,23 @@ class ApiQueryAllUsers extends ApiQueryBase {
 
                if (!is_null($params['group'])) {
                        // Filter only users that belong to a given group
-                       $tblName = $db->tableName('user_groups');
-                       $tables = "$tables INNER JOIN $tblName ug1 ON ug1.ug_user=user_id";
+                       $this->addTables('user_groups', 'ug1');
+                       $this->addWhere('ug1.ug_user=user_id');
                        $this->addWhereFld('ug1.ug_group', $params['group']);
                }
-
                if ($fld_groups) {
                        // Show the groups the given users belong to
                        // request more than needed to avoid not getting all rows that belong to one user
                        $groupCount = count(User::getAllGroups());
                        $sqlLimit = $limit+$groupCount+1;
-
-                       $tblName = $db->tableName('user_groups');
-                       $tables = "$tables LEFT JOIN $tblName ug2 ON ug2.ug_user=user_id";
+                       $this->addJoin(
+                               array('user', 'user_groups'),
+                               array(ApiQueryBase::LEFT_JOIN),
+                               array('ug2.ug_user=user_id'),
+                               array(null, 'ug2'));
                        $this->addFields('ug2.ug_group ug_group2');
                } else {
+                       $this->addTables('user');
                        $sqlLimit = $limit+1;
                }
 
@@ -86,7 +87,6 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        $this->addFields('user_registration');
 
                $this->addOption('LIMIT', $sqlLimit);
-               $this->addTables($tables);
 
                $this->addFields('user_name');
                $this->addFieldsIf('user_editcount', $fld_editcount);
index 4758542..efbca62 100644 (file)
@@ -97,11 +97,11 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase {
                }
 
                if($params['filterlanglinks'] == 'withoutlanglinks') {
-                       $pageName = $this->getDB()->tableName('page');
-                       $llName = $this->getDB()->tableName('langlinks');
-                       $tables = "$pageName LEFT JOIN $llName ON page_id=ll_from";
+                       $this->addJoin(
+                               array('page', 'langlinks'),
+                               array(ApiQueryBase::LEFT_JOIN),
+                               array('page_id=ll_from'));
                        $this->addWhere('ll_from IS NULL');
-                       $this->addTables($tables);
                        $forceNameTitleIndex = false;
                } else if($params['filterlanglinks'] == 'withlanglinks') {
                        $this->addTables(array('page', 'langlinks'));
index e2cfcfb..3b504ec 100644 (file)
@@ -101,8 +101,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                 * LIMIT 11 ORDER BY pl_from
                 */
                $db = $this->getDb();
-               list($tblpage, $tbllinks) = $db->tableNamesN('page', $this->bl_table);
-               $this->addTables("$tbllinks JOIN $tblpage ON {$this->bl_from}=page_id");
+               $this->addTables(array($this->bl_table, 'page'));
+               $this->addWhere("{$this->bl_from}=page_id");
                if(is_null($resultPageSet))
                        $this->addFields(array('page_id', 'page_title', 'page_namespace'));
                else
@@ -129,8 +129,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                 * LIMIT 11 ORDER BY pl_namespace, pl_title, pl_from
                 */
                $db = $this->getDb();
-               list($tblpage, $tbllinks) = $db->tableNamesN('page', $this->bl_table);
-               $this->addTables("$tbllinks JOIN $tblpage ON {$this->bl_from}=page_id");
+               $this->addTables(array($this->bl_table, 'page'));
+               $this->addWhere("{$this->bl_from}=page_id");
                if(is_null($resultPageSet))
                        $this->addFields(array('page_id', 'page_title', 'page_namespace', 'page_is_redirect'));
                else
index d8a6051..d9b9984 100644 (file)
@@ -37,6 +37,9 @@ if (!defined('MEDIAWIKI')) {
 abstract class ApiQueryBase extends ApiBase {
 
        private $mQueryModule, $mDb, $tables, $where, $fields, $options;
+       
+       const LEFT_JOIN = 1;
+       const RIGHT_JOIN = 2;
 
        public function __construct($query, $moduleName, $paramPrefix = '') {
                parent :: __construct($query->getMain(), $moduleName, $paramPrefix);
@@ -64,6 +67,35 @@ abstract class ApiQueryBase extends ApiBase {
                }
        }
 
+       protected function addJoin($tables, $types, $onClauses, $aliases = null) {
+               if(is_null($aliases))
+                       foreach($tables as $unused)
+                               $aliases[] = null;
+               if(!is_array($tables) || !is_array($types) || !is_array($onClauses) || !is_array($aliases))
+                       ApiBase::dieDebug(__METHOD__, 'This function only takes arrays as parameters');
+               $sql = $this->getDB()->tableName($tables[0]) . (is_null($aliases[0]) ? "" : " {$aliases[0]}");
+               for($i = 0; $i < count($tables) - 1; $i++)
+               {
+                       if($types[$i] == self::LEFT_JOIN)
+                               $join = "LEFT JOIN";
+                       else if($types[$i] == self::RIGHT_JOIN)
+                               $join = "RIGHT JOIN";
+                       else
+                               ApiBase::dieDebug(__METHOD__, "Invalid join type {$types[$i]}");
+                       
+                       if(is_array($onClauses[$i]))
+                               $on = $this->getDB()->makeList($onClauses[$i], LIST_AND);
+                       else
+                               $on = $onClauses[$i];
+                       $alias = $aliases[$i+1];
+                       $tblname = $this->getDB()->tableName($tables[$i+1]) . (is_null($alias) ? "" : " $alias");
+                       $sql = "$sql $join $tblname ON $on";
+               }
+               $this->addTables($sql);
+       }
+               
+               
+
        protected function addFields($value) {
                if (is_array($value))
                        $this->fields = array_merge($this->fields, $value);
index df93e7c..d5b8404 100644 (file)
@@ -57,11 +57,16 @@ class ApiQueryLogEvents extends ApiQueryBase {
                $hideLogs = LogEventsList::getExcludeClause($db);
                if($hideLogs !== false)
                        $this->addWhere($hideLogs);
-
-               $this->addOption('STRAIGHT_JOIN');
-               $this->addTables("$tbl_logging LEFT OUTER JOIN $tbl_page ON " .
-               "log_namespace=page_namespace AND log_title=page_title " .
-               "INNER JOIN $tbl_user ON user_id=log_user");
+               
+               $this->addTables('user');
+               $this->addWhere('user_id=log_user');
+               $this->addJoin(
+                               array('logging', 'page'),
+                               array(ApiQueryBase::LEFT_JOIN),
+                               array(
+                                       array(  'log_title=page_title',
+                                               'log_namespace=page_namespace'
+                                       )));
 
                $this->addFields(array (
                        'log_type',
index 16dd43b..4fd8298 100644 (file)
@@ -164,14 +164,19 @@ class ApiQueryRecentChanges extends ApiQueryBase {
                        $this->addFieldsIf('rc_patrolled', $this->fld_patrolled);
                        if($this->fld_redirect || isset($show['redirect']) || isset($show['!redirect']))
                        {
-                               $page = $db->tableName('page');
-                               $tables = "$page RIGHT JOIN $rc FORCE INDEX(rc_timestamp) ON page_namespace=rc_namespace AND page_title=rc_title";
+                               $this->addJoin(
+                                       array('page', 'recentchanges'),
+                                       array(ApiQueryBase::RIGHT_JOIN),
+                                       array(array(
+                                               'page_namespace=rc_namespace',
+                                               'page_title=rc_title')));
                                $this->addFields('page_is_redirect');
+                       } else {
+                               $this->addTables('recentchanges');
                        }
+               } else {
+                       $this->addTables('recentchanges');
                }
-               if(!isset($tables))
-                       $tables = "$rc FORCE INDEX(rc_timestamp)";
-               $this->addTables($tables);
                /* Specify the limit for our query. It's $limit+1 because we (possibly) need to
                 * generate a "continue" parameter, to allow paging. */
                $this->addOption('LIMIT', $limit +1);
index 21ceb27..11eff3c 100644 (file)
@@ -131,8 +131,10 @@ class ApiQueryContributions extends ApiQueryBase {
 
                //We're after the revision table, and the corresponding page row for
                //anything we retrieve.
-               list ($tbl_page, $tbl_revision) = $this->getDB()->tableNamesN('page', 'revision');
-               $this->addTables("$tbl_revision LEFT OUTER JOIN $tbl_page ON page_id=rev_page");
+               $this->addJoin(
+                       array('revision', 'page'),
+                       array(ApiQueryBase::LEFT_JOIN),
+                       array('page_id=rev_page'));
 
                $this->addWhereFld('rev_deleted', 0);
                // We only want pages by the specified users.
index c0cae50..8290818 100644 (file)
@@ -72,24 +72,41 @@ if (!defined('MEDIAWIKI')) {
                        return $retval;
 
                $db = $this->getDb();
-               $userTable = $db->tableName('user');
-               $tables = "$userTable AS u1";
                $this->addFields('u1.user_name');
                $this->addWhereFld('u1.user_name', $goodNames);
                $this->addFieldsIf('u1.user_editcount', isset($this->prop['editcount']));
 
+               $join = false;
+               $tables = array('user');
+               $types = array();
+               $conds = array();
+               $aliases = array('u1');
                if(isset($this->prop['groups'])) {
-                       $ug = $db->tableName('user_groups');
-                       $tables = "$tables LEFT JOIN $ug ON ug_user=u1.user_id";
+                       $join = true;
+                       $tables[] = 'user_groups';
+                       $types[] = ApiQueryBase::LEFT_JOIN;
+                       $conds[] = 'ug_user=u1.user_id';
+                       $aliases[] = null;
                        $this->addFields('ug_group');
                }
                if(isset($this->prop['blockinfo'])) {
-                       $ipb = $db->tableName('ipblocks');
-                       $tables = "$tables LEFT JOIN $ipb ON ipb_user=u1.user_id";
-                       $tables = "$tables LEFT JOIN $userTable AS u2 ON ipb_by=u2.user_id";
+                       $join = true;
+                       $tables[] = 'ipblocks';
+                       $types[] = ApiQueryBase::LEFT_JOIN;
+                       $conds[] = 'ipb_user=u1.user_id';
+                       $aliases[] = null;
+                       
+                       $tables[] = 'user';
+                       $types[] = ApiQueryBase::LEFT_JOIN;
+                       $conds[] = 'ipb_by=u2.user_id';
+                       $aliases[] = 'u2';
                        $this->addFields(array('ipb_reason', 'u2.user_name AS blocker_name'));
                }
-               $this->addTables($tables);
+               
+               if($join)
+                       $this->addJoin($tables, $types, $conds, $aliases);
+               else
+                       $this->addTables('user', 'u1');
 
                $data = array();
                $res = $this->select(__METHOD__);