[ Index ]

PHP Cross Reference of phpBB-3.2.11-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('ocinlogon'))
  49              {
  50                  $this->connect_error = 'ocinlogon function does not exist, is oci extension installed?';
  51                  return $this->sql_error('');
  52              }
  53              $this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8');
  54          }
  55          else if ($this->persistency)
  56          {
  57              if (!function_exists('ociplogon'))
  58              {
  59                  $this->connect_error = 'ociplogon function does not exist, is oci extension installed?';
  60                  return $this->sql_error('');
  61              }
  62              $this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8');
  63          }
  64          else
  65          {
  66              if (!function_exists('ocilogon'))
  67              {
  68                  $this->connect_error = 'ocilogon function does not exist, is oci extension installed?';
  69                  return $this->sql_error('');
  70              }
  71              $this->db_connect_id = @ocilogon($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 = @ociserverversion($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 @ocicommit($this->db_connect_id);
 123              break;
 124  
 125              case 'rollback':
 126                  return @ocirollback($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              // EXPLAIN only in extra debug mode
 250              if (defined('DEBUG'))
 251              {
 252                  $this->sql_report('start', $query);
 253              }
 254              else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
 255              {
 256                  $this->curtime = microtime(true);
 257              }
 258  
 259              $this->last_query_text = $query;
 260              $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
 261              $this->sql_add_num_queries($this->query_result);
 262  
 263              if ($this->query_result === false)
 264              {
 265                  $in_transaction = false;
 266                  if (!$this->transaction)
 267                  {
 268                      $this->sql_transaction('begin');
 269                  }
 270                  else
 271                  {
 272                      $in_transaction = true;
 273                  }
 274  
 275                  $array = array();
 276  
 277                  // We overcome Oracle's 4000 char limit by binding vars
 278                  if (strlen($query) > 4000)
 279                  {
 280                      if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/sU', $query, $regs))
 281                      {
 282                          if (strlen($regs[3]) > 4000)
 283                          {
 284                              $cols = explode(', ', $regs[2]);
 285  
 286                              preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER);
 287  
 288  /*                        The code inside this comment block breaks clob handling, but does allow the
 289                          database restore script to work.  If you want to allow no posts longer than 4KB
 290                          and/or need the db restore script, uncomment this.
 291  
 292  
 293                              if (count($cols) !== count($vals))
 294                              {
 295                                  // Try to replace some common data we know is from our restore script or from other sources
 296                                  $regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]);
 297                                  $_vals = explode(', ', $regs[3]);
 298  
 299                                  $vals = array();
 300                                  $is_in_val = false;
 301                                  $i = 0;
 302                                  $string = '';
 303  
 304                                  foreach ($_vals as $value)
 305                                  {
 306                                      if (strpos($value, "'") === false && !$is_in_val)
 307                                      {
 308                                          $vals[$i++] = $value;
 309                                          continue;
 310                                      }
 311  
 312                                      if (substr($value, -1) === "'")
 313                                      {
 314                                          $vals[$i] = $string . (($is_in_val) ? ', ' : '') . $value;
 315                                          $string = '';
 316                                          $is_in_val = false;
 317  
 318                                          if ($vals[$i][0] !== "'")
 319                                          {
 320                                              $vals[$i] = "''" . $vals[$i];
 321                                          }
 322                                          $i++;
 323                                          continue;
 324                                      }
 325                                      else
 326                                      {
 327                                          $string .= (($is_in_val) ? ', ' : '') . $value;
 328                                          $is_in_val = true;
 329                                      }
 330                                  }
 331  
 332                                  if ($string)
 333                                  {
 334                                      // New value if cols != value
 335                                      $vals[(count($cols) !== count($vals)) ? $i : $i - 1] .= $string;
 336                                  }
 337  
 338                                  $vals = array(0 => $vals);
 339                              }
 340  */
 341  
 342                              $inserts = $vals[0];
 343                              unset($vals);
 344  
 345                              foreach ($inserts as $key => $value)
 346                              {
 347                                  if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2
 348                                  {
 349                                      $inserts[$key] = ':' . strtoupper($cols[$key]);
 350                                      $array[$inserts[$key]] = str_replace("''", "'", substr($value, 1, -1));
 351                                  }
 352                              }
 353  
 354                              $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')';
 355                          }
 356                      }
 357                      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))
 358                      {
 359                          if (strlen($data[0][2]) > 4000)
 360                          {
 361                              $update = $data[0][1];
 362                              $where = $data[0][3];
 363                              preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[0][2], $temp, PREG_SET_ORDER);
 364                              unset($data);
 365  
 366                              $cols = array();
 367                              foreach ($temp as $value)
 368                              {
 369                                  if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) // check to see if this thing is greater than the max + 'x2
 370                                  {
 371                                      $cols[] = $value[1] . '=:' . strtoupper($value[1]);
 372                                      $array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1));
 373                                  }
 374                                  else
 375                                  {
 376                                      $cols[] = $value[1] . '=' . $value[2];
 377                                  }
 378                              }
 379  
 380                              $query = $update . implode(', ', $cols) . ' ' . $where;
 381                              unset($cols);
 382                          }
 383                      }
 384                  }
 385  
 386                  switch (substr($query, 0, 6))
 387                  {
 388                      case 'DELETE':
 389                          if (preg_match('/^(DELETE FROM [\w_]++ WHERE)((?:\s*(?:AND|OR)?\s*[\w_]+\s*(?:(?:=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]+)|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))*+)$/', $query, $regs))
 390                          {
 391                              $query = $regs[1] . $this->_rewrite_where($regs[2]);
 392                              unset($regs);
 393                          }
 394                      break;
 395  
 396                      case 'UPDATE':
 397                          if (preg_match('/^(UPDATE [\\w_]++\\s+SET [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++)(?:, [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++))*+\\s+WHERE)(.*)$/s',  $query, $regs))
 398                          {
 399                              $query = $regs[1] . $this->_rewrite_where($regs[2]);
 400                              unset($regs);
 401                          }
 402                      break;
 403  
 404                      case 'SELECT':
 405                          $query = preg_replace_callback('/([\w_.]++)\s*(?:(=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]++|([\w_.]++))|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]++,? ?)*+\))/', array($this, '_rewrite_col_compare'), $query);
 406                      break;
 407                  }
 408  
 409                  $this->query_result = @ociparse($this->db_connect_id, $query);
 410  
 411                  foreach ($array as $key => $value)
 412                  {
 413                      @ocibindbyname($this->query_result, $key, $array[$key], -1);
 414                  }
 415  
 416                  $success = @ociexecute($this->query_result, OCI_DEFAULT);
 417  
 418                  if (!$success)
 419                  {
 420                      $this->sql_error($query);
 421                      $this->query_result = false;
 422                  }
 423                  else
 424                  {
 425                      if (!$in_transaction)
 426                      {
 427                          $this->sql_transaction('commit');
 428                      }
 429                  }
 430  
 431                  if (defined('DEBUG'))
 432                  {
 433                      $this->sql_report('stop', $query);
 434                  }
 435                  else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
 436                  {
 437                      $this->sql_time += microtime(true) - $this->curtime;
 438                  }
 439  
 440                  if (!$this->query_result)
 441                  {
 442                      return false;
 443                  }
 444  
 445                  if ($cache && $cache_ttl)
 446                  {
 447                      $this->open_queries[(int) $this->query_result] = $this->query_result;
 448                      $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
 449                  }
 450                  else if (strpos($query, 'SELECT') === 0)
 451                  {
 452                      $this->open_queries[(int) $this->query_result] = $this->query_result;
 453                  }
 454              }
 455              else if (defined('DEBUG'))
 456              {
 457                  $this->sql_report('fromcache', $query);
 458              }
 459          }
 460          else
 461          {
 462              return false;
 463          }
 464  
 465          return $this->query_result;
 466      }
 467  
 468      /**
 469      * Build LIMIT query
 470      */
 471  	function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
 472      {
 473          $this->query_result = false;
 474  
 475          $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset;
 476  
 477          return $this->sql_query($query, $cache_ttl);
 478      }
 479  
 480      /**
 481      * {@inheritDoc}
 482      */
 483  	function sql_affectedrows()
 484      {
 485          return ($this->query_result) ? @ocirowcount($this->query_result) : false;
 486      }
 487  
 488      /**
 489      * {@inheritDoc}
 490      */
 491  	function sql_fetchrow($query_id = false)
 492      {
 493          global $cache;
 494  
 495          if ($query_id === false)
 496          {
 497              $query_id = $this->query_result;
 498          }
 499  
 500          if ($cache && $cache->sql_exists($query_id))
 501          {
 502              return $cache->sql_fetchrow($query_id);
 503          }
 504  
 505          if ($query_id)
 506          {
 507              $row = array();
 508              $result = ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS);
 509  
 510              if (!$result || !$row)
 511              {
 512                  return false;
 513              }
 514  
 515              $result_row = array();
 516              foreach ($row as $key => $value)
 517              {
 518                  // Oracle treats empty strings as null
 519                  if (is_null($value))
 520                  {
 521                      $value = '';
 522                  }
 523  
 524                  // OCI->CLOB?
 525                  if (is_object($value))
 526                  {
 527                      $value = $value->load();
 528                  }
 529  
 530                  $result_row[strtolower($key)] = $value;
 531              }
 532  
 533              return $result_row;
 534          }
 535  
 536          return false;
 537      }
 538  
 539      /**
 540      * {@inheritDoc}
 541      */
 542  	function sql_rowseek($rownum, &$query_id)
 543      {
 544          global $cache;
 545  
 546          if ($query_id === false)
 547          {
 548              $query_id = $this->query_result;
 549          }
 550  
 551          if ($cache && $cache->sql_exists($query_id))
 552          {
 553              return $cache->sql_rowseek($rownum, $query_id);
 554          }
 555  
 556          if (!$query_id)
 557          {
 558              return false;
 559          }
 560  
 561          // Reset internal pointer
 562          @ociexecute($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  	function sql_nextid()
 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 = @ociparse($this->db_connect_id, $query);
 589                  if ($stmt)
 590                  {
 591                      $success = @ociexecute($stmt, OCI_DEFAULT);
 592  
 593                      if ($success)
 594                      {
 595                          $temp_result = ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS);
 596                          ocifreestatement($stmt);
 597  
 598                          if ($temp_result)
 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          if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
 627          {
 628              return $cache->sql_freeresult($query_id);
 629          }
 630  
 631          if (isset($this->open_queries[(int) $query_id]))
 632          {
 633              unset($this->open_queries[(int) $query_id]);
 634              return ocifreestatement($query_id);
 635          }
 636  
 637          return false;
 638      }
 639  
 640      /**
 641      * {@inheritDoc}
 642      */
 643  	function sql_escape($msg)
 644      {
 645          return str_replace(array("'", "\0"), array("''", ''), $msg);
 646      }
 647  
 648      /**
 649      * Build LIKE expression
 650      * @access private
 651      */
 652  	function _sql_like_expression($expression)
 653      {
 654          return $expression . " ESCAPE '\\'";
 655      }
 656  
 657      /**
 658      * Build NOT LIKE expression
 659      * @access private
 660      */
 661  	function _sql_not_like_expression($expression)
 662      {
 663          return $expression . " ESCAPE '\\'";
 664      }
 665  
 666  	function _sql_custom_build($stage, $data)
 667      {
 668          return $data;
 669      }
 670  
 671  	function _sql_bit_and($column_name, $bit, $compare = '')
 672      {
 673          return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
 674      }
 675  
 676  	function _sql_bit_or($column_name, $bit, $compare = '')
 677      {
 678          return 'BITOR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
 679      }
 680  
 681      /**
 682      * return sql error array
 683      * @access private
 684      */
 685  	function _sql_error()
 686      {
 687          if (function_exists('ocierror'))
 688          {
 689              $error = @ocierror();
 690              $error = (!$error) ? @ocierror($this->query_result) : $error;
 691              $error = (!$error) ? @ocierror($this->db_connect_id) : $error;
 692  
 693              if ($error)
 694              {
 695                  $this->last_error_result = $error;
 696              }
 697              else
 698              {
 699                  $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
 700              }
 701          }
 702          else
 703          {
 704              $error = array(
 705                  'message'    => $this->connect_error,
 706                  'code'        => '',
 707              );
 708          }
 709  
 710          return $error;
 711      }
 712  
 713      /**
 714      * Close sql connection
 715      * @access private
 716      */
 717  	function _sql_close()
 718      {
 719          return @ocilogoff($this->db_connect_id);
 720      }
 721  
 722      /**
 723      * Build db-specific report
 724      * @access private
 725      */
 726  	function _sql_report($mode, $query = '')
 727      {
 728          switch ($mode)
 729          {
 730              case 'start':
 731  
 732                  $html_table = false;
 733  
 734                  // Grab a plan table, any will do
 735                  $sql = "SELECT table_name
 736                      FROM USER_TABLES
 737                      WHERE table_name LIKE '%PLAN_TABLE%'";
 738                  $stmt = ociparse($this->db_connect_id, $sql);
 739                  ociexecute($stmt);
 740                  $result = array();
 741  
 742                  if (ocifetchinto($stmt, $result, 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 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'");
 751                      ociexecute($stmt2);
 752                      ocifreestatement($stmt2);
 753  
 754                      // Explain the plan
 755                      $sql = "EXPLAIN PLAN
 756                          SET STATEMENT_ID = '$statement_id'
 757                          FOR $query";
 758                      $stmt2 = ociparse($this->db_connect_id, $sql);
 759                      ociexecute($stmt2);
 760                      ocifreestatement($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 = ociparse($this->db_connect_id, $sql);
 769                      ociexecute($stmt2);
 770  
 771                      $row = array();
 772                      while (ocifetchinto($stmt2, $row, OCI_ASSOC + OCI_RETURN_NULLS))
 773                      {
 774                          $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
 775                      }
 776  
 777                      ocifreestatement($stmt2);
 778  
 779                      // Remove the plan we just made, we delete them on request anyway
 780                      $stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'");
 781                      ociexecute($stmt2);
 782                      ocifreestatement($stmt2);
 783                  }
 784  
 785                  ocifreestatement($stmt);
 786  
 787                  if ($html_table)
 788                  {
 789                      $this->html_hold .= '</table>';
 790                  }
 791  
 792              break;
 793  
 794              case 'fromcache':
 795                  $endtime = explode(' ', microtime());
 796                  $endtime = $endtime[0] + $endtime[1];
 797  
 798                  $result = @ociparse($this->db_connect_id, $query);
 799                  if ($result)
 800                  {
 801                      $success = @ociexecute($result, OCI_DEFAULT);
 802                      if ($success)
 803                      {
 804                          $row = array();
 805  
 806                          while (ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS))
 807                          {
 808                              // Take the time spent on parsing rows into account
 809                          }
 810                          @ocifreestatement($result);
 811                      }
 812                  }
 813  
 814                  $splittime = explode(' ', microtime());
 815                  $splittime = $splittime[0] + $splittime[1];
 816  
 817                  $this->sql_report('record_fromcache', $query, $endtime, $splittime);
 818  
 819              break;
 820          }
 821      }
 822  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1