Index: trunk/phase3/includes/search/SearchMySQL.php |
— | — | @@ -171,12 +171,24 @@ |
172 | 172 | protected function searchInternal( $term, $fulltext ) { |
173 | 173 | global $wgCountTotalSearchHits; |
174 | 174 | |
| 175 | + // This seems of place, why is this called with empty term? |
| 176 | + if ( trim( $term ) === '' ) return null; |
| 177 | + |
175 | 178 | $filteredTerm = $this->filter( $term ); |
176 | | - $resultSet = $this->db->query( $this->getQuery( $filteredTerm, $fulltext ) ); |
| 179 | + $query = $this->getQuery( $filteredTerm, $fulltext ); |
| 180 | + $resultSet = $this->db->select( |
| 181 | + $query['tables'], $query['fields'], $query['conds'], |
| 182 | + __METHOD__, $query['options'], $query['joins'] |
| 183 | + ); |
177 | 184 | |
178 | 185 | $total = null; |
179 | 186 | if( $wgCountTotalSearchHits ) { |
180 | | - $totalResult = $this->db->query( $this->getCountQuery( $filteredTerm, $fulltext ) ); |
| 187 | + $query = $this->getCountQuery( $filteredTerm, $fulltext ); |
| 188 | + $totalResult = $this->db->select( |
| 189 | + $query['tables'], $query['fields'], $query['conds'], |
| 190 | + __METHOD__, $query['options'], $query['joins'] |
| 191 | + ); |
| 192 | + |
181 | 193 | $row = $totalResult->fetchObject(); |
182 | 194 | if( $row ) { |
183 | 195 | $total = intval( $row->c ); |
— | — | @@ -189,73 +201,62 @@ |
190 | 202 | |
191 | 203 | |
192 | 204 | /** |
193 | | - * Return a partial WHERE clause to exclude redirects, if so set |
194 | | - * @return String |
| 205 | + * Add redirect conditions |
| 206 | + * @param $query Array |
| 207 | + * @since 1.18 (changed) |
195 | 208 | */ |
196 | | - function queryRedirect() { |
197 | | - if( $this->showRedirects ) { |
198 | | - return ''; |
199 | | - } else { |
200 | | - return 'page_is_redirect=0'; |
| 209 | + function queryRedirect( &$query ) { |
| 210 | + if( !$this->showRedirects ) { |
| 211 | + $query['conds']['page_is_redirect'] = 0; |
201 | 212 | } |
202 | 213 | } |
203 | 214 | |
204 | 215 | /** |
205 | | - * Return a partial WHERE clause to limit the search to the given namespaces |
206 | | - * @return String |
| 216 | + * Add namespace conditions |
| 217 | + * @param $query Array |
| 218 | + * @since 1.18 (changed) |
207 | 219 | */ |
208 | | - function queryNamespaces() { |
209 | | - if( is_null($this->namespaces) ) |
210 | | - return ''; # search all |
211 | | - if ( !count( $this->namespaces ) ) { |
212 | | - $namespaces = '0'; |
213 | | - } else { |
214 | | - $namespaces = $this->db->makeList( $this->namespaces ); |
| 220 | + function queryNamespaces( &$query ) { |
| 221 | + if ( is_array( $this->namespaces ) ) { |
| 222 | + if ( count( $this->namespaces ) === 0 ) { |
| 223 | + $this->namespaces[] = '0'; |
| 224 | + } |
| 225 | + $query['conds']['page_namespace'] = $this->namespaces; |
215 | 226 | } |
216 | | - return 'page_namespace IN (' . $namespaces . ')'; |
217 | 227 | } |
218 | 228 | |
219 | 229 | /** |
220 | | - * Return a LIMIT clause to limit results on the query. |
221 | | - * @return String |
| 230 | + * Add limit options |
| 231 | + * @param $query Array |
| 232 | + * @since 1.18 |
222 | 233 | */ |
223 | | - function queryLimit() { |
224 | | - return $this->db->limitResult( '', $this->limit, $this->offset ); |
| 234 | + protected function limitResult( &$query ) { |
| 235 | + $query['options']['LIMIT'] = $this->limit; |
| 236 | + $query['options']['OFFSET'] = $this->offset; |
225 | 237 | } |
226 | 238 | |
227 | 239 | /** |
228 | | - * Does not do anything for generic search engine |
229 | | - * subclasses may define this though |
230 | | - * @return String |
231 | | - */ |
232 | | - function queryRanking( $filteredTerm, $fulltext ) { |
233 | | - return ''; |
234 | | - } |
235 | | - |
236 | | - /** |
237 | | - * Construct the full SQL query to do the search. |
| 240 | + * Construct the SQL query to do the search. |
238 | 241 | * The guts shoulds be constructed in queryMain() |
239 | 242 | * @param $filteredTerm String |
240 | 243 | * @param $fulltext Boolean |
| 244 | + * @return Array |
| 245 | + * @since 1.18 (changed) |
241 | 246 | */ |
242 | 247 | function getQuery( $filteredTerm, $fulltext ) { |
243 | | - $query = $this->queryMain( $filteredTerm, $fulltext ) . ' '; |
| 248 | + $query = array( |
| 249 | + 'tables' => array(), |
| 250 | + 'fields' => array(), |
| 251 | + 'conds' => array(), |
| 252 | + 'options' => array(), |
| 253 | + 'joins' => array(), |
| 254 | + ); |
244 | 255 | |
245 | | - $redir = $this->queryRedirect(); |
| 256 | + $this->queryMain( $query, $filteredTerm, $fulltext ); |
| 257 | + $this->queryRedirect( $query ); |
| 258 | + $this->queryNamespaces( $query ); |
| 259 | + $this->limitResult( $query ); |
246 | 260 | |
247 | | - if ( $redir ) { |
248 | | - $query .= 'AND ' . $redir . ' '; |
249 | | - } |
250 | | - |
251 | | - $namespace = $this->queryNamespaces(); |
252 | | - |
253 | | - if ( $namespace ) { |
254 | | - $query .= 'AND ' . $namespace . ' '; |
255 | | - } |
256 | | - |
257 | | - $query .= $this->queryRanking( $filteredTerm, $fulltext ) . ' ' . |
258 | | - $this->queryLimit(); |
259 | | - |
260 | 261 | return $query; |
261 | 262 | } |
262 | 263 | |
— | — | @@ -270,40 +271,40 @@ |
271 | 272 | |
272 | 273 | /** |
273 | 274 | * Get the base part of the search query. |
274 | | - * The actual match syntax will depend on the server |
275 | | - * version; MySQL 3 and MySQL 4 have different capabilities |
276 | | - * in their fulltext search indexes. |
277 | 275 | * |
278 | 276 | * @param $filteredTerm String |
279 | 277 | * @param $fulltext Boolean |
280 | | - * @return String |
| 278 | + * @since 1.18 (changed) |
281 | 279 | */ |
282 | | - function queryMain( $filteredTerm, $fulltext ) { |
| 280 | + function queryMain( &$query, $filteredTerm, $fulltext ) { |
283 | 281 | $match = $this->parseQuery( $filteredTerm, $fulltext ); |
284 | | - $page = $this->db->tableName( 'page' ); |
285 | | - $searchindex = $this->db->tableName( 'searchindex' ); |
286 | | - return 'SELECT page_id, page_namespace, page_title ' . |
287 | | - "FROM $page,$searchindex " . |
288 | | - 'WHERE page_id=si_page AND ' . $match; |
| 282 | + $query['tables'][] = 'page'; |
| 283 | + $query['tables'][] = 'searchindex'; |
| 284 | + $query['fields'][] = 'page_id'; |
| 285 | + $query['fields'][] = 'page_namespace'; |
| 286 | + $query['fields'][] = 'page_title'; |
| 287 | + $query['conds'][] = 'page_id=si_page'; |
| 288 | + $query['conds'][] = $match; |
289 | 289 | } |
290 | 290 | |
| 291 | + /** |
| 292 | + * @since 1.18 (changed) |
| 293 | + */ |
291 | 294 | function getCountQuery( $filteredTerm, $fulltext ) { |
292 | 295 | $match = $this->parseQuery( $filteredTerm, $fulltext ); |
293 | 296 | |
294 | | - $redir = $this->queryRedirect(); |
295 | | - $namespaces = $this->queryNamespaces(); |
296 | | - $conditions = array( 'page_id=si_page', $match ); |
297 | | - if ( $redir !== '' ) { |
298 | | - $conditions[] = $redir; |
299 | | - } |
300 | | - if ( $namespaces !== '' ) { |
301 | | - $conditions[] = $namespaces; |
302 | | - } |
303 | | - return $this->db->selectSQLText( array( 'page', 'searchindex' ), |
304 | | - 'COUNT(*) AS c', |
305 | | - $conditions, |
306 | | - __METHOD__ |
| 297 | + $query = array( |
| 298 | + 'tables' => array( 'page', 'searchindex' ), |
| 299 | + 'fields' => array( 'COUNT(*) as c' ), |
| 300 | + 'conds' => array( 'page_id=si_page', $match ), |
| 301 | + 'options' => array(), |
| 302 | + 'joins' => array(), |
307 | 303 | ); |
| 304 | + |
| 305 | + $this->queryRedirect( $query ); |
| 306 | + $this->queryNamespaces( $query ); |
| 307 | + |
| 308 | + return $query; |
308 | 309 | } |
309 | 310 | |
310 | 311 | /** |