Unverified Commit cfd9c0ac authored by Luís Cobucci's avatar Luís Cobucci

Merge branch 'fix/sqlite-schema-regex' into 2.6

Backporting: https://github.com/doctrine/dbal/pull/2865
parents 8302030c a3b5386c
......@@ -264,7 +264,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
$comment = $this->parseColumnCommentFromSQL($columnName, $createSql);
if (false !== $comment) {
if ($comment !== null) {
$type = $this->extractDoctrineTypeFromComment($comment, null);
if (null !== $type) {
......@@ -435,43 +435,29 @@ class SqliteSchemaManager extends AbstractSchemaManager
return $tableDiff;
}
/**
* @param string $column
* @param string $sql
*
* @return string|false
*/
private function parseColumnCollationFromSQL($column, $sql)
private function parseColumnCollationFromSQL(string $column, string $sql) : ?string
{
if (preg_match(
'{(?:'.preg_quote($column).'|'.preg_quote($this->_platform->quoteSingleIdentifier($column)).')
[^,(]+(?:\([^()]+\)[^,]*)?
(?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)*
COLLATE\s+["\']?([^\s,"\')]+)}isx', $sql, $match)) {
return $match[1];
$pattern = '{(?:\W' . preg_quote($column) . '\W|\W' . preg_quote($this->_platform->quoteSingleIdentifier($column))
. '\W)[^,(]+(?:\([^()]+\)[^,]*)?(?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)*COLLATE\s+["\']?([^\s,"\')]+)}isx';
if (preg_match($pattern, $sql, $match) !== 1) {
return null;
}
return false;
return $match[1];
}
/**
* @param string $column
* @param string $sql
*
* @return string|false
*/
private function parseColumnCommentFromSQL($column, $sql)
private function parseColumnCommentFromSQL(string $column, string $sql) : ?string
{
if (preg_match(
'{[\s(,](?:'.preg_quote($this->_platform->quoteSingleIdentifier($column)).'|'.preg_quote($column).')
(?:\(.*?\)|[^,(])*?,?((?:\s*--[^\n]*\n?)+)
}isx', $sql, $match
)) {
$comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n"));
return '' === $comment ? false : $comment;
$pattern = '{[\s(,](?:\W' . preg_quote($this->_platform->quoteSingleIdentifier($column)) . '\W|\W' . preg_quote($column)
. '\W)(?:\(.*?\)|[^,(])*?,?((?:(?!\n))(?:\s*--[^\n]*\n?)+)}ix';
if (preg_match($pattern, $sql, $match) !== 1) {
return null;
}
return false;
$comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n"));
return '' === $comment ? null : $comment;
}
}
......@@ -2,45 +2,101 @@
namespace Doctrine\Tests\DBAL\Schema;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\SqliteSchemaManager;
class SqliteSchemaManagerTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getDataColumnCollation
*
* @group 2865
*/
public function testParseColumnCollation($collation, $column, $sql)
public function testParseColumnCollation(?string $collation, string $column, string $sql) : void
{
$conn = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock();
$conn->expects($this->any())->method('getDatabasePlatform')->will($this->returnValue(new SqlitePlatform()));
$conn = $this->createMock(Connection::class);
$conn->method('getDatabasePlatform')->willReturn(new SqlitePlatform());
$manager = new SqliteSchemaManager($conn);
$ref = new \ReflectionMethod($manager, 'parseColumnCollationFromSQL');
$ref = new \ReflectionMethod($manager, 'parseColumnCollationFromSQL');
$ref->setAccessible(true);
$this->assertEquals($collation, $ref->invoke($manager, $column, $sql));
self::assertSame($collation, $ref->invoke($manager, $column, $sql));
}
public function getDataColumnCollation()
{
return array(
array(
'RTRIM', 'a', 'CREATE TABLE "a" ("a" text DEFAULT "aa" COLLATE "RTRIM" NOT NULL)'
),
array(
'utf-8', 'a', 'CREATE TABLE "a" ("b" text UNIQUE NOT NULL COLLATE NOCASE, "a" text DEFAULT "aa" COLLATE "utf-8" NOT NULL)'
),
array(
'NOCASE', 'a', 'CREATE TABLE "a" ("a" text DEFAULT (lower(ltrim(" a") || rtrim("a "))) CHECK ("a") NOT NULL COLLATE NOCASE UNIQUE, "b" text COLLATE RTRIM)'
),
array(
false, 'a', 'CREATE TABLE "a" ("a" text CHECK ("a") NOT NULL, "b" text COLLATE RTRIM)'
),
array(
'RTRIM', 'a"b', 'CREATE TABLE "a" ("a""b" text COLLATE RTRIM)'
),
);
return [
['RTRIM', 'a', 'CREATE TABLE "a" ("a" text DEFAULT "aa" COLLATE "RTRIM" NOT NULL)'],
['utf-8', 'a', 'CREATE TABLE "a" ("b" text UNIQUE NOT NULL COLLATE NOCASE, "a" text DEFAULT "aa" COLLATE "utf-8" NOT NULL)'],
['NOCASE', 'a', 'CREATE TABLE "a" ("a" text DEFAULT (lower(ltrim(" a") || rtrim("a "))) CHECK ("a") NOT NULL COLLATE NOCASE UNIQUE, "b" text COLLATE RTRIM)'],
[null, 'a', 'CREATE TABLE "a" ("a" text CHECK ("a") NOT NULL, "b" text COLLATE RTRIM)'],
['RTRIM', 'a"b', 'CREATE TABLE "a" ("a""b" text COLLATE RTRIM)'],
['BINARY', 'b', 'CREATE TABLE "a" (bb TEXT COLLATE RTRIM, b VARCHAR(42) NOT NULL COLLATE BINARY)'],
['BINARY', 'b', 'CREATE TABLE "a" (bbb TEXT COLLATE NOCASE, bb TEXT COLLATE RTRIM, b VARCHAR(42) NOT NULL COLLATE BINARY)'],
['BINARY', 'b', 'CREATE TABLE "a" (b VARCHAR(42) NOT NULL COLLATE BINARY, bb TEXT COLLATE RTRIM)'],
];
}
/**
* @dataProvider getDataColumnComment
*
* @group 2865
*/
public function testParseColumnCommentFromSQL(?string $comment, string $column, string $sql) : void
{
$conn = $this->createMock(Connection::class);
$conn->method('getDatabasePlatform')->willReturn(new SqlitePlatform());
$manager = new SqliteSchemaManager($conn);
$ref = new \ReflectionMethod($manager, 'parseColumnCommentFromSQL');
$ref->setAccessible(true);
self::assertSame($comment, $ref->invoke($manager, $column, $sql));
}
public function getDataColumnComment()
{
return [
'Single column with no comment' => [
null, 'a', 'CREATE TABLE "a" ("a" TEXT DEFAULT "a" COLLATE RTRIM)',
],
'Single column with type comment' => [
'(DC2Type:x)', 'a', 'CREATE TABLE "a" ("a" CLOB DEFAULT NULL COLLATE BINARY --(DC2Type:x)
)',
],
'Multiple similar columns with type comment 1' => [
null, 'b', 'CREATE TABLE "a" (a TEXT COLLATE RTRIM, "b" TEXT DEFAULT "a" COLLATE RTRIM, "bb" CLOB DEFAULT NULL COLLATE BINARY --(DC2Type:x)
)',
],
'Multiple similar columns with type comment 2' => [
'(DC2Type:x)', 'b', 'CREATE TABLE "a" (a TEXT COLLATE RTRIM, "bb" TEXT DEFAULT "a" COLLATE RTRIM, "b" CLOB DEFAULT NULL COLLATE BINARY --(DC2Type:x)
)',
],
'Multiple similar columns on different lines, with type comment 1' => [
null, 'bb', 'CREATE TABLE "a" (a TEXT COLLATE RTRIM, "b" CLOB DEFAULT NULL COLLATE BINARY --(DC2Type:x)
, "bb" TEXT DEFAULT "a" COLLATE RTRIM',
],
'Multiple similar columns on different lines, with type comment 2' => [
'(DC2Type:x)', 'bb', 'CREATE TABLE "a" (a TEXT COLLATE RTRIM, "bb" CLOB DEFAULT NULL COLLATE BINARY --(DC2Type:x)
, "b" TEXT DEFAULT "a" COLLATE RTRIM',
],
'Column with numeric but no comment 1' => [
null, 'a', 'CREATE TABLE "a" ("a" NUMERIC(10, 0) NOT NULL, "b" CLOB NOT NULL --(DC2Type:array)
, "c" CHAR(36) NOT NULL --(DC2Type:guid)
)',
],
'Column with numeric but no comment 2' => [
null, 'a', 'CREATE TABLE "b" ("a" NUMERIC(10, 0) NOT NULL, "b" CLOB NOT NULL --(DC2Type:array)
, "c" CHAR(36) NOT NULL --(DC2Type:guid)
)',
],
'Column with numeric but no comment 3' => [
'(DC2Type:guid)', 'c', 'CREATE TABLE "b" ("a" NUMERIC(10, 0) NOT NULL, "b" CLOB NOT NULL --(DC2Type:array)
, "c" CHAR(36) NOT NULL --(DC2Type:guid)
)',
],
];
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment