Issues (119)

src/Statements/PurgeStatement.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Statements;
6
7
use PhpMyAdmin\SqlParser\Components\Expression;
8
use PhpMyAdmin\SqlParser\Parser;
9
use PhpMyAdmin\SqlParser\Parsers\Expressions;
10
use PhpMyAdmin\SqlParser\Statement;
11
use PhpMyAdmin\SqlParser\Token;
12
use PhpMyAdmin\SqlParser\TokensList;
13
use PhpMyAdmin\SqlParser\TokenType;
14
15
use function in_array;
16
use function trim;
17
18
/**
19
 * `PURGE` statement.
20
 *
21
 * PURGE { BINARY | MASTER } LOGS
22
 *   { TO 'log_name' | BEFORE datetime_expr }
23
 */
24
class PurgeStatement extends Statement
25
{
26
    /**
27
     * The type of logs
28
     */
29
    public string|null $logType = null;
30
31
    /**
32
     * The end option of this query.
33
     */
34
    public string|null $endOption = null;
35
36
    /**
37
     * The end expr of this query.
38
     */
39
    public Expression|null $endExpr = null;
40
41 2
    public function build(): string
42
    {
43 2
        $ret = 'PURGE ' . $this->logType . ' LOGS '
44 2
            . ($this->endOption !== null ? ($this->endOption . ' ' . $this->endExpr) : '');
45
46 2
        return trim($ret);
47
    }
48
49
    /**
50
     * @param Parser     $parser the instance that requests parsing
51
     * @param TokensList $list   the list of tokens to be parsed
52
     */
53 16
    public function parse(Parser $parser, TokensList $list): void
54
    {
55 16
        ++$list->idx; // Skipping `PURGE`.
56
57
        /**
58
         * The state of the parser.
59
         */
60 16
        $state = 0;
61
62 16
        $prevToken = null;
63 16
        for (; $list->idx < $list->count; ++$list->idx) {
64
            /**
65
             * Token parsed at this moment.
66
             */
67 16
            $token = $list->tokens[$list->idx];
68
69
            // End of statement.
70 16
            if ($token->type === TokenType::Delimiter) {
71 16
                break;
72
            }
73
74
            // Skipping whitespaces and comments.
75 16
            if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
76 16
                continue;
77
            }
78
79
            switch ($state) {
80 16
                case 0:
81
                    // parse `{ BINARY | MASTER }`
82 16
                    $this->logType = self::parseExpectedKeyword($parser, $token, ['BINARY', 'MASTER']);
83 16
                    break;
84 16
                case 1:
85
                    // parse `LOGS`
86 16
                    self::parseExpectedKeyword($parser, $token, ['LOGS']);
87 16
                    break;
88 16
                case 2:
89
                    // parse `{ TO | BEFORE }`
90 16
                    $this->endOption = self::parseExpectedKeyword($parser, $token, ['TO', 'BEFORE']);
91 16
                    break;
92 12
                case 3:
93
                    // parse `expr`
94 12
                    $this->endExpr = Expressions::parse($parser, $list, []);
95 12
                    break;
96
                default:
97 2
                    $parser->error('Unexpected token.', $token);
98 2
                    break;
99
            }
100
101 16
            $state++;
102 16
            $prevToken = $token;
103
        }
104
105
        // Only one possible end state
106 16
        if ($state === 4) {
0 ignored issues
show
The condition $state === 4 is always false.
Loading history...
107 10
            return;
108
        }
109
110 6
        $parser->error('Unexpected token.', $prevToken);
111
    }
112
113
    /**
114
     * Parse expected keyword (or throw relevant error)
115
     *
116
     * @param Parser   $parser           the instance that requests parsing
117
     * @param Token    $token            token to be parsed
118
     * @param string[] $expectedKeywords array of possibly expected keywords at this point
119
     */
120 16
    private static function parseExpectedKeyword(Parser $parser, Token $token, array $expectedKeywords): string|null
121
    {
122 16
        if ($token->type === TokenType::Keyword) {
123 16
            if (in_array($token->keyword, $expectedKeywords)) {
124 14
                return $token->keyword;
125
            }
126
127 4
            $parser->error('Unexpected keyword', $token);
128
        } else {
129 2
            $parser->error('Unexpected token.', $token);
130
        }
131
132 4
        return null;
133
    }
134
}
135