Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
oracle.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 namespace phpbb\db\driver;
015
016 /**
017 * Oracle Database Abstraction Layer
018 */
019 class oracle extends \phpbb\db\driver\driver
020 {
021 var $last_query_text = '';
022 var $connect_error = '';
023
024 /**
025 * {@inheritDoc}
026 */
027 function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
028 {
029 $this->persistency = $persistency;
030 $this->user = $sqluser;
031 $this->server = $sqlserver . (($port) ? ':' . $port : '');
032 $this->dbname = $database;
033
034 $connect = $database;
035
036 // support for "easy connect naming"
037 if ($sqlserver !== '' && $sqlserver !== '/')
038 {
039 if (substr($sqlserver, -1, 1) == '/')
040 {
041 $sqlserver == substr($sqlserver, 0, -1);
042 }
043 $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database;
044 }
045
046 if ($new_link)
047 {
048 if (!function_exists('ocinlogon'))
049 {
050 $this->connect_error = 'ocinlogon function does not exist, is oci extension installed?';
051 return $this->sql_error('');
052 }
053 $this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8');
054 }
055 else if ($this->persistency)
056 {
057 if (!function_exists('ociplogon'))
058 {
059 $this->connect_error = 'ociplogon function does not exist, is oci extension installed?';
060 return $this->sql_error('');
061 }
062 $this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8');
063 }
064 else
065 {
066 if (!function_exists('ocilogon'))
067 {
068 $this->connect_error = 'ocilogon function does not exist, is oci extension installed?';
069 return $this->sql_error('');
070 }
071 $this->db_connect_id = @ocilogon($this->user, $sqlpassword, $connect, 'UTF8');
072 }
073
074 return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
075 }
076
077 /**
078 * {@inheritDoc}
079 */
080 function sql_server_info($raw = false, $use_cache = true)
081 {
082 /**
083 * force $use_cache false. I didn't research why the caching code below is commented out
084 * but I assume its because the Oracle extension provides a direct method to access it
085 * without a query.
086 */
087 /*
088 global $cache;
089
090 if (empty($cache) || ($this->sql_server_version = $cache->get('oracle_version')) === false)
091 {
092 $result = @ociparse($this->db_connect_id, 'SELECT * FROM v$version WHERE banner LIKE \'Oracle%\'');
093 @ociexecute($result, OCI_DEFAULT);
094 @ocicommit($this->db_connect_id);
095
096 $row = array();
097 @ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS);
098 @ocifreestatement($result);
099 $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 (sizeof($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 (sizeof($cols) !== sizeof($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[(sizeof($cols) !== sizeof($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 }
823