| | |
| | | * @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 |
| | |
| | | * @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 |
| | |
| | | * 'portability' => DB_PORTABILITY_ALL, |
| | | * ); |
| | | * |
| | | * $db =& DB::connect($dsn, $options); |
| | | * $db = DB::connect($dsn, $options); |
| | | * if (PEAR::isError($db)) { |
| | | * die($db->getMessage()); |
| | | * } |
| | |
| | | $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) { |
| | |
| | | */ |
| | | function simpleQuery($query) |
| | | { |
| | | $ismanip = DB::isManip($query); |
| | | $ismanip = $this->_checkManip($query); |
| | | $this->last_query = $query; |
| | | $query = $this->modifyQuery($query); |
| | | if (!$this->autocommit && $ismanip) { |
| | |
| | | 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)) { |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ quoteSmart() |
| | | // {{{ quoteBoolean() |
| | | |
| | | /** |
| | | * Formats input so it can be safely used in a query |
| | | * Formats a boolean value for use within a query in a locale-independent |
| | | * manner. |
| | | * |
| | | * @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 |
| | | * |
| | | * @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() |
| | | |
| | |
| | | * |
| | | * {@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 |
| | | * |
| | |
| | | */ |
| | | 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)); |
| | | } |
| | | } |
| | | |
| | | // }}} |
| | |
| | | $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) { |
| | |
| | | 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); |
| | | } |
| | |
| | | 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' |
| | |
| | | { |
| | | $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) . ' '; |
| | |
| | | $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++) { |
| | |
| | | . ' 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' |