diff --git a/js/tbl_structure.js b/js/tbl_structure.js index b8b8f68e1d..7eb36c0946 100644 --- a/js/tbl_structure.js +++ b/js/tbl_structure.js @@ -85,6 +85,7 @@ AJAX.registerTeardown('tbl_structure.js', function () { $(document).off('click', "#printView"); $(document).off('submit', ".append_fields_form.ajax"); $('body').off('click', '#fieldsForm.ajax button[name="submit_mult"], #fieldsForm.ajax input[name="submit_mult"]'); + $(document).off('click', 'a[name^=partition_action].ajax'); }); AJAX.registerOnload('tbl_structure.js', function () { @@ -432,6 +433,35 @@ AJAX.registerOnload('tbl_structure.js', function () { AJAX.source = $form; $.post($form.attr('action'), submitData, AJAX.responseHandler); }); + + /** + * Handles clicks on Action links in partition table + */ + $(document).on('click', 'a[name^=partition_action].ajax', function (e) { + e.preventDefault(); + var $link = $(this); + + function submitPartitionAction(url) { + var submitData = '&ajax_request=true&ajax_page_request=true'; + PMA_ajaxShowMessage(); + AJAX.source = $link; + $.post(url, submitData, AJAX.responseHandler); + } + + if ($link.is('#partition_action_DROP')) { + var question = PMA_messages.strDropPartitionWarning; + $link.PMA_confirm(question, $link.attr('href'), function (url) { + submitPartitionAction(url); + }); + } else if ($link.is('#partition_action_TRUNCATE')) { + var question = PMA_messages.strTruncatePartitionWarning; + $link.PMA_confirm(question, $link.attr('href'), function (url) { + submitPartitionAction(url); + }); + } else { + submitPartitionAction($link.attr('href')); + } + }); }); /** Handler for "More" dropdown in structure table rows */ diff --git a/libraries/Partition.class.php b/libraries/Partition.class.php index 387021be2f..414c2f0e7d 100644 --- a/libraries/Partition.class.php +++ b/libraries/Partition.class.php @@ -9,13 +9,336 @@ if (! defined('PHPMYADMIN')) { exit; } +/** + * Represents a sub partition of a table + * + * @package PhpMyAdmin + */ +class PMA_SubPartition +{ + /** + * @var string the database + */ + protected $db; + /** + * @var string the table + */ + protected $table; + /** + * @var string partition name + */ + protected $name; + /** + * @var integer ordinal + */ + protected $ordinal; + /** + * @var string partition method + */ + protected $method; + /** + * @var string partition expression + */ + protected $expression; + /** + * @var integer no of table rows in the partition + */ + protected $rows; + /** + * @var integer data length + */ + protected $dataLength; + /** + * @var integer index length + */ + protected $indexLength; + + /** + * Constructs a partition + * + * @param array $row fetched row from information_schema.PARTITIONS + */ + public function __construct($row) + { + $this->db = $row['TABLE_SCHEMA']; + $this->table = $row['TABLE_NAME']; + $this->loadData($row); + } + + /** + * Loads data from the fetched row from information_schema.PARTITIONS + * + * @param array $row fetched row + * + * @return void + */ + protected function loadData($row) + { + $this->name = $row['SUBPARTITION_NAME']; + $this->ordinal = $row['SUBPARTITION_ORDINAL_POSITION']; + $this->method = $row['SUBPARTITION_METHOD']; + $this->expression = $row['SUBPARTITION_EXPRESSION']; + $this->loadCommonData($row); + } + + /** + * Loads some data that is common to both partitions and sub partitions + * + * @param array $row fetched row + * + * @return void + */ + protected function loadCommonData($row) + { + $this->rows = $row['TABLE_ROWS']; + $this->dataLength = $row['DATA_LENGTH']; + $this->indexLength = $row['INDEX_LENGTH']; + } + + /** + * Return the partition name + * + * @return string partition name + */ + public function getName() + { + return $this->name; + } + + /** + * Return the ordinal of the partition + * + * @return number the ordinal + */ + public function getOrdinal() + { + return $this->ordinal; + } + + /** + * Returns the partition method + * + * @return string partition method + */ + public function getMethod() + { + return $this->method; + } + + /** + * Returns the partition expression + * + * @return string partition expression + */ + public function getExpression() + { + return $this->expression; + } + + /** + * Returns the number of data rows + * + * @return integer number of rows + */ + public function getRows() + { + return $this->rows; + } + + /** + * Returns the data length + * + * @return integer data length + */ + public function getDataLength() + { + return $this->dataLength; + } + + /** + * Returns the index length + * + * @return integer index length + */ + public function getIndexLength() + { + return $this->indexLength; + } +} + /** * base Partition Class * * @package PhpMyAdmin */ -class PMA_Partition +class PMA_Partition extends PMA_SubPartition { + /** + * @var string partition description + */ + protected $description; + /** + * @var PMA_SubPartition[] sub partitions + */ + protected $subPartitions = array(); + + /** + * Loads data from the fetched row from information_schema.PARTITIONS + * + * @param array $row fetched row + * + * @return void + */ + protected function loadData($row) + { + $this->name = $row['PARTITION_NAME']; + $this->ordinal = $row['PARTITION_ORDINAL_POSITION']; + $this->method = $row['PARTITION_METHOD']; + $this->expression = $row['PARTITION_EXPRESSION']; + $this->description = $row['PARTITION_DESCRIPTION']; + // no sub partitions, load all data to this object + if (empty($row['SUBPARTITION_NAME'])) { + $this->loadCommonData($row); + } + } + + /** + * Returns the partiotion description + * + * @return string partition description + */ + public function getDescription() + { + return $this->description; + } + + /** + * Add a sub partition + * + * @param PMA_SubPartition $partition + * + * @return void + */ + public function addSubPartition(PMA_SubPartition $partition) + { + $this->subPartitions[] = $partition; + } + + /** + * Whether there are sub partitions + * + * @return boolean + */ + public function hasSubPartitions() + { + return ! empty($this->subPartitions); + } + + /** + * Returns the number of data rows + * + * @return integer number of rows + */ + public function getRows() + { + if (empty($this->subPartitions)) { + return $this->rows; + } else { + $rows = 0; + foreach ($this->subPartitions as $subPartition) { + $rows += $subPartition->rows; + } + return $rows; + } + } + + /** + * Returns the total data length + * + * @return integer data length + */ + public function getDataLength() + { + if (empty($this->subPartitions)) { + return $this->dataLength; + } else { + $dataLength = 0; + foreach ($this->subPartitions as $subPartition) { + $dataLength += $subPartition->dataLength; + } + return $dataLength; + } + } + + /** + * Returns the tatal index length + * + * @return integer index length + */ + public function getIndexLength() + { + if (empty($this->subPartitions)) { + return $this->indexLength; + } else { + $indexLength = 0; + foreach ($this->subPartitions as $subPartition) { + $indexLength += $subPartition->indexLength; + } + return $indexLength; + } + } + + /** + * Returns the list of sub partitions + * + * @return PMA_SubPartition[] + */ + public function getSubPartitions() + { + return $this->subPartitions; + } + + /** + * Returns array of partitions for a specific db/table + * + * @param string $db database name + * @param string $table table name + * + * @access public + * @return PMA_Partition[] + */ + static public function getParititions($db, $table) + { + if (PMA_Partition::havePartitioning()) { + $result = $GLOBALS['dbi']->fetchResult( + "SELECT * FROM `information_schema`.`PARTITIONS`" + . " WHERE `TABLE_SCHEMA` = '" . PMA_Util::sqlAddSlashes($db) + . "' AND `TABLE_NAME` = '" . PMA_Util::sqlAddSlashes($table) . "'" + ); + if ($result) { + $partitionMap = array(); + foreach ($result as $row) { + if (isset($partitionMap[$row['PARTITION_NAME']])) { + $partition = $partitionMap[$row['PARTITION_NAME']]; + } else { + $partition = new PMA_Partition($row); + $partitionMap[$row['PARTITION_NAME']] = $partition; + } + + if (! empty($row['SUBPARTITION_NAME'])) { + $parentPartition = $partition; + $partition = new PMA_SubPartition($row); + $parentPartition->addSubPartition($partition); + } + } + return array_values($partitionMap); + } + return array(); + } else { + return array(); + } + } + /** * returns array of partition names for a specific db/table * @@ -96,4 +419,4 @@ class PMA_Partition } return $have_partitioning; } -} +} \ No newline at end of file diff --git a/libraries/controllers/TableStructureController.class.php b/libraries/controllers/TableStructureController.class.php index 3f14b01da2..85e5c1332c 100644 --- a/libraries/controllers/TableStructureController.class.php +++ b/libraries/controllers/TableStructureController.class.php @@ -11,6 +11,7 @@ namespace PMA\Controllers; use PMA\Template; use PMA_Index; +use PMA_Partition; use PMA_Table; use PMA_Message; use PMA_PageSettings; @@ -21,6 +22,7 @@ use SqlParser; require_once 'libraries/common.inc.php'; require_once 'libraries/tbl_info.inc.php'; require_once 'libraries/Index.class.php'; +require_once 'libraries/Partition.class.php'; require_once 'libraries/mysql_charsets.inc.php'; require_once 'libraries/config/page_settings.class.php'; require_once 'libraries/transformations.lib.php'; @@ -274,7 +276,9 @@ class TableStructureController extends TableController /** * Adding indexes */ - if (isset($_REQUEST['add_key'])) { + if (isset($_REQUEST['add_key']) + || isset($_REQUEST['partition_maintenance']) + ) { //todo: set some variables for sql.php include, to be eliminated //after refactoring sql.php $db = $this->db; diff --git a/libraries/sql.lib.php b/libraries/sql.lib.php index 52f94eea26..12c7998b3d 100644 --- a/libraries/sql.lib.php +++ b/libraries/sql.lib.php @@ -1234,7 +1234,9 @@ function PMA_deleteTransformationInfo($db, $table, $analyzed_sql_results) include_once 'libraries/transformations.lib.php'; $statement = $analyzed_sql_results['statement']; if ($statement instanceof SqlParser\Statements\AlterStatement) { - if ($statement->altered[0]->options->has('DROP')) { + if (!empty($statement->altered[0]) + && $statement->altered[0]->options->has('DROP') + ) { if (!empty($statement->altered[0]->field->column)) { PMA_clearTransformations( $db, diff --git a/templates/table/structure/display_partitions.phtml b/templates/table/structure/display_partitions.phtml new file mode 100644 index 0000000000..e11def912b --- /dev/null +++ b/templates/table/structure/display_partitions.phtml @@ -0,0 +1,120 @@ +
+
+ + +

+ + +

+ +

+ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $icon): ?> + + + + + getSubPartitions() as $subParition): ?> + + + + + + + + + + + + + + + + + + +
#
getOrdinal(); ?>getOrdinal(); ?>getName()); ?> + + getExpression()) + . ($partition->getMethod() == 'LIST' ? ' IN (' : ' < ') + . htmlspecialchars($partition->getDescription()) + . ($partition->getMethod() == 'LIST' ? ')' : ''); + ?> + + getRows(); ?>getDataLength(), 3, 1 + ); + ?> + + + getIndexLength(), 3, 1 + ); + ?> + + + + getName() + ) ?>" + id="partition_action_" + name="partition_action_" + class="ajax" + > + + +
getOrdinal(); ?>getName()); ?>getRows(); ?>getDataLength(), 3, 1 + ); + ?> + + + getIndexLength(), 3, 1 + ); + ?> + + +
+

+
\ No newline at end of file diff --git a/templates/table/structure/display_structure.phtml b/templates/table/structure/display_structure.phtml index 0d9f17d61b..7d79cb6a91 100644 --- a/templates/table/structure/display_structure.phtml +++ b/templates/table/structure/display_structure.phtml @@ -154,11 +154,54 @@ array('columns_list' => $columns_list) ); ?> + + + +getSubPartitions(); + $hasSubPartitions = $firstPartition->hasSubPartitions(); + if ($hasSubPartitions) { + $firstSubPartition = $subParitions[0]; + } + + $actionIcons = array( + 'ANALYZE' => PMA_Util::getIcon('b_search.png', __('Analyze')), + 'CHECK' => PMA_Util::getIcon('eye.png', __('Check')), + 'OPTIMIZE' => PMA_Util::getIcon('normalize.png', __('Optimize')), + 'REBUILD' => PMA_Util::getIcon('s_tbl.png', __('Rebuild')), + 'REPAIR' => PMA_Util::getIcon('b_tblops.png', __('Repair')), + 'TRUNCATE' => PMA_Util::getIcon('b_empty.png', __('Truncate')), + 'DROP' => PMA_Util::getIcon('b_drop.png', __('Drop')) + ); + + echo PMA\Template::get('table/structure/display_partitions')->render( + array( + 'table' => $table, + 'url_query' => $url_query, + 'partitions' => $partitions, + 'partitionMethod' => $firstPartition->getMethod(), + 'partitionExpression' => $firstPartition->getExpression(), + 'hasDescription' => ! empty($firstPartition->getDescription()), + 'hasSubPartitions' => $hasSubPartitions, + 'subPartitionMethod' => $hasSubPartitions ? $firstSubPartition->getMethod() : null, + 'subPartitionExpression' => $hasSubPartitions ? $firstSubPartition->getExpression() : null, + 'actionIcons' => $actionIcons, + ) + ); +} +?> +