Commit e2b11774 authored by Tiago Brito's avatar Tiago Brito

Merge pull request #8 from doctrine/master

Update from master main repository
parents f2aa22cc a67db17b
...@@ -31,7 +31,7 @@ before_script: ...@@ -31,7 +31,7 @@ before_script:
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi" - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
- sh -c "if [ '$DB' = 'mysqli' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi" - sh -c "if [ '$DB' = 'mysqli' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
script: phpunit --configuration tests/travis/$DB.travis.xml script: ./vendor/bin/phpunit --configuration tests/travis/$DB.travis.xml
matrix: matrix:
allow_failures: allow_failures:
...@@ -44,7 +44,7 @@ matrix: ...@@ -44,7 +44,7 @@ matrix:
- php: hhvm - php: hhvm
env: DB=sqlite env: DB=sqlite
- php: hhvm - php: hhvm
env: DB=mysqli env: DB=mysql
- php: hhvm-nightly - php: hhvm-nightly
exclude: exclude:
- php: hhvm - php: hhvm
......
# Upgrade to 2.5 # Upgrade to 2.5
## BC BREAK: time type resets date fields to UNIX epoch
When mapping `time` type field to PHP's `DateTime` instance all unused date fields are
reset to UNIX epoch (i.e. 1970-01-01). This might break any logic which relies on comparing
`DateTime` instances with date fields set to the current date.
Use `!` format prefix (see http://php.net/manual/en/datetime.createfromformat.php) for parsing
time strings to prevent having different date fields when comparing user input and `DateTime`
instances as mapped by Doctrine.
## BC BREAK: Doctrine\DBAL\Schema\Table ## BC BREAK: Doctrine\DBAL\Schema\Table
The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table`` The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table``
......
...@@ -307,7 +307,7 @@ Prepare a given SQL statement and return the ...@@ -307,7 +307,7 @@ Prepare a given SQL statement and return the
array( array(
0 => array( 0 => array(
'username' => 'jwage', 'username' => 'jwage',
'password' => 'changeme 'password' => 'changeme'
) )
) )
*/ */
...@@ -344,7 +344,7 @@ parameters to the execute method, then returning the statement: ...@@ -344,7 +344,7 @@ parameters to the execute method, then returning the statement:
/* /*
array( array(
0 => 'jwage', 0 => 'jwage',
1 => 'changeme 1 => 'changeme'
) )
*/ */
...@@ -367,7 +367,7 @@ Execute the query and fetch all results into an array: ...@@ -367,7 +367,7 @@ Execute the query and fetch all results into an array:
array( array(
0 => array( 0 => array(
'username' => 'jwage', 'username' => 'jwage',
'password' => 'changeme 'password' => 'changeme'
) )
) )
*/ */
...@@ -385,7 +385,7 @@ Numeric index retrieval of first result row of the given query: ...@@ -385,7 +385,7 @@ Numeric index retrieval of first result row of the given query:
/* /*
array( array(
0 => 'jwage', 0 => 'jwage',
1 => 'changeme 1 => 'changeme'
) )
*/ */
...@@ -412,7 +412,7 @@ Retrieve assoc row of the first result row. ...@@ -412,7 +412,7 @@ Retrieve assoc row of the first result row.
/* /*
array( array(
'username' => 'jwage', 'username' => 'jwage',
'password' => 'changeme 'password' => 'changeme'
) )
*/ */
......
...@@ -597,7 +597,7 @@ class Connection implements DriverConnection ...@@ -597,7 +597,7 @@ class Connection implements DriverConnection
*/ */
public function close() public function close()
{ {
unset($this->_conn); $this->_conn = null;
$this->_isConnected = false; $this->_isConnected = false;
} }
......
...@@ -50,6 +50,12 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar ...@@ -50,6 +50,12 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
public function __construct(array $params, $username, $password, array $driverOptions = array()) public function __construct(array $params, $username, $password, array $driverOptions = array())
{ {
$port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port'); $port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port');
// Fallback to default MySQL port if not given.
if ( ! $port) {
$port = 3306;
}
$socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket'); $socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket');
$dbname = isset($params['dbname']) ? $params['dbname'] : null; $dbname = isset($params['dbname']) ? $params['dbname'] : null;
......
...@@ -48,6 +48,18 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection ...@@ -48,6 +48,18 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
} }
} }
/**
* {@inheritdoc}
*/
public function exec($statement)
{
try {
return parent::exec($statement);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -100,11 +112,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection ...@@ -100,11 +112,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/ */
public function quote($input, $type = \PDO::PARAM_STR) public function quote($input, $type = \PDO::PARAM_STR)
{ {
try { return parent::quote($input, $type);
return parent::quote($input, $type);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
} }
/** /**
...@@ -112,11 +120,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection ...@@ -112,11 +120,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/ */
public function lastInsertId($name = null) public function lastInsertId($name = null)
{ {
try { return parent::lastInsertId($name);
return parent::lastInsertId($name);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
} }
/** /**
......
...@@ -43,6 +43,10 @@ class Driver extends AbstractSQLServerDriver ...@@ -43,6 +43,10 @@ class Driver extends AbstractSQLServerDriver
if (isset($params['dbname'])) { if (isset($params['dbname'])) {
$driverOptions['Database'] = $params['dbname']; $driverOptions['Database'] = $params['dbname'];
} }
if (isset($params['charset'])) {
$driverOptions['CharacterSet'] = $params['charset'];
}
$driverOptions['UID'] = $username; $driverOptions['UID'] = $username;
$driverOptions['PWD'] = $password; $driverOptions['PWD'] = $password;
......
...@@ -1574,8 +1574,10 @@ abstract class AbstractPlatform ...@@ -1574,8 +1574,10 @@ abstract class AbstractPlatform
$sql = $this->_getCreateTableSQL($tableName, $columns, $options); $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
if ($this->supportsCommentOnStatement()) { if ($this->supportsCommentOnStatement()) {
foreach ($table->getColumns() as $column) { foreach ($table->getColumns() as $column) {
if ($this->getColumnComment($column)) { $comment = $this->getColumnComment($column);
$sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $this->getColumnComment($column));
if (null !== $comment && '' !== $comment) {
$sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment);
} }
} }
} }
...@@ -1592,9 +1594,12 @@ abstract class AbstractPlatform ...@@ -1592,9 +1594,12 @@ abstract class AbstractPlatform
*/ */
public function getCommentOnColumnSQL($tableName, $columnName, $comment) public function getCommentOnColumnSQL($tableName, $columnName, $comment)
{ {
$tableName = new Identifier($tableName);
$columnName = new Identifier($columnName);
$comment = $this->quoteStringLiteral($comment); $comment = $this->quoteStringLiteral($comment);
return "COMMENT ON COLUMN " . $tableName . "." . $columnName . " IS " . $comment; return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) .
" IS " . $comment;
} }
/** /**
...@@ -2014,7 +2019,7 @@ abstract class AbstractPlatform ...@@ -2014,7 +2019,7 @@ abstract class AbstractPlatform
*/ */
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{ {
$tableName = $diff->getName()->getQuotedName($this); $tableName = $diff->getName($this)->getQuotedName($this);
$sql = array(); $sql = array();
if ($this->supportsForeignKeyConstraints()) { if ($this->supportsForeignKeyConstraints()) {
...@@ -2045,7 +2050,7 @@ abstract class AbstractPlatform ...@@ -2045,7 +2050,7 @@ abstract class AbstractPlatform
{ {
$tableName = (false !== $diff->newName) $tableName = (false !== $diff->newName)
? $diff->getNewName()->getQuotedName($this) ? $diff->getNewName()->getQuotedName($this)
: $diff->getName()->getQuotedName($this); : $diff->getName($this)->getQuotedName($this);
$sql = array(); $sql = array();
...@@ -2205,7 +2210,7 @@ abstract class AbstractPlatform ...@@ -2205,7 +2210,7 @@ abstract class AbstractPlatform
$columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation; $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
} }
if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment']) { if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') {
$columnDef .= " COMMENT " . $this->quoteStringLiteral($field['comment']); $columnDef .= " COMMENT " . $this->quoteStringLiteral($field['comment']);
} }
......
...@@ -519,12 +519,16 @@ class DB2Platform extends AbstractPlatform ...@@ -519,12 +519,16 @@ class DB2Platform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
if (count($queryParts) > 0) { if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . implode(" ", $queryParts); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(" ", $queryParts);
} }
// Some table alteration operations require a table reorganization. // Some table alteration operations require a table reorganization.
if ( ! empty($diff->removedColumns) || ! empty($diff->changedColumns)) { if ( ! empty($diff->removedColumns) || ! empty($diff->changedColumns)) {
$sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName()->getQuotedName($this) . "')"; $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName($this)->getQuotedName($this) . "')";
}
if ($diff->newName !== false) {
$sql[] = 'RENAME TABLE ' . $diff->getName($this)->getQuotedName($this) . ' TO ' . $diff->getNewName()->getQuotedName($this);
} }
$sql = array_merge( $sql = array_merge(
...@@ -532,10 +536,6 @@ class DB2Platform extends AbstractPlatform ...@@ -532,10 +536,6 @@ class DB2Platform extends AbstractPlatform
$sql, $sql,
$this->getPostAlterTableIndexForeignKeySQL($diff) $this->getPostAlterTableIndexForeignKeySQL($diff)
); );
if ($diff->newName !== false) {
$sql[] = 'RENAME TABLE ' . $diff->getName()->getQuotedName($this) . ' TO ' . $diff->getNewName()->getQuotedName($this);
}
} }
return array_merge($sql, $tableSql, $columnSql); return array_merge($sql, $tableSql, $columnSql);
...@@ -547,7 +547,7 @@ class DB2Platform extends AbstractPlatform ...@@ -547,7 +547,7 @@ class DB2Platform extends AbstractPlatform
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{ {
$sql = array(); $sql = array();
$table = $diff->getName()->getQuotedName($this); $table = $diff->getName($this)->getQuotedName($this);
foreach ($diff->removedIndexes as $remKey => $remIndex) { foreach ($diff->removedIndexes as $remKey => $remIndex) {
foreach ($diff->addedIndexes as $addKey => $addIndex) { foreach ($diff->addedIndexes as $addKey => $addIndex) {
......
...@@ -549,7 +549,7 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -549,7 +549,7 @@ class DrizzlePlatform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
if (count($queryParts) > 0) { if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . implode(", ", $queryParts); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts);
} }
$sql = array_merge( $sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPreAlterTableIndexForeignKeySQL($diff),
......
...@@ -593,7 +593,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -593,7 +593,7 @@ class MySqlPlatform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
if (count($queryParts) > 0) { if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . implode(", ", $queryParts); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts);
} }
$sql = array_merge( $sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPreAlterTableIndexForeignKeySQL($diff),
...@@ -611,7 +611,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -611,7 +611,7 @@ class MySqlPlatform extends AbstractPlatform
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{ {
$sql = array(); $sql = array();
$table = $diff->getName()->getQuotedName($this); $table = $diff->getName($this)->getQuotedName($this);
foreach ($diff->removedIndexes as $remKey => $remIndex) { foreach ($diff->removedIndexes as $remKey => $remIndex) {
// Dropping primary keys requires to unset autoincrement attribute on the particular column first. // Dropping primary keys requires to unset autoincrement attribute on the particular column first.
......
...@@ -453,9 +453,16 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -453,9 +453,16 @@ class PostgreSqlPlatform extends AbstractPlatform
} }
$query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
if ($comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); $comment = $this->getColumnComment($column);
if (null !== $comment && '' !== $comment) {
$commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$comment
);
} }
} }
...@@ -465,7 +472,7 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -465,7 +472,7 @@ class PostgreSqlPlatform extends AbstractPlatform
} }
$query = 'DROP ' . $column->getQuotedName($this); $query = 'DROP ' . $column->getQuotedName($this);
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
} }
foreach ($diff->changedColumns as $columnDiff) { foreach ($diff->changedColumns as $columnDiff) {
...@@ -486,7 +493,7 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -486,7 +493,7 @@ class PostgreSqlPlatform extends AbstractPlatform
// here was a server version check before, but DBAL API does not support this anymore. // here was a server version check before, but DBAL API does not support this anymore.
$query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this); $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this);
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
} }
if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) { if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) {
...@@ -494,12 +501,12 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -494,12 +501,12 @@ class PostgreSqlPlatform extends AbstractPlatform
? ' DROP DEFAULT' ? ' DROP DEFAULT'
: ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray()); : ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray());
$query = 'ALTER ' . $oldColumnName . $defaultClause; $query = 'ALTER ' . $oldColumnName . $defaultClause;
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
} }
if ($columnDiff->hasChanged('notnull')) { if ($columnDiff->hasChanged('notnull')) {
$query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL'; $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL';
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
} }
if ($columnDiff->hasChanged('autoincrement')) { if ($columnDiff->hasChanged('autoincrement')) {
...@@ -508,27 +515,27 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -508,27 +515,27 @@ class PostgreSqlPlatform extends AbstractPlatform
$seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName); $seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName);
$sql[] = "CREATE SEQUENCE " . $seqName; $sql[] = "CREATE SEQUENCE " . $seqName;
$sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->getName()->getQuotedName($this) . "))"; $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->getName($this)->getQuotedName($this) . "))";
$query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; $query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')";
$sql[] = "ALTER TABLE " . $diff->getName()->getQuotedName($this) . " " . $query; $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query;
} else { } else {
// Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have // Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have
$query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT"; $query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT";
$sql[] = "ALTER TABLE " . $diff->getName()->getQuotedName($this) . " " . $query; $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query;
} }
} }
if ($columnDiff->hasChanged('comment')) { if ($columnDiff->hasChanged('comment')) {
$commentsSQL[] = $this->getCommentOnColumnSQL( $commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->name, $diff->getName($this)->getQuotedName($this),
$column->getName(), $column->getQuotedName($this),
$this->getColumnComment($column) $this->getColumnComment($column)
); );
} }
if ($columnDiff->hasChanged('length')) { if ($columnDiff->hasChanged('length')) {
$query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSqlDeclaration($column->toArray(), $this); $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSqlDeclaration($column->toArray(), $this);
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
} }
} }
...@@ -539,18 +546,24 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -539,18 +546,24 @@ class PostgreSqlPlatform extends AbstractPlatform
$oldColumnName = new Identifier($oldColumnName); $oldColumnName = new Identifier($oldColumnName);
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) .
' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this);
} }
$tableSql = array(); $tableSql = array();
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$sql = array_merge($sql, $commentsSQL);
if ($diff->newName !== false) { if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this);
} }
$sql = array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff), $commentsSQL); $sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
$this->getPostAlterTableIndexForeignKeySQL($diff)
);
} }
return array_merge($sql, $tableSql, $columnSql); return array_merge($sql, $tableSql, $columnSql);
...@@ -615,9 +628,12 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -615,9 +628,12 @@ class PostgreSqlPlatform extends AbstractPlatform
*/ */
public function getCommentOnColumnSQL($tableName, $columnName, $comment) public function getCommentOnColumnSQL($tableName, $columnName, $comment)
{ {
$tableName = new Identifier($tableName);
$columnName = new Identifier($columnName);
$comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment);
return "COMMENT ON COLUMN $tableName.$columnName IS $comment"; return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) .
" IS $comment";
} }
/** /**
...@@ -821,7 +837,7 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -821,7 +837,7 @@ class PostgreSqlPlatform extends AbstractPlatform
} }
); );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
...@@ -829,8 +845,8 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -829,8 +845,8 @@ class PostgreSqlPlatform extends AbstractPlatform
{ {
if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) { if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) {
return false; return false;
} }
return parent::convertFromBoolean($item); return parent::convertFromBoolean($item);
} }
......
...@@ -143,8 +143,12 @@ class SQLAnywherePlatform extends AbstractPlatform ...@@ -143,8 +143,12 @@ class SQLAnywherePlatform extends AbstractPlatform
$comment = $this->getColumnComment($column); $comment = $this->getColumnComment($column);
if ($comment) { if (null !== $comment && '' !== $comment) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getQuotedName($this), $comment); $commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$comment
);
} }
} }
...@@ -173,7 +177,7 @@ class SQLAnywherePlatform extends AbstractPlatform ...@@ -173,7 +177,7 @@ class SQLAnywherePlatform extends AbstractPlatform
$column = $columnDiff->column; $column = $columnDiff->column;
$commentsSQL[] = $this->getCommentOnColumnSQL( $commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->name, $diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this), $column->getQuotedName($this),
$this->getColumnComment($column) $this->getColumnComment($column)
); );
...@@ -185,21 +189,27 @@ class SQLAnywherePlatform extends AbstractPlatform ...@@ -185,21 +189,27 @@ class SQLAnywherePlatform extends AbstractPlatform
continue; continue;
} }
$sql[] = $this->getAlterTableClause($diff->getName()) . ' ' . $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' .
$this->getAlterTableRenameColumnClause($oldColumnName, $column); $this->getAlterTableRenameColumnClause($oldColumnName, $column);
} }
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
if ( ! empty($alterClauses)) { if ( ! empty($alterClauses)) {
$sql[] = $this->getAlterTableClause($diff->getName()) . ' ' . implode(", ", $alterClauses); $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . implode(", ", $alterClauses);
} }
$sql = array_merge($sql, $commentsSQL);
if ($diff->newName !== false) { if ($diff->newName !== false) {
$sql[] = $this->getAlterTableClause($diff->getName()) . ' ' . $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' .
$this->getAlterTableRenameTableClause($diff->getNewName()); $this->getAlterTableRenameTableClause($diff->getNewName());
} }
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL); $sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
$this->getPostAlterTableIndexForeignKeySQL($diff)
);
} }
return array_merge($sql, $tableSql, $columnSql); return array_merge($sql, $tableSql, $columnSql);
...@@ -357,9 +367,12 @@ class SQLAnywherePlatform extends AbstractPlatform ...@@ -357,9 +367,12 @@ class SQLAnywherePlatform extends AbstractPlatform
*/ */
public function getCommentOnColumnSQL($tableName, $columnName, $comment) public function getCommentOnColumnSQL($tableName, $columnName, $comment)
{ {
$tableName = new Identifier($tableName);
$columnName = new Identifier($columnName);
$comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment);
return "COMMENT ON COLUMN $tableName.$columnName IS $comment"; return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . '.' . $columnName->getQuotedName($this) .
" IS $comment";
} }
/** /**
......
...@@ -501,12 +501,16 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -501,12 +501,16 @@ class SQLServerPlatform extends AbstractPlatform
$oldColumnName = new Identifier($oldColumnName); $oldColumnName = new Identifier($oldColumnName);
$sql[] = "sp_RENAME '" . $diff->name . "." . $oldColumnName->getQuotedName($this) . $sql[] = "sp_RENAME '" .
$diff->getName($this)->getQuotedName($this) . "." . $oldColumnName->getQuotedName($this) .
"', '" . $column->getQuotedName($this) . "', 'COLUMN'"; "', '" . $column->getQuotedName($this) . "', 'COLUMN'";
// Recreate default constraint with new column name if necessary (for future reference). // Recreate default constraint with new column name if necessary (for future reference).
if ($column->getDefault() !== null) { if ($column->getDefault() !== null) {
$queryParts[] = $this->getAlterTableDropDefaultConstraintClause($diff->name, $oldColumnName); $queryParts[] = $this->getAlterTableDropDefaultConstraintClause(
$diff->name,
$oldColumnName->getQuotedName($this)
);
$queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column);
} }
} }
...@@ -518,13 +522,13 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -518,13 +522,13 @@ class SQLServerPlatform extends AbstractPlatform
} }
foreach ($queryParts as $query) { foreach ($queryParts as $query) {
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
} }
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSql); $sql = array_merge($sql, $commentsSql);
if ($diff->newName !== false) { if ($diff->newName !== false) {
$sql[] = "sp_RENAME '" . $diff->getName()->getQuotedName($this) . "', '" . $diff->getNewName()->getQuotedName($this) . "'"; $sql[] = "sp_RENAME '" . $diff->getName($this)->getQuotedName($this) . "', '" . $diff->getNewName()->getName() . "'";
/** /**
* Rename table's default constraints names * Rename table's default constraints names
...@@ -540,10 +544,16 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -540,10 +544,16 @@ class SQLServerPlatform extends AbstractPlatform
"'" . $this->generateIdentifierName($diff->newName) . "') + ''', ''OBJECT'';' " . "'" . $this->generateIdentifierName($diff->newName) . "') + ''', ''OBJECT'';' " .
"FROM sys.default_constraints dc " . "FROM sys.default_constraints dc " .
"JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id " . "JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id " .
"WHERE tbl.name = '" . $diff->getNewName()->getQuotedName($this) . "';" . "WHERE tbl.name = '" . $diff->getNewName()->getName() . "';" .
"EXEC sp_executesql @sql"; "EXEC sp_executesql @sql";
} }
$sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
$this->getPostAlterTableIndexForeignKeySQL($diff)
);
return array_merge($sql, $tableSql, $columnSql); return array_merge($sql, $tableSql, $columnSql);
} }
...@@ -719,10 +729,10 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -719,10 +729,10 @@ class SQLServerPlatform extends AbstractPlatform
$level2Name = null $level2Name = null
) { ) {
return "EXEC sp_addextendedproperty " . return "EXEC sp_addextendedproperty " .
"N'" . $name . "', N'" . $value . "', " . "N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " .
"N'" . $level0Type . "', " . $level0Name . ', ' . "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' . "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name; "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name;
} }
/** /**
...@@ -750,10 +760,10 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -750,10 +760,10 @@ class SQLServerPlatform extends AbstractPlatform
$level2Name = null $level2Name = null
) { ) {
return "EXEC sp_dropextendedproperty " . return "EXEC sp_dropextendedproperty " .
"N'" . $name . "', " . "N" . $this->quoteStringLiteral($name) . ", " .
"N'" . $level0Type . "', " . $level0Name . ', ' . "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' . "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name; "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name;
} }
/** /**
...@@ -783,10 +793,10 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -783,10 +793,10 @@ class SQLServerPlatform extends AbstractPlatform
$level2Name = null $level2Name = null
) { ) {
return "EXEC sp_updateextendedproperty " . return "EXEC sp_updateextendedproperty " .
"N'" . $name . "', N'" . $value . "', " . "N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " .
"N'" . $level0Type . "', " . $level0Name . ', ' . "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' . "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name; "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name;
} }
/** /**
...@@ -1175,7 +1185,7 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -1175,7 +1185,7 @@ class SQLServerPlatform extends AbstractPlatform
//Remove ORDER BY from $query (including nested parentheses in order by list). //Remove ORDER BY from $query (including nested parentheses in order by list).
$query = preg_replace('/\s+ORDER\s+BY\s+([^()]+|\((?:(?:(?>[^()]+)|(?R))*)\))+/i', '', $query); $query = preg_replace('/\s+ORDER\s+BY\s+([^()]+|\((?:(?:(?>[^()]+)|(?R))*)\))+/i', '', $query);
$format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d'; $format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d ORDER BY doctrine_rownum';
// Pattern to match "main" SELECT ... FROM clause (including nested parentheses in select list). // Pattern to match "main" SELECT ... FROM clause (including nested parentheses in select list).
$selectFromPattern = '/^(\s*SELECT\s+(?:(.*)(?![^(]*\))))\sFROM\s/i'; $selectFromPattern = '/^(\s*SELECT\s+(?:(.*)(?![^(]*\))))\sFROM\s/i';
......
...@@ -645,13 +645,13 @@ class SqlitePlatform extends AbstractPlatform ...@@ -645,13 +645,13 @@ class SqlitePlatform extends AbstractPlatform
} }
$sql = array(); $sql = array();
$tableName = $diff->newName ?: $diff->name; $tableName = $diff->newName ? $diff->getNewName(): $diff->getName($this);
foreach ($this->getIndexesInAlteredTable($diff) as $index) { foreach ($this->getIndexesInAlteredTable($diff) as $index) {
if ($index->isPrimary()) { if ($index->isPrimary()) {
continue; continue;
} }
$sql[] = $this->getCreateIndexSQL($index, $tableName); $sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this));
} }
return $sql; return $sql;
...@@ -836,7 +836,7 @@ class SqlitePlatform extends AbstractPlatform ...@@ -836,7 +836,7 @@ class SqlitePlatform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$dataTable = new Table('__temp__'.$table->getName()); $dataTable = new Table('__temp__'.$table->getName());
$newTable = new Table($table->getName(), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions());
$newTable->addOption('alter', true); $newTable->addOption('alter', true);
$sql = $this->getPreAlterTableIndexForeignKeySQL($diff); $sql = $this->getPreAlterTableIndexForeignKeySQL($diff);
...@@ -849,7 +849,7 @@ class SqlitePlatform extends AbstractPlatform ...@@ -849,7 +849,7 @@ class SqlitePlatform extends AbstractPlatform
$sql[] = $this->getDropTableSQL($dataTable); $sql[] = $this->getDropTableSQL($dataTable);
if ($diff->newName && $diff->newName != $diff->name) { if ($diff->newName && $diff->newName != $diff->name) {
$renamedTable = new Identifier($diff->newName); $renamedTable = $diff->getNewName();
$sql[] = 'ALTER TABLE '.$newTable->getQuotedName($this).' RENAME TO '.$renamedTable->getQuotedName($this); $sql[] = 'ALTER TABLE '.$newTable->getQuotedName($this).' RENAME TO '.$renamedTable->getQuotedName($this);
} }
......
...@@ -275,27 +275,27 @@ class ExpressionBuilder ...@@ -275,27 +275,27 @@ class ExpressionBuilder
/** /**
* Creates a IN () comparison expression with the given arguments. * Creates a IN () comparison expression with the given arguments.
* *
* @param string $x The field in string format to be inspected by IN() comparison. * @param string $x The field in string format to be inspected by IN() comparison.
* @param array $y The array of values to be used by IN() comparison. * @param string|array $y The placeholder or the array of values to be used by IN() comparison.
* *
* @return string * @return string
*/ */
public function in($x, array $y) public function in($x, $y)
{ {
return $this->comparison($x, 'IN', '('.implode(', ', $y).')'); return $this->comparison($x, 'IN', '('.implode(', ', (array) $y).')');
} }
/** /**
* Creates a NOT IN () comparison expression with the given arguments. * Creates a NOT IN () comparison expression with the given arguments.
* *
* @param string $x The field in string format to be inspected by NOT IN() comparison. * @param string $x The field in string format to be inspected by NOT IN() comparison.
* @param array $y The array of values to be used by NOT IN() comparison. * @param string|array $y The placeholder or the array of values to be used by NOT IN() comparison.
* *
* @return string * @return string
*/ */
public function notIn($x, array $y) public function notIn($x, $y)
{ {
return $this->comparison($x, 'NOT IN', '('.implode(', ', $y).')'); return $this->comparison($x, 'NOT IN', '('.implode(', ', (array) $y).')');
} }
/** /**
......
...@@ -90,6 +90,11 @@ class SQLParserUtils ...@@ -90,6 +90,11 @@ class SQLParserUtils
$arrayPositions = array(); $arrayPositions = array();
$bindIndex = -1; $bindIndex = -1;
if ($isPositional) {
ksort($params);
ksort($types);
}
foreach ($types as $name => $type) { foreach ($types as $name => $type) {
++$bindIndex; ++$bindIndex;
...@@ -113,6 +118,8 @@ class SQLParserUtils ...@@ -113,6 +118,8 @@ class SQLParserUtils
if ($isPositional) { if ($isPositional) {
$paramOffset = 0; $paramOffset = 0;
$queryOffset = 0; $queryOffset = 0;
$params = array_values($params);
$types = array_values($types);
foreach ($paramPos as $needle => $needlePos) { foreach ($paramPos as $needle => $needlePos) {
if ( ! isset($arrayPositions[$needle])) { if ( ! isset($arrayPositions[$needle])) {
......
...@@ -421,8 +421,11 @@ class Comparator ...@@ -421,8 +421,11 @@ class Comparator
} }
} }
// only allow to delete comment if its set to '' not to null. // A null value and an empty string are actually equal for a comment so they should not trigger a change.
if ($properties1['comment'] !== null && $properties1['comment'] != $properties2['comment']) { if ($properties1['comment'] !== $properties2['comment'] &&
! (null === $properties1['comment'] && '' === $properties2['comment']) &&
! (null === $properties2['comment'] && '' === $properties1['comment'])
) {
$changedProperties[] = 'comment'; $changedProperties[] = 'comment';
} }
......
...@@ -46,7 +46,9 @@ class DrizzleSchemaManager extends AbstractSchemaManager ...@@ -46,7 +46,9 @@ class DrizzleSchemaManager extends AbstractSchemaManager
'autoincrement' => (bool)$tableColumn['IS_AUTO_INCREMENT'], 'autoincrement' => (bool)$tableColumn['IS_AUTO_INCREMENT'],
'scale' => (int)$tableColumn['NUMERIC_SCALE'], 'scale' => (int)$tableColumn['NUMERIC_SCALE'],
'precision' => (int)$tableColumn['NUMERIC_PRECISION'], 'precision' => (int)$tableColumn['NUMERIC_PRECISION'],
'comment' => (isset($tableColumn['COLUMN_COMMENT']) ? $tableColumn['COLUMN_COMMENT'] : null), 'comment' => isset($tableColumn['COLUMN_COMMENT']) && '' !== $tableColumn['COLUMN_COMMENT']
? $tableColumn['COLUMN_COMMENT']
: null,
); );
$column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options); $column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options);
......
...@@ -187,7 +187,9 @@ class MySqlSchemaManager extends AbstractSchemaManager ...@@ -187,7 +187,9 @@ class MySqlSchemaManager extends AbstractSchemaManager
'scale' => null, 'scale' => null,
'precision' => null, 'precision' => null,
'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false), 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
'comment' => isset($tableColumn['comment']) ? $tableColumn['comment'] : null, 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''
? $tableColumn['comment']
: null,
); );
if ($scale !== null && $precision !== null) { if ($scale !== null && $precision !== null) {
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
/** /**
* Oracle Schema Manager. * Oracle Schema Manager.
* *
...@@ -36,7 +38,7 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -36,7 +38,7 @@ class OracleSchemaManager extends AbstractSchemaManager
{ {
$view = \array_change_key_case($view, CASE_LOWER); $view = \array_change_key_case($view, CASE_LOWER);
return new View($view['view_name'], $view['text']); return new View($this->getQuotedIdentifierName($view['view_name']), $view['text']);
} }
/** /**
...@@ -58,7 +60,7 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -58,7 +60,7 @@ class OracleSchemaManager extends AbstractSchemaManager
{ {
$table = \array_change_key_case($table, CASE_LOWER); $table = \array_change_key_case($table, CASE_LOWER);
return $table['table_name']; return $this->getQuotedIdentifierName($table['table_name']);
} }
/** /**
...@@ -84,7 +86,7 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -84,7 +86,7 @@ class OracleSchemaManager extends AbstractSchemaManager
$buffer['non_unique'] = ($tableIndex['is_unique'] == 0) ? true : false; $buffer['non_unique'] = ($tableIndex['is_unique'] == 0) ? true : false;
} }
$buffer['key_name'] = $keyName; $buffer['key_name'] = $keyName;
$buffer['column_name'] = $tableIndex['column_name']; $buffer['column_name'] = $this->getQuotedIdentifierName($tableIndex['column_name']);
$indexBuffer[] = $buffer; $indexBuffer[] = $buffer;
} }
...@@ -203,11 +205,13 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -203,11 +205,13 @@ class OracleSchemaManager extends AbstractSchemaManager
'length' => $length, 'length' => $length,
'precision' => $precision, 'precision' => $precision,
'scale' => $scale, 'scale' => $scale,
'comment' => (isset($tableColumn['comments'])) ? $tableColumn['comments'] : null, 'comment' => isset($tableColumn['comments']) && '' !== $tableColumn['comments']
? $tableColumn['comments']
: null,
'platformDetails' => array(), 'platformDetails' => array(),
); );
return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options); return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options);
} }
/** /**
...@@ -224,22 +228,26 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -224,22 +228,26 @@ class OracleSchemaManager extends AbstractSchemaManager
} }
$list[$value['constraint_name']] = array( $list[$value['constraint_name']] = array(
'name' => $value['constraint_name'], 'name' => $this->getQuotedIdentifierName($value['constraint_name']),
'local' => array(), 'local' => array(),
'foreign' => array(), 'foreign' => array(),
'foreignTable' => $value['references_table'], 'foreignTable' => $value['references_table'],
'onDelete' => $value['delete_rule'], 'onDelete' => $value['delete_rule'],
); );
} }
$list[$value['constraint_name']]['local'][$value['position']] = $value['local_column'];
$list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column']; $localColumn = $this->getQuotedIdentifierName($value['local_column']);
$foreignColumn = $this->getQuotedIdentifierName($value['foreign_column']);
$list[$value['constraint_name']]['local'][$value['position']] = $localColumn;
$list[$value['constraint_name']]['foreign'][$value['position']] = $foreignColumn;
} }
$result = array(); $result = array();
foreach ($list as $constraint) { foreach ($list as $constraint) {
$result[] = new ForeignKeyConstraint( $result[] = new ForeignKeyConstraint(
array_values($constraint['local']), $constraint['foreignTable'], array_values($constraint['local']), $this->getQuotedIdentifierName($constraint['foreignTable']),
array_values($constraint['foreign']), $constraint['name'], array_values($constraint['foreign']), $this->getQuotedIdentifierName($constraint['name']),
array('onDelete' => $constraint['onDelete']) array('onDelete' => $constraint['onDelete'])
); );
} }
...@@ -254,7 +262,11 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -254,7 +262,11 @@ class OracleSchemaManager extends AbstractSchemaManager
{ {
$sequence = \array_change_key_case($sequence, CASE_LOWER); $sequence = \array_change_key_case($sequence, CASE_LOWER);
return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']); return new Sequence(
$this->getQuotedIdentifierName($sequence['sequence_name']),
$sequence['increment_by'],
$sequence['min_value']
);
} }
/** /**
...@@ -323,4 +335,23 @@ class OracleSchemaManager extends AbstractSchemaManager ...@@ -323,4 +335,23 @@ class OracleSchemaManager extends AbstractSchemaManager
parent::dropTable($name); parent::dropTable($name);
} }
/**
* Returns the quoted representation of the given identifier name.
*
* Quotes non-uppercase identifiers explicitly to preserve case
* and thus make references to the particular identifier work.
*
* @param string $identifier The identifier to quote.
*
* @return string The quoted identifier.
*/
private function getQuotedIdentifierName($identifier)
{
if (preg_match('/[a-z]/', $identifier)) {
return $this->_platform->quoteIdentifier($identifier);
}
return $identifier;
}
} }
...@@ -436,7 +436,9 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager ...@@ -436,7 +436,9 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
'fixed' => $fixed, 'fixed' => $fixed,
'unsigned' => false, 'unsigned' => false,
'autoincrement' => $autoincrement, 'autoincrement' => $autoincrement,
'comment' => $tableColumn['comment'], 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''
? $tableColumn['comment']
: null,
); );
$column = new Column($tableColumn['field'], Type::getType($type), $options); $column = new Column($tableColumn['field'], Type::getType($type), $options);
......
...@@ -144,7 +144,9 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager ...@@ -144,7 +144,9 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager
'notnull' => (bool) $tableColumn['notnull'], 'notnull' => (bool) $tableColumn['notnull'],
'default' => $default, 'default' => $default,
'autoincrement' => (bool) $tableColumn['autoincrement'], 'autoincrement' => (bool) $tableColumn['autoincrement'],
'comment' => $tableColumn['comment'] 'comment' => isset($tableColumn['comment']) && '' !== $tableColumn['comment']
? $tableColumn['comment']
: null,
)); ));
} }
......
...@@ -183,7 +183,7 @@ class Table extends AbstractAsset ...@@ -183,7 +183,7 @@ class Table extends AbstractAsset
*/ */
public function dropIndex($indexName) public function dropIndex($indexName)
{ {
$indexName = strtolower($indexName); $indexName = $this->normalizeIdentifier($indexName);
if ( ! $this->hasIndex($indexName)) { if ( ! $this->hasIndex($indexName)) {
throw SchemaException::indexDoesNotExist($indexName, $this->_name); throw SchemaException::indexDoesNotExist($indexName, $this->_name);
} }
...@@ -222,8 +222,8 @@ class Table extends AbstractAsset ...@@ -222,8 +222,8 @@ class Table extends AbstractAsset
*/ */
public function renameIndex($oldIndexName, $newIndexName = null) public function renameIndex($oldIndexName, $newIndexName = null)
{ {
$oldIndexName = strtolower($oldIndexName); $oldIndexName = $this->normalizeIdentifier($oldIndexName);
$normalizedNewIndexName = strtolower($newIndexName); $normalizedNewIndexName = $this->normalizeIdentifier($newIndexName);
if ($oldIndexName === $normalizedNewIndexName) { if ($oldIndexName === $normalizedNewIndexName) {
return $this; return $this;
...@@ -287,7 +287,7 @@ class Table extends AbstractAsset ...@@ -287,7 +287,7 @@ class Table extends AbstractAsset
*/ */
private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = array(), array $options = array()) private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = array(), array $options = array())
{ {
if (preg_match('(([^a-zA-Z0-9_]+))', $indexName)) { if (preg_match('(([^a-zA-Z0-9_]+))', $this->normalizeIdentifier($indexName))) {
throw SchemaException::indexNameInvalid($indexName); throw SchemaException::indexNameInvalid($indexName);
} }
...@@ -362,7 +362,7 @@ class Table extends AbstractAsset ...@@ -362,7 +362,7 @@ class Table extends AbstractAsset
*/ */
public function dropColumn($columnName) public function dropColumn($columnName)
{ {
$columnName = strtolower($columnName); $columnName = $this->normalizeIdentifier($columnName);
unset($this->_columns[$columnName]); unset($this->_columns[$columnName]);
return $this; return $this;
...@@ -469,7 +469,7 @@ class Table extends AbstractAsset ...@@ -469,7 +469,7 @@ class Table extends AbstractAsset
protected function _addColumn(Column $column) protected function _addColumn(Column $column)
{ {
$columnName = $column->getName(); $columnName = $column->getName();
$columnName = strtolower($columnName); $columnName = $this->normalizeIdentifier($columnName);
if (isset($this->_columns[$columnName])) { if (isset($this->_columns[$columnName])) {
throw SchemaException::columnAlreadyExists($this->getName(), $columnName); throw SchemaException::columnAlreadyExists($this->getName(), $columnName);
...@@ -497,7 +497,7 @@ class Table extends AbstractAsset ...@@ -497,7 +497,7 @@ class Table extends AbstractAsset
} }
$indexName = $indexCandidate->getName(); $indexName = $indexCandidate->getName();
$indexName = strtolower($indexName); $indexName = $this->normalizeIdentifier($indexName);
if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) { if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) {
throw SchemaException::indexAlreadyExists($indexName, $this->_name); throw SchemaException::indexAlreadyExists($indexName, $this->_name);
...@@ -535,7 +535,7 @@ class Table extends AbstractAsset ...@@ -535,7 +535,7 @@ class Table extends AbstractAsset
array_merge((array)$this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength() array_merge((array)$this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength()
); );
} }
$name = strtolower($name); $name = $this->normalizeIdentifier($name);
$this->_fkConstraints[$name] = $constraint; $this->_fkConstraints[$name] = $constraint;
// add an explicit index on the foreign key columns. If there is already an index that fulfils this requirements drop the request. // add an explicit index on the foreign key columns. If there is already an index that fulfils this requirements drop the request.
...@@ -553,7 +553,7 @@ class Table extends AbstractAsset ...@@ -553,7 +553,7 @@ class Table extends AbstractAsset
*/ */
public function hasForeignKey($constraintName) public function hasForeignKey($constraintName)
{ {
$constraintName = strtolower($constraintName); $constraintName = $this->normalizeIdentifier($constraintName);
return isset($this->_fkConstraints[$constraintName]); return isset($this->_fkConstraints[$constraintName]);
} }
...@@ -569,7 +569,7 @@ class Table extends AbstractAsset ...@@ -569,7 +569,7 @@ class Table extends AbstractAsset
*/ */
public function getForeignKey($constraintName) public function getForeignKey($constraintName)
{ {
$constraintName = strtolower($constraintName); $constraintName = $this->normalizeIdentifier($constraintName);
if (!$this->hasForeignKey($constraintName)) { if (!$this->hasForeignKey($constraintName)) {
throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
} }
...@@ -588,7 +588,7 @@ class Table extends AbstractAsset ...@@ -588,7 +588,7 @@ class Table extends AbstractAsset
*/ */
public function removeForeignKey($constraintName) public function removeForeignKey($constraintName)
{ {
$constraintName = strtolower($constraintName); $constraintName = $this->normalizeIdentifier($constraintName);
if (!$this->hasForeignKey($constraintName)) { if (!$this->hasForeignKey($constraintName)) {
throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
} }
...@@ -631,7 +631,7 @@ class Table extends AbstractAsset ...@@ -631,7 +631,7 @@ class Table extends AbstractAsset
*/ */
public function hasColumn($columnName) public function hasColumn($columnName)
{ {
$columnName = $this->trimQuotes(strtolower($columnName)); $columnName = $this->normalizeIdentifier($columnName);
return isset($this->_columns[$columnName]); return isset($this->_columns[$columnName]);
} }
...@@ -647,7 +647,7 @@ class Table extends AbstractAsset ...@@ -647,7 +647,7 @@ class Table extends AbstractAsset
*/ */
public function getColumn($columnName) public function getColumn($columnName)
{ {
$columnName = strtolower($this->trimQuotes($columnName)); $columnName = $this->normalizeIdentifier($columnName);
if ( ! $this->hasColumn($columnName)) { if ( ! $this->hasColumn($columnName)) {
throw SchemaException::columnDoesNotExist($columnName, $this->_name); throw SchemaException::columnDoesNotExist($columnName, $this->_name);
} }
...@@ -704,7 +704,7 @@ class Table extends AbstractAsset ...@@ -704,7 +704,7 @@ class Table extends AbstractAsset
*/ */
public function hasIndex($indexName) public function hasIndex($indexName)
{ {
$indexName = strtolower($indexName); $indexName = $this->normalizeIdentifier($indexName);
return (isset($this->_indexes[$indexName])); return (isset($this->_indexes[$indexName]));
} }
...@@ -720,7 +720,7 @@ class Table extends AbstractAsset ...@@ -720,7 +720,7 @@ class Table extends AbstractAsset
*/ */
public function getIndex($indexName) public function getIndex($indexName)
{ {
$indexName = strtolower($indexName); $indexName = $this->normalizeIdentifier($indexName);
if ( ! $this->hasIndex($indexName)) { if ( ! $this->hasIndex($indexName)) {
throw SchemaException::indexDoesNotExist($indexName, $this->_name); throw SchemaException::indexDoesNotExist($indexName, $this->_name);
} }
...@@ -814,4 +814,18 @@ class Table extends AbstractAsset ...@@ -814,4 +814,18 @@ class Table extends AbstractAsset
$this->_fkConstraints[$k]->setLocalTable($this); $this->_fkConstraints[$k]->setLocalTable($this);
} }
} }
/**
* Normalizes a given identifier.
*
* Trims quotes and lowercases the given identifier.
*
* @param string $identifier The identifier to normalize.
*
* @return string The normalized identifier.
*/
private function normalizeIdentifier($identifier)
{
return $this->trimQuotes(strtolower($identifier));
}
} }
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/** /**
* Table Diff. * Table Diff.
* *
...@@ -147,18 +149,22 @@ class TableDiff ...@@ -147,18 +149,22 @@ class TableDiff
} }
/** /**
* @param AbstractPlatform $platform The platform to use for retrieving this table diff's name.
*
* @return \Doctrine\DBAL\Schema\Identifier * @return \Doctrine\DBAL\Schema\Identifier
*/ */
public function getName() public function getName(AbstractPlatform $platform)
{ {
return new Identifier($this->name); return new Identifier(
$this->fromTable instanceof Table ? $this->fromTable->getQuotedName($platform) : $this->name
);
} }
/** /**
* @return \Doctrine\DBAL\Schema\Identifier * @return \Doctrine\DBAL\Schema\Identifier|boolean
*/ */
public function getNewName() public function getNewName()
{ {
return new Identifier($this->newName); return $this->newName ? new Identifier($this->newName) : $this->newName;
} }
} }
...@@ -62,7 +62,7 @@ class TimeType extends Type ...@@ -62,7 +62,7 @@ class TimeType extends Type
return $value; return $value;
} }
$val = \DateTime::createFromFormat($platform->getTimeFormatString(), $value); $val = \DateTime::createFromFormat('!' . $platform->getTimeFormatString(), $value);
if ( ! $val) { if ( ! $val) {
throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString());
} }
......
...@@ -403,6 +403,15 @@ SQLSTATE[HY000]: General error: 1 near \"MUUHAAAAHAAAA\""); ...@@ -403,6 +403,15 @@ SQLSTATE[HY000]: General error: 1 near \"MUUHAAAAHAAAA\"");
$this->assertSame($result, $conn->fetchColumn($statement, $params, $column, $types)); $this->assertSame($result, $conn->fetchColumn($statement, $params, $column, $types));
} }
public function testConnectionIsClosed()
{
$this->_conn->close();
$this->setExpectedException('Doctrine\\DBAL\\Exception\\DriverException');
$this->_conn->quoteIdentifier('Bug');
}
public function testFetchAll() public function testFetchAll()
{ {
$statement = 'SELECT * FROM foo WHERE bar = ?'; $statement = 'SELECT * FROM foo WHERE bar = ?';
......
...@@ -24,7 +24,7 @@ class PDOConnectionTest extends DbalFunctionalTestCase ...@@ -24,7 +24,7 @@ class PDOConnectionTest extends DbalFunctionalTestCase
$this->driverConnection = $this->_conn->getWrappedConnection(); $this->driverConnection = $this->_conn->getWrappedConnection();
if ( ! $this->_conn->getWrappedConnection() instanceof PDOConnection) { if ( ! $this->driverConnection instanceof PDOConnection) {
$this->markTestSkipped('PDO connection only test.'); $this->markTestSkipped('PDO connection only test.');
} }
} }
...@@ -33,4 +33,54 @@ class PDOConnectionTest extends DbalFunctionalTestCase ...@@ -33,4 +33,54 @@ class PDOConnectionTest extends DbalFunctionalTestCase
{ {
$this->assertFalse($this->driverConnection->requiresQueryForServerVersion()); $this->assertFalse($this->driverConnection->requiresQueryForServerVersion());
} }
/**
* @expectedException \Doctrine\DBAL\Driver\PDOException
*/
public function testThrowsWrappedExceptionOnConstruct()
{
new PDOConnection('foo');
}
/**
* @group DBAL-1022
*
* @expectedException \Doctrine\DBAL\Driver\PDOException
*/
public function testThrowsWrappedExceptionOnExec()
{
$this->driverConnection->exec('foo');
}
/**
* @expectedException \Doctrine\DBAL\Driver\PDOException
*/
public function testThrowsWrappedExceptionOnPrepare()
{
// Emulated prepared statements have to be disabled for this test
// so that PDO actually communicates with the database server to check the query.
$this->driverConnection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$this->driverConnection->prepare('foo');
// Some PDO adapters like PostgreSQL do not check the query server-side
// even though emulated prepared statements are disabled,
// so an exception is thrown only eventually.
// Skip the test otherwise.
$this->markTestSkipped(
sprintf(
'The PDO adapter %s does not check the query to be prepared server-side, ' .
'so no assertions can be made.',
$this->_conn->getDriver()->getName()
)
);
}
/**
* @expectedException \Doctrine\DBAL\Driver\PDOException
*/
public function testThrowsWrappedExceptionOnQuery()
{
$this->driverConnection->query('foo');
}
} }
...@@ -61,6 +61,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -61,6 +61,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
/** /**
* @group DBAL-472 * @group DBAL-472
* @group DBAL-1001
*/ */
public function testAlterTableColumnNotNull() public function testAlterTableColumnNotNull()
{ {
...@@ -70,6 +71,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -70,6 +71,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$table->addColumn('id', 'integer'); $table->addColumn('id', 'integer');
$table->addColumn('foo', 'integer'); $table->addColumn('foo', 'integer');
$table->addColumn('bar', 'string');
$table->setPrimaryKey(array('id')); $table->setPrimaryKey(array('id'));
$this->_sm->dropAndCreateTable($table); $this->_sm->dropAndCreateTable($table);
...@@ -78,9 +80,11 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -78,9 +80,11 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertTrue($columns['id']->getNotnull()); $this->assertTrue($columns['id']->getNotnull());
$this->assertTrue($columns['foo']->getNotnull()); $this->assertTrue($columns['foo']->getNotnull());
$this->assertTrue($columns['bar']->getNotnull());
$diffTable = clone $table; $diffTable = clone $table;
$diffTable->changeColumn('foo', array('notnull' => false)); $diffTable->changeColumn('foo', array('notnull' => false));
$diffTable->changeColumn('bar', array('length' => 1024));
$this->_sm->alterTable($comparator->diffTable($table, $diffTable)); $this->_sm->alterTable($comparator->diffTable($table, $diffTable));
...@@ -88,6 +92,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -88,6 +92,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertTrue($columns['id']->getNotnull()); $this->assertTrue($columns['id']->getNotnull());
$this->assertFalse($columns['foo']->getNotnull()); $this->assertFalse($columns['foo']->getNotnull());
$this->assertTrue($columns['bar']->getNotnull());
} }
public function testListDatabases() public function testListDatabases()
...@@ -102,4 +107,115 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -102,4 +107,115 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertContains('c##test_create_database', $databases); $this->assertContains('c##test_create_database', $databases);
} }
/**
* @group DBAL-831
*/
public function testListTableDetailsWithDifferentIdentifierQuotingRequirements()
{
$primaryTableName = '"Primary_Table"';
$offlinePrimaryTable = new Schema\Table($primaryTableName);
$offlinePrimaryTable->addColumn(
'"Id"',
'integer',
array('autoincrement' => true, 'comment' => 'Explicit casing.')
);
$offlinePrimaryTable->addColumn('select', 'integer', array('comment' => 'Reserved keyword.'));
$offlinePrimaryTable->addColumn('foo', 'integer', array('comment' => 'Implicit uppercasing.'));
$offlinePrimaryTable->addColumn('BAR', 'integer');
$offlinePrimaryTable->addColumn('"BAZ"', 'integer');
$offlinePrimaryTable->addIndex(array('select'), 'from');
$offlinePrimaryTable->addIndex(array('foo'), 'foo_index');
$offlinePrimaryTable->addIndex(array('BAR'), 'BAR_INDEX');
$offlinePrimaryTable->addIndex(array('"BAZ"'), 'BAZ_INDEX');
$offlinePrimaryTable->setPrimaryKey(array('"Id"'));
$foreignTableName = 'foreign';
$offlineForeignTable = new Schema\Table($foreignTableName);
$offlineForeignTable->addColumn('id', 'integer', array('autoincrement' => true));
$offlineForeignTable->addColumn('"Fk"', 'integer');
$offlineForeignTable->addIndex(array('"Fk"'), '"Fk_index"');
$offlineForeignTable->addForeignKeyConstraint(
$primaryTableName,
array('"Fk"'),
array('"Id"'),
array(),
'"Primary_Table_Fk"'
);
$offlineForeignTable->setPrimaryKey(array('id'));
$this->_sm->tryMethod('dropTable', $foreignTableName);
$this->_sm->tryMethod('dropTable', $primaryTableName);
$this->_sm->createTable($offlinePrimaryTable);
$this->_sm->createTable($offlineForeignTable);
$onlinePrimaryTable = $this->_sm->listTableDetails($primaryTableName);
$onlineForeignTable = $this->_sm->listTableDetails($foreignTableName);
$platform = $this->_sm->getDatabasePlatform();
// Primary table assertions
$this->assertSame($primaryTableName, $onlinePrimaryTable->getQuotedName($platform));
$this->assertTrue($onlinePrimaryTable->hasColumn('"Id"'));
$this->assertSame('"Id"', $onlinePrimaryTable->getColumn('"Id"')->getQuotedName($platform));
$this->assertTrue($onlinePrimaryTable->hasPrimaryKey());
$this->assertSame(array('"Id"'), $onlinePrimaryTable->getPrimaryKey()->getQuotedColumns($platform));
$this->assertTrue($onlinePrimaryTable->hasColumn('select'));
$this->assertSame('"select"', $onlinePrimaryTable->getColumn('select')->getQuotedName($platform));
$this->assertTrue($onlinePrimaryTable->hasColumn('foo'));
$this->assertSame('FOO', $onlinePrimaryTable->getColumn('foo')->getQuotedName($platform));
$this->assertTrue($onlinePrimaryTable->hasColumn('BAR'));
$this->assertSame('BAR', $onlinePrimaryTable->getColumn('BAR')->getQuotedName($platform));
$this->assertTrue($onlinePrimaryTable->hasColumn('"BAZ"'));
$this->assertSame('BAZ', $onlinePrimaryTable->getColumn('"BAZ"')->getQuotedName($platform));
$this->assertTrue($onlinePrimaryTable->hasIndex('from'));
$this->assertTrue($onlinePrimaryTable->getIndex('from')->hasColumnAtPosition('"select"'));
$this->assertSame(array('"select"'), $onlinePrimaryTable->getIndex('from')->getQuotedColumns($platform));
$this->assertTrue($onlinePrimaryTable->hasIndex('foo_index'));
$this->assertTrue($onlinePrimaryTable->getIndex('foo_index')->hasColumnAtPosition('foo'));
$this->assertSame(array('FOO'), $onlinePrimaryTable->getIndex('foo_index')->getQuotedColumns($platform));
$this->assertTrue($onlinePrimaryTable->hasIndex('BAR_INDEX'));
$this->assertTrue($onlinePrimaryTable->getIndex('BAR_INDEX')->hasColumnAtPosition('BAR'));
$this->assertSame(array('BAR'), $onlinePrimaryTable->getIndex('BAR_INDEX')->getQuotedColumns($platform));
$this->assertTrue($onlinePrimaryTable->hasIndex('BAZ_INDEX'));
$this->assertTrue($onlinePrimaryTable->getIndex('BAZ_INDEX')->hasColumnAtPosition('"BAZ"'));
$this->assertSame(array('BAZ'), $onlinePrimaryTable->getIndex('BAZ_INDEX')->getQuotedColumns($platform));
// Foreign table assertions
$this->assertTrue($onlineForeignTable->hasColumn('id'));
$this->assertSame('ID', $onlineForeignTable->getColumn('id')->getQuotedName($platform));
$this->assertTrue($onlineForeignTable->hasPrimaryKey());
$this->assertSame(array('ID'), $onlineForeignTable->getPrimaryKey()->getQuotedColumns($platform));
$this->assertTrue($onlineForeignTable->hasColumn('"Fk"'));
$this->assertSame('"Fk"', $onlineForeignTable->getColumn('"Fk"')->getQuotedName($platform));
$this->assertTrue($onlineForeignTable->hasIndex('"Fk_index"'));
$this->assertTrue($onlineForeignTable->getIndex('"Fk_index"')->hasColumnAtPosition('"Fk"'));
$this->assertSame(array('"Fk"'), $onlineForeignTable->getIndex('"Fk_index"')->getQuotedColumns($platform));
$this->assertTrue($onlineForeignTable->hasForeignKey('"Primary_Table_Fk"'));
$this->assertSame(
$primaryTableName,
$onlineForeignTable->getForeignKey('"Primary_Table_Fk"')->getQuotedForeignTableName($platform)
);
$this->assertSame(
array('"Fk"'),
$onlineForeignTable->getForeignKey('"Primary_Table_Fk"')->getQuotedLocalColumns($platform)
);
$this->assertSame(
array('"Id"'),
$onlineForeignTable->getForeignKey('"Primary_Table_Fk"')->getQuotedForeignColumns($platform)
);
}
} }
...@@ -887,4 +887,71 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -887,4 +887,71 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$columns = $this->_sm->listTableColumns("my_table"); $columns = $this->_sm->listTableColumns("my_table");
$this->assertEquals("It's a comment with a quote", $columns['id']->getComment()); $this->assertEquals("It's a comment with a quote", $columns['id']->getComment());
} }
/**
* @group DBAL-1009
*
* @dataProvider getAlterColumnComment
*/
public function testAlterColumnComment($comment1, $expectedComment1, $comment2, $expectedComment2)
{
if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
$this->_conn->getDatabasePlatform()->getName() != 'mssql') {
$this->markTestSkipped('Database does not support column comments.');
}
$offlineTable = new Table('alter_column_comment_test');
$offlineTable->addColumn('comment1', 'integer', array('comment' => $comment1));
$offlineTable->addColumn('comment2', 'integer', array('comment' => $comment2));
$offlineTable->addColumn('no_comment1', 'integer');
$offlineTable->addColumn('no_comment2', 'integer');
$this->_sm->dropAndCreateTable($offlineTable);
$onlineTable = $this->_sm->listTableDetails("alter_column_comment_test");
$this->assertSame($expectedComment1, $onlineTable->getColumn('comment1')->getComment());
$this->assertSame($expectedComment2, $onlineTable->getColumn('comment2')->getComment());
$this->assertNull($onlineTable->getColumn('no_comment1')->getComment());
$this->assertNull($onlineTable->getColumn('no_comment2')->getComment());
$onlineTable->changeColumn('comment1', array('comment' => $comment2));
$onlineTable->changeColumn('comment2', array('comment' => $comment1));
$onlineTable->changeColumn('no_comment1', array('comment' => $comment1));
$onlineTable->changeColumn('no_comment2', array('comment' => $comment2));
$comparator = new Comparator();
$tableDiff = $comparator->diffTable($offlineTable, $onlineTable);
$this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $tableDiff);
$this->_sm->alterTable($tableDiff);
$onlineTable = $this->_sm->listTableDetails("alter_column_comment_test");
$this->assertSame($expectedComment2, $onlineTable->getColumn('comment1')->getComment());
$this->assertSame($expectedComment1, $onlineTable->getColumn('comment2')->getComment());
$this->assertSame($expectedComment1, $onlineTable->getColumn('no_comment1')->getComment());
$this->assertSame($expectedComment2, $onlineTable->getColumn('no_comment2')->getComment());
}
public function getAlterColumnComment()
{
return array(
array(null, null, ' ', ' '),
array(null, null, '0', '0'),
array(null, null, 'foo', 'foo'),
array('', null, ' ', ' '),
array('', null, '0', '0'),
array('', null, 'foo', 'foo'),
array(' ', ' ', '0', '0'),
array(' ', ' ', 'foo', 'foo'),
array('0', '0', 'foo', 'foo'),
);
}
} }
...@@ -39,6 +39,8 @@ class DBAL421Test extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -39,6 +39,8 @@ class DBAL421Test extends \Doctrine\Tests\DbalFunctionalTestCase
$this->assertNotContains($guid, $guids, "Duplicate GUID detected"); $this->assertNotContains($guid, $guids, "Duplicate GUID detected");
$guids[] = $guid; $guids[] = $guid;
} }
$statement->closeCursor();
} }
private function getSelectGuidSql() private function getSelectGuidSql()
......
...@@ -59,7 +59,7 @@ class TypeConversionTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -59,7 +59,7 @@ class TypeConversionTest extends \Doctrine\Tests\DbalFunctionalTestCase
array('datetime', new \DateTime('2010-04-05 10:10:10'), 'DateTime'), array('datetime', new \DateTime('2010-04-05 10:10:10'), 'DateTime'),
array('datetimetz', new \DateTime('2010-04-05 10:10:10'), 'DateTime'), array('datetimetz', new \DateTime('2010-04-05 10:10:10'), 'DateTime'),
array('date', new \DateTime('2010-04-05'), 'DateTime'), array('date', new \DateTime('2010-04-05'), 'DateTime'),
array('time', new \DateTime('10:10:10'), 'DateTime'), array('time', new \DateTime('1970-01-01 10:10:10'), 'DateTime'),
array('text', str_repeat('foo ', 1000), 'string'), array('text', str_repeat('foo ', 1000), 'string'),
array('array', array('foo' => 'bar'), 'array'), array('array', array('foo' => 'bar'), 'array'),
array('json_array', array('foo' => 'bar'), 'array'), array('json_array', array('foo' => 'bar'), 'array'),
......
...@@ -604,4 +604,41 @@ abstract class AbstractMySQLPlatformTestCase extends AbstractPlatformTestCase ...@@ -604,4 +604,41 @@ abstract class AbstractMySQLPlatformTestCase extends AbstractPlatformTestCase
{ {
$this->assertSame('CHAR(36)', $this->_platform->getGuidTypeDeclarationSQL(array())); $this->assertSame('CHAR(36)', $this->_platform->getGuidTypeDeclarationSQL(array()));
} }
/**
* {@inheritdoc}
*/
public function getAlterTableRenameColumnSQL()
{
return array(
"ALTER TABLE foo CHANGE bar baz INT DEFAULT 666 NOT NULL COMMENT 'rename test'",
);
}
/**
* {@inheritdoc}
*/
protected function getQuotesTableIdentifiersInAlterTableSQL()
{
return array(
'ALTER TABLE `foo` DROP FOREIGN KEY fk1',
'ALTER TABLE `foo` DROP FOREIGN KEY fk2',
'ALTER TABLE `foo` RENAME TO `table`, ADD bloo INT NOT NULL, DROP baz, CHANGE bar bar INT DEFAULT NULL, ' .
'CHANGE id war INT NOT NULL',
'ALTER TABLE `table` ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id)',
'ALTER TABLE `table` ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id)',
);
}
/**
* {@inheritdoc}
*/
protected function getCommentOnColumnSQL()
{
return array(
"COMMENT ON COLUMN foo.bar IS 'comment'",
"COMMENT ON COLUMN `Foo`.`BAR` IS 'comment'",
"COMMENT ON COLUMN `select`.`from` IS 'comment'",
);
}
} }
...@@ -5,6 +5,8 @@ namespace Doctrine\Tests\DBAL\Platforms; ...@@ -5,6 +5,8 @@ namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\Common\EventManager; use Doctrine\Common\EventManager;
use Doctrine\DBAL\Events; use Doctrine\DBAL\Events;
use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnDiff;
use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Index;
...@@ -914,6 +916,28 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase ...@@ -914,6 +916,28 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
); );
} }
/**
* @return array
*
* @see testGetCommentOnColumnSQL
*/
abstract protected function getCommentOnColumnSQL();
/**
* @group DBAL-1004
*/
public function testGetCommentOnColumnSQL()
{
$this->assertSame(
$this->getCommentOnColumnSQL(),
array(
$this->_platform->getCommentOnColumnSQL('foo', 'bar', 'comment'), // regular identifiers
$this->_platform->getCommentOnColumnSQL('`Foo`', '`BAR`', 'comment'), // explicitly quoted identifiers
$this->_platform->getCommentOnColumnSQL('select', 'from', 'comment'), // reserved keyword identifiers
)
);
}
protected function getQuotedStringLiteralWithoutQuoteCharacter() protected function getQuotedStringLiteralWithoutQuoteCharacter()
{ {
return "'No quote'"; return "'No quote'";
...@@ -956,4 +980,74 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase ...@@ -956,4 +980,74 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{ {
$this->_platform->getGuidTypeDeclarationSQL(array()); $this->_platform->getGuidTypeDeclarationSQL(array());
} }
/**
* @group DBAL-1010
*/
public function testGeneratesAlterTableRenameColumnSQL()
{
$table = new Table('foo');
$table->addColumn(
'bar',
'integer',
array('notnull' => true, 'default' => 666, 'comment' => 'rename test')
);
$tableDiff = new TableDiff('foo');
$tableDiff->fromTable = $table;
$tableDiff->renamedColumns['bar'] = new Column(
'baz',
Type::getType('integer'),
array('notnull' => true, 'default' => 666, 'comment' => 'rename test')
);
$this->assertSame($this->getAlterTableRenameColumnSQL(), $this->_platform->getAlterTableSQL($tableDiff));
}
/**
* @return array
*/
abstract public function getAlterTableRenameColumnSQL();
/**
* @group DBAL-1016
*/
public function testQuotesTableIdentifiersInAlterTableSQL()
{
$table = new Table('"foo"');
$table->addColumn('id', 'integer');
$table->addColumn('fk', 'integer');
$table->addColumn('fk2', 'integer');
$table->addColumn('fk3', 'integer');
$table->addColumn('bar', 'integer');
$table->addColumn('baz', 'integer');
$table->addForeignKeyConstraint('fk_table', array('fk'), array('id'), array(), 'fk1');
$table->addForeignKeyConstraint('fk_table', array('fk2'), array('id'), array(), 'fk2');
$tableDiff = new TableDiff('"foo"');
$tableDiff->fromTable = $table;
$tableDiff->newName = 'table';
$tableDiff->addedColumns['bloo'] = new Column('bloo', Type::getType('integer'));
$tableDiff->changedColumns['bar'] = new ColumnDiff(
'bar',
new Column('bar', Type::getType('integer'), array('notnull' => false)),
array('notnull'),
$table->getColumn('bar')
);
$tableDiff->renamedColumns['id'] = new Column('war', Type::getType('integer'));
$tableDiff->removedColumns['baz'] = new Column('baz', Type::getType('integer'));
$tableDiff->addedForeignKeys[] = new ForeignKeyConstraint(array('fk3'), 'fk_table', array('id'), 'fk_add');
$tableDiff->changedForeignKeys[] = new ForeignKeyConstraint(array('fk2'), 'fk_table2', array('id'), 'fk2');
$tableDiff->removedForeignKeys[] = new ForeignKeyConstraint(array('fk'), 'fk_table', array('id'), 'fk1');
$this->assertSame(
$this->getQuotesTableIdentifiersInAlterTableSQL(),
$this->_platform->getAlterTableSQL($tableDiff)
);
}
/**
* @return array
*/
abstract protected function getQuotesTableIdentifiersInAlterTableSQL();
} }
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
namespace Doctrine\Tests\DBAL\Platforms; namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\Type;
abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCase abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCase
{ {
...@@ -674,4 +676,67 @@ abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCa ...@@ -674,4 +676,67 @@ abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCa
{ {
$this->assertSame('UUID', $this->_platform->getGuidTypeDeclarationSQL(array())); $this->assertSame('UUID', $this->_platform->getGuidTypeDeclarationSQL(array()));
} }
/**
* {@inheritdoc}
*/
public function getAlterTableRenameColumnSQL()
{
return array(
'ALTER TABLE foo RENAME COLUMN bar TO baz',
);
}
/**
* {@inheritdoc}
*/
protected function getQuotesTableIdentifiersInAlterTableSQL()
{
return array(
'ALTER TABLE "foo" DROP CONSTRAINT fk1',
'ALTER TABLE "foo" DROP CONSTRAINT fk2',
'ALTER TABLE "foo" ADD bloo INT NOT NULL',
'ALTER TABLE "foo" DROP baz',
'ALTER TABLE "foo" ALTER bar DROP NOT NULL',
'ALTER TABLE "foo" RENAME COLUMN id TO war',
'ALTER TABLE "foo" RENAME TO "table"',
'ALTER TABLE "table" ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id) NOT DEFERRABLE ' .
'INITIALLY IMMEDIATE',
'ALTER TABLE "table" ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id) NOT DEFERRABLE ' .
'INITIALLY IMMEDIATE',
);
}
/**
* {@inheritdoc}
*/
protected function getCommentOnColumnSQL()
{
return array(
'COMMENT ON COLUMN foo.bar IS \'comment\'',
'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
'COMMENT ON COLUMN "select"."from" IS \'comment\'',
);
}
/**
* @group DBAL-1004
*/
public function testAltersTableColumnCommentWithExplicitlyQuotedIdentifiers()
{
$table1 = new Table('"foo"', array(new Column('"bar"', Type::getType('integer'))));
$table2 = new Table('"foo"', array(new Column('"bar"', Type::getType('integer'), array('comment' => 'baz'))));
$comparator = new Comparator();
$tableDiff = $comparator->diffTable($table1, $table2);
$this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $tableDiff);
$this->assertSame(
array(
'COMMENT ON COLUMN "foo"."bar" IS \'baz\'',
),
$this->_platform->getAlterTableSQL($tableDiff)
);
}
} }
...@@ -471,4 +471,43 @@ class DB2PlatformTest extends AbstractPlatformTestCase ...@@ -471,4 +471,43 @@ class DB2PlatformTest extends AbstractPlatformTestCase
{ {
$this->assertSame('CHAR(36)', $this->_platform->getGuidTypeDeclarationSQL(array())); $this->assertSame('CHAR(36)', $this->_platform->getGuidTypeDeclarationSQL(array()));
} }
/**
* {@inheritdoc}
*/
public function getAlterTableRenameColumnSQL()
{
return array(
'ALTER TABLE foo RENAME COLUMN bar TO baz',
);
}
/**
* {@inheritdoc}
*/
protected function getQuotesTableIdentifiersInAlterTableSQL()
{
return array(
'ALTER TABLE "foo" DROP FOREIGN KEY fk1',
'ALTER TABLE "foo" DROP FOREIGN KEY fk2',
'ALTER TABLE "foo" ADD COLUMN bloo INTEGER NOT NULL WITH DEFAULT DROP COLUMN baz ' .
'ALTER bar bar INTEGER DEFAULT NULL RENAME COLUMN id TO war',
'CALL SYSPROC.ADMIN_CMD (\'REORG TABLE "foo"\')',
'RENAME TABLE "foo" TO "table"',
'ALTER TABLE "table" ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id)',
'ALTER TABLE "table" ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id)',
);
}
/**
* {@inheritdoc}
*/
protected function getCommentOnColumnSQL()
{
return array(
'COMMENT ON COLUMN foo.bar IS \'comment\'',
'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
'COMMENT ON COLUMN "select"."from" IS \'comment\'',
);
}
} }
...@@ -8,6 +8,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; ...@@ -8,6 +8,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\SQLAnywherePlatform; use Doctrine\DBAL\Platforms\SQLAnywherePlatform;
use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\ColumnDiff;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Table;
...@@ -863,4 +864,63 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase ...@@ -863,4 +864,63 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase
{ {
$this->assertSame('UNIQUEIDENTIFIER', $this->_platform->getGuidTypeDeclarationSQL(array())); $this->assertSame('UNIQUEIDENTIFIER', $this->_platform->getGuidTypeDeclarationSQL(array()));
} }
/**
* {@inheritdoc}
*/
public function getAlterTableRenameColumnSQL()
{
return array(
'ALTER TABLE foo RENAME bar TO baz',
);
}
/**
* {@inheritdoc}
*/
protected function getQuotesTableIdentifiersInAlterTableSQL()
{
return array(
'ALTER TABLE "foo" DROP FOREIGN KEY fk1',
'ALTER TABLE "foo" DROP FOREIGN KEY fk2',
'ALTER TABLE "foo" RENAME id TO war',
'ALTER TABLE "foo" ADD bloo INT NOT NULL, DROP baz, ALTER bar INT DEFAULT NULL',
'ALTER TABLE "foo" RENAME "table"',
'ALTER TABLE "table" ADD CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id)',
'ALTER TABLE "table" ADD CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id)',
);
}
/**
* {@inheritdoc}
*/
protected function getCommentOnColumnSQL()
{
return array(
'COMMENT ON COLUMN foo.bar IS \'comment\'',
'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
'COMMENT ON COLUMN "select"."from" IS \'comment\'',
);
}
/**
* @group DBAL-1004
*/
public function testAltersTableColumnCommentWithExplicitlyQuotedIdentifiers()
{
$table1 = new Table('"foo"', array(new Column('"bar"', Type::getType('integer'))));
$table2 = new Table('"foo"', array(new Column('"bar"', Type::getType('integer'), array('comment' => 'baz'))));
$comparator = new Comparator();
$tableDiff = $comparator->diffTable($table1, $table2);
$this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $tableDiff);
$this->assertSame(
array(
'COMMENT ON COLUMN "foo"."bar" IS \'baz\'',
),
$this->_platform->getAlterTableSQL($tableDiff)
);
}
} }
...@@ -498,8 +498,8 @@ class SqlitePlatformTest extends AbstractPlatformTestCase ...@@ -498,8 +498,8 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
'CREATE TABLE "table" (id INTEGER NOT NULL, PRIMARY KEY(id))', 'CREATE TABLE "table" (id INTEGER NOT NULL, PRIMARY KEY(id))',
'INSERT INTO "table" (id) SELECT id FROM __temp__table', 'INSERT INTO "table" (id) SELECT id FROM __temp__table',
'DROP TABLE __temp__table', 'DROP TABLE __temp__table',
'CREATE INDEX "select" ON table (id)', 'CREATE INDEX "select" ON "table" (id)',
'CREATE INDEX "bar" ON table (id)', 'CREATE INDEX "bar" ON "table" (id)',
); );
} }
...@@ -560,4 +560,52 @@ class SqlitePlatformTest extends AbstractPlatformTestCase ...@@ -560,4 +560,52 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
{ {
$this->assertSame('CHAR(36)', $this->_platform->getGuidTypeDeclarationSQL(array())); $this->assertSame('CHAR(36)', $this->_platform->getGuidTypeDeclarationSQL(array()));
} }
/**
* {@inheritdoc}
*/
public function getAlterTableRenameColumnSQL()
{
return array(
'CREATE TEMPORARY TABLE __temp__foo AS SELECT bar FROM foo',
'DROP TABLE foo',
'CREATE TABLE foo (baz INTEGER DEFAULT 666 NOT NULL)',
'INSERT INTO foo (baz) SELECT bar FROM __temp__foo',
'DROP TABLE __temp__foo',
);
}
/**
* {@inheritdoc}
*/
protected function getQuotesTableIdentifiersInAlterTableSQL()
{
return array(
'DROP INDEX IDX_8C736521A81E660E',
'DROP INDEX IDX_8C736521FDC58D6C',
'CREATE TEMPORARY TABLE __temp__foo AS SELECT fk, fk2, id, fk3, bar FROM "foo"',
'DROP TABLE "foo"',
'CREATE TABLE "foo" (fk2 INTEGER NOT NULL, fk3 INTEGER NOT NULL, fk INTEGER NOT NULL, war INTEGER NOT NULL, ' .
'bar INTEGER DEFAULT NULL, bloo INTEGER NOT NULL, ' .
'CONSTRAINT fk2 FOREIGN KEY (fk2) REFERENCES fk_table2 (id) NOT DEFERRABLE INITIALLY IMMEDIATE, ' .
'CONSTRAINT fk_add FOREIGN KEY (fk3) REFERENCES fk_table (id) NOT DEFERRABLE INITIALLY IMMEDIATE)',
'INSERT INTO "foo" (fk, fk2, war, fk3, bar) SELECT fk, fk2, id, fk3, bar FROM __temp__foo',
'DROP TABLE __temp__foo',
'ALTER TABLE "foo" RENAME TO "table"',
'CREATE INDEX IDX_8C736521A81E660E ON "table" (fk)',
'CREATE INDEX IDX_8C736521FDC58D6C ON "table" (fk2)',
);
}
/**
* {@inheritdoc}
*/
protected function getCommentOnColumnSQL()
{
return array(
'COMMENT ON COLUMN foo.bar IS \'comment\'',
'COMMENT ON COLUMN "Foo"."BAR" IS \'comment\'',
'COMMENT ON COLUMN "select"."from" IS \'comment\'',
);
}
} }
...@@ -204,8 +204,18 @@ class ExpressionBuilderTest extends \Doctrine\Tests\DbalTestCase ...@@ -204,8 +204,18 @@ class ExpressionBuilderTest extends \Doctrine\Tests\DbalTestCase
$this->assertEquals('u.groups IN (1, 3, 4, 7)', $this->expr->in('u.groups', array(1,3,4,7))); $this->assertEquals('u.groups IN (1, 3, 4, 7)', $this->expr->in('u.groups', array(1,3,4,7)));
} }
public function testInWithPlaceholder()
{
$this->assertEquals('u.groups IN (?)', $this->expr->in('u.groups', '?'));
}
public function testNotIn() public function testNotIn()
{ {
$this->assertEquals('u.groups NOT IN (1, 3, 4, 7)', $this->expr->notIn('u.groups', array(1,3,4,7))); $this->assertEquals('u.groups NOT IN (1, 3, 4, 7)', $this->expr->notIn('u.groups', array(1,3,4,7)));
} }
}
\ No newline at end of file public function testNotInWithPlaceholder()
{
$this->assertEquals('u.groups NOT IN (:values)', $this->expr->notIn('u.groups', ':values'));
}
}
...@@ -13,7 +13,7 @@ require_once __DIR__ . '/../TestInit.php'; ...@@ -13,7 +13,7 @@ require_once __DIR__ . '/../TestInit.php';
*/ */
class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
{ {
static public function dataGetPlaceholderPositions() public function dataGetPlaceholderPositions()
{ {
return array( return array(
// none // none
...@@ -73,7 +73,7 @@ SQLDATA ...@@ -73,7 +73,7 @@ SQLDATA
$this->assertEquals($expectedParamPos, $actualParamPos); $this->assertEquals($expectedParamPos, $actualParamPos);
} }
static public function dataExpandListParameters() public function dataExpandListParameters()
{ {
return array( return array(
// Positional: Very simple with one needle // Positional: Very simple with one needle
...@@ -148,6 +148,24 @@ SQLDATA ...@@ -148,6 +148,24 @@ SQLDATA
array(1 => 'bar', 0 => 1, 2 => 'baz'), array(1 => 'bar', 0 => 1, 2 => 'baz'),
array(1 => \PDO::PARAM_STR, 2 => \PDO::PARAM_STR) array(1 => \PDO::PARAM_STR, 2 => \PDO::PARAM_STR)
), ),
// Positional: explicit keys for array params and array types
array(
"SELECT * FROM Foo WHERE foo IN (?) AND bar IN (?) AND baz = ?",
array(1 => array('bar1', 'bar2'), 2 => true, 0 => array(1, 2, 3)),
array(2 => \PDO::PARAM_BOOL, 1 => Connection::PARAM_STR_ARRAY, 0 => Connection::PARAM_INT_ARRAY),
'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ?',
array(1, 2, 3, 'bar1', 'bar2', true),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_STR, \PDO::PARAM_STR, \PDO::PARAM_BOOL)
),
// Positional starts from 1: One non-list before and one after list-needle
array(
"SELECT * FROM Foo WHERE foo = ? AND bar IN (?) AND baz = ? AND foo IN (?)",
array(1 => 1, 2 => array(1, 2, 3), 3 => 4, 4 => array(5, 6)),
array(1 => \PDO::PARAM_INT, 2 => Connection::PARAM_INT_ARRAY, 3 => \PDO::PARAM_INT, 4 => Connection::PARAM_INT_ARRAY),
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ? AND foo IN (?, ?)',
array(1, 1, 2, 3, 4, 5, 6),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
),
// Named parameters : Very simple with param int // Named parameters : Very simple with param int
array( array(
"SELECT * FROM Foo WHERE foo = :foo", "SELECT * FROM Foo WHERE foo = :foo",
...@@ -339,7 +357,7 @@ SQLDATA ...@@ -339,7 +357,7 @@ SQLDATA
$this->assertEquals($expectedTypes, $types, "Types dont match"); $this->assertEquals($expectedTypes, $types, "Types dont match");
} }
public static function dataQueryWithMissingParameters() public function dataQueryWithMissingParameters()
{ {
return array( return array(
array( array(
......
...@@ -1122,4 +1122,52 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -1122,4 +1122,52 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array('notnull', 'default', 'comment'), $comparator->diffColumn($column1, $column2)); $this->assertEquals(array('notnull', 'default', 'comment'), $comparator->diffColumn($column1, $column2));
$this->assertEquals(array('notnull', 'default', 'comment'), $comparator->diffColumn($column2, $column1)); $this->assertEquals(array('notnull', 'default', 'comment'), $comparator->diffColumn($column2, $column1));
} }
/**
* @group DBAL-1009
*
* @dataProvider getCompareColumnComments
*/
public function testCompareColumnComments($comment1, $comment2, $equals)
{
$column1 = new Column('foo', Type::getType('integer'), array('comment' => $comment1));
$column2 = new Column('foo', Type::getType('integer'), array('comment' => $comment2));
$comparator = new Comparator();
$expectedDiff = $equals ? array() : array('comment');
$actualDiff = $comparator->diffColumn($column1, $column2);
$this->assertSame($expectedDiff, $actualDiff);
$actualDiff = $comparator->diffColumn($column2, $column1);
$this->assertSame($expectedDiff, $actualDiff);
}
public function getCompareColumnComments()
{
return array(
array(null, null, true),
array('', '', true),
array(' ', ' ', true),
array('0', '0', true),
array('foo', 'foo', true),
array(null, '', true),
array(null, ' ', false),
array(null, '0', false),
array(null, 'foo', false),
array('', ' ', false),
array('', '0', false),
array('', 'foo', false),
array(' ', '0', false),
array(' ', 'foo', false),
array('0', 'foo', false),
);
}
} }
<?php
namespace Doctrine\Tests\DBAL\Schema;
use Doctrine\DBAL\Schema\Identifier;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\Tests\DBAL\Mocks\MockPlatform;
class TableDiffTest extends \PHPUnit_Framework_TestCase
{
/**
* @group DBAL-1013
*/
public function testReturnsName()
{
$tableDiff = new TableDiff('foo');
$this->assertEquals(new Identifier('foo'), $tableDiff->getName(new MockPlatform()));
}
/**
* @group DBAL-1016
*/
public function testPrefersNameFromTableObject()
{
$platformMock = new MockPlatform();
$tableMock = $this->getMockBuilder('Doctrine\DBAL\Schema\Table')
->disableOriginalConstructor()
->getMock();
$tableDiff = new TableDiff('foo');
$tableDiff->fromTable = $tableMock;
$tableMock->expects($this->once())
->method('getQuotedName')
->with($platformMock)
->will($this->returnValue('foo'));
$this->assertEquals(new Identifier('foo'), $tableDiff->getName($platformMock));
}
/**
* @group DBAL-1013
*/
public function testReturnsNewName()
{
$tableDiff = new TableDiff('foo');
$this->assertFalse($tableDiff->getNewName());
$tableDiff->newName = 'bar';
$this->assertEquals(new Identifier('bar'), $tableDiff->getNewName());
}
}
...@@ -623,4 +623,76 @@ class TableTest extends \Doctrine\Tests\DbalTestCase ...@@ -623,4 +623,76 @@ class TableTest extends \Doctrine\Tests\DbalTestCase
$table->renameIndex('idx_id', 'idx_foo'); $table->renameIndex('idx_id', 'idx_foo');
} }
/**
* @dataProvider getNormalizesAssetNames
* @group DBAL-831
*/
public function testNormalizesColumnNames($assetName)
{
$table = new Table('test');
$table->addColumn($assetName, 'integer');
$table->addIndex(array($assetName), $assetName);
$table->addForeignKeyConstraint('test', array($assetName), array($assetName), array(), $assetName);
$this->assertTrue($table->hasColumn($assetName));
$this->assertTrue($table->hasColumn('foo'));
$this->assertInstanceOf('Doctrine\DBAL\Schema\Column', $table->getColumn($assetName));
$this->assertInstanceOf('Doctrine\DBAL\Schema\Column', $table->getColumn('foo'));
$this->assertTrue($table->hasIndex($assetName));
$this->assertTrue($table->hasIndex('foo'));
$this->assertInstanceOf('Doctrine\DBAL\Schema\Index', $table->getIndex($assetName));
$this->assertInstanceOf('Doctrine\DBAL\Schema\Index', $table->getIndex('foo'));
$this->assertTrue($table->hasForeignKey($assetName));
$this->assertTrue($table->hasForeignKey('foo'));
$this->assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $table->getForeignKey($assetName));
$this->assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $table->getForeignKey('foo'));
$table->renameIndex($assetName, $assetName);
$this->assertTrue($table->hasIndex($assetName));
$this->assertTrue($table->hasIndex('foo'));
$table->renameIndex($assetName, 'foo');
$this->assertTrue($table->hasIndex($assetName));
$this->assertTrue($table->hasIndex('foo'));
$table->renameIndex('foo', $assetName);
$this->assertTrue($table->hasIndex($assetName));
$this->assertTrue($table->hasIndex('foo'));
$table->renameIndex($assetName, 'bar');
$this->assertFalse($table->hasIndex($assetName));
$this->assertFalse($table->hasIndex('foo'));
$this->assertTrue($table->hasIndex('bar'));
$table->renameIndex('bar', $assetName);
$table->dropColumn($assetName);
$table->dropIndex($assetName);
$table->removeForeignKey($assetName);
$this->assertFalse($table->hasColumn($assetName));
$this->assertFalse($table->hasColumn('foo'));
$this->assertFalse($table->hasIndex($assetName));
$this->assertFalse($table->hasIndex('foo'));
$this->assertFalse($table->hasForeignKey($assetName));
$this->assertFalse($table->hasForeignKey('foo'));
}
public function getNormalizesAssetNames()
{
return array(
array('foo'),
array('FOO'),
array('`foo`'),
array('`FOO`'),
array('"foo"'),
array('"FOO"'),
array('"foo"'),
array('"FOO"'),
);
}
} }
...@@ -34,6 +34,13 @@ class TimeTest extends \Doctrine\Tests\DbalTestCase ...@@ -34,6 +34,13 @@ class TimeTest extends \Doctrine\Tests\DbalTestCase
); );
} }
public function testDateFieldResetInPHPValue()
{
$time = $this->_type->convertToPHPValue('01:23:34', $this->_platform);
$this->assertEquals('01:23:34', $time->format('H:i:s'));
$this->assertEquals('1970-01-01', $time->format('Y-m-d'));
}
public function testInvalidTimeFormatConversion() public function testInvalidTimeFormatConversion()
{ {
$this->setExpectedException('Doctrine\DBAL\Types\ConversionException'); $this->setExpectedException('Doctrine\DBAL\Types\ConversionException');
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
error_reporting(E_ALL | E_STRICT); error_reporting(E_ALL | E_STRICT);
date_default_timezone_set('UTC');
if (file_exists(__DIR__ . '/../../../vendor/autoload.php')) { if (file_exists(__DIR__ . '/../../../vendor/autoload.php')) {
// dependencies were installed via composer - this is the main project // dependencies were installed via composer - this is the main project
......
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