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:
- 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"
script: phpunit --configuration tests/travis/$DB.travis.xml
script: ./vendor/bin/phpunit --configuration tests/travis/$DB.travis.xml
matrix:
allow_failures:
......@@ -44,7 +44,7 @@ matrix:
- php: hhvm
env: DB=sqlite
- php: hhvm
env: DB=mysqli
env: DB=mysql
- php: hhvm-nightly
exclude:
- php: hhvm
......
# 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
The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table``
......
......@@ -307,7 +307,7 @@ Prepare a given SQL statement and return the
array(
0 => array(
'username' => 'jwage',
'password' => 'changeme
'password' => 'changeme'
)
)
*/
......@@ -344,7 +344,7 @@ parameters to the execute method, then returning the statement:
/*
array(
0 => 'jwage',
1 => 'changeme
1 => 'changeme'
)
*/
......@@ -367,7 +367,7 @@ Execute the query and fetch all results into an array:
array(
0 => array(
'username' => 'jwage',
'password' => 'changeme
'password' => 'changeme'
)
)
*/
......@@ -385,7 +385,7 @@ Numeric index retrieval of first result row of the given query:
/*
array(
0 => 'jwage',
1 => 'changeme
1 => 'changeme'
)
*/
......@@ -412,7 +412,7 @@ Retrieve assoc row of the first result row.
/*
array(
'username' => 'jwage',
'password' => 'changeme
'password' => 'changeme'
)
*/
......
......@@ -597,7 +597,7 @@ class Connection implements DriverConnection
*/
public function close()
{
unset($this->_conn);
$this->_conn = null;
$this->_isConnected = false;
}
......
......@@ -50,6 +50,12 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
public function __construct(array $params, $username, $password, array $driverOptions = array())
{
$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');
$dbname = isset($params['dbname']) ? $params['dbname'] : null;
......
......@@ -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}
*/
......@@ -100,11 +112,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/
public function quote($input, $type = \PDO::PARAM_STR)
{
try {
return parent::quote($input, $type);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
return parent::quote($input, $type);
}
/**
......@@ -112,11 +120,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/
public function lastInsertId($name = null)
{
try {
return parent::lastInsertId($name);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
return parent::lastInsertId($name);
}
/**
......
......@@ -43,6 +43,10 @@ class Driver extends AbstractSQLServerDriver
if (isset($params['dbname'])) {
$driverOptions['Database'] = $params['dbname'];
}
if (isset($params['charset'])) {
$driverOptions['CharacterSet'] = $params['charset'];
}
$driverOptions['UID'] = $username;
$driverOptions['PWD'] = $password;
......
......@@ -1574,8 +1574,10 @@ abstract class AbstractPlatform
$sql = $this->_getCreateTableSQL($tableName, $columns, $options);
if ($this->supportsCommentOnStatement()) {
foreach ($table->getColumns() as $column) {
if ($this->getColumnComment($column)) {
$sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $this->getColumnComment($column));
$comment = $this->getColumnComment($column);
if (null !== $comment && '' !== $comment) {
$sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment);
}
}
}
......@@ -1592,9 +1594,12 @@ abstract class AbstractPlatform
*/
public function getCommentOnColumnSQL($tableName, $columnName, $comment)
{
$tableName = new Identifier($tableName);
$columnName = new Identifier($columnName);
$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
*/
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{
$tableName = $diff->getName()->getQuotedName($this);
$tableName = $diff->getName($this)->getQuotedName($this);
$sql = array();
if ($this->supportsForeignKeyConstraints()) {
......@@ -2045,7 +2050,7 @@ abstract class AbstractPlatform
{
$tableName = (false !== $diff->newName)
? $diff->getNewName()->getQuotedName($this)
: $diff->getName()->getQuotedName($this);
: $diff->getName($this)->getQuotedName($this);
$sql = array();
......@@ -2205,7 +2210,7 @@ abstract class AbstractPlatform
$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']);
}
......
......@@ -519,12 +519,16 @@ class DB2Platform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
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.
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(
......@@ -532,10 +536,6 @@ class DB2Platform extends AbstractPlatform
$sql,
$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);
......@@ -547,7 +547,7 @@ class DB2Platform extends AbstractPlatform
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{
$sql = array();
$table = $diff->getName()->getQuotedName($this);
$table = $diff->getName($this)->getQuotedName($this);
foreach ($diff->removedIndexes as $remKey => $remIndex) {
foreach ($diff->addedIndexes as $addKey => $addIndex) {
......
......@@ -549,7 +549,7 @@ class DrizzlePlatform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
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(
$this->getPreAlterTableIndexForeignKeySQL($diff),
......
......@@ -593,7 +593,7 @@ class MySqlPlatform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
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(
$this->getPreAlterTableIndexForeignKeySQL($diff),
......@@ -611,7 +611,7 @@ class MySqlPlatform extends AbstractPlatform
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{
$sql = array();
$table = $diff->getName()->getQuotedName($this);
$table = $diff->getName($this)->getQuotedName($this);
foreach ($diff->removedIndexes as $remKey => $remIndex) {
// Dropping primary keys requires to unset autoincrement attribute on the particular column first.
......
......@@ -453,9 +453,16 @@ class PostgreSqlPlatform extends AbstractPlatform
}
$query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->getName()->getQuotedName($this) . ' ' . $query;
if ($comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
$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
}
$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) {
......@@ -486,7 +493,7 @@ class PostgreSqlPlatform extends AbstractPlatform
// here was a server version check before, but DBAL API does not support this anymore.
$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')) {
......@@ -494,12 +501,12 @@ class PostgreSqlPlatform extends AbstractPlatform
? ' DROP DEFAULT'
: ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray());
$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')) {
$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')) {
......@@ -508,27 +515,27 @@ class PostgreSqlPlatform extends AbstractPlatform
$seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName);
$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 . "')";
$sql[] = "ALTER TABLE " . $diff->getName()->getQuotedName($this) . " " . $query;
$sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query;
} else {
// Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have
$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')) {
$commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->name,
$column->getName(),
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$this->getColumnComment($column)
);
}
if ($columnDiff->hasChanged('length')) {
$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
$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);
}
$tableSql = array();
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$sql = array_merge($sql, $commentsSQL);
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);
......@@ -615,9 +628,12 @@ class PostgreSqlPlatform extends AbstractPlatform
*/
public function getCommentOnColumnSQL($tableName, $columnName, $comment)
{
$tableName = new Identifier($tableName);
$columnName = new Identifier($columnName);
$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
}
);
}
/**
* {@inheritDoc}
*/
......@@ -829,8 +845,8 @@ class PostgreSqlPlatform extends AbstractPlatform
{
if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) {
return false;
}
}
return parent::convertFromBoolean($item);
}
......
......@@ -143,8 +143,12 @@ class SQLAnywherePlatform extends AbstractPlatform
$comment = $this->getColumnComment($column);
if ($comment) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getQuotedName($this), $comment);
if (null !== $comment && '' !== $comment) {
$commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$comment
);
}
}
......@@ -173,7 +177,7 @@ class SQLAnywherePlatform extends AbstractPlatform
$column = $columnDiff->column;
$commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->name,
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$this->getColumnComment($column)
);
......@@ -185,21 +189,27 @@ class SQLAnywherePlatform extends AbstractPlatform
continue;
}
$sql[] = $this->getAlterTableClause($diff->getName()) . ' ' .
$sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' .
$this->getAlterTableRenameColumnClause($oldColumnName, $column);
}
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
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) {
$sql[] = $this->getAlterTableClause($diff->getName()) . ' ' .
$sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' .
$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);
......@@ -357,9 +367,12 @@ class SQLAnywherePlatform extends AbstractPlatform
*/
public function getCommentOnColumnSQL($tableName, $columnName, $comment)
{
$tableName = new Identifier($tableName);
$columnName = new Identifier($columnName);
$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
$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'";
// Recreate default constraint with new column name if necessary (for future reference).
if ($column->getDefault() !== null) {
$queryParts[] = $this->getAlterTableDropDefaultConstraintClause($diff->name, $oldColumnName);
$queryParts[] = $this->getAlterTableDropDefaultConstraintClause(
$diff->name,
$oldColumnName->getQuotedName($this)
);
$queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column);
}
}
......@@ -518,13 +522,13 @@ class SQLServerPlatform extends AbstractPlatform
}
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) {
$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
......@@ -540,10 +544,16 @@ class SQLServerPlatform extends AbstractPlatform
"'" . $this->generateIdentifierName($diff->newName) . "') + ''', ''OBJECT'';' " .
"FROM sys.default_constraints dc " .
"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";
}
$sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
$this->getPostAlterTableIndexForeignKeySQL($diff)
);
return array_merge($sql, $tableSql, $columnSql);
}
......@@ -719,10 +729,10 @@ class SQLServerPlatform extends AbstractPlatform
$level2Name = null
) {
return "EXEC sp_addextendedproperty " .
"N'" . $name . "', N'" . $value . "', " .
"N'" . $level0Type . "', " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name;
"N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " .
"N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' .
"N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' .
"N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name;
}
/**
......@@ -750,10 +760,10 @@ class SQLServerPlatform extends AbstractPlatform
$level2Name = null
) {
return "EXEC sp_dropextendedproperty " .
"N'" . $name . "', " .
"N'" . $level0Type . "', " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name;
"N" . $this->quoteStringLiteral($name) . ", " .
"N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' .
"N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' .
"N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name;
}
/**
......@@ -783,10 +793,10 @@ class SQLServerPlatform extends AbstractPlatform
$level2Name = null
) {
return "EXEC sp_updateextendedproperty " .
"N'" . $name . "', N'" . $value . "', " .
"N'" . $level0Type . "', " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name;
"N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " .
"N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' .
"N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' .
"N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name;
}
/**
......@@ -1175,7 +1185,7 @@ class SQLServerPlatform extends AbstractPlatform
//Remove ORDER BY from $query (including nested parentheses in order by list).
$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).
$selectFromPattern = '/^(\s*SELECT\s+(?:(.*)(?![^(]*\))))\sFROM\s/i';
......
......@@ -645,13 +645,13 @@ class SqlitePlatform extends AbstractPlatform
}
$sql = array();
$tableName = $diff->newName ?: $diff->name;
$tableName = $diff->newName ? $diff->getNewName(): $diff->getName($this);
foreach ($this->getIndexesInAlteredTable($diff) as $index) {
if ($index->isPrimary()) {
continue;
}
$sql[] = $this->getCreateIndexSQL($index, $tableName);
$sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this));
}
return $sql;
......@@ -836,7 +836,7 @@ class SqlitePlatform extends AbstractPlatform
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$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);
$sql = $this->getPreAlterTableIndexForeignKeySQL($diff);
......@@ -849,7 +849,7 @@ class SqlitePlatform extends AbstractPlatform
$sql[] = $this->getDropTableSQL($dataTable);
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);
}
......
......@@ -275,27 +275,27 @@ class ExpressionBuilder
/**
* Creates a IN () comparison expression with the given arguments.
*
* @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 $x The field in string format to be inspected by IN() comparison.
* @param string|array $y The placeholder or the array of values to be used by IN() comparison.
*
* @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.
*
* @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 $x The field in string format to be inspected by NOT IN() comparison.
* @param string|array $y The placeholder or the array of values to be used by NOT IN() comparison.
*
* @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
$arrayPositions = array();
$bindIndex = -1;
if ($isPositional) {
ksort($params);
ksort($types);
}
foreach ($types as $name => $type) {
++$bindIndex;
......@@ -113,6 +118,8 @@ class SQLParserUtils
if ($isPositional) {
$paramOffset = 0;
$queryOffset = 0;
$params = array_values($params);
$types = array_values($types);
foreach ($paramPos as $needle => $needlePos) {
if ( ! isset($arrayPositions[$needle])) {
......
......@@ -421,8 +421,11 @@ class Comparator
}
}
// only allow to delete comment if its set to '' not to null.
if ($properties1['comment'] !== null && $properties1['comment'] != $properties2['comment']) {
// A null value and an empty string are actually equal for a comment so they should not trigger a change.
if ($properties1['comment'] !== $properties2['comment'] &&
! (null === $properties1['comment'] && '' === $properties2['comment']) &&
! (null === $properties2['comment'] && '' === $properties1['comment'])
) {
$changedProperties[] = 'comment';
}
......
......@@ -46,7 +46,9 @@ class DrizzleSchemaManager extends AbstractSchemaManager
'autoincrement' => (bool)$tableColumn['IS_AUTO_INCREMENT'],
'scale' => (int)$tableColumn['NUMERIC_SCALE'],
'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);
......
......@@ -187,7 +187,9 @@ class MySqlSchemaManager extends AbstractSchemaManager
'scale' => null,
'precision' => null,
'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) {
......
......@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
/**
* Oracle Schema Manager.
*
......@@ -36,7 +38,7 @@ class OracleSchemaManager extends AbstractSchemaManager
{
$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
{
$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
$buffer['non_unique'] = ($tableIndex['is_unique'] == 0) ? true : false;
}
$buffer['key_name'] = $keyName;
$buffer['column_name'] = $tableIndex['column_name'];
$buffer['column_name'] = $this->getQuotedIdentifierName($tableIndex['column_name']);
$indexBuffer[] = $buffer;
}
......@@ -203,11 +205,13 @@ class OracleSchemaManager extends AbstractSchemaManager
'length' => $length,
'precision' => $precision,
'scale' => $scale,
'comment' => (isset($tableColumn['comments'])) ? $tableColumn['comments'] : null,
'comment' => isset($tableColumn['comments']) && '' !== $tableColumn['comments']
? $tableColumn['comments']
: null,
'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
}
$list[$value['constraint_name']] = array(
'name' => $value['constraint_name'],
'name' => $this->getQuotedIdentifierName($value['constraint_name']),
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['references_table'],
'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();
foreach ($list as $constraint) {
$result[] = new ForeignKeyConstraint(
array_values($constraint['local']), $constraint['foreignTable'],
array_values($constraint['foreign']), $constraint['name'],
array_values($constraint['local']), $this->getQuotedIdentifierName($constraint['foreignTable']),
array_values($constraint['foreign']), $this->getQuotedIdentifierName($constraint['name']),
array('onDelete' => $constraint['onDelete'])
);
}
......@@ -254,7 +262,11 @@ class OracleSchemaManager extends AbstractSchemaManager
{
$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
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
'fixed' => $fixed,
'unsigned' => false,
'autoincrement' => $autoincrement,
'comment' => $tableColumn['comment'],
'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''
? $tableColumn['comment']
: null,
);
$column = new Column($tableColumn['field'], Type::getType($type), $options);
......
......@@ -144,7 +144,9 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager
'notnull' => (bool) $tableColumn['notnull'],
'default' => $default,
'autoincrement' => (bool) $tableColumn['autoincrement'],
'comment' => $tableColumn['comment']
'comment' => isset($tableColumn['comment']) && '' !== $tableColumn['comment']
? $tableColumn['comment']
: null,
));
}
......
......@@ -183,7 +183,7 @@ class Table extends AbstractAsset
*/
public function dropIndex($indexName)
{
$indexName = strtolower($indexName);
$indexName = $this->normalizeIdentifier($indexName);
if ( ! $this->hasIndex($indexName)) {
throw SchemaException::indexDoesNotExist($indexName, $this->_name);
}
......@@ -222,8 +222,8 @@ class Table extends AbstractAsset
*/
public function renameIndex($oldIndexName, $newIndexName = null)
{
$oldIndexName = strtolower($oldIndexName);
$normalizedNewIndexName = strtolower($newIndexName);
$oldIndexName = $this->normalizeIdentifier($oldIndexName);
$normalizedNewIndexName = $this->normalizeIdentifier($newIndexName);
if ($oldIndexName === $normalizedNewIndexName) {
return $this;
......@@ -287,7 +287,7 @@ class Table extends AbstractAsset
*/
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);
}
......@@ -362,7 +362,7 @@ class Table extends AbstractAsset
*/
public function dropColumn($columnName)
{
$columnName = strtolower($columnName);
$columnName = $this->normalizeIdentifier($columnName);
unset($this->_columns[$columnName]);
return $this;
......@@ -469,7 +469,7 @@ class Table extends AbstractAsset
protected function _addColumn(Column $column)
{
$columnName = $column->getName();
$columnName = strtolower($columnName);
$columnName = $this->normalizeIdentifier($columnName);
if (isset($this->_columns[$columnName])) {
throw SchemaException::columnAlreadyExists($this->getName(), $columnName);
......@@ -497,7 +497,7 @@ class Table extends AbstractAsset
}
$indexName = $indexCandidate->getName();
$indexName = strtolower($indexName);
$indexName = $this->normalizeIdentifier($indexName);
if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) {
throw SchemaException::indexAlreadyExists($indexName, $this->_name);
......@@ -535,7 +535,7 @@ class Table extends AbstractAsset
array_merge((array)$this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength()
);
}
$name = strtolower($name);
$name = $this->normalizeIdentifier($name);
$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.
......@@ -553,7 +553,7 @@ class Table extends AbstractAsset
*/
public function hasForeignKey($constraintName)
{
$constraintName = strtolower($constraintName);
$constraintName = $this->normalizeIdentifier($constraintName);
return isset($this->_fkConstraints[$constraintName]);
}
......@@ -569,7 +569,7 @@ class Table extends AbstractAsset
*/
public function getForeignKey($constraintName)
{
$constraintName = strtolower($constraintName);
$constraintName = $this->normalizeIdentifier($constraintName);
if (!$this->hasForeignKey($constraintName)) {
throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
}
......@@ -588,7 +588,7 @@ class Table extends AbstractAsset
*/
public function removeForeignKey($constraintName)
{
$constraintName = strtolower($constraintName);
$constraintName = $this->normalizeIdentifier($constraintName);
if (!$this->hasForeignKey($constraintName)) {
throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
}
......@@ -631,7 +631,7 @@ class Table extends AbstractAsset
*/
public function hasColumn($columnName)
{
$columnName = $this->trimQuotes(strtolower($columnName));
$columnName = $this->normalizeIdentifier($columnName);
return isset($this->_columns[$columnName]);
}
......@@ -647,7 +647,7 @@ class Table extends AbstractAsset
*/
public function getColumn($columnName)
{
$columnName = strtolower($this->trimQuotes($columnName));
$columnName = $this->normalizeIdentifier($columnName);
if ( ! $this->hasColumn($columnName)) {
throw SchemaException::columnDoesNotExist($columnName, $this->_name);
}
......@@ -704,7 +704,7 @@ class Table extends AbstractAsset
*/
public function hasIndex($indexName)
{
$indexName = strtolower($indexName);
$indexName = $this->normalizeIdentifier($indexName);
return (isset($this->_indexes[$indexName]));
}
......@@ -720,7 +720,7 @@ class Table extends AbstractAsset
*/
public function getIndex($indexName)
{
$indexName = strtolower($indexName);
$indexName = $this->normalizeIdentifier($indexName);
if ( ! $this->hasIndex($indexName)) {
throw SchemaException::indexDoesNotExist($indexName, $this->_name);
}
......@@ -814,4 +814,18 @@ class Table extends AbstractAsset
$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 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Table Diff.
*
......@@ -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
*/
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()
{
return new Identifier($this->newName);
return $this->newName ? new Identifier($this->newName) : $this->newName;
}
}
......@@ -62,7 +62,7 @@ class TimeType extends Type
return $value;
}
$val = \DateTime::createFromFormat($platform->getTimeFormatString(), $value);
$val = \DateTime::createFromFormat('!' . $platform->getTimeFormatString(), $value);
if ( ! $val) {
throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString());
}
......
......@@ -403,6 +403,15 @@ SQLSTATE[HY000]: General error: 1 near \"MUUHAAAAHAAAA\"");
$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()
{
$statement = 'SELECT * FROM foo WHERE bar = ?';
......
......@@ -24,7 +24,7 @@ class PDOConnectionTest extends DbalFunctionalTestCase
$this->driverConnection = $this->_conn->getWrappedConnection();
if ( ! $this->_conn->getWrappedConnection() instanceof PDOConnection) {
if ( ! $this->driverConnection instanceof PDOConnection) {
$this->markTestSkipped('PDO connection only test.');
}
}
......@@ -33,4 +33,54 @@ class PDOConnectionTest extends DbalFunctionalTestCase
{
$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
/**
* @group DBAL-472
* @group DBAL-1001
*/
public function testAlterTableColumnNotNull()
{
......@@ -70,6 +71,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$table->addColumn('id', 'integer');
$table->addColumn('foo', 'integer');
$table->addColumn('bar', 'string');
$table->setPrimaryKey(array('id'));
$this->_sm->dropAndCreateTable($table);
......@@ -78,9 +80,11 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertTrue($columns['id']->getNotnull());
$this->assertTrue($columns['foo']->getNotnull());
$this->assertTrue($columns['bar']->getNotnull());
$diffTable = clone $table;
$diffTable->changeColumn('foo', array('notnull' => false));
$diffTable->changeColumn('bar', array('length' => 1024));
$this->_sm->alterTable($comparator->diffTable($table, $diffTable));
......@@ -88,6 +92,7 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertTrue($columns['id']->getNotnull());
$this->assertFalse($columns['foo']->getNotnull());
$this->assertTrue($columns['bar']->getNotnull());
}
public function testListDatabases()
......@@ -102,4 +107,115 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$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
$columns = $this->_sm->listTableColumns("my_table");
$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
$this->assertNotContains($guid, $guids, "Duplicate GUID detected");
$guids[] = $guid;
}
$statement->closeCursor();
}
private function getSelectGuidSql()
......
......@@ -59,7 +59,7 @@ class TypeConversionTest extends \Doctrine\Tests\DbalFunctionalTestCase
array('datetime', 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('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('array', array('foo' => 'bar'), 'array'),
array('json_array', array('foo' => 'bar'), 'array'),
......
......@@ -604,4 +604,41 @@ abstract class AbstractMySQLPlatformTestCase extends AbstractPlatformTestCase
{
$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;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnDiff;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Index;
......@@ -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()
{
return "'No quote'";
......@@ -956,4 +980,74 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{
$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 @@
namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\Type;
abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCase
{
......@@ -674,4 +676,67 @@ abstract class AbstractPostgreSqlPlatformTestCase extends AbstractPlatformTestCa
{
$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
{
$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;
use Doctrine\DBAL\Platforms\SQLAnywherePlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnDiff;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Table;
......@@ -863,4 +864,63 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase
{
$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
'CREATE TABLE "table" (id INTEGER NOT NULL, PRIMARY KEY(id))',
'INSERT INTO "table" (id) SELECT id FROM __temp__table',
'DROP TABLE __temp__table',
'CREATE INDEX "select" ON table (id)',
'CREATE INDEX "bar" ON table (id)',
'CREATE INDEX "select" ON "table" (id)',
'CREATE INDEX "bar" ON "table" (id)',
);
}
......@@ -560,4 +560,52 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
{
$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
$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()
{
$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';
*/
class SQLParserUtilsTest extends \Doctrine\Tests\DbalTestCase
{
static public function dataGetPlaceholderPositions()
public function dataGetPlaceholderPositions()
{
return array(
// none
......@@ -73,7 +73,7 @@ SQLDATA
$this->assertEquals($expectedParamPos, $actualParamPos);
}
static public function dataExpandListParameters()
public function dataExpandListParameters()
{
return array(
// Positional: Very simple with one needle
......@@ -148,6 +148,24 @@ SQLDATA
array(1 => 'bar', 0 => 1, 2 => 'baz'),
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
array(
"SELECT * FROM Foo WHERE foo = :foo",
......@@ -339,7 +357,7 @@ SQLDATA
$this->assertEquals($expectedTypes, $types, "Types dont match");
}
public static function dataQueryWithMissingParameters()
public function dataQueryWithMissingParameters()
{
return array(
array(
......
......@@ -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($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
$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
);
}
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()
{
$this->setExpectedException('Doctrine\DBAL\Types\ConversionException');
......
......@@ -4,6 +4,7 @@
*/
error_reporting(E_ALL | E_STRICT);
date_default_timezone_set('UTC');
if (file_exists(__DIR__ . '/../../../vendor/autoload.php')) {
// 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