diff --git a/src/Parser.php b/src/Parser.php index d098e15..f3e06a0 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -23,7 +23,7 @@ public function parseDatabase($sqlScript) { $database = new Database(); - $tables = $this->parseTables($sqlScript); + $tables = $this->parseTables($this->convertStringsToBase64($sqlScript)); foreach ($tables as $table) { $this->parseTableDefinition($table); @@ -48,12 +48,12 @@ public function parseTables($sqlScript) for ($i = 0; $i < $loopCounter; $i++) { $name = $matches['tableName'][$i]; $ifNotExists = $matches['ifNotExists'][$i]; - $definition = $matches['tableDefinition'][$i]; - $creationScript = $matches['creationScript'][$i]; + $definition = $this->convertStringsFromBase64($matches['tableDefinition'][$i]); + $creationScript = $this->convertStringsFromBase64($matches['creationScript'][$i]); $engine = $matches['engine'][$i]; $autoIncrement = $matches['autoIncrement'][$i]; $defaultCharset = $matches['defaultCharset'][$i]; - $comment = $matches['comment'][$i]; + $comment = base64_decode($matches['comment'][$i]); $rowFormat = $matches['rowFormat'][$i]; $keyBlockSize = $matches['keyBlockSize'][$i]; @@ -355,4 +355,38 @@ private function getColumnPrecision($decimalPrecision, $doublePrecision, $floatP return; } + + public function convertStringsToBase64($sqlScript) + { + $sqlScript = preg_replace_callback('/DEFAULT\s*\'(?[^\']+)\'/', function ($matches) { + return sprintf('DEFAULT \'%s\'', base64_encode($matches['defaultValue'])); + }, $sqlScript); + + $sqlScript = preg_replace_callback('/COMMENT\s*\'(?[^\']+)\'/', function ($matches) { + return sprintf('COMMENT \'%s\'', base64_encode($matches['comment'])); + }, $sqlScript); + + $sqlScript = preg_replace_callback('/COMMENT\s*=\s*\'(?([^\']|\'\')+)\'/', function ($matches) { + return sprintf('COMMENT=\'%s\'', base64_encode($matches['comment'])); + }, $sqlScript); + + return $sqlScript; + } + + public function convertStringsFromBase64($sqlScript) + { + $sqlScript = preg_replace_callback('/DEFAULT\s*\'(?[^\']+)\'/', function ($matches) { + return sprintf('DEFAULT \'%s\'', base64_decode($matches['defaultValue'])); + }, $sqlScript); + + $sqlScript = preg_replace_callback('/COMMENT\s*\'(?[^\']+)\'/', function ($matches) { + return sprintf('COMMENT \'%s\'', base64_decode($matches['comment'])); + }, $sqlScript); + + $sqlScript = preg_replace_callback('/COMMENT\s*=\s*\'(?([^\']|\'\')+)\'/', function ($matches) { + return sprintf('COMMENT=\'%s\'', base64_decode($matches['comment'])); + }, $sqlScript); + + return $sqlScript; + } } diff --git a/tests/ParserTest.php b/tests/ParserTest.php index bfdb9d7..d04e08e 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -359,4 +359,23 @@ public function testIsParsingFractionalSeconds() $this->assertEquals('`timestamp_column` TIMESTAMP(2) NOT NULL', $database->getTableByName('fractional_seconds')->getColumnByName('timestamp_column')->generateCreationScript()); $this->assertEquals('`time_column` TIME(3) NOT NULL', $database->getTableByName('fractional_seconds')->getColumnByName('time_column')->generateCreationScript()); } + + public function testIsParsingColumnWithBackslashInDefaultValue() + { + $creationScript = $this->getDatabaseFixture('backslash.sql'); + + $parser = new Parser(); + + $database = $parser->parseDatabase($creationScript); + + $this->assertInstanceOf(Database::class, $database); + $this->assertCount(1, $database->getTables()); + $this->assertCount(1, $database->getTableByName('backslash')->getColumns()); + $this->assertCount(0, $database->getTableByName('backslash')->getPrimaryKeys()); + $this->assertCount(0, $database->getTableByName('backslash')->getIndexes()); + $this->assertEquals('utf8', $database->getTableByName('backslash')->getDefaultCharset()); + $this->assertEquals('InnoDB', $database->getTableByName('backslash')->getEngine()); + $this->assertEquals('Table/Comment', $database->getTableByName('backslash')->getComment()); + $this->assertEquals('`time_zone` varchar(255) NOT NULL DEFAULT \'America/Los_Angeles\' COMMENT \'Column/Comment\'', $database->getTableByName('backslash')->getColumnByName('time_zone')->generateCreationScript()); + } } diff --git a/tests/fixtures/backslash.sql b/tests/fixtures/backslash.sql new file mode 100644 index 0000000..c71353c --- /dev/null +++ b/tests/fixtures/backslash.sql @@ -0,0 +1,3 @@ +CREATE TABLE IF NOT EXISTS `backslash` ( + `time_zone` varchar(255) NOT NULL DEFAULT 'America/Los_Angeles' COMMENT 'Column/Comment' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT = 'Table/Comment'; diff --git a/tests/fixtures/comment_change1.sql b/tests/fixtures/comment_change1.sql index 7196a46..176225f 100644 --- a/tests/fixtures/comment_change1.sql +++ b/tests/fixtures/comment_change1.sql @@ -1,3 +1,3 @@ CREATE TABLE `comments` ( - `field1` varchar(50) NOT NULL COMMENT 'Old Comment', + `field1` varchar(50) NOT NULL COMMENT 'Old Comment' ) ENGINE=InnoDB; diff --git a/tests/fixtures/comment_change2.sql b/tests/fixtures/comment_change2.sql index 6eae121..81fa12d 100644 --- a/tests/fixtures/comment_change2.sql +++ b/tests/fixtures/comment_change2.sql @@ -1,3 +1,3 @@ CREATE TABLE `comments` ( - `field1` varchar(50) NOT NULL COMMENT 'New Comment', + `field1` varchar(50) NOT NULL COMMENT 'New Comment' ) ENGINE=InnoDB;