PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/system/database/drivers/mysqli/mysqli_driver.php

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