Skip to content

Commit 37df692

Browse files
committed
Add support for PURGE statements
Fix #207 Signed-off-by: Deven Bansod <[email protected]>
1 parent 5e8dbcf commit 37df692

18 files changed

+212
-0
lines changed

src/Parser.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class Parser extends Core
8686
'COMMIT' => 'PhpMyAdmin\\SqlParser\\Statements\\TransactionStatement',
8787
'ROLLBACK' => 'PhpMyAdmin\\SqlParser\\Statements\\TransactionStatement',
8888
'START TRANSACTION' => 'PhpMyAdmin\\SqlParser\\Statements\\TransactionStatement',
89+
90+
'PURGE' => 'PhpMyAdmin\\SqlParser\\Statements\\PurgeStatement',
8991
);
9092

9193
/**

src/Statements/PurgeStatement.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
/**
4+
* `PURGE` statement.
5+
*/
6+
7+
namespace PhpMyAdmin\SqlParser\Statements;
8+
9+
use PhpMyAdmin\SqlParser\Components\Expression;
10+
use PhpMyAdmin\SqlParser\Components\OptionsArray;
11+
use PhpMyAdmin\SqlParser\Parser;
12+
use PhpMyAdmin\SqlParser\Statement;
13+
use PhpMyAdmin\SqlParser\Token;
14+
use PhpMyAdmin\SqlParser\TokensList;
15+
16+
/**
17+
* `PURGE` statement.
18+
*
19+
* PURGE { BINARY | MASTER } LOGS
20+
* { TO 'log_name' | BEFORE datetime_expr }
21+
*
22+
* @category Statements
23+
*
24+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
25+
*/
26+
class PurgeStatement extends Statement
27+
{
28+
/**
29+
* The type of logs
30+
*
31+
* @var String
32+
*/
33+
public $log_type;
34+
35+
/**
36+
* The end option of this query.
37+
*
38+
* @var String
39+
*/
40+
public $end_option;
41+
42+
/**
43+
* The end expr of this query.
44+
*
45+
* @var String
46+
*/
47+
public $end_expr;
48+
49+
/**
50+
* @return string
51+
*/
52+
public function build()
53+
{
54+
$ret = 'PURGE ' . $this->log_type . ' ' . 'LOGS '
55+
. ($this->end_option !== null ? ($this->end_option . ' ' . $this->end_expr) : '');
56+
return trim($ret);
57+
}
58+
59+
/**
60+
* @param Parser $parser the instance that requests parsing
61+
* @param TokensList $list the list of tokens to be parsed
62+
*/
63+
public function parse(Parser $parser, TokensList $list)
64+
{
65+
++$list->idx; // Skipping `PURGE`.
66+
67+
/**
68+
* The state of the parser.
69+
*
70+
* @var int
71+
*/
72+
$state = 0;
73+
74+
for (; $list->idx < $list->count; ++$list->idx) {
75+
/**
76+
* Token parsed at this moment.
77+
*
78+
* @var Token
79+
*/
80+
$token = $list->tokens[$list->idx];
81+
82+
// End of statement.
83+
if ($token->type === Token::TYPE_DELIMITER) {
84+
break;
85+
}
86+
87+
// Skipping whitespaces and comments.
88+
if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
89+
continue;
90+
}
91+
92+
switch ($state) {
93+
case 0:
94+
// parse `{ BINARY | MASTER }`
95+
$this->log_type = self::parseExpectedKeyword($parser, $token, array('BINARY', 'MASTER'));
96+
break;
97+
case 1:
98+
// parse `LOGS`
99+
self::parseExpectedKeyword($parser, $token, array('LOGS'));
100+
break;
101+
case 2:
102+
// parse `{ TO | BEFORE }`
103+
$this->end_option = self::parseExpectedKeyword($parser, $token, array('TO', 'BEFORE'));
104+
break;
105+
case 3:
106+
// parse `expr`
107+
$this->end_expr = Expression::parse($parser, $list, array());
108+
break;
109+
default:
110+
$parser->error('Unexpected token.', $token);
111+
break;
112+
}
113+
$state++;
114+
$prevToken = $token;
115+
}
116+
117+
// Only one possible end state
118+
if ($state != 4) {
119+
$parser->error('Unexpected token.', $prevToken);
120+
}
121+
}
122+
123+
/**
124+
* Parse expected keyword (or throw relevant error)
125+
*
126+
* @param Parser $parser the instance that requests parsing
127+
* @param Token $token token to be parsed
128+
* @param Array $expected_keywords array of possibly expected keywords at this point
129+
*/
130+
private static function parseExpectedKeyword($parser, $token, $expected_keywords)
131+
{
132+
if ($token->type === Token::TYPE_KEYWORD) {
133+
if (in_array($token->keyword, $expected_keywords)) {
134+
return $token->keyword;
135+
} else {
136+
$parser->error('Unexpected keyword', $token);
137+
}
138+
} else {
139+
$parser->error('Unexpected token.', $token);
140+
}
141+
return null;
142+
}
143+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace PhpMyAdmin\SqlParser\Tests\Builder;
4+
5+
use PhpMyAdmin\SqlParser\Parser;
6+
use PhpMyAdmin\SqlParser\Tests\TestCase;
7+
8+
class PurgeStatementTest extends TestCase
9+
{
10+
public function testBuilder()
11+
{
12+
$query = 'PURGE BINARY LOGS TO \'mysql-bin.010\'';
13+
$parser = new Parser($query);
14+
$stmt = $parser->statements[0];
15+
$this->assertEquals($query, $stmt->build());
16+
17+
$query = 'PURGE BINARY LOGS BEFORE \'2008-04-02 22:46:26\'';
18+
$parser = new Parser($query);
19+
$stmt = $parser->statements[0];
20+
$this->assertEquals($query, $stmt->build());
21+
}
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace PhpMyAdmin\SqlParser\Tests\Parser;
4+
5+
use PhpMyAdmin\SqlParser\Tests\TestCase;
6+
7+
class PurgeStatementTest extends TestCase
8+
{
9+
/**
10+
* @dataProvider testPurgeProvider
11+
*
12+
* @param mixed $test
13+
*/
14+
public function testPurge($test)
15+
{
16+
$this->runParserTest($test);
17+
}
18+
19+
public function testPurgeProvider()
20+
{
21+
return array(
22+
array('parser/parsePurge'),
23+
array('parser/parsePurge2'),
24+
array('parser/parsePurge3'),
25+
array('parser/parsePurge4'),
26+
array('parser/parsePurgeErr'),
27+
array('parser/parsePurgeErr2'),
28+
array('parser/parsePurgeErr3'),
29+
);
30+
}
31+
}

tests/data/parser/parsePurge.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PURGE BINARY LOGS TO 'mysql-bin.010';

tests/data/parser/parsePurge.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a:4:{s:5:"query";s:37:"PURGE BINARY LOGS TO 'mysql-bin.010';";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:37:"PURGE BINARY LOGS TO 'mysql-bin.010';";s:3:"len";i:37;s:4:"last";i:37;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:11:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"PURGE";s:5:"value";s:5:"PURGE";s:7:"keyword";s:5:"PURGE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:0;}i:1;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:5;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"BINARY";s:5:"value";s:6:"BINARY";s:7:"keyword";s:6:"BINARY";s:4:"type";i:1;s:5:"flags";i:43;s:8:"position";i:6;}i:3;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:12;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:4:"LOGS";s:5:"value";s:4:"LOGS";s:7:"keyword";s:4:"LOGS";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:13;}i:5;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:17;}i:6;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:2:"TO";s:5:"value";s:2:"TO";s:7:"keyword";s:2:"TO";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:18;}i:7;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:20;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:15:"'mysql-bin.010'";s:5:"value";s:13:"mysql-bin.010";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:21;}i:9;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:36;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";N;s:5:"value";N;s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:11;s:3:"idx";i:11;}s:9:"delimiter";s:1:";";s:12:"delimiterLen";i:1;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"parser";O:27:"PhpMyAdmin\SqlParser\Parser":5:{s:4:"list";r:7;s:10:"statements";a:1:{i:0;O:46:"PhpMyAdmin\SqlParser\Statements\PurgeStatement":6:{s:8:"log_type";s:6:"BINARY";s:10:"end_option";s:2:"TO";s:8:"end_expr";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:13:"mysql-bin.010";s:4:"expr";s:15:"'mysql-bin.010'";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"options";N;s:5:"first";i:0;s:4:"last";i:9;}}s:8:"brackets";i:0;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"errors";a:2:{s:5:"lexer";a:0:{}s:6:"parser";a:0:{}}}

tests/data/parser/parsePurge2.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';

tests/data/parser/parsePurge2.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a:4:{s:5:"query";s:47:"PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:47:"PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';";s:3:"len";i:47;s:4:"last";i:47;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:11:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"PURGE";s:5:"value";s:5:"PURGE";s:7:"keyword";s:5:"PURGE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:0;}i:1;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:5;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"BINARY";s:5:"value";s:6:"BINARY";s:7:"keyword";s:6:"BINARY";s:4:"type";i:1;s:5:"flags";i:43;s:8:"position";i:6;}i:3;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:12;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:4:"LOGS";s:5:"value";s:4:"LOGS";s:7:"keyword";s:4:"LOGS";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:13;}i:5;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:17;}i:6;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"BEFORE";s:5:"value";s:6:"BEFORE";s:7:"keyword";s:6:"BEFORE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:18;}i:7;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:24;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:21:"'2008-04-02 22:46:26'";s:5:"value";s:19:"2008-04-02 22:46:26";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:25;}i:9;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:46;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";N;s:5:"value";N;s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:11;s:3:"idx";i:11;}s:9:"delimiter";s:1:";";s:12:"delimiterLen";i:1;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"parser";O:27:"PhpMyAdmin\SqlParser\Parser":5:{s:4:"list";r:7;s:10:"statements";a:1:{i:0;O:46:"PhpMyAdmin\SqlParser\Statements\PurgeStatement":6:{s:8:"log_type";s:6:"BINARY";s:10:"end_option";s:6:"BEFORE";s:8:"end_expr";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:19:"2008-04-02 22:46:26";s:4:"expr";s:21:"'2008-04-02 22:46:26'";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"options";N;s:5:"first";i:0;s:4:"last";i:9;}}s:8:"brackets";i:0;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"errors";a:2:{s:5:"lexer";a:0:{}s:6:"parser";a:0:{}}}

tests/data/parser/parsePurge3.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PURGE MASTER LOGS BEFORE '2008-04-02 22:46:26';

tests/data/parser/parsePurge3.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a:4:{s:5:"query";s:47:"PURGE MASTER LOGS BEFORE '2008-04-02 22:46:26';";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:47:"PURGE MASTER LOGS BEFORE '2008-04-02 22:46:26';";s:3:"len";i:47;s:4:"last";i:47;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:11:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"PURGE";s:5:"value";s:5:"PURGE";s:7:"keyword";s:5:"PURGE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:0;}i:1;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:5;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"MASTER";s:5:"value";s:6:"MASTER";s:7:"keyword";s:6:"MASTER";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:6;}i:3;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:12;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:4:"LOGS";s:5:"value";s:4:"LOGS";s:7:"keyword";s:4:"LOGS";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:13;}i:5;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:17;}i:6;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"BEFORE";s:5:"value";s:6:"BEFORE";s:7:"keyword";s:6:"BEFORE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:18;}i:7;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:24;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:21:"'2008-04-02 22:46:26'";s:5:"value";s:19:"2008-04-02 22:46:26";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:25;}i:9;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:46;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";N;s:5:"value";N;s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:11;s:3:"idx";i:11;}s:9:"delimiter";s:1:";";s:12:"delimiterLen";i:1;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"parser";O:27:"PhpMyAdmin\SqlParser\Parser":5:{s:4:"list";r:7;s:10:"statements";a:1:{i:0;O:46:"PhpMyAdmin\SqlParser\Statements\PurgeStatement":6:{s:8:"log_type";s:6:"MASTER";s:10:"end_option";s:6:"BEFORE";s:8:"end_expr";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:19:"2008-04-02 22:46:26";s:4:"expr";s:21:"'2008-04-02 22:46:26'";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"options";N;s:5:"first";i:0;s:4:"last";i:9;}}s:8:"brackets";i:0;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"errors";a:2:{s:5:"lexer";a:0:{}s:6:"parser";a:0:{}}}

0 commit comments

Comments
 (0)