Source for file db-postgres.php

Documentation is available at db-postgres.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: db-postgres.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for POSTGRES database access. */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package database */* POSTGRES database interface
  27. * This is a database interface class. It is an impedance-matcher
  28. * between the high-level Phplib functions for accessing data, and
  29. * the specific functions suplpied by Php to access a particular
  30. * flavour of databse such as Postgres, MS-SQL Server, Sybase etc.
  31. * @package database
  32. * @access private
  33. */
  34. class db_postgres extends database {
  35. /** Constructor */
  36.  
  37. function db_postgres($name="", $user="", $passwd="", $host="", $port=0, $enc="", $datestyle="") {
  38. $this->database($name, $user, $passwd, $host, $port, $enc, $datestyle);
  39. $this->type = "postgres";
  40. }
  41. // ....................................................................
  42. /**
  43. * Connect to the database.
  44. * @param boolean $persistent Whether to connect persistently or not
  45. * @return boolean Status true if connected successfully
  46. */
  47. function connect($persistent=NOT_PERSISTENT) {
  48. if (!$this->connected) {
  49. $connstr = "";
  50. if ($this->host != "") $connstr .= " host=" . $this->host;
  51. if ($this->port != 0 ) $connstr .= " port=" . $this->port;
  52. $connstr .= " dbname=" . $this->name;
  53. $connstr .= " user=" . $this->user;
  54. if ($this->passwd != "") $connstr .= " password=" . $this->passwd;
  55. $connstr = trim($connstr);
  56. if ($persistent)
  57. $this->dbid = pg_pconnect("$connstr");
  58. else
  59. $this->dbid = pg_connect("$connstr");
  60. if ($this->dbid) {
  61. if ($this->datestyle != "") $this->set_datestyle($this->datestyle);
  62. if ($this->enc != "") $this->set_char_encoding($this->enc);
  63. $this->connected = true;
  64. }
  65. }
  66. return $this->connected;
  67. }
  68. // ....................................................................
  69. /** Disconnect from the database, if connected. */
  70.  
  71. function disconnect() {
  72. if (pg_close($this->dbid))
  73. $this->connected = false;
  74. }
  75. // ....................................................................
  76. /**
  77. * Execute a query on the connected database.
  78. * @param string $sql The SQL query to execute on the database
  79. * @return resource A database query resource ID, or false if query failed
  80. */
  81. function query($sql) {
  82. $sql = $this->convert_boolean_syntax($sql);
  83. $this->timer->restart();
  84. if (PHP_VERSION >= 4.2) {
  85. $rid = pg_query($this->dbid, $sql);
  86. }
  87. else {
  88. $rid = pg_exec($this->dbid, $sql);
  89. }
  90. $this->timer->stop();
  91. $this->executable_sql = $sql;
  92. $this->rid = $rid;
  93. $this->query_report();
  94. return $rid;
  95. }
  96. // ....................................................................
  97. /**
  98. * Return the number of rows returned by a SELECT query.
  99. * @param resource $rid The resource ID for the executed query
  100. * @return integer The number of rows returned by the query
  101. */
  102. function numrows($rid) {
  103. if (PHP_VERSION >= 4.2) return pg_num_rows($rid);
  104. else return pg_numrows($rid);
  105. }
  106. // ....................................................................
  107. /**
  108. * Return the number of rows affected by a query.
  109. * @param resource $rid The resource ID for the executed query
  110. * @return integer The number of rows affected by the query
  111. */
  112. function affectedrows($rid) {
  113. if (PHP_VERSION >= 4.2) return pg_affected_rows($rid);
  114. else return pg_cmdtuples($rid);
  115. }
  116. // ....................................................................
  117. /**
  118. * Free a resource.
  119. * @param resource $rid The resource ID for the executed query
  120. */
  121. function freeresult($rid) {
  122. if (PHP_VERSION >= 4.2) pg_free_result($rid);
  123. else pg_freeresult($rid);
  124. }
  125. // ....................................................................
  126. /**
  127. * Return the last error message.
  128. * @return string The last error message which was generated
  129. */
  130. function errormessage() {
  131. if (PHP_VERSION >= 4.2) return pg_last_error($this->dbid);
  132. else return pg_errormessage($this->dbid);
  133. }
  134. // ....................................................................
  135. /**
  136. * Return the specified row, as a standard (enumerated) array of
  137. * field values.
  138. * @param resource $rid The resource ID for the executed query
  139. * @param integer $rowno Row number (zero-based) of row to return
  140. * @return array Enumerated array of field values
  141. */
  142. function fetch_row($rid, $rowno) {
  143. return pg_fetch_row($rid, $rowno);
  144. }
  145. // ....................................................................
  146. /**
  147. * Return the specified row, as an associative array of fields
  148. * in a fieldname => value format.
  149. * @param resource $rid The resource ID for the executed query
  150. * @param integer $rowno Row number (zero-based) of row to return
  151. * @return array Associative array of field values
  152. */
  153. function fetch_array($rid, $rowno) {
  154. return pg_fetch_array($rid, $rowno);
  155. }
  156. // ....................................................................
  157. /**
  158. * Return a Php boolean from a database field value. The database field
  159. * is expected to be a container of some form of logical value. Here
  160. * is where we convert it according to the current database.
  161. * @param mixed $dbvalue The value from the database field to convert
  162. * @return boolean The boolean value derived from the field value
  163. */
  164. function bool_from_db_value($dbvalue) {
  165. return (
  166. (is_bool($dbvalue) && $dbvalue === true)
  167. || (is_string($dbvalue) && strtolower($dbvalue) === "t")
  168. || (is_string($dbvalue) && strtolower($dbvalue) === "true")
  169. || (is_numeric($dbvalue) && $dbvalue == 1)
  170. );
  171. }
  172. // ....................................................................
  173. /**
  174. * Return a suitable database field value to contain the value for
  175. * the given boolean.
  176. * @param boolean $boolvalue The boolean value to convert
  177. * @return mixed The value suitable for the database field
  178. */
  179. function db_value_from_bool($boolvalue) {
  180. return ((is_bool($boolvalue) && $boolvalue === true) ? "t" : "f");
  181. }
  182. // ....................................................................
  183. /**
  184. * Return the current sequence value, given a sequence name, the table
  185. * and the field it applies to.
  186. * @param string $sequencename The name of the sequence to use
  187. * @param string $table The name of the table the sequence is for
  188. * @param string $column The name of the table column the sequence is for
  189. * @return integer The current sequence value
  190. */
  191. function current_sequencevalue($sequencename, $table, $column) {
  192. $seq = 0;
  193. $rid = $this->query("SELECT CURRVAL('$sequencename')" );
  194. if ($rid !== false) {
  195. $row = $this->fetch_row($rid, 0);
  196. $seq = $row[0];
  197. }
  198. return $seq;
  199. }
  200. // ....................................................................
  201. /**
  202. * Return the next sequence value, given a sequence name, the table
  203. * and the field it applies to.
  204. * @param string $sequencename The name of the sequence to use
  205. * @param string $table The name of the table the sequence is for
  206. * @param string $column The name of the table column the sequence is for
  207. * @return integer The next sequence value
  208. */
  209. function next_sequencevalue($sequencename, $table, $column) {
  210. $seq = 0;
  211. $rid = $this->query("SELECT NEXTVAL('$sequencename')" );
  212. if ($rid !== false) {
  213. $row = $this->fetch_row($rid, 0);
  214. $seq = $row[0];
  215. }
  216. return $seq;
  217. }
  218. // ....................................................................
  219. /**
  220. * Set the sequence value, given a sequence name, the table
  221. * and the field it applies to.
  222. * @param integer $newval The sequence value to set
  223. * @param string $sequencename The name of the sequence to use
  224. * @param string $table The name of the table the sequence is for
  225. * @param string $column The name of the table column the sequence is for
  226. * @return boolean Whether the assignment succeeded or not
  227. */
  228. function set_sequencevalue($newval, $sequencename, $table, $column) {
  229. return $this->query("SELECT SETVAL('$sequencename',$newval)" );
  230. }
  231. // ....................................................................
  232. /**
  233. * Set the database date style. This affect the format that dates will
  234. * be displayed in, and the format they are submitted in.
  235. * @param string $datestyle The date style code to set
  236. * @return boolean Whether the setting succeeded or not
  237. */
  238. function set_datestyle($datestyle) {
  239. return $this->query("SET DateStyle='$datestyle'");
  240. }
  241. // ....................................................................
  242. /**
  243. * Set the database character encoding. This affects the encoding of
  244. * characters in the database.
  245. * @param string $encoding The character encoding to set
  246. * @return boolean Whether the setting succeeded or not
  247. */
  248. function set_char_encoding($encoding) {
  249. return $this->query("SET client_encoding='$encoding'");
  250. }
  251. // ....................................................................
  252. /**
  253. * Set the the lock mode on a list of tables in the database.
  254. * @param string $tablelist A comma-delimited list of tables to lock
  255. * @param string $mode The mode to lock them in
  256. * @return boolean Whether the setting succeeded or not
  257. */
  258. function lock($tablelist, $mode) {
  259. $res = true;
  260. $tables = explode(",", $tablelist);
  261. foreach($tables as $table) {
  262. $rid = $this->query("LOCK $table IN $mode");
  263. if ($rid === false) {
  264. $res = false;
  265. }
  266. }
  267. return $res;
  268. }
  269. // ....................................................................
  270. /**
  271. * Used to escape particular characters (typically the single quote) so
  272. * that they can form part of the database data, rather than being
  273. * interpreted as command syntax. Note that this implementation makes
  274. * sure the string has none of the deprecated backslashes added by the
  275. * old addslashes() function, before escaping the content properly.
  276. * @param string $str
  277. * @return string The same string with appropriate chars escaped.
  278. */
  279. function escape_string($str="") {
  280. if (is_string($str)) {
  281. $str = pg_escape_string(stripslashes($str));
  282. }
  283. return $str;
  284. } // escape_string
  285. // ....................................................................
  286. /**
  287. * Used to unescape any escaped characters. Normally databases require
  288. * nothing to be done here for single-quote escapes, as they return the
  289. * data already unescaped.
  290. * Note: for Postgres we have been using add/stripslashes to escape
  291. * string data. To remedy a security issue this is no longer used, but
  292. * we need to apply a stripslashes here to removed slashes from any
  293. * legacy data out there.
  294. * @param string $str
  295. * @return string The same string with escaped chars UN-escaped.
  296. */
  297. function unescape_string($str="") {
  298. if (is_string($str)) {
  299. $str = stripslashes($str);
  300. }
  301. return $str;
  302. } // unescape_string
  303. // ....................................................................
  304. /**
  305. * Given an Axyl SQL query object, build the SQL string from it
  306. * in suitable format for the currently connected database server.
  307. * @param pointer $sqlquery Pointer to an Axyl query object
  308. * @return string The SQL string built from the query object
  309. */
  310. function SQL(&$sqlquery) {
  311. $sql = "";
  312. switch (strtoupper($sqlquery->type)) {
  313. case "SELECT":
  314. $sql .= "SELECT ";
  315. if ($sqlquery->fields->total == 0) $sql .= "*";
  316. else $sql .= $sqlquery->fields->listed();
  317. $sql .= " FROM ";
  318. $sql .= $sqlquery->tables->listed();
  319. if ($sqlquery->where->total > 0) {
  320. $sql .= " WHERE ";
  321. $sql .= $sqlquery->where->listed(" ");
  322. }
  323. if ($sqlquery->groupby->total > 0) {
  324. $sql .= " GROUP BY ";
  325. $sql .= $sqlquery->groupby->listed();
  326. }
  327. if ($sqlquery->orderby->total > 0) {
  328. $sql .= " ORDER BY ";
  329. $sql .= $sqlquery->orderby->listed();
  330. }
  331. if ($sqlquery->limit > 0 || $sqlquery->offset > 0) {
  332. if ($sqlquery->limit > 0) {
  333. $sql .= " LIMIT $sqlquery->limit";
  334. }
  335. if ($sqlquery->offset > 0) {
  336. $sql .= " OFFSET $sqlquery->offset";
  337. }
  338. }
  339. break;
  340.  
  341. case "INSERT":
  342. $sql .= "INSERT INTO ";
  343. $sql .= $sqlquery->tables->listed();
  344. if ($sqlquery->fields->total > 0) {
  345. $sql .= " (" . $sqlquery->fields->listed() . ")";
  346. }
  347. $sql .= " VALUES ";
  348. $sql .= "(" . $sqlquery->fields->values() . ")";
  349. break;
  350.  
  351. case "DELETE":
  352. $sql .= "DELETE FROM ";
  353. $sql .= $sqlquery->tables->listed();
  354. if ($sqlquery->where->total > 0) {
  355. $sql .= " WHERE ";
  356. $sql .= $sqlquery->where->listed(" ");
  357. }
  358. break;
  359.  
  360. case "UPDATE":
  361. $sql .= "UPDATE ";
  362. $sql .= $sqlquery->tables->listed();
  363. $sql .= " SET ";
  364. $sql .= $sqlquery->fields->equated();
  365. if ($sqlquery->where->total > 0) {
  366. $sql .= " WHERE ";
  367. $sql .= $sqlquery->where->listed(" ");
  368. }
  369. break;
  370. }
  371. // Render any NULL values..
  372. $SQL = str_replace("'".NULLVALUE."'", "NULL", $sql);
  373.  
  374. // Return SQL we have built..
  375. return $SQL;
  376. }
  377. // ....................................................................
  378. /**
  379. * Make conversions of boolean syntax found in the SQL string and
  380. * return the 'standardised' SQL. This assumes that Axyl SQL will
  381. * be written in the form 'WHERE foo=TRUE'.
  382. * @param string $sql SQL string to make conversions in
  383. * @return string The converted SQL string
  384. */
  385. function convert_boolean_syntax($sql) {
  386. // No change for Postgres..
  387. $fixsql = $sql;
  388. return $fixsql;
  389. }
  390. }
  391.  
  392. // ----------------------------------------------------------------------
  393. // POSTGRES LOCKING Wrappers - The below functions are all high-level
  394. // functions written to facilitate Postgresql Locking
  395.  
  396. /**
  397. * Lock table in ROW SHARE MODE
  398. * Reserve table rows for possible future updates, when the
  399. * lock will be upgraded to an exclusive lock. This allows
  400. * others to share lock the records too, but not exclusively
  401. * lock them. The query SELECT...FOR UPDATE does this. You
  402. * will only be locking the records that you select from the
  403. * table, and no others.
  404. * @param string $tablelist List of tables to lock, comma-delimited
  405. */
  406. function lockrows_share($tablelist) {
  407. global $RESPONSE;
  408. $res = true;
  409. if (isset($RESPONSE)) {
  410. $res = $RESPONSE->datasource->lock($tablelist, "ROW SHARE MODE");
  411. }
  412. return $res;
  413. }
  414. // ......................................................................
  415. /**
  416. * Lock table in ROW EXCLUSIVE MODE
  417. * Lock rows in exclusive mode. This is automatically
  418. * acquired by UPDATE, DELETE or INSERT queries, so if you
  419. * used lockrows_share() then no further locking is needed
  420. * if you then perform an UPDATE. Updated rows will remain
  421. * exclusive locked until the end of the transaction.
  422. * @param string $tablelist List of tables to lock, comma-delimited
  423. */
  424. function lockrows_exclusive($tablelist) {
  425. global $RESPONSE;
  426. $res = true;
  427. if (isset($RESPONSE)) {
  428. $res = $RESPONSE->datasource->lock($tablelist, "ROW EXCLUSIVE MODE");
  429. }
  430. return $res;
  431. }
  432. // ......................................................................
  433. /**
  434. * Lock table in SHARE MODE
  435. * Holds the whole table in share lock mode. This makes
  436. * sure that no exclusive locks can be acquired and so
  437. * holds the data in the table constant for the transaction.
  438. * Useful if you need to rely on table data remaining
  439. * constant for a transaction span.
  440. * @param string $tablelist List of tables to lock, comma-delimited
  441. */
  442. function locktable_share($tablelist) {
  443. global $RESPONSE;
  444. $res = true;
  445. if (isset($RESPONSE)) {
  446. $res = $RESPONSE->datasource->lock($tablelist, "SHARE MODE");
  447. }
  448. return $res;
  449. }
  450. // ......................................................................
  451. /**
  452. * Lock table in EXCLUSIVE MODE
  453. * Locks the whole table exclusively. This is very restrictive
  454. * and prevents any other process getting a share lock on the
  455. * records (any of them) in the table.
  456. * @param string $tablelist List of tables to lock, comma-delimited
  457. */
  458. function locktable_exclusive($tablelist) {
  459. global $RESPONSE;
  460. $res = true;
  461. if (isset($RESPONSE)) {
  462. $res = $RESPONSE->datasource->lock($tablelist, "EXCLUSIVE MODE");
  463. }
  464. return $res;
  465. }
  466.  
  467. // ----------------------------------------------------------------------
  468. // Ensure Postgres Php module is present..
  469.  
  470. if (!extension_loaded("pgsql")) {
  471. if (!dl("pgsql.so")) {
  472. exit;
  473. }
  474. }
  475. // ----------------------------------------------------------------------
  476. ?>

Documentation generated by phpDocumentor 1.3.0RC3