Skip to content

Commit

Permalink
Fix #301 The "$" might be a character used in a name
Browse files Browse the repository at this point in the history
Signed-off-by: Hugues Peccatte <hugues.peccatte@aareon.fr>
  • Loading branch information
Hugues Peccatte committed May 2, 2020
1 parent 029d91b commit 93d49f1
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 12 deletions.
4 changes: 3 additions & 1 deletion src/Context.php
Expand Up @@ -464,7 +464,9 @@ public static function isSeparator($str)
{
// NOTES: Only non alphanumeric ASCII characters may be separators.
// `~` is the last printable ASCII character.
return ($str <= '~') && ($str !== '_')
return ($str <= '~')
&& ($str !== '_')
&& ($str !== '$')
&& (($str < '0') || ($str > '9'))
&& (($str < 'a') || ($str > 'z'))
&& (($str < 'A') || ($str > 'Z'));
Expand Down
8 changes: 8 additions & 0 deletions src/Lexer.php
Expand Up @@ -980,7 +980,15 @@ public function parseUnknown()

while (++$this->last < $this->len && ! Context::isSeparator($this->str[$this->last])) {
$token .= $this->str[$this->last];

// Test if end of token equals the current delimiter. If so, remove it from the token.
if (substr($token, -$this->delimiterLen) === $this->delimiter) {
$token = substr($token, 0, -$this->delimiterLen);
$this->last -= $this->delimiterLen - 1;
break;
}
}

--$this->last;

return new Token($token);
Expand Down
10 changes: 10 additions & 0 deletions tests/Components/ParameterDefinitionTest.php
Expand Up @@ -17,4 +17,14 @@ public function testParse()
$this->assertEquals('a', $component[0]->name);
$this->assertEquals('b', $component[1]->name);
}

public function testParseComplex()
{
$parser = new Parser();
$component = ParameterDefinition::parse(
$parser,
$this->getTokensList('CREATE DEFINER=`root`@`%` PROCEDURE `foo`( $bar int )')
);
$this->assertEquals('$bar', $component[0]->name);
}
}
4 changes: 2 additions & 2 deletions tests/Utils/ErrorTest.php
Expand Up @@ -11,14 +11,14 @@ class ErrorTest extends TestCase
{
public function testGet()
{
$lexer = new Lexer('SELECT * FROM db..tbl $');
$lexer = new Lexer('SELECT * FROM db..tbl }');
$parser = new Parser($lexer->list);
$this->assertEquals(
array(
array(
'Unexpected character.',
0,
'$',
'}',
22,
),
array(
Expand Down
2 changes: 1 addition & 1 deletion tests/data/parser/parseCreateFunctionErr3.in
@@ -1,3 +1,3 @@
DELIMITER$$
DELIMITER $$
CREATE FUNCTION coincide
END;$$
13 changes: 5 additions & 8 deletions tests/data/parser/parseCreateFunctionErr3.out
@@ -1,10 +1,7 @@
a:4:{s:5:"query";s:44:"DELIMITER$$
a:3:{s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:45:"DELIMITER $$
CREATE FUNCTION coincide
END;$$
";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:44:"DELIMITER$$
CREATE FUNCTION coincide
END;$$
";s:3:"len";i:44;s:4:"last";i:44;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:15:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:9:"DELIMITER";s:5:"value";s:9:"DELIMITER";s:7:"keyword";N;s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:0;}i:1;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"$";s:5:"value";s:1:"$";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:10;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:11;}i:3;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"CREATE";s:5:"value";s:6:"CREATE";s:7:"keyword";s:6:"CREATE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:12;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:18;}i:5;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"FUNCTION";s:5:"value";s:8:"FUNCTION";s:7:"keyword";s:8:"FUNCTION";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:19;}i:6;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:27;}i:7;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"coincide";s:5:"value";s:8:"coincide";s:7:"keyword";N;s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:28;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:36;}i:9;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:3:"END";s:5:"value";s:3:"END";s:7:"keyword";s:3:"END";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:37;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:7:"keyword";N;s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:40;}i:11;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"$";s:5:"value";s:1:"$";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:41;}i:12;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"$";s:5:"value";s:1:"$";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:42;}i:13;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:43;}i:14;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";N;s:5:"value";N;s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:15;s:3:"idx";i:17;}s:9:"delimiter";s:1:"$";s:12:"delimiterLen";i:1;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"parser";O:27:"PhpMyAdmin\SqlParser\Parser":5:{s:4:"list";r:7;s:10:"statements";a:1:{i:0;O:47:"PhpMyAdmin\SqlParser\Statements\CreateStatement":17:{s:4:"name";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";s:8:"coincide";s:6:"column";N;s:4:"expr";s:8:"coincide";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:13:"entityOptions";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:0:{}}s:6:"fields";N;s:6:"select";N;s:4:"like";N;s:11:"partitionBy";N;s:13:"partitionsNum";N;s:14:"subpartitionBy";N;s:16:"subpartitionsNum";N;s:10:"partitions";N;s:5:"table";N;s:6:"return";N;s:10:"parameters";a:0:{}s:4:"body";a:0:{}s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:1:{i:6;s:8:"FUNCTION";}}s:5:"first";i:3;s:4:"last";i:16;}}s:8:"brackets";i:0;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"errors";a:2:{s:5:"lexer";a:0:{}s:6:"parser";a:1:{i:0;a:3:{i:0;s:33:"A "RETURNS" keyword was expected.";i:1;r:72;i:2;i:0;}}}}
";s:3:"len";i:45;s:4:"last";i:45;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:15:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:9:"DELIMITER";s:5:"value";s:9:"DELIMITER";s:7:"keyword";N;s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:0;}i:1;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:9;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:2:"$$";s:5:"value";s:2:"$$";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:10;}i:3;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:12;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"CREATE";s:5:"value";s:6:"CREATE";s:7:"keyword";s:6:"CREATE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:13;}i:5;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:19;}i:6;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"FUNCTION";s:5:"value";s:8:"FUNCTION";s:7:"keyword";s:8:"FUNCTION";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:20;}i:7;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:28;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"coincide";s:5:"value";s:8:"coincide";s:7:"keyword";N;s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:29;}i:9;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:37;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:3:"END";s:5:"value";s:3:"END";s:7:"keyword";s:3:"END";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:38;}i:11;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:7:"keyword";N;s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:41;}i:12;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:2:"$$";s:5:"value";s:2:"$$";s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:42;}i:13;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:44;}i:14;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";N;s:5:"value";N;s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:15;s:3:"idx";i:17;}s:9:"delimiter";s:2:"$$";s:12:"delimiterLen";i:2;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"parser";O:27:"PhpMyAdmin\SqlParser\Parser":5:{s:4:"list";r:6;s:10:"statements";a:1:{i:0;O:47:"PhpMyAdmin\SqlParser\Statements\CreateStatement":17:{s:4:"name";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";s:8:"coincide";s:6:"column";N;s:4:"expr";s:8:"coincide";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:13:"entityOptions";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:0:{}}s:6:"fields";N;s:6:"select";N;s:4:"like";N;s:11:"partitionBy";N;s:13:"partitionsNum";N;s:14:"subpartitionBy";N;s:16:"subpartitionsNum";N;s:10:"partitions";N;s:5:"table";N;s:6:"return";N;s:10:"parameters";a:0:{}s:4:"body";a:0:{}s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:1:{i:6;s:8:"FUNCTION";}}s:5:"first";i:4;s:4:"last";i:16;}}s:8:"brackets";i:0;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"errors";a:2:{s:6:"parser";a:1:{i:0;a:3:{i:0;s:33:"A "RETURNS" keyword was expected.";i:1;r:78;i:2;i:0;}}s:5:"lexer";a:0:{}}}

0 comments on commit 93d49f1

Please sign in to comment.