[ Index ]
 

Code source de PHP PEAR 1.4.5

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

title

Body

[fermer]

/MDB/ -> oci8.php (source)

   1  <?php 
   2  // +----------------------------------------------------------------------+
   3  // | PHP Version 4                                                        |
   4  // +----------------------------------------------------------------------+
   5  // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
   6  // | Stig. S. Bakken, Lukas Smith                                         |
   7  // | All rights reserved.                                                 |
   8  // +----------------------------------------------------------------------+
   9  // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10  // | API as well as database abstraction for PHP applications.            |
  11  // | This LICENSE is in the BSD license style.                            |
  12  // |                                                                      |
  13  // | Redistribution and use in source and binary forms, with or without   |
  14  // | modification, are permitted provided that the following conditions   |
  15  // | are met:                                                             |
  16  // |                                                                      |
  17  // | Redistributions of source code must retain the above copyright       |
  18  // | notice, this list of conditions and the following disclaimer.        |
  19  // |                                                                      |
  20  // | Redistributions in binary form must reproduce the above copyright    |
  21  // | notice, this list of conditions and the following disclaimer in the  |
  22  // | documentation and/or other materials provided with the distribution. |
  23  // |                                                                      |
  24  // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25  // | Lukas Smith nor the names of his contributors may be used to endorse |
  26  // | or promote products derived from this software without specific prior|
  27  // | written permission.                                                  |
  28  // |                                                                      |
  29  // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30  // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31  // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32  // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33  // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34  // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35  // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36  // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37  // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38  // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39  // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40  // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41  // +----------------------------------------------------------------------+
  42  // | Author: Lukas Smith <smith@backendmedia.com>                         |
  43  // +----------------------------------------------------------------------+
  44  
  45  // $Id: oci8.php,v 1.21.4.24 2004/03/31 16:02:40 lsmith Exp $
  46  
  47  require_once ('MDB/Common.php');
  48  
  49  /**
  50   * MDB OCI8 driver
  51   *
  52   * Notes:
  53   * - when fetching in associative mode all keys are uppercased which is not the
  54   *   intenteded behavior. Due to BC issues this will not be changed in MDB 1.x
  55   *   however.
  56   *
  57   * - createDatabase and dropDatabase are not supported
  58   *
  59   * - Text fields with unspecified length limit are created as VARCHAR with an
  60   *   optional limit that may not exceed 4000 characters.
  61   *
  62   * - date fields are emulated with date fields with time set to 00:00:00.
  63       time fields are emulated with date fields with the day set to 0001-01-01.
  64   *
  65   * - The numRows method is emulated by fetching all the rows into memory.
  66   *   Avoid using it if for queries with large result sets.
  67   *
  68   * - Oracle does not provide direct support for returning result sets restricted
  69       to a given range. Such support is emulated in the MDB oci8 driver.
  70   *
  71   * - Storing data in large object fields has to be done in two phases: first the
  72       fields are initialized using a INSERT or UPDATE query that sets the fields
  73       to an empty value, then the data values are uploaded to the large objects
  74       returned by reference from the executed queries.
  75   *   Besides the fact that only INSERT and UPDATE queries are supported to
  76       upload large object data values, only UPDATE queries that affect only one
  77       row will set the large object fields correctly.
  78   *
  79   * - The driver alterTable method does not implement table or column renaming.
  80   *
  81   * @package MDB
  82   * @category Database
  83   * @author Lukas Smith <smith@backendmedia.com> 
  84   */
  85  class MDB_oci8 extends MDB_Common {
  86      var $connection = 0;
  87      var $connected_user;
  88      var $connected_password;
  89  
  90      var $escape_quotes = "'";
  91  
  92      var $uncommitedqueries = 0;
  93  
  94      var $results = array();
  95      var $current_row = array();
  96      var $columns = array();
  97      var $rows = array();
  98      var $limits = array();
  99      var $row_buffer = array();
 100      var $highest_fetched_row = array();
 101  
 102      // {{{ constructor
 103  
 104      /**
 105       * Constructor
 106       */
 107      function MDB_oci8()
 108      {
 109          $this->MDB_Common();
 110          $this->phptype = 'oci8';
 111          $this->dbsyntax = 'oci8';
 112          
 113          $this->supported['Sequences'] = 1;
 114          $this->supported['Indexes'] = 1;
 115          $this->supported['SummaryFunctions'] = 1;
 116          $this->supported['OrderByText'] = 1;
 117          $this->supported['CurrId'] = 1;
 118          $this->supported["AffectedRows"]= 1;
 119          $this->supported['Transactions'] = 1;
 120          $this->supported['SelectRowRanges'] = 1;
 121          $this->supported['LOBs'] = 1;
 122          $this->supported['Replace'] = 1;
 123          $this->supported['SubSelects'] = 1;
 124          
 125          $this->options['DBAUser'] = FALSE;
 126          $this->options['DBAPassword'] = FALSE;
 127          
 128          $this->errorcode_map = array(
 129              1 => MDB_ERROR_CONSTRAINT,
 130              900 => MDB_ERROR_SYNTAX,
 131              904 => MDB_ERROR_NOSUCHFIELD,
 132              921 => MDB_ERROR_SYNTAX,
 133              923 => MDB_ERROR_SYNTAX,
 134              942 => MDB_ERROR_NOSUCHTABLE,
 135              955 => MDB_ERROR_ALREADY_EXISTS,
 136              1400 => MDB_ERROR_CONSTRAINT_NOT_NULL,
 137              1407 => MDB_ERROR_CONSTRAINT_NOT_NULL,
 138              1476 => MDB_ERROR_DIVZERO,
 139              1722 => MDB_ERROR_INVALID_NUMBER,
 140              2289 => MDB_ERROR_NOSUCHTABLE,
 141              2291 => MDB_ERROR_CONSTRAINT,
 142              2449 => MDB_ERROR_CONSTRAINT,
 143          );
 144      }
 145  
 146      // }}}
 147      // {{{ errorNative()
 148  
 149      /**
 150       * Get the native error code of the last error (if any) that
 151       * occured on the current connection.
 152       * 
 153       * @access public 
 154       * @return int native oci8 error code
 155       */
 156      function errorNative($statement = NULL)
 157      {
 158          if (is_resource($statement)) {
 159              $error = @OCIError($statement);
 160          } else {
 161              $error = @OCIError($this->connection);
 162          }
 163          if (is_array($error)) {
 164              return($error['code']);
 165          }
 166          return(FALSE);
 167      }
 168  
 169      // }}}
 170      // {{{ oci8RaiseError()
 171  
 172      /**
 173       * This method is used to communicate an error and invoke error
 174       * callbacks etc.  Basically a wrapper for MDB::raiseError
 175       * that checks for native error msgs.
 176       * 
 177       * @param integer $errno error code
 178       * @param string  $message userinfo message
 179       * @return object a PEAR error object
 180       * @access public 
 181       * @see PEAR_Error
 182       */
 183      function oci8RaiseError($errno = NULL, $message = NULL)
 184      {
 185          if ($errno === NULL) {
 186              if ($this->connection) {
 187                  $error = @OCIError($this->connection);
 188              } else {
 189                  $error = @OCIError();
 190              }
 191              return($this->raiseError($this->errorCode($error['code']),
 192                  NULL, NULL, $message, $error['message']));
 193          } elseif (is_resource($errno)) {
 194              $error = @OCIError($errno);
 195              return($this->raiseError($this->errorCode($error['code']),
 196                  NULL, NULL, $message, $error['message']));
 197          }
 198          return($this->raiseError($this->errorCode($errno), NULL, NULL, $message));
 199      }
 200  
 201      // }}}
 202      // {{{ autoCommit()
 203  
 204      /**
 205       * Define whether database changes done on the database be automatically
 206       * committed. This function may also implicitly start or end a transaction.
 207       * 
 208       * @param boolean $auto_commit flag that indicates whether the database
 209       *                                 changes should be committed right after
 210       *                                 executing every query statement. If this
 211       *                                 argument is 0 a transaction implicitly
 212       *                                 started. Otherwise, if a transaction is
 213       *                                 in progress it is ended by committing any
 214       *                                 database changes that were pending.
 215       * @access public 
 216       * @return mixed MDB_OK on success, a MDB error on failure
 217       */
 218      function autoCommit($auto_commit)
 219      {
 220          $this->debug('AutoCommit: '.($auto_commit ? 'On' : 'Off'));
 221          if ($this->auto_commit == $auto_commit) {
 222              return(MDB_OK);
 223          }
 224          if ($this->connection && $auto_commit && MDB::isError($commit = $this->commit())) {
 225              return($commit);
 226          }
 227          $this->auto_commit = $auto_commit;
 228          $this->in_transaction = !$auto_commit;
 229          return(MDB_OK);
 230      }
 231  
 232      // }}}
 233      // {{{ commit()
 234  
 235      /**
 236       * Commit the database changes done during a transaction that is in
 237       * progress. This function may only be called when auto-committing is
 238       * disabled, otherwise it will fail. Therefore, a new transaction is
 239       * implicitly started after committing the pending changes.
 240       * 
 241       * @access public 
 242       * @return mixed MDB_OK on success, a MDB error on failure
 243       */
 244      function commit()
 245      {
 246          $this->debug('Commit Transaction');
 247          if (!isset($this->supported['Transactions'])) {
 248              return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
 249                  'Commit transactions: transactions are not in use'));
 250          }
 251          if ($this->auto_commit) {
 252              return($this->raiseError(MDB_ERROR, NULL, NULL,
 253              'Commit transactions: transaction changes are being auto commited'));
 254          }
 255          if ($this->uncommitedqueries) {
 256              if (!@OCICommit($this->connection)) {
 257                  return($this->oci8RaiseError(NULL,
 258                      'Commit transactions: Could not commit pending transaction: '."$message. Error: ".$error['code'].' ('.$error['message'].')'));
 259              }
 260              $this->uncommitedqueries = 0;
 261          }
 262          return(MDB_OK);
 263      }
 264  
 265      // }}}
 266      // {{{ rollback()
 267  
 268      /**
 269       * Cancel any database changes done during a transaction that is in
 270       * progress. This function may only be called when auto-committing is
 271       * disabled, otherwise it will fail. Therefore, a new transaction is
 272       * implicitly started after canceling the pending changes.
 273       * 
 274       * @access public 
 275       * @return mixed MDB_OK on success, a MDB error on failure
 276       */
 277      function rollback()
 278      {
 279          $this->debug('Rollback Transaction');
 280          if ($this->auto_commit) {
 281              return($this->raiseError(MDB_ERROR, NULL, NULL,
 282                  'Rollback transactions: transactions can not be rolled back when changes are auto commited'));
 283          }
 284          if ($this->uncommitedqueries) {
 285              if (!@OCIRollback($this->connection)) {
 286                  return($this->oci8RaiseError(NULL,
 287                      'Rollback transaction: Could not rollback pending transaction'));
 288              }
 289              $this->uncommitedqueries = 0;
 290          }
 291          return(MDB_OK);
 292      }
 293  
 294      // }}}
 295      // {{{ connect()
 296  
 297      /**
 298       * Connect to the database
 299       * 
 300       * @return TRUE on success, MDB_Error on failure
 301       */
 302      function connect($user = NULL , $password = NULL, $persistent = NULL)
 303      {
 304          if($user === NULL) {
 305              $user = $this->user;
 306          }
 307          if($password === NULL) {
 308              $password = $this->password;
 309          }
 310          if($persistent === NULL) {
 311              $persistent = $this->getOption('persistent');
 312          }
 313          if (isset($this->host)) {
 314              $sid = $this->host;
 315          } else {
 316              $sid = getenv('ORACLE_SID');
 317          }
 318          if(!strcmp($sid, '')) {
 319              return($this->raiseError(MDB_ERROR, NULL, NULL,
 320                  'Connect: it was not specified a valid Oracle Service IDentifier (SID)'));
 321          }
 322          if($this->connection != 0) {
 323              if (!strcmp($this->connected_user, $user)
 324                  && !strcmp($this->connected_password, $password)
 325                  && $this->opened_persistent == $persistent)
 326              {
 327                  return(MDB_OK);
 328              }
 329              $this->_close();
 330          }
 331  
 332          if(!PEAR::loadExtension($this->phptype)) {
 333              return(PEAR::raiseError(NULL, MDB_ERROR_NOT_FOUND,
 334                  NULL, NULL, 'extension '.$this->phptype.' is not compiled into PHP',
 335                  'MDB_Error', TRUE));
 336          }
 337  
 338          if (isset($this->options['HOME'])) {
 339              putenv('ORACLE_HOME='.$this->options['HOME']);
 340          }
 341          putenv('ORACLE_SID='.$sid);
 342          $function = ($persistent ? 'OCIPLogon' : 'OCINLogon');
 343          if (!function_exists($function)) {
 344              return($this->raiseError(MDB_ERROR, NULL, NULL,
 345                  'Connect: Oracle OCI API support is not available in this PHP configuration'));
 346          }
 347          if (!($this->connection = @$function($user, $password, $sid))) {
 348              return($this->oci8RaiseError(NULL,
 349                  'Connect: Could not connect to Oracle server'));
 350          }
 351          if (MDB::isError($doquery = $this->_doQuery("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'"))) {
 352              $this->_close();
 353              return($doquery);
 354          }
 355          if (MDB::isError($doquery = $this->_doQuery("ALTER SESSION SET NLS_NUMERIC_CHARACTERS='. '"))) {
 356              $this->_close();
 357              return($doquery);
 358          }
 359  
 360          $this->connected_user = $user;
 361          $this->connected_password = $password;
 362          $this->opened_persistent = $persistent;
 363          return(MDB_OK);
 364      }
 365  
 366      // }}}
 367      // {{{ _close()
 368  
 369      /**
 370       * all the RDBMS specific things needed close a DB connection
 371       * 
 372       * @access private 
 373       */
 374      function _close()
 375      {
 376          if ($this->connection != 0) {
 377              @OCILogOff($this->connection);
 378              $this->connection = 0;
 379              $this->affected_rows = -1;
 380              $this->uncommitedqueries = 0;
 381          }
 382      }
 383  
 384      // }}}
 385      // {{{ _doQuery()
 386  
 387      /**
 388       * all the RDBMS specific things needed close a DB connection
 389       * 
 390       * @access private
 391       */
 392      function _doQuery($query, $first = 0, $limit = 0, $prepared_query = 0)
 393      {
 394          $lobs = 0;
 395          $success = MDB_OK;
 396          $result = 0;
 397          $descriptors = array();
 398          if ($prepared_query) {
 399              $columns = '';
 400              $variables = '';
 401              for(reset($this->clobs[$prepared_query]), $clob = 0;
 402                  $clob < count($this->clobs[$prepared_query]);
 403                  $clob++, next($this->clobs[$prepared_query]))
 404              {
 405                  $position = key($this->clobs[$prepared_query]);
 406                  if (gettype($descriptors[$position] = @OCINewDescriptor($this->connection, OCI_D_LOB)) != 'object') {
 407                      $success = $this->raiseError(MDB_ERROR, NULL, NULL,
 408                          'Do query: Could not create descriptor for clob parameter');
 409                      break;
 410                  }
 411                  $columns.= ($lobs == 0 ? ' RETURNING ' : ',').$this->prepared_queries[$prepared_query-1]['Fields'][$position-1];
 412                  $variables.= ($lobs == 0 ? ' INTO ' : ',').':clob'.$position;
 413                  $lobs++;
 414              }
 415              if (!MDB::isError($success)) {
 416                  for(reset($this->blobs[$prepared_query]), $blob = 0;$blob < count($this->blobs[$prepared_query]);$blob++, next($this->blobs[$prepared_query])) {
 417                      $position = key($this->blobs[$prepared_query]);
 418                      if (gettype($descriptors[$position] = @OCINewDescriptor($this->connection, OCI_D_LOB)) != 'object') {
 419                          $success = $this->raiseError(MDB_ERROR, NULL, NULL,
 420                              'Do query: Could not create descriptor for blob parameter');
 421                          break;
 422                      }
 423                      $columns.= ($lobs == 0 ? ' RETURNING ' : ',').$this->prepared_queries[$prepared_query-1]['Fields'][$position-1];
 424                      $variables.= ($lobs == 0 ? ' INTO ' : ',').':blob'.$position;
 425                      $lobs++;
 426                  }
 427                  $query.= $columns.$variables;
 428              }
 429          }
 430          if (!MDB::isError($success)) {
 431              if (($statement = @OCIParse($this->connection, $query))) {
 432                  if ($lobs) {
 433                      for(reset($this->clobs[$prepared_query]), $clob = 0;$clob < count($this->clobs[$prepared_query]);$clob++, next($this->clobs[$prepared_query])) {
 434                          $position = key($this->clobs[$prepared_query]);
 435                          if (!@OCIBindByName($statement, ':clob'.$position, $descriptors[$position], -1, OCI_B_CLOB)) {
 436                              $success = $this->oci8RaiseError(NULL,
 437                                  'Do query: Could not bind clob upload descriptor');
 438                              break;
 439                          }
 440                      }
 441                      if (!MDB::isError($success)) {
 442                          for(reset($this->blobs[$prepared_query]), $blob = 0;
 443                              $blob < count($this->blobs[$prepared_query]);
 444                              $blob++, next($this->blobs[$prepared_query]))
 445                          {
 446                              $position = key($this->blobs[$prepared_query]);
 447                              if (!@OCIBindByName($statement, ':blob'.$position, $descriptors[$position], -1, OCI_B_BLOB)) {
 448                                  $success = $this->oci8RaiseError(NULL,
 449                                      'Do query: Could not bind blob upload descriptor');
 450                                  break;
 451                              }
 452                          }
 453                      }
 454                  }
 455                  if (!MDB::isError($success)) {
 456                      if (($result = @OCIExecute($statement, ($lobs == 0 && $this->auto_commit) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT))) {
 457                          if ($lobs) {
 458                              for(reset($this->clobs[$prepared_query]), $clob = 0;
 459                                  $clob < count($this->clobs[$prepared_query]);
 460                                  $clob++, next($this->clobs[$prepared_query]))
 461                              {
 462                                  $position = key($this->clobs[$prepared_query]);
 463                                  $clob_stream = $this->prepared_queries[$prepared_query-1]['Values'][$position-1];
 464                                  for($value = '';!$this->endOfLOB($clob_stream);) {
 465                                      if ($this->readLOB($clob_stream, $data, $this->getOption('lob_buffer_length')) < 0) {
 466                                          $success = $this->raiseError();
 467                                          break;
 468                                      }
 469                                      $value.= $data;
 470                                  }
 471                                  if (!MDB::isError($success) && !$descriptors[$position]->save($value)) {
 472                                      $success = $this->oci8RaiseError(NULL,
 473                                          'Do query: Could not upload clob data');
 474                                  }
 475                              }
 476                              if (!MDB::isError($success)) {
 477                                  for(reset($this->blobs[$prepared_query]), $blob = 0;$blob < count($this->blobs[$prepared_query]);$blob++, next($this->blobs[$prepared_query])) {
 478                                      $position = key($this->blobs[$prepared_query]);
 479                                      $blob_stream = $this->prepared_queries[$prepared_query-1]['Values'][$position-1];
 480                                      for($value = '';!$this->endOfLOB($blob_stream);) {
 481                                          if ($this->readLOB($blob_stream, $data, $this->getOption('lob_buffer_length')) < 0) {
 482                                              $success = $this->raiseError();
 483                                              break;
 484                                          }
 485                                          $value.= $data;
 486                                      }
 487                                      if (!MDB::isError($success) && !$descriptors[$position]->save($value)) {
 488                                          $success = $this->oci8RaiseError(NULL,
 489                                                  'Do query: Could not upload blob data');
 490                                      }
 491                                  }
 492                              }
 493                          }
 494                          if ($this->auto_commit) {
 495                              if ($lobs) {
 496                                  if (MDB::isError($success)) {
 497                                      if (!@OCIRollback($this->connection)) {
 498                                          $success = $this->oci8RaiseError(NULL,
 499                                              'Do query: '.$success->getUserinfo().' and then could not rollback LOB updating transaction');
 500                                      }
 501                                  } else {
 502                                      if (!@OCICommit($this->connection)) {
 503                                          $success = $this->oci8RaiseError(NULL,
 504                                              'Do query: Could not commit pending LOB updating transaction');
 505                                      }
 506                                  }
 507                              }
 508                          } else {
 509                              $this->uncommitedqueries++;
 510                          }
 511                          if (!MDB::isError($success)) {
 512                              switch (@OCIStatementType($statement)) {
 513                                  case 'SELECT':
 514                                      $result_value = intval($statement);
 515                                      $this->current_row[$result_value] = -1;
 516                                      if ($limit > 0) {
 517                                          $this->limits[$result_value] = array($first, $limit, 0);
 518                                      }
 519                                      $this->highest_fetched_row[$result_value] = -1;
 520                                      break;
 521                                  default:
 522                                      $this->affected_rows = @OCIRowCount($statement);
 523                                      @OCIFreeCursor($statement);
 524                                      break;
 525                              }
 526                              $result = $statement;
 527                          }
 528                      } else {
 529                          return($this->oci8RaiseError($statement, 'Do query: Could not execute query'));
 530                      }
 531                  }
 532              } else {
 533                  return($this->oci8RaiseError(NULL, 'Do query: Could not parse query'));
 534              }
 535          }
 536          for(reset($descriptors), $descriptor = 0;
 537              $descriptor < count($descriptors);
 538              $descriptor++, next($descriptors))
 539          {
 540              @OCIFreeDesc($descriptors[key($descriptors)]);
 541          }
 542          return($result);
 543      }
 544  
 545      // }}}
 546      // {{{ query()
 547  
 548     /**
 549       * Send a query to the database and return any results
 550       * 
 551       * @access public 
 552       * @param string $query the SQL query
 553       * @param array $types array that contains the types of the columns in
 554       *                         the result set
 555       * @return mixed a result handle or MDB_OK on success, a MDB error on failure
 556       */
 557      function query($query, $types = NULL)
 558      {
 559          $this->debug("Query: $query");
 560          $this->last_query = $query;
 561          $first = $this->first_selected_row;
 562          $limit = $this->selected_row_limit;
 563          $this->first_selected_row = $this->selected_row_limit = 0;
 564          if (MDB::isError($connect = $this->connect())) {
 565              return($connect);
 566          }
 567          if(!MDB::isError($result = $this->_doQuery($query, $first, $limit))) {
 568              if ($types != NULL) {
 569                  if (!is_array($types)) {
 570                      $types = array($types);
 571                  }
 572                  if (MDB::isError($err = $this->setResultTypes($result, $types))) {
 573                      $this->freeResult($result);
 574                      return($err);
 575                  }
 576              }
 577              return($result);
 578          }
 579          return($this->oci8RaiseError());
 580      }
 581  
 582      // }}}
 583      // {{{ _executePreparedQuery()
 584  
 585      /**
 586       * Execute a prepared query statement.
 587       *
 588       * @param int $prepared_query argument is a handle that was returned by
 589       *       the function prepareQuery()
 590       * @param string $query query to be executed
 591       * @param array $types array that contains the types of the columns in
 592       *       the result set
 593       * @return mixed a result handle or MDB_OK on success, a MDB error on failure
 594       * @access private
 595       */
 596      function _executePreparedQuery($prepared_query, $query)
 597      {
 598          $first = $this->first_selected_row;
 599          $limit = $this->selected_row_limit;
 600          $this->first_selected_row = $this->selected_row_limit = 0;
 601          if (MDB::isError($connect = $this->connect())) {
 602              return($connect);
 603          }
 604          return($this->_doQuery($query, $first, $limit, $prepared_query));
 605      }
 606  
 607      // }}}
 608      // {{{ _skipLimitOffset()
 609  
 610      /**
 611       * Skip the first row of a result set.
 612       *
 613       * @param resource $result
 614       * @return mixed a result handle or MDB_OK on success, a MDB error on failure
 615       * @access private
 616       */
 617      function _skipLimitOffset($result)
 618      {
 619          $result_value = intval($result);
 620          $first = $this->limits[$result_value][0];
 621          for(;$this->limits[$result_value][2] < $first;$this->limits[$result_value][2]++) {
 622              if (!@OCIFetch($result)) {
 623                  $this->limits[$result_value][2] = $first;
 624                  return($this->raiseError(MDB_ERROR, NULL, NULL,
 625                      'Skip first rows: could not skip a query result row'));
 626              }
 627          }
 628          return(MDB_OK);
 629      }
 630  
 631      // }}}
 632      // {{{ getColumnNames()
 633  
 634      /**
 635       * Retrieve the names of columns returned by the DBMS in a query result.
 636       * 
 637       * @param resource $result result identifier
 638       * @return mixed an associative array variable
 639       *                               that will hold the names of columns.The
 640       *                               indexes of the array are the column names
 641       *                               mapped to lower case and the values are the
 642       *                               respective numbers of the columns starting
 643       *                               from 0. Some DBMS may not return any
 644       *                               columns when the result set does not
 645       *                               contain any rows.
 646       * 
 647       *                               a MDB error on failure
 648       * @access public 
 649       */
 650      function getColumnNames($result)
 651      {
 652          $result_value = intval($result);
 653          if (!isset($this->highest_fetched_row[$result_value])) {
 654              return($this->raiseError(MDB_ERROR, NULL, NULL,
 655                  'Get column names: it was specified an inexisting result set'));
 656          }
 657          if (!isset($this->columns[$result_value])) {
 658              $this->columns[$result_value] = array();
 659              $columns = @OCINumCols($result);
 660              for($column = 0; $column < $columns; $column++) {
 661                  $field_name = @OCIColumnName($result, $column + 1);
 662                  if ($this->options['optimize'] == 'portability') {
 663                      $field_name = strtolower($field_name);
 664                  }
 665                  $this->columns[$result_value][$field_name] = $column;
 666              }
 667          }
 668          return($this->columns[$result_value]);
 669      }
 670  
 671      // }}}
 672      // {{{ numCols()
 673  
 674      /**
 675       * Count the number of columns returned by the DBMS in a query result.
 676       * 
 677       * @param resource $result result identifier
 678       * @return mixed integer value with the number of columns, a MDB error
 679       *      on failure
 680       * @access public
 681       */
 682      function numCols($result)
 683      {
 684          $result_value = intval($result);
 685          if (!isset($this->highest_fetched_row[$result_value])) {
 686              return($this->raiseError(MDB_ERROR, NULL, NULL,
 687                  'Number of columns: it was specified an inexisting result set'));
 688          }
 689          return(@OCINumCols($result));
 690      }
 691  
 692      // }}}
 693      // {{{ endOfResult()
 694  
 695      /**
 696       * check if the end of the result set has been reached
 697       * 
 698       * @param resource $result result identifier
 699       * @return mixed TRUE or FALSE on sucess, a MDB error on failure
 700       * @access public 
 701       */
 702      function endOfResult($result)
 703      {
 704          $result_value = intval($result);
 705          if (!isset($this->current_row[$result_value])) {
 706              return($this->raiseError(MDB_ERROR, NULL, NULL,
 707                  'End of result: attempted to check the end of an unknown result'));
 708          }
 709          if (isset($this->results[$result_value]) && end($this->results[$result_value]) === FALSE) {
 710              return(($this->highest_fetched_row[$result_value]-1) <= $this->current_row[$result_value]);
 711          }
 712          if (isset($this->row_buffer[$result_value])) {
 713              return(!$this->row_buffer[$result_value]);
 714          }
 715          if (isset($this->limits[$result_value])) {
 716              if (MDB::isError($this->_skipLimitOffset($result))
 717                  || ($this->current_row[$result_value]) > $this->limits[$result_value][1]
 718              ) {
 719                  return(TRUE);
 720              }
 721          }
 722          if (@OCIFetchInto($result, $this->row_buffer[$result_value], OCI_RETURN_NULLS)) {
 723              return(FALSE);
 724          }
 725          $this->row_buffer[$result_value] = FALSE;
 726          return(TRUE);
 727      }
 728  
 729      // }}}
 730      // {{{ _retrieveLob()
 731  
 732      /**
 733       * fetch a lob value from a result set
 734       * 
 735       * @param int $lob handle to a lob created by the createLob() function
 736       * @return mixed MDB_OK on success, a MDB error on failure
 737       * @access private 
 738       */
 739      function _retrieveLob($lob)
 740      {
 741          if (!isset($this->lobs[$lob])) {
 742              return($this->raiseError(MDB_ERROR, NULL, NULL,
 743                  'Retrieve LOB: it was not specified a valid lob'));
 744          }
 745          if (!isset($this->lobs[$lob]['Value'])) {
 746              unset($lob_object);
 747              $result = $this->lobs[$lob]['Result'];
 748              $row = $this->lobs[$lob]['Row'];
 749              $field = $this->lobs[$lob]['Field'];
 750              $lob_object = $this->fetch($result, $row, $field);
 751              if (MDB::isError($lob_object)) {
 752                  return $lob_object;
 753              }
 754              if (gettype($lob_object) != 'object') {
 755                  return($this->raiseError(MDB_ERROR, NULL, NULL,
 756                      'Retrieve LOB: attemped to retrieve LOB from non existing or NULL column'));
 757              }
 758              $this->lobs[$lob]['Value'] = $lob_object->load();
 759          }
 760          return(MDB_OK);
 761      }
 762  
 763      // }}}
 764      // {{{ fetch()
 765  
 766      /**
 767       * fetch value from a result set
 768       * 
 769       * @param resource $result result identifier
 770       * @param int $rownum number of the row where the data can be found
 771       * @param int $colnum field number where the data can be found
 772       * @return mixed string on success, a MDB error on failure
 773       * @access public 
 774       */
 775      function fetch($result, $rownum, $colnum)
 776      {
 777          $fetchmode = is_numeric($colnum) ? MDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC;
 778          $row = $this->fetchInto($result, $fetchmode, $rownum);
 779          if (MDB::isError($row)) {
 780              return($row);
 781          }
 782          if (!array_key_exists($colnum, $row)) {
 783              return(NULL);
 784          }
 785          return($row[$colnum]);
 786      }
 787  
 788      // }}}
 789      // {{{ fetchClob()
 790  
 791      /**
 792       * fetch a clob value from a result set
 793       * 
 794       * @param resource $result result identifier
 795       * @param int $row number of the row where the data can be found
 796       * @param int $field field number where the data can be found
 797       * @return mixed content of the specified data cell, a MDB error on failure,
 798       *                a MDB error on failure
 799       * @access public 
 800       */
 801      function fetchClob($result, $row, $field)
 802      {
 803          return($this->fetchLOB($result, $row, $field));
 804      }
 805  
 806      // }}}
 807      // {{{ fetchBlob()
 808      /**
 809       * fetch a blob value from a result set
 810       * 
 811       * @param resource $result result identifier
 812       * @param int $row number of the row where the data can be found
 813       * @param int $field field number where the data can be found
 814       * @return mixed content of the specified data cell, a MDB error on failure
 815       * @access public 
 816       */
 817      function fetchBlob($result, $row, $field)
 818      {
 819          return($this->fetchLOB($result, $row, $field));
 820      }
 821  
 822      // }}}
 823      // {{{ resultIsNull()
 824  
 825      /**
 826       * Determine whether the value of a query result located in given row and
 827       *    field is a NULL.
 828       * 
 829       * @param resource $result result identifier
 830       * @param int $rownum number of the row where the data can be found
 831       * @param int $field field number where the data can be found
 832       * @return mixed TRUE or FALSE on success, a MDB error on failure
 833       * @access public 
 834       */
 835      function resultIsNull($result, $rownum, $field)
 836      {
 837          $value = $this->fetch($result, $rownum, $field);
 838          if (MDB::isError($value)) {
 839              return($value);
 840          }
 841          return(!isset($value));
 842      }
 843  
 844      // }}}
 845      // {{{ convertResult()
 846  
 847      /**
 848       * convert a value to a RDBMS indepdenant MDB type
 849       * 
 850       * @param mixed $value value to be converted
 851       * @param int $type constant that specifies which type to convert to
 852       * @return mixed converted value
 853       * @access public 
 854       */
 855      function convertResult($value, $type)
 856      {
 857          switch ($type) {
 858              case MDB_TYPE_DATE:
 859                  return(substr($value, 0, strlen('YYYY-MM-DD')));
 860              case MDB_TYPE_TIME:
 861                  return(substr($value, strlen('YYYY-MM-DD '), strlen('HH:MI:SS')));
 862              default:
 863                  return($this->_baseConvertResult($value, $type));
 864          }
 865      }
 866  
 867      // }}}
 868      // {{{ numRows()
 869  
 870      /**
 871       * returns the number of rows in a result object
 872       * 
 873       * @param ressource $result a valid result ressouce pointer
 874       * @return mixed MDB_Error or the number of rows
 875       * @access public 
 876       */
 877      function numRows($result)
 878      {
 879          $result_value = intval($result);
 880          if (!isset($this->current_row[$result_value])) {
 881              return($this->raiseError(MDB_ERROR, NULL, NULL,
 882                  'Number of rows: attemped to obtain the number of rows contained in an unknown query result'));
 883          }
 884          if (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
 885              || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE
 886          ) {
 887              if (isset($this->limits[$result_value])) {
 888                  if (MDB::isError($skipfirstrow = $this->_skipLimitOffset($result))) {
 889                       return($skipfirstrow);
 890                  }
 891              }
 892              if (isset($this->row_buffer[$result_value])) {
 893                  ++$this->highest_fetched_row[$result_value];
 894                  $this->results[$result_value][$this->highest_fetched_row[$result_value]]
 895                      = $this->row_buffer[$result_value];
 896                  unset($this->row_buffer[$result_value]);
 897              }
 898              if (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
 899                  || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE
 900              ) {
 901                  while((!isset($this->limits[$result_value])
 902                          || ($this->highest_fetched_row[$result_value]+1) < $this->limits[$result_value][1]
 903                      )
 904                      && @OCIFetchInto($result, $buffer, OCI_RETURN_NULLS)
 905                  ) {
 906                      ++$this->highest_fetched_row[$result_value];
 907                      $this->results[$result_value][$this->highest_fetched_row[$result_value]] = $buffer;
 908                  }
 909                  ++$this->highest_fetched_row[$result_value];
 910                  $this->results[$result_value][$this->highest_fetched_row[$result_value]] = FALSE;
 911              }
 912          }
 913          return(max(0, $this->highest_fetched_row[$result_value]));
 914      }
 915  
 916      // }}}
 917      // {{{ freeResult()
 918  
 919      /**
 920       * Free the internal resources associated with $result.
 921       * 
 922       * @param  $result result identifier
 923       * @return bool TRUE on success, FALSE if $result is invalid
 924       * @access public 
 925       */
 926      function freeResult($result)
 927      {
 928          $result_value = intval($result);
 929          if (!isset($this->current_row[$result_value])) {
 930             return($this->raiseError(MDB_ERROR, NULL, NULL,
 931                 'Free result: attemped to free an unknown query result'));
 932          }
 933          if(isset($this->highest_fetched_row[$result_value])) {
 934              unset($this->highest_fetched_row[$result_value]);
 935          }
 936          if(isset($this->row_buffer[$result_value])) {
 937              unset($this->row_buffer[$result_value]);
 938          }
 939          if(isset($this->limits[$result_value])) {
 940              unset($this->limits[$result_value]);
 941          }
 942          if(isset($this->current_row[$result_value])) {
 943              unset($this->current_row[$result_value]);
 944          }
 945          if(isset($this->results[$result_value])) {
 946              unset($this->results[$result_value]);
 947          }
 948          if(isset($this->columns[$result_value])) {
 949              unset($this->columns[$result_value]);
 950          }
 951          if(isset($this->result_types[$result_value])) {
 952              unset($this->result_types[$result_value]);
 953          }
 954          return(@OCIFreeCursor($result));
 955      }
 956  
 957      // }}}
 958      // {{{ getTypeDeclaration()
 959  
 960      /**
 961       * Obtain DBMS specific native datatype as a string
 962       * 
 963       * @param string $field associative array with the name of the properties
 964       *        of the field being declared as array indexes. Currently, the types
 965       *        of supported field properties are as follows:
 966       * 
 967       * @return string with the correct RDBMS native type
 968       * @access public 
 969       */
 970      function getTypeDeclaration($field)
 971      {
 972          switch ($field['type']) {
 973              case 'integer':
 974                  return('INT');
 975              case 'text':
 976                  return('VARCHAR ('.(isset($field['length'])
 977                      ? $field['length'] : (isset($this->options['DefaultTextFieldLength'])
 978                          ? $this->options['DefaultTextFieldLength'] : 4000)).')');
 979              case 'boolean':
 980                  return('CHAR (1)');
 981              case 'date':
 982              case 'time':
 983              case 'timestamp':
 984                  return('DATE');
 985              case 'float':
 986                  return('NUMBER');
 987              case 'decimal':
 988                  return('NUMBER(*,'.$this->decimal_places.')');
 989          }
 990          return('');
 991      }
 992  
 993      // }}}
 994      // {{{ getIntegerDeclaration()
 995  
 996      /**
 997       * Obtain DBMS specific SQL code portion needed to declare an integer type
 998       * field to be used in statements like CREATE TABLE.
 999       * 
1000       * @param string $name name the field to be declared.
1001       * @param string $field associative array with the name of the properties
1002       *        of the field being declared as array indexes. Id
1003       * ently, the types
1004       *        of supported field properties are as follows:
1005       * 
1006       *        unsigned
1007       *            Boolean flag that indicates whether the field should be
1008       *            declared as unsigned integer if possible.
1009       * 
1010       *        default
1011       *            Integer value to be used as default for this field.
1012       * 
1013       *        notnull
1014       *            Boolean flag that indicates whether this field is constrained
1015       *            to not be set to NULL.
1016       * @return string DBMS specific SQL code portion that should be used to
1017       *        declare the specified field.
1018       * @access public 
1019       */
1020      function getIntegerDeclaration($name, $field)
1021      {
1022          if (isset($field['unsigned']))
1023              $this->warning = "unsigned integer field \"$name\" is being declared as signed integer";
1024          return("$name ".$this->getTypeDeclaration($field)
1025              .(isset($field['default']) ? ' DEFAULT '.$field['default'] : '')
1026              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1027      }
1028  
1029      // }}}
1030      // {{{ getTextDeclaration()
1031  
1032      /**
1033       * Obtain DBMS specific SQL code portion needed to declare an text type
1034       * field to be used in statements like CREATE TABLE.
1035       * 
1036       * @param string $name name the field to be declared.
1037       * @param string $field associative array with the name of the properties
1038       *        of the field being declared as array indexes. Currently, the types
1039       *        of supported field properties are as follows:
1040       * 
1041       *        length
1042       *            Integer value that determines the maximum length of the text
1043       *            field. If this argument is missing the field should be
1044       *            declared to have the longest length allowed by the DBMS.
1045       * 
1046       *        default
1047       *            Text value to be used as default for this field.
1048       * 
1049       *        notnull
1050       *            Boolean flag that indicates whether this field is constrained
1051       *            to not be set to NULL.
1052       * @return string DBMS specific SQL code portion that should be used to
1053       *        declare the specified field.
1054       * @access public 
1055       */
1056      function getTextDeclaration($name, $field)
1057      {
1058          return("$name ".$this->getTypeDeclaration($field)
1059              .(isset($field['default']) ? ' DEFAULT '.$this->getTextValue($field['default']) : '')
1060              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1061      }
1062  
1063      // }}}
1064      // {{{ getClobDeclaration()
1065  
1066      /**
1067       * Obtain DBMS specific SQL code portion needed to declare an character
1068       * large object type field to be used in statements like CREATE TABLE.
1069       * 
1070       * @param string $name name the field to be declared.
1071       * @param string $field associative array with the name of the properties
1072       *        of the field being declared as array indexes. Currently, the types
1073       *        of supported field properties are as follows:
1074       * 
1075       *        length
1076       *            Integer value that determines the maximum length of the large
1077       *            object field. If this argument is missing the field should be
1078       *            declared to have the longest length allowed by the DBMS.
1079       * 
1080       *        notnull
1081       *            Boolean flag that indicates whether this field is constrained
1082       *            to not be set to NULL.
1083       * @return string DBMS specific SQL code portion that should be used to
1084       *        declare the specified field.
1085       * @access public 
1086       */
1087      function getClobDeclaration($name, $field)
1088      {
1089          return("$name CLOB".(isset($field['notnull']) ? ' NOT NULL' : ''));
1090      }
1091  
1092      // }}}
1093      // {{{ getBlobDeclaration()
1094  
1095      /**
1096       * Obtain DBMS specific SQL code portion needed to declare an binary large
1097       * object type field to be used in statements like CREATE TABLE.
1098       * 
1099       * @param string $name name the field to be declared.
1100       * @param string $field associative array with the name of the properties
1101       *        of the field being declared as array indexes. Currently, the types
1102       *        of supported field properties are as follows:
1103       * 
1104       *        length
1105       *            Integer value that determines the maximum length of the large
1106       *            object field. If this argument is missing the field should be
1107       *            declared to have the longest length allowed by the DBMS.
1108       * 
1109       *        notnull
1110       *            Boolean flag that indicates whether this field is constrained
1111       *            to not be set to NULL.
1112       * @return string DBMS specific SQL code portion that should be used to
1113       *        declare the specified field.
1114       * @access public 
1115       */
1116      function getBlobDeclaration($name, $field)
1117      {
1118          return("$name BLOB".(isset($field['notnull']) ? ' NOT NULL' : ''));
1119      }
1120  
1121      // }}}
1122      // {{{ getBooleanDeclaration()
1123  
1124      /**
1125       * Obtain DBMS specific SQL code portion needed to declare a boolean type
1126       * field to be used in statements like CREATE TABLE.
1127       * 
1128       * @param string $name name the field to be declared.
1129       * @param string $field associative array with the name of the properties
1130       *        of the field being declared as array indexes. Currently, the types
1131       *        of supported field properties are as follows:
1132       * 
1133       *        default
1134       *            Boolean value to be used as default for this field.
1135       * 
1136       *        notnullL
1137       *            Boolean flag that indicates whether this field is constrained
1138       *            to not be set to NULL.
1139       * @return string DBMS specific SQL code portion that should be used to
1140       *        declare the specified field.
1141       * @access public 
1142       */
1143      function getBooleanDeclaration($name, $field)
1144      {
1145          return("$name ".$this->getTypeDeclaration($field)
1146              .(isset($field['default']) ? ' DEFAULT '
1147              .$this->getBooleanValue($field['default']) : '')
1148              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1149      }
1150  
1151      // }}}
1152      // {{{ getDateDeclaration()
1153  
1154      /**
1155       * Obtain DBMS specific SQL code portion needed to declare a date type
1156       * field to be used in statements like CREATE TABLE.
1157       * 
1158       * @param string $name name the field to be declared.
1159       * @param string $field associative array with the name of the properties
1160       *        of the field being declared as array indexes. Currently, the types
1161       *        of supported field properties are as follows:
1162       * 
1163       *        default
1164       *            Date value to be used as default for this field.
1165       * 
1166       *        notnull
1167       *            Boolean flag that indicates whether this field is constrained
1168       *            to not be set to NULL.
1169       * @return string DBMS specific SQL code portion that should be used to
1170       *        declare the specified field.
1171       * @access public 
1172       */
1173      function getDateDeclaration($name, $field)
1174      {
1175          return("$name ".$this->getTypeDeclaration($field)
1176              .(isset($field['default']) ? ' DEFAULT '
1177              .$this->getDateValue($field['default']) : '')
1178              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1179      }
1180  
1181      // }}}
1182      // {{{ getTimestampDeclaration()
1183  
1184      /**
1185       * Obtain DBMS specific SQL code portion needed to declare a timestamp
1186       * field to be used in statements like CREATE TABLE.
1187       * 
1188       * @param string $name name the field to be declared.
1189       * @param string $field associative array with the name of the properties
1190       *        of the field being declared as array indexes. Currently, the types
1191       *        of supported field properties are as follows:
1192       * 
1193       *        default
1194       *            Timestamp value to be used as default for this field.
1195       * 
1196       *        notnull
1197       *            Boolean flag that indicates whether this field is constrained
1198       *            to not be set to NULL.
1199       * @return string DBMS specific SQL code portion that should be used to
1200       *        declare the specified field.
1201       * @access public 
1202       */
1203      function getTimestampDeclaration($name, $field)
1204      {
1205          return("$name ".$this->getTypeDeclaration($field)
1206              .(isset($field['default']) ? ' DEFAULT '
1207              .$this->getTimestampValue($field['default']) : '')
1208              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1209      }
1210  
1211      // }}}
1212      // {{{ getTimeDeclaration()
1213  
1214      /**
1215       * Obtain DBMS specific SQL code portion needed to declare a time
1216       * field to be used in statements like CREATE TABLE.
1217       * 
1218       * @param string $name name the field to be declared.
1219       * @param string $field associative array with the name of the properties
1220       *        of the field being declared as array indexes. Currently, the types
1221       *        of supported field properties are as follows:
1222       * 
1223       *        default
1224       *            Time value to be used as default for this field.
1225       * 
1226       *        notnull
1227       *            Boolean flag that indicates whether this field is constrained
1228       *            to not be set to NULL.
1229       * @return string DBMS specific SQL code portion that should be used to
1230       *        declare the specified field.
1231       * @access public 
1232       */
1233      function getTimeDeclaration($name, $field)
1234      {
1235          return("$name ".$this->getTypeDeclaration($field)
1236              .(isset($field['default']) ? ' DEFAULT '
1237              .$this->getTimeValue($field['default']) : '')
1238              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1239      }
1240  
1241      // }}}
1242      // {{{ getFloatDeclaration()
1243  
1244      /**
1245       * Obtain DBMS specific SQL code portion needed to declare a float type
1246       * field to be used in statements like CREATE TABLE.
1247       * 
1248       * @param string $name name the field to be declared.
1249       * @param string $field associative array with the name of the properties
1250       *        of the field being declared as array indexes. Currently, the types
1251       *        of supported field properties are as follows:
1252       * 
1253       *        default
1254       *            Float value to be used as default for this field.
1255       * 
1256       *        notnull
1257       *            Boolean flag that indicates whether this field is constrained
1258       *            to not be set to NULL.
1259       * @return string DBMS specific SQL code portion that should be used to
1260       *        declare the specified field.
1261       * @access public 
1262       */
1263      function getFloatDeclaration($name, $field)
1264      {
1265          return("$name ".$this->getTypeDeclaration($field)
1266              .(isset($field['default']) ? ' DEFAULT '
1267              .$this->getFloatValue($field['default']) : '')
1268              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1269      }
1270  
1271      // }}}
1272      // {{{ getDecimalDeclaration()
1273  
1274      /**
1275       * Obtain DBMS specific SQL code portion needed to declare a decimal type
1276       * field to be used in statements like CREATE TABLE.
1277       * 
1278       * @param string $name name the field to be declared.
1279       * @param string $field associative array with the name of the properties
1280       *        of the field being declared as array indexes. Currently, the types
1281       *        of supported field properties are as follows:
1282       * 
1283       *        default
1284       *            Decimal value to be used as default for this field.
1285       * 
1286       *        notnull
1287       *            Boolean flag that indicates whether this field is constrained
1288       *            to not be set to NULL.
1289       * @return string DBMS specific SQL code portion that should be used to
1290       *        declare the specified field.
1291       * @access public 
1292       */
1293      function getDecimalDeclaration($name, $field)
1294      {
1295          return("$name ".$this->getTypeDeclaration($field)
1296              .(isset($field['default']) ? ' DEFAULT '
1297              .$this->getDecimalValue($field['default']) : '')
1298              .(isset($field['notnull']) ? ' NOT NULL' : ''));
1299      }
1300  
1301      // }}}
1302      // {{{ getClobValue()
1303  
1304      /**
1305       * Convert a text value into a DBMS specific format that is suitable to
1306       * compose query statements.
1307       * 
1308       * @param resource $prepared_query query handle from prepare()
1309       * @param  $parameter 
1310       * @param  $clob 
1311       * @return string text string that represents the given argument value in
1312       *        a DBMS specific format.
1313       * @access public 
1314       */
1315      function getClobValue($prepared_query, $parameter, $clob)
1316      {
1317          return('EMPTY_CLOB()');
1318      }
1319  
1320      // }}}
1321      // {{{ freeClobValue()
1322  
1323      /**
1324       * free a character large object
1325       * 
1326       * @param resource $prepared_query query handle from prepare()
1327       * @param string $blob 
1328       * @param string $value 
1329       * @access public 
1330       */
1331      function freeClobValue($prepared_query, $clob, &$value)
1332      {
1333          unset($value);
1334      }
1335  
1336      // }}}
1337      // {{{ getBlobValue()
1338  
1339      /**
1340       * Convert a text value into a DBMS specific format that is suitable to
1341       * compose query statements.
1342       * 
1343       * @param resource $prepared_query query handle from prepare()
1344       * @param  $parameter 
1345       * @param  $blob 
1346       * @return string text string that represents the given argument value in
1347       *        a DBMS specific format.
1348       * @access public 
1349       */
1350      function getBlobValue($prepared_query, $parameter, $blob)
1351      {
1352          return('EMPTY_BLOB()');
1353      }
1354  
1355      // }}}
1356      // {{{ freeBlobValue()
1357  
1358      /**
1359       * free a binary large object
1360       * 
1361       * @param resource $prepared_query query handle from prepare()
1362       * @param string $blob 
1363       * @param string $value 
1364       * @access public 
1365       */
1366      function freeBlobValue($prepared_query, $blob, &$value)
1367      {
1368          unset($value);
1369      }
1370  
1371      // }}}
1372      // {{{ getDateValue()
1373  
1374      /**
1375       * Convert a text value into a DBMS specific format that is suitable to
1376       * compose query statements.
1377       * 
1378       * @param string $value text string value that is intended to be converted.
1379       * @return string text string that represents the given argument value in
1380       *        a DBMS specific format.
1381       * @access public 
1382       */
1383      function getDateValue($value)
1384      {
1385          return(($value === NULL) ? 'NULL' : "TO_DATE('$value','YYYY-MM-DD')");
1386      }
1387  
1388      // }}}
1389      // {{{ getTimestampValue()
1390  
1391      /**
1392       * Convert a text value into a DBMS specific format that is suitable to
1393       * compose query statements.
1394       * 
1395       * @param string $value text string value that is intended to be converted.
1396       * @return string text string that represents the given argument value in
1397       *        a DBMS specific format.
1398       * @access public 
1399       */
1400      function getTimestampValue($value)
1401      {
1402          return(($value === NULL) ? 'NULL' : "TO_DATE('$value','YYYY-MM-DD HH24:MI:SS')");
1403      }
1404  
1405      // }}}
1406      // {{{ getTimeValue()
1407  
1408      /**
1409       * Convert a text value into a DBMS specific format that is suitable to
1410       *        compose query statements.
1411       * 
1412       * @param string $value text string value that is intended to be converted.
1413       * @return string text string that represents the given argument value in
1414       *        a DBMS specific format.
1415       * @access public 
1416       */
1417      function getTimeValue($value)
1418      {
1419          return(($value === NULL) ? 'NULL' : "TO_DATE('0001-01-01 $value','YYYY-MM-DD HH24:MI:SS')");
1420      }
1421  
1422      // }}}
1423      // {{{ getFloatValue()
1424  
1425      /**
1426       * Convert a text value into a DBMS specific format that is suitable to
1427       * compose query statements.
1428       * 
1429       * @param string $value text string value that is intended to be converted.
1430       * @return string text string that represents the given argument value in
1431       *        a DBMS specific format.
1432       * @access public 
1433       */
1434      function getFloatValue($value)
1435      {
1436          return(($value === NULL) ? 'NULL' : (float)$value);
1437      }
1438  
1439      // }}}
1440      // {{{ getDecimalValue()
1441  
1442      /**
1443       * Convert a text value into a DBMS specific format that is suitable to
1444       * compose query statements.
1445       * 
1446       * @param string $value text string value that is intended to be converted.
1447       * @return string text string that represents the given argument value in
1448       *        a DBMS specific format.
1449       * @access public 
1450       */
1451      function getDecimalValue($value)
1452      {
1453          return(($value === NULL) ? 'NULL' : $value);
1454      }
1455  
1456      // }}}
1457      // {{{ nextId()
1458  
1459      /**
1460       * returns the next free id of a sequence
1461       * 
1462       * @param string $seq_name name of the sequence
1463       * @param boolean $ondemand when TRUE the seqence is
1464       *                           automatic created, if it
1465       *                           not exists
1466       * @return mixed MDB_Error or id
1467       * @access public 
1468       */
1469      function nextId($seq_name, $ondemand = TRUE)
1470      {
1471          if (MDB::isError($connect = $this->connect())) {
1472              return($connect);
1473          }
1474          $sequence_name = $this->getSequenceName($seq_name);
1475          $this->expectError(MDB_ERROR_NOSUCHTABLE);
1476          $result = $this->_doQuery("SELECT $sequence_name.nextval FROM DUAL");
1477          $this->popExpect();
1478          if ($ondemand && MDB::isError($result)
1479              && $result->getCode() == MDB_ERROR_NOSUCHTABLE)
1480          {
1481              $result = $this->createSequence($seq_name, 1);
1482              if (MDB::isError($result)) {
1483                  return $result;
1484              }
1485              return $this->nextId($seq_name, false);
1486          }
1487          return($this->fetchOne($result));
1488      }
1489  
1490      // }}}
1491      // {{{ currId()
1492  
1493      /**
1494       * returns the current id of a sequence
1495       *
1496       * @param string $seq_name name of the sequence
1497       * @return mixed MDB_Error or id
1498       * @access public
1499       */
1500      function currId($seq_name)
1501      {
1502          $sequence_name = $this->getSequenceName($seq_name);
1503          $result = $this->_doQuery("SELECT $sequence_name.currval FROM DUAL");
1504          if (MDB::isError($result)) {
1505              return($this->raiseError(MDB_ERROR, NULL, NULL,
1506                  'currId: unable to select from ' . $seq_name) );
1507          }
1508          $result = $this->fetchOne($result);
1509          if (!is_numeric($result)) {
1510              return($this->raiseError(MDB_ERROR, NULL, NULL,
1511                  'currId: could not find value in sequence table'));
1512          }
1513          return($result);
1514      }
1515  
1516      // }}}
1517      // {{{ fetchInto()
1518  
1519      /**
1520       * Fetch a row and return data in an array.
1521       *
1522       * @param resource $result result identifier
1523       * @param int $fetchmode how the array data should be indexed
1524       * @param int $rownum the row number to fetch
1525       * @return mixed data array or NULL on success, a MDB error on failure
1526       * @access public
1527       */
1528      function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
1529      {
1530          $result_value = intval($result);
1531          if (!isset($this->current_row[$result_value])) {
1532              return($this->raiseError(MDB_ERROR, NULL, NULL,
1533                  'fetchInto: attemped to fetch on an unknown query result'));
1534          }
1535          if ($fetchmode == MDB_FETCHMODE_DEFAULT) {
1536              $fetchmode = $this->fetchmode;
1537          }
1538          if (is_null($rownum)) {
1539              $rownum = $this->current_row[$result_value] + 1;
1540          }
1541          if (!isset($this->results[$result_value][$rownum])
1542              && (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
1543                  || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE)
1544          ) {
1545              if (isset($this->limits[$result_value])) {
1546                  // upper limit
1547                  if ($rownum > $this->limits[$result_value][1]) {
1548                      // are all previous rows fetched so that we can set the end
1549                      // of the result set and not have any "holes" in between?
1550                      if ($rownum == 0
1551                          || (isset($this->results[$result_value])
1552                              && count($this->results[$result_value]) == $rownum
1553                          )
1554                      ) {
1555                          $this->highest_fetched_row[$result_value] = $rownum;
1556                          $this->current_row[$result_value] = $rownum;
1557                          $this->results[$result_value][$rownum] = FALSE;
1558                      }
1559                      if($this->options['autofree']) {
1560                          $this->freeResult($result);
1561                      }
1562                      return(NULL);
1563                  }
1564                  // offset skipping
1565                  if (MDB::isError($this->_skipLimitOffset($result))) {
1566                      $this->current_row[$result_value] = 0;
1567                      $this->results[$result_value] = array(FALSE);
1568                      if($this->options['autofree']) {
1569                          $this->freeResult($result);
1570                      }
1571                      return(NULL);
1572                  }
1573              }
1574              if (isset($this->row_buffer[$result_value])) {
1575                  ++$this->current_row[$result_value];
1576                  $this->results[$result_value][$this->current_row[$result_value]] =
1577                      $this->row_buffer[$result_value];
1578                  unset($this->row_buffer[$result_value]);
1579              }
1580              if (!isset($this->results[$result_value][$rownum])
1581                  && (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
1582                      || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE)
1583              ) {
1584                  while($this->current_row[$result_value] < $rownum
1585                      && @OCIFetchInto($result, $buffer, OCI_RETURN_NULLS)
1586                  ) {
1587                      ++$this->current_row[$result_value];
1588                      $this->results[$result_value][$this->current_row[$result_value]] = $buffer;
1589                  }
1590                  // end of result set reached
1591                  if ($this->current_row[$result_value] < $rownum) {
1592                      ++$this->current_row[$result_value];
1593                      $this->results[$result_value][$this->current_row[$result_value]] = FALSE;
1594                  }
1595              }
1596              $this->highest_fetched_row[$result_value] =
1597                  max($this->highest_fetched_row[$result_value],
1598                      $this->current_row[$result_value]);
1599          } else {
1600              ++$this->current_row[$result_value];
1601          }
1602          if (isset($this->results[$result_value][$rownum])
1603              && $this->results[$result_value][$rownum]
1604          ) {
1605              $row = $this->results[$result_value][$rownum];
1606          } else {
1607              if($this->options['autofree']) {
1608                  $this->freeResult($result);
1609              }
1610              return(NULL);
1611          }
1612          if ($fetchmode & MDB_FETCHMODE_ASSOC) {
1613              $column_names = $this->getColumnNames($result);
1614              foreach($column_names as $name => $i) {
1615                  $column_names[$name] = $row[$i];
1616              }
1617              $row = $column_names;
1618          }
1619          if (isset($this->result_types[$result_value])) {
1620              $row = $this->convertResultRow($result, $row);
1621          }
1622          return($row);
1623      }
1624  
1625      // }}}
1626      // {{{ nextResult()
1627  
1628      /**
1629       * Move the internal oracle result pointer to the next available result
1630       * Currently not supported
1631       * 
1632       * @param $result a oracle valid result resource
1633       * @return TRUE if a result is available otherwise return FALSE
1634       * @access public 
1635       */
1636      function nextResult($result)
1637      {
1638          return(FALSE);
1639      }
1640  
1641      // }}}
1642      // {{{ tableInfo()
1643  
1644      /**
1645       * returns meta data about the result set
1646       * 
1647       * @param resource $result result identifier
1648       * @param mixed $mode depends on implementation
1649       * @return array an nested array, or a MDB error
1650       * @access public 
1651       */
1652      function tableInfo($result, $mode = NULL)
1653      {
1654          $count = 0;
1655          $res = array();
1656          /**
1657           * depending on $mode, metadata returns the following values:
1658           * 
1659           * - mode is FALSE (default):
1660           * $res[]:
1661           *    [0]['table']       table name
1662           *    [0]['name']        field name
1663           *    [0]['type']        field type
1664           *    [0]['len']         field length
1665           *    [0]['nullable']    field can be NULL (boolean)
1666           *    [0]['format']      field precision if NUMBER
1667           *    [0]['default']     field default value
1668           * 
1669           * - mode is MDB_TABLEINFO_ORDER
1670           * $res[]:
1671           *    ['num_fields']     number of fields
1672           *    [0]['table']       table name
1673           *    [0]['name']        field name
1674           *    [0]['type']        field type
1675           *    [0]['len']         field length
1676           *    [0]['nullable']    field can be NULL (boolean)
1677           *    [0]['format']      field precision if NUMBER
1678           *    [0]['default']     field default value
1679           *    ['order'][field name] index of field named 'field name'
1680           *    The last one is used, if you have a field name, but no index.
1681           *    Test:  if (isset($result['order']['myfield'])) { ...
1682           * 
1683           * - mode is MDB_TABLEINFO_ORDERTABLE
1684           *     the same as above. but additionally
1685           *    ['ordertable'][table name][field name] index of field
1686           *       named 'field name'
1687           * 
1688           *       this is, because if you have fields from different
1689           *       tables with the same field name * they override each
1690           *       other with MDB_TABLEINFO_ORDER
1691           * 
1692           *       you can combine DB_TABLEINFO_ORDER and
1693           *       MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER |
1694           *       MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL
1695           */ 
1696          // if $result is a string, we collect info for a table only
1697          if (is_string($result)) {
1698              if (MDB::isError($connect = $this->connect())) {
1699                  return($connect);
1700              }
1701              $result = strtoupper($result);
1702              $q_fields = "select column_name, data_type, data_length, data_precision,
1703                       nullable, data_default from user_tab_columns
1704                       where table_name='$result' order by column_id";
1705              if (!$stmt = @OCIParse($this->connection, $q_fields)) {
1706                  return($this->oci8RaiseError());
1707              }
1708              if (!@OCIExecute($stmt, OCI_DEFAULT)) {
1709                  return($this->oci8RaiseError($stmt));
1710              } while (@OCIFetch($stmt)) {
1711                  $res[$count]['table'] = strtolower($result);
1712                  $res[$count]['name'] = strtolower(@OCIResult($stmt, 1));
1713                  $res[$count]['type'] = strtolower(@OCIResult($stmt, 2));
1714                  $res[$count]['len'] = @OCIResult($stmt, 3);
1715                  $res[$count]['format'] = @OCIResult($stmt, 4);
1716                  $res[$count]['nullable'] = (@OCIResult($stmt, 5) == 'Y') ? TRUE : FALSE;
1717                  $res[$count]['default'] = @OCIResult($stmt, 6);
1718                  if ($mode & MDB_TABLEINFO_ORDER) {
1719                      $res['order'][$res[$count]['name']] = $count;
1720                  }
1721                  if ($mode & MDB_TABLEINFO_ORDERTABLE) {
1722                      $res['ordertable'][$res[$count]['table']][$res[$count]['name']] = $count;
1723                  }
1724                  $count++;
1725              }
1726              if ($mode) {
1727                  $res['num_fields'] = $count;
1728              }
1729              @OCIFreeStatement($stmt);
1730          } else { // else we want information about a resultset
1731              #if ($result === $this->last_stmt) {
1732                  $count = @OCINumCols($result);
1733                  for ($i = 0; $i < $count; $i++) {
1734                      $res[$i]['name'] = strtolower(@OCIColumnName($result, $i + 1));
1735                      $res[$i]['type'] = strtolower(@OCIColumnType($result, $i + 1));
1736                      $res[$i]['len'] = @OCIColumnSize($result, $i + 1);
1737  
1738                      $q_fields = "SELECT table_name, data_precision, nullable, data_default from user_tab_columns WHERE column_name='".$res[$i]['name']."'";
1739                      if (!$stmt = @OCIParse($this->connection, $q_fields)) {
1740                          return($this->oci8RaiseError());
1741                      }
1742                      if (!@OCIExecute($stmt, OCI_DEFAULT)) {
1743                          return($this->oci8RaiseError($stmt));
1744                      }
1745                      @OCIFetch($stmt);
1746                      $res[$i]['table'] = strtolower(@OCIResult($stmt, 1));
1747                      $res[$i]['format'] = @OCIResult($stmt, 2);
1748                      $res[$i]['nullable'] = (@OCIResult($stmt, 3) == 'Y') ? TRUE : FALSE;
1749                      $res[$i]['default'] = @OCIResult($stmt, 4);
1750                      @OCIFreeStatement($stmt);
1751  
1752                      if ($mode & MDB_TABLEINFO_ORDER) {
1753                          $res['order'][$res[$i]['name']] = $i;
1754                      }
1755                      if ($mode & MDB_TABLEINFO_ORDERTABLE) {
1756                          $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1757                      }
1758                  }
1759                  if ($mode) {
1760                      $res['num_fields'] = $count;
1761                  }
1762              #} else {
1763              #    return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
1764              #}
1765          }
1766          return($res);
1767      }
1768  }
1769  ?>


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