Neevo Public API
  • Namespace
  • Class
  • Tree

Namespaces

  • Neevo
    • Cache
    • Drivers
    • Nette
  • PHP

Classes

  • MySQLDriver
  • MySQLiDriver
  • PDODriver
  • PgSQLDriver
  • SQLite2Driver
  • SQLite3Driver
  1 <?php
  2 /**
  3  * Neevo - Tiny database layer for PHP. (http://neevo.smasty.net)
  4  *
  5  * This source file is subject to the MIT license that is bundled
  6  * with this package in the file license.txt.
  7  *
  8  * Copyright (c) 2012 Smasty (http://smasty.net)
  9  *
 10  */
 11 
 12 namespace Neevo\Drivers;
 13 
 14 use DateTime;
 15 use InvalidArgumentException;
 16 use Neevo\BaseStatement;
 17 use Neevo\DriverException;
 18 use Neevo\DriverInterface;
 19 use Neevo\Manager;
 20 use Neevo\Parser;
 21 
 22 
 23 /**
 24  * Neevo MySQL driver (PHP extension 'mysql')
 25  *
 26  * Driver configuration:
 27  * - host => MySQL server name or address
 28  * - port (int) => MySQL server port
 29  * - username
 30  * - password
 31  * - database => database to select
 32  * - charset => Character encoding to set (defaults to utf8)
 33  * - persistent (bool) => Try to find a persistent link
 34  * - unbuffered (bool) => Sends query without fetching and buffering the result
 35  *
 36  * - resource (type resource) => Existing MySQL link
 37  * - lazy, table_prefix... => see {@see Neevo\Connection}
 38  *
 39  * @author Smasty
 40  */
 41 class MySQLDriver extends Parser implements DriverInterface {
 42 
 43 
 44     /** @var resource */
 45     private $resource;
 46 
 47     /** @var bool */
 48     private $unbuffered;
 49 
 50     /** @var int */
 51     private $affectedRows;
 52 
 53 
 54     /**
 55      * Checks for required PHP extension.
 56      * @throws DriverException
 57      */
 58     public function __construct(BaseStatement $statement = null){
 59         if(!extension_loaded("mysql"))
 60             throw new DriverException("Cannot instantiate Neevo MySQL driver - PHP extension 'mysql' not loaded.");
 61         if($statement instanceof BaseStatement)
 62             parent::__construct($statement);
 63     }
 64 
 65 
 66     /**
 67      * Creates connection to database.
 68      * @param array $config Configuration options
 69      * @throws DriverException
 70      */
 71     public function connect(array $config){
 72 
 73         // Defaults
 74         $defaults = array(
 75             'resource' => null,
 76             'charset' => 'utf8',
 77             'username' => ini_get('mysql.default_user'),
 78             'password' => ini_get('mysql.default_password'),
 79             'host' => ini_get('mysql.default_host'),
 80             'port' => ini_get('mysql.default_port'),
 81             'persistent' => false,
 82             'unbuffered' => false
 83         );
 84 
 85         $config += $defaults;
 86         if(isset($config['port']))
 87             $host = $config['host'] . ':' . $config['port'];
 88         else
 89             $host = $config['host'];
 90 
 91         // Connect
 92         if(is_resource($config['resource']))
 93             $connection = $config['resource'];
 94         elseif($config['persistent'])
 95             $connection = @mysql_pconnect($host, $config['username'], $config['password']);
 96         else
 97             $connection = @mysql_connect($host, $config['username'], $config['password']);
 98 
 99         if(!is_resource($connection))
100             throw new DriverException("Connection to host '$host' failed.");
101 
102         // Select DB
103         if(isset($config['database'])){
104             $db = mysql_select_db($config['database']);
105             if(!$db)
106                 throw new DriverException("Could not select database '$config[database]'.");
107         }
108 
109         $this->resource = $connection;
110 
111         //Set charset
112         if(is_resource($connection)){
113             if(function_exists('mysql_set_charset'))
114                 @mysql_set_charset($config['charset'], $connection);
115             else
116                 $this->runQuery("SET NAMES " . $config['charset']);
117         }
118 
119         $this->unbuffered = $config['unbuffered'];
120     }
121 
122 
123     /**
124      * Closes the connection.
125      */
126     public function closeConnection(){
127         @mysql_close($this->resource);
128     }
129 
130 
131     /**
132      * Frees memory used by given result set.
133      * @param resource $resultSet
134      * @return bool
135      */
136     public function freeResultSet($resultSet){
137         return @mysql_free_result($resultSet);
138     }
139 
140 
141     /**
142      * Executes given SQL statement.
143      * @param string $queryString
144      * @return resource|bool
145      * @throws DriverException
146      */
147     public function runQuery($queryString){
148 
149         $this->affectedRows = false;
150         if($this->unbuffered)
151             $result = @mysql_unbuffered_query($queryString, $this->resource);
152         else
153             $result = @mysql_query($queryString, $this->resource);
154 
155         $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));
156         if($error && $result === false)
157             throw new DriverException($error, @mysql_errno($this->resource), $queryString);
158 
159         $this->affectedRows = @mysql_affected_rows($this->resource);
160         return $result;
161     }
162 
163 
164     /**
165      * Begins a transaction if supported.
166      * @param string $savepoint
167      */
168     public function beginTransaction($savepoint = null){
169         $this->runQuery($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
170     }
171 
172 
173     /**
174      * Commits statements in a transaction.
175      * @param string $savepoint
176      */
177     public function commit($savepoint = null){
178         $this->runQuery($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
179     }
180 
181 
182     /**
183      * Rollback changes in a transaction.
184      * @param string $savepoint
185      */
186     public function rollback($savepoint = null){
187         $this->runQuery($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
188     }
189 
190 
191     /**
192      * Fetches row from given result set as an associative array.
193      * @param resource $resultSet
194      * @return array
195      */
196     public function fetch($resultSet){
197         return @mysql_fetch_assoc($resultSet);
198     }
199 
200 
201     /**
202      * Moves internal result pointer.
203      * @param resource $resultSet
204      * @param int $offset
205      * @return bool
206      * @throws DriverException
207      */
208     public function seek($resultSet, $offset){
209         if($this->unbuffered){
210             throw new DriverException('Cannot seek on unbuffered result.');
211         }
212         return @mysql_data_seek($resultSet, $offset);
213     }
214 
215 
216     /**
217      * Returns the ID generated in the INSERT statement.
218      * @return int
219      */
220     public function getInsertId(){
221         return @mysql_insert_id($this->resource);
222     }
223 
224 
225     /**
226      * Randomizes result order.
227      * @param BaseStatement $statement
228      */
229     public function randomizeOrder(BaseStatement $statement){
230         $statement->order('RAND()');
231     }
232 
233 
234     /**
235      * Returns the number of rows in the given result set.
236      * @param resource $resultSet
237      * @return int|bool
238      * @throws DriverException
239      */
240     public function getNumRows($resultSet){
241         if($this->unbuffered)
242             throw new DriverException('Cannot count rows on unbuffered result.');
243         return @mysql_num_rows($resultSet);
244     }
245 
246 
247     /**
248      * Returns the number of affected rows in previous operation.
249      * @return int
250      */
251     public function getAffectedRows(){
252         return $this->affectedRows;
253     }
254 
255 
256     /**
257      * Escapes given value.
258      * @param mixed $value
259      * @param string $type
260      * @return mixed
261      * @throws InvalidArgumentException
262      */
263     public function escape($value, $type){
264         switch($type){
265             case Manager::BOOL:
266                 return $value ? 1 : 0;
267 
268             case Manager::TEXT:
269                 return "'" . mysql_real_escape_string($value, $this->resource) . "'";
270 
271             case Manager::IDENTIFIER:
272                 return str_replace('`*`', '*', '`' . str_replace('.', '`.`', str_replace('`', '``', $value)) . '`');
273 
274             case Manager::BINARY:
275                 return "_binary'" . mysql_real_escape_string($value, $this->resource) . "'";
276 
277             case Manager::DATETIME:
278                 return ($value instanceof DateTime) ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
279 
280             default:
281                 throw new InvalidArgumentException('Unsupported data type.');
282                 break;
283         }
284     }
285 
286 
287     /**
288      * Decodes given value.
289      * @param mixed $value
290      * @param string $type
291      * @return mixed
292      * @throws InvalidArgumentException
293      */
294     public function unescape($value, $type){
295         if($type === Manager::BINARY)
296             return $value;
297         throw new InvalidArgumentException('Unsupported data type.');
298     }
299 
300 
301     /**
302      * Returns the PRIMARY KEY column for given table.
303      * @param string $table
304      * @return string
305      */
306     public function getPrimaryKey($table){
307         $key = '';
308         $q = $this->runQuery('SHOW FULL COLUMNS FROM ' . $table);
309         while($col = $this->fetch($q)){
310             if(strtolower($col['Key']) === 'pri' && $key === '')
311                 $key = $col['Field'];
312         }
313         return $key;
314     }
315 
316 
317     /**
318      * Returns types of columns in given result set.
319      * @param resource $resultSet
320      * @param string $table
321      * @return array
322      */
323     public function getColumnTypes($resultSet, $table){
324         $cols = array();
325         $count = mysql_num_fields($resultSet);
326         for($i = 0; $i < $count; $i++){
327             $field = mysql_fetch_field($resultSet, $i);
328             $cols[$field->name] = $field->type;
329         }
330         return $cols;
331     }
332 
333 
334     /**
335      * Parses UPDATE statement.
336      * @return string
337      */
338     protected function parseUpdateStmt(){
339         $sql = parent::parseUpdateStmt();
340         return $this->applyLimit($sql . $this->clauses[3]);
341     }
342 
343 
344     /**
345      * Parses DELETE statement.
346      * @return string
347      */
348     protected function parseDeleteStmt(){
349         $sql = parent::parseDeleteStmt();
350         return $this->applyLimit($sql . $this->clauses[3]);
351     }
352 
353 
354 }
355 
Neevo Public API API documentation generated by ApiGen 2.8.0