1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Doctrine\Tests\DBAL\Functional\Schema; |
4
|
|
|
|
5
|
|
|
use Doctrine\Common\EventManager; |
6
|
|
|
use Doctrine\DBAL\DBALException; |
7
|
|
|
use Doctrine\DBAL\Driver\Connection; |
8
|
|
|
use Doctrine\DBAL\Events; |
9
|
|
|
use Doctrine\DBAL\Platforms\OraclePlatform; |
10
|
|
|
use Doctrine\DBAL\Schema\AbstractAsset; |
11
|
|
|
use Doctrine\DBAL\Schema\AbstractSchemaManager; |
12
|
|
|
use Doctrine\DBAL\Schema\Column; |
13
|
|
|
use Doctrine\DBAL\Schema\ColumnDiff; |
14
|
|
|
use Doctrine\DBAL\Schema\Comparator; |
15
|
|
|
use Doctrine\DBAL\Schema\ForeignKeyConstraint; |
16
|
|
|
use Doctrine\DBAL\Schema\Index; |
17
|
|
|
use Doctrine\DBAL\Schema\SchemaDiff; |
18
|
|
|
use Doctrine\DBAL\Schema\Sequence; |
19
|
|
|
use Doctrine\DBAL\Schema\Table; |
20
|
|
|
use Doctrine\DBAL\Schema\TableDiff; |
21
|
|
|
use Doctrine\DBAL\Schema\View; |
22
|
|
|
use Doctrine\DBAL\Types\ArrayType; |
23
|
|
|
use Doctrine\DBAL\Types\BinaryType; |
24
|
|
|
use Doctrine\DBAL\Types\DateIntervalType; |
25
|
|
|
use Doctrine\DBAL\Types\DateTimeType; |
26
|
|
|
use Doctrine\DBAL\Types\DecimalType; |
27
|
|
|
use Doctrine\DBAL\Types\IntegerType; |
28
|
|
|
use Doctrine\DBAL\Types\ObjectType; |
29
|
|
|
use Doctrine\DBAL\Types\StringType; |
30
|
|
|
use Doctrine\DBAL\Types\TextType; |
31
|
|
|
use Doctrine\DBAL\Types\Type; |
32
|
|
|
use Doctrine\Tests\DbalFunctionalTestCase; |
33
|
|
|
use function array_filter; |
34
|
|
|
use function array_keys; |
35
|
|
|
use function array_map; |
36
|
|
|
use function array_search; |
37
|
|
|
use function array_values; |
38
|
|
|
use function count; |
39
|
|
|
use function current; |
40
|
|
|
use function end; |
41
|
|
|
use function explode; |
42
|
|
|
use function in_array; |
43
|
|
|
use function sprintf; |
44
|
|
|
use function str_replace; |
45
|
|
|
use function strcasecmp; |
46
|
|
|
use function strlen; |
47
|
|
|
use function strtolower; |
48
|
|
|
use function substr; |
49
|
|
|
|
50
|
|
|
abstract class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase |
51
|
|
|
{ |
52
|
|
|
/** @var AbstractSchemaManager */ |
53
|
|
|
protected $schemaManager; |
54
|
|
|
|
55
|
|
|
protected function getPlatformName() : string |
56
|
|
|
{ |
57
|
|
|
$class = static::class; |
58
|
|
|
$e = explode('\\', $class); |
59
|
|
|
$testClass = end($e); |
60
|
|
|
|
61
|
|
|
return strtolower(str_replace('SchemaManagerTest', null, $testClass)); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
protected function setUp() : void |
65
|
|
|
{ |
66
|
|
|
parent::setUp(); |
67
|
|
|
|
68
|
|
|
$dbms = $this->getPlatformName(); |
69
|
|
|
|
70
|
|
|
if ($this->connection->getDatabasePlatform()->getName() !== $dbms) { |
71
|
|
|
$this->markTestSkipped(static::class . ' requires the use of ' . $dbms); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
$this->schemaManager = $this->connection->getSchemaManager(); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
protected function tearDown() : void |
78
|
|
|
{ |
79
|
|
|
parent::tearDown(); |
80
|
|
|
|
81
|
|
|
$this->schemaManager->tryMethod('dropTable', 'testschema.my_table_in_namespace'); |
82
|
|
|
|
83
|
|
|
//TODO: SchemaDiff does not drop removed namespaces? |
84
|
|
|
try { |
85
|
|
|
//sql server versions below 2016 do not support 'IF EXISTS' so we have to catch the exception here |
86
|
|
|
$this->connection->exec('DROP SCHEMA testschema'); |
87
|
|
|
} catch (DBALException $e) { |
88
|
|
|
return; |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @group DBAL-1220 |
94
|
|
|
*/ |
95
|
|
|
public function testDropsDatabaseWithActiveConnections() : void |
96
|
|
|
{ |
97
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsCreateDropDatabase()) { |
98
|
|
|
$this->markTestSkipped('Cannot drop Database client side with this Driver.'); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
$this->schemaManager->dropAndCreateDatabase('test_drop_database'); |
102
|
|
|
|
103
|
|
|
$knownDatabases = $this->schemaManager->listDatabases(); |
104
|
|
|
if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { |
105
|
|
|
self::assertContains('TEST_DROP_DATABASE', $knownDatabases); |
106
|
|
|
} else { |
107
|
|
|
self::assertContains('test_drop_database', $knownDatabases); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$params = $this->connection->getParams(); |
111
|
|
|
if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { |
112
|
|
|
$params['user'] = 'test_drop_database'; |
113
|
|
|
} else { |
114
|
|
|
$params['dbname'] = 'test_drop_database'; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$user = $params['user'] ?? null; |
118
|
|
|
$password = $params['password'] ?? null; |
119
|
|
|
|
120
|
|
|
$connection = $this->connection->getDriver()->connect($params, $user, $password); |
121
|
|
|
|
122
|
|
|
self::assertInstanceOf(Connection::class, $connection); |
123
|
|
|
|
124
|
|
|
$this->schemaManager->dropDatabase('test_drop_database'); |
125
|
|
|
|
126
|
|
|
self::assertNotContains('test_drop_database', $this->schemaManager->listDatabases()); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @group DBAL-195 |
131
|
|
|
*/ |
132
|
|
|
public function testDropAndCreateSequence() : void |
133
|
|
|
{ |
134
|
|
|
$platform = $this->connection->getDatabasePlatform(); |
135
|
|
|
|
136
|
|
|
if (! $platform->supportsSequences()) { |
137
|
|
|
$this->markTestSkipped( |
138
|
|
|
sprintf('The "%s" platform does not support sequences.', $platform->getName()) |
139
|
|
|
); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
$name = 'dropcreate_sequences_test_seq'; |
143
|
|
|
|
144
|
|
|
$this->schemaManager->dropAndCreateSequence(new Sequence($name, 20, 10)); |
145
|
|
|
|
146
|
|
|
self::assertTrue($this->hasElementWithName($this->schemaManager->listSequences(), $name)); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* @param AbstractAsset[] $items |
151
|
|
|
*/ |
152
|
|
|
private function hasElementWithName(array $items, string $name) : bool |
153
|
|
|
{ |
154
|
|
|
$filteredList = array_filter( |
155
|
|
|
$items, |
156
|
|
|
static function (AbstractAsset $item) use ($name) : bool { |
157
|
|
|
return $item->getShortestName($item->getNamespaceName()) === $name; |
158
|
|
|
} |
159
|
|
|
); |
160
|
|
|
|
161
|
|
|
return count($filteredList) === 1; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
public function testListSequences() : void |
165
|
|
|
{ |
166
|
|
|
$platform = $this->connection->getDatabasePlatform(); |
167
|
|
|
|
168
|
|
|
if (! $platform->supportsSequences()) { |
169
|
|
|
$this->markTestSkipped( |
170
|
|
|
sprintf('The "%s" platform does not support sequences.', $platform->getName()) |
171
|
|
|
); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
$sequence = new Sequence('list_sequences_test_seq', 20, 10); |
175
|
|
|
$this->schemaManager->createSequence($sequence); |
176
|
|
|
|
177
|
|
|
$sequences = $this->schemaManager->listSequences(); |
178
|
|
|
|
179
|
|
|
self::assertIsArray($sequences, 'listSequences() should return an array.'); |
180
|
|
|
|
181
|
|
|
$foundSequence = null; |
182
|
|
|
foreach ($sequences as $sequence) { |
183
|
|
|
self::assertInstanceOf(Sequence::class, $sequence, 'Array elements of listSequences() should be Sequence instances.'); |
184
|
|
|
if (strtolower($sequence->getName()) !== 'list_sequences_test_seq') { |
185
|
|
|
continue; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
$foundSequence = $sequence; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
self::assertNotNull($foundSequence, "Sequence with name 'list_sequences_test_seq' was not found."); |
192
|
|
|
self::assertSame(20, $foundSequence->getAllocationSize(), 'Allocation Size is expected to be 20.'); |
193
|
|
|
self::assertSame(10, $foundSequence->getInitialValue(), 'Initial Value is expected to be 10.'); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
public function testListDatabases() : void |
197
|
|
|
{ |
198
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsCreateDropDatabase()) { |
199
|
|
|
$this->markTestSkipped('Cannot drop Database client side with this Driver.'); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
$this->schemaManager->dropAndCreateDatabase('test_create_database'); |
203
|
|
|
$databases = $this->schemaManager->listDatabases(); |
204
|
|
|
|
205
|
|
|
$databases = array_map('strtolower', $databases); |
206
|
|
|
|
207
|
|
|
self::assertContains('test_create_database', $databases); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @group DBAL-1058 |
212
|
|
|
*/ |
213
|
|
|
public function testListNamespaceNames() : void |
214
|
|
|
{ |
215
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) { |
216
|
|
|
$this->markTestSkipped('Platform does not support schemas.'); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
// Currently dropping schemas is not supported, so we have to workaround here. |
220
|
|
|
$namespaces = $this->schemaManager->listNamespaceNames(); |
221
|
|
|
$namespaces = array_map('strtolower', $namespaces); |
222
|
|
|
|
223
|
|
|
if (! in_array('test_create_schema', $namespaces)) { |
224
|
|
|
$this->connection->executeUpdate($this->schemaManager->getDatabasePlatform()->getCreateSchemaSQL('test_create_schema')); |
225
|
|
|
|
226
|
|
|
$namespaces = $this->schemaManager->listNamespaceNames(); |
227
|
|
|
$namespaces = array_map('strtolower', $namespaces); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
self::assertContains('test_create_schema', $namespaces); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
public function testListTables() : void |
234
|
|
|
{ |
235
|
|
|
$this->createTestTable('list_tables_test'); |
236
|
|
|
$tables = $this->schemaManager->listTables(); |
237
|
|
|
|
238
|
|
|
self::assertIsArray($tables); |
239
|
|
|
self::assertTrue(count($tables) > 0, "List Tables has to find at least one table named 'list_tables_test'."); |
240
|
|
|
|
241
|
|
|
$foundTable = false; |
242
|
|
|
foreach ($tables as $table) { |
243
|
|
|
self::assertInstanceOf(Table::class, $table); |
244
|
|
|
if (strtolower($table->getName()) !== 'list_tables_test') { |
245
|
|
|
continue; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
$foundTable = true; |
249
|
|
|
|
250
|
|
|
self::assertTrue($table->hasColumn('id')); |
251
|
|
|
self::assertTrue($table->hasColumn('test')); |
252
|
|
|
self::assertTrue($table->hasColumn('foreign_key_test')); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
self::assertTrue($foundTable, "The 'list_tables_test' table has to be found."); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
public function createListTableColumns() : Table |
259
|
|
|
{ |
260
|
|
|
$table = new Table('list_table_columns'); |
261
|
|
|
$table->addColumn('id', 'integer', ['notnull' => true]); |
262
|
|
|
$table->addColumn('test', 'string', ['length' => 255, 'notnull' => false, 'default' => 'expected default']); |
263
|
|
|
$table->addColumn('foo', 'text', ['notnull' => true]); |
264
|
|
|
$table->addColumn('bar', 'decimal', ['precision' => 10, 'scale' => 4, 'notnull' => false]); |
265
|
|
|
$table->addColumn('baz1', 'datetime'); |
266
|
|
|
$table->addColumn('baz2', 'time'); |
267
|
|
|
$table->addColumn('baz3', 'date'); |
268
|
|
|
$table->setPrimaryKey(['id']); |
269
|
|
|
|
270
|
|
|
return $table; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
public function testListTableColumns() : void |
274
|
|
|
{ |
275
|
|
|
$table = $this->createListTableColumns(); |
276
|
|
|
|
277
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
278
|
|
|
|
279
|
|
|
$columns = $this->schemaManager->listTableColumns('list_table_columns'); |
280
|
|
|
$columnsKeys = array_keys($columns); |
281
|
|
|
|
282
|
|
|
self::assertArrayHasKey('id', $columns); |
283
|
|
|
self::assertEquals(0, array_search('id', $columnsKeys)); |
284
|
|
|
self::assertEquals('id', strtolower($columns['id']->getname())); |
285
|
|
|
self::assertInstanceOf(IntegerType::class, $columns['id']->gettype()); |
286
|
|
|
self::assertEquals(false, $columns['id']->getunsigned()); |
287
|
|
|
self::assertEquals(true, $columns['id']->getnotnull()); |
288
|
|
|
self::assertEquals(null, $columns['id']->getdefault()); |
289
|
|
|
self::assertIsArray($columns['id']->getPlatformOptions()); |
290
|
|
|
|
291
|
|
|
self::assertArrayHasKey('test', $columns); |
292
|
|
|
self::assertEquals(1, array_search('test', $columnsKeys)); |
293
|
|
|
self::assertEquals('test', strtolower($columns['test']->getname())); |
294
|
|
|
self::assertInstanceOf(StringType::class, $columns['test']->gettype()); |
295
|
|
|
self::assertEquals(255, $columns['test']->getlength()); |
296
|
|
|
self::assertEquals(false, $columns['test']->getfixed()); |
297
|
|
|
self::assertEquals(false, $columns['test']->getnotnull()); |
298
|
|
|
self::assertEquals('expected default', $columns['test']->getdefault()); |
299
|
|
|
self::assertIsArray($columns['test']->getPlatformOptions()); |
300
|
|
|
|
301
|
|
|
self::assertEquals('foo', strtolower($columns['foo']->getname())); |
302
|
|
|
self::assertEquals(2, array_search('foo', $columnsKeys)); |
303
|
|
|
self::assertInstanceOf(TextType::class, $columns['foo']->gettype()); |
304
|
|
|
self::assertEquals(false, $columns['foo']->getunsigned()); |
305
|
|
|
self::assertEquals(false, $columns['foo']->getfixed()); |
306
|
|
|
self::assertEquals(true, $columns['foo']->getnotnull()); |
307
|
|
|
self::assertEquals(null, $columns['foo']->getdefault()); |
308
|
|
|
self::assertIsArray($columns['foo']->getPlatformOptions()); |
309
|
|
|
|
310
|
|
|
self::assertEquals('bar', strtolower($columns['bar']->getname())); |
311
|
|
|
self::assertEquals(3, array_search('bar', $columnsKeys)); |
312
|
|
|
self::assertInstanceOf(DecimalType::class, $columns['bar']->gettype()); |
313
|
|
|
self::assertEquals(null, $columns['bar']->getlength()); |
314
|
|
|
self::assertEquals(10, $columns['bar']->getprecision()); |
315
|
|
|
self::assertEquals(4, $columns['bar']->getscale()); |
316
|
|
|
self::assertEquals(false, $columns['bar']->getunsigned()); |
317
|
|
|
self::assertEquals(false, $columns['bar']->getfixed()); |
318
|
|
|
self::assertEquals(false, $columns['bar']->getnotnull()); |
319
|
|
|
self::assertEquals(null, $columns['bar']->getdefault()); |
320
|
|
|
self::assertIsArray($columns['bar']->getPlatformOptions()); |
321
|
|
|
|
322
|
|
|
self::assertEquals('baz1', strtolower($columns['baz1']->getname())); |
323
|
|
|
self::assertEquals(4, array_search('baz1', $columnsKeys)); |
324
|
|
|
self::assertInstanceOf(DateTimeType::class, $columns['baz1']->gettype()); |
325
|
|
|
self::assertEquals(true, $columns['baz1']->getnotnull()); |
326
|
|
|
self::assertEquals(null, $columns['baz1']->getdefault()); |
327
|
|
|
self::assertIsArray($columns['baz1']->getPlatformOptions()); |
328
|
|
|
|
329
|
|
|
self::assertEquals('baz2', strtolower($columns['baz2']->getname())); |
330
|
|
|
self::assertEquals(5, array_search('baz2', $columnsKeys)); |
331
|
|
|
self::assertContains($columns['baz2']->gettype()->getName(), ['time', 'date', 'datetime']); |
332
|
|
|
self::assertEquals(true, $columns['baz2']->getnotnull()); |
333
|
|
|
self::assertEquals(null, $columns['baz2']->getdefault()); |
334
|
|
|
self::assertIsArray($columns['baz2']->getPlatformOptions()); |
335
|
|
|
|
336
|
|
|
self::assertEquals('baz3', strtolower($columns['baz3']->getname())); |
337
|
|
|
self::assertEquals(6, array_search('baz3', $columnsKeys)); |
338
|
|
|
self::assertContains($columns['baz3']->gettype()->getName(), ['time', 'date', 'datetime']); |
339
|
|
|
self::assertEquals(true, $columns['baz3']->getnotnull()); |
340
|
|
|
self::assertEquals(null, $columns['baz3']->getdefault()); |
341
|
|
|
self::assertIsArray($columns['baz3']->getPlatformOptions()); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* @group DBAL-1078 |
346
|
|
|
*/ |
347
|
|
|
public function testListTableColumnsWithFixedStringColumn() : void |
348
|
|
|
{ |
349
|
|
|
$tableName = 'test_list_table_fixed_string'; |
350
|
|
|
|
351
|
|
|
$table = new Table($tableName); |
352
|
|
|
$table->addColumn('column_char', 'string', ['fixed' => true, 'length' => 2]); |
353
|
|
|
|
354
|
|
|
$this->schemaManager->createTable($table); |
355
|
|
|
|
356
|
|
|
$columns = $this->schemaManager->listTableColumns($tableName); |
357
|
|
|
|
358
|
|
|
self::assertArrayHasKey('column_char', $columns); |
359
|
|
|
self::assertInstanceOf(StringType::class, $columns['column_char']->getType()); |
360
|
|
|
self::assertTrue($columns['column_char']->getFixed()); |
361
|
|
|
self::assertSame(2, $columns['column_char']->getLength()); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
public function testListTableColumnsDispatchEvent() : void |
365
|
|
|
{ |
366
|
|
|
$table = $this->createListTableColumns(); |
367
|
|
|
|
368
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
369
|
|
|
|
370
|
|
|
$listenerMock = $this |
|
|
|
|
371
|
|
|
->getMockBuilder('ListTableColumnsDispatchEventListener') |
372
|
|
|
->setMethods(['onSchemaColumnDefinition']) |
373
|
|
|
->getMock(); |
374
|
|
|
$listenerMock |
375
|
|
|
->expects($this->exactly(7)) |
376
|
|
|
->method('onSchemaColumnDefinition'); |
377
|
|
|
|
378
|
|
|
$oldEventManager = $this->schemaManager->getDatabasePlatform()->getEventManager(); |
379
|
|
|
|
380
|
|
|
$eventManager = new EventManager(); |
381
|
|
|
$eventManager->addEventListener([Events::onSchemaColumnDefinition], $listenerMock); |
382
|
|
|
|
383
|
|
|
$this->schemaManager->getDatabasePlatform()->setEventManager($eventManager); |
384
|
|
|
|
385
|
|
|
$this->schemaManager->listTableColumns('list_table_columns'); |
386
|
|
|
|
387
|
|
|
$this->schemaManager->getDatabasePlatform()->setEventManager($oldEventManager); |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
public function testListTableIndexesDispatchEvent() : void |
391
|
|
|
{ |
392
|
|
|
$table = $this->getTestTable('list_table_indexes_test'); |
393
|
|
|
$table->addUniqueIndex(['test'], 'test_index_name'); |
394
|
|
|
$table->addIndex(['id', 'test'], 'test_composite_idx'); |
395
|
|
|
|
396
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
397
|
|
|
|
398
|
|
|
$listenerMock = $this |
|
|
|
|
399
|
|
|
->getMockBuilder('ListTableIndexesDispatchEventListener') |
400
|
|
|
->setMethods(['onSchemaIndexDefinition']) |
401
|
|
|
->getMock(); |
402
|
|
|
$listenerMock |
403
|
|
|
->expects($this->exactly(3)) |
404
|
|
|
->method('onSchemaIndexDefinition'); |
405
|
|
|
|
406
|
|
|
$oldEventManager = $this->schemaManager->getDatabasePlatform()->getEventManager(); |
407
|
|
|
|
408
|
|
|
$eventManager = new EventManager(); |
409
|
|
|
$eventManager->addEventListener([Events::onSchemaIndexDefinition], $listenerMock); |
410
|
|
|
|
411
|
|
|
$this->schemaManager->getDatabasePlatform()->setEventManager($eventManager); |
412
|
|
|
|
413
|
|
|
$this->schemaManager->listTableIndexes('list_table_indexes_test'); |
414
|
|
|
|
415
|
|
|
$this->schemaManager->getDatabasePlatform()->setEventManager($oldEventManager); |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
public function testDiffListTableColumns() : void |
419
|
|
|
{ |
420
|
|
|
if ($this->schemaManager->getDatabasePlatform()->getName() === 'oracle') { |
421
|
|
|
$this->markTestSkipped('Does not work with Oracle, since it cannot detect DateTime, Date and Time differenecs (at the moment).'); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
$offlineTable = $this->createListTableColumns(); |
425
|
|
|
$this->schemaManager->dropAndCreateTable($offlineTable); |
426
|
|
|
$onlineTable = $this->schemaManager->listTableDetails('list_table_columns'); |
427
|
|
|
|
428
|
|
|
$comparator = new Comparator(); |
429
|
|
|
$diff = $comparator->diffTable($offlineTable, $onlineTable); |
430
|
|
|
|
431
|
|
|
self::assertFalse($diff, 'No differences should be detected with the offline vs online schema.'); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
public function testListTableIndexes() : void |
435
|
|
|
{ |
436
|
|
|
$table = $this->getTestCompositeTable('list_table_indexes_test'); |
437
|
|
|
$table->addUniqueIndex(['test'], 'test_index_name'); |
438
|
|
|
$table->addIndex(['id', 'test'], 'test_composite_idx'); |
439
|
|
|
|
440
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
441
|
|
|
|
442
|
|
|
$tableIndexes = $this->schemaManager->listTableIndexes('list_table_indexes_test'); |
443
|
|
|
|
444
|
|
|
self::assertEquals(3, count($tableIndexes)); |
445
|
|
|
|
446
|
|
|
self::assertArrayHasKey('primary', $tableIndexes, 'listTableIndexes() has to return a "primary" array key.'); |
447
|
|
|
self::assertEquals(['id', 'other_id'], array_map('strtolower', $tableIndexes['primary']->getColumns())); |
448
|
|
|
self::assertTrue($tableIndexes['primary']->isUnique()); |
449
|
|
|
self::assertTrue($tableIndexes['primary']->isPrimary()); |
450
|
|
|
|
451
|
|
|
self::assertEquals('test_index_name', strtolower($tableIndexes['test_index_name']->getName())); |
452
|
|
|
self::assertEquals(['test'], array_map('strtolower', $tableIndexes['test_index_name']->getColumns())); |
453
|
|
|
self::assertTrue($tableIndexes['test_index_name']->isUnique()); |
454
|
|
|
self::assertFalse($tableIndexes['test_index_name']->isPrimary()); |
455
|
|
|
|
456
|
|
|
self::assertEquals('test_composite_idx', strtolower($tableIndexes['test_composite_idx']->getName())); |
457
|
|
|
self::assertEquals(['id', 'test'], array_map('strtolower', $tableIndexes['test_composite_idx']->getColumns())); |
458
|
|
|
self::assertFalse($tableIndexes['test_composite_idx']->isUnique()); |
459
|
|
|
self::assertFalse($tableIndexes['test_composite_idx']->isPrimary()); |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
public function testDropAndCreateIndex() : void |
463
|
|
|
{ |
464
|
|
|
$table = $this->getTestTable('test_create_index'); |
465
|
|
|
$table->addUniqueIndex(['test'], 'test'); |
466
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
467
|
|
|
|
468
|
|
|
$this->schemaManager->dropAndCreateIndex($table->getIndex('test'), $table); |
469
|
|
|
$tableIndexes = $this->schemaManager->listTableIndexes('test_create_index'); |
470
|
|
|
self::assertIsArray($tableIndexes); |
471
|
|
|
|
472
|
|
|
self::assertEquals('test', strtolower($tableIndexes['test']->getName())); |
473
|
|
|
self::assertEquals(['test'], array_map('strtolower', $tableIndexes['test']->getColumns())); |
474
|
|
|
self::assertTrue($tableIndexes['test']->isUnique()); |
475
|
|
|
self::assertFalse($tableIndexes['test']->isPrimary()); |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
public function testCreateTableWithForeignKeys() : void |
479
|
|
|
{ |
480
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
481
|
|
|
$this->markTestSkipped('Platform does not support foreign keys.'); |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
$tableB = $this->getTestTable('test_foreign'); |
485
|
|
|
|
486
|
|
|
$this->schemaManager->dropAndCreateTable($tableB); |
487
|
|
|
|
488
|
|
|
$tableA = $this->getTestTable('test_create_fk'); |
489
|
|
|
$tableA->addForeignKeyConstraint('test_foreign', ['foreign_key_test'], ['id']); |
490
|
|
|
|
491
|
|
|
$this->schemaManager->dropAndCreateTable($tableA); |
492
|
|
|
|
493
|
|
|
$fkTable = $this->schemaManager->listTableDetails('test_create_fk'); |
494
|
|
|
$fkConstraints = $fkTable->getForeignKeys(); |
495
|
|
|
self::assertEquals(1, count($fkConstraints), "Table 'test_create_fk1' has to have one foreign key."); |
496
|
|
|
|
497
|
|
|
$fkConstraint = current($fkConstraints); |
498
|
|
|
self::assertInstanceOf(ForeignKeyConstraint::class, $fkConstraint); |
499
|
|
|
self::assertEquals('test_foreign', strtolower($fkConstraint->getForeignTableName())); |
500
|
|
|
self::assertEquals(['foreign_key_test'], array_map('strtolower', $fkConstraint->getColumns())); |
501
|
|
|
self::assertEquals(['id'], array_map('strtolower', $fkConstraint->getForeignColumns())); |
502
|
|
|
|
503
|
|
|
self::assertTrue($fkTable->columnsAreIndexed($fkConstraint->getColumns()), 'The columns of a foreign key constraint should always be indexed.'); |
504
|
|
|
} |
505
|
|
|
|
506
|
|
|
public function testListForeignKeys() : void |
507
|
|
|
{ |
508
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
509
|
|
|
$this->markTestSkipped('Does not support foreign key constraints.'); |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
$this->createTestTable('test_create_fk1'); |
513
|
|
|
$this->createTestTable('test_create_fk2'); |
514
|
|
|
|
515
|
|
|
$foreignKey = new ForeignKeyConstraint( |
516
|
|
|
['foreign_key_test'], |
517
|
|
|
'test_create_fk2', |
518
|
|
|
['id'], |
519
|
|
|
'foreign_key_test_fk', |
520
|
|
|
['onDelete' => 'CASCADE'] |
521
|
|
|
); |
522
|
|
|
|
523
|
|
|
$this->schemaManager->createForeignKey($foreignKey, 'test_create_fk1'); |
524
|
|
|
|
525
|
|
|
$fkeys = $this->schemaManager->listTableForeignKeys('test_create_fk1'); |
526
|
|
|
|
527
|
|
|
self::assertEquals(1, count($fkeys), "Table 'test_create_fk1' has to have one foreign key."); |
528
|
|
|
|
529
|
|
|
self::assertInstanceOf(ForeignKeyConstraint::class, $fkeys[0]); |
530
|
|
|
self::assertEquals(['foreign_key_test'], array_map('strtolower', $fkeys[0]->getLocalColumns())); |
531
|
|
|
self::assertEquals(['id'], array_map('strtolower', $fkeys[0]->getForeignColumns())); |
532
|
|
|
self::assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName())); |
533
|
|
|
|
534
|
|
|
if (! $fkeys[0]->hasOption('onDelete')) { |
535
|
|
|
return; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
self::assertEquals('CASCADE', $fkeys[0]->getOption('onDelete')); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
protected function getCreateExampleViewSql() : void |
542
|
|
|
{ |
543
|
|
|
$this->markTestSkipped('No Create Example View SQL was defined for this SchemaManager'); |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
public function testCreateSchema() : void |
547
|
|
|
{ |
548
|
|
|
$this->createTestTable('test_table'); |
549
|
|
|
|
550
|
|
|
$schema = $this->schemaManager->createSchema(); |
551
|
|
|
self::assertTrue($schema->hasTable('test_table')); |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
public function testAlterTableScenario() : void |
555
|
|
|
{ |
556
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsAlterTable()) { |
557
|
|
|
$this->markTestSkipped('Alter Table is not supported by this platform.'); |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
$alterTable = $this->createTestTable('alter_table'); |
561
|
|
|
$this->createTestTable('alter_table_foreign'); |
562
|
|
|
|
563
|
|
|
$table = $this->schemaManager->listTableDetails('alter_table'); |
564
|
|
|
self::assertTrue($table->hasColumn('id')); |
565
|
|
|
self::assertTrue($table->hasColumn('test')); |
566
|
|
|
self::assertTrue($table->hasColumn('foreign_key_test')); |
567
|
|
|
self::assertEquals(0, count($table->getForeignKeys())); |
568
|
|
|
self::assertEquals(1, count($table->getIndexes())); |
569
|
|
|
|
570
|
|
|
$tableDiff = new TableDiff('alter_table'); |
571
|
|
|
$tableDiff->fromTable = $alterTable; |
572
|
|
|
$tableDiff->addedColumns['foo'] = new Column('foo', Type::getType('integer')); |
573
|
|
|
$tableDiff->removedColumns['test'] = $table->getColumn('test'); |
574
|
|
|
|
575
|
|
|
$this->schemaManager->alterTable($tableDiff); |
576
|
|
|
|
577
|
|
|
$table = $this->schemaManager->listTableDetails('alter_table'); |
578
|
|
|
self::assertFalse($table->hasColumn('test')); |
579
|
|
|
self::assertTrue($table->hasColumn('foo')); |
580
|
|
|
|
581
|
|
|
$tableDiff = new TableDiff('alter_table'); |
582
|
|
|
$tableDiff->fromTable = $table; |
583
|
|
|
$tableDiff->addedIndexes[] = new Index('foo_idx', ['foo']); |
584
|
|
|
|
585
|
|
|
$this->schemaManager->alterTable($tableDiff); |
586
|
|
|
|
587
|
|
|
$table = $this->schemaManager->listTableDetails('alter_table'); |
588
|
|
|
self::assertEquals(2, count($table->getIndexes())); |
589
|
|
|
self::assertTrue($table->hasIndex('foo_idx')); |
590
|
|
|
self::assertEquals(['foo'], array_map('strtolower', $table->getIndex('foo_idx')->getColumns())); |
591
|
|
|
self::assertFalse($table->getIndex('foo_idx')->isPrimary()); |
592
|
|
|
self::assertFalse($table->getIndex('foo_idx')->isUnique()); |
593
|
|
|
|
594
|
|
|
$tableDiff = new TableDiff('alter_table'); |
595
|
|
|
$tableDiff->fromTable = $table; |
596
|
|
|
$tableDiff->changedIndexes[] = new Index('foo_idx', ['foo', 'foreign_key_test']); |
597
|
|
|
|
598
|
|
|
$this->schemaManager->alterTable($tableDiff); |
599
|
|
|
|
600
|
|
|
$table = $this->schemaManager->listTableDetails('alter_table'); |
601
|
|
|
self::assertEquals(2, count($table->getIndexes())); |
602
|
|
|
self::assertTrue($table->hasIndex('foo_idx')); |
603
|
|
|
self::assertEquals(['foo', 'foreign_key_test'], array_map('strtolower', $table->getIndex('foo_idx')->getColumns())); |
604
|
|
|
|
605
|
|
|
$tableDiff = new TableDiff('alter_table'); |
606
|
|
|
$tableDiff->fromTable = $table; |
607
|
|
|
$tableDiff->renamedIndexes['foo_idx'] = new Index('bar_idx', ['foo', 'foreign_key_test']); |
608
|
|
|
|
609
|
|
|
$this->schemaManager->alterTable($tableDiff); |
610
|
|
|
|
611
|
|
|
$table = $this->schemaManager->listTableDetails('alter_table'); |
612
|
|
|
self::assertEquals(2, count($table->getIndexes())); |
613
|
|
|
self::assertTrue($table->hasIndex('bar_idx')); |
614
|
|
|
self::assertFalse($table->hasIndex('foo_idx')); |
615
|
|
|
self::assertEquals(['foo', 'foreign_key_test'], array_map('strtolower', $table->getIndex('bar_idx')->getColumns())); |
616
|
|
|
self::assertFalse($table->getIndex('bar_idx')->isPrimary()); |
617
|
|
|
self::assertFalse($table->getIndex('bar_idx')->isUnique()); |
618
|
|
|
|
619
|
|
|
$tableDiff = new TableDiff('alter_table'); |
620
|
|
|
$tableDiff->fromTable = $table; |
621
|
|
|
$tableDiff->removedIndexes[] = new Index('bar_idx', ['foo', 'foreign_key_test']); |
622
|
|
|
$fk = new ForeignKeyConstraint(['foreign_key_test'], 'alter_table_foreign', ['id']); |
623
|
|
|
$tableDiff->addedForeignKeys[] = $fk; |
624
|
|
|
|
625
|
|
|
$this->schemaManager->alterTable($tableDiff); |
626
|
|
|
$table = $this->schemaManager->listTableDetails('alter_table'); |
627
|
|
|
|
628
|
|
|
// dont check for index size here, some platforms automatically add indexes for foreign keys. |
629
|
|
|
self::assertFalse($table->hasIndex('bar_idx')); |
630
|
|
|
|
631
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
632
|
|
|
return; |
633
|
|
|
} |
634
|
|
|
|
635
|
|
|
$fks = $table->getForeignKeys(); |
636
|
|
|
self::assertCount(1, $fks); |
637
|
|
|
$foreignKey = current($fks); |
638
|
|
|
self::assertEquals('alter_table_foreign', strtolower($foreignKey->getForeignTableName())); |
639
|
|
|
self::assertEquals(['foreign_key_test'], array_map('strtolower', $foreignKey->getColumns())); |
640
|
|
|
self::assertEquals(['id'], array_map('strtolower', $foreignKey->getForeignColumns())); |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
public function testTableInNamespace() : void |
644
|
|
|
{ |
645
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) { |
646
|
|
|
$this->markTestSkipped('Schema definition is not supported by this platform.'); |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
//create schema |
650
|
|
|
$diff = new SchemaDiff(); |
651
|
|
|
$diff->newNamespaces[] = 'testschema'; |
652
|
|
|
|
653
|
|
|
foreach ($diff->toSql($this->schemaManager->getDatabasePlatform()) as $sql) { |
654
|
|
|
$this->connection->exec($sql); |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
//test if table is create in namespace |
658
|
|
|
$this->createTestTable('testschema.my_table_in_namespace'); |
659
|
|
|
self::assertContains('testschema.my_table_in_namespace', $this->schemaManager->listTableNames()); |
660
|
|
|
|
661
|
|
|
//tables without namespace should be created in default namespace |
662
|
|
|
//default namespaces are ignored in table listings |
663
|
|
|
$this->createTestTable('my_table_not_in_namespace'); |
664
|
|
|
self::assertContains('my_table_not_in_namespace', $this->schemaManager->listTableNames()); |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
public function testCreateAndListViews() : void |
668
|
|
|
{ |
669
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsViews()) { |
670
|
|
|
$this->markTestSkipped('Views is not supported by this platform.'); |
671
|
|
|
} |
672
|
|
|
|
673
|
|
|
$this->createTestTable('view_test_table'); |
674
|
|
|
|
675
|
|
|
$name = 'doctrine_test_view'; |
676
|
|
|
$sql = 'SELECT * FROM view_test_table'; |
677
|
|
|
|
678
|
|
|
$view = new View($name, $sql); |
679
|
|
|
|
680
|
|
|
$this->schemaManager->dropAndCreateView($view); |
681
|
|
|
|
682
|
|
|
self::assertTrue($this->hasElementWithName($this->schemaManager->listViews(), $name)); |
683
|
|
|
} |
684
|
|
|
|
685
|
|
|
public function testAutoincrementDetection() : void |
686
|
|
|
{ |
687
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsIdentityColumns()) { |
688
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have autoincrement'); |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
$table = new Table('test_autoincrement'); |
692
|
|
|
$table->setSchemaConfig($this->schemaManager->createSchemaConfig()); |
693
|
|
|
$table->addColumn('id', 'integer', ['autoincrement' => true]); |
694
|
|
|
$table->setPrimaryKey(['id']); |
695
|
|
|
|
696
|
|
|
$this->schemaManager->createTable($table); |
697
|
|
|
|
698
|
|
|
$inferredTable = $this->schemaManager->listTableDetails('test_autoincrement'); |
699
|
|
|
self::assertTrue($inferredTable->hasColumn('id')); |
700
|
|
|
self::assertTrue($inferredTable->getColumn('id')->getAutoincrement()); |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
/** |
704
|
|
|
* @group DBAL-792 |
705
|
|
|
*/ |
706
|
|
|
public function testAutoincrementDetectionMulticolumns() : void |
707
|
|
|
{ |
708
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsIdentityColumns()) { |
709
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have autoincrement'); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
$table = new Table('test_not_autoincrement'); |
713
|
|
|
$table->setSchemaConfig($this->schemaManager->createSchemaConfig()); |
714
|
|
|
$table->addColumn('id', 'integer'); |
715
|
|
|
$table->addColumn('other_id', 'integer'); |
716
|
|
|
$table->setPrimaryKey(['id', 'other_id']); |
717
|
|
|
|
718
|
|
|
$this->schemaManager->createTable($table); |
719
|
|
|
|
720
|
|
|
$inferredTable = $this->schemaManager->listTableDetails('test_not_autoincrement'); |
721
|
|
|
self::assertTrue($inferredTable->hasColumn('id')); |
722
|
|
|
self::assertFalse($inferredTable->getColumn('id')->getAutoincrement()); |
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
/** |
726
|
|
|
* @group DDC-887 |
727
|
|
|
*/ |
728
|
|
|
public function testUpdateSchemaWithForeignKeyRenaming() : void |
729
|
|
|
{ |
730
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
731
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have foreign keys.'); |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
$table = new Table('test_fk_base'); |
735
|
|
|
$table->addColumn('id', 'integer'); |
736
|
|
|
$table->setPrimaryKey(['id']); |
737
|
|
|
|
738
|
|
|
$tableFK = new Table('test_fk_rename'); |
739
|
|
|
$tableFK->setSchemaConfig($this->schemaManager->createSchemaConfig()); |
740
|
|
|
$tableFK->addColumn('id', 'integer'); |
741
|
|
|
$tableFK->addColumn('fk_id', 'integer'); |
742
|
|
|
$tableFK->setPrimaryKey(['id']); |
743
|
|
|
$tableFK->addIndex(['fk_id'], 'fk_idx'); |
744
|
|
|
$tableFK->addForeignKeyConstraint('test_fk_base', ['fk_id'], ['id']); |
745
|
|
|
|
746
|
|
|
$this->schemaManager->createTable($table); |
747
|
|
|
$this->schemaManager->createTable($tableFK); |
748
|
|
|
|
749
|
|
|
$tableFKNew = new Table('test_fk_rename'); |
750
|
|
|
$tableFKNew->setSchemaConfig($this->schemaManager->createSchemaConfig()); |
751
|
|
|
$tableFKNew->addColumn('id', 'integer'); |
752
|
|
|
$tableFKNew->addColumn('rename_fk_id', 'integer'); |
753
|
|
|
$tableFKNew->setPrimaryKey(['id']); |
754
|
|
|
$tableFKNew->addIndex(['rename_fk_id'], 'fk_idx'); |
755
|
|
|
$tableFKNew->addForeignKeyConstraint('test_fk_base', ['rename_fk_id'], ['id']); |
756
|
|
|
|
757
|
|
|
$c = new Comparator(); |
758
|
|
|
$tableDiff = $c->diffTable($tableFK, $tableFKNew); |
759
|
|
|
|
760
|
|
|
$this->schemaManager->alterTable($tableDiff); |
|
|
|
|
761
|
|
|
|
762
|
|
|
$table = $this->schemaManager->listTableDetails('test_fk_rename'); |
763
|
|
|
$foreignKeys = $table->getForeignKeys(); |
764
|
|
|
|
765
|
|
|
self::assertTrue($table->hasColumn('rename_fk_id')); |
766
|
|
|
self::assertCount(1, $foreignKeys); |
767
|
|
|
self::assertSame(['rename_fk_id'], array_map('strtolower', current($foreignKeys)->getColumns())); |
768
|
|
|
} |
769
|
|
|
|
770
|
|
|
/** |
771
|
|
|
* @group DBAL-1062 |
772
|
|
|
*/ |
773
|
|
|
public function testRenameIndexUsedInForeignKeyConstraint() : void |
774
|
|
|
{ |
775
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
776
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have foreign keys.'); |
777
|
|
|
} |
778
|
|
|
|
779
|
|
|
$primaryTable = new Table('test_rename_index_primary'); |
780
|
|
|
$primaryTable->addColumn('id', 'integer'); |
781
|
|
|
$primaryTable->setPrimaryKey(['id']); |
782
|
|
|
|
783
|
|
|
$foreignTable = new Table('test_rename_index_foreign'); |
784
|
|
|
$foreignTable->addColumn('fk', 'integer'); |
785
|
|
|
$foreignTable->addIndex(['fk'], 'rename_index_fk_idx'); |
786
|
|
|
$foreignTable->addForeignKeyConstraint( |
787
|
|
|
'test_rename_index_primary', |
788
|
|
|
['fk'], |
789
|
|
|
['id'], |
790
|
|
|
[], |
791
|
|
|
'fk_constraint' |
792
|
|
|
); |
793
|
|
|
|
794
|
|
|
$this->schemaManager->dropAndCreateTable($primaryTable); |
795
|
|
|
$this->schemaManager->dropAndCreateTable($foreignTable); |
796
|
|
|
|
797
|
|
|
$foreignTable2 = clone $foreignTable; |
798
|
|
|
$foreignTable2->renameIndex('rename_index_fk_idx', 'renamed_index_fk_idx'); |
799
|
|
|
|
800
|
|
|
$comparator = new Comparator(); |
801
|
|
|
|
802
|
|
|
$this->schemaManager->alterTable($comparator->diffTable($foreignTable, $foreignTable2)); |
|
|
|
|
803
|
|
|
|
804
|
|
|
$foreignTable = $this->schemaManager->listTableDetails('test_rename_index_foreign'); |
805
|
|
|
|
806
|
|
|
self::assertFalse($foreignTable->hasIndex('rename_index_fk_idx')); |
807
|
|
|
self::assertTrue($foreignTable->hasIndex('renamed_index_fk_idx')); |
808
|
|
|
self::assertTrue($foreignTable->hasForeignKey('fk_constraint')); |
809
|
|
|
} |
810
|
|
|
|
811
|
|
|
/** |
812
|
|
|
* @group DBAL-42 |
813
|
|
|
*/ |
814
|
|
|
public function testGetColumnComment() : void |
815
|
|
|
{ |
816
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() && |
817
|
|
|
! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() && |
818
|
|
|
$this->connection->getDatabasePlatform()->getName() !== 'mssql') { |
819
|
|
|
$this->markTestSkipped('Database does not support column comments.'); |
820
|
|
|
} |
821
|
|
|
|
822
|
|
|
$table = new Table('column_comment_test'); |
823
|
|
|
$table->addColumn('id', 'integer', ['comment' => 'This is a comment']); |
824
|
|
|
$table->setPrimaryKey(['id']); |
825
|
|
|
|
826
|
|
|
$this->schemaManager->createTable($table); |
827
|
|
|
|
828
|
|
|
$columns = $this->schemaManager->listTableColumns('column_comment_test'); |
829
|
|
|
self::assertEquals(1, count($columns)); |
830
|
|
|
self::assertEquals('This is a comment', $columns['id']->getComment()); |
831
|
|
|
|
832
|
|
|
$tableDiff = new TableDiff('column_comment_test'); |
833
|
|
|
$tableDiff->fromTable = $table; |
834
|
|
|
$tableDiff->changedColumns['id'] = new ColumnDiff( |
835
|
|
|
'id', |
836
|
|
|
new Column( |
837
|
|
|
'id', |
838
|
|
|
Type::getType('integer') |
839
|
|
|
), |
840
|
|
|
['comment'], |
841
|
|
|
new Column( |
842
|
|
|
'id', |
843
|
|
|
Type::getType('integer'), |
844
|
|
|
['comment' => 'This is a comment'] |
845
|
|
|
) |
846
|
|
|
); |
847
|
|
|
|
848
|
|
|
$this->schemaManager->alterTable($tableDiff); |
849
|
|
|
|
850
|
|
|
$columns = $this->schemaManager->listTableColumns('column_comment_test'); |
851
|
|
|
self::assertEquals(1, count($columns)); |
852
|
|
|
self::assertEmpty($columns['id']->getComment()); |
853
|
|
|
} |
854
|
|
|
|
855
|
|
|
/** |
856
|
|
|
* @group DBAL-42 |
857
|
|
|
*/ |
858
|
|
|
public function testAutomaticallyAppendCommentOnMarkedColumns() : void |
859
|
|
|
{ |
860
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() && |
861
|
|
|
! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() && |
862
|
|
|
$this->connection->getDatabasePlatform()->getName() !== 'mssql') { |
863
|
|
|
$this->markTestSkipped('Database does not support column comments.'); |
864
|
|
|
} |
865
|
|
|
|
866
|
|
|
$table = new Table('column_comment_test2'); |
867
|
|
|
$table->addColumn('id', 'integer', ['comment' => 'This is a comment']); |
868
|
|
|
$table->addColumn('obj', 'object', ['comment' => 'This is a comment']); |
869
|
|
|
$table->addColumn('arr', 'array', ['comment' => 'This is a comment']); |
870
|
|
|
$table->setPrimaryKey(['id']); |
871
|
|
|
|
872
|
|
|
$this->schemaManager->createTable($table); |
873
|
|
|
|
874
|
|
|
$columns = $this->schemaManager->listTableColumns('column_comment_test2'); |
875
|
|
|
self::assertEquals(3, count($columns)); |
876
|
|
|
self::assertEquals('This is a comment', $columns['id']->getComment()); |
877
|
|
|
self::assertEquals('This is a comment', $columns['obj']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.'); |
878
|
|
|
self::assertInstanceOf(ObjectType::class, $columns['obj']->getType(), 'The Doctrine2 should be detected from comment hint.'); |
879
|
|
|
self::assertEquals('This is a comment', $columns['arr']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.'); |
880
|
|
|
self::assertInstanceOf(ArrayType::class, $columns['arr']->getType(), 'The Doctrine2 should be detected from comment hint.'); |
881
|
|
|
} |
882
|
|
|
|
883
|
|
|
/** |
884
|
|
|
* @group DBAL-1228 |
885
|
|
|
*/ |
886
|
|
|
public function testCommentHintOnDateIntervalTypeColumn() : void |
887
|
|
|
{ |
888
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() && |
889
|
|
|
! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() && |
890
|
|
|
$this->connection->getDatabasePlatform()->getName() !== 'mssql') { |
891
|
|
|
$this->markTestSkipped('Database does not support column comments.'); |
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
$table = new Table('column_dateinterval_comment'); |
895
|
|
|
$table->addColumn('id', 'integer', ['comment' => 'This is a comment']); |
896
|
|
|
$table->addColumn('date_interval', 'dateinterval', ['comment' => 'This is a comment']); |
897
|
|
|
$table->setPrimaryKey(['id']); |
898
|
|
|
|
899
|
|
|
$this->schemaManager->createTable($table); |
900
|
|
|
|
901
|
|
|
$columns = $this->schemaManager->listTableColumns('column_dateinterval_comment'); |
902
|
|
|
self::assertEquals(2, count($columns)); |
903
|
|
|
self::assertEquals('This is a comment', $columns['id']->getComment()); |
904
|
|
|
self::assertEquals('This is a comment', $columns['date_interval']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.'); |
905
|
|
|
self::assertInstanceOf(DateIntervalType::class, $columns['date_interval']->getType(), 'The Doctrine2 should be detected from comment hint.'); |
906
|
|
|
} |
907
|
|
|
|
908
|
|
|
/** |
909
|
|
|
* @group DBAL-825 |
910
|
|
|
*/ |
911
|
|
|
public function testChangeColumnsTypeWithDefaultValue() : void |
912
|
|
|
{ |
913
|
|
|
$tableName = 'column_def_change_type'; |
914
|
|
|
$table = new Table($tableName); |
915
|
|
|
|
916
|
|
|
$table->addColumn('col_int', 'smallint', ['default' => 666]); |
917
|
|
|
$table->addColumn('col_string', 'string', ['default' => 'foo']); |
918
|
|
|
|
919
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
920
|
|
|
|
921
|
|
|
$tableDiff = new TableDiff($tableName); |
922
|
|
|
$tableDiff->fromTable = $table; |
923
|
|
|
$tableDiff->changedColumns['col_int'] = new ColumnDiff( |
924
|
|
|
'col_int', |
925
|
|
|
new Column('col_int', Type::getType('integer'), ['default' => 666]), |
926
|
|
|
['type'], |
927
|
|
|
new Column('col_int', Type::getType('smallint'), ['default' => 666]) |
928
|
|
|
); |
929
|
|
|
|
930
|
|
|
$tableDiff->changedColumns['col_string'] = new ColumnDiff( |
931
|
|
|
'col_string', |
932
|
|
|
new Column('col_string', Type::getType('string'), ['default' => 'foo', 'fixed' => true]), |
933
|
|
|
['fixed'], |
934
|
|
|
new Column('col_string', Type::getType('string'), ['default' => 'foo']) |
935
|
|
|
); |
936
|
|
|
|
937
|
|
|
$this->schemaManager->alterTable($tableDiff); |
938
|
|
|
|
939
|
|
|
$columns = $this->schemaManager->listTableColumns($tableName); |
940
|
|
|
|
941
|
|
|
self::assertInstanceOf(IntegerType::class, $columns['col_int']->getType()); |
942
|
|
|
self::assertEquals(666, $columns['col_int']->getDefault()); |
943
|
|
|
|
944
|
|
|
self::assertInstanceOf(StringType::class, $columns['col_string']->getType()); |
945
|
|
|
self::assertEquals('foo', $columns['col_string']->getDefault()); |
946
|
|
|
} |
947
|
|
|
|
948
|
|
|
/** |
949
|
|
|
* @group DBAL-197 |
950
|
|
|
*/ |
951
|
|
|
public function testListTableWithBlob() : void |
952
|
|
|
{ |
953
|
|
|
$table = new Table('test_blob_table'); |
954
|
|
|
$table->addColumn('id', 'integer', ['comment' => 'This is a comment']); |
955
|
|
|
$table->addColumn('binarydata', 'blob', []); |
956
|
|
|
$table->setPrimaryKey(['id']); |
957
|
|
|
|
958
|
|
|
$this->schemaManager->createTable($table); |
959
|
|
|
|
960
|
|
|
$created = $this->schemaManager->listTableDetails('test_blob_table'); |
961
|
|
|
|
962
|
|
|
self::assertTrue($created->hasColumn('id')); |
963
|
|
|
self::assertTrue($created->hasColumn('binarydata')); |
964
|
|
|
self::assertTrue($created->hasPrimaryKey()); |
965
|
|
|
} |
966
|
|
|
|
967
|
|
|
/** |
968
|
|
|
* @param mixed[] $data |
969
|
|
|
*/ |
970
|
|
|
protected function createTestTable(string $name = 'test_table', array $data = []) : Table |
971
|
|
|
{ |
972
|
|
|
$options = $data['options'] ?? []; |
973
|
|
|
|
974
|
|
|
$table = $this->getTestTable($name, $options); |
975
|
|
|
|
976
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
977
|
|
|
|
978
|
|
|
return $table; |
979
|
|
|
} |
980
|
|
|
|
981
|
|
|
/** |
982
|
|
|
* @param mixed[] $options |
983
|
|
|
*/ |
984
|
|
|
protected function getTestTable(string $name, array $options = []) : Table |
985
|
|
|
{ |
986
|
|
|
$table = new Table($name, [], [], [], false, $options); |
|
|
|
|
987
|
|
|
$table->setSchemaConfig($this->schemaManager->createSchemaConfig()); |
988
|
|
|
$table->addColumn('id', 'integer', ['notnull' => true]); |
989
|
|
|
$table->setPrimaryKey(['id']); |
990
|
|
|
$table->addColumn('test', 'string', ['length' => 255]); |
991
|
|
|
$table->addColumn('foreign_key_test', 'integer'); |
992
|
|
|
|
993
|
|
|
return $table; |
994
|
|
|
} |
995
|
|
|
|
996
|
|
|
protected function getTestCompositeTable(string $name) : Table |
997
|
|
|
{ |
998
|
|
|
$table = new Table($name, [], [], [], false, []); |
|
|
|
|
999
|
|
|
$table->setSchemaConfig($this->schemaManager->createSchemaConfig()); |
1000
|
|
|
$table->addColumn('id', 'integer', ['notnull' => true]); |
1001
|
|
|
$table->addColumn('other_id', 'integer', ['notnull' => true]); |
1002
|
|
|
$table->setPrimaryKey(['id', 'other_id']); |
1003
|
|
|
$table->addColumn('test', 'string', ['length' => 255]); |
1004
|
|
|
|
1005
|
|
|
return $table; |
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
/** |
1009
|
|
|
* @param Table[] $tables |
1010
|
|
|
*/ |
1011
|
|
|
protected function assertHasTable(array $tables) : void |
1012
|
|
|
{ |
1013
|
|
|
$foundTable = false; |
1014
|
|
|
foreach ($tables as $table) { |
1015
|
|
|
self::assertInstanceOf(Table::class, $table, 'No Table instance was found in tables array.'); |
1016
|
|
|
if (strtolower($table->getName()) !== 'list_tables_test_new_name') { |
1017
|
|
|
continue; |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
$foundTable = true; |
1021
|
|
|
} |
1022
|
|
|
self::assertTrue($foundTable, 'Could not find new table'); |
1023
|
|
|
} |
1024
|
|
|
|
1025
|
|
|
public function testListForeignKeysComposite() : void |
1026
|
|
|
{ |
1027
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
1028
|
|
|
$this->markTestSkipped('Does not support foreign key constraints.'); |
1029
|
|
|
} |
1030
|
|
|
|
1031
|
|
|
$this->schemaManager->createTable($this->getTestTable('test_create_fk3')); |
1032
|
|
|
$this->schemaManager->createTable($this->getTestCompositeTable('test_create_fk4')); |
1033
|
|
|
|
1034
|
|
|
$foreignKey = new ForeignKeyConstraint( |
1035
|
|
|
['id', 'foreign_key_test'], |
1036
|
|
|
'test_create_fk4', |
1037
|
|
|
['id', 'other_id'], |
1038
|
|
|
'foreign_key_test_fk2' |
1039
|
|
|
); |
1040
|
|
|
|
1041
|
|
|
$this->schemaManager->createForeignKey($foreignKey, 'test_create_fk3'); |
1042
|
|
|
|
1043
|
|
|
$fkeys = $this->schemaManager->listTableForeignKeys('test_create_fk3'); |
1044
|
|
|
|
1045
|
|
|
self::assertEquals(1, count($fkeys), "Table 'test_create_fk3' has to have one foreign key."); |
1046
|
|
|
|
1047
|
|
|
self::assertInstanceOf(ForeignKeyConstraint::class, $fkeys[0]); |
1048
|
|
|
self::assertEquals(['id', 'foreign_key_test'], array_map('strtolower', $fkeys[0]->getLocalColumns())); |
1049
|
|
|
self::assertEquals(['id', 'other_id'], array_map('strtolower', $fkeys[0]->getForeignColumns())); |
1050
|
|
|
} |
1051
|
|
|
|
1052
|
|
|
/** |
1053
|
|
|
* @group DBAL-44 |
1054
|
|
|
*/ |
1055
|
|
|
public function testColumnDefaultLifecycle() : void |
1056
|
|
|
{ |
1057
|
|
|
$table = new Table('col_def_lifecycle'); |
1058
|
|
|
$table->addColumn('id', 'integer', ['autoincrement' => true]); |
1059
|
|
|
$table->addColumn('column1', 'string', ['default' => null]); |
1060
|
|
|
$table->addColumn('column2', 'string', ['default' => false]); |
1061
|
|
|
$table->addColumn('column3', 'string', ['default' => true]); |
1062
|
|
|
$table->addColumn('column4', 'string', ['default' => 0]); |
1063
|
|
|
$table->addColumn('column5', 'string', ['default' => '']); |
1064
|
|
|
$table->addColumn('column6', 'string', ['default' => 'def']); |
1065
|
|
|
$table->addColumn('column7', 'integer', ['default' => 0]); |
1066
|
|
|
$table->setPrimaryKey(['id']); |
1067
|
|
|
|
1068
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
1069
|
|
|
|
1070
|
|
|
$columns = $this->schemaManager->listTableColumns('col_def_lifecycle'); |
1071
|
|
|
|
1072
|
|
|
self::assertNull($columns['id']->getDefault()); |
1073
|
|
|
self::assertNull($columns['column1']->getDefault()); |
1074
|
|
|
self::assertSame('', $columns['column2']->getDefault()); |
1075
|
|
|
self::assertSame('1', $columns['column3']->getDefault()); |
1076
|
|
|
self::assertSame('0', $columns['column4']->getDefault()); |
1077
|
|
|
self::assertSame('', $columns['column5']->getDefault()); |
1078
|
|
|
self::assertSame('def', $columns['column6']->getDefault()); |
1079
|
|
|
self::assertSame('0', $columns['column7']->getDefault()); |
1080
|
|
|
|
1081
|
|
|
$diffTable = clone $table; |
1082
|
|
|
|
1083
|
|
|
$diffTable->changeColumn('column1', ['default' => false]); |
1084
|
|
|
$diffTable->changeColumn('column2', ['default' => null]); |
1085
|
|
|
$diffTable->changeColumn('column3', ['default' => false]); |
1086
|
|
|
$diffTable->changeColumn('column4', ['default' => null]); |
1087
|
|
|
$diffTable->changeColumn('column5', ['default' => false]); |
1088
|
|
|
$diffTable->changeColumn('column6', ['default' => 666]); |
1089
|
|
|
$diffTable->changeColumn('column7', ['default' => null]); |
1090
|
|
|
|
1091
|
|
|
$comparator = new Comparator(); |
1092
|
|
|
|
1093
|
|
|
$this->schemaManager->alterTable($comparator->diffTable($table, $diffTable)); |
1094
|
|
|
|
1095
|
|
|
$columns = $this->schemaManager->listTableColumns('col_def_lifecycle'); |
1096
|
|
|
|
1097
|
|
|
self::assertSame('', $columns['column1']->getDefault()); |
1098
|
|
|
self::assertNull($columns['column2']->getDefault()); |
1099
|
|
|
self::assertSame('', $columns['column3']->getDefault()); |
1100
|
|
|
self::assertNull($columns['column4']->getDefault()); |
1101
|
|
|
self::assertSame('', $columns['column5']->getDefault()); |
1102
|
|
|
self::assertSame('666', $columns['column6']->getDefault()); |
1103
|
|
|
self::assertNull($columns['column7']->getDefault()); |
1104
|
|
|
} |
1105
|
|
|
|
1106
|
|
|
public function testListTableWithBinary() : void |
1107
|
|
|
{ |
1108
|
|
|
$tableName = 'test_binary_table'; |
1109
|
|
|
|
1110
|
|
|
$table = new Table($tableName); |
1111
|
|
|
$table->addColumn('id', 'integer'); |
1112
|
|
|
$table->addColumn('column_varbinary', 'binary', []); |
1113
|
|
|
$table->addColumn('column_binary', 'binary', ['fixed' => true]); |
1114
|
|
|
$table->setPrimaryKey(['id']); |
1115
|
|
|
|
1116
|
|
|
$this->schemaManager->createTable($table); |
1117
|
|
|
|
1118
|
|
|
$table = $this->schemaManager->listTableDetails($tableName); |
1119
|
|
|
|
1120
|
|
|
self::assertInstanceOf(BinaryType::class, $table->getColumn('column_varbinary')->getType()); |
1121
|
|
|
self::assertFalse($table->getColumn('column_varbinary')->getFixed()); |
1122
|
|
|
|
1123
|
|
|
self::assertInstanceOf(BinaryType::class, $table->getColumn('column_binary')->getType()); |
1124
|
|
|
self::assertTrue($table->getColumn('column_binary')->getFixed()); |
1125
|
|
|
} |
1126
|
|
|
|
1127
|
|
|
public function testListTableDetailsWithFullQualifiedTableName() : void |
1128
|
|
|
{ |
1129
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) { |
1130
|
|
|
$this->markTestSkipped('Test only works on platforms that support schemas.'); |
1131
|
|
|
} |
1132
|
|
|
|
1133
|
|
|
$defaultSchemaName = $this->schemaManager->getDatabasePlatform()->getDefaultSchemaName(); |
1134
|
|
|
$primaryTableName = 'primary_table'; |
1135
|
|
|
$foreignTableName = 'foreign_table'; |
1136
|
|
|
|
1137
|
|
|
$table = new Table($foreignTableName); |
1138
|
|
|
$table->addColumn('id', 'integer', ['autoincrement' => true]); |
1139
|
|
|
$table->setPrimaryKey(['id']); |
1140
|
|
|
|
1141
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
1142
|
|
|
|
1143
|
|
|
$table = new Table($primaryTableName); |
1144
|
|
|
$table->addColumn('id', 'integer', ['autoincrement' => true]); |
1145
|
|
|
$table->addColumn('foo', 'integer'); |
1146
|
|
|
$table->addColumn('bar', 'string'); |
1147
|
|
|
$table->addForeignKeyConstraint($foreignTableName, ['foo'], ['id']); |
1148
|
|
|
$table->addIndex(['bar']); |
1149
|
|
|
$table->setPrimaryKey(['id']); |
1150
|
|
|
|
1151
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
1152
|
|
|
|
1153
|
|
|
self::assertEquals( |
1154
|
|
|
$this->schemaManager->listTableColumns($primaryTableName), |
1155
|
|
|
$this->schemaManager->listTableColumns($defaultSchemaName . '.' . $primaryTableName) |
1156
|
|
|
); |
1157
|
|
|
self::assertEquals( |
1158
|
|
|
$this->schemaManager->listTableIndexes($primaryTableName), |
1159
|
|
|
$this->schemaManager->listTableIndexes($defaultSchemaName . '.' . $primaryTableName) |
1160
|
|
|
); |
1161
|
|
|
self::assertEquals( |
1162
|
|
|
$this->schemaManager->listTableForeignKeys($primaryTableName), |
1163
|
|
|
$this->schemaManager->listTableForeignKeys($defaultSchemaName . '.' . $primaryTableName) |
1164
|
|
|
); |
1165
|
|
|
} |
1166
|
|
|
|
1167
|
|
|
public function testCommentStringsAreQuoted() : void |
1168
|
|
|
{ |
1169
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() && |
1170
|
|
|
! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() && |
1171
|
|
|
$this->connection->getDatabasePlatform()->getName() !== 'mssql') { |
1172
|
|
|
$this->markTestSkipped('Database does not support column comments.'); |
1173
|
|
|
} |
1174
|
|
|
|
1175
|
|
|
$table = new Table('my_table'); |
1176
|
|
|
$table->addColumn('id', 'integer', ['comment' => "It's a comment with a quote"]); |
1177
|
|
|
$table->setPrimaryKey(['id']); |
1178
|
|
|
|
1179
|
|
|
$this->schemaManager->createTable($table); |
1180
|
|
|
|
1181
|
|
|
$columns = $this->schemaManager->listTableColumns('my_table'); |
1182
|
|
|
self::assertEquals("It's a comment with a quote", $columns['id']->getComment()); |
1183
|
|
|
} |
1184
|
|
|
|
1185
|
|
|
public function testCommentNotDuplicated() : void |
1186
|
|
|
{ |
1187
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments()) { |
1188
|
|
|
$this->markTestSkipped('Database does not support column comments.'); |
1189
|
|
|
} |
1190
|
|
|
|
1191
|
|
|
$options = [ |
1192
|
|
|
'type' => Type::getType('integer'), |
1193
|
|
|
'default' => 0, |
1194
|
|
|
'notnull' => true, |
1195
|
|
|
'comment' => 'expected+column+comment', |
1196
|
|
|
]; |
1197
|
|
|
$columnDefinition = substr($this->connection->getDatabasePlatform()->getColumnDeclarationSQL('id', $options), strlen('id') + 1); |
1198
|
|
|
|
1199
|
|
|
$table = new Table('my_table'); |
1200
|
|
|
$table->addColumn('id', 'integer', ['columnDefinition' => $columnDefinition, 'comment' => 'unexpected_column_comment']); |
1201
|
|
|
$sql = $this->connection->getDatabasePlatform()->getCreateTableSQL($table); |
1202
|
|
|
|
1203
|
|
|
self::assertStringContainsString('expected+column+comment', $sql[0]); |
1204
|
|
|
self::assertStringNotContainsString('unexpected_column_comment', $sql[0]); |
1205
|
|
|
} |
1206
|
|
|
|
1207
|
|
|
/** |
1208
|
|
|
* @group DBAL-1009 |
1209
|
|
|
* @dataProvider getAlterColumnComment |
1210
|
|
|
*/ |
1211
|
|
|
public function testAlterColumnComment( |
1212
|
|
|
?string $comment1, |
1213
|
|
|
?string $expectedComment1, |
1214
|
|
|
?string $comment2, |
1215
|
|
|
?string $expectedComment2 |
1216
|
|
|
) : void { |
1217
|
|
|
if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() && |
1218
|
|
|
! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() && |
1219
|
|
|
$this->connection->getDatabasePlatform()->getName() !== 'mssql') { |
1220
|
|
|
$this->markTestSkipped('Database does not support column comments.'); |
1221
|
|
|
} |
1222
|
|
|
|
1223
|
|
|
$offlineTable = new Table('alter_column_comment_test'); |
1224
|
|
|
$offlineTable->addColumn('comment1', 'integer', ['comment' => $comment1]); |
1225
|
|
|
$offlineTable->addColumn('comment2', 'integer', ['comment' => $comment2]); |
1226
|
|
|
$offlineTable->addColumn('no_comment1', 'integer'); |
1227
|
|
|
$offlineTable->addColumn('no_comment2', 'integer'); |
1228
|
|
|
$this->schemaManager->dropAndCreateTable($offlineTable); |
1229
|
|
|
|
1230
|
|
|
$onlineTable = $this->schemaManager->listTableDetails('alter_column_comment_test'); |
1231
|
|
|
|
1232
|
|
|
self::assertSame($expectedComment1, $onlineTable->getColumn('comment1')->getComment()); |
1233
|
|
|
self::assertSame($expectedComment2, $onlineTable->getColumn('comment2')->getComment()); |
1234
|
|
|
self::assertNull($onlineTable->getColumn('no_comment1')->getComment()); |
1235
|
|
|
self::assertNull($onlineTable->getColumn('no_comment2')->getComment()); |
1236
|
|
|
|
1237
|
|
|
$onlineTable->changeColumn('comment1', ['comment' => $comment2]); |
1238
|
|
|
$onlineTable->changeColumn('comment2', ['comment' => $comment1]); |
1239
|
|
|
$onlineTable->changeColumn('no_comment1', ['comment' => $comment1]); |
1240
|
|
|
$onlineTable->changeColumn('no_comment2', ['comment' => $comment2]); |
1241
|
|
|
|
1242
|
|
|
$comparator = new Comparator(); |
1243
|
|
|
|
1244
|
|
|
$tableDiff = $comparator->diffTable($offlineTable, $onlineTable); |
1245
|
|
|
|
1246
|
|
|
self::assertInstanceOf(TableDiff::class, $tableDiff); |
1247
|
|
|
|
1248
|
|
|
$this->schemaManager->alterTable($tableDiff); |
1249
|
|
|
|
1250
|
|
|
$onlineTable = $this->schemaManager->listTableDetails('alter_column_comment_test'); |
1251
|
|
|
|
1252
|
|
|
self::assertSame($expectedComment2, $onlineTable->getColumn('comment1')->getComment()); |
1253
|
|
|
self::assertSame($expectedComment1, $onlineTable->getColumn('comment2')->getComment()); |
1254
|
|
|
self::assertSame($expectedComment1, $onlineTable->getColumn('no_comment1')->getComment()); |
1255
|
|
|
self::assertSame($expectedComment2, $onlineTable->getColumn('no_comment2')->getComment()); |
1256
|
|
|
} |
1257
|
|
|
|
1258
|
|
|
/** |
1259
|
|
|
* @return mixed[][] |
1260
|
|
|
*/ |
1261
|
|
|
public static function getAlterColumnComment() : iterable |
1262
|
|
|
{ |
1263
|
|
|
return [ |
1264
|
|
|
[null, null, ' ', ' '], |
1265
|
|
|
[null, null, '0', '0'], |
1266
|
|
|
[null, null, 'foo', 'foo'], |
1267
|
|
|
|
1268
|
|
|
['', null, ' ', ' '], |
1269
|
|
|
['', null, '0', '0'], |
1270
|
|
|
['', null, 'foo', 'foo'], |
1271
|
|
|
|
1272
|
|
|
[' ', ' ', '0', '0'], |
1273
|
|
|
[' ', ' ', 'foo', 'foo'], |
1274
|
|
|
|
1275
|
|
|
['0', '0', 'foo', 'foo'], |
1276
|
|
|
]; |
1277
|
|
|
} |
1278
|
|
|
|
1279
|
|
|
/** |
1280
|
|
|
* @group DBAL-1095 |
1281
|
|
|
*/ |
1282
|
|
|
public function testDoesNotListIndexesImplicitlyCreatedByForeignKeys() : void |
1283
|
|
|
{ |
1284
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) { |
1285
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have foreign keys.'); |
1286
|
|
|
} |
1287
|
|
|
|
1288
|
|
|
$primaryTable = new Table('test_list_index_impl_primary'); |
1289
|
|
|
$primaryTable->addColumn('id', 'integer'); |
1290
|
|
|
$primaryTable->setPrimaryKey(['id']); |
1291
|
|
|
|
1292
|
|
|
$foreignTable = new Table('test_list_index_impl_foreign'); |
1293
|
|
|
$foreignTable->addColumn('fk1', 'integer'); |
1294
|
|
|
$foreignTable->addColumn('fk2', 'integer'); |
1295
|
|
|
$foreignTable->addIndex(['fk1'], 'explicit_fk1_idx'); |
1296
|
|
|
$foreignTable->addForeignKeyConstraint('test_list_index_impl_primary', ['fk1'], ['id']); |
1297
|
|
|
$foreignTable->addForeignKeyConstraint('test_list_index_impl_primary', ['fk2'], ['id']); |
1298
|
|
|
|
1299
|
|
|
$this->schemaManager->dropAndCreateTable($primaryTable); |
1300
|
|
|
$this->schemaManager->dropAndCreateTable($foreignTable); |
1301
|
|
|
|
1302
|
|
|
$indexes = $this->schemaManager->listTableIndexes('test_list_index_impl_foreign'); |
1303
|
|
|
|
1304
|
|
|
self::assertCount(2, $indexes); |
1305
|
|
|
self::assertArrayHasKey('explicit_fk1_idx', $indexes); |
1306
|
|
|
self::assertArrayHasKey('idx_3d6c147fdc58d6c', $indexes); |
1307
|
|
|
} |
1308
|
|
|
|
1309
|
|
|
/** |
1310
|
|
|
* @after |
1311
|
|
|
*/ |
1312
|
|
|
public function removeJsonArrayTable() : void |
1313
|
|
|
{ |
1314
|
|
|
if (! $this->schemaManager->tablesExist(['json_array_test'])) { |
1315
|
|
|
return; |
1316
|
|
|
} |
1317
|
|
|
|
1318
|
|
|
$this->schemaManager->dropTable('json_array_test'); |
1319
|
|
|
} |
1320
|
|
|
|
1321
|
|
|
/** |
1322
|
|
|
* @group 2782 |
1323
|
|
|
* @group 6654 |
1324
|
|
|
*/ |
1325
|
|
|
public function testComparatorShouldReturnFalseWhenLegacyJsonArrayColumnHasComment() : void |
1326
|
|
|
{ |
1327
|
|
|
$table = new Table('json_array_test'); |
1328
|
|
|
$table->addColumn('parameters', 'json_array'); |
1329
|
|
|
|
1330
|
|
|
$this->schemaManager->createTable($table); |
1331
|
|
|
|
1332
|
|
|
$comparator = new Comparator(); |
1333
|
|
|
$tableDiff = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table); |
1334
|
|
|
|
1335
|
|
|
self::assertFalse($tableDiff); |
1336
|
|
|
} |
1337
|
|
|
|
1338
|
|
|
/** |
1339
|
|
|
* @group 2782 |
1340
|
|
|
* @group 6654 |
1341
|
|
|
*/ |
1342
|
|
|
public function testComparatorShouldModifyOnlyTheCommentWhenUpdatingFromJsonArrayTypeOnLegacyPlatforms() : void |
1343
|
|
|
{ |
1344
|
|
|
if ($this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) { |
1345
|
|
|
$this->markTestSkipped('This test is only supported on platforms that do not have native JSON type.'); |
1346
|
|
|
} |
1347
|
|
|
|
1348
|
|
|
$table = new Table('json_array_test'); |
1349
|
|
|
$table->addColumn('parameters', 'json_array'); |
1350
|
|
|
|
1351
|
|
|
$this->schemaManager->createTable($table); |
1352
|
|
|
|
1353
|
|
|
$table = new Table('json_array_test'); |
1354
|
|
|
$table->addColumn('parameters', 'json'); |
1355
|
|
|
|
1356
|
|
|
$comparator = new Comparator(); |
1357
|
|
|
$tableDiff = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table); |
1358
|
|
|
|
1359
|
|
|
self::assertInstanceOf(TableDiff::class, $tableDiff); |
1360
|
|
|
|
1361
|
|
|
$changedColumn = $tableDiff->changedColumns['parameters'] ?? $tableDiff->changedColumns['PARAMETERS']; |
1362
|
|
|
|
1363
|
|
|
self::assertSame(['comment'], $changedColumn->changedProperties); |
1364
|
|
|
} |
1365
|
|
|
|
1366
|
|
|
/** |
1367
|
|
|
* @group 2782 |
1368
|
|
|
* @group 6654 |
1369
|
|
|
*/ |
1370
|
|
|
public function testComparatorShouldAddCommentToLegacyJsonArrayTypeThatDoesNotHaveIt() : void |
1371
|
|
|
{ |
1372
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) { |
1373
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have native JSON type.'); |
1374
|
|
|
} |
1375
|
|
|
|
1376
|
|
|
$this->connection->executeQuery('CREATE TABLE json_array_test (parameters JSON NOT NULL)'); |
1377
|
|
|
|
1378
|
|
|
$table = new Table('json_array_test'); |
1379
|
|
|
$table->addColumn('parameters', 'json_array'); |
1380
|
|
|
|
1381
|
|
|
$comparator = new Comparator(); |
1382
|
|
|
$tableDiff = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table); |
1383
|
|
|
|
1384
|
|
|
self::assertInstanceOf(TableDiff::class, $tableDiff); |
1385
|
|
|
self::assertSame(['comment'], $tableDiff->changedColumns['parameters']->changedProperties); |
1386
|
|
|
} |
1387
|
|
|
|
1388
|
|
|
/** |
1389
|
|
|
* @group 2782 |
1390
|
|
|
* @group 6654 |
1391
|
|
|
*/ |
1392
|
|
|
public function testComparatorShouldReturnAllChangesWhenUsingLegacyJsonArrayType() : void |
1393
|
|
|
{ |
1394
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) { |
1395
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have native JSON type.'); |
1396
|
|
|
} |
1397
|
|
|
|
1398
|
|
|
$this->connection->executeQuery('CREATE TABLE json_array_test (parameters JSON DEFAULT NULL)'); |
1399
|
|
|
|
1400
|
|
|
$table = new Table('json_array_test'); |
1401
|
|
|
$table->addColumn('parameters', 'json_array'); |
1402
|
|
|
|
1403
|
|
|
$comparator = new Comparator(); |
1404
|
|
|
$tableDiff = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table); |
1405
|
|
|
|
1406
|
|
|
self::assertInstanceOf(TableDiff::class, $tableDiff); |
1407
|
|
|
self::assertSame(['notnull', 'comment'], $tableDiff->changedColumns['parameters']->changedProperties); |
1408
|
|
|
} |
1409
|
|
|
|
1410
|
|
|
/** |
1411
|
|
|
* @group 2782 |
1412
|
|
|
* @group 6654 |
1413
|
|
|
*/ |
1414
|
|
|
public function testComparatorShouldReturnAllChangesWhenUsingLegacyJsonArrayTypeEvenWhenPlatformHasJsonSupport() : void |
1415
|
|
|
{ |
1416
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) { |
1417
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have native JSON type.'); |
1418
|
|
|
} |
1419
|
|
|
|
1420
|
|
|
$this->connection->executeQuery('CREATE TABLE json_array_test (parameters JSON DEFAULT NULL)'); |
1421
|
|
|
|
1422
|
|
|
$table = new Table('json_array_test'); |
1423
|
|
|
$table->addColumn('parameters', 'json_array'); |
1424
|
|
|
|
1425
|
|
|
$comparator = new Comparator(); |
1426
|
|
|
$tableDiff = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table); |
1427
|
|
|
|
1428
|
|
|
self::assertInstanceOf(TableDiff::class, $tableDiff); |
1429
|
|
|
self::assertSame(['notnull', 'comment'], $tableDiff->changedColumns['parameters']->changedProperties); |
1430
|
|
|
} |
1431
|
|
|
|
1432
|
|
|
/** |
1433
|
|
|
* @group 2782 |
1434
|
|
|
* @group 6654 |
1435
|
|
|
*/ |
1436
|
|
|
public function testComparatorShouldNotAddCommentToJsonTypeSinceItIsTheDefaultNow() : void |
1437
|
|
|
{ |
1438
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) { |
1439
|
|
|
$this->markTestSkipped('This test is only supported on platforms that have native JSON type.'); |
1440
|
|
|
} |
1441
|
|
|
|
1442
|
|
|
$this->connection->executeQuery('CREATE TABLE json_test (parameters JSON NOT NULL)'); |
1443
|
|
|
|
1444
|
|
|
$table = new Table('json_test'); |
1445
|
|
|
$table->addColumn('parameters', 'json'); |
1446
|
|
|
|
1447
|
|
|
$comparator = new Comparator(); |
1448
|
|
|
$tableDiff = $comparator->diffTable($this->schemaManager->listTableDetails('json_test'), $table); |
1449
|
|
|
|
1450
|
|
|
self::assertFalse($tableDiff); |
1451
|
|
|
} |
1452
|
|
|
|
1453
|
|
|
/** |
1454
|
|
|
* @dataProvider commentsProvider |
1455
|
|
|
* @group 2596 |
1456
|
|
|
*/ |
1457
|
|
|
public function testExtractDoctrineTypeFromComment(string $comment, string $expected, string $currentType) : void |
1458
|
|
|
{ |
1459
|
|
|
$result = $this->schemaManager->extractDoctrineTypeFromComment($comment, $currentType); |
1460
|
|
|
|
1461
|
|
|
self::assertSame($expected, $result); |
1462
|
|
|
} |
1463
|
|
|
|
1464
|
|
|
/** |
1465
|
|
|
* @return string[][] |
1466
|
|
|
*/ |
1467
|
|
|
public function commentsProvider() : array |
1468
|
|
|
{ |
1469
|
|
|
$currentType = 'current type'; |
1470
|
|
|
|
1471
|
|
|
return [ |
1472
|
|
|
'invalid custom type comments' => ['should.return.current.type', $currentType, $currentType], |
1473
|
|
|
'valid doctrine type' => ['(DC2Type:guid)', 'guid', $currentType], |
1474
|
|
|
'valid with dots' => ['(DC2Type:type.should.return)', 'type.should.return', $currentType], |
1475
|
|
|
'valid with namespace' => ['(DC2Type:Namespace\Class)', 'Namespace\Class', $currentType], |
1476
|
|
|
'valid with extra closing bracket' => ['(DC2Type:should.stop)).before)', 'should.stop', $currentType], |
1477
|
|
|
'valid with extra opening brackets' => ['(DC2Type:should((.stop)).before)', 'should((.stop', $currentType], |
1478
|
|
|
]; |
1479
|
|
|
} |
1480
|
|
|
|
1481
|
|
|
public function testCreateAndListSequences() : void |
1482
|
|
|
{ |
1483
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsSequences()) { |
1484
|
|
|
self::markTestSkipped('This test is only supported on platforms that support sequences.'); |
1485
|
|
|
} |
1486
|
|
|
|
1487
|
|
|
$sequence1Name = 'sequence_1'; |
1488
|
|
|
$sequence1AllocationSize = 1; |
1489
|
|
|
$sequence1InitialValue = 2; |
1490
|
|
|
$sequence2Name = 'sequence_2'; |
1491
|
|
|
$sequence2AllocationSize = 3; |
1492
|
|
|
$sequence2InitialValue = 4; |
1493
|
|
|
$sequence1 = new Sequence($sequence1Name, $sequence1AllocationSize, $sequence1InitialValue); |
1494
|
|
|
$sequence2 = new Sequence($sequence2Name, $sequence2AllocationSize, $sequence2InitialValue); |
1495
|
|
|
|
1496
|
|
|
$this->schemaManager->createSequence($sequence1); |
1497
|
|
|
$this->schemaManager->createSequence($sequence2); |
1498
|
|
|
|
1499
|
|
|
/** @var Sequence[] $actualSequences */ |
1500
|
|
|
$actualSequences = []; |
1501
|
|
|
foreach ($this->schemaManager->listSequences() as $sequence) { |
1502
|
|
|
$actualSequences[$sequence->getName()] = $sequence; |
1503
|
|
|
} |
1504
|
|
|
|
1505
|
|
|
$actualSequence1 = $actualSequences[$sequence1Name]; |
1506
|
|
|
$actualSequence2 = $actualSequences[$sequence2Name]; |
1507
|
|
|
|
1508
|
|
|
self::assertSame($sequence1Name, $actualSequence1->getName()); |
1509
|
|
|
self::assertEquals($sequence1AllocationSize, $actualSequence1->getAllocationSize()); |
1510
|
|
|
self::assertEquals($sequence1InitialValue, $actualSequence1->getInitialValue()); |
1511
|
|
|
|
1512
|
|
|
self::assertSame($sequence2Name, $actualSequence2->getName()); |
1513
|
|
|
self::assertEquals($sequence2AllocationSize, $actualSequence2->getAllocationSize()); |
1514
|
|
|
self::assertEquals($sequence2InitialValue, $actualSequence2->getInitialValue()); |
1515
|
|
|
} |
1516
|
|
|
|
1517
|
|
|
/** |
1518
|
|
|
* @group #3086 |
1519
|
|
|
*/ |
1520
|
|
|
public function testComparisonWithAutoDetectedSequenceDefinition() : void |
1521
|
|
|
{ |
1522
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsSequences()) { |
1523
|
|
|
self::markTestSkipped('This test is only supported on platforms that support sequences.'); |
1524
|
|
|
} |
1525
|
|
|
|
1526
|
|
|
$sequenceName = 'sequence_auto_detect_test'; |
1527
|
|
|
$sequenceAllocationSize = 5; |
1528
|
|
|
$sequenceInitialValue = 10; |
1529
|
|
|
$sequence = new Sequence($sequenceName, $sequenceAllocationSize, $sequenceInitialValue); |
1530
|
|
|
|
1531
|
|
|
$this->schemaManager->dropAndCreateSequence($sequence); |
1532
|
|
|
|
1533
|
|
|
$createdSequence = array_values( |
1534
|
|
|
array_filter( |
1535
|
|
|
$this->schemaManager->listSequences(), |
1536
|
|
|
static function (Sequence $sequence) use ($sequenceName) : bool { |
1537
|
|
|
return strcasecmp($sequence->getName(), $sequenceName) === 0; |
1538
|
|
|
} |
1539
|
|
|
) |
1540
|
|
|
)[0] ?? null; |
1541
|
|
|
|
1542
|
|
|
self::assertNotNull($createdSequence); |
1543
|
|
|
|
1544
|
|
|
$comparator = new Comparator(); |
1545
|
|
|
$tableDiff = $comparator->diffSequence($createdSequence, $sequence); |
1546
|
|
|
|
1547
|
|
|
self::assertFalse($tableDiff); |
1548
|
|
|
} |
1549
|
|
|
|
1550
|
|
|
/** |
1551
|
|
|
* @group DBAL-2921 |
1552
|
|
|
*/ |
1553
|
|
|
public function testPrimaryKeyAutoIncrement() : void |
1554
|
|
|
{ |
1555
|
|
|
$table = new Table('test_pk_auto_increment'); |
1556
|
|
|
$table->addColumn('id', 'integer', ['autoincrement' => true]); |
1557
|
|
|
$table->addColumn('text', 'string'); |
1558
|
|
|
$table->setPrimaryKey(['id']); |
1559
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
1560
|
|
|
|
1561
|
|
|
$this->connection->insert('test_pk_auto_increment', ['text' => '1']); |
1562
|
|
|
|
1563
|
|
|
$query = $this->connection->query('SELECT id FROM test_pk_auto_increment WHERE text = \'1\''); |
1564
|
|
|
$query->execute(); |
1565
|
|
|
$lastUsedIdBeforeDelete = (int) $query->fetchColumn(); |
1566
|
|
|
|
1567
|
|
|
$this->connection->query('DELETE FROM test_pk_auto_increment'); |
1568
|
|
|
|
1569
|
|
|
$this->connection->insert('test_pk_auto_increment', ['text' => '2']); |
1570
|
|
|
|
1571
|
|
|
$query = $this->connection->query('SELECT id FROM test_pk_auto_increment WHERE text = \'2\''); |
1572
|
|
|
$query->execute(); |
1573
|
|
|
$lastUsedIdAfterDelete = (int) $query->fetchColumn(); |
1574
|
|
|
|
1575
|
|
|
$this->assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete); |
1576
|
|
|
} |
1577
|
|
|
|
1578
|
|
|
public function testGenerateAnIndexWithPartialColumnLength() : void |
1579
|
|
|
{ |
1580
|
|
|
if (! $this->schemaManager->getDatabasePlatform()->supportsColumnLengthIndexes()) { |
1581
|
|
|
self::markTestSkipped('This test is only supported on platforms that support indexes with column length definitions.'); |
1582
|
|
|
} |
1583
|
|
|
|
1584
|
|
|
$table = new Table('test_partial_column_index'); |
1585
|
|
|
$table->addColumn('long_column', 'string', ['length' => 40]); |
1586
|
|
|
$table->addColumn('standard_column', 'integer'); |
1587
|
|
|
$table->addIndex(['long_column'], 'partial_long_column_idx', [], ['lengths' => [4]]); |
1588
|
|
|
$table->addIndex(['standard_column', 'long_column'], 'standard_and_partial_idx', [], ['lengths' => [null, 2]]); |
1589
|
|
|
|
1590
|
|
|
$expected = $table->getIndexes(); |
1591
|
|
|
|
1592
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
1593
|
|
|
|
1594
|
|
|
$onlineTable = $this->schemaManager->listTableDetails('test_partial_column_index'); |
1595
|
|
|
self::assertEquals($expected, $onlineTable->getIndexes()); |
1596
|
|
|
} |
1597
|
|
|
|
1598
|
|
|
public function testCommentInTable() : void |
1599
|
|
|
{ |
1600
|
|
|
$table = new Table('table_with_comment'); |
1601
|
|
|
$table->addColumn('id', 'integer'); |
1602
|
|
|
$table->setComment('Foo with control characters \'\\'); |
1603
|
|
|
$this->schemaManager->dropAndCreateTable($table); |
1604
|
|
|
|
1605
|
|
|
$table = $this->schemaManager->listTableDetails('table_with_comment'); |
1606
|
|
|
self::assertSame('Foo with control characters \'\\', $table->getComment()); |
1607
|
|
|
} |
1608
|
|
|
} |
1609
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.