Documentation is available at db-postgres.php
- <?php
- /* ******************************************************************** */
- /* CATALYST PHP Source Code */
- /* -------------------------------------------------------------------- */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to: */
- /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
- /* Boston, MA 02111-1307 USA */
- /* -------------------------------------------------------------------- */
- /* */
- /* Filename: db-postgres.php */
- /* Author: Paul Waite */
- /* Description: Definitions for POSTGRES database access. */
- /* */
- /* ******************************************************************** */
- /** @package database */* POSTGRES database interface
- * This is a database interface class. It is an impedance-matcher
- * between the high-level Phplib functions for accessing data, and
- * the specific functions suplpied by Php to access a particular
- * flavour of databse such as Postgres, MS-SQL Server, Sybase etc.
- * @package database
- * @access private
- */
- class db_postgres extends database {
- /** Constructor */
- function db_postgres($name="", $user="", $passwd="", $host="", $port=0, $enc="", $datestyle="") {
- $this->database($name, $user, $passwd, $host, $port, $enc, $datestyle);
- $this->type = "postgres";
- }
- // ....................................................................
- /**
- * Connect to the database.
- * @param boolean $persistent Whether to connect persistently or not
- * @return boolean Status true if connected successfully
- */
- function connect($persistent=NOT_PERSISTENT) {
- if (!$this->connected) {
- $connstr = "";
- if ($this->host != "") $connstr .= " host=" . $this->host;
- if ($this->port != 0 ) $connstr .= " port=" . $this->port;
- $connstr .= " dbname=" . $this->name;
- $connstr .= " user=" . $this->user;
- if ($this->passwd != "") $connstr .= " password=" . $this->passwd;
- $connstr = trim($connstr);
- if ($persistent)
- $this->dbid = pg_pconnect("$connstr");
- else
- $this->dbid = pg_connect("$connstr");
- if ($this->dbid) {
- if ($this->datestyle != "") $this->set_datestyle($this->datestyle);
- if ($this->enc != "") $this->set_char_encoding($this->enc);
- $this->connected = true;
- }
- }
- return $this->connected;
- }
- // ....................................................................
- /** Disconnect from the database, if connected. */
- function disconnect() {
- if (pg_close($this->dbid))
- $this->connected = false;
- }
- // ....................................................................
- /**
- * Execute a query on the connected database.
- * @param string $sql The SQL query to execute on the database
- * @return resource A database query resource ID, or false if query failed
- */
- function query($sql) {
- $sql = $this->convert_boolean_syntax($sql);
- $this->timer->restart();
- if (PHP_VERSION >= 4.2) {
- $rid = pg_query($this->dbid, $sql);
- }
- else {
- $rid = pg_exec($this->dbid, $sql);
- }
- $this->timer->stop();
- $this->executable_sql = $sql;
- $this->rid = $rid;
- $this->query_report();
- return $rid;
- }
- // ....................................................................
- /**
- * Return the number of rows returned by a SELECT query.
- * @param resource $rid The resource ID for the executed query
- * @return integer The number of rows returned by the query
- */
- function numrows($rid) {
- if (PHP_VERSION >= 4.2) return pg_num_rows($rid);
- else return pg_numrows($rid);
- }
- // ....................................................................
- /**
- * Return the number of rows affected by a query.
- * @param resource $rid The resource ID for the executed query
- * @return integer The number of rows affected by the query
- */
- function affectedrows($rid) {
- if (PHP_VERSION >= 4.2) return pg_affected_rows($rid);
- else return pg_cmdtuples($rid);
- }
- // ....................................................................
- /**
- * Free a resource.
- * @param resource $rid The resource ID for the executed query
- */
- function freeresult($rid) {
- if (PHP_VERSION >= 4.2) pg_free_result($rid);
- else pg_freeresult($rid);
- }
- // ....................................................................
- /**
- * Return the last error message.
- * @return string The last error message which was generated
- */
- function errormessage() {
- if (PHP_VERSION >= 4.2) return pg_last_error($this->dbid);
- else return pg_errormessage($this->dbid);
- }
- // ....................................................................
- /**
- * Return the specified row, as a standard (enumerated) array of
- * field values.
- * @param resource $rid The resource ID for the executed query
- * @param integer $rowno Row number (zero-based) of row to return
- * @return array Enumerated array of field values
- */
- function fetch_row($rid, $rowno) {
- return pg_fetch_row($rid, $rowno);
- }
- // ....................................................................
- /**
- * Return the specified row, as an associative array of fields
- * in a fieldname => value format.
- * @param resource $rid The resource ID for the executed query
- * @param integer $rowno Row number (zero-based) of row to return
- * @return array Associative array of field values
- */
- function fetch_array($rid, $rowno) {
- return pg_fetch_array($rid, $rowno);
- }
- // ....................................................................
- /**
- * Return a Php boolean from a database field value. The database field
- * is expected to be a container of some form of logical value. Here
- * is where we convert it according to the current database.
- * @param mixed $dbvalue The value from the database field to convert
- * @return boolean The boolean value derived from the field value
- */
- function bool_from_db_value($dbvalue) {
- return (
- (is_bool($dbvalue) && $dbvalue === true)
- || (is_string($dbvalue) && strtolower($dbvalue) === "t")
- || (is_string($dbvalue) && strtolower($dbvalue) === "true")
- || (is_numeric($dbvalue) && $dbvalue == 1)
- );
- }
- // ....................................................................
- /**
- * Return a suitable database field value to contain the value for
- * the given boolean.
- * @param boolean $boolvalue The boolean value to convert
- * @return mixed The value suitable for the database field
- */
- function db_value_from_bool($boolvalue) {
- return ((is_bool($boolvalue) && $boolvalue === true) ? "t" : "f");
- }
- // ....................................................................
- /**
- * Return the current sequence value, given a sequence name, the table
- * and the field it applies to.
- * @param string $sequencename The name of the sequence to use
- * @param string $table The name of the table the sequence is for
- * @param string $column The name of the table column the sequence is for
- * @return integer The current sequence value
- */
- function current_sequencevalue($sequencename, $table, $column) {
- $seq = 0;
- $rid = $this->query("SELECT CURRVAL('$sequencename')" );
- if ($rid !== false) {
- $row = $this->fetch_row($rid, 0);
- $seq = $row[0];
- }
- return $seq;
- }
- // ....................................................................
- /**
- * Return the next sequence value, given a sequence name, the table
- * and the field it applies to.
- * @param string $sequencename The name of the sequence to use
- * @param string $table The name of the table the sequence is for
- * @param string $column The name of the table column the sequence is for
- * @return integer The next sequence value
- */
- function next_sequencevalue($sequencename, $table, $column) {
- $seq = 0;
- $rid = $this->query("SELECT NEXTVAL('$sequencename')" );
- if ($rid !== false) {
- $row = $this->fetch_row($rid, 0);
- $seq = $row[0];
- }
- return $seq;
- }
- // ....................................................................
- /**
- * Set the sequence value, given a sequence name, the table
- * and the field it applies to.
- * @param integer $newval The sequence value to set
- * @param string $sequencename The name of the sequence to use
- * @param string $table The name of the table the sequence is for
- * @param string $column The name of the table column the sequence is for
- * @return boolean Whether the assignment succeeded or not
- */
- function set_sequencevalue($newval, $sequencename, $table, $column) {
- return $this->query("SELECT SETVAL('$sequencename',$newval)" );
- }
- // ....................................................................
- /**
- * Set the database date style. This affect the format that dates will
- * be displayed in, and the format they are submitted in.
- * @param string $datestyle The date style code to set
- * @return boolean Whether the setting succeeded or not
- */
- function set_datestyle($datestyle) {
- return $this->query("SET DateStyle='$datestyle'");
- }
- // ....................................................................
- /**
- * Set the database character encoding. This affects the encoding of
- * characters in the database.
- * @param string $encoding The character encoding to set
- * @return boolean Whether the setting succeeded or not
- */
- function set_char_encoding($encoding) {
- return $this->query("SET client_encoding='$encoding'");
- }
- // ....................................................................
- /**
- * Set the the lock mode on a list of tables in the database.
- * @param string $tablelist A comma-delimited list of tables to lock
- * @param string $mode The mode to lock them in
- * @return boolean Whether the setting succeeded or not
- */
- function lock($tablelist, $mode) {
- $res = true;
- $tables = explode(",", $tablelist);
- foreach($tables as $table) {
- $rid = $this->query("LOCK $table IN $mode");
- if ($rid === false) {
- $res = false;
- }
- }
- return $res;
- }
- // ....................................................................
- /**
- * Used to escape particular characters (typically the single quote) so
- * that they can form part of the database data, rather than being
- * interpreted as command syntax. Note that this implementation makes
- * sure the string has none of the deprecated backslashes added by the
- * old addslashes() function, before escaping the content properly.
- * @param string $str
- * @return string The same string with appropriate chars escaped.
- */
- function escape_string($str="") {
- if (is_string($str)) {
- $str = pg_escape_string(stripslashes($str));
- }
- return $str;
- } // escape_string
- // ....................................................................
- /**
- * Used to unescape any escaped characters. Normally databases require
- * nothing to be done here for single-quote escapes, as they return the
- * data already unescaped.
- * Note: for Postgres we have been using add/stripslashes to escape
- * string data. To remedy a security issue this is no longer used, but
- * we need to apply a stripslashes here to removed slashes from any
- * legacy data out there.
- * @param string $str
- * @return string The same string with escaped chars UN-escaped.
- */
- function unescape_string($str="") {
- if (is_string($str)) {
- $str = stripslashes($str);
- }
- return $str;
- } // unescape_string
- // ....................................................................
- /**
- * Given an Axyl SQL query object, build the SQL string from it
- * in suitable format for the currently connected database server.
- * @param pointer $sqlquery Pointer to an Axyl query object
- * @return string The SQL string built from the query object
- */
- function SQL(&$sqlquery) {
- $sql = "";
- switch (strtoupper($sqlquery->type)) {
- case "SELECT":
- $sql .= "SELECT ";
- if ($sqlquery->fields->total == 0) $sql .= "*";
- else $sql .= $sqlquery->fields->listed();
- $sql .= " FROM ";
- $sql .= $sqlquery->tables->listed();
- if ($sqlquery->where->total > 0) {
- $sql .= " WHERE ";
- $sql .= $sqlquery->where->listed(" ");
- }
- if ($sqlquery->groupby->total > 0) {
- $sql .= " GROUP BY ";
- $sql .= $sqlquery->groupby->listed();
- }
- if ($sqlquery->orderby->total > 0) {
- $sql .= " ORDER BY ";
- $sql .= $sqlquery->orderby->listed();
- }
- if ($sqlquery->limit > 0 || $sqlquery->offset > 0) {
- if ($sqlquery->limit > 0) {
- $sql .= " LIMIT $sqlquery->limit";
- }
- if ($sqlquery->offset > 0) {
- $sql .= " OFFSET $sqlquery->offset";
- }
- }
- break;
- case "INSERT":
- $sql .= "INSERT INTO ";
- $sql .= $sqlquery->tables->listed();
- if ($sqlquery->fields->total > 0) {
- $sql .= " (" . $sqlquery->fields->listed() . ")";
- }
- $sql .= " VALUES ";
- $sql .= "(" . $sqlquery->fields->values() . ")";
- break;
- case "DELETE":
- $sql .= "DELETE FROM ";
- $sql .= $sqlquery->tables->listed();
- if ($sqlquery->where->total > 0) {
- $sql .= " WHERE ";
- $sql .= $sqlquery->where->listed(" ");
- }
- break;
- case "UPDATE":
- $sql .= "UPDATE ";
- $sql .= $sqlquery->tables->listed();
- $sql .= " SET ";
- $sql .= $sqlquery->fields->equated();
- if ($sqlquery->where->total > 0) {
- $sql .= " WHERE ";
- $sql .= $sqlquery->where->listed(" ");
- }
- break;
- }
- // Render any NULL values..
- $SQL = str_replace("'".NULLVALUE."'", "NULL", $sql);
- // Return SQL we have built..
- return $SQL;
- }
- // ....................................................................
- /**
- * Make conversions of boolean syntax found in the SQL string and
- * return the 'standardised' SQL. This assumes that Axyl SQL will
- * be written in the form 'WHERE foo=TRUE'.
- * @param string $sql SQL string to make conversions in
- * @return string The converted SQL string
- */
- function convert_boolean_syntax($sql) {
- // No change for Postgres..
- $fixsql = $sql;
- return $fixsql;
- }
- }
- // ----------------------------------------------------------------------
- // POSTGRES LOCKING Wrappers - The below functions are all high-level
- // functions written to facilitate Postgresql Locking
- /**
- * Lock table in ROW SHARE MODE
- * Reserve table rows for possible future updates, when the
- * lock will be upgraded to an exclusive lock. This allows
- * others to share lock the records too, but not exclusively
- * lock them. The query SELECT...FOR UPDATE does this. You
- * will only be locking the records that you select from the
- * table, and no others.
- * @param string $tablelist List of tables to lock, comma-delimited
- */
- function lockrows_share($tablelist) {
- global $RESPONSE;
- $res = true;
- if (isset($RESPONSE)) {
- $res = $RESPONSE->datasource->lock($tablelist, "ROW SHARE MODE");
- }
- return $res;
- }
- // ......................................................................
- /**
- * Lock table in ROW EXCLUSIVE MODE
- * Lock rows in exclusive mode. This is automatically
- * acquired by UPDATE, DELETE or INSERT queries, so if you
- * used lockrows_share() then no further locking is needed
- * if you then perform an UPDATE. Updated rows will remain
- * exclusive locked until the end of the transaction.
- * @param string $tablelist List of tables to lock, comma-delimited
- */
- function lockrows_exclusive($tablelist) {
- global $RESPONSE;
- $res = true;
- if (isset($RESPONSE)) {
- $res = $RESPONSE->datasource->lock($tablelist, "ROW EXCLUSIVE MODE");
- }
- return $res;
- }
- // ......................................................................
- /**
- * Lock table in SHARE MODE
- * Holds the whole table in share lock mode. This makes
- * sure that no exclusive locks can be acquired and so
- * holds the data in the table constant for the transaction.
- * Useful if you need to rely on table data remaining
- * constant for a transaction span.
- * @param string $tablelist List of tables to lock, comma-delimited
- */
- function locktable_share($tablelist) {
- global $RESPONSE;
- $res = true;
- if (isset($RESPONSE)) {
- $res = $RESPONSE->datasource->lock($tablelist, "SHARE MODE");
- }
- return $res;
- }
- // ......................................................................
- /**
- * Lock table in EXCLUSIVE MODE
- * Locks the whole table exclusively. This is very restrictive
- * and prevents any other process getting a share lock on the
- * records (any of them) in the table.
- * @param string $tablelist List of tables to lock, comma-delimited
- */
- function locktable_exclusive($tablelist) {
- global $RESPONSE;
- $res = true;
- if (isset($RESPONSE)) {
- $res = $RESPONSE->datasource->lock($tablelist, "EXCLUSIVE MODE");
- }
- return $res;
- }
- // ----------------------------------------------------------------------
- // Ensure Postgres Php module is present..
- if (!extension_loaded("pgsql")) {
- if (!dl("pgsql.so")) {
- exit;
- }
- }
- // ----------------------------------------------------------------------
- ?>
Documentation generated by phpDocumentor 1.3.0RC3