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) {
  38. $this->database($name, $user, $passwd, $host, $port);
  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. $this->connected = true;
  62. }
  63. }
  64. return $this->connected;
  65. }
  66. // ....................................................................
  67. /** Disconnect from the database, if connected. */
  68.  
  69. function disconnect() {
  70. if (pg_close($this->dbid))
  71. $this->connected = false;
  72. }
  73. // ....................................................................
  74. /**
  75. * Execute a query on the connected database.
  76. * @param string $sql The SQL query to execute on the database
  77. * @return resource A database query resource ID, or false if query failed
  78. */
  79. function query($sql) {
  80. $sql = $this->convert_boolean_syntax($sql);
  81. $this->timer->restart();
  82. if (PHP_VERSION >= 4.2) {
  83. $rid = pg_query($this->dbid, $sql);
  84. }
  85. else {
  86. $rid = pg_exec($this->dbid, $sql);
  87. }
  88. $this->timer->stop();
  89. $this->executable_sql = $sql;
  90. $this->rid = $rid;
  91. $this->query_report();
  92. return $rid;
  93. }
  94. // ....................................................................
  95. /**
  96. * Return the number of rows returned by a SELECT query.
  97. * @param resource $rid The resource ID for the executed query
  98. * @return integer The number of rows returned by the query
  99. */
  100. function numrows($rid) {
  101. if (PHP_VERSION >= 4.2) return pg_num_rows($rid);
  102. else return pg_numrows($rid);
  103. }
  104. // ....................................................................
  105. /**
  106. * Return the number of rows affected by a query.
  107. * @param resource $rid The resource ID for the executed query
  108. * @return integer The number of rows affected by the query
  109. */
  110. function affectedrows($rid) {
  111. if (PHP_VERSION >= 4.2) return pg_affected_rows($rid);
  112. else return pg_cmdtuples($rid);
  113. }
  114. // ....................................................................
  115. /**
  116. * Free a resource.
  117. * @param resource $rid The resource ID for the executed query
  118. */
  119. function freeresult($rid) {
  120. if (PHP_VERSION >= 4.2) pg_free_result($rid);
  121. else pg_freeresult($rid);
  122. }
  123. // ....................................................................
  124. /**
  125. * Return the last error message.
  126. * @return string The last error message which was generated
  127. */
  128. function errormessage() {
  129. if (PHP_VERSION >= 4.2) return pg_last_error($this->dbid);
  130. else return pg_errormessage($this->dbid);
  131. }
  132. // ....................................................................
  133. /**
  134. * Return the specified row, as a standard (enumerated) array of
  135. * field values.
  136. * @param resource $rid The resource ID for the executed query
  137. * @param integer $rowno Row number (zero-based) of row to return
  138. * @return array Enumerated array of field values
  139. */
  140. function fetch_row($rid, $rowno) {
  141. return pg_fetch_row($rid, $rowno);
  142. }
  143. // ....................................................................
  144. /**
  145. * Return the specified row, as an associative array of fields
  146. * in a fieldname => value format.
  147. * @param resource $rid The resource ID for the executed query
  148. * @param integer $rowno Row number (zero-based) of row to return
  149. * @return array Associative array of field values
  150. */
  151. function fetch_array($rid, $rowno) {
  152. return pg_fetch_array($rid, $rowno);
  153. }
  154. // ....................................................................
  155. /**
  156. * Return a Php boolean from a database field value. The database field
  157. * is expected to be a container of some form of logical value. Here
  158. * is where we convert it according to the current database.
  159. * @param mixed $dbvalue The value from the database field to convert
  160. * @return boolean The boolean value derived from the field value
  161. */
  162. function bool_from_db_value($dbvalue) {
  163. return (
  164. (is_bool($dbvalue) && $dbvalue === true)
  165. || (is_string($dbvalue) && strtolower($dbvalue) === "t")
  166. || (is_string($dbvalue) && strtolower($dbvalue) === "true")
  167. || (is_numeric($dbvalue) && $dbvalue == 1)
  168. );
  169. }
  170. // ....................................................................
  171. /**
  172. * Return a suitable database field value to contain the value for
  173. * the given boolean.
  174. * @param boolean $boolvalue The boolean value to convert
  175. * @return mixed The value suitable for the database field
  176. */
  177. function db_value_from_bool($boolvalue) {
  178. return ((is_bool($boolvalue) && $boolvalue === true) ? "t" : "f");
  179. }
  180. // ....................................................................
  181. /**
  182. * Return the current sequence value, given a sequence name, the table
  183. * and the field it applies to.
  184. * @param string $sequencename The name of the sequence to use
  185. * @param string $table The name of the table the sequence is for
  186. * @param string $column The name of the table column the sequence is for
  187. * @return integer The current sequence value
  188. */
  189. function current_sequencevalue($sequencename, $table, $column) {
  190. $seq = 0;
  191. $rid = $this->query("SELECT CURRVAL('$sequencename')" );
  192. if ($rid !== false) {
  193. $row = $this->fetch_row($rid, 0);
  194. $seq = $row[0];
  195. }
  196. return $seq;
  197. }
  198. // ....................................................................
  199. /**
  200. * Return the next sequence value, given a sequence name, the table
  201. * and the field it applies to.
  202. * @param string $sequencename The name of the sequence to use
  203. * @param string $table The name of the table the sequence is for
  204. * @param string $column The name of the table column the sequence is for
  205. * @return integer The next sequence value
  206. */
  207. function next_sequencevalue($sequencename, $table, $column) {
  208. $seq = 0;
  209. $rid = $this->query("SELECT NEXTVAL('$sequencename')" );
  210. if ($rid !== false) {
  211. $row = $this->fetch_row($rid, 0);
  212. $seq = $row[0];
  213. }
  214. return $seq;
  215. }
  216. // ....................................................................
  217. /**
  218. * Set the sequence value, given a sequence name, the table
  219. * and the field it applies to.
  220. * @param integer $newval The sequence value to set
  221. * @param string $sequencename The name of the sequence to use
  222. * @param string $table The name of the table the sequence is for
  223. * @param string $column The name of the table column the sequence is for
  224. * @return boolean Whether the assignment succeeded or not
  225. */
  226. function set_sequencevalue($newval, $sequencename, $table, $column) {
  227. return $this->query("SELECT SETVAL('$sequencename',$newval)" );
  228. }
  229. // ....................................................................
  230. /**
  231. * Set the database date style. This affect the format that dates will
  232. * be displayed in, and the format they are submitted in.
  233. * @param string $datestyle The date style code to set
  234. * @return boolean Whether the setting succeeded or not
  235. */
  236. function set_datestyle($datestyle) {
  237. return $this->query("SET DateStyle='$datestyle'");
  238. }
  239. // ....................................................................
  240. /**
  241. * Set the database character encoding. This affects the encoding of
  242. * characters in the database.
  243. * @param string $encoding The character encoding to set
  244. * @return boolean Whether the setting succeeded or not
  245. */
  246. function set_char_encoding($encoding) {
  247. return $this->query("SET client_encoding='$encoding'");
  248. }
  249. // ....................................................................
  250. /**
  251. * Set the the lock mode on a list of tables in the database.
  252. * @param string $tablelist A comma-delimited list of tables to lock
  253. * @param string $mode The mode to lock them in
  254. * @return boolean Whether the setting succeeded or not
  255. */
  256. function lock($tablelist, $mode) {
  257. $res = true;
  258. $tables = explode(",", $tablelist);
  259. foreach($tables as $table) {
  260. $rid = $this->query("LOCK $table IN $mode");
  261. if ($rid === false) {
  262. $res = false;
  263. }
  264. }
  265. return $res;
  266. }
  267. // ....................................................................
  268. /**
  269. * Given an Axyl SQL query object, build the SQL string from it
  270. * in suitable format for the currently connected database server.
  271. * @param pointer $sqlquery Pointer to an Axyl query object
  272. * @return string The SQL string built from the query object
  273. */
  274. function SQL(&$sqlquery) {
  275. $sql = "";
  276. switch (strtoupper($sqlquery->type)) {
  277. case "SELECT":
  278. $sql .= "SELECT ";
  279. if ($sqlquery->fields->total == 0) $sql .= "*";
  280. else $sql .= $sqlquery->fields->listed();
  281. $sql .= " FROM ";
  282. $sql .= $sqlquery->tables->listed();
  283. if ($sqlquery->where->total > 0) {
  284. $sql .= " WHERE ";
  285. $sql .= $sqlquery->where->listed(" ");
  286. }
  287. if ($sqlquery->groupby->total > 0) {
  288. $sql .= " GROUP BY ";
  289. $sql .= $sqlquery->groupby->listed();
  290. }
  291. if ($sqlquery->orderby->total > 0) {
  292. $sql .= " ORDER BY ";
  293. $sql .= $sqlquery->orderby->listed();
  294. }
  295. if ($sqlquery->limit > 0 || $sqlquery->offset > 0) {
  296. if ($sqlquery->limit > 0) {
  297. $sql .= " LIMIT $sqlquery->limit";
  298. }
  299. if ($sqlquery->offset > 0) {
  300. $sql .= " OFFSET $sqlquery->offset";
  301. }
  302. }
  303. break;
  304.  
  305. case "INSERT":
  306. $sql .= "INSERT INTO ";
  307. $sql .= $sqlquery->tables->listed();
  308. if ($sqlquery->fields->total > 0) {
  309. $sql .= " (" . $sqlquery->fields->listed() . ")";
  310. }
  311. $sql .= " VALUES ";
  312. $sql .= "(" . $sqlquery->fields->values() . ")";
  313. break;
  314.  
  315. case "DELETE":
  316. $sql .= "DELETE FROM ";
  317. $sql .= $sqlquery->tables->listed();
  318. if ($sqlquery->where->total > 0) {
  319. $sql .= " WHERE ";
  320. $sql .= $sqlquery->where->listed(" ");
  321. }
  322. break;
  323.  
  324. case "UPDATE":
  325. $sql .= "UPDATE ";
  326. $sql .= $sqlquery->tables->listed();
  327. $sql .= " SET ";
  328. $sql .= $sqlquery->fields->equated();
  329. if ($sqlquery->where->total > 0) {
  330. $sql .= " WHERE ";
  331. $sql .= $sqlquery->where->listed(" ");
  332. }
  333. break;
  334. }
  335. // Render any NULL values..
  336. $SQL = str_replace("'".NULLVALUE."'", "NULL", $sql);
  337.  
  338. // Return SQL we have built..
  339. return $SQL;
  340. }
  341. // ....................................................................
  342. /**
  343. * Make conversions of boolean syntax found in the SQL string and
  344. * return the 'standardised' SQL. This assumes that Axyl SQL will
  345. * be written in the form 'WHERE foo=TRUE'.
  346. * @param string $sql SQL string to make conversions in
  347. * @return string The converted SQL string
  348. */
  349. function convert_boolean_syntax($sql) {
  350. // No change for Postgres..
  351. $fixsql = $sql;
  352. return $fixsql;
  353. }
  354. }
  355.  
  356. // ----------------------------------------------------------------------
  357. // POSTGRES LOCKING Wrappers - The below functions are all high-level
  358. // functions written to facilitate Postgresql Locking
  359.  
  360. /**
  361. * Lock table in ROW SHARE MODE
  362. * Reserve table rows for possible future updates, when the
  363. * lock will be upgraded to an exclusive lock. This allows
  364. * others to share lock the records too, but not exclusively
  365. * lock them. The query SELECT...FOR UPDATE does this. You
  366. * will only be locking the records that you select from the
  367. * table, and no others.
  368. * @param string $tablelist List of tables to lock, comma-delimited
  369. */
  370. function lockrows_share($tablelist) {
  371. global $RESPONSE;
  372. $res = true;
  373. if (isset($RESPONSE)) {
  374. $res = $RESPONSE->datasource->lock($tablelist, "ROW SHARE MODE");
  375. }
  376. return $res;
  377. }
  378. // ......................................................................
  379. /**
  380. * Lock table in ROW EXCLUSIVE MODE
  381. * Lock rows in exclusive mode. This is automatically
  382. * acquired by UPDATE, DELETE or INSERT queries, so if you
  383. * used lockrows_share() then no further locking is needed
  384. * if you then perform an UPDATE. Updated rows will remain
  385. * exclusive locked until the end of the transaction.
  386. * @param string $tablelist List of tables to lock, comma-delimited
  387. */
  388. function lockrows_exclusive($tablelist) {
  389. global $RESPONSE;
  390. $res = true;
  391. if (isset($RESPONSE)) {
  392. $res = $RESPONSE->datasource->lock($tablelist, "ROW EXCLUSIVE MODE");
  393. }
  394. return $res;
  395. }
  396. // ......................................................................
  397. /**
  398. * Lock table in SHARE MODE
  399. * Holds the whole table in share lock mode. This makes
  400. * sure that no exclusive locks can be acquired and so
  401. * holds the data in the table constant for the transaction.
  402. * Useful if you need to rely on table data remaining
  403. * constant for a transaction span.
  404. * @param string $tablelist List of tables to lock, comma-delimited
  405. */
  406. function locktable_share($tablelist) {
  407. global $RESPONSE;
  408. $res = true;
  409. if (isset($RESPONSE)) {
  410. $res = $RESPONSE->datasource->lock($tablelist, "SHARE MODE");
  411. }
  412. return $res;
  413. }
  414. // ......................................................................
  415. /**
  416. * Lock table in EXCLUSIVE MODE
  417. * Locks the whole table exclusively. This is very restrictive
  418. * and prevents any other process getting a share lock on the
  419. * records (any of them) in the table.
  420. * @param string $tablelist List of tables to lock, comma-delimited
  421. */
  422. function locktable_exclusive($tablelist) {
  423. global $RESPONSE;
  424. $res = true;
  425. if (isset($RESPONSE)) {
  426. $res = $RESPONSE->datasource->lock($tablelist, "EXCLUSIVE MODE");
  427. }
  428. return $res;
  429. }
  430.  
  431. // ----------------------------------------------------------------------
  432. // Ensure Postgres Php module is present..
  433.  
  434. if (!extension_loaded("pgsql")) {
  435. if (!dl("pgsql.so")) {
  436. exit;
  437. }
  438. }
  439. // ----------------------------------------------------------------------
  440. ?>

Documentation generated by phpDocumentor 1.3.0RC3