[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |