Skip to content

Commit 8d88dc7

Browse files
committed
Differentiating between ANALYZE and EXPLAIN statements
Signed-off-by: iifawzi <[email protected]>
1 parent a9cd167 commit 8d88dc7

File tree

9 files changed

+1441
-13
lines changed

9 files changed

+1441
-13
lines changed

src/Parser.php

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -466,27 +466,44 @@ public function parse()
466466
continue;
467467
}
468468

469-
// Checking if it is a known statement that can be parsed.
470-
if (empty(static::$STATEMENT_PARSERS[$token->keyword])) {
471-
if (! isset(static::$STATEMENT_PARSERS[$token->keyword])) {
472-
// A statement is considered recognized if the parser
473-
// is aware that it is a statement, but it does not have
474-
// a parser for it yet.
475-
$this->error('Unrecognized statement type.', $token);
476-
}
469+
$lastIdx = $list->idx;
470+
471+
++$list->idx; // Skip ANALYZE
472+
$first = $list->getNextOfType(Token::TYPE_KEYWORD);
473+
$second = $list->getNextOfType(Token::TYPE_KEYWORD);
474+
$statementName = null;
475+
476+
// ANALYZE keyword can be an indication of two cases:
477+
// 1- ANALAYZE TABLE statements, in both mariaDB and MySQL
478+
// 2- Explain statement, in case of mariaDB https://mariadb.com/kb/en/explain-analyze/
479+
// We need to point case 2 to use the EXPLAIN Parser.
480+
if ($token->keyword === 'ANALYZE' && $first->keyword !== 'TABLE' && $second->keyword !== 'TABLE') {
481+
$list->idx = $lastIdx;
482+
$statementName = 'EXPLAIN';
483+
} else {
484+
$list->idx = $lastIdx;
485+
// Checking if it is a known statement that can be parsed.
486+
if (empty(static::$STATEMENT_PARSERS[$token->keyword])) {
487+
if (! isset(static::$STATEMENT_PARSERS[$token->keyword])) {
488+
// A statement is considered recognized if the parser
489+
// is aware that it is a statement, but it does not have
490+
// a parser for it yet.
491+
$this->error('Unrecognized statement type.', $token);
492+
}
477493

478-
// Skipping to the end of this statement.
479-
$list->getNextOfType(Token::TYPE_DELIMITER);
480-
$prevLastIdx = $list->idx;
481-
continue;
494+
// Skipping to the end of this statement.
495+
$list->getNextOfType(Token::TYPE_DELIMITER);
496+
$prevLastIdx = $list->idx;
497+
continue;
498+
}
482499
}
483500

484501
/**
485502
* The name of the class that is used for parsing.
486503
*
487504
* @var string
488505
*/
489-
$class = static::$STATEMENT_PARSERS[$token->keyword];
506+
$class = static::$STATEMENT_PARSERS[$statementName ? $statementName : $token->keyword];
490507

491508
/**
492509
* Processed statement.

tests/Parser/AnalyzeStatementTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\SqlParser\Tests\Parser;
6+
7+
use PhpMyAdmin\SqlParser\Tests\TestCase;
8+
9+
class AnalyzeStatementTest extends TestCase
10+
{
11+
/**
12+
* @dataProvider analyzeProvider
13+
*/
14+
public function testAnalyze(string $test): void
15+
{
16+
$this->runParserTest($test);
17+
}
18+
19+
/**
20+
* @return string[][]
21+
*/
22+
public function analyzeProvider(): array
23+
{
24+
return [
25+
['parser/parseAnalyzeTable'],
26+
['parser/parseAnalyzeTable1'],
27+
];
28+
}
29+
}

tests/Parser/ExplainStatementTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function explainProvider(): array
2323
{
2424
return [
2525
['parser/parseExplain'],
26+
['parser/parseExplain1'],
2627
];
2728
}
2829
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ANALYZE TABLE tbl

0 commit comments

Comments
 (0)