Skip to content

Commit

Permalink
Fixing parser errors when adding columns with SET type
Browse files Browse the repository at this point in the history
Signed-off-by: Fawzi E. Abdulfattah <iifawzie@gmail.com>
  • Loading branch information
iifawzi committed Aug 15, 2021
1 parent 09fefbf commit e35b25a
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 7 deletions.
25 changes: 22 additions & 3 deletions src/Components/AlterOperation.php
Expand Up @@ -279,16 +279,35 @@ public static function parse(Parser $parser, TokensList $list, array $options =
}
} elseif (! self::checkIfTokenQuotedSymbol($token)) {
if (! empty(Parser::$STATEMENT_PARSERS[$token->value])) {
// We have reached the end of ALTER operation and suddenly found
// a start to new statement, but have not find a delimiter between them
// We want to get the next non-comment and non-space token after $token
// therefore, the first getNext call will start with the current $idx which's $token,
// will return it and increase $idx by 1, which's not guaranteed to be non-comment
// and non-space, that's why we're calling getNext again.
// In order to get back to the original value of idx, we kept it in $currentID

if (! ($token->value === 'SET' && $list->tokens[$list->idx - 1]->value === 'CHARACTER')) {
$currentTokenID = $list->idx;
$list->getNext();
$nextToken = $list->getNext();

if ($token->value === 'CHARACTER SET'){
// Reverting the changes we made in the beginning
$list->idx = $currentTokenID;
} else if ($token->value === 'SET' && $nextToken->value === '('){
// To avoid adding the tokens between the SET() parentheses to the unknown tokens
$list->getNextOfTypeAndValue(Token::TYPE_OPERATOR, ')');
} else if ($token->value === 'SET' && $nextToken->value === 'DEFAULT'){
// to avoid adding the `DEFAULT` token to the unknown tokens.
++$list->idx;
} else {
// We have reached the end of ALTER operation and suddenly found
// a start to new statement, but have not find a delimiter between them
$parser->error(
'A new statement was found, but no delimiter between it and the previous one.',
$token
);
break;
}

} elseif ((array_key_exists($array_key, self::$DB_OPTIONS)
|| array_key_exists($array_key, self::$TABLE_OPTIONS))
&& ! self::checkIfColumnDefinitionKeyword($array_key)
Expand Down
2 changes: 1 addition & 1 deletion tests/data/parser/parseAlter11.out
@@ -1 +1 @@
a:4:{s:5:"query";s:98:"ALTER TABLE `actor` ADD `last_update2` SET ('value1','value2','value3') NOT NULL AFTER last_update";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:98:"ALTER TABLE `actor` ADD `last_update2` SET ('value1','value2','value3') NOT NULL AFTER last_update";s:3:"len";i:98;s:4:"last";i:98;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:26:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"ALTER";s:5:"value";s:5:"ALTER";s:7:"keyword";s:5:"ALTER";s:4:"type";i:1;s:5:"flags";i:3;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:5;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"TABLE";s:5:"value";s:5:"TABLE";s:7:"keyword";s:5:"TABLE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:6;}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:11;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:7:"`actor`";s:5:"value";s:5:"actor";s:7:"keyword";N;s:4:"type";i:8;s:5:"flags";i:2;s:8:"position";i:12;}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:3:"ADD";s:5:"value";s:3:"ADD";s:7:"keyword";s:3:"ADD";s:4:"type";i:1;s:5:"flags";i:3;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:23;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:14:"`last_update2`";s:5:"value";s:12:"last_update2";s:7:"keyword";N;s:4:"type";i:8;s:5:"flags";i:2;s:8:"position";i:24;}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:38;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:3:"SET";s:5:"value";s:3:"SET";s:7:"keyword";s:3:"SET";s:4:"type";i:1;s:5:"flags";i:11;s:8:"position";i:39;}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:3;s:5:"flags";i:0;s:8:"position";i:42;}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:2;s:5:"flags";i:16;s:8:"position";i:43;}i:13;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"'value1'";s:5:"value";s:6:"value1";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:44;}i:14;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:52;}i:15;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"'value2'";s:5:"value";s:6:"value2";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:53;}i:16;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:61;}i:17;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"'value3'";s:5:"value";s:6:"value3";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:62;}i:18;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:70;}i:19;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:71;}i:20;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"NOT NULL";s:5:"value";s:8:"NOT NULL";s:7:"keyword";s:8:"NOT NULL";s:4:"type";i:1;s:5:"flags";i:7;s:8:"position";i:72;}i:21;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:80;}i:22;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"AFTER";s:5:"value";s:5:"AFTER";s:7:"keyword";s:5:"AFTER";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:81;}i:23;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:86;}i:24;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:11:"last_update";s:5:"value";s:11:"last_update";s:7:"keyword";N;s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:87;}i:25;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:26;s:3:"idx";i:26;}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:46:"PhpMyAdmin\SqlParser\Statements\AlterStatement":5:{s:5:"table";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";s:5:"actor";s:6:"column";N;s:4:"expr";s:7:"`actor`";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"altered";a:3:{i:0;O:46:"PhpMyAdmin\SqlParser\Components\AlterOperation":3:{s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:1:{i:1;s:3:"ADD";}}s:5:"field";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:12:"last_update2";s:4:"expr";s:14:"`last_update2`";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"unknown";a:0:{}}i:1;O:46:"PhpMyAdmin\SqlParser\Components\AlterOperation":3:{s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:0:{}}s:5:"field";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:6:"value2";s:4:"expr";s:8:"'value2'";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"unknown";a:0:{}}i:2;O:46:"PhpMyAdmin\SqlParser\Components\AlterOperation":3:{s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:0:{}}s:5:"field";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:6:"value3";s:4:"expr";s:8:"'value3'";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"unknown";a:7:{i:0;r:135;i:1;r:142;i:2;r:149;i:3;r:156;i:4;r:163;i:5;r:170;i:6;r:177;}}}s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:1:{i:3;s:5:"TABLE";}}s:5:"first";i:0;s:4:"last";i:25;}}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:3:{i:0;a:3:{i:0;s:76:"A new statement was found, but no delimiter between it and the previous one.";i:1;r:79;i:2;i:0;}i:1;a:3:{i:0;s:29:"Unrecognized alter operation.";i:1;r:121;i:2;i:0;}i:2;a:3:{i:0;s:29:"Unrecognized alter operation.";i:1;r:184;i:2;i:0;}}}}
a:4:{s:5:"query";s:98:"ALTER TABLE `actor` ADD `last_update2` SET ('value1','value2','value3') NOT NULL AFTER last_update";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:98:"ALTER TABLE `actor` ADD `last_update2` SET ('value1','value2','value3') NOT NULL AFTER last_update";s:3:"len";i:98;s:4:"last";i:98;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:26:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"ALTER";s:5:"value";s:5:"ALTER";s:7:"keyword";s:5:"ALTER";s:4:"type";i:1;s:5:"flags";i:3;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:5;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"TABLE";s:5:"value";s:5:"TABLE";s:7:"keyword";s:5:"TABLE";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:6;}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:11;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:7:"`actor`";s:5:"value";s:5:"actor";s:7:"keyword";N;s:4:"type";i:8;s:5:"flags";i:2;s:8:"position";i:12;}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:3:"ADD";s:5:"value";s:3:"ADD";s:7:"keyword";s:3:"ADD";s:4:"type";i:1;s:5:"flags";i:3;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:23;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:14:"`last_update2`";s:5:"value";s:12:"last_update2";s:7:"keyword";N;s:4:"type";i:8;s:5:"flags";i:2;s:8:"position";i:24;}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:38;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:3:"SET";s:5:"value";s:3:"SET";s:7:"keyword";s:3:"SET";s:4:"type";i:1;s:5:"flags";i:11;s:8:"position";i:39;}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:3;s:5:"flags";i:0;s:8:"position";i:42;}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:2;s:5:"flags";i:16;s:8:"position";i:43;}i:13;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"'value1'";s:5:"value";s:6:"value1";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:44;}i:14;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:52;}i:15;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"'value2'";s:5:"value";s:6:"value2";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:53;}i:16;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:61;}i:17;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"'value3'";s:5:"value";s:6:"value3";s:7:"keyword";N;s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:62;}i:18;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:70;}i:19;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:71;}i:20;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:8:"NOT NULL";s:5:"value";s:8:"NOT NULL";s:7:"keyword";s:8:"NOT NULL";s:4:"type";i:1;s:5:"flags";i:7;s:8:"position";i:72;}i:21;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:80;}i:22;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:5:"AFTER";s:5:"value";s:5:"AFTER";s:7:"keyword";s:5:"AFTER";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:81;}i:23;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:86;}i:24;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:11:"last_update";s:5:"value";s:11:"last_update";s:7:"keyword";N;s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:87;}i:25;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:26;s:3:"idx";i:26;}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:46:"PhpMyAdmin\SqlParser\Statements\AlterStatement":5:{s:5:"table";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";s:5:"actor";s:6:"column";N;s:4:"expr";s:7:"`actor`";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"altered";a:1:{i:0;O:46:"PhpMyAdmin\SqlParser\Components\AlterOperation":3:{s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:1:{i:1;s:3:"ADD";}}s:5:"field";O:42:"PhpMyAdmin\SqlParser\Components\Expression":7:{s:8:"database";N;s:5:"table";N;s:6:"column";s:12:"last_update2";s:4:"expr";s:14:"`last_update2`";s:5:"alias";N;s:8:"function";N;s:8:"subquery";N;}s:7:"unknown";a:6:{i:0;r:79;i:1;r:149;i:2;r:156;i:3;r:163;i:4;r:170;i:5;r:177;}}}s:7:"options";O:44:"PhpMyAdmin\SqlParser\Components\OptionsArray":1:{s:7:"options";a:1:{i:3;s:5:"TABLE";}}s:5:"first";i:0;s:4:"last";i:25;}}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:0:{}}}

0 comments on commit e35b25a

Please sign in to comment.