MDB2
[ class tree: MDB2 ] [ index: MDB2 ] [ all elements ]

Source for file pgsql.php

Documentation is available at pgsql.php

  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP versions 4 and 5                                                 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  7. // | Stig. S. Bakken, Lukas Smith                                         |
  8. // | All rights reserved.                                                 |
  9. // +----------------------------------------------------------------------+
  10. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  11. // | API as well as database abstraction for PHP applications.            |
  12. // | This LICENSE is in the BSD license style.                            |
  13. // |                                                                      |
  14. // | Redistribution and use in source and binary forms, with or without   |
  15. // | modification, are permitted provided that the following conditions   |
  16. // | are met:                                                             |
  17. // |                                                                      |
  18. // | Redistributions of source code must retain the above copyright       |
  19. // | notice, this list of conditions and the following disclaimer.        |
  20. // |                                                                      |
  21. // | Redistributions in binary form must reproduce the above copyright    |
  22. // | notice, this list of conditions and the following disclaimer in the  |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // |                                                                      |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission.                                                  |
  29. // |                                                                      |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Paul Cooper <pgc@ucecom.com>                                 |
  44. // +----------------------------------------------------------------------+
  45. //
  46. // $Id: pgsql.php,v 1.64 2005/04/25 13:09:03 lsmith Exp $
  47.  
  48. /**
  49.  * MDB2 PostGreSQL driver
  50.  *
  51.  * @package MDB2
  52.  * @category Database
  53.  * @author  Paul Cooper <pgc@ucecom.com>
  54.  */
  55. {
  56.     // {{{ properties
  57.     var $escape_quotes = "\\";
  58.  
  59.     // }}}
  60.     // {{{ constructor
  61.  
  62.     /**
  63.     * Constructor
  64.     */
  65.     function __construct()
  66.     {
  67.         parent::__construct();
  68.  
  69.         $this->phptype = 'pgsql';
  70.         $this->dbsyntax = 'pgsql';
  71.  
  72.         $this->supported['sequences'= true;
  73.         $this->supported['indexes'= true;
  74.         $this->supported['affected_rows'= true;
  75.         $this->supported['summary_functions'= true;
  76.         $this->supported['order_by_text'= true;
  77.         $this->supported['transactions'= true;
  78.         $this->supported['current_id'= true;
  79.         $this->supported['limit_queries'= true;
  80.         $this->supported['LOBs'= true;
  81.         $this->supported['replace'= true;
  82.         $this->supported['sub_selects'= true;
  83.         $this->supported['auto_increment'= false;
  84.     }
  85.  
  86.     // }}}
  87.     // {{{ errorInfo()
  88.  
  89.     /**
  90.      * This method is used to collect information about an error
  91.      *
  92.      * @param integer $error 
  93.      * @return array 
  94.      * @access public
  95.      */
  96.     function errorInfo($error = null)
  97.     {
  98.         $native_msg '';
  99.         if (is_resource($error)) {
  100.             $native_msg @pg_result_error($error);
  101.         elseif ($this->connection{
  102.             $native_msg @pg_last_error($this->connection);
  103.         }
  104.  
  105.         // Fall back to MDB2_ERROR if there was no mapping.
  106.         $error MDB2_ERROR;
  107.  
  108.         static $error_regexps;
  109.         if (empty($error_regexps)) {
  110.             $error_regexps = array(
  111.                 '/(relation|sequence|table).*does not exist|class .* not found/i'
  112.                     => MDB2_ERROR_NOSUCHTABLE,
  113.                 '/index .* does not exist/'
  114.                     => MDB2_ERROR_NOT_FOUND,
  115.                 '/column .* does not exist/i'
  116.                     => MDB2_ERROR_NOSUCHFIELD,
  117.                 '/relation .* already exists/i'
  118.                     => MDB2_ERROR_ALREADY_EXISTS,
  119.                 '/(divide|division) by zero$/i'
  120.                     => MDB2_ERROR_DIVZERO,
  121.                 '/pg_atoi: error in .*: can\'t parse /i'
  122.                     => MDB2_ERROR_INVALID_NUMBER,
  123.                 '/invalid input syntax for( type)? (integer|numeric)/i'
  124.                     => MDB2_ERROR_INVALID_NUMBER,
  125.                 '/value .* is out of range for type \w*int/i'
  126.                     => MDB2_ERROR_INVALID_NUMBER,
  127.                 '/integer out of range/i'
  128.                     => MDB2_ERROR_INVALID_NUMBER,
  129.                 '/value too long for type character/i'
  130.                     => MDB2_ERROR_INVALID,
  131.                 '/attribute .* not found|relation .* does not have attribute/i'
  132.                     => MDB2_ERROR_NOSUCHFIELD,
  133.                 '/column .* specified in USING clause does not exist in (left|right) table/i'
  134.                     => MDB2_ERROR_NOSUCHFIELD,
  135.                 '/parser: parse error at or near/i'
  136.                     => MDB2_ERROR_SYNTAX,
  137.                 '/syntax error at/'
  138.                     => MDB2_ERROR_SYNTAX,
  139.                 '/column reference .* is ambiguous/i'
  140.                     => MDB2_ERROR_SYNTAX,
  141.                 '/permission denied/'
  142.                     => MDB2_ERROR_ACCESS_VIOLATION,
  143.                 '/violates not-null constraint/'
  144.                     => MDB2_ERROR_CONSTRAINT_NOT_NULL,
  145.                 '/violates [\w ]+ constraint/'
  146.                     => MDB2_ERROR_CONSTRAINT,
  147.                 '/referential integrity violation/'
  148.                     => MDB2_ERROR_CONSTRAINT,
  149.                 '/more expressions than target columns/i'
  150.                     => MDB2_ERROR_VALUE_COUNT_ON_ROW,
  151.             );
  152.         }
  153.         foreach ($error_regexps as $regexp => $code{
  154.             if (preg_match($regexp$native_msg)) {
  155.                 $error $code;
  156.                 break;
  157.             }
  158.         }
  159.  
  160.         return array($errornull$native_msg);
  161.     }
  162.  
  163.     // }}}
  164.     // {{{ beginTransaction()
  165.  
  166.     /**
  167.      * Start a transaction.
  168.      *
  169.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  170.      * @access public
  171.      */
  172.     function beginTransaction()
  173.     {
  174.         $this->debug('starting transaction''beginTransaction');
  175.         if ($this->in_transaction{
  176.             return MDB2_OK;  //nothing to do
  177.         }
  178.         if (!$this->destructor_registered && $this->opened_persistent{
  179.             $this->destructor_registered = true;
  180.             register_shutdown_function('MDB2_closeOpenTransactions');
  181.         }
  182.         $result $this->_doQuery('BEGIN'true);
  183.         if (PEAR::isError($result)) {
  184.             return $result;
  185.         }
  186.         $this->in_transaction = true;
  187.         return MDB2_OK;
  188.     }
  189.  
  190.     // }}}
  191.     // {{{ commit()
  192.  
  193.     /**
  194.      * Commit the database changes done during a transaction that is in
  195.      * progress.
  196.      *
  197.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  198.      * @access public
  199.      */
  200.     function commit()
  201.     {
  202.         $this->debug('commit transaction''commit');
  203.         if (!$this->in_transaction{
  204.             return $this->raiseError(MDB2_ERRORnullnull,
  205.                 'commit: transaction changes are being auto committed');
  206.         }
  207.         $result $this->_doQuery('COMMIT'true);
  208.         if (PEAR::isError($result)) {
  209.             return $result;
  210.         }
  211.         $this->in_transaction = false;
  212.         return MDB2_OK;
  213.     }
  214.  
  215.     // }}}
  216.     // {{{ rollback()
  217.  
  218.     /**
  219.      * Cancel any database changes done during a transaction that is in
  220.      * progress.
  221.      *
  222.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  223.      * @access public
  224.      */
  225.     function rollback()
  226.     {
  227.         $this->debug('rolling back transaction''rollback');
  228.         if (!$this->in_transaction{
  229.             return $this->raiseError(MDB2_ERRORnullnull,
  230.                 'rollback: transactions can not be rolled back when changes are auto committed');
  231.         }
  232.         $result $this->_doQuery('ROLLBACK'true);
  233.         if (PEAR::isError($result)) {
  234.             return $result;
  235.         }
  236.         $this->in_transaction = false;
  237.         return MDB2_OK;
  238.     }
  239.  
  240.     // }}}
  241.     // {{{ _doConnect()
  242.  
  243.     /**
  244.      * Does the grunt work of connecting to the database
  245.      *
  246.      * @return mixed connection resource on success, MDB2 Error Object on failure
  247.      * @access protected
  248.      ***/
  249.     function _doConnect($database_name$persistent = false)
  250.     {
  251.         if ($database_name == ''{
  252.             $database_name 'template1';
  253.         }
  254.  
  255.         $protocol $this->dsn['protocol'$this->dsn['protocol''tcp';
  256.  
  257.         $params = array('');
  258.         if ($protocol == 'tcp'{
  259.             if ($this->dsn['hostspec']{
  260.                 $params[0.= 'host=' $this->dsn['hostspec'];
  261.             }
  262.             if ($this->dsn['port']{
  263.                 $params[0.= ' port=' $this->dsn['port'];
  264.             }
  265.         elseif ($protocol == 'unix'{
  266.             // Allow for pg socket in non-standard locations.
  267.             if ($this->dsn['socket']{
  268.                 $params[0.= 'host=' $this->dsn['socket'];
  269.             }
  270.             if ($this->dsn['port']{
  271.                 $params[0.= ' port=' $this->dsn['port'];
  272.             }
  273.         }
  274.         if ($database_name{
  275.             $params[0.= ' dbname=\'' addslashes($database_name'\'';
  276.         }
  277.         if ($this->dsn['username']{
  278.             $params[0.= ' user=\'' addslashes($this->dsn['username']'\'';
  279.         }
  280.         if ($this->dsn['password']{
  281.             $params[0.= ' password=\'' addslashes($this->dsn['password']'\'';
  282.         }
  283.         if (!empty($this->dsn['options'])) {
  284.             $params[0.= ' options=' $this->dsn['options'];
  285.         }
  286.         if (!empty($this->dsn['tty'])) {
  287.             $params[0.= ' tty=' $this->dsn['tty'];
  288.         }
  289.         if (!empty($this->dsn['connect_timeout'])) {
  290.             $params[0.= ' connect_timeout=' $this->dsn['connect_timeout'];
  291.         }
  292.         if (!empty($this->dsn['sslmode'])) {
  293.             $params[0.= ' sslmode=' $this->dsn['sslmode'];
  294.         }
  295.         if (!empty($this->dsn['service'])) {
  296.             $params[0.= ' service=' $this->dsn['service'];
  297.         }
  298.  
  299.         if (isset($this->dsn['new_link'])
  300.             && ($this->dsn['new_link'== 'true' || $this->dsn['new_link'=== true))
  301.         {
  302.             if (version_compare(phpversion()'4.3.0''>=')) {
  303.                 $params[= PGSQL_CONNECT_FORCE_NEW;
  304.             }
  305.         }
  306.  
  307.         $connect_function $persistent 'pg_pconnect' 'pg_connect';
  308.  
  309.         putenv('PGDATESTYLE=ISO');
  310.  
  311.         @ini_set('track_errors'true);
  312.         $php_errormsg '';
  313.         $connection @call_user_func_array($connect_function$params);
  314.         @ini_restore('track_errors');
  315.         if (!$connection{
  316.             return $this->raiseError(MDB2_ERROR_CONNECT_FAILED,
  317.                 nullnullstrip_tags($php_errormsg));
  318.         }
  319.         return $connection;
  320.     }
  321.  
  322.     // }}}
  323.     // {{{ connect()
  324.  
  325.     /**
  326.      * Connect to the database
  327.      *
  328.      * @return true on success, MDB2 Error Object on failure
  329.      * @access public
  330.      ***/
  331.     function connect()
  332.     {
  333.         if (is_resource($this->connection)) {
  334.             if (count(array_diff($this->connected_dsn$this->dsn)) == 0
  335.                 && $this->connected_database_name == $this->database_name
  336.                 && ($this->opened_persistent == $this->options['persistent'])
  337.             {
  338.                 return MDB2_OK;
  339.             }
  340.             $this->disconnect(false);
  341.         }
  342.  
  343.         if (!PEAR::loadExtension($this->phptype)) {
  344.             return $this->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  345.                 'connect: extension '.$this->phptype.' is not compiled into PHP');
  346.         }
  347.  
  348.         if ($this->database_name{
  349.             $connection $this->_doConnect($this->database_name$this->options['persistent']);
  350.             if (PEAR::isError($connection)) {
  351.                 return $connection;
  352.             }
  353.             $this->connection = $connection;
  354.             $this->connected_dsn = $this->dsn;
  355.             $this->connected_database_name = $this->database_name;
  356.             $this->opened_persistent = $this->options['persistent'];
  357.             $this->dbsyntax = $this->dsn['dbsyntax'$this->dsn['dbsyntax'$this->phptype;
  358.         }
  359.         return MDB2_OK;
  360.     }
  361.  
  362.     // }}}
  363.     // {{{ disconnect()
  364.  
  365.     /**
  366.      * Log out and disconnect from the database.
  367.      *
  368.      * @return mixed true on success, false if not connected and error
  369.      *                 object on error
  370.      * @access public
  371.      */
  372.     function disconnect($force = true)
  373.     {
  374.         if (is_resource($this->connection)) {
  375.             if (!$this->opened_persistent || $force{
  376.                 @pg_close($this->connection);
  377.             }
  378.             $this->connection = 0;
  379.         }
  380.         return MDB2_OK;
  381.     }
  382.  
  383.     // }}}
  384.     // {{{ standaloneQuery()
  385.  
  386.    /**
  387.      * execute a query as DBA
  388.      *
  389.      * @param string $query the SQL query
  390.      * @param mixed   $types  array that contains the types of the columns in
  391.      *                         the result set
  392.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  393.      * @access public
  394.      */
  395.     function &standaloneQuery($query$types = null)
  396.     {
  397.         $connection $this->_doConnect('template1'false);
  398.         if (PEAR::isError($connection)) {
  399.             return $this->raiseError(MDB2_ERROR_CONNECT_FAILEDnullnull,
  400.                 'Cannot connect to template1');
  401.         }
  402.  
  403.         $isManip MDB2::isManip($query);
  404.         $offset $this->row_offset;
  405.         $limit $this->row_limit;
  406.         $this->row_offset = $this->row_limit = 0;
  407.         $query $this->_modifyQuery($query$isManip$limit$offset);
  408.  
  409.         $result $this->_doQuery($query$isManip$connectionfalse);
  410.         @pg_close($connection);
  411.         if (PEAR::isError($result)) {
  412.             return $result;
  413.         }
  414.  
  415.         if ($isManip{
  416.             return $result;
  417.         }
  418.  
  419.         return $this->_wrapResult($result$typestruefalse$limit$offset);
  420.     }
  421.  
  422.     // }}}
  423.     // {{{ _doQuery()
  424.  
  425.     /**
  426.      * Execute a query
  427.      * @param string $query  query
  428.      * @param boolean $isManip  if the query is a manipulation query
  429.      * @param resource $connection 
  430.      * @param string $database_name 
  431.      * @return result or error object
  432.      * @access protected
  433.      */
  434.     function _doQuery($query$isManip = false$connection = null$database_name = null)
  435.     {
  436.         $this->last_query = $query;
  437.         $this->debug($query'query');
  438.         if ($this->options['disable_query']{
  439.             if ($isManip{
  440.                 return MDB2_OK;
  441.             }
  442.             return null;
  443.         }
  444.  
  445.         if (is_null($connection)) {
  446.             $error $this->connect();
  447.             if (PEAR::isError($error)) {
  448.                 return $error;
  449.             }
  450.             $connection $this->connection;
  451.         }
  452.  
  453.         $result @pg_query($connection$query);
  454.         if (!$result{
  455.             return $this->raiseError();
  456.         }
  457.  
  458.         if ($isManip{
  459.             return @pg_affected_rows($result);
  460.         }
  461.         return $result;
  462.     }
  463.  
  464.     // }}}
  465.     // {{{ _modifyQuery()
  466.  
  467.     /**
  468.      * Changes a query string for various DBMS specific reasons
  469.      *
  470.      * @param string $query  query to modify
  471.      * @return the new (modified) query
  472.      * @access protected
  473.      */
  474.     function _modifyQuery($query$isManip$limit$offset)
  475.     {
  476.         if ($limit > 0
  477.             && !preg_match('/LIMIT\s*\d(\s*(,|OFFSET)\s*\d+)?/i'$query)
  478.         {
  479.             $query rtrim($query);
  480.             if (substr($query-1== ';'{
  481.                 $query substr($query0-1);
  482.             }
  483.             if ($isManip{
  484.                 $manip preg_replace('/^(DELETE FROM|UPDATE).*$/''\\1'$query);
  485.                 $from $match[2];
  486.                 $where $match[3];
  487.                 $query $manip.' '.$from.' WHERE ctid=(SELECT ctid FROM '.$from.' '.$where.' LIMIT '.$limit.')';
  488.             else {
  489.                 $query .= " LIMIT $limit OFFSET $offset";
  490.             }
  491.         }
  492.         return $query;
  493.     }
  494.  
  495.     // }}}
  496.     // {{{ nextID()
  497.  
  498.     /**
  499.      * returns the next free id of a sequence
  500.      *
  501.      * @param string  $seq_name name of the sequence
  502.      * @param boolean $ondemand when true the seqence is
  503.      *                           automatic created, if it
  504.      *                           not exists
  505.      * @return mixed MDB2 Error Object or id
  506.      * @access public
  507.      */
  508.     function nextID($seq_name$ondemand = true)
  509.     {
  510.         $sequence_name $this->getSequenceName($seq_name);
  511.         $query = "SELECT NEXTVAL('$sequence_name')";
  512.         $this->expectError(MDB2_ERROR_NOSUCHTABLE);
  513.         $result $this->queryOne($query'integer');
  514.         $this->popExpect();
  515.         if (PEAR::isError($result)) {
  516.             if ($ondemand && $result->getCode(== MDB2_ERROR_NOSUCHTABLE{
  517.                 $this->loadModule('Manager');
  518.                 $result $this->manager->createSequence($seq_name1);
  519.                 if (PEAR::isError($result)) {
  520.                     return $this->raiseError(MDB2_ERRORnullnull,
  521.                         'nextID: on demand sequence could not be created');
  522.                 }
  523.                 return $this->nextId($seq_namefalse);
  524.             }
  525.         }
  526.         return $result;
  527.     }
  528.  
  529.     // }}}
  530.     // {{{ currID()
  531.  
  532.     /**
  533.      * returns the current id of a sequence
  534.      *
  535.      * @param string  $seq_name name of the sequence
  536.      * @return mixed MDB2 Error Object or id
  537.      * @access public
  538.      */
  539.     function currID($seq_name)
  540.     {
  541.         $sequence_name $this->getSequenceName($seq_name);
  542.         return $this->queryOne("SELECT last_value FROM $sequence_name"'integer');
  543.     }
  544. }
  545.  
  546. class MDB2_Result_pgsql extends MDB2_Result_Common
  547. {
  548.     // }}}
  549.     // {{{ fetchRow()
  550.  
  551.     /**
  552.      * Fetch a row and insert the data into an existing array.
  553.      *
  554.      * @param int       $fetchmode  how the array data should be indexed
  555.      * @param int    $rownum    number of the row where the data can be found
  556.      * @return int data array on success, a MDB2 error on failure
  557.      * @access public
  558.      */
  559.     function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT$rownum = null)
  560.     {
  561.         if (!is_null($rownum)) {
  562.             $seek $this->seek($rownum);
  563.             if (PEAR::isError($seek)) {
  564.                 return $seek;
  565.             }
  566.         }
  567.         if ($fetchmode == MDB2_FETCHMODE_DEFAULT{
  568.             $fetchmode $this->db->fetchmode;
  569.         }
  570.         if ($fetchmode MDB2_FETCHMODE_ASSOC{
  571.             $row @pg_fetch_array($this->resultnullPGSQL_ASSOC);
  572.             if (is_array($row)
  573.                 && $this->db->options['portability'MDB2_PORTABILITY_LOWERCASE
  574.             {
  575.                 $row array_change_key_case($rowCASE_LOWER);
  576.             }
  577.         else {
  578.             $row @pg_fetch_row($this->result);
  579.         }
  580.         if (!$row{
  581.             if (is_null($this->result)) {
  582.                 return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  583.                     'fetchRow: resultset has already been freed');
  584.             }
  585.             return null;
  586.         }
  587.         if ($this->db->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL{
  588.             $this->db->_convertEmptyArrayValuesToNull($row);
  589.         }
  590.         if (isset($this->values)) {
  591.             $this->_assignBindColumns($row);
  592.         }
  593.         if (isset($this->types)) {
  594.             $row $this->db->datatype->convertResultRow($this->types$row);
  595.         }
  596.         if ($fetchmode === MDB2_FETCHMODE_OBJECT{
  597.             $object_class $this->db->options['fetch_class'];
  598.             if ($object_class == 'stdClass'{
  599.                 $row = (object) $row;
  600.             else {
  601.                 $row &new $object_class($row);
  602.             }
  603.         }
  604.         ++$this->rownum;
  605.         return $row;
  606.     }
  607.  
  608.     // }}}
  609.     // {{{ _getColumnNames()
  610.  
  611.     /**
  612.      * Retrieve the names of columns returned by the DBMS in a query result.
  613.      *
  614.      * @return mixed                an associative array variable
  615.      *                               that will hold the names of columns. The
  616.      *                               indexes of the array are the column names
  617.      *                               mapped to lower case and the values are the
  618.      *                               respective numbers of the columns starting
  619.      *                               from 0. Some DBMS may not return any
  620.      *                               columns when the result set does not
  621.      *                               contain any rows.
  622.      *
  623.      *                               a MDB2 error on failure
  624.      * @access private
  625.      */
  626.     function _getColumnNames()
  627.     {
  628.         $columns = array();
  629.         $numcols $this->numCols();
  630.         if (PEAR::isError($numcols)) {
  631.             return $numcols;
  632.         }
  633.         for ($column = 0; $column $numcols$column++{
  634.             $column_name @pg_field_name($this->result$column);
  635.             $columns[$column_name$column;
  636.         }
  637.         if ($this->db->options['portability'MDB2_PORTABILITY_LOWERCASE{
  638.             $columns array_change_key_case($columnsCASE_LOWER);
  639.         }
  640.         return $columns;
  641.     }
  642.  
  643.     // }}}
  644.     // {{{ numCols()
  645.  
  646.     /**
  647.      * Count the number of columns returned by the DBMS in a query result.
  648.      *
  649.      * @access public
  650.      * @return mixed integer value with the number of columns, a MDB2 error
  651.      *                        on failure
  652.      */
  653.     function numCols()
  654.     {
  655.         $cols @pg_num_fields($this->result);
  656.         if (is_null($cols)) {
  657.             if (is_null($this->result)) {
  658.                 return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  659.                     'numCols: resultset has already been freed');
  660.             }
  661.             return $this->db->raiseError();
  662.         }
  663.         return $cols;
  664.     }
  665.  
  666.     // }}}
  667.     // {{{ free()
  668.  
  669.     /**
  670.      * Free the internal resources associated with result.
  671.      *
  672.      * @return boolean true on success, false if result is invalid
  673.      * @access public
  674.      */
  675.     function free()
  676.     {
  677.         $free @pg_free_result($this->result);
  678.         if (!$free{
  679.             if (is_null($this->result)) {
  680.                 return MDB2_OK;
  681.             }
  682.             return $this->db->raiseError();
  683.         }
  684.         $this->result = null;
  685.         return MDB2_OK;
  686.     }
  687. }
  688.  
  689. class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql
  690. {
  691.     // {{{ seek()
  692.  
  693.     /**
  694.     * seek to a specific row in a result set
  695.     *
  696.     * @param int    $rownum    number of the row where the data can be found
  697.     * @return mixed MDB2_OK on success, a MDB2 error on failure
  698.     * @access public
  699.     */
  700.     function seek($rownum = 0)
  701.     {
  702.         if ($this->rownum != ($rownum - 1&& !@pg_result_seek($this->result$rownum)) {
  703.             if (is_null($this->result)) {
  704.                 return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  705.                     'seek: resultset has already been freed');
  706.             }
  707.             return $this->db->raiseError(MDB2_ERROR_INVALIDnullnull,
  708.                 'seek: tried to seek to an invalid row number ('.$rownum.')');
  709.         }
  710.         $this->rownum $rownum - 1;
  711.         return MDB2_OK;
  712.     }
  713.  
  714.     // }}}
  715.     // {{{ valid()
  716.  
  717.     /**
  718.     * check if the end of the result set has been reached
  719.     *
  720.     * @return mixed true or false on sucess, a MDB2 error on failure
  721.     * @access public
  722.     */
  723.     function valid()
  724.     {
  725.         $numrows $this->numRows();
  726.         if (PEAR::isError($numrows)) {
  727.             return $numrows;
  728.         }
  729.         return $this->rownum ($numrows - 1);
  730.     }
  731.  
  732.     // }}}
  733.     // {{{ numRows()
  734.  
  735.     /**
  736.     * returns the number of rows in a result object
  737.     *
  738.     * @return mixed MDB2 Error Object or the number of rows
  739.     * @access public
  740.     */
  741.     function numRows()
  742.     {
  743.         $rows @pg_num_rows($this->result);
  744.         if (is_null($rows)) {
  745.             if (is_null($this->result)) {
  746.                 return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  747.                     'numRows: resultset has already been freed');
  748.             }
  749.             return $this->raiseError();
  750.         }
  751.         return $rows;
  752.     }
  753. }
  754.  
  755. class MDB2_Statement_pgsql extends MDB2_Statement_Common
  756. {
  757.  
  758. }
  759. ?>

Documentation generated on Mon, 11 Mar 2019 14:20:24 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.