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

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

https://bitbucket.org/kurniawanchan83/codeigniter
PHP | 532 lines | 214 code | 80 blank | 238 comment | 22 complexity | e349e9242e89ce8d36563e883eea5c33 MD5 | raw file
  1. <?php
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 5.2.4 or newer
  6. *
  7. * NOTICE OF LICENSE
  8. *
  9. * Licensed under the Open Software License version 3.0
  10. *
  11. * This source file is subject to the Open Software License (OSL 3.0) that is
  12. * bundled with this package in the files license.txt / license.rst. It is
  13. * also available through the world wide web at this URL:
  14. * http://opensource.org/licenses/OSL-3.0
  15. * If you did not receive a copy of the license and are unable to obtain it
  16. * through the world wide web, please send an email to
  17. * licensing@ellislab.com so we can send you a copy immediately.
  18. *
  19. * @package CodeIgniter
  20. * @author EllisLab Dev Team
  21. * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
  22. * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  23. * @link http://codeigniter.com
  24. * @since Version 1.0
  25. * @filesource
  26. */
  27. defined('BASEPATH') OR exit('No direct script access allowed');
  28. /**
  29. * MySQL Database Adapter Class
  30. *
  31. * Note: _DB is an extender class that the app controller
  32. * creates dynamically based on whether the query builder
  33. * class is being used or not.
  34. *
  35. * @package CodeIgniter
  36. * @subpackage Drivers
  37. * @category Database
  38. * @author EllisLab Dev Team
  39. * @link http://codeigniter.com/user_guide/database/
  40. */
  41. class CI_DB_mysql_driver extends CI_DB {
  42. /**
  43. * Database driver
  44. *
  45. * @var string
  46. */
  47. public $dbdriver = 'mysql';
  48. /**
  49. * Compression flag
  50. *
  51. * @var bool
  52. */
  53. public $compress = FALSE;
  54. /**
  55. * DELETE hack flag
  56. *
  57. * Whether to use the MySQL "delete hack" which allows the number
  58. * of affected rows to be shown. Uses a preg_replace when enabled,
  59. * adding a bit more processing to all queries.
  60. *
  61. * @var bool
  62. */
  63. public $delete_hack = TRUE;
  64. // --------------------------------------------------------------------
  65. /**
  66. * Identifier escape character
  67. *
  68. * @var string
  69. */
  70. protected $_escape_char = '`';
  71. // --------------------------------------------------------------------
  72. /**
  73. * Class constructor
  74. *
  75. * @param array $params
  76. * @return void
  77. */
  78. public function __construct($params)
  79. {
  80. parent::__construct($params);
  81. if ( ! empty($this->port))
  82. {
  83. $this->hostname .= ':'.$this->port;
  84. }
  85. }
  86. // --------------------------------------------------------------------
  87. /**
  88. * Non-persistent database connection
  89. *
  90. * @param bool $persistent
  91. * @return resource
  92. */
  93. public function db_connect($persistent = FALSE)
  94. {
  95. $client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS;
  96. if ($this->encrypt === TRUE)
  97. {
  98. $client_flags = $client_flags | MYSQL_CLIENT_SSL;
  99. }
  100. $this->conn_id = ($persistent === TRUE)
  101. ? @mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags)
  102. : @mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags);
  103. // ----------------------------------------------------------------
  104. // Select the DB... assuming a database name is specified in the config file
  105. if ($this->database !== '' && ! $this->db_select())
  106. {
  107. log_message('error', 'Unable to select database: '.$this->database);
  108. return ($this->db_debug === TRUE)
  109. ? $this->display_error('db_unable_to_select', $this->database)
  110. : FALSE;
  111. }
  112. return $this->conn_id;
  113. }
  114. // --------------------------------------------------------------------
  115. /**
  116. * Persistent database connection
  117. *
  118. * @return resource
  119. */
  120. public function db_pconnect()
  121. {
  122. return $this->db_connect(TRUE);
  123. }
  124. // --------------------------------------------------------------------
  125. /**
  126. * Reconnect
  127. *
  128. * Keep / reestablish the db connection if no queries have been
  129. * sent for a length of time exceeding the server's idle timeout
  130. *
  131. * @return void
  132. */
  133. public function reconnect()
  134. {
  135. if (mysql_ping($this->conn_id) === FALSE)
  136. {
  137. $this->conn_id = FALSE;
  138. }
  139. }
  140. // --------------------------------------------------------------------
  141. /**
  142. * Select the database
  143. *
  144. * @param string $database
  145. * @return bool
  146. */
  147. public function db_select($database = '')
  148. {
  149. if ($database === '')
  150. {
  151. $database = $this->database;
  152. }
  153. if (@mysql_select_db($database, $this->conn_id))
  154. {
  155. $this->database = $database;
  156. return TRUE;
  157. }
  158. return FALSE;
  159. }
  160. // --------------------------------------------------------------------
  161. /**
  162. * Set client character set
  163. *
  164. * @param string $charset
  165. * @return bool
  166. */
  167. protected function _db_set_charset($charset)
  168. {
  169. return @mysql_set_charset($charset, $this->conn_id);
  170. }
  171. // --------------------------------------------------------------------
  172. /**
  173. * Database version number
  174. *
  175. * @return string
  176. */
  177. public function version()
  178. {
  179. if (isset($this->data_cache['version']))
  180. {
  181. return $this->data_cache['version'];
  182. }
  183. elseif ( ! $this->conn_id)
  184. {
  185. $this->initialize();
  186. }
  187. if ( ! $this->conn_id OR ($version = @mysql_get_server_info($this->conn_id)) === FALSE)
  188. {
  189. return FALSE;
  190. }
  191. return $this->data_cache['version'] = $version;
  192. }
  193. // --------------------------------------------------------------------
  194. /**
  195. * Execute the query
  196. *
  197. * @param string $sql an SQL query
  198. * @return mixed
  199. */
  200. protected function _execute($sql)
  201. {
  202. return @mysql_query($this->_prep_query($sql), $this->conn_id);
  203. }
  204. // --------------------------------------------------------------------
  205. /**
  206. * Prep the query
  207. *
  208. * If needed, each database adapter can prep the query string
  209. *
  210. * @param string $sql an SQL query
  211. * @return string
  212. */
  213. protected function _prep_query($sql)
  214. {
  215. // mysql_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack
  216. // modifies the query so that it a proper number of affected rows is returned.
  217. if ($this->delete_hack === TRUE && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
  218. {
  219. return trim($sql).' WHERE 1=1';
  220. }
  221. return $sql;
  222. }
  223. // --------------------------------------------------------------------
  224. /**
  225. * Begin Transaction
  226. *
  227. * @param bool $test_mode
  228. * @return bool
  229. */
  230. public function trans_begin($test_mode = FALSE)
  231. {
  232. // When transactions are nested we only begin/commit/rollback the outermost ones
  233. if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
  234. {
  235. return TRUE;
  236. }
  237. // Reset the transaction failure flag.
  238. // If the $test_mode flag is set to TRUE transactions will be rolled back
  239. // even if the queries produce a successful result.
  240. $this->_trans_failure = ($test_mode === TRUE);
  241. $this->simple_query('SET AUTOCOMMIT=0');
  242. $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
  243. return TRUE;
  244. }
  245. // --------------------------------------------------------------------
  246. /**
  247. * Commit Transaction
  248. *
  249. * @return bool
  250. */
  251. public function trans_commit()
  252. {
  253. // When transactions are nested we only begin/commit/rollback the outermost ones
  254. if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
  255. {
  256. return TRUE;
  257. }
  258. $this->simple_query('COMMIT');
  259. $this->simple_query('SET AUTOCOMMIT=1');
  260. return TRUE;
  261. }
  262. // --------------------------------------------------------------------
  263. /**
  264. * Rollback Transaction
  265. *
  266. * @return bool
  267. */
  268. public function trans_rollback()
  269. {
  270. // When transactions are nested we only begin/commit/rollback the outermost ones
  271. if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
  272. {
  273. return TRUE;
  274. }
  275. $this->simple_query('ROLLBACK');
  276. $this->simple_query('SET AUTOCOMMIT=1');
  277. return TRUE;
  278. }
  279. // --------------------------------------------------------------------
  280. /**
  281. * Platform-dependant string escape
  282. *
  283. * @param string
  284. * @return string
  285. */
  286. protected function _escape_str($str)
  287. {
  288. return is_resource($this->conn_id)
  289. ? mysql_real_escape_string($str, $this->conn_id)
  290. : addslashes($str);
  291. }
  292. // --------------------------------------------------------------------
  293. /**
  294. * Affected Rows
  295. *
  296. * @return int
  297. */
  298. public function affected_rows()
  299. {
  300. return @mysql_affected_rows($this->conn_id);
  301. }
  302. // --------------------------------------------------------------------
  303. /**
  304. * Insert ID
  305. *
  306. * @return int
  307. */
  308. public function insert_id()
  309. {
  310. return @mysql_insert_id($this->conn_id);
  311. }
  312. // --------------------------------------------------------------------
  313. /**
  314. * List table query
  315. *
  316. * Generates a platform-specific query string so that the table names can be fetched
  317. *
  318. * @param bool $prefix_limit
  319. * @return string
  320. */
  321. protected function _list_tables($prefix_limit = FALSE)
  322. {
  323. $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
  324. if ($prefix_limit !== FALSE && $this->dbprefix !== '')
  325. {
  326. return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
  327. }
  328. return $sql;
  329. }
  330. // --------------------------------------------------------------------
  331. /**
  332. * Show column query
  333. *
  334. * Generates a platform-specific query string so that the column names can be fetched
  335. *
  336. * @param string $table
  337. * @return string
  338. */
  339. protected function _list_columns($table = '')
  340. {
  341. return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
  342. }
  343. // --------------------------------------------------------------------
  344. /**
  345. * Returns an object with field data
  346. *
  347. * @param string $table
  348. * @return array
  349. */
  350. public function field_data($table = '')
  351. {
  352. if ($table === '')
  353. {
  354. return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
  355. }
  356. if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
  357. {
  358. return FALSE;
  359. }
  360. $query = $query->result_object();
  361. $retval = array();
  362. for ($i = 0, $c = count($query); $i < $c; $i++)
  363. {
  364. $retval[$i] = new stdClass();
  365. $retval[$i]->name = $query[$i]->Field;
  366. sscanf($query[$i]->Type, '%[a-z](%d)',
  367. $retval[$i]->type,
  368. $retval[$i]->max_length
  369. );
  370. $retval[$i]->default = $query[$i]->Default;
  371. $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
  372. }
  373. return $retval;
  374. }
  375. // --------------------------------------------------------------------
  376. /**
  377. * Error
  378. *
  379. * Returns an array containing code and message of the last
  380. * database error that has occured.
  381. *
  382. * @return array
  383. */
  384. public function error()
  385. {
  386. return array('code' => mysql_errno($this->conn_id), 'message' => mysql_error($this->conn_id));
  387. }
  388. // --------------------------------------------------------------------
  389. /**
  390. * Update_Batch statement
  391. *
  392. * Generates a platform-specific batch update string from the supplied data
  393. *
  394. * @param string $table Table name
  395. * @param array $values Update data
  396. * @param string $index WHERE key
  397. * @return string
  398. */
  399. protected function _update_batch($table, $values, $index)
  400. {
  401. $ids = array();
  402. foreach ($values as $key => $val)
  403. {
  404. $ids[] = $val[$index];
  405. foreach (array_keys($val) as $field)
  406. {
  407. if ($field !== $index)
  408. {
  409. $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
  410. }
  411. }
  412. }
  413. $cases = '';
  414. foreach ($final as $k => $v)
  415. {
  416. $cases .= $k." = CASE \n"
  417. .implode("\n", $v)."\n"
  418. .'ELSE '.$k.' END, ';
  419. }
  420. $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
  421. return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
  422. }
  423. // --------------------------------------------------------------------
  424. /**
  425. * FROM tables
  426. *
  427. * Groups tables in FROM clauses if needed, so there is no confusion
  428. * about operator precedence.
  429. *
  430. * @return string
  431. */
  432. protected function _from_tables()
  433. {
  434. if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
  435. {
  436. return '('.implode(', ', $this->qb_from).')';
  437. }
  438. return implode(', ', $this->qb_from);
  439. }
  440. // --------------------------------------------------------------------
  441. /**
  442. * Close DB Connection
  443. *
  444. * @return void
  445. */
  446. protected function _close()
  447. {
  448. @mysql_close($this->conn_id);
  449. }
  450. }
  451. /* End of file mysql_driver.php */
  452. /* Location: ./system/database/drivers/mysql/mysql_driver.php */