[ Index ]
 

Code source de PHP PEAR 1.4.5

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

title

Body

[fermer]

/DB/ -> ibase.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 interbase extension
   7   * for interacting with Interbase and Firebird databases
   8   *
   9   * While this class works with PHP 4, PHP's InterBase extension is
  10   * unstable in PHP 4.  Use PHP 5.
  11   *
  12   * PHP versions 4 and 5
  13   *
  14   * LICENSE: This source file is subject to version 3.0 of the PHP license
  15   * that is available through the world-wide-web at the following URI:
  16   * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  17   * the PHP License and are unable to obtain it through the web, please
  18   * send a note to license@php.net so we can mail you a copy immediately.
  19   *
  20   * @category   Database
  21   * @package    DB
  22   * @author     Sterling Hughes <sterling@php.net>
  23   * @author     Daniel Convissor <danielc@php.net>
  24   * @copyright  1997-2005 The PHP Group
  25   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  26   * @version    CVS: $Id: ibase.php,v 1.113 2007/01/12 03:11:17 aharvey Exp $
  27   * @link       http://pear.php.net/package/DB
  28   */
  29  
  30  /**
  31   * Obtain the DB_common class so it can be extended from
  32   */
  33  require_once  'DB/common.php';
  34  
  35  /**
  36   * The methods PEAR DB uses to interact with PHP's interbase extension
  37   * for interacting with Interbase and Firebird databases
  38   *
  39   * These methods overload the ones declared in DB_common.
  40   *
  41   * While this class works with PHP 4, PHP's InterBase extension is
  42   * unstable in PHP 4.  Use PHP 5.
  43   *
  44   * NOTICE:  limitQuery() only works for Firebird.
  45   *
  46   * @category   Database
  47   * @package    DB
  48   * @author     Sterling Hughes <sterling@php.net>
  49   * @author     Daniel Convissor <danielc@php.net>
  50   * @copyright  1997-2005 The PHP Group
  51   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  52   * @version    Release: 1.7.9
  53   * @link       http://pear.php.net/package/DB
  54   * @since      Class became stable in Release 1.7.0
  55   */
  56  class DB_ibase extends DB_common
  57  {
  58      // {{{ properties
  59  
  60      /**
  61       * The DB driver type (mysql, oci8, odbc, etc.)
  62       * @var string
  63       */
  64      var $phptype = 'ibase';
  65  
  66      /**
  67       * The database syntax variant to be used (db2, access, etc.), if any
  68       * @var string
  69       */
  70      var $dbsyntax = 'ibase';
  71  
  72      /**
  73       * The capabilities of this DB implementation
  74       *
  75       * The 'new_link' element contains the PHP version that first provided
  76       * new_link support for this DBMS.  Contains false if it's unsupported.
  77       *
  78       * Meaning of the 'limit' element:
  79       *   + 'emulate' = emulate with fetch row by number
  80       *   + 'alter'   = alter the query
  81       *   + false     = skip rows
  82       *
  83       * NOTE: only firebird supports limit.
  84       *
  85       * @var array
  86       */
  87      var $features = array(
  88          'limit'         => false,
  89          'new_link'      => false,
  90          'numrows'       => 'emulate',
  91          'pconnect'      => true,
  92          'prepare'       => true,
  93          'ssl'           => false,
  94          'transactions'  => true,
  95      );
  96  
  97      /**
  98       * A mapping of native error codes to DB error codes
  99       * @var array
 100       */
 101      var $errorcode_map = array(
 102          -104 => DB_ERROR_SYNTAX,
 103          -150 => DB_ERROR_ACCESS_VIOLATION,
 104          -151 => DB_ERROR_ACCESS_VIOLATION,
 105          -155 => DB_ERROR_NOSUCHTABLE,
 106          -157 => DB_ERROR_NOSUCHFIELD,
 107          -158 => DB_ERROR_VALUE_COUNT_ON_ROW,
 108          -170 => DB_ERROR_MISMATCH,
 109          -171 => DB_ERROR_MISMATCH,
 110          -172 => DB_ERROR_INVALID,
 111          // -204 =>  // Covers too many errors, need to use regex on msg
 112          -205 => DB_ERROR_NOSUCHFIELD,
 113          -206 => DB_ERROR_NOSUCHFIELD,
 114          -208 => DB_ERROR_INVALID,
 115          -219 => DB_ERROR_NOSUCHTABLE,
 116          -297 => DB_ERROR_CONSTRAINT,
 117          -303 => DB_ERROR_INVALID,
 118          -413 => DB_ERROR_INVALID_NUMBER,
 119          -530 => DB_ERROR_CONSTRAINT,
 120          -551 => DB_ERROR_ACCESS_VIOLATION,
 121          -552 => DB_ERROR_ACCESS_VIOLATION,
 122          // -607 =>  // Covers too many errors, need to use regex on msg
 123          -625 => DB_ERROR_CONSTRAINT_NOT_NULL,
 124          -803 => DB_ERROR_CONSTRAINT,
 125          -804 => DB_ERROR_VALUE_COUNT_ON_ROW,
 126          // -902 =>  // Covers too many errors, need to use regex on msg
 127          -904 => DB_ERROR_CONNECT_FAILED,
 128          -922 => DB_ERROR_NOSUCHDB,
 129          -923 => DB_ERROR_CONNECT_FAILED,
 130          -924 => DB_ERROR_CONNECT_FAILED
 131      );
 132  
 133      /**
 134       * The raw database connection created by PHP
 135       * @var resource
 136       */
 137      var $connection;
 138  
 139      /**
 140       * The DSN information for connecting to a database
 141       * @var array
 142       */
 143      var $dsn = array();
 144  
 145  
 146      /**
 147       * The number of rows affected by a data manipulation query
 148       * @var integer
 149       * @access private
 150       */
 151      var $affected = 0;
 152  
 153      /**
 154       * Should data manipulation queries be committed automatically?
 155       * @var bool
 156       * @access private
 157       */
 158      var $autocommit = true;
 159  
 160      /**
 161       * The prepared statement handle from the most recently executed statement
 162       *
 163       * {@internal  Mainly here because the InterBase/Firebird API is only
 164       * able to retrieve data from result sets if the statemnt handle is
 165       * still in scope.}}
 166       *
 167       * @var resource
 168       */
 169      var $last_stmt;
 170  
 171      /**
 172       * Is the given prepared statement a data manipulation query?
 173       * @var array
 174       * @access private
 175       */
 176      var $manip_query = array();
 177  
 178  
 179      // }}}
 180      // {{{ constructor
 181  
 182      /**
 183       * This constructor calls <kbd>$this->DB_common()</kbd>
 184       *
 185       * @return void
 186       */
 187      function DB_ibase()
 188      {
 189          $this->DB_common();
 190      }
 191  
 192      // }}}
 193      // {{{ connect()
 194  
 195      /**
 196       * Connect to the database server, log in and open the database
 197       *
 198       * Don't call this method directly.  Use DB::connect() instead.
 199       *
 200       * PEAR DB's ibase driver supports the following extra DSN options:
 201       *   + buffers    The number of database buffers to allocate for the
 202       *                 server-side cache.
 203       *   + charset    The default character set for a database.
 204       *   + dialect    The default SQL dialect for any statement
 205       *                 executed within a connection.  Defaults to the
 206       *                 highest one supported by client libraries.
 207       *                 Functional only with InterBase 6 and up.
 208       *   + role       Functional only with InterBase 5 and up.
 209       *
 210       * @param array $dsn         the data source name
 211       * @param bool  $persistent  should the connection be persistent?
 212       *
 213       * @return int  DB_OK on success. A DB_Error object on failure.
 214       */
 215      function connect($dsn, $persistent = false)
 216      {
 217          if (!PEAR::loadExtension('interbase')) {
 218              return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
 219          }
 220  
 221          $this->dsn = $dsn;
 222          if ($dsn['dbsyntax']) {
 223              $this->dbsyntax = $dsn['dbsyntax'];
 224          }
 225          if ($this->dbsyntax == 'firebird') {
 226              $this->features['limit'] = 'alter';
 227          }
 228  
 229          $params = array(
 230              $dsn['hostspec']
 231                      ? ($dsn['hostspec'] . ':' . $dsn['database'])
 232                      : $dsn['database'],
 233              $dsn['username'] ? $dsn['username'] : null,
 234              $dsn['password'] ? $dsn['password'] : null,
 235              isset($dsn['charset']) ? $dsn['charset'] : null,
 236              isset($dsn['buffers']) ? $dsn['buffers'] : null,
 237              isset($dsn['dialect']) ? $dsn['dialect'] : null,
 238              isset($dsn['role'])    ? $dsn['role'] : null,
 239          );
 240  
 241          $connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect';
 242  
 243          $this->connection = @call_user_func_array($connect_function, $params);
 244          if (!$this->connection) {
 245              return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED);
 246          }
 247          return DB_OK;
 248      }
 249  
 250      // }}}
 251      // {{{ disconnect()
 252  
 253      /**
 254       * Disconnects from the database server
 255       *
 256       * @return bool  TRUE on success, FALSE on failure
 257       */
 258      function disconnect()
 259      {
 260          $ret = @ibase_close($this->connection);
 261          $this->connection = null;
 262          return $ret;
 263      }
 264  
 265      // }}}
 266      // {{{ simpleQuery()
 267  
 268      /**
 269       * Sends a query to the database server
 270       *
 271       * @param string  the SQL query string
 272       *
 273       * @return mixed  + a PHP result resrouce for successful SELECT queries
 274       *                + the DB_OK constant for other successful queries
 275       *                + a DB_Error object on failure
 276       */
 277      function simpleQuery($query)
 278      {
 279          $ismanip = $this->_checkManip($query);
 280          $this->last_query = $query;
 281          $query = $this->modifyQuery($query);
 282          $result = @ibase_query($this->connection, $query);
 283  
 284          if (!$result) {
 285              return $this->ibaseRaiseError();
 286          }
 287          if ($this->autocommit && $ismanip) {
 288              @ibase_commit($this->connection);
 289          }
 290          if ($ismanip) {
 291              $this->affected = $result;
 292              return DB_OK;
 293          } else {
 294              $this->affected = 0;
 295              return $result;
 296          }
 297      }
 298  
 299      // }}}
 300      // {{{ modifyLimitQuery()
 301  
 302      /**
 303       * Adds LIMIT clauses to a query string according to current DBMS standards
 304       *
 305       * Only works with Firebird.
 306       *
 307       * @param string $query   the query to modify
 308       * @param int    $from    the row to start to fetching (0 = the first row)
 309       * @param int    $count   the numbers of rows to fetch
 310       * @param mixed  $params  array, string or numeric data to be used in
 311       *                         execution of the statement.  Quantity of items
 312       *                         passed must match quantity of placeholders in
 313       *                         query:  meaning 1 placeholder for non-array
 314       *                         parameters or 1 placeholder per array element.
 315       *
 316       * @return string  the query string with LIMIT clauses added
 317       *
 318       * @access protected
 319       */
 320      function modifyLimitQuery($query, $from, $count, $params = array())
 321      {
 322          if ($this->dsn['dbsyntax'] == 'firebird') {
 323              $query = preg_replace('/^([\s(])*SELECT/i',
 324                                    "SELECT FIRST $count SKIP $from", $query);
 325          }
 326          return $query;
 327      }
 328  
 329      // }}}
 330      // {{{ nextResult()
 331  
 332      /**
 333       * Move the internal ibase result pointer to the next available result
 334       *
 335       * @param a valid fbsql result resource
 336       *
 337       * @access public
 338       *
 339       * @return true if a result is available otherwise return false
 340       */
 341      function nextResult($result)
 342      {
 343          return false;
 344      }
 345  
 346      // }}}
 347      // {{{ fetchInto()
 348  
 349      /**
 350       * Places a row from the result set into the given array
 351       *
 352       * Formating of the array and the data therein are configurable.
 353       * See DB_result::fetchInto() for more information.
 354       *
 355       * This method is not meant to be called directly.  Use
 356       * DB_result::fetchInto() instead.  It can't be declared "protected"
 357       * because DB_result is a separate object.
 358       *
 359       * @param resource $result    the query result resource
 360       * @param array    $arr       the referenced array to put the data in
 361       * @param int      $fetchmode how the resulting array should be indexed
 362       * @param int      $rownum    the row number to fetch (0 = first row)
 363       *
 364       * @return mixed  DB_OK on success, NULL when the end of a result set is
 365       *                 reached or on failure
 366       *
 367       * @see DB_result::fetchInto()
 368       */
 369      function fetchInto($result, &$arr, $fetchmode, $rownum = null)
 370      {
 371          if ($rownum !== null) {
 372              return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
 373          }
 374          if ($fetchmode & DB_FETCHMODE_ASSOC) {
 375              if (function_exists('ibase_fetch_assoc')) {
 376                  $arr = @ibase_fetch_assoc($result);
 377              } else {
 378                  $arr = get_object_vars(ibase_fetch_object($result));
 379              }
 380              if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
 381                  $arr = array_change_key_case($arr, CASE_LOWER);
 382              }
 383          } else {
 384              $arr = @ibase_fetch_row($result);
 385          }
 386          if (!$arr) {
 387              return null;
 388          }
 389          if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
 390              $this->_rtrimArrayValues($arr);
 391          }
 392          if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
 393              $this->_convertNullArrayValuesToEmpty($arr);
 394          }
 395          return DB_OK;
 396      }
 397  
 398      // }}}
 399      // {{{ freeResult()
 400  
 401      /**
 402       * Deletes the result set and frees the memory occupied by the result set
 403       *
 404       * This method is not meant to be called directly.  Use
 405       * DB_result::free() instead.  It can't be declared "protected"
 406       * because DB_result is a separate object.
 407       *
 408       * @param resource $result  PHP's query result resource
 409       *
 410       * @return bool  TRUE on success, FALSE if $result is invalid
 411       *
 412       * @see DB_result::free()
 413       */
 414      function freeResult($result)
 415      {
 416          return is_resource($result) ? ibase_free_result($result) : false;
 417      }
 418  
 419      // }}}
 420      // {{{ freeQuery()
 421  
 422      function freeQuery($query)
 423      {
 424          return is_resource($query) ? ibase_free_query($query) : false;
 425      }
 426  
 427      // }}}
 428      // {{{ affectedRows()
 429  
 430      /**
 431       * Determines the number of rows affected by a data maniuplation query
 432       *
 433       * 0 is returned for queries that don't manipulate data.
 434       *
 435       * @return int  the number of rows.  A DB_Error object on failure.
 436       */
 437      function affectedRows()
 438      {
 439          if (is_integer($this->affected)) {
 440              return $this->affected;
 441          }
 442          return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
 443      }
 444  
 445      // }}}
 446      // {{{ numCols()
 447  
 448      /**
 449       * Gets the number of columns in a result set
 450       *
 451       * This method is not meant to be called directly.  Use
 452       * DB_result::numCols() instead.  It can't be declared "protected"
 453       * because DB_result is a separate object.
 454       *
 455       * @param resource $result  PHP's query result resource
 456       *
 457       * @return int  the number of columns.  A DB_Error object on failure.
 458       *
 459       * @see DB_result::numCols()
 460       */
 461      function numCols($result)
 462      {
 463          $cols = @ibase_num_fields($result);
 464          if (!$cols) {
 465              return $this->ibaseRaiseError();
 466          }
 467          return $cols;
 468      }
 469  
 470      // }}}
 471      // {{{ prepare()
 472  
 473      /**
 474       * Prepares a query for multiple execution with execute().
 475       *
 476       * prepare() requires a generic query as string like <code>
 477       *    INSERT INTO numbers VALUES (?, ?, ?)
 478       * </code>.  The <kbd>?</kbd> characters are placeholders.
 479       *
 480       * Three types of placeholders can be used:
 481       *   + <kbd>?</kbd>  a quoted scalar value, i.e. strings, integers
 482       *   + <kbd>!</kbd>  value is inserted 'as is'
 483       *   + <kbd>&</kbd>  requires a file name.  The file's contents get
 484       *                     inserted into the query (i.e. saving binary
 485       *                     data in a db)
 486       *
 487       * Use backslashes to escape placeholder characters if you don't want
 488       * them to be interpreted as placeholders.  Example: <code>
 489       *    "UPDATE foo SET col=? WHERE col='over \& under'"
 490       * </code>
 491       *
 492       * @param string $query query to be prepared
 493       * @return mixed DB statement resource on success. DB_Error on failure.
 494       */
 495      function prepare($query)
 496      {
 497          $tokens   = preg_split('/((?<!\\\)[&?!])/', $query, -1,
 498                                 PREG_SPLIT_DELIM_CAPTURE);
 499          $token    = 0;
 500          $types    = array();
 501          $newquery = '';
 502  
 503          foreach ($tokens as $key => $val) {
 504              switch ($val) {
 505                  case '?':
 506                      $types[$token++] = DB_PARAM_SCALAR;
 507                      break;
 508                  case '&':
 509                      $types[$token++] = DB_PARAM_OPAQUE;
 510                      break;
 511                  case '!':
 512                      $types[$token++] = DB_PARAM_MISC;
 513                      break;
 514                  default:
 515                      $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val);
 516                      $newquery .= $tokens[$key] . '?';
 517              }
 518          }
 519  
 520          $newquery = substr($newquery, 0, -1);
 521          $this->last_query = $query;
 522          $newquery = $this->modifyQuery($newquery);
 523          $stmt = @ibase_prepare($this->connection, $newquery);
 524  
 525          if ($stmt === false) {
 526              $stmt = $this->ibaseRaiseError();
 527          } else {
 528              $this->prepare_types[(int)$stmt] = $types;
 529              $this->manip_query[(int)$stmt]   = DB::isManip($query);
 530          }
 531  
 532          return $stmt;
 533      }
 534  
 535      // }}}
 536      // {{{ execute()
 537  
 538      /**
 539       * Executes a DB statement prepared with prepare().
 540       *
 541       * @param resource  $stmt  a DB statement resource returned from prepare()
 542       * @param mixed  $data  array, string or numeric data to be used in
 543       *                      execution of the statement.  Quantity of items
 544       *                      passed must match quantity of placeholders in
 545       *                      query:  meaning 1 for non-array items or the
 546       *                      quantity of elements in the array.
 547       * @return object  a new DB_Result or a DB_Error when fail
 548       * @see DB_ibase::prepare()
 549       * @access public
 550       */
 551      function &execute($stmt, $data = array())
 552      {
 553          $data = (array)$data;
 554          $this->last_parameters = $data;
 555  
 556          $types =& $this->prepare_types[(int)$stmt];
 557          if (count($types) != count($data)) {
 558              $tmp =& $this->raiseError(DB_ERROR_MISMATCH);
 559              return $tmp;
 560          }
 561  
 562          $i = 0;
 563          foreach ($data as $key => $value) {
 564              if ($types[$i] == DB_PARAM_MISC) {
 565                  /*
 566                   * ibase doesn't seem to have the ability to pass a
 567                   * parameter along unchanged, so strip off quotes from start
 568                   * and end, plus turn two single quotes to one single quote,
 569                   * in order to avoid the quotes getting escaped by
 570                   * ibase and ending up in the database.
 571                   */
 572                  $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]);
 573                  $data[$key] = str_replace("''", "'", $data[$key]);
 574              } elseif ($types[$i] == DB_PARAM_OPAQUE) {
 575                  $fp = @fopen($data[$key], 'rb');
 576                  if (!$fp) {
 577                      $tmp =& $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
 578                      return $tmp;
 579                  }
 580                  $data[$key] = fread($fp, filesize($data[$key]));
 581                  fclose($fp);
 582              }
 583              $i++;
 584          }
 585  
 586          array_unshift($data, $stmt);
 587  
 588          $res = call_user_func_array('ibase_execute', $data);
 589          if (!$res) {
 590              $tmp =& $this->ibaseRaiseError();
 591              return $tmp;
 592          }
 593          /* XXX need this?
 594          if ($this->autocommit && $this->manip_query[(int)$stmt]) {
 595              @ibase_commit($this->connection);
 596          }*/
 597          $this->last_stmt = $stmt;
 598          if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) {
 599              $this->_last_query_manip = true;
 600              $this->_next_query_manip = false;
 601              $tmp = DB_OK;
 602          } else {
 603              $this->_last_query_manip = false;
 604              $tmp =& new DB_result($this, $res);
 605          }
 606          return $tmp;
 607      }
 608  
 609      /**
 610       * Frees the internal resources associated with a prepared query
 611       *
 612       * @param resource $stmt           the prepared statement's PHP resource
 613       * @param bool     $free_resource  should the PHP resource be freed too?
 614       *                                  Use false if you need to get data
 615       *                                  from the result set later.
 616       *
 617       * @return bool  TRUE on success, FALSE if $result is invalid
 618       *
 619       * @see DB_ibase::prepare()
 620       */
 621      function freePrepared($stmt, $free_resource = true)
 622      {
 623          if (!is_resource($stmt)) {
 624              return false;
 625          }
 626          if ($free_resource) {
 627              @ibase_free_query($stmt);
 628          }
 629          unset($this->prepare_tokens[(int)$stmt]);
 630          unset($this->prepare_types[(int)$stmt]);
 631          unset($this->manip_query[(int)$stmt]);
 632          return true;
 633      }
 634  
 635      // }}}
 636      // {{{ autoCommit()
 637  
 638      /**
 639       * Enables or disables automatic commits
 640       *
 641       * @param bool $onoff  true turns it on, false turns it off
 642       *
 643       * @return int  DB_OK on success.  A DB_Error object if the driver
 644       *               doesn't support auto-committing transactions.
 645       */
 646      function autoCommit($onoff = false)
 647      {
 648          $this->autocommit = $onoff ? 1 : 0;
 649          return DB_OK;
 650      }
 651  
 652      // }}}
 653      // {{{ commit()
 654  
 655      /**
 656       * Commits the current transaction
 657       *
 658       * @return int  DB_OK on success.  A DB_Error object on failure.
 659       */
 660      function commit()
 661      {
 662          return @ibase_commit($this->connection);
 663      }
 664  
 665      // }}}
 666      // {{{ rollback()
 667  
 668      /**
 669       * Reverts the current transaction
 670       *
 671       * @return int  DB_OK on success.  A DB_Error object on failure.
 672       */
 673      function rollback()
 674      {
 675          return @ibase_rollback($this->connection);
 676      }
 677  
 678      // }}}
 679      // {{{ transactionInit()
 680  
 681      function transactionInit($trans_args = 0)
 682      {
 683          return $trans_args
 684                  ? @ibase_trans($trans_args, $this->connection)
 685                  : @ibase_trans();
 686      }
 687  
 688      // }}}
 689      // {{{ nextId()
 690  
 691      /**
 692       * Returns the next free id in a sequence
 693       *
 694       * @param string  $seq_name  name of the sequence
 695       * @param boolean $ondemand  when true, the seqence is automatically
 696       *                            created if it does not exist
 697       *
 698       * @return int  the next id number in the sequence.
 699       *               A DB_Error object on failure.
 700       *
 701       * @see DB_common::nextID(), DB_common::getSequenceName(),
 702       *      DB_ibase::createSequence(), DB_ibase::dropSequence()
 703       */
 704      function nextId($seq_name, $ondemand = true)
 705      {
 706          $sqn = strtoupper($this->getSequenceName($seq_name));
 707          $repeat = 0;
 708          do {
 709              $this->pushErrorHandling(PEAR_ERROR_RETURN);
 710              $result =& $this->query("SELECT GEN_ID($sqn}, 1) "
 711                                     . 'FROM RDB$GENERATORS '
 712                                     . "WHERE RDB\$GENERATOR_NAME='$sqn}'");
 713              $this->popErrorHandling();
 714              if ($ondemand && DB::isError($result)) {
 715                  $repeat = 1;
 716                  $result = $this->createSequence($seq_name);
 717                  if (DB::isError($result)) {
 718                      return $result;
 719                  }
 720              } else {
 721                  $repeat = 0;
 722              }
 723          } while ($repeat);
 724          if (DB::isError($result)) {
 725              return $this->raiseError($result);
 726          }
 727          $arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
 728          $result->free();
 729          return $arr[0];
 730      }
 731  
 732      // }}}
 733      // {{{ createSequence()
 734  
 735      /**
 736       * Creates a new sequence
 737       *
 738       * @param string $seq_name  name of the new sequence
 739       *
 740       * @return int  DB_OK on success.  A DB_Error object on failure.
 741       *
 742       * @see DB_common::createSequence(), DB_common::getSequenceName(),
 743       *      DB_ibase::nextID(), DB_ibase::dropSequence()
 744       */
 745      function createSequence($seq_name)
 746      {
 747          $sqn = strtoupper($this->getSequenceName($seq_name));
 748          $this->pushErrorHandling(PEAR_ERROR_RETURN);
 749          $result = $this->query("CREATE GENERATOR $sqn}");
 750          $this->popErrorHandling();
 751  
 752          return $result;
 753      }
 754  
 755      // }}}
 756      // {{{ dropSequence()
 757  
 758      /**
 759       * Deletes a sequence
 760       *
 761       * @param string $seq_name  name of the sequence to be deleted
 762       *
 763       * @return int  DB_OK on success.  A DB_Error object on failure.
 764       *
 765       * @see DB_common::dropSequence(), DB_common::getSequenceName(),
 766       *      DB_ibase::nextID(), DB_ibase::createSequence()
 767       */
 768      function dropSequence($seq_name)
 769      {
 770          return $this->query('DELETE FROM RDB$GENERATORS '
 771                              . "WHERE RDB\$GENERATOR_NAME='"
 772                              . strtoupper($this->getSequenceName($seq_name))
 773                              . "'");
 774      }
 775  
 776      // }}}
 777      // {{{ _ibaseFieldFlags()
 778  
 779      /**
 780       * Get the column's flags
 781       *
 782       * Supports "primary_key", "unique_key", "not_null", "default",
 783       * "computed" and "blob".
 784       *
 785       * @param string $field_name  the name of the field
 786       * @param string $table_name  the name of the table
 787       *
 788       * @return string  the flags
 789       *
 790       * @access private
 791       */
 792      function _ibaseFieldFlags($field_name, $table_name)
 793      {
 794          $sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE'
 795                 .' FROM RDB$INDEX_SEGMENTS I'
 796                 .'  JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME'
 797                 .' WHERE I.RDB$FIELD_NAME=\'' . $field_name . '\''
 798                 .'  AND UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\'';
 799  
 800          $result = @ibase_query($this->connection, $sql);
 801          if (!$result) {
 802              return $this->ibaseRaiseError();
 803          }
 804  
 805          $flags = '';
 806          if ($obj = @ibase_fetch_object($result)) {
 807              @ibase_free_result($result);
 808              if (isset($obj->CTYPE)  && trim($obj->CTYPE) == 'PRIMARY KEY') {
 809                  $flags .= 'primary_key ';
 810              }
 811              if (isset($obj->CTYPE)  && trim($obj->CTYPE) == 'UNIQUE') {
 812                  $flags .= 'unique_key ';
 813              }
 814          }
 815  
 816          $sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,'
 817                 .'  R.RDB$DEFAULT_SOURCE AS DSOURCE,'
 818                 .'  F.RDB$FIELD_TYPE AS FTYPE,'
 819                 .'  F.RDB$COMPUTED_SOURCE AS CSOURCE'
 820                 .' FROM RDB$RELATION_FIELDS R '
 821                 .'  JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME'
 822                 .' WHERE UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\''
 823                 .'  AND R.RDB$FIELD_NAME=\'' . $field_name . '\'';
 824  
 825          $result = @ibase_query($this->connection, $sql);
 826          if (!$result) {
 827              return $this->ibaseRaiseError();
 828          }
 829          if ($obj = @ibase_fetch_object($result)) {
 830              @ibase_free_result($result);
 831              if (isset($obj->NFLAG)) {
 832                  $flags .= 'not_null ';
 833              }
 834              if (isset($obj->DSOURCE)) {
 835                  $flags .= 'default ';
 836              }
 837              if (isset($obj->CSOURCE)) {
 838                  $flags .= 'computed ';
 839              }
 840              if (isset($obj->FTYPE)  && $obj->FTYPE == 261) {
 841                  $flags .= 'blob ';
 842              }
 843          }
 844  
 845          return trim($flags);
 846      }
 847  
 848      // }}}
 849      // {{{ ibaseRaiseError()
 850  
 851      /**
 852       * Produces a DB_Error object regarding the current problem
 853       *
 854       * @param int $errno  if the error is being manually raised pass a
 855       *                     DB_ERROR* constant here.  If this isn't passed
 856       *                     the error information gathered from the DBMS.
 857       *
 858       * @return object  the DB_Error object
 859       *
 860       * @see DB_common::raiseError(),
 861       *      DB_ibase::errorNative(), DB_ibase::errorCode()
 862       */
 863      function &ibaseRaiseError($errno = null)
 864      {
 865          if ($errno === null) {
 866              $errno = $this->errorCode($this->errorNative());
 867          }
 868          $tmp =& $this->raiseError($errno, null, null, null, @ibase_errmsg());
 869          return $tmp;
 870      }
 871  
 872      // }}}
 873      // {{{ errorNative()
 874  
 875      /**
 876       * Gets the DBMS' native error code produced by the last query
 877       *
 878       * @return int  the DBMS' error code.  NULL if there is no error code.
 879       *
 880       * @since Method available since Release 1.7.0
 881       */
 882      function errorNative()
 883      {
 884          if (function_exists('ibase_errcode')) {
 885              return @ibase_errcode();
 886          }
 887          if (preg_match('/^Dynamic SQL Error SQL error code = ([0-9-]+)/i',
 888                         @ibase_errmsg(), $m)) {
 889              return (int)$m[1];
 890          }
 891          return null;
 892      }
 893  
 894      // }}}
 895      // {{{ errorCode()
 896  
 897      /**
 898       * Maps native error codes to DB's portable ones
 899       *
 900       * @param int $nativecode  the error code returned by the DBMS
 901       *
 902       * @return int  the portable DB error code.  Return DB_ERROR if the
 903       *               current driver doesn't have a mapping for the
 904       *               $nativecode submitted.
 905       *
 906       * @since Method available since Release 1.7.0
 907       */
 908      function errorCode($nativecode = null)
 909      {
 910          if (isset($this->errorcode_map[$nativecode])) {
 911              return $this->errorcode_map[$nativecode];
 912          }
 913  
 914          static $error_regexps;
 915          if (!isset($error_regexps)) {
 916              $error_regexps = array(
 917                  '/generator .* is not defined/'
 918                      => DB_ERROR_SYNTAX,  // for compat. w ibase_errcode()
 919                  '/table.*(not exist|not found|unknown)/i'
 920                      => DB_ERROR_NOSUCHTABLE,
 921                  '/table .* already exists/i'
 922                      => DB_ERROR_ALREADY_EXISTS,
 923                  '/unsuccessful metadata update .* failed attempt to store duplicate value/i'
 924                      => DB_ERROR_ALREADY_EXISTS,
 925                  '/unsuccessful metadata update .* not found/i'
 926                      => DB_ERROR_NOT_FOUND,
 927                  '/validation error for column .* value "\*\*\* null/i'
 928                      => DB_ERROR_CONSTRAINT_NOT_NULL,
 929                  '/violation of [\w ]+ constraint/i'
 930                      => DB_ERROR_CONSTRAINT,
 931                  '/conversion error from string/i'
 932                      => DB_ERROR_INVALID_NUMBER,
 933                  '/no permission for/i'
 934                      => DB_ERROR_ACCESS_VIOLATION,
 935                  '/arithmetic exception, numeric overflow, or string truncation/i'
 936                      => DB_ERROR_INVALID,
 937                  '/feature is not supported/i'
 938                      => DB_ERROR_NOT_CAPABLE,
 939              );
 940          }
 941  
 942          $errormsg = @ibase_errmsg();
 943          foreach ($error_regexps as $regexp => $code) {
 944              if (preg_match($regexp, $errormsg)) {
 945                  return $code;
 946              }
 947          }
 948          return DB_ERROR;
 949      }
 950  
 951      // }}}
 952      // {{{ tableInfo()
 953  
 954      /**
 955       * Returns information about a table or a result set
 956       *
 957       * NOTE: only supports 'table' and 'flags' if <var>$result</var>
 958       * is a table name.
 959       *
 960       * @param object|string  $result  DB_result object from a query or a
 961       *                                 string containing the name of a table.
 962       *                                 While this also accepts a query result
 963       *                                 resource identifier, this behavior is
 964       *                                 deprecated.
 965       * @param int            $mode    a valid tableInfo mode
 966       *
 967       * @return array  an associative array with the information requested.
 968       *                 A DB_Error object on failure.
 969       *
 970       * @see DB_common::tableInfo()
 971       */
 972      function tableInfo($result, $mode = null)
 973      {
 974          if (is_string($result)) {
 975              /*
 976               * Probably received a table name.
 977               * Create a result resource identifier.
 978               */
 979              $id = @ibase_query($this->connection,
 980                                 "SELECT * FROM $result WHERE 1=0");
 981              $got_string = true;
 982          } elseif (isset($result->result)) {
 983              /*
 984               * Probably received a result object.
 985               * Extract the result resource identifier.
 986               */
 987              $id = $result->result;
 988              $got_string = false;
 989          } else {
 990              /*
 991               * Probably received a result resource identifier.
 992               * Copy it.
 993               * Deprecated.  Here for compatibility only.
 994               */
 995              $id = $result;
 996              $got_string = false;
 997          }
 998  
 999          if (!is_resource($id)) {
1000              return $this->ibaseRaiseError(DB_ERROR_NEED_MORE_DATA);
1001          }
1002  
1003          if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
1004              $case_func = 'strtolower';
1005          } else {
1006              $case_func = 'strval';
1007          }
1008  
1009          $count = @ibase_num_fields($id);
1010          $res   = array();
1011  
1012          if ($mode) {
1013              $res['num_fields'] = $count;
1014          }
1015  
1016          for ($i = 0; $i < $count; $i++) {
1017              $info = @ibase_field_info($id, $i);
1018              $res[$i] = array(
1019                  'table' => $got_string ? $case_func($result) : '',
1020                  'name'  => $case_func($info['name']),
1021                  'type'  => $info['type'],
1022                  'len'   => $info['length'],
1023                  'flags' => ($got_string)
1024                              ? $this->_ibaseFieldFlags($info['name'], $result)
1025                              : '',
1026              );
1027              if ($mode & DB_TABLEINFO_ORDER) {
1028                  $res['order'][$res[$i]['name']] = $i;
1029              }
1030              if ($mode & DB_TABLEINFO_ORDERTABLE) {
1031                  $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1032              }
1033          }
1034  
1035          // free the result only if we were called on a table
1036          if ($got_string) {
1037              @ibase_free_result($id);
1038          }
1039          return $res;
1040      }
1041  
1042      // }}}
1043      // {{{ getSpecialQuery()
1044  
1045      /**
1046       * Obtains the query string needed for listing a given type of objects
1047       *
1048       * @param string $type  the kind of objects you want to retrieve
1049       *
1050       * @return string  the SQL query string or null if the driver doesn't
1051       *                  support the object type requested
1052       *
1053       * @access protected
1054       * @see DB_common::getListOf()
1055       */
1056      function getSpecialQuery($type)
1057      {
1058          switch ($type) {
1059              case 'tables':
1060                  return 'SELECT DISTINCT R.RDB$RELATION_NAME FROM '
1061                         . 'RDB$RELATION_FIELDS R WHERE R.RDB$SYSTEM_FLAG=0';
1062              case 'views':
1063                  return 'SELECT DISTINCT RDB$VIEW_NAME from RDB$VIEW_RELATIONS';
1064              case 'users':
1065                  return 'SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES';
1066              default:
1067                  return null;
1068          }
1069      }
1070  
1071      // }}}
1072  
1073  }
1074  
1075  /*
1076   * Local variables:
1077   * tab-width: 4
1078   * c-basic-offset: 4
1079   * End:
1080   */
1081  
1082  ?>


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