[ Index ]
 

Code source de PHP PEAR 1.4.5

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

title

Body

[fermer]

/DB/ -> ifx.php (source)

   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-2005 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.74 2007/01/12 03:11:17 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/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-2005 The PHP Group
  50   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  51   * @version    Release: 1.7.9
  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->connection, IFX_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 a 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($arr, CASE_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($result) ? ifx_free_result($result) : false;
 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($errno, null, null, null,
 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[$i] = array(
 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  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7