/halogy/database/drivers/postgre/postgre_driver.php

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