3 V5.14 8 Sept 2011 (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved.
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence. See License.txt.
7 Set tabs to 4 for best viewing.
9 Latest version is available at http://adodb.sourceforge.net
11 Library for basic performance monitoring and tuning.
13 My apologies if you see code mixed with presentation. The presentation suits
14 my needs. If you want to separate code from presentation, be my guest. Patches
19 if (!defined('ADODB_DIR')) include_once(dirname(__FILE__
).'/adodb.inc.php');
20 include_once(ADODB_DIR
.'/tohtml.inc.php');
22 define( 'ADODB_OPT_HIGH', 2);
23 define( 'ADODB_OPT_LOW', 1);
25 global $ADODB_PERF_MIN;
26 $ADODB_PERF_MIN = 0.05; // log only if >= minimum number of secs to run
29 // returns in K the memory of current process, or 0 if not known
30 function adodb_getmem()
32 if (function_exists('memory_get_usage'))
33 return (integer) ((memory_get_usage()+
512)/1024);
37 if ( strncmp(strtoupper(PHP_OS
),'WIN',3)==0) {
40 exec('tasklist /FI "PID eq ' . $pid. '" /FO LIST', $output);
41 return substr($output[5], strpos($output[5], ':') +
1);
45 exec("ps --pid $pid --no-headers -o%mem,size", $output);
46 if (sizeof($output) == 0) return 0;
48 $memarr = explode(' ',$output[0]);
49 if (sizeof($memarr)>=2) return (integer) $memarr[1];
54 // avoids localization problems where , is used instead of .
55 function adodb_round($n,$prec)
57 return number_format($n, $prec, '.', '');
60 /* obsolete: return microtime value as a float. Retained for backward compat */
61 function adodb_microtime()
63 return microtime(true);
67 function adodb_log_sql(&$connx,$sql,$inputarr)
69 $perf_table = adodb_perf
::table();
70 $connx->fnExecute
= false;
71 $a0 = microtime(true);
72 $rs = $connx->Execute($sql,$inputarr);
73 $a1 = microtime(true);
75 if (!empty($connx->_logsql
) && (empty($connx->_logsqlErrors
) ||
!$rs)) {
76 global $ADODB_LOG_CONN;
78 if (!empty($ADODB_LOG_CONN)) {
79 $conn = $ADODB_LOG_CONN;
80 if ($conn->databaseType
!= $connx->databaseType
)
81 $prefix = '/*dbx='.$connx->databaseType
.'*/ ';
89 $conn->_logsql
= false; // disable logsql error simulation
90 $dbT = $conn->databaseType
;
95 $errM = $connx->ErrorMsg();
96 $errN = $connx->ErrorNo();
98 $tracer = substr('ERROR: '.htmlspecialchars($errM),0,250);
104 $conn->debug
= false;
105 if (!is_object($rs) ||
$rs->dataProvider
== 'empty')
106 $conn->_affected
= $conn->affected_rows(true);
107 $conn->lastInsID
= @$conn->Insert_ID();
110 if (isset($_SERVER['HTTP_HOST'])) {
111 $tracer .= '<br>'.$_SERVER['HTTP_HOST'];
112 if (isset($_SERVER['PHP_SELF'])) $tracer .= htmlspecialchars($_SERVER['PHP_SELF']);
114 if (isset($_SERVER['PHP_SELF'])) $tracer .= '<br>'.htmlspecialchars($_SERVER['PHP_SELF']);
115 //$tracer .= (string) adodb_backtrace(false);
117 $tracer = (string) substr($tracer,0,500);
119 if (is_array($inputarr)) {
120 if (is_array(reset($inputarr))) $params = 'Array sizeof='.sizeof($inputarr);
122 // Quote string parameters so we can see them in the
123 // performance stats. This helps spot disabled indexes.
124 $xar_params = $inputarr;
125 foreach ($xar_params as $xar_param_key => $xar_param) {
126 if (gettype($xar_param) == 'string')
127 $xar_params[$xar_param_key] = '"' . $xar_param . '"';
129 $params = implode(', ', $xar_params);
130 if (strlen($params) >= 3000) $params = substr($params, 0, 3000);
136 if (is_array($sql)) $sql = $sql[0];
137 if ($prefix) $sql = $prefix.$sql;
138 $arr = array('b'=>strlen($sql).'.'.crc32($sql),
139 'c'=>substr($sql,0,3900), 'd'=>$params,'e'=>$tracer,'f'=>adodb_round($time,6));
141 $saved = $conn->debug
;
144 $d = $conn->sysTimeStamp
;
145 if (empty($d)) $d = date("'Y-m-d H:i:s'");
146 if ($conn->dataProvider
== 'oci8' && $dbT != 'oci8po') {
147 $isql = "insert into $perf_table values($d,:b,:c,:d,:e,:f)";
148 } else if ($dbT == 'odbc_mssql' ||
$dbT == 'informix' ||
strncmp($dbT,'odbtp',4)==0) {
150 if ($dbT == 'informix') $sql2 = substr($sql2,0,230);
152 $sql1 = $conn->qstr($arr['b']);
153 $sql2 = $conn->qstr($arr['c']);
154 $params = $conn->qstr($arr['d']);
155 $tracer = $conn->qstr($arr['e']);
157 $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values($d,$sql1,$sql2,$params,$tracer,$timer)";
158 if ($dbT == 'informix') $isql = str_replace(chr(10),' ',$isql);
161 if ($dbT == 'db2') $arr['f'] = (float) $arr['f'];
162 $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values( $d,?,?,?,?,?)";
165 global $ADODB_PERF_MIN;
166 if ($errN != 0 ||
$time >= $ADODB_PERF_MIN) {
167 $ok = $conn->Execute($isql,$arr);
171 $conn->debug
= $saved;
174 $conn->_logsql
= true;
176 $err2 = $conn->ErrorMsg();
177 $conn->_logsql
= true; // enable logsql error simulation
178 $perf = NewPerfMonitor($conn);
180 if ($perf->CreateLogTable()) $ok = $conn->Execute($isql,$arr);
182 $ok = $conn->Execute("create table $perf_table (
186 params varchar(3000),
188 timer decimal(16,6))");
191 ADOConnection
::outp( "<p><b>LOGSQL Insert Failed</b>: $isql<br>$err2</p>");
192 $conn->_logsql
= false;
195 $connx->_errorMsg
= $errM;
196 $connx->_errorCode
= $errN;
198 $connx->fnExecute
= 'adodb_log_sql';
204 The settings data structure is an associative array that database parameter per element.
206 Each database parameter element in the array is itself an array consisting of:
208 0: category code, used to group related db parameters
210 a. sql string to retrieve value, eg. "select value from v\$parameter where name='db_block_size'",
211 b. array holding sql string and field to look for, e.g. array('show variables','table_cache'),
212 c. a string prefixed by =, then a PHP method of the class is invoked,
213 e.g. to invoke $this->GetIndexValue(), set this array element to '=GetIndexValue',
214 2: description of the database parameter
219 var $color = '#F0F0F0';
220 var $table = '<table border=1 bgcolor=white>';
221 var $titles = '<tr><td><b>Parameter</b></td><td><b>Value</b></td><td><b>Description</b></td></tr>';
223 var $tablesSQL = false;
224 var $cliFormat = "%32s => %s \r\n";
225 var $sql1 = 'sql1'; // used for casting sql1 to text for mssql
227 var $helpurl = "<a href=http://phplens.com/adodb/reference.functions.fnexecute.and.fncacheexecute.properties.html#logsql>LogSQL help</a>";
228 var $createTableSQL = false;
229 var $maxLength = 2000;
231 // Sets the tablename to be used
232 static function table($newtable = false)
236 if (!empty($newtable)) $_table = $newtable;
237 if (empty($_table)) $_table = 'adodb_logsql';
241 // returns array with info to calculate CPU Load
246 cpu 524152 2662 2515228 336057010
247 cpu0 264339 1408 1257951 168025827
248 cpu1 259813 1254 1257277 168031181
251 intr 890153570 868093576 6 0 4 4 0 6 1 2 0 0 0 124 0 8098760 2 13961053 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
252 disk_io: (3,0):(3144904,54369,610378,3090535,50936192) (3,1):(3630212,54097,633016,3576115,50951320)
258 // Algorithm is taken from
259 // http://social.technet.microsoft.com/Forums/en-US/winservergen/thread/414b0e1b-499c-411e-8a02-6a12e339c0f1/
260 if (strncmp(PHP_OS
,'WIN',3)==0) {
261 if (PHP_VERSION
== '5.0.0') return false;
262 if (PHP_VERSION
== '5.0.1') return false;
263 if (PHP_VERSION
== '5.0.2') return false;
264 if (PHP_VERSION
== '5.0.3') return false;
265 if (PHP_VERSION
== '4.3.10') return false; # see http://bugs.php.net/bug.php?id=31737
267 static $FAIL = false;
268 if ($FAIL) return false;
270 $objName = "winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\CIMV2";
271 $myQuery = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = '_Total'";
274 @$objWMIService = new COM($objName);
275 if (!$objWMIService) {
284 foreach($objWMIService->ExecQuery($myQuery) as $objItem) {
285 $info[0] = $objItem->PercentProcessorTime();
288 } catch(Exception
$e) {
290 echo $e->getMessage();
297 // Algorithm - Steve Blinch (BlitzAffe Online, http://www.blitzaffe.com)
298 $statfile = '/proc/stat';
299 if (!file_exists($statfile)) return false;
301 $fd = fopen($statfile,"r");
302 if (!$fd) return false;
304 $statinfo = explode("\n",fgets($fd, 1024));
306 foreach($statinfo as $line) {
307 $info = explode(" ",$line);
308 if($info[0]=="cpu") {
309 array_shift($info); // pop off "cpu"
310 if(!$info[0]) array_shift($info); // pop off blank space (if any)
319 /* NOT IMPLEMENTED */
324 total: used: free: shared: buffers: cached:
325 Mem: 1055289344 917299200 137990144 0 165437440 599773184
326 Swap: 2146775040 11055104 2135719936
334 Inact_dirty: 322856 kB
335 Inact_clean: 24256 kB
336 Inact_target: 168316 kB
341 SwapTotal: 2096460 kB
343 Committed_AS: 348732 kB
349 Remember that this is client load, not db server load!
354 $info = $this->_CPULoad();
355 if (!$info) return false;
357 if (strncmp(PHP_OS
,'WIN',3)==0) {
358 return (integer) $info[0];
360 if (empty($this->_lastLoad
)) {
362 $this->_lastLoad
= $info;
363 $info = $this->_CPULoad();
366 $last = $this->_lastLoad
;
367 $this->_lastLoad
= $info;
369 $d_user = $info[0] - $last[0];
370 $d_nice = $info[1] - $last[1];
371 $d_system = $info[2] - $last[2];
372 $d_idle = $info[3] - $last[3];
374 //printf("Delta - User: %f Nice: %f System: %f Idle: %f<br>",$d_user,$d_nice,$d_system,$d_idle);
376 $total=$d_user+
$d_nice+
$d_system+
$d_idle;
377 if ($total<1) $total=1;
378 return 100*($d_user+
$d_nice+
$d_system)/$total;
382 function Tracer($sql)
384 $perf_table = adodb_perf
::table();
385 $saveE = $this->conn
->fnExecute
;
386 $this->conn
->fnExecute
= false;
388 global $ADODB_FETCH_MODE;
389 $save = $ADODB_FETCH_MODE;
390 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
391 if ($this->conn
->fetchMode
!== false) $savem = $this->conn
->SetFetchMode(false);
393 $sqlq = $this->conn
->qstr($sql);
394 $arr = $this->conn
->GetArray(
395 "select count(*),tracer
396 from $perf_table where sql1=$sqlq
401 $s .= '<h3>Scripts Affected</h3>';
402 foreach($arr as $k) {
403 $s .= sprintf("%4d",$k[0]).' '.strip_tags($k[1]).'<br>';
407 if (isset($savem)) $this->conn
->SetFetchMode($savem);
408 $ADODB_CACHE_MODE = $save;
409 $this->conn
->fnExecute
= $saveE;
414 Explain Plan for $sql.
415 If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the
418 function Explain($sql,$partial=false)
423 function InvalidSQL($numsql = 10)
426 if (isset($_GET['sql'])) return;
427 $s = '<h3>Invalid SQL</h3>';
428 $saveE = $this->conn
->fnExecute
;
429 $this->conn
->fnExecute
= false;
430 $perf_table = adodb_perf
::table();
431 $rs = $this->conn
->SelectLimit("select distinct count(*),sql1,tracer as error_msg from $perf_table where tracer like 'ERROR:%' group by sql1,tracer order by 1 desc",$numsql);//,$numsql);
432 $this->conn
->fnExecute
= $saveE;
434 $s .= rs2html($rs,false,false,false,false);
436 return "<p>$this->helpurl. ".$this->conn
->ErrorMsg()."</p>";
443 This script identifies the longest running SQL
445 function _SuspiciousSQL($numsql = 10)
447 global $ADODB_FETCH_MODE;
449 $perf_table = adodb_perf
::table();
450 $saveE = $this->conn
->fnExecute
;
451 $this->conn
->fnExecute
= false;
453 if (isset($_GET['exps']) && isset($_GET['sql'])) {
454 $partial = !empty($_GET['part']);
455 echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
458 if (isset($_GET['sql'])) return;
461 $save = $ADODB_FETCH_MODE;
462 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
463 if ($this->conn
->fetchMode
!== false) $savem = $this->conn
->SetFetchMode(false);
464 //$this->conn->debug=1;
465 $rs = $this->conn
->SelectLimit(
466 "select avg(timer) as avg_timer,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
468 where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
469 and (tracer is null or tracer not like 'ERROR:%')
471 order by 1 desc",$numsql);
472 if (isset($savem)) $this->conn
->SetFetchMode($savem);
473 $ADODB_FETCH_MODE = $save;
474 $this->conn
->fnExecute
= $saveE;
476 if (!$rs) return "<p>$this->helpurl. ".$this->conn
->ErrorMsg()."</p>";
477 $s = "<h3>Suspicious SQL</h3>
478 <font size=1>The following SQL have high average execution times</font><br>
479 <table border=1 bgcolor=white><tr><td><b>Avg Time</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
480 $max = $this->maxLength
;
482 $sql = $rs->fields
[1];
483 $raw = urlencode($sql);
484 if (strlen($raw)>$max-100) {
485 $sql2 = substr($sql,0,$max-500);
486 $raw = urlencode($sql2).'&part='.crc32($sql);
488 $prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".$raw."&x#explain\">";
490 if ($this->explain
== false ||
strlen($prefix)>$max) {
491 $suffix = ' ... <i>String too long for GET parameter: '.strlen($prefix).'</i>';
494 $s .= "<tr><td>".adodb_round($rs->fields
[0],6)."<td align=right>".$rs->fields
[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
495 "<td>".$rs->fields
[3]."<td>".$rs->fields
[4]."</tr>";
498 return $s."</table>";
502 function CheckMemory()
508 function SuspiciousSQL($numsql=10)
510 return adodb_perf
::_SuspiciousSQL($numsql);
513 function ExpensiveSQL($numsql=10)
515 return adodb_perf
::_ExpensiveSQL($numsql);
520 This reports the percentage of load on the instance due to the most
521 expensive few SQL statements. Tuning these statements can often
522 make huge improvements in overall system performance.
524 function _ExpensiveSQL($numsql = 10)
526 global $ADODB_FETCH_MODE;
528 $perf_table = adodb_perf
::table();
529 $saveE = $this->conn
->fnExecute
;
530 $this->conn
->fnExecute
= false;
532 if (isset($_GET['expe']) && isset($_GET['sql'])) {
533 $partial = !empty($_GET['part']);
534 echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
537 if (isset($_GET['sql'])) return;
540 $save = $ADODB_FETCH_MODE;
541 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
542 if ($this->conn
->fetchMode
!== false) $savem = $this->conn
->SetFetchMode(false);
544 $rs = $this->conn
->SelectLimit(
545 "select sum(timer) as total,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
547 where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
548 and (tracer is null or tracer not like 'ERROR:%')
551 order by 1 desc",$numsql);
552 if (isset($savem)) $this->conn
->SetFetchMode($savem);
553 $this->conn
->fnExecute
= $saveE;
554 $ADODB_FETCH_MODE = $save;
555 if (!$rs) return "<p>$this->helpurl. ".$this->conn
->ErrorMsg()."</p>";
556 $s = "<h3>Expensive SQL</h3>
557 <font size=1>Tuning the following SQL could reduce the server load substantially</font><br>
558 <table border=1 bgcolor=white><tr><td><b>Load</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
559 $max = $this->maxLength
;
561 $sql = $rs->fields
[1];
562 $raw = urlencode($sql);
563 if (strlen($raw)>$max-100) {
564 $sql2 = substr($sql,0,$max-500);
565 $raw = urlencode($sql2).'&part='.crc32($sql);
567 $prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".$raw."&x#explain\">";
569 if($this->explain
== false ||
strlen($prefix>$max)) {
573 $s .= "<tr><td>".adodb_round($rs->fields
[0],6)."<td align=right>".$rs->fields
[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
574 "<td>".$rs->fields
[3]."<td>".$rs->fields
[4]."</tr>";
577 return $s."</table>";
581 Raw function to return parameter value from $settings.
583 function DBParameter($param)
585 if (empty($this->settings
[$param])) return false;
586 $sql = $this->settings
[$param][1];
587 return $this->_DBParameter($sql);
591 Raw function returning array of poll paramters
593 function PollParameters()
595 $arr[0] = (float)$this->DBParameter('data cache hit ratio');
596 $arr[1] = (float)$this->DBParameter('data reads');
597 $arr[2] = (float)$this->DBParameter('data writes');
598 $arr[3] = (integer) $this->DBParameter('current connections');
603 Low-level Get Database Parameter
605 function _DBParameter($sql)
607 $savelog = $this->conn
->LogSQL(false);
608 if (is_array($sql)) {
609 global $ADODB_FETCH_MODE;
613 if (sizeof($sql)>2) $pos = $sql[2];
615 if (sizeof($sql)>3) $coef = $sql[3];
618 $save = $ADODB_FETCH_MODE;
619 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
620 if ($this->conn
->fetchMode
!== false) $savem = $this->conn
->SetFetchMode(false);
622 $rs = $this->conn
->Execute($sql1);
624 if (isset($savem)) $this->conn
->SetFetchMode($savem);
625 $ADODB_FETCH_MODE = $save;
628 $keyf = reset($rs->fields
);
629 if (trim($keyf) == $key) {
630 $ret = $rs->fields
[$pos];
631 if ($coef) $ret *= $coef;
638 $this->conn
->LogSQL($savelog);
641 if (strncmp($sql,'=',1) == 0) {
642 $fn = substr($sql,1);
645 $sql = str_replace('$DATABASE',$this->conn
->database
,$sql);
646 $ret = $this->conn
->GetOne($sql);
647 $this->conn
->LogSQL($savelog);
654 Warn if cache ratio falls below threshold. Displayed in "Description" column.
656 function WarnCacheRatio($val)
658 if ($val < $this->warnRatio
)
659 return '<font color=red><b>Cache ratio should be at least '.$this->warnRatio
.'%</b></font>';
665 $perf_table = adodb_perf
::table();
666 $this->conn
->Execute("delete from $perf_table where created<".$this->conn
->sysTimeStamp
);
668 /***********************************************************************************************/
669 // HIGH LEVEL UI FUNCTIONS
670 /***********************************************************************************************/
673 function UI($pollsecs=5)
675 global $ADODB_LOG_CONN;
677 $perf_table = adodb_perf
::table();
681 if ($conn->host
&& $conn->database
) $app .= ', db=';
682 $app .= $conn->database
;
684 if ($app) $app .= ', ';
685 $savelog = $this->conn
->LogSQL(false);
686 $info = $conn->ServerInfo();
687 if (isset($_GET['clearsql'])) {
690 $this->conn
->LogSQL($savelog);
694 if (isset($_GET['sql']) && get_magic_quotes_gpc()) {
695 $_GET['sql'] = $_GET['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$_GET['sql']);
698 if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10;
699 else $nsql = $_SESSION['ADODB_PERF_SQL'];
701 $app .= $info['description'];
704 if (isset($_GET['do'])) $do = $_GET['do'];
705 else if (isset($_POST['do'])) $do = $_POST['do'];
706 else if (isset($_GET['sql'])) $do = 'viewsql';
709 if (isset($_GET['nsql'])) {
710 if ($_GET['nsql'] > 0) $nsql = $_SESSION['ADODB_PERF_SQL'] = (integer) $_GET['nsql'];
712 echo "<title>ADOdb Performance Monitor on $app</title><body bgcolor=white>";
713 if ($do == 'viewsql') $form = "<td><form># SQL:<input type=hidden value=viewsql name=do> <input type=text size=4 name=nsql value=$nsql><input type=submit value=Go></td></form>";
714 else $form = "<td> </td>";
716 $allowsql = !defined('ADODB_PERF_NO_RUN_SQL');
717 global $ADODB_PERF_MIN;
718 $app .= " (Min sql timing \$ADODB_PERF_MIN=$ADODB_PERF_MIN secs)";
720 if (empty($_GET['hidem']))
721 echo "<table border=1 width=100% bgcolor=lightyellow><tr><td colspan=2>
722 <b><a href=http://adodb.sourceforge.net/?perf=1>ADOdb</a> Performance Monitor</b> <font size=1>for $app</font></tr><tr><td>
723 <a href=?do=stats><b>Performance Stats</b></a> <a href=?do=viewsql><b>View SQL</b></a>
724 <a href=?do=tables><b>View Tables</b></a> <a href=?do=poll><b>Poll Stats</b></a>",
725 $allowsql ?
' <a href=?do=dosql><b>Run SQL</b></a>' : '',
733 if (empty($ADODB_LOG_CONN))
734 echo "<p> <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
735 echo $this->HealthCheck();
736 //$this->conn->debug=1;
737 echo $this->CheckMemory();
740 $self = htmlspecialchars($_SERVER['PHP_SELF']);
741 echo "<iframe width=720 height=80%
742 src=\"{$self}?do=poll2&hidem=1\"></iframe>";
746 $this->Poll($pollsecs);
750 if (!$allowsql) break;
755 if (empty($_GET['hidem']))
756 echo " <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
757 echo($this->SuspiciousSQL($nsql));
758 echo($this->ExpensiveSQL($nsql));
759 echo($this->InvalidSQL($nsql));
762 echo $this->Tables(); break;
765 echo "<p><div align=center><font size=1>$ADODB_vers Sponsored by <a href=http://phplens.com/>phpLens</a></font></div>";
769 Runs in infinite loop, returning real-time statistics
771 function Poll($secs=5)
773 $this->conn
->fnExecute
= false;
774 //$this->conn->debug=1;
775 if ($secs <= 1) $secs = 1;
776 echo "Accumulating statistics, every $secs seconds...\n";flush();
777 $arro = $this->PollParameters();
783 $arr = $this->PollParameters();
785 $hits = sprintf('%2.2f',$arr[0]);
786 $reads = sprintf('%12.4f',($arr[1]-$arro[1])/$secs);
787 $writes = sprintf('%12.4f',($arr[2]-$arro[2])/$secs);
788 $sess = sprintf('%5d',$arr[3]);
790 $load = $this->CPULoad();
791 if ($load !== false) {
792 $oslabel = 'WS-CPU%';
793 $osval = sprintf(" %2.1f ",(float) $load);
798 if ($cnt %
10 == 0) echo " Time ".$oslabel." Hit% Sess Reads/s Writes/s\n";
800 echo date('H:i:s').' '.$osval."$hits $sess $reads $writes\n";
803 if (connection_aborted()) return;
811 Returns basic health check in a command line interface
813 function HealthCheckCLI()
815 return $this->HealthCheck(true);
820 Returns basic health check as HTML
822 function HealthCheck($cli=false)
824 $saveE = $this->conn
->fnExecute
;
825 $this->conn
->fnExecute
= false;
826 if ($cli) $html = '';
827 else $html = $this->table
.'<tr><td colspan=3><h3>'.$this->conn
->databaseType
.'</h3></td></tr>'.$this->titles
;
831 foreach($this->settings
as $name => $arr) {
832 if ($arr === false) break;
834 if (!is_string($name)) {
835 if ($cli) $html .= " -- $arr -- \n";
836 else $html .= "<tr bgcolor=$this->color><td colspan=3><i>$arr</i> </td></tr>";
840 if (!is_array($arr)) break;
843 if (sizeof($arr)>2) $desc = $arr[2];
844 else $desc = ' ';
847 if ($category == 'HIDE') continue;
849 $val = $this->_DBParameter($how);
851 if ($desc && strncmp($desc,"=",1) === 0) {
852 $fn = substr($desc,1);
853 $desc = $this->$fn($val);
856 if ($val === false) {
857 $m = $this->conn
->ErrorMsg();
860 if (is_numeric($val) && $val >= 256*1024) {
861 if ($val %
(1024*1024) == 0) {
864 } else if ($val %
1024 == 0) {
868 //$val = htmlspecialchars($val);
871 if ($category != $oldc) {
873 //$bgc = ($bgc == ' bgcolor='.$this->color) ? ' bgcolor=white' : ' bgcolor='.$this->color;
875 if (strlen($desc)==0) $desc = ' ';
876 if (strlen($val)==0) $val = ' ';
878 $html .= str_replace(' ','',sprintf($this->cliFormat
,strip_tags($name),strip_tags($val),strip_tags($desc)));
881 $html .= "<tr$bgc><td>".$name.'</td><td>'.$val.'</td><td>'.$desc."</td></tr>\n";
885 if (!$cli) $html .= "</table>\n";
886 $this->conn
->fnExecute
= $saveE;
891 function Tables($orderby='1')
893 if (!$this->tablesSQL
) return false;
895 $savelog = $this->conn
->LogSQL(false);
896 $rs = $this->conn
->Execute($this->tablesSQL
.' order by '.$orderby);
897 $this->conn
->LogSQL($savelog);
898 $html = rs2html($rs,false,false,false,false);
903 function CreateLogTable()
905 if (!$this->createTableSQL
) return false;
907 $table = $this->table();
908 $sql = str_replace('adodb_logsql',$table,$this->createTableSQL
);
909 $savelog = $this->conn
->LogSQL(false);
910 $ok = $this->conn
->Execute($sql);
911 $this->conn
->LogSQL($savelog);
912 return ($ok) ?
true : false;
919 $PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']);
920 $sql = isset($_REQUEST['sql']) ?
$_REQUEST['sql'] : '';
922 if (isset($_SESSION['phplens_sqlrows'])) $rows = $_SESSION['phplens_sqlrows'];
925 if (isset($_REQUEST['SMALLER'])) {
927 if ($rows < 3) $rows = 3;
928 $_SESSION['phplens_sqlrows'] = $rows;
930 if (isset($_REQUEST['BIGGER'])) {
932 $_SESSION['phplens_sqlrows'] = $rows;
937 <form method
="POST" action
="<?php echo $PHP_SELF ?>">
939 <td
> Form size
: <input type
="submit" value
=" < " name
="SMALLER"><input type
="submit" value
=" > > " name
="BIGGER">
942 <input type
="submit" value
=" Run SQL Below " name
="RUN"><input type
=hidden name
=do value
=dosql
>
945 <td colspan
=2><textarea rows
=<?php
print $rows; ?
> name
="sql" cols
="80"><?php
print htmlspecialchars($sql) ?
></textarea
>
952 if (!isset($_REQUEST['sql'])) return;
954 $sql = $this->undomq(trim($sql));
955 if (substr($sql,strlen($sql)-1) === ';') {
957 $sqla = $this->SplitSQL($sql);
962 foreach($sqla as $sqls) {
964 if (!$sqls) continue;
967 print "<p>".htmlspecialchars($sqls)."</p>";
970 $savelog = $this->conn
->LogSQL(false);
971 $rs = $this->conn
->Execute($sqls);
972 $this->conn
->LogSQL($savelog);
973 if ($rs && is_object($rs) && !$rs->EOF
) {
975 while ($rs->NextRecordSet()) {
976 print "<table width=98% bgcolor=#C0C0FF><tr><td> </td></tr></table>";
980 $e1 = (integer) $this->conn
->ErrorNo();
981 $e2 = $this->conn
->ErrorMsg();
982 if (($e1) ||
($e2)) {
983 if (empty($e1)) $e1 = '-1'; // postgresql fix
984 print ' '.$e1.': '.$e2;
986 print "<p>No Recordset returned<br></p>";
992 function SplitSQL($sql)
994 $arr = explode(';',$sql);
1000 if (get_magic_quotes_gpc()) {
1002 $m = str_replace('\\\\','\\',$m);
1003 $m = str_replace('\"','"',$m);
1004 $m = str_replace('\\\'','\'',$m);
1010 /************************************************************************/
1013 * Reorganise multiple table-indices/statistics/..
1014 * OptimizeMode could be given by last Parameter
1018 * optimizeTables( 'tableA');
1021 * optimizeTables( 'tableA', 'tableB', 'tableC');
1024 * optimizeTables( 'tableA', 'tableB', ADODB_OPT_LOW);
1027 * @param string table name of the table to optimize
1028 * @param int mode optimization-mode
1029 * <code>ADODB_OPT_HIGH</code> for full optimization
1030 * <code>ADODB_OPT_LOW</code> for CPU-less optimization
1031 * Default is LOW <code>ADODB_OPT_LOW</code>
1032 * @author Markus Staab
1033 * @return Returns <code>true</code> on success and <code>false</code> on error
1035 function OptimizeTables()
1037 $args = func_get_args();
1038 $numArgs = func_num_args();
1040 if ( $numArgs == 0) return false;
1042 $mode = ADODB_OPT_LOW
;
1043 $lastArg = $args[ $numArgs - 1];
1044 if ( !is_string($lastArg)) {
1046 unset( $args[ $numArgs - 1]);
1049 foreach( $args as $table) {
1050 $this->optimizeTable( $table, $mode);
1055 * Reorganise the table-indices/statistics/.. depending on the given mode.
1056 * Default Implementation throws an error.
1058 * @param string table name of the table to optimize
1059 * @param int mode optimization-mode
1060 * <code>ADODB_OPT_HIGH</code> for full optimization
1061 * <code>ADODB_OPT_LOW</code> for CPU-less optimization
1062 * Default is LOW <code>ADODB_OPT_LOW</code>
1063 * @author Markus Staab
1064 * @return Returns <code>true</code> on success and <code>false</code> on error
1066 function OptimizeTable( $table, $mode = ADODB_OPT_LOW
)
1068 ADOConnection
::outp( sprintf( "<p>%s: '%s' not implemented for driver '%s'</p>", __CLASS__
, __FUNCTION__
, $this->conn
->databaseType
));
1073 * Reorganise current database.
1074 * Default implementation loops over all <code>MetaTables()</code> and
1075 * optimize each using <code>optmizeTable()</code>
1077 * @author Markus Staab
1078 * @return Returns <code>true</code> on success and <code>false</code> on error
1080 function optimizeDatabase()
1082 $conn = $this->conn
;
1083 if ( !$conn) return false;
1085 $tables = $conn->MetaTables( 'TABLES');
1086 if ( !$tables ) return false;
1088 foreach( $tables as $table) {
1089 if ( !$this->optimizeTable( $table)) {