1: <?php
2: require_once('./qcubed.inc.php');
3:
4:
5: if ( !isset($_POST['intDatabaseIndex']) && !isset($_POST['strProfileData']) && !isset($_POST['strReferrer']) )
6: exit('Nothing to profile. No Database Profiling data recived.');
7:
8: if ( !isset($_POST['intDatabaseIndex']) || !isset($_POST['strProfileData']) || !isset($_POST['strReferrer']) )
9: throw new Exception('Database Profiling data appears to have been corrupted.');
10:
11: $intDatabaseIndex = intval($_POST['intDatabaseIndex']);
12: $strReferrer = QApplication::HtmlEntities($_POST['strReferrer']);
13:
14: $objProfileArray = unserialize(base64_decode($_POST['strProfileData']));
15: $objProfileArray = QType::Cast($objProfileArray, QType::ArrayType);
16: $intCount = count($objProfileArray);
17:
18: function PrintExplainStatement($strOriginalQuery) {
19: global $intDatabaseIndex;
20: if (substr_count($strOriginalQuery, "AUTOCOMMIT=1") > 0) {
21: return null;
22: }
23: $result = "";
24:
25: $objDb = QApplication::$Database[$intDatabaseIndex];
26: $objDbResult = $objDb->ExplainStatement($strOriginalQuery);
27: if (!$objDbResult) {
28: return "";
29: }
30:
31: $result .= "<table class='explainTable' border=1>";
32: $headersShown = false;
33: while ($mixRow = $objDbResult->FetchArray()) {
34: if (!$headersShown) {
35: $result .= "<thead class='header'>";
36: foreach ($mixRow as $key=>$value) {
37: if (!is_numeric($key)) {
38: $result .= "<td>" . $key . "</td>";
39: $headersShown = true;
40: }
41: }
42: $result .= '</thead>';
43: }
44: $result .= "<tr>";
45: foreach ($mixRow as $key=>$value) {
46: if (!is_numeric($key)) {
47: $result .= "<td>" . $value . "</td>";
48: }
49: }
50: $result .= "</tr>";
51: }
52: $result .= "</table>";
53: return $result;
54: }
55:
56: $strJsFileArray = explode(",", __JQUERY_BASE__);
57: ?>
58: <!DOCTYPE html>
59: <html>
60: <head>
61: <title>QCubed Development Framework - Database Profiling Tool</title>
62: <style type="text/css">@import url("<?php _p(__VIRTUAL_DIRECTORY__ . __CSS_ASSETS__); ?>/corepage.css");</style>
63: <?php
64: foreach ($strJsFileArray as $strJsFile) {
65: if (false !== strpos($strJsFile, "http")) {
66: ?>
67: <script type="text/javascript" src="<?php _p($strJsFile); ?>"></script>
68: <?php
69: } else {
70: $strSlash = '';
71: if (0 !== strpos($strJsFile, "/")) {
72: $strSlash = '/';
73: }
74: ?>
75: <script type="text/javascript" src="<?php _p(__VIRTUAL_DIRECTORY__ . __JS_ASSETS__ . $strSlash . $strJsFile); ?>"></script>
76: <?php
77: }
78: }
79: ?>
80: <script type="text/javascript">
81: function Toggle(strWhatId) {
82: var obj = document.getElementById(strWhatId);
83: var objButton = document.getElementById("button" + strWhatId);
84:
85: if (obj && objButton) {
86: if (obj.style.display == "block") {
87: obj.style.display = "none";
88: objButton.innerHTML = objButton.innerHTML.replace("Hide", "Show");
89: }
90:
91: else {
92: obj.style.display = "block";
93: objButton.innerHTML = objButton.innerHTML.replace("Show", "Hide");
94: }
95: }
96: return false;
97: }
98:
99: function ShowAll() {
100: jQuery(".querySection, .explainSection").each(function() {
101: if ($(this).css('display') == "none") {
102: Toggle(this.id);
103: }
104: });
105:
106: return false;
107: }
108:
109: function HideAll() {
110: jQuery(".querySection, .explainSection").each(function() {
111: if ($(this).css('display') == "block") {
112: Toggle(this.id);
113: }
114: });
115: return false;
116: }
117: </script>
118: <style>
119: .explainTable {
120: border: 1px solid black;
121: border-collapse:collapse;
122: margin-top: 5px;
123: }
124: .explainTable td {
125: padding: 4px;
126: }
127: .explainTable .header td {
128: background:
129: font-weight: bold;
130: }
131: </style>
132: </head>
133: <body>
134: <div id="container">
135: <div id="headerContainer">
136: <div id="headerBorder">
137: <div id="header">
138: <div id="hleft">
139: <span class="hsmall">QCubed Development Framework <?= QCUBED_VERSION_NUMBER_ONLY ?></span><br/>
140: <span class="hbig">Database Profiling Tool</span>
141: </div>
142: <div id="hright">
143: <b>Database Index:</b> <?php _p($intDatabaseIndex); ?>
144: <b>Database Type:</b> <?php _p(QApplication::$Database[$intDatabaseIndex]->Adapter); ?><br/>
145: <b>Database Server:</b> <?php _p(QApplication::$Database[$intDatabaseIndex]->Server); ?>
146: <b>Database Name:</b> <?php _p(QApplication::$Database[$intDatabaseIndex]->Database); ?><br/>
147: <b>Profile Generated From:</b> <?php _p($strReferrer, false); ?>
148: </div>
149: <div class="clear"></div>
150: </div>
151: </div>
152: </div>
153: </div>
154:
155: <div id="content">
156: <span class="title">
157: <?php
158: switch ($intCount) {
159: case 0: _p('<b>There were no queries that were performed.</b>', false); break;
160: case 1: _p('<b>There was 1 query that was performed.</b>', false); break;
161: default: printf('<b>There were %s queries that were performed.</b>', $intCount); break;
162: };
163: ?>
164: </span>
165: <br/>
166: <br/>
167: <a href="#" onClick="return ShowAll();" class="smallbutton">Show All</a>
168: <a href="#" onClick="return HideAll();" class="smallbutton">Hide All</a>
169: <br/>
170: <br/>
171: <?php
172: $intIndex = 1;
173:
174: foreach( $objProfileArray as $objProfile) {
175: $objBacktrace = $objProfile['objBacktrace'];
176: $strQuery = $objProfile['strQuery'];
177: $dblTimeInfo = $objProfile['dblTimeInfo'];
178:
179: $objArgs = (array_key_exists('args', $objBacktrace)) ? $objBacktrace['args'] : array();
180: $strClass = (array_key_exists('class', $objBacktrace)) ? $objBacktrace['class'] : null;
181: $strType = (array_key_exists('type', $objBacktrace)) ? $objBacktrace['type'] : null;
182: $strFunction = (array_key_exists('function', $objBacktrace)) ? $objBacktrace['function'] : null;
183: $strFile = (array_key_exists('file', $objBacktrace)) ? $objBacktrace['file'] : null;
184: $strLine = (array_key_exists('line', $objBacktrace)) ? $objBacktrace['line'] : null;
185: ?>
186: <span class="function">
187: Called by <?php _p($strClass . $strType . $strFunction . '(' . implode(', ', $objArgs) . ')'); ?>
188: </span> <br/>
189: <span class="function_details">
190: <b>File: </b><?php _p($strFile); ?>; <b>Line: </b><?php _p($strLine); ?>
191: </span>
192: <?php
193:
194: if($dblTimeInfo >= 1)
195: echo('<div class="time slow">');
196: else
197: echo'<div class="time">';
198: printf("Query took %.1f ms", $dblTimeInfo * 1000);
199: ?>
200: <?php $explainStatement = PrintExplainStatement($strQuery); ?>
201: <a href="#" onClick="return Toggle('query<?php _p($intIndex); ?>')" id="buttonquery<?php _p($intIndex); ?>" class="queryButton smallbutton">
202: Show SQL
203: </a>
204: <?php if ($explainStatement) { ?>
205:
206: <a href="#" onClick="return Toggle('explain<?php _p($intIndex); ?>')" id="buttonexplain<?php _p($intIndex); ?>" class="explainButton smallbutton">
207: Show EXPLAIN statement
208: </a>
209: <?php } ?>
210:
211: <pre id="query<?php _p($intIndex); ?>" style="display: none" class="querySection"><code><?php _p($strQuery); ?></code></pre>
212: <div id="explain<?php _p($intIndex); ?>" style="display: none" class="explainSection"><?= $explainStatement; ?></div>
213: <?php
214: echo '</div>';
215: ?>
216: <br/>
217: <?php
218: $intIndex++;
219: }
220: ?> </div>
221: </div>
222: <script>
223: if (<?php _p($intCount); ?> <= 5) ShowAll();
224: </script>
225: </body>
226: </html>