ViewQuery.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * Simple Machines Forum (SMF)
  4. *
  5. * @package SMF
  6. * @author Simple Machines http://www.simplemachines.org
  7. * @copyright 2011 Simple Machines
  8. * @license http://www.simplemachines.org/about/smf/license.php BSD
  9. *
  10. * @version 2.1 Alpha 1
  11. */
  12. if (!defined('SMF'))
  13. die('Hacking attempt...');
  14. /* This file is concerned with viewing queries, and is used for debugging.
  15. It contains only one function:
  16. void ViewQuery()
  17. - toggles the session variable 'view_queries'.
  18. - views a list of queries and analyzes them.
  19. - requires the admin_forum permission.
  20. - is accessed via ?action=viewquery.
  21. - strings in this function have not been internationalized.
  22. */
  23. // See the queries....
  24. function ViewQuery()
  25. {
  26. global $scripturl, $user_info, $settings, $context, $db_connection, $modSettings, $boarddir, $smcFunc, $txt, $db_show_debug;
  27. // We should have debug mode enabled, as well as something to display!
  28. if (!isset($db_show_debug) || $db_show_debug !== true || !isset($_SESSION['debug']))
  29. fatal_lang_error('no_access', false);
  30. // Don't allow except for administrators.
  31. isAllowedTo('admin_forum');
  32. // If we're just hiding/showing, do it now.
  33. if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'hide')
  34. {
  35. $_SESSION['view_queries'] = $_SESSION['view_queries'] == 1 ? 0 : 1;
  36. if (strpos($_SESSION['old_url'], 'action=viewquery') !== false)
  37. redirectexit();
  38. else
  39. redirectexit($_SESSION['old_url']);
  40. }
  41. call_integration_hook('integrate_egg_nog');
  42. $query_id = isset($_REQUEST['qq']) ? (int) $_REQUEST['qq'] - 1 : -1;
  43. echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  44. <html xmlns="http://www.w3.org/1999/xhtml"', $context['right_to_left'] ? ' dir="rtl"' : '', '>
  45. <head>
  46. <title>', $context['forum_name_html_safe'], '</title>
  47. <link rel="stylesheet" type="text/css" href="', $settings['theme_url'], '/css/index.css" />
  48. <style type="text/css">
  49. body
  50. {
  51. margin: 1ex;
  52. }
  53. body, td, th, .normaltext
  54. {
  55. font-size: x-small;
  56. }
  57. .smalltext
  58. {
  59. font-size: xx-small;
  60. }
  61. </style>
  62. </head>
  63. <body id="help_popup">
  64. <div class="tborder windowbg description">';
  65. foreach ($_SESSION['debug'] as $q => $query_data)
  66. {
  67. // Fix the indentation....
  68. $query_data['q'] = ltrim(str_replace("\r", '', $query_data['q']), "\n");
  69. $query = explode("\n", $query_data['q']);
  70. $min_indent = 0;
  71. foreach ($query as $line)
  72. {
  73. preg_match('/^(\t*)/', $line, $temp);
  74. if (strlen($temp[0]) < $min_indent || $min_indent == 0)
  75. $min_indent = strlen($temp[0]);
  76. }
  77. foreach ($query as $l => $dummy)
  78. $query[$l] = substr($dummy, $min_indent);
  79. $query_data['q'] = implode("\n", $query);
  80. // Make the filenames look a bit better.
  81. if (isset($query_data['f']))
  82. $query_data['f'] = preg_replace('~^' . preg_quote($boarddir, '~') . '~', '...', $query_data['f']);
  83. $is_select_query = strpos(trim($query_data['q']), 'SELECT') === 0;
  84. if ($is_select_query)
  85. $select = $query_data['q'];
  86. elseif (preg_match('~^INSERT(?: IGNORE)? INTO \w+(?:\s+\([^)]+\))?\s+(SELECT .+)$~s', trim($query_data['q']), $matches) != 0)
  87. {
  88. $is_select_query = true;
  89. $select = $matches[1];
  90. }
  91. elseif (preg_match('~^CREATE TEMPORARY TABLE .+?(SELECT .+)$~s', trim($query_data['q']), $matches) != 0)
  92. {
  93. $is_select_query = true;
  94. $select = $matches[1];
  95. }
  96. // Temporary tables created in earlier queries are not explainable.
  97. if ($is_select_query)
  98. {
  99. foreach (array('log_topics_unread', 'topics_posted_in', 'tmp_log_search_topics', 'tmp_log_search_messages') as $tmp)
  100. if (strpos($select, $tmp) !== false)
  101. {
  102. $is_select_query = false;
  103. break;
  104. }
  105. }
  106. echo '
  107. <div id="qq', $q, '" style="margin-bottom: 2ex;">
  108. <a', $is_select_query ? ' href="' . $scripturl . '?action=viewquery;qq=' . ($q + 1) . '#qq' . $q . '"' : '', ' style="font-weight: bold; text-decoration: none;">
  109. ', nl2br(str_replace("\t", '&nbsp;&nbsp;&nbsp;', htmlspecialchars($query_data['q']))), '
  110. </a><br />';
  111. if (!empty($query_data['f']) && !empty($query_data['l']))
  112. echo sprintf($txt['debug_query_in_line'], $query_data['f'], $query_data['l']);
  113. if (isset($query_data['s'], $query_data['t']) && isset($txt['debug_query_which_took_at']))
  114. echo sprintf($txt['debug_query_which_took_at'], round($query_data['t'], 8), round($query_data['s'], 8));
  115. else
  116. echo sprintf($txt['debug_query_which_took'], round($query_data['t'], 8));
  117. echo '
  118. </div>';
  119. // Explain the query.
  120. if ($query_id == $q && $is_select_query)
  121. {
  122. $result = $smcFunc['db_query']('', '
  123. EXPLAIN ' . $select,
  124. array(
  125. )
  126. );
  127. if ($result === false)
  128. {
  129. echo '
  130. <table border="1" cellpadding="4" cellspacing="0" style="empty-cells: show; font-family: serif; margin-bottom: 2ex;">
  131. <tr><td>', $smcFunc['db_error']($db_connection), '</td></tr>
  132. </table>';
  133. continue;
  134. }
  135. echo '
  136. <table border="1" rules="all" cellpadding="4" cellspacing="0" style="empty-cells: show; font-family: serif; margin-bottom: 2ex;">';
  137. $row = $smcFunc['db_fetch_assoc']($result);
  138. echo '
  139. <tr>
  140. <th>' . implode('</th>
  141. <th>', array_keys($row)) . '</th>
  142. </tr>';
  143. $smcFunc['db_data_seek']($result, 0);
  144. while ($row = $smcFunc['db_fetch_assoc']($result))
  145. {
  146. echo '
  147. <tr>
  148. <td>' . implode('</td>
  149. <td>', $row) . '</td>
  150. </tr>';
  151. }
  152. $smcFunc['db_free_result']($result);
  153. echo '
  154. </table>';
  155. }
  156. }
  157. echo '
  158. </div>
  159. </body>
  160. </html>';
  161. obExit(false);
  162. }
  163. ?>