Completed
Pull Request — master (#16756)
by Vladimir
13:05
created

SqlTokenizer   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 91.84%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 1
dl 0
loc 272
ccs 45
cts 49
cp 0.9184
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A isWhitespace() 0 13 1
A isOperator() 0 31 1
B isIdentifier() 0 28 6
A isStringLiteral() 0 17 4
B isKeyword() 0 137 2
A isComment() 0 20 3
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\db\sqlite;
9
10
/**
11
 * SqlTokenizer splits SQLite query into individual SQL tokens.
12
 * It's used to obtain a `CHECK` constraint information from a `CREATE TABLE` SQL code.
13
 *
14
 * @see http://www.sqlite.org/draft/tokenreq.html
15
 * @see https://sqlite.org/lang.html
16
 * @author Sergey Makinen <[email protected]>
17
 * @since 2.0.13
18
 */
19
class SqlTokenizer extends \yii\db\SqlTokenizer
20
{
21
    /**
22
     * {@inheritdoc}
23
     */
24 22
    protected function isWhitespace(&$length)
25
    {
26 22
        static $whitespaces = [
27
            "\f" => true,
28
            "\n" => true,
29
            "\r" => true,
30
            "\t" => true,
31
            ' ' => true,
32
        ];
33
34 22
        $length = 1;
35 22
        return isset($whitespaces[$this->substring($length)]);
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41 22
    protected function isComment(&$length)
42
    {
43 22
        static $comments = [
44
            '--' => true,
45
            '/*' => true,
46
        ];
47
48 22
        $length = 2;
49 22
        if (!isset($comments[$this->substring($length)])) {
50 22
            return false;
51
        }
52
53
        if ($this->substring($length) === '--') {
54
            $length = $this->indexAfter("\n") - $this->offset;
55
        } else {
56
            $length = $this->indexAfter('*/') - $this->offset;
57
        }
58
59
        return true;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65 22
    protected function isOperator(&$length, &$content)
66
    {
67 22
        static $operators = [
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 22
        return $this->startsWithAnyLongest($operators, true, $length);
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100 22
    protected function isIdentifier(&$length, &$content)
101
    {
102 22
        static $identifierDelimiters = [
103
            '"' => '"',
104
            '[' => ']',
105
            '`' => '`',
106
        ];
107
108 22
        if (!isset($identifierDelimiters[$this->substring(1)])) {
109 22
            return false;
110
        }
111
112 22
        $delimiter = $identifierDelimiters[$this->substring(1)];
113 22
        $offset = $this->offset;
114 22
        while (true) {
115 22
            $offset = $this->indexAfter($delimiter, $offset + 1);
116 22
            if ($delimiter === ']' || $this->substring(1, true, $offset) !== $delimiter) {
117 22
                break;
118
            }
119
        }
120 22
        $length = $offset - $this->offset;
121 22
        $content = $this->substring($length - 2, true, $this->offset + 1);
122 22
        if ($delimiter !== ']') {
123 22
            $content = strtr($content, ["$delimiter$delimiter" => $delimiter]);
124
        }
125
126 22
        return true;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132 22
    protected function isStringLiteral(&$length, &$content)
133
    {
134 22
        if ($this->substring(1) !== "'") {
135 22
            return false;
136
        }
137
138 3
        $offset = $this->offset;
139 3
        while (true) {
140 3
            $offset = $this->indexAfter("'", $offset + 1);
141 3
            if ($this->substring(1, true, $offset) !== "'") {
142 3
                break;
143
            }
144
        }
145 3
        $length = $offset - $this->offset;
146 3
        $content = strtr($this->substring($length - 2, true, $this->offset + 1), ["''" => "'"]);
147 3
        return true;
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153 22
    protected function isKeyword($string, &$content)
154
    {
155 22
        static $keywords = [
156
            'ABORT' => true,
157
            'ACTION' => true,
158
            'ADD' => true,
159
            'AFTER' => true,
160
            'ALL' => true,
161
            'ALTER' => true,
162
            'ANALYZE' => true,
163
            'AND' => true,
164
            'AS' => true,
165
            'ASC' => true,
166
            'ATTACH' => true,
167
            'AUTOINCREMENT' => true,
168
            'BEFORE' => true,
169
            'BEGIN' => true,
170
            'BETWEEN' => true,
171
            'BY' => true,
172
            'CASCADE' => true,
173
            'CASE' => true,
174
            'CAST' => true,
175
            'CHECK' => true,
176
            'COLLATE' => true,
177
            'COLUMN' => true,
178
            'COMMIT' => true,
179
            'CONFLICT' => true,
180
            'CONSTRAINT' => true,
181
            'CREATE' => true,
182
            'CROSS' => true,
183
            'CURRENT_DATE' => true,
184
            'CURRENT_TIME' => true,
185
            'CURRENT_TIMESTAMP' => true,
186
            'DATABASE' => true,
187
            'DEFAULT' => true,
188
            'DEFERRABLE' => true,
189
            'DEFERRED' => true,
190
            'DELETE' => true,
191
            'DESC' => true,
192
            'DETACH' => true,
193
            'DISTINCT' => true,
194
            'DROP' => true,
195
            'EACH' => true,
196
            'ELSE' => true,
197
            'END' => true,
198
            'ESCAPE' => true,
199
            'EXCEPT' => true,
200
            'EXCLUSIVE' => true,
201
            'EXISTS' => true,
202
            'EXPLAIN' => true,
203
            'FAIL' => true,
204
            'FOR' => true,
205
            'FOREIGN' => true,
206
            'FROM' => true,
207
            'FULL' => true,
208
            'GLOB' => true,
209
            'GROUP' => true,
210
            'HAVING' => true,
211
            'IF' => true,
212
            'IGNORE' => true,
213
            'IMMEDIATE' => true,
214
            'IN' => true,
215
            'INDEX' => true,
216
            'INDEXED' => true,
217
            'INITIALLY' => true,
218
            'INNER' => true,
219
            'INSERT' => true,
220
            'INSTEAD' => true,
221
            'INTERSECT' => true,
222
            'INTO' => true,
223
            'IS' => true,
224
            'ISNULL' => true,
225
            'JOIN' => true,
226
            'KEY' => true,
227
            'LEFT' => true,
228
            'LIKE' => true,
229
            'LIMIT' => true,
230
            'MATCH' => true,
231
            'NATURAL' => true,
232
            'NO' => true,
233
            'NOT' => true,
234
            'NOTNULL' => true,
235
            'NULL' => true,
236
            'OF' => true,
237
            'OFFSET' => true,
238
            'ON' => true,
239
            'OR' => true,
240
            'ORDER' => true,
241
            'OUTER' => true,
242
            'PLAN' => true,
243
            'PRAGMA' => true,
244
            'PRIMARY' => true,
245
            'QUERY' => true,
246
            'RAISE' => true,
247
            'RECURSIVE' => true,
248
            'REFERENCES' => true,
249
            'REGEXP' => true,
250
            'REINDEX' => true,
251
            'RELEASE' => true,
252
            'RENAME' => true,
253
            'REPLACE' => true,
254
            'RESTRICT' => true,
255
            'RIGHT' => true,
256
            'ROLLBACK' => true,
257
            'ROW' => true,
258
            'SAVEPOINT' => true,
259
            'SELECT' => true,
260
            'SET' => true,
261
            'TABLE' => true,
262
            'TEMP' => true,
263
            'TEMPORARY' => true,
264
            'THEN' => true,
265
            'TO' => true,
266
            'TRANSACTION' => true,
267
            'TRIGGER' => true,
268
            'UNION' => true,
269
            'UNIQUE' => true,
270
            'UPDATE' => true,
271
            'USING' => true,
272
            'VACUUM' => true,
273
            'VALUES' => true,
274
            'VIEW' => true,
275
            'VIRTUAL' => true,
276
            'WHEN' => true,
277
            'WHERE' => true,
278
            'WITH' => true,
279
            'WITHOUT' => true,
280
        ];
281
282 22
        $string = mb_strtoupper($string, 'UTF-8');
283 22
        if (!isset($keywords[$string])) {
284 22
            return false;
285
        }
286
287 22
        $content = $string;
288 22
        return true;
289
    }
290
}
291