diff options
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/TablePartitionDefinition.php')
| -rw-r--r-- | srcs/phpmyadmin/libraries/classes/TablePartitionDefinition.php | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/TablePartitionDefinition.php b/srcs/phpmyadmin/libraries/classes/TablePartitionDefinition.php new file mode 100644 index 0000000..89ece4b --- /dev/null +++ b/srcs/phpmyadmin/libraries/classes/TablePartitionDefinition.php @@ -0,0 +1,200 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * hold PhpMyAdmin\TablePartitionDefinition class + * + * @package PhpMyAdmin + */ +declare(strict_types=1); + +namespace PhpMyAdmin; + +use function array_merge; + +/** + * Class TablePartitionDefinition + * + * @package PhpMyAdmin + */ +class TablePartitionDefinition +{ + /** + * @param array|null $details Details that may be pre-filled + * + * @return array + */ + public static function getDetails(?array $details = null): array + { + if (! isset($details)) { + $details = self::generateDetails(); + } + + return $details; + } + + /** + * @return array + */ + protected static function generateDetails(): array + { + $partitionDetails = self::extractDetailsFromRequest(); + + // Only LIST and RANGE type parameters allow subpartitioning + $partitionDetails['can_have_subpartitions'] = $partitionDetails['partition_count'] > 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; + } +} |
