Skip to content

Commit 4c45eac

Browse files
committed
Fix #609 - Attempt to read property "keyword" on null
1 parent 3e9ce57 commit 4c45eac

File tree

4 files changed

+97
-15
lines changed

4 files changed

+97
-15
lines changed

phpstan-baseline.neon

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,11 +1950,6 @@ parameters:
19501950
count: 1
19511951
path: src/Utils/Query.php
19521952

1953-
-
1954-
message: "#^Cannot access property \\$keyword on PhpMyAdmin\\\\SqlParser\\\\Token\\|null\\.$#"
1955-
count: 1
1956-
path: src/Utils/Query.php
1957-
19581953
-
19591954
message: "#^Cannot call method has\\(\\) on PhpMyAdmin\\\\SqlParser\\\\Components\\\\OptionsArray\\|null\\.$#"
19601955
count: 4
@@ -2755,9 +2750,19 @@ parameters:
27552750
count: 1
27562751
path: tests/Utils/MiscTest.php
27572752

2753+
-
2754+
message: "#^Cannot access property \\$list on mixed\\.$#"
2755+
count: 4
2756+
path: tests/Utils/QueryTest.php
2757+
27582758
-
27592759
message: "#^Dynamic call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertEquals\\(\\)\\.$#"
2760-
count: 30
2760+
count: 37
2761+
path: tests/Utils/QueryTest.php
2762+
2763+
-
2764+
message: "#^Dynamic call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\)\\.$#"
2765+
count: 2
27612766
path: tests/Utils/QueryTest.php
27622767

27632768
-
@@ -2770,14 +2775,24 @@ parameters:
27702775
count: 1
27712776
path: tests/Utils/QueryTest.php
27722777

2778+
-
2779+
message: "#^Offset 'statement' does not exist on array\\{distinct\\?\\: bool, drop_database\\?\\: bool, group\\?\\: bool, having\\?\\: bool, is_affected\\?\\: bool, is_analyse\\?\\: bool, is_count\\?\\: bool, is_delete\\?\\: bool, \\.\\.\\.\\}\\.$#"
2780+
count: 2
2781+
path: tests/Utils/QueryTest.php
2782+
27732783
-
27742784
message: "#^Parameter \\#2 \\$list of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Query\\:\\:getClause\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\TokensList, PhpMyAdmin\\\\SqlParser\\\\TokensList\\|null given\\.$#"
27752785
count: 9
27762786
path: tests/Utils/QueryTest.php
27772787

27782788
-
27792789
message: "#^Parameter \\#2 \\$list of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Query\\:\\:replaceClause\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\TokensList, PhpMyAdmin\\\\SqlParser\\\\TokensList\\|null given\\.$#"
2780-
count: 5
2790+
count: 8
2791+
path: tests/Utils/QueryTest.php
2792+
2793+
-
2794+
message: "#^Parameter \\#2 \\$list of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Query\\:\\:replaceClause\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\TokensList, mixed given\\.$#"
2795+
count: 4
27812796
path: tests/Utils/QueryTest.php
27822797

27832798
-

psalm-baseline.xml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,12 +1371,14 @@
13711371
<code>$expr</code>
13721372
<code>$expr-&gt;function</code>
13731373
</MixedArgument>
1374-
<MixedArrayOffset occurrences="3">
1374+
<MixedArrayOffset occurrences="4">
1375+
<code>$clauses[$clauseType-&gt;keyword]</code>
13751376
<code>$clauses[$token-&gt;keyword]</code>
13761377
<code>$clauses[$token-&gt;keyword]</code>
13771378
<code>$tableAliases[$expr-&gt;table]</code>
13781379
</MixedArrayOffset>
1379-
<MixedArrayTypeCoercion occurrences="2">
1380+
<MixedArrayTypeCoercion occurrences="3">
1381+
<code>$clauses[$clauseType-&gt;keyword]</code>
13801382
<code>$clauses[$token-&gt;keyword]</code>
13811383
<code>$clauses[$token-&gt;keyword]</code>
13821384
</MixedArrayTypeCoercion>
@@ -1408,15 +1410,17 @@
14081410
<code>$i</code>
14091411
<code>$i</code>
14101412
</PossiblyNullOperand>
1411-
<PossiblyNullPropertyFetch occurrences="2">
1412-
<code>$lexer-&gt;list-&gt;getNextOfType(Token::TYPE_KEYWORD)-&gt;keyword</code>
1413+
<PossiblyNullPropertyFetch occurrences="1">
14131414
<code>$statement-&gt;into-&gt;dest</code>
14141415
</PossiblyNullPropertyFetch>
14151416
<PossiblyNullReference occurrences="3">
14161417
<code>has</code>
14171418
<code>has</code>
14181419
<code>has</code>
14191420
</PossiblyNullReference>
1421+
<UnnecessaryVarAnnotation occurrences="1">
1422+
<code>Token|null</code>
1423+
</UnnecessaryVarAnnotation>
14201424
</file>
14211425
<file src="src/Utils/Routine.php">
14221426
<MixedArgumentTypeCoercion occurrences="3">
@@ -1661,7 +1665,7 @@
16611665
</PossiblyNullArgument>
16621666
</file>
16631667
<file src="tests/Utils/QueryTest.php">
1664-
<PossiblyNullArgument occurrences="17">
1668+
<PossiblyNullArgument occurrences="24">
16651669
<code>$parser-&gt;list</code>
16661670
<code>$parser-&gt;list</code>
16671671
<code>$parser-&gt;list</code>
@@ -1679,7 +1683,20 @@
16791683
<code>$parser-&gt;list</code>
16801684
<code>$parser-&gt;list</code>
16811685
<code>$parser-&gt;list</code>
1686+
<code>$parser-&gt;list</code>
1687+
<code>$parser-&gt;list</code>
1688+
<code>$parser-&gt;list</code>
1689+
<code>$statements['parser']-&gt;list</code>
1690+
<code>$statements['parser']-&gt;list</code>
1691+
<code>$statements['parser']-&gt;list</code>
1692+
<code>$statements['parser']-&gt;list</code>
16821693
</PossiblyNullArgument>
1694+
<PossiblyUndefinedArrayOffset occurrences="4">
1695+
<code>$statements['parser']</code>
1696+
<code>$statements['parser']</code>
1697+
<code>$statements['statement']</code>
1698+
<code>$statements['statement']</code>
1699+
</PossiblyUndefinedArrayOffset>
16831700
<UnusedVariable occurrences="3">
16841701
<code>$delimiter</code>
16851702
<code>$delimiter</code>

src/Utils/Query.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,14 +656,14 @@ public static function getClause($statement, $list, $clause, $type = 0, $skipFir
656656
/**
657657
* The type of this clause.
658658
*
659-
* @var string
659+
* @var Token|null
660660
*/
661-
$clauseType = $lexer->list->getNextOfType(Token::TYPE_KEYWORD)->keyword;
661+
$clauseType = $lexer->list->getNextOfType(Token::TYPE_KEYWORD);
662662

663663
/**
664664
* The index of this clause.
665665
*/
666-
$clauseIdx = $clauses[$clauseType] ?? -1;
666+
$clauseIdx = $clauseType !== null ? $clauses[$clauseType->keyword] ?? -1 : -1;
667667

668668
$firstClauseIdx = $clauseIdx;
669669
$lastClauseIdx = $clauseIdx;

tests/Utils/QueryTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpMyAdmin\SqlParser\Tests\Utils;
66

77
use PhpMyAdmin\SqlParser\Parser;
8+
use PhpMyAdmin\SqlParser\Statement;
89
use PhpMyAdmin\SqlParser\Tests\TestCase;
910
use PhpMyAdmin\SqlParser\Utils\Query;
1011

@@ -416,6 +417,38 @@ public function testGetAll(): void
416417
);
417418
}
418419

420+
public function testGetAllTableWithDotsAndReplaceClause(): void
421+
{
422+
$query = 'SELECT * FROM `test.2024-11-01` ORDER BY `test.2024-11-01`.`id` ASC;';
423+
424+
$statements = Query::getAll($query);
425+
426+
$this->assertInstanceOf(Statement::class, $statements['statement']);
427+
428+
$fromClause = Query::replaceClause($statements['statement'], $statements['parser']->list, 'ORDER BY', '');
429+
$this->assertEquals('SELECT * FROM `test.2024-11-01` ', $fromClause);
430+
431+
$fromClause = Query::replaceClause($statements['statement'], $statements['parser']->list, 'ORDER BY');
432+
$this->assertEquals('SELECT * FROM `test.2024-11-01` ORDER BY ', $fromClause);
433+
434+
// With spaces
435+
$fromClause = Query::replaceClause($statements['statement'], $statements['parser']->list, 'ORDER BY ');
436+
$this->assertEquals('SELECT * FROM `test.2024-11-01` ORDER BY ', $fromClause);
437+
}
438+
439+
public function testGetAllTableWithDotsAndReplaceClauseEmptyName(): void
440+
{
441+
$query = 'SELECT * FROM `test.2024-11-01` ORDER BY `test.2024-11-01`.`id` ASC;';
442+
443+
$statements = Query::getAll($query);
444+
445+
$this->assertInstanceOf(Statement::class, $statements['statement']);
446+
447+
// No clause name
448+
$result = Query::replaceClause($statements['statement'], $statements['parser']->list, '');
449+
$this->assertEquals(' SELECT * FROM `test.2024-11-01` ORDER BY `test.2024-11-01`.`id` ASC', $result);
450+
}
451+
419452
/**
420453
* @param string[] $expected
421454
*
@@ -659,6 +692,23 @@ public function testReplaceNonExistingPart(): void
659692
);
660693
}
661694

695+
public function testReplaceClauseTableWithDots(): void
696+
{
697+
$query = 'SELECT * FROM `test.2024-11-01` ORDER BY `test.2024-11-01`.`id` ASC;';
698+
699+
$parser = new Parser($query);
700+
701+
$fromClause = Query::replaceClause($parser->statements[0], $parser->list, 'ORDER BY', '');
702+
$this->assertEquals('SELECT * FROM `test.2024-11-01` ', $fromClause);
703+
704+
$fromClause = Query::replaceClause($parser->statements[0], $parser->list, 'ORDER BY');
705+
$this->assertEquals('SELECT * FROM `test.2024-11-01` ORDER BY ', $fromClause);
706+
707+
// With spaces
708+
$fromClause = Query::replaceClause($parser->statements[0], $parser->list, 'ORDER BY ', '');
709+
$this->assertEquals('SELECT * FROM `test.2024-11-01` ', $fromClause);
710+
}
711+
662712
public function testReplaceClauses(): void
663713
{
664714
$parser = new Parser('SELECT *, (SELECT 1) FROM film LIMIT 0, 10;');

0 commit comments

Comments
 (0)