blob: ea0583e9e17f11cf514ae3bdde5b776193f81b35 [file] [log] [blame]
Derek Allard2067d1a2008-11-13 22:59:24 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
Derek Jones7f3719f2010-01-05 13:35:37 +00009 * @copyright Copyright (c) 2008 - 2010, EllisLab, Inc.
Derek Allard2067d1a2008-11-13 22:59:24 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18
19
20/**
21 * SQLite Database Adapter Class
22 *
23 * Note: _DB is an extender class that the app controller
24 * creates dynamically based on whether the active record
25 * class is being used or not.
26 *
27 * @package CodeIgniter
28 * @subpackage Drivers
29 * @category Database
30 * @author ExpressionEngine Dev Team
31 * @link http://codeigniter.com/user_guide/database/
32 */
33class CI_DB_sqlite_driver extends CI_DB {
34
35 var $dbdriver = 'sqlite';
Barry Mienydd671972010-10-04 16:33:58 +020036
Derek Allard2067d1a2008-11-13 22:59:24 +000037 // The character used to escape with - not needed for SQLite
38 var $_escape_char = '';
39
Derek Jonese4ed5832009-02-20 21:44:59 +000040 // clause and character used for LIKE escape sequences
Barry Mienydd671972010-10-04 16:33:58 +020041 var $_like_escape_str = " ESCAPE '%s' ";
Derek Jonese4ed5832009-02-20 21:44:59 +000042 var $_like_escape_chr = '!';
Barry Mienydd671972010-10-04 16:33:58 +020043
Derek Allard2067d1a2008-11-13 22:59:24 +000044 /**
45 * The syntax to count rows is slightly different across different
46 * database engines, so this string appears in each driver and is
47 * used for the count_all() and count_all_results() functions.
48 */
49 var $_count_string = "SELECT COUNT(*) AS ";
50 var $_random_keyword = ' Random()'; // database specific random keyword
51
52 /**
53 * Non-persistent database connection
54 *
55 * @access private called by the base class
56 * @return resource
Barry Mienydd671972010-10-04 16:33:58 +020057 */
Derek Allard2067d1a2008-11-13 22:59:24 +000058 function db_connect()
59 {
60 if ( ! $conn_id = @sqlite_open($this->database, FILE_WRITE_MODE, $error))
61 {
62 log_message('error', $error);
Barry Mienydd671972010-10-04 16:33:58 +020063
Derek Allard2067d1a2008-11-13 22:59:24 +000064 if ($this->db_debug)
65 {
Derek Allardfac8fbc2010-02-05 16:14:49 +000066 $this->display_error($error, '', TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +000067 }
Barry Mienydd671972010-10-04 16:33:58 +020068
Derek Allard2067d1a2008-11-13 22:59:24 +000069 return FALSE;
70 }
Barry Mienydd671972010-10-04 16:33:58 +020071
Derek Allard2067d1a2008-11-13 22:59:24 +000072 return $conn_id;
73 }
Barry Mienydd671972010-10-04 16:33:58 +020074
Derek Allard2067d1a2008-11-13 22:59:24 +000075 // --------------------------------------------------------------------
76
77 /**
78 * Persistent database connection
79 *
80 * @access private called by the base class
81 * @return resource
Barry Mienydd671972010-10-04 16:33:58 +020082 */
Derek Allard2067d1a2008-11-13 22:59:24 +000083 function db_pconnect()
84 {
85 if ( ! $conn_id = @sqlite_popen($this->database, FILE_WRITE_MODE, $error))
86 {
87 log_message('error', $error);
Barry Mienydd671972010-10-04 16:33:58 +020088
Derek Allard2067d1a2008-11-13 22:59:24 +000089 if ($this->db_debug)
90 {
Derek Allardfac8fbc2010-02-05 16:14:49 +000091 $this->display_error($error, '', TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +000092 }
Barry Mienydd671972010-10-04 16:33:58 +020093
Derek Allard2067d1a2008-11-13 22:59:24 +000094 return FALSE;
95 }
Barry Mienydd671972010-10-04 16:33:58 +020096
Derek Allard2067d1a2008-11-13 22:59:24 +000097 return $conn_id;
98 }
Barry Mienydd671972010-10-04 16:33:58 +020099
Derek Allard2067d1a2008-11-13 22:59:24 +0000100 // --------------------------------------------------------------------
101
102 /**
Derek Jones87cbafc2009-02-27 16:29:59 +0000103 * Reconnect
104 *
105 * Keep / reestablish the db connection if no queries have been
106 * sent for a length of time exceeding the server's idle timeout
107 *
108 * @access public
109 * @return void
110 */
111 function reconnect()
112 {
113 // not implemented in SQLite
114 }
115
116 // --------------------------------------------------------------------
117
118 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000119 * Select the database
120 *
121 * @access private called by the base class
122 * @return resource
Barry Mienydd671972010-10-04 16:33:58 +0200123 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000124 function db_select()
125 {
126 return TRUE;
127 }
128
129 // --------------------------------------------------------------------
130
131 /**
132 * Set client character set
133 *
134 * @access public
135 * @param string
136 * @param string
137 * @return resource
138 */
139 function db_set_charset($charset, $collation)
140 {
141 // @todo - add support if needed
142 return TRUE;
143 }
144
145 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200146
Derek Allard2067d1a2008-11-13 22:59:24 +0000147 /**
148 * Version number query string
149 *
150 * @access public
151 * @return string
152 */
153 function _version()
154 {
155 return sqlite_libversion();
156 }
Barry Mienydd671972010-10-04 16:33:58 +0200157
Derek Allard2067d1a2008-11-13 22:59:24 +0000158 // --------------------------------------------------------------------
159
160 /**
161 * Execute the query
162 *
163 * @access private called by the base class
164 * @param string an SQL query
165 * @return resource
Barry Mienydd671972010-10-04 16:33:58 +0200166 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 function _execute($sql)
168 {
169 $sql = $this->_prep_query($sql);
170 return @sqlite_query($this->conn_id, $sql);
171 }
Barry Mienydd671972010-10-04 16:33:58 +0200172
Derek Allard2067d1a2008-11-13 22:59:24 +0000173 // --------------------------------------------------------------------
174
175 /**
176 * Prep the query
177 *
178 * If needed, each database adapter can prep the query string
179 *
180 * @access private called by execute()
181 * @param string an SQL query
182 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200183 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000184 function _prep_query($sql)
185 {
186 return $sql;
187 }
188
189 // --------------------------------------------------------------------
190
191 /**
192 * Begin Transaction
193 *
194 * @access public
Barry Mienydd671972010-10-04 16:33:58 +0200195 * @return bool
196 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000197 function trans_begin($test_mode = FALSE)
198 {
199 if ( ! $this->trans_enabled)
200 {
201 return TRUE;
202 }
Barry Mienydd671972010-10-04 16:33:58 +0200203
Derek Allard2067d1a2008-11-13 22:59:24 +0000204 // When transactions are nested we only begin/commit/rollback the outermost ones
205 if ($this->_trans_depth > 0)
206 {
207 return TRUE;
208 }
209
210 // Reset the transaction failure flag.
211 // If the $test_mode flag is set to TRUE transactions will be rolled back
212 // even if the queries produce a successful result.
213 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
214
215 $this->simple_query('BEGIN TRANSACTION');
216 return TRUE;
217 }
218
219 // --------------------------------------------------------------------
220
221 /**
222 * Commit Transaction
223 *
224 * @access public
Barry Mienydd671972010-10-04 16:33:58 +0200225 * @return bool
226 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000227 function trans_commit()
228 {
229 if ( ! $this->trans_enabled)
230 {
231 return TRUE;
232 }
233
234 // When transactions are nested we only begin/commit/rollback the outermost ones
235 if ($this->_trans_depth > 0)
236 {
237 return TRUE;
238 }
239
240 $this->simple_query('COMMIT');
241 return TRUE;
242 }
243
244 // --------------------------------------------------------------------
245
246 /**
247 * Rollback Transaction
248 *
249 * @access public
Barry Mienydd671972010-10-04 16:33:58 +0200250 * @return bool
251 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000252 function trans_rollback()
253 {
254 if ( ! $this->trans_enabled)
255 {
256 return TRUE;
257 }
258
259 // When transactions are nested we only begin/commit/rollback the outermost ones
260 if ($this->_trans_depth > 0)
261 {
262 return TRUE;
263 }
264
265 $this->simple_query('ROLLBACK');
266 return TRUE;
267 }
Barry Mienydd671972010-10-04 16:33:58 +0200268
Derek Allard2067d1a2008-11-13 22:59:24 +0000269 // --------------------------------------------------------------------
270
271 /**
272 * Escape String
273 *
274 * @access public
275 * @param string
Derek Jonese4ed5832009-02-20 21:44:59 +0000276 * @param bool whether or not the string will be used in a LIKE condition
Derek Allard2067d1a2008-11-13 22:59:24 +0000277 * @return string
278 */
Derek Jonese4ed5832009-02-20 21:44:59 +0000279 function escape_str($str, $like = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000280 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000281 if (is_array($str))
282 {
283 foreach($str as $key => $val)
Barry Mienydd671972010-10-04 16:33:58 +0200284 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000285 $str[$key] = $this->escape_str($val, $like);
Barry Mienydd671972010-10-04 16:33:58 +0200286 }
287
288 return $str;
289 }
290
Derek Jonese4ed5832009-02-20 21:44:59 +0000291 $str = sqlite_escape_string($str);
Barry Mienydd671972010-10-04 16:33:58 +0200292
Derek Jonese4ed5832009-02-20 21:44:59 +0000293 // escape LIKE condition wildcards
294 if ($like === TRUE)
295 {
296 $str = str_replace( array('%', '_', $this->_like_escape_chr),
297 array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
298 $str);
299 }
Barry Mienydd671972010-10-04 16:33:58 +0200300
Derek Jonese4ed5832009-02-20 21:44:59 +0000301 return $str;
Derek Allard2067d1a2008-11-13 22:59:24 +0000302 }
Barry Mienydd671972010-10-04 16:33:58 +0200303
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 // --------------------------------------------------------------------
305
306 /**
307 * Affected Rows
308 *
309 * @access public
310 * @return integer
311 */
312 function affected_rows()
313 {
314 return sqlite_changes($this->conn_id);
315 }
Barry Mienydd671972010-10-04 16:33:58 +0200316
Derek Allard2067d1a2008-11-13 22:59:24 +0000317 // --------------------------------------------------------------------
318
319 /**
320 * Insert ID
321 *
322 * @access public
323 * @return integer
324 */
325 function insert_id()
326 {
327 return @sqlite_last_insert_rowid($this->conn_id);
328 }
329
330 // --------------------------------------------------------------------
331
332 /**
333 * "Count All" query
334 *
335 * Generates a platform-specific query string that counts all records in
336 * the specified database
337 *
338 * @access public
339 * @param string
340 * @return string
341 */
342 function count_all($table = '')
343 {
344 if ($table == '')
Derek Allarde37ab382009-02-03 16:13:57 +0000345 {
346 return 0;
347 }
348
349 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
Barry Mienydd671972010-10-04 16:33:58 +0200350
Derek Allard2067d1a2008-11-13 22:59:24 +0000351 if ($query->num_rows() == 0)
Derek Allarde37ab382009-02-03 16:13:57 +0000352 {
353 return 0;
354 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000355
356 $row = $query->row();
Derek Allarde37ab382009-02-03 16:13:57 +0000357 return (int) $row->numrows;
Derek Allard2067d1a2008-11-13 22:59:24 +0000358 }
359
360 // --------------------------------------------------------------------
361
362 /**
363 * List table query
364 *
365 * Generates a platform-specific query string so that the table names can be fetched
366 *
367 * @access private
368 * @param boolean
369 * @return string
370 */
371 function _list_tables($prefix_limit = FALSE)
372 {
373 $sql = "SELECT name from sqlite_master WHERE type='table'";
374
375 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
376 {
Greg Aker0d424892010-01-26 02:14:44 +0000377 $sql .= " AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
Derek Allard2067d1a2008-11-13 22:59:24 +0000378 }
379 return $sql;
380 }
381
382 // --------------------------------------------------------------------
383
384 /**
385 * Show column query
386 *
387 * Generates a platform-specific query string so that the column names can be fetched
388 *
389 * @access public
390 * @param string the table name
391 * @return string
392 */
393 function _list_columns($table = '')
394 {
395 // Not supported
396 return FALSE;
397 }
398
399 // --------------------------------------------------------------------
400
401 /**
402 * Field data query
403 *
404 * Generates a platform-specific query so that the column data can be retrieved
405 *
406 * @access public
407 * @param string the table name
408 * @return object
409 */
410 function _field_data($table)
411 {
412 return "SELECT * FROM ".$table." LIMIT 1";
413 }
414
415 // --------------------------------------------------------------------
416
417 /**
418 * The error message string
419 *
420 * @access private
421 * @return string
422 */
423 function _error_message()
424 {
425 return sqlite_error_string(sqlite_last_error($this->conn_id));
426 }
Barry Mienydd671972010-10-04 16:33:58 +0200427
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 // --------------------------------------------------------------------
429
430 /**
431 * The error message number
432 *
433 * @access private
434 * @return integer
435 */
436 function _error_number()
437 {
438 return sqlite_last_error($this->conn_id);
439 }
440
441 // --------------------------------------------------------------------
442
443 /**
444 * Escape the SQL Identifiers
445 *
446 * This function escapes column and table names
447 *
448 * @access private
449 * @param string
450 * @return string
451 */
452 function _escape_identifiers($item)
453 {
454 if ($this->_escape_char == '')
455 {
456 return $item;
457 }
458
459 foreach ($this->_reserved_identifiers as $id)
460 {
461 if (strpos($item, '.'.$id) !== FALSE)
462 {
Barry Mienydd671972010-10-04 16:33:58 +0200463 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
464
Derek Allard2067d1a2008-11-13 22:59:24 +0000465 // remove duplicates if the user already included the escape
466 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
Barry Mienydd671972010-10-04 16:33:58 +0200467 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 }
Barry Mienydd671972010-10-04 16:33:58 +0200469
Derek Allard2067d1a2008-11-13 22:59:24 +0000470 if (strpos($item, '.') !== FALSE)
471 {
Barry Mienydd671972010-10-04 16:33:58 +0200472 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
Derek Allard2067d1a2008-11-13 22:59:24 +0000473 }
474 else
475 {
476 $str = $this->_escape_char.$item.$this->_escape_char;
477 }
Barry Mienydd671972010-10-04 16:33:58 +0200478
Derek Allard2067d1a2008-11-13 22:59:24 +0000479 // remove duplicates if the user already included the escape
480 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
481 }
Barry Mienydd671972010-10-04 16:33:58 +0200482
Derek Allard2067d1a2008-11-13 22:59:24 +0000483 // --------------------------------------------------------------------
484
485 /**
486 * From Tables
487 *
488 * This function implicitly groups FROM tables so there is no confusion
489 * about operator precedence in harmony with SQL standards
490 *
491 * @access public
492 * @param type
493 * @return type
494 */
495 function _from_tables($tables)
496 {
497 if ( ! is_array($tables))
498 {
499 $tables = array($tables);
500 }
Barry Mienydd671972010-10-04 16:33:58 +0200501
Derek Allard2067d1a2008-11-13 22:59:24 +0000502 return '('.implode(', ', $tables).')';
503 }
504
505 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200506
Derek Allard2067d1a2008-11-13 22:59:24 +0000507 /**
508 * Insert statement
509 *
510 * Generates a platform-specific insert string from the supplied data
511 *
512 * @access public
513 * @param string the table name
514 * @param array the insert keys
515 * @param array the insert values
516 * @return string
517 */
518 function _insert($table, $keys, $values)
Barry Mienydd671972010-10-04 16:33:58 +0200519 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000520 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
521 }
Barry Mienydd671972010-10-04 16:33:58 +0200522
Derek Allard2067d1a2008-11-13 22:59:24 +0000523 // --------------------------------------------------------------------
524
525 /**
526 * Update statement
527 *
528 * Generates a platform-specific update string from the supplied data
529 *
530 * @access public
531 * @param string the table name
532 * @param array the update data
533 * @param array the where clause
534 * @param array the orderby clause
535 * @param array the limit clause
536 * @return string
537 */
538 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
539 {
540 foreach($values as $key => $val)
541 {
542 $valstr[] = $key." = ".$val;
543 }
Barry Mienydd671972010-10-04 16:33:58 +0200544
Derek Allard2067d1a2008-11-13 22:59:24 +0000545 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Barry Mienydd671972010-10-04 16:33:58 +0200546
Derek Allard2067d1a2008-11-13 22:59:24 +0000547 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
Barry Mienydd671972010-10-04 16:33:58 +0200548
Derek Allard2067d1a2008-11-13 22:59:24 +0000549 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
550
551 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
552
553 $sql .= $orderby.$limit;
Barry Mienydd671972010-10-04 16:33:58 +0200554
Derek Allard2067d1a2008-11-13 22:59:24 +0000555 return $sql;
556 }
557
Barry Mienydd671972010-10-04 16:33:58 +0200558
Derek Allard2067d1a2008-11-13 22:59:24 +0000559 // --------------------------------------------------------------------
560
561 /**
562 * Truncate statement
563 *
564 * Generates a platform-specific truncate string from the supplied data
565 * If the database does not support the truncate() command
566 * This function maps to "DELETE FROM table"
567 *
568 * @access public
569 * @param string the table name
570 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200571 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000572 function _truncate($table)
573 {
574 return $this->_delete($table);
575 }
Barry Mienydd671972010-10-04 16:33:58 +0200576
Derek Allard2067d1a2008-11-13 22:59:24 +0000577 // --------------------------------------------------------------------
578
579 /**
580 * Delete statement
581 *
582 * Generates a platform-specific delete string from the supplied data
583 *
584 * @access public
585 * @param string the table name
586 * @param array the where clause
587 * @param string the limit clause
588 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200589 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000590 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
591 {
592 $conditions = '';
593
594 if (count($where) > 0 OR count($like) > 0)
595 {
596 $conditions = "\nWHERE ";
597 $conditions .= implode("\n", $this->ar_where);
598
599 if (count($where) > 0 && count($like) > 0)
600 {
601 $conditions .= " AND ";
602 }
603 $conditions .= implode("\n", $like);
604 }
605
606 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Barry Mienydd671972010-10-04 16:33:58 +0200607
Derek Allard2067d1a2008-11-13 22:59:24 +0000608 return "DELETE FROM ".$table.$conditions.$limit;
609 }
Barry Mienydd671972010-10-04 16:33:58 +0200610
Derek Allard2067d1a2008-11-13 22:59:24 +0000611 // --------------------------------------------------------------------
612
613 /**
614 * Limit string
615 *
616 * Generates a platform-specific LIMIT clause
617 *
618 * @access public
619 * @param string the sql query string
620 * @param integer the number of rows to limit the query to
621 * @param integer the offset value
622 * @return string
623 */
624 function _limit($sql, $limit, $offset)
Barry Mienydd671972010-10-04 16:33:58 +0200625 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000626 if ($offset == 0)
627 {
628 $offset = '';
629 }
630 else
631 {
632 $offset .= ", ";
633 }
Barry Mienydd671972010-10-04 16:33:58 +0200634
Derek Allard2067d1a2008-11-13 22:59:24 +0000635 return $sql."LIMIT ".$offset.$limit;
636 }
637
638 // --------------------------------------------------------------------
639
640 /**
641 * Close DB Connection
642 *
643 * @access public
644 * @param resource
645 * @return void
646 */
647 function _close($conn_id)
648 {
649 @sqlite_close($conn_id);
650 }
651
652
653}
654
655
656/* End of file sqlite_driver.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000657/* Location: ./system/database/drivers/sqlite/sqlite_driver.php */