[ Index ]
 

Code source de SPIP Agora 1.4

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/Pear/DB/ -> odbc.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
   3  // +----------------------------------------------------------------------+
   4  // | PHP Version 4                                                        |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1997-2004 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  // | Author: Stig Bakken <ssb@php.net>                                    |
  17  // | Maintainer: Daniel Convissor <danielc@php.net>                       |
  18  // +----------------------------------------------------------------------+
  19  //
  20  // $Id: odbc.php,v 1.47 2004/10/04 17:14:32 danielc Exp $
  21  
  22  
  23  // XXX legend:
  24  //  More info on ODBC errors could be found here:
  25  //  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
  26  //
  27  // XXX ERRORMSG: The error message from the odbc function should
  28  //                 be registered here.
  29  
  30  
  31  require_once 'DB/common.php';
  32  
  33  /**
  34   * Database independent query interface definition for PHP's ODBC
  35   * extension.
  36   *
  37   * @package  DB
  38   * @version  $Id: odbc.php,v 1.47 2004/10/04 17:14:32 danielc Exp $
  39   * @category Database
  40   * @author   Stig Bakken <ssb@php.net>
  41   */
  42  class DB_odbc extends DB_common
  43  {
  44      // {{{ properties
  45  
  46      var $connection;
  47      var $phptype, $dbsyntax;
  48      var $row = array();
  49  
  50      // }}}
  51      // {{{ constructor
  52  
  53      function DB_odbc()
  54      {
  55          $this->DB_common();
  56          $this->phptype = 'odbc';
  57          $this->dbsyntax = 'sql92';
  58          $this->features = array(
  59              'prepare' => true,
  60              'pconnect' => true,
  61              'transactions' => false,
  62              'limit' => 'emulate'
  63          );
  64          $this->errorcode_map = array(
  65              '01004' => DB_ERROR_TRUNCATED,
  66              '07001' => DB_ERROR_MISMATCH,
  67              '21S01' => DB_ERROR_MISMATCH,
  68              '21S02' => DB_ERROR_MISMATCH,
  69              '22003' => DB_ERROR_INVALID_NUMBER,
  70              '22005' => DB_ERROR_INVALID_NUMBER,
  71              '22008' => DB_ERROR_INVALID_DATE,
  72              '22012' => DB_ERROR_DIVZERO,
  73              '23000' => DB_ERROR_CONSTRAINT,
  74              '23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
  75              '23503' => DB_ERROR_CONSTRAINT,
  76              '23505' => DB_ERROR_CONSTRAINT,
  77              '24000' => DB_ERROR_INVALID,
  78              '34000' => DB_ERROR_INVALID,
  79              '37000' => DB_ERROR_SYNTAX,
  80              '42000' => DB_ERROR_SYNTAX,
  81              '42601' => DB_ERROR_SYNTAX,
  82              'IM001' => DB_ERROR_UNSUPPORTED,
  83              'S0000' => DB_ERROR_NOSUCHTABLE,
  84              'S0001' => DB_ERROR_ALREADY_EXISTS,
  85              'S0002' => DB_ERROR_NOSUCHTABLE,
  86              'S0011' => DB_ERROR_ALREADY_EXISTS,
  87              'S0012' => DB_ERROR_NOT_FOUND,
  88              'S0021' => DB_ERROR_ALREADY_EXISTS,
  89              'S0022' => DB_ERROR_NOSUCHFIELD,
  90              'S1000' => DB_ERROR_CONSTRAINT_NOT_NULL,
  91              'S1009' => DB_ERROR_INVALID,
  92              'S1090' => DB_ERROR_INVALID,
  93              'S1C00' => DB_ERROR_NOT_CAPABLE
  94          );
  95      }
  96  
  97      // }}}
  98      // {{{ connect()
  99  
 100      /**
 101       * Connect to a database and log in as the specified user.
 102       *
 103       * @param $dsn the data source name (see DB::parseDSN for syntax)
 104       * @param $persistent (optional) whether the connection should
 105       *        be persistent
 106       *
 107       * @return int DB_OK on success, a DB error code on failure
 108       */
 109      function connect($dsninfo, $persistent = false)
 110      {
 111          if (!DB::assertExtension('odbc')) {
 112              return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
 113          }
 114  
 115          $this->dsn = $dsninfo;
 116          if ($dsninfo['dbsyntax']) {
 117              $this->dbsyntax = $dsninfo['dbsyntax'];
 118          }
 119          switch ($this->dbsyntax) {
 120              case 'solid':
 121                  $this->features = array(
 122                      'prepare' => true,
 123                      'pconnect' => true,
 124                      'transactions' => true
 125                  );
 126                  break;
 127              case 'navision':
 128                  // the Navision driver doesn't support fetch row by number
 129                  $this->features['limit'] = false;
 130          }
 131  
 132          /*
 133           * This is hear for backwards compatibility.
 134           * Should have been using 'database' all along, but used hostspec.
 135           */
 136          if ($dsninfo['database']) {
 137              $odbcdsn = $dsninfo['database'];
 138          } elseif ($dsninfo['hostspec']) {
 139              $odbcdsn = $dsninfo['hostspec'];
 140          } else {
 141              $odbcdsn = 'localhost';
 142          }
 143  
 144          if ($this->provides('pconnect')) {
 145              $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
 146          } else {
 147              $connect_function = 'odbc_connect';
 148          }
 149  
 150          if (empty($dsninfo['cursor'])) {
 151              $conn = @$connect_function($odbcdsn, $dsninfo['username'],
 152                                         $dsninfo['password']);
 153          } else {
 154              $conn = @$connect_function($odbcdsn, $dsninfo['username'],
 155                                         $dsninfo['password'],
 156                                         $dsninfo['cursor']);
 157          }
 158  
 159          if (!is_resource($conn)) {
 160              return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
 161                                           null, $this->errorNative());
 162          }
 163          $this->connection = $conn;
 164          return DB_OK;
 165      }
 166  
 167      // }}}
 168      // {{{ disconnect()
 169  
 170      function disconnect()
 171      {
 172          $err = @odbc_close($this->connection);
 173          $this->connection = null;
 174          return $err;
 175      }
 176  
 177      // }}}
 178      // {{{ simpleQuery()
 179  
 180      /**
 181       * Send a query to ODBC and return the results as a ODBC resource
 182       * identifier.
 183       *
 184       * @param $query the SQL query
 185       *
 186       * @return int returns a valid ODBC result for successful SELECT
 187       * queries, DB_OK for other successful queries.  A DB error code
 188       * is returned on failure.
 189       */
 190      function simpleQuery($query)
 191      {
 192          $this->last_query = $query;
 193          $query = $this->modifyQuery($query);
 194          $result = @odbc_exec($this->connection, $query);
 195          if (!$result) {
 196              return $this->odbcRaiseError(); // XXX ERRORMSG
 197          }
 198          // Determine which queries that should return data, and which
 199          // should return an error code only.
 200          if (DB::isManip($query)) {
 201              $this->manip_result = $result; // For affectedRows()
 202              return DB_OK;
 203          }
 204          $this->row[(int)$result] = 0;
 205          $this->manip_result = 0;
 206          return $result;
 207      }
 208  
 209      // }}}
 210      // {{{ nextResult()
 211  
 212      /**
 213       * Move the internal odbc result pointer to the next available result
 214       *
 215       * @param a valid fbsql result resource
 216       *
 217       * @access public
 218       *
 219       * @return true if a result is available otherwise return false
 220       */
 221      function nextResult($result)
 222      {
 223          return @odbc_next_result($result);
 224      }
 225  
 226      // }}}
 227      // {{{ fetchInto()
 228  
 229      /**
 230       * Fetch a row and insert the data into an existing array.
 231       *
 232       * Formating of the array and the data therein are configurable.
 233       * See DB_result::fetchInto() for more information.
 234       *
 235       * @param resource $result    query result identifier
 236       * @param array    $arr       (reference) array where data from the row
 237       *                            should be placed
 238       * @param int      $fetchmode how the resulting array should be indexed
 239       * @param int      $rownum    the row number to fetch
 240       *
 241       * @return mixed DB_OK on success, null when end of result set is
 242       *               reached or on failure
 243       *
 244       * @see DB_result::fetchInto()
 245       * @access private
 246       */
 247      function fetchInto($result, &$arr, $fetchmode, $rownum=null)
 248      {
 249          $arr = array();
 250          if ($rownum !== null) {
 251              $rownum++; // ODBC first row is 1
 252              if (version_compare(phpversion(), '4.2.0', 'ge')) {
 253                  $cols = @odbc_fetch_into($result, $arr, $rownum);
 254              } else {
 255                  $cols = @odbc_fetch_into($result, $rownum, $arr);
 256              }
 257          } else {
 258              $cols = @odbc_fetch_into($result, $arr);
 259          }
 260  
 261          if (!$cols) {
 262              /* XXX FIXME: doesn't work with unixODBC and easysoft
 263                            (get corrupted $errno values)
 264              if ($errno = @odbc_error($this->connection)) {
 265                  return $this->RaiseError($errno);
 266              }*/
 267              return null;
 268          }
 269          if ($fetchmode !== DB_FETCHMODE_ORDERED) {
 270              for ($i = 0; $i < count($arr); $i++) {
 271                  $colName = @odbc_field_name($result, $i+1);
 272                  $a[$colName] = $arr[$i];
 273              }
 274              if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
 275                  $a = array_change_key_case($a, CASE_LOWER);
 276              }
 277              $arr = $a;
 278          }
 279          if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
 280              $this->_rtrimArrayValues($arr);
 281          }
 282          if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
 283              $this->_convertNullArrayValuesToEmpty($arr);
 284          }
 285          return DB_OK;
 286      }
 287  
 288      // }}}
 289      // {{{ freeResult()
 290  
 291      function freeResult($result)
 292      {
 293          unset($this->row[(int)$result]);
 294          return @odbc_free_result($result);
 295      }
 296  
 297      // }}}
 298      // {{{ numCols()
 299  
 300      function numCols($result)
 301      {
 302          $cols = @odbc_num_fields($result);
 303          if (!$cols) {
 304              return $this->odbcRaiseError();
 305          }
 306          return $cols;
 307      }
 308  
 309      // }}}
 310      // {{{ affectedRows()
 311  
 312      /**
 313       * Returns the number of rows affected by a manipulative query
 314       * (INSERT, DELETE, UPDATE)
 315       * @return mixed int affected rows, 0 when non manip queries or
 316       *               DB error on error
 317       */
 318      function affectedRows()
 319      {
 320          if (empty($this->manip_result)) {  // In case of SELECT stms
 321              return 0;
 322          }
 323          $nrows = @odbc_num_rows($this->manip_result);
 324          if ($nrows == -1) {
 325              return $this->odbcRaiseError();
 326          }
 327          return $nrows;
 328      }
 329  
 330      // }}}
 331      // {{{ numRows()
 332  
 333      /**
 334       * ODBC may or may not support counting rows in the result set of
 335       * SELECTs.
 336       *
 337       * @param $result the odbc result resource
 338       * @return the number of rows, or 0
 339       */
 340      function numRows($result)
 341      {
 342          $nrows = @odbc_num_rows($result);
 343          if ($nrows == -1) {
 344              return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
 345          }
 346          return $nrows;
 347      }
 348  
 349      // }}}
 350      // {{{ quoteIdentifier()
 351  
 352      /**
 353       * Quote a string so it can be safely used as a table / column name
 354       *
 355       * Quoting style depends on which dbsyntax was passed in the DSN.
 356       *
 357       * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
 358       * "Use ANSI quoted identifiers" when setting up the ODBC data source.
 359       *
 360       * @param string $str  identifier name to be quoted
 361       *
 362       * @return string  quoted identifier string
 363       *
 364       * @since 1.6.0
 365       * @access public
 366       */
 367      function quoteIdentifier($str)
 368      {
 369          switch ($this->dsn['dbsyntax']) {
 370              case 'access':
 371                  return '[' . $str . ']';
 372              case 'mssql':
 373              case 'sybase':
 374                  return '[' . str_replace(']', ']]', $str) . ']';
 375              case 'mysql':
 376              case 'mysqli':
 377                  return '`' . $str . '`';
 378              default:
 379                  return '"' . str_replace('"', '""', $str) . '"';
 380          }
 381      }
 382  
 383      // }}}
 384      // {{{ quote()
 385  
 386      /**
 387       * @deprecated  Deprecated in release 1.6.0
 388       * @internal
 389       */
 390      function quote($str) {
 391          return $this->quoteSmart($str);
 392      }
 393  
 394      // }}}
 395      // {{{ errorNative()
 396  
 397      /**
 398       * Get the native error code of the last error (if any) that
 399       * occured on the current connection.
 400       *
 401       * @access public
 402       *
 403       * @return int ODBC error code
 404       */
 405      function errorNative()
 406      {
 407          if (!isset($this->connection) || !is_resource($this->connection)) {
 408              return @odbc_error() . ' ' . @odbc_errormsg();
 409          }
 410          return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
 411      }
 412  
 413      // }}}
 414      // {{{ nextId()
 415  
 416      /**
 417       * Returns the next free id in a sequence
 418       *
 419       * @param string  $seq_name  name of the sequence
 420       * @param boolean $ondemand  when true, the seqence is automatically
 421       *                           created if it does not exist
 422       *
 423       * @return int  the next id number in the sequence.  DB_Error if problem.
 424       *
 425       * @internal
 426       * @see DB_common::nextID()
 427       * @access public
 428       */
 429      function nextId($seq_name, $ondemand = true)
 430      {
 431          $seqname = $this->getSequenceName($seq_name);
 432          $repeat = 0;
 433          do {
 434              $this->pushErrorHandling(PEAR_ERROR_RETURN);
 435              $result = $this->query("update $seqname} set id = id + 1");
 436              $this->popErrorHandling();
 437              if ($ondemand && DB::isError($result) &&
 438                  $result->getCode() == DB_ERROR_NOSUCHTABLE) {
 439                  $repeat = 1;
 440                  $this->pushErrorHandling(PEAR_ERROR_RETURN);
 441                  $result = $this->createSequence($seq_name);
 442                  $this->popErrorHandling();
 443                  if (DB::isError($result)) {
 444                      return $this->raiseError($result);
 445                  }
 446                  $result = $this->query("insert into $seqname} (id) values(0)");
 447              } else {
 448                  $repeat = 0;
 449              }
 450          } while ($repeat);
 451  
 452          if (DB::isError($result)) {
 453              return $this->raiseError($result);
 454          }
 455  
 456          $result = $this->query("select id from $seqname}");
 457          if (DB::isError($result)) {
 458              return $result;
 459          }
 460  
 461          $row = $result->fetchRow(DB_FETCHMODE_ORDERED);
 462          if (DB::isError($row || !$row)) {
 463              return $row;
 464          }
 465  
 466          return $row[0];
 467      }
 468  
 469      /**
 470       * Creates a new sequence
 471       *
 472       * @param string $seq_name  name of the new sequence
 473       *
 474       * @return int  DB_OK on success.  A DB_Error object is returned if
 475       *              problems arise.
 476       *
 477       * @internal
 478       * @see DB_common::createSequence()
 479       * @access public
 480       */
 481      function createSequence($seq_name)
 482      {
 483          $seqname = $this->getSequenceName($seq_name);
 484          return $this->query("CREATE TABLE $seqname} ".
 485                              '(id integer NOT NULL,'.
 486                              ' PRIMARY KEY(id))');
 487      }
 488  
 489      // }}}
 490      // {{{ dropSequence()
 491  
 492      /**
 493       * Deletes a sequence
 494       *
 495       * @param string $seq_name  name of the sequence to be deleted
 496       *
 497       * @return int  DB_OK on success.  DB_Error if problems.
 498       *
 499       * @internal
 500       * @see DB_common::dropSequence()
 501       * @access public
 502       */
 503      function dropSequence($seq_name)
 504      {
 505          $seqname = $this->getSequenceName($seq_name);
 506          return $this->query("DROP TABLE $seqname}");
 507      }
 508  
 509      // }}}
 510      // {{{ autoCommit()
 511  
 512      function autoCommit($onoff = false)
 513      {
 514          if (!@odbc_autocommit($this->connection, $onoff)) {
 515              return $this->odbcRaiseError();
 516          }
 517          return DB_OK;
 518      }
 519  
 520      // }}}
 521      // {{{ commit()
 522  
 523      function commit()
 524      {
 525          if (!@odbc_commit($this->connection)) {
 526              return $this->odbcRaiseError();
 527          }
 528          return DB_OK;
 529      }
 530  
 531      // }}}
 532      // {{{ rollback()
 533  
 534      function rollback()
 535      {
 536          if (!@odbc_rollback($this->connection)) {
 537              return $this->odbcRaiseError();
 538          }
 539          return DB_OK;
 540      }
 541  
 542      // }}}
 543      // {{{ odbcRaiseError()
 544  
 545      /**
 546       * Gather information about an error, then use that info to create a
 547       * DB error object and finally return that object.
 548       *
 549       * @param  integer  $errno  PEAR error number (usually a DB constant) if
 550       *                          manually raising an error
 551       * @return object  DB error object
 552       * @see errorNative()
 553       * @see DB_common::errorCode()
 554       * @see DB_common::raiseError()
 555       */
 556      function odbcRaiseError($errno = null)
 557      {
 558          if ($errno === null) {
 559              switch ($this->dbsyntax) {
 560                  case 'access':
 561                      if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
 562                          $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
 563                      } else {
 564                          // Doing this in case mode changes during runtime.
 565                          $this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
 566                      }
 567              }
 568              $errno = $this->errorCode(odbc_error($this->connection));
 569          }
 570          return $this->raiseError($errno, null, null, null,
 571                          $this->errorNative());
 572      }
 573  
 574      // }}}
 575  
 576  }
 577  
 578  /*
 579   * Local variables:
 580   * tab-width: 4
 581   * c-basic-offset: 4
 582   * End:
 583   */
 584  
 585  ?>


Généré le : Sat Feb 24 14:40:03 2007 par Balluche grâce à PHPXref 0.7