/halogy/database/drivers/mysql/mysql_driver.php

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