r37270 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r37269‎ | r37270 | r37271 >
Date:17:32, 7 July 2008
Author:catrope
Status:old
Tags:
Comment:
API: Add paging (i.e. limit and continue) parameters to prop={links,templatelinks,langlinks,extlinks,categories,images}. This means that these modules will no longer request data from the database without a LIMIT, and that clients will have to use the query-continue method to get all the results.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryCategories.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryExternalLinks.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryImages.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryLangLinks.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryLinks.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/api/ApiQueryLinks.php
@@ -84,7 +84,22 @@
8585 $this->addTables($this->table);
8686 $this->addWhereFld($this->prefix . '_from', array_keys($this->getPageSet()->getGoodTitles()));
8787 $this->addWhereFld($this->prefix . '_namespace', $params['namespace']);
88 -
 88+
 89+ if(!is_null($params['continue'])) {
 90+ $cont = explode('|', $params['continue']);
 91+ if(count($cont) != 3)
 92+ $this->dieUsage("Invalid continue param. You should pass the " .
 93+ "original value returned by the previous query", "_badcontinue");
 94+ $plfrom = intval($cont[0]);
 95+ $plns = intval($cont[1]);
 96+ $pltitle = $this->getDb()->strencode($cont[2]);
 97+ $this->addWhere("{$this->prefix}_from > $plfrom OR ".
 98+ "({$this->prefix}_from = $plfrom AND ".
 99+ "({$this->prefix}_namespace > $plns OR ".
 100+ "({$this->prefix}_namespace = $plns AND ".
 101+ "{$this->prefix}_title >= '$pltitle')))");
 102+ }
 103+
89104 # Here's some MySQL craziness going on: if you use WHERE foo='bar'
90105 # and later ORDER BY foo MySQL doesn't notice the ORDER BY is pointless
91106 # but instead goes and filesorts, because the index for foo was used
@@ -93,11 +108,12 @@
94109 $order = array();
95110 if(count($this->getPageSet()->getGoodTitles()) != 1)
96111 $order[] = "{$this->prefix}_from";
97 - if(!isset($params['namespace']))
 112+ if(count($params['namespace']) != 1)
98113 $order[] = "{$this->prefix}_namespace";
99114 $order[] = "{$this->prefix}_title";
100115 $this->addOption('ORDER BY', implode(", ", $order));
101116 $this->addOption('USE INDEX', "{$this->prefix}_from");
 117+ $this->addOption('LIMIT', $params['limit'] + 1);
102118
103119 $db = $this->getDB();
104120 $res = $this->select(__METHOD__);
@@ -106,7 +122,15 @@
107123
108124 $data = array();
109125 $lastId = 0; // database has no ID 0
 126+ $count = 0;
110127 while ($row = $db->fetchObject($res)) {
 128+ if(++$count > $params['limit']) {
 129+ // We've reached the one extra which shows that
 130+ // there are additional pages to be had. Stop here...
 131+ $this->setContinueEnumParameter('continue',
 132+ "{$row->pl_from}|{$row->pl_namespace}|{$row->pl_title}");
 133+ break;
 134+ }
111135 if ($lastId != $row->pl_from) {
112136 if($lastId != 0) {
113137 $this->addPageSubItems($lastId, $data);
@@ -127,7 +151,15 @@
128152 } else {
129153
130154 $titles = array();
 155+ $count = 0;
131156 while ($row = $db->fetchObject($res)) {
 157+ if(++$count > $params['limit']) {
 158+ // We've reached the one extra which shows that
 159+ // there are additional pages to be had. Stop here...
 160+ $this->setContinueEnumParameter('continue',
 161+ "{$row->pl_from}|{$row->pl_namespace}|{$row->pl_title}");
 162+ break;
 163+ }
132164 $titles[] = Title :: makeTitle($row->pl_namespace, $row->pl_title);
133165 }
134166 $resultPageSet->populateFromTitles($titles);
@@ -142,15 +174,25 @@
143175 'namespace' => array(
144176 ApiBase :: PARAM_TYPE => 'namespace',
145177 ApiBase :: PARAM_ISMULTI => true
146 - )
 178+ ),
 179+ 'limit' => array(
 180+ ApiBase :: PARAM_DFLT => 10,
 181+ ApiBase :: PARAM_TYPE => 'limit',
 182+ ApiBase :: PARAM_MIN => 1,
 183+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 184+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 185+ ),
 186+ 'continue' => null,
147187 );
148188 }
149189
150190 public function getParamDescription()
151191 {
152192 return array(
153 - 'namespace' => "Show {$this->description}s in this namespace(s) only"
154 - );
 193+ 'namespace' => "Show {$this->description}s in this namespace(s) only",
 194+ 'limit' => 'How many links to return',
 195+ 'continue' => 'When more results are available, use this to continue',
 196+ );
155197 }
156198
157199 public function getDescription() {
Index: trunk/phase3/includes/api/ApiQueryLangLinks.php
@@ -43,6 +43,7 @@
4444 if ( $this->getPageSet()->getGoodTitleCount() == 0 )
4545 return;
4646
 47+ $params = $this->extractRequestParams();
4748 $this->addFields(array (
4849 'll_from',
4950 'll_lang',
@@ -51,14 +52,36 @@
5253
5354 $this->addTables('langlinks');
5455 $this->addWhereFld('ll_from', array_keys($this->getPageSet()->getGoodTitles()));
55 - $this->addOption('ORDER BY', "ll_from, ll_lang");
 56+ if(!is_null($params['continue'])) {
 57+ $cont = explode('|', $params['continue']);
 58+ if(count($cont) != 2)
 59+ $this->dieUsage("Invalid continue param. You should pass the " .
 60+ "original value returned by the previous query", "_badcontinue");
 61+ $llfrom = intval($cont[0]);
 62+ $lllang = $this->getDb()->strencode($cont[1]);
 63+ $this->addWhere("ll_from > $llfrom OR ".
 64+ "(ll_from = $llfrom AND ".
 65+ "ll_lang >= '$lllang')");
 66+ }
 67+ # Don't order by ll_from if it's constant in the WHERE clause
 68+ if(count($this->getPageSet()->getGoodTitles()) == 1)
 69+ $this->addOption('ORDER BY', 'll_lang');
 70+ else
 71+ $this->addOption('ORDER BY', 'll_from, ll_lang');
 72+ $this->addOption('LIMIT', $params['limit'] + 1);
5673 $res = $this->select(__METHOD__);
5774
5875 $data = array();
5976 $lastId = 0; // database has no ID 0
 77+ $count = 0;
6078 $db = $this->getDB();
6179 while ($row = $db->fetchObject($res)) {
62 -
 80+ if (++$count > $params['limit']) {
 81+ // We've reached the one extra which shows that
 82+ // there are additional pages to be had. Stop here...
 83+ $this->setContinueEnumParameter('continue', "{$row->ll_from}|{$row->ll_lang}");
 84+ break;
 85+ }
6386 if ($lastId != $row->ll_from) {
6487 if($lastId != 0) {
6588 $this->addPageSubItems($lastId, $data);
@@ -67,7 +90,7 @@
6891 $lastId = $row->ll_from;
6992 }
7093
71 - $entry = array('lang'=>$row->ll_lang);
 94+ $entry = array('lang' => $row->ll_lang);
7295 ApiResult :: setContent($entry, $row->ll_title);
7396 $data[] = $entry;
7497 }
@@ -79,6 +102,26 @@
80103 $db->freeResult($res);
81104 }
82105
 106+ public function getAllowedParams() {
 107+ return array(
 108+ 'limit' => array(
 109+ ApiBase :: PARAM_DFLT => 10,
 110+ ApiBase :: PARAM_TYPE => 'limit',
 111+ ApiBase :: PARAM_MIN => 1,
 112+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 113+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 114+ ),
 115+ 'continue' => null,
 116+ );
 117+ }
 118+
 119+ public function getParamDescription () {
 120+ return array(
 121+ 'limit' => 'How many langlinks to return',
 122+ 'continue' => 'When more results are available, use this to continue',
 123+ );
 124+ }
 125+
83126 public function getDescription() {
84127 return 'Returns all interlanguage links from the given page(s)';
85128 }
Index: trunk/phase3/includes/api/ApiQueryExternalLinks.php
@@ -43,6 +43,7 @@
4444 if ( $this->getPageSet()->getGoodTitleCount() == 0 )
4545 return;
4646
 47+ $params = $this->extractRequestParams();
4748 $this->addFields(array (
4849 'el_from',
4950 'el_to'
@@ -50,13 +51,26 @@
5152
5253 $this->addTables('externallinks');
5354 $this->addWhereFld('el_from', array_keys($this->getPageSet()->getGoodTitles()));
 55+ # Don't order by el_from if it's constant in the WHERE clause
 56+ if(count($this->getPageSet()->getGoodTitles()) != 1)
 57+ $this->addOption('ORDER BY', 'el_from');
 58+ $this->addOption('LIMIT', $params['limit'] + 1);
 59+ if(!is_null($params['offset']))
 60+ $this->addOption('OFFSET', $params['offset']);
5461
5562 $db = $this->getDB();
5663 $res = $this->select(__METHOD__);
5764
5865 $data = array();
5966 $lastId = 0; // database has no ID 0
 67+ $count = 0;
6068 while ($row = $db->fetchObject($res)) {
 69+ if (++$count > $params['limit']) {
 70+ // We've reached the one extra which shows that
 71+ // there are additional pages to be had. Stop here...
 72+ $this->setContinueEnumParameter('offset', @$params['offset'] + $params['limit']);
 73+ break;
 74+ }
6175 if ($lastId != $row->el_from) {
6276 if($lastId != 0) {
6377 $this->addPageSubItems($lastId, $data);
@@ -77,6 +91,26 @@
7892 $db->freeResult($res);
7993 }
8094
 95+ public function getAllowedParams() {
 96+ return array(
 97+ 'limit' => array(
 98+ ApiBase :: PARAM_DFLT => 10,
 99+ ApiBase :: PARAM_TYPE => 'limit',
 100+ ApiBase :: PARAM_MIN => 1,
 101+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 102+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 103+ ),
 104+ 'offset' => null,
 105+ );
 106+ }
 107+
 108+ public function getParamDescription () {
 109+ return array(
 110+ 'limit' => 'How many links to return',
 111+ 'offset' => 'When more results are available, use this to continue',
 112+ );
 113+ }
 114+
81115 public function getDescription() {
82116 return 'Returns all external urls (not interwikies) from the given page(s)';
83117 }
Index: trunk/phase3/includes/api/ApiQueryCategories.php
@@ -80,7 +80,22 @@
8181
8282 $this->addTables('categorylinks');
8383 $this->addWhereFld('cl_from', array_keys($this->getPageSet()->getGoodTitles()));
84 - $this->addOption('ORDER BY', "cl_from, cl_to");
 84+ if(!is_null($params['continue'])) {
 85+ $cont = explode('|', $params['continue']);
 86+ if(count($cont) != 2)
 87+ $this->dieUsage("Invalid continue param. You should pass the " .
 88+ "original value returned by the previous query", "_badcontinue");
 89+ $clfrom = intval($cont[0]);
 90+ $clto = $this->getDb()->strencode($cont[1]);
 91+ $this->addWhere("cl_from > $clfrom OR ".
 92+ "(cl_from = $clfrom AND ".
 93+ "cl_to >= '$clto')");
 94+ }
 95+ # Don't order by cl_from if it's constant in the WHERE clause
 96+ if(count($this->getPageSet()->getGoodTitles()) == 1)
 97+ $this->addOption('ORDER BY', 'cl_to');
 98+ else
 99+ $this->addOption('ORDER BY', "cl_from, cl_to");
85100
86101 $db = $this->getDB();
87102 $res = $this->select(__METHOD__);
@@ -89,7 +104,14 @@
90105
91106 $data = array();
92107 $lastId = 0; // database has no ID 0
 108+ $count = 0;
93109 while ($row = $db->fetchObject($res)) {
 110+ if (++$count > $params['limit']) {
 111+ // We've reached the one extra which shows that
 112+ // there are additional pages to be had. Stop here...
 113+ $this->setContinueEnumParameter('continue', "{$row->cl_from}|{$row->cl_to}");
 114+ break;
 115+ }
94116 if ($lastId != $row->cl_from) {
95117 if($lastId != 0) {
96118 $this->addPageSubItems($lastId, $data);
@@ -118,6 +140,13 @@
119141
120142 $titles = array();
121143 while ($row = $db->fetchObject($res)) {
 144+ if (++$count > $params['limit']) {
 145+ // We've reached the one extra which shows that
 146+ // there are additional pages to be had. Stop here...
 147+ $this->setContinueEnumParameter('continue', "{$row->il_from}|{$row->il_to}");
 148+ break;
 149+ }
 150+
122151 $titles[] = Title :: makeTitle(NS_CATEGORY, $row->cl_to);
123152 }
124153 $resultPageSet->populateFromTitles($titles);
@@ -134,13 +163,23 @@
135164 'sortkey',
136165 'timestamp',
137166 )
138 - )
 167+ ),
 168+ 'limit' => array(
 169+ ApiBase :: PARAM_DFLT => 10,
 170+ ApiBase :: PARAM_TYPE => 'limit',
 171+ ApiBase :: PARAM_MIN => 1,
 172+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 173+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 174+ ),
 175+ 'continue' => null,
139176 );
140177 }
141178
142179 public function getParamDescription() {
143180 return array (
144181 'prop' => 'Which additional properties to get for each category.',
 182+ 'limit' => 'How many langlinks to return',
 183+ 'continue' => 'When more results are available, use this to continue',
145184 );
146185 }
147186
Index: trunk/phase3/includes/api/ApiQueryImages.php
@@ -29,7 +29,7 @@
3030 }
3131
3232 /**
33 - * This query adds <images> subelement to all pages with the list of images embedded into those pages.
 33+ * This query adds an <images> subelement to all pages with the list of images embedded into those pages.
3434 *
3535 * @ingroup API
3636 */
@@ -52,6 +52,7 @@
5353 if ($this->getPageSet()->getGoodTitleCount() == 0)
5454 return; // nothing to do
5555
 56+ $params = $this->extractRequestParams();
5657 $this->addFields(array (
5758 'il_from',
5859 'il_to'
@@ -59,7 +60,23 @@
6061
6162 $this->addTables('imagelinks');
6263 $this->addWhereFld('il_from', array_keys($this->getPageSet()->getGoodTitles()));
63 - $this->addOption('ORDER BY', "il_from, il_to");
 64+ if(!is_null($params['continue'])) {
 65+ $cont = explode('|', $params['continue']);
 66+ if(count($cont) != 2)
 67+ $this->dieUsage("Invalid continue param. You should pass the " .
 68+ "original value returned by the previous query", "_badcontinue");
 69+ $ilfrom = intval($cont[0]);
 70+ $ilto = $this->getDb()->strencode($cont[1]);
 71+ $this->addWhere("il_from > $ilfrom OR ".
 72+ "(il_from = $ilfrom AND ".
 73+ "il_to >= '$ilto')");
 74+ }
 75+ # Don't order by il_from if it's constant in the WHERE clause
 76+ if(count($this->getPageSet()->getGoodTitles()) == 1)
 77+ $this->addOption('ORDER BY', 'il_to');
 78+ else
 79+ $this->addOption('ORDER BY', 'il_from, il_to');
 80+ $this->addOption('LIMIT', $params['limit'] + 1);
6481
6582 $db = $this->getDB();
6683 $res = $this->select(__METHOD__);
@@ -68,7 +85,14 @@
6986
7087 $data = array();
7188 $lastId = 0; // database has no ID 0
 89+ $count = 0;
7290 while ($row = $db->fetchObject($res)) {
 91+ if (++$count > $params['limit']) {
 92+ // We've reached the one extra which shows that
 93+ // there are additional pages to be had. Stop here...
 94+ $this->setContinueEnumParameter('continue', "{$row->il_from}|{$row->il_to}");
 95+ break;
 96+ }
7397 if ($lastId != $row->il_from) {
7498 if($lastId != 0) {
7599 $this->addPageSubItems($lastId, $data);
@@ -89,7 +113,14 @@
90114 } else {
91115
92116 $titles = array();
 117+ $count = 0;
93118 while ($row = $db->fetchObject($res)) {
 119+ if (++$count > $params['limit']) {
 120+ // We've reached the one extra which shows that
 121+ // there are additional pages to be had. Stop here...
 122+ $this->setContinueEnumParameter('continue', "{$row->il_from}|{$row->il_to}");
 123+ break;
 124+ }
94125 $titles[] = Title :: makeTitle(NS_IMAGE, $row->il_to);
95126 }
96127 $resultPageSet->populateFromTitles($titles);
@@ -98,6 +129,26 @@
99130 $db->freeResult($res);
100131 }
101132
 133+ public function getAllowedParams() {
 134+ return array(
 135+ 'limit' => array(
 136+ ApiBase :: PARAM_DFLT => 10,
 137+ ApiBase :: PARAM_TYPE => 'limit',
 138+ ApiBase :: PARAM_MIN => 1,
 139+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 140+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 141+ ),
 142+ 'continue' => null,
 143+ );
 144+ }
 145+
 146+ public function getParamDescription () {
 147+ return array(
 148+ 'limit' => 'How many images to return',
 149+ 'continue' => 'When more results are available, use this to continue',
 150+ );
 151+ }
 152+
102153 public function getDescription() {
103154 return 'Returns all images contained on the given page(s)';
104155 }
Index: trunk/phase3/RELEASE-NOTES
@@ -507,6 +507,8 @@
508508 * Added APIQueryInfoTokens and APIQueryRevisionsTokens hooks so extensions
509509 can add their own tokens
510510 * Added block and unblock tokens to prop=info as well
 511+* Added paging (limit and continue parameters) to
 512+ prop={links,templatelinks,langlinks,extlinks,categories,images}
511513
512514 === Languages updated in 1.13 ===
513515

Follow-up revisions

RevisionCommit summaryAuthorDate
r37502API: Some cleanup and fixes before 1.13 is released:...catrope14:13, 10 July 2008

Status & tagging log