Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
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('oci_new_connect'))
049 {
050 $this->connect_error = 'oci_new_connect function does not exist, is oci extension installed?';
051 return $this->sql_error('');
052 }
053 $this->db_connect_id = @oci_new_connect($this->user, $sqlpassword, $connect, 'UTF8');
054 }
055 else if ($this->persistency)
056 {
057 if (!function_exists('oci_pconnect'))
058 {
059 $this->connect_error = 'oci_pconnect function does not exist, is oci extension installed?';
060 return $this->sql_error('');
061 }
062 $this->db_connect_id = @oci_pconnect($this->user, $sqlpassword, $connect, 'UTF8');
063 }
064 else
065 {
066 if (!function_exists('oci_connect'))
067 {
068 $this->connect_error = 'oci_connect function does not exist, is oci extension installed?';
069 return $this->sql_error('');
070 }
071 $this->db_connect_id = @oci_connect($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 = @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 }
830