[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/phpbb/db/driver/ -> oracle.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\db\driver;
  15  
  16  /**
  17  * Oracle Database Abstraction Layer
  18  */
  19  class oracle extends \phpbb\db\driver\driver
  20  {
  21      var $last_query_text = '';
  22      var $connect_error = '';
  23  
  24      /**
  25      * {@inheritDoc}
  26      */
  27  	function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
  28      {
  29          $this->persistency = $persistency;
  30          $this->user = $sqluser;
  31          $this->server = $sqlserver . (($port) ? ':' . $port : '');
  32          $this->dbname = $database;
  33  
  34          $connect = $database;
  35  
  36          // support for "easy connect naming"
  37          if ($sqlserver !== '' && $sqlserver !== '/')
  38          {
  39              if (substr($sqlserver, -1, 1) == '/')
  40              {
  41                  $sqlserver == substr($sqlserver, 0, -1);
  42              }
  43              $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database;
  44          }
  45  
  46          if ($new_link)
  47          {
  48              if (!function_exists('oci_new_connect'))
  49              {
  50                  $this->connect_error = 'oci_new_connect function does not exist, is oci extension installed?';
  51                  return $this->sql_error('');
  52              }
  53              $this->db_connect_id = @oci_new_connect($this->user, $sqlpassword, $connect, 'UTF8');
  54          }
  55          else if ($this->persistency)
  56          {
  57              if (!function_exists('oci_pconnect'))
  58              {
  59                  $this->connect_error = 'oci_pconnect function does not exist, is oci extension installed?';
  60                  return $this->sql_error('');
  61              }
  62              $this->db_connect_id = @oci_pconnect($this->user, $sqlpassword, $connect, 'UTF8');
  63          }
  64          else
  65          {
  66              if (!function_exists('oci_connect'))
  67              {
  68                  $this->connect_error = 'oci_connect function does not exist, is oci extension installed?';
  69                  return $this->sql_error('');
  70              }
  71              $this->db_connect_id = @oci_connect($this->user, $sqlpassword, $connect, 'UTF8');
  72          }
  73  
  74          return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
  75      }
  76  
  77      /**
  78      * {@inheritDoc}
  79      */
  80  	function sql_server_info($raw = false, $use_cache = true)
  81      {
  82          /**
  83          * force $use_cache false.  I didn't research why the caching code below is commented out
  84          * but I assume its because the Oracle extension provides a direct method to access it
  85          * without a query.
  86          */
  87  /*
  88          global $cache;
  89  
  90          if (empty($cache) || ($this->sql_server_version = $cache->get('oracle_version')) === false)
  91          {
  92              $result = @ociparse($this->db_connect_id, 'SELECT * FROM v$version WHERE banner LIKE \'Oracle%\'');
  93              @ociexecute($result, OCI_DEFAULT);
  94              @ocicommit($this->db_connect_id);
  95  
  96              $row = array();
  97              @ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS);
  98              @ocifreestatement($result);
  99              $this->sql_server_version = trim($row['BANNER']);
 100  
 101              $cache->put('oracle_version', $this->sql_server_version);
 102          }
 103  */
 104          $this->sql_server_version = @oci_server_version($this->db_connect_id);
 105  
 106          return $this->sql_server_version;
 107      }
 108  
 109      /**
 110      * SQL Transaction
 111      * @access private
 112      */
 113  	function _sql_transaction($status = 'begin')
 114      {
 115          switch ($status)
 116          {
 117              case 'begin':
 118                  return true;
 119              break;
 120  
 121              case 'commit':
 122                  return @oci_commit($this->db_connect_id);
 123              break;
 124  
 125              case 'rollback':
 126                  return @oci_rollback($this->db_connect_id);
 127              break;
 128          }
 129  
 130          return true;
 131      }
 132  
 133      /**
 134      * Oracle specific code to handle the fact that it does not compare columns properly
 135      * @access private
 136      */
 137  	function _rewrite_col_compare($args)
 138      {
 139          if (count($args) == 4)
 140          {
 141              if ($args[2] == '=')
 142              {
 143                  return '(' . $args[0] . ' OR (' . $args[1] . ' is NULL AND ' . $args[3] . ' is NULL))';
 144              }
 145              else if ($args[2] == '<>')
 146              {
 147                  // really just a fancy way of saying foo <> bar or (foo is NULL XOR bar is NULL) but SQL has no XOR :P
 148                  return '(' . $args[0] . ' OR ((' . $args[1] . ' is NULL AND ' . $args[3] . ' is NOT NULL) OR (' . $args[1] . ' is NOT NULL AND ' . $args[3] . ' is NULL)))';
 149              }
 150          }
 151          else
 152          {
 153              return $this->_rewrite_where($args[0]);
 154          }
 155      }
 156  
 157      /**
 158      * Oracle specific code to handle it's lack of sanity
 159      * @access private
 160      */
 161  	function _rewrite_where($where_clause)
 162      {
 163          preg_match_all('/\s*(AND|OR)?\s*([\w_.()]++)\s*(?:(=|<[=>]?|>=?|LIKE)\s*((?>\'(?>[^\']++|\'\')*+\'|[\d-.()]+))|((NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))/', $where_clause, $result, PREG_SET_ORDER);
 164          $out = '';
 165          foreach ($result as $val)
 166          {
 167              if (!isset($val[5]))
 168              {
 169                  if ($val[4] !== "''")
 170                  {
 171                      $out .= $val[0];
 172                  }
 173                  else
 174                  {
 175                      $out .= ' ' . $val[1] . ' ' . $val[2];
 176                      if ($val[3] == '=')
 177                      {
 178                          $out .= ' is NULL';
 179                      }
 180                      else if ($val[3] == '<>')
 181                      {
 182                          $out .= ' is NOT NULL';
 183                      }
 184                  }
 185              }
 186              else
 187              {
 188                  $in_clause = array();
 189                  $sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1);
 190                  $extra = false;
 191                  preg_match_all('/\'(?>[^\']++|\'\')*+\'|[\d-.]++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER);
 192                  $i = 0;
 193                  foreach ($sub_vals[0] as $sub_val)
 194                  {
 195                      // two things:
 196                      // 1) This determines if an empty string was in the IN clausing, making us turn it into a NULL comparison
 197                      // 2) This fixes the 1000 list limit that Oracle has (ORA-01795)
 198                      if ($sub_val !== "''")
 199                      {
 200                          $in_clause[(int) $i++/1000][] = $sub_val;
 201                      }
 202                      else
 203                      {
 204                          $extra = true;
 205                      }
 206                  }
 207                  if (!$extra && $i < 1000)
 208                  {
 209                      $out .= $val[0];
 210                  }
 211                  else
 212                  {
 213                      $out .= ' ' . $val[1] . '(';
 214                      $in_array = array();
 215  
 216                      // constuct each IN() clause
 217                      foreach ($in_clause as $in_values)
 218                      {
 219                          $in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')';
 220                      }
 221  
 222                      // Join the IN() clauses against a few ORs (IN is just a nicer OR anyway)
 223                      $out .= implode(' OR ', $in_array);
 224  
 225                      // handle the empty string case
 226                      if ($extra)
 227                      {
 228                          $out .= ' OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL';
 229                      }
 230                      $out .= ')';
 231  
 232                      unset($in_array, $in_clause);
 233                  }
 234              }
 235          }
 236  
 237          return $out;
 238      }
 239  
 240      /**
 241      * {@inheritDoc}
 242      */
 243  	function sql_query($query = '', $cache_ttl = 0)
 244      {
 245          if ($query != '')
 246          {
 247              global $cache;
 248  
 249              if ($this->debug_sql_explain)
 250              {
 251                  $this->sql_report('start', $query);
 252              }
 253              else if ($this->debug_load_time)
 254              {
 255                  $this->curtime = microtime(true);
 256              }
 257  
 258              $this->last_query_text = $query;
 259              $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
 260              $this->sql_add_num_queries($this->query_result);
 261  
 262              if ($this->query_result === false)
 263              {
 264                  $in_transaction = false;
 265                  if (!$this->transaction)
 266                  {
 267                      $this->sql_transaction('begin');
 268                  }
 269                  else
 270                  {
 271                      $in_transaction = true;
 272                  }
 273  
 274                  $array = array();
 275  
 276                  // We overcome Oracle's 4000 char limit by binding vars
 277                  if (strlen($query) > 4000)
 278                  {
 279                      if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/sU', $query, $regs))
 280                      {
 281                          if (strlen($regs[3]) > 4000)
 282                          {
 283                              $cols = explode(', ', $regs[2]);
 284  
 285                              preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER);
 286  
 287  /*                        The code inside this comment block breaks clob handling, but does allow the
 288                          database restore script to work.  If you want to allow no posts longer than 4KB
 289                          and/or need the db restore script, uncomment this.
 290  
 291  
 292                              if (count($cols) !== count($vals))
 293                              {
 294                                  // Try to replace some common data we know is from our restore script or from other sources
 295                                  $regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]);
 296                                  $_vals = explode(', ', $regs[3]);
 297  
 298                                  $vals = array();
 299                                  $is_in_val = false;
 300                                  $i = 0;
 301                                  $string = '';
 302  
 303                                  foreach ($_vals as $value)
 304                                  {
 305                                      if (strpos($value, "'") === false && !$is_in_val)
 306                                      {
 307                                          $vals[$i++] = $value;
 308                                          continue;
 309                                      }
 310  
 311                                      if (substr($value, -1) === "'")
 312                                      {
 313                                          $vals[$i] = $string . (($is_in_val) ? ', ' : '') . $value;
 314                                          $string = '';
 315                                          $is_in_val = false;
 316  
 317                                          if ($vals[$i][0] !== "'")
 318                                          {
 319                                              $vals[$i] = "''" . $vals[$i];
 320                                          }
 321                                          $i++;
 322                                          continue;
 323                                      }
 324                                      else
 325                                      {
 326                                          $string .= (($is_in_val) ? ', ' : '') . $value;
 327                                          $is_in_val = true;
 328                                      }
 329                                  }
 330  
 331                                  if ($string)
 332                                  {
 333                                      // New value if cols != value
 334                                      $vals[(count($cols) !== count($vals)) ? $i : $i - 1] .= $string;
 335                                  }
 336  
 337                                  $vals = array(0 => $vals);
 338                              }
 339  */
 340  
 341                              $inserts = $vals[0];
 342                              unset($vals);
 343  
 344                              foreach ($inserts as $key => $value)
 345                              {
 346                                  if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2
 347                                  {
 348                                      $inserts[$key] = ':' . strtoupper($cols[$key]);
 349                                      $array[$inserts[$key]] = str_replace("''", "'", substr($value, 1, -1));
 350                                  }
 351                              }
 352  
 353                              $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')';
 354                          }
 355                      }
 356                      else if (preg_match_all('/^(UPDATE [\\w_]++\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER))
 357                      {
 358                          if (strlen($data[0][2]) > 4000)
 359                          {
 360                              $update = $data[0][1];
 361                              $where = $data[0][3];
 362                              preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[0][2], $temp, PREG_SET_ORDER);
 363                              unset($data);
 364  
 365                              $cols = array();
 366                              foreach ($temp as $value)
 367                              {
 368                                  if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) // check to see if this thing is greater than the max + 'x2
 369                                  {
 370                                      $cols[] = $value[1] . '=:' . strtoupper($value[1]);
 371                                      $array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1));
 372                                  }
 373                                  else
 374                                  {
 375                                      $cols[] = $value[1] . '=' . $value[2];
 376                                  }
 377                              }
 378  
 379                              $query = $update . implode(', ', $cols) . ' ' . $where;
 380                              unset($cols);
 381                          }
 382                      }
 383                  }
 384  
 385                  switch (substr($query, 0, 6))
 386                  {
 387                      case 'DELETE':
 388                          if (preg_match('/^(DELETE FROM [\w_]++ WHERE)((?:\s*(?:AND|OR)?\s*[\w_]+\s*(?:(?:=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]+)|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))*+)$/', $query, $regs))
 389                          {
 390                              $query = $regs[1] . $this->_rewrite_where($regs[2]);
 391                              unset($regs);
 392                          }
 393                      break;
 394  
 395                      case 'UPDATE':
 396                          if (preg_match('/^(UPDATE [\\w_]++\\s+SET [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++)(?:, [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++))*+\\s+WHERE)(.*)$/s',  $query, $regs))
 397                          {
 398                              $query = $regs[1] . $this->_rewrite_where($regs[2]);
 399                              unset($regs);
 400                          }
 401                      break;
 402  
 403                      case 'SELECT':
 404                          $query = preg_replace_callback('/([\w_.]++)\s*(?:(=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]++|([\w_.]++))|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]++,? ?)*+\))/', array($this, '_rewrite_col_compare'), $query);
 405                      break;
 406                  }
 407  
 408                  $this->query_result = @oci_parse($this->db_connect_id, $query);
 409  
 410                  foreach ($array as $key => $value)
 411                  {
 412                      @oci_bind_by_name($this->query_result, $key, $array[$key], -1);
 413                  }
 414  
 415                  $success = @oci_execute($this->query_result, OCI_DEFAULT);
 416  
 417                  if (!$success)
 418                  {
 419                      $this->sql_error($query);
 420                      $this->query_result = false;
 421                  }
 422                  else
 423                  {
 424                      if (!$in_transaction)
 425                      {
 426                          $this->sql_transaction('commit');
 427                      }
 428                  }
 429  
 430                  if ($this->debug_sql_explain)
 431                  {
 432                      $this->sql_report('stop', $query);
 433                  }
 434                  else if ($this->debug_load_time)
 435                  {
 436                      $this->sql_time += microtime(true) - $this->curtime;
 437                  }
 438  
 439                  if (!$this->query_result)
 440                  {
 441                      return false;
 442                  }
 443  
 444                  $safe_query_id = $this->clean_query_id($this->query_result);
 445  
 446                  if ($cache && $cache_ttl)
 447                  {
 448                      $this->open_queries[$safe_query_id] = $this->query_result;
 449                      $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
 450                  }
 451                  else if (strpos($query, 'SELECT') === 0)
 452                  {
 453                      $this->open_queries[$safe_query_id] = $this->query_result;
 454                  }
 455              }
 456              else if ($this->debug_sql_explain)
 457              {
 458                  $this->sql_report('fromcache', $query);
 459              }
 460          }
 461          else
 462          {
 463              return false;
 464          }
 465  
 466          return $this->query_result;
 467      }
 468  
 469      /**
 470      * Build LIMIT query
 471      */
 472  	function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
 473      {
 474          $this->query_result = false;
 475  
 476          $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset;
 477  
 478          return $this->sql_query($query, $cache_ttl);
 479      }
 480  
 481      /**
 482      * {@inheritDoc}
 483      */
 484  	function sql_affectedrows()
 485      {
 486          return ($this->query_result) ? @oci_num_rows($this->query_result) : false;
 487      }
 488  
 489      /**
 490      * {@inheritDoc}
 491      */
 492  	function sql_fetchrow($query_id = false)
 493      {
 494          global $cache;
 495  
 496          if ($query_id === false)
 497          {
 498              $query_id = $this->query_result;
 499          }
 500  
 501          $safe_query_id = $this->clean_query_id($query_id);
 502          if ($cache && $cache->sql_exists($safe_query_id))
 503          {
 504              return $cache->sql_fetchrow($safe_query_id);
 505          }
 506  
 507          if ($query_id)
 508          {
 509              if (!$row = oci_fetch_array($query_id, OCI_ASSOC + OCI_RETURN_NULLS))
 510              {
 511                  return false;
 512              }
 513  
 514              $result_row = array();
 515              foreach ($row as $key => $value)
 516              {
 517                  // Oracle treats empty strings as null
 518                  if (is_null($value))
 519                  {
 520                      $value = '';
 521                  }
 522  
 523                  // OCI->CLOB?
 524                  if (is_object($value))
 525                  {
 526                      $value = $value->load();
 527                  }
 528  
 529                  $result_row[strtolower($key)] = $value;
 530              }
 531  
 532              return $result_row;
 533          }
 534  
 535          return false;
 536      }
 537  
 538      /**
 539      * {@inheritDoc}
 540      */
 541  	function sql_rowseek($rownum, &$query_id)
 542      {
 543          global $cache;
 544  
 545          if ($query_id === false)
 546          {
 547              $query_id = $this->query_result;
 548          }
 549  
 550          $safe_query_id = $this->clean_query_id($query_id);
 551          if ($cache && $cache->sql_exists($safe_query_id))
 552          {
 553              return $cache->sql_rowseek($rownum, $safe_query_id);
 554          }
 555  
 556          if (!$query_id)
 557          {
 558              return false;
 559          }
 560  
 561          // Reset internal pointer
 562          @oci_execute($query_id, OCI_DEFAULT);
 563  
 564          // We do not fetch the row for rownum == 0 because then the next resultset would be the second row
 565          for ($i = 0; $i < $rownum; $i++)
 566          {
 567              if (!$this->sql_fetchrow($query_id))
 568              {
 569                  return false;
 570              }
 571          }
 572  
 573          return true;
 574      }
 575  
 576      /**
 577       * {@inheritdoc}
 578       */
 579  	public function sql_last_inserted_id()
 580      {
 581          $query_id = $this->query_result;
 582  
 583          if ($query_id !== false && $this->last_query_text != '')
 584          {
 585              if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename))
 586              {
 587                  $query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL';
 588                  $stmt = @oci_parse($this->db_connect_id, $query);
 589                  if ($stmt)
 590                  {
 591                      $success = @oci_execute($stmt, OCI_DEFAULT);
 592  
 593                      if ($success)
 594                      {
 595                          $temp_array = oci_fetch_array($stmt, OCI_ASSOC + OCI_RETURN_NULLS);
 596                          oci_free_statement($stmt);
 597  
 598                          if (!empty($temp_array))
 599                          {
 600                              return $temp_array['CURRVAL'];
 601                          }
 602                          else
 603                          {
 604                              return false;
 605                          }
 606                      }
 607                  }
 608              }
 609          }
 610  
 611          return false;
 612      }
 613  
 614      /**
 615      * {@inheritDoc}
 616      */
 617  	function sql_freeresult($query_id = false)
 618      {
 619          global $cache;
 620  
 621          if ($query_id === false)
 622          {
 623              $query_id = $this->query_result;
 624          }
 625  
 626          $safe_query_id = $this->clean_query_id($query_id);
 627          if ($cache && $cache->sql_exists($safe_query_id))
 628          {
 629              return $cache->sql_freeresult($safe_query_id);
 630          }
 631  
 632          if (isset($this->open_queries[$safe_query_id]))
 633          {
 634              unset($this->open_queries[$safe_query_id]);
 635              return oci_free_statement($query_id);
 636          }
 637  
 638          return false;
 639      }
 640  
 641      /**
 642      * {@inheritDoc}
 643      */
 644  	function sql_escape($msg)
 645      {
 646          return str_replace(array("'", "\0"), array("''", ''), $msg);
 647      }
 648  
 649      /**
 650      * Build LIKE expression
 651      * @access private
 652      */
 653  	function _sql_like_expression($expression)
 654      {
 655          return $expression . " ESCAPE '\\'";
 656      }
 657  
 658      /**
 659      * Build NOT LIKE expression
 660      * @access private
 661      */
 662  	function _sql_not_like_expression($expression)
 663      {
 664          return $expression . " ESCAPE '\\'";
 665      }
 666  
 667  	function _sql_custom_build($stage, $data)
 668      {
 669          return $data;
 670      }
 671  
 672  	function _sql_bit_and($column_name, $bit, $compare = '')
 673      {
 674          return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
 675      }
 676  
 677  	function _sql_bit_or($column_name, $bit, $compare = '')
 678      {
 679          return 'BITOR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
 680      }
 681  
 682      /**
 683      * return sql error array
 684      * @access private
 685      */
 686  	function _sql_error()
 687      {
 688          if (function_exists('oci_error'))
 689          {
 690              $error = @oci_error();
 691              $error = (!$error) ? @oci_error($this->query_result) : $error;
 692              $error = (!$error) ? @oci_error($this->db_connect_id) : $error;
 693  
 694              if ($error)
 695              {
 696                  $this->last_error_result = $error;
 697              }
 698              else
 699              {
 700                  $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
 701              }
 702          }
 703          else
 704          {
 705              $error = array(
 706                  'message'    => $this->connect_error,
 707                  'code'        => '',
 708              );
 709          }
 710  
 711          return $error;
 712      }
 713  
 714      /**
 715      * Close sql connection
 716      * @access private
 717      */
 718  	function _sql_close()
 719      {
 720          return @oci_close($this->db_connect_id);
 721      }
 722  
 723      /**
 724      * Build db-specific report
 725      * @access private
 726      */
 727  	function _sql_report($mode, $query = '')
 728      {
 729          switch ($mode)
 730          {
 731              case 'start':
 732  
 733                  $html_table = false;
 734  
 735                  // Grab a plan table, any will do
 736                  $sql = "SELECT table_name
 737                      FROM USER_TABLES
 738                      WHERE table_name LIKE '%PLAN_TABLE%'";
 739                  $stmt = oci_parse($this->db_connect_id, $sql);
 740                  oci_execute($stmt);
 741  
 742                  if ($result = oci_fetch_array($stmt, OCI_ASSOC + OCI_RETURN_NULLS))
 743                  {
 744                      $table = $result['TABLE_NAME'];
 745  
 746                      // This is the statement_id that will allow us to track the plan
 747                      $statement_id = substr(md5($query), 0, 30);
 748  
 749                      // Remove any stale plans
 750                      $stmt2 = oci_parse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'");
 751                      oci_execute($stmt2);
 752                      oci_free_statement($stmt2);
 753  
 754                      // Explain the plan
 755                      $sql = "EXPLAIN PLAN
 756                          SET STATEMENT_ID = '$statement_id'
 757                          FOR $query";
 758                      $stmt2 = oci_parse($this->db_connect_id, $sql);
 759                      oci_execute($stmt2);
 760                      oci_free_statement($stmt2);
 761  
 762                      // Get the data from the plan
 763                      $sql = "SELECT operation, options, object_name, object_type, cardinality, cost
 764                          FROM plan_table
 765                          START WITH id = 0 AND statement_id = '$statement_id'
 766                          CONNECT BY PRIOR id = parent_id
 767                              AND statement_id = '$statement_id'";
 768                      $stmt2 = oci_parse($this->db_connect_id, $sql);
 769                      oci_execute($stmt2);
 770  
 771                      while ($row = oci_fetch_array($stmt2, OCI_ASSOC + OCI_RETURN_NULLS))
 772                      {
 773                          $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
 774                      }
 775  
 776                      oci_free_statement($stmt2);
 777  
 778                      // Remove the plan we just made, we delete them on request anyway
 779                      $stmt2 = oci_parse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'");
 780                      oci_execute($stmt2);
 781                      oci_free_statement($stmt2);
 782                  }
 783  
 784                  oci_free_statement($stmt);
 785  
 786                  if ($html_table)
 787                  {
 788                      $this->html_hold .= '</table>';
 789                  }
 790  
 791              break;
 792  
 793              case 'fromcache':
 794                  $endtime = explode(' ', microtime());
 795                  $endtime = $endtime[0] + $endtime[1];
 796  
 797                  $result = @oci_parse($this->db_connect_id, $query);
 798                  if ($result)
 799                  {
 800                      $success = @oci_execute($result, OCI_DEFAULT);
 801                      if ($success)
 802                      {
 803                          array();
 804  
 805                          while ($row = oci_fetch_array($result, OCI_ASSOC + OCI_RETURN_NULLS))
 806                          {
 807                              // Take the time spent on parsing rows into account
 808                          }
 809                          @oci_free_statement($result);
 810                      }
 811                  }
 812  
 813                  $splittime = explode(' ', microtime());
 814                  $splittime = $splittime[0] + $splittime[1];
 815  
 816                  $this->sql_report('record_fromcache', $query, $endtime, $splittime);
 817  
 818              break;
 819          }
 820      }
 821  
 822      /**
 823      * {@inheritDoc}
 824      */
 825  	function sql_quote($msg)
 826      {
 827          return '"' . $msg . '"';
 828      }
 829  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1