PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/system/database/drivers/sqlite/sqlite_driver.php

http://php-personal-budget.googlecode.com/
PHP | 632 lines | 236 code | 98 blank | 298 comment | 28 complexity | f882f107729151ea3f459b7963f9188e MD5 | raw file
  1. <?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) 2006, 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. * SQLite Database Adapter Class
  18. *
  19. * Note: _DB is an extender class that the app controller
  20. * creates dynamically based on whether the active record
  21. * class is being used or not.
  22. *
  23. * @package CodeIgniter
  24. * @subpackage Drivers
  25. * @category Database
  26. * @author ExpressionEngine Dev Team
  27. * @link http://codeigniter.com/user_guide/database/
  28. */
  29. class CI_DB_sqlite_driver extends CI_DB {
  30. /**
  31. * The syntax to count rows is slightly different across different
  32. * database engines, so this string appears in each driver and is
  33. * used for the count_all() and count_all_results() functions.
  34. */
  35. var $_count_string = "SELECT COUNT(*) AS ";
  36. var $_random_keyword = ' Random()'; // database specific random keyword
  37. /**
  38. * Non-persistent database connection
  39. *
  40. * @access private called by the base class
  41. * @return resource
  42. */
  43. function db_connect()
  44. {
  45. if ( ! $conn_id = @sqlite_open($this->database, 0666, $error))
  46. {
  47. log_message('error', $error);
  48. if ($this->db_debug)
  49. {
  50. $this->display_error($error, '', TRUE);
  51. }
  52. return FALSE;
  53. }
  54. return $conn_id;
  55. }
  56. // --------------------------------------------------------------------
  57. /**
  58. * Persistent database connection
  59. *
  60. * @access private called by the base class
  61. * @return resource
  62. */
  63. function db_pconnect()
  64. {
  65. if ( ! $conn_id = @sqlite_popen($this->database, 0666, $error))
  66. {
  67. log_message('error', $error);
  68. if ($this->db_debug)
  69. {
  70. $this->display_error($error, '', TRUE);
  71. }
  72. return FALSE;
  73. }
  74. return $conn_id;
  75. }
  76. // --------------------------------------------------------------------
  77. /**
  78. * Select the database
  79. *
  80. * @access private called by the base class
  81. * @return resource
  82. */
  83. function db_select()
  84. {
  85. return TRUE;
  86. }
  87. // --------------------------------------------------------------------
  88. /**
  89. * Set client character set
  90. *
  91. * @access public
  92. * @param string
  93. * @param string
  94. * @return resource
  95. */
  96. function db_set_charset($charset, $collation)
  97. {
  98. // TODO - add support if needed
  99. return TRUE;
  100. }
  101. // --------------------------------------------------------------------
  102. /**
  103. * Version number query string
  104. *
  105. * @access public
  106. * @return string
  107. */
  108. function _version()
  109. {
  110. return sqlite_libversion();
  111. }
  112. // --------------------------------------------------------------------
  113. /**
  114. * Execute the query
  115. *
  116. * @access private called by the base class
  117. * @param string an SQL query
  118. * @return resource
  119. */
  120. function _execute($sql)
  121. {
  122. $sql = $this->_prep_query($sql);
  123. return @sqlite_query($this->conn_id, $sql);
  124. }
  125. // --------------------------------------------------------------------
  126. /**
  127. * Prep the query
  128. *
  129. * If needed, each database adapter can prep the query string
  130. *
  131. * @access private called by execute()
  132. * @param string an SQL query
  133. * @return string
  134. */
  135. function _prep_query($sql)
  136. {
  137. return $sql;
  138. }
  139. // --------------------------------------------------------------------
  140. /**
  141. * Begin Transaction
  142. *
  143. * @access public
  144. * @return bool
  145. */
  146. function trans_begin($test_mode = FALSE)
  147. {
  148. if ( ! $this->trans_enabled)
  149. {
  150. return TRUE;
  151. }
  152. // When transactions are nested we only begin/commit/rollback the outermost ones
  153. if ($this->_trans_depth > 0)
  154. {
  155. return TRUE;
  156. }
  157. // Reset the transaction failure flag.
  158. // If the $test_mode flag is set to TRUE transactions will be rolled back
  159. // even if the queries produce a successful result.
  160. $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
  161. $this->simple_query('BEGIN TRANSACTION');
  162. return TRUE;
  163. }
  164. // --------------------------------------------------------------------
  165. /**
  166. * Commit Transaction
  167. *
  168. * @access public
  169. * @return bool
  170. */
  171. function trans_commit()
  172. {
  173. if ( ! $this->trans_enabled)
  174. {
  175. return TRUE;
  176. }
  177. // When transactions are nested we only begin/commit/rollback the outermost ones
  178. if ($this->_trans_depth > 0)
  179. {
  180. return TRUE;
  181. }
  182. $this->simple_query('COMMIT');
  183. return TRUE;
  184. }
  185. // --------------------------------------------------------------------
  186. /**
  187. * Rollback Transaction
  188. *
  189. * @access public
  190. * @return bool
  191. */
  192. function trans_rollback()
  193. {
  194. if ( ! $this->trans_enabled)
  195. {
  196. return TRUE;
  197. }
  198. // When transactions are nested we only begin/commit/rollback the outermost ones
  199. if ($this->_trans_depth > 0)
  200. {
  201. return TRUE;
  202. }
  203. $this->simple_query('ROLLBACK');
  204. return TRUE;
  205. }
  206. // --------------------------------------------------------------------
  207. /**
  208. * Escape String
  209. *
  210. * @access public
  211. * @param string
  212. * @return string
  213. */
  214. function escape_str($str)
  215. {
  216. return sqlite_escape_string($str);
  217. }
  218. // --------------------------------------------------------------------
  219. /**
  220. * Affected Rows
  221. *
  222. * @access public
  223. * @return integer
  224. */
  225. function affected_rows()
  226. {
  227. return sqlite_changes($this->conn_id);
  228. }
  229. // --------------------------------------------------------------------
  230. /**
  231. * Insert ID
  232. *
  233. * @access public
  234. * @return integer
  235. */
  236. function insert_id()
  237. {
  238. return @sqlite_last_insert_rowid($this->conn_id);
  239. }
  240. // --------------------------------------------------------------------
  241. /**
  242. * "Count All" query
  243. *
  244. * Generates a platform-specific query string that counts all records in
  245. * the specified database
  246. *
  247. * @access public
  248. * @param string
  249. * @return string
  250. */
  251. function count_all($table = '')
  252. {
  253. if ($table == '')
  254. return '0';
  255. $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows'). " FROM " . $this->_protect_identifiers($this->dbprefix.$table));
  256. if ($query->num_rows() == 0)
  257. return '0';
  258. $row = $query->row();
  259. return $row->numrows;
  260. }
  261. // --------------------------------------------------------------------
  262. /**
  263. * List table query
  264. *
  265. * Generates a platform-specific query string so that the table names can be fetched
  266. *
  267. * @access private
  268. * @param boolean
  269. * @return string
  270. */
  271. function _list_tables($prefix_limit = FALSE)
  272. {
  273. $sql = "SELECT name from sqlite_master WHERE type='table'";
  274. if ($prefix_limit !== FALSE AND $this->dbprefix != '')
  275. {
  276. $sql .= " AND 'name' LIKE '".$this->dbprefix."%'";
  277. }
  278. return $sql;
  279. }
  280. // --------------------------------------------------------------------
  281. /**
  282. * Show column query
  283. *
  284. * Generates a platform-specific query string so that the column names can be fetched
  285. *
  286. * @access public
  287. * @param string the table name
  288. * @return string
  289. */
  290. function _list_columns($table = '')
  291. {
  292. // Not supported
  293. return FALSE;
  294. }
  295. // --------------------------------------------------------------------
  296. /**
  297. * Field data query
  298. *
  299. * Generates a platform-specific query so that the column data can be retrieved
  300. *
  301. * @access public
  302. * @param string the table name
  303. * @return object
  304. */
  305. function _field_data($table)
  306. {
  307. return "SELECT * FROM ".$this->_escape_table($table)." LIMIT 1";
  308. }
  309. // --------------------------------------------------------------------
  310. /**
  311. * The error message string
  312. *
  313. * @access private
  314. * @return string
  315. */
  316. function _error_message()
  317. {
  318. return sqlite_error_string(sqlite_last_error($this->conn_id));
  319. }
  320. // --------------------------------------------------------------------
  321. /**
  322. * The error message number
  323. *
  324. * @access private
  325. * @return integer
  326. */
  327. function _error_number()
  328. {
  329. return sqlite_last_error($this->conn_id);
  330. }
  331. // --------------------------------------------------------------------
  332. /**
  333. * Escape Table Name
  334. *
  335. * This function adds backticks if the table name has a period
  336. * in it. Some DBs will get cranky unless periods are escaped
  337. *
  338. * @access private
  339. * @param string the table name
  340. * @return string
  341. */
  342. function _escape_table($table)
  343. {
  344. if (stristr($table, '.'))
  345. {
  346. $table = preg_replace("/\./", "`.`", $table);
  347. }
  348. return $table;
  349. }
  350. // --------------------------------------------------------------------
  351. /**
  352. * Protect Identifiers
  353. *
  354. * This function adds backticks if appropriate based on db type
  355. *
  356. * @access private
  357. * @param mixed the item to escape
  358. * @param boolean only affect the first word
  359. * @return mixed the item with backticks
  360. */
  361. function _protect_identifiers($item, $first_word_only = FALSE)
  362. {
  363. if (is_array($item))
  364. {
  365. $escaped_array = array();
  366. foreach($item as $k=>$v)
  367. {
  368. $escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v, $first_word_only);
  369. }
  370. return $escaped_array;
  371. }
  372. // This function may get "item1 item2" as a string, and so
  373. // we may need "`item1` `item2`" and not "`item1 item2`"
  374. if (ctype_alnum($item) === FALSE)
  375. {
  376. // This function may get "field >= 1", and need it to return "`field` >= 1"
  377. $lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
  378. $item = preg_replace('/(^'.$lbound.')([\w\d\-\_]+?)(\s|\)|$)/iS', '$1`$2`$3', $item);
  379. }
  380. else
  381. {
  382. return "`{$item}`";
  383. }
  384. $exceptions = array('AS', '/', '-', '%', '+', '*');
  385. foreach ($exceptions as $exception)
  386. {
  387. if (stristr($item, " `{$exception}` ") !== FALSE)
  388. {
  389. $item = preg_replace('/ `('.preg_quote($exception).')` /i', ' $1 ', $item);
  390. }
  391. }
  392. return $item;
  393. }
  394. // --------------------------------------------------------------------
  395. /**
  396. * From Tables
  397. *
  398. * This function implicitly groups FROM tables so there is no confusion
  399. * about operator precedence in harmony with SQL standards
  400. *
  401. * @access public
  402. * @param type
  403. * @return type
  404. */
  405. function _from_tables($tables)
  406. {
  407. if (! is_array($tables))
  408. {
  409. $tables = array($tables);
  410. }
  411. return '('.implode(', ', $tables).')';
  412. }
  413. // --------------------------------------------------------------------
  414. /**
  415. * Insert statement
  416. *
  417. * Generates a platform-specific insert string from the supplied data
  418. *
  419. * @access public
  420. * @param string the table name
  421. * @param array the insert keys
  422. * @param array the insert values
  423. * @return string
  424. */
  425. function _insert($table, $keys, $values)
  426. {
  427. return "INSERT INTO ".$this->_escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
  428. }
  429. // --------------------------------------------------------------------
  430. /**
  431. * Update statement
  432. *
  433. * Generates a platform-specific update string from the supplied data
  434. *
  435. * @access public
  436. * @param string the table name
  437. * @param array the update data
  438. * @param array the where clause
  439. * @param array the orderby clause
  440. * @param array the limit clause
  441. * @return string
  442. */
  443. function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
  444. {
  445. foreach($values as $key => $val)
  446. {
  447. $valstr[] = $key." = ".$val;
  448. }
  449. $limit = (!$limit) ? '' : ' LIMIT '.$limit;
  450. $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
  451. return "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where).$orderby.$limit;
  452. }
  453. // --------------------------------------------------------------------
  454. /**
  455. * Truncate statement
  456. *
  457. * Generates a platform-specific truncate string from the supplied data
  458. * If the database does not support the truncate() command
  459. * This function maps to "DELETE FROM table"
  460. *
  461. * @access public
  462. * @param string the table name
  463. * @return string
  464. */
  465. function _truncate($table)
  466. {
  467. return $this->_delete($table);
  468. }
  469. // --------------------------------------------------------------------
  470. /**
  471. * Delete statement
  472. *
  473. * Generates a platform-specific delete string from the supplied data
  474. *
  475. * @access public
  476. * @param string the table name
  477. * @param array the where clause
  478. * @param string the limit clause
  479. * @return string
  480. */
  481. function _delete($table, $where = array(), $like = array(), $limit = FALSE)
  482. {
  483. $conditions = '';
  484. if (count($where) > 0 || count($like) > 0)
  485. {
  486. $conditions = "\nWHERE ";
  487. $conditions .= implode("\n", $this->ar_where);
  488. if (count($where) > 0 && count($like) > 0)
  489. {
  490. $conditions .= " AND ";
  491. }
  492. $conditions .= implode("\n", $like);
  493. }
  494. $limit = (!$limit) ? '' : ' LIMIT '.$limit;
  495. return "DELETE FROM ".$table.$conditions.$limit;
  496. }
  497. // --------------------------------------------------------------------
  498. /**
  499. * Limit string
  500. *
  501. * Generates a platform-specific LIMIT clause
  502. *
  503. * @access public
  504. * @param string the sql query string
  505. * @param integer the number of rows to limit the query to
  506. * @param integer the offset value
  507. * @return string
  508. */
  509. function _limit($sql, $limit, $offset)
  510. {
  511. if ($offset == 0)
  512. {
  513. $offset = '';
  514. }
  515. else
  516. {
  517. $offset .= ", ";
  518. }
  519. return $sql."LIMIT ".$offset.$limit;
  520. }
  521. // --------------------------------------------------------------------
  522. /**
  523. * Close DB Connection
  524. *
  525. * @access public
  526. * @param resource
  527. * @return void
  528. */
  529. function _close($conn_id)
  530. {
  531. @sqlite_close($conn_id);
  532. }
  533. }
  534. ?>