blob: 104a3bc362a055b7a63a4b3307574508ce277616 [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
9 * @copyright Copyright (c) 2008, EllisLab, Inc.
10 * @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';
36
37 // 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
41 var $_like_escape_str = " ESCAPE '%s' ";
42 var $_like_escape_chr = '!';
43
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
57 */
58 function db_connect()
59 {
60 if ( ! $conn_id = @sqlite_open($this->database, FILE_WRITE_MODE, $error))
61 {
62 log_message('error', $error);
63
64 if ($this->db_debug)
65 {
66 $this->display_error($error, '', TRUE);
67 }
68
69 return FALSE;
70 }
71
72 return $conn_id;
73 }
74
75 // --------------------------------------------------------------------
76
77 /**
78 * Persistent database connection
79 *
80 * @access private called by the base class
81 * @return resource
82 */
83 function db_pconnect()
84 {
85 if ( ! $conn_id = @sqlite_popen($this->database, FILE_WRITE_MODE, $error))
86 {
87 log_message('error', $error);
88
89 if ($this->db_debug)
90 {
91 $this->display_error($error, '', TRUE);
92 }
93
94 return FALSE;
95 }
96
97 return $conn_id;
98 }
99
100 // --------------------------------------------------------------------
101
102 /**
103 * Select the database
104 *
105 * @access private called by the base class
106 * @return resource
107 */
108 function db_select()
109 {
110 return TRUE;
111 }
112
113 // --------------------------------------------------------------------
114
115 /**
116 * Set client character set
117 *
118 * @access public
119 * @param string
120 * @param string
121 * @return resource
122 */
123 function db_set_charset($charset, $collation)
124 {
125 // @todo - add support if needed
126 return TRUE;
127 }
128
129 // --------------------------------------------------------------------
130
131 /**
132 * Version number query string
133 *
134 * @access public
135 * @return string
136 */
137 function _version()
138 {
139 return sqlite_libversion();
140 }
141
142 // --------------------------------------------------------------------
143
144 /**
145 * Execute the query
146 *
147 * @access private called by the base class
148 * @param string an SQL query
149 * @return resource
150 */
151 function _execute($sql)
152 {
153 $sql = $this->_prep_query($sql);
154 return @sqlite_query($this->conn_id, $sql);
155 }
156
157 // --------------------------------------------------------------------
158
159 /**
160 * Prep the query
161 *
162 * If needed, each database adapter can prep the query string
163 *
164 * @access private called by execute()
165 * @param string an SQL query
166 * @return string
167 */
168 function _prep_query($sql)
169 {
170 return $sql;
171 }
172
173 // --------------------------------------------------------------------
174
175 /**
176 * Begin Transaction
177 *
178 * @access public
179 * @return bool
180 */
181 function trans_begin($test_mode = FALSE)
182 {
183 if ( ! $this->trans_enabled)
184 {
185 return TRUE;
186 }
187
188 // When transactions are nested we only begin/commit/rollback the outermost ones
189 if ($this->_trans_depth > 0)
190 {
191 return TRUE;
192 }
193
194 // Reset the transaction failure flag.
195 // If the $test_mode flag is set to TRUE transactions will be rolled back
196 // even if the queries produce a successful result.
197 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
198
199 $this->simple_query('BEGIN TRANSACTION');
200 return TRUE;
201 }
202
203 // --------------------------------------------------------------------
204
205 /**
206 * Commit Transaction
207 *
208 * @access public
209 * @return bool
210 */
211 function trans_commit()
212 {
213 if ( ! $this->trans_enabled)
214 {
215 return TRUE;
216 }
217
218 // When transactions are nested we only begin/commit/rollback the outermost ones
219 if ($this->_trans_depth > 0)
220 {
221 return TRUE;
222 }
223
224 $this->simple_query('COMMIT');
225 return TRUE;
226 }
227
228 // --------------------------------------------------------------------
229
230 /**
231 * Rollback Transaction
232 *
233 * @access public
234 * @return bool
235 */
236 function trans_rollback()
237 {
238 if ( ! $this->trans_enabled)
239 {
240 return TRUE;
241 }
242
243 // When transactions are nested we only begin/commit/rollback the outermost ones
244 if ($this->_trans_depth > 0)
245 {
246 return TRUE;
247 }
248
249 $this->simple_query('ROLLBACK');
250 return TRUE;
251 }
252
253 // --------------------------------------------------------------------
254
255 /**
256 * Escape String
257 *
258 * @access public
259 * @param string
Derek Jonese4ed5832009-02-20 21:44:59 +0000260 * @param bool whether or not the string will be used in a LIKE condition
Derek Allard2067d1a2008-11-13 22:59:24 +0000261 * @return string
262 */
Derek Jonese4ed5832009-02-20 21:44:59 +0000263 function escape_str($str, $like = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000264 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000265 if (is_array($str))
266 {
267 foreach($str as $key => $val)
268 {
269 $str[$key] = $this->escape_str($val, $like);
270 }
271
272 return $str;
273 }
274
275 $str = sqlite_escape_string($str);
276
277 // escape LIKE condition wildcards
278 if ($like === TRUE)
279 {
280 $str = str_replace( array('%', '_', $this->_like_escape_chr),
281 array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
282 $str);
283 }
284
285 return $str;
Derek Allard2067d1a2008-11-13 22:59:24 +0000286 }
287
288 // --------------------------------------------------------------------
289
290 /**
291 * Affected Rows
292 *
293 * @access public
294 * @return integer
295 */
296 function affected_rows()
297 {
298 return sqlite_changes($this->conn_id);
299 }
300
301 // --------------------------------------------------------------------
302
303 /**
304 * Insert ID
305 *
306 * @access public
307 * @return integer
308 */
309 function insert_id()
310 {
311 return @sqlite_last_insert_rowid($this->conn_id);
312 }
313
314 // --------------------------------------------------------------------
315
316 /**
317 * "Count All" query
318 *
319 * Generates a platform-specific query string that counts all records in
320 * the specified database
321 *
322 * @access public
323 * @param string
324 * @return string
325 */
326 function count_all($table = '')
327 {
328 if ($table == '')
Derek Allarde37ab382009-02-03 16:13:57 +0000329 {
330 return 0;
331 }
332
333 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
Derek Allard2067d1a2008-11-13 22:59:24 +0000334
335 if ($query->num_rows() == 0)
Derek Allarde37ab382009-02-03 16:13:57 +0000336 {
337 return 0;
338 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000339
340 $row = $query->row();
Derek Allarde37ab382009-02-03 16:13:57 +0000341 return (int) $row->numrows;
Derek Allard2067d1a2008-11-13 22:59:24 +0000342 }
343
344 // --------------------------------------------------------------------
345
346 /**
347 * List table query
348 *
349 * Generates a platform-specific query string so that the table names can be fetched
350 *
351 * @access private
352 * @param boolean
353 * @return string
354 */
355 function _list_tables($prefix_limit = FALSE)
356 {
357 $sql = "SELECT name from sqlite_master WHERE type='table'";
358
359 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
360 {
361 $sql .= " AND 'name' LIKE '".$this->dbprefix."%'";
362 }
363 return $sql;
364 }
365
366 // --------------------------------------------------------------------
367
368 /**
369 * Show column query
370 *
371 * Generates a platform-specific query string so that the column names can be fetched
372 *
373 * @access public
374 * @param string the table name
375 * @return string
376 */
377 function _list_columns($table = '')
378 {
379 // Not supported
380 return FALSE;
381 }
382
383 // --------------------------------------------------------------------
384
385 /**
386 * Field data query
387 *
388 * Generates a platform-specific query so that the column data can be retrieved
389 *
390 * @access public
391 * @param string the table name
392 * @return object
393 */
394 function _field_data($table)
395 {
396 return "SELECT * FROM ".$table." LIMIT 1";
397 }
398
399 // --------------------------------------------------------------------
400
401 /**
402 * The error message string
403 *
404 * @access private
405 * @return string
406 */
407 function _error_message()
408 {
409 return sqlite_error_string(sqlite_last_error($this->conn_id));
410 }
411
412 // --------------------------------------------------------------------
413
414 /**
415 * The error message number
416 *
417 * @access private
418 * @return integer
419 */
420 function _error_number()
421 {
422 return sqlite_last_error($this->conn_id);
423 }
424
425 // --------------------------------------------------------------------
426
427 /**
428 * Escape the SQL Identifiers
429 *
430 * This function escapes column and table names
431 *
432 * @access private
433 * @param string
434 * @return string
435 */
436 function _escape_identifiers($item)
437 {
438 if ($this->_escape_char == '')
439 {
440 return $item;
441 }
442
443 foreach ($this->_reserved_identifiers as $id)
444 {
445 if (strpos($item, '.'.$id) !== FALSE)
446 {
447 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
448
449 // remove duplicates if the user already included the escape
450 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
451 }
452 }
453
454 if (strpos($item, '.') !== FALSE)
455 {
456 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
457 }
458 else
459 {
460 $str = $this->_escape_char.$item.$this->_escape_char;
461 }
462
463 // remove duplicates if the user already included the escape
464 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
465 }
466
467 // --------------------------------------------------------------------
468
469 /**
470 * From Tables
471 *
472 * This function implicitly groups FROM tables so there is no confusion
473 * about operator precedence in harmony with SQL standards
474 *
475 * @access public
476 * @param type
477 * @return type
478 */
479 function _from_tables($tables)
480 {
481 if ( ! is_array($tables))
482 {
483 $tables = array($tables);
484 }
485
486 return '('.implode(', ', $tables).')';
487 }
488
489 // --------------------------------------------------------------------
490
491 /**
492 * Insert statement
493 *
494 * Generates a platform-specific insert string from the supplied data
495 *
496 * @access public
497 * @param string the table name
498 * @param array the insert keys
499 * @param array the insert values
500 * @return string
501 */
502 function _insert($table, $keys, $values)
503 {
504 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
505 }
506
507 // --------------------------------------------------------------------
508
509 /**
510 * Update statement
511 *
512 * Generates a platform-specific update string from the supplied data
513 *
514 * @access public
515 * @param string the table name
516 * @param array the update data
517 * @param array the where clause
518 * @param array the orderby clause
519 * @param array the limit clause
520 * @return string
521 */
522 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
523 {
524 foreach($values as $key => $val)
525 {
526 $valstr[] = $key." = ".$val;
527 }
528
529 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
530
531 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
532
533 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
534
535 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
536
537 $sql .= $orderby.$limit;
538
539 return $sql;
540 }
541
542
543 // --------------------------------------------------------------------
544
545 /**
546 * Truncate statement
547 *
548 * Generates a platform-specific truncate string from the supplied data
549 * If the database does not support the truncate() command
550 * This function maps to "DELETE FROM table"
551 *
552 * @access public
553 * @param string the table name
554 * @return string
555 */
556 function _truncate($table)
557 {
558 return $this->_delete($table);
559 }
560
561 // --------------------------------------------------------------------
562
563 /**
564 * Delete statement
565 *
566 * Generates a platform-specific delete string from the supplied data
567 *
568 * @access public
569 * @param string the table name
570 * @param array the where clause
571 * @param string the limit clause
572 * @return string
573 */
574 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
575 {
576 $conditions = '';
577
578 if (count($where) > 0 OR count($like) > 0)
579 {
580 $conditions = "\nWHERE ";
581 $conditions .= implode("\n", $this->ar_where);
582
583 if (count($where) > 0 && count($like) > 0)
584 {
585 $conditions .= " AND ";
586 }
587 $conditions .= implode("\n", $like);
588 }
589
590 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
591
592 return "DELETE FROM ".$table.$conditions.$limit;
593 }
594
595 // --------------------------------------------------------------------
596
597 /**
598 * Limit string
599 *
600 * Generates a platform-specific LIMIT clause
601 *
602 * @access public
603 * @param string the sql query string
604 * @param integer the number of rows to limit the query to
605 * @param integer the offset value
606 * @return string
607 */
608 function _limit($sql, $limit, $offset)
609 {
610 if ($offset == 0)
611 {
612 $offset = '';
613 }
614 else
615 {
616 $offset .= ", ";
617 }
618
619 return $sql."LIMIT ".$offset.$limit;
620 }
621
622 // --------------------------------------------------------------------
623
624 /**
625 * Close DB Connection
626 *
627 * @access public
628 * @param resource
629 * @return void
630 */
631 function _close($conn_id)
632 {
633 @sqlite_close($conn_id);
634 }
635
636
637}
638
639
640/* End of file sqlite_driver.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000641/* Location: ./system/database/drivers/sqlite/sqlite_driver.php */