phpmyadmin /
sql-parser
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace PhpMyAdmin\SqlParser\Parsers; |
||
| 6 | |||
| 7 | use PhpMyAdmin\SqlParser\Components\PartitionDefinition; |
||
| 8 | use PhpMyAdmin\SqlParser\Parseable; |
||
| 9 | use PhpMyAdmin\SqlParser\Parser; |
||
| 10 | use PhpMyAdmin\SqlParser\TokensList; |
||
| 11 | use PhpMyAdmin\SqlParser\TokenType; |
||
| 12 | |||
| 13 | use function implode; |
||
| 14 | |||
| 15 | /** |
||
| 16 | * Parses the create definition of a partition. |
||
| 17 | * |
||
| 18 | * Used for parsing `CREATE TABLE` statement. |
||
| 19 | */ |
||
| 20 | final class PartitionDefinitions implements Parseable |
||
| 21 | { |
||
| 22 | /** |
||
| 23 | * All field options. |
||
| 24 | * |
||
| 25 | * @var array<string, int|array<int, int|string>> |
||
| 26 | * @psalm-var array<string, (positive-int|array{positive-int, ('var'|'var='|'expr'|'expr=')})> |
||
| 27 | */ |
||
| 28 | public static array $partitionOptions = [ |
||
| 29 | 'STORAGE ENGINE' => [ |
||
| 30 | 1, |
||
| 31 | 'var', |
||
| 32 | ], |
||
| 33 | 'ENGINE' => [ |
||
| 34 | 1, |
||
| 35 | 'var', |
||
| 36 | ], |
||
| 37 | 'COMMENT' => [ |
||
| 38 | 2, |
||
| 39 | 'var', |
||
| 40 | ], |
||
| 41 | 'DATA DIRECTORY' => [ |
||
| 42 | 3, |
||
| 43 | 'var', |
||
| 44 | ], |
||
| 45 | 'INDEX DIRECTORY' => [ |
||
| 46 | 4, |
||
| 47 | 'var', |
||
| 48 | ], |
||
| 49 | 'MAX_ROWS' => [ |
||
| 50 | 5, |
||
| 51 | 'var', |
||
| 52 | ], |
||
| 53 | 'MIN_ROWS' => [ |
||
| 54 | 6, |
||
| 55 | 'var', |
||
| 56 | ], |
||
| 57 | 'TABLESPACE' => [ |
||
| 58 | 7, |
||
| 59 | 'var', |
||
| 60 | ], |
||
| 61 | 'NODEGROUP' => [ |
||
| 62 | 8, |
||
| 63 | 'var', |
||
| 64 | ], |
||
| 65 | ]; |
||
| 66 | |||
| 67 | /** |
||
| 68 | * @param Parser $parser the parser that serves as context |
||
| 69 | * @param TokensList $list the list of tokens that are being parsed |
||
| 70 | * @param array<string, mixed> $options parameters for parsing |
||
| 71 | */ |
||
| 72 | 24 | public static function parse(Parser $parser, TokensList $list, array $options = []): PartitionDefinition |
|
| 73 | { |
||
| 74 | 24 | $ret = new PartitionDefinition(); |
|
| 75 | |||
| 76 | /** |
||
| 77 | * The state of the parser. |
||
| 78 | * |
||
| 79 | * Below are the states of the parser. |
||
| 80 | * |
||
| 81 | * 0 -------------[ PARTITION | SUBPARTITION ]------------> 1 |
||
| 82 | * |
||
| 83 | * 1 -----------------------[ name ]----------------------> 2 |
||
| 84 | * |
||
| 85 | * 2 ----------------------[ VALUES ]---------------------> 3 |
||
| 86 | * |
||
| 87 | * 3 ---------------------[ LESS THAN ]-------------------> 4 |
||
| 88 | * 3 ------------------------[ IN ]-----------------------> 4 |
||
| 89 | * |
||
| 90 | * 4 -----------------------[ expr ]----------------------> 5 |
||
| 91 | * |
||
| 92 | * 5 ----------------------[ options ]--------------------> 6 |
||
| 93 | * |
||
| 94 | * 6 ------------------[ subpartitions ]------------------> (END) |
||
| 95 | */ |
||
| 96 | 24 | $state = 0; |
|
| 97 | |||
| 98 | 24 | for (; $list->idx < $list->count; ++$list->idx) { |
|
| 99 | /** |
||
| 100 | * Token parsed at this moment. |
||
| 101 | */ |
||
| 102 | 24 | $token = $list->tokens[$list->idx]; |
|
| 103 | |||
| 104 | // End of statement. |
||
| 105 | 24 | if ($token->type === TokenType::Delimiter) { |
|
| 106 | 4 | break; |
|
| 107 | } |
||
| 108 | |||
| 109 | // Skipping whitespaces and comments. |
||
| 110 | 24 | if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) { |
|
| 111 | 24 | continue; |
|
| 112 | } |
||
| 113 | |||
| 114 | 24 | if ($state === 0) { |
|
| 115 | 24 | $ret->isSubpartition = ($token->type === TokenType::Keyword) && ($token->keyword === 'SUBPARTITION'); |
|
| 116 | 24 | $state = 1; |
|
| 117 | 24 | } elseif ($state === 1) { |
|
| 118 | 24 | $ret->name = (string) $token->value; |
|
| 119 | |||
| 120 | // Looking ahead for a 'VALUES' keyword. |
||
| 121 | // Loop until the end of the partition name (delimited by a whitespace) |
||
| 122 | 24 | while ($nextToken = $list->tokens[++$list->idx]) { |
|
| 123 | 24 | if ($nextToken->type !== TokenType::None) { |
|
| 124 | 24 | break; |
|
| 125 | } |
||
| 126 | |||
| 127 | 2 | $ret->name .= $nextToken->value; |
|
| 128 | } |
||
| 129 | |||
| 130 | 24 | $idx = $list->idx--; |
|
| 131 | // Get the first token after the white space. |
||
| 132 | 24 | $nextToken = $list->tokens[++$idx]; |
|
| 133 | |||
| 134 | 24 | $state = ($nextToken->type === TokenType::Keyword) |
|
| 135 | 24 | && ($nextToken->value === 'VALUES') |
|
| 136 | 24 | ? 2 : 5; |
|
| 137 | 24 | } elseif ($state === 2) { |
|
| 138 | 22 | $state = 3; |
|
| 139 | 24 | } elseif ($state === 3) { |
|
| 140 | 22 | $ret->type = $token->value; |
|
| 141 | 22 | $state = 4; |
|
| 142 | 24 | } elseif ($state === 4) { |
|
| 143 | 22 | if ($token->value === 'MAXVALUE') { |
|
| 144 | 14 | $ret->expr = $token->value; |
|
| 145 | } else { |
||
| 146 | 22 | $ret->expr = Expressions::parse( |
|
| 147 | 22 | $parser, |
|
| 148 | 22 | $list, |
|
| 149 | 22 | [ |
|
| 150 | 22 | 'parenthesesDelimited' => true, |
|
| 151 | 22 | 'breakOnAlias' => true, |
|
| 152 | 22 | ], |
|
| 153 | 22 | ); |
|
| 154 | } |
||
| 155 | |||
| 156 | 22 | $state = 5; |
|
| 157 | 22 | } elseif ($state === 5) { |
|
| 158 | 22 | $ret->options = OptionsArrays::parse($parser, $list, static::$partitionOptions); |
|
| 159 | 22 | $state = 6; |
|
| 160 | 20 | } elseif ($state === 6) { |
|
| 161 | 20 | if (($token->type === TokenType::Operator) && ($token->value === '(')) { |
|
| 162 | 10 | $ret->subpartitions = ArrayObjs::parse( |
|
|
0 ignored issues
–
show
|
|||
| 163 | 10 | $parser, |
|
| 164 | 10 | $list, |
|
| 165 | 10 | ['type' => self::class], |
|
| 166 | 10 | ); |
|
| 167 | 10 | ++$list->idx; |
|
| 168 | } |
||
| 169 | |||
| 170 | 20 | break; |
|
| 171 | } |
||
| 172 | } |
||
| 173 | |||
| 174 | 24 | --$list->idx; |
|
| 175 | |||
| 176 | 24 | return $ret; |
|
| 177 | } |
||
| 178 | |||
| 179 | /** @param PartitionDefinition[] $component the component to be built */ |
||
| 180 | 8 | public static function buildAll(array $component): string |
|
| 181 | { |
||
| 182 | 8 | return "(\n" . implode(",\n", $component) . "\n)"; |
|
| 183 | } |
||
| 184 | } |
||
| 185 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..