Failed Conditions
Pull Request — develop (#3348)
by Sergei
125:02 queued 59:58
created

AbstractSchemaManager::removeDoctrineTypeFromComment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
namespace Doctrine\DBAL\Schema;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\ConnectionException;
7
use Doctrine\DBAL\DBALException;
8
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
9
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
10
use Doctrine\DBAL\Events;
11
use Doctrine\DBAL\Platforms\AbstractPlatform;
12
use Throwable;
13
use function array_filter;
14
use function array_intersect;
15
use function array_map;
16
use function array_values;
17
use function assert;
18
use function call_user_func_array;
19
use function count;
20
use function func_get_args;
21
use function is_array;
22
use function is_callable;
23
use function preg_match;
24
use function strtolower;
25
26
/**
27
 * Base class for schema managers. Schema managers are used to inspect and/or
28
 * modify the database schema/structure.
29
 */
30
abstract class AbstractSchemaManager
31
{
32
    /**
33
     * Holds instance of the Doctrine connection for this schema manager.
34
     *
35
     * @var Connection
36
     */
37
    protected $_conn;
38
39
    /**
40
     * Holds instance of the database platform used for this schema manager.
41
     *
42
     * @var AbstractPlatform
43
     */
44
    protected $_platform;
45
46
    /**
47
     * Constructor. Accepts the Connection instance to manage the schema for.
48
     */
49
    public function __construct(Connection $conn, ?AbstractPlatform $platform = null)
50 5537
    {
51
        $this->_conn     = $conn;
52 5537
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
53 5537
    }
54 5537
55
    /**
56
     * Returns the associated platform.
57
     */
58
    public function getDatabasePlatform() : AbstractPlatform
59
    {
60
        return $this->_platform;
61 3718
    }
62
63 3718
    /**
64
     * Tries any method on the schema manager. Normally a method throws an
65
     * exception when your DBMS doesn't support it or if an error occurs.
66
     * This method allows you to try and method on your SchemaManager
67
     * instance and will return false if it does not work or is not supported.
68
     *
69
     * <code>
70
     * $result = $sm->tryMethod('dropView', 'view_name');
71
     * </code>
72
     *
73
     * @return mixed
74
     */
75
    public function tryMethod()
76
    {
77
        $args   = func_get_args();
78 5349
        $method = $args[0];
79
        unset($args[0]);
80 5349
        $args = array_values($args);
81 5349
82 5349
        $callback = [$this, $method];
83 5349
        assert(is_callable($callback));
84
85 5349
        try {
86 5349
            return call_user_func_array($callback, $args);
87
        } catch (Throwable $e) {
88
            return false;
89 5349
        }
90 5223
    }
91 5223
92
    /**
93
     * Lists the available databases for this connection.
94
     *
95
     * @return string[]
96
     */
97
    public function listDatabases() : array
98
    {
99
        $sql = $this->_platform->getListDatabasesSQL();
100 3301
101
        $databases = $this->_conn->fetchAll($sql);
102 3301
103
        return $this->_getPortableDatabasesList($databases);
104 3156
    }
105
106 3156
    /**
107
     * Returns a list of all namespaces in the current database.
108
     *
109
     * @return string[]
110
     */
111
    public function listNamespaceNames() : array
112
    {
113
        $sql = $this->_platform->getListNamespacesSQL();
114 1139
115
        $namespaces = $this->_conn->fetchAll($sql);
116 1139
117
        return $this->getPortableNamespacesList($namespaces);
118 1139
    }
119
120 1139
    /**
121
     * Lists the available sequences for this connection.
122
     *
123
     * @return Sequence[]
124
     */
125
    public function listSequences(?string $database = null) : array
126
    {
127
        if ($database === null) {
128
            $database = $this->_conn->getDatabase();
129
        }
130 1168
        $sql = $this->_platform->getListSequencesSQL($database);
131
132 1168
        $sequences = $this->_conn->fetchAll($sql);
133 1168
134
        return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
135 1168
    }
136
137 1168
    /**
138
     * Lists the columns for a given table.
139 1168
     *
140
     * In contrast to other libraries and to the old version of Doctrine,
141
     * this column definition does try to contain the 'primary' field for
142
     * the reason that it is not portable across different RDBMS. Use
143
     * {@see listTableIndexes($tableName)} to retrieve the primary key
144
     * of a table. We're a RDBMS specifies more details these are held
145
     * in the platformDetails array.
146
     *
147
     * @param string $table The name of the table.
148
     *
149
     * @return Column[]
150
     */
151
    public function listTableColumns(string $table, ?string $database = null) : array
152
    {
153
        if (! $database) {
154
            $database = $this->_conn->getDatabase();
155
        }
156
157 4230
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
158
159 4230
        $tableColumns = $this->_conn->fetchAll($sql);
160 4229
161
        return $this->_getPortableTableColumnList($table, $database, $tableColumns);
162
    }
163 4230
164
    /**
165 4230
     * Lists the indexes for a given table returning an array of Index instances.
166
     *
167 4230
     * Keys of the portable indexes list are all lower-cased.
168
     *
169
     * @param string $table The name of the table.
170
     *
171
     * @return Index[]
172
     */
173
    public function listTableIndexes(string $table) : array
174
    {
175
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
176
177
        $tableIndexes = $this->_conn->fetchAll($sql);
178
179 3920
        return $this->_getPortableTableIndexesList($tableIndexes, $table);
180
    }
181 3920
182
    /**
183 3920
     * Returns true if all the given tables exist.
184
     *
185 3920
     * @param string|string[] $tableNames
186
     */
187
    public function tablesExist($tableNames) : bool
188
    {
189
        $tableNames = array_map('strtolower', (array) $tableNames);
190
191
        return count($tableNames) === count(array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
192
    }
193
194
    /**
195 4646
     * Returns a list of all tables in the current database.
196
     *
197 4646
     * @return string[]
198
     */
199 4646
    public function listTableNames() : array
200
    {
201
        $sql = $this->_platform->getListTablesSQL();
202
203
        $tables     = $this->_conn->fetchAll($sql);
204
        $tableNames = $this->_getPortableTablesList($tables);
205
206
        return $this->filterAssetNames($tableNames);
207 4490
    }
208
209 4490
    /**
210
     * Filters asset names if they are configured to return only a subset of all
211 4490
     * the found elements.
212 4490
     *
213
     * @param mixed[] $assetNames
214 4490
     *
215
     * @return mixed[]
216
     */
217
    protected function filterAssetNames(array $assetNames) : array
218
    {
219
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
220
        if (! $filter) {
221
            return $assetNames;
222
        }
223
224
        return array_values(array_filter($assetNames, $filter));
225 4665
    }
226
227 4665
    /**
228 4665
     * @deprecated Use Configuration::getSchemaAssetsFilter() instead
229 4665
     */
230
    protected function getFilterSchemaAssetsExpression() : ?string
231
    {
232 1662
        return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();
1 ignored issue
show
Deprecated Code introduced by
The function Doctrine\DBAL\Configurat...chemaAssetsExpression() has been deprecated: Use Configuration::getSchemaAssetsFilter() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

232
        return /** @scrutinizer ignore-deprecated */ $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();

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.

Loading history...
233
    }
234
235
    /**
236
     * Lists the tables for this connection.
237
     *
238
     * @return Table[]
239
     */
240
    public function listTables() : array
241
    {
242
        $tableNames = $this->listTableNames();
243
244
        $tables = [];
245
        foreach ($tableNames as $tableName) {
246
            $tables[] = $this->listTableDetails($tableName);
247
        }
248
249
        return $tables;
250 4101
    }
251
252 4101
    public function listTableDetails(string $tableName) : Table
253
    {
254 4101
        $columns     = $this->listTableColumns($tableName);
255 4101
        $foreignKeys = [];
256 4057
257
        if ($this->_platform->supportsForeignKeyConstraints()) {
258
            $foreignKeys = $this->listTableForeignKeys($tableName);
259 4101
        }
260
261
        $indexes = $this->listTableIndexes($tableName);
262
263
        return new Table($tableName, $columns, $indexes, [], $foreignKeys, []);
264
    }
265
266
    /**
267 4218
     * Lists the views this connection has.
268
     *
269 4218
     * @return View[]
270 4218
     */
271
    public function listViews() : array
272 4218
    {
273 4069
        $database = $this->_conn->getDatabase();
274
        $sql      = $this->_platform->getListViewsSQL($database);
275
        $views    = $this->_conn->fetchAll($sql);
276 4218
277
        return $this->_getPortableViewsList($views);
278 4218
    }
279
280
    /**
281
     * Lists the foreign keys for the given table.
282
     *
283
     * @param string $table The name of the table.
284
     *
285
     * @return ForeignKeyConstraint[]
286 3062
     */
287
    public function listTableForeignKeys(string $table, ?string $database = null) : array
288 3062
    {
289 3062
        if ($database === null) {
290 3062
            $database = $this->_conn->getDatabase();
291
        }
292 3062
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);
293
        $tableForeignKeys = $this->_conn->fetchAll($sql);
294
295
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
296
    }
297
298
    /* drop*() Methods */
299
300
    /**
301
     * Drops a database.
302
     *
303 4109
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
304
     *
305 4109
     * @param string $database The name of the database to drop.
306 4109
     */
307
    public function dropDatabase(string $database) : void
308 4109
    {
309 4109
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
310
    }
311 4109
312
    /**
313
     * Drops the given table.
314
     *
315
     * @param string $tableName The name of the table to drop.
316
     */
317
    public function dropTable(string $tableName) : void
318
    {
319
        $this->_execSql($this->_platform->getDropTableSQL($tableName));
320
    }
321
322
    /**
323
     * Drops the index from the given table.
324
     *
325 4882
     * @param Index|string $index The name of the index.
326
     * @param Table|string $table The name of the table.
327 4882
     */
328 4331
    public function dropIndex($index, $table) : void
329
    {
330
        if ($index instanceof Index) {
331
            $index = $index->getQuotedName($this->_platform);
332
        }
333
334
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
335
    }
336
337 5159
    /**
338
     * Drops the constraint from the given table.
339 5159
     *
340 5087
     * @param Table|string $table The name of the table.
341
     */
342
    public function dropConstraint(Constraint $constraint, $table) : void
343
    {
344
        $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
345
    }
346
347
    /**
348
     * Drops a foreign key from a table.
349
     *
350 3182
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
351
     * @param Table|string                $table      The name of the table with the foreign key.
352 3182
     */
353
    public function dropForeignKey($foreignKey, $table) : void
354
    {
355
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
356 3182
    }
357 3182
358
    /**
359
     * Drops a sequence with a given name.
360
     *
361
     * @param string $name The name of the sequence to drop.
362
     */
363
    public function dropSequence(string $name) : void
364
    {
365
        $this->_execSql($this->_platform->getDropSequenceSQL($name));
366
    }
367
368
    /**
369
     * Drops a view.
370
     *
371
     * @param string $name The name of the view.
372
     */
373
    public function dropView(string $name) : void
374
    {
375
        $this->_execSql($this->_platform->getDropViewSQL($name));
376
    }
377
378
    /* create*() Methods */
379
380
    /**
381
     * Creates a new database.
382
     *
383
     * @param string $database The name of the database to create.
384
     */
385
    public function createDatabase(string $database) : void
386
    {
387
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
388
    }
389
390
    /**
391 1165
     * Creates a new table.
392
     */
393 1165
    public function createTable(Table $table) : void
394
    {
395
        $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
396
        $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
397
    }
398
399
    /**
400
     * Creates a new sequence.
401
     *
402
     * @throws ConnectionException If something fails at database level.
403 3228
     */
404
    public function createSequence(Sequence $sequence) : void
405 3228
    {
406
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
407
    }
408
409
    /**
410
     * Creates a constraint on a table.
411
     *
412
     * @param Table|string $table
413
     */
414
    public function createConstraint(Constraint $constraint, $table) : void
415
    {
416
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
417 4880
    }
418
419 4880
    /**
420 4880
     * Creates a new index on a table.
421
     *
422
     * @param Table|string $table The name of the table on which the index is to be created.
423
     */
424
    public function createIndex(Index $index, $table) : void
425
    {
426
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
427 5177
    }
428
429 5177
    /**
430 5177
     * Creates a new foreign key.
431 5156
     *
432
     * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
433
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
434
     */
435
    public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
436
    {
437
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
438
    }
439
440
    /**
441
     * Creates a new view.
442 1167
     */
443
    public function createView(View $view) : void
444 1167
    {
445 1167
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
446
    }
447
448
    /* dropAndCreate*() Methods */
449
450
    /**
451
     * Drops and creates a constraint.
452
     *
453
     * @see dropConstraint()
454 1
     * @see createConstraint()
455
     *
456 1
     * @param Table|string $table
457 1
     */
458
    public function dropAndCreateConstraint(Constraint $constraint, $table) : void
459
    {
460
        $this->tryMethod('dropConstraint', $constraint, $table);
461
        $this->createConstraint($constraint, $table);
462
    }
463
464
    /**
465
     * Drops and creates a new index on a table.
466 3182
     *
467
     * @param Table|string $table The name of the table on which the index is to be created.
468 3182
     */
469 3182
    public function dropAndCreateIndex(Index $index, $table) : void
470
    {
471
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
472
        $this->createIndex($index, $table);
473
    }
474
475
    /**
476
     * Drops and creates a new foreign key.
477
     *
478
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
479 3193
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
480
     */
481 3193
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
482 3193
    {
483
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
484
        $this->createForeignKey($foreignKey, $table);
485
    }
486
487
    /**
488
     * Drops and create a new sequence.
489 3228
     *
490
     * @throws ConnectionException If something fails at database level.
491 3228
     */
492 3228
    public function dropAndCreateSequence(Sequence $sequence) : void
493
    {
494
        $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
495
        $this->createSequence($sequence);
496
    }
497
498
    /**
499
     * Drops and creates a new table.
500
     */
501
    public function dropAndCreateTable(Table $table) : void
502
    {
503
        $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
504
        $this->createTable($table);
505
    }
506
507
    /**
508
     * Drops and creates a new database.
509
     *
510
     * @param string $database The name of the database to create.
511
     */
512
    public function dropAndCreateDatabase(string $database) : void
513
    {
514
        $this->tryMethod('dropDatabase', $database);
515
        $this->createDatabase($database);
516
    }
517
518
    /**
519 3182
     * Drops and creates a new view.
520
     */
521 3182
    public function dropAndCreateView(View $view) : void
522 3182
    {
523 3182
        $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
524
        $this->createView($view);
525
    }
526
527
    /* alterTable() Methods */
528
529
    /**
530
     * Alters an existing tables schema.
531
     */
532
    public function alterTable(TableDiff $tableDiff) : void
533
    {
534
        $queries = $this->_platform->getAlterTableSQL($tableDiff);
535
536
        if (! is_array($queries) || ! count($queries)) {
537
            return;
538
        }
539
540
        foreach ($queries as $ddlQuery) {
541
            $this->_execSql($ddlQuery);
542
        }
543
    }
544
545
    /**
546 1165
     * Renames a given table to another name.
547
     *
548 1165
     * @param string $name    The current name of the table.
549 1165
     * @param string $newName The new name of the table.
550 1165
     */
551
    public function renameTable(string $name, string $newName) : void
552
    {
553
        $tableDiff          = new TableDiff($name);
554
        $tableDiff->newName = $newName;
555
        $this->alterTable($tableDiff);
556
    }
557 5120
558
    /**
559 5120
     * Methods for filtering return values of list*() methods to convert
560 5120
     * the native DBMS data definition to a portable Doctrine definition
561 5120
     */
562
563
    /**
564
     * @param mixed[] $databases
565
     *
566
     * @return string[]
567
     */
568
    protected function _getPortableDatabasesList(array $databases) : array
569
    {
570 5025
        $list = [];
571
        foreach ($databases as $value) {
572 5025
            $value = $this->_getPortableDatabaseDefinition($value);
573 5025
574 5025
            if (! $value) {
575
                continue;
576
            }
577
578
            $list[] = $value;
579
        }
580
581 3228
        return $list;
582
    }
583 3228
584 3228
    /**
585 3228
     * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
586
     *
587
     * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition.
588
     *
589
     * @return string[]
590
     */
591
    protected function getPortableNamespacesList(array $namespaces) : array
592
    {
593
        $namespacesList = [];
594 3892
595
        foreach ($namespaces as $namespace) {
596 3892
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
597
        }
598 3892
599 1582
        return $namespacesList;
600
    }
601
602 3892
    /**
603 3892
     * @param mixed $database
604
     *
605 3892
     * @return mixed
606
     */
607
    protected function _getPortableDatabaseDefinition($database)
608
    {
609
        return $database;
610
    }
611
612
    /**
613
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
614
     *
615 1
     * @param mixed[] $namespace The native DBMS namespace definition.
616
     *
617 1
     * @return mixed
618 1
     */
619 1
    protected function getPortableNamespaceDefinition(array $namespace)
620 1
    {
621
        return $namespace;
622
    }
623
624
    /**
625
     * @param mixed[][] $functions
626
     *
627
     * @return mixed[][]
628
     */
629
    protected function _getPortableFunctionsList(array $functions) : array
630
    {
631
        $list = [];
632 3156
        foreach ($functions as $value) {
633
            $value = $this->_getPortableFunctionDefinition($value);
634 3156
635 3156
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type array<mixed,mixed> is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
636 3156
                continue;
637
            }
638 3156
639
            $list[] = $value;
640
        }
641
642 3156
        return $list;
643
    }
644
645 3156
    /**
646
     * @param mixed[] $function
647
     *
648
     * @return mixed
649
     */
650
    protected function _getPortableFunctionDefinition(array $function)
651
    {
652
        return $function;
653
    }
654
655 1139
    /**
656
     * @param mixed[][] $triggers
657 1139
     *
658
     * @return mixed[][]
659 1139
     */
660 1139
    protected function _getPortableTriggersList(array $triggers) : array
661
    {
662
        $list = [];
663 1139
        foreach ($triggers as $value) {
664
            $value = $this->_getPortableTriggerDefinition($value);
665
666
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type array<mixed,mixed> is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
667
                continue;
668
            }
669
670
            $list[] = $value;
671
        }
672
673
        return $list;
674
    }
675
676
    /**
677
     * @param mixed[] $trigger
678
     *
679
     * @return mixed
680
     */
681
    protected function _getPortableTriggerDefinition(array $trigger)
682
    {
683
        return $trigger;
684
    }
685
686
    /**
687
     * @param mixed[][] $sequences
688
     *
689
     * @return Sequence[]
690
     */
691
    protected function _getPortableSequencesList(array $sequences) : array
692
    {
693
        $list = [];
694
695
        foreach ($sequences as $value) {
696
            $list[] = $this->_getPortableSequenceDefinition($value);
697
        }
698
699
        return $list;
700
    }
701
702
    /**
703
     * @param mixed[] $sequence
704
     *
705
     * @throws DBALException
706
     */
707
    protected function _getPortableSequenceDefinition(array $sequence) : Sequence
708
    {
709
        throw DBALException::notSupported('Sequences');
710
    }
711
712
    /**
713
     * Independent of the database the keys of the column list result are lowercased.
714
     *
715
     * The name of the created column instance however is kept in its case.
716
     *
717
     * @param string    $table        The name of the table.
718
     * @param mixed[][] $tableColumns
719
     *
720
     * @return Column[]
721
     */
722
    protected function _getPortableTableColumnList(string $table, ?string $database, array $tableColumns) : array
723
    {
724
        $eventManager = $this->_platform->getEventManager();
725
726
        $list = [];
727
        foreach ($tableColumns as $tableColumn) {
728
            $column           = null;
729
            $defaultPrevented = false;
730
731
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
732
                $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
733
                $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
734
735
                $defaultPrevented = $eventArgs->isDefaultPrevented();
736
                $column           = $eventArgs->getColumn();
737
            }
738
739
            if (! $defaultPrevented) {
740
                $column = $this->_getPortableTableColumnDefinition($tableColumn);
741
            }
742
743
            if (! $column) {
744
                continue;
745
            }
746
747
            $name        = strtolower($column->getQuotedName($this->_platform));
748
            $list[$name] = $column;
749
        }
750
751
        return $list;
752
    }
753
754
    /**
755 296
     * Gets Table Column Definition.
756
     *
757 296
     * @param mixed[] $tableColumn
758
     */
759 296
    abstract protected function _getPortableTableColumnDefinition(array $tableColumn) : Column;
760 296
761
    /**
762
     * Aggregates and groups the index results according to the required data result.
763 296
     *
764
     * @param mixed[][] $tableIndexRows
765
     *
766
     * @return Index[]
767
     */
768
    protected function _getPortableTableIndexesList(array $tableIndexRows, string $tableName) : array
769
    {
770
        $result = [];
771
        foreach ($tableIndexRows as $tableIndex) {
772
            $indexName = $keyName = $tableIndex['key_name'];
773
            if ($tableIndex['primary']) {
774
                $keyName = 'primary';
775
            }
776
            $keyName = strtolower($keyName);
777
778
            if (! isset($result[$keyName])) {
779
                $options = [
780
                    'lengths' => [],
781
                ];
782
783
                if (isset($tableIndex['where'])) {
784
                    $options['where'] = $tableIndex['where'];
785
                }
786
787
                $result[$keyName] = [
788
                    'name' => $indexName,
789 4230
                    'columns' => [],
790
                    'unique' => ! $tableIndex['non_unique'],
791 4230
                    'primary' => $tableIndex['primary'],
792
                    'flags' => $tableIndex['flags'] ?? [],
793 4230
                    'options' => $options,
794 4230
                ];
795 4230
            }
796 4230
797
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
798 4230
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
799 3278
        }
800 3278
801
        $eventManager = $this->_platform->getEventManager();
802 3278
803 3278
        $indexes = [];
804
        foreach ($result as $indexKey => $data) {
805
            $index            = null;
806 4230
            $defaultPrevented = false;
807 4230
808
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
809
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
810 4230
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
811
812
                $defaultPrevented = $eventArgs->isDefaultPrevented();
813
                $index            = $eventArgs->getIndex();
814 4230
            }
815 4230
816
            if (! $defaultPrevented) {
817
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
818 4230
            }
819
820
            if (! $index) {
821
                continue;
822
            }
823
824
            $indexes[$indexKey] = $index;
825
        }
826
827
        return $indexes;
828
    }
829
830
    /**
831
     * @param mixed[][] $tables
832
     *
833
     * @return string[]
834
     */
835
    protected function _getPortableTablesList(array $tables) : array
836
    {
837 4223
        $list = [];
838
        foreach ($tables as $value) {
839 4223
            $value = $this->_getPortableTableDefinition($value);
840 4223
841 4166
            if (! $value) {
842 4166
                continue;
843 4164
            }
844
845 4166
            $list[] = $value;
846
        }
847 4166
848
        return $list;
849 4166
    }
850
851
    /**
852 4166
     * @param mixed $table
853 936
     */
854
    protected function _getPortableTableDefinition($table) : string
855
    {
856 4166
        return $table;
857 4166
    }
858
859 4166
    /**
860 4166
     * @param mixed[][] $users
861 4166
     *
862 4166
     * @return string[][]
863
     */
864
    protected function _getPortableUsersList(array $users) : array
865
    {
866 4166
        $list = [];
867 4166
        foreach ($users as $value) {
868
            $value = $this->_getPortableUserDefinition($value);
869
870 4223
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
871
                continue;
872 4223
            }
873 4223
874 4166
            $list[] = $value;
875 4166
        }
876
877 4166
        return $list;
878 3254
    }
879 3254
880
    /**
881 3254
     * @param string[] $user
882 3254
     *
883
     * @return string[]
884
     */
885 4166
    protected function _getPortableUserDefinition(array $user) : array
886 4166
    {
887
        return $user;
888
    }
889 4166
890
    /**
891
     * @param mixed[][] $views
892
     *
893 4166
     * @return View[]
894
     */
895
    protected function _getPortableViewsList(array $views) : array
896 4223
    {
897
        $list = [];
898
        foreach ($views as $value) {
899
            $view        = $this->_getPortableViewDefinition($value);
900
            $name        = strtolower($view->getQuotedName($this->_platform));
901
            $list[$name] = $view;
902
        }
903
904 4490
        return $list;
905
    }
906 4490
907 4490
    /**
908 4488
     * @param mixed[] $view
909
     */
910 4488
    protected function _getPortableViewDefinition(array $view) : View
911
    {
912
        throw DBALException::notSupported('Views');
913
    }
914 4488
915
    /**
916
     * @param mixed[][] $tableForeignKeys
917 4490
     *
918
     * @return ForeignKeyConstraint[]
919
     */
920
    protected function _getPortableTableForeignKeysList(array $tableForeignKeys) : array
921
    {
922
        $list = [];
923
924
        foreach ($tableForeignKeys as $value) {
925
            $list[] = $this->_getPortableTableForeignKeyDefinition($value);
926
        }
927
928
        return $list;
929
    }
930
931
    /**
932
     * @param mixed $tableForeignKey
933
     */
934
    protected function _getPortableTableForeignKeyDefinition($tableForeignKey) : ForeignKeyConstraint
935
    {
936
        return $tableForeignKey;
937
    }
938
939
    /**
940
     * @param string[]|string $sql
941
     */
942
    protected function _execSql($sql) : void
943
    {
944
        foreach ((array) $sql as $query) {
945
            $this->_conn->executeUpdate($query);
946
        }
947
    }
948
949
    /**
950
     * Creates a schema instance for the current database.
951
     */
952
    public function createSchema() : Schema
953
    {
954
        $namespaces = [];
955
956
        if ($this->_platform->supportsSchemas()) {
957
            $namespaces = $this->listNamespaceNames();
958
        }
959
960
        $sequences = [];
961
962
        if ($this->_platform->supportsSequences()) {
963
            $sequences = $this->listSequences();
964
        }
965
966 3062
        $tables = $this->listTables();
967
968 3062
        return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces);
969 3062
    }
970 3062
971
    /**
972 3062
     * Creates the configuration for this schema.
973
     */
974
    public function createSchemaConfig() : SchemaConfig
975
    {
976 3062
        $schemaConfig = new SchemaConfig();
977 3062
        $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
978
979
        $searchPaths = $this->getSchemaSearchPaths();
980 3062
        if (isset($searchPaths[0])) {
981
            $schemaConfig->setName($searchPaths[0]);
982
        }
983
984
        $params = $this->_conn->getParams();
985
        if (! isset($params['defaultTableOptions'])) {
986
            $params['defaultTableOptions'] = [];
987
        }
988
        if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
989
            $params['defaultTableOptions']['charset'] = $params['charset'];
990
        }
991
        $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
992
993
        return $schemaConfig;
994
    }
995
996
    /**
997
     * The search path for namespaces in the currently connected database.
998 1482
     *
999
     * The first entry is usually the default namespace in the Schema. All
1000 1482
     * further namespaces contain tables/sequences which can also be addressed
1001
     * with a short, not full-qualified name.
1002 1482
     *
1003 1383
     * For databases that don't support subschema/namespaces this method
1004
     * returns the name of the currently connected database.
1005
     *
1006 1482
     * @return string[]
1007
     */
1008
    public function getSchemaSearchPaths() : array
1009
    {
1010
        $database = $this->_conn->getDatabase();
1011
1012
        if ($database !== null) {
1013
            return [$database];
1014
        }
1015
1016
        return [];
1017
    }
1018
1019
    /**
1020
     * Given a table comment this method tries to extract a type hint for Doctrine Type, or returns
1021
     * the type given as default.
1022
     */
1023
    public function extractDoctrineTypeFromComment(?string &$comment) : ?string
1024 5378
    {
1025
        if ($comment === null || ! preg_match('/(.*)\(DC2Type:(((?!\)).)+)\)(.*)/', $comment, $match)) {
1026 5378
            return null;
1027 5378
        }
1028
1029 5351
        $comment = $match[1] . $match[4];
1030
1031
        return $match[2];
1032
    }
1033
}
1034