diff --git a/ChangeLog b/ChangeLog index 33cebede5d..710dc59478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ phpMyAdmin - ChangeLog - issue #12159 Fix PHP error if user did unpack new version over old one - issue #12165 Fix parsing of expression 0 - issue #12146 Document setup with Google Cloud SQL +- issue #12197 Fix parsing of queries with double \ 4.6.0.0 (2016-03-22) + issue #11456 Disabled storage engines diff --git a/libraries/sql-parser/src/Components/Condition.php b/libraries/sql-parser/src/Components/Condition.php index b902121c84..cb1a5f8af5 100644 --- a/libraries/sql-parser/src/Components/Condition.php +++ b/libraries/sql-parser/src/Components/Condition.php @@ -53,6 +53,8 @@ class Condition extends Component 'NOT' => 1, 'NULL' => 1, 'OR' => 1, + 'REGEXP' => 1, + 'RLIKE' => 1, 'XOR' => 1, ); diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php index 0a6cd73dc5..62b776d171 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -153,7 +153,7 @@ class ContextMySql50000 extends Context 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, - 'DATA DIRECTORY' => 7, + 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php index 0242254286..7cb8541c44 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -166,7 +166,7 @@ class ContextMySql50100 extends Context 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, - 'DATA DIRECTORY' => 7, + 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php index dd8c165a12..04d723d03e 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -170,7 +170,7 @@ class ContextMySql50500 extends Context 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, - 'DATA DIRECTORY' => 7, + 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php index 189363f5e9..0e4fef27dc 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -176,7 +176,7 @@ class ContextMySql50600 extends Context 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, - 'DATA DIRECTORY' => 7, + 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php index 8ed4f11bd1..bdcb45e320 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -182,7 +182,7 @@ class ContextMySql50700 extends Context 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7, 'SET PASSWORD' => 7, 'SQL SECURITY' => 7, 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, - 'DATA DIRECTORY' => 7, + 'DATA DIRECTORY' => 7, 'UNION DISTINCT' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, 'LEFT OUTER JOIN' => 7, 'SUBPARTITION BY' => 7, 'GENERATED ALWAYS' => 7, 'RIGHT OUTER JOIN' => 7, diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 3c72a8598e..74274f0c9c 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -120,6 +120,10 @@ class Parser 'class' => 'SqlParser\\Components\\UnionKeyword', 'field' => 'union', ), + 'UNION DISTINCT' => array( + 'class' => 'SqlParser\\Components\\UnionKeyword', + 'field' => 'union', + ), // Actual clause parsers. 'ALTER' => array( @@ -427,7 +431,7 @@ class Parser continue; } - if (($token->value === 'UNION') || ($token->value === 'UNION ALL')) { + if (($token->value === 'UNION') || ($token->value === 'UNION ALL') || ($token->value === 'UNION DISTINCT')) { $unionType = $token->value; continue; } diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index eb9f3cbe03..2b81a844df 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -250,7 +250,7 @@ abstract class Statement // Unions are parsed by the parser because they represent more than // one statement. - if (($token->value === 'UNION') || ($token->value === 'UNION ALL')) { + if (($token->value === 'UNION') || ($token->value === 'UNION ALL') || ($token->value === 'UNION DISTINCT')) { break; } diff --git a/libraries/sql-parser/src/Utils/BufferedQuery.php b/libraries/sql-parser/src/Utils/BufferedQuery.php index 500862a19b..8aad59f543 100644 --- a/libraries/sql-parser/src/Utils/BufferedQuery.php +++ b/libraries/sql-parser/src/Utils/BufferedQuery.php @@ -199,7 +199,7 @@ class BufferedQuery * treated differently, because of the preceding backslash, it will * be ignored. */ - if (($this->status & static::STATUS_COMMENT == 0) && ($this->query[$i] === '\\')) { + if ((($this->status & static::STATUS_COMMENT) == 0) && ($this->query[$i] === '\\')) { $this->current .= $this->query[$i] . $this->query[++$i]; continue; } @@ -209,14 +209,14 @@ class BufferedQuery */ if ($this->status === static::STATUS_STRING_SINGLE_QUOTES) { // Single-quoted strings like 'foo'. - if ($this->query[$i] === '\'' && $this->query[$i - 1] !== '\\') { + if ($this->query[$i] === '\'') { $this->status = 0; } $this->current .= $this->query[$i]; continue; } elseif ($this->status === static::STATUS_STRING_DOUBLE_QUOTES) { // Double-quoted strings like "bar". - if ($this->query[$i] === '"' && $this->query[$i - 1] !== '\\') { + if ($this->query[$i] === '"') { $this->status = 0; } $this->current .= $this->query[$i]; diff --git a/libraries/sql-parser/src/Utils/Formatter.php b/libraries/sql-parser/src/Utils/Formatter.php index 56d4bcb437..fd41f9e1ab 100644 --- a/libraries/sql-parser/src/Utils/Formatter.php +++ b/libraries/sql-parser/src/Utils/Formatter.php @@ -207,6 +207,13 @@ class Formatter */ $lineEnded = false; + /** + * Whether current group is short (no linebreaks) + * + * @var bool $shortGroup + */ + $shortGroup = false; + /** * The name of the last clause. * @@ -339,6 +346,7 @@ class Formatter // pieces only if the clause is not inlined or this fragment // is between brackets that are on new line. if (((empty(self::$INLINE_CLAUSES[$lastClause])) + && ! $shortGroup && ($this->options['parts_newline'])) || (end($blocksLineEndings) === true) ) { @@ -351,14 +359,17 @@ class Formatter // them is longer than 30 characters. if (($prev->type === Token::TYPE_OPERATOR) && ($prev->value === '(')) { array_push($blocksIndentation, $indent); + $shortGroup = true; if (static::getGroupLength($list) > 30) { ++$indent; $lineEnded = true; + $shortGroup = false; } array_push($blocksLineEndings, $lineEnded); } elseif (($curr->type === Token::TYPE_OPERATOR) && ($curr->value === ')')) { $indent = array_pop($blocksIndentation); $lineEnded |= array_pop($blocksLineEndings); + $shortGroup = false; } // Delimiter must be placed on the same line with the last