Neevo Public API
  • Namespace
  • Class
  • Tree

Namespaces

  • Neevo
    • Nette
  • None
  • PHP

Classes

  • Neevo
  • NeevoBaseStmt
  • NeevoCacheFile
  • NeevoCacheMemcache
  • NeevoCacheMemory
  • NeevoCacheSession
  • NeevoConnection
  • NeevoDriverMySQL
  • NeevoDriverMySQLi
  • NeevoDriverPgSQL
  • NeevoDriverSQLite2
  • NeevoDriverSQLite3
  • NeevoLiteral
  • NeevoLoader
  • NeevoObserverMap
  • NeevoParser
  • NeevoResult
  • NeevoResultIterator
  • NeevoRow
  • NeevoStmt

Interfaces

  • INeevoCache
  • INeevoDriver
  • INeevoObservable
  • INeevoObserver

Exceptions

  • NeevoDriverException
  • NeevoException
  • NeevoImplementationException
  1 <?php
  2 /**
  3  * Neevo - Tiny open-source database abstraction layer for PHP
  4  *
  5  * Copyright 2010-2011 Martin Srank (http://smasty.net)
  6  *
  7  * This source file is subject to the MIT license that is bundled
  8  * with this package in the file license.txt.
  9  *
 10  * @author   Martin Srank (http://smasty.net)
 11  * @license http://neevo.smasty.net/license MIT license
 12  * @link         http://neevo.smasty.net/
 13  *
 14  */
 15 
 16 
 17 /**
 18  * Neevo SQLite 2 driver (PHP extension 'sqlite')
 19  *
 20  * Driver configuration:
 21  *  - database (or file)
 22  *  - memory (bool) => use an in-memory database (overrides 'database')
 23  *  - charset => Character encoding to set (defaults to utf-8)
 24  *  - dbcharset => Database character encoding (will be converted to 'charset')
 25  *  - persistent (bool) => Try to find a persistent link
 26  *  - unbuffered (bool) => Sends query without fetching and buffering the result
 27  *
 28  *  - updateLimit (bool) => Set TRUE if SQLite driver was compiled with SQLITE_ENABLE_UPDATE_DELETE_LIMIT
 29  *  - resource (type resource) => Existing SQLite 2 link
 30  *  - lazy, table_prefix... => see NeevoConnection
 31  *
 32  * @author Martin Srank
 33  * @package Neevo\Drivers
 34  */
 35 class NeevoDriverSQLite2 extends NeevoParser implements INeevoDriver {
 36 
 37 
 38     /** @var string */
 39     private $charset;
 40 
 41     /** @var string */
 42     private $dbCharset;
 43 
 44     /** @var bool */
 45     private $updateLimit;
 46 
 47     /** @var resource */
 48     private $resource;
 49 
 50     /** @var bool */
 51     private $unbuffered;
 52 
 53     /** @var bool */
 54     private $persistent;
 55 
 56     /** @var int */
 57     private $affectedRows;
 58 
 59     /** @var array */
 60     private $tblData = array();
 61 
 62 
 63     /**
 64      * Check for required PHP extension.
 65      * @return void
 66      * @throws NeevoDriverException
 67      */
 68     public function __construct(NeevoBaseStmt $statement = null){
 69         if(!extension_loaded("sqlite"))
 70             throw new NeevoDriverException("Cannot instantiate Neevo SQLite driver - PHP extension 'sqlite' not loaded.");
 71         if($statement instanceof NeevoBaseStmt)
 72             parent::__construct($statement);
 73     }
 74 
 75 
 76     /**
 77      * Create connection to database.
 78      * @param array $config Configuration options
 79      * @return void
 80      * @throws NeevoException
 81      */
 82     public function connect(array $config){
 83         NeevoConnection::alias($config, 'database', 'file');
 84         NeevoConnection::alias($config, 'updateLimit', 'update_limit');
 85 
 86         $defaults = array(
 87             'memory' => false,
 88             'resource' => null,
 89             'updateLimit' => false,
 90             'charset' => 'UTF-8',
 91             'dbcharset' => 'UTF-8',
 92             'persistent' => false,
 93             'unbuffered' => false
 94         );
 95 
 96         $config += $defaults;
 97 
 98         if($config['memory'])
 99             $config['database'] = ':memory:';
100 
101         // Connect
102         if(is_resource($config['resource']))
103             $connection = $config['resource'];
104         elseif($config['persistent'])
105             $connection = @sqlite_popen($config['database'], 0666, $error);
106         else
107             $connection = @sqlite_open($config['database'], 0666, $error);
108 
109         if(!is_resource($connection))
110             throw new NeevoException("Opening database file '$config[database]' failed.");
111 
112         $this->resource = $connection;
113         $this->updateLimit = (bool) $config['updateLimit'];
114 
115         // Set charset
116         $this->dbCharset = $config['dbcharset'];
117         $this->charset = $config['charset'];
118         if(strcasecmp($this->dbCharset, $this->charset) === 0)
119             $this->dbCharset = $this->charset = null;
120 
121         $this->unbuffered = $config['unbuffered'];
122         $this->persistent = $config['persistent'];
123     }
124 
125 
126     /**
127      * Close the connection.
128      * @return void
129      */
130     public function closeConnection(){
131         if(!$this->persistent && $this->resource !== null)
132             @sqlite_close($this->resource);
133     }
134 
135 
136     /**
137      * Free memory used by given result set.
138      * @param resource $resultSet
139      * @return bool
140      */
141     public function freeResultSet($resultSet){
142         return true;
143     }
144 
145 
146     /**
147      * Execute given SQL statement.
148      * @param string $queryString
149      * @return resource|bool
150      * @throws NeevoException
151      */
152     public function runQuery($queryString){
153 
154         $this->affectedRows = false;
155         if($this->dbCharset !== null)
156             $queryString = iconv($this->charset, $this->dbCharset . '//IGNORE', $queryString);
157 
158         if($this->unbuffered)
159             $result = @sqlite_unbuffered_query($this->resource, $queryString, null, $error);
160         else
161             $result = @sqlite_query($this->resource, $queryString, null, $error);
162 
163         if($error && $result === false)
164             throw new NeevoException("Query failed. $error", sqlite_last_error($this->resource), $queryString);
165 
166         $this->affectedRows = @sqlite_changes($this->resource);
167         return $result;
168     }
169 
170 
171     /**
172      * Begin a transaction if supported.
173      * @param string $savepoint
174      * @return void
175      */
176     public function beginTransaction($savepoint = null){
177         $this->runQuery('BEGIN');
178     }
179 
180 
181     /**
182      * Commit statements in a transaction.
183      * @param string $savepoint
184      * @return void
185      */
186     public function commit($savepoint = null){
187         $this->runQuery('COMMIT');
188     }
189 
190 
191     /**
192      * Rollback changes in a transaction.
193      * @param string $savepoint
194      * @return void
195      */
196     public function rollback($savepoint = null){
197         $this->runQuery('ROLLBACK');
198     }
199 
200 
201     /**
202      * Fetch row from given result set as an associative array.
203      * @param resource $resultSet
204      * @return array
205      */
206     public function fetch($resultSet){
207         $row = @sqlite_fetch_array($resultSet, SQLITE_ASSOC);
208         if($row){
209             $charset = $this->charset === null ? null : $this->charset.'//TRANSLIT';
210 
211             $fields = array();
212             foreach($row as $key => $val){
213                 if($charset !== null && is_string($val))
214                     $val = iconv($this->dbcharset, $charset, $val);
215                 $key = str_replace(array('[', ']'), '', $key);
216                 $pos = strpos($key, '.');
217                 if($pos !== false)
218                     $key = substr($key, $pos + 1);
219                 $fields[$key] = $val;
220             }
221             $row = $fields;
222         }
223         return $row;
224     }
225 
226 
227     /**
228      * Move internal result pointer.
229      * @param resource $resultSet
230      * @param int $offset
231      * @return bool
232      * @throws NeevoDriverException
233      */
234     public function seek($resultSet, $offset){
235         if($this->unbuffered)
236             throw new NeevoDriverException('Cannot seek on unbuffered result.');
237         return @sqlite_seek($resultSet, $offset);
238     }
239 
240 
241     /**
242      * Get the ID generated in the INSERT statement.
243      * @return int
244      */
245     public function getInsertId(){
246         return @sqlite_last_insert_rowid($this->resource);
247     }
248 
249 
250     /**
251      * Randomize result order.
252      * @param NeevoBaseStmt $statement
253      * @return void
254      */
255     public function randomizeOrder(NeevoBaseStmt $statement){
256         $statement->order('RANDOM()');
257     }
258 
259 
260     /**
261      * Get the number of rows in the given result set.
262      * @param resource $resultSet
263      * @return int|FALSE
264      * @throws NeevoDriverException
265      */
266     public function getNumRows($resultSet){
267         if($this->unbuffered)
268             throw new NeevoDriverException('Cannot count rows on unbuffered result.');
269         return @sqlite_num_rows($resultSet);
270     }
271 
272 
273     /**
274      * Get the number of affected rows in previous operation.
275      * @return int
276      */
277     public function getAffectedRows(){
278         return $this->affectedRows;
279     }
280 
281 
282     /**
283      * Escape given value.
284      * @param mixed $value
285      * @param string $type
286      * @return mixed
287      * @throws InvalidArgumentException
288      */
289     public function escape($value, $type){
290         switch($type){
291             case Neevo::BOOL:
292                 return $value ? 1 :0;
293 
294             case Neevo::TEXT:
295             case Neevo::BINARY:
296                 return "'". sqlite_escape_string($value) ."'";
297 
298             case Neevo::IDENTIFIER:
299                 return str_replace('[*]', '*', '[' . str_replace('.', '].[', $value) . ']');
300 
301             case Neevo::DATETIME:
302                 return ($value instanceof DateTime) ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
303 
304             default:
305                 throw new InvalidArgumentException('Unsupported data type.');
306                 break;
307         }
308     }
309 
310 
311     /**
312      * Decode given value.
313      * @param mixed $value
314      * @param string $type
315      * @return mixed
316      * @throws InvalidArgumentException
317      */
318     public function unescape($value, $type){
319         if($type === Neevo::BINARY)
320             return $value;
321         throw new InvalidArgumentException('Unsupported data type.');
322     }
323 
324 
325     /**
326      * Get the PRIMARY KEY column for given table.
327      * @param string $table
328      * @return string
329      */
330     public function getPrimaryKey($table){
331         $key = '';
332         $pos = strpos($table, '.');
333         if($pos !== false)
334             $table = substr($table, $pos + 1);
335         if(isset($this->tblData[$table]))
336             $sql = $this->tblData[$table];
337         else{
338             $q = $this->runQuery("SELECT sql FROM sqlite_master WHERE tbl_name='$table'");
339             $r = $this->fetch($q);
340             if($r === false)
341                 return '';
342             $this->tblData[$table] = $sql = $r['sql'];
343         }
344 
345         $sql = explode("\n", $sql);
346         foreach($sql as $field){
347             $field = trim($field);
348             if(stripos($field, 'PRIMARY KEY') !== false && $key === '')
349                 $key = preg_replace('~^"(\w+)".*$~i', '$1', $field);
350         }
351         return $key;
352     }
353 
354 
355     /**
356      * Get types of columns in given result set.
357      * @param resource $resultSet
358      * @param string $table
359      * @return array
360      */
361     public function getColumnTypes($resultSet, $table){
362         if($table === null)
363             return array();
364         if(isset($this->tblData[$table]))
365             $sql = $this->tblData[$table];
366         else
367             $q = $this->runQuery("SELECT sql FROM sqlite_master WHERE tbl_name='$table'");
368             $r = $this->fetch($q);
369             if($r === false)
370                 return array();
371             $this->tblData[$table] = $sql = $r['sql'];
372         $sql = explode("\n", $sql);
373 
374         $cols = array();
375         foreach($sql as $field){
376             $field = trim($field);
377             preg_match('~^"(\w+)"\s+(integer|real|numeric|text|blob).+$~i', $field, $m);
378             if(isset($m[1], $m[2]))
379                 $cols[$m[1]] = $m[2];
380         }
381         return $cols;
382     }
383 
384 
385     /*  ************  NeevoParser overrides  ************  */
386 
387 
388     /**
389      * Parse UPDATE statement.
390      * @return string
391      */
392     protected function parseUpdateStmt(){
393         $sql = parent::parseUpdateStmt();
394         return $this->updateLimit ? $this->applyLimit($sql . $this->clauses[3]) : $sql;
395     }
396 
397 
398     /**
399      * Parse DELETE statement.
400      * @return string
401      */
402     protected function parseDeleteStmt(){
403         $sql = parent::parseDeleteStmt();
404         return $this->updateLimit ? $this->applyLimit($sql . $this->clauses[3]) : $sql;
405     }
406 
407 
408 }
409 
Neevo Public API API documentation generated by ApiGen 2.8.0