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

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

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