PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/system/database/drivers/mysql/mysql_driver.php

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