2 /* vim: set expandtab sw=4 ts=4 sts=4: */
5 * @author Alexander Rutkowski
11 require_once './libraries/common.inc.php';
12 require_once './libraries/Table.class.php';
14 require './libraries/tbl_common.php';
15 $url_query .= '&goto=tbl_tracking.php&back=tbl_tracking.php';
16 $url_params['goto'] = 'tbl_tracking.php';;
17 $url_params['back'] = 'tbl_tracking.php';
19 // Get relation settings
20 require_once './libraries/relation.lib.php';
22 // Init vars for tracking report
23 if(isset($_REQUEST['report']) or isset($_REQUEST['report_export']))
25 $data = PMA_Tracker
::getTrackedData($_REQUEST['db'], $_REQUEST['table'], $_REQUEST['version']);
27 $selection_schema = '';
31 if(!isset($_REQUEST['logtype']))
32 $_REQUEST['logtype'] = 'schema_and_data';
34 if($_REQUEST['logtype'] == 'schema')
35 $selection_schema = 'selected';
36 else if($_REQUEST['logtype'] == 'data')
37 $selection_data = 'selected';
39 $selection_both = 'selected';
41 if(!isset($_REQUEST['date_from']))
42 $_REQUEST['date_from'] = $data['date_from'];
43 if(!isset($_REQUEST['date_to']))
44 $_REQUEST['date_to'] = $data['date_to'];
46 if(!isset($_REQUEST['users']))
47 $_REQUEST['users'] = '*';
49 $filter_ts_from = strtotime($_REQUEST['date_from']);
50 $filter_ts_to = strtotime($_REQUEST['date_to']);
51 $filter_users = array_map('trim', explode(',', $_REQUEST['users']));
55 if(isset($_REQUEST['report_export']))
57 // Filtering data definition statements
58 if($_REQUEST['logtype'] == 'schema' or $_REQUEST['logtype'] == 'schema_and_data')
61 foreach( $data['ddlog'] as $entry )
63 $timestamp = strtotime($entry['date']);
65 if( $timestamp >= $filter_ts_from and $timestamp <= $filter_ts_to and
66 ( in_array('*', $filter_users) or in_array($entry['username'], $filter_users) ) )
67 $entries[] = array( 'id' => $id,
68 'timestamp' => $timestamp,
69 'username' => $entry['username'],
70 'statement' => $entry['statement']
77 // Filtering data manipulation statments
78 if($_REQUEST['logtype'] == 'data' or $_REQUEST['logtype'] == 'schema_and_data')
81 foreach( $data['dmlog'] as $entry )
83 $timestamp = strtotime($entry['date']);
85 if( $timestamp >= $filter_ts_from and $timestamp <= $filter_ts_to and
86 ( in_array('*', $filter_users) or in_array($entry['username'], $filter_users) ) )
87 $entries[] = array( 'id' => $id,
88 'timestamp' => $timestamp,
89 'username' => $entry['username'],
90 'statement' => $entry['statement']
98 foreach ($entries as $key => $row)
100 $ids[$key] = $row['id'];
101 $timestamps[$key] = $row['timestamp'];
102 $usernames[$key] = $row['username'];
103 $statements[$key] = $row['statement'];
106 array_multisort($timestamps, SORT_ASC
, $ids, SORT_ASC
, $usernames, SORT_ASC
, $statements, SORT_ASC
, $entries);
111 // Export as file download
112 if(isset($_REQUEST['report_export']) and $_REQUEST['export_type'] == 'sqldumpfile')
115 @ini_set
('url_rewriter.tags','');
117 $dump = "# Tracking report for table `" . $_REQUEST['table'] . "`\n" .
118 "# " . date('Y-m-d H:i:s') . "\n";
119 foreach($entries as $entry)
120 $dump .= $entry['statement'];
122 $filename = 'log_' . $_REQUEST['table'] . '.sql';
123 header('Content-Type: text/x-sql');
124 header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
125 header('Content-Disposition: attachment; filename="' . $filename . '"');
126 if (PMA_USR_BROWSER_AGENT
== 'IE')
128 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
129 header('Pragma: public');
133 header('Pragma: no-cache');
134 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
143 * Gets tables informations
146 //require './libraries/tbl_info.inc.php';
149 * Displays top menu links
151 require_once './libraries/tbl_links.inc.php';
161 // Create tracking version
162 if(isset($_REQUEST['submit_create_version']))
166 if($_REQUEST['alter_table'] == true)
167 $tracking_set .= 'ALTER TABLE,';
168 if($_REQUEST['rename_table'] == true)
169 $tracking_set .= 'RENAME TABLE,';
170 if($_REQUEST['create_table'] == true)
171 $tracking_set .= 'CREATE TABLE,';
172 if($_REQUEST['drop_table'] == true)
173 $tracking_set .= 'DROP TABLE,';
174 if($_REQUEST['create_index'] == true)
175 $tracking_set .= 'CREATE INDEX,';
176 if($_REQUEST['drop_index'] == true)
177 $tracking_set .= 'DROP INDEX,';
178 if($_REQUEST['insert'] == true)
179 $tracking_set .= 'INSERT,';
180 if($_REQUEST['update'] == true)
181 $tracking_set .= 'UPDATE,';
182 if($_REQUEST['delete'] == true)
183 $tracking_set .= 'DELETE,';
184 if($_REQUEST['truncate'] == true)
185 $tracking_set .= 'TRUNCATE,';
187 $tracking_set = rtrim($tracking_set, ',');
189 if(PMA_Tracker
::createVersion($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version'], $tracking_set ))
191 $msg = PMA_Message
::success(sprintf($strTrackingVersionCreated, $_REQUEST['version'], $GLOBALS['db'], $GLOBALS['table']));
196 // Deactivate tracking
197 if(isset($_REQUEST['submit_deactivate_now']))
199 if(PMA_Tracker
::deactivateTracking($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version']))
201 $msg = PMA_Message
::success(sprintf($strTrackingVersionDeactivated, $GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version']));
207 if(isset($_REQUEST['submit_activate_now']))
209 if(PMA_Tracker
::activateTracking($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version']))
211 $msg = PMA_Message
::success(sprintf($strTrackingVersionActivated, $GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version']));
216 // Export as SQL execution
217 if(isset($_REQUEST['report_export']) and $_REQUEST['export_type'] == 'execution')
219 foreach($entries as $entry)
220 $sql_result = PMA_DBI_query( "/*NOTRACK*/\n" . $entry['statement'] );
222 $msg = PMA_Message
::success($strTrackingSQLExecuted);
226 // Export as SQL dump
227 if(isset($_REQUEST['report_export']) and $_REQUEST['export_type'] == 'sqldump')
229 $new_query = "# You can execute the dump by creating and using a temporary table. Please ensure that you have the privileges to do that. \n" .
230 "# Comment out or remove these two lines if you don't need them. \n" .
232 "CREATE database IF NOT EXISTS pma_temp_db; \n" .
233 "USE pma_temp_db; \n" .
235 "/* BEGIN OF SQL DUMP */ \n";
237 foreach($entries as $entry)
238 $new_query .= $entry['statement'];
240 $msg = PMA_Message
::success($strTrackingSQLExported);
244 $table_temp = $table;
247 $GLOBALS['js_include'][] = 'functions.js';
248 require_once './libraries/sql_query_form.lib.php';
250 PMA_sqlQueryForm($new_query, 'sql');
253 $table = $table_temp;
261 if(isset($_REQUEST['snapshot']))
264 <h3
><?php
echo $strTrackingStructureSnapshot;?
> [<a href
="tbl_tracking.php?<?php echo $url_query;?>"><?php
echo $strTrackingReportClose;?
></a
>]</h3
>
267 $data = PMA_Tracker
::getTrackedData($_REQUEST['db'], $_REQUEST['table'], $_REQUEST['version']);
269 // Get first DROP TABLE and CREATE TABLE statements
270 $drop_create_statements = $data['ddlog'][0]['statement'];
272 if(strstr($data['ddlog'][0]['statement'], 'DROP TABLE'))
273 $drop_create_statements .= $data['ddlog'][1]['statement'];
276 PMA_showMessage(sprintf($strTrackingVersionSnapshotSQL, $_REQUEST['version']), $drop_create_statements);
278 // Unserialize snapshot
279 $temp = unserialize($data['schema_snapshot']);
280 $columns = $temp['COLUMNS'];
281 $indexes = $temp['INDEXES'];
283 <h3
><?php
echo $strStructure;?
></h3
>
284 <table id
="tablestructure" class="data">
287 <th
><?php
echo $strField; ?
></th
>
288 <th
><?php
echo $strType; ?
></th
>
289 <th
><?php
echo $strCollation; ?
></th
>
290 <th
><?php
echo $strNull; ?
></th
>
291 <th
><?php
echo $strDefault; ?
></th
>
292 <th
><?php
echo $strExtra; ?
></th
>
293 <th
><?php
echo $strComment; ?
></th
>
300 foreach($columns as $field_index => $field)
303 <tr
class="<?php echo $style; ?>">
305 if($field['Key'] == 'PRI')
306 echo '<td><b><u>' . $field['Field'] . '</u></b></td>'."\n";
308 echo '<td><b>' . $field['Field'] . '</b></td>'."\n";
310 <td
><?php
echo $field['Type'];?
></td
>
311 <td
><?php
echo $field['Collation'];?
></td
>
312 <td
><?php
echo $field['Null'];?
></td
>
313 <td
><?php
echo $field['Default'];?
></td
>
314 <td
><?php
echo $field['Extra'];?
></td
>
315 <td
><?php
echo $field['Comment'];?
></td
>
318 if($style == 'even') $style = 'odd'; else $style = 'even';
325 if(count($indexes) > 0)
328 <h3
><?php
echo $strIndexes;?
></h3
>
329 <table id
="tablestructure_indexes" class="data">
332 <th
><?php
echo $strKeyname;?
></th
>
333 <th
><?php
echo $strType;?
></th
>
334 <th
><?php
echo $strUnique;?
></th
>
335 <th
><?php
echo $strPacked;?
></th
>
336 <th
><?php
echo $strField;?
></th
>
337 <th
><?php
echo $strCardinality;?
></th
>
338 <th
><?php
echo $strCollation;?
></th
>
339 <th
><?php
echo $strNull;?
></th
>
340 <th
><?php
echo $strComment;?
></th
>
345 foreach($indexes as $indexes_index => $index)
347 if($index['Non_unique'] == 0)
348 $str_unique = $strYes;
350 $str_unique = $strNo;
352 if($index['Packed'] != '')
353 $str_packed = $strYes;
355 $str_packed = $strNo;
357 <tr
class="<?php echo $style; ?>">
358 <td
><b
><?php
echo $index['Key_name'];?
></b
></td
>
359 <td
><?php
echo $index['Index_type'];?
></td
>
360 <td
><?php
echo $str_unique;?
></td
>
361 <td
><?php
echo $str_packed;?
></td
>
362 <td
><?php
echo $index['Column_name'];?
></td
>
363 <td
><?php
echo $index['Cardinality'];?
></td
>
364 <td
><?php
echo $index['Collation'];?
></td
>
365 <td
><?php
echo $index['Null'];?
></td
>
366 <td
><?php
echo $index['Comment'];?
></td
>
369 if($style == 'even') $style = 'odd'; else $style = 'even';
380 // end of snapshot report
385 if(isset($_REQUEST['report']) or isset($_REQUEST['report_export']))
388 <h3
><?php
echo $strTrackingReport;?
> [<a href
="tbl_tracking.php?<?php echo $url_query;?>"><?php
echo $strTrackingReportClose;?
></a
>]</h3
>
390 <small
><?php
echo $strTrackingStatements . ' ' . $data['tracking']; ?
></small
><br
/>
393 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>&report=true&version=<?php echo $_REQUEST['version'];?>">
396 $str1 = '<select name="logtype">' .
397 '<option value="schema"' . $selection_schema . '>' . $strStrucOnly . '</option>' .
398 '<option value="data"' . $selection_data . '>' . $strDataOnly . '</option>' .
399 '<option value="schema_and_data"' . $selection_both . '>' . $strStrucData . '</option>' .
401 $str2 = '<input type="text" name="date_from" value="' . $_REQUEST['date_from'] . '" size="19">';
402 $str3 = '<input type="text" name="date_to" value="' . $_REQUEST['date_to'] . '" size="19">';
403 $str4 = '<input type="text" name="users" value="' . $_REQUEST['users'] . '">';
404 $str5 = '<input type="submit" name="list_report" value="' . $strGo . '">';
406 printf($strTrackingShowLogDateUsers, $str1, $str2, $str3, $str4, $str5);
410 * First, list tracked data defintion statements
413 if($selection_schema == 'selected' or $selection_both == 'selected')
416 <table id
="versions" class="data" width
="100%">
419 <th width
="18">#</th>
420 <th width
="100"><?php
echo $strTrackingDate;?
></th
>
421 <th width
="60"><?php
echo $strTrackingUsername;?
></th
>
422 <th
><?php
echo $strTrackingDataDefinitionStatement;?
></th
>
428 foreach ($data['ddlog'] as $entry)
430 $parsed_sql = PMA_SQP_parse($entry['statement']);
431 $statement = PMA_formatSql($parsed_sql);
432 $timestamp = strtotime($entry['date']);
434 if( $timestamp >= $filter_ts_from and $timestamp <= $filter_ts_to and
435 ( in_array('*', $filter_users) or in_array($entry['username'], $filter_users) ) )
438 <tr
class="<?php echo $style; ?>">
439 <td
><small
><?php
echo $i;?
></small
></td
>
440 <td
><small
><?php
echo $entry['date'];?
></small
></td
>
441 <td
><small
><?php
echo $entry['username']; ?
></small
></td
>
442 <td
><?php
echo $statement; ?
></td
>
445 if($style == 'even') $style = 'odd'; else $style = 'even';
457 * Secondly, list tracked data manipulation statements
460 if(($selection_data == 'selected' or $selection_both == 'selected') and count($data['dmlog']) > 0)
463 <table id
="versions" class="data" width
="100%">
466 <th width
="18">#</th>
467 <th width
="100"><?php
echo $strTrackingDate;?
></th
>
468 <th width
="60"><?php
echo $strTrackingUsername;?
></th
>
469 <th
><?php
echo $strTrackingDataManipulationStatement;?
></th
>
475 foreach ($data['dmlog'] as $entry)
477 $parsed_sql = PMA_SQP_parse($entry['statement']);
478 $statement = PMA_formatSql($parsed_sql);
479 $timestamp = strtotime($entry['date']);
481 if( $timestamp >= $filter_ts_from and $timestamp <= $filter_ts_to and
482 ( in_array('*', $filter_users) or in_array($entry['username'], $filter_users) ) )
485 <tr
class="<?php echo $style; ?>">
486 <td
><small
><?php
echo $i; ?
></small
></td
>
487 <td
><small
><?php
echo $entry['date']; ?
></small
></td
>
488 <td
><small
><?php
echo $entry['username']; ?
></small
></td
>
489 <td
><?php
echo $statement; ?
></td
>
492 if($style == 'even') $style = 'odd'; else $style = 'even';
503 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>&report=true&version=<?php echo $_REQUEST['version'];?>">
507 printf($strTrackingShowLogDateUsers, $str1, $str2, $str3, $str4, $str5);
509 $str_export1 = '<select name="export_type">' .
510 '<option value="sqldumpfile">' . $strTrackingSQLDumpFile . '</option>' .
511 '<option value="sqldump">' . $strTrackingSQLDump . '</option>' .
512 '<option value="execution" onclick="alert(\''.$strTrackingSQLExecutionAlert .'\')">' . $strTrackingSQLExecution . '</option>' .
515 $str_export2 = '<input type="submit" name="report_export" value="'. $strGo .'">';
518 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>&report=true&version=<?php echo $_REQUEST['version'];?>">
519 <input type
="hidden" name
="logtype" value
="<?php echo $_REQUEST['logtype'];?>">
520 <input type
="hidden" name
="date_from" value
="<?php echo $_REQUEST['date_from'];?>">
521 <input type
="hidden" name
="date_to" value
="<?php echo $_REQUEST['date_to'];?>">
522 <input type
="hidden" name
="users" value
="<?php echo $_REQUEST['users'];?>">
524 echo "<br/>" . sprintf($strTrackingExportAs, $str_export1) . $str_export2 . "<br/>";
528 echo "<br/><br/><hr/><br/>\n";
533 * List selectable tables
536 $sql_query = " SELECT DISTINCT db_name, table_name FROM " .
537 PMA_backquote($GLOBALS['cfg']['Server']['pmadb']) . "." .
538 PMA_backquote($GLOBALS['cfg']['Server']['tracking']) .
539 " WHERE " . PMA_backquote('db_name') . " = '" . PMA_sqlAddslashes($GLOBALS['db']) . "' " .
540 " ORDER BY ". PMA_backquote('db_name') . ", " . PMA_backquote('table_name');
542 $sql_result = PMA_query_as_controluser($sql_query);
544 if(PMA_DBI_num_rows($sql_result) > 0)
547 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query;?>">
548 <select name
="table">
550 while($entries = PMA_DBI_fetch_array($sql_result))
552 if(PMA_Tracker
::isTracked($entries['db_name'], $entries['table_name']))
557 if($entries['table_name'] == $_REQUEST['table'])
562 echo '<option value="'.$entries['table_name'].'"'.$s.'>'.$entries['db_name'].' . '.$entries['table_name'] .$status.'</option>'."\n";
566 <input type
="submit" name
="show_versions_submit" value
="<?php echo $strTrackingShowVersions;?>">
575 * List versions of current table
578 $sql_query = " SELECT * FROM " .
579 PMA_backquote($GLOBALS['cfg']['Server']['pmadb']) . "." .
580 PMA_backquote($GLOBALS['cfg']['Server']['tracking']) .
581 " WHERE " . PMA_backquote('db_name') . " = '" . PMA_sqlAddslashes($_REQUEST['db']) . "' ".
582 " AND " . PMA_backquote('table_name') . " = '" . PMA_sqlAddslashes($_REQUEST['table']) ."' ".
583 " ORDER BY ". PMA_backquote('version') . " DESC ";
585 $sql_result = PMA_query_as_controluser($sql_query);
588 $maxversion = PMA_DBI_fetch_array($sql_result);
589 $last_version = $maxversion['version'];
591 if($last_version > 0)
595 <table id
="versions" class="data">
598 <th
><?php
echo $strDatabase;?
></th
>
599 <th
><?php
echo $strTable;?
></th
>
600 <th
><?php
echo $strTrackingThVersion;?
></th
>
601 <th
><?php
echo $strTrackingThCreated;?
></th
>
602 <th
><?php
echo $strTrackingThUpdated;?
></th
>
603 <th
><?php
echo $strStatus;?
></th
>
604 <th
><?php
echo $strShow;?
></th
>
610 PMA_DBI_data_seek($sql_result, 0);
611 while($version = PMA_DBI_fetch_array($sql_result))
614 if($version['tracking_active'] == 1)
615 $version_status = $strTrackingStatusActive;
617 $version_status = $strTrackingStatusNotActive;
619 if(($version['version'] == $last_version) and ($version_status == $strTrackingStatusNotActive))
620 $tracking_active = false;
621 if(($version['version'] == $last_version) and ($version_status == $strTrackingStatusActive))
622 $tracking_active = true;
624 <tr
class="<?php echo $style;?>">
625 <td
><?php
echo $version['db_name'];?
></td
>
626 <td
><?php
echo $version['table_name'];?
></td
>
627 <td
><?php
echo $version['version'];?
></td
>
628 <td
><?php
echo $version['date_created'];?
></td
>
629 <td
><?php
echo $version['date_updated'];?
></td
>
630 <td
><?php
echo $version_status;?
></td
>
631 <td
> <a href
="tbl_tracking.php?<?php echo $url_query;?>&report=true&version=<?php echo $version['version'];?>"><?php
echo $strTrackingReport;?
></a
> |
<a href
="tbl_tracking.php?<?php echo $url_query;?>&snapshot=true&version=<?php echo $version['version'];?>"><?php
echo $strTrackingStructureSnapshot;?
></a
></td
>
634 if($style == 'even') $style = 'odd'; else $style = 'even';
639 <?php
if($tracking_active == true) {?
>
640 <div id
="div_deactivate_tracking">
641 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>">
643 <legend
><?php
printf($strTrackingDeactivateTrackingFor, $GLOBALS['db'], $GLOBALS['table']); ?
></legend
>
644 <input type
="hidden" name
="version" value
="<?php echo $last_version; ?>">
645 <input type
="submit" name
="submit_deactivate_now" value
="<?php echo $strTrackingDeactivateNow; ?>" />
652 <?php
if($tracking_active == false) {?
>
653 <div id
="div_activate_tracking">
654 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>">
656 <legend
><?php
printf($strTrackingActivateTrackingFor, $GLOBALS['db'], $GLOBALS['table']); ?
></legend
>
657 <input type
="hidden" name
="version" value
="<?php echo $last_version; ?>">
658 <input type
="submit" name
="submit_activate_now" value
="<?php echo $strTrackingActivateNow; ?>" />
670 <div id
="div_create_version">
671 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>">
672 <?php
echo PMA_generate_common_hidden_inputs($GLOBALS['db'], $GLOBALS['table']); ?
>
674 <legend
><?php
printf($strTrackingCreateVersionOf, ($last_version +
1), $GLOBALS['db'], $GLOBALS['table']); ?
></legend
>
676 <input type
="hidden" name
="version" value
="<?php echo ($last_version + 1); ?>">
678 <p
><?php
echo $strTrackingTrackDDStatements;?
></p
>
679 <input type
="checkbox" name
="alter_table" value
="true" checked
/> ALTER TABLE
<br
/>
680 <input type
="checkbox" name
="rename_table" value
="true" checked
/> RENAME TABLE
<br
/>
681 <input type
="checkbox" name
="create_table" value
="true" checked
/> CREATE TABLE
<br
/>
682 <input type
="checkbox" name
="drop_table" value
="true" checked
/> DROP TABLE
<br
/>
684 <input type
="checkbox" name
="create_index" value
="true" checked
/> CREATE INDEX
<br
/>
685 <input type
="checkbox" name
="drop_index" value
="true" checked
/> DROP INDEX
<br
/>
686 <p
><?php
echo $strTrackingTrackDMStatements;?
></p
>
687 <input type
="checkbox" name
="insert" value
="true" checked
/> INSERT
<br
/>
688 <input type
="checkbox" name
="update" value
="true" checked
/> UPDATE
<br
/>
689 <input type
="checkbox" name
="delete" value
="true" checked
/> DELETE
<br
/>
690 <input type
="checkbox" name
="truncate" value
="true" checked
/> TRUNCATE
<br
/>
693 <fieldset
class="tblFooters">
695 <input type
="submit" name
="submit_create_version" value
="<?php echo $strTrackingCreateVersion; ?>" />
700 <br
class="clearfloat"/>
704 * Displays the footer
706 require_once './libraries/footer.inc.php';