| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Paul Cooper <pgc@ucecom.com> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: pgsql.php,v 1.186 2007/11/10 13:27:03 quipo Exp $
|
| | | // $Id: pgsql.php,v 1.197 2008/03/08 14:18:39 quipo Exp $
|
| | |
|
| | | /**
|
| | | * MDB2 PostGreSQL driver
|
| | |
| | | $this->supported['LOBs'] = true;
|
| | | $this->supported['replace'] = 'emulated';
|
| | | $this->supported['sub_selects'] = true;
|
| | | $this->supported['triggers'] = true;
|
| | | $this->supported['auto_increment'] = 'emulated';
|
| | | $this->supported['primary_key'] = true;
|
| | | $this->supported['result_introspection'] = true;
|
| | |
| | | $this->supported['pattern_escaping'] = true;
|
| | | $this->supported['new_link'] = true;
|
| | |
|
| | | $this->options['DBA_username'] = false;
|
| | | $this->options['DBA_password'] = false;
|
| | | $this->options['multi_query'] = false;
|
| | | $this->options['disable_smart_seqname'] = false;
|
| | | $this->options['max_identifiers_length'] = 63;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | $native_msg = 'Database connection has been lost.';
|
| | | $error_code = MDB2_ERROR_CONNECT_FAILED;
|
| | | }
|
| | | } else {
|
| | | $native_msg = @pg_last_error();
|
| | | }
|
| | |
|
| | | static $error_regexps;
|
| | |
| | | => MDB2_ERROR_NOSUCHFIELD,
|
| | | '/(relation|sequence|table).*does not exist|class .* not found/i'
|
| | | => MDB2_ERROR_NOSUCHTABLE,
|
| | | '/database .* does not exist/'
|
| | | => MDB2_ERROR_NOT_FOUND,
|
| | | '/index .* does not exist/'
|
| | | => MDB2_ERROR_NOT_FOUND,
|
| | | '/database .* already exists/i'
|
| | | => MDB2_ERROR_ALREADY_EXISTS,
|
| | | '/relation .* already exists/i'
|
| | | => MDB2_ERROR_ALREADY_EXISTS,
|
| | | '/(divide|division) by zero$/i'
|
| | |
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | | if (version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {
|
| | | if (is_resource($connection) && version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {
|
| | | $text = @pg_escape_string($connection, $text);
|
| | | } else {
|
| | | $text = @pg_escape_string($text);
|
| | |
| | | // {{{ _doConnect()
|
| | |
|
| | | /**
|
| | | * Does the grunt work of connecting to the database
|
| | | * Do the grunt work of connecting to the database
|
| | | *
|
| | | * @return mixed connection resource on success, MDB2 Error Object on failure
|
| | | * @access protected
|
| | | **/
|
| | | function _doConnect($database_name, $persistent = false)
|
| | | */
|
| | | function _doConnect($username, $password, $database_name, $persistent = false)
|
| | | {
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | | |
| | | if ($database_name == '') {
|
| | | $database_name = 'template1';
|
| | | }
|
| | |
| | | if ($database_name) {
|
| | | $params[0].= ' dbname=\'' . addslashes($database_name) . '\'';
|
| | | }
|
| | | if ($this->dsn['username']) {
|
| | | $params[0].= ' user=\'' . addslashes($this->dsn['username']) . '\'';
|
| | | if ($username) {
|
| | | $params[0].= ' user=\'' . addslashes($username) . '\'';
|
| | | }
|
| | | if ($this->dsn['password']) {
|
| | | $params[0].= ' password=\'' . addslashes($this->dsn['password']) . '\'';
|
| | | if ($password) {
|
| | | $params[0].= ' password=\'' . addslashes($password) . '\'';
|
| | | }
|
| | | if (!empty($this->dsn['options'])) {
|
| | | $params[0].= ' options=' . $this->dsn['options'];
|
| | |
| | | }
|
| | |
|
| | | $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
|
| | |
|
| | | $connection = @call_user_func_array($connect_function, $params);
|
| | | if (!$connection) {
|
| | | return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | |
| | | *
|
| | | * @return true on success, MDB2 Error Object on failure
|
| | | * @access public
|
| | | **/
|
| | | */
|
| | | function connect()
|
| | | {
|
| | | if (is_resource($this->connection)) {
|
| | |
| | | $this->disconnect(false);
|
| | | }
|
| | |
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | |
|
| | | if ($this->database_name) {
|
| | | $connection = $this->_doConnect($this->database_name, $this->options['persistent']);
|
| | | $connection = $this->_doConnect($this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->database_name,
|
| | | $this->options['persistent']);
|
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $this->connection = $connection;
|
| | | $this->connected_dsn = $this->dsn;
|
| | | $this->connected_database_name = $this->database_name;
|
| | | $this->opened_persistent = $this->options['persistent'];
|
| | | $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
|
| | | }
|
| | |
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | |
| | | return $connection;
|
| | | }
|
| | | }
|
| | |
|
| | | if (is_array($charset)) {
|
| | | $charset = array_shift($charset);
|
| | | $this->warnings[] = 'postgresql does not support setting client collation';
|
| | | }
|
| | | $result = @pg_set_client_encoding($connection, $charset);
|
| | | if ($result == -1) {
|
| | | return $this->raiseError(null, null, null,
|
| | | 'Unable to set client charset: '.$charset, __FUNCTION__);
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ databaseExists()
|
| | |
|
| | | /**
|
| | | * check if given database name is exists?
|
| | | *
|
| | | * @param string $name name of the database that should be checked
|
| | | *
|
| | | * @return mixed true/false on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function databaseExists($name)
|
| | | {
|
| | | $res = $this->_doConnect($this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->escape($name),
|
| | | $this->options['persistent']);
|
| | | if (!PEAR::isError($res)) {
|
| | | return true;
|
| | | }
|
| | |
|
| | | return false;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | */
|
| | | function &standaloneQuery($query, $types = null, $is_manip = false)
|
| | | {
|
| | | $connection = $this->_doConnect('template1', false);
|
| | | $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username'];
|
| | | $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password'];
|
| | | $connection = $this->_doConnect($user, $pass, $this->database_name, $this->options['persistent']);
|
| | | if (PEAR::isError($connection)) {
|
| | | $err =& $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | | 'Cannot connect to template1', __FUNCTION__);
|
| | | return $err;
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $offset = $this->offset;
|
| | |
| | | $this->offset = $this->limit = 0;
|
| | | $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
|
| | |
|
| | | $result =& $this->_doQuery($query, $is_manip, $connection, false);
|
| | | @pg_close($connection);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name);
|
| | | if (!PEAR::isError($result)) {
|
| | | if ($is_manip) {
|
| | | $result = $this->_affectedRows($connection, $result);
|
| | | } else {
|
| | | $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset);
|
| | | }
|
| | | }
|
| | |
|
| | | if ($is_manip) {
|
| | | $affected_rows = $this->_affectedRows($connection, $result);
|
| | | return $affected_rows;
|
| | | }
|
| | | $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset);
|
| | | @pg_close($connection);
|
| | | return $result;
|
| | | }
|
| | |
|
| | |
| | | return $connection;
|
| | | }
|
| | | static $prep_statement_counter = 1;
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++;
|
| | | $statement_name = strtolower($statement_name);
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand()));
|
| | | $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']);
|
| | | if ($pgtypes === false) {
|
| | | $result = @pg_prepare($connection, $statement_name, $query);
|
| | | if (!$result) {
|
| | |
| | | WHERE d.adrelid = a.attrelid
|
| | | AND d.adnum = a.attnum
|
| | | AND a.atthasdef
|
| | | ) FROM 'nextval[^\']*\'([^\']*)')
|
| | | ) FROM 'nextval[^'']*''([^'']*)')
|
| | | FROM pg_attribute a
|
| | | LEFT JOIN pg_class c ON c.oid = a.attrelid
|
| | | LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef
|
| | |
| | | {
|
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
|
| | | $query = "SELECT NEXTVAL('$sequence_name')";
|
| | | $this->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $this->expectError(MDB2_ERROR_NOSUCHTABLE);
|
| | | $result = $this->queryOne($query, 'integer');
|
| | | $this->popExpect();
|
| | | $this->popErrorHandling();
|
| | | if (PEAR::isError($result)) {
|
| | | if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
|
| | | $this->loadModule('Manager', null, true);
|
| | |
| | | return $this->queryOne('SELECT lastval()', 'integer');
|
| | | }
|
| | | $seq = $table.(empty($field) ? '' : '_'.$field);
|
| | | $sequence_name = $this->getSequenceName($seq);
|
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true);
|
| | | return $this->queryOne("SELECT currval('$sequence_name')", 'integer');
|
| | | }
|
| | |
|