mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-09 04:48:53 +00:00
- clean up firebird, I will consider changing it to use fetch array instead of fetch object. it's identity code already uses this method as of right... now :D - fix a tiny bug in MySQL's driver (remember to pass the connect id to all DBAL functions) - add new_link as a new param for sql_connect. This allows you to make connections that are not dependant on each other. This is done for our friends mysql, mssql, postgresql and oracle. Now for everybody else.. (I said this was clever ;) MySQLi and SQLite should always spawn a new connection when you call it while mssql_odbc and firebird both will create new links if you give them different params (different creds) than the previous connection(s). Thus we can always promise new links :D - fixed a bug in the converter - cleaned up the dbal a little git-svn-id: file:///svn/phpbb/trunk@7009 89ea8834-ac86-4346-8a33-228a782c2dd0
741 lines
No EOL
18 KiB
PHP
741 lines
No EOL
18 KiB
PHP
<?php
|
|
/**
|
|
*
|
|
* @package dbal
|
|
* @version $Id$
|
|
* @copyright (c) 2005 phpBB Group
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Database Abstraction Layer
|
|
* @package dbal
|
|
*/
|
|
class dbal
|
|
{
|
|
var $db_connect_id;
|
|
var $query_result;
|
|
var $return_on_error = false;
|
|
var $transaction = false;
|
|
var $sql_time = 0;
|
|
var $num_queries = array();
|
|
var $open_queries = array();
|
|
|
|
var $curtime = 0;
|
|
var $query_hold = '';
|
|
var $html_hold = '';
|
|
var $sql_report = '';
|
|
|
|
var $persistency = false;
|
|
var $user = '';
|
|
var $server = '';
|
|
var $dbname = '';
|
|
|
|
// Set to true if error triggered
|
|
var $sql_error_triggered = false;
|
|
|
|
// Holding the last sql query on sql error
|
|
var $sql_error_sql = '';
|
|
|
|
/**
|
|
* Current sql layer
|
|
*/
|
|
var $sql_layer = '';
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
function dbal()
|
|
{
|
|
$this->num_queries = array(
|
|
'cached' => 0,
|
|
'normal' => 0,
|
|
'total' => 0,
|
|
);
|
|
|
|
// Fill default sql layer based on the class being called.
|
|
// This can be changed by the specified layer itself later if needed.
|
|
$this->sql_layer = substr(get_class($this), 5);
|
|
}
|
|
|
|
/**
|
|
* return on error or display error message
|
|
*/
|
|
function sql_return_on_error($fail = false)
|
|
{
|
|
$this->sql_error_triggered = false;
|
|
$this->sql_error_sql = '';
|
|
|
|
$this->return_on_error = $fail;
|
|
}
|
|
|
|
/**
|
|
* Return number of sql queries and cached sql queries used
|
|
*/
|
|
function sql_num_queries($cached = false)
|
|
{
|
|
return ($cached) ? $this->num_queries['cached'] : $this->num_queries['normal'];
|
|
}
|
|
|
|
/**
|
|
* Add to query count
|
|
*/
|
|
function sql_add_num_queries($cached = false)
|
|
{
|
|
$this->num_queries['cached'] += ($cached) ? 1 : 0;
|
|
$this->num_queries['normal'] += ($cached) ? 0 : 1;
|
|
$this->num_queries['total'] += 1;
|
|
}
|
|
|
|
/**
|
|
* DBAL garbage collection, close sql connection
|
|
*/
|
|
function sql_close()
|
|
{
|
|
if (!$this->db_connect_id)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ($this->transaction)
|
|
{
|
|
$this->sql_transaction('commit');
|
|
}
|
|
|
|
foreach ($this->open_queries as $query_id)
|
|
{
|
|
$this->sql_freeresult($query_id);
|
|
}
|
|
|
|
return $this->_sql_close();
|
|
}
|
|
|
|
/**
|
|
* Build LIMIT query
|
|
* Doing some validation here.
|
|
*/
|
|
function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
|
|
{
|
|
if (empty($query))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Never use a negative total or offset
|
|
$total = ($total < 0) ? 0 : $total;
|
|
$offset = ($offset < 0) ? 0 : $offset;
|
|
|
|
return $this->_sql_query_limit($query, $total, $offset, $cache_ttl);
|
|
}
|
|
|
|
/**
|
|
* Fetch all rows
|
|
*/
|
|
function sql_fetchrowset($query_id = false)
|
|
{
|
|
if ($query_id === false)
|
|
{
|
|
$query_id = $this->query_result;
|
|
}
|
|
|
|
if ($query_id !== false)
|
|
{
|
|
$result = array();
|
|
while ($row = $this->sql_fetchrow($query_id))
|
|
{
|
|
$result[] = $row;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Fetch field
|
|
* if rownum is false, the current row is used, else it is pointing to the row (zero-based)
|
|
*/
|
|
function sql_fetchfield($field, $rownum = false, $query_id = false)
|
|
{
|
|
global $cache;
|
|
|
|
if ($query_id === false)
|
|
{
|
|
$query_id = $this->query_result;
|
|
}
|
|
|
|
if ($query_id !== false)
|
|
{
|
|
if ($rownum !== false)
|
|
{
|
|
$this->sql_rowseek($rownum, $query_id);
|
|
}
|
|
|
|
if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
|
|
{
|
|
return $cache->sql_fetchfield($query_id, $field);
|
|
}
|
|
|
|
$row = $this->sql_fetchrow($query_id);
|
|
return (isset($row[$field])) ? $row[$field] : false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* SQL Transaction
|
|
* @access private
|
|
*/
|
|
function sql_transaction($status = 'begin')
|
|
{
|
|
switch ($status)
|
|
{
|
|
case 'begin':
|
|
// Commit previously opened transaction before opening another transaction
|
|
if ($this->transaction)
|
|
{
|
|
$this->_sql_transaction('commit');
|
|
}
|
|
|
|
$result = $this->_sql_transaction('begin');
|
|
$this->transaction = true;
|
|
break;
|
|
|
|
case 'commit':
|
|
$result = $this->_sql_transaction('commit');
|
|
$this->transaction = false;
|
|
|
|
if (!$result)
|
|
{
|
|
$this->_sql_transaction('rollback');
|
|
}
|
|
break;
|
|
|
|
case 'rollback':
|
|
$result = $this->_sql_transaction('rollback');
|
|
$this->transaction = false;
|
|
break;
|
|
|
|
default:
|
|
$result = $this->_sql_transaction($status);
|
|
break;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Build sql statement from array for insert/update/select statements
|
|
*
|
|
* Idea for this from Ikonboard
|
|
* Possible query values: INSERT, INSERT_SELECT, MULTI_INSERT, UPDATE, SELECT
|
|
*
|
|
*/
|
|
function sql_build_array($query, $assoc_ary = false)
|
|
{
|
|
if (!is_array($assoc_ary))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$fields = $values = array();
|
|
|
|
if ($query == 'INSERT' || $query == 'INSERT_SELECT')
|
|
{
|
|
foreach ($assoc_ary as $key => $var)
|
|
{
|
|
$fields[] = $key;
|
|
|
|
if (is_array($var) && is_string($var[0]))
|
|
{
|
|
// This is used for INSERT_SELECT(s)
|
|
$values[] = $var[0];
|
|
}
|
|
else
|
|
{
|
|
$values[] = $this->_sql_validate_value($var);
|
|
}
|
|
}
|
|
|
|
$query = ($query == 'INSERT') ? ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')' : ' (' . implode(', ', $fields) . ') SELECT ' . implode(', ', $values) . ' ';
|
|
}
|
|
else if ($query == 'MULTI_INSERT')
|
|
{
|
|
$ary = array();
|
|
foreach ($assoc_ary as $id => $sql_ary)
|
|
{
|
|
// If by accident the sql array is only one-dimensional we build a normal insert statement
|
|
if (!is_array($sql_ary))
|
|
{
|
|
return $this->sql_build_array('INSERT', $assoc_ary);
|
|
}
|
|
|
|
$values = array();
|
|
foreach ($sql_ary as $key => $var)
|
|
{
|
|
$values[] = $this->_sql_validate_value($var);
|
|
}
|
|
$ary[] = '(' . implode(', ', $values) . ')';
|
|
}
|
|
|
|
$query = ' (' . implode(', ', array_keys($assoc_ary[0])) . ') VALUES ' . implode(', ', $ary);
|
|
}
|
|
else if ($query == 'UPDATE' || $query == 'SELECT')
|
|
{
|
|
$values = array();
|
|
foreach ($assoc_ary as $key => $var)
|
|
{
|
|
$values[] = "$key = " . $this->_sql_validate_value($var);
|
|
}
|
|
$query = implode(($query == 'UPDATE') ? ', ' : ' AND ', $values);
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* Build IN or NOT IN sql comparison string, uses <> or = on single element
|
|
* arrays to improve comparison speed
|
|
* @access public
|
|
* @param string $field name of the sql column that shall be compared
|
|
* @param array $array array of values that are allowed (IN) or not allowed (NOT IN)
|
|
* @param bool $negate true for IN (), false for NOT IN ()
|
|
* @param bool $allow_empty_set Allow $array to be empty, this function will return 1=1 or 1=0 then
|
|
*/
|
|
function sql_in_set($field, $array, $negate = false, $allow_empty_set = false)
|
|
{
|
|
if (!sizeof($array))
|
|
{
|
|
if (!$allow_empty_set)
|
|
{
|
|
// Print the backtrace to help identifying the location of the problematic code
|
|
$this->sql_error('No values specified for SQL IN comparison');
|
|
}
|
|
else
|
|
{
|
|
// NOT IN () actually means everything so use a tautology
|
|
if ($negate)
|
|
{
|
|
return '1=1';
|
|
}
|
|
// IN () actually means nothing so use a contradiction
|
|
else
|
|
{
|
|
return '1=0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!is_array($array))
|
|
{
|
|
$array = array($array);
|
|
}
|
|
|
|
if (sizeof($array) == 1)
|
|
{
|
|
@reset($array);
|
|
$var = current($array);
|
|
|
|
return $field . ($negate ? ' <> ' : ' = ') . $this->_sql_validate_value($var);
|
|
}
|
|
else
|
|
{
|
|
return $field . ($negate ? ' NOT IN ' : ' IN ') . '(' . implode(', ', array_map(array($this, '_sql_validate_value'), $array)) . ')';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run more than one insert statement.
|
|
*
|
|
* @param string $table table name to run the statements on
|
|
* @param array &$sql_ary multi-dimensional array holding the statement data.
|
|
*
|
|
* @return bool false if no statements were executed.
|
|
* @access public
|
|
*/
|
|
function sql_multi_insert($table, &$sql_ary)
|
|
{
|
|
if (!sizeof($sql_ary))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
switch ($this->sql_layer)
|
|
{
|
|
case 'mysql':
|
|
case 'mysql4':
|
|
case 'mysqli':
|
|
$this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('MULTI_INSERT', $sql_ary));
|
|
break;
|
|
|
|
default:
|
|
foreach ($sql_ary as $ary)
|
|
{
|
|
if (!is_array($ary))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary));
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Function for validating values
|
|
* @access private
|
|
*/
|
|
function _sql_validate_value($var)
|
|
{
|
|
if (is_null($var))
|
|
{
|
|
return 'NULL';
|
|
}
|
|
else if (is_string($var))
|
|
{
|
|
return "'" . $this->sql_escape($var) . "'";
|
|
}
|
|
else
|
|
{
|
|
return (is_bool($var)) ? intval($var) : $var;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build sql statement from array for select and select distinct statements
|
|
*
|
|
* Possible query values: SELECT, SELECT_DISTINCT
|
|
*/
|
|
function sql_build_query($query, $array)
|
|
{
|
|
$sql = '';
|
|
switch ($query)
|
|
{
|
|
case 'SELECT':
|
|
case 'SELECT_DISTINCT';
|
|
|
|
$sql = str_replace('_', ' ', $query) . ' ' . $array['SELECT'] . ' FROM ';
|
|
|
|
$table_array = array();
|
|
foreach ($array['FROM'] as $table_name => $alias)
|
|
{
|
|
if (is_array($alias))
|
|
{
|
|
foreach ($alias as $multi_alias)
|
|
{
|
|
$table_array[] = $table_name . ' ' . $multi_alias;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$table_array[] = $table_name . ' ' . $alias;
|
|
}
|
|
}
|
|
|
|
$sql .= $this->_sql_custom_build('FROM', implode(', ', $table_array));
|
|
|
|
if (!empty($array['LEFT_JOIN']))
|
|
{
|
|
foreach ($array['LEFT_JOIN'] as $join)
|
|
{
|
|
$sql .= ' LEFT JOIN ' . key($join['FROM']) . ' ' . current($join['FROM']) . ' ON (' . $join['ON'] . ')';
|
|
}
|
|
}
|
|
|
|
if (!empty($array['WHERE']))
|
|
{
|
|
$sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']);
|
|
}
|
|
|
|
if (!empty($array['GROUP_BY']))
|
|
{
|
|
$sql .= ' GROUP BY ' . $array['GROUP_BY'];
|
|
}
|
|
|
|
if (!empty($array['ORDER_BY']))
|
|
{
|
|
$sql .= ' ORDER BY ' . $array['ORDER_BY'];
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return $sql;
|
|
}
|
|
|
|
/**
|
|
* display sql error page
|
|
*/
|
|
function sql_error($sql = '')
|
|
{
|
|
global $auth, $user, $config;
|
|
|
|
// Set var to retrieve errored status
|
|
$this->sql_error_triggered = true;
|
|
$this->sql_error_sql = $sql;
|
|
|
|
$error = $this->_sql_error();
|
|
|
|
if (!$this->return_on_error)
|
|
{
|
|
$message = '<u>SQL ERROR</u> [ ' . $this->sql_layer . ' ]<br /><br />' . $error['message'] . ' [' . $error['code'] . ']';
|
|
|
|
// Show complete SQL error and path to administrators only
|
|
// Additionally show complete error on installation or if extended debug mode is enabled
|
|
// The DEBUG_EXTRA constant is for development only!
|
|
if (isset($auth) && ($auth->acl_get('a_') || defined('IN_INSTALL') || defined('DEBUG_EXTRA')))
|
|
{
|
|
// Print out a nice backtrace...
|
|
$backtrace = get_backtrace();
|
|
|
|
$message .= ($sql) ? '<br /><br /><u>SQL</u><br /><br />' . htmlspecialchars($sql) : '';
|
|
$message .= ($backtrace) ? '<br /><br /><u>BACKTRACE</u><br />' . $backtrace : '';
|
|
$message .= '<br />';
|
|
}
|
|
else
|
|
{
|
|
// If error occurs in initiating the session we need to use a pre-defined language string
|
|
// This could happen if the connection could not be established for example (then we are not able to grab the default language)
|
|
if (!isset($user->lang['SQL_ERROR_OCCURRED']))
|
|
{
|
|
$message .= '<br /><br />An sql error occurred while fetching this page. Please contact an administrator if this problem persists.';
|
|
}
|
|
else
|
|
{
|
|
if (!empty($config['board_contact']))
|
|
{
|
|
$message .= '<br /><br />' . sprintf($user->lang['SQL_ERROR_OCCURRED'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
|
|
}
|
|
else
|
|
{
|
|
$message .= '<br /><br />' . sprintf($user->lang['SQL_ERROR_OCCURRED'], '', '');
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->transaction)
|
|
{
|
|
$this->sql_transaction('rollback');
|
|
}
|
|
|
|
if (strlen($message) > 1024)
|
|
{
|
|
// We need to define $msg_long_text here to circumvent text stripping.
|
|
global $msg_long_text;
|
|
$msg_long_text = $message;
|
|
|
|
trigger_error(false, E_USER_ERROR);
|
|
}
|
|
|
|
trigger_error($message, E_USER_ERROR);
|
|
}
|
|
|
|
return $error;
|
|
}
|
|
|
|
/**
|
|
* Explain queries
|
|
*/
|
|
function sql_report($mode, $query = '')
|
|
{
|
|
global $cache, $starttime, $phpbb_root_path, $user;
|
|
|
|
if (empty($_REQUEST['explain']))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!$query && $this->query_hold != '')
|
|
{
|
|
$query = $this->query_hold;
|
|
}
|
|
|
|
switch ($mode)
|
|
{
|
|
case 'display':
|
|
if (!empty($cache))
|
|
{
|
|
$cache->unload();
|
|
}
|
|
$this->sql_close();
|
|
|
|
$mtime = explode(' ', microtime());
|
|
$totaltime = $mtime[0] + $mtime[1] - $starttime;
|
|
|
|
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
|
<meta http-equiv="Content-Style-Type" content="text/css" />
|
|
<meta http-equiv="imagetoolbar" content="no" />
|
|
<title>SQL Report</title>
|
|
<link href="' . $phpbb_root_path . 'adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" />
|
|
</head>
|
|
<body id="errorpage">
|
|
<div id="wrap">
|
|
<div id="page-header">
|
|
<a href="' . build_url('explain') . '">Return to previous page</a>
|
|
</div>
|
|
<div id="page-body">
|
|
<div class="panel">
|
|
<span class="corners-top"><span></span></span>
|
|
<div id="content">
|
|
<h1>SQL Report</h1>
|
|
<br />
|
|
<p><b>Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries['normal']} queries" . (($this->num_queries['cached']) ? " + {$this->num_queries['cached']} " . (($this->num_queries['cached'] == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '</b></p>
|
|
|
|
<p>Time spent on ' . $this->sql_layer . ' queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></p>
|
|
|
|
<br /><br />
|
|
' . $this->sql_report . '
|
|
</div>
|
|
<span class="corners-bottom"><span></span></span>
|
|
</div>
|
|
</div>
|
|
<div id="page-footer">
|
|
Powered by phpBB © ' . date('Y') . ' <a href="http://www.phpbb.com/">phpBB Group</a>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>';
|
|
exit;
|
|
break;
|
|
|
|
case 'stop':
|
|
$endtime = explode(' ', microtime());
|
|
$endtime = $endtime[0] + $endtime[1];
|
|
|
|
$this->sql_report .= '
|
|
|
|
<table cellspacing="1">
|
|
<thead>
|
|
<tr>
|
|
<th>Query #' . $this->num_queries['total'] . '</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="row3"><textarea style="font-family:\'Courier New\',monospace;width:99%" rows="5" cols="10">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td>
|
|
</tr>
|
|
</table>
|
|
|
|
' . $this->html_hold . '
|
|
|
|
<p style="text-align: center;">
|
|
';
|
|
|
|
if ($this->query_result)
|
|
{
|
|
if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query))
|
|
{
|
|
$this->sql_report .= 'Affected rows: <b>' . $this->sql_affectedrows($this->query_result) . '</b> | ';
|
|
}
|
|
$this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: <b>' . sprintf('%.5f', $endtime - $this->curtime) . 's</b>';
|
|
}
|
|
else
|
|
{
|
|
$error = $this->sql_error();
|
|
$this->sql_report .= '<b style="color: red">FAILED</b> - ' . $this->sql_layer . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']);
|
|
}
|
|
|
|
$this->sql_report .= '</p><br /><br />';
|
|
|
|
$this->sql_time += $endtime - $this->curtime;
|
|
break;
|
|
|
|
case 'start':
|
|
$this->query_hold = $query;
|
|
$this->html_hold = '';
|
|
|
|
$this->_sql_report($mode, $query);
|
|
|
|
$this->curtime = explode(' ', microtime());
|
|
$this->curtime = $this->curtime[0] + $this->curtime[1];
|
|
|
|
break;
|
|
|
|
case 'add_select_row':
|
|
|
|
$html_table = func_get_arg(2);
|
|
$row = func_get_arg(3);
|
|
|
|
if (!$html_table && sizeof($row))
|
|
{
|
|
$html_table = true;
|
|
$this->html_hold .= '<table cellspacing="1"><tr>';
|
|
|
|
foreach (array_keys($row) as $val)
|
|
{
|
|
$this->html_hold .= '<th>' . (($val) ? ucwords(str_replace('_', ' ', $val)) : ' ') . '</th>';
|
|
}
|
|
$this->html_hold .= '</tr>';
|
|
}
|
|
$this->html_hold .= '<tr>';
|
|
|
|
$class = 'row1';
|
|
foreach (array_values($row) as $val)
|
|
{
|
|
$class = ($class == 'row1') ? 'row2' : 'row1';
|
|
$this->html_hold .= '<td class="' . $class . '">' . (($val) ? $val : ' ') . '</td>';
|
|
}
|
|
$this->html_hold .= '</tr>';
|
|
|
|
return $html_table;
|
|
|
|
break;
|
|
|
|
case 'fromcache':
|
|
|
|
$this->_sql_report($mode, $query);
|
|
|
|
break;
|
|
|
|
case 'record_fromcache':
|
|
|
|
$endtime = func_get_arg(2);
|
|
$splittime = func_get_arg(3);
|
|
|
|
$time_cache = $endtime - $this->curtime;
|
|
$time_db = $splittime - $endtime;
|
|
$color = ($time_db > $time_cache) ? 'green' : 'red';
|
|
|
|
$this->sql_report .= '<table cellspacing="1"><thead><tr><th>Query results obtained from the cache</th></tr></thead><tbody><tr>';
|
|
$this->sql_report .= '<td class="row3"><textarea style="font-family:\'Courier New\',monospace;width:99%" rows="5" cols="10">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td></tr></tbody></table>';
|
|
$this->sql_report .= '<p style="text-align: center;">';
|
|
$this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed [cache]: <b style="color: ' . $color . '">' . sprintf('%.5f', ($time_cache)) . 's</b> | Elapsed [db]: <b>' . sprintf('%.5f', $time_db) . 's</b></p><br /><br />';
|
|
|
|
// Pad the start time to not interfere with page timing
|
|
$starttime += $time_db;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$this->_sql_report($mode, $query);
|
|
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*/
|
|
if (!defined('IN_PHPBB'))
|
|
{
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* This variable holds the class name to use later
|
|
*/
|
|
$sql_db = 'dbal_' . $dbms;
|
|
|
|
?>
|