00001 <?php 00002 # Copyright (C) 2004 Brion Vibber <brion@pobox.com> 00003 # http://www.mediawiki.org/ 00004 # 00005 # This program is free software; you can redistribute it and/or modify 00006 # it under the terms of the GNU General Public License as published by 00007 # the Free Software Foundation; either version 2 of the License, or 00008 # (at your option) any later version. 00009 # 00010 # This program is distributed in the hope that it will be useful, 00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 # GNU General Public License for more details. 00014 # 00015 # You should have received a copy of the GNU General Public License along 00016 # with this program; if not, write to the Free Software Foundation, Inc., 00017 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 # http://www.gnu.org/copyleft/gpl.html 00019 00029 class SearchOracle extends SearchEngine { 00030 function __construct($db) { 00031 $this->db = $db; 00032 } 00033 00041 function searchText( $term ) { 00042 $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), true))); 00043 return new OracleSearchResultSet($resultSet, $this->searchTerms); 00044 } 00045 00053 function searchTitle($term) { 00054 $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), false))); 00055 return new MySQLSearchResultSet($resultSet, $this->searchTerms); 00056 } 00057 00058 00064 function queryRedirect() { 00065 if ($this->showRedirects) { 00066 return ''; 00067 } else { 00068 return 'AND page_is_redirect=0'; 00069 } 00070 } 00071 00077 function queryNamespaces() { 00078 if( is_null($this->namespaces) ) 00079 return ''; 00080 if ( !count( $this->namespaces ) ) { 00081 $namespaces = '0'; 00082 } else { 00083 $namespaces = $this->db->makeList( $this->namespaces ); 00084 } 00085 return 'AND page_namespace IN (' . $namespaces . ')'; 00086 } 00087 00093 function queryLimit($sql) { 00094 return $this->db->limitResult($sql, $this->limit, $this->offset); 00095 } 00096 00103 function queryRanking($filteredTerm, $fulltext) { 00104 return ' ORDER BY score(1)'; 00105 } 00106 00114 function getQuery( $filteredTerm, $fulltext ) { 00115 return $this->queryLimit($this->queryMain($filteredTerm, $fulltext) . ' ' . 00116 $this->queryRedirect() . ' ' . 00117 $this->queryNamespaces() . ' ' . 00118 $this->queryRanking( $filteredTerm, $fulltext ) . ' '); 00119 } 00120 00121 00127 function getIndexField($fulltext) { 00128 return $fulltext ? 'si_text' : 'si_title'; 00129 } 00130 00139 function queryMain( $filteredTerm, $fulltext ) { 00140 $match = $this->parseQuery($filteredTerm, $fulltext); 00141 $page = $this->db->tableName('page'); 00142 $searchindex = $this->db->tableName('searchindex'); 00143 return 'SELECT page_id, page_namespace, page_title ' . 00144 "FROM $page,$searchindex " . 00145 'WHERE page_id=si_page AND ' . $match; 00146 } 00147 00152 function parseQuery($filteredText, $fulltext) { 00153 global $wgContLang; 00154 $lc = SearchEngine::legalSearchChars(); 00155 $this->searchTerms = array(); 00156 00157 # FIXME: This doesn't handle parenthetical expressions. 00158 $m = array(); 00159 $q = array(); 00160 00161 if (preg_match_all('/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/', 00162 $filteredText, $m, PREG_SET_ORDER)) { 00163 foreach($m as $terms) { 00164 $q[] = $terms[1] . $wgContLang->stripForSearch($terms[2]); 00165 00166 if (!empty($terms[3])) { 00167 $regexp = preg_quote( $terms[3], '/' ); 00168 if ($terms[4]) 00169 $regexp .= "[0-9A-Za-z_]+"; 00170 } else { 00171 $regexp = preg_quote(str_replace('"', '', $terms[2]), '/'); 00172 } 00173 $this->searchTerms[] = $regexp; 00174 } 00175 } 00176 00177 $searchon = $this->db->addQuotes(join(',', $q)); 00178 $field = $this->getIndexField($fulltext); 00179 return " CONTAINS($field, $searchon, 1) > 0 "; 00180 } 00181 00190 function update($id, $title, $text) { 00191 $dbw = wfGetDB(DB_MASTER); 00192 $dbw->replace('searchindex', 00193 array('si_page'), 00194 array( 00195 'si_page' => $id, 00196 'si_title' => $title, 00197 'si_text' => $text 00198 ), 'SearchOracle::update' ); 00199 $dbw->query("CALL ctx_ddl.sync_index('si_text_idx')"); 00200 $dbw->query("CALL ctx_ddl.sync_index('si_title_idx')"); 00201 } 00202 00210 function updateTitle($id, $title) { 00211 $dbw = wfGetDB(DB_MASTER); 00212 00213 $dbw->update('searchindex', 00214 array('si_title' => $title), 00215 array('si_page' => $id), 00216 'SearchOracle::updateTitle', 00217 array()); 00218 } 00219 } 00220 00224 class OracleSearchResultSet extends SearchResultSet { 00225 function __construct($resultSet, $terms) { 00226 $this->mResultSet = $resultSet; 00227 $this->mTerms = $terms; 00228 } 00229 00230 function termMatches() { 00231 return $this->mTerms; 00232 } 00233 00234 function numRows() { 00235 return $this->mResultSet->numRows(); 00236 } 00237 00238 function next() { 00239 $row = $this->mResultSet->fetchObject(); 00240 if ($row === false) 00241 return false; 00242 return new SearchResult($row); 00243 } 00244 }