diff options
Diffstat (limited to 'program/lib/DB/pgsql.php')
-rw-r--r-- | program/lib/DB/pgsql.php | 131 |
1 files changed, 75 insertions, 56 deletions
diff --git a/program/lib/DB/pgsql.php b/program/lib/DB/pgsql.php index ae229afa1..fc3762a65 100644 --- a/program/lib/DB/pgsql.php +++ b/program/lib/DB/pgsql.php @@ -19,7 +19,7 @@ * @author Rui Hirokawa <hirokawa@php.net> * @author Stig Bakken <ssb@php.net> * @author Daniel Convissor <danielc@php.net> - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2007 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version CVS: $Id$ * @link http://pear.php.net/package/DB @@ -41,9 +41,9 @@ require_once 'DB/common.php'; * @author Rui Hirokawa <hirokawa@php.net> * @author Stig Bakken <ssb@php.net> * @author Daniel Convissor <danielc@php.net> - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2007 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: @package_version@ + * @version Release: 1.7.13 * @link http://pear.php.net/package/DB */ class DB_pgsql extends DB_common @@ -193,7 +193,7 @@ class DB_pgsql extends DB_common * 'portability' => DB_PORTABILITY_ALL, * ); * - * $db =& DB::connect($dsn, $options); + * $db = DB::connect($dsn, $options); * if (PEAR::isError($db)) { * die($db->getMessage()); * } @@ -277,10 +277,10 @@ class DB_pgsql extends DB_common $this->connection = @call_user_func_array($connect_function, $params); } else { - ini_set('track_errors', 1); + @ini_set('track_errors', 1); $this->connection = @call_user_func_array($connect_function, $params); - ini_set('track_errors', $ini); + @ini_set('track_errors', $ini); } if (!$this->connection) { @@ -320,7 +320,7 @@ class DB_pgsql extends DB_common */ function simpleQuery($query) { - $ismanip = DB::isManip($query); + $ismanip = $this->_checkManip($query); $this->last_query = $query; $query = $this->modifyQuery($query); if (!$this->autocommit && $ismanip) { @@ -336,19 +336,26 @@ class DB_pgsql extends DB_common if (!$result) { return $this->pgsqlRaiseError(); } - // Determine which queries that should return data, and which - // should return an error code only. + + /* + * Determine whether queries produce affected rows, result or nothing. + * + * This logic was introduced in version 1.1 of the file by ssb, + * though the regex has been modified slightly since then. + * + * PostgreSQL commands: + * ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, + * CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, + * GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, + * REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, + * UNLISTEN, UPDATE, VACUUM + */ if ($ismanip) { $this->affected = @pg_affected_rows($result); return DB_OK; - } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|SHOW)\s/si', $query)) { - /* PostgreSQL commands: - ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, - CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, - GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, - REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, - UNLISTEN, UPDATE, VACUUM - */ + } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|FETCH|SHOW)\s/si', + $query)) + { $this->row[(int)$result] = 0; // reset the row counter. $numrows = $this->numRows($result); if (is_object($numrows)) { @@ -471,38 +478,21 @@ class DB_pgsql extends DB_common } // }}} - // {{{ quoteSmart() + // {{{ quoteBoolean() /** - * Formats input so it can be safely used in a query - * - * @param mixed $in the data to be formatted - * - * @return mixed the formatted data. The format depends on the input's - * PHP type: - * + null = the string <samp>NULL</samp> - * + boolean = string <samp>TRUE</samp> or <samp>FALSE</samp> - * + integer or double = the unquoted number - * + other (including strings and numeric strings) = - * the data escaped according to MySQL's settings - * then encapsulated between single quotes + * Formats a boolean value for use within a query in a locale-independent + * manner. * + * @param boolean the boolean value to be quoted. + * @return string the quoted string. * @see DB_common::quoteSmart() - * @since Method available since Release 1.6.0 + * @since Method available since release 1.7.8. */ - function quoteSmart($in) - { - if (is_int($in) || is_double($in)) { - return $in; - } elseif (is_bool($in)) { - return $in ? 'TRUE' : 'FALSE'; - } elseif (is_null($in)) { - return 'NULL'; - } else { - return "'" . $this->escapeSimple($in) . "'"; - } + function quoteBoolean($boolean) { + return $boolean ? 'TRUE' : 'FALSE'; } - + // }}} // {{{ escapeSimple() @@ -512,9 +502,6 @@ class DB_pgsql extends DB_common * {@internal PostgreSQL treats a backslash as an escape character, * so they are escaped as well. * - * Not using pg_escape_string() yet because it requires PostgreSQL - * to be at version 7.2 or greater.}} - * * @param string $str the string to be escaped * * @return string the escaped string @@ -524,7 +511,21 @@ class DB_pgsql extends DB_common */ function escapeSimple($str) { - return str_replace("'", "''", str_replace('\\', '\\\\', $str)); + if (function_exists('pg_escape_string')) { + /* This fixes an undocumented BC break in PHP 5.2.0 which changed + * the prototype of pg_escape_string. I'm not thrilled about having + * to sniff the PHP version, quite frankly, but it's the only way + * to deal with the problem. Revision 1.331.2.13.2.10 on + * php-src/ext/pgsql/pgsql.c (PHP_5_2 branch) is to blame, for the + * record. */ + if (version_compare(PHP_VERSION, '5.2.0', '>=')) { + return pg_escape_string($this->connection, $str); + } else { + return pg_escape_string($str); + } + } else { + return str_replace("'", "''", str_replace('\\', '\\\\', $str)); + } } // }}} @@ -675,7 +676,7 @@ class DB_pgsql extends DB_common $repeat = false; do { $this->pushErrorHandling(PEAR_ERROR_RETURN); - $result =& $this->query("SELECT NEXTVAL('${seqname}')"); + $result = $this->query("SELECT NEXTVAL('${seqname}')"); $this->popErrorHandling(); if ($ondemand && DB::isError($result) && $result->getCode() == DB_ERROR_NOSUCHTABLE) { @@ -779,6 +780,10 @@ class DB_pgsql extends DB_common function pgsqlRaiseError($errno = null) { $native = $this->errorNative(); + if (!$native) { + $native = 'Database connection has been lost.'; + $errno = DB_ERROR_CONNECT_FAILED; + } if ($errno === null) { $errno = $this->errorCode($native); } @@ -815,12 +820,12 @@ class DB_pgsql extends DB_common static $error_regexps; if (!isset($error_regexps)) { $error_regexps = array( + '/column .* (of relation .*)?does not exist/i' + => DB_ERROR_NOSUCHFIELD, '/(relation|sequence|table).*does not exist|class .* not found/i' => DB_ERROR_NOSUCHTABLE, '/index .* does not exist/' => DB_ERROR_NOT_FOUND, - '/column .* does not exist/i' - => DB_ERROR_NOSUCHFIELD, '/relation .* already exists/i' => DB_ERROR_ALREADY_EXISTS, '/(divide|division) by zero$/i' @@ -976,22 +981,33 @@ class DB_pgsql extends DB_common { $field_name = @pg_fieldname($resource, $num_field); + // Check if there's a schema in $table_name and update things + // accordingly. + $from = 'pg_attribute f, pg_class tab, pg_type typ'; + if (strpos($table_name, '.') !== false) { + $from .= ', pg_namespace nsp'; + list($schema, $table) = explode('.', $table_name); + $tableWhere = "tab.relname = '$table' AND tab.relnamespace = nsp.oid AND nsp.nspname = '$schema'"; + } else { + $tableWhere = "tab.relname = '$table_name'"; + } + $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef - FROM pg_attribute f, pg_class tab, pg_type typ + FROM $from WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid AND f.attname = '$field_name' - AND tab.relname = '$table_name'"); + AND $tableWhere"); if (@pg_numrows($result) > 0) { $row = @pg_fetch_row($result, 0); $flags = ($row[0] == 't') ? 'not_null ' : ''; if ($row[1] == 't') { $result = @pg_exec($this->connection, "SELECT a.adsrc - FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a + FROM $from, pg_attrdef a WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid AND f.attrelid = a.adrelid AND f.attname = '$field_name' - AND tab.relname = '$table_name' AND f.attnum = a.adnum"); + AND $tableWhere AND f.attnum = a.adnum"); $row = @pg_fetch_row($result, 0); $num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]); $flags .= 'default_' . rawurlencode($num) . ' '; @@ -1000,12 +1016,12 @@ class DB_pgsql extends DB_common $flags = ''; } $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey - FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i + FROM $from, pg_index i WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid AND f.attrelid = i.indrelid AND f.attname = '$field_name' - AND tab.relname = '$table_name'"); + AND $tableWhere"); $count = @pg_numrows($result); for ($i = 0; $i < $count ; $i++) { @@ -1066,6 +1082,9 @@ class DB_pgsql extends DB_common . ' FROM pg_catalog.pg_tables' . ' WHERE schemaname NOT IN' . " ('pg_catalog', 'information_schema', 'pg_toast')"; + case 'schema.views': + return "SELECT schemaname || '.' || viewname from pg_views WHERE schemaname" + . " NOT IN ('information_schema', 'pg_catalog')"; case 'views': // Table cols: viewname | viewowner | definition return 'SELECT viewname from pg_views WHERE schemaname' |