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 Version 4                                                        |
  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.13 2004/04/23 17:06:46 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 MDB2_Driver_pgsql()
  66.     {
  67.         $this->MDB2_Driver_Common();
  68.         $this->phptype 'pgsql';
  69.         $this->dbsyntax 'pgsql';
  70.  
  71.         $this->supported['sequences'= true;
  72.         $this->supported['indexes'= true;
  73.         $this->supported['affected_rows'= true;
  74.         $this->supported['summary_functions'= true;
  75.         $this->supported['order_by_text'= true;
  76.         $this->supported['transactions'= true;
  77.         $this->supported['current_id'= true;
  78.         $this->supported['limit_queries'= true;
  79.         $this->supported['LOBs'= true;
  80.         $this->supported['replace'= true;
  81.         $this->supported['sub_selects'= true;
  82.     }
  83.  
  84.     // }}}
  85.     // {{{ errorInfo()
  86.  
  87.     /**
  88.      * This method is used to collect information about an error
  89.      *
  90.      * @param integer $error 
  91.      * @return array 
  92.      * @access public
  93.      */
  94.     function errorInfo($error = null)
  95.     {
  96.         if (is_resource($error)) {
  97.             $native_msg @pg_result_error($error);
  98.         else {
  99.             $native_msg @pg_errormessage($this->connection);
  100.         }
  101.  
  102.         // Fall back to MDB2_ERROR if there was no mapping.
  103.         $error MDB2_ERROR;
  104.  
  105.         static $error_regexps;
  106.         if (empty($error_regexps)) {
  107.             $error_regexps = array(
  108.                 '/([Tt]able does not exist\.|[Rr]elation [\"\'].*[\"\'] does not exist|[Ss]equence does not exist|[Cc]lass ".+" not found)$/' => MDB2_ERROR_NOSUCHTABLE,
  109.                 '/[Tt]able [\"\'].*[\"\'] does not exist/' => MDB2_ERROR_NOSUCHTABLE,
  110.                 '/[Rr]elation [\"\'].*[\"\'] already exists|[Cc]annot insert a duplicate key into (a )?unique index.*/' => MDB2_ERROR_ALREADY_EXISTS,
  111.                 '/divide by zero$/'                     => MDB2_ERROR_DIVZERO,
  112.                 '/pg_atoi: error in .*: can\'t parse /' => MDB2_ERROR_INVALID_NUMBER,
  113.                 '/ttribute [\"\'].*[\"\'] not found$|[Rr]elation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => MDB2_ERROR_NOSUCHFIELD,
  114.                 '/parser: parse error at or near \"/'   => MDB2_ERROR_SYNTAX,
  115.                 '/syntax error at/'                     => MDB2_ERROR_SYNTAX,
  116.                 '/violates not-null constraint/'        => MDB2_ERROR_CONSTRAINT_NOT_NULL,
  117.                 '/violates [\w ]+ constraint/'          => MDB2_ERROR_CONSTRAINT,
  118.                 '/referential integrity violation/'     => MDB2_ERROR_CONSTRAINT,
  119.                 '/deadlock detected/'                   => MDB2_ERROR_DEADLOCK
  120.             );
  121.         }
  122.         foreach ($error_regexps as $regexp => $code{
  123.             if (preg_match($regexp$native_msg)) {
  124.                 $error $code;
  125.                 break;
  126.             }
  127.         }
  128.  
  129.         return array($errornull$native_msg);
  130.     }
  131.  
  132.     // }}}
  133.     // {{{ autoCommit()
  134.  
  135.     /**
  136.      * Define whether database changes done on the database be automatically
  137.      * committed. This function may also implicitly start or end a transaction.
  138.      *
  139.      * @param boolean $auto_commit flag that indicates whether the database
  140.      *      changes should be committed right after executing every query
  141.      *      statement. If this argument is 0 a transaction implicitly started.
  142.      *      Otherwise, if a transaction is in progress it is ended by committing
  143.      *      any database changes that were pending.
  144.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  145.      * @access public
  146.      */
  147.     function autoCommit($auto_commit)
  148.     {
  149.         $this->debug(($auto_commit 'On' 'Off')'autoCommit');
  150.         if ($this->auto_commit == $auto_commit{
  151.             return MDB2_OK;
  152.         }
  153.         if ($this->connection{
  154.             $result $this->_doQuery($auto_commit 'END' 'BEGIN');
  155.             if (MDB2::isError($result)) {
  156.                 return $result;
  157.             }
  158.         }
  159.         $this->auto_commit = $auto_commit;
  160.         $this->in_transaction !$auto_commit;
  161.         return MDB2_OK;
  162.     }
  163.  
  164.     // }}}
  165.     // {{{ commit()
  166.  
  167.     /**
  168.      * Commit the database changes done during a transaction that is in
  169.      * progress. This function may only be called when auto-committing is
  170.      * disabled, otherwise it will fail. Therefore, a new transaction is
  171.      * implicitly started after committing the pending changes.
  172.      *
  173.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  174.      * @access public
  175.      */
  176.     function commit()
  177.     {
  178.         $this->debug('commit transaction''commit');
  179.         if ($this->auto_commit{
  180.             return $this->raiseError(MDB2_ERRORnullnull,
  181.                 'commit: transaction changes are being auto commited');
  182.         }
  183.         $result $this->_doQuery('COMMIT');
  184.         if (MDB2::isError($result)) {
  185.             return $result;
  186.         }
  187.         return $this->_doQuery('BEGIN');
  188.     }
  189.  
  190.     // }}}
  191.     // {{{ rollback()
  192.  
  193.     /**
  194.      * Cancel any database changes done during a transaction that is in
  195.      * progress. This function may only be called when auto-committing is
  196.      * disabled, otherwise it will fail. Therefore, a new transaction is
  197.      * implicitly started after canceling the pending changes.
  198.      *
  199.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  200.      * @access public
  201.      */
  202.     function rollback()
  203.     {
  204.         $this->debug('rolling back transaction''rollback');
  205.         if ($this->auto_commit{
  206.             return $this->raiseError(MDB2_ERRORnullnull,
  207.                 'rollback: transactions can not be rolled back when changes are auto commited');
  208.         }
  209.         $result $this->_doQuery('ROLLBACK');
  210.         if (MDB2::isError($result)) {
  211.             return $result;
  212.         }
  213.         return $this->_doQuery('BEGIN');
  214.     }
  215.  
  216.     // }}}
  217.     // {{{ _doConnect()
  218.  
  219.     /**
  220.      * Does the grunt work of connecting to the database
  221.      *
  222.      * @return mixed connection resource on success, MDB2 Error Object on failure
  223.      * @access private
  224.      ***/
  225.     function _doConnect($database_name$persistent)
  226.     {
  227.         if ($database_name == ''{
  228.             $database_name 'template1';
  229.         }
  230.         $dsninfo $this->dsn;
  231.         $protocol (isset($dsninfo['protocol'])) $dsninfo['protocol''tcp';
  232.         $connstr '';
  233.  
  234.         if ($protocol == 'tcp'{
  235.             if (!empty($dsninfo['hostspec'])) {
  236.                 $connstr 'host=' $dsninfo['hostspec'];
  237.             }
  238.             if (!empty($dsninfo['port'])) {
  239.                 $connstr .= ' port=' $dsninfo['port'];
  240.             }
  241.         }
  242.  
  243.         if (isset($database_name)) {
  244.             $connstr .= ' dbname=\'' addslashes($database_name'\'';
  245.         }
  246.         if (!empty($dsninfo['username'])) {
  247.             $connstr .= ' user=\'' addslashes($dsninfo['username']'\'';
  248.         }
  249.         if (!empty($dsninfo['password'])) {
  250.             $connstr .= ' password=\'' addslashes($dsninfo['password']'\'';
  251.         }
  252.         if (!empty($dsninfo['options'])) {
  253.             $connstr .= ' options=' $dsninfo['options'];
  254.         }
  255.         if (!empty($dsninfo['tty'])) {
  256.             $connstr .= ' tty=' $dsninfo['tty'];
  257.         }
  258.         putenv('PGDATESTYLE=ISO');
  259.  
  260.         $function ($persistent 'pg_pconnect' 'pg_connect');
  261.         // catch error
  262.         ob_start();
  263.         $connection @$function($connstr);
  264.         $error_msg ob_get_contents();
  265.         ob_end_clean();
  266.  
  267.         if ($connection > 0{
  268.             return $connection;
  269.         }
  270.         if (!$error_msg{
  271.             $error_msg 'Could not connect to PostgreSQL server';
  272.         }
  273.         return $this->raiseError(MDB2_ERROR_CONNECT_FAILEDnullnull,
  274.             $error_msg);
  275.     }
  276.  
  277.     // }}}
  278.     // {{{ connect()
  279.  
  280.     /**
  281.      * Connect to the database
  282.      *
  283.      * @return true on success, MDB2 Error Object on failure
  284.      * @access public
  285.      ***/
  286.     function connect()
  287.     {
  288.         if ($this->connection != 0{
  289.             if (count(array_diff($this->connected_dsn$this->dsn)) == 0
  290.                 && !strcmp($this->connected_database_name$this->database_name)
  291.                 && ($this->opened_persistent == $this->options['persistent']))
  292.             {
  293.                 return MDB2_OK;
  294.             }
  295.             @pg_close($this->connection);
  296.             $this->affected_rows = -1;
  297.             $this->connection = 0;
  298.         }
  299.  
  300.         if (!PEAR::loadExtension($this->phptype)) {
  301.             return $this->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  302.                 'connect: extension '.$this->phptype.' is not compiled into PHP');
  303.         }
  304.  
  305.         if ($this->database_name{
  306.             if (function_exists('pg_cmdtuples')) {
  307.                 $connection $this->_doConnect('template1'0);
  308.                 if (!MDB2::isError($connection)) {
  309.                     if (($result @pg_exec($connection'BEGIN'))) {
  310.                         $error_reporting error_reporting(63);
  311.                         @pg_cmdtuples($result);
  312.                         if (!isset($php_errormsg)
  313.                             || strcmp($php_errormsg'This compilation does not support pg_cmdtuples()')
  314.                         {
  315.                             $this->supported['affected_rows'= true;
  316.                         }
  317.                         error_reporting($error_reporting);
  318.                     else {
  319.                         $err $this->raiseError($result);
  320.                     }
  321.                     @pg_close($connection);
  322.                 else {
  323.                     $err $this->raiseError(MDB2_ERRORnullnull,
  324.                         'connect: could not execute BEGIN');
  325.                 }
  326.                 if (isset($err&& MDB2::isError($err)) {
  327.                     return $err;
  328.                 }
  329.             }
  330.             $connection $this->_doConnect($this->database_name$this->options['persistent']);
  331.             if (MDB2::isError($connection)) {
  332.                 return $connection;
  333.             }
  334.             $this->connection $connection;
  335.             $this->connected_dsn $this->dsn;
  336.             $this->connected_database_name $this->database_name;
  337.             $this->opened_persistent $this->options['persistent'];
  338.  
  339.             if (!$this->auto_commit
  340.                 && MDB2::isError($trans_result $this->_doQuery('BEGIN'))
  341.             {
  342.                 @pg_close($this->connection);
  343.                 $this->connection = 0;
  344.                 $this->affected_rows = -1;
  345.                 return $trans_result;
  346.             }
  347.         }
  348.         return MDB2_OK;
  349.     }
  350.  
  351.     // }}}
  352.     // {{{ _close()
  353.     /**
  354.      * Close the database connection
  355.      *
  356.      * @return boolean 
  357.      * @access private
  358.      ***/
  359.     function _close()
  360.     {
  361.         if ($this->connection != 0{
  362.             if (!$this->auto_commit{
  363.                 $result $this->_doQuery('END');
  364.             }
  365.             @pg_close($this->connection);
  366.             $this->connection = 0;
  367.             $this->affected_rows = -1;
  368.             unset($GLOBALS['_MDB2_databases'][$this->db_index]);
  369.  
  370.             if (isset($result&& MDB2::isError($result)) {
  371.                 return $result;
  372.             }
  373.         }
  374.         return MDB2_OK;
  375.     }
  376.  
  377.     // }}}
  378.     // {{{ _doQuery()
  379.  
  380.     /**
  381.      * Execute a query
  382.      * @param string $query the SQL query
  383.      * @return mixed result identifier if query executed, else MDB2_error
  384.      * @access private
  385.      ***/
  386.     function _doQuery($query)
  387.     {
  388.         $result @pg_exec($this->connection$query);
  389.         if ($result{
  390.             $this->affected_rows (isset($this->supported['affected_rows']@pg_cmdtuples($result: -1);
  391.         else {
  392.             return $this->raiseError($result);
  393.         }
  394.         return $result;
  395.     }
  396.  
  397.     // }}}
  398.     // {{{ standaloneQuery()
  399.  
  400.    /**
  401.      * execute a query as DBA
  402.      *
  403.      * @param string $query the SQL query
  404.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  405.      * @access public
  406.      */
  407.     function standaloneQuery($query)
  408.     {
  409.         if (($connection $this->_doConnect('template1'0)) == 0{
  410.             return $this->raiseError(MDB2_ERROR_CONNECT_FAILEDnullnull,
  411.                 'Cannot connect to template1');
  412.         }
  413.         if (!($result @pg_exec($connection$query))) {
  414.             $this->raiseError($result);
  415.         }
  416.         @pg_close($connection);
  417.         return $result;
  418.     }
  419.  
  420.     // }}}
  421.     // {{{ query()
  422.  
  423.     /**
  424.      * Send a query to the database and return any results
  425.      *
  426.      * @param string $query the SQL query
  427.      * @param array $types array that contains the types of the columns in
  428.      *                          the result set
  429.      * @param mixed $result_class string which specifies which result class to use
  430.      * @param mixed $result_wrap_class string which specifies which class to wrap results in
  431.      * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
  432.      *
  433.      * @access public
  434.      */
  435.     function &query($query$types = null$result_class = false$result_wrap_class = false)
  436.     {
  437.         $ismanip MDB2::isManip($query);
  438.         $offset $this->row_offset;
  439.         $limit $this->row_limit;
  440.         $this->row_offset $this->row_limit = 0;
  441.         $this->last_query = $query;
  442.         $this->debug($query'query');
  443.  
  444.         $connected $this->connect();
  445.         if (MDB2::isError($connected)) {
  446.             return $connected;
  447.         }
  448.  
  449.         if (!$ismanip && $limit > 0{
  450.             if ($this->auto_commit && MDB2::isError($result $this->_doQuery('BEGIN'))) {
  451.                 return $result;
  452.             }
  453.             $result $this->_doQuery('DECLARE select_cursor SCROLL CURSOR FOR '.$query);
  454.             if (!MDB2::isError($result)) {
  455.                 if ($offset > 0
  456.                     && MDB2::isError($result $this->_doQuery("MOVE FORWARD $offset FROM select_cursor"))
  457.                 {
  458.                     @pg_free_result($result);
  459.                     return $result;
  460.                 }
  461.                 $result $this->_doQuery("FETCH FORWARD $limit FROM select_cursor");
  462.                 if (MDB2::isError($result)) {
  463.                     @pg_free_result($result);
  464.                     return $result;
  465.                 }
  466.             else {
  467.                 return $result;
  468.             }
  469.             if ($this->auto_commit && MDB2::isError($result2 $this->_doQuery('END'))) {
  470.                 @pg_free_result($result);
  471.                 return $result2;
  472.             }
  473.         else {
  474.             $result $this->_doQuery($query);
  475.             if (MDB2::isError($result)) {
  476.                 return $result;
  477.             }
  478.         }
  479.         if (!MDB2::isError($result)) {
  480.             if ($ismanip{
  481.                 $this->affected_rows @pg_cmdtuples($result);
  482.                 return MDB2_OK;
  483.             elseif ((preg_match('/^\s*\(?\s*SELECT\s+/si'$query)
  484.                     && !preg_match('/^\s*\(?\s*SELECT\s+INTO\s/si'$query))
  485.                 || preg_match('/^\s*EXPLAIN/si',$query)
  486.             {
  487.                 if (!$result_class{
  488.                     $result_class $this->options['result_buffering']
  489.                         ? $this->options['buffered_result_class'$this->options['result_class'];
  490.                 }
  491.                 $class_name sprintf($result_class$this->phptype);
  492.                 $result =new $class_name($this$result);
  493.                 if ($types{
  494.                     $err $result->setResultTypes($types);
  495.                     if (MDB2::isError($err)) {
  496.                         $result->free();
  497.                         return $err;
  498.                     }
  499.                 }
  500.                 if (!$result_wrap_class{
  501.                     $result_wrap_class $this->options['result_wrap_class'];
  502.                 }
  503.                 if ($result_wrap_class{
  504.                     $result =new $result_wrap_class($result);
  505.                 }
  506.                 return $result;
  507.             else {
  508.                 $this->affected_rows = 0;
  509.                 return MDB2_OK;
  510.             }
  511.         }
  512.         return $result;
  513.     }
  514.  
  515.     // }}}
  516.     // {{{ nextID()
  517.  
  518.     /**
  519.      * returns the next free id of a sequence
  520.      *
  521.      * @param string  $seq_name name of the sequence
  522.      * @param boolean $ondemand when true the seqence is
  523.      *                           automatic created, if it
  524.      *                           not exists
  525.      * @return mixed MDB2 Error Object or id
  526.      * @access public
  527.      */
  528.     function nextID($seq_name$ondemand = true)
  529.     {
  530.         $sequence_name $this->getSequenceName($seq_name);
  531.         $this->expectError(MDB2_ERROR_NOSUCHTABLE);
  532.         $result $this->queryOne("SELECT NEXTVAL('$sequence_name')"'integer');
  533.         $this->popExpect();
  534.         if (MDB2::isError($result)) {
  535.             if ($ondemand && $result->getCode(== MDB2_ERROR_NOSUCHTABLE{
  536.                 $this->loadModule('manager');
  537.                 $result $this->manager->createSequence($seq_name1);
  538.                 if (MDB2::isError($result)) {
  539.                     return $this->raiseError(MDB2_ERRORnullnull,
  540.                         'nextID: on demand sequence could not be created');
  541.                 }
  542.                 return $this->nextId($seq_namefalse);
  543.             }
  544.         }
  545.         return $result;
  546.     }
  547.  
  548.     // }}}
  549.     // {{{ currID()
  550.  
  551.     /**
  552.      * returns the current id of a sequence
  553.      *
  554.      * @param string  $seq_name name of the sequence
  555.      * @return mixed MDB2 Error Object or id
  556.      * @access public
  557.      */
  558.     function currID($seq_name)
  559.     {
  560.         $seqname $this->getSequenceName($seq_name);
  561.         return $this->queryOne("SELECT last_value FROM $seqname"'integer');
  562.     }
  563. }
  564.  
  565. class MDB2_Result_pgsql extends MDB2_Result_Common
  566. {
  567.     // }}}
  568.     // {{{ constructor
  569.  
  570.     /**
  571.      * Constructor
  572.      */
  573.     function MDB2_Result_pgsql(&$mdb&$result)
  574.     {
  575.         parent::MDB2_Result_Common($mdb$result);
  576.     }
  577.  
  578.     // }}}
  579.     // {{{ fetch()
  580.  
  581.     /**
  582.     * fetch value from a result set
  583.     *
  584.     * @param int    $rownum    number of the row where the data can be found
  585.     * @param int    $colnum    field number where the data can be found
  586.     * @return mixed string on success, a MDB2 error on failure
  587.     * @access public
  588.     */
  589.     function fetch($rownum = 0$colnum = 0)
  590.     {
  591.         $value @pg_result($this->result$rownum$colnum);
  592.         if (!$value{
  593.             if (is_null($this->result)) {
  594.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  595.                     'fetch: resultset has already been freed');
  596.             }
  597.         }
  598.         if (isset($this->types[$colnum])) {
  599.             $value $this->mdb->datatype->convertResult($value$this->types[$colnum]);
  600.         }
  601.         if ($this->mdb->options['portability'MDB2_PORTABILITY_RTRIM{
  602.             $value rtrim($value);
  603.         }
  604.         if ($value === ''
  605.             && $this->mdb->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL
  606.         {
  607.             $value = null;
  608.         }
  609.         return $value;
  610.     }
  611.  
  612.     // }}}
  613.     // {{{ fetchRow()
  614.  
  615.     /**
  616.      * Fetch a row and insert the data into an existing array.
  617.      *
  618.      * @param int       $fetchmode  how the array data should be indexed
  619.      * @return int data array on success, a MDB2 error on failure
  620.      * @access public
  621.      */
  622.     function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT)
  623.     {
  624.         if ($fetchmode == MDB2_FETCHMODE_DEFAULT{
  625.             $fetchmode $this->mdb->fetchmode;
  626.         }
  627.         if ($fetchmode MDB2_FETCHMODE_ASSOC{
  628.             $row @pg_fetch_array($this->resultnullPGSQL_ASSOC);
  629.             if (is_array($row)
  630.                 && $this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE
  631.             {
  632.                 $row array_change_key_case($rowCASE_LOWER);
  633.             }
  634.         else {
  635.             $row @pg_fetch_row($this->result);
  636.         }
  637.         if (!$row{
  638.             if (is_null($this->result)) {
  639.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  640.                     'fetchRow: resultset has already been freed');
  641.             }
  642.             return null;
  643.         }
  644.         if (isset($this->types)) {
  645.             $row $this->mdb->datatype->convertResultRow($this->types$row);
  646.         }
  647.         if ($this->mdb->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL{
  648.             $this->mdb->_convertEmptyArrayValuesToNull($row);
  649.         }
  650.         ++$this->rownum;
  651.         return $row;
  652.     }
  653.  
  654.     // }}}
  655.     // {{{ getColumnNames()
  656.  
  657.     /**
  658.      * Retrieve the names of columns returned by the DBMS in a query result.
  659.      *
  660.      * @return mixed                an associative array variable
  661.      *                               that will hold the names of columns. The
  662.      *                               indexes of the array are the column names
  663.      *                               mapped to lower case and the values are the
  664.      *                               respective numbers of the columns starting
  665.      *                               from 0. Some DBMS may not return any
  666.      *                               columns when the result set does not
  667.      *                               contain any rows.
  668.      *
  669.      *                               a MDB2 error on failure
  670.      * @access public
  671.      */
  672.     function getColumnNames()
  673.     {
  674.         $columns = array();
  675.         $numcols $this->numCols();
  676.         if (MDB2::isError($numcols)) {
  677.             return $numcols;
  678.         }
  679.         for ($column = 0; $column $numcols$column++{
  680.             $column_name @pg_field_name($this->result$column);
  681.             $columns[$column_name$column;
  682.         }
  683.         if ($this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE{
  684.             $columns array_change_key_case($columnsCASE_LOWER);
  685.         }
  686.         return $columns;
  687.     }
  688.  
  689.     // }}}
  690.     // {{{ numCols()
  691.  
  692.     /**
  693.      * Count the number of columns returned by the DBMS in a query result.
  694.      *
  695.      * @access public
  696.      * @return mixed integer value with the number of columns, a MDB2 error
  697.      *                        on failure
  698.      */
  699.     function numCols()
  700.     {
  701.         $cols @pg_num_fields($this->result);
  702.         if (is_null($cols)) {
  703.             if (is_null($this->result)) {
  704.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  705.                     'numCols: resultset has already been freed');
  706.             }
  707.             return $this->mdb->raiseError();
  708.         }
  709.         return $cols;
  710.     }
  711.  
  712.     // }}}
  713.     // {{{ resultIsNull()
  714.  
  715.     /**
  716.      * Determine whether the value of a query result located in given row and
  717.      *    field is a null.
  718.      *
  719.      * @param int $rownum number of the row where the data can be found
  720.      * @param int $colnum field number where the data can be found
  721.      * @return mixed true or false on success, a MDB2 error on failure
  722.      * @access public
  723.      */
  724.     function resultIsNull($rownum$colnum)
  725.     {
  726.         if ($this->mdb->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL{
  727.             return parent::resultIsNull($rownum$colnum);
  728.         }
  729.         $value = pg_field_is_null($this->result$rownum$colnum);
  730.         if (!$value{
  731.             if (is_null($this->result)) {
  732.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  733.                     'fetch: resultset has already been freed');
  734.             }
  735.         }
  736.         return (bool)$value;
  737.     }
  738.  
  739.     // }}}
  740.     // {{{ free()
  741.  
  742.     /**
  743.      * Free the internal resources associated with result.
  744.      *
  745.      * @return boolean true on success, false if result is invalid
  746.      * @access public
  747.      */
  748.     function free()
  749.     {
  750.         $free @pg_free_result($this->result);
  751.         if (!$free{
  752.             if (is_null($this->result)) {
  753.                 return MDB2_OK;
  754.             }
  755.             return $this->mdb->raiseError();
  756.         }
  757.         $this->result = null;
  758.         return MDB2_OK;
  759.     }
  760. }
  761.  
  762. class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql
  763. {
  764.     // }}}
  765.     // {{{ constructor
  766.  
  767.     /**
  768.      * Constructor
  769.      */
  770.     function MDB2_BufferedResult_pgsql(&$mdb&$result)
  771.     {
  772.         parent::MDB2_Result_pgsql($mdb$result);
  773.     }
  774.  
  775.     // }}}
  776.     // {{{ seek()
  777.  
  778.     /**
  779.     * seek to a specific row in a result set
  780.     *
  781.     * @param int    $rownum    number of the row where the data can be found
  782.     * @return mixed MDB2_OK on success, a MDB2 error on failure
  783.     * @access public
  784.     */
  785.     function seek($rownum = 0)
  786.     {
  787.         if (!@pg_result_seek($this->result$rownum)) {
  788.             if (is_null($this->result)) {
  789.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  790.                     'seek: resultset has already been freed');
  791.             }
  792.             return $this->mdb->raiseError(MDB2_ERROR_INVALIDnullnull,
  793.                 'seek: tried to seek to an invalid row number ('.$rownum.')');
  794.         }
  795.         $this->rownum $rownum - 1;
  796.         return MDB2_OK;
  797.     }
  798.  
  799.     // }}}
  800.     // {{{ valid()
  801.  
  802.     /**
  803.     * check if the end of the result set has been reached
  804.     *
  805.     * @return mixed true or false on sucess, a MDB2 error on failure
  806.     * @access public
  807.     */
  808.     function valid()
  809.     {
  810.         $numrows $this->numRows();
  811.         if (MDB2::isError($numrows)) {
  812.             return $numrows;
  813.         }
  814.         return $this->rownum ($numrows - 1);
  815.     }
  816.  
  817.     // }}}
  818.     // {{{ numRows()
  819.  
  820.     /**
  821.     * returns the number of rows in a result object
  822.     *
  823.     * @return mixed MDB2 Error Object or the number of rows
  824.     * @access public
  825.     */
  826.     function numRows()
  827.     {
  828.         $rows @pg_num_rows($this->result);
  829.         if (is_null($rows)) {
  830.             if (is_null($this->result)) {
  831.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  832.                     'numRows: resultset has already been freed');
  833.             }
  834.             return $this->raiseError();
  835.         }
  836.         return $rows;
  837.     }
  838. }
  839.  
  840. ?>

Documentation generated on Mon, 11 Mar 2019 10:15:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.