Skip to content

Commit 33799aa

Browse files
committed
Split up IndexHint
Signed-off-by: Kamil Tekiela <[email protected]>
1 parent bc850bf commit 33799aa

File tree

5 files changed

+160
-146
lines changed

5 files changed

+160
-146
lines changed

phpstan-baseline.neon

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,6 @@ parameters:
9595
count: 1
9696
path: src/Components/GroupKeyword.php
9797

98-
-
99-
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\IndexHint\\:\\:\\$type \\(string\\|null\\) does not accept mixed\\.$#"
100-
count: 1
101-
path: src/Components/IndexHint.php
102-
10398
-
10499
message: "#^Cannot access property \\$values on array\\<PhpMyAdmin\\\\SqlParser\\\\Component\\>\\|PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\.$#"
105100
count: 1
@@ -215,6 +210,11 @@ parameters:
215210
count: 2
216211
path: src/Components/Lists/GroupKeywords.php
217212

213+
-
214+
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\IndexHint\\:\\:\\$type \\(string\\|null\\) does not accept mixed\\.$#"
215+
count: 1
216+
path: src/Components/Lists/IndexHints.php
217+
218218
-
219219
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\LockExpression\\:\\:\\$table \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\) does not accept PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#"
220220
count: 1

psalm-baseline.xml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,10 @@
141141
</PossiblyUnusedProperty>
142142
</file>
143143
<file src="src/Components/IndexHint.php">
144-
<MixedAssignment>
145-
<code><![CDATA[$expr->type]]></code>
146-
</MixedAssignment>
147144
<PossiblyNullOperand>
148145
<code><![CDATA[$this->indexOrKey]]></code>
149146
<code><![CDATA[$this->type]]></code>
150147
</PossiblyNullOperand>
151-
<PossiblyUnusedMethod>
152-
<code>buildAll</code>
153-
</PossiblyUnusedMethod>
154148
</file>
155149
<file src="src/Components/IntoKeyword.php">
156150
<MixedArgument>
@@ -269,6 +263,14 @@
269263
<code>$options</code>
270264
</UnusedParam>
271265
</file>
266+
<file src="src/Components/Lists/IndexHints.php">
267+
<MixedAssignment>
268+
<code><![CDATA[$expr->type]]></code>
269+
</MixedAssignment>
270+
<PossiblyUnusedMethod>
271+
<code>buildAll</code>
272+
</PossiblyUnusedMethod>
273+
</file>
272274
<file src="src/Components/LockExpression.php">
273275
<MissingConstructor>
274276
<code>$table</code>

src/Components/IndexHint.php

Lines changed: 0 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@
55
namespace PhpMyAdmin\SqlParser\Components;
66

77
use PhpMyAdmin\SqlParser\Component;
8-
use PhpMyAdmin\SqlParser\Components\Lists\ExpressionArray;
9-
use PhpMyAdmin\SqlParser\Parser;
10-
use PhpMyAdmin\SqlParser\TokensList;
11-
use PhpMyAdmin\SqlParser\TokenType;
12-
13-
use function implode;
148

159
/**
1610
* Parses an Index hint.
@@ -57,126 +51,6 @@ public function __construct(
5751
$this->indexes = $indexes;
5852
}
5953

60-
/**
61-
* @param Parser $parser the parser that serves as context
62-
* @param TokensList $list the list of tokens that are being parsed
63-
* @param array<string, mixed> $options parameters for parsing
64-
*
65-
* @return IndexHint[]
66-
*/
67-
public static function parse(Parser $parser, TokensList $list, array $options = []): array
68-
{
69-
$ret = [];
70-
$expr = new static();
71-
$expr->type = $options['type'] ?? null;
72-
/**
73-
* The state of the parser.
74-
*
75-
* Below are the states of the parser.
76-
* 0 ----------------- [ USE/IGNORE/FORCE ]-----------------> 1
77-
* 1 -------------------- [ INDEX/KEY ] --------------------> 2
78-
* 2 ----------------------- [ FOR ] -----------------------> 3
79-
* 2 -------------------- [ expr_list ] --------------------> 0
80-
* 3 -------------- [ JOIN/GROUP BY/ORDER BY ] -------------> 4
81-
* 4 -------------------- [ expr_list ] --------------------> 0
82-
*
83-
* @var int
84-
*/
85-
$state = 0;
86-
87-
// By design, the parser will parse first token after the keyword. So, the keyword
88-
// must be analyzed too, in order to determine the type of this index hint.
89-
if ($list->idx > 0) {
90-
--$list->idx;
91-
}
92-
93-
for (; $list->idx < $list->count; ++$list->idx) {
94-
/**
95-
* Token parsed at this moment.
96-
*/
97-
$token = $list->tokens[$list->idx];
98-
99-
// End of statement.
100-
if ($token->type === TokenType::Delimiter) {
101-
break;
102-
}
103-
104-
// Skipping whitespaces and comments.
105-
if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
106-
continue;
107-
}
108-
109-
switch ($state) {
110-
case 0:
111-
if ($token->type === TokenType::Keyword) {
112-
if ($token->keyword !== 'USE' && $token->keyword !== 'IGNORE' && $token->keyword !== 'FORCE') {
113-
break 2;
114-
}
115-
116-
$expr->type = $token->keyword;
117-
$state = 1;
118-
}
119-
120-
break;
121-
case 1:
122-
if ($token->type === TokenType::Keyword) {
123-
if ($token->keyword === 'INDEX' || $token->keyword === 'KEY') {
124-
$expr->indexOrKey = $token->keyword;
125-
} else {
126-
$parser->error('Unexpected keyword.', $token);
127-
}
128-
129-
$state = 2;
130-
} else {
131-
// we expect the token to be a keyword
132-
$parser->error('Unexpected token.', $token);
133-
}
134-
135-
break;
136-
case 2:
137-
if ($token->type === TokenType::Keyword && $token->keyword === 'FOR') {
138-
$state = 3;
139-
} else {
140-
$expr->indexes = ExpressionArray::parse($parser, $list);
141-
$state = 0;
142-
$ret[] = $expr;
143-
$expr = new static();
144-
}
145-
146-
break;
147-
case 3:
148-
if ($token->type === TokenType::Keyword) {
149-
if (
150-
$token->keyword === 'JOIN'
151-
|| $token->keyword === 'GROUP BY'
152-
|| $token->keyword === 'ORDER BY'
153-
) {
154-
$expr->for = $token->keyword;
155-
} else {
156-
$parser->error('Unexpected keyword.', $token);
157-
}
158-
159-
$state = 4;
160-
} else {
161-
// we expect the token to be a keyword
162-
$parser->error('Unexpected token.', $token);
163-
}
164-
165-
break;
166-
case 4:
167-
$expr->indexes = ExpressionArray::parse($parser, $list);
168-
$state = 0;
169-
$ret[] = $expr;
170-
$expr = new static();
171-
break;
172-
}
173-
}
174-
175-
--$list->idx;
176-
177-
return $ret;
178-
}
179-
18054
public function build(): string
18155
{
18256
$ret = $this->type . ' ' . $this->indexOrKey . ' ';
@@ -187,12 +61,6 @@ public function build(): string
18761
return $ret . Expression::buildAll($this->indexes);
18862
}
18963

190-
/** @param IndexHint[] $component the component to be built */
191-
public static function buildAll(array $component): string
192-
{
193-
return implode(' ', $component);
194-
}
195-
19664
public function __toString(): string
19765
{
19866
return $this->build();
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\SqlParser\Components\Lists;
6+
7+
use PhpMyAdmin\SqlParser\Components\IndexHint;
8+
use PhpMyAdmin\SqlParser\Parser;
9+
use PhpMyAdmin\SqlParser\TokensList;
10+
use PhpMyAdmin\SqlParser\TokenType;
11+
12+
use function implode;
13+
14+
/**
15+
* Parses an Index hint.
16+
*/
17+
final class IndexHints
18+
{
19+
/**
20+
* @param Parser $parser the parser that serves as context
21+
* @param TokensList $list the list of tokens that are being parsed
22+
* @param array<string, mixed> $options parameters for parsing
23+
*
24+
* @return IndexHint[]
25+
*/
26+
public static function parse(Parser $parser, TokensList $list, array $options = []): array
27+
{
28+
$ret = [];
29+
$expr = new IndexHint();
30+
$expr->type = $options['type'] ?? null;
31+
/**
32+
* The state of the parser.
33+
*
34+
* Below are the states of the parser.
35+
* 0 ----------------- [ USE/IGNORE/FORCE ]-----------------> 1
36+
* 1 -------------------- [ INDEX/KEY ] --------------------> 2
37+
* 2 ----------------------- [ FOR ] -----------------------> 3
38+
* 2 -------------------- [ expr_list ] --------------------> 0
39+
* 3 -------------- [ JOIN/GROUP BY/ORDER BY ] -------------> 4
40+
* 4 -------------------- [ expr_list ] --------------------> 0
41+
*
42+
* @var int
43+
*/
44+
$state = 0;
45+
46+
// By design, the parser will parse first token after the keyword. So, the keyword
47+
// must be analyzed too, in order to determine the type of this index hint.
48+
if ($list->idx > 0) {
49+
--$list->idx;
50+
}
51+
52+
for (; $list->idx < $list->count; ++$list->idx) {
53+
/**
54+
* Token parsed at this moment.
55+
*/
56+
$token = $list->tokens[$list->idx];
57+
58+
// End of statement.
59+
if ($token->type === TokenType::Delimiter) {
60+
break;
61+
}
62+
63+
// Skipping whitespaces and comments.
64+
if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
65+
continue;
66+
}
67+
68+
switch ($state) {
69+
case 0:
70+
if ($token->type === TokenType::Keyword) {
71+
if ($token->keyword !== 'USE' && $token->keyword !== 'IGNORE' && $token->keyword !== 'FORCE') {
72+
break 2;
73+
}
74+
75+
$expr->type = $token->keyword;
76+
$state = 1;
77+
}
78+
79+
break;
80+
case 1:
81+
if ($token->type === TokenType::Keyword) {
82+
if ($token->keyword === 'INDEX' || $token->keyword === 'KEY') {
83+
$expr->indexOrKey = $token->keyword;
84+
} else {
85+
$parser->error('Unexpected keyword.', $token);
86+
}
87+
88+
$state = 2;
89+
} else {
90+
// we expect the token to be a keyword
91+
$parser->error('Unexpected token.', $token);
92+
}
93+
94+
break;
95+
case 2:
96+
if ($token->type === TokenType::Keyword && $token->keyword === 'FOR') {
97+
$state = 3;
98+
} else {
99+
$expr->indexes = ExpressionArray::parse($parser, $list);
100+
$state = 0;
101+
$ret[] = $expr;
102+
$expr = new IndexHint();
103+
}
104+
105+
break;
106+
case 3:
107+
if ($token->type === TokenType::Keyword) {
108+
if (
109+
$token->keyword === 'JOIN'
110+
|| $token->keyword === 'GROUP BY'
111+
|| $token->keyword === 'ORDER BY'
112+
) {
113+
$expr->for = $token->keyword;
114+
} else {
115+
$parser->error('Unexpected keyword.', $token);
116+
}
117+
118+
$state = 4;
119+
} else {
120+
// we expect the token to be a keyword
121+
$parser->error('Unexpected token.', $token);
122+
}
123+
124+
break;
125+
case 4:
126+
$expr->indexes = ExpressionArray::parse($parser, $list);
127+
$state = 0;
128+
$ret[] = $expr;
129+
$expr = new IndexHint();
130+
break;
131+
}
132+
}
133+
134+
--$list->idx;
135+
136+
return $ret;
137+
}
138+
139+
/** @param IndexHint[] $component the component to be built */
140+
public static function buildAll(array $component): string
141+
{
142+
return implode(' ', $component);
143+
}
144+
}

src/Parser.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class Parser
191191
'options' => ['parseField' => 'table'],
192192
],
193193
'FORCE' => [
194-
'class' => Components\IndexHint::class,
194+
'class' => Components\Lists\IndexHints::class,
195195
'field' => 'index_hints',
196196
],
197197
'FROM' => [
@@ -208,7 +208,7 @@ class Parser
208208
'field' => 'having',
209209
],
210210
'IGNORE' => [
211-
'class' => Components\IndexHint::class,
211+
'class' => Components\Lists\IndexHints::class,
212212
'field' => 'index_hints',
213213
],
214214
'INTO' => [
@@ -330,7 +330,7 @@ class Parser
330330
'options' => ['parseField' => 'table'],
331331
],
332332
'USE' => [
333-
'class' => Components\IndexHint::class,
333+
'class' => Components\Lists\IndexHints::class,
334334
'field' => 'index_hints',
335335
],
336336
'VALUE' => [

0 commit comments

Comments
 (0)