PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/system/database/drivers/postgre/postgre_driver.php

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