[BUGFIX] Add missing namespace parts
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Database / Schema / Parser / IndexDefinitionTest.php
1 <?php
2 declare(strict_types=1);
3
4 namespace TYPO3\CMS\Core\Tests\Unit\Database\Schema\Parser;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateIndexDefinitionItem;
20 use TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateTableStatement;
21 use TYPO3\CMS\Core\Database\Schema\Parser\AST\Identifier;
22 use TYPO3\CMS\Core\Database\Schema\Parser\Parser;
23
24 /**
25 * Tests for CreateIndexDefinitionItem
26 */
27 class IndexDefinitionTest extends \TYPO3\Components\TestingFramework\Core\Unit\UnitTestCase
28 {
29 /**
30 * Each parameter array consists of the following values:
31 * - index definition SQL fragment
32 * - expected index name
33 * - array of index column definitions [name, length, direction]
34 * - isPrimary
35 * - isUnique
36 * - isFulltext
37 * - isSpatial
38 * - indexType
39 * - options array
40 *
41 * @return array
42 */
43 public function canParseIndexDefinitionDataProvider(): array
44 {
45 return [
46 'PRIMARY KEY (single column)' => [
47 'PRIMARY KEY (`aField`)',
48 '',
49 [['aField', 0, null]],
50 true,
51 false,
52 false,
53 false,
54 '',
55 [],
56 ],
57 'PRIMARY KEY (multiple columns)' => [
58 'PRIMARY KEY (`aField`, `bField`(199), cField)',
59 '',
60 [['aField', 0, null], ['bField', 199, null], ['cField', 0, null]],
61 true,
62 false,
63 false,
64 false,
65 '',
66 [],
67 ],
68 'PRIMARY KEY (index type)' => [
69 'PRIMARY KEY USING HASH (`aField`)',
70 '',
71 [['aField', 0, null]],
72 true,
73 false,
74 false,
75 false,
76 'HASH',
77 [],
78 ],
79 'PRIMARY KEY (index options)' => [
80 "PRIMARY KEY (`aField`, bField(199)) KEY_BLOCK_SIZE 4 WITH PARSER `something` COMMENT 'aTest'",
81 '',
82 [['aField', 0, null], ['bField', 199, null]],
83 true,
84 false,
85 false,
86 false,
87 '',
88 [
89 'key_block_size' => 4,
90 'parser' => new Identifier('something'),
91 'comment' => 'aTest',
92 ],
93 ],
94 'PRIMARY KEY (all parts)' => [
95 "PRIMARY KEY USING BTREE (`aField`, bField(199)) KEY_BLOCK_SIZE 4 COMMENT 'aTest'",
96 '',
97 [['aField', 0, null], ['bField', 199, null]],
98 true,
99 false,
100 false,
101 false,
102 'BTREE',
103 [
104 'key_block_size' => 4,
105 'comment' => 'aTest',
106 ],
107 ],
108 'INDEX (single column)' => [
109 'INDEX (`aField`(24))',
110 '',
111 [['aField', 24, null]],
112 false,
113 false,
114 false,
115 false,
116 '',
117 [],
118 ],
119 'INDEX (multiple columns)' => [
120 'INDEX (`aField`(24), bField)',
121 '',
122 [['aField', 24, null], ['bField', 0, null]],
123 false,
124 false,
125 false,
126 false,
127 '',
128 [],
129 ],
130 'INDEX (index name)' => [
131 'INDEX aIndex (`aField`)',
132 'aIndex',
133 [['aField', 0, null]],
134 false,
135 false,
136 false,
137 false,
138 '',
139 [],
140 ],
141 'INDEX (index type)' => [
142 'INDEX USING HASH (`aField`)',
143 '',
144 [['aField', 0, null]],
145 false,
146 false,
147 false,
148 false,
149 'HASH',
150 [],
151 ],
152 'INDEX (index name & type)' => [
153 'INDEX `aIndex` USING BTREE (`aField`)',
154 'aIndex',
155 [['aField', 0, null]],
156 false,
157 false,
158 false,
159 false,
160 'BTREE',
161 [],
162 ],
163 'INDEX (all parts)' => [
164 "INDEX `aIndex` USING BTREE (`aField`) COMMENT 'aComment'",
165 'aIndex',
166 [['aField', 0, null]],
167 false,
168 false,
169 false,
170 false,
171 'BTREE',
172 [
173 'comment' => 'aComment',
174 ],
175 ],
176 'KEY (single column)' => [
177 'KEY (`aField`(24))',
178 '',
179 [['aField', 24, null]],
180 false,
181 false,
182 false,
183 false,
184 '',
185 [],
186 ],
187 'KEY (multiple columns)' => [
188 'KEY (`aField`(24), bField)',
189 '',
190 [['aField', 24, null], ['bField', 0, null]],
191 false,
192 false,
193 false,
194 false,
195 '',
196 [],
197 ],
198 'KEY (index name)' => [
199 'KEY aIndex (`aField`)',
200 'aIndex',
201 [['aField', 0, null]],
202 false,
203 false,
204 false,
205 false,
206 '',
207 [],
208 ],
209 'KEY (index type)' => [
210 'KEY USING BTREE (aField(96))',
211 '',
212 [['aField', 96, null]],
213 false,
214 false,
215 false,
216 false,
217 'BTREE',
218 [],
219 ],
220 'KEY (index name & type)' => [
221 'KEY `aIndex` USING HASH (`aField`)',
222 'aIndex',
223 [['aField', 0, null]],
224 false,
225 false,
226 false,
227 false,
228 'HASH',
229 [],
230 ],
231 'KEY (all parts)' => [
232 'KEY `aIndex` USING HASH (`aField`) WITH PARSER aParser',
233 'aIndex',
234 [['aField', 0, null]],
235 false,
236 false,
237 false,
238 false,
239 'HASH',
240 [
241 'parser' => new Identifier('aParser'),
242 ],
243 ],
244 'UNIQUE (single column)' => [
245 'UNIQUE (`aField`)',
246 '',
247 [['aField', 0, null]],
248 false,
249 true,
250 false,
251 false,
252 '',
253 [],
254 ],
255 'UNIQUE (multiple columns)' => [
256 'UNIQUE (`aField`, bField, cField(40))',
257 '',
258 [['aField', 0, null], ['bField', 0, null], ['cField', 40, null]],
259 false,
260 true,
261 false,
262 false,
263 '',
264 [],
265 ],
266 'UNIQUE INDEX (single column)' => [
267 'UNIQUE INDEX (`aField`)',
268 '',
269 [['aField', 0, null]],
270 false,
271 true,
272 false,
273 false,
274 '',
275 [],
276 ],
277 'UNIQUE KEY (multiple columns)' => [
278 'UNIQUE KEY (`aField`, bField, cField(40))',
279 '',
280 [['aField', 0, null], ['bField', 0, null], ['cField', 40, null]],
281 false,
282 true,
283 false,
284 false,
285 '',
286 [],
287 ],
288 'UNIQUE (index name)' => [
289 'UNIQUE aIndex (`aField`)',
290 'aIndex',
291 [['aField', 0, null]],
292 false,
293 true,
294 false,
295 false,
296 '',
297 [],
298 ],
299 'UNIQUE (index type)' => [
300 'UNIQUE USING BTREE (`aField`)',
301 '',
302 [['aField', 0, null]],
303 false,
304 true,
305 false,
306 false,
307 'BTREE',
308 [],
309 ],
310 'UNIQUE (index name & type)' => [
311 'UNIQUE `aIndex` USING BTREE (`aField`)',
312 'aIndex',
313 [['aField', 0, null]],
314 false,
315 true,
316 false,
317 false,
318 'BTREE',
319 [],
320 ],
321 'UNIQUE (all parts)' => [
322 'UNIQUE `aIndex` USING BTREE (`aField`) KEY_BLOCK_SIZE = 24',
323 'aIndex',
324 [['aField', 0, null]],
325 false,
326 true,
327 false,
328 false,
329 'BTREE',
330 [
331 'key_block_size' => 24,
332 ],
333 ],
334 'FULLTEXT (single column)' => [
335 'FULLTEXT (`aField`)',
336 '',
337 [['aField', 0, null]],
338 false,
339 false,
340 true,
341 false,
342 '',
343 [],
344 ],
345 'FULLTEXT (multiple columns)' => [
346 'FULLTEXT (`aField`, `bField`)',
347 '',
348 [['aField', 0, null], ['bField', 0, null]],
349 false,
350 false,
351 true,
352 false,
353 '',
354 [],
355 ],
356 'FULLTEXT (index name)' => [
357 'FULLTEXT aIndex (`aField`, `bField`)',
358 'aIndex',
359 [['aField', 0, null], ['bField', 0, null]],
360 false,
361 false,
362 true,
363 false,
364 '',
365 [],
366 ],
367 'FULLTEXT (all parts)' => [
368 "FULLTEXT `aIndex` (`aField`, `bField`) COMMENT 'aComment'",
369 'aIndex',
370 [['aField', 0, null], ['bField', 0, null]],
371 false,
372 false,
373 true,
374 false,
375 '',
376 [
377 'comment' => 'aComment',
378 ],
379 ],
380 'FULLTEXT INDEX (single column)' => [
381 'FULLTEXT INDEX (`aField`)',
382 '',
383 [['aField', 0, null]],
384 false,
385 false,
386 true,
387 false,
388 '',
389 [],
390 ],
391 'FULLTEXT INDEX (multiple columns)' => [
392 'FULLTEXT INDEX (`aField`, bField(19))',
393 '',
394 [['aField', 0, null], ['bField', 19, null]],
395 false,
396 false,
397 true,
398 false,
399 '',
400 [],
401 ],
402 'FULLTEXT KEY (single column)' => [
403 'FULLTEXT KEY (aField(20))',
404 '',
405 [['aField', 20, null]],
406 false,
407 false,
408 true,
409 false,
410 '',
411 [],
412 ],
413 'FULLTEXT KEY (multiple columns)' => [
414 'FULLTEXT KEY (aField(20), `bField`)',
415 '',
416 [['aField', 20, null], ['bField', 0, null]],
417 false,
418 false,
419 true,
420 false,
421 '',
422 [],
423 ],
424 'SPATIAL (single column)' => [
425 'SPATIAL (`aField`)',
426 '',
427 [['aField', 0, null]],
428 false,
429 false,
430 false,
431 true,
432 '',
433 [],
434 ],
435 'SPATIAL (multiple columns)' => [
436 'SPATIAL (`aField`, `bField`)',
437 '',
438 [['aField', 0, null], ['bField', 0, null]],
439 false,
440 false,
441 false,
442 true,
443 '',
444 [],
445 ],
446 'SPATIAL (index name)' => [
447 'SPATIAL `aIndex` (`aField`, `bField`)',
448 'aIndex',
449 [['aField', 0, null], ['bField', 0, null]],
450 false,
451 false,
452 false,
453 true,
454 '',
455 [],
456 ],
457 'SPATIAL (all parts)' => [
458 "SPATIAL `aIndex` (`aField`, `bField`) WITH PARSER aParser COMMENT 'aComment'",
459 'aIndex',
460 [['aField', 0, null], ['bField', 0, null]],
461 false,
462 false,
463 false,
464 true,
465 '',
466 [
467 'parser' => new Identifier('aParser'),
468 'comment' => 'aComment',
469 ],
470 ],
471 'SPATIAL INDEX (single column)' => [
472 'SPATIAL INDEX (`aField`)',
473 '',
474 [['aField', 0, null]],
475 false,
476 false,
477 false,
478 true,
479 '',
480 [],
481 ],
482 'SPATIAL INDEX (multiple columns)' => [
483 'SPATIAL INDEX (aField, bField)',
484 '',
485 [['aField', 0, null], ['bField', 0, null]],
486 false,
487 false,
488 false,
489 true,
490 '',
491 [],
492 ],
493 'SPATIAL KEY (single column)' => [
494 'SPATIAL KEY (aField)',
495 '',
496 [['aField', 0, null]],
497 false,
498 false,
499 false,
500 true,
501 '',
502 [],
503 ],
504 'SPATIAL KEY (multiple columns)' => [
505 'SPATIAL KEY (aField, bField(240))',
506 '',
507 [['aField', 0, null], ['bField', 240, null]],
508 false,
509 false,
510 false,
511 true,
512 '',
513 [],
514 ],
515 ];
516 }
517
518 /**
519 * @test
520 * @dataProvider canParseIndexDefinitionDataProvider
521 * @param string $indexDefinition
522 * @param string $indexName
523 * @param array $indexColumns
524 * @param bool $isPrimary
525 * @param bool $isUnique
526 * @param bool $isFulltext
527 * @param bool $isSpatial
528 * @param string $indexType
529 * @param array $indexOptions
530 */
531 public function canParseIndexDefinition(
532 string $indexDefinition,
533 string $indexName,
534 array $indexColumns,
535 bool $isPrimary,
536 bool $isUnique,
537 bool $isFulltext,
538 bool $isSpatial,
539 string $indexType,
540 array $indexOptions
541 ) {
542 $statement = sprintf('CREATE TABLE `aTable`(`aField` INT(11), %s);', $indexDefinition);
543 $subject = $this->createSubject($statement);
544
545 $this->assertInstanceOf(CreateIndexDefinitionItem::class, $subject);
546 $this->assertSame($indexName, $subject->indexName->schemaObjectName);
547 $this->assertSame($isPrimary, $subject->isPrimary);
548 $this->assertSame($isUnique, $subject->isUnique);
549 $this->assertSame($isFulltext, $subject->isFulltext);
550 $this->assertSame($isSpatial, $subject->isSpatial);
551 $this->assertSame($indexType, $subject->indexType);
552 $this->assertEquals($indexOptions, $subject->options);
553
554 foreach ($indexColumns as $index => $column) {
555 $this->assertSame($column[0], $subject->columnNames[$index]->columnName->schemaObjectName);
556 $this->assertSame($column[1], $subject->columnNames[$index]->length);
557 $this->assertSame($column[2], $subject->columnNames[$index]->direction);
558 }
559 }
560
561 /**
562 * Parse the CREATE TABLE statement and return the reference definition
563 *
564 * @param string $statement
565 * @return \TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateIndexDefinitionItem
566 */
567 protected function createSubject(string $statement): CreateIndexDefinitionItem
568 {
569 $parser = new Parser($statement);
570 /** @var CreateTableStatement $createTableStatement */
571 $createTableStatement = $parser->getAST();
572
573 return $createTableStatement->createDefinition->items[1];
574 }
575 }