| Source for file pgsql.phpDocumentation is available at pgsql.php 
// vim: set et ts=4 sw=4 fdm=marker:// +----------------------------------------------------------------------+// | PHP versions 4 and 5                                                 |// +----------------------------------------------------------------------+// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 |// | Stig. S. Bakken, Lukas Smith                                         |// | All rights reserved.                                                 |// +----------------------------------------------------------------------+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |// | API as well as database abstraction for PHP applications.            |// | This LICENSE is in the BSD license style.                            |// | Redistribution and use in source and binary forms, with or without   |// | modification, are permitted provided that the following conditions   |// | Redistributions of source code must retain the above copyright       |// | notice, this list of conditions and the following disclaimer.        |// | Redistributions in binary form must reproduce the above copyright    |// | notice, this list of conditions and the following disclaimer in the  |// | documentation and/or other materials provided with the distribution. |// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |// | Lukas Smith nor the names of his contributors may be used to endorse |// | or promote products derived from this software without specific prior|// | written permission.                                                  |// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |// | POSSIBILITY OF SUCH DAMAGE.                                          |// +----------------------------------------------------------------------+// | Author: Paul Cooper <pgc@ucecom.com>                                 |// +----------------------------------------------------------------------+// $Id: pgsql.php 327317 2012-08-27 15:17:08Z danielc $ * @author  Paul Cooper <pgc@ucecom.com>    var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => '\\') ;        $this->phptype = 'pgsql' ;        $this->dbsyntax = 'pgsql' ;        $this->supported['sequences'] = true;        $this->supported['indexes'] = true;        $this->supported['affected_rows'] = true;        $this->supported['summary_functions'] = true;        $this->supported['order_by_text'] = true;        $this->supported['transactions'] = true;        $this->supported['savepoints'] = true;        $this->supported['current_id'] = true;        $this->supported['limit_queries'] = true;        $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['prepared_statements'] = true;        $this->supported['identifier_quoting'] = 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'] = true;        $this->options['max_identifiers_length'] = 63;     * This method is used to collect information about an error        // Fall back to MDB2_ERROR if there was no mapping.        $error_code = MDB2_ERROR;            $native_msg = @ pg_result_error($error) ;        } elseif ($this->connection) {            $native_msg = @ pg_last_error($this->connection) ;            if (!$native_msg && @ pg_connection_status($this->connection) === PGSQL_CONNECTION_BAD) {                $native_msg = 'Database connection has been lost.' ;                $error_code = MDB2_ERROR_CONNECT_FAILED;            $native_msg = @ pg_last_error() ;        if (empty($error_regexps)) {                '/column .* (of relation .*)?does not exist/i'                    => MDB2_ERROR_NOSUCHFIELD,                '/(relation|sequence|table).*does not exist|class .* not found/i'                    => MDB2_ERROR_NOSUCHTABLE,                '/database .* does not exist/'                '/constraint .* does not exist/'                '/index .* does not exist/'                '/database .* already exists/i'                    => MDB2_ERROR_ALREADY_EXISTS,                '/relation .* already exists/i'                    => MDB2_ERROR_ALREADY_EXISTS,                '/(divide|division) by zero$/i'                '/pg_atoi: error in .*: can\'t parse /i'                    => MDB2_ERROR_INVALID_NUMBER,                '/invalid input syntax for( type)? (integer|numeric)/i'                    => MDB2_ERROR_INVALID_NUMBER,                '/value .* is out of range for type \w*int/i'                    => MDB2_ERROR_INVALID_NUMBER,                '/integer out of range/i'                    => MDB2_ERROR_INVALID_NUMBER,                '/value too long for type character/i'                '/attribute .* not found|relation .* does not have attribute/i'                    => MDB2_ERROR_NOSUCHFIELD,                '/column .* specified in USING clause does not exist in (left|right) table/i'                    => MDB2_ERROR_NOSUCHFIELD,                '/parser: parse error at or near/i'                '/column reference .* is ambiguous/i'                    => MDB2_ERROR_ACCESS_VIOLATION,                '/violates not-null constraint/'                    => MDB2_ERROR_CONSTRAINT_NOT_NULL,                '/violates [\w ]+ constraint/'                    => MDB2_ERROR_CONSTRAINT,                '/referential integrity violation/'                    => MDB2_ERROR_CONSTRAINT,                '/more expressions than target columns/i'                    => MDB2_ERROR_VALUE_COUNT_ON_ROW,            foreach ($error_regexps as $regexp => $code) {        return array($error_code, null, $native_msg) ;     * Quotes a string so it can be safely used in a query. It will quote     * the text so it can safely be used within a query.     * @param   string  the input string to quote     * @param   bool    escape wildcards     * @return  string  quoted string    function escape($text, $escape_wildcards = false)            $text = $this-> escapePattern($text) ;        $connection = $this-> getConnection() ;        if (MDB2:: isError($connection)) {            $text = @ pg_escape_string($connection, $text) ;            $text = @ pg_escape_string($text) ;    // {{{ beginTransaction()     * Start a transaction or set a savepoint.     * @param   string  name of a savepoint to set     * @return  mixed   MDB2_OK on success, a MDB2 error on failure        $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)) ;        if (null !== $savepoint) {            if (!$this->in_transaction) {                return $this->raiseError( MDB2_ERROR_INVALID, null, null,                    'savepoint cannot be released when changes are auto committed', __FUNCTION__) ;            $query = 'SAVEPOINT ' .$savepoint ;        if ($this->in_transaction) {            return MDB2_OK;  //nothing to do        if (!$this->destructor_registered && $this->opened_persistent) {            $this->destructor_registered = true;        $result = $this->_doQuery('BEGIN', true) ;        if (MDB2:: isError($result)) {        $this->in_transaction = true;     * Commit the database changes done during a transaction that is in     * progress or release a savepoint. This function may only be called when     * auto-committing is disabled, otherwise it will fail. Therefore, a new     * transaction is implicitly started after committing the pending changes.     * @param   string  name of a savepoint to release     * @return  mixed   MDB2_OK on success, a MDB2 error on failure    function commit($savepoint = null)        $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)) ;        if (!$this->in_transaction) {            return $this->raiseError( MDB2_ERROR_INVALID, null, null,                'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__) ;        if (null !== $savepoint) {            $query = 'RELEASE SAVEPOINT ' .$savepoint ;        $result = $this->_doQuery('COMMIT', true) ;        if (MDB2:: isError($result)) {        $this->in_transaction = false;     * Cancel any database changes done during a transaction or since a specific     * savepoint that is in progress. This function may only be called when     * auto-committing is disabled, otherwise it will fail. Therefore, a new     * transaction is implicitly started after canceling the pending changes.     * @param   string  name of a savepoint to rollback to     * @return  mixed   MDB2_OK on success, a MDB2 error on failure        $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)) ;        if (!$this->in_transaction) {            return $this->raiseError( MDB2_ERROR_INVALID, null, null,                'rollback cannot be done changes are auto committed', __FUNCTION__) ;        if (null !== $savepoint) {            $query = 'ROLLBACK TO SAVEPOINT ' .$savepoint ;        $result = $this->_doQuery($query, true) ;        if (MDB2:: isError($result)) {        $this->in_transaction = false;    // {{{ function setTransactionIsolation()     * Set the transacton isolation level.     * @param   string  standard isolation level     *                   READ UNCOMMITTED (allows dirty reads)     *                   READ COMMITTED (prevents dirty reads)     *                   REPEATABLE READ (prevents nonrepeatable reads)     *                   SERIALIZABLE (prevents phantom reads)     * @param   array some transaction options:     *                   'wait' => 'WAIT' | 'NO WAIT'     *                   'rw'   => 'READ WRITE' | 'READ ONLY'     * @return  mixed   MDB2_OK on success, a MDB2 error on failure        $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)) ;            return $this->raiseError( MDB2_ERROR_UNSUPPORTED, null, null,                'isolation level is not supported: '.$isolation, __FUNCTION__) ;        $query = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL $isolation ";     * Do the grunt work of connecting to the database     * @return mixed connection resource on success, MDB2 Error Object on failure    function _doConnect($username, $password, $database_name, $persistent = false)            return $this->raiseError( MDB2_ERROR_NOT_FOUND, null, null,                'extension '.$this->phptype .' is not compiled into PHP', __FUNCTION__) ;        if ($database_name == '') {            $database_name = 'template1' ;        $protocol = $this->dsn['protocol'] ? $this->dsn['protocol'] : 'tcp' ;        if ($protocol == 'tcp') {            if ($this->dsn['hostspec']) {                $params[0] .= 'host=' . $this->dsn['hostspec'] ;            if ($this->dsn['port']) {                $params[0] .= ' port=' . $this->dsn['port'] ;        } elseif ($protocol == 'unix') {            // Allow for pg socket in non-standard locations.            if ($this->dsn['socket']) {                $params[0] .= 'host=' . $this->dsn['socket'] ;            if ($this->dsn['port']) {                $params[0] .= ' port=' . $this->dsn['port'] ;            $params[0] .= ' dbname=\'' . addslashes($database_name) . '\'' ;            $params[0] .= ' user=\'' . addslashes($username) . '\'' ;            $params[0] .= ' password=\'' . addslashes($password) . '\'' ;        if (!empty($this->dsn['options'])) {            $params[0] .= ' options=' . $this->dsn['options'] ;        if (!empty($this->dsn['tty'])) {            $params[0] .= ' tty=' . $this->dsn['tty'] ;        if (!empty($this->dsn['connect_timeout'])) {            $params[0] .= ' connect_timeout=' . $this->dsn['connect_timeout'] ;        if (!empty($this->dsn['sslmode'])) {            $params[0] .= ' sslmode=' . $this->dsn['sslmode'] ;        if (!empty($this->dsn['service'])) {            $params[0] .= ' service=' . $this->dsn['service'] ;        if ($this->_isNewLinkSet()) {                $params[] = PGSQL_CONNECT_FORCE_NEW;        $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect' ;            return $this->raiseError( MDB2_ERROR_CONNECT_FAILED, null, null,                'unable to establish a connection', __FUNCTION__) ;       if (empty($this->dsn['disable_iso_date'])) {            if (!@pg_query($connection, "SET SESSION DATESTYLE = 'ISO'")) {                return $this->raiseError( null, null, null,                    'Unable to set date style to iso', __FUNCTION__) ;        if (!empty($this->dsn['charset'])) {            $result = $this->setCharset($this->dsn['charset'], $connection) ;            if (MDB2:: isError($result)) {        // Enable extra compatibility settings on 8.2 and later            $version = pg_parameter_status($connection, 'server_version') ;                return $this->raiseError( null, null, null,                  'Unable to retrieve server version', __FUNCTION__) ;            $version = explode ('.', $version) ;                || ($version['0'] == 8 && $version['1'] >= 2)                if (!@pg_query($connection, "SET SESSION STANDARD_CONFORMING_STRINGS = OFF")) {                    return $this->raiseError( null, null, null,                      'Unable to set standard_conforming_strings to off', __FUNCTION__) ;                if (!@pg_query($connection, "SET SESSION ESCAPE_STRING_WARNING = OFF")) {                    return $this->raiseError( null, null, null,                      'Unable to set escape_string_warning to off', __FUNCTION__) ;     * Connect to the database     * @return true on success, MDB2 Error Object on failure            //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0            if (MDB2:: areEquals($this->connected_dsn, $this->dsn)                && $this->connected_database_name == $this->database_name                && ($this->opened_persistent == $this->options['persistent'])        if ($this->database_name) {            $connection = $this->_doConnect($this->dsn['username'],                                            $this->options['persistent']);            if (MDB2:: isError($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 ;     * Set the charset on the current connection     * @param resource  connection handle     * @return true on success, MDB2 Error Object on failure        if (null === $connection) {            $connection = $this-> getConnection() ;            if (MDB2:: isError($connection)) {            $this->warnings[] = 'postgresql does not support setting client collation' ;        $result = @ pg_set_client_encoding($connection, $charset) ;            return $this->raiseError( null, null, null,                'Unable to set client charset: '.$charset, __FUNCTION__) ;     * 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                                 $this->options['persistent']);        if (!MDB2:: isError($res)) {     * Log out and disconnect from the database.     * @param  boolean $force if the disconnect should be forced even if the     *                         connection is opened persistently     * @return mixed true on success, false if not connected and error            if ($this->in_transaction) {                $database_name = $this->database_name ;                $persistent = $this->options['persistent'] ;                $this->dsn = $this->connected_dsn ;                $this->database_name = $this->connected_database_name ;                $this->options['persistent'] = $this->opened_persistent ;                $this->database_name = $database_name ;                $this->options['persistent'] = $persistent ;            if (!$this->opened_persistent || $force) {                $ok = @ pg_close($this->connection) ;                    return $this->raiseError( MDB2_ERROR_DISCONNECT_FAILED,                           null, null, null, __FUNCTION__) ;        return parent:: disconnect($force) ;     * @param string $query the SQL query     * @param mixed   $types  array that contains the types of the columns in     * @param boolean $is_manip  if the query is a manipulation query     * @return mixed MDB2_OK on success, a MDB2 error on failure        $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 (MDB2:: isError($connection)) {        $this->offset = $this->limit = 0;        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset) ;        $result = $this->_doQuery($query, $is_manip, $connection, $this->database_name) ;        if (!MDB2:: isError($result)) {                $result =  $this-> _affectedRows($connection, $result) ;                $result = $this-> _wrapResult($result, $types, true, true, $limit, $offset) ;     * @param string $query  query     * @param boolean $is_manip  if the query is a manipulation query     * @param resource $connection      * @param string $database_name      * @return result or error object    function _doQuery($query, $is_manip = false, $connection = null, $database_name = null)        $this->last_query = $query ;        $result = $this-> debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')) ;            if (MDB2:: isError($result)) {        if ($this->options['disable_query']) {            $result = $is_manip ? 0 : null;        if (null === $connection) {            $connection = $this-> getConnection() ;            if (MDB2:: isError($connection)) {        $function = $this->options['multi_query'] ? 'pg_send_query' : 'pg_query' ;        $result = @$function($connection, $query) ;            $err = $this-> raiseError( null, null, null,                'Could not execute statement', __FUNCTION__) ;        } elseif ($this->options['multi_query']) {            if (!($result = @ pg_get_result($connection))) {                $err = $this-> raiseError( null, null, null,                        'Could not get the first result from a multi query', __FUNCTION__) ;        $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)) ;     * Returns the number of rows affected     * @param resource $result      * @param resource $connection      * @return mixed MDB2 Error Object or the number of rows affected    function _affectedRows($connection, $result = null)        if (null === $connection) {            $connection = $this-> getConnection() ;            if (MDB2:: isError($connection)) {        return @pg_affected_rows($result) ;     * Changes a query string for various DBMS specific reasons     * @param string $query  query to modify     * @param boolean $is_manip  if it is a DML query     * @param integer $limit  limit the number of rows     * @param integer $offset  start reading from given offset     * @return string modified query            && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)            if (substr($query, -1) == ';') {                $query = substr($query, 0, -1) ;                $query.= "LIMIT $limit OFFSET $offset ";    // {{{ _modifyManipQuery()     * Changes a manip query string for various DBMS specific reasons     * @param string $query  query to modify     * @param integer $limit  limit the number of rows     * @return string modified query        $where = $pos ? substr($query, $pos) : '' ;        $manip_clause = '(\bDELETE\b\s+(?:\*\s+)?\bFROM\b|\bUPDATE\b)' ;        $from_clause  = '([\w\.]+)' ;        $where_clause = '(?:(.*)\bWHERE\b\s+(.*))|(.*)' ;        $pattern = '/^' . $manip_clause . '\s+' . $from_clause .'(?:\s)*(?:' . $where_clause .')?$/i' ;            $what  = (count($matches) == 6) ? $match[ 5] : $match[ 3] ;            return $manip.' ' .$from .' ' .$what .' WHERE ctid=(SELECT ctid FROM ' .$from .' ' .$where .' LIMIT ' .$limit .')' ;    // {{{ getServerVersion()     * return version information about the server     * @param bool   $native  determines if the raw version string should be returned     * @return mixed array/string with version information or MDB2 error object        $query = 'SHOW SERVER_VERSION' ;        if ($this->connected_server_info) {            $server_info = $this->connected_server_info ;            $server_info = $this-> queryOne($query, 'text') ;            if (MDB2:: isError($server_info)) {        $this->connected_server_info = $server_info ;        if (!$native && ! MDB2:: isError($server_info)) {            $tmp = explode('.', $server_info, 3) ;                    'native' => $server_info,                    'major' => isset($tmp[ 0]) ? $tmp[ 0] : null,                    'minor' => isset($tmp[ 1]) ? $tmp[ 1] : null,                    'patch' => isset($tmp[ 2]) ? $tmp[ 2] : null,                    'native' => $server_info,     * Prepares a query for multiple execution with execute().     * With some database backends, this is emulated.     * prepare() requires a generic query as string like     * 'INSERT INTO numbers VALUES(?,?)' or     * 'INSERT INTO numbers VALUES(:foo,:bar)'.     * The ? and :name and are placeholders which can be set using     * bindParam() and the query can be sent off using the execute() method.     * The allowed format for :name can be set with the 'bindname_format' option.     * @param string $query the query to prepare     * @param mixed   $types  array that contains the types of the placeholders     * @param mixed   $result_types  array that contains the types of the columns in     *                         the result set or MDB2_PREPARE_RESULT, if set to     *                         MDB2_PREPARE_MANIP the query is handled as a manipulation query     * @param mixed   $lobs   key (field) value (parameter) pair for all lob placeholders     * @return mixed resource handle for the prepared query on success, a MDB2     * @see bindParam, execute    function prepare($query, $types = null, $result_types = null, $lobs = array())        if ($this->options['emulate_prepared']) {            return parent:: prepare($query, $types, $result_types, $lobs) ;        $is_manip = ($result_types === MDB2_PREPARE_MANIP) ;        $this->offset = $this->limit = 0;        $result = $this-> debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')) ;            if (MDB2:: isError($result)) {        if ($pgtypes !== false && ! empty($types)) {            $this->loadModule('Datatype', null, true) ;        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset) ;        $placeholder_type_guess = $placeholder_type = null;        $position = $parameter = 0;        while ($position < strlen($query)) {            $q_position = strpos($query, $question, $position) ;            $c_position = strpos($query, $colon, $position) ;            //skip "::type" cast ("select id::varchar(20) from sometable where name=?")            $doublecolon_position = strpos($query, '::', $position) ;            if ($doublecolon_position !== false && $doublecolon_position == $c_position) {                $c_position = strpos($query, $colon, $position +2) ;            if ($q_position && $c_position) {                $p_position = min($q_position, $c_position) ;                $p_position = $q_position ;                $p_position = $c_position ;            if (null === $placeholder_type) {                $placeholder_type_guess = $query[$p_position] ;            $new_pos = $this-> _skipDelimitedStrings($query, $position, $p_position) ;            if (MDB2:: isError($new_pos)) {            if ($new_pos != $position) {                continue; //evaluate again starting from the new position            if ($query[$position] == $placeholder_type_guess) {                if (null === $placeholder_type) {                    $placeholder_type = $query[$p_position] ;                    $question = $colon = $placeholder_type ;                    if (!empty($types) && is_array($types)) {                        if ($placeholder_type == ':') {                if ($placeholder_type_guess == '?') {                    $regexp = '/^.{' .($position +1) .'}(' .$this->options['bindname_format'] .').*$/s' ;                        $err = $this-> raiseError( MDB2_ERROR_SYNTAX, null, null,                            'named parameter name must match "bindname_format" option', __FUNCTION__) ;                if ($pgtypes !== false) {                        $pgtypes[] = $this->datatype-> mapPrepareDatatype($types[$name]) ;                        $pgtypes[] = $this->datatype-> mapPrepareDatatype($types[$parameter]) ;                if (($key_parameter = array_search($name, $positions)) !== false) {                    $parameter = $key_parameter + 1;                    //foreach ($positions as $key => $value) {                    //    if ($key_parameter == $key) {                    //$next_parameter = $parameter;                $position = $p_position + strlen($parameter) ;        $connection = $this-> getConnection() ;        if (MDB2:: isError($connection)) {        static $prep_statement_counter = 1;        $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 (false === $pgtypes) {            $result = @ pg_prepare($connection, $statement_name, $query) ;                $err = $this-> raiseError( null, null, null,                    'Unable to create prepared statement handle', __FUNCTION__) ;                $types_string = ' (' .implode(', ', $pgtypes) .') ' ;            $query = 'PREPARE ' .$statement_name .$types_string .' AS ' .$query ;            $statement = $this->_doQuery($query, true, $connection) ;            if (MDB2:: isError($statement)) {        $class_name = 'MDB2_Statement_' .$this->phptype ;        $obj = new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset) ;        $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)) ;    // {{{ function getSequenceName($sqn)     * adds sequence name formatting to a sequence name     * @param   string  name of the sequence     * @return  string  formatted sequence name        if (false === $this->options['disable_smart_seqname']) {            if (strpos($sqn, '_') !== false) {                list($table, $field) = explode('_', $sqn, 2) ;            $schema_list = $this-> queryOne("SELECT array_to_string(current_schemas(false), ',')") ;            if (MDB2:: isError($schema_list) || empty($schema_list) || count($schema_list) < 2) {                $schema_clause = ' AND n.nspname=current_schema()' ;                $schemas = explode(',', $schema_list) ;                $schema_clause = ' AND n.nspname IN (' .$schema_list .')' ;                foreach ($schemas as $schema) {                    $order_by .= ' WHEN n.nspname=' .$schema .' THEN ' .$counter ++;                $order_by .= ' ELSE ' .$counter .' END, a.attnum' ;            $query = "SELECT substring((SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)                           WHERE d.adrelid = a.attrelid                         ) FROM 'nextval[^'']*''([^'']*)')                    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                    LEFT JOIN pg_namespace n ON c.relnamespace = n.oid                       WHERE (c.relname = ".$this-> quote($sqn, 'text') ;                $query .= " OR (c.relname = " .$this-> quote($table, 'text') ." AND a.attname = " .$this-> quote($field, 'text') .")" ;                         AND pg_get_expr(d.adbin, d.adrelid) LIKE 'nextval%'            $seqname = $this-> queryOne($query) ;            if (!MDB2:: isError($seqname) && ! empty($seqname) && is_string($seqname)) {        return parent:: getSequenceName($sqn) ;     * Returns the next free id of a sequence     * @param string $seq_name name of the sequence     * @param boolean $ondemand when true the sequence is     *                           automatic created, if it     * @return mixed MDB2 Error Object or id    function nextID($seq_name, $ondemand = true)        $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->popErrorHandling() ;        if (MDB2:: isError($result)) {            if ($ondemand && $result-> getCode() == MDB2_ERROR_NOSUCHTABLE) {                $this->loadModule('Manager', null, true) ;                $result = $this->manager-> createSequence($seq_name) ;                if (MDB2:: isError($result)) {                    return $this->raiseError($result, null, null,                        'on demand sequence could not be created', __FUNCTION__) ;                return $this->nextId($seq_name, false) ;     * Returns the autoincrement ID if supported or $id or fetches the current     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)     * @param string $table name of the table into which a new row was inserted     * @param string $field name of the field into which a new row was inserted     * @return mixed MDB2 Error Object or id        if (empty($table) && empty($field)) {            return $this->queryOne('SELECT lastval()', 'integer') ;        $seq = $table .( empty($field) ? '' : '_' .$field) ;        $sequence_name = $this-> quoteIdentifier($this->getSequenceName($seq), true) ;        return $this->queryOne( "SELECT currval('$sequence_name') ", 'integer') ;     * Returns the current id of a sequence     * @param string $seq_name name of the sequence     * @return mixed MDB2 Error Object or id        $sequence_name = $this-> quoteIdentifier($this->getSequenceName($seq_name), true) ;        return $this->queryOne( "SELECT last_value FROM $sequence_name ", 'integer') ; * MDB2 PostGreSQL result driver * @author  Paul Cooper <pgc@ucecom.com>     * Fetch a row and insert the data into an existing array.     * @param int       $fetchmode  how the array data should be indexed     * @param int    $rownum    number of the row where the data can be found     * @return int data array on success, a MDB2 error on failure    function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)            $seek = $this-> seek($rownum) ;            if (MDB2:: isError($seek)) {        if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {            $fetchmode = $this->db-> fetchmode;        if (   $fetchmode == MDB2_FETCHMODE_ASSOC            || $fetchmode == MDB2_FETCHMODE_OBJECT            $row = @ pg_fetch_array($this->result, null, PGSQL_ASSOC) ;                && $this->db-> options['portability'] & MDB2_PORTABILITY_FIX_CASE            $row = @ pg_fetch_row($this->result) ;            if (false === $this->result) {                $err = $this->db-> raiseError( MDB2_ERROR_NEED_MORE_DATA, null, null,                    'resultset has already been freed', __FUNCTION__) ;        $mode = $this->db-> options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;        if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) {            if (empty($this->types)) {                $mode += MDB2_PORTABILITY_RTRIM;            $this->db->_fixResultArrayValues($row, $mode) ;        if (   (   $fetchmode != MDB2_FETCHMODE_ASSOC                && $fetchmode != MDB2_FETCHMODE_OBJECT)            $row = $this->db-> datatype-> convertResultRow($this->types, $row, $rtrim) ;        } elseif (($fetchmode == MDB2_FETCHMODE_ASSOC                || $fetchmode == MDB2_FETCHMODE_OBJECT)            && ! empty($this->types_assoc)            $row = $this->db-> datatype-> convertResultRow($this->types_assoc, $row, $rtrim) ;        if (!empty($this->values)) {            $this->_assignBindColumns($row) ;        if ($fetchmode === MDB2_FETCHMODE_OBJECT) {            $object_class = $this->db-> options['fetch_class'] ;            if ($object_class == 'stdClass') {                $rowObj = new $object_class($row) ;     * Retrieve the names of columns returned by the DBMS in a query result.     * @return  mixed   Array variable that holds the names of columns as keys     *                   or an MDB2 error on failure.     *                   Some DBMS may not return any columns when the result set     *                   does not contain any rows.    function _getColumnNames()        if (MDB2:: isError($numcols)) {        for ($column = 0; $column < $numcols ; $column ++) {            $column_name = @ pg_field_name($this->result, $column) ;            $columns[$column_name] = $column ;        if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {     * Count the number of columns returned by the DBMS in a query result.     * @return mixed integer value with the number of columns, a MDB2 error        $cols = @ pg_num_fields($this->result) ;            if (false === $this->result) {                return $this->db->raiseError( MDB2_ERROR_NEED_MORE_DATA, null, null,                    'resultset has already been freed', __FUNCTION__) ;            if (null === $this->result) {                return count($this->types);            return $this->db->raiseError( null, null, null,                'Could not get column count', __FUNCTION__) ;     * Move the internal result pointer to the next available result     * @return true on success, false if there is no more result set or an error object on failure        $connection = $this->db-> getConnection() ;        if (MDB2:: isError($connection)) {        if (!($this->result = @ pg_get_result($connection))) {     * Free the internal resources associated with result.     * @return boolean true on success, false if result is invalid        if (is_resource($this->result) && $this->db-> connection) {            $free = @ pg_free_result($this->result) ;                return $this->db->raiseError( null, null, null,                    'Could not free result', __FUNCTION__) ; * MDB2 PostGreSQL buffered result driver * @author  Paul Cooper <pgc@ucecom.com>     * Seek to a specific row in a result set     * @param int    $rownum    number of the row where the data can be found     * @return mixed MDB2_OK on success, a MDB2 error on failure    function seek($rownum = 0)        if ($this->rownum != ($rownum - 1) && !@ pg_result_seek($this->result, $rownum)) {            if (false === $this->result) {                return $this->db->raiseError( MDB2_ERROR_NEED_MORE_DATA, null, null,                    'resultset has already been freed', __FUNCTION__) ;            if (null === $this->result) {            return $this->db->raiseError( MDB2_ERROR_INVALID, null, null,                'tried to seek to an invalid row number ('.$rownum .')', __FUNCTION__) ;        $this->rownum = $rownum - 1;     * Check if the end of the result set has been reached     * @return mixed true or false on sucess, a MDB2 error on failure        if (MDB2:: isError($numrows)) {        return $this->rownum < ($numrows - 1) ;     * Returns the number of rows in a result object     * @return mixed MDB2 Error Object or the number of rows        $rows = @ pg_num_rows($this->result) ;            if (false === $this->result) {                return $this->db->raiseError( MDB2_ERROR_NEED_MORE_DATA, null, null,                    'resultset has already been freed', __FUNCTION__) ;            if (null === $this->result) {            return $this->db->raiseError( null, null, null,                'Could not get row count', __FUNCTION__) ; * MDB2 PostGreSQL statement driver * @author  Paul Cooper <pgc@ucecom.com>     * Execute a prepared query statement helper method.     * @param mixed $result_class string which specifies which result class to use     * @param mixed $result_wrap_class string which specifies which class to wrap results in     * @return mixed MDB2_Result or integer (affected rows) on success,     *                a MDB2 error on failure    function _execute($result_class = true, $result_wrap_class = true)        if (null === $this->statement) {            return parent:: _execute($result_class, $result_wrap_class) ;        $this->db->last_query = $this->query ;        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values)) ;        if ($this->db->getOption('disable_query')) {            $result = $this->is_manip ? 0 : null;        $connection = $this->db-> getConnection() ;        if (MDB2:: isError($connection)) {        // todo: disabled until pg_execute() bytea issues are cleared up            $query = 'EXECUTE ' .$this->statement ;        if (!empty($this->positions)) {            foreach ($this->positions as $parameter) {                    return $this->db->raiseError( MDB2_ERROR_NOT_FOUND, null, null,                        'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__) ;                $value = $this->values[$parameter] ;                $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null;                if (is_resource($value) || $type == 'clob' || $type == 'blob' || $this->db-> options['lob_allow_url_include']) {                        if ($match[1] == 'file://') {                        $value = @fopen($value, 'r') ;                            $data.= @fread($value, $this->db-> options['lob_buffer_length']) ;                $quoted = $this->db-> quote($value, $type, $query) ;                if (MDB2:: isError($quoted)) {                $query.= ' (' .implode(', ', $parameters) .')' ;            $result = @ pg_execute($connection, $this->statement, $parameters) ;                $err = $this->db-> raiseError( null, null, null,                    'Unable to execute statement', __FUNCTION__) ;            $result = $this->db-> _doQuery($query, $this->is_manip, $connection) ;            if (MDB2:: isError($result)) {            $affected_rows = $this->db-> _affectedRows($connection, $result) ;        $result = $this->db-> _wrapResult($result, $this->result_types,            $result_class, $result_wrap_class, $this->limit, $this->offset);        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)) ;     * Release resources allocated for the specified prepared query.     * @return mixed MDB2_OK on success, a MDB2 error on failure        if (null === $this->positions) {            return $this->db->raiseError( MDB2_ERROR, null, null,                'Prepared statement has already been freed', __FUNCTION__) ;        if (null !== $this->statement) {            $connection = $this->db-> getConnection() ;            if (MDB2:: isError($connection)) {            $query = 'DEALLOCATE PREPARE ' .$this->statement ;            $result = $this->db-> _doQuery($query, true, $connection) ;     * @param string $name name of the table that should be dropped     * @return mixed MDB2_OK on success, a MDB2 error on failure        $db = $this-> getDBInstance() ;        if (MDB2:: isError($db)) {        $name = $db-> quoteIdentifier($name, true) ;        $result = $db-> exec( "DROP TABLE $name ") ;        if (MDB2:: isError($result)) {            $result = $db-> exec( "DROP TABLE $name CASCADE ") ;
		    
 
		    Documentation generated on Mon, 11 Mar 2019 15:51:24 -0400 by phpDocumentor 1.4.4 . PEAR Logo Copyright ©  PHP Group 2004.
	       |