Passed
Push — master ( b16987...8b6d77 )
by Maurício
03:49 queued 13s
created

PartitionDefinitions   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 69
dl 0
loc 163
ccs 56
cts 56
cp 1
rs 10
c 1
b 0
f 0
wmc 21

2 Methods

Rating   Name   Duplication   Size   Complexity  
A buildAll() 0 3 1
D parse() 0 105 20
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 $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 = $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
Documentation Bug introduced by
It seems like PhpMyAdmin\SqlParser\Par...'type' => self::class)) of type PhpMyAdmin\SqlParser\Components\ArrayObj is incompatible with the declared type PhpMyAdmin\SqlParser\Com...s\PartitionDefinition[] of property $subpartitions.

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..

Loading history...
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