Action should always be displayed here
[phpmyadmin/dkf.git] / libraries / Tracker.class.php
blobf03018ab221c3ce11fadf839c17d2fc4d5c14bab
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
5 * @author Alexander Rutkowski
6 * @version $Id$
7 * @package phpMyAdmin
8 */
10 /**
11 * Gets relation settings
13 require_once './libraries/relation.lib.php';
15 /**
16 * This class tracks changes on databases, tables and views.
17 * For more information please see phpMyAdmin/Documentation.html
19 * @author Alexander Rutkowski <alexander.rutkowski@googlemail.com>
20 * @package phpMyAdmin
22 * @todo use stristr instead of strstr
24 class PMA_Tracker
26 /**
27 * Whether tracking is ready.
29 static protected $enabled = false;
31 /**
32 * Defines the internal PMA table which contains tracking data.
34 * @access protected
35 * @var string
37 static protected $pma_table;
39 /**
40 * Defines the usage of DROP TABLE statment in SQL dumps.
42 * @access protected
43 * @var boolean
45 static protected $add_drop_table;
47 /**
48 * Defines the usage of DROP VIEW statment in SQL dumps.
50 * @access protected
51 * @var boolean
53 static protected $add_drop_view;
55 /**
56 * Defines the usage of DROP DATABASE statment in SQL dumps.
58 * @access protected
59 * @var boolean
61 static protected $add_drop_database;
63 /**
64 * Defines auto-creation of tracking versions.
66 * @var boolean
68 static protected $version_auto_create;
70 /**
71 * Defines the default set of tracked statements.
73 * @var string
75 static protected $default_tracking_set;
77 /**
78 * Initializes settings. See phpMyAdmin/Documentation.html.
80 * @static
83 static public function init()
85 self::$pma_table = PMA_backquote($GLOBALS['cfg']['Server']['pmadb']) .".".
86 PMA_backquote($GLOBALS['cfg']['Server']['tracking']);
88 self::$add_drop_table = $GLOBALS['cfg']['Server']['tracking_add_drop_table'];
90 self::$add_drop_view = $GLOBALS['cfg']['Server']['tracking_add_drop_view'];
92 self::$add_drop_database = $GLOBALS['cfg']['Server']['tracking_add_drop_database'];
94 self::$default_tracking_set = $GLOBALS['cfg']['Server']['tracking_default_statements'];
96 self::$version_auto_create = $GLOBALS['cfg']['Server']['tracking_version_auto_create'];
101 * Actually enables tracking. This needs to be done after all
102 * underlaying code is initialized.
104 * @static
107 static public function enable()
109 self::$enabled = true;
113 * Gets the on/off value of the Tracker module, starts initialization.
115 * @static
117 * @return boolean (true=on|false=off)
119 static public function isActive()
121 if (! self::$enabled) {
122 return false;
124 /* We need to avoid attempt to track any queries from PMA_getRelationsParam */
125 self::$enabled = false;
126 $cfgRelation = PMA_getRelationsParam();
127 /* Restore original state */
128 self::$enabled = true;
129 if (! $cfgRelation['trackingwork']) {
130 return false;
132 self::init();
134 if (isset(self::$pma_table)) {
135 return true;
136 } else {
137 return false;
142 * Returns a simple DROP TABLE statement.
144 * @param string $tablename
145 * @return string
147 static public function getStatementDropTable($tablename)
149 return 'DROP TABLE IF EXISTS ' . $tablename;
153 * Returns a simple DROP VIEW statement.
155 * @param string $viewname
156 * @return string
158 static public function getStatementDropView($viewname)
160 return 'DROP VIEW IF EXISTS ' . $viewname;
164 * Returns a simple DROP DATABASE statement.
166 * @param string $dbname
167 * @return string
169 static public function getStatementDropDatabase($dbname)
171 return 'DROP DATABASE IF EXISTS ' . $dbname;
175 * Parses the name of a table from a SQL statement substring.
177 * @static
179 * @param string $string part of SQL statement
181 * @return string the name of table
183 static protected function getTableName($string)
185 if (strstr($string, '.')) {
186 $temp = explode('.', $string);
187 $tablename = $temp[1];
189 else {
190 $tablename = $string;
193 $str = explode("\n", $tablename);
194 $tablename = $str[0];
196 $tablename = str_replace(';', '', $tablename);
197 $tablename = str_replace('`', '', $tablename);
198 $tablename = trim($tablename);
200 return $tablename;
205 * Gets the tracking status of a table, is it active or deactive ?
207 * @static
209 * @param string $dbname name of database
210 * @param string $tablename name of table
212 * @return boolean true or false
214 static public function isTracked($dbname, $tablename)
216 if (! self::$enabled) {
217 return false;
219 /* We need to avoid attempt to track any queries from PMA_getRelationsParam */
220 self::$enabled = false;
221 $cfgRelation = PMA_getRelationsParam();
222 /* Restore original state */
223 self::$enabled = true;
224 if (! $cfgRelation['trackingwork']) {
225 return false;
228 $sql_query =
229 " SELECT tracking_active FROM " . self::$pma_table .
230 " WHERE " . PMA_backquote('db_name') . " = '" . PMA_sqlAddslashes($dbname) . "' " .
231 " AND " . PMA_backquote('table_name') . " = '" . PMA_sqlAddslashes($tablename) . "' " .
232 " ORDER BY version DESC";
234 $row = PMA_DBI_fetch_array(PMA_query_as_controluser($sql_query));
236 if (isset($row['tracking_active']) && $row['tracking_active'] == 1) {
237 return true;
238 } else {
239 return false;
244 * Returns the comment line for the log.
246 * @return string Comment, contains date and username
248 static public function getLogComment()
250 $date = date('Y-m-d H:i:s');
252 return "# log " . $date . " " . $GLOBALS['cfg']['Server']['user'] . "\n";
256 * Creates tracking version of a table / view
257 * (in other words: create a job to track future changes on the table).
259 * @static
261 * @param string $dbname name of database
262 * @param string $tablename name of table
263 * @param string $version version
264 * @param string $tracking_set set of tracking statements
265 * @param string $is_view if table is a view
267 * @return int result of version insertion
269 static public function createVersion($dbname, $tablename, $version, $tracking_set = '', $is_view = false)
271 global $sql_backquotes;
273 if ($tracking_set == '') {
274 $tracking_set = self::$default_tracking_set;
277 require_once './libraries/export/sql.php';
279 $sql_backquotes = true;
281 $date = date('Y-m-d H:i:s');
283 // Get data definition snapshot of table
284 $sql_query = '
285 SHOW FULL COLUMNS FROM ' . PMA_backquote($dbname) . '.' . PMA_backquote($tablename);
287 $sql_result = PMA_DBI_query($sql_query);
289 while ($row = PMA_DBI_fetch_array($sql_result)) {
290 $columns[] = $row;
293 $sql_query = '
294 SHOW INDEX FROM ' . PMA_backquote($dbname) . '.' . PMA_backquote($tablename);
296 $sql_result = PMA_DBI_query($sql_query);
298 $indexes = array();
300 while($row = PMA_DBI_fetch_array($sql_result)) {
301 $indexes[] = $row;
304 $snapshot = array('COLUMNS' => $columns, 'INDEXES' => $indexes);
305 $snapshot = serialize($snapshot);
307 // Get DROP TABLE / DROP VIEW and CREATE TABLE SQL statements
308 $sql_backquotes = true;
310 $create_sql = "";
312 if (self::$add_drop_table == true && $is_view == false) {
313 $create_sql .= self::getLogComment() .
314 self::getStatementDropTable(PMA_backquote($tablename)) . ";\n";
318 if (self::$add_drop_view == true && $is_view == true) {
319 $create_sql .= self::getLogComment() .
320 self::getStatementDropView(PMA_backquote($tablename)) . ";\n";
323 $create_sql .= self::getLogComment() .
324 PMA_getTableDef($dbname, $tablename, "\n", "");
326 // Save version
328 $sql_query =
329 "/*NOTRACK*/\n" .
330 "INSERT INTO" . self::$pma_table . " (" .
331 "db_name, " .
332 "table_name, " .
333 "version, " .
334 "date_created, " .
335 "date_updated, " .
336 "schema_snapshot, " .
337 "schema_sql, " .
338 "data_sql, " .
339 "tracking " .
340 ") " .
341 "values (
342 '" . PMA_sqlAddslashes($dbname) . "',
343 '" . PMA_sqlAddslashes($tablename) . "',
344 '" . PMA_sqlAddslashes($version) . "',
345 '" . PMA_sqlAddslashes($date) . "',
346 '" . PMA_sqlAddslashes($date) . "',
347 '" . PMA_sqlAddslashes($snapshot) . "',
348 '" . PMA_sqlAddslashes($create_sql) . "',
349 '" . PMA_sqlAddslashes("\n") . "',
350 '" . PMA_sqlAddslashes($tracking_set) . "' )";
352 $result = PMA_query_as_controluser($sql_query);
354 if ($result) {
355 // Deactivate previous version
356 self::deactivateTracking($dbname, $tablename, ($version - 1));
359 return $result;
364 * Removes all tracking data for a table
366 * @static
368 * @param string $dbname name of database
369 * @param string $tablename name of table
371 * @return int result of version insertion
373 static public function deleteTracking($dbname, $tablename)
375 $sql_query =
376 "/*NOTRACK*/\n" .
377 "DELETE FROM " . self::$pma_table . " WHERE `db_name` = '" . PMA_sqlAddslashes($dbname) . "' AND `table_name` = '" . PMA_sqlAddslashes($tablename) . "'";
378 $result = PMA_query_as_controluser($sql_query);
380 return $result;
384 * Creates tracking version of a database
385 * (in other words: create a job to track future changes on the database).
387 * @static
389 * @param string $dbname name of database
390 * @param string $version version
391 * @param string $query query
392 * @param string $tracking_set set of tracking statements
394 * @return int result of version insertion
396 static public function createDatabaseVersion($dbname, $version, $query, $tracking_set = 'CREATE DATABASE,ALTER DATABASE,DROP DATABASE')
398 global $sql_backquotes;
400 $date = date('Y-m-d H:i:s');
402 if ($tracking_set == '') {
403 $tracking_set = self::$default_tracking_set;
406 require_once './libraries/export/sql.php';
408 $create_sql = "";
410 if (self::$add_drop_database == true) {
411 $create_sql .= self::getLogComment() .
412 self::getStatementDropDatabase(PMA_backquote($dbname)) . ";\n";
415 $create_sql .= self::getLogComment() . $query;
417 // Save version
418 $sql_query =
419 "/*NOTRACK*/\n" .
420 "INSERT INTO" . self::$pma_table . " (" .
421 "db_name, " .
422 "table_name, " .
423 "version, " .
424 "date_created, " .
425 "date_updated, " .
426 "schema_snapshot, " .
427 "schema_sql, " .
428 "data_sql, " .
429 "tracking " .
430 ") " .
431 "values (
432 '" . PMA_sqlAddslashes($dbname) . "',
433 '" . PMA_sqlAddslashes('') . "',
434 '" . PMA_sqlAddslashes($version) . "',
435 '" . PMA_sqlAddslashes($date) . "',
436 '" . PMA_sqlAddslashes($date) . "',
437 '" . PMA_sqlAddslashes('') . "',
438 '" . PMA_sqlAddslashes($create_sql) . "',
439 '" . PMA_sqlAddslashes("\n") . "',
440 '" . PMA_sqlAddslashes($tracking_set) . "' )";
442 $result = PMA_query_as_controluser($sql_query);
444 return $result;
450 * Changes tracking of a table.
452 * @static
454 * @param string $dbname name of database
455 * @param string $tablename name of table
456 * @param string $version version
457 * @param integer $new_state the new state of tracking
459 * @return int result of SQL query
461 static private function changeTracking($dbname, $tablename, $version, $new_state)
463 $sql_query =
464 " UPDATE " . self::$pma_table .
465 " SET `tracking_active` = '" . $new_state . "' " .
466 " WHERE `db_name` = '" . PMA_sqlAddslashes($dbname) . "' " .
467 " AND `table_name` = '" . PMA_sqlAddslashes($tablename) . "' " .
468 " AND `version` = '" . PMA_sqlAddslashes($version) . "' ";
470 $result = PMA_query_as_controluser($sql_query);
472 return $result;
476 * Activates tracking of a table.
478 * @static
480 * @param string $dbname name of database
481 * @param string $tablename name of table
482 * @param string $version version
484 * @return int result of SQL query
486 static public function activateTracking($dbname, $tablename, $version)
488 return self::changeTracking($dbname, $tablename, $version, 1);
493 * Deactivates tracking of a table.
495 * @static
497 * @param string $dbname name of database
498 * @param string $tablename name of table
499 * @param string $version version
501 * @return int result of SQL query
503 static public function deactivateTracking($dbname, $tablename, $version)
505 return self::changeTracking($dbname, $tablename, $version, 0);
510 * Gets the newest version of a tracking job
511 * (in other words: gets the HEAD version).
513 * @static
515 * @param string $dbname name of database
516 * @param string $tablename name of table
517 * @param string $statement tracked statement
519 * @return int (-1 if no version exists | > 0 if a version exists)
521 static public function getVersion($dbname, $tablename, $statement = null)
523 $sql_query =
524 " SELECT MAX(version) FROM " . self::$pma_table .
525 " WHERE `db_name` = '" . PMA_sqlAddslashes($dbname) . "' " .
526 " AND `table_name` = '" . PMA_sqlAddslashes($tablename) . "' ";
528 if ($statement != "") {
529 $sql_query .= " AND FIND_IN_SET('" . $statement . "',tracking) > 0" ;
531 $row = PMA_DBI_fetch_array(PMA_query_as_controluser($sql_query));
532 if (isset($row[0])) {
533 $version = $row[0];
535 if (! isset($version)) {
536 $version = -1;
538 return $version;
543 * Gets the record of a tracking job.
545 * @static
547 * @param string $dbname name of database
548 * @param string $tablename name of table
549 * @param string $version version number
551 * @return mixed record DDM log, DDL log, structure snapshot, tracked statements.
553 static public function getTrackedData($dbname, $tablename, $version)
555 if (! isset(self::$pma_table)) {
556 self::init();
558 $sql_query = " SELECT * FROM " . self::$pma_table .
559 " WHERE `db_name` = '" . PMA_sqlAddslashes($dbname) . "' ";
560 if (! empty($tablename)) {
561 $sql_query .= " AND `table_name` = '" . PMA_sqlAddslashes($tablename) ."' ";
563 $sql_query .= " AND `version` = '" . PMA_sqlAddslashes($version) ."' ".
564 " ORDER BY `version` DESC ";
566 $mixed = PMA_DBI_fetch_array(PMA_query_as_controluser($sql_query));
568 // Parse log
569 $log_schema_entries = explode('# log ', $mixed['schema_sql']);
570 $log_data_entries = explode('# log ', $mixed['data_sql']);
572 $ddl_date_from = $date = date('Y-m-d H:i:s');
574 $ddlog = array();
575 $i = 0;
577 // Iterate tracked data definition statements
578 // For each log entry we want to get date, username and statement
579 foreach ($log_schema_entries as $log_entry) {
580 if (trim($log_entry) != '') {
581 $date = substr($log_entry, 0, 19);
582 $username = substr($log_entry, 20, strpos($log_entry, "\n") - 20);
583 if ($i == 0) {
584 $ddl_date_from = $date;
586 $statement = rtrim(strstr($log_entry, "\n"));
588 $ddlog[] = array( 'date' => $date,
589 'username'=> $username,
590 'statement' => $statement );
591 $i++;
595 $date_from = $ddl_date_from;
596 $date_to = $ddl_date_to = $date;
598 $dml_date_from = $date_from;
600 $dmlog = array();
601 $i = 0;
603 // Iterate tracked data manipulation statements
604 // For each log entry we want to get date, username and statement
605 foreach ($log_data_entries as $log_entry) {
606 if (trim($log_entry) != '') {
607 $date = substr($log_entry, 0, 19);
608 $username = substr($log_entry, 20, strpos($log_entry, "\n") - 20);
609 if ($i == 0) {
610 $dml_date_from = $date;
612 $statement = rtrim(strstr($log_entry, "\n"));
614 $dmlog[] = array( 'date' => $date,
615 'username' => $username,
616 'statement' => $statement );
617 $i++;
621 $dml_date_to = $date;
623 // Define begin and end of date range for both logs
624 if (strtotime($ddl_date_from) <= strtotime($dml_date_from)) {
625 $data['date_from'] = $ddl_date_from;
626 } else {
627 $data['date_from'] = $dml_date_from;
629 if (strtotime($ddl_date_to) >= strtotime($dml_date_to)) {
630 $data['date_to'] = $ddl_date_to;
631 } else {
632 $data['date_to'] = $dml_date_to;
634 $data['ddlog'] = $ddlog;
635 $data['dmlog'] = $dmlog;
636 $data['tracking'] = $mixed['tracking'];
637 $data['schema_snapshot'] = $mixed['schema_snapshot'];
639 return $data;
644 * Parses a query. Gets
645 * - statement identifier (UPDATE, ALTER TABLE, ...)
646 * - type of statement, is it part of DDL or DML ?
647 * - tablename
649 * @static
650 * @todo: using PMA SQL Parser when possible
651 * @todo: support multi-table/view drops
653 * @param string $query
655 * @return mixed Array containing identifier, type and tablename.
658 static public function parseQuery($query)
661 // Usage of PMA_SQP does not work here
663 // require_once("libraries/sqlparser.lib.php");
664 // $parsed_sql = PMA_SQP_parse($query);
665 // $sql_info = PMA_SQP_analyze($parsed_sql);
667 $query = str_replace("\n", " ", $query);
668 $query = str_replace("\r", " ", $query);
670 $query = trim($query);
671 $query = trim($query, ' -');
673 $tokens = explode(" ", $query);
674 $tokens = array_map('strtoupper', $tokens);
676 // Parse USE statement, need it for SQL dump imports
677 if (substr($query, 0, 4) == 'USE ') {
678 $prefix = explode('USE ', $query);
679 $GLOBALS['db'] = self::getTableName($prefix[1]);
683 * DDL statements
686 $result['type'] = 'DDL';
688 // Parse CREATE VIEW statement
689 if (in_array('CREATE', $tokens) == true &&
690 in_array('VIEW', $tokens) == true &&
691 in_array('AS', $tokens) == true) {
692 $result['identifier'] = 'CREATE VIEW';
694 $index = array_search('VIEW', $tokens);
696 $result['tablename'] = strtolower(self::getTableName($tokens[$index + 1]));
699 // Parse ALTER VIEW statement
700 if (in_array('ALTER', $tokens) == true &&
701 in_array('VIEW', $tokens) == true &&
702 in_array('AS', $tokens) == true &&
703 ! isset($result['identifier'])) {
704 $result['identifier'] = 'ALTER VIEW';
706 $index = array_search('VIEW', $tokens);
708 $result['tablename'] = strtolower(self::getTableName($tokens[$index + 1]));
711 // Parse DROP VIEW statement
712 if (! isset($result['identifier']) && substr($query, 0, 10) == 'DROP VIEW ') {
713 $result['identifier'] = 'DROP VIEW';
715 $prefix = explode('DROP VIEW ', $query);
716 $str = strstr($prefix[1], 'IF EXISTS');
718 if ($str == FALSE ) {
719 $str = $prefix[1];
721 $result['tablename'] = self::getTableName($str);
724 // Parse CREATE DATABASE statement
725 if (! isset($result['identifier']) && substr($query, 0, 15) == 'CREATE DATABASE') {
726 $result['identifier'] = 'CREATE DATABASE';
727 $str = str_replace('CREATE DATABASE', '', $query);
728 $str = str_replace('IF NOT EXISTS', '', $str);
730 $prefix = explode('DEFAULT ', $str);
732 $result['tablename'] = '';
733 $GLOBALS['db'] = self::getTableName($prefix[0]);
736 // Parse ALTER DATABASE statement
737 if (! isset($result['identifier']) && substr($query, 0, 14) == 'ALTER DATABASE') {
738 $result['identifier'] = 'ALTER DATABASE';
739 $result['tablename'] = '';
742 // Parse DROP DATABASE statement
743 if (! isset($result['identifier']) && substr($query, 0, 13) == 'DROP DATABASE') {
744 $result['identifier'] = 'DROP DATABASE';
745 $str = str_replace('DROP DATABASE', '', $query);
746 $str = str_replace('IF EXISTS', '', $str);
747 $GLOBALS['db'] = self::getTableName($str);
748 $result['tablename'] = '';
751 // Parse CREATE TABLE statement
752 if (! isset($result['identifier']) && substr($query, 0, 12) == 'CREATE TABLE' ) {
753 $result['identifier'] = 'CREATE TABLE';
754 $query = str_replace('IF NOT EXISTS', '', $query);
755 $prefix = explode('CREATE TABLE ', $query);
756 $suffix = explode('(', $prefix[1]);
757 $result['tablename'] = self::getTableName($suffix[0]);
760 // Parse ALTER TABLE statement
761 if (! isset($result['identifier']) && substr($query, 0, 12) == 'ALTER TABLE ') {
762 $result['identifier'] = 'ALTER TABLE';
764 $prefix = explode('ALTER TABLE ', $query);
765 $suffix = explode(' ', $prefix[1]);
766 $result['tablename'] = self::getTableName($suffix[0]);
769 // Parse DROP TABLE statement
770 if (! isset($result['identifier']) && substr($query, 0, 11) == 'DROP TABLE ') {
771 $result['identifier'] = 'DROP TABLE';
773 $prefix = explode('DROP TABLE ', $query);
774 $str = strstr($prefix[1], 'IF EXISTS');
776 if ($str == FALSE ) {
777 $str = $prefix[1];
779 $result['tablename'] = self::getTableName($str);
782 // Parse CREATE INDEX statement
783 if (! isset($result['identifier']) &&
784 ( substr($query, 0, 12) == 'CREATE INDEX' ||
785 substr($query, 0, 19) == 'CREATE UNIQUE INDEX' ||
786 substr($query, 0, 20) == 'CREATE SPATIAL INDEX'
789 $result['identifier'] = 'CREATE INDEX';
790 $prefix = explode('ON ', $query);
791 $suffix = explode('(', $prefix[1]);
792 $result['tablename'] = self::getTableName($suffix[0]);
795 // Parse DROP INDEX statement
796 if (! isset($result['identifier']) && substr($query, 0, 10) == 'DROP INDEX') {
797 $result['identifier'] = 'DROP INDEX';
798 $prefix = explode('ON ', $query);
799 $result['tablename'] = self::getTableName($prefix[1]);
802 // Parse RENAME TABLE statement
803 if (! isset($result['identifier']) && substr($query, 0, 13) == 'RENAME TABLE ') {
804 $result['identifier'] = 'RENAME TABLE';
805 $prefix = explode('RENAME TABLE ', $query);
806 $names = explode(' TO ', $prefix[1]);
807 $result['tablename'] = self::getTableName($names[0]);
808 $result["tablename_after_rename"] = self::getTableName($names[1]);
812 * DML statements
815 if (! isset($result['identifier'])) {
816 $result["type"] = 'DML';
818 // Parse UPDATE statement
819 if (! isset($result['identifier']) && substr($query, 0, 6) == 'UPDATE') {
820 $result['identifier'] = 'UPDATE';
821 $prefix = explode('UPDATE ', $query);
822 $suffix = explode(' ', $prefix[1]);
823 $result['tablename'] = self::getTableName($suffix[0]);
826 // Parse INSERT INTO statement
827 if (! isset($result['identifier']) && substr($query, 0, 11 ) == 'INSERT INTO') {
828 $result['identifier'] = 'INSERT';
829 $prefix = explode('INSERT INTO', $query);
830 $suffix = explode('(', $prefix[1]);
831 $result['tablename'] = self::getTableName($suffix[0]);
834 // Parse DELETE statement
835 if (! isset($result['identifier']) && substr($query, 0, 6 ) == 'DELETE') {
836 $result['identifier'] = 'DELETE';
837 $prefix = explode('FROM ', $query);
838 $suffix = explode(' ', $prefix[1]);
839 $result['tablename'] = self::getTableName($suffix[0]);
842 // Parse TRUNCATE statement
843 if (! isset($result['identifier']) && substr($query, 0, 8 ) == 'TRUNCATE') {
844 $result['identifier'] = 'TRUNCATE';
845 $prefix = explode('TRUNCATE', $query);
846 $result['tablename'] = self::getTableName($prefix[1]);
849 return $result;
854 * Analyzes a given SQL statement and saves tracking data.
857 * @static
858 * @param string $query a SQL query
860 static public function handleQuery($query)
862 // If query is marked as untouchable, leave
863 if (strstr($query, "/*NOTRACK*/")) {
864 return false;
867 if (! (substr($query, -1) == ';')) {
868 $query = $query . ";\n";
870 // Get some information about query
871 $result = self::parseQuery($query);
873 // Get database name
874 $dbname = trim($GLOBALS['db'], '`');
875 // $dbname can be empty, for example when coming from Synchronize
876 // and this is a query for the remote server
877 if (empty($dbname)) {
878 return false;
881 // If we found a valid statement
882 if (isset($result['identifier'])) {
883 $version = self::getVersion($dbname, $result['tablename'], $result['identifier']);
885 // If version not exists and auto-creation is enabled
886 if (self::$version_auto_create == true
887 && self::isTracked($dbname, $result['tablename']) == false
888 && $version == -1) {
889 // Create the version
891 switch ($result['identifier']) {
892 case 'CREATE TABLE':
893 self::createVersion($dbname, $result['tablename'], '1');
894 break;
895 case 'CREATE VIEW':
896 self::createVersion($dbname, $result['tablename'], '1', '', true);
897 break;
898 case 'CREATE DATABASE':
899 self::createDatabaseVersion($dbname, '1', $query);
900 break;
901 } // end switch
904 // If version exists
905 if (self::isTracked($dbname, $result['tablename']) && $version != -1) {
906 if ($result['type'] == 'DDL') {
907 $save_to = 'schema_sql';
908 } elseif ($result['type'] == 'DML') {
909 $save_to = 'data_sql';
910 } else {
911 $save_to = '';
913 $date = date('Y-m-d H:i:s');
915 // Cut off `dbname`. from query
916 $query = preg_replace('/`' . $dbname . '`\s?\./', '', $query);
918 // Add log information
919 $query = self::getLogComment() . $query ;
921 // Mark it as untouchable
922 $sql_query =
923 " /*NOTRACK*/\n" .
924 " UPDATE " . self::$pma_table .
925 " SET " . PMA_backquote($save_to) ." = CONCAT( " . PMA_backquote($save_to) . ",'\n" . PMA_sqlAddslashes($query) . "') ," .
926 " `date_updated` = '" . $date . "' ";
928 // If table was renamed we have to change the tablename attribute in pma_tracking too
929 if ($result['identifier'] == 'RENAME TABLE') {
930 $sql_query .= ', `table_name` = \'' . PMA_sqlAddslashes($result['tablename_after_rename']) . '\' ';
933 // Save the tracking information only for
934 // 1. the database
935 // 2. the table / view
936 // 3. the statements
937 // we want to track
938 $sql_query .=
939 " WHERE FIND_IN_SET('" . $result['identifier'] . "',tracking) > 0" .
940 " AND `db_name` = '" . PMA_sqlAddslashes($dbname) . "' " .
941 " AND `table_name` = '" . PMA_sqlAddslashes($result['tablename']) . "' " .
942 " AND `version` = '" . PMA_sqlAddslashes($version) . "' ";
944 $result = PMA_query_as_controluser($sql_query);