return_on_error = $fail; } /** * Return number of sql queries used (cached and real queries are counted the same) */ function sql_num_queries() { return $this->num_queries; } /** * DBAL garbage collection, close sql connection */ function sql_close() { if (!$this->db_connect_id) { return false; } if ($this->transaction) { $this->sql_transaction('commit'); } if (sizeof($this->open_queries)) { foreach ($this->open_queries as $i_query_id => $query_id) { $this->sql_freeresult($query_id); } } return $this->_sql_close(); } /** * Fetch all rows */ function sql_fetchrowset($query_id = false) { if (!$query_id) { $query_id = $this->query_result; } if ($query_id) { $result = array(); while ($row = $this->sql_fetchrow($query_id)) { $result[] = $row; } return $result; } return false; } /** * 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 = array(); $values = array(); if ($query == 'INSERT' || $query == 'INSERT_SELECT') { foreach ($assoc_ary as $key => $var) { $fields[] = $key; if (is_null($var)) { $values[] = 'NULL'; } else if (is_string($var)) { $values[] = "'" . $this->sql_escape($var) . "'"; } else if (is_array($var) && is_string($var[0])) { $values[] = $var[0]; } else { $values[] = (is_bool($var)) ? intval($var) : $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) { $values = array(); foreach ($sql_ary as $key => $var) { if (is_null($var)) { $values[] = 'NULL'; } elseif (is_string($var)) { $values[] = "'" . $this->sql_escape($var) . "'"; } else { $values[] = (is_bool($var)) ? intval($var) : $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) { if (is_null($var)) { $values[] = "$key = NULL"; } elseif (is_string($var)) { $values[] = "$key = '" . $this->sql_escape($var) . "'"; } else { $values[] = (is_bool($var)) ? "$key = " . intval($var) : "$key = $var"; } } $query = implode(($query == 'UPDATE') ? ', ' : ' AND ', $values); } return $query; } /** * display sql error page */ function sql_error($sql = '') { $error = $this->_sql_error(); if (!$this->return_on_error) { $this_page = (isset($_SERVER['PHP_SELF']) && !empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']; $this_page .= '&' . ((isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : (isset($_ENV['QUERY_STRING']) ? $_ENV['QUERY_STRING'] : '')); $message = 'SQL ERROR [ ' . SQL_LAYER . ' ]

' . $error['message'] . ' [' . $error['code'] . ']

CALLING PAGE

' . htmlspecialchars($this_page) . (($sql != '') ? '

SQL

' . $sql : '') . '
'; if ($this->transaction) { $this->sql_transaction('rollback'); } trigger_error($message, E_USER_ERROR); } return $error; } /** * Explain queries * @child _sql_report */ function sql_report($mode, $query = '') { global $cache, $starttime, $phpbb_root_path; if (empty($_GET['explain'])) { return; } 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 ' Explain
phpBB Logo SQL Report      

Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries} queries" . (($this->cache_num_queries) ? " + {$this->cache_num_queries} " . (($this->cache_num_queries == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '
Time spent on MySQL queries: ' . round($this->sql_time, 5) . 's | Time spent on PHP: ' . round($totaltime - $this->sql_time, 5) . 's
' . $this->sql_report . '

'; exit; break; case 'stop': $endtime = explode(' ', microtime()); $endtime = $endtime[0] + $endtime[1]; $this->sql_report .= '

Query #' . $this->num_queries . '
' . $this->html_hold . '

'; if ($this->query_result) { if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query)) { $this->sql_report .= 'Affected rows: ' . $this->sql_affectedrows($this->query_result) . ' | '; } $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: ' . sprintf('%.5f', $endtime - $this->curtime) . 's'; } else { $error = $this->sql_error(); $this->sql_report .= 'FAILED - ' . SQL_LAYER . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']); } $this->sql_report .= '

'; $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 .= ''; foreach (array_keys($row) as $val) { $this->html_hold .= ''; } $this->html_hold .= ''; } $this->html_hold .= ''; $class = 'row1'; foreach (array_values($row) as $val) { $class = ($class == 'row1') ? 'row2' : 'row1'; $this->html_hold .= ''; } $this->html_hold .= ''; return $html_table; break; case 'fromcache': $this->_sql_report($mode, $query); $this->cache_num_queries++; 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 .= '

' . (($val) ? ucwords(str_replace('_', ' ', $val)) : ' ') . '
' . (($val) ? $val : ' ') . '
Query results obtained from the cache

'; $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed [cache]: ' . sprintf('%.5f', ($time_cache)) . 's | Elapsed [db]: ' . sprintf('%.5f', $time_db) . 's

'; // Pad the start time to not interfere with page timing $starttime += $time_db; break; default: $this->_sql_report($mode, $query); break; } } } /** */ if (!defined('IN_PHPBB')) { exit; } /** * This variable holds the class name to use later */ $sql_db = 'dbal_' . $dbms; ?>