<?php 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; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Types\Type; use Doctrine\Tests\Types\CommentedType; abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase { /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ protected $_platform; abstract public function createPlatform(); protected function setUp() { $this->_platform = $this->createPlatform(); } /** * @group DDC-1360 */ public function testQuoteIdentifier() { if ($this->_platform->getName() == "mssql") { $this->markTestSkipped('Not working this way on mssql.'); } $c = $this->_platform->getIdentifierQuoteCharacter(); $this->assertEquals($c."test".$c, $this->_platform->quoteIdentifier("test")); $this->assertEquals($c."test".$c.".".$c."test".$c, $this->_platform->quoteIdentifier("test.test")); $this->assertEquals(str_repeat($c, 4), $this->_platform->quoteIdentifier($c)); } /** * @group DDC-1360 */ public function testQuoteSingleIdentifier() { if ($this->_platform->getName() == "mssql") { $this->markTestSkipped('Not working this way on mssql.'); } $c = $this->_platform->getIdentifierQuoteCharacter(); $this->assertEquals($c."test".$c, $this->_platform->quoteSingleIdentifier("test")); $this->assertEquals($c."test.test".$c, $this->_platform->quoteSingleIdentifier("test.test")); $this->assertEquals(str_repeat($c, 4), $this->_platform->quoteSingleIdentifier($c)); } /** * @group DBAL-1029 * * @dataProvider getReturnsForeignKeyReferentialActionSQL */ public function testReturnsForeignKeyReferentialActionSQL($action, $expectedSQL) { $this->assertSame($expectedSQL, $this->_platform->getForeignKeyReferentialActionSQL($action)); } /** * @return array */ public function getReturnsForeignKeyReferentialActionSQL() { return array( array('CASCADE', 'CASCADE'), array('SET NULL', 'SET NULL'), array('NO ACTION', 'NO ACTION'), array('RESTRICT', 'RESTRICT'), array('SET DEFAULT', 'SET DEFAULT'), array('CaScAdE', 'CASCADE'), ); } public function testGetInvalidForeignKeyReferentialActionSQL() { $this->setExpectedException('InvalidArgumentException'); $this->_platform->getForeignKeyReferentialActionSQL('unknown'); } public function testGetUnknownDoctrineMappingType() { $this->setExpectedException('Doctrine\DBAL\DBALException'); $this->_platform->getDoctrineTypeMapping('foobar'); } public function testRegisterDoctrineMappingType() { $this->_platform->registerDoctrineTypeMapping('foo', 'integer'); $this->assertEquals('integer', $this->_platform->getDoctrineTypeMapping('foo')); } public function testRegisterUnknownDoctrineMappingType() { $this->setExpectedException('Doctrine\DBAL\DBALException'); $this->_platform->registerDoctrineTypeMapping('foo', 'bar'); } /** * @group DBAL-2594 */ public function testRegistersCommentedDoctrineMappingTypeImplicitly() { if (!Type::hasType('my_commented')) { Type::addType('my_commented', CommentedType::class); } $type = Type::getType('my_commented'); $this->_platform->registerDoctrineTypeMapping('foo', 'my_commented'); $this->assertTrue($this->_platform->isCommentedDoctrineType($type)); } /** * @group DBAL-939 * * @dataProvider getIsCommentedDoctrineType */ public function testIsCommentedDoctrineType(Type $type, $commented) { $this->assertSame($commented, $this->_platform->isCommentedDoctrineType($type)); } public function getIsCommentedDoctrineType() { $this->setUp(); $data = array(); foreach (Type::getTypesMap() as $typeName => $className) { $type = Type::getType($typeName); $data[$typeName] = array( $type, $type->requiresSQLCommentHint($this->_platform), ); } return $data; } public function testCreateWithNoColumns() { $table = new Table('test'); $this->setExpectedException('Doctrine\DBAL\DBALException'); $sql = $this->_platform->getCreateTableSQL($table); } public function testGeneratesTableCreationSql() { $table = new Table('test'); $table->addColumn('id', 'integer', array('notnull' => true, 'autoincrement' => true)); $table->addColumn('test', 'string', array('notnull' => false, 'length' => 255)); $table->setPrimaryKey(array('id')); $sql = $this->_platform->getCreateTableSQL($table); $this->assertEquals($this->getGenerateTableSql(), $sql[0]); } abstract public function getGenerateTableSql(); public function testGenerateTableWithMultiColumnUniqueIndex() { $table = new Table('test'); $table->addColumn('foo', 'string', array('notnull' => false, 'length' => 255)); $table->addColumn('bar', 'string', array('notnull' => false, 'length' => 255)); $table->addUniqueIndex(array("foo", "bar")); $sql = $this->_platform->getCreateTableSQL($table); $this->assertEquals($this->getGenerateTableWithMultiColumnUniqueIndexSql(), $sql); } abstract public function getGenerateTableWithMultiColumnUniqueIndexSql(); public function testGeneratesIndexCreationSql() { $indexDef = new \Doctrine\DBAL\Schema\Index('my_idx', array('user_name', 'last_login')); $this->assertEquals( $this->getGenerateIndexSql(), $this->_platform->getCreateIndexSQL($indexDef, 'mytable') ); } abstract public function getGenerateIndexSql(); public function testGeneratesUniqueIndexCreationSql() { $indexDef = new \Doctrine\DBAL\Schema\Index('index_name', array('test', 'test2'), true); $sql = $this->_platform->getCreateIndexSQL($indexDef, 'test'); $this->assertEquals($this->getGenerateUniqueIndexSql(), $sql); } abstract public function getGenerateUniqueIndexSql(); public function testGeneratesPartialIndexesSqlOnlyWhenSupportingPartialIndexes() { $where = 'test IS NULL AND test2 IS NOT NULL'; $indexDef = new \Doctrine\DBAL\Schema\Index('name', array('test', 'test2'), false, false, array(), array('where' => $where)); $uniqueIndex = new \Doctrine\DBAL\Schema\Index('name', array('test', 'test2'), true, false, array(), array('where' => $where)); $expected = ' WHERE ' . $where; $actuals = array(); if ($this->supportsInlineIndexDeclaration()) { $actuals []= $this->_platform->getIndexDeclarationSQL('name', $indexDef); } $actuals []= $this->_platform->getUniqueConstraintDeclarationSQL('name', $uniqueIndex); $actuals []= $this->_platform->getCreateIndexSQL($indexDef, 'table'); foreach ($actuals as $actual) { if ($this->_platform->supportsPartialIndexes()) { $this->assertStringEndsWith($expected, $actual, 'WHERE clause should be present'); } else { $this->assertStringEndsNotWith($expected, $actual, 'WHERE clause should NOT be present'); } } } public function testGeneratesForeignKeyCreationSql() { $fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('fk_name_id'), 'other_table', array('id'), ''); $sql = $this->_platform->getCreateForeignKeySQL($fk, 'test'); $this->assertEquals($sql, $this->getGenerateForeignKeySql()); } abstract public function getGenerateForeignKeySql(); public function testGeneratesConstraintCreationSql() { $idx = new \Doctrine\DBAL\Schema\Index('constraint_name', array('test'), true, false); $sql = $this->_platform->getCreateConstraintSQL($idx, 'test'); $this->assertEquals($this->getGenerateConstraintUniqueIndexSql(), $sql); $pk = new \Doctrine\DBAL\Schema\Index('constraint_name', array('test'), true, true); $sql = $this->_platform->getCreateConstraintSQL($pk, 'test'); $this->assertEquals($this->getGenerateConstraintPrimaryIndexSql(), $sql); $fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('fk_name'), 'foreign', array('id'), 'constraint_fk'); $sql = $this->_platform->getCreateConstraintSQL($fk, 'test'); $this->assertEquals($this->getGenerateConstraintForeignKeySql($fk), $sql); } public function testGeneratesForeignKeySqlOnlyWhenSupportingForeignKeys() { $fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('fk_name'), 'foreign', array('id'), 'constraint_fk'); if ($this->_platform->supportsForeignKeyConstraints()) { $this->assertInternalType( 'string', $this->_platform->getCreateForeignKeySQL($fk, 'test') ); } else { $this->setExpectedException('Doctrine\DBAL\DBALException'); $this->_platform->getCreateForeignKeySQL($fk, 'test'); } } protected function getBitAndComparisonExpressionSql($value1, $value2) { return '(' . $value1 . ' & ' . $value2 . ')'; } /** * @group DDC-1213 */ public function testGeneratesBitAndComparisonExpressionSql() { $sql = $this->_platform->getBitAndComparisonExpression(2, 4); $this->assertEquals($this->getBitAndComparisonExpressionSql(2, 4), $sql); } protected function getBitOrComparisonExpressionSql($value1, $value2) { return '(' . $value1 . ' | ' . $value2 . ')'; } /** * @group DDC-1213 */ public function testGeneratesBitOrComparisonExpressionSql() { $sql = $this->_platform->getBitOrComparisonExpression(2, 4); $this->assertEquals($this->getBitOrComparisonExpressionSql(2, 4), $sql); } public function getGenerateConstraintUniqueIndexSql() { return 'ALTER TABLE test ADD CONSTRAINT constraint_name UNIQUE (test)'; } public function getGenerateConstraintPrimaryIndexSql() { return 'ALTER TABLE test ADD CONSTRAINT constraint_name PRIMARY KEY (test)'; } public function getGenerateConstraintForeignKeySql(ForeignKeyConstraint $fk) { $quotedForeignTable = $fk->getQuotedForeignTableName($this->_platform); return "ALTER TABLE test ADD CONSTRAINT constraint_fk FOREIGN KEY (fk_name) REFERENCES $quotedForeignTable (id)"; } abstract public function getGenerateAlterTableSql(); public function testGeneratesTableAlterationSql() { $expectedSql = $this->getGenerateAlterTableSql(); $table = new Table('mytable'); $table->addColumn('id', 'integer', array('autoincrement' => true)); $table->addColumn('foo', 'integer'); $table->addColumn('bar', 'string'); $table->addColumn('bloo', 'boolean'); $table->setPrimaryKey(array('id')); $tableDiff = new TableDiff('mytable'); $tableDiff->fromTable = $table; $tableDiff->newName = 'userlist'; $tableDiff->addedColumns['quota'] = new \Doctrine\DBAL\Schema\Column('quota', \Doctrine\DBAL\Types\Type::getType('integer'), array('notnull' => false)); $tableDiff->removedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', \Doctrine\DBAL\Types\Type::getType('integer')); $tableDiff->changedColumns['bar'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'bar', new \Doctrine\DBAL\Schema\Column( 'baz', \Doctrine\DBAL\Types\Type::getType('string'), array('default' => 'def') ), array('type', 'notnull', 'default') ); $tableDiff->changedColumns['bloo'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'bloo', new \Doctrine\DBAL\Schema\Column( 'bloo', \Doctrine\DBAL\Types\Type::getType('boolean'), array('default' => false) ), array('type', 'notnull', 'default') ); $sql = $this->_platform->getAlterTableSQL($tableDiff); $this->assertEquals($expectedSql, $sql); } public function testGetCustomColumnDeclarationSql() { $field = array('columnDefinition' => 'MEDIUMINT(6) UNSIGNED'); $this->assertEquals('foo MEDIUMINT(6) UNSIGNED', $this->_platform->getColumnDeclarationSQL('foo', $field)); } public function testGetCreateTableSqlDispatchEvent() { $listenerMock = $this->getMockBuilder('GetCreateTableSqlDispatchEvenListener') ->setMethods(array('onSchemaCreateTable', 'onSchemaCreateTableColumn')) ->getMock(); $listenerMock ->expects($this->once()) ->method('onSchemaCreateTable'); $listenerMock ->expects($this->exactly(2)) ->method('onSchemaCreateTableColumn'); $eventManager = new EventManager(); $eventManager->addEventListener(array(Events::onSchemaCreateTable, Events::onSchemaCreateTableColumn), $listenerMock); $this->_platform->setEventManager($eventManager); $table = new Table('test'); $table->addColumn('foo', 'string', array('notnull' => false, 'length' => 255)); $table->addColumn('bar', 'string', array('notnull' => false, 'length' => 255)); $this->_platform->getCreateTableSQL($table); } public function testGetDropTableSqlDispatchEvent() { $listenerMock = $this->getMockBuilder('GetDropTableSqlDispatchEventListener') ->setMethods(array('onSchemaDropTable')) ->getMock(); $listenerMock ->expects($this->once()) ->method('onSchemaDropTable'); $eventManager = new EventManager(); $eventManager->addEventListener(array(Events::onSchemaDropTable), $listenerMock); $this->_platform->setEventManager($eventManager); $this->_platform->getDropTableSQL('TABLE'); } public function testGetAlterTableSqlDispatchEvent() { $events = array( 'onSchemaAlterTable', 'onSchemaAlterTableAddColumn', 'onSchemaAlterTableRemoveColumn', 'onSchemaAlterTableChangeColumn', 'onSchemaAlterTableRenameColumn' ); $listenerMock = $this->getMockBuilder('GetAlterTableSqlDispatchEvenListener') ->setMethods($events) ->getMock(); $listenerMock ->expects($this->once()) ->method('onSchemaAlterTable'); $listenerMock ->expects($this->once()) ->method('onSchemaAlterTableAddColumn'); $listenerMock ->expects($this->once()) ->method('onSchemaAlterTableRemoveColumn'); $listenerMock ->expects($this->once()) ->method('onSchemaAlterTableChangeColumn'); $listenerMock ->expects($this->once()) ->method('onSchemaAlterTableRenameColumn'); $eventManager = new EventManager(); $events = array( Events::onSchemaAlterTable, Events::onSchemaAlterTableAddColumn, Events::onSchemaAlterTableRemoveColumn, Events::onSchemaAlterTableChangeColumn, Events::onSchemaAlterTableRenameColumn ); $eventManager->addEventListener($events, $listenerMock); $this->_platform->setEventManager($eventManager); $table = new Table('mytable'); $table->addColumn('removed', 'integer'); $table->addColumn('changed', 'integer'); $table->addColumn('renamed', 'integer'); $tableDiff = new TableDiff('mytable'); $tableDiff->fromTable = $table; $tableDiff->addedColumns['added'] = new \Doctrine\DBAL\Schema\Column('added', \Doctrine\DBAL\Types\Type::getType('integer'), array()); $tableDiff->removedColumns['removed'] = new \Doctrine\DBAL\Schema\Column('removed', \Doctrine\DBAL\Types\Type::getType('integer'), array()); $tableDiff->changedColumns['changed'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'changed', new \Doctrine\DBAL\Schema\Column( 'changed2', \Doctrine\DBAL\Types\Type::getType('string'), array() ), array() ); $tableDiff->renamedColumns['renamed'] = new \Doctrine\DBAL\Schema\Column('renamed2', \Doctrine\DBAL\Types\Type::getType('integer'), array()); $this->_platform->getAlterTableSQL($tableDiff); } /** * @group DBAL-42 */ public function testCreateTableColumnComments() { $table = new Table('test'); $table->addColumn('id', 'integer', array('comment' => 'This is a comment')); $table->setPrimaryKey(array('id')); $this->assertEquals($this->getCreateTableColumnCommentsSQL(), $this->_platform->getCreateTableSQL($table)); } /** * @group DBAL-42 */ public function testAlterTableColumnComments() { $tableDiff = new TableDiff('mytable'); $tableDiff->addedColumns['quota'] = new \Doctrine\DBAL\Schema\Column('quota', \Doctrine\DBAL\Types\Type::getType('integer'), array('comment' => 'A comment')); $tableDiff->changedColumns['foo'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'foo', new \Doctrine\DBAL\Schema\Column( 'foo', \Doctrine\DBAL\Types\Type::getType('string') ), array('comment') ); $tableDiff->changedColumns['bar'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'bar', new \Doctrine\DBAL\Schema\Column( 'baz', \Doctrine\DBAL\Types\Type::getType('string'), array('comment' => 'B comment') ), array('comment') ); $this->assertEquals($this->getAlterTableColumnCommentsSQL(), $this->_platform->getAlterTableSQL($tableDiff)); } public function testCreateTableColumnTypeComments() { $table = new Table('test'); $table->addColumn('id', 'integer'); $table->addColumn('data', 'array'); $table->setPrimaryKey(array('id')); $this->assertEquals($this->getCreateTableColumnTypeCommentsSQL(), $this->_platform->getCreateTableSQL($table)); } public function getCreateTableColumnCommentsSQL() { $this->markTestSkipped('Platform does not support Column comments.'); } public function getAlterTableColumnCommentsSQL() { $this->markTestSkipped('Platform does not support Column comments.'); } public function getCreateTableColumnTypeCommentsSQL() { $this->markTestSkipped('Platform does not support Column comments.'); } public function testGetDefaultValueDeclarationSQL() { // non-timestamp value will get single quotes $field = array( 'type' => 'string', 'default' => 'non_timestamp' ); $this->assertEquals(" DEFAULT 'non_timestamp'", $this->_platform->getDefaultValueDeclarationSQL($field)); } public function testGetDefaultValueDeclarationSQLDateTime() { // timestamps on datetime types should not be quoted foreach (array('datetime', 'datetimetz') as $type) { $field = array( 'type' => Type::getType($type), 'default' => $this->_platform->getCurrentTimestampSQL() ); $this->assertEquals(' DEFAULT ' . $this->_platform->getCurrentTimestampSQL(), $this->_platform->getDefaultValueDeclarationSQL($field)); } } public function testGetDefaultValueDeclarationSQLForIntegerTypes() { foreach(array('bigint', 'integer', 'smallint') as $type) { $field = array( 'type' => Type::getType($type), 'default' => 1 ); $this->assertEquals( ' DEFAULT 1', $this->_platform->getDefaultValueDeclarationSQL($field) ); } } /** * @group DBAL-45 */ public function testKeywordList() { $keywordList = $this->_platform->getReservedKeywordsList(); $this->assertInstanceOf('Doctrine\DBAL\Platforms\Keywords\KeywordList', $keywordList); $this->assertTrue($keywordList->isKeyword('table')); } /** * @group DBAL-374 */ public function testQuotedColumnInPrimaryKeyPropagation() { $table = new Table('`quoted`'); $table->addColumn('create', 'string'); $table->setPrimaryKey(array('create')); $sql = $this->_platform->getCreateTableSQL($table); $this->assertEquals($this->getQuotedColumnInPrimaryKeySQL(), $sql); } abstract protected function getQuotedColumnInPrimaryKeySQL(); abstract protected function getQuotedColumnInIndexSQL(); abstract protected function getQuotedNameInIndexSQL(); abstract protected function getQuotedColumnInForeignKeySQL(); /** * @group DBAL-374 */ public function testQuotedColumnInIndexPropagation() { $table = new Table('`quoted`'); $table->addColumn('create', 'string'); $table->addIndex(array('create')); $sql = $this->_platform->getCreateTableSQL($table); $this->assertEquals($this->getQuotedColumnInIndexSQL(), $sql); } public function testQuotedNameInIndexSQL() { $table = new Table('test'); $table->addColumn('column1', 'string'); $table->addIndex(array('column1'), '`key`'); $sql = $this->_platform->getCreateTableSQL($table); $this->assertEquals($this->getQuotedNameInIndexSQL(), $sql); } /** * @group DBAL-374 */ public function testQuotedColumnInForeignKeyPropagation() { $table = new Table('`quoted`'); $table->addColumn('create', 'string'); $table->addColumn('foo', 'string'); $table->addColumn('`bar`', 'string'); // Foreign table with reserved keyword as name (needs quotation). $foreignTable = new Table('foreign'); $foreignTable->addColumn('create', 'string'); // Foreign column with reserved keyword as name (needs quotation). $foreignTable->addColumn('bar', 'string'); // Foreign column with non-reserved keyword as name (does not need quotation). $foreignTable->addColumn('`foo-bar`', 'string'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite). $table->addForeignKeyConstraint($foreignTable, array('create', 'foo', '`bar`'), array('create', 'bar', '`foo-bar`'), array(), 'FK_WITH_RESERVED_KEYWORD'); // Foreign table with non-reserved keyword as name (does not need quotation). $foreignTable = new Table('foo'); $foreignTable->addColumn('create', 'string'); // Foreign column with reserved keyword as name (needs quotation). $foreignTable->addColumn('bar', 'string'); // Foreign column with non-reserved keyword as name (does not need quotation). $foreignTable->addColumn('`foo-bar`', 'string'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite). $table->addForeignKeyConstraint($foreignTable, array('create', 'foo', '`bar`'), array('create', 'bar', '`foo-bar`'), array(), 'FK_WITH_NON_RESERVED_KEYWORD'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite). $foreignTable = new Table('`foo-bar`'); $foreignTable->addColumn('create', 'string'); // Foreign column with reserved keyword as name (needs quotation). $foreignTable->addColumn('bar', 'string'); // Foreign column with non-reserved keyword as name (does not need quotation). $foreignTable->addColumn('`foo-bar`', 'string'); // Foreign table with special character in name (needs quotation on some platforms, e.g. Sqlite). $table->addForeignKeyConstraint($foreignTable, array('create', 'foo', '`bar`'), array('create', 'bar', '`foo-bar`'), array(), 'FK_WITH_INTENDED_QUOTATION'); $sql = $this->_platform->getCreateTableSQL($table, AbstractPlatform::CREATE_FOREIGNKEYS); $this->assertEquals($this->getQuotedColumnInForeignKeySQL(), $sql); } /** * @group DBAL-1051 */ public function testQuotesReservedKeywordInUniqueConstraintDeclarationSQL() { $index = new Index('select', array('foo'), true); $this->assertSame( $this->getQuotesReservedKeywordInUniqueConstraintDeclarationSQL(), $this->_platform->getUniqueConstraintDeclarationSQL('select', $index) ); } /** * @return string */ abstract protected function getQuotesReservedKeywordInUniqueConstraintDeclarationSQL(); /** * @group DBAL-2270 */ public function testQuotesReservedKeywordInTruncateTableSQL() { $this->assertSame( $this->getQuotesReservedKeywordInTruncateTableSQL(), $this->_platform->getTruncateTableSQL('select') ); } /** * @return string */ abstract protected function getQuotesReservedKeywordInTruncateTableSQL(); /** * @group DBAL-1051 */ public function testQuotesReservedKeywordInIndexDeclarationSQL() { $index = new Index('select', array('foo')); if (! $this->supportsInlineIndexDeclaration()) { $this->setExpectedException('Doctrine\DBAL\DBALException'); } $this->assertSame( $this->getQuotesReservedKeywordInIndexDeclarationSQL(), $this->_platform->getIndexDeclarationSQL('select', $index) ); } /** * @return string */ abstract protected function getQuotesReservedKeywordInIndexDeclarationSQL(); /** * @return boolean */ protected function supportsInlineIndexDeclaration() { return true; } public function testSupportsCommentOnStatement() { $this->assertSame($this->supportsCommentOnStatement(), $this->_platform->supportsCommentOnStatement()); } /** * @return bool */ protected function supportsCommentOnStatement() { return false; } /** * @expectedException \Doctrine\DBAL\DBALException */ public function testGetCreateSchemaSQL() { $this->_platform->getCreateSchemaSQL('schema'); } /** * @group DBAL-585 */ public function testAlterTableChangeQuotedColumn() { $tableDiff = new \Doctrine\DBAL\Schema\TableDiff('mytable'); $tableDiff->fromTable = new \Doctrine\DBAL\Schema\Table('mytable'); $tableDiff->changedColumns['foo'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'select', new \Doctrine\DBAL\Schema\Column( 'select', \Doctrine\DBAL\Types\Type::getType('string') ), array('type') ); $this->assertContains( $this->_platform->quoteIdentifier('select'), implode(';', $this->_platform->getAlterTableSQL($tableDiff)) ); } /** * @group DBAL-563 */ public function testUsesSequenceEmulatedIdentityColumns() { $this->assertFalse($this->_platform->usesSequenceEmulatedIdentityColumns()); } /** * @group DBAL-563 * @expectedException \Doctrine\DBAL\DBALException */ public function testReturnsIdentitySequenceName() { $this->_platform->getIdentitySequenceName('mytable', 'mycolumn'); } public function testReturnsBinaryDefaultLength() { $this->assertSame($this->getBinaryDefaultLength(), $this->_platform->getBinaryDefaultLength()); } protected function getBinaryDefaultLength() { return 255; } public function testReturnsBinaryMaxLength() { $this->assertSame($this->getBinaryMaxLength(), $this->_platform->getBinaryMaxLength()); } protected function getBinaryMaxLength() { return 4000; } /** * @expectedException \Doctrine\DBAL\DBALException */ public function testReturnsBinaryTypeDeclarationSQL() { $this->_platform->getBinaryTypeDeclarationSQL(array()); } /** * @group DBAL-553 */ public function hasNativeJsonType() { $this->assertFalse($this->_platform->hasNativeJsonType()); } /** * @group DBAL-553 */ public function testReturnsJsonTypeDeclarationSQL() { $column = array( 'length' => 666, 'notnull' => true, 'type' => Type::getType('json_array'), ); $this->assertSame( $this->_platform->getClobTypeDeclarationSQL($column), $this->_platform->getJsonTypeDeclarationSQL($column) ); } /** * @group DBAL-234 */ public function testAlterTableRenameIndex() { $tableDiff = new TableDiff('mytable'); $tableDiff->fromTable = new Table('mytable'); $tableDiff->fromTable->addColumn('id', 'integer'); $tableDiff->fromTable->setPrimaryKey(array('id')); $tableDiff->renamedIndexes = array( 'idx_foo' => new Index('idx_bar', array('id')) ); $this->assertSame( $this->getAlterTableRenameIndexSQL(), $this->_platform->getAlterTableSQL($tableDiff) ); } /** * @group DBAL-234 */ protected function getAlterTableRenameIndexSQL() { return array( 'DROP INDEX idx_foo', 'CREATE INDEX idx_bar ON mytable (id)', ); } /** * @group DBAL-234 */ public function testQuotesAlterTableRenameIndex() { $tableDiff = new TableDiff('table'); $tableDiff->fromTable = new Table('table'); $tableDiff->fromTable->addColumn('id', 'integer'); $tableDiff->fromTable->setPrimaryKey(array('id')); $tableDiff->renamedIndexes = array( 'create' => new Index('select', array('id')), '`foo`' => new Index('`bar`', array('id')), ); $this->assertSame( $this->getQuotedAlterTableRenameIndexSQL(), $this->_platform->getAlterTableSQL($tableDiff) ); } /** * @group DBAL-234 */ protected function getQuotedAlterTableRenameIndexSQL() { return array( 'DROP INDEX "create"', 'CREATE INDEX "select" ON "table" (id)', 'DROP INDEX "foo"', 'CREATE INDEX "bar" ON "table" (id)', ); } /** * @group DBAL-835 */ public function testQuotesAlterTableRenameColumn() { $fromTable = new Table('mytable'); $fromTable->addColumn('unquoted1', 'integer', array('comment' => 'Unquoted 1')); $fromTable->addColumn('unquoted2', 'integer', array('comment' => 'Unquoted 2')); $fromTable->addColumn('unquoted3', 'integer', array('comment' => 'Unquoted 3')); $fromTable->addColumn('create', 'integer', array('comment' => 'Reserved keyword 1')); $fromTable->addColumn('table', 'integer', array('comment' => 'Reserved keyword 2')); $fromTable->addColumn('select', 'integer', array('comment' => 'Reserved keyword 3')); $fromTable->addColumn('`quoted1`', 'integer', array('comment' => 'Quoted 1')); $fromTable->addColumn('`quoted2`', 'integer', array('comment' => 'Quoted 2')); $fromTable->addColumn('`quoted3`', 'integer', array('comment' => 'Quoted 3')); $toTable = new Table('mytable'); $toTable->addColumn('unquoted', 'integer', array('comment' => 'Unquoted 1')); // unquoted -> unquoted $toTable->addColumn('where', 'integer', array('comment' => 'Unquoted 2')); // unquoted -> reserved keyword $toTable->addColumn('`foo`', 'integer', array('comment' => 'Unquoted 3')); // unquoted -> quoted $toTable->addColumn('reserved_keyword', 'integer', array('comment' => 'Reserved keyword 1')); // reserved keyword -> unquoted $toTable->addColumn('from', 'integer', array('comment' => 'Reserved keyword 2')); // reserved keyword -> reserved keyword $toTable->addColumn('`bar`', 'integer', array('comment' => 'Reserved keyword 3')); // reserved keyword -> quoted $toTable->addColumn('quoted', 'integer', array('comment' => 'Quoted 1')); // quoted -> unquoted $toTable->addColumn('and', 'integer', array('comment' => 'Quoted 2')); // quoted -> reserved keyword $toTable->addColumn('`baz`', 'integer', array('comment' => 'Quoted 3')); // quoted -> quoted $comparator = new Comparator(); $this->assertEquals( $this->getQuotedAlterTableRenameColumnSQL(), $this->_platform->getAlterTableSQL($comparator->diffTable($fromTable, $toTable)) ); } /** * Returns SQL statements for {@link testQuotesAlterTableRenameColumn}. * * @return array * * @group DBAL-835 */ abstract protected function getQuotedAlterTableRenameColumnSQL(); /** * @group DBAL-835 */ public function testQuotesAlterTableChangeColumnLength() { $fromTable = new Table('mytable'); $fromTable->addColumn('unquoted1', 'string', array('comment' => 'Unquoted 1', 'length' => 10)); $fromTable->addColumn('unquoted2', 'string', array('comment' => 'Unquoted 2', 'length' => 10)); $fromTable->addColumn('unquoted3', 'string', array('comment' => 'Unquoted 3', 'length' => 10)); $fromTable->addColumn('create', 'string', array('comment' => 'Reserved keyword 1', 'length' => 10)); $fromTable->addColumn('table', 'string', array('comment' => 'Reserved keyword 2', 'length' => 10)); $fromTable->addColumn('select', 'string', array('comment' => 'Reserved keyword 3', 'length' => 10)); $toTable = new Table('mytable'); $toTable->addColumn('unquoted1', 'string', array('comment' => 'Unquoted 1', 'length' => 255)); $toTable->addColumn('unquoted2', 'string', array('comment' => 'Unquoted 2', 'length' => 255)); $toTable->addColumn('unquoted3', 'string', array('comment' => 'Unquoted 3', 'length' => 255)); $toTable->addColumn('create', 'string', array('comment' => 'Reserved keyword 1', 'length' => 255)); $toTable->addColumn('table', 'string', array('comment' => 'Reserved keyword 2', 'length' => 255)); $toTable->addColumn('select', 'string', array('comment' => 'Reserved keyword 3', 'length' => 255)); $comparator = new Comparator(); $this->assertEquals( $this->getQuotedAlterTableChangeColumnLengthSQL(), $this->_platform->getAlterTableSQL($comparator->diffTable($fromTable, $toTable)) ); } /** * Returns SQL statements for {@link testQuotesAlterTableChangeColumnLength}. * * @return array * * @group DBAL-835 */ abstract protected function getQuotedAlterTableChangeColumnLengthSQL(); /** * @group DBAL-807 */ public function testAlterTableRenameIndexInSchema() { $tableDiff = new TableDiff('myschema.mytable'); $tableDiff->fromTable = new Table('myschema.mytable'); $tableDiff->fromTable->addColumn('id', 'integer'); $tableDiff->fromTable->setPrimaryKey(array('id')); $tableDiff->renamedIndexes = array( 'idx_foo' => new Index('idx_bar', array('id')) ); $this->assertSame( $this->getAlterTableRenameIndexInSchemaSQL(), $this->_platform->getAlterTableSQL($tableDiff) ); } /** * @group DBAL-807 */ protected function getAlterTableRenameIndexInSchemaSQL() { return array( 'DROP INDEX idx_foo', 'CREATE INDEX idx_bar ON myschema.mytable (id)', ); } /** * @group DBAL-807 */ public function testQuotesAlterTableRenameIndexInSchema() { $tableDiff = new TableDiff('`schema`.table'); $tableDiff->fromTable = new Table('`schema`.table'); $tableDiff->fromTable->addColumn('id', 'integer'); $tableDiff->fromTable->setPrimaryKey(array('id')); $tableDiff->renamedIndexes = array( 'create' => new Index('select', array('id')), '`foo`' => new Index('`bar`', array('id')), ); $this->assertSame( $this->getQuotedAlterTableRenameIndexInSchemaSQL(), $this->_platform->getAlterTableSQL($tableDiff) ); } /** * @group DBAL-234 */ protected function getQuotedAlterTableRenameIndexInSchemaSQL() { return array( 'DROP INDEX "schema"."create"', 'CREATE INDEX "select" ON "schema"."table" (id)', 'DROP INDEX "schema"."foo"', 'CREATE INDEX "bar" ON "schema"."table" (id)', ); } /** * @group DBAL-1237 */ public function testQuotesDropForeignKeySQL() { if (! $this->_platform->supportsForeignKeyConstraints()) { $this->markTestSkipped( sprintf('%s does not support foreign key constraints.', get_class($this->_platform)) ); } $tableName = 'table'; $table = new Table($tableName); $foreignKeyName = 'select'; $foreignKey = new ForeignKeyConstraint(array(), 'foo', array(), 'select'); $expectedSql = $this->getQuotesDropForeignKeySQL(); $this->assertSame($expectedSql, $this->_platform->getDropForeignKeySQL($foreignKeyName, $tableName)); $this->assertSame($expectedSql, $this->_platform->getDropForeignKeySQL($foreignKey, $table)); } protected function getQuotesDropForeignKeySQL() { return 'ALTER TABLE "table" DROP FOREIGN KEY "select"'; } /** * @group DBAL-1237 */ public function testQuotesDropConstraintSQL() { $tableName = 'table'; $table = new Table($tableName); $constraintName = 'select'; $constraint = new ForeignKeyConstraint(array(), 'foo', array(), 'select'); $expectedSql = $this->getQuotesDropConstraintSQL(); $this->assertSame($expectedSql, $this->_platform->getDropConstraintSQL($constraintName, $tableName)); $this->assertSame($expectedSql, $this->_platform->getDropConstraintSQL($constraint, $table)); } protected function getQuotesDropConstraintSQL() { return 'ALTER TABLE "table" DROP CONSTRAINT "select"'; } protected function getStringLiteralQuoteCharacter() { return "'"; } public function testGetStringLiteralQuoteCharacter() { $this->assertSame($this->getStringLiteralQuoteCharacter(), $this->_platform->getStringLiteralQuoteCharacter()); } protected function getQuotedCommentOnColumnSQLWithoutQuoteCharacter() { return "COMMENT ON COLUMN mytable.id IS 'This is a comment'"; } public function testGetCommentOnColumnSQLWithoutQuoteCharacter() { $this->assertEquals( $this->getQuotedCommentOnColumnSQLWithoutQuoteCharacter(), $this->_platform->getCommentOnColumnSQL('mytable', 'id', 'This is a comment') ); } protected function getQuotedCommentOnColumnSQLWithQuoteCharacter() { return "COMMENT ON COLUMN mytable.id IS 'It''s a quote !'"; } public function testGetCommentOnColumnSQLWithQuoteCharacter() { $c = $this->getStringLiteralQuoteCharacter(); $this->assertEquals( $this->getQuotedCommentOnColumnSQLWithQuoteCharacter(), $this->_platform->getCommentOnColumnSQL('mytable', 'id', "It" . $c . "s a quote !") ); } /** * @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 ) ); } /** * @group DBAL-1176 * * @dataProvider getGeneratesInlineColumnCommentSQL */ public function testGeneratesInlineColumnCommentSQL($comment, $expectedSql) { if (! $this->_platform->supportsInlineColumnComments()) { $this->markTestSkipped(sprintf('%s does not support inline column comments.', get_class($this->_platform))); } $this->assertSame($expectedSql, $this->_platform->getInlineColumnCommentSQL($comment)); } public function getGeneratesInlineColumnCommentSQL() { return array( 'regular comment' => array('Regular comment', $this->getInlineColumnRegularCommentSQL()), 'comment requiring escaping' => array( sprintf( 'Using inline comment delimiter %s works', $this->getInlineColumnCommentDelimiter() ), $this->getInlineColumnCommentRequiringEscapingSQL() ), 'empty comment' => array('', $this->getInlineColumnEmptyCommentSQL()), ); } protected function getInlineColumnCommentDelimiter() { return "'"; } protected function getInlineColumnRegularCommentSQL() { return "COMMENT 'Regular comment'"; } protected function getInlineColumnCommentRequiringEscapingSQL() { return "COMMENT 'Using inline comment delimiter '' works'"; } protected function getInlineColumnEmptyCommentSQL() { return "COMMENT ''"; } protected function getQuotedStringLiteralWithoutQuoteCharacter() { return "'No quote'"; } protected function getQuotedStringLiteralWithQuoteCharacter() { return "'It''s a quote'"; } protected function getQuotedStringLiteralQuoteCharacter() { return "''''"; } /** * @group DBAL-1176 */ public function testThrowsExceptionOnGeneratingInlineColumnCommentSQLIfUnsupported() { if ($this->_platform->supportsInlineColumnComments()) { $this->markTestSkipped(sprintf('%s supports inline column comments.', get_class($this->_platform))); } $this->setExpectedException( 'Doctrine\DBAL\DBALException', "Operation 'Doctrine\\DBAL\\Platforms\\AbstractPlatform::getInlineColumnCommentSQL' is not supported by platform.", 0 ); $this->_platform->getInlineColumnCommentSQL('unsupported'); } public function testQuoteStringLiteral() { $c = $this->getStringLiteralQuoteCharacter(); $this->assertEquals( $this->getQuotedStringLiteralWithoutQuoteCharacter(), $this->_platform->quoteStringLiteral('No quote') ); $this->assertEquals( $this->getQuotedStringLiteralWithQuoteCharacter(), $this->_platform->quoteStringLiteral('It' . $c . 's a quote') ); $this->assertEquals( $this->getQuotedStringLiteralQuoteCharacter(), $this->_platform->quoteStringLiteral($c) ); } /** * @group DBAL-423 * * @expectedException \Doctrine\DBAL\DBALException */ public function testReturnsGuidTypeDeclarationSQL() { $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(); /** * @group DBAL-1090 */ public function testAlterStringToFixedString() { $table = new Table('mytable'); $table->addColumn('name', 'string', array('length' => 2)); $tableDiff = new TableDiff('mytable'); $tableDiff->fromTable = $table; $tableDiff->changedColumns['name'] = new \Doctrine\DBAL\Schema\ColumnDiff( 'name', new \Doctrine\DBAL\Schema\Column( 'name', \Doctrine\DBAL\Types\Type::getType('string'), array('fixed' => true, 'length' => 2) ), array('fixed') ); $sql = $this->_platform->getAlterTableSQL($tableDiff); $expectedSql = $this->getAlterStringToFixedStringSQL(); $this->assertEquals($expectedSql, $sql); } /** * @return array */ abstract protected function getAlterStringToFixedStringSQL(); /** * @group DBAL-1062 */ public function testGeneratesAlterTableRenameIndexUsedByForeignKeySQL() { $foreignTable = new Table('foreign_table'); $foreignTable->addColumn('id', 'integer'); $foreignTable->setPrimaryKey(array('id')); $primaryTable = new Table('mytable'); $primaryTable->addColumn('foo', 'integer'); $primaryTable->addColumn('bar', 'integer'); $primaryTable->addColumn('baz', 'integer'); $primaryTable->addIndex(array('foo'), 'idx_foo'); $primaryTable->addIndex(array('bar'), 'idx_bar'); $primaryTable->addForeignKeyConstraint($foreignTable, array('foo'), array('id'), array(), 'fk_foo'); $primaryTable->addForeignKeyConstraint($foreignTable, array('bar'), array('id'), array(), 'fk_bar'); $tableDiff = new TableDiff('mytable'); $tableDiff->fromTable = $primaryTable; $tableDiff->renamedIndexes['idx_foo'] = new Index('idx_foo_renamed', array('foo')); $this->assertSame( $this->getGeneratesAlterTableRenameIndexUsedByForeignKeySQL(), $this->_platform->getAlterTableSQL($tableDiff) ); } /** * @return array */ abstract protected function getGeneratesAlterTableRenameIndexUsedByForeignKeySQL(); /** * @group DBAL-1082 * * @dataProvider getGeneratesDecimalTypeDeclarationSQL */ public function testGeneratesDecimalTypeDeclarationSQL(array $column, $expectedSql) { $this->assertSame($expectedSql, $this->_platform->getDecimalTypeDeclarationSQL($column)); } /** * @return array */ public function getGeneratesDecimalTypeDeclarationSQL() { return array( array(array(), 'NUMERIC(10, 0)'), array(array('unsigned' => true), 'NUMERIC(10, 0)'), array(array('unsigned' => false), 'NUMERIC(10, 0)'), array(array('precision' => 5), 'NUMERIC(5, 0)'), array(array('scale' => 5), 'NUMERIC(10, 5)'), array(array('precision' => 8, 'scale' => 2), 'NUMERIC(8, 2)'), ); } /** * @group DBAL-1082 * * @dataProvider getGeneratesFloatDeclarationSQL */ public function testGeneratesFloatDeclarationSQL(array $column, $expectedSql) { $this->assertSame($expectedSql, $this->_platform->getFloatDeclarationSQL($column)); } /** * @return array */ public function getGeneratesFloatDeclarationSQL() { return array( array(array(), 'DOUBLE PRECISION'), array(array('unsigned' => true), 'DOUBLE PRECISION'), array(array('unsigned' => false), 'DOUBLE PRECISION'), array(array('precision' => 5), 'DOUBLE PRECISION'), array(array('scale' => 5), 'DOUBLE PRECISION'), array(array('precision' => 8, 'scale' => 2), 'DOUBLE PRECISION'), ); } }