home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 March / PCWorld_2003-03_cd.bin / Software / Vyzkuste / phptriad / phptriad2-2-1.exe / php / pear / DB / odbc.php < prev    next >
Encoding:
PHP Script  |  2001-11-13  |  12.7 KB  |  446 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2001 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stig Bakken <ssb@fast.no>                                   |
  17. // |                                                                      |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: odbc.php,v 1.36.2.4 2001/11/13 01:26:42 ssb Exp $
  21. //
  22. // Database independent query interface definition for PHP's ODBC
  23. // extension.
  24. //
  25.  
  26. //
  27. // XXX legend:
  28. //  More info on ODBC errors could be found here:
  29. //  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
  30. //
  31. // XXX ERRORMSG: The error message from the odbc function should
  32. //                 be registered here.
  33. //
  34.  
  35. require_once 'DB/common.php';
  36.  
  37. class DB_odbc extends DB_common
  38. {
  39.     // {{{ properties
  40.  
  41.     var $connection;
  42.     var $phptype, $dbsyntax;
  43.     var $row = array();
  44.  
  45.     // }}}
  46.     // {{{ constructor
  47.  
  48.     function DB_odbc()
  49.     {
  50.         $this->DB_common();
  51.         $this->phptype = 'odbc';
  52.         $this->dbsyntax = 'sql92';
  53.         $this->features = array(
  54.             'prepare' => true,
  55.             'pconnect' => true,
  56.             'transactions' => false,
  57.             'limit' => 'emulate'
  58.         );
  59.         $this->errorcode_map = array(
  60.             '01004' => DB_ERROR_TRUNCATED,
  61.             '07001' => DB_ERROR_MISMATCH,
  62.             '21S01' => DB_ERROR_MISMATCH,
  63.             '21S02' => DB_ERROR_MISMATCH,
  64.             '22003' => DB_ERROR_INVALID_NUMBER,
  65.             '22008' => DB_ERROR_INVALID_DATE,
  66.             '22012' => DB_ERROR_DIVZERO,
  67.             '23000' => DB_ERROR_CONSTRAINT,
  68.             '24000' => DB_ERROR_INVALID,
  69.             '34000' => DB_ERROR_INVALID,
  70.             '37000' => DB_ERROR_SYNTAX,
  71.             '42000' => DB_ERROR_SYNTAX,
  72.             'IM001' => DB_ERROR_UNSUPPORTED,
  73.             'S0000' => DB_ERROR_NOSUCHTABLE,
  74.             'S0001' => DB_ERROR_NOT_FOUND,
  75.             'S0002' => DB_ERROR_NOT_FOUND,
  76.             'S0011' => DB_ERROR_ALREADY_EXISTS,
  77.             'S0012' => DB_ERROR_NOT_FOUND,
  78.             'S0021' => DB_ERROR_ALREADY_EXISTS,
  79.             'S0022' => DB_ERROR_NOT_FOUND,
  80.             'S1009' => DB_ERROR_INVALID,
  81.             'S1090' => DB_ERROR_INVALID,
  82.             'S1C00' => DB_ERROR_NOT_CAPABLE
  83.         );
  84.     }
  85.  
  86.     // }}}
  87.     // {{{ connect()
  88.  
  89.     /**
  90.      * Connect to a database and log in as the specified user.
  91.      *
  92.      * @param $dsn the data source name (see DB::parseDSN for syntax)
  93.      * @param $persistent (optional) whether the connection should
  94.      *        be persistent
  95.      *
  96.      * @return int DB_OK on success, a DB error code on failure
  97.      */
  98.     function connect($dsninfo, $persistent = false)
  99.     {
  100.         if (!DB::assertExtension('odbc'))
  101.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  102.  
  103.         $this->dsn = $dsninfo;
  104.         if (!empty($dsninfo['dbsyntax'])) {
  105.             $this->dbsyntax = $dsninfo['dbsyntax'];
  106.         }
  107.         switch ($this->dbsyntax) {
  108.             case 'solid':
  109.                 $this->features = array(
  110.                     'prepare' => true,
  111.                     'pconnect' => true,
  112.                     'transactions' => true
  113.                 );
  114.                 $default_dsn = 'localhost';
  115.                 break;
  116.             default:
  117.                 break;
  118.         }
  119.         $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
  120.         $user = $dsninfo['username'];
  121.         $pw = $dsninfo['password'];
  122.         if ($this->provides('pconnect')) {
  123.             $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
  124.         } else {
  125.             $connect_function = 'odbc_connect';
  126.         }
  127.         $conn = @$connect_function($dbhost, $user, $pw);
  128.         if (!is_resource($conn)) {
  129.             return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
  130.                                          null, $this->errorNative());
  131.         }
  132.         $this->connection = $conn;
  133.         return DB_OK;
  134.     }
  135.  
  136.     // }}}
  137.     // {{{ disconnect()
  138.  
  139.     function disconnect()
  140.     {
  141.         $err = @odbc_close($this->connection);
  142.         $this->connection = null;
  143.         return $err;
  144.     }
  145.  
  146.     // }}}
  147.     // {{{ simpleQuery()
  148.  
  149.     /**
  150.      * Send a query to ODBC and return the results as a ODBC resource
  151.      * identifier.
  152.      *
  153.      * @param $query the SQL query
  154.      *
  155.      * @return int returns a valid ODBC result for successful SELECT
  156.      * queries, DB_OK for other successful queries.  A DB error code
  157.      * is returned on failure.
  158.      */
  159.     function simpleQuery($query)
  160.     {
  161.         $this->last_query = $query;
  162.         $query = $this->modifyQuery($query);
  163.         $result = @odbc_exec($this->connection, $query);
  164.         if (!$result) {
  165.             return $this->odbcRaiseError(); // XXX ERRORMSG
  166.         }
  167.         // Determine which queries that should return data, and which
  168.         // should return an error code only.
  169.         if (DB::isManip($query)) {
  170.             return DB_OK;
  171.         }
  172.         $this->row[$result] = 0;
  173.         return $result;
  174.     }
  175.  
  176.     // }}}
  177.     // {{{ nextResult()
  178.  
  179.     /**
  180.      * Move the internal odbc result pointer to the next available result
  181.      *
  182.      * @param a valid fbsql result resource
  183.      *
  184.      * @access public
  185.      *
  186.      * @return true if a result is available otherwise return false
  187.      */
  188.     function nextResult($result)
  189.     {
  190.         return odbc_next_result($result);
  191.     }
  192.  
  193.     // }}}
  194.     // {{{ fetchRow()
  195.  
  196.     function fetchRow($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
  197.     {
  198.         if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  199.             $fetchmode = $this->fetchmode;
  200.         }
  201.         $res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
  202.         if ($res !== DB_OK) {
  203.             return $res;
  204.         }
  205.         return $arr;
  206.     }
  207.  
  208.     // }}}
  209.     // {{{ fetchInto()
  210.  
  211.     function fetchInto($result, &$row, $fetchmode, $rownum=null)
  212.     {
  213.         $row = array();
  214.         if ($rownum !== null) {
  215.             if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
  216.                 $cols = odbc_fetch_into($result, $rownum, &$row);
  217.             } else {
  218.                 $cols = odbc_fetch_into($result, $rownum, $row);
  219.             }
  220.         } else {
  221.             if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
  222.                 $cols = odbc_fetch_into($result, &$row);
  223.             } else {
  224.                 $cols = odbc_fetch_into($result, $row);
  225.             }
  226.         }
  227.  
  228.         if (!$cols) {
  229.             /* XXX FIXME: doesn't work with unixODBC and easysoft
  230.                           (get corrupted $errno values)
  231.             if ($errno = odbc_error($this->connection)) {
  232.                 return $this->RaiseError($errno);
  233.             }*/
  234.             return null;
  235.         }
  236.         if ($fetchmode !== DB_FETCHMODE_ORDERED) {
  237.             for ($i = 0; $i < count($row); $i++) {
  238.                 $colName = odbc_field_name($result, $i+1);
  239.                 $a[$colName] = $row[$i];
  240.             }
  241.             $row = $a;
  242.         }
  243.         return DB_OK;
  244.     }
  245.  
  246.     // }}}
  247.     // {{{ freeResult()
  248.  
  249.     function freeResult($result)
  250.     {
  251.         $err = odbc_free_result($result); // XXX ERRORMSG
  252.         return $err;
  253.     }
  254.  
  255.     // }}}
  256.     // {{{ numCols()
  257.  
  258.     function numCols($result)
  259.     {
  260.         $cols = @odbc_num_fields($result);
  261.         if (!$cols) {
  262.             return $this->odbcRaiseError();
  263.         }
  264.         return $cols;
  265.     }
  266.  
  267.     // }}}
  268.     // {{{ numRows()
  269.  
  270.     /**
  271.      * ODBC may or may not support counting rows in the result set of
  272.      * SELECTs.
  273.      *
  274.      * @param $result the odbc result resource
  275.      * @return the number of rows, or 0
  276.      */
  277.     function numRows($result)
  278.     {
  279.         return odbc_num_rows($result);
  280.     }
  281.  
  282.     // }}}
  283.     // {{{ errorNative()
  284.  
  285.     /**
  286.      * Get the native error code of the last error (if any) that
  287.      * occured on the current connection.
  288.      *
  289.      * @access public
  290.      *
  291.      * @return int ODBC error code
  292.      */
  293.  
  294.     function errorNative()
  295.     {
  296.         if (!isset($this->connection) || !is_resource($this->connection)) {
  297.             return odbc_error() . ' ' . odbc_errormsg();
  298.         }
  299.         return odbc_error($this->connection) . ' ' . odbc_errormsg($this->connection);
  300.     }
  301.  
  302.     // }}}
  303.     // {{{ nextId()
  304.  
  305.     /**
  306.      * Get the next value in a sequence.  We emulate sequences
  307.      * for odbc. Will create the sequence if it does not exist.
  308.      *
  309.      * @access public
  310.      *
  311.      * @param $seq_name the name of the sequence
  312.      *
  313.      * @param $ondemand whether to create the sequence table on demand
  314.      * (default is true)
  315.      *
  316.      * @return a sequence integer, or a DB error
  317.      */
  318.     function nextId($seq_name, $ondemand = true)
  319.     {
  320.         $sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
  321.         $repeat = 0;
  322.         do {
  323.             $result = $this->query("update ${sqn}_seq set id = id + 1");
  324.             if ($ondemand && DB::isError($result) &&
  325.                 $result->getCode() == DB_ERROR_NOT_FOUND) {
  326.                 $repeat = 1;
  327.                 $result = $this->createSequence($seq_name);
  328.                 if (DB::isError($result)) {
  329.                     return $result;
  330.                 }
  331.                 $result = $this->query("insert into ${sqn}_seq (id) values(0)");
  332.             } else {
  333.                 $repeat = 0;
  334.             }
  335.         } while ($repeat);
  336.  
  337.         if (DB::isError($result)) {
  338.             return $result;
  339.         }
  340.  
  341.         $result = $this->query("select id from ${sqn}_seq");
  342.         if (DB::isError($result)) {
  343.             return $result;
  344.         }
  345.  
  346.         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
  347.         if (DB::isError($row || !$row)) {
  348.             return $row;
  349.         }
  350.  
  351.         return $row['id'];
  352.     }
  353.  
  354.     // }}}
  355.     // {{{ createSequence()
  356.  
  357.     function createSequence($seq_name)
  358.     {
  359.         $sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
  360.         return $this->query("CREATE TABLE ${sqn}_seq ".
  361.                             '(id bigint NOT NULL,'.
  362.                             ' PRIMARY KEY(id))');
  363.     }
  364.  
  365.     // }}}
  366.     // {{{ dropSequence()
  367.  
  368.     function dropSequence($seq_name)
  369.     {
  370.         $sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
  371.         return $this->query("DROP TABLE ${sqn}_seq");
  372.     }
  373.  
  374.     // }}}
  375.     // {{{ autoCommit()
  376.  
  377.     function autoCommit($onoff = false)
  378.     {
  379.         if (!@odbc_autocommit($this->connection, $onoff)) {
  380.             return $this->odbcRaiseError();
  381.         }
  382.         return DB_OK;
  383.     }
  384.  
  385.     // }}}
  386.     // {{{ commit()
  387.  
  388.     function commit()
  389.     {
  390.         if (!@odbc_commit($this->connection)) {
  391.             return $this->odbcRaiseError();
  392.         }
  393.         return DB_OK;
  394.     }
  395.  
  396.     // }}}
  397.     // {{{ rollback()
  398.  
  399.     function rollback()
  400.     {
  401.         if (!@odbc_rollback($this->connection)) {
  402.             return $this->odbcRaiseError();
  403.         }
  404.         return DB_OK;
  405.     }
  406.  
  407.     // }}}
  408.     // {{{ odbcRaiseError()
  409.  
  410.     function odbcRaiseError($errno = null)
  411.     {
  412.         if ($errno === null) {
  413.             $errno = $this->errorCode(odbc_error($this->connection));
  414.         }
  415.         return $this->raiseError($errno, null, null, null,
  416.                         $this->errorNative());
  417.     }
  418.  
  419.     // }}}
  420.     // {{{ getSpecialQuery()
  421.  
  422.     /**
  423.     * Returns the query needed to get some backend info
  424.     * @param string $type What kind of info you want to retrieve
  425.     * @return string The SQL query string
  426.     */
  427.     function getSpecialQuery($type)
  428.     {
  429.         switch ($type) {
  430.             case 'tables':
  431.             default:
  432.                 return null;
  433.         }
  434.         return $sql;
  435.     }
  436.  
  437.     // }}}
  438.  
  439. }
  440.  
  441. // Local variables:
  442. // tab-width: 4
  443. // c-basic-offset: 4
  444. // End:
  445. ?>
  446.