forked from phpmyadmin/sql-parser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLockStatement.php
More file actions
136 lines (114 loc) · 3.43 KB
/
LockStatement.php
File metadata and controls
136 lines (114 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?php
/**
* `LOCK` statement.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Statements;
use PhpMyAdmin\SqlParser\Components\LockExpression;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Statement;
use PhpMyAdmin\SqlParser\Token;
use PhpMyAdmin\SqlParser\TokensList;
use function trim;
/**
* `LOCK` statement.
*/
class LockStatement extends Statement
{
/**
* Tables with their Lock expressions.
*
* @var LockExpression[]
*/
public $locked = [];
/**
* Whether it's a LOCK statement
* if false, it's an UNLOCK statement
*
* @var bool
*/
public $isLock = true;
/**
* @param Parser $parser the instance that requests parsing
* @param TokensList $list the list of tokens to be parsed
*/
public function parse(Parser $parser, TokensList $list)
{
if ($list->tokens[$list->idx]->value === 'UNLOCK') {
// this is in fact an UNLOCK statement
$this->isLock = false;
}
++$list->idx; // Skipping `LOCK`.
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ---------------- [ TABLES ] -----------------> 1
* 1 -------------- [ lock_expr ] ----------------> 2
* 2 ------------------ [ , ] --------------------> 1
*
* @var int
*/
$state = 0;
/**
* Previous parsed token
*/
$prevToken = null;
for (; $list->idx < $list->count; ++$list->idx) {
/**
* Token parsed at this moment.
*
* @var Token
*/
$token = $list->tokens[$list->idx];
// End of statement.
if ($token->type === Token::TYPE_DELIMITER) {
break;
}
// Skipping whitespaces and comments.
if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
continue;
}
if ($state === 0) {
if ($token->type === Token::TYPE_KEYWORD) {
if ($token->keyword !== 'TABLES') {
$parser->error('Unexpected keyword.', $token);
break;
}
$state = 1;
continue;
}
$parser->error('Unexpected token.', $token);
break;
}
if ($state === 1) {
if (! $this->isLock) {
// UNLOCK statement should not have any more tokens
$parser->error('Unexpected token.', $token);
break;
}
$this->locked[] = LockExpression::parse($parser, $list);
$state = 2;
} elseif ($state === 2) {
if ($token->value === ',') {
// move over to parsing next lock expression
$state = 1;
}
}
$prevToken = $token;
}
if ($state === 2 || $prevToken === null) {
return;
}
$parser->error('Unexpected end of LOCK statement.', $prevToken);
}
/**
* @return string
*/
public function build()
{
return trim(($this->isLock ? 'LOCK' : 'UNLOCK')
. ' TABLES ' . LockExpression::build($this->locked));
}
}