Completed
Push — master ( 0e2450...c4efad )
by Maurício
42s queued 37s
created

QueryTest::testGetAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 34
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 39
rs 9.376
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Tests\Utils;
6
7
use PhpMyAdmin\SqlParser\Parser;
8
use PhpMyAdmin\SqlParser\Tests\TestCase;
9
use PhpMyAdmin\SqlParser\Utils\Query;
10
use PhpMyAdmin\SqlParser\Utils\StatementFlags;
11
use PhpMyAdmin\SqlParser\Utils\StatementType;
12
use PHPUnit\Framework\Attributes\DataProvider;
13
14
class QueryTest extends TestCase
15
{
16
    /**
17
     * @psalm-param non-empty-string $query
18
     * @psalm-param array<key-of<properties-of<StatementFlags>>, bool|StatementType|null> $expected
19
     */
20
    #[DataProvider('getFlagsProvider')]
21
    public function testGetFlags(string $query, array $expected): void
22
    {
23
        $parser = new Parser($query);
24
        $flags = new StatementFlags();
25
        foreach ($expected as $property => $expectedValue) {
26
            $flags->$property = $expectedValue;
27
        }
28
29
        $this->assertEquals($flags, Query::getFlags($parser->statements[0]));
30
    }
31
32
    /** @psalm-return list<array{non-empty-string, array<key-of<properties-of<StatementFlags>>, bool|StatementType|null>}> */
33
    public static function getFlagsProvider(): array
34
    {
35
        return [
36
            [
37
                'ALTER TABLE DROP col',
38
                [
39
                    'reload' => true,
40
                    'queryType' => StatementType::Alter,
41
                ],
42
            ],
43
            [
44
                'CALL test()',
45
                [
46
                    'isProcedure' => true,
47
                    'queryType' => StatementType::Call,
48
                ],
49
            ],
50
            [
51
                'CREATE TABLE tbl (id INT)',
52
                [
53
                    'reload' => true,
54
                    'queryType' => StatementType::Create,
55
                ],
56
            ],
57
            [
58
                'CHECK TABLE tbl',
59
                [
60
                    'isMaint' => true,
61
                    'queryType' => StatementType::Check,
62
                ],
63
            ],
64
            [
65
                'DELETE FROM tbl',
66
                [
67
                    'isAffected' => true,
68
                    'isDelete' => true,
69
                    'queryType' => StatementType::Delete,
70
                ],
71
            ],
72
            [
73
                'DROP VIEW v',
74
                [
75
                    'reload' => true,
76
                    'queryType' => StatementType::Drop,
77
                ],
78
            ],
79
            [
80
                'DROP DATABASE db',
81
                [
82
                    'dropDatabase' => true,
83
                    'reload' => true,
84
                    'queryType' => StatementType::Drop,
85
                ],
86
            ],
87
            [
88
                'EXPLAIN tbl',
89
                [
90
                    'isExplain' => true,
91
                    'queryType' => StatementType::Explain,
92
                ],
93
            ],
94
            [
95
                'LOAD DATA INFILE \'/tmp/test.txt\' INTO TABLE test',
96
                [
97
                    'isAffected' => true,
98
                    'isInsert' => true,
99
                    'queryType' => StatementType::Load,
100
                ],
101
            ],
102
            [
103
                'INSERT INTO tbl VALUES (1)',
104
                [
105
                    'isAffected' => true,
106
                    'isInsert' => true,
107
                    'queryType' => StatementType::Insert,
108
                ],
109
            ],
110
            [
111
                'REPLACE INTO tbl VALUES (2)',
112
                [
113
                    'isAffected' => true,
114
                    'isReplace' => true,
115
                    'isInsert' => true,
116
                    'queryType' => StatementType::Replace,
117
                ],
118
            ],
119
            [
120
                'SELECT 1',
121
                [
122
                    'isSelect' => true,
123
                    'queryType' => StatementType::Select,
124
                ],
125
            ],
126
            [
127
                'SELECT * FROM tbl',
128
                [
129
                    'isSelect' => true,
130
                    'selectFrom' => true,
131
                    'queryType' => StatementType::Select,
132
                ],
133
            ],
134
            [
135
                'SELECT DISTINCT * FROM tbl LIMIT 0, 10 ORDER BY id',
136
                [
137
                    'distinct' => true,
138
                    'isSelect' => true,
139
                    'selectFrom' => true,
140
                    'limit' => true,
141
                    'order' => true,
142
                    'queryType' => StatementType::Select,
143
                ],
144
            ],
145
            [
146
                'SELECT * FROM actor GROUP BY actor_id',
147
                [
148
                    'isGroup' => true,
149
                    'isSelect' => true,
150
                    'selectFrom' => true,
151
                    'group' => true,
152
                    'queryType' => StatementType::Select,
153
                ],
154
            ],
155
            [
156
                'SELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);',
157
                [
158
                    'isAnalyse' => true,
159
                    'isSelect' => true,
160
                    'selectFrom' => true,
161
                    'queryType' => StatementType::Select,
162
                ],
163
            ],
164
            [
165
                'SELECT * FROM tbl INTO OUTFILE "/tmp/export.txt"',
166
                [
167
                    'isExport' => true,
168
                    'isSelect' => true,
169
                    'selectFrom' => true,
170
                    'queryType' => StatementType::Select,
171
                ],
172
            ],
173
            [
174
                'SELECT COUNT(id), SUM(id) FROM tbl',
175
                [
176
                    'isCount' => true,
177
                    'isFunc' => true,
178
                    'isSelect' => true,
179
                    'selectFrom' => true,
180
                    'queryType' => StatementType::Select,
181
                ],
182
            ],
183
            [
184
                'SELECT (SELECT "foo")',
185
                [
186
                    'isSelect' => true,
187
                    'isSubQuery' => true,
188
                    'queryType' => StatementType::Select,
189
                ],
190
            ],
191
            [
192
                'SELECT * FROM customer HAVING store_id = 2;',
193
                [
194
                    'isSelect' => true,
195
                    'selectFrom' => true,
196
                    'isGroup' => true,
197
                    'having' => true,
198
                    'queryType' => StatementType::Select,
199
                ],
200
            ],
201
            [
202
                'SELECT * FROM table1 INNER JOIN table2 ON table1.id=table2.id;',
203
                [
204
                    'isSelect' => true,
205
                    'selectFrom' => true,
206
                    'join' => true,
207
                    'queryType' => StatementType::Select,
208
                ],
209
            ],
210
            [
211
                'SHOW CREATE TABLE tbl',
212
                [
213
                    'isShow' => true,
214
                    'queryType' => StatementType::Show,
215
                ],
216
            ],
217
            [
218
                'UPDATE tbl SET id = 1',
219
                [
220
                    'isAffected' => true,
221
                    'queryType' => StatementType::Update,
222
                ],
223
            ],
224
            [
225
                'ANALYZE TABLE tbl',
226
                [
227
                    'isMaint' => true,
228
                    'queryType' => StatementType::Analyze,
229
                ],
230
            ],
231
            [
232
                'CHECKSUM TABLE tbl',
233
                [
234
                    'isMaint' => true,
235
                    'queryType' => StatementType::Checksum,
236
                ],
237
            ],
238
            [
239
                'OPTIMIZE TABLE tbl',
240
                [
241
                    'isMaint' => true,
242
                    'queryType' => StatementType::Optimize,
243
                ],
244
            ],
245
            [
246
                'REPAIR TABLE tbl',
247
                [
248
                    'isMaint' => true,
249
                    'queryType' => StatementType::Repair,
250
                ],
251
            ],
252
            [
253
                '(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) ' .
254
                'UNION ' .
255
                '(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);',
256
                [
257
                    'isSelect' => true,
258
                    'selectFrom' => true,
259
                    'limit' => true,
260
                    'order' => true,
261
                    'union' => true,
262
                    'queryType' => StatementType::Select,
263
                ],
264
            ],
265
            [
266
                'SELECT * FROM orders AS ord WHERE 1',
267
                [
268
                    'queryType' => StatementType::Select,
269
                    'isSelect' => true,
270
                    'selectFrom' => true,
271
                ],
272
            ],
273
            [
274
                'SET NAMES \'latin\'',
275
                ['queryType' => StatementType::Set],
276
            ],
277
        ];
278
    }
279
280
    public function testGetFlagsWithEmptyString(): void
281
    {
282
        $statementInfo = Query::getAll('');
283
        self::assertEquals(new Parser(''), $statementInfo->parser);
284
        self::assertNull($statementInfo->statement);
285
        self::assertSame([], $statementInfo->selectTables);
286
        self::assertSame([], $statementInfo->selectExpressions);
287
        $flags = $statementInfo->flags;
288
        self::assertFalse($flags->distinct);
289
        self::assertFalse($flags->dropDatabase);
290
        self::assertFalse($flags->group);
291
        self::assertFalse($flags->having);
292
        self::assertFalse($flags->isAffected);
293
        self::assertFalse($flags->isAnalyse);
294
        self::assertFalse($flags->isCount);
295
        /** @psalm-suppress DeprecatedProperty */
296
        self::assertFalse($flags->isDelete);
0 ignored issues
show
Deprecated Code introduced by
The property PhpMyAdmin\SqlParser\Uti...atementFlags::$isDelete has been deprecated: Use {@see self::$queryType} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

296
        self::assertFalse(/** @scrutinizer ignore-deprecated */ $flags->isDelete);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
297
        /** @psalm-suppress DeprecatedProperty */
298
        self::assertFalse($flags->isExplain);
0 ignored issues
show
Deprecated Code introduced by
The property PhpMyAdmin\SqlParser\Uti...tementFlags::$isExplain has been deprecated: Use {@see self::$queryType} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

298
        self::assertFalse(/** @scrutinizer ignore-deprecated */ $flags->isExplain);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
299
        self::assertFalse($flags->isExport);
300
        self::assertFalse($flags->isFunc);
301
        self::assertFalse($flags->isGroup);
302
        self::assertFalse($flags->isInsert);
303
        self::assertFalse($flags->isMaint);
304
        self::assertFalse($flags->isProcedure);
305
        /** @psalm-suppress DeprecatedProperty */
306
        self::assertFalse($flags->isReplace);
0 ignored issues
show
Deprecated Code introduced by
The property PhpMyAdmin\SqlParser\Uti...tementFlags::$isReplace has been deprecated: Use {@see self::$queryType} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

306
        self::assertFalse(/** @scrutinizer ignore-deprecated */ $flags->isReplace);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
307
        /** @psalm-suppress DeprecatedProperty */
308
        self::assertFalse($flags->isSelect);
0 ignored issues
show
Deprecated Code introduced by
The property PhpMyAdmin\SqlParser\Uti...atementFlags::$isSelect has been deprecated: Use {@see self::$queryType} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

308
        self::assertFalse(/** @scrutinizer ignore-deprecated */ $flags->isSelect);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
309
        /** @psalm-suppress DeprecatedProperty */
310
        self::assertFalse($flags->isShow);
0 ignored issues
show
Deprecated Code introduced by
The property PhpMyAdmin\SqlParser\Utils\StatementFlags::$isShow has been deprecated: Use {@see self::$queryType} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

310
        self::assertFalse(/** @scrutinizer ignore-deprecated */ $flags->isShow);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
311
        self::assertFalse($flags->isSubQuery);
312
        self::assertFalse($flags->join);
313
        self::assertFalse($flags->limit);
314
        self::assertFalse($flags->offset);
315
        self::assertFalse($flags->order);
316
        self::assertNull($flags->queryType);
317
        self::assertFalse($flags->reload);
318
        self::assertFalse($flags->selectFrom);
319
        self::assertFalse($flags->union);
320
    }
321
322
    public function testGetAll(): void
323
    {
324
        $query = 'SELECT *, actor.actor_id, sakila2.film.* FROM sakila2.city, sakila2.film, actor';
325
        $parser = new Parser($query);
326
        $statementInfo = Query::getAll($query);
327
        self::assertEquals($parser, $statementInfo->parser);
328
        self::assertEquals($parser->statements[0], $statementInfo->statement);
329
        self::assertEquals(Query::getFlags($parser->statements[0]), $statementInfo->flags);
330
        self::assertSame([['actor', null], ['film', 'sakila2']], $statementInfo->selectTables);
331
        self::assertSame(['*'], $statementInfo->selectExpressions);
332
333
        $query = 'SELECT * FROM sakila.actor, film';
334
        $parser = new Parser($query);
335
        $statementInfo = Query::getAll($query);
336
        self::assertEquals($parser, $statementInfo->parser);
337
        self::assertEquals($parser->statements[0], $statementInfo->statement);
338
        self::assertEquals(Query::getFlags($parser->statements[0]), $statementInfo->flags);
339
        self::assertSame([['actor', 'sakila'], ['film', null]], $statementInfo->selectTables);
340
        self::assertSame(['*'], $statementInfo->selectExpressions);
341
342
        $query = 'SELECT a.actor_id FROM sakila.actor AS a, film';
343
        $parser = new Parser($query);
344
        $statementInfo = Query::getAll($query);
345
        self::assertEquals($parser, $statementInfo->parser);
346
        self::assertEquals($parser->statements[0], $statementInfo->statement);
347
        self::assertEquals(Query::getFlags($parser->statements[0]), $statementInfo->flags);
348
        self::assertSame([['actor', 'sakila']], $statementInfo->selectTables);
349
        self::assertSame([], $statementInfo->selectExpressions);
350
351
        $query = 'SELECT CASE WHEN 2 IS NULL THEN "this is true" ELSE "this is false" END';
352
        $parser = new Parser($query);
353
        $statementInfo = Query::getAll($query);
354
        self::assertEquals($parser, $statementInfo->parser);
355
        self::assertEquals($parser->statements[0], $statementInfo->statement);
356
        self::assertEquals(Query::getFlags($parser->statements[0]), $statementInfo->flags);
357
        self::assertSame([], $statementInfo->selectTables);
358
        self::assertSame(
359
            ['CASE WHEN 2 IS NULL THEN "this is true" ELSE "this is false" END'],
360
            $statementInfo->selectExpressions,
361
        );
362
    }
363
364
    /** @param string[] $expected */
365
    #[DataProvider('getTablesProvider')]
366
    public function testGetTables(string $query, array $expected): void
367
    {
368
        $parser = new Parser($query);
369
        $this->assertEquals(
370
            $expected,
371
            Query::getTables($parser->statements[0]),
372
        );
373
    }
374
375
    /**
376
     * @return array<int, array<int, string|string[]>>
377
     * @psalm-return list<array{string, string[]}>
378
     */
379
    public static function getTablesProvider(): array
380
    {
381
        return [
382
            [
383
                'INSERT INTO tbl(`id`, `name`) VALUES (1, "Name")',
384
                ['`tbl`'],
385
            ],
386
            [
387
                'INSERT INTO 0tbl(`id`, `name`) VALUES (1, "Name")',
388
                ['`0tbl`'],
389
            ],
390
            [
391
                'UPDATE tbl SET id = 0',
392
                ['`tbl`'],
393
            ],
394
            [
395
                'UPDATE 0tbl SET id = 0',
396
                ['`0tbl`'],
397
            ],
398
            [
399
                'DELETE FROM tbl WHERE id < 10',
400
                ['`tbl`'],
401
            ],
402
            [
403
                'DELETE FROM 0tbl WHERE id < 10',
404
                ['`0tbl`'],
405
            ],
406
            [
407
                'TRUNCATE tbl',
408
                ['`tbl`'],
409
            ],
410
            [
411
                'DROP VIEW v',
412
                [],
413
            ],
414
            [
415
                'DROP TABLE tbl1, tbl2',
416
                [
417
                    '`tbl1`',
418
                    '`tbl2`',
419
                ],
420
            ],
421
            [
422
                'RENAME TABLE a TO b, c TO d',
423
                [
424
                    '`a`',
425
                    '`c`',
426
                ],
427
            ],
428
        ];
429
    }
430
431
    public function testGetClause(): void
432
    {
433
        /* Assertion 1 */
434
        $parser = new Parser(
435
            'SELECT c.city_id, c.country_id ' .
436
            'FROM `city` ' .
437
            'WHERE city_id < 1 /* test */' .
438
            'ORDER BY city_id ASC ' .
439
            'LIMIT 0, 1 ' .
440
            'INTO OUTFILE "/dev/null"',
441
        );
442
        $this->assertNotNull($parser->list);
443
        $this->assertEquals(
444
            '0, 1 INTO OUTFILE "/dev/null"',
445
            Query::getClause(
446
                $parser->statements[0],
447
                $parser->list,
0 ignored issues
show
Bug introduced by
It seems like $parser->list can also be of type null; however, parameter $list of PhpMyAdmin\SqlParser\Utils\Query::getClause() does only seem to accept PhpMyAdmin\SqlParser\TokensList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

447
                /** @scrutinizer ignore-type */ $parser->list,
Loading history...
448
                'LIMIT',
449
                0,
450
            ),
451
        );
452
        // Assert it returns all clauses between FROM and LIMIT
453
        $this->assertEquals(
454
            'WHERE city_id < 1 ORDER BY city_id ASC',
455
            Query::getClause(
456
                $parser->statements[0],
457
                $parser->list,
458
                'FROM',
459
                'LIMIT',
460
            ),
461
        );
462
        // Assert it returns all clauses between SELECT and LIMIT
463
        $this->assertEquals(
464
            'FROM `city` WHERE city_id < 1 ORDER BY city_id ASC',
465
            Query::getClause(
466
                $parser->statements[0],
467
                $parser->list,
468
                'LIMIT',
469
                'SELECT',
470
            ),
471
        );
472
473
        /* Assertion 2 */
474
        $parser = new Parser(
475
            'DELETE FROM `renewal` ' .
476
            'WHERE number = "1DB" AND actionDate <= CURRENT_DATE() ' .
477
            'ORDER BY id ASC ' .
478
            'LIMIT 1',
479
        );
480
        $this->assertNotNull($parser->list);
481
        $this->assertEquals(
482
            'number = "1DB" AND actionDate <= CURRENT_DATE()',
483
            Query::getClause(
484
                $parser->statements[0],
485
                $parser->list,
486
                'WHERE',
487
            ),
488
        );
489
        $this->assertEquals(
490
            '1',
491
            Query::getClause(
492
                $parser->statements[0],
493
                $parser->list,
494
                'LIMIT',
495
            ),
496
        );
497
        $this->assertEquals(
498
            'id ASC',
499
            Query::getClause(
500
                $parser->statements[0],
501
                $parser->list,
502
                'ORDER BY',
503
            ),
504
        );
505
506
        /* Assertion 3 */
507
        $parser = new Parser(
508
            'UPDATE `renewal` SET `some_column` = 1 ' .
509
            'WHERE number = "1DB" AND actionDate <= CURRENT_DATE() ' .
510
            'ORDER BY id ASC ' .
511
            'LIMIT 1',
512
        );
513
        $this->assertNotNull($parser->list);
514
        $this->assertEquals(
515
            'number = "1DB" AND actionDate <= CURRENT_DATE()',
516
            Query::getClause(
517
                $parser->statements[0],
518
                $parser->list,
519
                'WHERE',
520
            ),
521
        );
522
        $this->assertEquals(
523
            '1',
524
            Query::getClause(
525
                $parser->statements[0],
526
                $parser->list,
527
                'LIMIT',
528
            ),
529
        );
530
        $this->assertEquals(
531
            'id ASC',
532
            Query::getClause(
533
                $parser->statements[0],
534
                $parser->list,
535
                'ORDER BY',
536
            ),
537
        );
538
    }
539
540
    public function testReplaceClause(): void
541
    {
542
        $parser = new Parser('SELECT *, (SELECT 1) FROM film LIMIT 0, 10;');
543
        $this->assertNotNull($parser->list);
544
        $this->assertEquals(
545
            'SELECT *, (SELECT 1) FROM film WHERE film_id > 0 LIMIT 0, 10',
546
            Query::replaceClause(
547
                $parser->statements[0],
548
                $parser->list,
0 ignored issues
show
Bug introduced by
It seems like $parser->list can also be of type null; however, parameter $list of PhpMyAdmin\SqlParser\Utils\Query::replaceClause() does only seem to accept PhpMyAdmin\SqlParser\TokensList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

548
                /** @scrutinizer ignore-type */ $parser->list,
Loading history...
549
                'WHERE film_id > 0',
550
            ),
551
        );
552
553
        $parser = new Parser(
554
            'select supplier.city, supplier.id from supplier '
555
            . 'union select customer.city, customer.id from customer',
556
        );
557
        $this->assertNotNull($parser->list);
558
        $this->assertEquals(
559
            'select supplier.city, supplier.id from supplier '
560
            . 'union select customer.city, customer.id from customer'
561
            . ' ORDER BY city ',
562
            Query::replaceClause(
563
                $parser->statements[0],
564
                $parser->list,
565
                'ORDER BY city',
566
            ),
567
        );
568
    }
569
570
    public function testReplaceClauseOnlyKeyword(): void
571
    {
572
        $parser = new Parser('SELECT *, (SELECT 1) FROM film LIMIT 0, 10');
573
        $this->assertNotNull($parser->list);
574
        $this->assertEquals(
575
            ' SELECT SQL_CALC_FOUND_ROWS *, (SELECT 1) FROM film LIMIT 0, 10',
576
            Query::replaceClause(
577
                $parser->statements[0],
578
                $parser->list,
0 ignored issues
show
Bug introduced by
It seems like $parser->list can also be of type null; however, parameter $list of PhpMyAdmin\SqlParser\Utils\Query::replaceClause() does only seem to accept PhpMyAdmin\SqlParser\TokensList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

578
                /** @scrutinizer ignore-type */ $parser->list,
Loading history...
579
                'SELECT SQL_CALC_FOUND_ROWS',
580
                null,
581
                true,
582
            ),
583
        );
584
    }
585
586
    public function testReplaceNonExistingPart(): void
587
    {
588
        $parser = new Parser('ALTER TABLE `sale_mast` OPTIMIZE PARTITION p3');
589
        $this->assertNotNull($parser->list);
590
        $this->assertEquals(
591
            '  ALTER TABLE `sale_mast` OPTIMIZE PARTITION p3',
592
            Query::replaceClause(
593
                $parser->statements[0],
594
                $parser->list,
0 ignored issues
show
Bug introduced by
It seems like $parser->list can also be of type null; however, parameter $list of PhpMyAdmin\SqlParser\Utils\Query::replaceClause() does only seem to accept PhpMyAdmin\SqlParser\TokensList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

594
                /** @scrutinizer ignore-type */ $parser->list,
Loading history...
595
                'ORDER BY',
596
                '',
597
            ),
598
        );
599
    }
600
601
    public function testReplaceClauses(): void
602
    {
603
        $parser = new Parser('SELECT *, (SELECT 1) FROM film LIMIT 0, 10;');
604
        $this->assertNotNull($parser->list);
605
        $this->assertSame('', Query::replaceClauses($parser->statements[0], $parser->list, []));
0 ignored issues
show
Bug introduced by
It seems like $parser->list can also be of type null; however, parameter $list of PhpMyAdmin\SqlParser\Utils\Query::replaceClauses() does only seem to accept PhpMyAdmin\SqlParser\TokensList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

605
        $this->assertSame('', Query::replaceClauses($parser->statements[0], /** @scrutinizer ignore-type */ $parser->list, []));
Loading history...
606
        $this->assertEquals(
607
            'SELECT *, (SELECT 1) FROM film WHERE film_id > 0 LIMIT 0, 10',
608
            Query::replaceClauses(
609
                $parser->statements[0],
610
                $parser->list,
611
                [
612
                    [
613
                        'WHERE',
614
                        'WHERE film_id > 0',
615
                    ],
616
                ],
617
            ),
618
        );
619
620
        $parser = new Parser(
621
            'SELECT c.city_id, c.country_id ' .
622
            'INTO OUTFILE "/dev/null" ' .
623
            'FROM `city` ' .
624
            'WHERE city_id < 1 ' .
625
            'ORDER BY city_id ASC ' .
626
            'LIMIT 0, 1 ',
627
        );
628
        $this->assertNotNull($parser->list);
629
        $this->assertEquals(
630
            'SELECT c.city_id, c.country_id ' .
631
            'INTO OUTFILE "/dev/null" ' .
632
            'FROM city AS c   ' .
633
            'ORDER BY city_id ASC ' .
634
            'LIMIT 0, 10 ',
635
            Query::replaceClauses(
636
                $parser->statements[0],
637
                $parser->list,
638
                [
639
                    [
640
                        'FROM',
641
                        'FROM city AS c',
642
                    ],
643
                    [
644
                        'WHERE',
645
                        '',
646
                    ],
647
                    [
648
                        'LIMIT',
649
                        'LIMIT 0, 10',
650
                    ],
651
                ],
652
            ),
653
        );
654
    }
655
656
    public function testGetFirstStatement(): void
657
    {
658
        $query = 'USE saki';
659
        $delimiter = null;
660
        [$statement, $query, $delimiter] = Query::getFirstStatement($query, $delimiter);
661
        $this->assertNull($statement);
662
        $this->assertEquals('USE saki', $query);
663
        $this->assertNull($delimiter);
664
665
        $query = 'USE sakila; ' .
666
            '/*test comment*/' .
667
            'SELECT * FROM actor; ' .
668
            'DELIMITER $$ ' .
669
            'UPDATE actor SET last_name = "abc"$$' .
670
            '/*!SELECT * FROM actor WHERE last_name = "abc"*/$$';
671
        $delimiter = null;
672
673
        [$statement, $query, $delimiter] = Query::getFirstStatement($query, $delimiter);
674
        $this->assertEquals('USE sakila;', $statement);
675
676
        [$statement, $query, $delimiter] = Query::getFirstStatement($query, $delimiter);
677
        $this->assertEquals('SELECT * FROM actor;', $statement);
678
679
        [$statement, $query, $delimiter] = Query::getFirstStatement($query, $delimiter);
680
        $this->assertEquals('DELIMITER $$', $statement);
681
        $this->assertEquals('$$', $delimiter);
682
683
        [$statement, $query, $delimiter] = Query::getFirstStatement($query, $delimiter);
684
        $this->assertEquals('UPDATE actor SET last_name = "abc"$$', $statement);
685
686
        [$statement, $query, $delimiter] = Query::getFirstStatement($query, $delimiter);
687
        $this->assertEquals('SELECT * FROM actor WHERE last_name = "abc"$$', $statement);
688
        $this->assertSame('', $query);
689
        $this->assertSame('$$', $delimiter);
690
    }
691
}
692