[ PHPXref.com ] [ Generated: Sun Jul 20 20:47:21 2008 ] [ TPLN 2.6 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/TPLN/pear/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.70 2005/02/20 00:44:48 danielc 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: @package_version@
  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          '-292'    => DB_ERROR_CONSTRAINT_NOT_NULL,
 105          '-310'    => DB_ERROR_ALREADY_EXISTS,
 106          '-316'    => DB_ERROR_ALREADY_EXISTS,
 107          '-319'    => DB_ERROR_NOT_FOUND,
 108          '-329'    => DB_ERROR_NODBSELECTED,
 109          '-346'    => DB_ERROR_CONSTRAINT,
 110          '-386'    => DB_ERROR_CONSTRAINT_NOT_NULL,
 111          '-391'    => DB_ERROR_CONSTRAINT_NOT_NULL,
 112          '-554'    => DB_ERROR_SYNTAX,
 113          '-691'    => DB_ERROR_CONSTRAINT,
 114          '-692'    => DB_ERROR_CONSTRAINT,
 115          '-703'    => DB_ERROR_CONSTRAINT_NOT_NULL,
 116          '-1204'   => DB_ERROR_INVALID_DATE,
 117          '-1205'   => DB_ERROR_INVALID_DATE,
 118          '-1206'   => DB_ERROR_INVALID_DATE,
 119          '-1209'   => DB_ERROR_INVALID_DATE,
 120          '-1210'   => DB_ERROR_INVALID_DATE,
 121          '-1212'   => DB_ERROR_INVALID_DATE,
 122          '-1213'   => DB_ERROR_INVALID_NUMBER,
 123      );
 124  
 125      /**
 126       * The raw database connection created by PHP
 127       * @var resource
 128       */
 129      var $connection;
 130  
 131      /**
 132       * The DSN information for connecting to a database
 133       * @var array
 134       */
 135      var $dsn = array();
 136  
 137  
 138      /**
 139       * Should data manipulation queries be committed automatically?
 140       * @var bool
 141       * @access private
 142       */
 143      var $autocommit = true;
 144  
 145      /**
 146       * The quantity of transactions begun
 147       *
 148       * {@internal  While this is private, it can't actually be designated
 149       * private in PHP 5 because it is directly accessed in the test suite.}}
 150       *
 151       * @var integer
 152       * @access private
 153       */
 154      var $transaction_opcount = 0;
 155  
 156      /**
 157       * The number of rows affected by a data manipulation query
 158       * @var integer
 159       * @access private
 160       */
 161      var $affected = 0;
 162  
 163  
 164      // }}}
 165      // {{{ constructor
 166  
 167      /**
 168       * This constructor calls <kbd>$this->DB_common()</kbd>
 169       *
 170       * @return void
 171       */
 172      function DB_ifx()
 173      {
 174          $this->DB_common();
 175      }
 176  
 177      // }}}
 178      // {{{ connect()
 179  
 180      /**
 181       * Connect to the database server, log in and open the database
 182       *
 183       * Don't call this method directly.  Use DB::connect() instead.
 184       *
 185       * @param array $dsn         the data source name
 186       * @param bool  $persistent  should the connection be persistent?
 187       *
 188       * @return int  DB_OK on success. A DB_Error object on failure.
 189       */
 190      function connect($dsn, $persistent = false)
 191      {
 192          if (!PEAR::loadExtension('informix') &&
 193              !PEAR::loadExtension('Informix'))
 194          {
 195              return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
 196          }
 197  
 198          $this->dsn = $dsn;
 199          if ($dsn['dbsyntax']) {
 200              $this->dbsyntax = $dsn['dbsyntax'];
 201          }
 202  
 203          $dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : '';
 204          $dbname = $dsn['database'] ? $dsn['database'] . $dbhost : '';
 205          $user = $dsn['username'] ? $dsn['username'] : '';
 206          $pw = $dsn['password'] ? $dsn['password'] : '';
 207  
 208          $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect';
 209  
 210          $this->connection = @$connect_function($dbname, $user, $pw);
 211          if (!is_resource($this->connection)) {
 212              return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED);
 213          }
 214          return DB_OK;
 215      }
 216  
 217      // }}}
 218      // {{{ disconnect()
 219  
 220      /**
 221       * Disconnects from the database server
 222       *
 223       * @return bool  TRUE on success, FALSE on failure
 224       */
 225      function disconnect()
 226      {
 227          $ret = @ifx_close($this->connection);
 228          $this->connection = null;
 229          return $ret;
 230      }
 231  
 232      // }}}
 233      // {{{ simpleQuery()
 234  
 235      /**
 236       * Sends a query to the database server
 237       *
 238       * @param string  the SQL query string
 239       *
 240       * @return mixed  + a PHP result resrouce for successful SELECT queries
 241       *                + the DB_OK constant for other successful queries
 242       *                + a DB_Error object on failure
 243       */
 244      function simpleQuery($query)
 245      {
 246          $ismanip = DB::isManip($query);
 247          $this->last_query = $query;
 248          $this->affected   = null;
 249          if (preg_match('/(SELECT)/i', $query)) {    //TESTME: Use !DB::isManip()?
 250              // the scroll is needed for fetching absolute row numbers
 251              // in a select query result
 252              $result = @ifx_query($query, $this->connection, IFX_SCROLL);
 253          } else {
 254              if (!$this->autocommit && $ismanip) {
 255                  if ($this->transaction_opcount == 0) {
 256                      $result = @ifx_query('BEGIN WORK', $this->connection);
 257                      if (!$result) {
 258                          return $this->ifxRaiseError();
 259                      }
 260                  }
 261                  $this->transaction_opcount++;
 262              }
 263              $result = @ifx_query($query, $this->connection);
 264          }
 265          if (!$result) {
 266              return $this->ifxRaiseError();
 267          }
 268          $this->affected = @ifx_affected_rows($result);
 269          // Determine which queries should return data, and which
 270          // should return an error code only.
 271          if (preg_match('/(SELECT)/i', $query)) {
 272              return $result;
 273          }
 274          // XXX Testme: free results inside a transaction
 275          // may cause to stop it and commit the work?
 276  
 277          // Result has to be freed even with a insert or update
 278          @ifx_free_result($result);
 279  
 280          return DB_OK;
 281      }
 282  
 283      // }}}
 284      // {{{ nextResult()
 285  
 286      /**
 287       * Move the internal ifx result pointer to the next available result
 288       *
 289       * @param a valid fbsql result resource
 290       *
 291       * @access public
 292       *
 293       * @return true if a result is available otherwise return false
 294       */
 295      function nextResult($result)
 296      {
 297          return false;
 298      }
 299  
 300      // }}}
 301      // {{{ affectedRows()
 302  
 303      /**
 304       * Determines the number of rows affected by a data maniuplation query
 305       *
 306       * 0 is returned for queries that don't manipulate data.
 307       *
 308       * @return int  the number of rows.  A DB_Error object on failure.
 309       */
 310      function affectedRows()
 311      {
 312          if (DB::isManip($this->last_query)) {
 313              return $this->affected;
 314          } else {
 315              return 0;
 316          }
 317      }
 318  
 319      // }}}
 320      // {{{ fetchInto()
 321  
 322      /**
 323       * Places a row from the result set into the given array
 324       *
 325       * Formating of the array and the data therein are configurable.
 326       * See DB_result::fetchInto() for more information.
 327       *
 328       * This method is not meant to be called directly.  Use
 329       * DB_result::fetchInto() instead.  It can't be declared "protected"
 330       * because DB_result is a separate object.
 331       *
 332       * @param resource $result    the query result resource
 333       * @param array    $arr       the referenced array to put the data in
 334       * @param int      $fetchmode how the resulting array should be indexed
 335       * @param int      $rownum    the row number to fetch (0 = first row)
 336       *
 337       * @return mixed  DB_OK on success, NULL when the end of a result set is
 338       *                 reached or on failure
 339       *
 340       * @see DB_result::fetchInto()
 341       */
 342      function fetchInto($result, &$arr, $fetchmode, $rownum = null)
 343      {
 344          if (($rownum !== null) && ($rownum < 0)) {
 345              return null;
 346          }
 347          if ($rownum === null) {
 348              /*
 349               * Even though fetch_row() should return the next row  if
 350               * $rownum is null, it doesn't in all cases.  Bug 598.
 351               */
 352              $rownum = 'NEXT';
 353          } else {
 354              // Index starts at row 1, unlike most DBMS's starting at 0.
 355              $rownum++;
 356          }
 357          if (!$arr = @ifx_fetch_row($result, $rownum)) {
 358              return null;
 359          }
 360          if ($fetchmode !== DB_FETCHMODE_ASSOC) {
 361              $i=0;
 362              $order = array();
 363              foreach ($arr as $val) {
 364                  $order[$i++] = $val;
 365              }
 366              $arr = $order;
 367          } elseif ($fetchmode == DB_FETCHMODE_ASSOC &&
 368                    $this->options['portability'] & DB_PORTABILITY_LOWERCASE)
 369          {
 370              $arr = array_change_key_case($arr, CASE_LOWER);
 371          }
 372          if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
 373              $this->_rtrimArrayValues($arr);
 374          }
 375          if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
 376              $this->_convertNullArrayValuesToEmpty($arr);
 377          }
 378          return DB_OK;
 379      }
 380  
 381      // }}}
 382      // {{{ numCols()
 383  
 384      /**
 385       * Gets the number of columns in a result set
 386       *
 387       * This method is not meant to be called directly.  Use
 388       * DB_result::numCols() instead.  It can't be declared "protected"
 389       * because DB_result is a separate object.
 390       *
 391       * @param resource $result  PHP's query result resource
 392       *
 393       * @return int  the number of columns.  A DB_Error object on failure.
 394       *
 395       * @see DB_result::numCols()
 396       */
 397      function numCols($result)
 398      {
 399          if (!$cols = @ifx_num_fields($result)) {
 400              return $this->ifxRaiseError();
 401          }
 402          return $cols;
 403      }
 404  
 405      // }}}
 406      // {{{ freeResult()
 407  
 408      /**
 409       * Deletes the result set and frees the memory occupied by the result set
 410       *
 411       * This method is not meant to be called directly.  Use
 412       * DB_result::free() instead.  It can't be declared "protected"
 413       * because DB_result is a separate object.
 414       *
 415       * @param resource $result  PHP's query result resource
 416       *
 417       * @return bool  TRUE on success, FALSE if $result is invalid
 418       *
 419       * @see DB_result::free()
 420       */
 421      function freeResult($result)
 422      {
 423          return @ifx_free_result($result);
 424      }
 425  
 426      // }}}
 427      // {{{ autoCommit()
 428  
 429      /**
 430       * Enables or disables automatic commits
 431       *
 432       * @param bool $onoff  true turns it on, false turns it off
 433       *
 434       * @return int  DB_OK on success.  A DB_Error object if the driver
 435       *               doesn't support auto-committing transactions.
 436       */
 437      function autoCommit($onoff = true)
 438      {
 439          // XXX if $this->transaction_opcount > 0, we should probably
 440          // issue a warning here.
 441          $this->autocommit = $onoff ? true : false;
 442          return DB_OK;
 443      }
 444  
 445      // }}}
 446      // {{{ commit()
 447  
 448      /**
 449       * Commits the current transaction
 450       *
 451       * @return int  DB_OK on success.  A DB_Error object on failure.
 452       */
 453      function commit()
 454      {
 455          if ($this->transaction_opcount > 0) {
 456              $result = @ifx_query('COMMIT WORK', $this->connection);
 457              $this->transaction_opcount = 0;
 458              if (!$result) {
 459                  return $this->ifxRaiseError();
 460              }
 461          }
 462          return DB_OK;
 463      }
 464  
 465      // }}}
 466      // {{{ rollback()
 467  
 468      /**
 469       * Reverts the current transaction
 470       *
 471       * @return int  DB_OK on success.  A DB_Error object on failure.
 472       */
 473      function rollback()
 474      {
 475          if ($this->transaction_opcount > 0) {
 476              $result = @ifx_query('ROLLBACK WORK', $this->connection);
 477              $this->transaction_opcount = 0;
 478              if (!$result) {
 479                  return $this->ifxRaiseError();
 480              }
 481          }
 482          return DB_OK;
 483      }
 484  
 485      // }}}
 486      // {{{ ifxRaiseError()
 487  
 488      /**
 489       * Produces a DB_Error object regarding the current problem
 490       *
 491       * @param int $errno  if the error is being manually raised pass a
 492       *                     DB_ERROR* constant here.  If this isn't passed
 493       *                     the error information gathered from the DBMS.
 494       *
 495       * @return object  the DB_Error object
 496       *
 497       * @see DB_common::raiseError(),
 498       *      DB_ifx::errorNative(), DB_ifx::errorCode()
 499       */
 500      function ifxRaiseError($errno = null)
 501      {
 502          if ($errno === null) {
 503              $errno = $this->errorCode(ifx_error());
 504          }
 505          return $this->raiseError($errno, null, null, null,
 506                                   $this->errorNative());
 507      }
 508  
 509      // }}}
 510      // {{{ errorNative()
 511  
 512      /**
 513       * Gets the DBMS' native error code and message produced by the last query
 514       *
 515       * @return string  the DBMS' error code and message
 516       */
 517      function errorNative()
 518      {
 519          return @ifx_error() . ' ' . @ifx_errormsg();
 520      }
 521  
 522      // }}}
 523      // {{{ errorCode()
 524  
 525      /**
 526       * Maps native error codes to DB's portable ones.
 527       *
 528       * Requires that the DB implementation's constructor fills
 529       * in the <var>$errorcode_map</var> property.
 530       *
 531       * @param  string  $nativecode  error code returned by the database
 532       * @return int a portable DB error code, or DB_ERROR if this DB
 533       * implementation has no mapping for the given error code.
 534       */
 535      function errorCode($nativecode)
 536      {
 537          if (ereg('SQLCODE=(.*)]', $nativecode, $match)) {
 538              $code = $match[1];
 539              if (isset($this->errorcode_map[$code])) {
 540                  return $this->errorcode_map[$code];
 541              }
 542          }
 543          return DB_ERROR;
 544      }
 545  
 546      // }}}
 547      // {{{ tableInfo()
 548  
 549      /**
 550       * Returns information about a table or a result set
 551       *
 552       * NOTE: only supports 'table' if <var>$result</var> is a table name.
 553       *
 554       * If analyzing a query result and the result has duplicate field names,
 555       * an error will be raised saying
 556       * <samp>can't distinguish duplicate field names</samp>.
 557       *
 558       * @param object|string  $result  DB_result object from a query or a
 559       *                                 string containing the name of a table.
 560       *                                 While this also accepts a query result
 561       *                                 resource identifier, this behavior is
 562       *                                 deprecated.
 563       * @param int            $mode    a valid tableInfo mode
 564       *
 565       * @return array  an associative array with the information requested.
 566       *                 A DB_Error object on failure.
 567       *
 568       * @see DB_common::tableInfo()
 569       * @since Method available since Release 1.6.0
 570       */
 571      function tableInfo($result, $mode = null)
 572      {
 573          if (is_string($result)) {
 574              /*
 575               * Probably received a table name.
 576               * Create a result resource identifier.
 577               */
 578              $id = @ifx_query("SELECT * FROM $result WHERE 1=0",
 579                               $this->connection);
 580              $got_string = true;
 581          } elseif (isset($result->result)) {
 582              /*
 583               * Probably received a result object.
 584               * Extract the result resource identifier.
 585               */
 586              $id = $result->result;
 587              $got_string = false;
 588          } else {
 589              /*
 590               * Probably received a result resource identifier.
 591               * Copy it.
 592               */
 593              $id = $result;
 594              $got_string = false;
 595          }
 596  
 597          if (!is_resource($id)) {
 598              return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA);
 599          }
 600  
 601          $flds = @ifx_fieldproperties($id);
 602          $count = @ifx_num_fields($id);
 603  
 604          if (count($flds) != $count) {
 605              return $this->raiseError("can't distinguish duplicate field names");
 606          }
 607  
 608          if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
 609              $case_func = 'strtolower';
 610          } else {
 611              $case_func = 'strval';
 612          }
 613  
 614          $i   = 0;
 615          $res = array();
 616  
 617          if ($mode) {
 618              $res['num_fields'] = $count;
 619          }
 620  
 621          foreach ($flds as $key => $value) {
 622              $props = explode(';', $value);
 623              $res[$i] = array(
 624                  'table' => $got_string ? $case_func($result) : '',
 625                  'name'  => $case_func($key),
 626                  'type'  => $props[0],
 627                  'len'   => $props[1],
 628                  'flags' => $props[4] == 'N' ? 'not_null' : '',
 629              );
 630              if ($mode & DB_TABLEINFO_ORDER) {
 631                  $res['order'][$res[$i]['name']] = $i;
 632              }
 633              if ($mode & DB_TABLEINFO_ORDERTABLE) {
 634                  $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
 635              }
 636              $i++;
 637          }
 638  
 639          // free the result only if we were called on a table
 640          if ($got_string) {
 641              @ifx_free_result($id);
 642          }
 643          return $res;
 644      }
 645  
 646      // }}}
 647      // {{{ getSpecialQuery()
 648  
 649      /**
 650       * Obtains the query string needed for listing a given type of objects
 651       *
 652       * @param string $type  the kind of objects you want to retrieve
 653       *
 654       * @return string  the SQL query string or null if the driver doesn't
 655       *                  support the object type requested
 656       *
 657       * @access protected
 658       * @see DB_common::getListOf()
 659       */
 660      function getSpecialQuery($type)
 661      {
 662          switch ($type) {
 663              case 'tables':
 664                  return 'SELECT tabname FROM systables WHERE tabid >= 100';
 665              default:
 666                  return null;
 667          }
 668      }
 669  
 670      // }}}
 671  
 672  }
 673  
 674  /*
 675   * Local variables:
 676   * tab-width: 4
 677   * c-basic-offset: 4
 678   * End:
 679   */
 680  
 681  ?>


[ Powered by PHPXref - Served by Debian GNU/Linux ]