3 namespace Doctrine\Tests\DBAL\Functional\Schema;
5 use Doctrine\DBAL\Schema;
6 use Doctrine\DBAL\Types\Type;
7 use Doctrine\DBAL\Platforms\AbstractPlatform;
9 require_once __DIR__ . '/../../../TestInit.php';
11 class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
13 public function tearDown()
21 $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression(null);
27 public function testGetSearchPath()
29 $params = $this->_conn->getParams();
31 $paths = $this->_sm->getSchemaSearchPaths();
32 $this->assertEquals(array($params['user'], 'public'), $paths);
38 public function testGetSchemaNames()
40 $names = $this->_sm->getSchemaNames();
42 $this->assertInternalType('array', $names);
43 $this->assertTrue(count($names) > 0);
44 $this->assertTrue(in_array('public', $names), "The public schema should be found.");
50 public function testSupportDomainTypeFallback()
52 $createDomainTypeSQL = "CREATE DOMAIN MyMoney AS DECIMAL(18,2)";
53 $this->_conn->exec($createDomainTypeSQL);
55 $createTableSQL = "CREATE TABLE domain_type_test (id INT PRIMARY KEY, value MyMoney)";
56 $this->_conn->exec($createTableSQL);
58 $table = $this->_conn->getSchemaManager()->listTableDetails('domain_type_test');
59 $this->assertInstanceOf('Doctrine\DBAL\Types\DecimalType', $table->getColumn('value')->getType());
61 Type::addType('MyMoney', 'Doctrine\Tests\DBAL\Functional\Schema\MoneyType');
62 $this->_conn->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'MyMoney');
64 $table = $this->_conn->getSchemaManager()->listTableDetails('domain_type_test');
65 $this->assertInstanceOf('Doctrine\Tests\DBAL\Functional\Schema\MoneyType', $table->getColumn('value')->getType());
71 public function testDetectsAutoIncrement()
73 $autoincTable = new \Doctrine\DBAL\Schema\Table('autoinc_table');
74 $column = $autoincTable->addColumn('id', 'integer');
75 $column->setAutoincrement(true);
76 $this->_sm->createTable($autoincTable);
77 $autoincTable = $this->_sm->listTableDetails('autoinc_table');
79 $this->assertTrue($autoincTable->getColumn('id')->getAutoincrement());
85 public function testAlterTableAutoIncrementAdd()
87 $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_add');
88 $column = $tableFrom->addColumn('id', 'integer');
89 $this->_sm->createTable($tableFrom);
90 $tableFrom = $this->_sm->listTableDetails('autoinc_table_add');
91 $this->assertFalse($tableFrom->getColumn('id')->getAutoincrement());
93 $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_add');
94 $column = $tableTo->addColumn('id', 'integer');
95 $column->setAutoincrement(true);
97 $c = new \Doctrine\DBAL\Schema\Comparator();
98 $diff = $c->diffTable($tableFrom, $tableTo);
99 $sql = $this->_conn->getDatabasePlatform()->getAlterTableSQL($diff);
100 $this->assertEquals(array(
101 "CREATE SEQUENCE autoinc_table_add_id_seq",
102 "SELECT setval('autoinc_table_add_id_seq', (SELECT MAX(id) FROM autoinc_table_add))",
103 "ALTER TABLE autoinc_table_add ALTER id SET DEFAULT nextval('autoinc_table_add_id_seq')",
106 $this->_sm->alterTable($diff);
107 $tableFinal = $this->_sm->listTableDetails('autoinc_table_add');
108 $this->assertTrue($tableFinal->getColumn('id')->getAutoincrement());
114 public function testAlterTableAutoIncrementDrop()
116 $tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_drop');
117 $column = $tableFrom->addColumn('id', 'integer');
118 $column->setAutoincrement(true);
119 $this->_sm->createTable($tableFrom);
120 $tableFrom = $this->_sm->listTableDetails('autoinc_table_drop');
121 $this->assertTrue($tableFrom->getColumn('id')->getAutoincrement());
123 $tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_drop');
124 $column = $tableTo->addColumn('id', 'integer');
126 $c = new \Doctrine\DBAL\Schema\Comparator();
127 $diff = $c->diffTable($tableFrom, $tableTo);
128 $this->assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
129 $this->assertEquals(array("ALTER TABLE autoinc_table_drop ALTER id DROP DEFAULT"), $this->_conn->getDatabasePlatform()->getAlterTableSQL($diff));
131 $this->_sm->alterTable($diff);
132 $tableFinal = $this->_sm->listTableDetails('autoinc_table_drop');
133 $this->assertFalse($tableFinal->getColumn('id')->getAutoincrement());
139 public function testTableWithSchema()
141 $this->_conn->exec('CREATE SCHEMA nested');
143 $nestedRelatedTable = new \Doctrine\DBAL\Schema\Table('nested.schemarelated');
144 $column = $nestedRelatedTable->addColumn('id', 'integer');
145 $column->setAutoincrement(true);
146 $nestedRelatedTable->setPrimaryKey(array('id'));
148 $nestedSchemaTable = new \Doctrine\DBAL\Schema\Table('nested.schematable');
149 $column = $nestedSchemaTable->addColumn('id', 'integer');
150 $column->setAutoincrement(true);
151 $nestedSchemaTable->setPrimaryKey(array('id'));
152 $nestedSchemaTable->addUnnamedForeignKeyConstraint($nestedRelatedTable, array('id'), array('id'));
154 $this->_sm->createTable($nestedRelatedTable);
155 $this->_sm->createTable($nestedSchemaTable);
157 $tables = $this->_sm->listTableNames();
158 $this->assertContains('nested.schematable', $tables, "The table should be detected with its non-public schema.");
160 $nestedSchemaTable = $this->_sm->listTableDetails('nested.schematable');
161 $this->assertTrue($nestedSchemaTable->hasColumn('id'));
162 $this->assertEquals(array('id'), $nestedSchemaTable->getPrimaryKey()->getColumns());
164 $relatedFks = $nestedSchemaTable->getForeignKeys();
165 $this->assertEquals(1, count($relatedFks));
166 $relatedFk = array_pop($relatedFks);
167 $this->assertEquals("nested.schemarelated", $relatedFk->getForeignTableName());
174 public function testReturnQuotedAssets()
176 $sql = 'create table dbal91_something ( id integer CONSTRAINT id_something PRIMARY KEY NOT NULL ,"table" integer );';
177 $this->_conn->exec($sql);
179 $sql = 'ALTER TABLE dbal91_something ADD CONSTRAINT something_input FOREIGN KEY( "table" ) REFERENCES dbal91_something ON UPDATE CASCADE;';
180 $this->_conn->exec($sql);
182 $table = $this->_sm->listTableDetails('dbal91_something');
186 "CREATE TABLE dbal91_something (id INT NOT NULL, \"table\" INT DEFAULT NULL, PRIMARY KEY(id))",
187 "CREATE INDEX IDX_A9401304ECA7352B ON dbal91_something (\"table\")",
189 $this->_conn->getDatabasePlatform()->getCreateTableSQL($table)
196 public function testFilterSchemaExpression()
198 $testTable = new \Doctrine\DBAL\Schema\Table('dbal204_test_prefix');
199 $column = $testTable->addColumn('id', 'integer');
200 $this->_sm->createTable($testTable);
201 $testTable = new \Doctrine\DBAL\Schema\Table('dbal204_without_prefix');
202 $column = $testTable->addColumn('id', 'integer');
203 $this->_sm->createTable($testTable);
205 $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_#');
206 $names = $this->_sm->listTableNames();
207 $this->assertEquals(2, count($names));
209 $this->_conn->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_test#');
210 $names = $this->_sm->listTableNames();
211 $this->assertEquals(1, count($names));
214 public function testListForeignKeys()
216 if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
217 $this->markTestSkipped('Does not support foreign key constraints.');
220 $fkOptions = array('SET NULL', 'SET DEFAULT', 'NO ACTION','CASCADE', 'RESTRICT');
221 $foreignKeys = array();
222 $fkTable = $this->getTestTable('test_create_fk1');
223 for($i = 0; $i < count($fkOptions); $i++) {
224 $fkTable->addColumn("foreign_key_test$i", 'integer');
225 $foreignKeys[] = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
226 array("foreign_key_test$i"), 'test_create_fk2', array('id'), "foreign_key_test_$i"."_fk", array('onDelete' => $fkOptions[$i]));
228 $this->_sm->dropAndCreateTable($fkTable);
229 $this->createTestTable('test_create_fk2');
231 foreach($foreignKeys as $foreignKey) {
232 $this->_sm->createForeignKey($foreignKey, 'test_create_fk1');
234 $fkeys = $this->_sm->listTableForeignKeys('test_create_fk1');
235 $this->assertEquals(count($foreignKeys), count($fkeys), "Table 'test_create_fk1' has to have " . count($foreignKeys) . " foreign keys.");
236 for ($i = 0; $i < count($fkeys); $i++) {
237 $this->assertEquals(array("foreign_key_test$i"), array_map('strtolower', $fkeys[$i]->getLocalColumns()));
238 $this->assertEquals(array('id'), array_map('strtolower', $fkeys[$i]->getForeignColumns()));
239 $this->assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
240 if ($foreignKeys[$i]->getOption('onDelete') == 'NO ACTION') {
241 $this->assertFalse($fkeys[$i]->hasOption('onDelete'), 'Unexpected option: '. $fkeys[$i]->getOption('onDelete'));
243 $this->assertEquals($foreignKeys[$i]->getOption('onDelete'), $fkeys[$i]->getOption('onDelete'));
249 class MoneyType extends Type
252 public function getName()
257 public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)