diff --git a/libraries/classes/Controllers/Table/StructureController.php b/libraries/classes/Controllers/Table/StructureController.php index 9bdb796e44..70b83ca4f9 100644 --- a/libraries/classes/Controllers/Table/StructureController.php +++ b/libraries/classes/Controllers/Table/StructureController.php @@ -26,6 +26,7 @@ use PhpMyAdmin\SqlParser\Parser; use PhpMyAdmin\SqlParser\Statements\CreateStatement; use PhpMyAdmin\StorageEngine; use PhpMyAdmin\Table; +use PhpMyAdmin\TablePartitionDefinition; use PhpMyAdmin\Tracker; use PhpMyAdmin\Transformations; use PhpMyAdmin\Url; @@ -561,7 +562,7 @@ class StructureController extends AbstractController $partitionDetails = $this->_extractPartitionDetails(); } - include ROOT_PATH . 'libraries/tbl_partition_definition.inc.php'; + $partitionDetails = TablePartitionDefinition::getDetails($partitionDetails); $this->response->addHTML( $this->template->render('table/structure/partition_definition_form', [ 'db' => $this->db, diff --git a/libraries/classes/TablePartitionDefinition.php b/libraries/classes/TablePartitionDefinition.php new file mode 100644 index 0000000000..89ece4bfd2 --- /dev/null +++ b/libraries/classes/TablePartitionDefinition.php @@ -0,0 +1,200 @@ + 1 + && isset($partitionDetails['partition_by']) + && ($partitionDetails['partition_by'] === 'RANGE' + || $partitionDetails['partition_by'] === 'RANGE COLUMNS' + || $partitionDetails['partition_by'] === 'LIST' + || $partitionDetails['partition_by'] === 'LIST COLUMNS'); + + // Values are specified only for LIST and RANGE type partitions + $partitionDetails['value_enabled'] = isset($partitionDetails['partition_by']) + && ($partitionDetails['partition_by'] === 'RANGE' + || $partitionDetails['partition_by'] === 'RANGE COLUMNS' + || $partitionDetails['partition_by'] === 'LIST' + || $partitionDetails['partition_by'] === 'LIST COLUMNS'); + + return self::extractPartitions($partitionDetails); + } + + /** + * Extract some partitioning and subpartitioning parameters from the request + * + * @return array + */ + protected static function extractDetailsFromRequest(): array + { + $partitionParams = [ + 'partition_by' => null, + 'partition_expr' => null, + 'subpartition_by' => null, + 'subpartition_expr' => null, + ]; + //Initialize details with values to "null" if not in request + $details = array_merge( + $partitionParams, + //Keep $_POST values, but only for keys that are in $partitionParams + array_intersect_key($_POST, $partitionParams) + ); + + $details['partition_count'] = self::extractPartitionCount('partition_count') ?: ''; + $details['subpartition_count'] = self::extractPartitionCount('subpartition_count') ?: ''; + + return $details; + } + + /** + * @param string $paramLabel Label searched in request + * + * @return int + */ + protected static function extractPartitionCount(string $paramLabel): int + { + if (Core::isValid($_POST[$paramLabel], 'numeric')) { + // MySQL's limit is 8192, so do not allow more + $count = min((int) $_POST[$paramLabel], 8192); + } else { + $count = 0; + } + return $count; + } + + /** + * @param array $partitionDetails Details of partitions + * + * @return array + */ + protected static function extractPartitions(array $partitionDetails): array + { + $partitionCount = $partitionDetails['partition_count']; + $subpartitionCount = $partitionDetails['subpartition_count']; + + // No partitions + if ($partitionCount <= 1) { + return $partitionDetails; + } + + // Has partitions + $partitions = $_POST['partitions'] ?? []; + + // Remove details of the additional partitions + // when number of partitions have been reduced + array_splice($partitions, $partitionCount); + + for ($i = 0; $i < $partitionCount; $i++) { + if (! isset($partitions[$i])) { // Newly added partition + $partitions[$i] = [ + 'name' => 'p' . $i, + 'value_type' => '', + 'value' => '', + 'engine' => '', + 'comment' => '', + 'data_directory' => '', + 'index_directory' => '', + 'max_rows' => '', + 'min_rows' => '', + 'tablespace' => '', + 'node_group' => '', + ]; + } + + $partition =& $partitions[$i]; + $partition['prefix'] = 'partitions[' . $i . ']'; + + // Changing from HASH/KEY to RANGE/LIST + if (! isset($partition['value_type'])) { + $partition['value_type'] = ''; + $partition['value'] = ''; + } + if (! isset($partition['engine'])) { // When removing subpartitioning + $partition['engine'] = ''; + $partition['comment'] = ''; + $partition['data_directory'] = ''; + $partition['index_directory'] = ''; + $partition['max_rows'] = ''; + $partition['min_rows'] = ''; + $partition['tablespace'] = ''; + $partition['node_group'] = ''; + } + + // No subpartitions + if ($subpartitionCount <= 1 || $partitionDetails['can_have_subpartitions'] !== true) { + unset($partition['subpartitions'], $partition['subpartition_count']); + continue; + } + + // Has subpartitions + $partition['subpartition_count'] = $subpartitionCount; + + if (! isset($partition['subpartitions'])) { + $partition['subpartitions'] = []; + } + $subpartitions =& $partition['subpartitions']; + + // Remove details of the additional subpartitions + // when number of subpartitions have been reduced + array_splice($subpartitions, $subpartitionCount); + + for ($j = 0; $j < $subpartitionCount; $j++) { + if (! isset($subpartitions[$j])) { // Newly added subpartition + $subpartitions[$j] = [ + 'name' => $partition['name'] . '_s' . $j, + 'engine' => '', + 'comment' => '', + 'data_directory' => '', + 'index_directory' => '', + 'max_rows' => '', + 'min_rows' => '', + 'tablespace' => '', + 'node_group' => '', + ]; + } + + $subpartitions[$j]['prefix'] = 'partitions[' . $i . ']' + . '[subpartitions][' . $j . ']'; + } + } + $partitionDetails['partitions'] = $partitions; + return $partitionDetails; + } +} diff --git a/libraries/tbl_columns_definition_form.inc.php b/libraries/tbl_columns_definition_form.inc.php index fd7157d210..6e4224362b 100644 --- a/libraries/tbl_columns_definition_form.inc.php +++ b/libraries/tbl_columns_definition_form.inc.php @@ -13,6 +13,7 @@ use PhpMyAdmin\Partition; use PhpMyAdmin\Relation; use PhpMyAdmin\Response; use PhpMyAdmin\Table; +use PhpMyAdmin\TablePartitionDefinition; use PhpMyAdmin\Template; use PhpMyAdmin\Transformations; use PhpMyAdmin\Util; @@ -476,7 +477,7 @@ for ($columnNumber = 0; $columnNumber < $num_fields; $columnNumber++) { ]; } // end for -include ROOT_PATH . 'libraries/tbl_partition_definition.inc.php'; +$partitionDetails = TablePartitionDefinition::getDetails(); $html = $template->render('columns_definitions/column_definitions_form', [ 'is_backup' => $is_backup, 'fields_meta' => isset($fields_meta) ? $fields_meta : null, diff --git a/libraries/tbl_partition_definition.inc.php b/libraries/tbl_partition_definition.inc.php deleted file mode 100644 index 57daff00b6..0000000000 --- a/libraries/tbl_partition_definition.inc.php +++ /dev/null @@ -1,145 +0,0 @@ - 1 - && isset($_POST['partition_by']) - && ($_POST['partition_by'] == 'RANGE' - || $_POST['partition_by'] == 'RANGE COLUMNS' - || $_POST['partition_by'] == 'LIST' - || $_POST['partition_by'] == 'LIST COLUMNS'); - - // Values are specified only for LIST and RANGE type partitions - $partitionDetails['value_enabled'] = isset($_POST['partition_by']) - && ($_POST['partition_by'] == 'RANGE' - || $_POST['partition_by'] == 'RANGE COLUMNS' - || $_POST['partition_by'] == 'LIST' - || $_POST['partition_by'] == 'LIST COLUMNS'); - - // Has partitions - if ($partition_count > 1) { - $partitions = isset($_POST['partitions']) - ? $_POST['partitions'] - : []; - - // Remove details of the additional partitions - // when number of partitions have been reduced - array_splice($partitions, $partition_count); - - for ($i = 0; $i < $partition_count; $i++) { - if (! isset($partitions[$i])) { // Newly added partition - $partitions[$i] = [ - 'name' => 'p' . $i, - 'value_type' => '', - 'value' => '', - 'engine' => '', - 'comment' => '', - 'data_directory' => '', - 'index_directory' => '', - 'max_rows' => '', - 'min_rows' => '', - 'tablespace' => '', - 'node_group' => '', - ]; - } - - $partition =& $partitions[$i]; - $partition['prefix'] = 'partitions[' . $i . ']'; - - // Changing from HASH/KEY to RANGE/LIST - if (! isset($partition['value_type'])) { - $partition['value_type'] = ''; - $partition['value'] = ''; - } - if (! isset($partition['engine'])) { // When removing subpartitioning - $partition['engine'] = ''; - $partition['comment'] = ''; - $partition['data_directory'] = ''; - $partition['index_directory'] = ''; - $partition['max_rows'] = ''; - $partition['min_rows'] = ''; - $partition['tablespace'] = ''; - $partition['node_group'] = ''; - } - - if ($subpartition_count > 1 - && $partitionDetails['can_have_subpartitions'] == true - ) { // Has subpartitions - $partition['subpartition_count'] = $subpartition_count; - - if (! isset($partition['subpartitions'])) { - $partition['subpartitions'] = []; - } - $subpartitions =& $partition['subpartitions']; - - // Remove details of the additional subpartitions - // when number of subpartitions have been reduced - array_splice($subpartitions, $subpartition_count); - - for ($j = 0; $j < $subpartition_count; $j++) { - if (! isset($subpartitions[$j])) { // Newly added subpartition - $subpartitions[$j] = [ - 'name' => $partition['name'] . '_s' . $j, - 'engine' => '', - 'comment' => '', - 'data_directory' => '', - 'index_directory' => '', - 'max_rows' => '', - 'min_rows' => '', - 'tablespace' => '', - 'node_group' => '', - ]; - } - - $subpartition =& $subpartitions[$j]; - $subpartition['prefix'] = 'partitions[' . $i . ']' - . '[subpartitions][' . $j . ']'; - } - } else { // No subpartitions - unset($partition['subpartitions']); - unset($partition['subpartition_count']); - } - } - $partitionDetails['partitions'] = $partitions; - } -}