1 <?php
2 3 4 5 6 7 8 9 10
11
12
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 class NeevoDriverMySQL extends NeevoParser implements INeevoDriver {
33
34
35
36 private $resource;
37
38
39 private $unbuffered;
40
41
42 private $affectedRows;
43
44
45 46 47 48 49
50 public function __construct(NeevoBaseStmt $statement = null){
51 if(!extension_loaded("mysql"))
52 throw new NeevoDriverException("Cannot instantiate Neevo MySQL driver - PHP extension 'mysql' not loaded.");
53 if($statement instanceof NeevoBaseStmt)
54 parent::__construct($statement);
55 }
56
57
58 59 60 61 62 63
64 public function connect(array $config){
65
66
67 $defaults = array(
68 'resource' => null,
69 'charset' => 'utf8',
70 'username' => ini_get('mysql.default_user'),
71 'password' => ini_get('mysql.default_password'),
72 'host' => ini_get('mysql.default_host'),
73 'port' => ini_get('mysql.default_port'),
74 'persistent' => false,
75 'unbuffered' => false
76 );
77
78 $config += $defaults;
79 if(isset($config['port']))
80 $host = $config['host'] .':'. $config['port'];
81 else
82 $host = $config['host'];
83
84
85 if(is_resource($config['resource']))
86 $connection = $config['resource'];
87 elseif($config['persistent'])
88 $connection = @mysql_pconnect($host, $config['username'], $config['password']);
89 else
90 $connection = @mysql_connect($host, $config['username'], $config['password']);
91
92 if(!is_resource($connection))
93 throw new NeevoException("Connection to host '$host' failed.");
94
95
96 if($config['database']){
97 $db = mysql_select_db($config['database']);
98 if(!$db) throw new NeevoException("Could not select database '$config[database]'.");
99 }
100
101 $this->resource = $connection;
102
103
104 if(is_resource($connection)){
105 if(function_exists('mysql_set_charset'))
106 @mysql_set_charset($config['charset'], $connection);
107 else
108 $this->runQuery("SET NAMES ".$config['charset']);
109 }
110
111 $this->unbuffered = $config['unbuffered'];
112 }
113
114
115 116 117 118
119 public function closeConnection(){
120 @mysql_close($this->resource);
121 }
122
123
124 125 126 127 128
129 public function freeResultSet($resultSet){
130 return @mysql_free_result($resultSet);
131 }
132
133
134 135 136 137 138 139
140 public function runQuery($queryString){
141
142 $this->affectedRows = false;
143 if($this->unbuffered)
144 $result = @mysql_unbuffered_query($queryString, $this->resource);
145 else
146 $result = @mysql_query($queryString, $this->resource);
147
148 $error = str_replace('You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use', 'Syntax error', @mysql_error($this->resource));
149 if($error && $result === false)
150 throw new NeevoException("Query failed. $error", @mysql_errno($this->resource), $queryString);
151
152 $this->affectedRows = @mysql_affected_rows($this->resource);
153 return $result;
154 }
155
156
157 158 159 160 161
162 public function beginTransaction($savepoint = null){
163 $this->runQuery($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
164 }
165
166
167 168 169 170 171
172 public function commit($savepoint = null){
173 $this->runQuery($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
174 }
175
176
177 178 179 180 181
182 public function rollback($savepoint = null){
183 $this->runQuery($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
184 }
185
186
187 188 189 190 191
192 public function fetch($resultSet){
193 return @mysql_fetch_assoc($resultSet);
194 }
195
196
197 198 199 200 201 202 203
204 public function seek($resultSet, $offset){
205 if($this->unbuffered){
206 throw new NeevoDriverException('Cannot seek on unbuffered result.');
207 }
208 return @mysql_data_seek($resultSet, $offset);
209 }
210
211
212 213 214 215
216 public function getInsertId(){
217 return @mysql_insert_id($this->resource);
218 }
219
220
221 222 223 224 225
226 public function randomizeOrder(NeevoBaseStmt $statement){
227 $statement->order('RAND()');
228 }
229
230
231 232 233 234 235 236
237 public function getNumRows($resultSet){
238 if($this->unbuffered)
239 throw new NeevoDriverException('Cannot count rows on unbuffered result.');
240 return @mysql_num_rows($resultSet);
241 }
242
243
244 245 246 247
248 public function getAffectedRows(){
249 return $this->affectedRows;
250 }
251
252
253 254 255 256 257 258 259
260 public function escape($value, $type){
261 switch($type){
262 case Neevo::BOOL:
263 return $value ? 1 : 0;
264
265 case Neevo::TEXT:
266 return "'". mysql_real_escape_string($value, $this->resource) ."'";
267
268 case Neevo::IDENTIFIER:
269 return str_replace('`*`', '*', '`' . str_replace('.', '`.`', str_replace('`', '``', $value)) . '`');
270
271 case Neevo::BINARY:
272 return "_binary'" . mysql_real_escape_string($value, $this->resource) . "'";
273
274 case Neevo::DATETIME:
275 return ($value instanceof DateTime) ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
276
277 default:
278 throw new InvalidArgumentException('Unsupported data type.');
279 break;
280 }
281 }
282
283
284 285 286 287 288 289 290
291 public function unescape($value, $type){
292 if($type === Neevo::BINARY)
293 return $value;
294 throw new InvalidArgumentException('Unsupported data type.');
295 }
296
297
298 299 300 301 302
303 public function getPrimaryKey($table){
304 $key = '';
305 $q = $this->runQuery('SHOW FULL COLUMNS FROM '.$table);
306 while($col = $this->fetch($q)){
307 if(strtolower($col['Key']) === 'pri' && $key === '')
308 $key = $col['Field'];
309 }
310 return $key;
311 }
312
313
314 315 316 317 318 319
320 public function getColumnTypes($resultSet, $table){
321 $cols = array();
322 $count = mysql_num_fields($resultSet);
323 for($i = 0; $i < $count; $i++){
324 $field = mysql_fetch_field($resultSet, $i);
325 $cols[$field->name] = $field->type;
326 }
327 return $cols;
328 }
329
330
331
332
333
334 335 336 337
338 protected function parseUpdateStmt(){
339 $sql = parent::parseUpdateStmt();
340 return $this->applyLimit($sql . $this->clauses[3]);
341 }
342
343
344 345 346 347
348 protected function parseDeleteStmt(){
349 $sql = parent::parseDeleteStmt();
350 return $this->applyLimit($sql . $this->clauses[3]);
351 }
352
353
354 }
355