Source for file odbc.php

Documentation is available at odbc.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * The PEAR DB driver for PHP's odbc extension
  7.  * for interacting with databases via ODBC connections
  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     Stig Bakken <ssb@php.net>
  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: odbc.php,v 1.81 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 odbc extension
  34.  * for interacting with databases via ODBC connections
  35.  *
  36.  * These methods overload the ones declared in DB_common.
  37.  *
  38.  * More info on ODBC errors could be found here:
  39.  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
  40.  *
  41.  * @category   Database
  42.  * @package    DB
  43.  * @author     Stig Bakken <ssb@php.net>
  44.  * @author     Daniel Convissor <danielc@php.net>
  45.  * @copyright  1997-2007 The PHP Group
  46.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  47.  * @version    Release: 1.7.13
  48.  * @link       http://pear.php.net/package/DB
  49.  */
  50. class DB_odbc extends DB_common
  51. {
  52.     // {{{ properties
  53.  
  54.     /**
  55.      * The DB driver type (mysql, oci8, odbc, etc.)
  56.      * @var string 
  57.      */
  58.     var $phptype = 'odbc';
  59.  
  60.     /**
  61.      * The database syntax variant to be used (db2, access, etc.), if any
  62.      * @var string 
  63.      */
  64.     var $dbsyntax = 'sql92';
  65.  
  66.     /**
  67.      * The capabilities of this DB implementation
  68.      *
  69.      * The 'new_link' element contains the PHP version that first provided
  70.      * new_link support for this DBMS.  Contains false if it's unsupported.
  71.      *
  72.      * Meaning of the 'limit' element:
  73.      *   + 'emulate' = emulate with fetch row by number
  74.      *   + 'alter'   = alter the query
  75.      *   + false     = skip rows
  76.      *
  77.      * NOTE: The feature set of the following drivers are different than
  78.      * the default:
  79.      *   + solid: 'transactions' = true
  80.      *   + navision: 'limit' = false
  81.      *
  82.      * @var array 
  83.      */
  84.     var $features = array(
  85.         'limit'         => 'emulate',
  86.         'new_link'      => false,
  87.         'numrows'       => true,
  88.         'pconnect'      => true,
  89.         'prepare'       => false,
  90.         'ssl'           => false,
  91.         'transactions'  => false,
  92.     );
  93.  
  94.     /**
  95.      * A mapping of native error codes to DB error codes
  96.      * @var array 
  97.      */
  98.     var $errorcode_map = array(
  99.         '01004' => DB_ERROR_TRUNCATED,
  100.         '07001' => DB_ERROR_MISMATCH,
  101.         '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW,
  102.         '21S02' => DB_ERROR_MISMATCH,
  103.         '22001' => DB_ERROR_INVALID,
  104.         '22003' => DB_ERROR_INVALID_NUMBER,
  105.         '22005' => DB_ERROR_INVALID_NUMBER,
  106.         '22008' => DB_ERROR_INVALID_DATE,
  107.         '22012' => DB_ERROR_DIVZERO,
  108.         '23000' => DB_ERROR_CONSTRAINT,
  109.         '23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
  110.         '23503' => DB_ERROR_CONSTRAINT,
  111.         '23504' => DB_ERROR_CONSTRAINT,
  112.         '23505' => DB_ERROR_CONSTRAINT,
  113.         '24000' => DB_ERROR_INVALID,
  114.         '34000' => DB_ERROR_INVALID,
  115.         '37000' => DB_ERROR_SYNTAX,
  116.         '42000' => DB_ERROR_SYNTAX,
  117.         '42601' => DB_ERROR_SYNTAX,
  118.         'IM001' => DB_ERROR_UNSUPPORTED,
  119.         'S0000' => DB_ERROR_NOSUCHTABLE,
  120.         'S0001' => DB_ERROR_ALREADY_EXISTS,
  121.         'S0002' => DB_ERROR_NOSUCHTABLE,
  122.         'S0011' => DB_ERROR_ALREADY_EXISTS,
  123.         'S0012' => DB_ERROR_NOT_FOUND,
  124.         'S0021' => DB_ERROR_ALREADY_EXISTS,
  125.         'S0022' => DB_ERROR_NOSUCHFIELD,
  126.         'S1009' => DB_ERROR_INVALID,
  127.         'S1090' => DB_ERROR_INVALID,
  128.         'S1C00' => DB_ERROR_NOT_CAPABLE,
  129.     );
  130.  
  131.     /**
  132.      * The raw database connection created by PHP
  133.      * @var resource 
  134.      */
  135.     var $connection;
  136.  
  137.     /**
  138.      * The DSN information for connecting to a database
  139.      * @var array 
  140.      */
  141.     var $dsn = array();
  142.  
  143.  
  144.     /**
  145.      * The number of rows affected by a data manipulation query
  146.      * @var integer 
  147.      * @access private
  148.      */
  149.     var $affected 0;
  150.  
  151.  
  152.     // }}}
  153.     // {{{ constructor
  154.  
  155.     /**
  156.      * This constructor calls <kbd>$this->DB_common()</kbd>
  157.      *
  158.      * @return void 
  159.      */
  160.     function DB_odbc()
  161.     {
  162.         $this->DB_common();
  163.     }
  164.  
  165.     // }}}
  166.     // {{{ connect()
  167.  
  168.     /**
  169.      * Connect to the database server, log in and open the database
  170.      *
  171.      * Don't call this method directly.  Use DB::connect() instead.
  172.      *
  173.      * PEAR DB's odbc driver supports the following extra DSN options:
  174.      *   + cursor  The type of cursor to be used for this connection.
  175.      *
  176.      * @param array $dsn         the data source name
  177.      * @param bool  $persistent  should the connection be persistent?
  178.      *
  179.      * @return int  DB_OK on success. A DB_Error object on failure.
  180.      */
  181.     function connect($dsn$persistent false)
  182.     {
  183.         if (!PEAR::loadExtension('odbc')) {
  184.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  185.         }
  186.  
  187.         $this->dsn = $dsn;
  188.         if ($dsn['dbsyntax']{
  189.             $this->dbsyntax = $dsn['dbsyntax'];
  190.         }
  191.         switch ($this->dbsyntax{
  192.             case 'access':
  193.             case 'db2':
  194.             case 'solid':
  195.                 $this->features['transactions'true;
  196.                 break;
  197.             case 'navision':
  198.                 $this->features['limit'false;
  199.         }
  200.  
  201.         /*
  202.          * This is hear for backwards compatibility. Should have been using
  203.          * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
  204.          */
  205.         if ($dsn['database']{
  206.             $odbcdsn $dsn['database'];
  207.         elseif ($dsn['hostspec']{
  208.             $odbcdsn $dsn['hostspec'];
  209.         else {
  210.             $odbcdsn 'localhost';
  211.         }
  212.  
  213.         $connect_function $persistent 'odbc_pconnect' 'odbc_connect';
  214.  
  215.         if (empty($dsn['cursor'])) {
  216.             $this->connection = @$connect_function($odbcdsn$dsn['username'],
  217.                                                    $dsn['password']);
  218.         else {
  219.             $this->connection = @$connect_function($odbcdsn$dsn['username'],
  220.                                                    $dsn['password'],
  221.                                                    $dsn['cursor']);
  222.         }
  223.  
  224.         if (!is_resource($this->connection)) {
  225.             return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  226.                                      nullnullnull,
  227.                                      $this->errorNative());
  228.         }
  229.         return DB_OK;
  230.     }
  231.  
  232.     // }}}
  233.     // {{{ disconnect()
  234.  
  235.     /**
  236.      * Disconnects from the database server
  237.      *
  238.      * @return bool  TRUE on success, FALSE on failure
  239.      */
  240.     function disconnect()
  241.     {
  242.         $err @odbc_close($this->connection);
  243.         $this->connection = null;
  244.         return $err;
  245.     }
  246.  
  247.     // }}}
  248.     // {{{ simpleQuery()
  249.  
  250.     /**
  251.      * Sends a query to the database server
  252.      *
  253.      * @param string  the SQL query string
  254.      *
  255.      * @return mixed  + a PHP result resrouce for successful SELECT queries
  256.      *                 + the DB_OK constant for other successful queries
  257.      *                 + a DB_Error object on failure
  258.      */
  259.     function simpleQuery($query)
  260.     {
  261.         $this->last_query = $query;
  262.         $query $this->modifyQuery($query);
  263.         $result @odbc_exec($this->connection$query);
  264.         if (!$result{
  265.             return $this->odbcRaiseError()// XXX ERRORMSG
  266.         }
  267.         // Determine which queries that should return data, and which
  268.         // should return an error code only.
  269.         if ($this->_checkManip($query)) {
  270.             $this->affected $result// For affectedRows()
  271.             return DB_OK;
  272.         }
  273.         $this->affected 0;
  274.         return $result;
  275.     }
  276.  
  277.     // }}}
  278.     // {{{ nextResult()
  279.  
  280.     /**
  281.      * Move the internal odbc result pointer to the next available result
  282.      *
  283.      * @param valid fbsql result resource
  284.      *
  285.      * @access public
  286.      *
  287.      * @return true if a result is available otherwise return false
  288.      */
  289.     function nextResult($result)
  290.     {
  291.         return @odbc_next_result($result);
  292.     }
  293.  
  294.     // }}}
  295.     // {{{ fetchInto()
  296.  
  297.     /**
  298.      * Places a row from the result set into the given array
  299.      *
  300.      * Formating of the array and the data therein are configurable.
  301.      * See DB_result::fetchInto() for more information.
  302.      *
  303.      * This method is not meant to be called directly.  Use
  304.      * DB_result::fetchInto() instead.  It can't be declared "protected"
  305.      * because DB_result is a separate object.
  306.      *
  307.      * @param resource $result    the query result resource
  308.      * @param array    $arr       the referenced array to put the data in
  309.      * @param int      $fetchmode how the resulting array should be indexed
  310.      * @param int      $rownum    the row number to fetch (0 = first row)
  311.      *
  312.      * @return mixed  DB_OK on success, NULL when the end of a result set is
  313.      *                  reached or on failure
  314.      *
  315.      * @see DB_result::fetchInto()
  316.      */
  317.     function fetchInto($result&$arr$fetchmode$rownum null)
  318.     {
  319.         $arr array();
  320.         if ($rownum !== null{
  321.             $rownum++// ODBC first row is 1
  322.             if (version_compare(phpversion()'4.2.0''ge')) {
  323.                 $cols @odbc_fetch_into($result$arr$rownum);
  324.             else {
  325.                 $cols @odbc_fetch_into($result$rownum$arr);
  326.             }
  327.         else {
  328.             $cols @odbc_fetch_into($result$arr);
  329.         }
  330.         if (!$cols{
  331.             return null;
  332.         }
  333.         if ($fetchmode !== DB_FETCHMODE_ORDERED{
  334.             for ($i 0$i count($arr)$i++{
  335.                 $colName @odbc_field_name($result$i+1);
  336.                 $a[$colName$arr[$i];
  337.             }
  338.             if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  339.                 $a array_change_key_case($aCASE_LOWER);
  340.             }
  341.             $arr $a;
  342.         }
  343.         if ($this->options['portability'DB_PORTABILITY_RTRIM{
  344.             $this->_rtrimArrayValues($arr);
  345.         }
  346.         if ($this->options['portability'DB_PORTABILITY_NULL_TO_EMPTY{
  347.             $this->_convertNullArrayValuesToEmpty($arr);
  348.         }
  349.         return DB_OK;
  350.     }
  351.  
  352.     // }}}
  353.     // {{{ freeResult()
  354.  
  355.     /**
  356.      * Deletes the result set and frees the memory occupied by the result set
  357.      *
  358.      * This method is not meant to be called directly.  Use
  359.      * DB_result::free() instead.  It can't be declared "protected"
  360.      * because DB_result is a separate object.
  361.      *
  362.      * @param resource $result  PHP's query result resource
  363.      *
  364.      * @return bool  TRUE on success, FALSE if $result is invalid
  365.      *
  366.      * @see DB_result::free()
  367.      */
  368.     function freeResult($result)
  369.     {
  370.         return is_resource($resultodbc_free_result($resultfalse;
  371.     }
  372.  
  373.     // }}}
  374.     // {{{ numCols()
  375.  
  376.     /**
  377.      * Gets the number of columns in a result set
  378.      *
  379.      * This method is not meant to be called directly.  Use
  380.      * DB_result::numCols() instead.  It can't be declared "protected"
  381.      * because DB_result is a separate object.
  382.      *
  383.      * @param resource $result  PHP's query result resource
  384.      *
  385.      * @return int  the number of columns.  A DB_Error object on failure.
  386.      *
  387.      * @see DB_result::numCols()
  388.      */
  389.     function numCols($result)
  390.     {
  391.         $cols @odbc_num_fields($result);
  392.         if (!$cols{
  393.             return $this->odbcRaiseError();
  394.         }
  395.         return $cols;
  396.     }
  397.  
  398.     // }}}
  399.     // {{{ affectedRows()
  400.  
  401.     /**
  402.      * Determines the number of rows affected by a data maniuplation query
  403.      *
  404.      * 0 is returned for queries that don't manipulate data.
  405.      *
  406.      * @return int  the number of rows.  A DB_Error object on failure.
  407.      */
  408.     function affectedRows()
  409.     {
  410.         if (empty($this->affected)) {  // In case of SELECT stms
  411.             return 0;
  412.         }
  413.         $nrows @odbc_num_rows($this->affected);
  414.         if ($nrows == -1{
  415.             return $this->odbcRaiseError();
  416.         }
  417.         return $nrows;
  418.     }
  419.  
  420.     // }}}
  421.     // {{{ numRows()
  422.  
  423.     /**
  424.      * Gets the number of rows in a result set
  425.      *
  426.      * Not all ODBC drivers support this functionality.  If they don't
  427.      * a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
  428.      *
  429.      * This method is not meant to be called directly.  Use
  430.      * DB_result::numRows() instead.  It can't be declared "protected"
  431.      * because DB_result is a separate object.
  432.      *
  433.      * @param resource $result  PHP's query result resource
  434.      *
  435.      * @return int  the number of rows.  A DB_Error object on failure.
  436.      *
  437.      * @see DB_result::numRows()
  438.      */
  439.     function numRows($result)
  440.     {
  441.         $nrows @odbc_num_rows($result);
  442.         if ($nrows == -1{
  443.             return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
  444.         }
  445.         if ($nrows === false{
  446.             return $this->odbcRaiseError();
  447.         }
  448.         return $nrows;
  449.     }
  450.  
  451.     // }}}
  452.     // {{{ quoteIdentifier()
  453.  
  454.     /**
  455.      * Quotes a string so it can be safely used as a table or column name
  456.      *
  457.      * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
  458.      * "Use ANSI quoted identifiers" when setting up the ODBC data source.
  459.      *
  460.      * @param string $str  identifier name to be quoted
  461.      *
  462.      * @return string  quoted identifier string
  463.      *
  464.      * @see DB_common::quoteIdentifier()
  465.      * @since Method available since Release 1.6.0
  466.      */
  467.     function quoteIdentifier($str)
  468.     {
  469.         switch ($this->dsn['dbsyntax']{
  470.             case 'access':
  471.                 return '[' $str ']';
  472.             case 'mssql':
  473.             case 'sybase':
  474.                 return '[' str_replace(']'']]'$str']';
  475.             case 'mysql':
  476.             case 'mysqli':
  477.                 return '`' $str '`';
  478.             default:
  479.                 return '"' str_replace('"''""'$str'"';
  480.         }
  481.     }
  482.  
  483.     // }}}
  484.     // {{{ quote()
  485.  
  486.     /**
  487.      * @deprecated  Deprecated in release 1.6.0
  488.      * @internal
  489.      */
  490.     function quote($str)
  491.     {
  492.         return $this->quoteSmart($str);
  493.     }
  494.  
  495.     // }}}
  496.     // {{{ nextId()
  497.  
  498.     /**
  499.      * Returns the next free id in a sequence
  500.      *
  501.      * @param string  $seq_name  name of the sequence
  502.      * @param boolean $ondemand  when true, the seqence is automatically
  503.      *                             created if it does not exist
  504.      *
  505.      * @return int  the next id number in the sequence.
  506.      *                A DB_Error object on failure.
  507.      *
  508.      * @see DB_common::nextID(), DB_common::getSequenceName(),
  509.      *       DB_odbc::createSequence(), DB_odbc::dropSequence()
  510.      */
  511.     function nextId($seq_name$ondemand true)
  512.     {
  513.         $seqname $this->getSequenceName($seq_name);
  514.         $repeat 0;
  515.         do {
  516.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  517.             $result $this->query("update ${seqname} set id = id + 1");
  518.             $this->popErrorHandling();
  519.             if ($ondemand && DB::isError($result&&
  520.                 $result->getCode(== DB_ERROR_NOSUCHTABLE{
  521.                 $repeat 1;
  522.                 $this->pushErrorHandling(PEAR_ERROR_RETURN);
  523.                 $result $this->createSequence($seq_name);
  524.                 $this->popErrorHandling();
  525.                 if (DB::isError($result)) {
  526.                     return $this->raiseError($result);
  527.                 }
  528.                 $result $this->query("insert into ${seqname} (id) values(0)");
  529.             else {
  530.                 $repeat 0;
  531.             }
  532.         while ($repeat);
  533.  
  534.         if (DB::isError($result)) {
  535.             return $this->raiseError($result);
  536.         }
  537.  
  538.         $result $this->query("select id from ${seqname}");
  539.         if (DB::isError($result)) {
  540.             return $result;
  541.         }
  542.  
  543.         $row $result->fetchRow(DB_FETCHMODE_ORDERED);
  544.         if (DB::isError($row || !$row)) {
  545.             return $row;
  546.         }
  547.  
  548.         return $row[0];
  549.     }
  550.  
  551.     /**
  552.      * Creates a new sequence
  553.      *
  554.      * @param string $seq_name  name of the new sequence
  555.      *
  556.      * @return int  DB_OK on success.  A DB_Error object on failure.
  557.      *
  558.      * @see DB_common::createSequence(), DB_common::getSequenceName(),
  559.      *       DB_odbc::nextID(), DB_odbc::dropSequence()
  560.      */
  561.     function createSequence($seq_name)
  562.     {
  563.         return $this->query('CREATE TABLE '
  564.                             . $this->getSequenceName($seq_name)
  565.                             . ' (id integer NOT NULL,'
  566.                             . ' PRIMARY KEY(id))');
  567.     }
  568.  
  569.     // }}}
  570.     // {{{ dropSequence()
  571.  
  572.     /**
  573.      * Deletes a sequence
  574.      *
  575.      * @param string $seq_name  name of the sequence to be deleted
  576.      *
  577.      * @return int  DB_OK on success.  A DB_Error object on failure.
  578.      *
  579.      * @see DB_common::dropSequence(), DB_common::getSequenceName(),
  580.      *       DB_odbc::nextID(), DB_odbc::createSequence()
  581.      */
  582.     function dropSequence($seq_name)
  583.     {
  584.         return $this->query('DROP TABLE ' $this->getSequenceName($seq_name));
  585.     }
  586.  
  587.     // }}}
  588.     // {{{ autoCommit()
  589.  
  590.     /**
  591.      * Enables or disables automatic commits
  592.      *
  593.      * @param bool $onoff  true turns it on, false turns it off
  594.      *
  595.      * @return int  DB_OK on success.  A DB_Error object if the driver
  596.      *                doesn't support auto-committing transactions.
  597.      */
  598.     function autoCommit($onoff false)
  599.     {
  600.         if (!@odbc_autocommit($this->connection$onoff)) {
  601.             return $this->odbcRaiseError();
  602.         }
  603.         return DB_OK;
  604.     }
  605.  
  606.     // }}}
  607.     // {{{ commit()
  608.  
  609.     /**
  610.      * Commits the current transaction
  611.      *
  612.      * @return int  DB_OK on success.  A DB_Error object on failure.
  613.      */
  614.     function commit()
  615.     {
  616.         if (!@odbc_commit($this->connection)) {
  617.             return $this->odbcRaiseError();
  618.         }
  619.         return DB_OK;
  620.     }
  621.  
  622.     // }}}
  623.     // {{{ rollback()
  624.  
  625.     /**
  626.      * Reverts the current transaction
  627.      *
  628.      * @return int  DB_OK on success.  A DB_Error object on failure.
  629.      */
  630.     function rollback()
  631.     {
  632.         if (!@odbc_rollback($this->connection)) {
  633.             return $this->odbcRaiseError();
  634.         }
  635.         return DB_OK;
  636.     }
  637.  
  638.     // }}}
  639.     // {{{ odbcRaiseError()
  640.  
  641.     /**
  642.      * Produces a DB_Error object regarding the current problem
  643.      *
  644.      * @param int $errno  if the error is being manually raised pass a
  645.      *                      DB_ERROR* constant here.  If this isn't passed
  646.      *                      the error information gathered from the DBMS.
  647.      *
  648.      * @return object  the DB_Error object
  649.      *
  650.      * @see DB_common::raiseError(),
  651.      *       DB_odbc::errorNative(), DB_common::errorCode()
  652.      */
  653.     function odbcRaiseError($errno null)
  654.     {
  655.         if ($errno === null{
  656.             switch ($this->dbsyntax{
  657.                 case 'access':
  658.                     if ($this->options['portability'DB_PORTABILITY_ERRORS{
  659.                         $this->errorcode_map['07001'DB_ERROR_NOSUCHFIELD;
  660.                     else {
  661.                         // Doing this in case mode changes during runtime.
  662.                         $this->errorcode_map['07001'DB_ERROR_MISMATCH;
  663.                     }
  664.  
  665.                     $native_code odbc_error($this->connection);
  666.  
  667.                     // S1000 is for "General Error."  Let's be more specific.
  668.                     if ($native_code == 'S1000'{
  669.                         $errormsg odbc_errormsg($this->connection);
  670.                         static $error_regexps;
  671.                         if (!isset($error_regexps)) {
  672.                             $error_regexps array(
  673.                                 '/includes related records.$/i'  => DB_ERROR_CONSTRAINT,
  674.                                 '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
  675.                             );
  676.                         }
  677.                         foreach ($error_regexps as $regexp => $code{
  678.                             if (preg_match($regexp$errormsg)) {
  679.                                 return $this->raiseError($code,
  680.                                         nullnullnull,
  681.                                         $native_code ' ' $errormsg);
  682.                             }
  683.                         }
  684.                         $errno DB_ERROR;
  685.                     else {
  686.                         $errno $this->errorCode($native_code);
  687.                     }
  688.                     break;
  689.                 default:
  690.                     $errno $this->errorCode(odbc_error($this->connection));
  691.             }
  692.         }
  693.         return $this->raiseError($errnonullnullnull,
  694.                                  $this->errorNative());
  695.     }
  696.  
  697.     // }}}
  698.     // {{{ errorNative()
  699.  
  700.     /**
  701.      * Gets the DBMS' native error code and message produced by the last query
  702.      *
  703.      * @return string  the DBMS' error code and message
  704.      */
  705.     function errorNative()
  706.     {
  707.         if (!is_resource($this->connection)) {
  708.             return @odbc_error(' ' @odbc_errormsg();
  709.         }
  710.         return @odbc_error($this->connection' ' @odbc_errormsg($this->connection);
  711.     }
  712.  
  713.     // }}}
  714.     // {{{ tableInfo()
  715.  
  716.     /**
  717.      * Returns information about a table or a result set
  718.      *
  719.      * @param object|string $result  DB_result object from a query or a
  720.      *                                  string containing the name of a table.
  721.      *                                  While this also accepts a query result
  722.      *                                  resource identifier, this behavior is
  723.      *                                  deprecated.
  724.      * @param int            $mode    a valid tableInfo mode
  725.      *
  726.      * @return array  an associative array with the information requested.
  727.      *                  A DB_Error object on failure.
  728.      *
  729.      * @see DB_common::tableInfo()
  730.      * @since Method available since Release 1.7.0
  731.      */
  732.     function tableInfo($result$mode null)
  733.     {
  734.         if (is_string($result)) {
  735.             /*
  736.              * Probably received a table name.
  737.              * Create a result resource identifier.
  738.              */
  739.             $id @odbc_exec($this->connection"SELECT * FROM $result");
  740.             if (!$id{
  741.                 return $this->odbcRaiseError();
  742.             }
  743.             $got_string true;
  744.         elseif (isset($result->result)) {
  745.             /*
  746.              * Probably received a result object.
  747.              * Extract the result resource identifier.
  748.              */
  749.             $id $result->result;
  750.             $got_string false;
  751.         else {
  752.             /*
  753.              * Probably received a result resource identifier.
  754.              * Copy it.
  755.              * Deprecated.  Here for compatibility only.
  756.              */
  757.             $id $result;
  758.             $got_string false;
  759.         }
  760.  
  761.         if (!is_resource($id)) {
  762.             return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
  763.         }
  764.  
  765.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  766.             $case_func 'strtolower';
  767.         else {
  768.             $case_func 'strval';
  769.         }
  770.  
  771.         $count @odbc_num_fields($id);
  772.         $res   array();
  773.  
  774.         if ($mode{
  775.             $res['num_fields'$count;
  776.         }
  777.  
  778.         for ($i 0$i $count$i++{
  779.             $col $i 1;
  780.             $res[$iarray(
  781.                 'table' => $got_string $case_func($result'',
  782.                 'name'  => $case_func(@odbc_field_name($id$col)),
  783.                 'type'  => @odbc_field_type($id$col),
  784.                 'len'   => @odbc_field_len($id$col),
  785.                 'flags' => '',
  786.             );
  787.             if ($mode DB_TABLEINFO_ORDER{
  788.                 $res['order'][$res[$i]['name']] $i;
  789.             }
  790.             if ($mode DB_TABLEINFO_ORDERTABLE{
  791.                 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  792.             }
  793.         }
  794.  
  795.         // free the result only if we were called on a table
  796.         if ($got_string{
  797.             @odbc_free_result($id);
  798.         }
  799.         return $res;
  800.     }
  801.  
  802.     // }}}
  803.     // {{{ getSpecialQuery()
  804.  
  805.     /**
  806.      * Obtains the query string needed for listing a given type of objects
  807.      *
  808.      * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
  809.      *
  810.      * @param string $type  the kind of objects you want to retrieve
  811.      *
  812.      * @return string  the list of objects requested
  813.      *
  814.      * @access protected
  815.      * @see DB_common::getListOf()
  816.      * @since Method available since Release 1.7.0
  817.      */
  818.     function getSpecialQuery($type)
  819.     {
  820.         switch ($type{
  821.             case 'databases':
  822.                 if (!function_exists('odbc_data_source')) {
  823.                     return null;
  824.                 }
  825.                 $res @odbc_data_source($this->connectionSQL_FETCH_FIRST);
  826.                 if (is_array($res)) {
  827.                     $out array($res['server']);
  828.                     while($res @odbc_data_source($this->connection,
  829.                                                    SQL_FETCH_NEXT))
  830.                     {
  831.                         $out[$res['server'];
  832.                     }
  833.                     return $out;
  834.                 else {
  835.                     return $this->odbcRaiseError();
  836.                 }
  837.                 break;
  838.             case 'tables':
  839.             case 'schema.tables':
  840.                 $keep 'TABLE';
  841.                 break;
  842.             case 'views':
  843.                 $keep 'VIEW';
  844.                 break;
  845.             default:
  846.                 return null;
  847.         }
  848.  
  849.         /*
  850.          * Removing non-conforming items in the while loop rather than
  851.          * in the odbc_tables() call because some backends choke on this:
  852.          *     odbc_tables($this->connection, '', '', '', 'TABLE')
  853.          */
  854.         $res  @odbc_tables($this->connection);
  855.         if (!$res{
  856.             return $this->odbcRaiseError();
  857.         }
  858.         $out array();
  859.         while ($row odbc_fetch_array($res)) {
  860.             if ($row['TABLE_TYPE'!= $keep{
  861.                 continue;
  862.             }
  863.             if ($type == 'schema.tables'{
  864.                 $out[$row['TABLE_SCHEM''.' $row['TABLE_NAME'];
  865.             else {
  866.                 $out[$row['TABLE_NAME'];
  867.             }
  868.         }
  869.         return $out;
  870.     }
  871.  
  872.     // }}}
  873.  
  874. }
  875.  
  876. /*
  877.  * Local variables:
  878.  * tab-width: 4
  879.  * c-basic-offset: 4
  880.  * End:
  881.  */
  882.  
  883. ?>

Documentation generated on Wed, 09 Feb 2011 09:02:37 +0700 by phpDocumentor 1.4.2