diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index fcfc802d..1e0fa42a 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -2472,7 +2472,7 @@ parameters:
-
message: "#^Dynamic call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertEquals\\(\\)\\.$#"
- count: 30
+ count: 34
path: tests/Lexer/IsMethodsTest.php
-
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 10ebc58e..85d6aed5 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -811,7 +811,7 @@
$token
$token
-
+
$this->delimiter
$this->str[$this->last++]
$this->str[$this->last]
@@ -836,6 +836,7 @@
$this->str[++$this->last]
$this->str[++$this->last]
$this->str[++$this->last]
+ $this->str[++$this->last]
null
diff --git a/src/Context.php b/src/Context.php
index d332450c..d82808af 100644
--- a/src/Context.php
+++ b/src/Context.php
@@ -443,10 +443,19 @@ public static function isComment($str, $end = false)
return Token::FLAG_COMMENT_BASH;
}
- // If comment is opening C style (/*), warning, it could be a MySQL command (/*!)
+ // If comment is opening C style (/*), warning, it could be
+ // - a MySQL command (/*!)
+ // - a MariaDB command (/*M!)
if (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
- return ($len > 2) && ($str[2] === '!') ?
- Token::FLAG_COMMENT_MYSQL_CMD : Token::FLAG_COMMENT_C;
+ if ($len > 2 && $str[2] === '!') {
+ return Token::FLAG_COMMENT_MYSQL_CMD;
+ }
+
+ if ($len > 3 && $str[2] === 'M' && $str[3] === '!') {
+ return Token::FLAG_COMMENT_MARIADB_CMD;
+ }
+
+ return Token::FLAG_COMMENT_C;
}
// If comment is closing C style (*/), warning, it could conflicts with wildcard and a real opening C style.
diff --git a/src/Lexer.php b/src/Lexer.php
index 0e34bc38..2160b935 100644
--- a/src/Lexer.php
+++ b/src/Lexer.php
@@ -693,10 +693,21 @@ public function parseComment()
return new Token($token, Token::TYPE_COMMENT, $flags);
}
- // Checking if this is a MySQL-specific command.
- if ($this->last + 1 < $this->len && $this->str[$this->last + 1] === '!') {
- $flags |= Token::FLAG_COMMENT_MYSQL_CMD;
+ // Checking if this is a MySQL (/*!) or MariaDB (/*M!) specific command.
+ if (
+ $this->last + 1 < $this->len &&
+ ($this->str[$this->last + 1] === '!' ||
+ ($this->str[$this->last + 1] === 'M' &&
+ $this->last + 2 < $this->len &&
+ $this->str[$this->last + 2] === '!'))
+ ) {
$token .= $this->str[++$this->last];
+ if ($this->str[$this->last] === '!') {
+ $flags |= Token::FLAG_COMMENT_MYSQL_CMD;
+ } else {
+ $flags |= Token::FLAG_COMMENT_MARIADB_CMD;
+ $token .= $this->str[++$this->last];
+ }
while (
++$this->last < $this->len
diff --git a/src/Token.php b/src/Token.php
index e4a2f45d..81e5a2e0 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -152,6 +152,7 @@ class Token
public const FLAG_COMMENT_C = 2;
public const FLAG_COMMENT_SQL = 4;
public const FLAG_COMMENT_MYSQL_CMD = 8;
+ public const FLAG_COMMENT_MARIADB_CMD = 16;
// Operators related flags.
public const FLAG_OPERATOR_ARITHMETIC = 1;
diff --git a/tests/Lexer/IsMethodsTest.php b/tests/Lexer/IsMethodsTest.php
index afc8948a..226f39b8 100644
--- a/tests/Lexer/IsMethodsTest.php
+++ b/tests/Lexer/IsMethodsTest.php
@@ -61,6 +61,10 @@ public function testIsComment(): void
{
$this->assertEquals(Token::FLAG_COMMENT_BASH, Context::isComment('#'));
$this->assertEquals(Token::FLAG_COMMENT_C, Context::isComment('/*'));
+ $this->assertEquals(Token::FLAG_COMMENT_MYSQL_CMD, Context::isComment('/*!'));
+ $this->assertEquals(Token::FLAG_COMMENT_MYSQL_CMD, Context::isComment('/*!50000'));
+ $this->assertEquals(Token::FLAG_COMMENT_MARIADB_CMD, Context::isComment('/*M!'));
+ $this->assertEquals(Token::FLAG_COMMENT_MARIADB_CMD, Context::isComment('/*M!100300'));
$this->assertEquals(Token::FLAG_COMMENT_C, Context::isComment('*/'));
$this->assertEquals(Token::FLAG_COMMENT_SQL, Context::isComment('-- '));
$this->assertEquals(Token::FLAG_COMMENT_SQL, Context::isComment("--\t"));
diff --git a/tests/Parser/CreateStatementTest.php b/tests/Parser/CreateStatementTest.php
index c6f1e5a3..d9d28c7f 100644
--- a/tests/Parser/CreateStatementTest.php
+++ b/tests/Parser/CreateStatementTest.php
@@ -60,6 +60,7 @@ public static function createProvider(): array
['parser/parseCreateTableErr5'],
['parser/parseCreateTableSelect'],
['parser/parseCreateTableAsSelect'],
+ ['parser/parseCreateTableColumnCompressed'],
['parser/parseCreateTableLike'],
['parser/parseCreateTableSpatial'],
['parser/parseCreateTableSRID'],
diff --git a/tests/data/lexer/lexComment.in b/tests/data/lexer/lexComment.in
index 86ed94f9..7f4d8d61 100644
--- a/tests/data/lexer/lexComment.in
+++ b/tests/data/lexer/lexComment.in
@@ -1,4 +1,5 @@
# comment
-SELECT /*!50000 STRAIGHT_JOIN */ col1 FROM table1, table2 /* select query */
+SELECT /*!50000 STRAIGHT_JOIN */ col1 FROM table1, table2; /* select query */
-- comment
--- comment 2
\ No newline at end of file
+-- comment 2
+SELECT /*M!100300 1, */ 2;
\ No newline at end of file
diff --git a/tests/data/lexer/lexComment.out b/tests/data/lexer/lexComment.out
index 8af1028b..d4a2dcf5 100644
--- a/tests/data/lexer/lexComment.out
+++ b/tests/data/lexer/lexComment.out
@@ -1,10 +1,10 @@
{
- "query": "# comment\nSELECT /*!50000 STRAIGHT_JOIN */ col1 FROM table1, table2 /* select query */\n-- comment\n-- comment 2",
+ "query": "# comment\nSELECT /*!50000 STRAIGHT_JOIN */ col1 FROM table1, table2; /* select query */\n-- comment\n-- comment 2\nSELECT /*M!100300 1, */ 2;",
"lexer": {
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
- "str": "# comment\nSELECT /*!50000 STRAIGHT_JOIN */ col1 FROM table1, table2 /* select query */\n-- comment\n-- comment 2",
- "len": 110,
- "last": 111,
+ "str": "# comment\nSELECT /*!50000 STRAIGHT_JOIN */ col1 FROM table1, table2; /* select query */\n-- comment\n-- comment 2\nSELECT /*M!100300 1, */ 2;",
+ "len": 138,
+ "last": 138,
"list": {
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
"tokens": [
@@ -170,6 +170,15 @@
"flags": 0,
"position": 61
},
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": ";",
+ "value": ";",
+ "keyword": null,
+ "type": 9,
+ "flags": 0,
+ "position": 67
+ },
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": " ",
@@ -177,7 +186,7 @@
"keyword": null,
"type": 3,
"flags": 0,
- "position": 67
+ "position": 68
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
@@ -186,7 +195,7 @@
"keyword": null,
"type": 4,
"flags": 2,
- "position": 68
+ "position": 69
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
@@ -195,7 +204,7 @@
"keyword": null,
"type": 3,
"flags": 0,
- "position": 86
+ "position": 87
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
@@ -204,7 +213,7 @@
"keyword": null,
"type": 4,
"flags": 4,
- "position": 87
+ "position": 88
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
@@ -213,7 +222,7 @@
"keyword": null,
"type": 3,
"flags": 0,
- "position": 97
+ "position": 98
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
@@ -222,7 +231,115 @@
"keyword": null,
"type": 4,
"flags": 4,
- "position": 98
+ "position": 99
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "\n",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 111
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "SELECT",
+ "value": "SELECT",
+ "keyword": "SELECT",
+ "type": 1,
+ "flags": 3,
+ "position": 112
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 118
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "/*M!100300",
+ "value": "/*M!100300",
+ "keyword": null,
+ "type": 4,
+ "flags": 18,
+ "position": 119
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 129
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "1",
+ "value": 1,
+ "keyword": null,
+ "type": 6,
+ "flags": 0,
+ "position": 130
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": ",",
+ "value": ",",
+ "keyword": null,
+ "type": 2,
+ "flags": 16,
+ "position": 131
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 132
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "*/",
+ "value": "*/",
+ "keyword": null,
+ "type": 4,
+ "flags": 2,
+ "position": 133
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 135
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "2",
+ "value": 2,
+ "keyword": null,
+ "type": 6,
+ "flags": 0,
+ "position": 136
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": ";",
+ "value": ";",
+ "keyword": null,
+ "type": 9,
+ "flags": 0,
+ "position": 137
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
@@ -234,7 +351,7 @@
"position": null
}
],
- "count": 25,
+ "count": 38,
"idx": 0
},
"delimiter": ";",
diff --git a/tests/data/parser/parseCreateTableColumnCompressed.in b/tests/data/parser/parseCreateTableColumnCompressed.in
new file mode 100644
index 00000000..f6fb1ab5
--- /dev/null
+++ b/tests/data/parser/parseCreateTableColumnCompressed.in
@@ -0,0 +1 @@
+CREATE TABLE `t` (`c1` longtext /*M!100301 COMPRESSED*/);
\ No newline at end of file
diff --git a/tests/data/parser/parseCreateTableColumnCompressed.out b/tests/data/parser/parseCreateTableColumnCompressed.out
new file mode 100644
index 00000000..9dc7d1dd
--- /dev/null
+++ b/tests/data/parser/parseCreateTableColumnCompressed.out
@@ -0,0 +1,258 @@
+{
+ "query": "CREATE TABLE `t` (`c1` longtext /*M!100301 COMPRESSED*/);",
+ "lexer": {
+ "@type": "PhpMyAdmin\\SqlParser\\Lexer",
+ "str": "CREATE TABLE `t` (`c1` longtext /*M!100301 COMPRESSED*/);",
+ "len": 57,
+ "last": 57,
+ "list": {
+ "@type": "PhpMyAdmin\\SqlParser\\TokensList",
+ "tokens": [
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "CREATE",
+ "value": "CREATE",
+ "keyword": "CREATE",
+ "type": 1,
+ "flags": 3,
+ "position": 0
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 6
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "TABLE",
+ "value": "TABLE",
+ "keyword": "TABLE",
+ "type": 1,
+ "flags": 3,
+ "position": 7
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 12
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "`t`",
+ "value": "t",
+ "keyword": null,
+ "type": 8,
+ "flags": 2,
+ "position": 13
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 16
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "(",
+ "value": "(",
+ "keyword": null,
+ "type": 2,
+ "flags": 16,
+ "position": 17
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "`c1`",
+ "value": "c1",
+ "keyword": null,
+ "type": 8,
+ "flags": 2,
+ "position": 18
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 22
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "longtext",
+ "value": "LONGTEXT",
+ "keyword": "LONGTEXT",
+ "type": 1,
+ "flags": 11,
+ "position": 23
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 31
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "/*M!100301",
+ "value": "/*M!100301",
+ "keyword": null,
+ "type": 4,
+ "flags": 18,
+ "position": 32
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 42
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "COMPRESSED",
+ "value": "COMPRESSED",
+ "keyword": "COMPRESSED",
+ "type": 1,
+ "flags": 1,
+ "position": 43
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "*/",
+ "value": "*/",
+ "keyword": null,
+ "type": 4,
+ "flags": 2,
+ "position": 53
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": ")",
+ "value": ")",
+ "keyword": null,
+ "type": 2,
+ "flags": 16,
+ "position": 55
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": ";",
+ "value": ";",
+ "keyword": null,
+ "type": 9,
+ "flags": 0,
+ "position": 56
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": null,
+ "value": null,
+ "keyword": null,
+ "type": 9,
+ "flags": 0,
+ "position": null
+ }
+ ],
+ "count": 18,
+ "idx": 18
+ },
+ "delimiter": ";",
+ "delimiterLen": 1,
+ "strict": false,
+ "errors": []
+ },
+ "parser": {
+ "@type": "PhpMyAdmin\\SqlParser\\Parser",
+ "list": {
+ "@type": "@1"
+ },
+ "statements": [
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Statements\\CreateStatement",
+ "name": {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
+ "database": null,
+ "table": "t",
+ "column": null,
+ "expr": "`t`",
+ "alias": null,
+ "function": null,
+ "subquery": null
+ },
+ "entityOptions": {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
+ "options": []
+ },
+ "fields": [
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\CreateDefinition",
+ "name": "c1",
+ "isConstraint": null,
+ "type": {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\DataType",
+ "name": "LONGTEXT",
+ "parameters": [],
+ "options": {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
+ "options": []
+ }
+ },
+ "key": null,
+ "references": null,
+ "options": {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
+ "options": {
+ "16": "COMPRESSED"
+ }
+ }
+ }
+ ],
+ "with": null,
+ "select": null,
+ "like": null,
+ "partitionBy": null,
+ "partitionsNum": null,
+ "subpartitionBy": null,
+ "subpartitionsNum": null,
+ "partitions": null,
+ "table": null,
+ "return": null,
+ "parameters": null,
+ "body": [],
+ "options": {
+ "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
+ "options": {
+ "6": "TABLE"
+ }
+ },
+ "first": 0,
+ "last": 16
+ }
+ ],
+ "brackets": 0,
+ "strict": false,
+ "errors": []
+ },
+ "errors": {
+ "lexer": [],
+ "parser": []
+ }
+}
\ No newline at end of file