/halogy/database/drivers/mysqli/mysqli_driver.php

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