Index: trunk/phase3/maintenance/archives/patch-cl_type.sql |
— | — | @@ -0,0 +1,6 @@ |
| 2 | +-- |
| 3 | +-- Change cl_type to a varchar from an enum because of the weird semantics of |
| 4 | +-- the < and > operators when working with enums |
| 5 | +-- |
| 6 | + |
| 7 | +ALTER TABLE /*_*/categorylinks MODIFY cl_type varchar(6) NOT NULL default 'page'; |
Property changes on: trunk/phase3/maintenance/archives/patch-cl_type.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 8 | + native |
Index: trunk/phase3/maintenance/tables.sql |
— | — | @@ -521,7 +521,9 @@ |
522 | 522 | -- paginate the three categories separately. This never has to be updated |
523 | 523 | -- after the page is created, since none of these page types can be moved to |
524 | 524 | -- any other. |
525 | | - cl_type ENUM('page', 'subcat', 'file') NOT NULL default 'page' |
| 525 | + -- This used to be ENUM('page', 'subcat', 'file') but was changed to a |
| 526 | + -- varchar because of the weird semantics of < and > when used on enums |
| 527 | + cl_type varchar(6) NOT NULL default 'page' |
526 | 528 | ) /*$wgDBTableOptions*/; |
527 | 529 | |
528 | 530 | CREATE UNIQUE INDEX /*i*/cl_from ON /*_*/categorylinks (cl_from,cl_to); |
Index: trunk/phase3/includes/installer/MysqlUpdater.php |
— | — | @@ -175,6 +175,7 @@ |
176 | 176 | array( 'dropIndex', 'archive', 'ar_page_revid', 'patch-archive_kill_ar_page_revid.sql' ), |
177 | 177 | array( 'addIndex', 'archive', 'ar_revid', 'patch-archive_ar_revid.sql' ), |
178 | 178 | array( 'doLangLinksLengthUpdate' ), |
| 179 | + array( 'doClTypeVarcharUpdate' ), |
179 | 180 | ); |
180 | 181 | } |
181 | 182 | |
— | — | @@ -828,4 +829,18 @@ |
829 | 830 | $this->output( "...ll_lang is up-to-date.\n" ); |
830 | 831 | } |
831 | 832 | } |
| 833 | + |
| 834 | + protected function doClTypeVarcharUpdate() { |
| 835 | + $categorylinks = $this->db->tableName( 'categorylinks' ); |
| 836 | + $res = $this->db->query( "SHOW COLUMNS FROM $categorylinks LIKE 'cl_type'" ); |
| 837 | + $row = $this->db->fetchObject( $res ); |
| 838 | + |
| 839 | + if ( $row && substr( $row->Type, 0, 4 ) == 'enum' ) { |
| 840 | + $this->output( 'Changing cl_type from enum to varchar...' ); |
| 841 | + $this->applyPatch( 'patch-cl_type.sql' ); |
| 842 | + $this->output( "done.\n" ); |
| 843 | + } else { |
| 844 | + $this->output( "...cl_type is up-to-date.\n" ); |
| 845 | + } |
| 846 | + } |
832 | 847 | } |
Index: trunk/phase3/includes/api/ApiQueryCategoryMembers.php |
— | — | @@ -122,39 +122,27 @@ |
123 | 123 | $this->addOption( 'USE INDEX', 'cl_timestamp' ); |
124 | 124 | } else { |
125 | 125 | if ( $params['continue'] ) { |
126 | | - // from|sortkey |
127 | | - $cont = explode( '|', $params['continue'], 2 ); |
128 | | - if ( count( $cont ) != 2 ) { |
| 126 | + // type|from|sortkey |
| 127 | + $cont = explode( '|', $params['continue'], 3 ); |
| 128 | + if ( count( $cont ) != 3 ) { |
129 | 129 | $this->dieUsage( 'Invalid continue param. You should pass the original value returned '. |
130 | 130 | 'by the previous query', '_badcontinue' |
131 | 131 | ); |
132 | 132 | } |
133 | | - list ( $from, $contsortkey ) = $cont; |
134 | | - if ( intval( $from ) == 0 ) { |
135 | | - $this->dieUsage( 'Invalid continue param. You should pass the original value returned '. |
136 | | - 'by the previous query', '_badcontinue' |
137 | | - ); |
138 | | - } |
139 | | - $where_outer = array(); |
140 | | - $where_inner = array(); |
141 | | - $db = $this->getDB(); |
142 | | - $op = ( $dir === 'newer' ? '>' : '<' ); |
143 | | - $sortdir = ( $dir === 'newer' ? 'asc' : 'desc' ); |
144 | | - $where_outer[] = 'cl_sortkey ' . $op . ' ' . |
145 | | - $db->addQuotes( $contsortkey ); |
146 | | - // OR |
147 | | - $where_inner[] = 'cl_sortkey = ' . |
148 | | - $db->addQuotes( $contsortkey ); |
149 | | - // AND |
150 | | - $where_inner[] = 'cl_from ' . $op . '= '. $from; |
151 | | - |
152 | | - $where_outer[] = $db->makeList( $where_inner, LIST_AND ); |
153 | | - $this->addWhere( $db->makeList( $where_outer, LIST_OR ) ); |
154 | | - $this->addOption( 'ORDER BY', |
155 | | - 'cl_sortkey ' . $sortdir .', cl_from ' . $sortdir ); |
| 133 | + $escType = $this->getDB()->addQuotes( $cont[0] ); |
| 134 | + $from = intval( $cont[1] ); |
| 135 | + $escSortkey = $this->getDB()->addQuotes( $cont[2] ); |
| 136 | + $op = $dir == 'newer' ? '>' : '<'; |
| 137 | + $this->addWhere( "cl_type $op $escType OR " . |
| 138 | + "(cl_type = $escType AND " . |
| 139 | + "(cl_sortkey $op $escSortkey OR " . |
| 140 | + "(cl_sortkey = $escSortkey AND " . |
| 141 | + "cl_from $op= $from)))" |
| 142 | + ); |
156 | 143 | |
157 | 144 | } else { |
158 | | - // The below produces ORDER BY cl_sortkey, cl_from, possibly with DESC added to each of them |
| 145 | + // The below produces ORDER BY cl_type, cl_sortkey, cl_from, possibly with DESC added to each of them |
| 146 | + $this->addWhereRange( 'cl_type', $dir, null, null ); |
159 | 147 | $this->addWhereRange( 'cl_sortkey', |
160 | 148 | $dir, |
161 | 149 | $params['startsortkey'], |
— | — | @@ -183,7 +171,7 @@ |
184 | 172 | // because we don't have to worry about pipes in the sortkey that way |
185 | 173 | // (and type and from can't contain pipes anyway) |
186 | 174 | $this->setContinueEnumParameter( 'continue', |
187 | | - "{$row->cl_from}|{$row->cl_sortkey}" |
| 175 | + "{$row->cl_type}|{$row->cl_from}|{$row->cl_sortkey}" |
188 | 176 | ); |
189 | 177 | } |
190 | 178 | break; |
— | — | @@ -225,7 +213,7 @@ |
226 | 214 | $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->cl_timestamp ) ); |
227 | 215 | } else { |
228 | 216 | $this->setContinueEnumParameter( 'continue', |
229 | | - "{$row->cl_from}|{$row->cl_sortkey}" |
| 217 | + "{$row->cl_type}|{$row->cl_from}|{$row->cl_sortkey}" |
230 | 218 | ); |
231 | 219 | } |
232 | 220 | break; |