Source for file ifx.php

Documentation is available at ifx.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * The PEAR DB driver for PHP's ifx extension
  7.  * for interacting with Informix databases
  8.  *
  9.  * PHP versions 4 and 5
  10.  *
  11.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  12.  * that is available through the world-wide-web at the following URI:
  13.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  14.  * the PHP License and are unable to obtain it through the web, please
  15.  * send a note to license@php.net so we can mail you a copy immediately.
  16.  *
  17.  * @category   Database
  18.  * @package    DB
  19.  * @author     Tomas V.V.Cox <cox@idecnet.com>
  20.  * @author     Daniel Convissor <danielc@php.net>
  21.  * @copyright  1997-2007 The PHP Group
  22.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  23.  * @version    CVS: $Id: ifx.php,v 1.75 2007/07/06 05:19:21 aharvey Exp $
  24.  * @link       http://pear.php.net/package/DB
  25.  */
  26.  
  27. /**
  28.  * Obtain the DB_common class so it can be extended from
  29.  */
  30. require_once DB_PEAR_PATH.'DB/common.php';
  31.  
  32. /**
  33.  * The methods PEAR DB uses to interact with PHP's ifx extension
  34.  * for interacting with Informix databases
  35.  *
  36.  * These methods overload the ones declared in DB_common.
  37.  *
  38.  * More info on Informix errors can be found at:
  39.  * http://www.informix.com/answers/english/ierrors.htm
  40.  *
  41.  * TODO:
  42.  *   - set needed env Informix vars on connect
  43.  *   - implement native prepare/execute
  44.  *
  45.  * @category   Database
  46.  * @package    DB
  47.  * @author     Tomas V.V.Cox <cox@idecnet.com>
  48.  * @author     Daniel Convissor <danielc@php.net>
  49.  * @copyright  1997-2007 The PHP Group
  50.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  51.  * @version    Release: 1.7.13
  52.  * @link       http://pear.php.net/package/DB
  53.  */
  54. class DB_ifx extends DB_common
  55. {
  56.     // {{{ properties
  57.  
  58.     /**
  59.      * The DB driver type (mysql, oci8, odbc, etc.)
  60.      * @var string 
  61.      */
  62.     var $phptype = 'ifx';
  63.  
  64.     /**
  65.      * The database syntax variant to be used (db2, access, etc.), if any
  66.      * @var string 
  67.      */
  68.     var $dbsyntax = 'ifx';
  69.  
  70.     /**
  71.      * The capabilities of this DB implementation
  72.      *
  73.      * The 'new_link' element contains the PHP version that first provided
  74.      * new_link support for this DBMS.  Contains false if it's unsupported.
  75.      *
  76.      * Meaning of the 'limit' element:
  77.      *   + 'emulate' = emulate with fetch row by number
  78.      *   + 'alter'   = alter the query
  79.      *   + false     = skip rows
  80.      *
  81.      * @var array 
  82.      */
  83.     var $features = array(
  84.         'limit'         => 'emulate',
  85.         'new_link'      => false,
  86.         'numrows'       => 'emulate',
  87.         'pconnect'      => true,
  88.         'prepare'       => false,
  89.         'ssl'           => false,
  90.         'transactions'  => true,
  91.     );
  92.  
  93.     /**
  94.      * A mapping of native error codes to DB error codes
  95.      * @var array 
  96.      */
  97.     var $errorcode_map = array(
  98.         '-201'    => DB_ERROR_SYNTAX,
  99.         '-206'    => DB_ERROR_NOSUCHTABLE,
  100.         '-217'    => DB_ERROR_NOSUCHFIELD,
  101.         '-236'    => DB_ERROR_VALUE_COUNT_ON_ROW,
  102.         '-239'    => DB_ERROR_CONSTRAINT,
  103.         '-253'    => DB_ERROR_SYNTAX,
  104.         '-268'    => DB_ERROR_CONSTRAINT,
  105.         '-292'    => DB_ERROR_CONSTRAINT_NOT_NULL,
  106.         '-310'    => DB_ERROR_ALREADY_EXISTS,
  107.         '-316'    => DB_ERROR_ALREADY_EXISTS,
  108.         '-319'    => DB_ERROR_NOT_FOUND,
  109.         '-329'    => DB_ERROR_NODBSELECTED,
  110.         '-346'    => DB_ERROR_CONSTRAINT,
  111.         '-386'    => DB_ERROR_CONSTRAINT_NOT_NULL,
  112.         '-391'    => DB_ERROR_CONSTRAINT_NOT_NULL,
  113.         '-554'    => DB_ERROR_SYNTAX,
  114.         '-691'    => DB_ERROR_CONSTRAINT,
  115.         '-692'    => DB_ERROR_CONSTRAINT,
  116.         '-703'    => DB_ERROR_CONSTRAINT_NOT_NULL,
  117.         '-1202'   => DB_ERROR_DIVZERO,
  118.         '-1204'   => DB_ERROR_INVALID_DATE,
  119.         '-1205'   => DB_ERROR_INVALID_DATE,
  120.         '-1206'   => DB_ERROR_INVALID_DATE,
  121.         '-1209'   => DB_ERROR_INVALID_DATE,
  122.         '-1210'   => DB_ERROR_INVALID_DATE,
  123.         '-1212'   => DB_ERROR_INVALID_DATE,
  124.         '-1213'   => DB_ERROR_INVALID_NUMBER,
  125.     );
  126.  
  127.     /**
  128.      * The raw database connection created by PHP
  129.      * @var resource 
  130.      */
  131.     var $connection;
  132.  
  133.     /**
  134.      * The DSN information for connecting to a database
  135.      * @var array 
  136.      */
  137.     var $dsn = array();
  138.  
  139.  
  140.     /**
  141.      * Should data manipulation queries be committed automatically?
  142.      * @var bool 
  143.      * @access private
  144.      */
  145.     var $autocommit true;
  146.  
  147.     /**
  148.      * The quantity of transactions begun
  149.      *
  150.      * {@internal  While this is private, it can't actually be designated
  151.      * private in PHP 5 because it is directly accessed in the test suite.}}}
  152.      *
  153.      * @var integer 
  154.      * @access private
  155.      */
  156.     var $transaction_opcount 0;
  157.  
  158.     /**
  159.      * The number of rows affected by a data manipulation query
  160.      * @var integer 
  161.      * @access private
  162.      */
  163.     var $affected 0;
  164.  
  165.  
  166.     // }}}
  167.     // {{{ constructor
  168.  
  169.     /**
  170.      * This constructor calls <kbd>$this->DB_common()</kbd>
  171.      *
  172.      * @return void 
  173.      */
  174.     function DB_ifx()
  175.     {
  176.         $this->DB_common();
  177.     }
  178.  
  179.     // }}}
  180.     // {{{ connect()
  181.  
  182.     /**
  183.      * Connect to the database server, log in and open the database
  184.      *
  185.      * Don't call this method directly.  Use DB::connect() instead.
  186.      *
  187.      * @param array $dsn         the data source name
  188.      * @param bool  $persistent  should the connection be persistent?
  189.      *
  190.      * @return int  DB_OK on success. A DB_Error object on failure.
  191.      */
  192.     function connect($dsn$persistent false)
  193.     {
  194.         if (!PEAR::loadExtension('informix'&&
  195.             !PEAR::loadExtension('Informix'))
  196.         {
  197.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  198.         }
  199.  
  200.         $this->dsn = $dsn;
  201.         if ($dsn['dbsyntax']{
  202.             $this->dbsyntax = $dsn['dbsyntax'];
  203.         }
  204.  
  205.         $dbhost $dsn['hostspec''@' $dsn['hostspec''';
  206.         $dbname $dsn['database'$dsn['database'$dbhost '';
  207.         $user $dsn['username'$dsn['username''';
  208.         $pw $dsn['password'$dsn['password''';
  209.  
  210.         $connect_function $persistent 'ifx_pconnect' 'ifx_connect';
  211.  
  212.         $this->connection = @$connect_function($dbname$user$pw);
  213.         if (!is_resource($this->connection)) {
  214.             return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED);
  215.         }
  216.         return DB_OK;
  217.     }
  218.  
  219.     // }}}
  220.     // {{{ disconnect()
  221.  
  222.     /**
  223.      * Disconnects from the database server
  224.      *
  225.      * @return bool  TRUE on success, FALSE on failure
  226.      */
  227.     function disconnect()
  228.     {
  229.         $ret @ifx_close($this->connection);
  230.         $this->connection = null;
  231.         return $ret;
  232.     }
  233.  
  234.     // }}}
  235.     // {{{ simpleQuery()
  236.  
  237.     /**
  238.      * Sends a query to the database server
  239.      *
  240.      * @param string  the SQL query string
  241.      *
  242.      * @return mixed  + a PHP result resrouce for successful SELECT queries
  243.      *                 + the DB_OK constant for other successful queries
  244.      *                 + a DB_Error object on failure
  245.      */
  246.     function simpleQuery($query)
  247.     {
  248.         $ismanip $this->_checkManip($query);
  249.         $this->last_query = $query;
  250.         $this->affected   null;
  251.         if (preg_match('/(SELECT|EXECUTE)/i'$query)) {    //TESTME: Use !DB::isManip()?
  252.             // the scroll is needed for fetching absolute row numbers
  253.             // in a select query result
  254.             $result @ifx_query($query$this->connectionIFX_SCROLL);
  255.         else {
  256.             if (!$this->autocommit && $ismanip{
  257.                 if ($this->transaction_opcount == 0{
  258.                     $result @ifx_query('BEGIN WORK'$this->connection);
  259.                     if (!$result{
  260.                         return $this->ifxRaiseError();
  261.                     }
  262.                 }
  263.                 $this->transaction_opcount++;
  264.             }
  265.             $result @ifx_query($query$this->connection);
  266.         }
  267.         if (!$result{
  268.             return $this->ifxRaiseError();
  269.         }
  270.         $this->affected @ifx_affected_rows($result);
  271.         // Determine which queries should return data, and which
  272.         // should return an error code only.
  273.         if (preg_match('/(SELECT|EXECUTE)/i'$query)) {
  274.             return $result;
  275.         }
  276.         // XXX Testme: free results inside a transaction
  277.         // may cause to stop it and commit the work?
  278.  
  279.         // Result has to be freed even with a insert or update
  280.         @ifx_free_result($result);
  281.  
  282.         return DB_OK;
  283.     }
  284.  
  285.     // }}}
  286.     // {{{ nextResult()
  287.  
  288.     /**
  289.      * Move the internal ifx result pointer to the next available result
  290.      *
  291.      * @param valid fbsql result resource
  292.      *
  293.      * @access public
  294.      *
  295.      * @return true if a result is available otherwise return false
  296.      */
  297.     function nextResult($result)
  298.     {
  299.         return false;
  300.     }
  301.  
  302.     // }}}
  303.     // {{{ affectedRows()
  304.  
  305.     /**
  306.      * Determines the number of rows affected by a data maniuplation query
  307.      *
  308.      * 0 is returned for queries that don't manipulate data.
  309.      *
  310.      * @return int  the number of rows.  A DB_Error object on failure.
  311.      */
  312.     function affectedRows()
  313.     {
  314.         if ($this->_last_query_manip{
  315.             return $this->affected;
  316.         else {
  317.             return 0;
  318.         }
  319.     }
  320.  
  321.     // }}}
  322.     // {{{ fetchInto()
  323.  
  324.     /**
  325.      * Places a row from the result set into the given array
  326.      *
  327.      * Formating of the array and the data therein are configurable.
  328.      * See DB_result::fetchInto() for more information.
  329.      *
  330.      * This method is not meant to be called directly.  Use
  331.      * DB_result::fetchInto() instead.  It can't be declared "protected"
  332.      * because DB_result is a separate object.
  333.      *
  334.      * @param resource $result    the query result resource
  335.      * @param array    $arr       the referenced array to put the data in
  336.      * @param int      $fetchmode how the resulting array should be indexed
  337.      * @param int      $rownum    the row number to fetch (0 = first row)
  338.      *
  339.      * @return mixed  DB_OK on success, NULL when the end of a result set is
  340.      *                  reached or on failure
  341.      *
  342.      * @see DB_result::fetchInto()
  343.      */
  344.     function fetchInto($result&$arr$fetchmode$rownum null)
  345.     {
  346.         if (($rownum !== null&& ($rownum 0)) {
  347.             return null;
  348.         }
  349.         if ($rownum === null{
  350.             /*
  351.              * Even though fetch_row() should return the next row  if
  352.              * $rownum is null, it doesn't in all cases.  Bug 598.
  353.              */
  354.             $rownum 'NEXT';
  355.         else {
  356.             // Index starts at row 1, unlike most DBMS's starting at 0.
  357.             $rownum++;
  358.         }
  359.         if (!$arr @ifx_fetch_row($result$rownum)) {
  360.             return null;
  361.         }
  362.         if ($fetchmode !== DB_FETCHMODE_ASSOC{
  363.             $i=0;
  364.             $order array();
  365.             foreach ($arr as $val{
  366.                 $order[$i++$val;
  367.             }
  368.             $arr $order;
  369.         elseif ($fetchmode == DB_FETCHMODE_ASSOC &&
  370.                   $this->options['portability'DB_PORTABILITY_LOWERCASE)
  371.         {
  372.             $arr array_change_key_case($arrCASE_LOWER);
  373.         }
  374.         if ($this->options['portability'DB_PORTABILITY_RTRIM{
  375.             $this->_rtrimArrayValues($arr);
  376.         }
  377.         if ($this->options['portability'DB_PORTABILITY_NULL_TO_EMPTY{
  378.             $this->_convertNullArrayValuesToEmpty($arr);
  379.         }
  380.         return DB_OK;
  381.     }
  382.  
  383.     // }}}
  384.     // {{{ numCols()
  385.  
  386.     /**
  387.      * Gets the number of columns in a result set
  388.      *
  389.      * This method is not meant to be called directly.  Use
  390.      * DB_result::numCols() instead.  It can't be declared "protected"
  391.      * because DB_result is a separate object.
  392.      *
  393.      * @param resource $result  PHP's query result resource
  394.      *
  395.      * @return int  the number of columns.  A DB_Error object on failure.
  396.      *
  397.      * @see DB_result::numCols()
  398.      */
  399.     function numCols($result)
  400.     {
  401.         if (!$cols @ifx_num_fields($result)) {
  402.             return $this->ifxRaiseError();
  403.         }
  404.         return $cols;
  405.     }
  406.  
  407.     // }}}
  408.     // {{{ freeResult()
  409.  
  410.     /**
  411.      * Deletes the result set and frees the memory occupied by the result set
  412.      *
  413.      * This method is not meant to be called directly.  Use
  414.      * DB_result::free() instead.  It can't be declared "protected"
  415.      * because DB_result is a separate object.
  416.      *
  417.      * @param resource $result  PHP's query result resource
  418.      *
  419.      * @return bool  TRUE on success, FALSE if $result is invalid
  420.      *
  421.      * @see DB_result::free()
  422.      */
  423.     function freeResult($result)
  424.     {
  425.         return is_resource($resultifx_free_result($resultfalse;
  426.     }
  427.  
  428.     // }}}
  429.     // {{{ autoCommit()
  430.  
  431.     /**
  432.      * Enables or disables automatic commits
  433.      *
  434.      * @param bool $onoff  true turns it on, false turns it off
  435.      *
  436.      * @return int  DB_OK on success.  A DB_Error object if the driver
  437.      *                doesn't support auto-committing transactions.
  438.      */
  439.     function autoCommit($onoff true)
  440.     {
  441.         // XXX if $this->transaction_opcount > 0, we should probably
  442.         // issue a warning here.
  443.         $this->autocommit $onoff true false;
  444.         return DB_OK;
  445.     }
  446.  
  447.     // }}}
  448.     // {{{ commit()
  449.  
  450.     /**
  451.      * Commits the current transaction
  452.      *
  453.      * @return int  DB_OK on success.  A DB_Error object on failure.
  454.      */
  455.     function commit()
  456.     {
  457.         if ($this->transaction_opcount 0{
  458.             $result @ifx_query('COMMIT WORK'$this->connection);
  459.             $this->transaction_opcount 0;
  460.             if (!$result{
  461.                 return $this->ifxRaiseError();
  462.             }
  463.         }
  464.         return DB_OK;
  465.     }
  466.  
  467.     // }}}
  468.     // {{{ rollback()
  469.  
  470.     /**
  471.      * Reverts the current transaction
  472.      *
  473.      * @return int  DB_OK on success.  A DB_Error object on failure.
  474.      */
  475.     function rollback()
  476.     {
  477.         if ($this->transaction_opcount 0{
  478.             $result @ifx_query('ROLLBACK WORK'$this->connection);
  479.             $this->transaction_opcount 0;
  480.             if (!$result{
  481.                 return $this->ifxRaiseError();
  482.             }
  483.         }
  484.         return DB_OK;
  485.     }
  486.  
  487.     // }}}
  488.     // {{{ ifxRaiseError()
  489.  
  490.     /**
  491.      * Produces a DB_Error object regarding the current problem
  492.      *
  493.      * @param int $errno  if the error is being manually raised pass a
  494.      *                      DB_ERROR* constant here.  If this isn't passed
  495.      *                      the error information gathered from the DBMS.
  496.      *
  497.      * @return object  the DB_Error object
  498.      *
  499.      * @see DB_common::raiseError(),
  500.      *       DB_ifx::errorNative(), DB_ifx::errorCode()
  501.      */
  502.     function ifxRaiseError($errno null)
  503.     {
  504.         if ($errno === null{
  505.             $errno $this->errorCode(ifx_error());
  506.         }
  507.         return $this->raiseError($errnonullnullnull,
  508.                                  $this->errorNative());
  509.     }
  510.  
  511.     // }}}
  512.     // {{{ errorNative()
  513.  
  514.     /**
  515.      * Gets the DBMS' native error code and message produced by the last query
  516.      *
  517.      * @return string  the DBMS' error code and message
  518.      */
  519.     function errorNative()
  520.     {
  521.         return @ifx_error(' ' @ifx_errormsg();
  522.     }
  523.  
  524.     // }}}
  525.     // {{{ errorCode()
  526.  
  527.     /**
  528.      * Maps native error codes to DB's portable ones.
  529.      *
  530.      * Requires that the DB implementation's constructor fills
  531.      * in the <var>$errorcode_map</var> property.
  532.      *
  533.      * @param  string  $nativecode  error code returned by the database
  534.      * @return int a portable DB error code, or DB_ERROR if this DB
  535.      *  implementation has no mapping for the given error code.
  536.      */
  537.     function errorCode($nativecode)
  538.     {
  539.         if (ereg('SQLCODE=(.*)]'$nativecode$match)) {
  540.             $code $match[1];
  541.             if (isset($this->errorcode_map[$code])) {
  542.                 return $this->errorcode_map[$code];
  543.             }
  544.         }
  545.         return DB_ERROR;
  546.     }
  547.  
  548.     // }}}
  549.     // {{{ tableInfo()
  550.  
  551.     /**
  552.      * Returns information about a table or a result set
  553.      *
  554.      * NOTE: only supports 'table' if <var>$result</var> is a table name.
  555.      *
  556.      * If analyzing a query result and the result has duplicate field names,
  557.      * an error will be raised saying
  558.      * <samp>can't distinguish duplicate field names</samp>.
  559.      *
  560.      * @param object|string $result  DB_result object from a query or a
  561.      *                                  string containing the name of a table.
  562.      *                                  While this also accepts a query result
  563.      *                                  resource identifier, this behavior is
  564.      *                                  deprecated.
  565.      * @param int            $mode    a valid tableInfo mode
  566.      *
  567.      * @return array  an associative array with the information requested.
  568.      *                  A DB_Error object on failure.
  569.      *
  570.      * @see DB_common::tableInfo()
  571.      * @since Method available since Release 1.6.0
  572.      */
  573.     function tableInfo($result$mode null)
  574.     {
  575.         if (is_string($result)) {
  576.             /*
  577.              * Probably received a table name.
  578.              * Create a result resource identifier.
  579.              */
  580.             $id @ifx_query("SELECT * FROM $result WHERE 1=0",
  581.                              $this->connection);
  582.             $got_string true;
  583.         elseif (isset($result->result)) {
  584.             /*
  585.              * Probably received a result object.
  586.              * Extract the result resource identifier.
  587.              */
  588.             $id $result->result;
  589.             $got_string false;
  590.         else {
  591.             /*
  592.              * Probably received a result resource identifier.
  593.              * Copy it.
  594.              */
  595.             $id $result;
  596.             $got_string false;
  597.         }
  598.  
  599.         if (!is_resource($id)) {
  600.             return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA);
  601.         }
  602.  
  603.         $flds @ifx_fieldproperties($id);
  604.         $count @ifx_num_fields($id);
  605.  
  606.         if (count($flds!= $count{
  607.             return $this->raiseError("can't distinguish duplicate field names");
  608.         }
  609.  
  610.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  611.             $case_func 'strtolower';
  612.         else {
  613.             $case_func 'strval';
  614.         }
  615.  
  616.         $i   0;
  617.         $res array();
  618.  
  619.         if ($mode{
  620.             $res['num_fields'$count;
  621.         }
  622.  
  623.         foreach ($flds as $key => $value{
  624.             $props explode(';'$value);
  625.             $res[$iarray(
  626.                 'table' => $got_string $case_func($result'',
  627.                 'name'  => $case_func($key),
  628.                 'type'  => $props[0],
  629.                 'len'   => $props[1],
  630.                 'flags' => $props[4== 'N' 'not_null' '',
  631.             );
  632.             if ($mode DB_TABLEINFO_ORDER{
  633.                 $res['order'][$res[$i]['name']] $i;
  634.             }
  635.             if ($mode DB_TABLEINFO_ORDERTABLE{
  636.                 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  637.             }
  638.             $i++;
  639.         }
  640.  
  641.         // free the result only if we were called on a table
  642.         if ($got_string{
  643.             @ifx_free_result($id);
  644.         }
  645.         return $res;
  646.     }
  647.  
  648.     // }}}
  649.     // {{{ getSpecialQuery()
  650.  
  651.     /**
  652.      * Obtains the query string needed for listing a given type of objects
  653.      *
  654.      * @param string $type  the kind of objects you want to retrieve
  655.      *
  656.      * @return string  the SQL query string or null if the driver doesn't
  657.      *                   support the object type requested
  658.      *
  659.      * @access protected
  660.      * @see DB_common::getListOf()
  661.      */
  662.     function getSpecialQuery($type)
  663.     {
  664.         switch ($type{
  665.             case 'tables':
  666.                 return 'SELECT tabname FROM systables WHERE tabid >= 100';
  667.             default:
  668.                 return null;
  669.         }
  670.     }
  671.  
  672.     // }}}
  673.  
  674. }
  675.  
  676. /*
  677.  * Local variables:
  678.  * tab-width: 4
  679.  * c-basic-offset: 4
  680.  * End:
  681.  */
  682.  
  683. ?>

Documentation generated on Wed, 09 Feb 2011 09:01:36 +0700 by phpDocumentor 1.4.2