Index: branches/querypage-work/phase3/includes/QueryPage.php |
— | — | @@ -87,8 +87,8 @@ |
88 | 88 | |
89 | 89 | /** |
90 | 90 | * 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. |
93 | 93 | */ |
94 | 94 | function getName() { |
95 | 95 | return ''; |
— | — | @@ -119,8 +119,8 @@ |
120 | 120 | * These may be stored in the querycache table for expensive queries, |
121 | 121 | * and that cached data will be returned sometimes, so the presence of |
122 | 122 | * 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()). |
125 | 125 | * |
126 | 126 | * Don't include an ORDER or LIMIT clause, they will be added |
127 | 127 | * @return array |
— | — | @@ -138,6 +138,19 @@ |
139 | 139 | } |
140 | 140 | |
141 | 141 | /** |
| 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 | + /** |
142 | 155 | * Override to sort by increasing values |
143 | 156 | */ |
144 | 157 | function sortDescending() { |
— | — | @@ -242,7 +255,12 @@ |
243 | 256 | $vals = array(); |
244 | 257 | while ( $res && $row = $dbr->fetchObject( $res ) ) { |
245 | 258 | 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 | + } |
247 | 265 | } else { |
248 | 266 | $value = 0; |
249 | 267 | } |
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedcategories.php |
— | — | @@ -19,22 +19,19 @@ |
20 | 20 | return 'Wantedcategories'; |
21 | 21 | } |
22 | 22 | |
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 | + ); |
39 | 36 | } |
40 | 37 | |
41 | 38 | function formatResult( $skin, $result ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialWithoutinterwiki.php |
— | — | @@ -50,22 +50,23 @@ |
51 | 51 | return false; |
52 | 52 | } |
53 | 53 | |
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; |
70 | 71 | } |
71 | 72 | |
72 | 73 | function setPrefix( $prefix = '' ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialUnusedimages.php |
— | — | @@ -21,32 +21,41 @@ |
22 | 22 | } |
23 | 23 | function isSyndicated() { return false; } |
24 | 24 | |
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 | + ); |
33 | 39 | 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' ); |
48 | 52 | } |
| 53 | + return $retval; |
49 | 54 | } |
50 | 55 | |
| 56 | + function usesTimestamps() { |
| 57 | + return true; |
| 58 | + } |
| 59 | + |
51 | 60 | function getPageHeader() { |
52 | 61 | return wfMsgExt( 'unusedimagestext', array( 'parse' ) ); |
53 | 62 | } |
Index: branches/querypage-work/phase3/includes/specials/SpecialUncategorizedimages.php |
— | — | @@ -10,6 +10,7 @@ |
11 | 11 | /** |
12 | 12 | * @ingroup SpecialPage |
13 | 13 | */ |
| 14 | +// FIXME: Use an instance of UncategorizedPagesPage or something |
14 | 15 | class UncategorizedImagesPage extends ImageQueryPage { |
15 | 16 | |
16 | 17 | function getName() { |
Index: branches/querypage-work/phase3/includes/specials/SpecialAncientpages.php |
— | — | @@ -21,24 +21,23 @@ |
22 | 22 | function isSyndicated() { return false; } |
23 | 23 | |
24 | 24 | function getQueryInfo() { |
25 | | - // FIXME convert timestamps elsewhere |
26 | | - // Possibly add bool returnsTimestamps() |
27 | 25 | // FIXME standardize 'name' AS type ? |
28 | | - global $wgDBtype; |
29 | | - $epoch = $wgDBtype == 'mysql' ? 'UNIX_TIMESTAMP(rev_timestamp)' : |
30 | | - 'EXTRACT(epoch FROM rev_timestamp)'; |
31 | 26 | return array( |
32 | 27 | 'tables' => array( 'page', 'revision' ), |
33 | 28 | 'fields' => array( "'{$this->getName()}' AS type", |
34 | 29 | 'page_namespace AS namespace', |
35 | 30 | 'page_title AS title', |
36 | | - "$epoch AS value" ), |
| 31 | + 'rev_timestamp AS value' ), |
37 | 32 | 'conds' => array( 'page_namespace' => NS_MAIN, |
38 | 33 | 'page_is_redirect' => 0, |
39 | 34 | 'page_latest=rev_id' ) |
40 | 35 | ); |
41 | 36 | } |
42 | 37 | |
| 38 | + function usesTimestamps() { |
| 39 | + return true; |
| 40 | + } |
| 41 | + |
43 | 42 | function sortDescending() { |
44 | 43 | return false; |
45 | 44 | } |
— | — | @@ -49,7 +48,7 @@ |
50 | 49 | $d = $wgLang->timeanddate( wfTimestamp( TS_MW, $result->value ), true ); |
51 | 50 | $title = Title::makeTitle( $result->namespace, $result->title ); |
52 | 51 | $link = $skin->makeKnownLinkObj( $title, htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) ); |
53 | | - return wfSpecialList($link, $d); |
| 52 | + return wfSpecialList( $link, $d ); |
54 | 53 | } |
55 | 54 | } |
56 | 55 | |
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedpages.php |
— | — | @@ -44,6 +44,37 @@ |
45 | 45 | wfRunHooks( 'WantedPages::getSQL', array( &$this, &$sql ) ); |
46 | 46 | return $sql; |
47 | 47 | } |
| 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 | + } |
48 | 79 | } |
49 | 80 | |
50 | 81 | /** |
Index: branches/querypage-work/phase3/includes/specials/SpecialMostlinked.php |
— | — | @@ -25,19 +25,21 @@ |
26 | 26 | /** |
27 | 27 | * Note: Getting page_namespace only works if $this->isCached() is false |
28 | 28 | */ |
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 | + ); |
42 | 44 | } |
43 | 45 | |
44 | 46 | /** |
Index: branches/querypage-work/phase3/includes/specials/SpecialMostlinkedcategories.php |
— | — | @@ -19,20 +19,15 @@ |
20 | 20 | function isExpensive() { return true; } |
21 | 21 | function isSyndicated() { return false; } |
22 | 22 | |
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 | + ); |
37 | 32 | } |
38 | 33 | |
39 | 34 | function sortDescending() { return true; } |
Index: branches/querypage-work/phase3/includes/specials/SpecialDoubleRedirects.php |
— | — | @@ -22,52 +22,53 @@ |
23 | 23 | return wfMsgExt( 'doubleredirectstext', array( 'parse' ) ); |
24 | 24 | } |
25 | 25 | |
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) { |
30 | 27 | $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; |
48 | 49 | } |
49 | | - |
50 | | - return $sql; |
| 50 | + return $retval; |
51 | 51 | } |
52 | 52 | |
53 | | - function getSQL() { |
54 | | - $dbr = wfGetDB( DB_SLAVE ); |
55 | | - return $this->getSQLText( $dbr ); |
| 53 | + function getQueryInfo() { |
| 54 | + return $this->reallyGetQueryInfo(); |
56 | 55 | } |
57 | 56 | |
58 | | - function getOrder() { |
59 | | - return ''; |
| 57 | + function getOrderFields() { |
| 58 | + // FIXME: really? |
| 59 | + return array (); |
60 | 60 | } |
61 | 61 | |
62 | 62 | function formatResult( $skin, $result ) { |
63 | 63 | global $wgContLang; |
64 | 64 | |
65 | | - $fname = 'DoubleRedirectsPage::formatResult'; |
66 | 65 | $titleA = Title::makeTitle( $result->namespace, $result->title ); |
67 | 66 | |
68 | 67 | if ( $result && !isset( $result->nsb ) ) { |
69 | 68 | $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__ ); |
72 | 73 | if ( $res ) { |
73 | 74 | $result = $dbr->fetchObject( $res ); |
74 | 75 | $dbr->freeResult( $res ); |
Index: branches/querypage-work/phase3/includes/specials/SpecialListredirects.php |
— | — | @@ -14,19 +14,26 @@ |
15 | 15 | */ |
16 | 16 | class ListredirectsPage extends QueryPage { |
17 | 17 | |
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; } |
22 | 22 | |
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 | + ); |
29 | 31 | } |
30 | 32 | |
| 33 | + function getOrderFields() { |
| 34 | + // FIXME: really? |
| 35 | + return array (); |
| 36 | + } |
| 37 | + |
31 | 38 | function formatResult( $skin, $result ) { |
32 | 39 | global $wgContLang; |
33 | 40 | |
Index: branches/querypage-work/phase3/includes/specials/SpecialLinkSearch.php |
— | — | @@ -117,35 +117,28 @@ |
118 | 118 | return $params; |
119 | 119 | } |
120 | 120 | |
121 | | - function getSQL() { |
| 121 | + function getQueryInfo() { |
122 | 122 | global $wgMiserMode; |
123 | 123 | $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 ); |
130 | 129 | $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; |
150 | 143 | } |
151 | 144 | |
152 | 145 | function formatResult( $skin, $result ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialFewestrevisions.php |
— | — | @@ -24,27 +24,28 @@ |
25 | 25 | return false; |
26 | 26 | } |
27 | 27 | |
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', |
42 | 39 | // ^^^ This was probably here to weed out redirects. |
43 | 40 | // Since we mark them as such now, it might be |
44 | 41 | // useful to remove this. People _do_ create pages |
45 | 42 | // and never revise them, they aren't necessarily |
46 | 43 | // redirects. |
| 44 | + 'GROUP BY' => 'page_namespace, page_title' . |
| 45 | + 'page_is_redirect' ) |
| 46 | + ); |
47 | 47 | } |
48 | 48 | |
| 49 | + |
49 | 50 | function sortDescending() { |
50 | 51 | return false; |
51 | 52 | } |
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedtemplates.php |
— | — | @@ -7,7 +7,6 @@ |
8 | 8 | /** |
9 | 9 | * A querypage to list the most wanted templates - implements Special:Wantedtemplates |
10 | 10 | * based on SpecialWantedcategories.php by Ævar Arnfjörð Bjarmason <avarab@gmail.com> |
11 | | - * makeWlhLink() taken from SpecialMostlinkedtemplates by Rob Church <robchur@gmail.com> |
12 | 11 | * |
13 | 12 | * @ingroup SpecialPage |
14 | 13 | * |
— | — | @@ -21,22 +20,21 @@ |
22 | 21 | return 'Wantedtemplates'; |
23 | 22 | } |
24 | 23 | |
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 | + ); |
41 | 39 | } |
42 | 40 | |
43 | 41 | /** |
Index: branches/querypage-work/phase3/includes/specials/SpecialMostrevisions.php |
— | — | @@ -12,44 +12,10 @@ |
13 | 13 | /** |
14 | 14 | * @ingroup SpecialPage |
15 | 15 | */ |
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; |
38 | 19 | } |
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 | | - } |
54 | 20 | } |
55 | 21 | |
56 | 22 | /** |
Index: branches/querypage-work/phase3/includes/specials/SpecialMostcategories.php |
— | — | @@ -18,22 +18,20 @@ |
19 | 19 | function isExpensive() { return true; } |
20 | 20 | function isSyndicated() { return false; } |
21 | 21 | |
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 | + ); |
38 | 36 | } |
39 | 37 | |
40 | 38 | function formatResult( $skin, $result ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialUnwatchedpages.php |
— | — | @@ -19,21 +19,21 @@ |
20 | 20 | function isExpensive() { return true; } |
21 | 21 | function isSyndicated() { return false; } |
22 | 22 | |
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 | + ); |
38 | 38 | } |
39 | 39 | |
40 | 40 | function sortDescending() { return false; } |
Index: branches/querypage-work/phase3/includes/specials/SpecialWantedfiles.php |
— | — | @@ -19,22 +19,19 @@ |
20 | 20 | return 'Wantedfiles'; |
21 | 21 | } |
22 | 22 | |
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 | + ); |
39 | 36 | } |
40 | 37 | } |
41 | 38 | |
Index: branches/querypage-work/phase3/includes/specials/SpecialMostimages.php |
— | — | @@ -18,20 +18,16 @@ |
19 | 19 | function isExpensive() { return true; } |
20 | 20 | function isSyndicated() { return false; } |
21 | 21 | |
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 | + ); |
36 | 32 | } |
37 | 33 | |
38 | 34 | function getCellHtml( $row ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialLonelypages.php |
— | — | @@ -27,25 +27,29 @@ |
28 | 28 | } |
29 | 29 | function isSyndicated() { return false; } |
30 | 30 | |
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 | + ); |
50 | 54 | } |
51 | 55 | } |
52 | 56 | |
Index: branches/querypage-work/phase3/includes/specials/SpecialUncategorizedpages.php |
— | — | @@ -8,6 +8,7 @@ |
9 | 9 | * A special page looking for page without any category. |
10 | 10 | * @ingroup SpecialPage |
11 | 11 | */ |
| 12 | +// FIXME: Make $requestedNamespace selectable, unify all subclasses into one |
12 | 13 | class UncategorizedPagesPage extends PageQueryPage { |
13 | 14 | var $requestedNamespace = NS_MAIN; |
14 | 15 | |
— | — | @@ -24,22 +25,19 @@ |
25 | 26 | } |
26 | 27 | function isSyndicated() { return false; } |
27 | 28 | |
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 | + ); |
44 | 42 | } |
45 | 43 | } |
46 | 44 | |
Index: branches/querypage-work/phase3/includes/specials/SpecialMostlinkedtemplates.php |
— | — | @@ -49,22 +49,16 @@ |
50 | 50 | return true; |
51 | 51 | } |
52 | 52 | |
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 | + ); |
69 | 63 | } |
70 | 64 | |
71 | 65 | /** |
Index: branches/querypage-work/phase3/includes/specials/SpecialUnusedcategories.php |
— | — | @@ -19,17 +19,19 @@ |
20 | 20 | return wfMsgExt( 'unusedcategoriestext', array( 'parse' ) ); |
21 | 21 | } |
22 | 22 | |
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 | + ); |
34 | 36 | } |
35 | 37 | |
36 | 38 | function formatResult( $skin, $result ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialShortpages.php |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | |
19 | 19 | /** |
20 | 20 | * This query is indexed as of 1.5 |
| 21 | + * FIXME: Mark as inexpensive |
21 | 22 | */ |
22 | 23 | function isExpensive() { |
23 | 24 | return true; |
— | — | @@ -26,27 +27,19 @@ |
27 | 28 | return false; |
28 | 29 | } |
29 | 30 | |
30 | | - function getSQL() { |
| 31 | + function getQueryInfo() { |
31 | 32 | 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 | + ); |
51 | 44 | } |
52 | 45 | |
53 | 46 | function preprocessResults( $db, $res ) { |
Index: branches/querypage-work/phase3/includes/specials/SpecialUnusedtemplates.php |
— | — | @@ -18,17 +18,20 @@ |
19 | 19 | function isSyndicated() { return false; } |
20 | 20 | function sortDescending() { return false; } |
21 | 21 | |
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 | + ); |
33 | 36 | } |
34 | 37 | |
35 | 38 | 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 |
1 | 14 | + native |