r49631 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r49630‎ | r49631 | r49632 >
Date:18:04, 18 April 2009
Author:catrope
Status:deferred
Tags:
Comment:
* querypage-work: Migrate all QueryPage subclasses to getQueryInfo()
* Implement Mostrevisionspage as a subclass of Fewestrevisionpages
Modified paths:
  • /branches/querypage-work/TODO (added) (history)
  • /branches/querypage-work/phase3/includes/QueryPage.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialAncientpages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialDoubleRedirects.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialFewestrevisions.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialLinkSearch.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialListredirects.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialLonelypages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialMostcategories.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialMostimages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialMostlinked.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialMostlinkedcategories.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialMostlinkedtemplates.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialMostrevisions.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialShortpages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialUncategorizedimages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialUncategorizedpages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialUnusedcategories.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialUnusedimages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialUnusedtemplates.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialUnwatchedpages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialWantedcategories.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialWantedfiles.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialWantedpages.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialWantedtemplates.php (modified) (history)
  • /branches/querypage-work/phase3/includes/specials/SpecialWithoutinterwiki.php (modified) (history)

Diff [purge]

Index: branches/querypage-work/phase3/includes/QueryPage.php
@@ -87,8 +87,8 @@
8888
8989 /**
9090 * Subclasses return their name here. Make sure the name is also
91 - * specified in SpecialPage.php and in Language.php as a language message
92 - * param.
 91+ * specified in SpecialPage.php and in Language.php as a language
 92+ * message param.
9393 */
9494 function getName() {
9595 return '';
@@ -119,8 +119,8 @@
120120 * These may be stored in the querycache table for expensive queries,
121121 * and that cached data will be returned sometimes, so the presence of
122122 * extra fields can't be relied upon. The cached 'value' column will be
123 - * an integer; non-numeric values are useful only for sorting the initial
124 - * query.
 123+ * an integer; non-numeric values are useful only for sorting the
 124+ * initial query (except if they're timestamps, see usesTimestamps()).
125125 *
126126 * Don't include an ORDER or LIMIT clause, they will be added
127127 * @return array
@@ -138,6 +138,19 @@
139139 }
140140
141141 /**
 142+ * Does this query return timestamps rather than integers in its
 143+ * 'value' field? If true, this class will convert 'value' to a
 144+ * UNIX timestamp for caching.
 145+ * NOTE: formatRow() may get timestamps in TS_MW (mysql), TS_DB (pgsql)
 146+ * or TS_UNIX (querycache) format, so be sure to always run them
 147+ * through wfTimestamp()
 148+ * @return bool
 149+ */
 150+ function usesTimestamps() {
 151+ return false;
 152+ }
 153+
 154+ /**
142155 * Override to sort by increasing values
143156 */
144157 function sortDescending() {
@@ -242,7 +255,12 @@
243256 $vals = array();
244257 while ( $res && $row = $dbr->fetchObject( $res ) ) {
245258 if ( isset( $row->value ) ) {
246 - $value = intval( $row->value ); // @bug 14414
 259+ if ( $this->usesTimestamps() ) {
 260+ $value = wfTimestamp( TS_UNIX,
 261+ $row->value );
 262+ } else {
 263+ $value = intval( $row->value ); // @bug 14414
 264+ }
247265 } else {
248266 $value = 0;
249267 }
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedcategories.php
@@ -19,22 +19,19 @@
2020 return 'Wantedcategories';
2121 }
2222
23 - function getSQL() {
24 - $dbr = wfGetDB( DB_SLAVE );
25 - list( $categorylinks, $page ) = $dbr->tableNamesN( 'categorylinks', 'page' );
26 - $name = $dbr->addQuotes( $this->getName() );
27 - return
28 - "
29 - SELECT
30 - $name as type,
31 - " . NS_CATEGORY . " as namespace,
32 - cl_to as title,
33 - COUNT(*) as value
34 - FROM $categorylinks
35 - LEFT JOIN $page ON cl_to = page_title AND page_namespace = ". NS_CATEGORY ."
36 - WHERE page_title IS NULL
37 - GROUP BY cl_to
38 - ";
 23+ function getQueryInfo() {
 24+ return array (
 25+ 'tables' => array ( 'categorylinks', 'page' ),
 26+ 'fields' => array ( "'{$this->getName()}' AS type",
 27+ "'" . NS_CATEGORY . "' AS namespace",
 28+ 'cl_to AS title',
 29+ 'COUNT(*) AS value' ),
 30+ 'conds' => array ( 'page_title IS NULL' ),
 31+ 'options' => array ( 'GROUP BY' => 'cl_to' ),
 32+ 'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
 33+ array ( 'page_title = cl_to',
 34+ 'page_namespace' => NS_CATEGORY ) ) )
 35+ );
3936 }
4037
4138 function formatResult( $skin, $result ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialWithoutinterwiki.php
@@ -50,22 +50,23 @@
5151 return false;
5252 }
5353
54 - function getSQL() {
55 - $dbr = wfGetDB( DB_SLAVE );
56 - list( $page, $langlinks ) = $dbr->tableNamesN( 'page', 'langlinks' );
57 - $prefix = $this->prefix ? "AND page_title LIKE '" . $dbr->escapeLike( $this->prefix ) . "%'" : '';
58 - return
59 - "SELECT 'Withoutinterwiki' AS type,
60 - page_namespace AS namespace,
61 - page_title AS title,
62 - page_title AS value
63 - FROM $page
64 - LEFT JOIN $langlinks
65 - ON ll_from = page_id
66 - WHERE ll_title IS NULL
67 - AND page_namespace=" . NS_MAIN . "
68 - AND page_is_redirect = 0
69 - {$prefix}";
 54+ function getQueryInfo() {
 55+ $query = array (
 56+ 'tables' => array ( 'page', 'langlinks' ),
 57+ 'fields' => array ( "'{$this->getName()}' AS type",
 58+ 'page_namespace AS namespace',
 59+ 'page_title AS title',
 60+ 'page_title AS value' ),
 61+ 'conds' => array ( 'll_title IS NULL' ),
 62+ 'join_conds' => array ( 'langlinks' => array (
 63+ 'LEFT JOIN', 'll_from = page_id' ) )
 64+ );
 65+ if ( $this->prefix ) {
 66+ $dbr = wfGetDb( DB_SLAVE );
 67+ $encPrefix = $dbr->escapeLike( $this->prefix );
 68+ $query['conds'][] = "page_title LIKE '{$encPrefix}%'";
 69+ }
 70+ return $query;
7071 }
7172
7273 function setPrefix( $prefix = '' ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialUnusedimages.php
@@ -21,32 +21,41 @@
2222 }
2323 function isSyndicated() { return false; }
2424
25 - function getSQL() {
26 - global $wgCountCategorizedImagesAsUsed, $wgDBtype;
27 - $dbr = wfGetDB( DB_SLAVE );
28 -
29 - $epoch = $wgDBtype == 'mysql' ?
30 - 'UNIX_TIMESTAMP(img_timestamp)' :
31 - 'EXTRACT(epoch FROM img_timestamp)';
32 -
 25+ function getQueryInfo() {
 26+ global $wgCountCategorizedImagesAsUsed;
 27+ $retval = array (
 28+ 'tables' => array ( 'image', 'imagelinks' ),
 29+ 'fields' => array ( "'{$this->getName()}' AS type",
 30+ "'" . NS_FILE . "' AS namespace",
 31+ 'img_name AS title',
 32+ 'img_timestamp AS value',
 33+ 'img_user', 'img_user_text',
 34+ 'img_description' ),
 35+ 'conds' => array ( 'il_to IS NULL' ),
 36+ 'join_conds' => array ( 'imagelinks' => array (
 37+ 'LEFT JOIN', 'il_to = img_name' ) )
 38+ );
3339 if ( $wgCountCategorizedImagesAsUsed ) {
34 - list( $page, $image, $imagelinks, $categorylinks ) = $dbr->tableNamesN( 'page', 'image', 'imagelinks', 'categorylinks' );
35 -
36 - return "SELECT 'Unusedimages' as type, 6 as namespace, img_name as title, $epoch as value,
37 - img_user, img_user_text, img_description
38 - FROM ((($page AS I LEFT JOIN $categorylinks AS L ON I.page_id = L.cl_from)
39 - LEFT JOIN $imagelinks AS P ON I.page_title = P.il_to)
40 - INNER JOIN $image AS G ON I.page_title = G.img_name)
41 - WHERE I.page_namespace = ".NS_FILE." AND L.cl_from IS NULL AND P.il_to IS NULL";
42 - } else {
43 - list( $image, $imagelinks ) = $dbr->tableNamesN( 'image','imagelinks' );
44 -
45 - return "SELECT 'Unusedimages' as type, 6 as namespace, img_name as title, $epoch as value,
46 - img_user, img_user_text, img_description
47 - FROM $image LEFT JOIN $imagelinks ON img_name=il_to WHERE il_to IS NULL ";
 40+ // Order is significant
 41+ $retval['tables'] = array ( 'page', 'categorylinks',
 42+ 'imagelinks', 'image' );
 43+ $retval['conds']['page_namespace'] = NS_FILE;
 44+ $retval['conds'][] = 'cl_from IS NULL';
 45+ $retval['join_conds']['categorylinks'] = array (
 46+ 'LEFT JOIN', 'cl_from = page_id' );
 47+ $retval['join_conds']['imagelinks'] = array (
 48+ 'LEFT JOIN', 'il_to = page_title' );
 49+ // TODO: Make this one implicit?
 50+ $retval['join_conds']['image'] = array (
 51+ 'INNER JOIN', 'img_name = page_title' );
4852 }
 53+ return $retval;
4954 }
5055
 56+ function usesTimestamps() {
 57+ return true;
 58+ }
 59+
5160 function getPageHeader() {
5261 return wfMsgExt( 'unusedimagestext', array( 'parse' ) );
5362 }
Index: branches/querypage-work/phase3/includes/specials/SpecialUncategorizedimages.php
@@ -10,6 +10,7 @@
1111 /**
1212 * @ingroup SpecialPage
1313 */
 14+// FIXME: Use an instance of UncategorizedPagesPage or something
1415 class UncategorizedImagesPage extends ImageQueryPage {
1516
1617 function getName() {
Index: branches/querypage-work/phase3/includes/specials/SpecialAncientpages.php
@@ -21,24 +21,23 @@
2222 function isSyndicated() { return false; }
2323
2424 function getQueryInfo() {
25 - // FIXME convert timestamps elsewhere
26 - // Possibly add bool returnsTimestamps()
2725 // FIXME standardize 'name' AS type ?
28 - global $wgDBtype;
29 - $epoch = $wgDBtype == 'mysql' ? 'UNIX_TIMESTAMP(rev_timestamp)' :
30 - 'EXTRACT(epoch FROM rev_timestamp)';
3126 return array(
3227 'tables' => array( 'page', 'revision' ),
3328 'fields' => array( "'{$this->getName()}' AS type",
3429 'page_namespace AS namespace',
3530 'page_title AS title',
36 - "$epoch AS value" ),
 31+ 'rev_timestamp AS value' ),
3732 'conds' => array( 'page_namespace' => NS_MAIN,
3833 'page_is_redirect' => 0,
3934 'page_latest=rev_id' )
4035 );
4136 }
4237
 38+ function usesTimestamps() {
 39+ return true;
 40+ }
 41+
4342 function sortDescending() {
4443 return false;
4544 }
@@ -49,7 +48,7 @@
5049 $d = $wgLang->timeanddate( wfTimestamp( TS_MW, $result->value ), true );
5150 $title = Title::makeTitle( $result->namespace, $result->title );
5251 $link = $skin->makeKnownLinkObj( $title, htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) );
53 - return wfSpecialList($link, $d);
 52+ return wfSpecialList( $link, $d );
5453 }
5554 }
5655
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedpages.php
@@ -44,6 +44,37 @@
4545 wfRunHooks( 'WantedPages::getSQL', array( &$this, &$sql ) );
4646 return $sql;
4747 }
 48+
 49+ function getQueryInfo() {
 50+ global $wgWantedPagesThreshold;
 51+ $count = $wgWantedPagesThreshold - 1;
 52+ $query = array (
 53+ 'tables' => array ( 'pagelinks', 'page AS pg1',
 54+ 'page AS pg2' ),
 55+ 'fields' => array ( "'{$this->getName()}' AS type",
 56+ 'pl_namespace AS namespace',
 57+ 'pl_title AS title',
 58+ 'COUNT(*) AS value' ),
 59+ 'conds' => array ( 'pg1.page_namespace IS NULL',
 60+ "pl_namespace NOT IN ( '" . NS_USER .
 61+ "', '" . NS_USER_TALK . "' )",
 62+ "pg2.page_namespace != '" .
 63+ NS_MEDIAWIKI . "'" ),
 64+ 'options' => array ( 'HAVING' => "COUNT(*) > $count",
 65+ 'GROUP BY' => 'pl_namespace, pl_title' ),
 66+ // TODO: test this join
 67+ 'join_conds' => array ( 'page AS pg1' => array (
 68+ 'LEFT JOIN', array (
 69+ 'pg1.page_namespace = pl_namespace',
 70+ 'pg2.page_title = pl_title' ) ),
 71+ 'page AS pg2' => array ( 'LEFT JOIN',
 72+ 'pg2.page_id = pl_from' ) )
 73+ );
 74+ // TODO: find and migrate WantedPages::getSQL hook usage
 75+ wfRunHooks( 'WantedPages::getQueryInfo',
 76+ array( &$this, &$query ) );
 77+ return $query;
 78+ }
4879 }
4980
5081 /**
Index: branches/querypage-work/phase3/includes/specials/SpecialMostlinked.php
@@ -25,19 +25,21 @@
2626 /**
2727 * Note: Getting page_namespace only works if $this->isCached() is false
2828 */
29 - function getSQL() {
30 - $dbr = wfGetDB( DB_SLAVE );
31 - list( $pagelinks, $page ) = $dbr->tableNamesN( 'pagelinks', 'page' );
32 - return
33 - "SELECT 'Mostlinked' AS type,
34 - pl_namespace AS namespace,
35 - pl_title AS title,
36 - COUNT(*) AS value,
37 - page_namespace
38 - FROM $pagelinks
39 - LEFT JOIN $page ON pl_namespace=page_namespace AND pl_title=page_title
40 - GROUP BY pl_namespace, pl_title, page_namespace
41 - HAVING COUNT(*) > 1";
 29+ function getQueryInfo() {
 30+ return array (
 31+ 'tables' => array ( 'pagelinks', 'page' ),
 32+ 'fields' => array ( "'{$this->getName()}' AS type",
 33+ 'pl_namespace AS namespace',
 34+ 'pl_title AS title',
 35+ 'COUNT(*) AS value',
 36+ 'page_namespace' ),
 37+ 'options' => array ( 'HAVING' => 'COUNT(*) > 1',
 38+ 'GROUP BY' => 'pl_namespace, pl_title, '.
 39+ 'page_namespace' ),
 40+ 'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
 41+ array ( 'page_namespace = pl_namespace',
 42+ 'page_title = pl_title' ) ) )
 43+ );
4244 }
4345
4446 /**
Index: branches/querypage-work/phase3/includes/specials/SpecialMostlinkedcategories.php
@@ -19,20 +19,15 @@
2020 function isExpensive() { return true; }
2121 function isSyndicated() { return false; }
2222
23 - function getSQL() {
24 - $dbr = wfGetDB( DB_SLAVE );
25 - $categorylinks = $dbr->tableName( 'categorylinks' );
26 - $name = $dbr->addQuotes( $this->getName() );
27 - return
28 - "
29 - SELECT
30 - $name as type,
31 - " . NS_CATEGORY . " as namespace,
32 - cl_to as title,
33 - COUNT(*) as value
34 - FROM $categorylinks
35 - GROUP BY cl_to
36 - ";
 23+ function getQueryInfo() {
 24+ return array (
 25+ 'tables' => array ( 'categorylinks' ),
 26+ 'fields' => array ( "'{$this->getName()}' AS type",
 27+ "'" . NS_CATEGORY . "' AS namespace",
 28+ 'cl_to AS title',
 29+ 'COUNT(*) AS value' ),
 30+ 'options' => array ( 'GROUP BY' => 'cl_to' )
 31+ );
3732 }
3833
3934 function sortDescending() { return true; }
Index: branches/querypage-work/phase3/includes/specials/SpecialDoubleRedirects.php
@@ -22,52 +22,53 @@
2323 return wfMsgExt( 'doubleredirectstext', array( 'parse' ) );
2424 }
2525
26 - function getSQLText( &$dbr, $namespace = null, $title = null ) {
27 -
28 - list( $page, $redirect ) = $dbr->tableNamesN( 'page', 'redirect' );
29 -
 26+ function reallyGetQueryInfo($namespace = null, $title = null) {
3027 $limitToTitle = !( $namespace === null && $title === null );
31 - $sql = $limitToTitle ? "SELECT" : "SELECT 'DoubleRedirects' as type," ;
32 - $sql .=
33 - " pa.page_namespace as namespace, pa.page_title as title," .
34 - " pb.page_namespace as nsb, pb.page_title as tb," .
35 - " pc.page_namespace as nsc, pc.page_title as tc" .
36 - " FROM $redirect AS ra, $redirect AS rb, $page AS pa, $page AS pb, $page AS pc" .
37 - " WHERE ra.rd_from=pa.page_id" .
38 - " AND ra.rd_namespace=pb.page_namespace" .
39 - " AND ra.rd_title=pb.page_title" .
40 - " AND rb.rd_from=pb.page_id" .
41 - " AND rb.rd_namespace=pc.page_namespace" .
42 - " AND rb.rd_title=pc.page_title";
43 -
44 - if( $limitToTitle ) {
45 - $encTitle = $dbr->addQuotes( $title );
46 - $sql .= " AND pa.page_namespace=$namespace" .
47 - " AND pa.page_title=$encTitle";
 28+ $retval = array (
 29+ 'tables' => array ( 'redirect AS ra', 'redirect AS rb',
 30+ 'page AS pa', 'page AS pb',
 31+ 'page AS pc' ),
 32+ 'fields' => array ( '"{$this->getName()}" AS type',
 33+ 'pa.page_namespace AS namespace',
 34+ 'pa.page_title AS title',
 35+ 'pb.page_namespace AS nsb',
 36+ 'pb.page_title AS tb',
 37+ 'pc.page_namespace AS nsc',
 38+ 'pc.page_title AS tc' ),
 39+ 'conds' => array ( 'ra.rd_from = pa.page_id',
 40+ 'pb.page_namespace = ra.rd_namespace',
 41+ 'pb.page_title = rb.rd_title',
 42+ 'rb.rd_from = pb.page_id',
 43+ 'pc.page_namespace = rb.rd_namespace',
 44+ 'pc.page_title = rb.rd_title' )
 45+ );
 46+ if ( $limitToTitle ) {
 47+ $retval['conds']['pa.page_namespace'] = $namespace;
 48+ $retval['conds']['pa.page_title'] = $title;
4849 }
49 -
50 - return $sql;
 50+ return $retval;
5151 }
5252
53 - function getSQL() {
54 - $dbr = wfGetDB( DB_SLAVE );
55 - return $this->getSQLText( $dbr );
 53+ function getQueryInfo() {
 54+ return $this->reallyGetQueryInfo();
5655 }
5756
58 - function getOrder() {
59 - return '';
 57+ function getOrderFields() {
 58+ // FIXME: really?
 59+ return array ();
6060 }
6161
6262 function formatResult( $skin, $result ) {
6363 global $wgContLang;
6464
65 - $fname = 'DoubleRedirectsPage::formatResult';
6665 $titleA = Title::makeTitle( $result->namespace, $result->title );
6766
6867 if ( $result && !isset( $result->nsb ) ) {
6968 $dbr = wfGetDB( DB_SLAVE );
70 - $sql = $this->getSQLText( $dbr, $result->namespace, $result->title );
71 - $res = $dbr->query( $sql, $fname );
 69+ $qi = $this->reallyGetQueryInfo( $result->namespace,
 70+ $result->title );
 71+ $res = $dbr->select($qi['tables'], $qi['fields'],
 72+ $qi['conds'], __METHOD__ );
7273 if ( $res ) {
7374 $result = $dbr->fetchObject( $res );
7475 $dbr->freeResult( $res );
Index: branches/querypage-work/phase3/includes/specials/SpecialListredirects.php
@@ -14,19 +14,26 @@
1515 */
1616 class ListredirectsPage extends QueryPage {
1717
18 - function getName() { return( 'Listredirects' ); }
19 - function isExpensive() { return( true ); }
20 - function isSyndicated() { return( false ); }
21 - function sortDescending() { return( false ); }
 18+ function getName() { return 'Listredirects'; }
 19+ function isExpensive() { return true; }
 20+ function isSyndicated() { return false; }
 21+ function sortDescending() { return false; }
2222
23 - function getSQL() {
24 - $dbr = wfGetDB( DB_SLAVE );
25 - $page = $dbr->tableName( 'page' );
26 - $sql = "SELECT 'Listredirects' AS type, page_title AS title, page_namespace AS namespace,
27 - 0 AS value FROM $page WHERE page_is_redirect = 1";
28 - return( $sql );
 23+ function getQueryInfo() {
 24+ return array (
 25+ 'tables' => array ( 'page' ),
 26+ 'fields' => array ( "'{$this->getName()}' AS type",
 27+ 'page_namespace AS namespace',
 28+ 'page_title AS title' ),
 29+ 'conds' => array ( 'page_is_redirect' => 1 )
 30+ );
2931 }
3032
 33+ function getOrderFields() {
 34+ // FIXME: really?
 35+ return array ();
 36+ }
 37+
3138 function formatResult( $skin, $result ) {
3239 global $wgContLang;
3340
Index: branches/querypage-work/phase3/includes/specials/SpecialLinkSearch.php
@@ -117,35 +117,28 @@
118118 return $params;
119119 }
120120
121 - function getSQL() {
 121+ function getQueryInfo() {
122122 global $wgMiserMode;
123123 $dbr = wfGetDB( DB_SLAVE );
124 - $page = $dbr->tableName( 'page' );
125 - $externallinks = $dbr->tableName( 'externallinks' );
126 -
127 - /* strip everything past first wildcard, so that index-based-only lookup would be done */
128 - list( $munged, $clause ) = self::mungeQuery( $this->mQuery, $this->mProt );
129 - $stripped = substr($munged,0,strpos($munged,'%')+1);
 124+ // strip everything past first wildcard, so that
 125+ // index-based-only lookup would be done
 126+ list( $munged, $clause ) = self::mungeQuery( $this->mQuery,
 127+ $this->mProt );
 128+ $stripped = substr( $munged, 0, strpos( $munged, '%' ) + 1 );
130129 $encSearch = $dbr->addQuotes( $stripped );
131 -
132 - $encSQL = '';
133 - if ( isset ($this->mNs) && !$wgMiserMode )
134 - $encSQL = 'AND page_namespace=' . $dbr->addQuotes( $this->mNs );
135 -
136 - $use_index = $dbr->useIndexClause( $clause );
137 - return
138 - "SELECT
139 - page_namespace AS namespace,
140 - page_title AS title,
141 - el_index AS value,
142 - el_to AS url
143 - FROM
144 - $page,
145 - $externallinks $use_index
146 - WHERE
147 - page_id=el_from
148 - AND $clause LIKE $encSearch
149 - $encSQL";
 130+ $retval = array (
 131+ 'tables' => array ( 'page', 'externallinks' ),
 132+ 'fields' => array ( 'page_namespace AS namespace',
 133+ 'page_title AS title',
 134+ 'el_index AS value', 'el_to AS url' ),
 135+ 'conds' => array ( 'page_id = el_from',
 136+ "$clause LIKE $encSearch" ),
 137+ 'options' => array( 'USE INDEX' => $clause )
 138+ );
 139+ if ( isset( $this->mNs ) && !$wgMiserMode ) {
 140+ $retval['conds']['page_namespace'] = $this->mNs;
 141+ }
 142+ return $retval;
150143 }
151144
152145 function formatResult( $skin, $result ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialFewestrevisions.php
@@ -24,27 +24,28 @@
2525 return false;
2626 }
2727
28 - function getSql() {
29 - $dbr = wfGetDB( DB_SLAVE );
30 - list( $revision, $page ) = $dbr->tableNamesN( 'revision', 'page' );
31 -
32 - return "SELECT 'Fewestrevisions' as type,
33 - page_namespace as namespace,
34 - page_title as title,
35 - page_is_redirect as redirect,
36 - COUNT(*) as value
37 - FROM $revision
38 - JOIN $page ON page_id = rev_page
39 - WHERE page_namespace = " . NS_MAIN . "
40 - GROUP BY page_namespace, page_title, page_is_redirect
41 - HAVING COUNT(*) > 1";
 28+ function getQueryInfo() {
 29+ return array (
 30+ 'tables' => array ( 'revision', 'page' ),
 31+ 'fields' => array ( "'{$this->getName()}' AS type",
 32+ 'page_namespace AS namespace',
 33+ 'page_title AS title',
 34+ 'COUNT(*) AS value',
 35+ 'page_is_redirect AS redirect' ),
 36+ 'conds' => array ( 'page_namespace' => NS_MAIN,
 37+ 'page_id = rev_page' ),
 38+ 'options' => array ( 'HAVING' => 'COUNT(*) > 1',
4239 // ^^^ This was probably here to weed out redirects.
4340 // Since we mark them as such now, it might be
4441 // useful to remove this. People _do_ create pages
4542 // and never revise them, they aren't necessarily
4643 // redirects.
 44+ 'GROUP BY' => 'page_namespace, page_title' .
 45+ 'page_is_redirect' )
 46+ );
4747 }
4848
 49+
4950 function sortDescending() {
5051 return false;
5152 }
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedtemplates.php
@@ -7,7 +7,6 @@
88 /**
99 * A querypage to list the most wanted templates - implements Special:Wantedtemplates
1010 * based on SpecialWantedcategories.php by Ævar Arnfjörð Bjarmason <avarab@gmail.com>
11 - * makeWlhLink() taken from SpecialMostlinkedtemplates by Rob Church <robchur@gmail.com>
1211 *
1312 * @ingroup SpecialPage
1413 *
@@ -21,22 +20,21 @@
2221 return 'Wantedtemplates';
2322 }
2423
25 - function getSQL() {
26 - $dbr = wfGetDB( DB_SLAVE );
27 - list( $templatelinks, $page ) = $dbr->tableNamesN( 'templatelinks', 'page' );
28 - $name = $dbr->addQuotes( $this->getName() );
29 - return
30 - "
31 - SELECT $name as type,
32 - tl_namespace as namespace,
33 - tl_title as title,
34 - COUNT(*) as value
35 - FROM $templatelinks LEFT JOIN
36 - $page ON tl_title = page_title AND tl_namespace = page_namespace
37 - WHERE page_title IS NULL AND tl_namespace = ". NS_TEMPLATE ."
38 - GROUP BY tl_namespace, tl_title
39 - ";
40 - }
 24+ function getQueryInfo() {
 25+ return array (
 26+ 'tables' => array ( 'templatelinks', 'page' ),
 27+ 'fields' => array ( "'{$this->getName()}' AS type",
 28+ 'tl_namespace AS namespace',
 29+ 'tl_title AS title',
 30+ 'COUNT(*) AS value' ),
 31+ 'conds' => array ( 'page_title IS NULL',
 32+ 'tl_namespace' => NS_TEMPLATE ),
 33+ 'options' => array (
 34+ 'GROUP BY' => 'tl_namespace, tl_title' ),
 35+ 'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
 36+ array ( 'page_namespace = tl_namespace',
 37+ 'page_title = tl_title' ) ) )
 38+ );
4139 }
4240
4341 /**
Index: branches/querypage-work/phase3/includes/specials/SpecialMostrevisions.php
@@ -12,44 +12,10 @@
1313 /**
1414 * @ingroup SpecialPage
1515 */
16 -class MostrevisionsPage extends QueryPage {
17 -
18 - function getName() { return 'Mostrevisions'; }
19 - function isExpensive() { return true; }
20 - function isSyndicated() { return false; }
21 -
22 - function getSQL() {
23 - $dbr = wfGetDB( DB_SLAVE );
24 - list( $revision, $page ) = $dbr->tableNamesN( 'revision', 'page' );
25 - return
26 - "
27 - SELECT
28 - 'Mostrevisions' as type,
29 - page_namespace as namespace,
30 - page_title as title,
31 - COUNT(*) as value
32 - FROM $revision
33 - JOIN $page ON page_id = rev_page
34 - WHERE page_namespace = " . NS_MAIN . "
35 - GROUP BY page_namespace, page_title
36 - HAVING COUNT(*) > 1
37 - ";
 16+class MostrevisionsPage extends FewestrevisionsPage {
 17+ function sortDescending() {
 18+ return true;
3819 }
39 -
40 - function formatResult( $skin, $result ) {
41 - global $wgLang, $wgContLang;
42 -
43 - $nt = Title::makeTitle( $result->namespace, $result->title );
44 - $text = $wgContLang->convert( $nt->getPrefixedText() );
45 -
46 - $plink = $skin->makeKnownLinkObj( $nt, $text );
47 -
48 - $nl = wfMsgExt( 'nrevisions', array( 'parsemag', 'escape'),
49 - $wgLang->formatNum( $result->value ) );
50 - $nlink = $skin->makeKnownLinkObj( $nt, $nl, 'action=history' );
51 -
52 - return wfSpecialList($plink, $nlink);
53 - }
5420 }
5521
5622 /**
Index: branches/querypage-work/phase3/includes/specials/SpecialMostcategories.php
@@ -18,22 +18,20 @@
1919 function isExpensive() { return true; }
2020 function isSyndicated() { return false; }
2121
22 - function getSQL() {
23 - $dbr = wfGetDB( DB_SLAVE );
24 - list( $categorylinks, $page) = $dbr->tableNamesN( 'categorylinks', 'page' );
25 - return
26 - "
27 - SELECT
28 - 'Mostcategories' as type,
29 - page_namespace as namespace,
30 - page_title as title,
31 - COUNT(*) as value
32 - FROM $categorylinks
33 - LEFT JOIN $page ON cl_from = page_id
34 - WHERE page_namespace = " . NS_MAIN . "
35 - GROUP BY page_namespace, page_title
36 - HAVING COUNT(*) > 1
37 - ";
 22+ function getQueryInfo() {
 23+ return array (
 24+ 'tables' => array ( 'categorylinks', 'page' ),
 25+ 'fields' => array ( "'{$this->getName()}' AS name",
 26+ 'page_namespace AS namespace',
 27+ 'page_title AS title',
 28+ 'COUNT(*) AS value' ),
 29+ 'conds' => array ( 'page_namespace' => NS_MAIN ),
 30+ 'options' => array ( 'HAVING' => 'COUNT(*) > 1',
 31+ 'GROUP BY' => 'page_namespace, page_title' ),
 32+ // TODO: test this JOIN
 33+ 'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
 34+ 'page_id = cl_from' ) )
 35+ );
3836 }
3937
4038 function formatResult( $skin, $result ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialUnwatchedpages.php
@@ -19,21 +19,21 @@
2020 function isExpensive() { return true; }
2121 function isSyndicated() { return false; }
2222
23 - function getSQL() {
24 - $dbr = wfGetDB( DB_SLAVE );
25 - list( $page, $watchlist ) = $dbr->tableNamesN( 'page', 'watchlist' );
26 - $mwns = NS_MEDIAWIKI;
27 - return
28 - "
29 - SELECT
30 - 'Unwatchedpages' as type,
31 - page_namespace as namespace,
32 - page_title as title,
33 - page_namespace as value
34 - FROM $page
35 - LEFT JOIN $watchlist ON wl_namespace = page_namespace AND page_title = wl_title
36 - WHERE wl_title IS NULL AND page_is_redirect = 0 AND page_namespace<>$mwns
37 - ";
 23+ function getQueryInfo() {
 24+ return array (
 25+ 'tables' => array ( 'page', 'watchlist' ),
 26+ 'fields' => array ( "'{$this->getName()}' AS type",
 27+ 'page_namespace AS namespace',
 28+ 'page_title AS title',
 29+ 'page_namespace AS value' ),
 30+ 'conds' => array ( 'wl_title IS NULL',
 31+ 'page_is_redirect' => 0,
 32+ "page_namespace != '" . NS_MEDIAWIKI .
 33+ "'" ),
 34+ 'join_conds' => array ( 'watchlist' => array (
 35+ 'LEFT JOIN', array ( 'wl_title = page_title',
 36+ 'wl_namespace = page_namespace' ) ) )
 37+ );
3838 }
3939
4040 function sortDescending() { return false; }
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedfiles.php
@@ -19,22 +19,19 @@
2020 return 'Wantedfiles';
2121 }
2222
23 - function getSQL() {
24 - $dbr = wfGetDB( DB_SLAVE );
25 - list( $imagelinks, $page ) = $dbr->tableNamesN( 'imagelinks', 'page' );
26 - $name = $dbr->addQuotes( $this->getName() );
27 - return
28 - "
29 - SELECT
30 - $name as type,
31 - " . NS_FILE . " as namespace,
32 - il_to as title,
33 - COUNT(*) as value
34 - FROM $imagelinks
35 - LEFT JOIN $page ON il_to = page_title AND page_namespace = ". NS_FILE ."
36 - WHERE page_title IS NULL
37 - GROUP BY il_to
38 - ";
 23+ function getQueryInfo() {
 24+ return array (
 25+ 'tables' => array ( 'imagelinks', 'page' ),
 26+ 'fields' => array ( "'{$this->getName()}' AS type",
 27+ "'" . NS_FILE . "' AS namespace",
 28+ 'il_to AS title',
 29+ 'COUNT(*) AS value' ),
 30+ 'conds' => array ( 'page_title IS NULL' ),
 31+ 'options' => array ( 'GROUP BY' => 'il_to' ),
 32+ 'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
 33+ array ( 'il_to = page_title',
 34+ 'page_namespace' => NS_FILE ) ) )
 35+ );
3936 }
4037 }
4138
Index: branches/querypage-work/phase3/includes/specials/SpecialMostimages.php
@@ -18,20 +18,16 @@
1919 function isExpensive() { return true; }
2020 function isSyndicated() { return false; }
2121
22 - function getSQL() {
23 - $dbr = wfGetDB( DB_SLAVE );
24 - $imagelinks = $dbr->tableName( 'imagelinks' );
25 - return
26 - "
27 - SELECT
28 - 'Mostimages' as type,
29 - " . NS_FILE . " as namespace,
30 - il_to as title,
31 - COUNT(*) as value
32 - FROM $imagelinks
33 - GROUP BY il_to
34 - HAVING COUNT(*) > 1
35 - ";
 22+ function getQueryInfo() {
 23+ return array (
 24+ 'tables' => array ( 'imagelinks' ),
 25+ 'fields' => array ( "'{$this->getName()}' AS type",
 26+ "'" . NS_FILE . "' AS namespace",
 27+ 'il_to AS title',
 28+ 'COUNT(*) AS value' ),
 29+ 'options' => array ( 'GROUP BY' => 'il_to',
 30+ 'HAVING' => 'COUNT(*) > 1' )
 31+ );
3632 }
3733
3834 function getCellHtml( $row ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialLonelypages.php
@@ -27,25 +27,29 @@
2828 }
2929 function isSyndicated() { return false; }
3030
31 - function getSQL() {
32 - $dbr = wfGetDB( DB_SLAVE );
33 - list( $page, $pagelinks, $templatelinks ) = $dbr->tableNamesN( 'page', 'pagelinks', 'templatelinks' );
34 -
35 - return
36 - "SELECT 'Lonelypages' AS type,
37 - page_namespace AS namespace,
38 - page_title AS title,
39 - page_title AS value
40 - FROM $page
41 - LEFT JOIN $pagelinks
42 - ON page_namespace=pl_namespace AND page_title=pl_title
43 - LEFT JOIN $templatelinks
44 - ON page_namespace=tl_namespace AND page_title=tl_title
45 - WHERE pl_namespace IS NULL
46 - AND page_namespace=".NS_MAIN."
47 - AND page_is_redirect=0
48 - AND tl_namespace IS NULL";
49 -
 31+ function getQueryInfo() {
 32+ return array (
 33+ 'tables' => array ( 'page', 'pagelinks',
 34+ 'templatelinks' ),
 35+ 'fields' => array ( "'{$this->getName()}' AS type",
 36+ 'page_namespace AS namespace',
 37+ 'page_title AS title',
 38+ 'page_title AS value' ),
 39+ 'conds' => array ( 'pl_namespace IS NULL',
 40+ 'page_namespace' => NS_MAIN,
 41+ 'page_is_redirect' => 0,
 42+ 'tl_namespace IS NULL' ),
 43+ // TODO: test this JOIN
 44+ 'join_conds' => array (
 45+ 'pagelinks' => array (
 46+ 'LEFT JOIN', array (
 47+ 'pl_namespace = page_namespace',
 48+ 'pl_title = page_title' ) ),
 49+ 'templatelinks' => array (
 50+ 'LEFT JOIN', array (
 51+ 'tl_namespace = page_namespace',
 52+ 'tl_title = page_title' ) ) )
 53+ );
5054 }
5155 }
5256
Index: branches/querypage-work/phase3/includes/specials/SpecialUncategorizedpages.php
@@ -8,6 +8,7 @@
99 * A special page looking for page without any category.
1010 * @ingroup SpecialPage
1111 */
 12+// FIXME: Make $requestedNamespace selectable, unify all subclasses into one
1213 class UncategorizedPagesPage extends PageQueryPage {
1314 var $requestedNamespace = NS_MAIN;
1415
@@ -24,22 +25,19 @@
2526 }
2627 function isSyndicated() { return false; }
2728
28 - function getSQL() {
29 - $dbr = wfGetDB( DB_SLAVE );
30 - list( $page, $categorylinks ) = $dbr->tableNamesN( 'page', 'categorylinks' );
31 - $name = $dbr->addQuotes( $this->getName() );
32 -
33 - return
34 - "
35 - SELECT
36 - $name as type,
37 - page_namespace AS namespace,
38 - page_title AS title,
39 - page_title AS value
40 - FROM $page
41 - LEFT JOIN $categorylinks ON page_id=cl_from
42 - WHERE cl_from IS NULL AND page_namespace={$this->requestedNamespace} AND page_is_redirect=0
43 - ";
 29+ function getQueryInfo() {
 30+ return array (
 31+ 'tables' => array ( 'page', 'categorylinks' ),
 32+ 'fields' => array ( "'{$this->getName()}' AS type",
 33+ 'page_namespace AS namespace',
 34+ 'page_title AS title',
 35+ 'page_title AS value' ),
 36+ 'conds' => array ( 'cl_from IS NULL',
 37+ 'page_namespace' => $this->requestedNamespace,
 38+ 'page_is_redirect' => 0 ),
 39+ 'join_conds' => array ( 'categorylinks' => array (
 40+ 'LEFT JOIN', 'cl_from = page_id' ) )
 41+ );
4442 }
4543 }
4644
Index: branches/querypage-work/phase3/includes/specials/SpecialMostlinkedtemplates.php
@@ -49,22 +49,16 @@
5050 return true;
5151 }
5252
53 - /**
54 - * Generate SQL for the report
55 - *
56 - * @return string
57 - */
58 - public function getSql() {
59 - $dbr = wfGetDB( DB_SLAVE );
60 - $templatelinks = $dbr->tableName( 'templatelinks' );
61 - $name = $dbr->addQuotes( $this->getName() );
62 - return "SELECT {$name} AS type,
63 - " . NS_TEMPLATE . " AS namespace,
64 - tl_title AS title,
65 - COUNT(*) AS value
66 - FROM {$templatelinks}
67 - WHERE tl_namespace = " . NS_TEMPLATE . "
68 - GROUP BY tl_title";
 53+ public function getQueryInfo() {
 54+ return array (
 55+ 'tables' => array ( 'templatelinks' ),
 56+ 'fields' => array ( "'{$this->getName()}' AS type",
 57+ 'tl_namespace AS namespace',
 58+ 'tl_title AS title',
 59+ 'COUNT(*) AS value' ),
 60+ 'conds' => array ( 'tl_namespace' => NS_TEMPLATE' ),
 61+ 'options' => array( 'GROUP BY' => 'tl_title' )
 62+ );
6963 }
7064
7165 /**
Index: branches/querypage-work/phase3/includes/specials/SpecialUnusedcategories.php
@@ -19,17 +19,19 @@
2020 return wfMsgExt( 'unusedcategoriestext', array( 'parse' ) );
2121 }
2222
23 - function getSQL() {
24 - $NScat = NS_CATEGORY;
25 - $dbr = wfGetDB( DB_SLAVE );
26 - list( $categorylinks, $page ) = $dbr->tableNamesN( 'categorylinks', 'page' );
27 - return "SELECT 'Unusedcategories' as type,
28 - {$NScat} as namespace, page_title as title, page_title as value
29 - FROM $page
30 - LEFT JOIN $categorylinks ON page_title=cl_to
31 - WHERE cl_from IS NULL
32 - AND page_namespace = {$NScat}
33 - AND page_is_redirect = 0";
 23+ function getQueryInfo() {
 24+ return array (
 25+ 'tables' => array ( 'page', 'categorylinks' ),
 26+ 'fields' => array ( "'{$this->getName()}' AS type",
 27+ 'page_namespace AS namespace',
 28+ 'page_title AS title',
 29+ 'page_title AS value' ),
 30+ 'conds' => array ( 'cl_from IS NULL',
 31+ 'page_namespace' => NS_CATEGORY,
 32+ 'page_is_redirect' => 0 ),
 33+ 'join_conds' => array ( 'categorylinks' => array (
 34+ 'LEFT JOIN', 'cl_to = page_title' ) )
 35+ );
3436 }
3537
3638 function formatResult( $skin, $result ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialShortpages.php
@@ -17,6 +17,7 @@
1818
1919 /**
2020 * This query is indexed as of 1.5
 21+ * FIXME: Mark as inexpensive
2122 */
2223 function isExpensive() {
2324 return true;
@@ -26,27 +27,19 @@
2728 return false;
2829 }
2930
30 - function getSQL() {
 31+ function getQueryInfo() {
3132 global $wgContentNamespaces;
32 -
33 - $dbr = wfGetDB( DB_SLAVE );
34 - $page = $dbr->tableName( 'page' );
35 - $name = $dbr->addQuotes( $this->getName() );
36 -
37 - $forceindex = $dbr->useIndexClause("page_len");
38 -
39 - if ($wgContentNamespaces)
40 - $nsclause = "page_namespace IN (" . $dbr->makeList($wgContentNamespaces) . ")";
41 - else
42 - $nsclause = "page_namespace = " . NS_MAIN;
43 -
44 - return
45 - "SELECT $name as type,
46 - page_namespace as namespace,
47 - page_title as title,
48 - page_len AS value
49 - FROM $page $forceindex
50 - WHERE $nsclause AND page_is_redirect=0";
 33+ $ns = ( $wgContentNamespaces ? $wgContentNamespaces : NS_MAIN );
 34+ return array (
 35+ 'tables' => array ( 'page' ),
 36+ 'fields' => array ( "'{$this->getName()}' AS type",
 37+ 'page_namespace AS namespace',
 38+ 'page_title AS title',
 39+ 'page_len AS value' ),
 40+ 'conds' => array ( 'page_namespace' => $ns,
 41+ 'page_is_redirect' => 0 ),
 42+ 'options' => array ( 'USE INDEX' => 'page_len' )
 43+ );
5144 }
5245
5346 function preprocessResults( $db, $res ) {
Index: branches/querypage-work/phase3/includes/specials/SpecialUnusedtemplates.php
@@ -18,17 +18,20 @@
1919 function isSyndicated() { return false; }
2020 function sortDescending() { return false; }
2121
22 - function getSQL() {
23 - $dbr = wfGetDB( DB_SLAVE );
24 - list( $page, $templatelinks) = $dbr->tableNamesN( 'page', 'templatelinks' );
25 - $sql = "SELECT 'Unusedtemplates' AS type, page_title AS title,
26 - page_namespace AS namespace, 0 AS value
27 - FROM $page
28 - LEFT JOIN $templatelinks
29 - ON page_namespace = tl_namespace AND page_title = tl_title
30 - WHERE page_namespace = 10 AND tl_from IS NULL
31 - AND page_is_redirect = 0";
32 - return $sql;
 22+ function getQueryInfo() {
 23+ return array (
 24+ 'tables' => array ( 'page', 'templatelinks' ),
 25+ 'fields' => array ( "'{$this->getName()}' AS type",
 26+ 'page_namespace AS namespace',
 27+ 'page_title AS title',
 28+ '0 AS value' ),
 29+ 'conds' => array ( 'page_namespace' => NS_TEMPLATE,
 30+ 'tl_from IS NULL',
 31+ 'page_redirect' => 0 ),
 32+ 'join_conds' => array ( 'templatelinks' => array (
 33+ 'LEFT JOIN', array ( 'tl_title = page_title',
 34+ 'tl_namespace = page_namespace' ) ) )
 35+ );
3336 }
3437
3538 function formatResult( $skin, $result ) {
Index: branches/querypage-work/TODO
@@ -0,0 +1,12 @@
 2+* Test JOINs using table aliases
 3+* Make INNER JOIN implicit in Unusedimages?
 4+* Find and migrate code using WantedPages::getSQL hook
 5+* Check sorting sanity
 6+** Check whether sorts are efficient and page right
 7+** Check whether sorting by nothing is really what we want
 8+** Check whether selecting title or ns AS value is really what we want
 9+* Replace $result->type with getName(), remove type from queries
 10+* Mark ShortPages as inexpensive
 11+* Reuse UncategorizedPages code in UncategorizedImages somehow
 12+* Make UncategorizedPages parameterized by namespace
 13+
Property changes on: branches/querypage-work/TODO
___________________________________________________________________
Added: svn:eol-style
114 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r65317querypage-work2: Merge r49631reedy14:17, 20 April 2010

Status & tagging log