00001 <?php
00002
00003
00004
00005
00006
00007
00008 class DBDriverSphinx implements IDBDriver {
00009 const DEFAULT_CONNECTION_NAME = 'sphinx';
00010 const SPHINX_ATTRIBUTE = 16384;
00011
00012
00013
00014
00015
00016
00017 const FEATURE_WEIGHTS = 'weights';
00018
00019
00020
00021
00022
00023 const FEATURE_STRIP_OPERATORS = 'strip_operators';
00024
00025
00026
00027
00028
00029 const FEATURE_MATCH_MODE = 'match_mode';
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 const FEATURE_SUBINDEXES = 'subindexes';
00046
00047
00048
00049
00050 const MATCH_BOOL = 'bool';
00051
00052
00053
00054 const MATCH_EX = 'ex';
00055
00056
00057
00058 const MATCH_OR = 'or';
00059
00060
00061
00062 const MATCH_AND = 'and';
00063
00064
00065
00066 const MATCH_PHRASE = 'phrase';
00067
00068 private $client = false;
00069 private $connect_params;
00070
00071
00072
00073
00074
00075 public function get_driver_name() {
00076 return 'sphinx';
00077 }
00078
00079
00080
00081
00082
00083
00084 public function get_host() {
00085 $tmp = array(
00086 Arr::get_item($this->connect_params, 'host', ''),
00087 Arr::get_item($this->connect_params, 'port', '')
00088 );
00089 return trim(implode($tmp), ':');
00090 }
00091
00092
00093
00094
00095
00096
00097 public function get_db_name() {
00098 return Arr::get_item($this->connect_params, 'dbname', '');
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 public function initialize($dbname, $user = '', $password = '', $host = 'localhost', $params = false) {
00110 $host_and_port = explode(':', $host);
00111 if (count($host_and_port) < 2) {
00112 $host_and_port[] = 9312;
00113 }
00114 $this->connect_params = array(
00115 'host' => $host_and_port[0],
00116 'port' => Cast::int($host_and_port[1]),
00117 'dbname' => $dbname
00118 );
00119 }
00120
00121
00122
00123
00124
00125
00126 private function connect() {
00127 if ($this->client === false) {
00128 $this->client = new SphinxClient();
00129 $this->client->SetServer($this->connect_params['host'], $this->connect_params['port']);
00130 }
00131 }
00132
00133
00134
00135
00136
00137
00138 public function quote($value) {
00139 return "'" . $this->escape($value) . "'";
00140 }
00141
00142
00143
00144
00145
00146
00147 public function escape_database_entity($obj, $type = self::FIELD) {
00148 return $obj;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 public function escape($value) {
00158
00159
00160 $from = array ( '\\', '@', '&', '/');
00161 $to = array ( '\\\\', '\@', '\&', '\/');
00162 $ret = str_replace($from, $to, $value);
00163
00164
00165
00166
00167
00168
00169 return $ret;
00170 }
00171
00172
00173
00174
00175
00176
00177 public function get_status() {
00178 $this->connect();
00179 $ret = new Status();
00180 $err = $this->client->GetLastError();
00181 if ($err) {
00182 $ret->append($err);
00183 }
00184 return $ret;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193 public function execute($sql) {
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 public function query($query) {
00203 $this->connect();
00204
00205 $arr_query = unserialize($query);
00206 $features = Arr::get_item($arr_query, 'features', false);
00207
00208 $terms = Arr::get_item_recursive($arr_query, 'conditions[query]', '');
00209 if (Arr::get_item($features, self::FEATURE_STRIP_OPERATORS, false)) {
00210 $terms = self::strip_operators($terms);
00211 }
00212
00213
00214 $this->client->SetSelect($arr_query['fields']);
00215 $this->client->SetArrayResult(true);
00216 if ($arr_query['order']) {
00217 $this->client->SetSortMode(SPH_SORT_EXTENDED, $arr_query['order']);
00218 }
00219 $limit = $arr_query['limit'];
00220 if ($limit) {
00221 $arr_limit = explode(';', $limit);
00222 $arr_limit = array_map('intval', $arr_limit);
00223 $this->client->SetLimits($arr_limit[0], $arr_limit[1]);
00224 }
00225
00226
00227 foreach(Arr::get_item_recursive($arr_query, 'conditions[filter]', array()) as $filter) {
00228 $this->client->SetFilter(
00229 $filter['attribute'],
00230 $filter['values'],
00231 $filter['exclude']
00232 );
00233 }
00234
00235
00236 $this->client->SetFieldWeights(Arr::get_item($features, self::FEATURE_WEIGHTS, array()));
00237
00238
00239 $matchmode = '';
00240 switch(Arr::get_item($features, self::FEATURE_MATCH_MODE, self::MATCH_EX)) {
00241 case self::MATCH_BOOL:
00242 $matchmode = SPH_MATCH_BOOLEAN;
00243 break;
00244 case self::MATCH_OR:
00245 $matchmode = SPH_MATCH_ANY;
00246 break;
00247 case self::MATCH_AND:
00248 $matchmode = SPH_MATCH_ALL;
00249 break;
00250 case self::MATCH_PHRASE:
00251 $matchmode = SPH_MATCH_PHRASE;
00252 break;
00253 case self::MATCH_EX:
00254 default:
00255 $matchmode = SPH_MATCH_EXTENDED2;
00256 break;
00257 }
00258 $this->client->SetMatchMode($matchmode);
00259
00260
00261 $index_base_name = $this->connect_params['dbname'] . $arr_query['from'];
00262 $index_names = array();
00263 $index_weight = array();
00264 foreach(Arr::get_item($features, self::FEATURE_SUBINDEXES, array()) as $key => $value) {
00265 if (is_numeric($key)) {
00266 $subindex_name = $index_base_name . $value;
00267 }
00268 else {
00269 $subindex_name = $index_base_name . $key;
00270 $index_weight[$subindex_name] = $value;
00271 }
00272 $index_names[] = $subindex_name;
00273 }
00274 $index_name = count($index_names) ? implode(',', $index_names) : $index_base_name;
00275 if (count($index_weight)) {
00276 $this->client->SetIndexWeights($index_weight);
00277 }
00278 $result = $this->client->Query($terms, $index_name);
00279
00280 $ret = false;
00281 if (isset($features['count'])) {
00282 $ret = new DBResultSetCountSphinx($result, $this->get_status());
00283 }
00284 else {
00285 $ret = new DBResultSetSphinx($result, $this->get_status());
00286 }
00287 $this->client = false;
00288 return $ret;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 public function explain($sql) {
00298 return false;
00299 }
00300
00301
00302
00303
00304
00305
00306 public function make_default() {
00307 return new Status();
00308 }
00309
00310
00311
00312
00313 public function trans_start() {
00314 }
00315
00316
00317
00318
00319 public function trans_commit() {
00320 }
00321
00322
00323
00324
00325 public function trans_rollback() {
00326 }
00327
00328
00329
00330
00331 public function last_insert_id() {
00332 return 0;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 public function has_feature($feature) {
00342 return false;
00343 }
00344
00345
00346
00347
00348 public static function strip_operators($terms) {
00349 $ops = '|-!@[]()*"<=^$~/';
00350 $replace = str_repeat(' ', strlen($ops));
00351 return strtr($terms, $ops, $replace);
00352 }
00353 }