home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / phptriad / phptriadsetup2-11.exe / php / pear / DB / oci8.php < prev    next >
PHP Script  |  2001-03-12  |  12KB  |  470 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: James L. Pine <jlp@valinux.com>                             |
  17. // |                                                                      |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // Database independent query interface definition for PHP's Oracle 8
  21. // call-interface extension.
  22. //
  23.  
  24. //
  25. // be aware...  OCIError() only appears to return anything when given a
  26. // statement, so functions return the generic DB_ERROR instead of more
  27. // useful errors that have to do with feedback from the database.
  28. //
  29.  
  30.  
  31. require_once 'DB/common.php';
  32.  
  33. class DB_oci8 extends DB_common
  34. {
  35.     // {{{ properties
  36.  
  37.     var $connection;
  38.     var $phptype, $dbsyntax;
  39.     var $manip_query = array();
  40.     var $prepare_types = array();
  41.     var $autoCommit = 1;
  42.     var $last_stmt = false;
  43.  
  44.     // }}}
  45.     // {{{ constructor
  46.  
  47.     function DB_oci8()
  48.     {
  49.         $this->DB_common();
  50.         $this->phptype = 'oci8';
  51.         $this->dbsyntax = 'oci8';
  52.         $this->features = array(
  53.             'prepare' => false,
  54.             'pconnect' => true,
  55.             'transactions' => true
  56.         );
  57.         $this->errorcode_map = array();
  58.     }
  59.  
  60.     // }}}
  61.     // {{{ connect()
  62.  
  63.     /**
  64.      * Connect to a database and log in as the specified user.
  65.      *
  66.      * @param $dsn the data source name (see DB::parseDSN for syntax)
  67.      * @param $persistent (optional) whether the connection should
  68.      *        be persistent
  69.      *
  70.      * @return int DB_OK on success, a DB error code on failure
  71.      */
  72.     function connect($dsn, $persistent = false)
  73.     {
  74.         if (is_array($dsn)) {
  75.             $dsninfo = &$dsn;
  76.         } else {
  77.             $dsninfo = DB::parseDSN($dsn);
  78.         }
  79.         if (!$dsninfo || !$dsninfo['phptype']) {
  80.             return $this->raiseError();
  81.         }
  82.         $this->dsn = $dsninfo;
  83.         $user = $dsninfo['username'];
  84.         $pw = $dsninfo['password'];
  85.         $hostspec = $dsninfo['hostspec'];
  86.  
  87.         DB::assertExtension("oci8");
  88.         $connect_function = $persistent ? 'OCIPLogon' : 'OCILogon';
  89.         if ($hostspec) {
  90.             $conn = @$connect_function($user,$pw,$hostspec);
  91.         } elseif ($user || $pw) {
  92.             $conn = @$connect_function($user,$pw);
  93.         } else {
  94.             $conn = false;
  95.         }
  96.         if ($conn == false) {
  97.             return $this->raiseError();
  98.         }
  99.         $this->connection = $conn;
  100.         return DB_OK;
  101.     }
  102.  
  103.     // }}}
  104.     // {{{ disconnect()
  105.  
  106.     /**
  107.      * Log out and disconnect from the database.
  108.      *
  109.      * @return bool TRUE on success, FALSE if not connected.
  110.      */
  111.     function disconnect()
  112.     {
  113.         return @OCILogOff($this->connection);
  114.     }
  115.  
  116.     // }}}
  117.     // {{{ simpleQuery()
  118.  
  119.     /**
  120.      * Send a query to oracle and return the results as an oci8 resource
  121.      * identifier.
  122.      *
  123.      * @param $query the SQL query
  124.      *
  125.      * @return int returns a valid oci8 result for successful SELECT
  126.      * queries, DB_OK for other successful queries.  A DB error code
  127.      * is returned on failure.
  128.      */
  129.     function simpleQuery($query)
  130.     {
  131.         $this->last_query = $query;
  132.         $query = $this->modifyQuery($query);
  133.         $result = @OCIParse($this->connection, $query);
  134.         if (!$result) {
  135.             return $this->raiseError();
  136.         }
  137.         if ($this->autoCommit) {
  138.             $success = @OCIExecute($result,OCI_COMMIT_ON_SUCCESS);
  139.         }
  140.         else {
  141.             $success = @OCIExecute($result,OCI_DEFAULT);
  142.         }
  143.         if (!$success) {
  144.             return $this->raiseError();
  145.         }
  146.         $this->last_stmt=$result;
  147.         // Determine which queries that should return data, and which
  148.         // should return an error code only.
  149.         return DB::isManip($query) ? DB_OK : $result;
  150.     }
  151.  
  152.     // }}}
  153.     // {{{ fetchRow()
  154.  
  155.     /**
  156.      * Fetch a row and return as array.
  157.      *
  158.      * @param $result oci8 result identifier
  159.      * @param $fetchmode how the resulting array should be indexed
  160.      *
  161.      * @return int an array on success, a DB error code on failure, NULL
  162.      *             if there is no more data
  163.      */
  164.     function &fetchRow($result, $fetchmode = DB_FETCHMODE_DEFAULT)
  165.     {
  166.     if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  167.         $fetchmode = $this->fetchmode;
  168.     }
  169.     if ($fetchmode & DB_FETCHMODE_ASSOC) {
  170.         $moredata = @OCIFetchInto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
  171.     } else {
  172.         $moredata = @OCIFetchInto($result, $row, OCI_RETURN_NULLS + OCI_RETURN_LOBS);
  173.     }
  174.     if (!$row) {
  175.         return $this->raiseError();
  176.     }
  177.     if ($moredata == NULL) {
  178.         return NULL;
  179.     }
  180.     return $row;
  181.     }
  182.     
  183.     // }}}
  184.     // {{{ fetchInto()
  185.  
  186.     /**
  187.      * Fetch a row and insert the data into an existing array.
  188.      *
  189.      * @param $result oci8 result identifier
  190.      * @param $arr (reference) array where data from the row is stored
  191.      * @param $fetchmode how the array data should be indexed
  192.      *
  193.      * @return int DB_OK on success, a DB error code on failure
  194.      */
  195.     function fetchInto($result, &$arr, $fetchmode = DB_FETCHMODE_DEFAULT)
  196.     {
  197.         if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  198.             $fetchmode = $this->fetchmode;
  199.         }
  200.         if ($fetchmode & DB_FETCHMODE_ASSOC) {
  201.             $moredata = @OCIFetchInto($result,$arr,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
  202.         } else {
  203.             $moredata = @OCIFetchInto($result,$arr,OCI_RETURN_NULLS+OCI_RETURN_LOBS);
  204.         }
  205.         if (!($arr && $moredata)) {
  206.             return $this->raiseError();
  207.         }
  208.         return DB_OK;
  209.     }
  210.  
  211.     // }}}
  212.     // {{{ freeResult()
  213.  
  214.     /**
  215.      * Free the internal resources associated with $result.
  216.      *
  217.      * @param $result oci8 result identifier or DB statement identifier
  218.      *
  219.      * @return bool TRUE on success, FALSE if $result is invalid
  220.      */
  221.     function freeResult($result)
  222.     {
  223.         if (is_resource($result)) {
  224.             return @OCIFreeStatement($result);
  225.         }
  226.         if (!isset($this->prepare_tokens[$result])) {
  227.             return false;
  228.         }
  229.         unset($this->prepare_tokens[$result]);
  230.         unset($this->prepare_types[$result]);
  231.         return true; 
  232.     }
  233.  
  234.     // }}}
  235.     // {{{ numCols()
  236.  
  237.     /**
  238.      * Get the number of columns in a result set.
  239.      *
  240.      * @param $result oci8 result identifier
  241.      *
  242.      * @return int the number of columns per row in $result
  243.      */
  244.     function numCols($result)
  245.     {
  246.         $cols = @OCINumCols($result);
  247.         if (!$cols) {
  248.             return $this->raiseError();
  249.         }
  250.         return $cols;
  251.     }
  252.  
  253.     // }}}
  254.     // {{{ errorNative()
  255.  
  256.     /**
  257.      * Get the native error code of the last error (if any) that occured
  258.      * on the current connection.  This does not work, as OCIError does
  259.      * not work unless given a statement.  If OCIError does return
  260.      * something, so will this.
  261.      *
  262.      * @return int native oci8 error code
  263.      */
  264.     function errorNative()
  265.     {
  266.         $error = @OCIError($this->connection);
  267.         if (is_array($error)) {
  268.             return $error['code'];
  269.         }
  270.         return false;
  271.     }
  272.  
  273.     // }}}
  274.     // {{{ prepare()
  275.  
  276.     /**
  277.      * Prepares a query for multiple execution with execute().  With
  278.      * oci8, this is emulated.
  279.      * @param $query query to be prepared
  280.      *
  281.      * @return DB statement resource
  282.      */
  283.     function prepare($query)
  284.     {
  285.         $tokens = split('[\&\?]', $query);
  286.         $token = 0;
  287.         $types = array();
  288.         for ($i = 0; $i < strlen($query); $i++) {
  289.             switch ($query[$i]) {
  290.                 case '?':
  291.                     $types[$token++] = DB_PARAM_SCALAR;
  292.                     break;
  293.                 case '&':
  294.                     $types[$token++] = DB_PARAM_OPAQUE;
  295.                     break;
  296.             }
  297.         }
  298.         $binds = sizeof($tokens) - 1;
  299.         for ($i = 0; $i < $binds; $i++) {
  300.             $newquery .= $tokens[$i] . ":bind" . $i;
  301.         }
  302.         $newquery .= $tokens[$i];
  303.         $this->last_query = $query;
  304.         $newquery = $this->modifyQuery($newquery);
  305.         $stmt = @OCIParse($this->connection, $newquery);
  306.         $this->prepare_types[$stmt] = $types;
  307.         $this->manip_query[$stmt] = DB::isManip($query);
  308.         return $stmt;
  309.     }
  310.  
  311.     // }}}
  312.     // {{{ execute()
  313.  
  314.     /**
  315.      * Executes a DB statement prepared with prepare().
  316.      *
  317.      * @param $stmt a DB statement resource (returned from prepare())
  318.      * @param $data data to be used in execution of the statement
  319.      *
  320.      * @return int returns an oci8 result resource for successful
  321.      * SELECT queries, DB_OK for other successful queries.  A DB error
  322.      * code is returned on failure.
  323.      */
  324.     function execute($stmt, $data = false)
  325.     {
  326.         $types=&$this->prepare_types[$stmt];
  327.         if (($size=sizeof($types))!=sizeof($data)) {
  328.             return $this->raiseError();
  329.         }
  330.         for ($i=0;$i<$size;$i++) {
  331.             if (is_array($data)) {
  332.                 $pdata[$i]=$data[$i];
  333.             }
  334.             else {
  335.                 $pdata[$i]=$data;
  336.             }
  337.             if ($types[$i]==DB_PARAM_OPAQUE) {
  338.                 $fp = fopen($pdata[$i], "r");
  339.                 $pdata = '';
  340.                 if ($fp) {
  341.                     while (($buf = fread($fp, 4096)) != false) {
  342.                         $pdata[$i] .= $buf;
  343.                     }
  344.                 }
  345.             }
  346.             if (!@OCIBindByName($stmt,":bind".$i,$pdata[$i],-1)) {
  347.                 return $this->raiseError();
  348.             }
  349.         }
  350.         if ($this->autoCommit) {
  351.             $success = @OCIExecute($stmt,OCI_COMMIT_ON_SUCCESS);
  352.         }
  353.         else {
  354.             $success = @OCIExecute($stmt,OCI_DEFAULT);
  355.         }
  356.         if (!$success) {
  357.             return $this->raiseError();
  358.         }
  359.         $this->last_stmt=$stmt;
  360.         if ($this->manip_query[$stmt]) {
  361.             return $DB_OK;
  362.         } else {
  363.             return $stmt;
  364.         }
  365.     }
  366.  
  367.     // }}}
  368.     // {{{ autoCommit()
  369.  
  370.     /**
  371.      * Enable/disable automatic commits
  372.      * 
  373.      * @param $onoff true/false whether to autocommit
  374.      */
  375.     function autoCommit($onoff = false)
  376.     {
  377.         if (!$onoff) {
  378.             $this->autoCommit = 0;
  379.         }
  380.         else {
  381.             $this->autoCommit = 1;
  382.         }
  383.         return DB_OK;
  384.     }
  385.  
  386.     // }}}
  387.     // {{{ commit()
  388.  
  389.     /**
  390.      * Commit transactions on the current connection
  391.      *
  392.      * @return DB_ERROR or DB_OK
  393.      */
  394.     function commit()
  395.     {
  396.         $result = @OCICommit($this->connection);
  397.         if (!$result) {
  398.             return $this->raiseError();
  399.         }
  400.         return DB_OK;
  401.     }
  402.  
  403.     // }}}
  404.     // {{{ rollback()
  405.  
  406.     /**
  407.      * Roll back all uncommitted transactions on the current connection.
  408.      *
  409.      * @return DB_ERROR or DB_OK
  410.      */
  411.     function rollback()
  412.     {
  413.         $result = @OCIRollback($this->connection);
  414.         if (!$result) {
  415.             return $this->raiseError();
  416.         }
  417.         return DB_OK;
  418.     }
  419.  
  420.     // }}}
  421.     // {{{ affectedRows()
  422.  
  423.     /**
  424.      * Gets the number of rows affected by the last query.
  425.      * if the last query was a select, returns 0.
  426.      *
  427.      * @return number of rows affected by the last query or DB_ERROR
  428.      */
  429.     function affectedRows()
  430.     {
  431.         if ($this->last_stmt === false) {
  432.             return $this->raiseError();
  433.         }
  434.         $result = @OCIRowCount($this->last_stmt);
  435.         if ($result === false) {
  436.              return $this->raiseError();
  437.         }
  438.         return $result;
  439.     }
  440.  
  441.     // }}}
  442.     // {{{ modifyQuery()
  443.  
  444.     function modifyQuery($query)
  445.     {
  446.         // "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle
  447.         if (preg_match('/^\s*SELECT/i', $query) &&
  448.             !preg_match('/\sFROM\s/i', $query)) {
  449.             $query .= " FROM dual";
  450.         }
  451.         return $query;
  452.     }
  453.  
  454.     // }}}
  455.     // {{{ quoteString()
  456.  
  457.     function quoteString($string)
  458.     {
  459.         return str_replace("'", "''", $string);
  460.     }
  461.  
  462.     // }}}
  463. }
  464.  
  465. // Local variables:
  466. // tab-width: 4
  467. // c-basic-offset: 4
  468. // End:
  469. ?>
  470.