Restored relevant changes from #2850, PowerKiKi/default-values-with-backslashes

parent 9b75cd5f
# Upgrade to 2.10 # Upgrade to 2.10
## MINOR BC BREAK: escaped default values
Default values will be automatically escaped. So default values must now be specified non-escaped.
Before:
$column->setDefault('Foo\\\\Bar\\\\Baz');
After:
$column->setDefault('Foo\\Bar\\Baz');
## Deprecated `Type::*` constants ## Deprecated `Type::*` constants
The constants for built-in types have been moved from `Doctrine\DBAL\Types\Type` to a separate class `Doctrine\DBAL\Types\Types`. The constants for built-in types have been moved from `Doctrine\DBAL\Types\Type` to a separate class `Doctrine\DBAL\Types\Types`.
......
...@@ -2311,7 +2311,7 @@ abstract class AbstractPlatform ...@@ -2311,7 +2311,7 @@ abstract class AbstractPlatform
return " DEFAULT '" . $this->convertBooleans($default) . "'"; return " DEFAULT '" . $this->convertBooleans($default) . "'";
} }
return " DEFAULT '" . $default . "'"; return ' DEFAULT ' . $this->quoteStringLiteral($default);
} }
/** /**
......
...@@ -395,11 +395,12 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager ...@@ -395,11 +395,12 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
$length = null; $length = null;
break; break;
case 'text': case 'text':
case '_varchar':
case 'varchar':
$tableColumn['default'] = $this->parseDefaultExpression($tableColumn['default']);
$fixed = false; $fixed = false;
break; break;
case 'varchar':
case 'interval': case 'interval':
case '_varchar':
$fixed = false; $fixed = false;
break; break;
case 'char': case 'char':
...@@ -479,4 +480,16 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager ...@@ -479,4 +480,16 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
return $defaultValue; return $defaultValue;
} }
/**
* Parses a default value expression as given by PostgreSQL
*/
private function parseDefaultExpression(?string $default) : ?string
{
if ($default === null) {
return $default;
}
return str_replace("''", "'", $default);
}
} }
...@@ -325,8 +325,9 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -325,8 +325,9 @@ class SqliteSchemaManager extends AbstractSchemaManager
$default = null; $default = null;
} }
if ($default !== null) { if ($default !== null) {
// SQLite returns strings wrapped in single quotes, so we need to strip them // SQLite returns strings wrapped in single quotes and escaped, so we need to strip them
$default = preg_replace("/^'(.*)'$/", '\1', $default); $default = preg_replace("/^'(.*)'$/s", '\1', $default);
$default = str_replace("''", "'", $default);
} }
$notnull = (bool) $tableColumn['notnull']; $notnull = (bool) $tableColumn['notnull'];
......
...@@ -1495,6 +1495,67 @@ abstract class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase ...@@ -1495,6 +1495,67 @@ abstract class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
self::assertEquals($sequence2InitialValue, $actualSequence2->getInitialValue()); self::assertEquals($sequence2InitialValue, $actualSequence2->getInitialValue());
} }
/**
* Returns potential escaped literals from all platforms combined.
*
* @see https://dev.mysql.com/doc/refman/5.7/en/string-literals.html
* @see http://www.sqlite.org/lang_expr.html
* @see https://www.postgresql.org/docs/9.6/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE
*
* @return mixed[][]
*/
private function getEscapedLiterals() : iterable
{
return [
['An ASCII NUL (X\'00\')', "foo\\0bar"],
['Single quote, C-style', "foo\\'bar"],
['Single quote, doubled-style', "foo''bar"],
['Double quote, C-style', 'foo\\"bar'],
['Double quote, double-style', 'foo""bar'],
['Backspace', 'foo\\bbar'],
['New-line', 'foo\\nbar'],
['Carriage return', 'foo\\rbar'],
['Tab', 'foo\\tbar'],
['ASCII 26 (Control+Z)', 'foo\\Zbar'],
['Backslash (\)', 'foo\\\\bar'],
['Percent (%)', 'foo\\%bar'],
['Underscore (_)', 'foo\\_bar'],
];
}
private function createTableForDefaultValues() : void
{
$table = new Table('string_escaped_default_value');
foreach ($this->getEscapedLiterals() as $i => $literal) {
$table->addColumn('field' . $i, 'string', ['default' => $literal[1]]);
}
$table->addColumn('def_foo', 'string');
$this->schemaManager->dropAndCreateTable($table);
}
public function testEscapedDefaultValueCanBeIntrospected() : void
{
$this->createTableForDefaultValues();
$onlineTable = $this->schemaManager->listTableDetails('string_escaped_default_value');
foreach ($this->getEscapedLiterals() as $i => $literal) {
self::assertSame($literal[1], $onlineTable->getColumn('field' . $i)->getDefault(), 'should be able introspect the value of default for: ' . $literal[0]);
}
}
public function testEscapedDefaultValueCanBeInserted() : void
{
$this->createTableForDefaultValues();
$this->connection->insert('string_escaped_default_value', ['def_foo' => 'foo']);
foreach ($this->getEscapedLiterals() as $i => $literal) {
$value = $this->connection->fetchColumn('SELECT field' . $i . ' FROM string_escaped_default_value');
self::assertSame($literal[1], $value, 'inserted default value should be the configured default value for: ' . $literal[0]);
}
}
/** /**
* @group #3086 * @group #3086
*/ */
......
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